<commit_before>var assert = require("chai").assert;
var reactHut = require("../bin/react-hut");
var render = require("enzyme").render;
var React = require("react");

function verifyTree(result, expected) {
        assert.equal(
            render(
{result}
).html(),
            render(
{expected}
).html());
}

describe("react-hut", () => {

    describe(".createHut()", () => {

        it("should return a function", () => {
            assert.isFunction(reactHut.createHut(React));
        });

        it("should throw error if react is not passed", () => {
            assert.throws(() => reactHut.createHut({}));
            assert.throws(() => reactHut.createHut());
        });
    });

    describe("default hut context", () => {
        let H = reactHut.createHut(React, {});
        let CustomElement = React.createClass({
            render() { return

                {this.props.value}
                {this.props.children}

}
        });

        describe("simple rendering", () => {

            it("should return null when called without input or with null as input", () => {
                assert.isNull(H());
                assert.isNull(H(null));

                assert.isNull(H([]));
                assert.isNull(H([null]));
            });

            it("should render a root primitive  without props", () => {
                verifyTree(H(["div", {}, []]),
);
            });

            it("should render a custom root element without props", () => {
                verifyTree(H([CustomElement]), <CustomElement/>);
            });

            it("should render different primitive element", () => {
                verifyTree(H(["div", {}, []]),
);
                verifyTree(H(["i", {}, []]), );
                verifyTree(H(["button", {}, []]), <button/>);
                verifyTree(H(["h1", {}, []]),
);
            });

            it("should render root element with props", () => {
                verifyTree(H([CustomElement, {value: "demo"}, []]), <CustomElement value="demo"/>);
            });

            it("should render root element with props and children", () => {
                verifyTree(H(
                    [
                        CustomElement, {value: "demo"},
                        [
                            ["div", {}, []],
                            ["div", {}, []]
                        ]

                    ]), <CustomElement value="demo">

                </CustomElement>);
            });

            it("should render root element with children", () => {
                verifyTree(H(
                    [
                        CustomElement,
                        [
                            ["div", {}, []],
                            ["div", {}, []]
                        ]

                    ]), <CustomElement>

                </CustomElement>);
            });

            it("should render child elements", () => {
                verifyTree(H(
                    [
                        CustomElement, {},
                        [
                            ["header", {className: "header"}, []],
                            ["div", {className: "content"}, []]
                        ]
                    ]),
                    <CustomElement>

                    </CustomElement>);

            });

            it("should render deeply nested child elements", () => {
                verifyTree(H(
                    [
                        CustomElement, {},
                        [
                            ["header", {className: "header"},
                                [
                                    ["h1", {}, "main-title"],
                                    ["h2", {}, "sub-title"],
                                    ["h3", {}, "sub-sub-title"]
                                ]
                            ],

                            ["div", {className: "content"},
                                [
                                    ["label", {}, "content"]
                                ]
                            ]
                        ]
                    ]),
                    <CustomElement>

main-title

sub-title

sub-sub-title

                            content

                    </CustomElement>);

            })

        });

        describe("invalid input", () => {

            it("should throw when root element is not inside an array and has > 3 args", () => {
                assert.throws(() => H("div", {}, [], "invalid"));
            });

            it("should throw when root element is inside an array and has > 1 args", () => {
                assert.throws(() => H(["div", {}, []], "invalid"));
            });

            it("should throw when multiple root elements are provided", () => {
                assert.throws(() => H(["h1"], ["h2"]));
            });

            it("should throw when a list of multiple nested children is provided", () => {
                assert.throws(() => H(["div", [[["span"], ["div"]]]]));
                assert.throws(() => H(["div", ["div", [["span"], ["div"]]]]));

            });

        });

        describe("nested array components", () => {

            it("should unpack nested root elements", () => {
                verifyTree(H([["div", {className: "demo"}, []]]),

);
            });

            it("should unpack deeply nested root elements", () => {
                verifyTree(H([[[[[[[[["div", {className: "demo"}, []]]]]]]]]]),

);
            });

            it("should unpack deeply nested single child elements", () => {
                verifyTree(H(["div", {className: "demo"}, [

                    ["span", {className: "one"}, "one"],
                    [[[[[["span", {className: "two"}, "two"]]]]]]

                ]]),

                    one
                    two

);
            });
        });

        describe("shorthand notation", () => {

            it("should be possible to omit [] when a component does't have props or children ", () => {

                verifyTree(H(["div", {className: "demo"}, [CustomElement, "div", "ul"]]),

                        <CustomElement />

);
            });

            it("should be possible to omit children  when a component does't have any ", () => {

                verifyTree(H(["div", {className: "demo"},
                        [[CustomElement, {value: "v"}], ["div", {className: "foo"}], "ul"]
                    ]),

                        <CustomElement value="v"/>

);
            });

            it("should be possible to omit props but still provide children", () => {

                verifyTree(H([
                        "div",
                        [
                            [CustomElement, {value: "v"}],
                            ["div",
                                [
                                    ["span", "value"]
                                ]
                            ]
                        ]
                    ]),

                        <CustomElement value="v"/>

                            value

);
            });

            it("should be possible to mix shorthand notation with normal notation", () => {

                verifyTree(H([
                        "div", {className: "demo"},
                        [
                            "div",
                            ["div", {className: "foo"}, []],
                            ["h1", "title"],
                            "span"
                        ]
                    ]),

title

);
            });

        })
    });
});<commit_msg>updated spec<commit_after>var assert = require("chai").assert;
var reactHut = require("../bin/react-hut");
var render = require("enzyme").render;
var React = require("react");

function verifyTree(result, expected) {
        assert.equal(
            render(
{result}
).html(),
            render(
{expected}
).html());
}

describe("react-hut", () => {

    describe(".createHut()", () => {

        it("should return a function", () => {
            assert.isFunction(reactHut.createHut(React));
        });

        it("should throw error if react is not passed", () => {
            assert.throws(() => reactHut.createHut({}));
            assert.throws(() => reactHut.createHut());
        });
    });

    describe("default hut context", () => {
        let H = reactHut.createHut(React, {});
        let CustomElement = React.createClass({
            render() { return

                {this.props.value}
                {this.props.children}

}
        });

        describe("simple rendering", () => {

            it("should return null when called without input or with null as input", () => {
                assert.isNull(H());
                assert.isNull(H(null));

                assert.isNull(H([]));
                assert.isNull(H([null]));
            });

            it("should render a root primitive", () => {
                verifyTree(H(["div", {}, []]),
);
            });

            it("should render a custom root element", () => {
                verifyTree(H([CustomElement]), <CustomElement/>);
            });

            it("should render different primitive element", () => {
                verifyTree(H(["div", {}, []]),
);
                verifyTree(H(["i", {}, []]), );
                verifyTree(H(["button", {}, []]), <button/>);
                verifyTree(H(["h1", {}, []]),
);
            });

            it("should render root element with props", () => {
                verifyTree(H([CustomElement, {value: "demo"}, []]), <CustomElement value="demo"/>);
            });

            it("should render root element with props and children", () => {
                verifyTree(H(
                    [
                        CustomElement, {value: "demo"},
                        [
                            ["div", {}, []],
                            ["div", {}, []]
                        ]

                    ]), <CustomElement value="demo">

                </CustomElement>);
            });

            it("should render child elements", () => {
                verifyTree(H(
                    [
                        CustomElement, {},
                        [
                            ["header", {className: "header"}, []],
                            ["div", {className: "content"}, []]
                        ]
                    ]),
                    <CustomElement>

                    </CustomElement>);

            });

            it("should not fuck with children that are not arrays", () => {
                verifyTree(H(
                    [
                        CustomElement, {},
                        [
                            "I'm a simple string ",
                            "answer is: ",
                            42
                        ]

                    ]), <CustomElement>{["I'm a simple string ", "answer is: ", 42]}</CustomElement>);
            });

            it("should be possible to mix literals with child components", () => {
                verifyTree(H(
                    [
                        CustomElement, {},
                        [
                            ["span", {className : "s1"}],
                            "I'm a simple string ",
                            "answer is: ",
                            42,
                            ["span", {className : "s2"}]
                        ]

                    ]), <CustomElement>
                        {["I'm a simple string ", "answer is: ", 42]}
                    </CustomElement>);
            });

            it("should render deeply nested child elements", () => {
                verifyTree(H(
                    [
                        CustomElement, {},
                        [
                            ["header", {className: "header"},
                                [
                                    ["h1", {}, "main-title"],
                                    ["h2", {}, "sub-title"],
                                    ["h3", {}, "sub-sub-title"]
                                ]
                            ],

                            ["div", {className: "content"},
                                [
                                    ["label", {}, "content"]
                                ]
                            ]
                        ]
                    ]),
                    <CustomElement>

main-title

sub-title

sub-sub-title

                            content

                    </CustomElement>);

            })

            it("should render a list of elements and return an array", () => {
                var list = H([
                    ["div", {className : "d1"}, []],
                    ["div", {className : "d2"}, [["span"]]]
                ]);

                assert.lengthOf(list, 2);
                verifyTree(list[0],
);
                verifyTree(list[0],

);
            });
        });

        describe("invalid input", () => {

            it("should throw when root element has > 3 args", () => {
                assert.throws(() => H("div", {}, [], "invalid"));
                assert.throws(() => H(["div", {}, [], "invalid"]));
            });

            it("should throw when a deeply nested element fragment has > 3 args", () => {
                assert.throws(() => H(["div", {},
                    [
                        ["div", {}, [], "invalid", "extra", "args"]
                    ]
                ]));
            });

        });

        describe("nested array components", () => {

            it("should unpack nested root elements", () => {
                verifyTree(H([["div", {className: "demo"}, []]]),

);
            });

            it("should unpack deeply nested root elements", () => {
                verifyTree(H([[[[[[[[["div", {className: "demo"}, []]]]]]]]]]),

);
            });

            it("should unpack deeply nested single child elements", () => {
                verifyTree(H(["div", {className: "demo"}, [

                    ["span", {className: "one"}, "one"],
                    [[[[[["span", {className: "two"}, "two"]]]]]]

                ]]),

                    one
                    two

);
            });

            it("should unpack deeply nested multi child elements", () => {
                verifyTree(H(["div", {className: "demo"}, [

                    ["span", {className: "one"}, "one"],
                    [[[[[["span", {className: "two"}, "two"]]]]]],
                    [[["div"], ["span"]], [[[[["span", {className: "two"}, "two"]]]]]]

                ]]),

                    one

                    two

);
            });
        });

        describe("shorthand notation", () => {

            it("should be possible to omit children & props ", () => {

                verifyTree(H(
                    ["div", {className: "demo"},
                        [
                            [CustomElement], ["ul"]
                        ]
                    ]),

                        <CustomElement />

);
            });

            it("should be possible to omit children", () => {

                verifyTree(H(["div", {className: "demo"},
                        [[CustomElement, {value: "v"}], ["div", {className: "foo"}], "ul"]
                    ]),

                        <CustomElement value="v"/>

);
            });

            it("should also work on root element", () => {
                verifyTree(H("div"),
)
                verifyTree(H("div", ["string literal"]),
string literal
)
                verifyTree(H("div", {className : "foo"}),
)
                verifyTree(H("div", {className : "foo"}, ["string literal"]),
string literal
)
            });

            it("should be possible to omit props but still provide children", () => {

                verifyTree(H([
                        "div",
                        [
                            [CustomElement, {value: "v"}],
                            ["div",
                                [
                                    ["span", "value"]
                                ]
                            ]
                        ]
                    ]),

                        <CustomElement value="v"/>

                            value

);
            });

            it("should be possible to mix shorthand notation with normal notation", () => {

                verifyTree(H([
                        "div", {className: "demo"},
                        [
                            ["div"],
                            ["div", {className: "foo"}, []],
                            ["h1", "title"],
                            ["span"]
                        ]
                    ]),

title

);
            });

        })
    });
});<|endoftext|>


<commit_before>/**
 * Randy is a country singer that sends notifications, drives a Trans Am, and is one serious bad ass.
 *
 * @package randy
 * @author Andrew Sliwinski <andrew@diy.org>
 */

/**
 * Dependencies
 */
var _       = require('underscore'),
    async   = require('async'),
    redis   = require('redis'),
    sio     = require('socket.io'),
    uuid    = require('node-uuid');

var Util    = require('./util'),
    Storage = require('./storage');

/**
 * Generic socket emitter.
 *
 * @param {Object} Socket
 * @param {Object} Notice
 *
 * @return {void}
 */
function emit (socket, notice) {
    socket.emit('notice', notice);
}

// --------------------------------

/**
 * Constructor
 */
function Randy () {
    var self = this;

    // Setup
    self.ns         = 'randy';
    self.pub        = null;
    self.sub        = null;
    self.store      = null;
    self.io         = null;
    self.sockets    = new Object(null);

    /**
     * Gets the socket (if available) for the specified target.
     *
     * @param {String} Target
     *
     * @return {Object}
     */
    function getSocket (target, callback) {
        if (target === null || target === '') {
            callback(null, self.io.sockets);
        } else {
            try {
                callback(null, self.sockets[target].socket);
            } catch (err) {
                Util.stdout(err);
            }
        }
    };

    /**
     * Subscription "message" event handler.
     *
     * @param {String} Channel
     * @param {String} Notice (JSON String)
     *
     * @return {void}
     */
    self.listener   = function (channel, data) {
        async.auto({
            decode:      function (callback) {
                Util.parse(data, callback);
            },

            socket:     ['decode', function (callback, obj) {
                getSocket(obj.decode.target, callback);
            }],

            emit:       ['socket', function (callback, obj) {
                emit(obj.socket, obj.decode);
            }]
        }, Util.stdout);
    };

    /**
     * Socket.io "connection" event handler.
     *
     * @param {Object} Socket
     *
     * @return {void}
     */
    self.connection = function (socket) {

        /**
         * Registers a socket to begin recieving notifications.
         *
         * @param {String} Unique user id
         *
         * @return {void}
         */
        socket.on('register', function (id) {
            // Check if exists
            if (typeof self.sockets[id] === 'undefined') {
                self.sockets[id] = {
                    id:         socket.id,
                    socket:     socket
                };
            } else {
                self.sockets[id].id     = socket.id;
                self.sockets[id].socket = socket;
            }

            // Emit from storage
            self.store.all(id, function (err, obj) {
                if (err) {
                    callback(err);
                } else {
                    async.forEach(obj, function (a, callback) {
                        emit(socket, a);
                        callback();
                    }, Util.stdout);
                }
            });
        });

        /**
         * Dismisses a persistent notification.
         *
         * @param {Object} Identity
         *                      - id {String, Required}
         *                      - uid {String, Required}
         *
         * @return {void}
         */
        socket.on('dismiss', function (data) {
            self.store.del(data.uid, data.id, Util.stdout);
        });

        /**
         * Submits a new event via the loopback interface.
         *
         * @param {Object} Notification object (see "register" method).
         *
         * @return {void}
         */
        socket.on('loopback', function (data) {
            self.submit(data, Util.stdout);
        });
    };
};

/**
 * Start listening for connections on the specified port.
 *
 * @param {Number} Port
 *
 * @return {Error}
 */
Randy.prototype.listen = function (port, arg, callback) {
    var self = this;

    // Detect argument list
    if (_.isUndefined(callback)) {
        callback    = arg;
        arg         = {
            port:       null,
            host:       null,
            pass:       null,
            options:    null
        };
    };

    try {
        // Connect
        self.store  = new Storage(redis.createClient(arg.port, arg.host, arg.options));
        self.pub    = redis.createClient(arg.port, arg.host, arg.options);
        self.sub    = redis.createClient(arg.port, arg.host, arg.options);

        // Authenticate
        if (arg.pass !== null) {
            self.store.auth(arg.pass, stdout);
            self.pub.auth(arg.pass, stdout);
            self.sub.auth(arg.pass, stdout);
        }

        // Pub / Sub
        self.sub.subscribe(self.ns);
        self.sub.on('message', self.listener);

        // Socket.io
        self.io     = sio.listen(Number(port));
        self.io.set('log level', 1);
        self.io.sockets.on('connection', self.connection);
        callback(null);
    } catch (err) {
        Util.stdout(err);
    }
};

/**
 * Submits a new notification.
 *
 * @param {Object} Notification
 *                  - persist {Boolean, Default=false}
 *                  - target {String, Default=null}
 *                  - message {String, Required}
 *
 * @return {Error}
 */
Randy.prototype.submit = function (notice, callback) {
    var self = this;

    _.defaults(notice, {
        id:         uuid.v4(),                  // Assign uuid
        stamp:      new Date().toJSON(),        // Timestamp
        persist:    false,
        target:     null,
        message:    null
    });

    // Normalize typing
    notice.persist  = (notice.persist.toLowerCase() === 'true' || notice.persist === true) ? true : false;
    notice.target   = (notice.target === '') ? null : notice.target;

    // Persist
    if (notice.persist && notice.target !== null) {
        self.store.set(notice.target, notice.id, notice, Util.stdout);
    }

    // If no message is specified, drop the request
    if (notice.message === null || notice.message === '') {
        return callback('No message was specified.');
    }

    // Hash notice and publish to redis store
    async.auto({
        encode:     function (callback) {
            Util.stringify(notice, callback);
        },

        publish:    ['encode', function (callback, obj) {
            self.pub.publish(self.ns, obj.encode);
            callback(null);
        }]
    }, callback);
};

/**
 * Destroy the socket.io connection and redis subscription(s).
 *
 * @return {Error}
 */
Randy.prototype.destroy = function (callback) {
    var self = this;

    try {
        self.sub.unsubscribe();
        self.pub.end();
        self.sub.end();
        callback(null);
    } catch (err) {
        Util.stdout(err);
    }
};

// --------------------------------
// --------------------------------

/**
 * Export
 */
module.exports = new Randy();
<commit_msg>Normalize "null" values from process.env<commit_after>/**
 * Randy is a country singer that sends notifications, drives a Trans Am, and is one serious bad ass.
 *
 * @package randy
 * @author Andrew Sliwinski <andrew@diy.org>
 */

/**
 * Dependencies
 */
var _       = require('underscore'),
    async   = require('async'),
    redis   = require('redis'),
    sio     = require('socket.io'),
    uuid    = require('node-uuid');

var Util    = require('./util'),
    Storage = require('./storage');

/**
 * Generic socket emitter.
 *
 * @param {Object} Socket
 * @param {Object} Notice
 *
 * @return {void}
 */
function emit (socket, notice) {
    socket.emit('notice', notice);
}

// --------------------------------

/**
 * Constructor
 */
function Randy () {
    var self = this;

    // Setup
    self.ns         = 'randy';
    self.pub        = null;
    self.sub        = null;
    self.store      = null;
    self.io         = null;
    self.sockets    = new Object(null);

    /**
     * Gets the socket (if available) for the specified target.
     *
     * @param {String} Target
     *
     * @return {Object}
     */
    function getSocket (target, callback) {
        if (target === null || target === '') {
            callback(null, self.io.sockets);
        } else {
            try {
                callback(null, self.sockets[target].socket);
            } catch (err) {
                Util.stdout(err);
            }
        }
    };

    /**
     * Subscription "message" event handler.
     *
     * @param {String} Channel
     * @param {String} Notice (JSON String)
     *
     * @return {void}
     */
    self.listener   = function (channel, data) {
        async.auto({
            decode:      function (callback) {
                Util.parse(data, callback);
            },

            socket:     ['decode', function (callback, obj) {
                getSocket(obj.decode.target, callback);
            }],

            emit:       ['socket', function (callback, obj) {
                emit(obj.socket, obj.decode);
            }]
        }, Util.stdout);
    };

    /**
     * Socket.io "connection" event handler.
     *
     * @param {Object} Socket
     *
     * @return {void}
     */
    self.connection = function (socket) {

        /**
         * Registers a socket to begin recieving notifications.
         *
         * @param {String} Unique user id
         *
         * @return {void}
         */
        socket.on('register', function (id) {
            // Check if exists
            if (typeof self.sockets[id] === 'undefined') {
                self.sockets[id] = {
                    id:         socket.id,
                    socket:     socket
                };
            } else {
                self.sockets[id].id     = socket.id;
                self.sockets[id].socket = socket;
            }

            // Emit from storage
            self.store.all(id, function (err, obj) {
                if (err) {
                    callback(err);
                } else {
                    async.forEach(obj, function (a, callback) {
                        emit(socket, a);
                        callback();
                    }, Util.stdout);
                }
            });
        });

        /**
         * Dismisses a persistent notification.
         *
         * @param {Object} Identity
         *                      - id {String, Required}
         *                      - uid {String, Required}
         *
         * @return {void}
         */
        socket.on('dismiss', function (data) {
            self.store.del(data.uid, data.id, Util.stdout);
        });

        /**
         * Submits a new event via the loopback interface.
         *
         * @param {Object} Notification object (see "register" method).
         *
         * @return {void}
         */
        socket.on('loopback', function (data) {
            self.submit(data, Util.stdout);
        });
    };
};

/**
 * Start listening for connections on the specified port.
 *
 * @param {Number} Port
 *
 * @return {Error}
 */
Randy.prototype.listen = function (port, arg, callback) {
    var self = this;

    // Detect argument list
    if (_.isUndefined(callback)) {
        callback    = arg;
        arg         = {
            port:       null,
            host:       null,
            pass:       null,
            options:    null
        };
    };

    // Normalize "null" types
    for (var item in arg) {
        arg[item] = (arg[item] === 'null') ? null : arg[item];
    }

    try {
        // Connect
        self.store  = new Storage(redis.createClient(arg.port, arg.host, arg.options));
        self.pub    = redis.createClient(arg.port, arg.host, arg.options);
        self.sub    = redis.createClient(arg.port, arg.host, arg.options);

        // Authenticate
        if (arg.pass !== null) {
            self.store.auth(arg.pass, stdout);
            self.pub.auth(arg.pass, stdout);
            self.sub.auth(arg.pass, stdout);
        }

        // Pub / Sub
        self.sub.subscribe(self.ns);
        self.sub.on('message', self.listener);

        // Socket.io
        self.io     = sio.listen(Number(port));
        self.io.set('log level', 1);
        self.io.sockets.on('connection', self.connection);
        callback(null);
    } catch (err) {
        Util.stdout(err);
    }
};

/**
 * Submits a new notification.
 *
 * @param {Object} Notification
 *                  - persist {Boolean, Default=false}
 *                  - target {String, Default=null}
 *                  - message {String, Required}
 *
 * @return {Error}
 */
Randy.prototype.submit = function (notice, callback) {
    var self = this;

    _.defaults(notice, {
        id:         uuid.v4(),                  // Assign uuid
        stamp:      new Date().toJSON(),        // Timestamp
        persist:    false,
        target:     null,
        message:    null
    });

    // Normalize typing
    notice.persist  = (notice.persist.toLowerCase() === 'true' || notice.persist === true) ? true : false;
    notice.target   = (notice.target === '') ? null : notice.target;

    // Persist
    if (notice.persist && notice.target !== null) {
        self.store.set(notice.target, notice.id, notice, Util.stdout);
    }

    // If no message is specified, drop the request
    if (notice.message === null || notice.message === '') {
        return callback('No message was specified.');
    }

    // Hash notice and publish to redis store
    async.auto({
        encode:     function (callback) {
            Util.stringify(notice, callback);
        },

        publish:    ['encode', function (callback, obj) {
            self.pub.publish(self.ns, obj.encode);
            callback(null);
        }]
    }, callback);
};

/**
 * Destroy the socket.io connection and redis subscription(s).
 *
 * @return {Error}
 */
Randy.prototype.destroy = function (callback) {
    var self = this;

    try {
        self.sub.unsubscribe();
        self.pub.end();
        self.sub.end();
        callback(null);
    } catch (err) {
        Util.stdout(err);
    }
};

// --------------------------------
// --------------------------------

/**
 * Export
 */
module.exports = new Randy();
<|endoftext|>


<commit_before>/*
 * raja browser client
 */
(function() {

window.raja = new Raja();

script('/socket.io/socket.io.js', function(err) {
	if (err) throw err;
	var proto = io.Manager.prototype;
	raja._on = proto.on;
	raja._emit = proto.emit;
	raja.off = proto.off;
	raja.listeners = proto.listeners;
	raja.ready();
});

function Raja() {
	this.delays = [];
	this.base = document.getElementById('raja-io').content;
}

Raja.prototype.delay = function(url, listener) {
	this.delays.push([url, listener]);
	return this;
};

Raja.prototype.ready = function() {
	this.url = this.absolute('.');
	// work around webkit bug https://bugs.webkit.org/show_bug.cgi?id=4363
	var lastMod = Date.parse(document.lastModified);
	var now = new Date();
	var diff = (new Date(now.toLocaleString())).getTimezoneOffset() - now.getTimezoneOffset();
	if (!diff) diff = now.getTimezoneOffset() * 60000;
	else diff = 0;
	this.mtime = lastMod - diff;

	if (isNaN(this.mtime)) this.mtime = Date.now();
	this.resources = {};
	var links = document.head.querySelectorAll('link[rel="resource"]');
	for (var i=0; i < links.length; i++) {
		var link = links.item(i);
		this.resources[link.href] = {url: link.href, mtime: this.mtime};
	}
	var list = this.delays;
	delete this.delays;
	for (var i=0; i < list.length; i++) {
		this.on(list[i][0], list[i][1]);
	}
};

Raja.prototype.link = function(url) {
	var link = $('head > link[rel="resource"][href="'+url+'"]');
	if (link) return;
	link = document.createElement('link');
	link.rel = "resource";
	link.href = url;
	var tn = document.createTextNode("\n");
	document.head.insertBefore(link, document.head.firstChild);
	document.head.insertBefore(tn, link);
};

Raja.prototype.emit = function(what) {
	var args = Array.prototype.slice.call(arguments, 0);
	try {
		this._emit.apply(this, args);
	} catch(e) {
		console.error(e);
	}
	if (what == "error" && this.listeners("error").length == 0) {
		args.shift();
		console.error.apply(console, args);
	}
};

Raja.prototype.on = function(url, listener) {
	if (!this.resources) {
		return this.delay(url, listener);
	}
	if (!this.io) this.setio();
	var self = this;
	if (url == "error") return this._on(url, listener);
	var plistener = function() {
		try {
			listener.apply(null, Array.prototype.slice.call(arguments));
		} catch(e) {
			self.emit('error', e);
		}
	};
	url = this.absolute(url);
	var murl = url.split('?').shift();
	this._on(murl, plistener);
	var resources = this.resources;
	var resource = resources[murl];
	if (!resource) resource = resources[murl] = {url: murl};
	if (resource.error) return;

	(function(next) {
		if (resource.data !== undefined) {
			// resource has been loaded once
			// this is wrong when murl != url
			listener(resource.data, {method:"get", url: url, mtime: resource.mtime});
			return next();
		} else if (resource.mtime !== undefined) {
			// resource merged, just join it
			return next();
		} else if (resource.queue) {
			// resource is currently loading
			resource.queue.push(listener);
			return;
		}
		// resource has not been loaded, is not loading. Proceed
		resource.queue = [listener];
		Raja.xhr(url, function(err, txt, mtime) {
			var obj = tryJSON(txt);
			if (err) {
				resource.error = err;
				return next(err);
			}
			self.link(resource.url);
			resource.mtime = mtime;
			resource.data = obj;
			var queue = resource.queue;
			for (var i=0; i < queue.length; i++) {
				try {
					queue[i](obj, {method:"get", url: url, mtime: mtime});
				} catch(e) {
					console.error(e);
				}
			}
			delete resource.queue;
			next();
		});
	})(function(err) {
		if (err) self.emit('error', err);
	});
	return this;
};

Raja.prototype.setio = function() {
	this.io = io(this.base);
	var self = this;
	this.io.on('reconnect_failed', function(err) {
		if (err) self.emit('error', err);
	});
	this.io.emit('join', {
		room: this.url,
		mtime: this.mtime
	});

	this.io.on('message', function(msg) {
		if (!msg.url) return;
		var data = msg.data;
		if (data) delete msg.data;
		var fresh = msg.mtime > self.mtime;
		if (fresh) {
			self.mtime = msg.mtime;
		}
		var parents = msg.parents;
		parents.unshift(msg.url);
		for (var i=0; i < parents.length; i++) {
			var url = parents[i];
			var resource = self.resources[url];
			if (resource) {
				if (!resource.mtime || msg.mtime > resource.mtime) resource.mtime = msg.mtime;
				self.emit(msg.url, data, msg);
			} else if (fresh && url != self.url) {
				// some dependency that isn't a resource - a static file ? - has changed
			}
		}
	});
};

Raja.prototype.absolute = function(url) {
	if (/^https?/i.test(url)) return url;
	var path = document.location.pathname;
	if (url.indexOf('..') == 0) {
		path = path.split('/');
		path.pop();
		url = path.join('/') + url.substring(2);
	} else if (url.indexOf('.') == 0) {
		url = path + url.substring(1);
	}
	// regular interpretation of url
	if (!this._a) this._a = document.createElement('a');
	this._a.href = url;
	return this._a.href;
};

Raja.xhr = function(url, cb) {
	var req = new XMLHttpRequest();
	req.open('GET', url, true);
	req.onreadystatechange = function (e) {
		if (req.readyState == 4) {
			if (req.status >= 200 && req.status < 300) {
				cb(null, req.responseText, tryDate(req.getResponseHeader("Last-Modified")));
			} else {
				cb(req.status, req.responseText);
			}
		}
	};
	req.send(null);
	return req;
};

function script(url, cb) {
	var script = document.createElement("script");
	script.async = true;
	script.type = 'text/javascript';
	script.charset = 'utf-8';
	script.src = url;
	function done() {
		script.onload = null;
		script.onerror = null;
		if (script.parentNode) {
			script.parentNode.removeChild(script);
		}
		script = null;
	}
	script.onload = function() {
		done();
		cb();
	};
	script.onerror = function(e) {
		done();
		cb(e);
	};
	// Circumvent IE6 bugs with base elements
	document.head.insertBefore(script, document.head.firstChild);
}

function tryJSON(txt) {
	var obj;
	try {
		obj = JSON.parse(txt);
	} catch(e) {
		console.error(e.toString());
		return txt;
	}
	return obj;
}

function tryDate(txt) {
	if (!txt) return;
	var date = new Date(txt);
	var time = date.getTime();
	if (isNaN(time)) return;
	else return time;
}

function $(str) {
	return document.querySelector(str);
}

})();
<commit_msg>Expose utilities and xhr methods<commit_after>/*
 * raja browser client
 */
(function() {

window.raja = new Raja();

insertScript('/socket.io/socket.io.js', function(err) {
	if (err) throw err;
	var proto = io.Manager.prototype;
	raja._on = proto.on;
	raja._emit = proto.emit;
	raja.off = proto.off;
	raja.listeners = proto.listeners;
	raja.ready();
});

function Raja() {
	this.delays = [];
	this.base = document.getElementById('raja-io').content;
}

Raja.prototype.delay = function(url, listener) {
	this.delays.push([url, listener]);
	return this;
};

Raja.prototype.ready = function() {
	this.url = Raja.absolute('.');
	// work around webkit bug https://bugs.webkit.org/show_bug.cgi?id=4363
	var lastMod = Date.parse(document.lastModified);
	var now = new Date();
	var diff = (new Date(now.toLocaleString())).getTimezoneOffset() - now.getTimezoneOffset();
	if (!diff) diff = now.getTimezoneOffset() * 60000;
	else diff = 0;
	this.mtime = lastMod - diff;

	if (isNaN(this.mtime)) this.mtime = Date.now();
	this.resources = {};
	var links = document.head.querySelectorAll('link[rel="resource"]');
	for (var i=0; i < links.length; i++) {
		var link = links.item(i);
		this.resources[link.href] = {url: link.href, mtime: this.mtime};
	}
	var list = this.delays;
	delete this.delays;
	for (var i=0; i < list.length; i++) {
		this.on(list[i][0], list[i][1]);
	}
};

Raja.prototype.link = function(url) {
	var link = $('head > link[rel="resource"][href="'+url+'"]');
	if (link) return;
	link = document.createElement('link');
	link.rel = "resource";
	link.href = url;
	var tn = document.createTextNode("\n");
	document.head.insertBefore(link, document.head.firstChild);
	document.head.insertBefore(tn, link);
};

Raja.prototype.emit = function(what) {
	var args = Array.prototype.slice.call(arguments, 0);
	try {
		this._emit.apply(this, args);
	} catch(e) {
		console.error(e);
	}
	if (what == "error" && this.listeners("error").length == 0) {
		args.shift();
		console.error.apply(console, args);
	}
};

Raja.prototype.on = function(url, listener) {
	if (!this.resources) {
		return this.delay(url, listener);
	}
	if (!this.io) this.setio();
	var self = this;
	if (url == "error") return this._on(url, listener);
	var plistener = function() {
		try {
			listener.apply(null, Array.prototype.slice.call(arguments));
		} catch(e) {
			self.emit('error', e);
		}
	};
	url = Raja.absolute(url);
	var murl = url.split('?').shift();
	this._on(murl, plistener);
	var resources = this.resources;
	var resource = resources[murl];
	if (!resource) resource = resources[murl] = {url: murl};
	if (resource.error) return;

	(function(next) {
		if (resource.data !== undefined) {
			// resource has been loaded once
			// this is wrong when murl != url
			listener(resource.data, {method:"get", url: url, mtime: resource.mtime});
			return next();
		} else if (resource.mtime !== undefined) {
			// resource merged, just join it
			return next();
		} else if (resource.queue) {
			// resource is currently loading
			resource.queue.push(listener);
			return;
		}
		// resource has not been loaded, is not loading. Proceed
		resource.queue = [listener];
		var xhr = Raja.GET(url, function(err, obj) {
			if (err) {
				resource.error = err;
				return next(err);
			}
			var mtime = tryDate(xhr.getResponseHeader("Last-Modified"));
			self.link(resource.url);
			resource.mtime = mtime;
			resource.data = obj;
			var queue = resource.queue;
			for (var i=0; i < queue.length; i++) {
				try {
					queue[i](obj, {method:"get", url: url, mtime: mtime});
				} catch(e) {
					console.error(e);
				}
			}
			delete resource.queue;
			next();
		});
	})(function(err) {
		if (err) self.emit('error', err);
	});
	return this;
};

Raja.prototype.setio = function() {
	this.io = io(this.base);
	var self = this;
	this.io.on('reconnect_failed', function(err) {
		if (err) self.emit('error', err);
	});
	this.io.emit('join', {
		room: this.url,
		mtime: this.mtime
	});

	this.io.on('message', function(msg) {
		if (!msg.url) return;
		var data = msg.data;
		if (data) delete msg.data;
		var fresh = msg.mtime > self.mtime;
		if (fresh) {
			self.mtime = msg.mtime;
		}
		var parents = msg.parents;
		parents.unshift(msg.url);
		for (var i=0; i < parents.length; i++) {
			var url = parents[i];
			var resource = self.resources[url];
			if (resource) {
				if (!resource.mtime || msg.mtime > resource.mtime) resource.mtime = msg.mtime;
				self.emit(msg.url, data, msg);
			} else if (fresh && url != self.url) {
				// some dependency that isn't a resource - a static file ? - has changed
			}
		}
	});
};

Raja.absolute = function(url) {
	if (/^https?/i.test(url)) return url;
	var path = document.location.pathname;
	if (url.indexOf('..') == 0) {
		path = path.split('/');
		path.pop();
		url = path.join('/') + url.substring(2);
	} else if (url.indexOf('.') == 0) {
		url = path + url.substring(1);
	}
	// regular interpretation of url
	if (!Raja.absolute.a) Raja.absolute.a = document.createElement('a');
	Raja.absolute.a.href = url;
	return Raja.absolute.a.href;
};

Raja.setQuery = function(url, obj) {
	if (!obj) return url;
	var comps = [];
	var str;
	for (var k in obj) {
		str = encodeURIComponent(k);
		if (obj[k] != null) str += '=' + encodeURIComponent(obj[k]);
		comps.push(str);
	}
	if (comps.length) {
		if (url.indexOf('?') > 0) url += '&';
		else url += '?';
		url += comps.join('&');
	}
	return url;
};

for (var method in {GET:1, PUT:1, POST:1, DELETE:1}) {
	Raja[method] = (function(method) { return function(url, query, body, cb) {
		if (!cb) {
			if (typeof body == "function") {
				cb = body;
				body = null;
			} else if (typeof query == "function") {
				cb = query;
				query = null;
			} else {
				cb = function() {};
			}
		}
		url = Raja.absolute(url);
		// consume url parameters from query object (even if it is a body)
		if (query) {
			url = url.replace(/\/:(\w+)/g, function(str, name) {
				var val = query[name];
				if (val != null) {
					delete query[name];
					return '/' + val;
				} else {
					return '/:' + name;
				}
			});
		}
		if (/^(HEAD|GET|COPY)$/i.test(method)) {
			query = query || body || {};
		} else {
			// give priority to body
			if (!body && query) {
				body = query;
				query = null;
			}
			if (body) body = JSON.stringify(body);
		}
		url = setQuery(url, query);
		var xhr = new XMLHttpRequest();
		xhr.open(method, url, true);
		xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
		xhr.onreadystatechange = function (e) {
			if (xhr.readyState == 4) {
				var code = xhr.status;
				var response = tryJSON(xhr.responseText);
				if (code >= 200 && code < 400) {
					cb(code, response);
				} else {
					var err = new Error(response);
					err.code = code;
					cb(err);
				}
			}
		};
		xhr.send(body);
		return xhr;
	};})(method);
}

Raja.insertScript = function(url, cb) {
	var script = document.createElement("script");
	script.async = true;
	script.type = 'text/javascript';
	script.charset = 'utf-8';
	script.src = url;
	function done() {
		script.onload = null;
		script.onerror = null;
		if (script.parentNode) {
			script.parentNode.removeChild(script);
		}
		script = null;
	}
	script.onload = function() {
		done();
		cb();
	};
	script.onerror = function(e) {
		done();
		cb(e);
	};
	// Circumvent IE6 bugs with base elements
	document.head.insertBefore(script, document.head.firstChild);
};

function tryJSON(txt) {
	var obj;
	try {
		obj = JSON.parse(txt);
	} catch(e) {
		console.error(e.toString());
		return txt;
	}
	return obj;
}

function tryDate(txt) {
	if (!txt) return;
	var date = new Date(txt);
	var time = date.getTime();
	if (isNaN(time)) return;
	else return time;
}

function $(str) {
	return document.querySelector(str);
}

})();
<|endoftext|>


<commit_before>var test = require('tap').test,
fs = require('fs'),
tail = require('../tail.js').tail;

function _log(msg){
  process.stderr.write(new Buffer(JSON.stringify(msg)+"\n"));
}

var cleanup = [];

test('should be able to tail something',function(t){
  var log = './'+Date.now()+'.log';
  cleanup.push(log);

  var watcher = tail(log,{start:0});

  t.ok(typeof watcher == 'object','watcher should be some kind of object');
  t.ok(watcher.on,'watcher should have an on method');

  var testedChange = 0;
  watcher.on('change',function(){
    if(!testedChange) {
      t.ok(++testedChange,'change event should have been fired');
    }
  });

  var writeDone,
  buf = '',
  prevpos = 0,
  prevdata = '',
  timer = setTimeout(function(){
    t.fail('hard timeout of 20 seconds reached. something is wrong');
    t.end();
    watcher.close();
  },20000)
  len = -1,
  checkBuf = function(){
    if(len == buf.length) {
      watcher.close();
      clearTimeout(timer);
      t.ok(len == buf.length,'buffer should be expected length');
      t.end();
    }
  }
  watcher.on('data',function(buffer,tailInfo){
    buf += buffer.toString();
    prevdata = buffer.toString();

    t.ok(buffer.length,'buffer should have length');
    t.notEqual(prevpos,tailInfo.pos,'for another change should not have the same pos in tailed file as before');
    t.equal(prevpos+buffer.length,tailInfo.pos,'prev pos + buffer read should be new pos');

    prevpos = tailInfo.pos;

    if(writeDone){
      checkBuf()
    }
  });

  writeLog(log,function(err,l){
    len = l;
    writeDone = 1;
    checkBuf();
  });

});

test('should be able to pause/resume tail',function(t){
  var log = './'+Date.now()+'-'+Math.random()+'.log';
  cleanup.push(log);

  var watcher = tail(log),
  buf = '',
  timer = setTimeout(function(){
    t.fail('hard timeout of 20 seconds reached. something is wrong');
    t.end();
    watcher.close();
  },20000),
  c = 0,
  len = -1,
  checkBuf = function(){
    if(len == buf.length) {
      clearTimeout(timer);
      watcher.close();
      t.ok(len == buf.length,'buffer should be expected length');
      t.end();
    }
  }
  ;

  watcher.pause();
  setTimeout(function(){
    t.equals(c,0,'should not have emitted any data events while paused');
    watcher.resume();
  },500);

  watcher.on('data',function(data){
    c++;
    buf += data.toString();
    checkBuf();
  });

  writeLog(log,function(err,l){
    writeDone = 1;
    len = l;
    process.nextTick(function(){
      checkBuf();
    });
  });

});

process.on('exit',function(){
    var fs = require('fs');
    while(cleanup.length) {
      try {
        fs.unlinkSync(cleanup.pop());

      } catch (e){
        console.log('cleanup error');
        console.error(e);
      }
    }
});

function writeLog(log,cb){
  var ws = fs.createWriteStream(log,{flags:'w+'}),
  loop = 10,
  len = 0,
  inter;

  ws.on('open',function(){
    inter = setInterval(function(){
      if(!(--loop)) {
        clearInterval(inter);
        cb(null,len);
        return;
      }

      try{
        //_log('writing');
        var b = new Buffer(Date.now()+"\n");
        len += b.length;
        ws.write(b);
      } catch (e) {
        _log(e+' >> '+e.stack);
      }
    },10);
  });

  return inter;
}
<commit_msg>fixing jshint errors<commit_after>var test = require('tap').test,
fs = require('fs'),
tail = require('../tail.js').tail;

function _log(msg){
  process.stderr.write(new Buffer(JSON.stringify(msg)+"\n"));
}

var cleanup = [];

test('should be able to tail something',function(t){
  var log = './'+Date.now()+'.log';
  cleanup.push(log);

  var watcher = tail(log,{start:0});

  t.ok(typeof watcher == 'object','watcher should be some kind of object');
  t.ok(watcher.on,'watcher should have an on method');

  var testedChange = 0;
  watcher.on('change',function(){
    if(!testedChange) {
      t.ok(++testedChange,'change event should have been fired');
    }
  });

  var writeDone,
  buf = '',
  prevpos = 0,
  prevdata = '',
  timer = setTimeout(function(){
    t.fail('hard timeout of 20 seconds reached. something is wrong');
    t.end();
    watcher.close();
  },20000),
  len = -1,
  checkBuf = function(){
    if(len == buf.length) {
      watcher.close();
      clearTimeout(timer);
      t.ok(len == buf.length,'buffer should be expected length');
      t.end();
    }
  };

  watcher.on('data',function(buffer,tailInfo){
    buf += buffer.toString();
    prevdata = buffer.toString();

    t.ok(buffer.length,'buffer should have length');
    t.notEqual(prevpos,tailInfo.pos,'for another change should not have the same pos in tailed file as before');
    t.equal(prevpos+buffer.length,tailInfo.pos,'prev pos + buffer read should be new pos');

    prevpos = tailInfo.pos;

    if(writeDone){
      checkBuf();
    }
  });

  writeLog(log,function(err,l){
    len = l;
    writeDone = 1;
    checkBuf();
  });

});

test('should be able to pause/resume tail',function(t){
  var log = './'+Date.now()+'-'+Math.random()+'.log';
  cleanup.push(log);

  var watcher = tail(log),
  buf = '',
  timer = setTimeout(function(){
    t.fail('hard timeout of 20 seconds reached. something is wrong');
    t.end();
    watcher.close();
  },20000),
  c = 0,
  len = -1,
  checkBuf = function(){
    if(len == buf.length) {
      clearTimeout(timer);
      watcher.close();
      t.ok(len == buf.length,'buffer should be expected length');
      t.end();
    }
  }
  ;

  watcher.pause();
  setTimeout(function(){
    t.equals(c,0,'should not have emitted any data events while paused');
    watcher.resume();
  },500);

  watcher.on('data',function(data){
    c++;
    buf += data.toString();
    checkBuf();
  });

  writeLog(log,function(err,l){
    writeDone = 1;
    len = l;
    process.nextTick(function(){
      checkBuf();
    });
  });

});

process.on('exit',function(){
    var fs = require('fs');
    while(cleanup.length) {
      try {
        fs.unlinkSync(cleanup.pop());

      } catch (e){
        console.log('cleanup error');
        console.error(e);
      }
    }
});

function writeLog(log,cb){
  var ws = fs.createWriteStream(log,{flags:'w+'}),
  loop = 10,
  len = 0,
  inter;

  ws.on('open',function(){
    inter = setInterval(function(){
      if(!(--loop)) {
        clearInterval(inter);
        cb(null,len);
        return;
      }

      try{
        //_log('writing');
        var b = new Buffer(Date.now()+"\n");
        len += b.length;
        ws.write(b);
      } catch (e) {
        _log(e+' >> '+e.stack);
      }
    },10);
  });

  return inter;
}
<|endoftext|>


<commit_before>import fs from 'fs';
import chalk from 'chalk';
import gulp from 'gulp';
import babel from 'gulp-babel';
import rename from 'gulp-rename';
import clean from 'gulp-rimraf';
import minify from 'gulp-minifier';
import jeditor from "gulp-json-editor";
import runSequence from 'run-sequence';
import config from './src/config';

const dist = './dist';
const dist_server = `${dist}/server`;
const dist_swagger = `${dist_server}/lib/swagger/api-docs`;
const dist_client = `${dist}/client`;
const pm2_simple = `simple.config.js`;
const pm2_cluster = `cluster.config.js`;

gulp.task('build', () => {
  // Sequence
  runSequence('build-clean', 'build-babel', 'build-replace');
});

gulp.task('build-clean', () => {
  // Remove files dist, but ignore assets
  return gulp.src([
    `${dist_server}/*`, `!${dist_server}/assets`
  ], { read: false }).pipe(clean({ force: true }));
});

gulp.task('build-babel', () => {
  // Babel transform, ignore config and swagger api-docs
  return gulp.src(['src/**/*.js', '!src/config/*.js', '!src/lib/swagger/api-docs/*']).pipe(babel()).pipe(gulp.dest(dist_server));
});

gulp.task('build-replace', () => {
  // Copy file config dev or production
  const conf = process.argv[3] ? 'index' : 'production';
  // Copy config production
  gulp.src([`src/config/${conf}.js`]).pipe(babel()).pipe(rename('index.js')).pipe(gulp.dest(`${dist_server}/config`));
  // Copy views
  gulp.src(['src/views/**/*.*', '!src/views/**/*.js']).pipe(minify({ minify: true, collapseWhitespace: true, conservativeCollapse: true, minifyCSS: true })).pipe(gulp.dest(`${dist_server}/views`));
  // Copy assets
  gulp.src(['src/assets/**/*']).pipe(gulp.dest(`${dist_server}/assets`));
  // Copy *.yaml
  gulp.src(['src/**/*.yaml']).pipe(gulp.dest(dist_server));
  // Copy swagger/api-docs
  gulp.src([`src/lib/swagger/api-docs/*`]).pipe(gulp.dest(dist_swagger));
  // package.json
  gulp.src("package.json").pipe(jeditor((json) => {
    delete json.devDependencies;
    json.scripts = {
      "start": `npm run redis && node server/app.js`,
      "simple": `npm run redis && npm stop && pm2 startOrRestart ${pm2_simple}`,
      "cluster": `npm run redis && npm stop && pm2 startOrRestart ${pm2_cluster}`,
      "redis": `redis-cli config set notify-keyspace-events KEA`,
      "stop": `pm2 delete ${pm2_simple} ${pm2_cluster}`
    };
    return json;
  })).pipe(gulp.dest(dist));
  // Copy pm2 files
  gulp.src([pm2_simple, pm2_cluster]).pipe(gulp.dest(dist));
  // If not exits client folder, then copy current client
  if (fs.existsSync(`${dist}/client`)) {
    gulp.src(['client/**/*']).pipe(gulp.dest(dist_client));
  }
  // Success
  setTimeout(() => console.log(chalk.greenBright('\n---------\nBuild success!\n---------\n')), 500);
});
<commit_msg>updated build<commit_after>import fs from 'fs';
import chalk from 'chalk';
import gulp from 'gulp';
import babel from 'gulp-babel';
import rename from 'gulp-rename';
import clean from 'gulp-rimraf';
import minify from 'gulp-minifier';
import jeditor from "gulp-json-editor";
import runSequence from 'run-sequence';
import config from './src/config';

const dist = './dist';
const dist_server = `${dist}/server`;
const dist_swagger = `${dist_server}/lib/swagger/api-docs`;
const dist_client = `${dist}/client`;
const pm2_simple = `simple.config.js`;
const pm2_cluster = `cluster.config.js`;

gulp.task('build', () => {
  // Sequence
  runSequence('build-clean', 'build-babel', 'build-replace');
});

gulp.task('build-clean', () => {
  // Remove files dist, but ignore assets
  return gulp.src([
    `${dist_server}/*`, `!${dist_server}/assets`, `${dist_client}`
  ], { read: false }).pipe(clean({ force: true }));
});

gulp.task('build-babel', () => {
  // Babel transform, ignore config and swagger api-docs
  return gulp.src(['src/**/*.js', '!src/config/*.js', '!src/lib/swagger/api-docs/*']).pipe(babel()).pipe(gulp.dest(dist_server));
});

gulp.task('build-replace', () => {
  // Copy file config dev or production
  const conf = process.argv[3] ? 'index' : 'production';
  // Copy config production
  gulp.src([`src/config/${conf}.js`]).pipe(babel()).pipe(rename('index.js')).pipe(gulp.dest(`${dist_server}/config`));
  // Copy views
  gulp.src(['src/views/**/*.*', '!src/views/**/*.js']).pipe(minify({ minify: true, collapseWhitespace: true, conservativeCollapse: true, minifyCSS: true })).pipe(gulp.dest(`${dist_server}/views`));
  // Copy assets
  gulp.src(['src/assets/**/*']).pipe(gulp.dest(`${dist_server}/assets`));
  // Copy *.yaml
  gulp.src(['src/**/*.yaml']).pipe(gulp.dest(dist_server));
  // Copy swagger/api-docs
  gulp.src([`src/lib/swagger/api-docs/*`]).pipe(gulp.dest(dist_swagger));
  // package.json
  gulp.src("package.json").pipe(jeditor((json) => {
    delete json.devDependencies;
    json.scripts = {
      "start": `npm run redis && node server/app.js`,
      "simple": `npm run redis && npm stop && pm2 startOrRestart ${pm2_simple}`,
      "cluster": `npm run redis && npm stop && pm2 startOrRestart ${pm2_cluster}`,
      "redis": `redis-cli config set notify-keyspace-events KEA`,
      "stop": `pm2 delete ${pm2_simple} ${pm2_cluster}`
    };
    return json;
  })).pipe(gulp.dest(dist));
  // Copy pm2 files
  gulp.src([pm2_simple, pm2_cluster]).pipe(gulp.dest(dist));
  // If exits client folder, then copy current client
  if (fs.existsSync(`${dist}/client`)) {
    gulp.src(['client/**/*']).pipe(gulp.dest(dist_client));
  } else {
    // If not exits client folder, then copy default client
    gulp.src(['src/views/default/favicon.ico', 'src/views/default/logo.svg']).pipe(gulp.dest(dist_client));
    gulp.src(['src/views/default/client.html']).pipe(minify({ minify: true, collapseWhitespace: true, conservativeCollapse: true})).pipe(rename('index.html')).pipe(gulp.dest(dist_client));
  }
  // Success
  setTimeout(() => console.log(chalk.greenBright('\n---------\nBuild success!\n---------\n')), 500);
});
<|endoftext|>


<commit_before>/** Title: Barefoot
 * Barefoot makes code sharing between browser and server reality. Write your
 * application once and run it on both ends of the wire.
 *
 * It builds upon the popular Backbone.JS library and keeps its own additions as
 * unobtrusive as possible.
 *
 * Server side execution is accomplished by using Node.JS and Express.JS. Once
 * delivered to the users browser, no additional JavaScript libraries are
 * needed when configured properly.
 *
 * If you implement your views with care, your client side follows the
 * "Unobtrusive JavaScript" principle
 * (http://roca-style.org/#unobtrusive-javascript) completely.
 *
 * Author:
 * * Manuel Alabor, <manuel@alabor.me>
 *
 * Source on Github:
 * * https://github.com/swissmanu/barefoot
 *
 *
 * License:
 * Copyright (c) 2013 Manuel Alabor
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
function boot(options) {
	var util = require('./util')
		, _ = require('underscore')
		, environment = _.result(options,'environment') || util.getEnvironment()
		, mixins = util.loadMixins(environment)
		, Router = require('./router')(mixins.RouterMixin)
		, View = require('./view')(mixins.ViewMixin)
		, Model = require('./model')(mixins.ModelMixin)
		, Collection = require('./collection')(mixins.CollectionMixin)
		, APIAdapter = require('./apiadapter')(mixins.APIAdapterMixin)
		, DataStore = require('./datastore')(mixins.DataStoreMixin, Model)
		, Errors = require('./errors');

	/* start
	 * Starts your application using the given router.
	 *
	 * Parameters:
	 *     (<Barefoot.Router>) Router - A <Barefoot.Router> class. Make sure you
	 *                                  do *not* pass an instance! (no
	 *                                  "new Router()" etc.)
	 *     (Object) startOptions - These object literal is passed to the final
	 *                             Router.
	 */
	function start(Router, startOptions) {
		mixins.startup(Router, APIAdapter, startOptions);
	}

	return {
		Router: Router
		, View: View
		, APIAdapter: APIAdapter
		, DataStore: DataStore
		, Model: Model
		, Collection: Collection
		, errors: Errors
		, start: start
	};
}

module.exports = (function() {
	return boot.apply(this, arguments);
});<commit_msg>added isRunningOnServer helper function<commit_after>/** Title: Barefoot
 * Barefoot makes code sharing between browser and server reality. Write your
 * application once and run it on both ends of the wire.
 *
 * It builds upon the popular Backbone.JS library and keeps its own additions as
 * unobtrusive as possible.
 *
 * Server side execution is accomplished by using Node.JS and Express.JS. Once
 * delivered to the users browser, no additional JavaScript libraries are
 * needed when configured properly.
 *
 * If you implement your views with care, your client side follows the
 * "Unobtrusive JavaScript" principle
 * (http://roca-style.org/#unobtrusive-javascript) completely.
 *
 * Author:
 * * Manuel Alabor, <manuel@alabor.me>
 *
 * Source on Github:
 * * https://github.com/swissmanu/barefoot
 *
 *
 * License:
 * Copyright (c) 2013 Manuel Alabor
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
function boot(options) {
	var util = require('./util')
		, _ = require('underscore')
		, environment = _.result(options,'environment') || util.getEnvironment()
		, mixins = util.loadMixins(environment)
		, Router = require('./router')(mixins.RouterMixin)
		, View = require('./view')(mixins.ViewMixin)
		, Model = require('./model')(mixins.ModelMixin)
		, Collection = require('./collection')(mixins.CollectionMixin)
		, APIAdapter = require('./apiadapter')(mixins.APIAdapterMixin)
		, DataStore = require('./datastore')(mixins.DataStoreMixin, Model)
		, Errors = require('./errors');

	/* start
	 * Starts your application using the given router.
	 *
	 * Parameters:
	 *     (<Barefoot.Router>) Router - A <Barefoot.Router> class. Make sure you
	 *                                  do *not* pass an instance! (no
	 *                                  "new Router()" etc.)
	 *     (Object) startOptions - These object literal is passed to the final
	 *                             Router.
	 */
	function start(Router, startOptions) {
		mixins.startup(Router, APIAdapter, startOptions);
	}

	/* isRunningOnServer
	 * Returns true if barefoot is running on the server currently.
	 *
	 * Returns:
	 *     (Bool)
	 */
	function isRunningOnServer() {
		return (!process.browser);
	}

	return {
		Router: Router
		, View: View
		, APIAdapter: APIAdapter
		, DataStore: DataStore
		, Model: Model
		, Collection: Collection
		, errors: Errors
		, start: start
		, isRunningOnServer: isRunningOnServer
	};
}

module.exports = (function() {
	return boot.apply(this, arguments);
});<|endoftext|>


<commit_before>import gulp from 'gulp';
import babel from 'gulp-babel';
import browserify from 'browserify';
import babelify from 'babelify';
import fs from 'fs';

gulp.task('build:es', () => {
  gulp.src('src/**/*.js')
    .pipe(babel({
      babelrc: false,
      presets: [
        ['env', { modules: false }],
      ],
    }))
    .pipe(gulp.dest('lib/es'));
});

gulp.task('build:umd', () => {
  const babelifyOptions = {
    presets: [
      ['env'],
    ],
    plugins: [
      ['transform-runtime',
        {
          helpers: false,
          polyfill: false,
          regenerator: true,
          moduleName: 'babel-runtime',
        }],
    ],
  };

  browserify({ standalone: 'whyat' })
    .transform(babelify, babelifyOptions)
    .require(require.resolve('./src/tracker.js'), { entry: true })
    .bundle()
    .pipe(fs.createWriteStream('dist/whyat.js'));
});
<commit_msg>fix #12 : adapt gulp task to gulp 4.0.0 version<commit_after>import gulp from 'gulp';
import babel from 'gulp-babel';
import browserify from 'browserify';
import babelify from 'babelify';
import fs from 'fs';

gulp.task('build:es', (done) => {
  gulp.src('src/**/*.js')
    .pipe(babel({
      babelrc: false,
      presets: [
        ['env', { modules: false }],
      ],
    }))
    .pipe(gulp.dest('lib/es'));
  done();
});

gulp.task('build:umd', (done) => {
  const babelifyOptions = {
    presets: [
      ['env'],
    ],
    plugins: [
      ['transform-runtime',
        {
          helpers: false,
          polyfill: false,
          regenerator: true,
          moduleName: 'babel-runtime',
        }],
    ],
  };

  browserify({ standalone: 'whyat' })
    .transform(babelify, babelifyOptions)
    .require(require.resolve('./src/tracker.js'), { entry: true })
    .bundle()
    .pipe(fs.createWriteStream('dist/whyat.js'));
  done();
});
<|endoftext|>


<commit_before>'use babel';

import { CompositeDisposable, Disposable } from 'atom';
import { View as RemplClientView, createElement as createRemplView } from './rempl-view';
import { View as ServerDialogView, createElement as createServerDialog } from './server-dialog-view';
import { View as StatusBarView, createElement as createStatusBar } from './status-bar';
import { createEnv } from 'rempl';

const clients = new Set();
let DEFAULT_SERVER_URL = '';

atom.views.addViewProvider(RemplClientView, createRemplView);
atom.views.addViewProvider(ServerDialogView, createServerDialog);
atom.views.addViewProvider(StatusBarView, createStatusBar);

class RemplClient {
    activate() {
        let onChooseServer = () => {
            let serverUrl = this.serverInput.item.editor.getText();

            this.addClient(serverUrl);
            this.serverInput.item.editor.setText(DEFAULT_SERVER_URL);
            this.serverInput.hide();
        };
        let onCancelChoose = () => {
            if (this.serverInput.isVisible()) {
                this.serverInput.item.editor.setText(DEFAULT_SERVER_URL);
                this.serverInput.hide();
            }
        };

        this.disposable = new CompositeDisposable();
        this.disposable.add(atom.commands.add('atom-workspace', {
            'rempl:connect': () => {
                this.serverInput.show();
                this.serverInput.item.editor.element.focus();
            }
        }));

        this.initEnv();

        this.disposable.add(atom.config.observe('rempl-host.defaultHost', value => DEFAULT_SERVER_URL = value));
        this.serverInput = atom.workspace.addModalPanel({ item: new ServerDialogView(), visible: false });
        this.serverInput.item.editor.setText(DEFAULT_SERVER_URL);
        this.disposable.add(atom.commands.add(this.serverInput.item.editor.element, {
            'core:confirm': onChooseServer
        }));
        this.disposable.add(atom.commands.add(atom.views.getView(atom.workspace), {
            'core:cancel': onCancelChoose
        }));
        this.disposable.add(new Disposable(() => {
            this.serverInput.destroy();
        }));
        this.disposable.add(atom.workspace.onDidAddPaneItem(data => {
            if (data.item && data.item instanceof RemplClientView) {
                this.attachCallbacks(data.item);
            }
        }));
        this.disposable.add(atom.workspace.onDidDestroyPaneItem(data => {
            if (data.item && data.item instanceof RemplClientView) {
                this.removeClient(data.item);
            }
        }));
        this.activeEditor = {
            instance: null,
            disposable: new CompositeDisposable()
        };
        this.disposable.add(this.activeEditor.disposable);
        this.disposable.add(atom.workspace.onDidChangeActivePaneItem(item => {
            let editor = atom.workspace.getActiveTextEditor()

            this.updateActiveTab(item);

            if (this.activeEditor.instance === editor) {
                return;
            }

            if (this.activeEditor.instance) {
                this.activeEditor.disposable.dispose();
                this.activeEditor.disposable = new CompositeDisposable();
            }

            this.activeEditor.instance = editor;

            if (editor) {
                this.activeEditor.disposable.add(
                    editor.onDidChangeSelectionRange(() => this.updateActiveTab()),
                    editor.onDidAddSelection(() => this.updateActiveTab()),
                    editor.onDidRemoveSelection(() => this.updateActiveTab()),
                    editor.onDidChangePath(() => this.updateActiveTab()),
                    editor.onDidChangeGrammar(() => this.updateActiveTab())
                );
            }
        }));
    }

    initEnv() {
        if (this.env) {
            return;
        }

        this.env = createEnv('editor');
        this.env.publish({
            name: 'Atom',
            version: atom.getVersion()
        });
        this.updateActiveTab();
        this.env.provide({
            setStatusBarContent: (content) => {
                this.statusBarTile.getItem().setContent(content || '');
            },
            publisherChanged: () => {
                // subscriber.setPublisher(publisher);
                // subscriber.updateTitle();
                // delete subscriber.allowToGetContent;
            },
            openFile: (filePath, selections, callback) => {
                selections = this.normalizeSelections(selections);

                if (!filePath) {
                    return callback({ code: 'NO_FILE_SPECIFIED' });
                }

                // this is insane (function + bind), but without it we're getting error: 'Undefined label _loop'
                // seems like some bug in babel
                atom.workspace.open(filePath).then(function (selections) {
                    if (selections) {
                        let editor = atom.workspace.getActiveTextEditor();

                        if (editor) {
                            editor.setSelectedBufferRanges(selections);
                        }
                    }

                    callback();
                }.bind(null, selections), () => callback({ code: 'OPEN_FILE_ERROR' }));
            },
            getContent: (callback) => {
                let allow = this.allowToGetContent;
                let editor = atom.workspace.getActiveTextEditor();

                if (!editor || allow === false) {
                    return callback({ code: 'NOT_ALLOWED' });
                }

                if (!allow) {
                    atom.confirm({
                        message: `Rempl subscriber - ???`,
                        detailedMessage: 'Trying to get content of the current file',
                        buttons: {
                            Allow: () => allow = true,
                            Disallow: () => allow = false,
                            'Allow and remember': () => this.allowToGetContent = allow = true,
                            'Disallow and remember': () => this.allowToGetContent = allow = false
                        }
                    });
                }

                if (allow) {
                    callback(null, editor.getText());
                } else {
                    callback({ code: 'NOT_ALLOWED' });
                }
            }
        });
    }

    updateActiveTab() {
        let activePane = atom.workspace.getActivePaneItem();
        let textEditor = atom.workspace.getActiveTextEditor();
        let info = {
            title: activePane ? activePane.getTitle() : null,
            isEditor: Boolean(textEditor),
            selections: null,
            file: null
        }

        if (textEditor) {
            info.selections = this.getEditorSelections(textEditor);
            info.file = {
                path: textEditor.getPath() || null,
                name: textEditor.getFileName(),
                syntax: textEditor.getGrammar().name
            };
        }

        this.env.ns('activeTab').publish(info);
    }

    getEditorSelections(editor) {
        if (!editor) {
            return [];
        }

        return editor.getSelectedBufferRanges()
            .map(range => {
                return {
                    start: {
                        line: range.start.row + 1,
                        column: range.start.column + 1
                    },
                    end: {
                        line: range.end.row + 1,
                        column: range.end.column + 1
                    }
                }
            });
    }

    attachCallbacks(item) {
        let view = atom.views.getView(item);

        view.addEventListener('attached', () => {
            this.env.linkWindow(view.iframe.contentWindow);
        });
        view.addEventListener('detached', () => {
            this.removeClient(item);
        });
    }

    addClient(url) {
        let client = new RemplClientView(url);

        clients.add(client);
        atom.workspace.getActivePane().addItem(client);
        atom.workspace.getActivePane().activateNextItem();

        return client;
    }

    removeClient(client) {
        clients.delete(client);
    }

    normalizeSelections(selections) {
        // normalize selections
        if (!selections) {
            selections = [];
        } else if (!Array.isArray(selections)) {
            selections = [selections];
        }

        selections = selections
            .filter(range => range && range.start && range.start.line)
            .map(range => {
                let { start, end } = range;

                if (!end || !end.line) {
                    end = Object.assign(start);
                }

                start.column = start.column || 1;
                end.column = end.column || 1;

                range.start = {
                    row: +start.line - 1,
                    column: +start.column - 1
                };
                range.end = {
                    row: +end.line - 1,
                    column: +end.column - 1
                };

                return range;
            });

        if (!selections.length) {
            selections.push({
                start: { row: 1, column: 1},
                end: { row: 1, column: 1 }
            });
        }

        return selections;
    }

    consumeStatusBar(statusBar) {
        this.statusBarTile = statusBar.addLeftTile({ item: new StatusBarView(), priority: 100 });
    }

    deactivate() {
        clients.forEach((api, client) => client.destroy());
        clients.clear();
        this.activeEditor.instance = null;

        if (this.statusBarTile) {
            this.statusBarTile.destroy();
        }

        this.disposable.dispose();
    }

    deserializeClient(state) {
        this.initEnv();

        if (state.url) {
            let client = new RemplClientView(state.url, state.publisher);

            clients.add(client);
            this.attachCallbacks(client);

            return client;
        }
    }
}

module.exports = new RemplClient();
module.exports.config = {
    defaultHost: {
        type: 'string',
        default: 'http://localhost:8177/',
        title: 'Rempl-server url by default'
    }
}
<commit_msg>fix active editor attachment on plugin activation<commit_after>'use babel';

import { CompositeDisposable, Disposable } from 'atom';
import { View as RemplClientView, createElement as createRemplView } from './rempl-view';
import { View as ServerDialogView, createElement as createServerDialog } from './server-dialog-view';
import { View as StatusBarView, createElement as createStatusBar } from './status-bar';
import { createEnv } from 'rempl';

const clients = new Set();
let DEFAULT_SERVER_URL = '';

atom.views.addViewProvider(RemplClientView, createRemplView);
atom.views.addViewProvider(ServerDialogView, createServerDialog);
atom.views.addViewProvider(StatusBarView, createStatusBar);

class RemplClient {
    activate() {
        let onChooseServer = () => {
            let serverUrl = this.serverInput.item.editor.getText();

            this.addClient(serverUrl);
            this.serverInput.item.editor.setText(DEFAULT_SERVER_URL);
            this.serverInput.hide();
        };
        let onCancelChoose = () => {
            if (this.serverInput.isVisible()) {
                this.serverInput.item.editor.setText(DEFAULT_SERVER_URL);
                this.serverInput.hide();
            }
        };

        this.disposable = new CompositeDisposable();
        this.disposable.add(atom.commands.add('atom-workspace', {
            'rempl:connect': () => {
                this.serverInput.show();
                this.serverInput.item.editor.element.focus();
            }
        }));

        this.initEnv();
        this.activeEditor = {
            instance: null,
            disposable: new CompositeDisposable()
        };

        this.disposable.add(atom.config.observe('rempl-host.defaultHost', value => DEFAULT_SERVER_URL = value));
        this.serverInput = atom.workspace.addModalPanel({ item: new ServerDialogView(), visible: false });
        this.serverInput.item.editor.setText(DEFAULT_SERVER_URL);
        this.disposable.add(atom.commands.add(this.serverInput.item.editor.element, {
            'core:confirm': onChooseServer
        }));
        this.disposable.add(atom.commands.add(atom.views.getView(atom.workspace), {
            'core:cancel': onCancelChoose
        }));
        this.disposable.add(new Disposable(() => {
            this.serverInput.destroy();
        }));
        this.disposable.add(atom.workspace.onDidChangeActivePaneItem(item => {
            this.setActiveTextEditor(item);
        }));
        this.disposable.add(atom.workspace.onDidAddPaneItem(data => {
            if (data.item && data.item instanceof RemplClientView) {
                this.attachCallbacks(data.item);
            }
        }));
        this.disposable.add(atom.workspace.onDidDestroyPaneItem(data => {
            if (data.item && data.item instanceof RemplClientView) {
                this.removeClient(data.item);
            }
        }));

        this.setActiveTextEditor();
    }

    initEnv() {
        if (this.env) {
            return;
        }

        this.env = createEnv('editor');
        this.env.publish({
            name: 'Atom',
            version: atom.getVersion()
        });
        this.updateActiveTab();
        this.env.provide({
            setStatusBarContent: (content) => {
                this.statusBarTile.getItem().setContent(content || '');
            },
            publisherChanged: () => {
                // subscriber.setPublisher(publisher);
                // subscriber.updateTitle();
                // delete subscriber.allowToGetContent;
            },
            openFile: (filePath, selections, callback) => {
                selections = this.normalizeSelections(selections);

                if (!filePath) {
                    return callback({ code: 'NO_FILE_SPECIFIED' });
                }

                // this is insane (function + bind), but without it we're getting error: 'Undefined label _loop'
                // seems like some bug in babel
                atom.workspace.open(filePath).then(function (selections) {
                    if (selections) {
                        let editor = atom.workspace.getActiveTextEditor();

                        if (editor) {
                            editor.setSelectedBufferRanges(selections);
                        }
                    }

                    callback();
                }.bind(null, selections), () => callback({ code: 'OPEN_FILE_ERROR' }));
            },
            getContent: (callback) => {
                let allow = this.allowToGetContent;
                let editor = atom.workspace.getActiveTextEditor();

                if (!editor || allow === false) {
                    return callback({ code: 'NOT_ALLOWED' });
                }

                if (!allow) {
                    atom.confirm({
                        message: `Rempl subscriber - ???`,
                        detailedMessage: 'Trying to get content of the current file',
                        buttons: {
                            Allow: () => allow = true,
                            Disallow: () => allow = false,
                            'Allow and remember': () => this.allowToGetContent = allow = true,
                            'Disallow and remember': () => this.allowToGetContent = allow = false
                        }
                    });
                }

                if (allow) {
                    callback(null, editor.getText());
                } else {
                    callback({ code: 'NOT_ALLOWED' });
                }
            }
        });
    }

    setActiveTextEditor() {
        let editor = atom.workspace.getActiveTextEditor()

        this.updateActiveTab();

        if (this.activeEditor.instance === editor) {
            return;
        }

        if (this.activeEditor.instance) {
            this.activeEditor.disposable.dispose();
            this.activeEditor.disposable = new CompositeDisposable();
        }

        this.activeEditor.instance = editor;

        if (editor) {
            this.activeEditor.disposable.add(
                editor.onDidChangeSelectionRange(() => this.updateActiveTab()),
                editor.onDidAddSelection(() => this.updateActiveTab()),
                editor.onDidRemoveSelection(() => this.updateActiveTab()),
                editor.onDidChangePath(() => this.updateActiveTab()),
                editor.onDidChangeGrammar(() => this.updateActiveTab())
            );
        }
    }

    updateActiveTab() {
        let activePane = atom.workspace.getActivePaneItem();
        let textEditor = atom.workspace.getActiveTextEditor();
        let info = {
            title: activePane ? activePane.getTitle() : null,
            isEditor: Boolean(textEditor),
            selections: null,
            file: null
        }

        if (textEditor) {
            info.selections = this.getEditorSelections(textEditor);
            info.file = {
                path: textEditor.getPath() || null,
                name: textEditor.getFileName(),
                syntax: textEditor.getGrammar().name
            };
        }

        this.env.ns('activeTab').publish(info);
    }

    getEditorSelections(editor) {
        if (!editor) {
            return [];
        }

        return editor.getSelectedBufferRanges()
            .map(range => {
                return {
                    start: {
                        line: range.start.row + 1,
                        column: range.start.column + 1
                    },
                    end: {
                        line: range.end.row + 1,
                        column: range.end.column + 1
                    }
                }
            });
    }

    attachCallbacks(item) {
        let view = atom.views.getView(item);

        view.addEventListener('attached', () => {
            this.env.linkWindow(view.iframe.contentWindow);
        });
        view.addEventListener('detached', () => {
            this.removeClient(item);
        });
    }

    addClient(url) {
        let client = new RemplClientView(url);

        clients.add(client);
        atom.workspace.getActivePane().addItem(client);
        atom.workspace.getActivePane().activateNextItem();

        return client;
    }

    removeClient(client) {
        clients.delete(client);
    }

    normalizeSelections(selections) {
        // normalize selections
        if (!selections) {
            selections = [];
        } else if (!Array.isArray(selections)) {
            selections = [selections];
        }

        selections = selections
            .filter(range => range && range.start && range.start.line)
            .map(range => {
                let { start, end } = range;

                if (!end || !end.line) {
                    end = Object.assign(start);
                }

                start.column = start.column || 1;
                end.column = end.column || 1;

                range.start = {
                    row: +start.line - 1,
                    column: +start.column - 1
                };
                range.end = {
                    row: +end.line - 1,
                    column: +end.column - 1
                };

                return range;
            });

        if (!selections.length) {
            selections.push({
                start: { row: 1, column: 1 },
                end: { row: 1, column: 1 }
            });
        }

        return selections;
    }

    consumeStatusBar(statusBar) {
        this.statusBarTile = statusBar.addLeftTile({ item: new StatusBarView(), priority: 100 });
    }

    deactivate() {
        clients.forEach((api, client) => client.destroy());
        clients.clear();

        this.activeEditor.disposable.dispose();
        this.activeEditor = null;

        if (this.statusBarTile) {
            this.statusBarTile.destroy();
        }

        this.disposable.dispose();
    }

    deserializeClient(state) {
        this.initEnv();

        if (state.url) {
            let client = new RemplClientView(state.url, state.publisher);

            clients.add(client);
            this.attachCallbacks(client);

            return client;
        }
    }
}

module.exports = new RemplClient();
module.exports.config = {
    defaultHost: {
        type: 'string',
        default: 'http://localhost:8177/',
        title: 'Rempl-server url by default'
    }
}
<|endoftext|>


<commit_before>'use strict';
import gulp from 'gulp';
import del from 'del';

const builder = require('electron-builder');
const electron = require('electron-connect').server.create();
// const Platform = builder.Platform;
gulp.task('default', () => {

});
gulp.task('build:pack', () => {
	builder.build({
		targets: builder.Platform.win32,
		config: {
			win: {
				target: [
					'dir'
				]
			},
			iconUrl: 'https://github.com/willyb321/elite-journal/blob/master/build/icon.ico?raw=true',
			remoteReleases: true
		}
	})
		.then(() => {
			console.log('Built the app in dist/');
		})
		.catch(err => {
			console.error(err);
		});
});
gulp.task('build:dist', () => {
	builder.build({
		targets: builder.Platform.win32,
		config: {
			win: {
				target: [
					'nsis'
				]
			},
			nsis: {
				oneClick: true
			},
			iconUrl: 'https://github.com/willyb321/elite-journal/blob/master/build/icon.ico?raw=true',
			remoteReleases: true
		}
	})
		.then(() => {
			console.log('Built an NSIS installer in dist/');
		})
		.catch(err => {
			console.error(err);
		});
});
gulp.task('clean', () => {
	return del(['dist']);
});
<commit_msg>whoops<commit_after>'use strict';
import gulp from 'gulp';
import del from 'del';

const builder = require('electron-builder');
// const Platform = builder.Platform;
gulp.task('default', () => {

});
gulp.task('build:pack', () => {
	builder.build({
		targets: builder.Platform.win32,
		config: {
			win: {
				target: [
					'dir'
				]
			},
			iconUrl: 'https://github.com/willyb321/elite-journal/blob/master/build/icon.ico?raw=true',
			remoteReleases: true
		}
	})
		.then(() => {
			console.log('Built the app in dist/');
		})
		.catch(err => {
			console.error(err);
		});
});
gulp.task('build:dist', () => {
	builder.build({
		targets: builder.Platform.win32,
		config: {
			win: {
				target: [
					'nsis'
				]
			},
			nsis: {
				oneClick: true
			},
			iconUrl: 'https://github.com/willyb321/elite-journal/blob/master/build/icon.ico?raw=true',
			remoteReleases: true
		}
	})
		.then(() => {
			console.log('Built an NSIS installer in dist/');
		})
		.catch(err => {
			console.error(err);
		});
});
gulp.task('clean', () => {
	return del(['dist']);
});
<|endoftext|>


<commit_before>var sacloud = require('sacloud');
var fs = require('fs');
var csv = require('comma-separated-values');
var Server = require('../lib/Server');

var defaultTag = 'dojopaas'

var config = {
  defaultTag: 'dojopaas',
  zone: "29001", // サンドボックス
  api: "https://secure.sakura.ad.jp/cloud/zone/tk1v/api/cloud/1.1/",
  plan: 1001,
  packetfilterid: '112900927419',
  disk: {
    Plan: { ID: 4 },
    SizeMB: 20480,
    SourceArchive: { ID: "112900758037" }
  }
}

sacloud.API_ROOT = config.api;
var client = sacloud.createClient({
  accessToken        : process.env.SACLOUD_ACCESS_TOKEN,
  accessTokenSecret  : process.env.SACLOUD_ACCESS_TOKEN_SECRET,
  disableLocalizeKeys: false, // (optional;default:false) false: lower-camelize the property names in response Object
  debug              : false // (optional;default:false) output debug requests to console.
});

Promise.resolve()
.then(() => {
  return new Promise((resolve, reject) => {
    client.createRequest({
      method: 'GET',
      path  : 'server',
      body  : {
        Filter: {
          "Tags": config.defaultTag
        }
      }
    }).send((err, result) => {
      if (err) reject(err);
      resolve(result);
    });
  });
}).then((data) => {
  for (var i=0; i<data.response.servers.length; i++) {
    var server = new Server(client);
    server.destroy(data.response.servers[i].id)
  }
  return new Promise((resolve, reject) => {
    var server = new Server(client);
    server.create({
      zone: config.zone,
      plan: config.plan,
      packetfilterid: config.packetfilterid,
      name: "test",
      description: "This is a instance for test",
      tags: [config.defaultTag],
      pubkey: "xxxx",
      disk: config.disk,
      resolve: resolve
    })
  })
}).then((data) => {
  client.createRequest({
    method: 'GET',
    path  : 'server/'+data,
  }).send((err, result) => {
    if (err) throw new Error(err);
    if ('up' === result.response.server.instance.status) {
      console.log('OK')
    } else {
      throw new Error('Can not start Instance!');
    }
  });
}).catch((err) => {
  throw new Error(err);
})
<commit_msg>add debug to the test<commit_after>var sacloud = require('sacloud');
var fs = require('fs');
var csv = require('comma-separated-values');
var Server = require('../lib/Server');

var defaultTag = 'dojopaas'

var config = {
  defaultTag: 'dojopaas',
  zone: "29001", // サンドボックス
  api: "https://secure.sakura.ad.jp/cloud/zone/tk1v/api/cloud/1.1/",
  plan: 1001,
  packetfilterid: '112900927419',
  disk: {
    Plan: { ID: 4 },
    SizeMB: 20480,
    SourceArchive: { ID: "112900758037" }
  }
}

sacloud.API_ROOT = config.api;
var client = sacloud.createClient({
  accessToken        : process.env.SACLOUD_ACCESS_TOKEN,
  accessTokenSecret  : process.env.SACLOUD_ACCESS_TOKEN_SECRET,
  disableLocalizeKeys: false, // (optional;default:false) false: lower-camelize the property names in response Object
  debug              : true // (optional;default:false) output debug requests to console.
});

Promise.resolve()
.then(() => {
  return new Promise((resolve, reject) => {
    client.createRequest({
      method: 'GET',
      path  : 'server',
      body  : {
        Filter: {
          "Tags": config.defaultTag
        }
      }
    }).send((err, result) => {
      if (err) reject(err);
      resolve(result);
    });
  });
}).then((data) => {
  for (var i=0; i<data.response.servers.length; i++) {
    var server = new Server(client);
    server.destroy(data.response.servers[i].id)
  }
  return new Promise((resolve, reject) => {
    var server = new Server(client);
    server.create({
      zone: config.zone,
      plan: config.plan,
      packetfilterid: config.packetfilterid,
      name: "test",
      description: "This is a instance for test",
      tags: [config.defaultTag],
      pubkey: "xxxx",
      disk: config.disk,
      resolve: resolve
    })
  })
}).then((data) => {
  client.createRequest({
    method: 'GET',
    path  : 'server/'+data,
  }).send((err, result) => {
    if (err) throw new Error(err);
    if ('up' === result.response.server.instance.status) {
      console.log('OK')
    } else {
      throw new Error('Can not start Instance!');
    }
  });
}).catch((err) => {
  throw new Error(err);
})
<|endoftext|>