UNPKG

built.io

Version:

SDK for Built.io Backend

575 lines (550 loc) 17.8 kB
var R = require('ramda'); var utility = require('./utilities/utility'); var instanceMethodBuilder = require('./utilities/instanceMethodBuilder')(); var Built = require('./built'); var dummyString = "$dummy" /** * @class Group * @classdesc * A Group is special type of field in Built.io Backend. The reason its named such is that its a set of fields grouped together. * Each group field has its own schema and can contain sub-groups. * @instance * @description This should be used to represent a 'group field' in your class. * This representation can then be passed to methods that accept a Built.Group structure as argument. * @param {String} fieldUid The Uid of the field in your class schema. * @param {object|Built.Group|Built.GroupMultiple} data Can be 1] Plain JavaScript object representing intial values 2] Instance of Built.Group (sub-group) 3] Instance of Built.GroupMultiple (sub-group) * @example * <h3><u>Constructor accepting Plain JavaScript Object</u></h3> * var person = Built.Group('person', { * name: 'John', * age: 22 * }); * <h3><u>Constructor accepting instance of Built.Group</u></h3> * // To construct structure in which a group field contains a sub-group use syntax shown below * var address = Built.Group('address', { * city: 'Mumbai', * state: 'Maharashtra' * }); * var person = Built.Group('person', address); * console.log(person.toJSON()) * @return {Group} */ var groupCons = module.exports = R.curry(function(field, value) { var data = {} if(!utility.isObject(value) || utility.isArray(value)){ throw new Error("Expected JavaScript Object found '"+ typeof(value)+"'") } // If value is Built.Group or Built.GroupMultiple we need to Deserialize if (value.toJSON) { value = value.toJSON() } // Deserializing sub structure(Example a property could be assigned a Built.Upsert object) // value = utility.deserializeObject(value) value = JSON.parse(JSON.stringify(value)) data[field] = value; var returnObj = { data : data, field : field, _isGroup : true, toJSON : function() { if(field === dummyString){ return data[field] } return data } } return instanceMethodBuilder.build(module.exports, returnObj) }) /** * Use this method to add a new key value pair in group. * <p class="text-danger"> * [Does not modify the Class Schema] * </p> * @memberof Group * @function set * @param {String} key The key for the new property * @param {String} value Value for the new property * @instance * @example * // 'blt5d4sample2633b' is a dummy Application API key * var group = Built.Group('person', { * name: 'John' * }) * group = group.set('age', 22) * @return {Group} */ module.exports.set = R.curry(function(key, value, group){ var newGroupField = getMixinedObject({}, group) newGroupField[key] = value return groupCons(group.field, newGroupField); }); instanceMethodBuilder.define('set', 3) /** * Gets the data for the given property * @memberof Group * @function get * @param {String} property The property whose data is to be fetched * @instance * @example * // 'blt5d4sample2633b' is a dummy Application API key * var group = Built.Group('person', { * name: 'John' * }) * console.log(group.get('name')) * @return {variable} */ module.exports.get = R.curry(function(grpField, group){ if(group.field === dummyString){ return group.toJSON()[grpField] } var data = group.toJSON() return data[group.field][grpField] }); instanceMethodBuilder.define('get', 2) /** * To set multiple key value pair in group use this method. * <p class="text-danger"> * [Does not modify the Class Schema] * </p> * @memberof Group * @function assign * @param {object} data Plain JavaScript object containing the new parameters * @instance * @example * // 'blt5d4sample2633b' is a dummy Application API key * var group = Built.Group('person', { * name: 'John' * }) * group = group.assign({ * age: 22, * gender: 'Male' * }) @return {Group} */ module.exports.assign = R.curry(function(jsObj, group){ var newGroupField = getMixinedObject({}, group) newGroupField = R.mixin(jsObj, newGroupField) return groupCons(group.field, newGroupField); }); instanceMethodBuilder.define('assign', 2) /** * To delete a property from group * <p class="text-danger"> * [Does not modify the Class Schema] * </p> * @memberof Group * @function remove * @param {String} key Key of the property to be removed * @instance * @example * // 'blt5d4sample2633b' is a dummy Application API key * var group = Built.Group('person', { * name: 'John', * age: 22 * }) * group = group.remove('age') * @return {Group} */ module.exports.remove = R.curry(function(key, group){ var newGroupField = getMixinedObject({}, group); if(newGroupField[key]) delete newGroupField[key] return groupCons(group.field, newGroupField); }) instanceMethodBuilder.define('remove', 2) var pushPullHelper = R.curry(function(operation,key, value, index, group) { // Value can be instance of GroupMultiple if(value.toJSON){ value = value.toJSON()[key] } //index = "" indicated append operation if(index !== "" && !utility.isNumber(index)){ throw new Error('Index value inappropriate'); } //operation can be PUSH or PULL var ops = utility.keyValue(key, utility.keyValue(operation, { data : value, index : index })); var mixedObject = getMixinedObject(ops, group) return groupCons(group.field, mixedObject); }) var referenceHelper = R.curry(function(fieldUid, value, group){ // deserilizing all objects if any are present value = JSON.parse(JSON.stringify(value)) var mixedObject = getMixinedObject({}, group) mixedObject[fieldUid] = value return groupCons(group.field, mixedObject) }) /** * Assigns referenced object's uids to a reference field of an object * @function setReference * @param {String} field_uid The uid of the field whose references are to be set * @param {String | Array} refValue Single uid/SDK object or Array of uids/SDK objects * @throws new Error('new Error('Uid not found')) * @instance * @memberof Group * @example * // 'blt5d4sample2633b' is a dummy Application API key * // 'Class('class_name').Object returns an 'Object' constructor * // 'project' is a uid of a class on Built.io Backend * var Project = Built.App('blt5d4sample2633b').Class('project').Object; * var project = Project(); * * var pm = Built.Group('project_manager', [{ * name: 'John', * age: 32 * }]) * * pm = pm.setReference("departments", ["blt124sample2122l", "blt311sample2324G"]) * * project * .addGroup(pm) * .save() * .then(function(project) { * console.log(project.toJSON()) * }) @return {Group} */ module.exports.setReference = R.curry(function(fieldUid, refValue, group) { var finalValue = refValue // For multiple if(utility.isArray(refValue)){ //check whether it is array of built objects if(refValue[0] && refValue[0].app){ finalValue = [] for (var i = 0; i < refValue.length; i++) { if(!refValue[i].getUid()){ throw new Error('Uid not found'); } finalValue.push(refValue[i].getUid()); } } } else { if(refValue.app) finalValue = refValue.getUid() } return referenceHelper(fieldUid, finalValue, group) }); instanceMethodBuilder.define('setReference',3); /** * Fires a query on Built.io Backend and the object that fulfills the query condition is assigned in the reference field. * Note: 'query' should be such that only one object should satisfy it, as Built.io Backend doesn't allow multipe references to be set using a 'query' * @function setReferenceWhere * @memberof Group * @param {String} field_uid The uid of the reference field * @param {object} query JavaScript object specifying the conditions * @example * // 'blt5d4sample2633b' is a dummy Application API key * // 'Class('class_name').Object returns an 'Object' constructor * // 'project' is a uid of a class on Built.io Backend * var Project = Built.App('blt5d4sample2633b').Class('project').Object; * var project = Project(); * * var pm = Built.Group('project_manager', [{ * name: 'John', * age: 32 * }]) * * pm = pm.setReferenceWhere("departments", { * department_type:"type2" * }) * * project * .addGroup(pm) * .save() * .then(function(project) { * console.log(project.toJSON()) * }) @return {Group} */ module.exports.setReferenceWhere = R.curry(function(fieldUid, conditions, group){ var whereClause = { WHERE: conditions } return referenceHelper(fieldUid, whereClause, group) }) instanceMethodBuilder.define('setReferenceWhere', 3) /** * This method will first create object(s) in referred class and then assigns its uids in the base class's referring field. * Example: Consider you have a reference field 'project' in class 'Bugs' class. This method would first create object(s) in 'Project' class * and then assign its 'uids' in 'Bugs' class's reference field 'project'. * @function setReferenceWithObject * @memberof Group * @param {String} field_uid The uid of the reference field or "." delimated string for 'group' fields as shown in example * @param {Object | Array} refObjs JSON object or an array of plain JavaScript objects or SDK object(s) * @example * // 'blt5d4sample2633b' is a dummy Application API key * // 'Class('class_name').Object returns an 'Object' constructor * // 'project' is a uid of a class on Built.io Backend * var Project = Built.App('blt5d4sample2633b').Class('project').Object; * var project = Project(); * * var pm = Built.Group('project_manager', [{ * name: 'John', * age: 32 * }]) * * pm = pm.setReferenceWithObject("departments", [{ * name:'Department A', * department_type: "type1" * },{ * name: "Department B", * department_type: "type2" * }]) * * project * .addGroup(pm) * .save() * .then(function(project) { * console.log(project.toJSON()) * }) @return {Group} */ module.exports.setReferenceWithObject = R.curry(function(fieldUid, refValue, group) { var finalValue = refValue if(utility.isArray(refValue)){ if(refValue[0] && refValue[0].app){ //check whether it is array of built objects finalValue = [] for (var i = 0; i < refValue.length; i++) { finalValue.push(refValue[i].toJSON()); } } } else { if(refValue.app) finalValue = refValue.toJSON() } return referenceHelper(fieldUid, finalValue, group) }); instanceMethodBuilder.define('setReferenceWithObject',3); /** * Use this method to perfom a upsert(update else insert) operation on reference field. * @function upsertForReference * @memberof Group * @param {String} field_uid Reference uid on which UPSERT is to be performed * @param {Built.Upsert} upsert Instance of Built.Upsert * @instance * @example * // 'blt5d4sample2633b' is a dummy Application API key * // 'Class('class_name').Object returns an 'Object' constructor * // 'project' is a uid of a class on Built.io Backend * var Project = Built.App('blt5d4sample2633b').Class('project').Object; * var project = Project(); * * // Creating instance of Built.Upsert to represent the upsert scenarios * var upsertDep = Built.Upsert([{ * condition:{ * name: "Department A1" * }, * replacement:{ * name: "Department A", * department_type: "type1" * } * },{ * condition:{ * name: "Department B1" * }, * replacement:{ * name: "Department B", * department_type: "type1" * } * }]); * * var pm = Built.Group('project_manager', { * name: 'John', * age: 32 * }); * * pm = pm.upsertForReference('departments', upsertDep) * * project * .addGroup(pm) * .save() * .then(function(project) { * console.log(project.toJSON()) * }) @return {Group} */ module.exports.upsertForReference = referenceHelper instanceMethodBuilder.define('upsertForReference', 3) /** * Pushes a value in the multiple field. The method ensures push operation to be atmoic * @memberof Group * @function pushValue * @param {String} fieldUid The uid of the field in which push operation needs to be performed * @param {object|Built.Group|Built.GroupMultiple} value Value that needs to be pushed * @instance * @example * // 'blt5d4sample2633b' is a dummy Application API key * // 'address' is field in person group which is marked multiple * var person = Built.Group('person', { * name: 'John', * age: 22 * }) * person = person.pushValue('address',["Mumbai"]) * * //Consider 'person' class has a group field which is marked multiple * //to push a new value in this field follow the example shown below * var person = Built.Group('person', { * name: 'John', * age: 22 * }) * var addressGrp = Built.Group("address",{ * city: 'Mumbai', * state: 'Maharashtra' * }) * person.pushValue("address", addressGrp) * @return {Group} */ module.exports.pushValue = function(key, value, group){ return pushPullHelper("PUSH", key, value, "", group) } instanceMethodBuilder.define('pushValue', 3) /** * Updates a value in the multiple field. The method ensures update operation to be atmoic * @memberof Group * @function updateValueAtIndex * @param {String} fieldUid The uid of the field in which update operation needs to be performed * @param {object|Built.Group|Built.GroupMultiple} value Value that needs to be updated * @param {Number} index Index at which update should be performed * @instance * @example * // 'blt5d4sample2633b' is a dummy Application API key * // 'address' is field in person group which is marked multiple * var person = Built.Group('person', { * name: 'John', * age: 22 * }) * person = person.updateValueAtIndex('address',["Mumbai"], 2) * * //Consider 'person' class has a group field which is marked multiple * //to push a new value in this field follow the example shown below * var person = Built.Group('person', { * name: 'John', * age: 22 * }) * var addressGrp = Built.Group("address",{ * city: 'Mumbai', * state: 'Maharashtra' * }) * person.updateValueAtIndex("address", addressGrp, 2) * @return {Group} */ module.exports.updateValueAtIndex = function(key, value, index, group){ return pushPullHelper("UPDATE", key, value, index, group) } instanceMethodBuilder.define('updateValueAtIndex', 4) /** * Adds a sub-group under the current group. * @memberof Group * @function addGroup * @param {Built.Group|Built.GroupMultiple} group Instance of Buillt.Group or Built.GroupMultiple * @instance * @example * // 'blt5d4sample2633b' is a dummy Application API key * var person = Built.Group('person', { * name: 'John', * age: 22 * }) * var address = Built.Group('address',{ * city: 'Mumbai', * area: 20000 * }) * person = person.addGroup(address) * @return {Group} */ module.exports.addGroup = function (anotherGrp, group) { var mixedObject = getMixinedObject(anotherGrp.toJSON(), group) return groupCons(group.field, mixedObject) } instanceMethodBuilder.define('addGroup', 2) /** * Pulls a matching value from the multiple field. The method ensures pull operation to be atmoic * @memberof Group * @function pullValue * @param {String} fieldUid The uid of the field in which push operation needs to be performed * @param {object|Built.Group|Built.GroupMultiple} conditions Value that needs to be pulled * @instance * @example * // 'blt5d4sample2633b' is a dummy Application API key * // 'address' is field in person group which is marked multiple * var person = Built.Group('person', { * name: 'John', * age: 22 * }) * person = person.pullValue('address',["Mumbai"]) * * //Consider 'person' class has a group field which is marked multiple * //to pull a value from this field follow the example shown below * var person = Built.Group('person', { * name: 'John', * age: 22 * }) * var addressGrp = Built.Group("address",{ * city: 'Mumbai', * state: 'Maharashtra' * }) * person.pullValue("address", addressGrp) * @return {Group} */ module.exports.pullValue = function(key, value, group){ return pushPullHelper("PULL", key, value, "", group) } instanceMethodBuilder.define('pullValue', 3) /** * Pulls a value from the multiple field at a given index. The method ensures pull operation to be atmoic * @memberof Group * @function pullValueAtIndex * @param {String} fieldUid The uid of the field in which push operation needs to be performed * @param {Number} index Index from which a value needs to be pulled * @instance * @example * // 'blt5d4sample2633b' is a dummy Application API key * // 'address' is field in person group which is marked multiple * var person = Built.Group('person', { * name: 'John', * age: 22 * }) * person = person.pullValueAtIndex('address', 1) * @return {Group} */ module.exports.pullValueAtIndex = function(key, index, group){ return pushPullHelper('PULL',key,"",index, group); } instanceMethodBuilder.define('pullValueAtIndex', 3) /** * Wraps a sub-group in Built.Group construct and returns it * @memberof Group * @function getGroupForKey * @param {field} fieldUid The uid of the sub group field * @instance * @example * // 'blt5d4sample2633b' is a dummy Application API key * // 'address' is a sub-group in person group. * var person = Built.Group('person', { * name: 'John', * age: 22, * address: { * city: "Mumbai", * state: "Maharasthra" * } * }) * * var addressGrp = person.getGroupForKey("address") * console.log(addressGrp.toJSON()) * @return {Group} */ module.exports.getGroupForKey = function(key, group){ var mixedData = getMixinedObject({}, group) if(!mixedData[key]) throw new Error("Key not found in group") if(utility.isArray(mixedData[key])) return Built.GroupMultiple(key, mixedData[key]) else return groupCons(key, mixedData[key]) } instanceMethodBuilder.define('getGroupForKey', 2) function getMixinedObject(toBeMixed, group){ toBeMixed = toBeMixed || {} return R.mixin(toBeMixed, group.data[group.field]); }