| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805 | var EventEmitter = require("events").EventEmittervar _ = require("lodash");var async = require("async");function uberfactory(uuid, slugger) {    var ignores = [        "uninherits",        "inherits",        "unextends",        "extends",        "unisa",        "isa",        "relatesAsToWith",        "test",        "emita",        "emitas",        "data2",        "getStuff",        "pingup",        "data",        "metas2",        "metas",        "metas3",        "exporta",        "pickdeep",        "withAllSync",        "withAll",        "innerExport",        "exportFlatSync",        "exportSync",        "export2",        "export",        "domain",        "_events",        "rawListeners",        "_maxListeners",        "setMaxListeners",        "getMaxListeners",        "emit",        "addListener",        "on",        "prependListener",        "once",        "prependOnceListener",        "removeListener",        "removeAllListeners",        "listeners",        "listenerCount",        "eventNames",        "_data", "path", "name", "children", "parents", "_inherits", "_extends", "_isa",        "_hasa", "_relations", "_references", "_created", "_metas",        "_rootname", "exportSerialised"    ]    return function factory(therootname) {        var seed = therootname;        var ROOT = new electra(therootname, true, false)        function inner(name) {            if (typeof(name) == "undefined") {                return ROOT;            }            name = slugger(name);            if (!ROOT.children[name]) {                ROOT.children[name] = new electra(name);            }            return ROOT.children[name]        }        function electra(name, isroot, parent) {            //name = slugger(name);            this._data = {}            this._metas = {};            this.path = (parent ? parent.path : "") + name;            this.name = name;            //this._id = uuid();            this.children = {};            this.parents = {};            this._inherits = {};            this._extends = {};            this._isa = {};            this._hasa = {};            this._relations = {};            this._references = {};            this._created = new Date();            this._rootname = therootname;            var self = this;            if (parent) {                this.parents[parent.name] = parent;                this.path = parent.path + "/" + name            }            if (isroot) {                this.isroot = true;                return this;            }            function xinner(name) {                var args = Array.prototype.slice.apply(arguments, [0]);                if (args.length > 1) {                    return args.map(function(n) {                        return xinner(n)                    })                }                if (typeof(name) == "undefined") {                    return self;                }                name = slugger(name);                if (name.indexOf("://") > -1) {                    if (!self.children[name]) {                        self.children[name] = new electra(name, false, self);                        self.pingup("created", self.children[name](), name)                        self.emit("added", name);                    }                    return self.children[name]                }                if (name.indexOf("/") > -1) {                    //its a path;                    var arr = name.split("/");                    var newname = arr.shift();                    if (!self.children[newname]) {                        self.children[newname] = new electra(newname, false, self);                        self.pingup("created", self.children[newname](), newname, arr)                        self.emit("added", newname);                    }                    return self.children[newname](arr.join("/"))                }                if (!self.children[name]) {                    self.children[name] = new electra(name, false, self);                    self.pingup("created", self.children[name](), name)                }                return self.children[name]            }            return xinner        }        electra.prototype.__proto__ = EventEmitter.prototype        electra.prototype.inherits = function(obj_) {            var obj = typeof(obj_) === "function" ? obj_() : typeof(obj_) === "object" ? obj_ : typeof(obj_) === "string" ? inner(obj_)() : false            if (obj) {                this._inherits[obj.path] = obj;                obj._extends[this.path] = this;            }            return this;        }        electra.prototype.uninherits = function(obj_) {            var obj = typeof(obj_) === "function" ? obj_() : typeof(obj_) === "object" ? obj_ : typeof(obj_) === "string" ? inner(obj_)() : false            if (obj && this._inherits[obj.path]) {                delete this._inherits[obj.path]                delete obj._extends[this.path]            }            return this;        }        electra.prototype.extends = function(obj_) {            var obj = typeof(obj_) === "function" ? obj_() : typeof(obj_) === "object" ? obj_ : typeof(obj_) === "string" ? inner(obj_)() : false            if (obj) {                this._extends[obj.path] = obj;                obj._inherits[this.path] = this;            }            return this;        }        electra.prototype.unextends = function(obj_) {            var obj = typeof(obj_) === "function" ? obj_() : typeof(obj_) === "object" ? obj_ : typeof(obj_) === "string" ? inner(obj_)() : false            if (obj && this._extends[obj.path]) {                delete this._extends[obj.path]                delete obj._inherits[this.path]            }            return this;        }        electra.prototype.isa = function(elef) {            var self = this;            var args = Array.prototype.slice.apply(arguments, [0]);            if (args.length > 1) {                args.map(function(n) {                    var ele = typeof(n) === "function" ? n() : n;                    self._isa[ele.path] = ele                    ele._hasa[self.path] = self;                    self.pingup("isa", self, ele.path)                    ele.pingup("isa", self, ele.path)                })            } else {                if (typeof(elef) === "object" && elef.length) {                    elef.map(function(n) {                        var ele = typeof(n) === "function" ? n() : n;                        self._isa[ele.path] = ele                        ele._hasa[self.path] = self;                        self.pingup("isa", self, ele.path)                        ele.pingup("isa", self, ele.path)                    })                } else {                    var ele = typeof(elef) === "function" ? elef() : typeof(elef) === "object" ? elef : typeof(elef) === "string" ? inner(elef)() : false                    if (ele) {                        this._isa[ele.path] = ele                        ele._hasa[this.path] = this;                        self.pingup("isa", self, ele.path)                        ele.pingup("isa", self, ele.path)                    }                }            }            return this;        }        electra.prototype.unisa = function(elef) {            var self = this;            var args = Array.prototype.slice.apply(arguments, [0]);            if (args.length > 1) {                args.map(function(n) {                    var ele = typeof(n) === "function" ? n() : n;                    delete self._isa[ele.path]                    delete ele._hasa[self.path]                    self.pingup("isa", self, ele.path)                    ele.pingup("isa", self, ele.path)                })            } else {                if (typeof(elef) === "object" && elef.length) {                    elef.map(function(n) {                        var ele = typeof(n) === "function" ? n() : n;                        delete self._isa[ele.path]                        delete ele._hasa[self.path]                        self.pingup("isa", self, ele.path)                        ele.pingup("isa", self, ele.path)                    })                } else {                    var ele = typeof(elef) === "function" ? elef() : elef;                    delete this._isa[ele.path]                    delete ele._hasa[this.path]                    self.pingup("isa", self, ele.path)                    ele.pingup("isa", self, ele.path)                }            }            return this;        }        electra.prototype.relatesAsToWith = function(relationout, elef, relationto, withstuff) {            var self = this;            if (typeof(relationto) === "undefined") {                relationto = relationout;            }            if (typeof(withstuff) === "undefined") {                withstuff = "";            }            var withstuffOut = Object.assign({                "out": relationout,                "in": relationto            }, withstuff);            var withstuffTo = Object.assign({                "in": relationout,                "out": relationto            }, withstuff);            if (typeof(elef) === "object" && elef.length) {                elef.map(function(n) {                    var ele = typeof(n) === "function" ? n() : n;                    self._relations[relationout] = self._relations[relationout] || {}                    self._relations[relationout][ele.path] = {                        ref: ele,                        context: withstuffOut                    }                    ele._relations[relationto] = ele._relations[relationto] || {}                    ele._relations[relationto][self.path] = {                        ref: self,                        context: withstuffTo                    }                })            } else {                var ele = typeof(elef) === "function" ? elef() : elef;                self._relations[relationout] = self._relations[relationout] || {}                self._relations[relationout][ele.path] = {                    ref: ele,                    context: withstuffOut                }                ele._relations[relationto] = ele._relations[relationto] || {}                ele._relations[relationto][self.path] = {                    ref: self,                    context: withstuffTo                }            }            return this;        }        electra.prototype.test = function() {            return this;        }        electra.prototype.emita = function() {            var self = this;            var args = Array.prototype.slice.apply(arguments, [0]);            var kk = _.keys(this.parents);            if (kk.length > 0) {                kk.map(function(k) {                    self.parents[k].emita.apply(self.parents[k], args)                })            } else {}            var kk = _.keys(this.children);            if (kk.length > 0) {                kk.map(function(k) {                    //self.children[k].emita.apply(self.children[k],args)                })            } else {}            /*    	_.map(this.children,function(child,name){    		child().emita.apply(child(),args);    	})	**/        }        electra.prototype.emitas = function() {            var self = this;            var args = Array.prototype.slice.apply(arguments, [0]);            var kk = _.keys(this.parents);            if (kk.length > 0) {                kk.map(function(k) {                    self.parents[k].emita.apply(self.parents[k], args)                })            } else {}            var kk = _.keys(this.children);            if (kk.length > 0) {                kk.map(function(k) {                    //self.children[k].emita.apply(self.children[k],args)                })            } else {}            /*    	_.map(this.children,function(child,name){    		child().emita.apply(child(),args);    	})	**/        }        electra.prototype.data2 = function(key, value) {            var self = this;            if (typeof(key) === "undefined") {                return this._data;            } else {                if (typeof(value) === "undefined") {                    if (typeof(key) === "object") {                        var oldvalue = this._data;                        this._data = Object.assign(this._data, key);                        _.map(this.parents, function(par, nam) {                            par.emit("changed", self, "[[object]]", self._data, oldvalue);                        })                        this.emit("changed", this, "[[object]]", this._data, oldvalue);                        return this;                    } else {                        return this._data[key];                    }                } else {                    var oldvalue = this._data[key];                    this._data[key] = value;                    _.map(this.parents, function(par, nam) {                        par.emit("changed", self, key, value, oldvalue);                    })                    this.emit("changed", this, key, value, oldvalue);                    return this._data[key];                }            }        }        electra.prototype.getStuff = function(stuff, applybefore, named_, dd) {            var named = named_ || "data";            var dd = dd || false;            var obj = {                name: this.path,                from: named,                data: applybefore(getpath(this, stuff))            }            var arr = [obj];            if (dd) {                return arr            }            arr = [].concat.apply(arr, _.map(this._inherits, function(par, nam) {                return par.getStuff.apply(par, [stuff, applybefore, "inherit_" + named_]);            }))            arr = [].concat.apply(arr, _.map(this.parents, function(par, nam) {                return par.getStuff.apply(par, [stuff, applybefore, "parent_" + named_]);            }))            arr = [].concat.apply(arr, _.map(this._isa, function(par, nam) {                return par.getStuff.apply(par, [stuff, applybefore, "isa_" + named_, true]);            }))            arr = arr.filter(function(a) {                return a.data ? a.data.length > 0 : false            });            return arr        }        electra.prototype.pingup = function() {            var args = Array.prototype.slice.apply(arguments, [0]);            _.map(this.parents, function(par, nam) {                return par.pingup.apply(par, args);            })            this.emit.apply(this, args);        }        electra.prototype.data = function(key, value) {            var self = this;            if (typeof(key) === "undefined") {                return this._data;            } else {                if (typeof(value) === "undefined") {                    if (typeof(key) === "object") {                        var oldvalue = this._data;                        this._data = Object.assign(this._data, key);                        this.pingup("changed", self, "[[object]]", self._data, oldvalue)                        return this;                    } else {                        return this._data[key];                    }                } else {                    var oldvalue = getpath(this._data, key); //this._data[key];                    setpath(this._data, key, value)                    //                    this._data[key] = value;                    this.pingup("changed", self, key, value, oldvalue)                    return getpath(this._data, key); //this._data[key];                }            }        }        electra.prototype.metas = function(key, value) {            var self = this;            if (typeof(key) === "undefined") {                return this._metas;            } else {                if (typeof(value) === "undefined") {                    if (typeof(key) === "object") {                        var oldvalue = this._metas;                        this._metas = Object.assign(this._metas, key);                        this.pingup("changed:meta", self, "[[object]]", self._metas, oldvalue)                        return this;                    } else {                        return this._metas[key];                    }                } else {                    var oldvalue = this._metas[key];                    this._metas[key] = value;                    this.pingup("changed:meta", self, key, value, oldvalue)                    return this._metas[key];                }            }        }        /*        electra.prototype.metas = function() {            var self = this;            var args = Array.prototype.slice.apply(arguments, [0]);            if (args.length === 0) {                return this._metas;            }            args.map(function(obj_) {                var obj = typeof(obj_) === "function" ? obj_() : typeof(obj_) === "object" ? obj_ : typeof(obj_) === "string" ? inner(obj_)() : false                if (obj) {                    self._metas.push({                        "meta": obj,                        "data": {}                    })                }            })            return this;        }        electra.prototype.metas3 = function(arr) {            var self = this;            self._metas = self._metas.concat(arr);            return self;        }*/        electra.prototype.exporta = function(path) {            this.export(path, function(err, arr) {                //    console.log("EXPORTED", err, JSON.stringify(arr, true, 2));            })        }        electra.prototype.pickdeep = function(prop, cb) {            var self = this;            async.mapLimit(this.children, 10, function(obj, next) {                //setTimeout(function(){                obj().pickdeep(prop, next)                //},1)                //	 		next(null,)            }, function(err, collect) {                cb(err, [].concat.apply([self[prop]], collect));            })            return this;        }        electra.prototype.withAllSync = function(func, cb) {            var self = this;            async.mapLimit(this.children, 10, function(obj, next) {                //setTimeout(function(){                obj().withAllSync(func, next)                //},1)                //	 		next(null,)            }, function(err, collect) {                cb(err, [].concat.apply([func(self)], collect));            })            return this;        }        electra.prototype.withAll = function(func, cb) {            var self = this;            async.mapLimit(this.children, 10, function(obj, next) {                obj().withAll(func, next)            }, function(err, collect) {                func(self, function(err2, result) {                    cb(err || err2, [].concat.apply([result], collect));                })            })            return this;        }        electra.prototype.exportSync = function(path, serializers) {            var self = this;            var obj = self.innerExport(path, serializers);            var collect = _.map(self.children, function(child, name) {                return child().exportSync(path + "/" + name, serializers)            })            collect.sort(function(a, b) {                return a.name > b.name ? 1 : a.name < b.name ? -1 : 0            })            obj.children = collect;            return obj;        }        electra.prototype.exportFlatSync = function(path) {            var self = this;            return [].concat.apply([self.innerExport(path)], _.map(self.children, function(child, name) {                return child().exportFlatSync(path + "/" + name)            }))        }        electra.prototype.export2 = function(path, cb) {            var self = this;            var obj = self.innerExport(path);            obj.children = _.map(self.children, function(a, n) {                return a().path            });            cb(null, obj);        }        electra.prototype.innerExport = function(path, serializers) {            var self = this;            var obj = {};            // obj._id = self._id;            obj.name = self.name;            obj.path = self.path;            obj.created = self._created.toJSON();            obj.data = self._data;            obj.meta = self._metas;            obj.inherits = _.map(self._inherits, function(a, n) {                return a.path            });            obj.extends = _.map(self._extends, function(a, n) {                return a.path            });            /*obj.parents = _.map(self.parents, function(a, n) {                return a.path            });*/            obj.isa = _.map(self._isa, function(a, n) {                return a.path            });            /*obj.hasa = _.map(self._hasa, function(a, n) {                return a.path            });*/            obj.rel = {};            _.map(self._relations, function(a, n) {                obj.rel[n] = {}                _.map(a, function(aa, nn) {                    obj.rel[n][aa.ref.path] = aa.context;                });            });            //clean up            obj.inherits = obj.inherits.length ? obj.inherits : undefined;            obj.extends = obj.extends.length ? obj.extends : undefined;            //obj.parents = obj.parents.length ? obj.parents : undefined;            obj.isa = obj.isa.length ? obj.isa : undefined;            //obj.hasa = obj.hasa.length ? obj.hasa : undefined;            obj.data = _.size(obj.data) ? obj.data : undefined;            obj.meta = _.size(obj.meta) ? obj.meta : undefined;            obj.rel = _.size(obj.rel) ? obj.rel : undefined;            _.keys(obj).map(function(k) {                if (obj[k] === undefined) {                    delete obj[k];                    //obj[k] = null /* nope */                }            })            var therest = _.omit(self, ignores);            //seriadeep(therest, obj, serializers,1);            _.map(therest, function(val, ke) {                if (typeof(val) === "function") {                    obj[ke] = "$$$FUNCTION$$$" + val;                } else {                    if (serializers && serializers[ke]) {                        obj[ke] = serializers[ke](val);                    } else {                        _.map(val,function(cval,cprop){                        })                        obj[ke] = val;                    }                }            })            return obj        }        function seriadeep(rest, obj, serializers,one) {            if(one>2){return }            _.map(rest, function(val, ke) {                if (typeof(val) === "function") {                    obj[ke] = "$$$FUNCTION$$$" + val;                } else if (typeof(val) === "object") {                    obj[ke] = seriadeep(val, obj, serializers, (one||1) +1);                } else {                    if (serializers && serializers[ke]) {                        obj[ke] = serializers[ke](val)                    } else {                        obj[ke] = val;                    }                }            })        }        electra.prototype.exportSerialised = function(serializers) {            var self = this;            return function(path, cb) {                async.mapLimit(this.children, 10, function(obj, next) {                    obj().exportSerialised(serializers)(path + obj().name, next)                    //          next(null,)                }, function(err, collect) {                    var obj = self.innerExport(path, serializers);                    collect.sort(function(a, b) {                        return a.name > b.name ? 1 : a.name < b.name ? -1 : 0                    })                    obj.children = collect;                    cb(err, obj);                })                return this;            }        }        electra.prototype.export = function(path, cb) {            var self = this;            async.mapLimit(this.children, 10, function(obj, next) {                obj().export(path + obj().name, next)            }, function(err, collect) {                var obj = self.innerExport(path);                if (collect.sort) {                    collect.sort(function(a, b) {                        return a.name > b.name ? 1 : a.name < b.name ? -1 : 0                    })                }                obj.children = collect;                cb(err, obj);            })            return this;        }        return inner    }}function getpath(obj, path) {    path = path || "";    var arr = path.split(".");    var t = obj;    var done = false;    if (arr.length) {        while (arr.length && !done) {            var check = arr.shift();            if (check !== "") {                t = t[check];            }            if (typeof t !== "object") {                done = true;            }        }    }    return t;}function setpath(obj, path, value) {    if (typeof obj !== "object" || !obj) {        throw new Error("obj is not Object");    }    if (typeof path !== "string" || path === "") {        throw new Error("path must be string with length > 0");    }    var arr = path.split(".");    var done = false;    var t = obj;    if (arr.length > 1) {        while (arr.length && t && !done) {            var check = arr.shift();            if (typeof t[check] === "object" && arr.length > 0) {                t = t[check];            } else {                done = true;                arr.unshift(check);            }        }        var xt = t;        while (arr.length) {            var tt = arr.shift();            if (arr.length) { //go deeper                xt = xt[tt] = {};            } else {                //last                xt[tt] = value;            }        }    } else {        if (arr.length === 1 && arr[0] !== "") {            t[arr[0]] = value;        }    }}uberfactory.ignores = ignores = [    "inherits",    "uninherits",    "unextends",    "extends",    "isa",    "unisa",    "relatesAsToWith",    "test",    "emita",    "emitas",    "data2",    "getStuff",    "pingup",    "data",    "metas2",    "metas",    "metas3",    "exporta",    "pickdeep",    "withAllSync",    "withAll",    "innerExport",    "exportFlatSync",    "exportSync",    "export2",    "export",    "domain",    "_events",    "rawListeners",    "_maxListeners",    "setMaxListeners",    "getMaxListeners",    "emit",    "addListener",    "on",    "prependListener",    "once",    "prependOnceListener",    "removeListener",    "removeAllListeners",    "listeners",    "listenerCount",    "eventNames",    "_data", "path", "name", "children", "parents", "_inherits", "_extends", "_isa",    "_hasa", "_relations", "_references", "_created", "_metas",    "_rootname", "exportSerialised"]module.exports = uberfactory;
 |