<commit_before>/**
 * Created by Dana Zhang on 4/8/2014.
 */

define(['plugin/PluginConfig',
    'plugin/PluginBase',
    'plugin/PluginResult',
    'json2xml'], function (PluginConfig, PluginBase, PluginResult, Json2Xml) {

    'use strict';

    var LogicGatesExporterPlugin = function () {
        PluginBase.call(this);

        this.objectToVisit = 1; // number of objects that have to be visited, visiting the selected node makes it start with 1
        this.diagramPath = "";
        this.modelID = 0;
        this.wiresToAdd = [];
        this.circuits = [];
        this.components = {};
        this.idLUT = {};
        this.childrenLUT = {};

        this.GATE_TYPES = {
            "Not": true,
            "Buffer": true,
            "And": true,
            "Or": true,
            "Nand": true,
            "Nor": true,
            "Xor": true,
            "Xnor": true,
            "NumericInput": true,
            "NumericOutput": true,
            "UserOutput": true,
            "UserInput": true,
            "Clock": true
        };

        this.COMPLEX = {
            "And": true,
            "Or": true,
            "Nand": true,
            "Nor": true,
            "Xor": true,
            "Xnor": true
        };

        this.WIRE_TYPES = {
            "OutputPort2InputPort": true,
            "UserInput2InputPort": true,
            "OutputPort2UserOutput": true,
            "UserInputBase2UserOutput": true,
            "PortBase2UserIOBase": true,
            "UserIOBase2PortBase": true,
            "UserIOBase2UserIOBase": true
        };
    };

    LogicGatesExporterPlugin.prototype = Object.create(PluginBase.prototype);
    LogicGatesExporterPlugin.prototype.constructor = LogicGatesExporterPlugin;

    LogicGatesExporterPlugin.prototype.getName = function () {
        return 'LogicGatesExporter';
    };

    LogicGatesExporterPlugin.prototype.main = function (callback) {
        var self = this,
            core = self.core,
            selectedNode = self.activeNode,
            pluginResult = self.result; // You probably don't need a separate variable for this...

        if (!selectedNode) {
            callback('selectedNode is not defined', pluginResult);
            return;
        }

        core.loadChildren(selectedNode, function (err, childNodes) {
            self.visitObject(err, childNodes, core, callback);
        });
    };

    LogicGatesExporterPlugin.prototype.visitObject = function (err, childNodes, core, callback) {
        var self = this,
            i,
            child,
            gmeID,
            parentPath,
            baseNode,
            metaType, // get child's base META Type
            parentClass,
            parentMeta,
            isComplex,
            isGate,
            isWire,
            pluginResult;

        self.objectToVisit += childNodes.length; // all child objects have to be visited
        for (i = 0; i < childNodes.length; i += 1) {

            child = childNodes[i];
            gmeID = core.getPath(child);
            parentPath = core.getPath(core.getParent(child));
            // baseClass = core.getBase(child);
            //metaType = baseClass ? core.getAttribute(baseClass, 'name') : ""; // get child's base META Type
            baseNode = self.getMetaType(child);
            metaType = baseNode ? core.getAttribute(baseNode, 'name') : "";
            // parentClass = core.getBase(core.getParent(child));
            parentClass = self.getMetaType(core.getParent(child));
            parentMeta = parentClass ? core.getAttribute(parentClass, 'name') : "";
            isComplex = self.COMPLEX[metaType];
            isGate = self.GATE_TYPES[metaType] && parentMeta === "LogicCircuit";
            isWire = self.WIRE_TYPES[metaType] && parentMeta === "LogicCircuit";

            if (isGate) {

                // if key not exist already, add key; otherwise ignore
                if (!self.idLUT.hasOwnProperty(gmeID)) {
                    // PC: addGate needs to be defined and called as an asynchronous function. see PC10
                    self.addGate(child, metaType, isComplex, parentPath);
                }

            } else if (isWire) {

                self.wiresToAdd.push(child);

            } else if (metaType === 'InputPort') {

                if (!self.childrenLUT.hasOwnProperty(parentPath)) {

                    self.childrenLUT[parentPath] = [];
                }
                self.childrenLUT[parentPath].push(gmeID);
            }

            core.loadChildren(childNodes[i], function (err, childNodes) {
                self.visitObject(err, childNodes, core, callback);
            });
        }

        self.objectToVisit -= 1; // another object was just visited

        if (self.objectToVisit === 0) {

            // had to do it this way because we need to wait for all the gates to be added before adding the wires to avoid problems async causes
            for (i = 0; i < self.wiresToAdd.length; i += 1) {
                self.addWire(self.wiresToAdd[i]);
            }

            self.createObjectFromDiagram();

            // all objects have been visited
            pluginResult = new PluginResult();
            pluginResult.success = true;
            if (callback) {
                callback(null, pluginResult);
            }
        }
    };

    /**
    * This function adds a gate to the circuit diagram it belongs to
    * @param {object} nodeObj - current node to be visited
    * @param {string} metaType - meta type of current node
    * @param {boolean} isComplex - indicating whether the current node is a complex logic gate
    * @param {string} parentPath - the circuit diagram the current node belongs to
    * @returns {string} The version of the plugin.
    * @public
    */

    LogicGatesExporterPlugin.prototype.addGate = function (nodeObj, metaType, isComplex, parentPath) {
        var self = this,
            core = self.core,
            gmeID = core.getPath(nodeObj),
            name = core.getAttribute(nodeObj, 'name'),
            bits = core.getAttribute(nodeObj, 'Bits'),
            selRep = core.getAttribute(nodeObj, 'SelRep'),
            xNull = nodeObj.data,
            yNull = nodeObj.data.reg,
            xPos = parseInt(nodeObj.data.reg.position.x, 10),
            yPos = parseInt(nodeObj.data.reg.position.y, 10),
            value = core.getAttribute(nodeObj, 'Value'),
            angle = 0,
            gate;

            // debugging use: this becomes true when a gate in a subcircuit is being visited
//            if (!xNull || !yNull || !nodeObj || !yNull.position)
//            {
//                console.log("abc");
//            }

        self.idLUT[gmeID] = self.modelID;

        // all logic gates component have attrs: Type, Name, ID
        //                                 element: Point (attrs: X, Y, Angle)
        gate = {
            "@Type": metaType,
            "@Name": name,
            "@ID": self.modelID,
            "Point": {
                "@X": xPos,
                "@Y": yPos,
                "@Angle": angle
            }
        };

        if (isComplex) {
            // PC: loadChildren is asynchronous the execution will most likely step to #192 before gate is updated.
            // This fact also makes addGate asynchronous.
            core.loadChildren(nodeObj, function (err, childNodes) {
                gate["@NumInputs"] = childNodes.length - 1;
            });

        } else if (metaType === "Clock") {
            gate["@Milliseconds"] = core.getAttribute(nodeObj, 'Milliseconds');

        } else if (metaType === "NumericInput" || metaType === "NumericOutput") {
            gate["@Bits"] = bits;
            gate["@SelRep"] = selRep;
            gate["@Value"] = value;
        }

        if (!self.components.hasOwnProperty(parentPath)) {
            self.components[parentPath] = {
                "Gate": [],
                "Wire": []
            };
        }
        if (parentPath) {

            self.components[parentPath].Gate.push(gate);
        }

        self.modelID += 1;
    };

    LogicGatesExporterPlugin.prototype.addWire = function (nodeObj) {
        var self = this,
            core = self.core,
            src = core.getPointerPath(nodeObj, "src"),
            dst = core.getPointerPath(nodeObj, "dst"),
            srcID,
            dstID,
            srcPort = 0,
            dstPort = 0,
            wire,
            parentCircuitPath,
            validGates;

        // PC: loadByPath is asynchronous and addWire becomes that too.
        core.loadByPath(self.rootNode, src, function (err, node) {
            // You can define variables here since your callback function defines a closure.
            // They will only be accessible within this scope and not in "addWire", however you
            // can access the variables defined in "addWire" here.
            var srcMetaType,
                srcNodeObj,
                parentPath,
                metaType,
                isGate,
                isPort,
                isComplex;

            if (!err) {
                metaType = core.getAttribute(core.getBase(node), 'name');
                isComplex = self.COMPLEX[metaType];
                isGate = self.GATE_TYPES[metaType];
                isPort = metaType === 'InputPort' || metaType === 'OutputPort';

                if (isGate) {
                    srcNodeObj = node;
                    parentPath = core.getPath(core.getParent(srcNodeObj));
                    srcMetaType = metaType;
                } else if (isPort) {
                    srcNodeObj = core.getParent(node);
                    src = core.getPath(srcNodeObj);
                    srcMetaType = core.getAttribute(srcNodeObj, 'name');
                    parentPath = core.getPath(srcNodeObj);
                    srcPort = 0;
                }

                if ((isPort || isGate) && (!self.idLUT.hasOwnProperty(src))) {
                    self.addGate(srcNodeObj, srcMetaType, isComplex, parentPath);
                }
            }
        });

        core.loadByPath(self.rootNode, dst, function (err, node) {

            var portGMEId,
                parentPath,
                metaType,
                isComplex,
                isGate,
                isPort,
                dstMetaType,
                dstNodeObj;

            if (!err) {
                metaType = core.getAttribute(core.getBase(node), 'name');
                isComplex = self.COMPLEX[metaType];
                isGate = self.GATE_TYPES[metaType];
                isPort = metaType === 'InputPort' || metaType === 'OutputPort';

                if (isGate) {
                    dstNodeObj = node;
                    parentPath = core.getPath(core.getParent(dstNodeObj));
                    dstMetaType = metaType;
                } else if (isPort) {
                    dstNodeObj = core.getParent(node);
                    portGMEId = core.getPath(dstNodeObj);
                    dst = core.getPath(dstNodeObj);
                    dstMetaType = core.getAttribute(dstNodeObj, 'name');
                    parentPath = core.getPath(dstNodeObj);
                    dstPort = self.childrenLUT[parentPath].indexOf(portGMEId);
                }

                if ((isPort || isGate) && !self.idLUT.hasOwnProperty(dst)) {
                    self.addGate(dstNodeObj, dstMetaType, isComplex, parentPath);
                }
            }
        });

        // Wire component's elements: From (attrs: ID, Port), To (attrs: ID, Port)

        parentCircuitPath = core.getPath(core.getParent(nodeObj));
        // PC: At this point src, dst, srcID, dstID might not have been modified by
        // the core.loadPath callbacks. More on that later...
        srcID = self.idLUT[src];
        dstID = self.idLUT[dst];

        wire = {
            "From": {
                "@ID": srcID,
                "@Port": srcPort
            },
            "To": {
                "@ID": dstID,
                "@Port": dstPort
            }
        };

        if (!self.components.hasOwnProperty(parentCircuitPath)) {
            self.components[parentCircuitPath] = {
                "Gate": [],
                "Wire": []
            };
        }

        validGates = (srcPort !== undefined) && (dstPort !== undefined) && (srcID !== undefined) && (dstID !== undefined);
        if (parentCircuitPath && validGates) {
            self.components[parentCircuitPath].Wire.push(wire);
        }
    };

    LogicGatesExporterPlugin.prototype.createObjectFromDiagram = function () {
        var self = this,
            i = 0,
            parentPath,
            diagram,
            j2x,
            output;

        for (parentPath in self.components) {
            if (self.components.hasOwnProperty(parentPath)) {
                diagram = {
                    "CircuitGroup": {
                        "@Version": 1.2,
                        "Circuit" : {
                            "Gates": {},
                            "Wires": {}
                        }
                    }
                };

                diagram.CircuitGroup.Circuit.Gates.Gate = self.components[parentPath].Gate;
                diagram.CircuitGroup.Circuit.Wires.Wire = self.components[parentPath].Wire;
                self.circuits.push(diagram);

                j2x = new Json2Xml();
                output = j2x.convert(diagram);
                // PC: the file system has changed recently and is still under construction..
                // self.fs.addFile("output" + i + ".gcg", output);
            }
            i += 1;
        }
        // PC: the file system has changed recently and is still under construction..
        // self.fs.saveArtifact();
    };

    /**
     * Checks if the given node is of the given meta-type.
     * Usage: <tt>self.isMetaTypeOf(aNode, self.META['FCO']);</tt>
     * @param node - Node to be checked for type.
     * @param metaNode - Node object defining the meta type.
     * @returns {boolean} - True if the given object was of the META type.
     */
    LogicGatesExporterPlugin.prototype.isMetaTypeOf = function (node, metaNode) {
        var self = this,
            metaGuid = self.core.getGuid(metaNode);
        while (node) {
            if (self.core.getGuid(node) === metaGuid) {
                return true;
            }
            node = self.core.getBase(node);
        }
        return false;
    };

    /**
     * Finds and returns the node object defining the meta type for node.
     * @param node - Node to be checked for type.
     * @returns {Object} - Node object defining the meta type of node.
     */
    LogicGatesExporterPlugin.prototype.getMetaType = function (node) {
        var self = this,
            name;
        while (node) {
            name = self.core.getAttribute(node, 'name');
            if (self.META.hasOwnProperty(name) && self.core.getPath(self.META[name]) === self.core.getPath(node)) {
                break;
            }
            node = self.core.getBase(node);
        }
        return node;
    };

    return LogicGatesExporterPlugin;
});<commit_msg>GH-5 Used core API to get gate position from registry<commit_after>/**
 * Created by Dana Zhang on 4/8/2014.
 */

define(['plugin/PluginConfig',
    'plugin/PluginBase',
    'plugin/PluginResult',
    'json2xml'], function (PluginConfig, PluginBase, PluginResult, Json2Xml) {

    'use strict';

    var LogicGatesExporterPlugin = function () {
        PluginBase.call(this);

        this.objectToVisit = 1; // number of objects that have to be visited, visiting the selected node makes it start with 1
        this.diagramPath = "";
        this.modelID = 0;
        this.wiresToAdd = [];
        this.circuits = [];
        this.components = {};
        this.idLUT = {};
        this.childrenLUT = {};

        this.GATE_TYPES = {
            "Not": true,
            "Buffer": true,
            "And": true,
            "Or": true,
            "Nand": true,
            "Nor": true,
            "Xor": true,
            "Xnor": true,
            "NumericInput": true,
            "NumericOutput": true,
            "UserOutput": true,
            "UserInput": true,
            "Clock": true
        };

        this.COMPLEX = {
            "And": true,
            "Or": true,
            "Nand": true,
            "Nor": true,
            "Xor": true,
            "Xnor": true
        };

        this.WIRE_TYPES = {
            "OutputPort2InputPort": true,
            "UserInput2InputPort": true,
            "OutputPort2UserOutput": true,
            "UserInputBase2UserOutput": true,
            "PortBase2UserIOBase": true,
            "UserIOBase2PortBase": true,
            "UserIOBase2UserIOBase": true
        };
    };

    LogicGatesExporterPlugin.prototype = Object.create(PluginBase.prototype);
    LogicGatesExporterPlugin.prototype.constructor = LogicGatesExporterPlugin;

    LogicGatesExporterPlugin.prototype.getName = function () {
        return 'LogicGatesExporter';
    };

    LogicGatesExporterPlugin.prototype.main = function (callback) {
        var self = this,
            core = self.core,
            selectedNode = self.activeNode,
            pluginResult = self.result; // You probably don't need a separate variable for this...

        if (!selectedNode) {
            callback('selectedNode is not defined', pluginResult);
            return;
        }

        core.loadChildren(selectedNode, function (err, childNodes) {
            self.visitObject(err, childNodes, core, callback);
        });
    };

    LogicGatesExporterPlugin.prototype.visitObject = function (err, childNodes, core, callback) {
        var self = this,
            i,
            child,
            gmeID,
            parentPath,
            baseNode,
            metaType, // get child's base META Type
            parentClass,
            parentMeta,
            isComplex,
            isGate,
            isWire,
            pluginResult;

        self.objectToVisit += childNodes.length; // all child objects have to be visited
        for (i = 0; i < childNodes.length; i += 1) {

            child = childNodes[i];
            gmeID = core.getPath(child);
            parentPath = core.getPath(core.getParent(child));
            // baseClass = core.getBase(child);
            //metaType = baseClass ? core.getAttribute(baseClass, 'name') : ""; // get child's base META Type
            baseNode = self.getMetaType(child);
            metaType = baseNode ? core.getAttribute(baseNode, 'name') : "";
            // parentClass = core.getBase(core.getParent(child));
            parentClass = self.getMetaType(core.getParent(child));
            parentMeta = parentClass ? core.getAttribute(parentClass, 'name') : "";
            isComplex = self.COMPLEX[metaType];
            isGate = self.GATE_TYPES[metaType] && parentMeta === "LogicCircuit";
            isWire = self.WIRE_TYPES[metaType] && parentMeta === "LogicCircuit";

            if (isGate) {

                // if key not exist already, add key; otherwise ignore
                if (!self.idLUT.hasOwnProperty(gmeID)) {
                    // PC: addGate needs to be defined and called as an asynchronous function. see PC10
                    self.addGate(child, metaType, isComplex, parentPath);
                }

            } else if (isWire) {

                self.wiresToAdd.push(child);

            } else if (metaType === 'InputPort') {

                if (!self.childrenLUT.hasOwnProperty(parentPath)) {

                    self.childrenLUT[parentPath] = [];
                }
                self.childrenLUT[parentPath].push(gmeID);
            }

            core.loadChildren(childNodes[i], function (err, childNodes) {
                self.visitObject(err, childNodes, core, callback);
            });
        }

        self.objectToVisit -= 1; // another object was just visited

        if (self.objectToVisit === 0) {

            // had to do it this way because we need to wait for all the gates to be added before adding the wires to avoid problems async causes
            for (i = 0; i < self.wiresToAdd.length; i += 1) {
                self.addWire(self.wiresToAdd[i]);
            }

            self.createObjectFromDiagram();

            // all objects have been visited
            pluginResult = new PluginResult();
            pluginResult.success = true;
            if (callback) {
                callback(null, pluginResult);
            }
        }
    };

    /**
    * This function adds a gate to the circuit diagram it belongs to
    * @param {object} nodeObj - current node to be visited
    * @param {string} metaType - meta type of current node
    * @param {boolean} isComplex - indicating whether the current node is a complex logic gate
    * @param {string} parentPath - the circuit diagram the current node belongs to
    * @returns {string} The version of the plugin.
    * @public
    */

    LogicGatesExporterPlugin.prototype.addGate = function (nodeObj, metaType, isComplex, parentPath) {
        var self = this,
            core = self.core,
            gmeID = core.getPath(nodeObj),
            name = core.getAttribute(nodeObj, 'name'),
            bits = core.getAttribute(nodeObj, 'Bits'),
            selRep = core.getAttribute(nodeObj, 'SelRep'),
            position = core.getRegistry(nodeObj, 'position'),
            xPos = position.x,
            yPos = position.y,
            value = core.getAttribute(nodeObj, 'Value'),
            angle = 0,
            gate;

            // debugging use: this becomes true when a gate in a subcircuit is being visited
//            if (!xNull || !yNull || !nodeObj || !yNull.position)
//            {
//                console.log("abc");
//            }

        self.idLUT[gmeID] = self.modelID;

        // all logic gates component have attrs: Type, Name, ID
        //                                 element: Point (attrs: X, Y, Angle)
        gate = {
            "@Type": metaType,
            "@Name": name,
            "@ID": self.modelID,
            "Point": {
                "@X": xPos,
                "@Y": yPos,
                "@Angle": angle
            }
        };

        if (isComplex) {
            // PC: loadChildren is asynchronous the execution will most likely step to #192 before gate is updated.
            // This fact also makes addGate asynchronous.
            core.loadChildren(nodeObj, function (err, childNodes) {
                gate["@NumInputs"] = childNodes.length - 1;
            });

        } else if (metaType === "Clock") {
            gate["@Milliseconds"] = core.getAttribute(nodeObj, 'Milliseconds');

        } else if (metaType === "NumericInput" || metaType === "NumericOutput") {
            gate["@Bits"] = bits;
            gate["@SelRep"] = selRep;
            gate["@Value"] = value;
        }

        if (!self.components.hasOwnProperty(parentPath)) {
            self.components[parentPath] = {
                "Gate": [],
                "Wire": []
            };
        }
        if (parentPath) {

            self.components[parentPath].Gate.push(gate);
        }

        self.modelID += 1;
    };

    LogicGatesExporterPlugin.prototype.addWire = function (nodeObj) {
        var self = this,
            core = self.core,
            src = core.getPointerPath(nodeObj, "src"),
            dst = core.getPointerPath(nodeObj, "dst"),
            srcID,
            dstID,
            srcPort = 0,
            dstPort = 0,
            wire,
            parentCircuitPath,
            validGates;

        // PC: loadByPath is asynchronous and addWire becomes that too.
        core.loadByPath(self.rootNode, src, function (err, node) {
            // You can define variables here since your callback function defines a closure.
            // They will only be accessible within this scope and not in "addWire", however you
            // can access the variables defined in "addWire" here.
            var srcMetaType,
                srcNodeObj,
                parentPath,
                metaType,
                isGate,
                isPort,
                isComplex;

            if (!err) {
                metaType = core.getAttribute(core.getBase(node), 'name');
                isComplex = self.COMPLEX[metaType];
                isGate = self.GATE_TYPES[metaType];
                isPort = metaType === 'InputPort' || metaType === 'OutputPort';

                if (isGate) {
                    srcNodeObj = node;
                    parentPath = core.getPath(core.getParent(srcNodeObj));
                    srcMetaType = metaType;
                } else if (isPort) {
                    srcNodeObj = core.getParent(node);
                    src = core.getPath(srcNodeObj);
                    srcMetaType = core.getAttribute(srcNodeObj, 'name');
                    parentPath = core.getPath(srcNodeObj);
                    srcPort = 0;
                }

                if ((isPort || isGate) && (!self.idLUT.hasOwnProperty(src))) {
                    self.addGate(srcNodeObj, srcMetaType, isComplex, parentPath);
                }
            }
        });

        core.loadByPath(self.rootNode, dst, function (err, node) {

            var portGMEId,
                parentPath,
                metaType,
                isComplex,
                isGate,
                isPort,
                dstMetaType,
                dstNodeObj;

            if (!err) {
                metaType = core.getAttribute(core.getBase(node), 'name');
                isComplex = self.COMPLEX[metaType];
                isGate = self.GATE_TYPES[metaType];
                isPort = metaType === 'InputPort' || metaType === 'OutputPort';

                if (isGate) {
                    dstNodeObj = node;
                    parentPath = core.getPath(core.getParent(dstNodeObj));
                    dstMetaType = metaType;
                } else if (isPort) {
                    dstNodeObj = core.getParent(node);
                    portGMEId = core.getPath(dstNodeObj);
                    dst = core.getPath(dstNodeObj);
                    dstMetaType = core.getAttribute(dstNodeObj, 'name');
                    parentPath = core.getPath(dstNodeObj);
                    dstPort = self.childrenLUT[parentPath].indexOf(portGMEId);
                }

                if ((isPort || isGate) && !self.idLUT.hasOwnProperty(dst)) {
                    self.addGate(dstNodeObj, dstMetaType, isComplex, parentPath);
                }
            }
        });

        // Wire component's elements: From (attrs: ID, Port), To (attrs: ID, Port)

        parentCircuitPath = core.getPath(core.getParent(nodeObj));
        // PC: At this point src, dst, srcID, dstID might not have been modified by
        // the core.loadPath callbacks. More on that later...
        srcID = self.idLUT[src];
        dstID = self.idLUT[dst];

        wire = {
            "From": {
                "@ID": srcID,
                "@Port": srcPort
            },
            "To": {
                "@ID": dstID,
                "@Port": dstPort
            }
        };

        if (!self.components.hasOwnProperty(parentCircuitPath)) {
            self.components[parentCircuitPath] = {
                "Gate": [],
                "Wire": []
            };
        }

        validGates = (srcPort !== undefined) && (dstPort !== undefined) && (srcID !== undefined) && (dstID !== undefined);
        if (parentCircuitPath && validGates) {
            self.components[parentCircuitPath].Wire.push(wire);
        }
    };

    LogicGatesExporterPlugin.prototype.createObjectFromDiagram = function () {
        var self = this,
            i = 0,
            parentPath,
            diagram,
            j2x,
            output;

        for (parentPath in self.components) {
            if (self.components.hasOwnProperty(parentPath)) {
                diagram = {
                    "CircuitGroup": {
                        "@Version": 1.2,
                        "Circuit" : {
                            "Gates": {},
                            "Wires": {}
                        }
                    }
                };

                diagram.CircuitGroup.Circuit.Gates.Gate = self.components[parentPath].Gate;
                diagram.CircuitGroup.Circuit.Wires.Wire = self.components[parentPath].Wire;
                self.circuits.push(diagram);

                j2x = new Json2Xml();
                output = j2x.convert(diagram);
                // PC: the file system has changed recently and is still under construction..
                // self.fs.addFile("output" + i + ".gcg", output);
            }
            i += 1;
        }
        // PC: the file system has changed recently and is still under construction..
        // self.fs.saveArtifact();
    };

    /**
     * Checks if the given node is of the given meta-type.
     * Usage: <tt>self.isMetaTypeOf(aNode, self.META['FCO']);</tt>
     * @param node - Node to be checked for type.
     * @param metaNode - Node object defining the meta type.
     * @returns {boolean} - True if the given object was of the META type.
     */
    LogicGatesExporterPlugin.prototype.isMetaTypeOf = function (node, metaNode) {
        var self = this,
            metaGuid = self.core.getGuid(metaNode);
        while (node) {
            if (self.core.getGuid(node) === metaGuid) {
                return true;
            }
            node = self.core.getBase(node);
        }
        return false;
    };

    /**
     * Finds and returns the node object defining the meta type for node.
     * @param node - Node to be checked for type.
     * @returns {Object} - Node object defining the meta type of node.
     */
    LogicGatesExporterPlugin.prototype.getMetaType = function (node) {
        var self = this,
            name;
        while (node) {
            name = self.core.getAttribute(node, 'name');
            if (self.META.hasOwnProperty(name) && self.core.getPath(self.META[name]) === self.core.getPath(node)) {
                break;
            }
            node = self.core.getBase(node);
        }
        return node;
    };

    return LogicGatesExporterPlugin;
});<|endoftext|>


<commit_before>/* @flow */
import { combineRules } from 'fela'

export default function FelaComponentFactory(
  createElement: Function,
  RendererContext: any,
  FelaTheme: Function
): Function {
  function FelaComponent({ children, as = 'div', style, ...otherProps }) {
    const renderFn = renderer => {
      if (renderer.devMode && style == null) {
        // eslint-disable-next-line no-console
        console.warn(
          '"FelaComponent" is being rendered without a style prop\nIf all you need is access to theme, try using "FelaTheme" or the "useFela" hook instead'
        )
      }

      return createElement(FelaTheme, undefined, theme => {
        // TODO: could optimize perf by not calling combineRules if not necessary
        const className = renderer.renderRule(combineRules(style), {
          ...otherProps,
          theme,
        })

        if (children instanceof Function) {
          return children({
            className,
            theme,
            as,
          })
        }

        return createElement(as, { className }, children)
      })
    }

    return createElement(RendererContext.Consumer, undefined, renderFn)
  }

  return FelaComponent
}
<commit_msg>implement returning style object for native renderer<commit_after>/* @flow */
import { combineRules } from 'fela'

export default function FelaComponentFactory(
  createElement: Function,
  RendererContext: any,
  FelaTheme: Function
): Function {
  function FelaComponent({ children, as = 'div', style, ...otherProps }) {
    const renderFn = renderer => {
      if (renderer.devMode && style == null) {
        // eslint-disable-next-line no-console
        console.warn(
          '"FelaComponent" is being rendered without a style prop\nIf all you need is access to theme, try using "FelaTheme" or the "useFela" hook instead'
        )
      }

      return createElement(FelaTheme, undefined, theme => {
        // TODO: could optimize perf by not calling combineRules if not necessary
        const renderedRule = renderer.renderRule(combineRules(style), {
          ...otherProps,
          theme,
        })

        if (children instanceof Function) {
          return children({
            className: !renderer.isNativeRenderer && renderedRule,
            style: renderer.isNativeRenderer && renderedRule,
            theme,
            as,
          })
        }

        return createElement(
          as,
          {
            className: !renderer.isNativeRenderer && renderedRule,
            style: renderer.isNativeRenderer && renderedRule,
          },
          children
        )
      })
    }

    return createElement(RendererContext.Consumer, undefined, renderFn)
  }

  return FelaComponent
}
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const EventEmitter= require('events').EventEmitter;

const versionio = require('version-io');
const changelog = require('changelog-io');
const rendy = require('rendy');
const spawnify = require('spawnify');
const series = require('async/series');
const minor = require('minor');
const prepend = require('prepend');
const grizzly = require('grizzly');
const jessy = require('jessy');
const readPkg = require('read-pkg-up');
const fullstore = require('fullstore');
const currify = require('currify');

const removeBowerVersion = currify(require('./remove-bower-version'));

const isUndefined = (a) => typeof a === 'undefined';

const Cmd = [
    'git add --all',
    'git commit -m "chore(package) v{{ version }}"',
    'git pull --rebase',
    'git push origin {{ branch }}',
].join('&&');

const CmdTag = [
    'git tag v{{ version }}',
    'git push origin v{{ version }}'
].join('&&');

const InfoDir = fullstore();

const setInfoDir = (data) => {
    const dir = path.dirname(data.path);

    InfoDir(dir);

    return data;
};

const getPkg = (data) => data.pkg;

module.exports = (version) => {
    const emitter = new EventEmitter();

    const onError = (e) => {
        const error = Error(`Error reading package.json: ${e.message}`);
        emitter.emit('error', error);
    };

    const start = currify((version, emitter, info) => {
        if (!version)
            return emitter.emit('data',
                `publish <version>\n` +
                `package: ${ info.name } ${ info.version }`
            );

        publish(version, info, emitter);
    });

    readPkg()
        .then(setInfoDir)
        .then(getPkg)
        .then(start(version, emitter))
        .catch(onError);

    return emitter;
};

function publish(version, info, emitter) {
    let type = '--';
    let chlog = '';

    if (!version.indexOf('v')) {
        version = version.slice(1);
        type += 'v' + version;
    } else if (/major|minor|patch/.test(version)) {
        type += version;
        version = minor(version, info.version);
    }

    const cmd = rendy(Cmd, {
        version: version,
        branch: info.branch || 'master'
    });

    const cmdTag = rendy(CmdTag, {
        version: version
    });

    series([
        function beforePublish(callback) {
            const cmd = jessy('scripts.wisdom', info);

            if (!cmd)
                return callback();

            runWisdom('wisdom', type, version, emitter, callback);
        },

        (callback) => {
            if (!isUndefined(info.changelog) && !info.changelog) {
                emitter.emit('data', 'changelog: false\n');
                return callback();
            }

            changelog(version, (error, data) => {
                if (error) {
                    error.message += '\n';
                    callback(error);
                    return;
                }

                const name = path.join(InfoDir(), 'ChangeLog');

                prepend(name, data, callback);

                chlog = rmLines(data, 2);
                chlog = markdown(chlog);
            });
        },

        (callback) => {
            versionio(version, callback);
        },

        removeBowerVersion(emitter),

        (callback) => {
            execute(cmd, version, emitter, callback);
        },

        function release(callback) {
            const isNoRelease = !info.release && !isUndefined(info.release);

            if (isNoRelease) {
                emitter.emit('data', 'release: false\n');
                return callback();
            }

            execute(cmdTag, version, emitter, callback);
        },

        function publish(callback) {
            if (!info.release && !isUndefined(info.release))
                return callback();

            const tag = 'v' + version;
            const data = {
                user: getUser(info),
                repo: getRepoName(info),
                tag,
                name: info.name + ' ' + tag,
                body: chlog
            };

            grizzly(null, data, (error) => {
                if (!error) {
                    emitter.emit('data', 'release: ok\n');
                    return callback();
                }

                emitter.emit('data', 'Error releasing on github. Trying again.\n');
                publish(callback);
            });
        },

        function npmPublish(callback) {
            if (info.private)
                return callback();

            execute('npm publish', version, emitter, callback);
        },

        function afterPublish(callback) {
            const cmd = jessy('scripts.wisdom:done', info);

            if (!cmd)
                return callback();

            runWisdom('wisdom:done', null, version, emitter, callback);
        },
    ], (error) => {
        if (error)
            emitter.emit('error', error);

        emitter.emit('exit');
    });

    return emitter;
}

function getEnv(version) {
    return Object.assign(process.env, {
        wisdom_version: version,
        WISDOM_VERSION: version
    });
}

function execute(cmd, version, emitter, callback) {
    let rejected;

    const spawn = spawnify(cmd, {
        env: getEnv(version),
        cwd: InfoDir(),
    });

    spawn.on('error', (error) => {
        rejected = ~error.message.indexOf('rejected');

        emitter.emit('error', error);

        if (rejected)
            callback(error);
    });

    spawn.on('data', (data) => {
        emitter.emit('data', data);
    });

    spawn.on('exit', () => {
        if (!rejected)
            callback();
    });
}

function runWisdom(name, type, version, emitter, callback) {
    let array = ['npm', 'run', name];

    if (type)
        array = array.concat('--', type);

    const cmd = array.join(' ');
    const spawn = spawnify(cmd, {
        env: getEnv(version)
    });

    spawn.on('error', (error) => {
        emitter.emit('error', error);
    });

    spawn.on('data', (data) => {
        emitter.emit('data', data);
    });

    spawn.on('close', callback);
}

function rmLines(str, count) {
    return str
        .split('\n')
        .slice(count)
        .join('\n');
}

function markdown(str) {
    return str
        .replace(/\bfix\b:/g, '## fix')
        .replace(/\bfeature\b:/g, '## feature');
}

function getRepoName(json) {
    return (jessy('repository.url', json) || '')
        .split('/')
        .pop()
        .replace('.git', '');
}

function getUser(json) {
    const FROM_USER = 3;
    const WITHOUT_REPO = -1;

    return json.repository.url
        .split('/')
        .slice(FROM_USER, WITHOUT_REPO)
        .pop();
}

<commit_msg>fix(wisdom) currify<commit_after>'use strict';

const path = require('path');
const EventEmitter= require('events').EventEmitter;

const versionio = require('version-io');
const changelog = require('changelog-io');
const rendy = require('rendy');
const spawnify = require('spawnify');
const series = require('async/series');
const minor = require('minor');
const prepend = require('prepend');
const grizzly = require('grizzly');
const jessy = require('jessy');
const readPkg = require('read-pkg-up');
const fullstore = require('fullstore');
const currify = require('currify/legacy');

const removeBowerVersion = currify(require('./remove-bower-version'));

const isUndefined = (a) => typeof a === 'undefined';

const Cmd = [
    'git add --all',
    'git commit -m "chore(package) v{{ version }}"',
    'git pull --rebase',
    'git push origin {{ branch }}',
].join('&&');

const CmdTag = [
    'git tag v{{ version }}',
    'git push origin v{{ version }}'
].join('&&');

const InfoDir = fullstore();

const setInfoDir = (data) => {
    const dir = path.dirname(data.path);

    InfoDir(dir);

    return data;
};

const getPkg = (data) => data.pkg;

module.exports = (version) => {
    const emitter = new EventEmitter();

    const onError = (e) => {
        const error = Error(`Error reading package.json: ${e.message}`);
        emitter.emit('error', error);
    };

    const start = currify((version, emitter, info) => {
        if (!version)
            return emitter.emit('data',
                `publish <version>\n` +
                `package: ${ info.name } ${ info.version }`
            );

        publish(version, info, emitter);
    });

    readPkg()
        .then(setInfoDir)
        .then(getPkg)
        .then(start(version, emitter))
        .catch(onError);

    return emitter;
};

function publish(version, info, emitter) {
    let type = '--';
    let chlog = '';

    if (!version.indexOf('v')) {
        version = version.slice(1);
        type += 'v' + version;
    } else if (/major|minor|patch/.test(version)) {
        type += version;
        version = minor(version, info.version);
    }

    const cmd = rendy(Cmd, {
        version: version,
        branch: info.branch || 'master'
    });

    const cmdTag = rendy(CmdTag, {
        version: version
    });

    series([
        function beforePublish(callback) {
            const cmd = jessy('scripts.wisdom', info);

            if (!cmd)
                return callback();

            runWisdom('wisdom', type, version, emitter, callback);
        },

        (callback) => {
            if (!isUndefined(info.changelog) && !info.changelog) {
                emitter.emit('data', 'changelog: false\n');
                return callback();
            }

            changelog(version, (error, data) => {
                if (error) {
                    error.message += '\n';
                    callback(error);
                    return;
                }

                const name = path.join(InfoDir(), 'ChangeLog');

                prepend(name, data, callback);

                chlog = rmLines(data, 2);
                chlog = markdown(chlog);
            });
        },

        (callback) => {
            versionio(version, callback);
        },

        removeBowerVersion(emitter),

        (callback) => {
            execute(cmd, version, emitter, callback);
        },

        function release(callback) {
            const isNoRelease = !info.release && !isUndefined(info.release);

            if (isNoRelease) {
                emitter.emit('data', 'release: false\n');
                return callback();
            }

            execute(cmdTag, version, emitter, callback);
        },

        function publish(callback) {
            if (!info.release && !isUndefined(info.release))
                return callback();

            const tag = 'v' + version;
            const data = {
                user: getUser(info),
                repo: getRepoName(info),
                tag,
                name: info.name + ' ' + tag,
                body: chlog
            };

            grizzly(null, data, (error) => {
                if (!error) {
                    emitter.emit('data', 'release: ok\n');
                    return callback();
                }

                emitter.emit('data', 'Error releasing on github. Trying again.\n');
                publish(callback);
            });
        },

        function npmPublish(callback) {
            if (info.private)
                return callback();

            execute('npm publish', version, emitter, callback);
        },

        function afterPublish(callback) {
            const cmd = jessy('scripts.wisdom:done', info);

            if (!cmd)
                return callback();

            runWisdom('wisdom:done', null, version, emitter, callback);
        },
    ], (error) => {
        if (error)
            emitter.emit('error', error);

        emitter.emit('exit');
    });

    return emitter;
}

function getEnv(version) {
    return Object.assign(process.env, {
        wisdom_version: version,
        WISDOM_VERSION: version
    });
}

function execute(cmd, version, emitter, callback) {
    let rejected;

    const spawn = spawnify(cmd, {
        env: getEnv(version),
        cwd: InfoDir(),
    });

    spawn.on('error', (error) => {
        rejected = ~error.message.indexOf('rejected');

        emitter.emit('error', error);

        if (rejected)
            callback(error);
    });

    spawn.on('data', (data) => {
        emitter.emit('data', data);
    });

    spawn.on('exit', () => {
        if (!rejected)
            callback();
    });
}

function runWisdom(name, type, version, emitter, callback) {
    let array = ['npm', 'run', name];

    if (type)
        array = array.concat('--', type);

    const cmd = array.join(' ');
    const spawn = spawnify(cmd, {
        env: getEnv(version)
    });

    spawn.on('error', (error) => {
        emitter.emit('error', error);
    });

    spawn.on('data', (data) => {
        emitter.emit('data', data);
    });

    spawn.on('close', callback);
}

function rmLines(str, count) {
    return str
        .split('\n')
        .slice(count)
        .join('\n');
}

function markdown(str) {
    return str
        .replace(/\bfix\b:/g, '## fix')
        .replace(/\bfeature\b:/g, '## feature');
}

function getRepoName(json) {
    return (jessy('repository.url', json) || '')
        .split('/')
        .pop()
        .replace('.git', '');
}

function getUser(json) {
    const FROM_USER = 3;
    const WITHOUT_REPO = -1;

    return json.repository.url
        .split('/')
        .slice(FROM_USER, WITHOUT_REPO)
        .pop();
}

<|endoftext|>


<commit_before>var fs = require('fs');

function TumblrClient(credentials) {
  this.credentials = credentials || {};
}

var request;

module.exports = {

  Client: TumblrClient,

  createClient: function (credentials) {
    return new TumblrClient(credentials);
  },

  request: function(r) {
    request = r;
  }

};

var baseURL = 'http://api.tumblr.com/v2';

var calls = {
  postCreation: function (type, requireOptions, allowsData) {
    return function (blogName, options, callback) {
      validations.require(options, requireOptions);
      this._createPost(blogName, type, options, allowsData, callback);
    };
  }
};

TumblrClient.prototype = {

  // Tagged

  tagged: function (tag, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    this._get('/tagged', options, callback);
  },

  // Blogs

  blogInfo: function (blogName, callback) {
    this._get(blogURLPath(blogName, '/info'), {api_key: this.credentials.consumer_key}, callback);
  },

  avatar: function (blogName, size, callback) {
    if (isFunction(size)) { callback = size; size = null; }

    this._get(blogURLPath(blogName, '/avatar/' + (size || 64)), {api_key: this.credentials.consumer_key}, callback);
  },

  blogLikes: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    this._get(blogURLPath(blogName, '/likes'), options, callback);
  },

  followers: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }
    this._get(blogURLPath(blogName, '/followers'), options, callback);
  },

  posts: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    var path = '/posts';
    if (options.type) {
      path += '/' + options.type;
    }

    this._get(blogURLPath(blogName, path), options, callback);
  },

  queue: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get(blogURLPath(blogName, '/posts/queue'), options, callback);
  },

  drafts: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get(blogURLPath(blogName, '/posts/draft'), options, callback);
  },

  submissions: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get(blogURLPath(blogName, '/posts/submission'), options, callback);
  },

  // Posts

  edit: function (blogName, options, callback) {
    this._post(blogURLPath(blogName, '/post/edit'), options, callback);
  },

  reblog: function (blogName, options, callback) {
    this._post(blogURLPath(blogName, '/post/reblog'), options, callback);
  },

  deletePost: function (blogName, id, callback) {
    this._post(blogURLPath(blogName, '/post/delete'), {id: id}, callback);
  },

  photo: calls.postCreation('photo', ['data', 'source'],       true),
  audio: calls.postCreation('audio', ['data', 'external_url'], true),
  video: calls.postCreation('video', ['data', 'embed'],        true),
  quote: calls.postCreation('quote', ['quote'],                false),
  text:  calls.postCreation('text',  ['body'],                 false),
  link:  calls.postCreation('link',  ['url'],                  false),
  chat:  calls.postCreation('chat',  ['conversation'],         false),

  // User

  userInfo: function (callback) {
    this._get('/user/info', {}, callback);
  },

  dashboard: function (options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get('/user/dashboard', options, callback);
  },

  likes: function (options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    this._get('/user/likes', options, callback);
  },

  following: function (options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get('/user/following', options, callback);
  },

  follow: function (blogName, callback) {
    this._post('/user/follow', {url: blogURL(blogName)}, callback);
  },

  unfollow: function (blogName, callback) {
    this._post('/user/unfollow', {url: blogURL(blogName)}, callback);
  },

  like: function (id, reblogKey, callback) {
    this._post('/user/like', {id: id, reblog_key: reblogKey}, callback);
  },

  unlike: function (id, reblogKey, callback) {
    this._post('/user/unlike', {id: id, reblog_key: reblogKey}, callback);
  },

  // Helpers

  _createPost: function (blogName, type, options, acceptsData, callback) {
    options = options || {};
    options.type = type;

    if (acceptsData && options.data) {
      var that = this;
      fs.readFile(options.data, function (err, data) {
        if (err) throw err;
        options.data = data.toString('base64');
        that._post(blogURLPath(blogName, '/post'), options, callback);
      });
    } else {
      this._post(blogURLPath(blogName, '/post'), options, callback);
    }
  },

  _get: function (path, params, callback) {
    request.get({url: baseURL + path, qs: params, oauth: this.credentials, followRedirect: false}, requestCallback(callback));
  },

  _post: function (path, params, callback) {
    request.post({url: baseURL + path, form: params, oauth: this.credentials, followRedirect: false}, requestCallback(callback));
  }

};

var requireValidation = function (options, choices) {
  var count = 0;
  for (var i = 0; i < choices.length; i++) {
    if (!options[choices[i]]) count += 1;
  }
  if (choices.length === 1) {
    if (count === 0) {
      throw new Error('Missing required field: "' + choices[0] + '"');
    }
  } else if (choices.length > 1) {
    if (count === 0) {
      throw new Error('Missing one of: ' + choices.join(','));
    }
    if (count > 1) {
      throw new Error('Can only use one of: ' + choices.join(','));
    }
  }
};

function blogURL(blogName) {
  return blogName + '.tumblr.com';
}

function blogURLPath(blogName, path) {
  return '/blog/' + blogURL(blogName) + path;
}

function requestCallback(callback) {
  if (!callback) return function () {};

  return function (err, response, body) {
    if (err) return callback(err);

    var responseBody = JSON.parse(body),
      statusCode = responseBody.meta.status,
      message = responseBody.meta.msg;

    if (Math.floor(statusCode / 100) !== 2 && statusCode != 301) // Avatar requests will return 301 responses
      return callback(new Error('API error: ' + statusCode + ' ' + message));

    return callback(null, responseBody.response);
  };
}

function isFunction(value) {
  return Object.prototype.toString.call(value) == '[object Function]';
}
<commit_msg>Object creation change<commit_after>var fs = require('fs');

function TumblrClient(credentials) {
  this.credentials = credentials || {};
}

var request;

module.exports = {

  Client: TumblrClient,

  createClient: function (credentials) {
    var client = Object.create(TumblrClient.prototype);
    TumblrClient.bind(client)(credentials);
    return client;
  },

  request: function(r) {
    request = r;
  }

};

var baseURL = 'http://api.tumblr.com/v2';

var calls = {
  postCreation: function (type, requireOptions, allowsData) {
    return function (blogName, options, callback) {
      validations.require(options, requireOptions);
      this._createPost(blogName, type, options, allowsData, callback);
    };
  }
};

TumblrClient.prototype = {

  // Tagged

  tagged: function (tag, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    this._get('/tagged', options, callback);
  },

  // Blogs

  blogInfo: function (blogName, callback) {
    this._get(blogURLPath(blogName, '/info'), {api_key: this.credentials.consumer_key}, callback);
  },

  avatar: function (blogName, size, callback) {
    if (isFunction(size)) { callback = size; size = null; }

    this._get(blogURLPath(blogName, '/avatar/' + (size || 64)), {api_key: this.credentials.consumer_key}, callback);
  },

  blogLikes: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    this._get(blogURLPath(blogName, '/likes'), options, callback);
  },

  followers: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }
    this._get(blogURLPath(blogName, '/followers'), options, callback);
  },

  posts: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    var path = '/posts';
    if (options.type) {
      path += '/' + options.type;
    }

    this._get(blogURLPath(blogName, path), options, callback);
  },

  queue: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get(blogURLPath(blogName, '/posts/queue'), options, callback);
  },

  drafts: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get(blogURLPath(blogName, '/posts/draft'), options, callback);
  },

  submissions: function (blogName, options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get(blogURLPath(blogName, '/posts/submission'), options, callback);
  },

  // Posts

  edit: function (blogName, options, callback) {
    this._post(blogURLPath(blogName, '/post/edit'), options, callback);
  },

  reblog: function (blogName, options, callback) {
    this._post(blogURLPath(blogName, '/post/reblog'), options, callback);
  },

  deletePost: function (blogName, id, callback) {
    this._post(blogURLPath(blogName, '/post/delete'), {id: id}, callback);
  },

  photo: calls.postCreation('photo', ['data', 'source'],       true),
  audio: calls.postCreation('audio', ['data', 'external_url'], true),
  video: calls.postCreation('video', ['data', 'embed'],        true),
  quote: calls.postCreation('quote', ['quote'],                false),
  text:  calls.postCreation('text',  ['body'],                 false),
  link:  calls.postCreation('link',  ['url'],                  false),
  chat:  calls.postCreation('chat',  ['conversation'],         false),

  // User

  userInfo: function (callback) {
    this._get('/user/info', {}, callback);
  },

  dashboard: function (options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get('/user/dashboard', options, callback);
  },

  likes: function (options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    options = options || {};
    options.api_key = this.credentials.consumer_key;

    this._get('/user/likes', options, callback);
  },

  following: function (options, callback) {
    if (isFunction(options)) { callback = options; options = {}; }

    this._get('/user/following', options, callback);
  },

  follow: function (blogName, callback) {
    this._post('/user/follow', {url: blogURL(blogName)}, callback);
  },

  unfollow: function (blogName, callback) {
    this._post('/user/unfollow', {url: blogURL(blogName)}, callback);
  },

  like: function (id, reblogKey, callback) {
    this._post('/user/like', {id: id, reblog_key: reblogKey}, callback);
  },

  unlike: function (id, reblogKey, callback) {
    this._post('/user/unlike', {id: id, reblog_key: reblogKey}, callback);
  },

  // Helpers

  _createPost: function (blogName, type, options, acceptsData, callback) {
    options = options || {};
    options.type = type;

    if (acceptsData && options.data) {
      var that = this;
      fs.readFile(options.data, function (err, data) {
        if (err) throw err;
        options.data = data.toString('base64');
        that._post(blogURLPath(blogName, '/post'), options, callback);
      });
    } else {
      this._post(blogURLPath(blogName, '/post'), options, callback);
    }
  },

  _get: function (path, params, callback) {
    request.get({url: baseURL + path, qs: params, oauth: this.credentials, followRedirect: false}, requestCallback(callback));
  },

  _post: function (path, params, callback) {
    request.post({url: baseURL + path, form: params, oauth: this.credentials, followRedirect: false}, requestCallback(callback));
  }

};

var requireValidation = function (options, choices) {
  var count = 0;
  for (var i = 0; i < choices.length; i++) {
    if (!options[choices[i]]) count += 1;
  }
  if (choices.length === 1) {
    if (count === 0) {
      throw new Error('Missing required field: "' + choices[0] + '"');
    }
  } else if (choices.length > 1) {
    if (count === 0) {
      throw new Error('Missing one of: ' + choices.join(','));
    }
    if (count > 1) {
      throw new Error('Can only use one of: ' + choices.join(','));
    }
  }
};

function blogURL(blogName) {
  return blogName + '.tumblr.com';
}

function blogURLPath(blogName, path) {
  return '/blog/' + blogURL(blogName) + path;
}

function requestCallback(callback) {
  if (!callback) return function () {};

  return function (err, response, body) {
    if (err) return callback(err);

    var responseBody = JSON.parse(body),
      statusCode = responseBody.meta.status,
      message = responseBody.meta.msg;

    if (Math.floor(statusCode / 100) !== 2 && statusCode != 301) // Avatar requests will return 301 responses
      return callback(new Error('API error: ' + statusCode + ' ' + message));

    return callback(null, responseBody.response);
  };
}

function isFunction(value) {
  return Object.prototype.toString.call(value) == '[object Function]';
}
<|endoftext|>


<commit_before>'use strict';

//# Initialization Wizard

//** Setup dependencies
var inquirer = require('inquirer'),
     install = require('./install'),
           _ = require('lodash');

//* Callback must be in the form `function(results)`
module.exports = function(options, indexCb) {

  function require(value) {
    return !!value.trim() || 'Required';
  }

  var questions = [{
    type: 'input',
    name: 'name',
    message: 'What would you have your MEAN app be called?',
    default: options.name,
    validate: required
  }];

  inquirer.prompt(questions, function(results) {
    _.assign(options, results);
    install.init(options, indexCb);
  })
}
<commit_msg>fix(wizard): correct function name<commit_after>'use strict';

//# Initialization Wizard

//** Setup dependencies
var inquirer = require('inquirer'),
     install = require('./install'),
           _ = require('lodash');

//* Callback must be in the form `function(results)`
module.exports = function(options, indexCb) {

  function required(value) {
    return !!value.trim() || 'Required';
  }

  var questions = [{
    type: 'input',
    name: 'name',
    message: 'What would you have your MEAN app be called?',
    default: options.name,
    validate: required
  }];

  inquirer.prompt(questions, function(results) {
    _.assign(options, results);
    install.init(options, indexCb);
  })
}
<|endoftext|>


<commit_before>/*jslint node:true */
/*if (!Promise) {
  var Promise = require("bluebird");
}*/

var TVDBClient = require('node-tvdb');
var moment = require('moment');
var slug = require('slug');
var models = require('../models');
var config = require('../config');

/**
 * Test if a genre is already in database
 *
 * @param {string} genreName - The genre name
 * @return {Promise}
 */
function testGenre(genreName) {
  'use strict';
  return new Promise(function (resolve, reject) {
    models.Genre
      .findOrCreate({ where: { name: genreName } })
      .spread(function (genre, created) {
        if (created) {
          console.info('Genre ' + genreName + ' has been created.');
        }
        resolve(genre);
      })
      .catch(function (err) {
        reject(err);
      });
  });
}

/**
 * Insert a new episode
 *
 * @param {integer} showid - The show id
 * @param {object} episode - The episode
 * @return {Promise}
 */
function insertEpisode(showid, episode) {
  'use strict';
  return new Promise(function (resolve, reject) {
    var firstAired = null;
    if (episode.FirstAired !== null) {
      firstAired = new Date(episode.FirstAired);
    }
    models.Episode
      .create(
        {
          ShowId: showid,
          season: episode.SeasonNumber,
          episode: episode.EpisodeNumber,
          title: episode.EpisodeName,
          date: firstAired
        }
      )
      .then(function (episode) {
        resolve(episode);
      })
      .catch(function (err) {
        console.log(episode);
        reject(err);
      });
  });
}

/**
 * Class for tvshow
 *
 * @class tvshow
 */
var tvshow = {
  /**
   * Add a new show
   *
   * @param {integer} showid - The show id
   * @return {Promise}
   */
  add: function (showid) {
    'use strict';
    return new Promise(function (resolve, reject) {
      models.Show
        .findById(showid)
        .then(function (show) {
          if (show === null) {
            console.info('Getting TV show from TVDB.');
            var tvdb = new TVDBClient(config.tvdbkey);
            tvdb.getSeriesById(showid)
              .then(function (show) {
                var genresPromises = show.Genre
                  .split('|')
                  .map(function (genre) {
                    if (genre !== '') {
                      return testGenre(genre);
                    }
                  });
                Promise.all(genresPromises)
                  .then(function (genres) {
                    /* Cleanup genres */
                    genres = genres.filter(function (genre) {
                      return genre !== undefined;
                    });
                    var ended = false,
                      started = Date.parse(show.FirstAired);
                    if (started === 'Nan') {
                      started = 0;
                    }
                    if (show.Status === 'Ended') {
                      ended = true;
                    }
                    console.info('Insert the TVShow ' + show.SeriesName);
                    models.Show
                      .create(
                        {
                          id: show.id,
                          name: show.SeriesName,
                          slug: slug(show.SeriesName),
                          image: show.poster,
                          started: moment(started).year(),
                          classification: show.ContentRating,
                          ended: ended,
                          runtime: show.Runtime,
                          imdb_id: show.IMDB_ID
                        }
                      )
                      .then(function (show) {
                        show
                          .setGenres(genres)
                          .then(function () {
                            resolve(show);
                          })
                          .catch(function (err) {
                            reject(err);
                          });
                      })
                      .catch(function (err) {
                        reject(err);
                      });
                  });
              })
              .catch(function (err) {
                reject(err);
              });
          }
        })
        .catch(function (err) {
          reject(err);
        });
    });
  },
  /**
   * Update a show
   *
   * Update by show id integer or string : Update from TVRage
   * Update by show object : Update with the array of episodes
   *
   * @param {string|integer|object} show - The show id or the show object
   * @param {object} episodes - The list of episodes to update
   * @return {Promise}
   */
  update: function (show, episodes) {
    'use strict';
    var self = this;
    return new Promise(function (resolve, reject) {
      if (typeof show === 'string' || typeof show === 'number') {
        models.Show
          .findById(show)
          .then(function (show) {
            if (show === null) {
              reject('The show ' + show.name + ' is not registred.');
            } else {
              var tvdb = new TVDBClient(config.tvdbkey);
              tvdb
                .getSeriesAllById(show.id)
                .then(function (episodes) {
                  show.image = episodes.poster;
                  if (episodes.Status === 'Ended') {
                    show.ended = true;
                  }
                  self.update(show, episodes.Episodes)
                    .then(function () {
                      resolve();
                    })
                    .catch(function (err) {
                      reject(err);
                    });
                })
                .catch(function (err) {
                  reject(err);
                });
            }
          })
          .catch(function (err) {
            reject(err);
          });
      } else {
        models.Episode
          .destroy({ where: { ShowId: show.id }})
          .then(function () {
            var episodesPromise = episodes.map(function (episode) {
              if (!episode.EpisodeName) {
                episode.EpisodeName = 'TBA';
              }
              return insertEpisode(show.id, episode);
            });
            Promise.all(episodesPromise)
              .then(function () {
                show.last_update = moment();
                show.save()
                  .then(function () {
                    resolve();
                  })
                  .catch(function (err) {
                    reject(err);
                  });
              })
              .catch(function (err) {
                reject(err);
              });
          })
          .catch(function (err) {
            reject(err);
          });
      }
    });
  }
};

module.exports = tvshow;
<commit_msg>Remove episode with no name and season 0 and episode 0<commit_after>/*jslint node:true */
/*if (!Promise) {
  var Promise = require("bluebird");
}*/

var TVDBClient = require('node-tvdb');
var moment = require('moment');
var slug = require('slug');
var models = require('../models');
var config = require('../config');

/**
 * Test if a genre is already in database
 *
 * @param {string} genreName - The genre name
 * @return {Promise}
 */
function testGenre(genreName) {
  'use strict';
  return new Promise(function (resolve, reject) {
    models.Genre
      .findOrCreate({ where: { name: genreName } })
      .spread(function (genre, created) {
        if (created) {
          console.info('Genre ' + genreName + ' has been created.');
        }
        resolve(genre);
      })
      .catch(function (err) {
        reject(err);
      });
  });
}

/**
 * Insert a new episode
 *
 * @param {integer} showid - The show id
 * @param {object} episode - The episode
 * @return {Promise}
 */
function insertEpisode(showid, episode) {
  'use strict';
  return new Promise(function (resolve, reject) {
    var firstAired = null;
    if (episode.FirstAired !== null) {
      firstAired = new Date(episode.FirstAired);
    }
    if (episode.EpisodeName === 'TBA'
       && episode.SeasonNumber == 0
       && episode.EpisodeNumber == 0) {
      resolve();
    }
    models.Episode
      .create(
        {
          ShowId: showid,
          season: episode.SeasonNumber,
          episode: episode.EpisodeNumber,
          title: episode.EpisodeName,
          date: firstAired
        }
      )
      .then(function (episode) {
        resolve(episode);
      })
      .catch(function (err) {
        console.log(episode);
        reject(err);
      });
  });
}

/**
 * Class for tvshow
 *
 * @class tvshow
 */
var tvshow = {
  /**
   * Add a new show
   *
   * @param {integer} showid - The show id
   * @return {Promise}
   */
  add: function (showid) {
    'use strict';
    return new Promise(function (resolve, reject) {
      models.Show
        .findById(showid)
        .then(function (show) {
          if (show === null) {
            console.info('Getting TV show from TVDB.');
            var tvdb = new TVDBClient(config.tvdbkey);
            tvdb.getSeriesById(showid)
              .then(function (show) {
                var genresPromises = show.Genre
                  .split('|')
                  .map(function (genre) {
                    if (genre !== '') {
                      return testGenre(genre);
                    }
                  });
                Promise.all(genresPromises)
                  .then(function (genres) {
                    /* Cleanup genres */
                    genres = genres.filter(function (genre) {
                      return genre !== undefined;
                    });
                    var ended = false,
                      started = Date.parse(show.FirstAired);
                    if (started === 'Nan') {
                      started = 0;
                    }
                    if (show.Status === 'Ended') {
                      ended = true;
                    }
                    console.info('Insert the TVShow ' + show.SeriesName);
                    models.Show
                      .create(
                        {
                          id: show.id,
                          name: show.SeriesName,
                          slug: slug(show.SeriesName),
                          image: show.poster,
                          started: moment(started).year(),
                          classification: show.ContentRating,
                          ended: ended,
                          runtime: show.Runtime,
                          imdb_id: show.IMDB_ID
                        }
                      )
                      .then(function (show) {
                        show
                          .setGenres(genres)
                          .then(function () {
                            resolve(show);
                          })
                          .catch(function (err) {
                            reject(err);
                          });
                      })
                      .catch(function (err) {
                        reject(err);
                      });
                  });
              })
              .catch(function (err) {
                reject(err);
              });
          }
        })
        .catch(function (err) {
          reject(err);
        });
    });
  },
  /**
   * Update a show
   *
   * Update by show id integer or string : Update from TVRage
   * Update by show object : Update with the array of episodes
   *
   * @param {string|integer|object} show - The show id or the show object
   * @param {object} episodes - The list of episodes to update
   * @return {Promise}
   */
  update: function (show, episodes) {
    'use strict';
    var self = this;
    return new Promise(function (resolve, reject) {
      if (typeof show === 'string' || typeof show === 'number') {
        models.Show
          .findById(show)
          .then(function (show) {
            if (show === null) {
              reject('The show ' + show.name + ' is not registred.');
            } else {
              var tvdb = new TVDBClient(config.tvdbkey);
              tvdb
                .getSeriesAllById(show.id)
                .then(function (episodes) {
                  show.image = episodes.poster;
                  if (episodes.Status === 'Ended') {
                    show.ended = true;
                  }
                  self.update(show, episodes.Episodes)
                    .then(function () {
                      resolve();
                    })
                    .catch(function (err) {
                      reject(err);
                    });
                })
                .catch(function (err) {
                  reject(err);
                });
            }
          })
          .catch(function (err) {
            reject(err);
          });
      } else {
        models.Episode
          .destroy({ where: { ShowId: show.id }})
          .then(function () {
            var episodesPromise = episodes.map(function (episode) {
              if (!episode.EpisodeName) {
                episode.EpisodeName = 'TBA';
              }
              return insertEpisode(show.id, episode);
            });
            Promise.all(episodesPromise)
              .then(function () {
                show.last_update = moment();
                show.save()
                  .then(function () {
                    resolve();
                  })
                  .catch(function (err) {
                    reject(err);
                  });
              })
              .catch(function (err) {
                reject(err);
              });
          })
          .catch(function (err) {
            reject(err);
          });
      }
    });
  }
};

module.exports = tvshow;
<|endoftext|>


<commit_before>var _ = require('underscore');
var Backbone = require('backbone');

var wordnik_bb = require('../lib/wordnik-bb.js');
console.log("!!!",wordnik_bb);
/*
  ======== A Handy Little Nodeunit Reference ========
  https://github.com/caolan/nodeunit

  Test methods:
    test.expect(numAssertions)
    test.done()
  Test assertions:
    test.ok(value, [message])
    test.equal(actual, expected, [message])
    test.notEqual(actual, expected, [message])
    test.deepEqual(actual, expected, [message])
    test.notDeepEqual(actual, expected, [message])
    test.strictEqual(actual, expected, [message])
    test.notStrictEqual(actual, expected, [message])
    test.throws(block, [error], [message])
    test.doesNotThrow(block, [error], [message])
    test.ifError(value)
*/

exports['init'] = {
  setUp: function(done) {
    // setup here
    done();
  },
  'no args': function(test) {
    test.expect(2);
    // tests here
    test.equal(typeof wordnik_bb, "object", "Wornik lib returns an object.");
    test.equal(typeof wordnik_bb.init, "function", 'The object has an init function');
    test.done();
  }
};
<commit_msg>More tests.<commit_after>var _ = require('underscore');
var Backbone = require('backbone');

var wordnik_bb = require('../lib/wordnik-bb.js');

/*
  ======== A Handy Little Nodeunit Reference ========
  https://github.com/caolan/nodeunit

  Test methods:
    test.expect(numAssertions)
    test.done()
  Test assertions:
    test.ok(value, [message])
    test.equal(actual, expected, [message])
    test.notEqual(actual, expected, [message])
    test.deepEqual(actual, expected, [message])
    test.notDeepEqual(actual, expected, [message])
    test.strictEqual(actual, expected, [message])
    test.notStrictEqual(actual, expected, [message])
    test.throws(block, [error], [message])
    test.doesNotThrow(block, [error], [message])
    test.ifError(value)
*/

exports['init'] = {
  setUp: function(done) {
    // setup here
    this.Wordnik = wordnik_bb.init('');
    done();
  },
  'Wordnik object structure': function(test) {
    test.expect(2);
    // tests here
    test.equal(typeof wordnik_bb, "object", "Wordnik lib returns an object.");
    test.equal(typeof wordnik_bb.init, "function", 'The object has an init function');
    test.done();
  },
  'Word model': function(test) {
    test.expect(2);
    test.equal(typeof this.Wordnik.Word, "function", "Word is a function (constructor)");
    var word = new this.Wordnik.Word({ word: 'kings' });
    test.ok(word.idAttribute, "Word constructor returns a Backbone Model");
    test.done();
  }
};
<|endoftext|>


<commit_before>var fs = require('../');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var test = require('tap').test;
var p = require('path').resolve(__dirname, 'files');

process.chdir(__dirname)

// Make sure to reserve the stderr fd
process.stderr.write('');

var num = 4097;
var paths = new Array(num);

test('make files', function (t) {
  rimraf.sync(p);
  mkdirp.sync(p);

  for (var i = 0; i < num; ++i) {
    paths[i] = 'files/file-' + i;
    fs.writeFileSync(paths[i], 'content');
  }

  t.end();
})

test('copy files', function (t) {
  for (var i = 0; i < num; ++i) {
    paths[i] = 'files/file-' + i;
    fs.copyFile(paths[i], paths[i] + '.copy', function(err) {
      if (err)
        throw err;
    });
  }

  t.end();
})

test('copy files with flags', function (t) {
  for (var i = 0; i < num; ++i) {
    paths[i] = 'files/file-' + i;
    fs.copyFile(paths[i], paths[i] + '.copy', 2, function(err) {
      if (err)
        throw err;
    });
  }

  t.end();
})

test('read files', function (t) {
  function expectContent(err, data) {
    if (err)
      throw err;

    t.equal(data, 'content')
  }

  // now read them
  t.plan(num * 2)
  for (var i = 0; i < num; ++i) {
    fs.readFile(paths[i], 'ascii', expectContent);
    fs.readFile(paths[i] + '.copy', 'ascii', expectContent);
  }
});

test('cleanup', function (t) {
  rimraf.sync(p);
  t.end();
});
<commit_msg>avoid spurious EBUSY in windows CI tests<commit_after>var fs = require('../')
var rimraf = require('rimraf')
var mkdirp = require('mkdirp')
var test = require('tap').test
var p = require('path').resolve(__dirname, 'files')

process.chdir(__dirname)

// Make sure to reserve the stderr fd
process.stderr.write('')

var num = 4097
var paths = new Array(num)

test('make files', function (t) {
  rimraf(p, function (err) {
    if (err) {
      throw err
    }
    mkdirp(p, function (err) {
      if (err) {
        throw err
      }
      for (var i = 0; i < num; ++i) {
        paths[i] = 'files/file-' + i
        fs.writeFileSync(paths[i], 'content')
      }

      t.end()
    })
  })
})

test('copy files', function (t) {
  var rem = num
  for (var i = 0; i < num; ++i) {
    paths[i] = 'files/file-' + i
    fs.copyFile(paths[i], paths[i] + '.copy', function(err) {
      if (err)
        throw err
      if (--rem === 0) {
        t.end()
      }
    })
  }
})

test('copy files with flags', function (t) {
  var rem = num
  for (var i = 0; i < num; ++i) {
    paths[i] = 'files/file-' + i
    fs.copyFile(paths[i], paths[i] + '.copy', 2, function(err) {
      if (err)
        throw err
      if (--rem === 0) {
        t.end()
      }
    })
  }
})

test('read files', function (t) {
  function expectContent(err, data) {
    if (err)
      throw err

    t.equal(data, 'content')
  }

  // now read them
  t.plan(num * 2)
  for (var i = 0; i < num; ++i) {
    fs.readFile(paths[i], 'ascii', expectContent)
    fs.readFile(paths[i] + '.copy', 'ascii', expectContent)
  }
})

test('cleanup', function (t) {
  rimraf(p, function () {
    t.end()
  })
})
<|endoftext|>


<commit_before>var d3 = require('d3')

module.exports = function (tree) {

  function draw (selection) {
    selection.each(function (data, i) {
      var node = d3.select(this)
                   .classed('root', !tree.options.forest && i === 0)

      node.select('svg.icon')
          .attr('class', function (d) {
            return 'icon ' + tree.nodes[d.id][tree.options.accessors.color]
          })
          .select('use')
          .attr('xlink:href', function (d) {
            return '#icon-' + tree.nodes[d.id][tree.options.accessors.icon]
          })

      // change the state of the toggle icon by adjusting its class
      node.select('.toggler')
               .attr('class', function (d) {
                 return 'toggler ' + (d.children ? 'expanded' : d._allChildren && d._allChildren.length ? 'collapsed' : 'leaf')
               })

      // Perhaps the name changed
      node.select('div.label')
                .text(function (d) {
                  return tree.nodes[d.id][tree.options.accessors.label]
                })

      // If the tree has indicators, we may need to update the color
      node.select('div.indicator')
          .attr('class', function (d) {
            return 'label-mask indicator ' + tree.nodes[d.id][tree.options.accessors.color]
          })

      node.style(tree.prefix + 'transform', function (d) {
            return 'translate(0px,' + d._y + 'px)'
          })
          .style('opacity', 1)

      // Now we can move the group so it's indented correctly
      node.select('div.node-contents')
          .attr('style', function (d) {
            return tree.prefix + 'transform:' + 'translate(' + d._x + 'px,0px)'
          })
    })

    return selection
  }

  return draw
}
<commit_msg>Adds icon class to svg.icon<commit_after>var d3 = require('d3')

module.exports = function (tree) {

  function draw (selection) {
    selection.each(function (data, i) {
      var node = d3.select(this)
                   .classed('root', !tree.options.forest && i === 0)

      node.select('svg.icon')
          .attr('class', function (d) {
            return 'icon ' + tree.nodes[d.id][tree.options.accessors.color] + ' ' + (tree.nodes[d.id][tree.options.accessors.icon] || '')
          })
          .select('use')
          .attr('xlink:href', function (d) {
            return '#icon-' + tree.nodes[d.id][tree.options.accessors.icon]
          })

      // change the state of the toggle icon by adjusting its class
      node.select('.toggler')
               .attr('class', function (d) {
                 return 'toggler ' + (d.children ? 'expanded' : d._allChildren && d._allChildren.length ? 'collapsed' : 'leaf')
               })

      // Perhaps the name changed
      node.select('div.label')
                .text(function (d) {
                  return tree.nodes[d.id][tree.options.accessors.label]
                })

      // If the tree has indicators, we may need to update the color
      node.select('div.indicator')
          .attr('class', function (d) {
            return 'label-mask indicator ' + tree.nodes[d.id][tree.options.accessors.color]
          })

      node.style(tree.prefix + 'transform', function (d) {
            return 'translate(0px,' + d._y + 'px)'
          })
          .style('opacity', 1)

      // Now we can move the group so it's indented correctly
      node.select('div.node-contents')
          .attr('style', function (d) {
            return tree.prefix + 'transform:' + 'translate(' + d._x + 'px,0px)'
          })
    })

    return selection
  }

  return draw
}
<|endoftext|>


<commit_before>
const Cluster = require("cluster");
const Path = require("path");

const Message = require(Path.join(__dirname, 'message'));

class Worker {

  constructor() {
    this.promises = {};
    this.parent = process;
  }

  start(onMessage, envInput) {

    if (!this.process) {
      let env = envInput || {
        parent: this.parent.pid,
      };

      let handler = (message) => {
        let msg = Message.deserialize(message);

        let promise = this.promises[msg.promise];

        promise.resolve(msg.response);
      };

      this.process = this.constructor.start(handler.bind(this), env);
    }

    return this.process;
  }

  stop() {
    let process = this.process.process;

    process.kill('SIGTERM');
  }

  send(msg) {
    this.process.send(msg); // send to our worker process
  }

  static generateExecuteMessage(func, args, delay) {
    let msg = new Message({
      action: func,
      arguments: args,
      delay: delay,
    });

    return msg;
  }

  static generatePromiseData(resolve, reject) {
    return {
      resolve: resolve,
      reject: reject,

    };
  }

  execute(func, args) {
    let msg = this.constructor.generateExecuteMessage(func, args);

    return this.constructor.execute(this, msg);
  }

  executeTimeout(func, delay, args) {
    let msg = this.constructor.generateExecuteMessage(func, args, delay);

    return this.constructor.execute(this, msg);
  }

  static execute(worker, msg) {

    return new Promise(function(worker, msg, resolve, reject) {
      msg.payload.promise = this.generatePromiseId();
      worker.promises[msg.payload.promise] = this.generatePromiseData(resolve, reject)

      worker.send(msg.serialize());
    }.bind(this, worker, msg));
  }

  static generatePromiseId() {
    return process.pid.toString() + '-' + Math.round(Math.random() * 10e15).toString(36);
  }

  static start(onMessage, env) {
    Cluster.setupMaster({
      exec: __filename,
    });

    let process = Cluster.fork(env);
    process.on('message', onMessage);  // msg from worker.

    return process;
  }

  static onMessage(msg) {
    // handle a message from the master.
    let args = msg.arguments;

    return msg.action.apply(this, args);
  }

}

// The runtime context, from here, is from within a worker process..
if (require.main === module) {
  // our file was called directly rather than req'd.
 //

  function responseFormat(ret, promiseId) {
    return {
      response: ret,
      promise: promiseId,
    }

  }

  process.on('message', (message) => {
    // handle a message from the master.

    let msg = Message.deserialize(message);
    //let ret = {
    //  response: Worker.onMessage(msg),
    //  promise: msg.promise,
    //};

    let promise;
    if (msg.delay) {
      let timeoutPromise = new Promise(function(msg, resolve, reject) {

        setTimeout(function(msg, resolve, reject) {
          let ret = Worker.onMessage(msg);

          resolve(ret);
        }.bind(undefined, msg, resolve, reject), msg.delay);

      }.bind(undefined, msg));

      timeoutPromise.then(function(msg, ret) {
        let res = responseFormat(ret, msg.promise);
        let outbound = new Message(res);

        process.send(outbound.serialize());
      }.bind(undefined, msg));

    } else {
      let ret = Worker.onMessage(msg);
      let res = responseFormat(ret, msg.promise);

      let outbound = new Message(res);
      process.send(outbound.serialize());
    }

  });

} else {
  // our file is loaded in a require(...) statement.
  module.exports = Worker;

}
<commit_msg>refactor worker to allow for user workers or dependencies<commit_after>
const Cluster = require("cluster");
const Path = require("path");

const Message = require(Path.join(__dirname, 'message'));

class Worker {

  constructor() {
    this.promises = {};
    this.parent = process;
  }

  start(onMessage, envInput) {

    if (!this.process) {
      let env = envInput || {
        parent: this.parent.pid,
      };

      let handler = (message) => {
        let msg = Message.deserialize(message);

        let promise = this.promises[msg.promise];

        promise.resolve(msg.response);
      };

      this.process = this.constructor.start(handler.bind(this), env);
    }

    return this.process;
  }

  stop() {
    let process = this.process.process;

    process.kill('SIGTERM');
  }

  send(msg) {
    this.process.send(msg); // send to our worker process
  }

  static generateExecuteMessage(func, args, delay) {
    let msg = new Message({
      action: func,
      arguments: args,
      delay: delay,
    });

    return msg;
  }

  static generatePromiseData(resolve, reject) {
    return {
      resolve: resolve,
      reject: reject,

    };
  }

  execute(func, args) {
    let msg = this.constructor.generateExecuteMessage(func, args);

    return this.constructor.execute(this, msg);
  }

  executeTimeout(func, delay, args) {
    let msg = this.constructor.generateExecuteMessage(func, args, delay);

    return this.constructor.execute(this, msg);
  }

  static execute(worker, msg) {

    return new Promise(function(worker, msg, resolve, reject) {
      msg.payload.promise = this.generatePromiseId();
      worker.promises[msg.payload.promise] = this.generatePromiseData(resolve, reject)

      worker.send(msg.serialize());
    }.bind(this, worker, msg));
  }

  static generatePromiseId() {
    return process.pid.toString() + '-' + Math.round(Math.random() * 10e15).toString(36);
  }

  static start(onMessage, env) {
    Cluster.setupMaster({
      exec: __filename,
    });

    let process = Cluster.fork(env);
    process.on('message', onMessage);  // msg from worker.

    return process;
  }

  static sendResponseMessage(msg, content) {
    let payload = {
      promise: msg.promise,
      response: content,
    };

    let res = new Message(payload);

    process.send(res.serialize());
  }

  static onMessage(msg) {

    let promise = new Promise((resolve, reject) => {

      let func = () => {
        let args = msg.arguments;

        try {
          let ret = msg.action.apply(Worker, args);

          resolve(ret);
        } catch(err) {

          reject(err);
        }

      };

      if (msg.delay) {
        setTimeout(func, msg.delay);
      } else {
        setImmediate(func);
      }

    });

    return promise;
  }

  static parseArguments(argsAry) {
    let args = new Array(...argsAry);  // non-destructive.
    let output = {};

    while (args.length) {
      let arg = args.shift();

      if (arg.match(/^--[^\s]+$/)) {
        // it's a flag.

        switch(arg.toLowerCase()) {
          case '--require':
            let param = args.shift();
            let components = param.split(/[\s]*\=[\s]*/);

            output.require = output.require || {};
            output.require[components[0]] = components[1];
            break;

          case '--worker':
            let path = args.shift();

            output.worker = path;
            break;
        }

      }

    }

    return output;
  }

}

// The runtime context, from here, is from within a worker process..
if (Cluster.isWorker) {
  // our file was called directly rather than req'd.

  let args = Worker.parseArguments(process.argv);

  for (let key in args.require) {
    // import some require'd libs.
    let path = args.require[key];

    this[key] = require(path);
  }

  let UserWorker = args.worker && require(args.worker);

  process.on('message', (message) => {
    // handle a message from the master.

    let msg = Message.deserialize(message);

    let workerObj = UserWorker || Worker;
    workerObj.onMessage(msg)
      .then(workerObj.sendResponseMessage.bind(undefined, msg));

  });

} else {
  // our file is loaded in a require(...) statement.
  module.exports = Worker;

}
<|endoftext|>


<commit_before>
// update - update (and upload) latest tweet and likes

var blake = require('blake')
  , http = require('http')
  , config = require('../config.js')
  , Transform = require('stream').Transform
  , Readable = require('stream').Readable
  , readArray = require('event-stream').readArray
  , filenames = [config.likes, config.tweet]
  , source = config.source
  , target = config.target

module.exports = function (req, res) {
  var stream = new Readable()
    , generator = blake(source, target)
    , started = false

  stream._read = function () {
    if (started) return // lord, have mercy
    started = true
    readArray(filenames).pipe(generator)
  }

  generator.on('readable', function () {
    var str = null, ok = true
    while (ok && null !== (str = generator.read())) {
      ok = stream.push(str + '\n')
    }
  })

  generator.on('end', function () {
    upload(stream).on('error', function (er) {
      stream.push('service unavailable\n')
      stream.push(null)
    })
    generator.removeAllListeners()
  })

  stream.pipe(res)
}

function upload (stream) {
  return http.get(config.upload, function (res) {
    res.on('readable', function () {
      var chunk = null, ok = true
      while (ok && null !== (chunk = res.read())) {
        ok = stream.push(chunk)
      }
    })
    res.on('end', function () {
      res.removeAllListeners()
      stream.push(null)
    })
  })
}
<commit_msg>Prevent crash<commit_after>
// update - update (and upload) latest tweet and likes

var blake = require('blake')
  , http = require('http')
  , config = require('../config.js')
  , Transform = require('stream').Transform
  , Readable = require('stream').Readable
  , readArray = require('event-stream').readArray
  , filenames = [config.likes, config.tweet]
  , source = config.source
  , target = config.target

module.exports = function (req, res) {
  var stream = new Readable()
    , gen = blake(source, target)
    , started = false

  stream._read = function () {
    if (started) return // lord, have mercy
    started = true
    readArray(filenames).pipe(gen)
  }

  gen.on('readable', function () {
    var str = null, ok = true
    while (ok && null !== (str = gen.read())) {
      ok = stream.push(str + '\n')
    }
  })

  gen.on('error', function (er) {
    console.error(er)
  }

  gen.on('end', function () {
    upload(stream).on('error', function (er) {
      stream.push('service unavailable\n')
      stream.push(null)
    })
    gen.removeAllListeners()
  })

  stream.pipe(res)
}

function upload (stream) {
  return http.get(config.upload, function (res) {
    res.on('readable', function () {
      var chunk = null, ok = true
      while (ok && null !== (chunk = res.read())) {
        ok = stream.push(chunk)
      }
    })
    res.on('end', function () {
      res.removeAllListeners()
      stream.push(null)
    })
  })
}
<|endoftext|>