usergrid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From snoopd...@apache.org
Subject [15/41] lots of updates
Date Tue, 11 Feb 2014 23:20:59 GMT
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9dfc5628/sdks/html5-javascript/lib/modules/Entity.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Entity.js b/sdks/html5-javascript/lib/modules/Entity.js
new file mode 100644
index 0000000..e84e400
--- /dev/null
+++ b/sdks/html5-javascript/lib/modules/Entity.js
@@ -0,0 +1,684 @@
+/*
+ *  A class to Model a Usergrid Entity.
+ *  Set the type and uuid of entity in the 'data' json object
+ *
+ *  @constructor
+ *  @param {object} options {client:client, data:{'type':'collection_type', uuid:'uuid', 'key':'value'}}
+ */
+Usergrid.Entity = function(options) {
+  if (options) {
+    this._data = options.data || {};
+    this._client = options.client || {};
+  }
+};
+
+/*
+ *  method to determine whether or not the passed variable is a Usergrid Entity
+ *
+ *  @method isEntity
+ *  @public
+ *  @params {any} obj - any variable
+ *  @return {boolean} Returns true or false
+ */
+Usergrid.Entity.isEntity = function(obj){
+  return (obj && obj instanceof Usergrid.Entity);
+}
+
+/*
+ *  method to determine whether or not the passed variable is a Usergrid Entity
+ *  That has been saved.
+ *
+ *  @method isPersistedEntity
+ *  @public
+ *  @params {any} obj - any variable
+ *  @return {boolean} Returns true or false
+ */
+Usergrid.Entity.isPersistedEntity = function(obj){
+  return (isEntity(obj) && isUUID(obj.get('uuid')));
+}
+
+/*
+ *  returns a serialized version of the entity object
+ *
+ *  Note: use the client.restoreEntity() function to restore
+ *
+ *  @method serialize
+ *  @return {string} data
+ */
+Usergrid.Entity.prototype.serialize = function () {
+  return JSON.stringify(this._data);
+};
+
+/*
+ *  gets a specific field or the entire data object. If null or no argument
+ *  passed, will return all data, else, will return a specific field
+ *
+ *  @method get
+ *  @param {string} field
+ *  @return {string} || {object} data
+ */
+Usergrid.Entity.prototype.get = function (key) {
+    var value;
+    if(arguments.length===0){
+        value=this._data;
+    }else if(arguments.length>1){
+        key=[].slice.call(arguments).reduce(function(p,c,i,a){
+            if(c instanceof Array){
+                p= p.concat(c);
+            }else{
+                p.push(c);
+            }
+            return p;
+        },[]);
+    }
+    if(key instanceof Array){
+        var self=this;
+        value=key.map(function(k){return self.get(k)});
+    }else if("undefined" !== typeof key){
+        value=this._data[key];
+    }
+    return value;
+};
+/*
+ *  adds a specific key value pair or object to the Entity's data
+ *  is additive - will not overwrite existing values unless they
+ *  are explicitly specified
+ *
+ *  @method set
+ *  @param {string} key || {object}
+ *  @param {string} value
+ *  @return none
+ */
+Usergrid.Entity.prototype.set = function (key, value) {
+  if (typeof key === 'object') {
+    for(var field in key) {
+      this._data[field] = key[field];
+    }
+  } else if (typeof key === 'string') {
+    if (value === null) {
+      delete this._data[key];
+    } else {
+      this._data[key] = value;
+    }
+  } else {
+    this._data = {};
+  }
+};
+
+Usergrid.Entity.prototype.getEndpoint = function () {
+    var type = this.get('type'), name, endpoint;
+    var nameProperties=['uuid', 'name'];
+    if (type === undefined) {
+        throw new UsergridError('cannot fetch entity, no entity type specified', 'no_type_specified');
+    }else if(type==="users"){
+        nameProperties.unshift('username');
+    }
+
+    var names= this.get(nameProperties).filter(function(x){return "undefined"!==typeof x});
+    if (names.length===0) {
+        throw new UsergridError("Cannot infer an UUID or type from the entity", 'no_name_specified');
+    }else{
+        name=names.shift();
+    }
+    return [type, name].join('/');
+};
+/*
+ *  Saves the entity back to the database
+ *
+ *  @method save
+ *  @public
+ *  @param {function} callback
+ *  @return {callback} callback(err, data)
+ */
+Usergrid.Entity.prototype.save = function (callback) {
+  var self = this,
+    type = this.get('type'),
+    method = 'POST',
+    entityId=this.get("uuid"),
+    data = {},
+    entityData = this.get(),
+    /*password = this.get('password'),
+    oldpassword = this.get('oldpassword'),
+    newpassword = this.get('newpassword'),*/
+    SYSTEM_PROPERTIES=['metadata','created','modified','oldpassword','newpassword','type','activated','uuid'],
+    options={
+      method:method,
+      endpoint:type
+    };
+    console.log("SAVE DATA #1", entityId, entityData);
+
+  //update the entity
+  if (entityId) {
+    options.method = 'PUT';
+    options.endpoint += '/' + entityId;
+  }
+
+  //remove system-specific properties
+  Object.keys(entityData)
+      .filter(function(key){return (SYSTEM_PROPERTIES.indexOf(key)===-1)})
+    .forEach(function(key){
+      data[key]= entityData[key];
+    });
+    console.log("SAVE DATA #2", data);
+    options.body=data;
+  //save the entity first
+  this._client.request(options, function (err, response) {
+      console.log("SAVE DATA #3", response);
+      var entity=response.getEntity();
+      if(entity){
+          self.set(entity);
+      }
+      doCallback(callback,[err, self]);
+
+      /*
+        TODO move user logic to its own entity
+       */
+
+    /*
+
+     //clear out pw info if present
+     self.set('password', null);
+     self.set('oldpassword', null);
+     self.set('newpassword', null);
+    if (err && self._client.logging) {
+      console.log('could not save entity');
+      if (typeof(callback) === 'function') {
+        return callback(err, retdata, self);
+      }
+    } else {
+      if (retdata.entities) {
+        if (retdata.entities.length) {
+          var entity = retdata.entities[0];
+          self.set(entity);
+          var path = retdata.path;
+          //for connections, API returns type
+          while (path.substring(0, 1) === "/") {
+            path = path.substring(1);
+          }
+          self.set('type', path);
+        }
+      }
+      //if this is a user, update the password if it has been specified;
+        var needPasswordChange = ((self.get('type') === 'user' || self.get('type') === 'users') && oldpassword && newpassword);
+      if (needPasswordChange) {
+        //Note: we have a ticket in to change PUT calls to /users to accept the password change
+        //      once that is done, we will remove this call and merge it all into one
+        var pwdata = {};
+          pwdata.oldpassword = oldpassword;
+          pwdata.newpassword = newpassword;
+        var options = {
+          method:'PUT',
+          endpoint:type+'/password',
+          body:pwdata
+        }
+        self._client.request(options, function (err, data) {
+          if (err && self._client.logging) {
+            console.log('could not update user');
+          }
+          //remove old and new password fields so they don't end up as part of the entity object
+          self.set('oldpassword', null);
+          self.set('newpassword', null);
+          if (typeof(callback) === 'function') {
+            callback(err, data, self);
+          }
+        });
+      } else if (typeof(callback) === 'function') {
+        callback(err, retdata, self);
+      }
+    }*/
+  });
+};
+
+/*
+ *  refreshes the entity by making a GET call back to the database
+ *
+ *  @method fetch
+ *  @public
+ *  @param {function} callback
+ *  @return {callback} callback(err, data)
+ */
+Usergrid.Entity.prototype.fetch = function (callback) {
+    var endpoint, self = this;
+
+    //Check for an entity type, then if a uuid is available, use that, otherwise, use the name
+    //try {
+    endpoint=this.getEndpoint();
+    /*} catch (e) {
+     if (self._client.logging) {
+     console.log(e);
+     }
+     return callback(true, {
+     error: e
+     }, self);
+     }*/
+    var options = {
+        method: 'GET',
+        endpoint: endpoint
+    };
+    this._client.request(options, function (err, response) {
+        var entity=response.getEntity();
+        if(entity){
+            self.set(entity);
+        }
+        console.log("AFTER FETCH", self.get(), entity, response);
+        doCallback(callback,[err, entity, self]);
+    });
+};
+
+/*
+ *  deletes the entity from the database - will only delete
+ *  if the object has a valid uuid
+ *
+ *  @method destroy
+ *  @public
+ *  @param {function} callback
+ *  @return {callback} callback(err, data)
+ *
+ */
+Usergrid.Entity.prototype.destroy = function (callback) {
+  var self = this;
+  var endpoint = this.getEndpoint();
+
+  var options = {
+    method:'DELETE',
+    endpoint:endpoint
+  };
+  this._client.request(options, function (err, data) {
+    if (!err) {
+      self.set(null);
+    }
+    if (typeof(callback) === 'function') {
+      doCallback(callback,[err, data]);
+    }
+  });
+};
+
+/*
+ *  connects one entity to another
+ *
+ *  @method connect
+ *  @public
+ *  @param {string} connection
+ *  @param {object} entity
+ *  @param {function} callback
+ *  @return {callback} callback(err, data)
+ *
+ */
+Usergrid.Entity.prototype.connect = function (connection, entity, callback) {
+
+  var self = this;
+
+  var error;
+  //connectee info
+  var connecteeType = entity.get('type');
+  var connectee = this.getEntityId(entity);
+  if (!connectee) {
+    if (typeof(callback) === 'function') {
+      error = 'Error trying to delete object - no uuid specified.';
+      if (self._client.logging) {
+        console.log(error);
+      }
+      callback(true, error);
+    }
+    return;
+  }
+
+  //connector info
+  var connectorType = this.get('type');
+  var connector = this.getEntityId(this);
+  if (!connector) {
+    if (typeof(callback) === 'function') {
+      error = 'Error in connect - no uuid specified.';
+      if (self._client.logging) {
+        console.log(error);
+      }
+      callback(true, error);
+    }
+    return;
+  }
+
+  var endpoint = connectorType + '/' + connector + '/' + connection + '/' + connecteeType + '/' + connectee;
+  var options = {
+    method:'POST',
+    endpoint:endpoint
+  };
+  this._client.request(options, function (err, data) {
+    if (err && self._client.logging) {
+      console.log('entity could not be connected');
+    }
+    if (typeof(callback) === 'function') {
+      callback(err, data);
+    }
+  });
+};
+
+/*
+ *  returns a unique identifier for an entity
+ *
+ *  @method connect
+ *  @public
+ *  @param {object} entity
+ *  @param {function} callback
+ *  @return {callback} callback(err, data)
+ *
+ */
+Usergrid.Entity.prototype.getEntityId = function (entity) {
+  var id = false;
+  if (isUUID(entity.get('uuid'))) {
+    id = entity.get('uuid');
+  } else {
+    if (this.get("type") === 'users') {
+      id = entity.get('username');
+    } else if (entity.get('name')) {
+      id = entity.get('name');
+    }
+  }
+  return id;
+};
+
+/*
+ *  gets an entities connections
+ *
+ *  @method getConnections
+ *  @public
+ *  @param {string} connection
+ *  @param {object} entity
+ *  @param {function} callback
+ *  @return {callback} callback(err, data, connections)
+ *
+ */
+Usergrid.Entity.prototype.getConnections = function (connection, callback) {
+
+  var self = this;
+
+  //connector info
+  var connectorType = this.get('type');
+  var connector = this.getEntityId(this);
+  if (!connector) {
+    if (typeof(callback) === 'function') {
+      var error = 'Error in getConnections - no uuid specified.';
+      if (self._client.logging) {
+        console.log(error);
+      }
+      callback(true, error);
+    }
+    return;
+  }
+
+  var endpoint = connectorType + '/' + connector + '/' + connection + '/';
+  var options = {
+    method:'GET',
+    endpoint:endpoint
+  };
+  this._client.request(options, function (err, data) {
+    if (err && self._client.logging) {
+      console.log('entity could not be connected');
+    }
+
+    self[connection] = {};
+
+    var length = data.entities.length;
+    for (var i = 0; i < length; i++) {
+      if (data.entities[i].type === 'user'){
+        self[connection][data.entities[i].username] = data.entities[i];
+      } else {
+        self[connection][data.entities[i].name] = data.entities[i]
+      }
+    }
+
+    if (typeof(callback) === 'function') {
+      callback(err, data, data.entities);
+    }
+  });
+
+};
+
+Usergrid.Entity.prototype.getGroups = function (callback) {
+
+  var self = this;
+
+  var endpoint = 'users' + '/' + this.get('uuid') + '/groups' ;
+  var options = {
+    method:'GET',
+    endpoint:endpoint
+  };
+  this._client.request(options, function (err, data) {
+    if (err && self._client.logging) {
+      console.log('entity could not be connected');
+    }
+
+    self.groups = data.entities;
+
+    if (typeof(callback) === 'function') {
+      callback(err, data, data.entities);
+    }
+  });
+
+};
+
+Usergrid.Entity.prototype.getActivities = function (callback) {
+
+  var self = this;
+
+  var endpoint = this.get('type') + '/' + this.get('uuid') + '/activities' ;
+  var options = {
+    method:'GET',
+    endpoint:endpoint
+  };
+  this._client.request(options, function (err, data) {
+    if (err && self._client.logging) {
+      console.log('entity could not be connected');
+    }
+
+    for (var entity in data.entities) {
+      data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
+    }
+
+    self.activities = data.entities;
+
+    if (typeof(callback) === 'function') {
+      callback(err, data, data.entities);
+    }
+  });
+
+};
+
+Usergrid.Entity.prototype.getFollowing = function (callback) {
+
+  var self = this;
+
+  var endpoint = 'users' + '/' + this.get('uuid') + '/following' ;
+  var options = {
+    method:'GET',
+    endpoint:endpoint
+  };
+  this._client.request(options, function (err, data) {
+    if (err && self._client.logging) {
+      console.log('could not get user following');
+    }
+
+    for (var entity in data.entities) {
+      data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
+      var image = self._client.getDisplayImage(data.entities[entity].email, data.entities[entity].picture);
+      data.entities[entity]._portal_image_icon =  image;
+    }
+
+    self.following = data.entities;
+
+    if (typeof(callback) === 'function') {
+      callback(err, data, data.entities);
+    }
+  });
+
+};
+
+
+Usergrid.Entity.prototype.getFollowers = function (callback) {
+
+  var self = this;
+
+  var endpoint = 'users' + '/' + this.get('uuid') + '/followers' ;
+  var options = {
+    method:'GET',
+    endpoint:endpoint
+  };
+  this._client.request(options, function (err, data) {
+    if (err && self._client.logging) {
+      console.log('could not get user followers');
+    }
+
+    for (var entity in data.entities) {
+      data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
+      var image = self._client.getDisplayImage(data.entities[entity].email, data.entities[entity].picture);
+      data.entities[entity]._portal_image_icon =  image;
+    }
+
+    self.followers = data.entities;
+
+    if (typeof(callback) === 'function') {
+      callback(err, data, data.entities);
+    }
+  });
+
+};
+
+Usergrid.Entity.prototype.getRoles = function (callback) {
+
+  var self = this;
+
+  var endpoint = this.get('type') + '/' + this.get('uuid') + '/roles' ;
+  var options = {
+    method:'GET',
+    endpoint:endpoint
+  };
+  this._client.request(options, function (err, data) {
+    if (err && self._client.logging) {
+      console.log('could not get user roles');
+    }
+
+    self.roles = data.entities;
+
+    if (typeof(callback) === 'function') {
+      callback(err, data, data.entities);
+    }
+  });
+
+};
+
+Usergrid.Entity.prototype.getPermissions = function (callback) {
+
+  var self = this;
+
+  var endpoint = this.get('type') + '/' + this.get('uuid') + '/permissions' ;
+  var options = {
+    method:'GET',
+    endpoint:endpoint
+  };
+  this._client.request(options, function (err, data) {
+    if (err && self._client.logging) {
+      console.log('could not get user permissions');
+    }
+
+    var permissions = [];
+    if (data.data) {
+      var perms = data.data;
+      var count = 0;
+
+      for (var i in perms) {
+        count++;
+        var perm = perms[i];
+        var parts = perm.split(':');
+        var ops_part = "";
+        var path_part = parts[0];
+
+        if (parts.length > 1) {
+          ops_part = parts[0];
+          path_part = parts[1];
+        }
+
+        ops_part.replace("*", "get,post,put,delete")
+        var ops = ops_part.split(',');
+        var ops_object = {}
+        ops_object.get = 'no';
+        ops_object.post = 'no';
+        ops_object.put = 'no';
+        ops_object.delete = 'no';
+        for (var j in ops) {
+          ops_object[ops[j]] = 'yes';
+        }
+
+        permissions.push({
+          operations: ops_object,
+          path: path_part,
+          perm: perm
+        });
+      }
+    }
+
+    self.permissions = permissions;
+
+    if (typeof(callback) === 'function') {
+      callback(err, data, data.entities);
+    }
+  });
+
+};
+
+/*
+ *  disconnects one entity from another
+ *
+ *  @method disconnect
+ *  @public
+ *  @param {string} connection
+ *  @param {object} entity
+ *  @param {function} callback
+ *  @return {callback} callback(err, data)
+ *
+ */
+Usergrid.Entity.prototype.disconnect = function (connection, entity, callback) {
+
+  var self = this;
+
+  var error;
+  //connectee info
+  var connecteeType = entity.get('type');
+  var connectee = this.getEntityId(entity);
+  if (!connectee) {
+    if (typeof(callback) === 'function') {
+      error = 'Error trying to delete object - no uuid specified.';
+      if (self._client.logging) {
+        console.log(error);
+      }
+      callback(true, error);
+    }
+    return;
+  }
+
+  //connector info
+  var connectorType = this.get('type');
+  var connector = this.getEntityId(this);
+  if (!connector) {
+    if (typeof(callback) === 'function') {
+      error = 'Error in connect - no uuid specified.';
+      if (self._client.logging) {
+        console.log(error);
+      }
+      callback(true, error);
+    }
+    return;
+  }
+
+  var endpoint = connectorType + '/' + connector + '/' + connection + '/' + connecteeType + '/' + connectee;
+  var options = {
+    method:'DELETE',
+    endpoint:endpoint
+  };
+  this._client.request(options, function (err, data) {
+    if (err && self._client.logging) {
+      console.log('entity could not be disconnected');
+    }
+    if (typeof(callback) === 'function') {
+      callback(err, data);
+    }
+  });
+};

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9dfc5628/sdks/html5-javascript/lib/modules/Error.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Error.js b/sdks/html5-javascript/lib/modules/Error.js
new file mode 100644
index 0000000..e2b44b8
--- /dev/null
+++ b/sdks/html5-javascript/lib/modules/Error.js
@@ -0,0 +1,125 @@
+//noinspection ThisExpressionReferencesGlobalObjectJS
+
+/**
+ * Created by ryan bridges on 2014-02-05.
+ */
+(function (global) {
+    //noinspection JSUnusedAssignment
+    var name = 'UsergridError',
+        short,
+        _name = global[name],
+        _short = (short && short !== undefined) ? global[short] : undefined;
+
+    /*
+     *  Instantiates a new UsergridError
+     *
+     *  @method UsergridError
+     *  @public
+     *  @params {<string>} message
+     *  @params {<string>} id       - the error code, id, or name
+     *  @params {<int>} timestamp
+     *  @params {<int>} duration
+     *  @params {<string>} exception    - the Java exception from Usergrid
+     *  @return Returns - a new UsergridError object
+     *
+     *  Example:
+     *
+     *  UsergridError(message);
+     */
+
+    function UsergridError(message, name, timestamp, duration, exception){
+        this.message=message;
+        this.name=name;
+        this.timestamp=timestamp||Date.now();
+        this.duration=duration||0;
+        this.exception=exception;
+    }
+    UsergridError.prototype=new Error();
+    UsergridError.prototype.constructor = UsergridError;
+    /*
+     *  Creates a UsergridError from the JSON response returned from the backend
+     *
+     *  @method fromResponse
+     *  @public
+     *  @params {object} response - the deserialized HTTP response from the Usergrid API
+     *  @return Returns a new UsergridError object.
+     *
+     *  Example:
+     *  {
+     *  "error":"organization_application_not_found",
+     *  "timestamp":1391618508079,
+     *  "duration":0,
+     *  "exception":"org.usergrid.rest.exceptions.OrganizationApplicationNotFoundException",
+     *  "error_description":"Could not find application for yourorgname/sandboxxxxx from URI: yourorgname/sandboxxxxx"
+     *  }
+     */
+    UsergridError.fromResponse=function(response){
+        if(response && "undefined"!==typeof response){
+            return new UsergridError(response.error_description, response.error, response.timestamp, response.duration, response.exception);
+        }else{
+            return new UsergridError();
+        }
+    };
+    UsergridError.createSubClass=function(name){
+        if(name in global && global[name])return global[name]
+        global[name]=function(){};
+        global[name].name=name;
+        global[name].prototype=new UsergridError();
+        return global[name];
+    };
+
+    function UsergridHTTPResponseError(message, name, timestamp, duration, exception){
+        this.message=message;
+        this.name=name;
+        this.timestamp=timestamp||Date.now();
+        this.duration=duration||0;
+        this.exception=exception;
+    }
+    UsergridHTTPResponseError.prototype=new UsergridError();
+    function UsergridInvalidHTTPMethodError(message, name, timestamp, duration, exception){
+        this.message=message;
+        this.name=name;
+        this.timestamp=timestamp||Date.now();
+        this.duration=duration||0;
+        this.exception=exception;
+    }
+    UsergridInvalidHTTPMethodError.prototype=new UsergridError();
+    function UsergridInvalidURIError(message, name, timestamp, duration, exception){
+        this.message=message;
+        this.name=name;
+        this.timestamp=timestamp||Date.now();
+        this.duration=duration||0;
+        this.exception=exception;
+    }
+    UsergridInvalidURIError.prototype=new UsergridError();
+    function UsergridKeystoreDatabaseUpgradeNeededError(message, name, timestamp, duration, exception){
+        this.message=message;
+        this.name=name;
+        this.timestamp=timestamp||Date.now();
+        this.duration=duration||0;
+        this.exception=exception;
+    }
+    UsergridKeystoreDatabaseUpgradeNeededError.prototype=new UsergridError();
+
+    global['UsergridHTTPResponseError'] = UsergridHTTPResponseError;
+    global['UsergridInvalidHTTPMethodError'] = UsergridInvalidHTTPMethodError;
+    global['UsergridInvalidURIError'] = UsergridInvalidURIError;
+    global['UsergridKeystoreDatabaseUpgradeNeededError'] = UsergridKeystoreDatabaseUpgradeNeededError;
+
+    global[name] = UsergridError;
+    if (short !== undefined) {
+        //noinspection JSUnusedAssignment
+        global[short] = UsergridError;
+    }
+    global[name].noConflict = function () {
+        if (_name) {
+            global[name] = _name;
+        }
+        if (short !== undefined) {
+            global[short] = _short;
+        }
+        return UsergridError;
+    };
+    return global[name];
+}(this));
+

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9dfc5628/sdks/html5-javascript/lib/modules/Folder.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Folder.js b/sdks/html5-javascript/lib/modules/Folder.js
new file mode 100644
index 0000000..11d7521
--- /dev/null
+++ b/sdks/html5-javascript/lib/modules/Folder.js
@@ -0,0 +1,167 @@
+/*
+ *  A class to model a Usergrid folder.
+ *
+ *  @constructor
+ *  @param {object} options {name:"MyPhotos", path:"/user/uploads", owner:"00000000-0000-0000-0000-000000000000" }
+ *  @returns {callback} callback(err, folder)
+ */
+Usergrid.Folder = function(options, callback) {
+	var self = this,
+		messages = [];
+	console.log("FOLDER OPTIONS", options);
+	self._client = options.client;
+	self._data = options.data || {};
+	self._data.type = "folders";
+	var missingData = ["name", "owner", "path"].some(function(required) { return !(required in self._data)});
+	if(missingData){
+		return doCallback(callback, [true, new Usergrid.Error("Invalid asset data: 'name', 'owner', and 'path' are required properties.")], self);
+	}
+	self.save(function(err, data) {
+		if (err) {
+			doCallback(callback, [true, new Usergrid.Error(data)], self);
+		} else {
+			if (data.entities.length){
+				self.set(data.entities[0]);
+			}
+			doCallback(callback, [false, self], self);
+		}
+	});
+};
+/*
+ *  Inherit from Usergrid.Entity.
+ */
+Usergrid.Folder.prototype = new Usergrid.Entity();
+
+
+/*
+ *  fetch the folder and associated assets
+ *
+ *  @method fetch
+ *  @public
+ *  @param {function} callback(err, self)
+ *  @returns {callback} callback(err, self)
+ */
+Usergrid.Folder.prototype.fetch = function(callback) {
+	var self = this;
+	Usergrid.Entity.prototype.fetch.call(self, function(err, data) {
+		console.log("self", self.get());
+		console.log("data", data);
+		if (!err) {
+			self.getAssets(function(err, data) {
+				if (err) {
+					doCallback(callback, [true, new Usergrid.Error(data)], self);
+				} else {
+					doCallback(callback, [null, self], self);
+				}
+			});
+		} else {
+			doCallback(callback, [true, new Usergrid.Error(data)], self)
+		}
+	})
+};
+/*
+ *  Add an asset to the folder.
+ *
+ *  @method addAsset
+ *  @public
+ *  @param {object} options {asset:(uuid || Usergrid.Asset || {name:"photo.jpg", path:"/user/uploads", "content-type":"image/jpeg", owner:"F01DE600-0000-0000-0000-000000000000" }) }
+ *  @returns {callback} callback(err, folder)
+ */
+Usergrid.Folder.prototype.addAsset = function(options, callback) {
+	var self = this;
+	if (('asset' in options)) {
+		var asset = null;
+		switch (typeof options.asset) {
+			case 'object':
+				asset = options.asset;
+				if (!(asset instanceof Usergrid.Entity)) {
+					asset = new Usergrid.Asset(asset);
+				}
+				break;
+			case 'string':
+				if (isUUID(options.asset)) {
+					asset = new Usergrid.Asset({
+						client: self._client,
+						data: {
+							uuid: options.asset,
+							type: "assets"
+						}
+					});
+				}
+				break;
+		}
+		if (asset && asset instanceof Usergrid.Entity) {
+			asset.fetch(function(err, data) {
+				if (err) {
+					doCallback(callback, [err, new Usergrid.Error(data)], self)
+				} else {
+					var endpoint = ["folders", self.get("uuid"), "assets", asset.get("uuid")].join('/');
+					var options = {
+						method: 'POST',
+						endpoint: endpoint
+					};
+					self._client.request(options, callback);
+				}
+			})
+		}
+	} else {
+		//nothing to add
+		doCallback(callback, [true, {
+			error_description: "No asset specified"
+		}], self)
+	}
+};
+
+/*
+ *  Remove an asset from the folder.
+ *
+ *  @method removeAsset
+ *  @public
+ *  @param {object} options {asset:(uuid || Usergrid.Asset || {name:"photo.jpg", path:"/user/uploads", "content-type":"image/jpeg", owner:"F01DE600-0000-0000-0000-000000000000" }) }
+ *  @returns {callback} callback(err, folder)
+ */
+Usergrid.Folder.prototype.removeAsset = function(options, callback) {
+	var self = this;
+	if (('asset' in options)) {
+		var asset = null;
+		switch (typeof options.asset) {
+			case 'object':
+				asset = options.asset;
+				break;
+			case 'string':
+				if (isUUID(options.asset)) {
+					asset = new Usergrid.Asset({
+						client: self._client,
+						data: {
+							uuid: options.asset,
+							type: "assets"
+						}
+					});
+				}
+				break;
+		}
+		if (asset && asset !== null) {
+			var endpoint = ["folders", self.get("uuid"), "assets", asset.get("uuid")].join('/');
+			self._client.request({
+				method: 'DELETE',
+				endpoint: endpoint
+			}, callback);
+		}
+	} else {
+		//nothing to add
+		doCallback(callback, [true, {
+			error_description: "No asset specified"
+		}], self)
+	}
+};
+
+/*
+ *  List the assets in the folder.
+ *
+ *  @method getAssets
+ *  @public
+ *  @returns {callback} callback(err, assets)
+ */
+Usergrid.Folder.prototype.getAssets = function(callback) {
+	return this.getConnections("assets", callback);
+};

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9dfc5628/sdks/html5-javascript/lib/modules/Group.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Group.js b/sdks/html5-javascript/lib/modules/Group.js
new file mode 100644
index 0000000..2a853be
--- /dev/null
+++ b/sdks/html5-javascript/lib/modules/Group.js
@@ -0,0 +1,233 @@
+/*
+ *  A class to model a Usergrid group.
+ *  Set the path in the options object.
+ *
+ *  @constructor
+ *  @param {object} options {client:client, data: {'key': 'value'}, path:'path'}
+ */
+Usergrid.Group = function(options, callback) {
+  this._path = options.path;
+  this._list = [];
+  this._client = options.client;
+  this._data = options.data || {};
+  this._data.type = "groups";
+};
+
+/*
+ *  Inherit from Usergrid.Entity.
+ *  Note: This only accounts for data on the group object itself.
+ *  You need to use add and remove to manipulate group membership.
+ */
+Usergrid.Group.prototype = new Usergrid.Entity();
+
+/*
+ *  Fetches current group data, and members.
+ *
+ *  @method fetch
+ *  @public
+ *  @param {function} callback
+ *  @returns {function} callback(err, data)
+ */
+Usergrid.Group.prototype.fetch = function(callback) {
+  var self = this;
+  var groupEndpoint = 'groups/'+this._path;
+  var memberEndpoint = 'groups/'+this._path+'/users';
+
+  var groupOptions = {
+    method:'GET',
+    endpoint:groupEndpoint
+  }
+
+  var memberOptions = {
+    method:'GET',
+    endpoint:memberEndpoint
+  }
+
+  this._client.request(groupOptions, function(err, data){
+    if(err) {
+      if(self._client.logging) {
+        console.log('error getting group');
+      }
+      if(typeof(callback) === 'function') {
+        callback(err, data);
+      }
+    } else {
+      if(data.entities) {
+        var groupData = data.entities[0];
+        self._data = groupData || {};
+        self._client.request(memberOptions, function(err, data) {
+          if(err && self._client.logging) {
+            console.log('error getting group users');
+          } else {
+            if(data.entities) {
+              var count = data.entities.length;
+              self._list = [];
+              for (var i = 0; i < count; i++) {
+                var uuid = data.entities[i].uuid;
+                if(uuid) {
+                  var entityData = data.entities[i] || {};
+                  var entityOptions = {
+                    type: entityData.type,
+                    client: self._client,
+                    uuid:uuid,
+                    data:entityData
+                  };
+                  var entity = new Usergrid.Entity(entityOptions);
+                  self._list.push(entity);
+                }
+
+              }
+            }
+          }
+          if(typeof(callback) === 'function') {
+            callback(err, data, self._list);
+          }
+        });
+      }
+    }
+  });
+};
+
+/*
+ *  Retrieves the members of a group.
+ *
+ *  @method members
+ *  @public
+ *  @param {function} callback
+ *  @return {function} callback(err, data);
+ */
+Usergrid.Group.prototype.members = function(callback) {
+  if(typeof(callback) === 'function') {
+    callback(null, this._list);
+  }
+};
+
+/*
+ *  Adds a user to the group, and refreshes the group object.
+ *
+ *  Options object: {user: user_entity}
+ *
+ *  @method add
+ *  @public
+ *  @params {object} options
+ *  @param {function} callback
+ *  @return {function} callback(err, data)
+ */
+Usergrid.Group.prototype.add = function(options, callback) {
+  var self = this;
+  var options = {
+    method:"POST",
+    endpoint:"groups/"+this._path+"/users/"+options.user.get('username')
+  }
+
+  this._client.request(options, function(error, data){
+    if(error) {
+      if(typeof(callback) === 'function') {
+        callback(error, data, data.entities);
+      }
+    } else {
+      self.fetch(callback);
+    }
+  });
+}
+
+/*
+ *  Removes a user from a group, and refreshes the group object.
+ *
+ *  Options object: {user: user_entity}
+ *
+ *  @method remove
+ *  @public
+ *  @params {object} options
+ *  @param {function} callback
+ *  @return {function} callback(err, data)
+ */
+Usergrid.Group.prototype.remove = function(options, callback) {
+  var self = this;
+
+  var options = {
+    method:"DELETE",
+    endpoint:"groups/"+this._path+"/users/"+options.user.get('username')
+  }
+
+  this._client.request(options, function(error, data){
+    if(error) {
+      if(typeof(callback) === 'function') {
+        callback(error, data);
+      }
+    } else {
+      self.fetch(callback);
+    }
+  });
+}
+
+/*
+ * Gets feed for a group.
+ *
+ * @public
+ * @method feed
+ * @param {function} callback
+ * @returns {callback} callback(err, data, activities)
+ */
+Usergrid.Group.prototype.feed = function(callback) {
+  var self = this;
+
+  var endpoint = "groups/"+this._path+"/feed";
+
+  var options = {
+    method:"GET",
+    endpoint:endpoint
+  }
+
+  this._client.request(options, function(err, data){
+    if (err && self.logging) {
+      console.log('error trying to log user in');
+    }
+    if(typeof(callback) === 'function') {
+      callback(err, data, data.entities);
+    }
+  });
+}
+
+/*
+ * Creates activity and posts to group feed.
+ *
+ * options object: {user: user_entity, content: "activity content"}
+ *
+ * @public
+ * @method createGroupActivity
+ * @params {object} options
+ * @param {function} callback
+ * @returns {callback} callback(err, entity)
+ */
+Usergrid.Group.prototype.createGroupActivity = function(options, callback){
+  var user = options.user;
+  options = {
+    client: this._client,
+    data: {
+      actor: {
+        "displayName": user.get("username"),
+        "uuid": user.get("uuid"),
+        "username": user.get("username"),
+        "email": user.get("email"),
+        "picture": user.get("picture"),
+        "image": {
+          "duration": 0,
+          "height": 80,
+          "url": user.get("picture"),
+          "width": 80
+        },
+      },
+      "verb": "post",
+      "content": options.content,
+      "type": 'groups/' + this._path + '/activities'
+    }
+  }
+
+  var entity = new Usergrid.Entity(options);
+  entity.save(function(err, data) {
+    if (typeof(callback) === 'function') {
+      callback(err, entity);
+    }
+  });
+};

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9dfc5628/sdks/html5-javascript/lib/modules/util/Ajax.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/util/Ajax.js b/sdks/html5-javascript/lib/modules/util/Ajax.js
new file mode 100644
index 0000000..e8228ea
--- /dev/null
+++ b/sdks/html5-javascript/lib/modules/util/Ajax.js
@@ -0,0 +1,74 @@
+//Ajax
+(function() {
+    var name = 'Ajax', global = this, overwrittenName = global[name], exports;
+
+    Function.prototype.partial = function() {
+        var fn = this,b = [].slice.call(arguments);
+        return fn.bind(undefined, b);
+    }
+
+    exports = (function() {
+        function Ajax() {
+            this.logger=new global.Logger(name);
+            var self=this;
+            function encode(data) {
+                var result = "";
+                if (typeof data === "string") {
+                    result = data;
+                } else {
+                    var e = encodeURIComponent;
+                    for (var i in data) {
+                        if (data.hasOwnProperty(i)) {
+                            result += '&' + e(i) + '=' + e(data[i]);
+                        }
+                    }
+                }
+                return result;
+            }
+            var request = function(m, u, d) {
+                var p = new Promise(), timeout;
+                self.logger.time(m + ' ' + u);
+                self.logger.timeEnd(m + ' ' + u);
+                (function(xhr) {
+                    xhr.onreadystatechange = function() {
+                        this.readyState ^ 4 || (self.logger.timeEnd(m + ' ' + u), clearTimeout(timeout), p.done(null, this));
+                    };
+                    xhr.onerror=function(response){
+                        clearTimeout(timeout);
+                        p.done(response, null);
+                    }
+                    xhr.oncomplete=function(response){
+                        clearTimeout(timeout);
+                        self.info("%s request to %s returned %s", m, u, this.status );
+                    }
+                    xhr.open(m, u);
+                    if (d) {
+                        xhr.setRequestHeader("Content-Type", "application/json");
+                        xhr.setRequestHeader("Accept", "application/json");
+                    }
+                    timeout = setTimeout(function() {
+                        xhr.abort();
+                        p.done("API Call timed out.", null)
+                    }, 30000);
+                    //TODO stick that timeout in a config variable
+                    xhr.send(encode(d));
+                }(new XMLHttpRequest()));
+                return p;
+            };
+            this.request=request;
+            this.get = request.partial('GET');
+            this.post = request.partial('POST');
+            this.put = request.partial('PUT');
+            this.delete = request.partial('DELETE');
+        }
+        return new Ajax();
+    }());
+    global[name] =  exports;
+    global[name].noConflict = function() {
+        if(overwrittenName){
+            global[name] = overwrittenName;
+        }
+        return exports;
+    };
+    return global[name];
+}());

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9dfc5628/sdks/html5-javascript/lib/modules/util/Event.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/util/Event.js b/sdks/html5-javascript/lib/modules/util/Event.js
new file mode 100644
index 0000000..146d03e
--- /dev/null
+++ b/sdks/html5-javascript/lib/modules/util/Event.js
@@ -0,0 +1,33 @@
+var UsergridEventable	= function(){
+    throw Error("'UsergridEventable' is not intended to be invoked directly")
+}
+UsergridEventable.prototype	= {
+    bind	: function(event, fn){
+        this._events = this._events || {};
+        this._events[event] = this._events[event]	|| [];
+        this._events[event].push(fn);
+    },
+    unbind	: function(event, fn){
+        this._events = this._events || {};
+        if( event in this._events === false  )	return;
+        this._events[event].splice(this._events[event].indexOf(fn), 1);
+    },
+    trigger	: function(event /* , args... */){
+        this._events = this._events || {};
+        if( event in this._events === false  )	return;
+        for(var i = 0; i < this._events[event].length; i++){
+            this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1))
+        }
+    }
+};
+UsergridEventable.mixin	= function(destObject){
+    var props	= ['bind', 'unbind', 'trigger'];
+    for(var i = 0; i < props.length; i ++){
+        if(props[i] in destObject.prototype){
+            console.warn("overwriting '"+props[i]+"' on '"+destObject.name+"'.");
+            console.warn("the previous version can be found at '_"+props[i]+"' on '"+destObject.name+"'.");
+            destObject.prototype['_'+props[i]]=destObject.prototype[props[i]];
+        }
+        destObject.prototype[props[i]]	= UsergridEventable.prototype[props[i]];
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9dfc5628/sdks/html5-javascript/lib/modules/util/KeyStore.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/util/KeyStore.js b/sdks/html5-javascript/lib/modules/util/KeyStore.js
new file mode 100644
index 0000000..6a3ec1c
--- /dev/null
+++ b/sdks/html5-javascript/lib/modules/util/KeyStore.js
@@ -0,0 +1,199 @@
+//KeyStore
+var KeyStore = (function(global) {
+    global.indexedDB = global.indexedDB || global.mozIndexedDB || global.webkitIndexedDB || global.msIndexedDB;
+    // (Mozilla has never prefixed these objects, so we don't need global.mozIDB*)
+    global.IDBTransaction = global.IDBTransaction || global.webkitIDBTransaction || global.msIDBTransaction;
+    global.IDBKeyRange = global.IDBKeyRange || global.webkitIDBKeyRange || global.msIDBKeyRange;
+
+    var store="data",
+        keyPath="key",
+        database="test_keystore",
+        version= 8,
+        logger=new Logger('KeyStore');
+    var db, objectStore;
+    function createObjectStore(db, name, keyPath){
+        var p = new Promise(), objectStore;
+        try {
+            objectStore = event.currentTarget.transaction.objectStore(store);
+            //console.log(objectStore);
+            if (!objectStore) throw "not found";
+        } catch (e) {
+            logger.warn("creating new objectStore",e);
+            objectStore = db.createObjectStore(name, {
+                keyPath: keyPath
+            });
+        } finally {
+            objectStore.transaction.oncomplete = function(event) {
+                // console.info("created ObjectStore: '%s'", store);
+                p.done(null, objectStore);
+            };
+        }
+        return p;
+    }
+    function createObjectStoreIndex(objectStore, keyPath){
+        var p = new Promise(), index;
+        try {
+            index = objectStore.index(keyPath);
+            if (!index) throw "not found";
+        } catch (e) {
+            objectStore.createIndex(keyPath, keyPath, {
+                unique: true
+            });
+        } finally {
+            // objectStore.transaction.oncomplete = function(event) {
+            // console.info("created ObjectStore index: '%s'", keyPath);
+            p.done(null, db);
+            // };
+        }
+        return p;
+    }
+    function openDatabase(){
+        var p = new Promise();
+        var request = indexedDB.open(database, version);
+        request.onerror = function(event) {
+            console.error("internal keystore error: " + event.target.errorCode);
+            p.done(event.target, null);
+        };
+        request.onupgradeneeded = function(event) {
+            console.warn("upgrading internal keystore");
+            Promise.chain([
+                function(err, db){return createObjectStore(event.target.result, store, keyPath)},
+                function(err, objectStore){return createObjectStoreIndex(objectStore, keyPath)}
+            ])
+        };
+        request.onsuccess = function(event) {
+            //console.info("successfully opened database %s", event.target.result);
+            p.done(null, event.target.result);
+        };
+        return p;
+    }
+
+    function get(key) {
+        var p=new Promise();
+        openDatabase().then(function(err, db){
+            var item = db.transaction(store, "readwrite").objectStore(store).index(keyPath).get(key);
+            item.onsuccess = function(event) {
+                // console.log(event.target.result);
+                p.done(null, event.target.result);//request.result
+            };
+            item.onerror = function(event) {
+                p.done(event.target.error, null);
+            };
+        })
+        return p;
+    }
+    function save(key, value) {
+        var p=new Promise();
+        openDatabase().then(function(err, db){
+            var _store=db.transaction(store, "readwrite").objectStore(store);
+            var item = _store.index(keyPath).get(key);
+            item.onsuccess = function(event) {
+                //update
+                _store.put({key:key,value:value}).onsuccess=function(){
+                    console.log("put");
+                    p.done(null, event.target.result);//request.result
+                }
+            };
+            item.onerror = function(event) {
+                _store.post({key:key,value:value}).onsuccess=function(){
+                    console.log("post");
+                    p.done(event.target.error, null);//request.result
+                }
+                //p.done(event.target.error, event.target.result);
+            };
+        })
+        return p;
+    }
+    function remove(key) {
+        var p=new Promise();
+        openDatabase().then(function(err, db){
+            var item = db.transaction(store, "readwrite").objectStore(store).delete(key);
+            item.onsuccess = function(event) {
+                p.done(null, event.target.result);//request.result
+            };
+            item.onerror = function(event) {
+                p.done(event.target.error, event.target.result);
+            };
+        });
+        return p;
+    }
+    function post(key, value) {
+        var p=new Promise();
+        openDatabase().then(function(err, db){
+            var item = db.transaction(store, "readwrite").objectStore(store).add({key:key, value:value});
+            item.onsuccess = function(event) {
+                p.done(null, event.target.result);//request.result
+            };
+            item.onerror = function(event) {
+                p.done(event.target.error, event.target.result);
+            };
+        })
+        return p;
+    }
+    function put(key, value) {
+        var p=new Promise();
+        var item = db.transaction(store, "readwrite").objectStore(store).put(key, value);
+        item.onsuccess = function(event) {
+            p.done(null, event.target.result);//request.result
+        };
+        item.onerror = function(event) {
+            p.done(event.target.error, event.target.result);
+        };
+        return p;
+    }
+    /*
+     *
+     * {databases:[{
+     *      name:'name'
+     *     version:1,
+     *      'stores':[
+     *          {
+     *             name:'name',
+     *             options:{}
+     *          }
+     *      ]
+     *
+     * }]
+     *
+     */
+    function KeyStoreFactory(options){
+        this.data=options;
+        var self=this;
+        self.data.databases.forEach(function(database){
+            console.log(database);
+            //make DB request;
+        });
+    }
+    KeyStoreFactory.prototype=new UsergridEvent();
+    KeyStoreFactory.prototype.openDatabase=function(database){
+        var self=this, p=new Promise();
+        var request = indexedDB.open(database, version);
+        request.onerror = function(event) {
+            console.error("internal keystore error: " + event.target.errorCode);
+            p.done(event.target, null);
+        };
+        request.onupgradeneeded = function(event) {
+            console.warn("upgrading internal keystore");
+            throw new UsergridKeystoreDatabaseUpgradeNeededError("internal keystore requires upgrade");
+            /*Promise.chain([
+                function(err, db){return createObjectStore(event.target.result, store, keyPath)},
+                function(err, objectStore){return createObjectStoreIndex(objectStore, keyPath)}
+            ])*/
+        };
+        request.onsuccess = function(event) {
+            //console.info("successfully opened database %s", event.target.result);
+            p.done(null, event.target.result);
+        };
+        return p;
+    }
+    global['KeyStoreFactory']=KeyStoreFactory;
+    global['KeyStore']={
+        openDatabase:openDatabase,
+        get:get,
+        put:put,
+        post:post,
+        save:save,
+        remove:remove
+    };
+    return global['KeyStore'];
+}(this));

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9dfc5628/sdks/html5-javascript/lib/modules/util/Logger.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/util/Logger.js b/sdks/html5-javascript/lib/modules/util/Logger.js
new file mode 100644
index 0000000..f81a0e8
--- /dev/null
+++ b/sdks/html5-javascript/lib/modules/util/Logger.js
@@ -0,0 +1,68 @@
+//Logger
+(function() {
+    var name = 'Logger', global = this, overwrittenName = global[name], exports;
+    /* logging */
+    function Logger(name) {
+        this.logEnabled = true;
+        this.init(name, true);
+    }
+    Logger.METHODS=[
+        "log", "error", "warn", "info", "debug", "assert", "clear", "count",
+        "dir", "dirxml", "exception", "group", "groupCollapsed", "groupEnd",
+        "profile", "profileEnd", "table", "time", "timeEnd", "trace"
+    ];
+    Logger.prototype.init=function(name, logEnabled){
+        this.name=name||"UNKNOWN";
+        this.logEnabled=logEnabled||true;
+        var addMethod=function(method){this[method]=this.createLogMethod(method)}.bind(this);
+        Logger.METHODS.forEach(addMethod)
+    }
+    Logger.prototype.createLogMethod=function(method){
+        return Logger.prototype.log.bind(this, method);
+    }
+    Logger.prototype.prefix=function(method, args){
+        var prepend='['+method.toUpperCase()+']['+name+"]:\t";
+        if(['log', 'error', 'warn', 'info'].indexOf(method)!==-1){
+            if("string"===typeof args[0]){
+                args[0]=prepend+args[0];
+            }else{
+                args.unshift(prepend);
+            }
+        }
+        return args;
+    }
+    Logger.prototype.log=function(){
+        var args=[].slice.call(arguments);
+        method=args.shift();
+        if(Logger.METHODS.indexOf(method)===-1){
+            method="log";
+        }
+        if(!(this.logEnabled && console && console[method]))return;
+        args=this.prefix(method, args);
+        console[method].apply(console, args);
+    }
+    Logger.prototype.setLogEnabled=function(logEnabled){
+        this.logEnabled=logEnabled||true;
+    }
+
+    Logger.mixin	= function(destObject){
+        destObject.__logger=new Logger(destObject.name||"UNKNOWN");
+        var addMethod=function(method){
+            if(method in destObject.prototype){
+                console.warn("overwriting '"+method+"' on '"+destObject.name+"'.");
+                console.warn("the previous version can be found at '_"+method+"' on '"+destObject.name+"'.");
+                destObject.prototype['_'+method]=destObject.prototype[method];
+            }
+            destObject.prototype[method]=destObject.__logger.createLogMethod(method);
+        };
+        Logger.METHODS.forEach(addMethod)
+    }
+    global[name] =  Logger;
+    global[name].noConflict = function() {
+        if(overwrittenName){
+            global[name] = overwrittenName;
+        }
+        return Logger;
+    };
+    return global[name];
+}());

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9dfc5628/sdks/html5-javascript/lib/modules/util/Promise.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/util/Promise.js b/sdks/html5-javascript/lib/modules/util/Promise.js
new file mode 100644
index 0000000..e2d97a6
--- /dev/null
+++ b/sdks/html5-javascript/lib/modules/util/Promise.js
@@ -0,0 +1,83 @@
+//Promise
+(function(global) {
+    var name = 'Promise', overwrittenName = global[name], exports;
+
+        function Promise() {
+            this.complete = false;
+            this.error = null;
+            this.result = null;
+            this.callbacks = [];
+        }
+        Promise.prototype.create = function() {
+            return new Promise()
+        };
+        Promise.prototype.then = function(callback, context) {
+            var f = function() {
+                return callback.apply(context, arguments)
+            };
+            if (this.complete) {
+                f(this.error, this.result);
+            } else {
+                this.callbacks.push(f);
+            }
+        };
+        Promise.prototype.done = function(error, result) {
+            this.complete = true;
+            this.error = error;
+            this.result = result;
+            if(this.callbacks){
+                for (var i = 0; i < this.callbacks.length; i++) this.callbacks[i](error, result);
+                this.callbacks.length = 0;
+            }
+        };
+        Promise.join = function(promises) {
+            var p = new Promise(),
+                total = promises.length,
+                completed = 0,
+                errors = [],
+                results = [];
+
+            function notifier(i) {
+                return function(error, result) {
+                    completed += 1;
+                    errors[i] = error;
+                    results[i] = result;
+                    if (completed === total) {
+                        p.done(errors, results);
+                    }
+                };
+            }
+            for (var i = 0; i < total; i++) {
+                promises[i]().then(notifier(i));
+            }
+            return p;
+        };
+        Promise.chain = function(promises, error, result) {
+            var p = new Promise();
+            if (promises===null||promises.length === 0) {
+                p.done(error, result);
+            } else {
+                promises[0](error, result).then(function(res, err) {
+                    promises.splice(0, 1);
+                    //self.logger.info(promises.length)
+                    if(promises){
+                        Promise.chain(promises, res, err).then(function(r, e) {
+                            p.done(r, e);
+                        });
+                    }else{
+                        p.done(res, err);
+                    }
+                });
+            }
+            return p;
+        };
+
+    global[name] =  Promise;
+    global[name].noConflict = function() {
+        if(overwrittenName){
+            global[name] = overwrittenName;
+        }
+        return Promise;
+    };
+    return global[name];
+}(this));

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9dfc5628/sdks/html5-javascript/lib/modules/util/Storable.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/util/Storable.js b/sdks/html5-javascript/lib/modules/util/Storable.js
new file mode 100644
index 0000000..5c4da2e
--- /dev/null
+++ b/sdks/html5-javascript/lib/modules/util/Storable.js
@@ -0,0 +1,88 @@
+function UsergridStorable(storage, keyPrefix){
+    //throw Error("'UsergridStorable' is not intended to be invoked directly")
+}
+UsergridStorable.prototype.setStorage = function(storage) {
+    if(!(storage instanceof Storage)){
+        console.warn("parameter passed to 'setStorage' is not a browser Storage interface. using sessionStorage");
+        storage=sessionStorage;
+    }
+    return this._storage=storage;
+};
+UsergridStorable.prototype.getStorage = function() {
+    if(!(this._storage instanceof Storage)){
+        console.warn("parameter passed to 'setStorage' is not a browser Storage interface. using sessionStorage");
+        this._storage=sessionStorage;
+    }
+    return this._storage;
+};
+UsergridStorable.prototype.getStorageKey = function(key) {
+    if(!this._keyPrefix)this._keyPrefix='usergrid_js_sdk_';
+    return this._keyPrefix+key;
+};
+UsergridStorable.prototype.get=function(key){
+    var value;
+    if(arguments.length>1){
+        key=[].slice.call(arguments).reduce(function(p,c,i,a){
+            if(c instanceof Array){
+                p= p.concat(c);
+            }else{
+                p.push(c);
+            }
+            return p;
+        },[]);
+    }
+    if(this._storage instanceof Storage){
+        if(key instanceof Array){
+            var self=this;
+            value=key.map(function(k){return self.get(k)});
+        }else if("undefined" !== typeof key){
+            this[key]=JSON.parse(this.getStorage().getItem(this.getStorageKey(key)));
+            value=this[key];
+        }
+    }
+    return value;
+}
+UsergridStorable.prototype.set=function(key, value){
+    if(this._storage instanceof Storage){
+        if(value){
+            this[key]=JSON.stringify(value);
+            this.getStorage().setItem(this.getStorageKey(key),this[key]);
+        }else{
+            delete this[key];
+            this.getStorage().removeItem(this.getStorageKey(key));
+        }
+    }
+}
+/*
+ *  A public method to store the OAuth token for later use - uses localstorage if available
+ *
+ *  @method setToken
+ *  @public
+ *  @params {string} token
+ *  @return none
+ */
+UsergridStorable.prototype.setToken = function (token) {
+    return this.set('token', token);
+};
+
+/*
+ *  A public method to get the OAuth token
+ *
+ *  @method getToken
+ *  @public
+ *  @return {string} token
+ */
+UsergridStorable.prototype.getToken = function () {
+    return this.get('token');
+};
+UsergridStorable.mixin	= function(destObject){
+    var props	= ['getStorage', 'setStorage', 'getStorageKey', 'get', 'set', 'getToken', 'setToken'];
+    for(var i = 0; i < props.length; i ++){
+        if(props[i] in destObject.prototype){
+            console.warn("overwriting '"+props[i]+"' on '"+destObject.name+"'.");
+            console.warn("the previous version can be found at '_"+props[i]+"' on '"+destObject.name+"'.");
+            destObject.prototype['_'+props[i]]=destObject.prototype[props[i]];
+        }
+        destObject.prototype[props[i]]	= UsergridStorable.prototype[props[i]];
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9dfc5628/sdks/html5-javascript/tests/mocha/test.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/tests/mocha/test.js b/sdks/html5-javascript/tests/mocha/test.js
index b07463c..ec132a8 100644
--- a/sdks/html5-javascript/tests/mocha/test.js
+++ b/sdks/html5-javascript/tests/mocha/test.js
@@ -115,7 +115,7 @@ describe('Usergrid', function() {
 				usergridTestHarness(err, data, done, [
 
 					function(err, data) {
-						assert(data.entities.length >= 0);
+						assert(!data.entities);
 						console.log(JSON.stringify(data))
 					}
 				]);
@@ -129,7 +129,7 @@ describe('Usergrid', function() {
 				usergridTestHarness(err, data, done, [
 
 					function(err, data) {
-						assert(data.entities.length === 0)
+						assert(!data.entities)
 					}
 				]);
 			});
@@ -152,10 +152,10 @@ describe('Usergrid', function() {
 				type: 'dogs',
 				name: 'Rocky'
 			}
-
-			client.createEntity(options, function(err, data) {
+			client.createEntity(options, function(err, entity) {
 				assert(!err, "dog not created");
-				dog = data;
+				dog = entity;
+                console.log("AFTER CREATE", dog.get());
 				done();
 			});
 		});
@@ -165,6 +165,7 @@ describe('Usergrid', function() {
 				done();
 				return;
 			}
+            console.log("BEFORE FETCH", dog.get());
 			//once the dog is created, you can set single properties:
 			dog.fetch(function(err) {
 				assert(!err, "dog not fetched");
@@ -187,7 +188,7 @@ describe('Usergrid', function() {
 			}
 			//set is additive, so previously set properties are not overwritten
 			dog.set(data);
-
+            console.log("BEFORE SAVE", dog.get());
 			//finally, call save on the object to save it back to the database
 			dog.save(function(err) {
 				assert(!err, "dog not saved");


Mime
View raw message