poserver
Version:
Server for JD Bot
114 lines (102 loc) • 4.04 kB
JavaScript
/**
* Created by tomdaley on 10/12/16.
*
* Use Case: If you create objects that have functions attached to them, those functions are lost when the bot library
* serializes the object. (The bot library calls JSON.stringify().) When the object is returned to our code, it only
* has data members (i.e. the result of JSON.parse()). This class is meant to keep a list of classes that can be
* revived AFTER the call to JSON.parse() and then actually revive them on receipt.
*
* To make this work, add a "__type" (that's two underscores) string property to your class and let that be the
* string name of the class, e.g. "Person". When the object tree is serialized, it will contain objects of that class
* type and each object will have the __type member. Also, the object constructor must be able to be called with a
* an empty object ({}) as its only parameter, e.g. var person = new Person({});
*/
;
var _level = 0;
var _dots = '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>';
var _logging = false;
var Types = function ()
{
};
Types._types = {};
Types.setLogging = function (shouldLog)
{
_logging = shouldLog;
};
/**
* Call this to register a type that can be revived. Only purpose of this method is to maintain a dictionary of
* classes, indexed by class name with the value being the constructor for that class.
*
* What I wanted was to call registerType() from within each classes definition file so that as I created more
* classes, they would register themselves and I would never have to update the app.js code. However, I just can't
* figure out how to have a static class member. I've ready a zillion articles and either I'm not understanding
* them or they are aimed at solving a different problem.
*
* Sooooo, what you do is call this ONCE for each revive-able class in the same visibility as you plan to call
* the revive() method. E.G.:
*
* Types.registerType("Person", require('./clsPerson'));
* session.userData.userProfile = Types.revive(session.userData.userProfile);
*
* @param {string} typeName - Name of the class as it will appear in the __type property for that class
* @param {function} typeClass - Constructor function for the class. Must accept an empty object ({}) as only arg.
*/
Types.registerType = function (typeName, typeClass)
{
Types._types[typeName] = typeClass;
if (_logging) console.log("%TYPES after registering %s", typeName);
if (_logging) console.log(Types._types);
};
/**
* Revives an object that has been serialized.
*
* @param {object} obj - Data-only object to be revived.
* @param {string} keyName - Name of property being revived. Only used for debugging.
* @returns {Object} - Revived object tree.
*/
Types.revive = function (obj, keyName)
{
_level++;
var revived;
keyName = keyName || "";
if (obj.hasOwnProperty("__type"))
{
try
{
revived = new Types._types[obj.__type]({});
if (_logging) console.log(_dots.slice(0, _level) + "Reviving instance of " + obj.__type);
}
catch (err)
{
console.log(Object.keys(Types._types));
console.error("Error reviving %s - did you call registerType() first?", obj.__type);
throw(err);
}
}
else if (typeof obj == "array")
{
revived = [];
if (_logging) console.log(_dots.slice(0, _leval) + "Reviving instance of Array %s", keyName);
}
else
{
revived = {};
if (_logging) console.log(_dots.slice(0, _level) + "Reviving instance of Object %s", keyName);
}
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++)
{
if (typeof obj[keys[i]] === "object")
{
revived[keys[i]] = this.revive(obj[keys[i]], keys[i]);
}
else
{
revived[keys[i]] = obj[keys[i]];
if (_logging) console.log(_dots.slice(0, _level + 1) + keys[i] + " = " + obj[keys[i]]);
}
}
_level--;
return revived;
};
module.exports = Types;