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/10 17:21:00 UTC
[03/12] Refactored individual modules for standard callback signature
and updated tests
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/usergrid.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/usergrid.js b/sdks/html5-javascript/usergrid.js
index 45696bf..98fa616 100644
--- a/sdks/html5-javascript/usergrid.js
+++ b/sdks/html5-javascript/usergrid.js
@@ -1,4 +1,4 @@
-/*! usergrid@0.11.0 2014-03-21 */
+/*! usergrid@0.11.0 2014-04-01 */
var UsergridEventable = function() {
throw Error("'UsergridEventable' is not intended to be invoked directly");
};
@@ -110,9 +110,6 @@ UsergridEventable.mixin = function(destObject) {
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);
@@ -208,8 +205,11 @@ UsergridEventable.mixin = function(destObject) {
self.logger.time(m + " " + u);
(function(xhr) {
xhr.onreadystatechange = function() {
- this.readyState ^ 4 || (self.logger.timeEnd(m + " " + u), clearTimeout(timeout),
- p.done(null, this));
+ if (this.readyState === 4) {
+ self.logger.timeEnd(m + " " + u);
+ clearTimeout(timeout);
+ p.done(null, this);
+ }
};
xhr.onerror = function(response) {
clearTimeout(timeout);
@@ -419,6 +419,7 @@ function doCallback(callback, params, context) {
//noinspection ThisExpressionReferencesGlobalObjectJS
(function(global) {
var name = "Usergrid", overwrittenName = global[name];
+ var VALID_REQUEST_METHODS = [ "GET", "POST", "PUT", "DELETE" ];
function Usergrid() {
this.logger = new Logger(name);
}
@@ -426,7 +427,6 @@ function doCallback(callback, params, context) {
//TODO actually implement this
return true;
};
- var VALID_REQUEST_METHODS = [ "GET", "POST", "PUT", "DELETE" ];
Usergrid.Request = function(method, endpoint, query_params, data, callback) {
var p = new Promise();
/*
@@ -519,14 +519,19 @@ function doCallback(callback, params, context) {
});
switch (this.statusGroup) {
case 200:
+ //success
this.success = true;
break;
case 400:
- case 500:
- case 300:
- case 100:
- default:
+ //user error
+ case 500:
+ //server error
+ case 300:
+ //cache and redirects
+ case 100:
+ //upgrade
+ default:
//server error
this.success = false;
break;
@@ -539,11 +544,11 @@ function doCallback(callback, params, context) {
return p;
};
Usergrid.Response.prototype.getEntities = function() {
- var entities = [];
+ var entities;
if (this.success) {
entities = this.data ? this.data.entities : this.entities;
}
- return entities;
+ return entities || [];
};
Usergrid.Response.prototype.getEntity = function() {
var entities = this.getEntities();
@@ -562,6 +567,7 @@ function doCallback(callback, params, context) {
(function() {
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";
@@ -578,11 +584,6 @@ function doCallback(callback, params, context) {
//other options
this.buildCurl = options.buildCurl || false;
this.logging = options.logging || false;
- //timeout and callbacks
- this._callTimeout = options.callTimeout || 3e4;
- //default to 30 seconds
- this._callTimeoutCallback = options.callTimeoutCallback || null;
- this.logoutCallback = options.logoutCallback || null;
};
/*
* Main function for making requests to the API. Can be called directly.
@@ -601,7 +602,6 @@ function doCallback(callback, params, context) {
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.request = function(options, callback) {
- var self = this;
var method = options.method || "GET";
var endpoint = options.endpoint;
var body = options.body || {};
@@ -612,11 +612,11 @@ function doCallback(callback, params, context) {
var appName = this.get("appName");
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);
+ /*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();
}
@@ -631,11 +631,16 @@ function doCallback(callback, params, context) {
if (default_qs) {
qs = propCopy(qs, default_qs);
}
+ var self = this;
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();
+ /*if (AUTH_ERRORS.indexOf(response.error) !== -1) {
+ return logoutCallback();
+ }*/
+ if (err) {
+ doCallback(callback, [ err, response, self ], self);
+ } else {
+ doCallback(callback, [ null, response, self ], self);
}
- doCallback(callback, [ err, response ]);
});
};
/*
@@ -670,14 +675,13 @@ function doCallback(callback, params, context) {
* @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);
});
};
/*
@@ -692,14 +696,12 @@ function doCallback(callback, params, context) {
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.createEntity = function(options, callback) {
- var entity_data = {
+ var entity = new Usergrid.Entity({
client: this,
data: options
- };
- var entity = new Usergrid.Entity(entity_data);
- var self = this;
- entity.save(function(err, data) {
- doCallback(callback, [ err, entity, data ]);
+ });
+ entity.save(function(err, response) {
+ doCallback(callback, [ err, response, entity ], entity);
});
};
/*
@@ -717,13 +719,12 @@ function doCallback(callback, params, context) {
* @return {callback} callback(err, data)
*/
Usergrid.Client.prototype.getEntity = function(options, callback) {
- var options = {
+ var entity = new Usergrid.Entity({
client: this,
data: options
- };
- var entity = new Usergrid.Entity(options);
- entity.fetch(function(err, data) {
- doCallback(callback, [ err, entity, data ]);
+ });
+ entity.fetch(function(err, response) {
+ doCallback(callback, [ err, response, entity ], entity);
});
};
/*
@@ -758,8 +759,9 @@ function doCallback(callback, params, context) {
*/
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);
});
};
/*
@@ -837,13 +839,13 @@ function doCallback(callback, params, context) {
*/
Usergrid.Client.prototype.createUserActivity = function(user, options, callback) {
options.type = "users/" + user + "/activities";
- var options = {
+ 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 ]);
});
};
/*
@@ -1168,24 +1170,24 @@ function doCallback(callback, params, context) {
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
- */
+ * 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) {
+ if (revokeAll === true) {
options.endpoint = "users/" + username + "/revoketokens";
- } else if (token == null) {
+ } else if (token === null) {
options.endpoint = "users/" + username + "/revoketoken?token=" + this.getToken();
} else {
options.endpoint = "users/" + username + "/revoketoken?token=" + token;
@@ -1197,7 +1199,7 @@ function doCallback(callback, params, context) {
}
doCallback(callback, [ err, data, null ], self);
} else {
- if (revokeAll == true) {
+ if (revokeAll === true) {
console.log("all user tokens invalidated");
} else {
console.log("token invalidated");
@@ -1207,23 +1209,23 @@ function doCallback(callback, params, context) {
});
};
/*
- * 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
- */
+ * 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) {
+ 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) {
+ if (revokeAll === true || token === this.getToken() || token === null) {
this.setToken(null);
}
}
@@ -1288,8 +1290,11 @@ var ENTITY_SYSTEM_PROPERTIES = [ "metadata", "created", "modified", "oldpassword
* @param {object} options {client:client, data:{'type':'collection_type', uuid:'uuid', 'key':'value'}}
*/
Usergrid.Entity = function(options) {
+ this._data = {};
+ this._client = undefined;
if (options) {
- this._data = options.data || {};
+ //this._data = options.data || {};
+ this.set(options.data || {});
this._client = options.client || {};
}
};
@@ -1391,22 +1396,16 @@ Usergrid.Entity.prototype.set = function(key, value) {
};
Usergrid.Entity.prototype.getEndpoint = function() {
- var type = this.get("type"), name, endpoint;
- var nameProperties = [ "uuid", "name" ];
+ var type = this.get("type"), nameProperties = [ "uuid", "name" ], name;
if (type === undefined) {
throw new UsergridError("cannot fetch entity, no entity type specified", "no_type_specified");
- } else if (type === "users" || type === "user") {
+ } else if (/^users?$/.test(type)) {
nameProperties.unshift("username");
}
- var names = this.get(nameProperties).filter(function(x) {
- return x != null && "undefined" !== typeof x;
- });
- if (names.length === 0) {
- return type;
- } else {
- name = names.shift();
- }
- return [ type, name ].join("/");
+ name = this.get(nameProperties).filter(function(x) {
+ return x !== null && "undefined" !== typeof x;
+ }).shift();
+ return name ? [ type, name ].join("/") : type;
};
/*
@@ -1415,77 +1414,83 @@ Usergrid.Entity.prototype.getEndpoint = function() {
* @method save
* @public
* @param {function} callback
- * @return {callback} callback(err, data)
+ * @return {callback} callback(err, response, self)
*/
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"), options = {
+ var self = this, type = this.get("type"), method = "POST", entityId = this.get("uuid"), changePassword, entityData = this.get(), options = {
method: method,
endpoint: type
};
- //update the entity
+ //update the entity if the UUID is present
if (entityId) {
options.method = "PUT";
options.endpoint += "/" + entityId;
}
//remove system-specific properties
- Object.keys(entityData).filter(function(key) {
+ options.body = Object.keys(entityData).filter(function(key) {
return ENTITY_SYSTEM_PROPERTIES.indexOf(key) === -1;
- }).forEach(function(key) {
+ }).reduce(function(data, key) {
data[key] = entityData[key];
- });
- options.body = data;
- //save the entity first
- this._client.request(options, function(err, response) {
+ return data;
+ }, {});
+ self._client.request(options, function(err, response) {
var entity = response.getEntity();
if (entity) {
self.set(entity);
self.set("type", /^\//.test(response.path) ? response.path.substring(1) : response.path);
}
- // 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");
- doCallback(callback, [ err, response, self ]);
- } else if (/^users?/.test(self.get("type")) && oldpassword && newpassword) {
- //if this is a user, update the password if it has been specified;
- //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 options = {
- method: "PUT",
- endpoint: type + "/" + self.get("uuid") + "/password",
- body: {
- uuid: self.get("uuid"),
- username: self.get("username"),
- password: password,
- oldpassword: oldpassword,
- newpassword: newpassword
- }
- };
- 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({
- password: null,
- oldpassword: null,
- newpassword: null
- });
- doCallback(callback, [ err, data, self ]);
- });
- } else {
- doCallback(callback, [ err, response, self ]);
}
+ doCallback(callback, [ err, response, self ], self);
});
};
/*
+ *
+ * Updates the user's password
+ */
+Usergrid.Entity.prototype.changePassword = function(oldpassword, password, newpassword, callback) {
+ //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 self = this;
+ if ("function" === typeof oldpassword && callback === undefined) {
+ callback = oldpassword;
+ oldpassword = self.get("oldpassword");
+ password = self.get("password");
+ newpassword = self.get("newpassword");
+ }
+ //clear out pw info if present
+ self.set({
+ password: null,
+ oldpassword: null,
+ newpassword: null
+ });
+ if (/^users?$/.test(self.get("type")) && oldpassword && newpassword) {
+ var options = {
+ method: "PUT",
+ endpoint: "users/" + self.get("uuid") + "/password",
+ body: {
+ uuid: self.get("uuid"),
+ username: self.get("username"),
+ password: password,
+ oldpassword: oldpassword,
+ newpassword: newpassword
+ }
+ };
+ self._client.request(options, function(err, response) {
+ 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
+ doCallback(callback, [ err, response, self ], self);
+ });
+ } else {
+ throw new UsergridInvalidArgumentError("Invalid arguments passed to 'changePassword'");
+ }
+};
+
+/*
* refreshes the entity by making a GET call back to the database
*
* @method fetch
@@ -1505,7 +1510,7 @@ Usergrid.Entity.prototype.fetch = function(callback) {
if (entity) {
self.set(entity);
}
- doCallback(callback, [ err, entity, self ]);
+ doCallback(callback, [ err, response, self ], self);
});
};
@@ -1526,11 +1531,11 @@ Usergrid.Entity.prototype.destroy = function(callback) {
method: "DELETE",
endpoint: endpoint
};
- this._client.request(options, function(err, data) {
+ this._client.request(options, function(err, response) {
if (!err) {
self.set(null);
}
- doCallback(callback, [ err, data ]);
+ doCallback(callback, [ err, response, self ], self);
});
};
@@ -1546,44 +1551,63 @@ Usergrid.Entity.prototype.destroy = function(callback) {
*
*/
Usergrid.Entity.prototype.connect = function(connection, entity, callback) {
+ this.addOrRemoveConnection("POST", connection, entity, callback);
+};
+
+/*
+ * 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) {
+ this.addOrRemoveConnection("DELETE", connection, entity, callback);
+};
+
+/*
+ * adds or removes a connection between two entities
+ *
+ * @method addOrRemoveConnection
+ * @public
+ * @param {string} method
+ * @param {string} connection
+ * @param {object} entity
+ * @param {function} callback
+ * @return {callback} callback(err, data)
+ *
+ */
+Usergrid.Entity.prototype.addOrRemoveConnection = function(method, connection, entity, callback) {
var self = this;
- var error;
+ if ([ "POST", "DELETE" ].indexOf(method.toUpperCase()) == -1) {
+ throw new UsergridInvalidArgumentError("invalid method for connection call. must be 'POST' or 'DELETE'");
+ }
//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);
- }
- doCallback(callback, [ true, error ], self);
- }
- return;
+ throw new UsergridInvalidArgumentError("connectee could not be identified");
}
//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);
- }
- doCallback(callback, [ true, error ], self);
- }
- return;
+ throw new UsergridInvalidArgumentError("connector could not be identified");
}
- var endpoint = connectorType + "/" + connector + "/" + connection + "/" + connecteeType + "/" + connectee;
+ var endpoint = [ connectorType, connector, connection, connecteeType, connectee ].join("/");
var options = {
- method: "POST",
+ method: method,
endpoint: endpoint
};
- this._client.request(options, function(err, data) {
+ this._client.request(options, function(err, response) {
if (err && self._client.logging) {
- console.log("entity could not be connected");
+ console.log("There was an error with the connection call");
}
- doCallback(callback, [ err, data ], self);
+ doCallback(callback, [ err, response, self ], self);
});
};
@@ -1777,7 +1801,7 @@ Usergrid.Entity.prototype.getPermissions = function(callback) {
ops_part = parts[0];
path_part = parts[1];
}
- ops_part.replace("*", "get,post,put,delete");
+ ops_part = ops_part.replace("*", "get,post,put,delete");
var ops = ops_part.split(",");
var ops_object = {};
ops_object.get = "no";
@@ -1800,69 +1824,15 @@ Usergrid.Entity.prototype.getPermissions = function(callback) {
};
/*
- * 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);
- }
- doCallback(callback, [ true, error ], self);
- }
- 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);
- }
- doCallback(callback, [ true, error ], self);
- }
- 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");
- }
- doCallback(callback, [ err, data ], self);
- });
-};
-
-/*
* The Collection class models Usergrid Collections. It essentially
* acts as a container for holding Entity objects, while providing
* additional funcitonality such as paging, and saving
*
* @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;
this._type = options.type;
@@ -1885,10 +1855,6 @@ Usergrid.Collection = function(options, callback) {
}
}
}
- if (callback) {
- //populate the collection
- this.fetch(callback);
- }
};
/*
@@ -1930,24 +1896,26 @@ Usergrid.Collection.prototype.serialize = function() {
return data;
};
-Usergrid.Collection.prototype.addCollection = function(collectionName, options, callback) {
- self = this;
- options.client = this._client;
- var collection = new Usergrid.Collection(options, function(err, data) {
- if (typeof callback === "function") {
- collection.resetEntityPointer();
- while (collection.hasNextEntity()) {
- var user = collection.getNextEntity();
- var email = user.get("email");
- var image = self._client.getDisplayImage(user.get("email"), user.get("picture"));
- user._portal_image_icon = image;
- }
- self[collectionName] = collection;
- doCallback(callback, [ err, collection ], self);
- }
- });
-};
+//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) {
+ if (typeof(callback) === 'function') {
+
+ collection.resetEntityPointer();
+ while(collection.hasNextEntity()) {
+ var user = collection.getNextEntity();
+ var email = user.get('email');
+ var image = self._client.getDisplayImage(user.get('email'), user.get('picture'));
+ user._portal_image_icon = image;
+ }
+ self[collectionName] = collection;
+ doCallback(callback, [err, collection], self);
+ }
+ });
+};*/
/*
* Populates the collection from the server
*
@@ -1969,42 +1937,27 @@ Usergrid.Collection.prototype.fetch = function(callback) {
endpoint: this._type,
qs: this.qs
};
- this._client.request(options, function(err, data) {
+ 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);
});
};
@@ -2016,17 +1969,16 @@ 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);
});
};
@@ -2046,30 +1998,58 @@ Usergrid.Collection.prototype.addExistingEntity = function(entity) {
*/
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);
}
+ //remove entity from the local store
+ self.removeEntity(entity);
});
- //remove entity from the local store
- this.removeEntity(entity);
};
+/*
+ * 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 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;
+ var removedEntity = this.getEntityByCriteria(function(item) {
+ return entity.uuid === item.get("uuid");
+ });
+ delete this._list[this._list.indexOf(removedEntity)];
+ return removedEntity;
};
/*
@@ -2081,22 +2061,23 @@ Usergrid.Collection.prototype.removeEntity = function(entity) {
* @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);
- }
+ 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);
}
- //get the entity from the database
- var options = {
- data: {
- type: this._type,
- uuid: uuid
- },
- client: this._client
- };
- var entity = new Usergrid.Entity(options);
- entity.fetch(callback);
};
/*
@@ -2334,40 +2315,33 @@ Usergrid.Group.prototype.fetch = function(callback) {
method: "GET",
endpoint: memberEndpoint
};
- this._client.request(groupOptions, function(err, data) {
+ this._client.request(groupOptions, function(err, response) {
if (err) {
if (self._client.logging) {
console.log("error getting group");
}
- doCallback(callback, [ err, data ], self);
+ doCallback(callback, [ err, response ], self);
} else {
- if (data.entities && data.entities.length) {
- var groupData = data.entities[0];
- self._data = groupData || {};
- self._client.request(memberOptions, function(err, data) {
+ var entities = response.getEntities();
+ if (entities && entities.length) {
+ var groupresponse = entities.shift();
+ //self._response = groupresponse || {};
+ self._client.request(memberOptions, function(err, response) {
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);
- }
- }
- }
+ self._list = response.getEntities().filter(function(entity) {
+ return isUUID(entity.uuid);
+ }).map(function(entity) {
+ return new Usergrid.Entity({
+ type: entity.type,
+ client: self._client,
+ uuid: entity.uuid,
+ response: entity
+ });
+ });
}
- doCallback(callback, [ err, data, self._list ], self);
+ doCallback(callback, [ err, response, self ], self);
});
}
}
@@ -2383,11 +2357,12 @@ Usergrid.Group.prototype.fetch = function(callback) {
* @return {function} callback(err, data);
*/
Usergrid.Group.prototype.members = function(callback) {
- doCallback(callback, [ null, this._list ], this);
+ //doCallback(callback, [null, this._list, this], this);
+ return this._list;
};
/*
- * Adds a user to the group, and refreshes the group object.
+ * Adds an existing user to the group, and refreshes the group object.
*
* Options object: {user: user_entity}
*
@@ -2399,17 +2374,21 @@ Usergrid.Group.prototype.members = function(callback) {
*/
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) {
- doCallback(callback, [ error, data, data.entities ], self);
- } else {
- self.fetch(callback);
- }
- });
+ if (options.user) {
+ options = {
+ method: "POST",
+ endpoint: "groups/" + this._path + "/users/" + options.user.get("username")
+ };
+ this._client.request(options, function(error, response) {
+ if (error) {
+ doCallback(callback, [ error, response, self ], self);
+ } else {
+ self.fetch(callback);
+ }
+ });
+ } else {
+ doCallback(callback, [ new UsergridError("no user specified", "no_user_specified"), null, this ], this);
+ }
};
/*
@@ -2425,17 +2404,21 @@ Usergrid.Group.prototype.add = function(options, callback) {
*/
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) {
- doCallback(callback, [ error, data ], self);
- } else {
- self.fetch(callback);
- }
- });
+ if (options.user) {
+ options = {
+ method: "DELETE",
+ endpoint: "groups/" + this._path + "/users/" + options.user.get("username")
+ };
+ this._client.request(options, function(error, response) {
+ if (error) {
+ doCallback(callback, [ error, response, self ], self);
+ } else {
+ self.fetch(callback);
+ }
+ });
+ } else {
+ doCallback(callback, [ new UsergridError("no user specified", "no_user_specified"), null, this ], this);
+ }
};
/*
@@ -2448,16 +2431,12 @@ Usergrid.Group.prototype.remove = function(options, callback) {
*/
Usergrid.Group.prototype.feed = function(callback) {
var self = this;
- var endpoint = "groups/" + this._path + "/feed";
var options = {
method: "GET",
- endpoint: endpoint
+ endpoint: "groups/" + this._path + "/feed"
};
- this._client.request(options, function(err, data) {
- if (err && self.logging) {
- console.log("error trying to log user in");
- }
- doCallback(callback, [ err, data, data.entities ], self);
+ this._client.request(options, function(err, response) {
+ doCallback(callback, [ err, response, self ], self);
});
};
@@ -2473,8 +2452,9 @@ Usergrid.Group.prototype.feed = function(callback) {
* @returns {callback} callback(err, entity)
*/
Usergrid.Group.prototype.createGroupActivity = function(options, callback) {
+ var self = this;
var user = options.user;
- options = {
+ var entity = new Usergrid.Entity({
client: this._client,
data: {
actor: {
@@ -2494,10 +2474,9 @@ Usergrid.Group.prototype.createGroupActivity = function(options, callback) {
content: options.content,
type: "groups/" + this._path + "/activities"
}
- };
- var entity = new Usergrid.Entity(options);
- entity.save(function(err, data) {
- doCallback(callback, [ err, entity ]);
+ });
+ entity.save(function(err, response, entity) {
+ doCallback(callback, [ err, response, self ]);
});
};
@@ -2509,14 +2488,14 @@ Usergrid.Group.prototype.createGroupActivity = function(options, callback) {
* @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.type = "events";
this._data.counters = options.counters || {};
- doCallback(callback, [ false, self ], self);
+ doCallback(callback, [ false, this ], this);
};
var COUNTER_RESOLUTIONS = [ "all", "minute", "five_minutes", "half_hour", "hour", "six_day", "day", "week", "month" ];
@@ -2555,9 +2534,9 @@ Usergrid.Counter.prototype.fetch = function(callback) {
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);
+ return doCallback(callback, [ new UsergridInvalidArgumentError("'name' for increment, decrement must be a number"), null, self ], self);
} else if (isNaN(value)) {
- return doCallback(callback, [ true, "'value' for increment, decrement must be a number" ], self);
+ 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);
@@ -2624,42 +2603,8 @@ Usergrid.Counter.prototype.getData = function(options, callback) {
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());
- }
- }
+ 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) {
@@ -2677,10 +2622,31 @@ Usergrid.Counter.prototype.getData = function(options, callback) {
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;
+}
+
/*
* A class to model a Usergrid folder.
*
@@ -2698,16 +2664,16 @@ Usergrid.Folder = function(options, callback) {
return !(required in self._data);
});
if (missingData) {
- return doCallback(callback, [ true, new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties.") ], self);
+ return doCallback(callback, [ new UsergridInvalidArgumentError("Invalid asset data: 'name', 'owner', and 'path' are required properties."), null, self ], self);
}
- self.save(function(err, data) {
+ self.save(function(err, response) {
if (err) {
- doCallback(callback, [ true, new UsergridError(data) ], self);
+ doCallback(callback, [ new UsergridError(response), response, self ], self);
} else {
- if (data && data.entities && data.entities.length) {
- self.set(data.entities[0]);
+ if (response && response.entities && response.entities.length) {
+ self.set(response.entities[0]);
}
- doCallback(callback, [ false, self ], self);
+ doCallback(callback, [ null, response, self ], self);
}
});
};
@@ -2731,15 +2697,15 @@ Usergrid.Folder.prototype.fetch = function(callback) {
console.log("self", self.get());
console.log("data", data);
if (!err) {
- self.getAssets(function(err, data) {
+ self.getAssets(function(err, response) {
if (err) {
- doCallback(callback, [ true, new UsergridError(data) ], self);
+ doCallback(callback, [ new UsergridError(response), resonse, self ], self);
} else {
doCallback(callback, [ null, self ], self);
}
});
} else {
- doCallback(callback, [ true, new UsergridError(data) ], self);
+ doCallback(callback, [ null, data, self ], self);
}
});
};
@@ -2779,7 +2745,7 @@ Usergrid.Folder.prototype.addAsset = function(options, callback) {
if (asset && asset instanceof Usergrid.Entity) {
asset.fetch(function(err, data) {
if (err) {
- doCallback(callback, [ err, new UsergridError(data) ], self);
+ doCallback(callback, [ new UsergridError(data), data, self ], self);
} else {
var endpoint = [ "folders", self.get("uuid"), "assets", asset.get("uuid") ].join("/");
var options = {
@@ -2792,9 +2758,7 @@ Usergrid.Folder.prototype.addAsset = function(options, callback) {
}
} else {
//nothing to add
- doCallback(callback, [ true, {
- error_description: "No asset specified"
- } ], self);
+ doCallback(callback, [ new UsergridInvalidArgumentError("No asset specified"), null, self ], self);
}
};
@@ -2832,13 +2796,17 @@ Usergrid.Folder.prototype.removeAsset = function(options, callback) {
self._client.request({
method: "DELETE",
endpoint: endpoint
- }, callback);
+ }, function(err, response) {
+ if (err) {
+ doCallback(callback, [ new UsergridError(response), response, self ], self);
+ } else {
+ doCallback(callback, [ null, response, self ], self);
+ }
+ });
}
} else {
//nothing to add
- doCallback(callback, [ true, {
- error_description: "No asset specified"
- } ], self);
+ doCallback(callback, [ new UsergridInvalidArgumentError("No asset specified"), null, self ], self);
}
};
@@ -2886,18 +2854,19 @@ Usergrid.Asset = function(options, callback) {
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, [ 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);
}
- doCallback(callback, [ false, self ], self);
- }
- });
+ });
+ }
};
/*
@@ -2921,17 +2890,24 @@ 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);
}
};
@@ -2945,7 +2921,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("/");
@@ -2958,9 +2935,9 @@ Usergrid.Asset.prototype.upload = function(data, callback) {
};
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();
@@ -2990,11 +2967,11 @@ 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();
};
@@ -3072,7 +3049,7 @@ Usergrid.Asset.prototype.download = function(callback) {
UsergridHTTPResponseError.prototype = new UsergridError();
function UsergridInvalidHTTPMethodError(message, name, timestamp, duration, exception) {
this.message = message;
- this.name = name;
+ this.name = name || "invalid_http_method";
this.timestamp = timestamp || Date.now();
this.duration = duration || 0;
this.exception = exception;
@@ -3080,12 +3057,20 @@ Usergrid.Asset.prototype.download = function(callback) {
UsergridInvalidHTTPMethodError.prototype = new UsergridError();
function UsergridInvalidURIError(message, name, timestamp, duration, exception) {
this.message = message;
- this.name = name;
+ this.name = name || "invalid_uri";
this.timestamp = timestamp || Date.now();
this.duration = duration || 0;
this.exception = exception;
}
UsergridInvalidURIError.prototype = new UsergridError();
+ function UsergridInvalidArgumentError(message, name, timestamp, duration, exception) {
+ this.message = message;
+ this.name = name || "invalid_argument";
+ this.timestamp = timestamp || Date.now();
+ this.duration = duration || 0;
+ this.exception = exception;
+ }
+ UsergridInvalidArgumentError.prototype = new UsergridError();
function UsergridKeystoreDatabaseUpgradeNeededError(message, name, timestamp, duration, exception) {
this.message = message;
this.name = name;
@@ -3094,10 +3079,11 @@ Usergrid.Asset.prototype.download = function(callback) {
this.exception = exception;
}
UsergridKeystoreDatabaseUpgradeNeededError.prototype = new UsergridError();
- global["UsergridHTTPResponseError"] = UsergridHTTPResponseError;
- global["UsergridInvalidHTTPMethodError"] = UsergridInvalidHTTPMethodError;
- global["UsergridInvalidURIError"] = UsergridInvalidURIError;
- global["UsergridKeystoreDatabaseUpgradeNeededError"] = UsergridKeystoreDatabaseUpgradeNeededError;
+ global.UsergridHTTPResponseError = UsergridHTTPResponseError;
+ global.UsergridInvalidHTTPMethodError = UsergridInvalidHTTPMethodError;
+ global.UsergridInvalidURIError = UsergridInvalidURIError;
+ global.UsergridInvalidArgumentError = UsergridInvalidArgumentError;
+ global.UsergridKeystoreDatabaseUpgradeNeededError = UsergridKeystoreDatabaseUpgradeNeededError;
global[name] = UsergridError;
if (short !== undefined) {
//noinspection JSUnusedAssignment