Adding floCloudAPI

floCloudAPI has methods to send application data, request application data, reset or update object data.
This commit is contained in:
sairajzero 2019-11-19 20:11:32 +05:30
parent d79d54b400
commit 289089d972

View File

@ -5914,5 +5914,412 @@
}
}
</script>
<script>
//For diff base
/*
Functions available:
diff(originalObj, updatedObj) returns the difference of the original and updated objects
addedDiff(original, updatedObj) returns only the values added to the updated object
deletedDiff(original, updatedObj) returns only the values deleted in the updated object
updatedDiff(original, updatedObj) returns only the values that have been changed in the updated object
detailedDiff(original, updatedObj) returns an object with the added, deleted and updated differences
mergeRecurcive(original, diff) this will get you a new object that will merge all the changes between the old object and the new object
*/
const isDate = d => d instanceof Date;
const isEmpty = o => Object.keys(o).length === 0;
const isObject = o => o != null && typeof o === 'object';
const properObject = o => isObject(o) && !o.hasOwnProperty ? { ...o } : o;
const getLargerArray = (l, r) => l.length > r.length ? l : r;
const preserve = (diff, left, right) => {
if (!isObject(diff)) return diff;
return Object.keys(diff).reduce((acc, key) => {
const leftArray = left[key];
const rightArray = right[key];
if (Array.isArray(leftArray) && Array.isArray(rightArray)) {
const array = [...getLargerArray(leftArray, rightArray)];
return {
...acc,
[key]: array.reduce((acc2, item, index) => {
if (diff[key].hasOwnProperty(index)) {
acc2[index] = preserve(diff[key][index], leftArray[index], rightArray[index]); // diff recurse and check for nested arrays
return acc2;
}
delete acc2[index]; // no diff aka empty
return acc2;
}, array)
};
}
return {
...acc,
[key]: diff[key]
};
}, {});
};
const updatedDiff = (lhs, rhs) => {
if (lhs === rhs) return {};
if (!isObject(lhs) || !isObject(rhs)) return rhs;
const l = properObject(lhs);
const r = properObject(rhs);
if (isDate(l) || isDate(r)) {
if (l.valueOf() == r.valueOf()) return {};
return r;
}
return Object.keys(r).reduce((acc, key) => {
if (l.hasOwnProperty(key)) {
const difference = updatedDiff(l[key], r[key]);
if (isObject(difference) && isEmpty(difference) && !isDate(difference)) return acc;
return { ...acc, [key]: difference };
}
return acc;
}, {});
};
const diff = (lhs, rhs) => {
if (lhs === rhs) return {}; // equal return no diff
if (!isObject(lhs) || !isObject(rhs)) return rhs; // return updated rhs
const l = properObject(lhs);
const r = properObject(rhs);
const deletedValues = Object.keys(l).reduce((acc, key) => {
return r.hasOwnProperty(key) ? acc : { ...acc, [key]: null };
}, {});
if (isDate(l) || isDate(r)) {
if (l.valueOf() == r.valueOf()) return {};
return r;
}
return Object.keys(r).reduce((acc, key) => {
if (!l.hasOwnProperty(key)) return { ...acc, [key]: r[key] }; // return added r key
const difference = diff(l[key], r[key]);
if (isObject(difference) && isEmpty(difference) && !isDate(difference)) return acc; // return no diff
return { ...acc, [key]: difference }; // return updated key
}, deletedValues);
};
const detailedDiff = (lhs, rhs) => ({
added: addedDiff(lhs, rhs),
deleted: deletedDiff(lhs, rhs),
updated: updatedDiff(lhs, rhs),
});
const addedDiff = (lhs, rhs) => {
if (lhs === rhs || !isObject(lhs) || !isObject(rhs)) return {};
const l = properObject(lhs);
const r = properObject(rhs);
return Object.keys(r).reduce((acc, key) => {
if (l.hasOwnProperty(key)) {
const difference = addedDiff(l[key], r[key]);
if (isObject(difference) && isEmpty(difference)) return acc;
return { ...acc, [key]: difference };
}
return { ...acc, [key]: r[key] };
}, {});
};
const arrayDiff = (lhs, rhs) => {
if (lhs === rhs) return {}; // equal return no diff
if (!isObject(lhs) || !isObject(rhs)) return rhs; // return updated rhs
const l = properObject(lhs);
const r = properObject(rhs);
const deletedValues = Object.keys(l).reduce((acc, key) => {
return r.hasOwnProperty(key) ? acc : { ...acc, [key]: null };
}, {});
if (isDate(l) || isDate(r)) {
if (l.valueOf() == r.valueOf()) return {};
return r;
}
if (Array.isArray(r) && Array.isArray(l)) {
const deletedValues = l.reduce((acc, item, index) => {
return r.hasOwnProperty(index) ? acc.concat(item) : acc.concat(null);
}, []);
return r.reduce((acc, rightItem, index) => {
if (!deletedValues.hasOwnProperty(index)) {
return acc.concat(rightItem);
}
const leftItem = l[index];
const difference = diff(rightItem, leftItem);
if (isObject(difference) && isEmpty(difference) && !isDate(difference)) {
delete acc[index];
return acc; // return no diff
}
return acc.slice(0, index).concat(rightItem).concat(acc.slice(index + 1)); // return updated key
}, deletedValues);
}
return Object.keys(r).reduce((acc, key) => {
if (!l.hasOwnProperty(key)) return { ...acc, [key]: r[key] }; // return added r key
const difference = diff(l[key], r[key]);
if (isObject(difference) && isEmpty(difference) && !isDate(difference)) return acc; // return no diff
return { ...acc, [key]: difference }; // return updated key
}, deletedValues);
};
const deletedDiff = (lhs, rhs) => {
if (lhs === rhs || !isObject(lhs) || !isObject(rhs)) return {};
const l = properObject(lhs);
const r = properObject(rhs);
return Object.keys(l).reduce((acc, key) => {
if (r.hasOwnProperty(key)) {
const difference = deletedDiff(l[key], r[key]);
if (isObject(difference) && isEmpty(difference)) return acc;
return { ...acc, [key]: difference };
}
return { ...acc, [key]: null };
}, {});
};
function mergeRecursive(obj1, obj2) {
for (var p in obj2) {
try {
if(obj2[p].constructor == Object) {
obj1[p] = mergeRecursive(obj1[p], obj2[p]);
}
// Property in destination object set; update its value.
else if (Ext.isArray(obj2[p])) {
// obj1[p] = [];
if (obj2[p].length < 1) {
obj1[p] = obj2[p];
}
else {
obj1[p] = mergeRecursive(obj1[p], obj2[p]);
}
}else{
obj1[p] = obj2[p];
}
} catch (e) {
// Property in destination object not set; create it and set its value.
obj1[p] = obj2[p];
}
}
return obj1;
}
/*
var test = {
foo : {
bar : {
baz : null
}
},
bar : 1
};
cleanse(test);
Rohit: Added a small fix for object being entered as Array*/
function cleanse(obj) {
console.log(obj)
Object.keys(obj).forEach(function(key) {
var value = obj[key];
if (typeof value === "object" && value !== null) {
// Recurse...
cleanse(value);
// ...and remove if now "empty" (NOTE: insert your definition of "empty" here)
if (!Object.keys(value).length) {
delete obj[key]
}
}
else if (value === null) {
// null, remove it
delete obj[key];
}
});
if(obj.constructor.toString().indexOf("Array") != -1) {obj = obj.filter(function (el) {
return el != null;
});}
return obj;
}
/*obj is original object or array, diff is the output of detailedDiff */
function mergeAllDiff(obj,diff){
if(Object.keys(diff.updated).length !== 0)
obj = mergeRecursive(obj,diff.updated)
if(Object.keys(diff.deleted).length !== 0){
obj = mergeRecursive(obj,diff.deleted)
obj = cleanse(obj)
}
if(Object.keys(diff.added).length !== 0)
obj = mergeRecursive(obj,diff.added)
return obj
}
</script>
<script>
floCloudAPI = {
//send Any message to supernode cloud storage
sendApplicationData: function(message, type, options = {}){
return new Promise((resolve,reject) => {
var data = {
senderID : myFloID,
receiverID: options.receiverID || floGlobals.adminID,
pubKey : myPubKey,
message : message,
sign: floCrypto.signData(JSON.stringify(message), myPrivKey),
application : options.application || floGlobals.application,
type: type,
comment: options.comment || ""
}
floSupernode.sendData(JSON.stringify(data), data.receiverID)
.then(result => resolve(result))
.catch(error => reject(error))
})
},
//request an object data from supernode cloud
requestObjectData: function(objectName, options = {}){
var request = {
receiverID: options.receiverID || floGlobals.adminID,
senderIDs: options.senderIDs || floGlobals.subAdmins,
application: options.application || floGlobals.application,
type: `${objectName}@Reset`,
lowerVectorClock: floGlobals.vectorClock[objectName]+1,
mostRecent: true
}
floSupernode.requestData(JSON.stringify(request),request.receiverID).then(resetData => {
reactor.dispatchEvent('resetData', resetData);
request.type = `${objectName}@Update`
request.lowerVectorClock = floGlobals.vectorClock[objectName]+1
request.mostRecent = false
floSupernode.requestData(JSON.stringify(request), request.receiverID)
.then(updateData => reactor.dispatchEvent('updateData', updateData))
}).catch(error => reactor.dispatchEvent('errorHandle', error))
},
//reset or initialize an object and send it to cloud
resetObjectData: function(newObject, objectName, options = {}){
var message = {
division: options.division || floGlobals.division,
object: objectName,
vectorClock: floGlobals.vectorClock[object],
reset: newObject
}
this.sendApplicationData(message, `${object}@Reset`, options)
.then(result => reactor.dispatchEvent('logHandle',result))
.catch(error => reactor.dispatchEvent('errorHandle',error))
},
//update the diff and send it to cloud
updateObjectData: function(oldObject, newObject, objectName, options = {}){
var message = {
division: options.division || floGlobals.division,
object: objectName,
vectorClock: floGlobals.vectorClock[object],
diff: detailedDiff(oldObject, newObject)
}
this.sendApplicationData(message, `${object}@Update`, options)
.then(result => reactor.dispatchEvent('logHandle',result))
.catch(error => reactor.dispatchEvent('errorHandle',error))
}
}
reactor.registerEvent('resetData');
reactor.addEventListener('resetData', function(dataSet){
try{
dataSet = JSON.parse(dataSet);
console.log(dataSet)
for(vc in dataSet){
if(floGlobals.subAdmins.includes(dataSet[v].senderID)){
var message = dataSet[v].message;
if(message.reset){
floGlobals.appObjects[message.object] = message.reset
floGlobals.vectorClock[message.object] = vc
//compactIDB.writeData("appObjects", floGlobals.appObjects[message.object], message.object)
//compactIDB.writeData("vectorClocks", vc, message.object)
}
}
}
}catch(error){
console.log(error)
}
});
reactor.registerEvent('updateData');
reactor.addEventListener('updateData', function(dataSet){
try{
dataSet = JSON.parse(dataSet);
console.log(dataSet)
for(vc in dataSet){
if(floGlobals.subAdmins.includes(dataSet[v].senderID)){
var message = dataSet[v].message;
if(message.diff){
floGlobals.appObjects[message.object] = mergeAllDiff(floGlobals.appObjects[message.object], message.diff)
//compactIDB.writeData("objects",floGlobals.appObjects[message.object], message.object)
}
}
floGlobals.vectorClock[message.object] = vc
//compactIDB.writeData("vectorClocks", vc, message.object)
}
}catch(error){
console.log(error)
}
});
reactor.registerEvent('errorHandle');
reactor.addEventListener('errorHandle', function(event){
console.log(event)
});
reactor.registerEvent('logHandle');
reactor.addEventListener('logHandle', function(event){
console.log(event)
});
</script>
</body>
</html>