UNPKG

poserver

Version:
114 lines (102 loc) 4.04 kB
/** * 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({}); */ "use strict"; 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;