<commit_before>/**
 *  Library with useful methods applied to DOM elements (host objects) or built-in JavaScript objects.
 *  Methods naming may look slightly strange but it be better than unexpected name collisions.
 *  Main goal of library at the current stage is not to implement it in a real project, but testing approaches, browser features, generate new ideas.
 *
 *  @author zhibirc
 *  @license
 */
(function () {
    'use strict';

    var domElemProto = Element.prototype,
		objProto = Object.prototype,
		arrProto = Array.prototype,
		strProto = String.prototype,
		fnProto = Function.prototype,
        errors = {
            hide: 'Argument incorrect! Allowed 0 and 1 only.',
            remove: 'Argument incorrect! Allowed "chain" and "save" (without flag is equivalent) only.'
        };

	function isUndef(n) {
		return typeof n === 'undefined';
	}

    /**
     * Method <_remove_> for DOM elements. Remove particular element and additionally accepts two various behaviours.
     * Flag "save" (or without flag at all) means that removed element returns.
     * Flag "chain" means that the parent element returns to build methods chains.
     *
     * @author zhibirc
     * @param {String} aim - Must be "save", "chain".
     * @returns {Object}
     */
    domElemProto._remove_ = function (aim) {
        var parent;

        if (aim === 'save') {
            return this.parentNode.removeChild(this);
        } else if (aim === 'chain') {
            parent = this.parentNode;
            parent.removeChild(this);
            return parent;
        } else {
            throw new SyntaxError(errors.remove);
        }
    };

    /**
     * Method <_hide_> for DOM elements. Accepts two various behaviours depend on flag. All flags must be numbers.
     * Flag 0 instructs to hide element by change its opacity.
     * Flag 1 instructs to hide element by change its display to "none".
     *
     * @author zhibirc
     * @param {Number} level - Must be 0 or 1.
     * @returns {Object}
     */
    domElemProto._hide_ = function (level) {
        switch (level)  {
            case 0:
                this.style.visibility = 'hidden';
                break;
            case 1:
                this.style.display = 'none';
                break;
            default:
                throw new SyntaxError(errors.hide);
        }
        return this;
    };

    /**
     * Implement <last> method for collections of DOM elements.
     *
     * @author zhibirc
     * @returns {Object}
     */
    NodeList.prototype._last_ = HTMLCollection.prototype._last_ = function () {
        return this[this.length - 1];
    };

    /** Function that fixes a case when TextNode returns instead of HTML element (in FF at least). */
    function getFirstChild(elem) {
        var firstChild = elem.firstChild;

        while (firstChild && firstChild.nodeType !== 1) {
            firstChild = firstChild.nextSibling;
        }

        return firstChild;
    }

    /** Useful for loops. Finally invoke 'console.store.s;'. */
    if (typeof console !== 'undefined' && Object.isExtensible(console)) {
        console.store = console.store || {};
        console.store.basket = console.store.basket || '';
        console.store.__defineSetter__('s', function (msg) {
            return this.basket +=
                /* optionally: (new Date).getTime() + */ msg + ';\n';
        });
        console.store.__defineGetter__('s', function () {
            console.log(this.basket);
        });
    }

    /**
     * Adding outline borders to each element on the page.
     *
     * @author Addi Osmani
     */
    (function (a) {
        [].forEach.call(
            document.querySelectorAll(a),
            function (b) {
                b.style.outline = '1px solid #' + (~~(Math.random() * (1 << 24))).toString(16)
            }
        )
    })('*');

    /**
     * Multiply string N-times - first edition.
     *
     * @author zhibirc
     */
    strProto['*'] = function (multiplier) {
        for (var i = multiplier, str = ''; i--; str += this);

        return str;
    };

    /**
     * Multiply string N-times - second edition.
     *
     * @author zhibirc
     */
    strProto['*'] = function (multiplier) {
        return Array(++multiplier).join(this);
    };

    /**
     * Implement well known and standard behaviour of constants in ES5.
     *
     * @author zhibirc
     */
    var CONST = (function () {
        var constStore = Object.create(null);

        return function (name, value) {
            if (typeof value === 'undefined') {
                return constStore[name];
            } else {
                Object.defineProperty(constStore, name, {
                    value: value
                });
                return 0;
            }
        }
    }());

    /**
     * Complex event installer on DOM elements.
     *
     * @author zhibirc
     */
    function addHandler(elem, actions) {
        var errors = ['Wrong invocation! Properly syntax: addHandler(element, { event_0: callback_0, ..., event_N: callback_N})'],
			evt;

		function isValid(n) {
			// TODO: implement validation.
		}

        if (arguments.length !== 2 || ![1, 9, window].some(function (_) { return _ === elem.nodeType || _ === window; }) || !isValid(actions)) {
            if (typeof console !== 'undefined' && typeof console.warn === 'function') {
                console.warn(errors[0]);
            }
            return 0;
        }

		for (evt in actions) {
			if (objProto.hasOwnProperty.call(actions, evt)) {
				if (elem.addEventListener) {
					elem.addEventListener(evt, actions[evt], false);
				} else if (elem.attachEvent) {
					elem.attachEvent('on' + evt, function () { actions[evt].call(elem); });
				} else {
					elem['on' + evt] = actions[evt];
				}
			}
		}

    }

    /**
     * PHP function number_format in JS.
     *
     * @author zhibirc
     */
    function numberFormat(value, decimal, delim, thousands_sep) {
        'use strict';
        if (typeof value !== 'number' || !isFinite(value)) {
            throw new TypeError('Parameter "value" must be a real Number!');
        }
        var resultValue = value,
            delimiter = delim || '.',
            digitParts = [],
            intPart = '';

        decimal && (resultValue = resultValue.toFixed(decimal));
        resultValue = parseInt(resultValue, 10) + delimiter + String(resultValue).split(/\W+/)[1];
        if (thousands_sep) {
            digitParts = resultValue.split(delimiter);
            intPart = digitParts[0].replace(new RegExp("^(\\d{1,intPart.length - 3})(?=\\d{3})", 'g'), "$1" + thousands_sep);
            resultValue = intPart + delimiter + digitParts[1];
        }
        return resultValue;
    }

    /**
     * Extend jQuery-prototype ($.fn) with method serializeToJSON().
     *
     * @author zhibirc
     */
    $.fn.extend({
        serializeToJSON: function () {
            return '"{' + $(this).serialize()
                    .split('&')
                    .map(function (elem) {
                        return elem.split('=');
                    })
                    .map(function (elem) {
                        return elem.map(function (elem, idx, array) {
                            var __elem;
                            elem = elem.replace(/(%[\da-f]+)/ig, function (group_0) {
                                return decodeURIComponent(group_0);
                            });
                            idx && (__elem = +elem);
                            return isFinite(__elem) ? elem : '"' + elem + '"';
                        });
                    })
                    .map(function (elem) {
                        return elem.join(':')
                    })
                    .join(',') + '}"';
        }
    });

    /**
     * Extend DOM Element prototype to implement functionality of eventListenerList (proposal function which has been removed from the spec draft).
     */
    (function () {
        Element.prototype.eventListenerList = {};
        Element.prototype._addEventListener = Element.prototype.addEventListener;
        Element.prototype.addEventListener = function (a, b, c) {
            this._addEventListener(a, b, c);
            if (!this.eventListenerList[a]) this.eventListenerList[a] = [];
            this.eventListenerList[a].push(b);
        };
    })();

    /**
     * Returns an array of longest words.
     *
     * @author zhibirc
     * @todo Add the functionality to determine the level of 'longest'.
     */
    function getLongestWord(str) {
        'use strict';
        var normalize = str.split(/[^-a-zа-я\d]/i),
            max_len = Math.max.apply(Math, normalize.map(function (elem) {
                return elem.length;
            }));
        return str.match(RegExp('[а-я]{' + max_len + '}', 'ig'));
    }

	/**
	 * Add arbitrary amount of elements (or elements from an array) to the end of current array.
	 */
	arrProto['<<'] = function () {
		var args, elems, i, l;

		if (!arguments.length) {
			return this;
		}

		args = arrProto.slice.call(arguments);

		elems = args.length === 1 && Array.isArray(args[0]) ? args[0] : args;

		for (i = 0, l = elems.length; i < l; i += 1) {
			this.push(elems[i]);
		}

		return this; // Suitable for chaining purposes.
	};
}());<commit_msg>Finished addHandler for events.<commit_after>/**
 *  Library with useful methods applied to DOM elements (host objects) or built-in JavaScript objects.
 *  Methods naming may look slightly strange but it be better than unexpected name collisions.
 *  Main goal of library at the current stage is not to implement it in a real project, but testing approaches, browser features, generate new ideas.
 *
 *  @author zhibirc
 *  @license
 */
(function () {
    'use strict';

    var domElemProto = Element.prototype,
		objProto = Object.prototype,
		arrProto = Array.prototype,
		strProto = String.prototype,
		fnProto = Function.prototype,
        errors = {
            hide: 'Argument incorrect! Allowed 0 and 1 only.',
            remove: 'Argument incorrect! Allowed "chain" and "save" (without flag is equivalent) only.'
        };

	function isUndef(n) {
		return typeof n === 'undefined';
	}

    /**
     * Method <_remove_> for DOM elements. Remove particular element and additionally accepts two various behaviours.
     * Flag "save" (or without flag at all) means that removed element returns.
     * Flag "chain" means that the parent element returns to build methods chains.
     *
     * @author zhibirc
     * @param {String} aim - Must be "save", "chain".
     * @returns {Object}
     */
    domElemProto._remove_ = function (aim) {
        var parent;

        if (aim === 'save') {
            return this.parentNode.removeChild(this);
        } else if (aim === 'chain') {
            parent = this.parentNode;
            parent.removeChild(this);
            return parent;
        } else {
            throw new SyntaxError(errors.remove);
        }
    };

    /**
     * Method <_hide_> for DOM elements. Accepts two various behaviours depend on flag. All flags must be numbers.
     * Flag 0 instructs to hide element by change its opacity.
     * Flag 1 instructs to hide element by change its display to "none".
     *
     * @author zhibirc
     * @param {Number} level - Must be 0 or 1.
     * @returns {Object}
     */
    domElemProto._hide_ = function (level) {
        switch (level)  {
            case 0:
                this.style.visibility = 'hidden';
                break;
            case 1:
                this.style.display = 'none';
                break;
            default:
                throw new SyntaxError(errors.hide);
        }
        return this;
    };

    /**
     * Implement <last> method for collections of DOM elements.
     *
     * @author zhibirc
     * @returns {Object}
     */
    NodeList.prototype._last_ = HTMLCollection.prototype._last_ = function () {
        return this[this.length - 1];
    };

    /** Function that fixes a case when TextNode returns instead of HTML element (in FF at least). */
    function getFirstChild(elem) {
        var firstChild = elem.firstChild;

        while (firstChild && firstChild.nodeType !== 1) {
            firstChild = firstChild.nextSibling;
        }

        return firstChild;
    }

    /** Useful for loops. Finally invoke 'console.store.s;'. */
    if (typeof console !== 'undefined' && Object.isExtensible(console)) {
        console.store = console.store || {};
        console.store.basket = console.store.basket || '';
        console.store.__defineSetter__('s', function (msg) {
            return this.basket +=
                /* optionally: (new Date).getTime() + */ msg + ';\n';
        });
        console.store.__defineGetter__('s', function () {
            console.log(this.basket);
        });
    }

    /**
     * Adding outline borders to each element on the page.
     *
     * @author Addi Osmani
     */
    (function (a) {
        [].forEach.call(
            document.querySelectorAll(a),
            function (b) {
                b.style.outline = '1px solid #' + (~~(Math.random() * (1 << 24))).toString(16)
            }
        )
    })('*');

    /**
     * Multiply string N-times - first edition.
     *
     * @author zhibirc
     */
    strProto['*'] = function (multiplier) {
        for (var i = multiplier, str = ''; i--; str += this);

        return str;
    };

    /**
     * Multiply string N-times - second edition.
     *
     * @author zhibirc
     */
    strProto['*'] = function (multiplier) {
        return Array(++multiplier).join(this);
    };

    /**
     * Implement well known and standard behaviour of constants in ES5.
     *
     * @author zhibirc
     */
    var CONST = (function () {
        var constStore = Object.create(null);

        return function (name, value) {
            if (typeof value === 'undefined') {
                return constStore[name];
            } else {
                Object.defineProperty(constStore, name, {
                    value: value
                });
                return 0;
            }
        }
    }());

    /**
     * Complex event installer on DOM elements with old browser support.
     * @author zhibirc
     */
    function addHandler(elem, actions) { // TODO: polyfills of 'some' and 'Object.keys()' required.
        var errors = ['Wrong syntax, event handlers have not been installed!\n' +
					  'Properly syntax: addHandler(element, { event_0: callback_0, ..., event_N: callback_N })'], evt;

		function isValid(n) {
			var keys;

			if (objProto.toString.call(n).slice(8, -1) !== 'Object') {
				return false;
			}

			keys = Object.keys(n);

			if (!+keys || keys.some(function (_) { return typeof n[_] !== 'function'; })) {
				return false;
			}

			return true;
		}

        if (arguments.length !== 2 || ![1, 9, window].some(function (_) { return _ === elem.nodeType || _ === window; }) || !isValid(actions)) {
            throw new Error(errors[0]);
        }

		for (evt in actions) {
			if (objProto.hasOwnProperty.call(actions, evt)) {
				if (elem.addEventListener) {
					elem.addEventListener(evt, actions[evt], false);
				} else if (elem.attachEvent) {
					elem.attachEvent('on' + evt, function () { actions[evt].call(elem); });
				} else {
					elem['on' + evt] = actions[evt];
				}
			}
		}

    }

    /**
     * PHP function number_format in JS.
     *
     * @author zhibirc
     */
    function numberFormat(value, decimal, delim, thousands_sep) {
        'use strict';
        if (typeof value !== 'number' || !isFinite(value)) {
            throw new TypeError('Parameter "value" must be a real Number!');
        }
        var resultValue = value,
            delimiter = delim || '.',
            digitParts = [],
            intPart = '';

        decimal && (resultValue = resultValue.toFixed(decimal));
        resultValue = parseInt(resultValue, 10) + delimiter + String(resultValue).split(/\W+/)[1];
        if (thousands_sep) {
            digitParts = resultValue.split(delimiter);
            intPart = digitParts[0].replace(new RegExp("^(\\d{1,intPart.length - 3})(?=\\d{3})", 'g'), "$1" + thousands_sep);
            resultValue = intPart + delimiter + digitParts[1];
        }
        return resultValue;
    }

    /**
     * Extend jQuery-prototype ($.fn) with method serializeToJSON().
     *
     * @author zhibirc
     */
    $.fn.extend({
        serializeToJSON: function () {
            return '"{' + $(this).serialize()
                    .split('&')
                    .map(function (elem) {
                        return elem.split('=');
                    })
                    .map(function (elem) {
                        return elem.map(function (elem, idx, array) {
                            var __elem;
                            elem = elem.replace(/(%[\da-f]+)/ig, function (group_0) {
                                return decodeURIComponent(group_0);
                            });
                            idx && (__elem = +elem);
                            return isFinite(__elem) ? elem : '"' + elem + '"';
                        });
                    })
                    .map(function (elem) {
                        return elem.join(':')
                    })
                    .join(',') + '}"';
        }
    });

    /**
     * Extend DOM Element prototype to implement functionality of eventListenerList (proposal function which has been removed from the spec draft).
     */
    (function () {
        Element.prototype.eventListenerList = {};
        Element.prototype._addEventListener = Element.prototype.addEventListener;
        Element.prototype.addEventListener = function (a, b, c) {
            this._addEventListener(a, b, c);
            if (!this.eventListenerList[a]) this.eventListenerList[a] = [];
            this.eventListenerList[a].push(b);
        };
    })();

    /**
     * Returns an array of longest words.
     *
     * @author zhibirc
     * @todo Add the functionality to determine the level of 'longest'.
     */
    function getLongestWord(str) {
        'use strict';
        var normalize = str.split(/[^-a-zа-я\d]/i),
            max_len = Math.max.apply(Math, normalize.map(function (elem) {
                return elem.length;
            }));
        return str.match(RegExp('[а-я]{' + max_len + '}', 'ig'));
    }

	/**
	 * Add arbitrary amount of elements (or elements from an array) to the end of current array.
	 */
	arrProto['<<'] = function () {
		var args, elems, i, l;

		if (!arguments.length) {
			return this;
		}

		args = arrProto.slice.call(arguments);

		elems = args.length === 1 && Array.isArray(args[0]) ? args[0] : args;

		for (i = 0, l = elems.length; i < l; i += 1) {
			this.push(elems[i]);
		}

		return this; // Suitable for chaining purposes.
	};

	/**
	 * Beautify with guillemets.
	 * Select a node in your element inspector and run the following code in console.
	 */
	 (function () {
		 var el = $0;
		 // TODO
	 }());
}());<|endoftext|>


<commit_before>'use strict'

const Config = require('./config.js')
const request = require('request-promise')

const Rooms = (() => {
	const local = `${Config.local}/rooms`
	const heroku = `${Config.heroku}/rooms`
    const options = {
        uri: local,
        method: 'GET'
    }

    return {
        getRooms: (socket) => {
            return new Promise((resolve, reject) => {
                request(options).then((data) => {
                    const rooms = JSON.parse(data)
                    let chatRooms = Object.keys(rooms)
                        .filter(room => Object.keys(rooms[room].sockets)[0] !== room)

                    if (chatRooms.length === 0) {
                        socket.emit('create', 'Default Room')
                        chatRooms.push('Default Room')
                    }

                    resolve(chatRooms)
                }).catch((err) => {
                    reject(err);
                })
            })
        }
    }
})()

module.exports = Rooms
<commit_msg>Changed promise styling, and default room name<commit_after>'use strict'

const Config = require('./config.js')
const request = require('request-promise')

const Rooms = (() => {
	const local = `${Config.local}/rooms`
	const heroku = `${Config.heroku}/rooms`
    const options = {
        uri: heroku,
        method: 'GET'
    }

    function getRooms() {
        return new Promise((resolve, reject) => {
            request(options)
                .then((data) => {
                    const rooms = JSON.parse(data)
                    let chatRooms = Object.keys(rooms)
                        .filter(room => Object.keys(rooms[room].sockets)[0] !== room)

                    if (chatRooms.length === 0) {
                        chatRooms.push('default-room')
                    }

                    resolve(chatRooms)
                })
                .catch((err) => {
                    reject(err)
                })
        })
    }

    return {
        getRooms
    }

})()

module.exports = Rooms
<|endoftext|>


<commit_before>'use strict';

// MODULES //

var isObject = require( 'validate.io-object' );
var isString = require( 'validate.io-string-primitive' );
var isFunction = require( 'validate.io-function' );
var copy = require( 'utils-copy' );
var noop = require( '@kgryte/noop' );
var validate = require( './validate.js' );
var defaults = require( './defaults.json' );
var getTasks = require( './get_tasks.js' );

// STARTER //

/**
* FUNCTION: starter( dest[, opts ][, clbk ] )
*	Runs starter tasks.
*
* @param {String} dest - destination directory
* @param {Object} [opts] - function options
* @param {String} [opts.name=""] - module name
* @param {String} [opts.author=""] - module author
* @param {String} [opts.email=""] - author email
* @param {String} [opts.desc=""] - module description
* @param {String[]} [opts.keywords=[]] - module keywords
* @param {String} [opts.cmd=""] - command
* @param {String} [opts.repo=""] - module Github repository
* @param {String} [opts.license="MIT"] - license
* @param {String} [opts.holder=""] - copyright holder
* @param {Boolean} [opts.browser=true] - boolean indicating whether the module is browser compatible
* @param {Boolean} [opts.git=true] - boolean indicating whether to initialize a local git repository
* @param {Boolean} [opts.remote=true] - boolean indicating whether to initialize a remote git repository
* @param {Boolean} [opts.star=true] - boolean indicating whether to star a remote git repository
* @param {Boolean} [opts.ci=true] - boolean indicating whether to initialize continuous integration
* @param {Boolean} [opts.install=true] - boolean indicating whether to run installation tasks
* @param {String|Boolean} [opts.open="subl ."] - command to open a destination directory or `false`
* @param {Boolean} [opts.silent=false] - boolean indicating whether to turn off verbose logging
* @param {Function} [clbk] - callback to invoke upon creating starter kit
*/
function starter() {
	var options;
	var nPhases;
	var debug;
	var nargs;
	var tasks;
	var args;
	var opts;
	var dest;
	var clbk;
	var log;
	var err;
	var idx;

	args = arguments;
	nargs = args.length;
	if ( !nargs ) {
		throw new Error( 'insufficient input arguments. Must provide a file destination.' );
	}
	dest = args[ 0 ];
	if ( !isString( dest ) ) {
		throw new TypeError( 'invalid input argument. First argument must be a string primitive. Value: `' + dest + '`.' );
	}
	if ( nargs === 1 ) {
		clbk = noop;
	}
	else if ( nargs === 2 ) {
		if ( isObject( args[ 1 ] ) ) {
			options = args[ 1 ];
			clbk = noop;
		}
		else if ( isFunction( args[ 1 ] ) ) {
			clbk = args[ 1 ];
		}
		else {
			throw new TypeError( 'invalid input argument. Second argument must either be an options object or a callback. Value: `' + args[ 1 ] + '`.' );
		}
	}
	else {
		options = args[ 1 ];
		clbk = args[ 2 ];
		if ( !isFunction( clbk ) ) {
			throw new TypeError( 'invalid input argument. Callback argument must be a function. Value: `' + clbk + '`.' );
		}
	}
	opts = copy( defaults );
	if ( options ) {
		err = validate( opts, options );
		if ( err ) {
			throw err;
		}
	}
	if ( opts.silent === true ) {
		debug = require( './debug.js' );
	} else {
		process.env.DEBUG = '*';
		debug = require( 'debug' );
	}
	log = debug( 'starter-kit:main' );

	tasks = getTasks( debug );
	nPhases = tasks.length;
	idx = 0;

	log( 'Beginning tasks for phase %d of %d...', idx, nPhases );
	execTasks( tasks[ idx ], next );

	/**
	* FUNCTION: execTasks( tasks, clbk )
	*	Executes tasks.
	*
	* @private
	* @param {Function[]} tasks - task array
	* @param {Function} clbk - callback to invoke after completing tasks
	* @returns {Void}
	*/
	function execTasks( tasks, clbk ) {
		var count;
		var len;
		var i;

		log( 'Beginning tasks...' );
		len = tasks.length;
		count = 0;
		for ( i = 0; i < len; i++ ) {
			log( 'Beginning task %d of %d...', i+1, len );
			tasks[ i ]( dest, opts, done );
		}
		/**
		* FUNCTION: done( [error] )
		*	Callback invoked upon completing a task.
		*
		* @private
		* @param {Error} [error] - error
		* @returns {Void}
		*/
		function done( error ) {
			if ( error ) {
				return clbk( error );
			}
			count += 1;
			log( 'Finished a task. %d of %d complete.', count, len );
			if ( count === len ) {
				log( 'Finished all tasks.' );
				clbk();
			}
		}
	} // end FUNCTION execTasks()

	/**
	* FUNCTION: next( [error] )
	*	Callback invoked after completing a phase's tasks.
	*
	* @private
	* @param {Error} [error] - error
	* @returns {Void}
	*/
	function next( error ) {
		if ( error ) {
			return clbk( error );
		}
		log( 'All tasks for phase %d are complete.', idx );
		idx += 1;
		if ( idx < nPhases ) {
			log( 'Beginning tasks for phase %d of %d...', idx, nPhases );
			return execTasks( tasks[ idx ], next );
		}
		log( 'Finished all task phases.' );
		clbk();
	} // end FUNCTION next()
} // end FUNCTION starter()

// EXPORTS //

module.exports = starter;
<commit_msg>Fix phase logging<commit_after>'use strict';

// MODULES //

var isObject = require( 'validate.io-object' );
var isString = require( 'validate.io-string-primitive' );
var isFunction = require( 'validate.io-function' );
var copy = require( 'utils-copy' );
var noop = require( '@kgryte/noop' );
var validate = require( './validate.js' );
var defaults = require( './defaults.json' );
var getTasks = require( './get_tasks.js' );

// STARTER //

/**
* FUNCTION: starter( dest[, opts ][, clbk ] )
*	Runs starter tasks.
*
* @param {String} dest - destination directory
* @param {Object} [opts] - function options
* @param {String} [opts.name=""] - module name
* @param {String} [opts.author=""] - module author
* @param {String} [opts.email=""] - author email
* @param {String} [opts.desc=""] - module description
* @param {String[]} [opts.keywords=[]] - module keywords
* @param {String} [opts.cmd=""] - command
* @param {String} [opts.repo=""] - module Github repository
* @param {String} [opts.license="MIT"] - license
* @param {String} [opts.holder=""] - copyright holder
* @param {Boolean} [opts.browser=true] - boolean indicating whether the module is browser compatible
* @param {Boolean} [opts.git=true] - boolean indicating whether to initialize a local git repository
* @param {Boolean} [opts.remote=true] - boolean indicating whether to initialize a remote git repository
* @param {Boolean} [opts.star=true] - boolean indicating whether to star a remote git repository
* @param {Boolean} [opts.ci=true] - boolean indicating whether to initialize continuous integration
* @param {Boolean} [opts.install=true] - boolean indicating whether to run installation tasks
* @param {String|Boolean} [opts.open="subl ."] - command to open a destination directory or `false`
* @param {Boolean} [opts.silent=false] - boolean indicating whether to turn off verbose logging
* @param {Function} [clbk] - callback to invoke upon creating starter kit
*/
function starter() {
	var options;
	var nPhases;
	var debug;
	var nargs;
	var tasks;
	var args;
	var opts;
	var dest;
	var clbk;
	var log;
	var err;
	var idx;

	args = arguments;
	nargs = args.length;
	if ( !nargs ) {
		throw new Error( 'insufficient input arguments. Must provide a file destination.' );
	}
	dest = args[ 0 ];
	if ( !isString( dest ) ) {
		throw new TypeError( 'invalid input argument. First argument must be a string primitive. Value: `' + dest + '`.' );
	}
	if ( nargs === 1 ) {
		clbk = noop;
	}
	else if ( nargs === 2 ) {
		if ( isObject( args[ 1 ] ) ) {
			options = args[ 1 ];
			clbk = noop;
		}
		else if ( isFunction( args[ 1 ] ) ) {
			clbk = args[ 1 ];
		}
		else {
			throw new TypeError( 'invalid input argument. Second argument must either be an options object or a callback. Value: `' + args[ 1 ] + '`.' );
		}
	}
	else {
		options = args[ 1 ];
		clbk = args[ 2 ];
		if ( !isFunction( clbk ) ) {
			throw new TypeError( 'invalid input argument. Callback argument must be a function. Value: `' + clbk + '`.' );
		}
	}
	opts = copy( defaults );
	if ( options ) {
		err = validate( opts, options );
		if ( err ) {
			throw err;
		}
	}
	if ( opts.silent === true ) {
		debug = require( './debug.js' );
	} else {
		process.env.DEBUG = '*';
		debug = require( 'debug' );
	}
	log = debug( 'starter-kit:main' );

	tasks = getTasks( debug );
	nPhases = tasks.length;
	idx = 0;

	log( 'Beginning tasks for phase %d of %d...', idx+1, nPhases );
	execTasks( tasks[ idx ], next );

	/**
	* FUNCTION: execTasks( tasks, clbk )
	*	Executes tasks.
	*
	* @private
	* @param {Function[]} tasks - task array
	* @param {Function} clbk - callback to invoke after completing tasks
	* @returns {Void}
	*/
	function execTasks( tasks, clbk ) {
		var count;
		var len;
		var i;

		log( 'Beginning tasks...' );
		len = tasks.length;
		count = 0;
		for ( i = 0; i < len; i++ ) {
			log( 'Beginning task %d of %d...', i+1, len );
			tasks[ i ]( dest, opts, done );
		}
		/**
		* FUNCTION: done( [error] )
		*	Callback invoked upon completing a task.
		*
		* @private
		* @param {Error} [error] - error
		* @returns {Void}
		*/
		function done( error ) {
			if ( error ) {
				return clbk( error );
			}
			count += 1;
			log( 'Finished a task. %d of %d complete.', count, len );
			if ( count === len ) {
				log( 'Finished all tasks.' );
				clbk();
			}
		}
	} // end FUNCTION execTasks()

	/**
	* FUNCTION: next( [error] )
	*	Callback invoked after completing a phase's tasks.
	*
	* @private
	* @param {Error} [error] - error
	* @returns {Void}
	*/
	function next( error ) {
		if ( error ) {
			return clbk( error );
		}
		log( 'All tasks for phase %d are complete.', idx );
		idx += 1;
		if ( idx < nPhases ) {
			log( 'Beginning tasks for phase %d of %d...', idx+1, nPhases );
			return execTasks( tasks[ idx ], next );
		}
		log( 'Finished all task phases.' );
		clbk();
	} // end FUNCTION next()
} // end FUNCTION starter()

// EXPORTS //

module.exports = starter;
<|endoftext|>


<commit_before>var start_text = `
Read all of the \"R\" rules entries before starting the adventure. To get started, type \`Read R1\`
`

exports.start_text = start_text;<commit_msg>Escaping.<commit_after>var start_text = `
Read all of the \"R\" rules entries before starting the adventure. To get started, type \`Read R1\`.
`

var r1_text = `
Welcome to the world of Sargon the Wizard. You\'re about to set out on a thrilling, magic-filled adventure in a dangerous, haunted castle, and you\'ll be on your own. Only your wits and your weapons can help you.
If you choose...
`

module.exports = {
  start_text = start_text,
  r1_text = r1_text
}<|endoftext|>


<commit_before>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

process.chdir(__dirname);

var fs = require('fs');
var sys = require('sys');
var path = require('path');
var spawn = require('child_process').spawn;

var async = require('async');
var sprintf = require('sprintf').sprintf;
var longStackTraces = require('long-stack-traces/lib/long-stack-traces');

var constants = require('./constants');
var parser = require('./parser');
var common = require('./common');
var testUtil = require('./util');

var successes = 0;
var failures = 0;
var timeouts = 0;

var dateStart;

/**
 * Spawn a new child, run a test file and report results.
 *
 * @param {String} filePath Full Absolute path to the test file.
 * @param {Boolean} failFast True to exit after first failure.
 * @param {Number} verbosity Test runner verbosity (0 = quiet, 3 = very verbose).
 * @param {Function} callback Callback which is called on completion.
 */
var executeTest = function(filePath, failFast, verbosity, callback) {
  var fileName = path.basename(filePath);

  testUtil.printMsg(sprintf('Running test file: %s', fileName), verbosity, 3);

  var args = ['run_test_file.js', filePath];
  var child = spawn(process.execPath, args);
  var stderr = [];
  var stdout = [];
  var dead = false;
  var timedOut = false;
  var timeoutId;
  var succeededResult, failedResult;

  child.stderr.on('data', function(chunk) {
    stderr.push(chunk);
  });

  child.stdout.on('data', function(chunk) {
    stdout.push(chunk);
  });

  child.on('exit', function(code) {
    var stdoutJoined = stdout.join('');
    var stderrJoined = stderr.join('');

    clearTimeout(timeoutId);

    result = common.parseResult(stderrJoined);
    succeededResult = result[0];
    failedResult = result[1];

    // Print test results
    sys.puts(fileName);
    common.reportSucceeded(succeededResult);
    common.reportFailed(failedResult);

    successes += Object.keys(succeededResult).length;
    failures += Object.keys(failedResult).length;

    callback(null);
    return;
  });

  timeoutId = setTimeout(function() {
    timeouts++;
    child.kill('SIGKILL');
  }, timeout);
};

var runTests = function(tests, failFast, verbosity) {
  dateStart = testUtil.getUnixTimestamp();
  async.forEachSeries(tests, function(test, callback) {
    executeTest(test, failFast, verbosity, callback);
  },

  function(err) {
    common.printTestsSummary(dateStart, successes, failures, timeouts);
  });
};

process.addListener('SIGINT', function() {
  common.printTestsSummary(dateStart, successes, failures, timeouts);
});

var failFast = false;
var verbosity = constants.DEFAULT_VERBOSITY;
var timeout = constants.DEFAULT_TEST_TIMEOUT;
var tests = [];

var run = function(argv) {
  var p = parser.getParser();
  p.banner = 'Usage: whiskey --tests "files" [options]';

  p.on('failfast', function(opt, value) {
    failFast = true;
  });

  p.on('verbosity', function(opt, value) {
    if (value) {
      verbosity = value;
    }
  });

  p.on('timeout', function(opt, value) {
    if (value) {
      timeout = value;
    }
  });

  p.on('tests', function(opt, value) {
    if (value) {
      tests = value.split(' ');
    }
    else {
      tests = [];
    }
  });

  p.parse(process.argv);

  if (tests.length > 0) {
    runTests(tests, failFast, verbosity);
  }
  else {
    sys.puts(p.banner);
  }
};

exports.run = run;
<commit_msg>Add support for failfast mode.<commit_after>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

process.chdir(__dirname);

var fs = require('fs');
var sys = require('sys');
var path = require('path');
var spawn = require('child_process').spawn;

var async = require('async');
var sprintf = require('sprintf').sprintf;
var longStackTraces = require('long-stack-traces/lib/long-stack-traces');

var constants = require('./constants');
var parser = require('./parser');
var common = require('./common');
var testUtil = require('./util');

var successes = 0;
var failures = 0;
var timeouts = 0;

var dateStart;

/**
 * Spawn a new child, run a test file and report results.
 *
 * @param {String} filePath Full Absolute path to the test file.
 * @param {Boolean} failfast True to exit after first failure.
 * @param {Number} verbosity Test runner verbosity (0 = quiet, 3 = very verbose).
 * @param {Function} callback Callback which is called on completion.
 */
var executeTest = function(filePath, failfast, verbosity, callback) {
  var fileName = path.basename(filePath);

  testUtil.printMsg(sprintf('Running test file: %s', fileName), verbosity, 3);

  var args = ['run_test_file.js', filePath];
  var child = spawn(process.execPath, args);
  var stderr = [];
  var stdout = [];
  var dead = false;
  var timedOut = false;
  var timeoutId;
  var succeededResult, failedResult;

  child.stderr.on('data', function(chunk) {
    stderr.push(chunk);
  });

  child.stdout.on('data', function(chunk) {
    stdout.push(chunk);
  });

  child.on('exit', function(code) {
    var stdoutJoined = stdout.join('');
    var stderrJoined = stderr.join('');

    clearTimeout(timeoutId);

    result = common.parseResult(stderrJoined);
    succeededResult = result[0];
    failedResult = result[1];

    // Print test results
    sys.puts(fileName);
    common.reportSucceeded(succeededResult);
    common.reportFailed(failedResult);

    successes += Object.keys(succeededResult).length;
    failures += Object.keys(failedResult).length;

    if (failfast && failedResult) {
      common.printTestsSummary(dateStart, successes, failures, timeouts);
    }

    callback(null);
    return;
  });

  timeoutId = setTimeout(function() {
    timeouts++;
    child.kill('SIGKILL');
  }, timeout);
};

var runTests = function(tests, failFast, verbosity) {
  dateStart = testUtil.getUnixTimestamp();
  async.forEachSeries(tests, function(test, callback) {
    executeTest(test, failFast, verbosity, callback);
  },

  function(err) {
    common.printTestsSummary(dateStart, successes, failures, timeouts);
  });
};

process.addListener('SIGINT', function() {
  common.printTestsSummary(dateStart, successes, failures, timeouts);
});

var failFast = false;
var verbosity = constants.DEFAULT_VERBOSITY;
var timeout = constants.DEFAULT_TEST_TIMEOUT;
var tests = [];

var run = function(argv) {
  var p = parser.getParser();
  p.banner = 'Usage: whiskey --tests "files" [options]';

  p.on('failfast', function(opt, value) {
    failFast = true;
  });

  p.on('verbosity', function(opt, value) {
    if (value) {
      verbosity = value;
    }
  });

  p.on('timeout', function(opt, value) {
    if (value) {
      timeout = value;
    }
  });

  p.on('tests', function(opt, value) {
    if (value) {
      tests = value.split(' ');
    }
    else {
      tests = [];
    }
  });

  p.parse(process.argv);

  if (tests.length > 0) {
    runTests(tests, failFast, verbosity);
  }
  else {
    sys.puts(p.banner);
  }
};

exports.run = run;
<|endoftext|>


<commit_before>let fs;
let rimraf;
let clone;

// Node packages
try {
  fs = require('fs');
  rimraf = require('rimraf');
  clone = require('git-clone');
} catch (e) {
  console.log(`🙁  Packages missing, run 'npm install' / 'yarn install' first`);
  process.exit(0);
}

// Custom config files
const defaultPackages = require('./packages/default-packages');
const config = require('./_config/config');

// Define custom functions
const Helpers = require('./functions/helpers');
const Dependency = require('./functions/dependency');
const Package = require('./functions/package');
const Configuration = require('./functions/configuration');
const Setup = require('./functions/setup');

let props = process.argv.slice(2);
let setup;
let name;
let extensions;
let packagesSet = false;
let gitRepo = false;
let implementPwa = true;
let customPackages = true;

config.directory.tempDirectory = config.directory.tempDirectoryName;

// Set the debug env variable
process.env.DEBUG = process.argv.includes('debug');
process.env.TESTING = process.argv.includes('testing') || process.argv.includes('skip');
process.env.SKIP = process.argv.includes('skip');

let configuration;

// This function is called after the user filled the questions from start.js
const start = (answers) => {
  Helpers.emptyLog();
  setup = answers.setup;
  extensions = answers.extensions;
  gitRepo = (typeof answers.gitUrl !== 'undefined') ? answers.gitUrl : false;
  implementPwa = answers.implementPwa;

  if (gitRepo) {
    config.directory.tempDirectory = config.directory.gitTempDirectoryName;
  }

  Helpers.removeTempDirectories(startCallback);
};

const startCallback = () => {
  if (gitRepo) {
    return pullGitRepository();
  }

  return continueSetup();
}

// This function is called when a user calls index.js
const quickStart = () => {
  setup = props[0];
  name = props[1];
  extensions = true; // True means all extensions are used

  Helpers.removeTempDirectories(continueSetup);
};

const pullGitRepository = () => {
  console.log(`✨  Cloning ${gitRepo}`);
  clone(gitRepo, config.directory.tempDirectory, () => {
    console.log('👌  Finished cloning');
    Helpers.emptyLog();

    // Remove .git directory from the pulled repo
    // Callback => createTempDirectory
    rimraf(`./${config.directory.tempDirectory}/.git`, createTempDirectory);
  });
};

const continueSetup = () => {
  // Callback => createTempDirectory
  fs.stat(`./_viewlayers/${setup}`, (err, stats) => {
    if (err) {
      Helpers.exit(`Setup directory '${setup}' does not exist in _viewlayers`);
    }

    if (!stats.isDirectory()) {
      Helpers.exit('Setup directory is not a directory');
    }

    return createTempDirectory();
  });
};

// Create temporary directory for the application
const createTempDirectory = () => {
  console.log(`🔨  Creating directory '${config.directory.tempDirectory}'`);
  // Callback => copyPackageJson
  if (gitRepo) {
    return copyPackageJson();
  }

  fs.mkdir(config.directory.tempDirectory, copyPackageJson);
};

// packages.js exists | Callback => installPackages
// No packages.js in setup | Callback => moveConfiguration
const copyPackageJson = () => {
  Helpers.emptyLog();
  console.log(`✨  Setting up ${setup} project`);
  Helpers.emptyLog();

  const packagesPath = (gitRepo)
    ? `./${config.directory.gitTempDirectoryName}/packages`
    : `./_viewlayers/${setup}/packages`;

  fs.stat(`${packagesPath}.js`, (err, stats) => {

    if (err) {
      customPackages = false;
      console.log('No packages.js file found, skipping dependency installation');
    }

    if (customPackages) {
      packagesSet = true;
      configuration = require(packagesPath);
    }

    // Use function to move the package.json file. Pass installPackages as callback
    // Callback => installPackages
    Package.movePackageJson(setup, installPackages, implementPwa);
  });
};

const installPackages = () => {
  // Move node process to new directory
  process.chdir(config.directory.tempDirectory);

  // If setup has custom packages, make sure those are also installed
  if (customPackages) {
    const setupPackages = Package.createPackageString(configuration);
  }

  const devPackages = `${defaultPackages.dev.concat().join(' ')} ${(customPackages) ? setupPackages.dev : ''}`;
  const mainPackages = `${defaultPackages.main.concat().join(' ')} ${(customPackages) ? setupPackages.main : ''}`;

  // Install normal- and dev dependencies.
  // Callback => moveConfiguration
  Dependency.install(
    mainPackages,
    0,
    Dependency.install.bind(this, devPackages, 1, moveConfiguration));
};

// Only move editorconfig if the user selected this
const moveConfiguration = () => {
  Helpers.emptyLog();
  // Jump one directory up with node process
  process.chdir(`../`);

  if (typeof extensions === 'object' && extensions.includes('editorconfig')) {
    return Configuration.moveEditorConfig(moveApplicationSetup);
  }

  return moveApplicationSetup();
};

// Callback => checkIfESLintEnabled
const moveApplicationSetup = () => {
  Setup.moveViewLayerSetup(setup, checkIfESLintEnabled);
};

// Callback => moveBundlerConfiguration
const checkIfESLintEnabled = () => {
  if (typeof extensions === 'object' && extensions.includes('eslint') === false) {
    console.log('ESLint was not enabled');
    removeESLintConfig();
  }

  return moveBundlerConfiguration();
}

const removeESLintConfig = () => {
  const ESLintPath = `${config.directory.tempDirectory}/.eslintrc`;
  fs.stat(ESLintPath, (err, stats) => {
    fs.unlink(ESLintPath, (err) => {
      if (err) {
        console.log('err', err);
      }
      console.log('ESLint configuration removed')
    });
  });
};

// Callback => moveTemplateConfiguration
const moveBundlerConfiguration = () => {
  const bundlerPath = `${config.directory.tempDirectory}/webpack`;
  fs.stat(bundlerPath, (err, stats) => {
    // If there is no webpack directory found
    if (err) {
      const bundler = 'webpack';
      return Setup.moveBundlerSetup(bundler, moveTemplateConfiguration);
    }

    // If a webpack setup is already found, skip copying it
    return moveTemplateConfiguration();
  });
};

// Callback => moveProgressiveWebAppConfig | moveGithooksConfiguration
const moveTemplateConfiguration = () => {
    Setup.moveTemplates(implementPwa, (implementPwa) ? moveProgressiveWebAppConfig : moveGithooksConfiguration);
};

// This function is only called when user answered yes on the pwa question
// Move the _pwa directory to the temporary application directory
// Callback => moveGithooksConfiguration
const moveProgressiveWebAppConfig = () => {
  Setup.moveProgressiveWebAppConfiguration(moveGithooksConfiguration);
};

// Callback => cleanup
const moveGithooksConfiguration = () => {
  // Only move githooks if the user selected them
  if (typeof extensions === 'object' && extensions.includes('githooks')) {
    if (process.env.TESTING === 'true') {
      return Setup.moveGithooks(finished);
    }

    return Setup.moveGithooks(cleanup);
  }

  // If githooks are not selected, continue without moving them
  if (process.env.TESTING === 'true') {
    return finished();
  }

  return cleanup();
};

// Callback => moveTempFilesToRoot
const cleanup = () => {
  fs.readdir('.', (err, files) => {
    // If packages.js was set, remove them from the directory
    if (packagesSet) {
      files.push(`./${config.directory.tempDirectory}/packages.js`);
    }

    Helpers.removeFiles(files, moveTempFilesToRoot);
  });
};

// Callback => finished
const moveTempFilesToRoot = () => {
  Helpers.moveTempFiles(finished);
};

const finished = () => {
  Helpers.emptyLog();
  console.log('🎉  Completed');
}

module.exports.start = start;
module.exports.quickStart = quickStart;
<commit_msg>:boom: Fixed packages error<commit_after>let fs;
let rimraf;
let clone;

// Node packages
try {
  fs = require('fs');
  rimraf = require('rimraf');
  clone = require('git-clone');
} catch (e) {
  console.log(`🙁  Packages missing, run 'npm install' / 'yarn install' first`);
  process.exit(0);
}

// Custom config files
const defaultPackages = require('./packages/default-packages');
const config = require('./_config/config');

// Define custom functions
const Helpers = require('./functions/helpers');
const Dependency = require('./functions/dependency');
const Package = require('./functions/package');
const Configuration = require('./functions/configuration');
const Setup = require('./functions/setup');

let props = process.argv.slice(2);
let setup;
let name;
let extensions;
let packagesSet = false;
let gitRepo = false;
let implementPwa = true;
let customPackages = true;

config.directory.tempDirectory = config.directory.tempDirectoryName;

// Set the debug env variable
process.env.DEBUG = process.argv.includes('debug');
process.env.TESTING = process.argv.includes('testing') || process.argv.includes('skip');
process.env.SKIP = process.argv.includes('skip');

let configuration;

// This function is called after the user filled the questions from start.js
const start = (answers) => {
  Helpers.emptyLog();
  setup = answers.setup;
  extensions = answers.extensions;
  gitRepo = (typeof answers.gitUrl !== 'undefined') ? answers.gitUrl : false;
  implementPwa = answers.implementPwa;

  if (gitRepo) {
    config.directory.tempDirectory = config.directory.gitTempDirectoryName;
  }

  Helpers.removeTempDirectories(startCallback);
};

const startCallback = () => {
  if (gitRepo) {
    return pullGitRepository();
  }

  return continueSetup();
}

// This function is called when a user calls index.js
const quickStart = () => {
  setup = props[0];
  name = props[1];
  extensions = true; // True means all extensions are used

  Helpers.removeTempDirectories(continueSetup);
};

const pullGitRepository = () => {
  console.log(`✨  Cloning ${gitRepo}`);
  clone(gitRepo, config.directory.tempDirectory, () => {
    console.log('👌  Finished cloning');
    Helpers.emptyLog();

    // Remove .git directory from the pulled repo
    // Callback => createTempDirectory
    rimraf(`./${config.directory.tempDirectory}/.git`, createTempDirectory);
  });
};

const continueSetup = () => {
  // Callback => createTempDirectory
  fs.stat(`./_viewlayers/${setup}`, (err, stats) => {
    if (err) {
      Helpers.exit(`Setup directory '${setup}' does not exist in _viewlayers`);
    }

    if (!stats.isDirectory()) {
      Helpers.exit('Setup directory is not a directory');
    }

    return createTempDirectory();
  });
};

// Create temporary directory for the application
const createTempDirectory = () => {
  console.log(`🔨  Creating directory '${config.directory.tempDirectory}'`);
  // Callback => copyPackageJson
  if (gitRepo) {
    return copyPackageJson();
  }

  fs.mkdir(config.directory.tempDirectory, copyPackageJson);
};

// packages.js exists | Callback => installPackages
// No packages.js in setup | Callback => moveConfiguration
const copyPackageJson = () => {
  Helpers.emptyLog();
  console.log(`✨  Setting up ${setup} project`);
  Helpers.emptyLog();

  const packagesPath = (gitRepo)
    ? `./${config.directory.gitTempDirectoryName}/packages`
    : `./_viewlayers/${setup}/packages`;

  fs.stat(`${packagesPath}.js`, (err, stats) => {

    if (err) {
      customPackages = false;
      console.log('No packages.js file found, skipping dependency installation');
    }

    if (customPackages) {
      packagesSet = true;
      configuration = require(packagesPath);
    }

    // Use function to move the package.json file. Pass installPackages as callback
    // Callback => installPackages
    Package.movePackageJson(setup, installPackages, implementPwa);
  });
};

const installPackages = () => {
  // Move node process to new directory
  process.chdir(config.directory.tempDirectory);
  let setupPackages = { dev: '', main: '' };

  // If setup has custom packages, make sure those are also installed
  if (customPackages) {
    setupPackages = Package.createPackageString(configuration);
  }

  const devPackages = `${defaultPackages.dev.concat().join(' ')} ${(customPackages) ? setupPackages.dev : ''}`;
  const mainPackages = `${defaultPackages.main.concat().join(' ')} ${(customPackages) ? setupPackages.main : ''}`;

  // Install normal- and dev dependencies.
  // Callback => moveConfiguration
  Dependency.install(
    mainPackages,
    0,
    Dependency.install.bind(this, devPackages, 1, moveConfiguration));
};

// Only move editorconfig if the user selected this
const moveConfiguration = () => {
  Helpers.emptyLog();
  // Jump one directory up with node process
  process.chdir(`../`);

  if (typeof extensions === 'object' && extensions.includes('editorconfig')) {
    return Configuration.moveEditorConfig(moveApplicationSetup);
  }

  return moveApplicationSetup();
};

// Callback => checkIfESLintEnabled
const moveApplicationSetup = () => {
  Setup.moveViewLayerSetup(setup, checkIfESLintEnabled);
};

// Callback => moveBundlerConfiguration
const checkIfESLintEnabled = () => {
  if (typeof extensions === 'object' && extensions.includes('eslint') === false) {
    console.log('ESLint was not enabled');
    removeESLintConfig();
  }

  return moveBundlerConfiguration();
}

const removeESLintConfig = () => {
  const ESLintPath = `${config.directory.tempDirectory}/.eslintrc`;
  fs.stat(ESLintPath, (err, stats) => {
    fs.unlink(ESLintPath, (err) => {
      if (err) {
        console.log('err', err);
      }
      console.log('ESLint configuration removed')
    });
  });
};

// Callback => moveTemplateConfiguration
const moveBundlerConfiguration = () => {
  const bundlerPath = `${config.directory.tempDirectory}/webpack`;
  fs.stat(bundlerPath, (err, stats) => {
    // If there is no webpack directory found
    if (err) {
      const bundler = 'webpack';
      return Setup.moveBundlerSetup(bundler, moveTemplateConfiguration);
    }

    // If a webpack setup is already found, skip copying it
    return moveTemplateConfiguration();
  });
};

// Callback => moveProgressiveWebAppConfig | moveGithooksConfiguration
const moveTemplateConfiguration = () => {
  Setup.moveTemplates(implementPwa, (implementPwa) ? moveProgressiveWebAppConfig : moveGithooksConfiguration);
};

// This function is only called when user answered yes on the pwa question
// Move the _pwa directory to the temporary application directory
// Callback => moveGithooksConfiguration
const moveProgressiveWebAppConfig = () => {
  Setup.moveProgressiveWebAppConfiguration(moveGithooksConfiguration);
};

// Callback => cleanup
const moveGithooksConfiguration = () => {
  // Only move githooks if the user selected them
  if (typeof extensions === 'object' && extensions.includes('githooks')) {
    if (process.env.TESTING === 'true') {
      return Setup.moveGithooks(finished);
    }

    return Setup.moveGithooks(cleanup);
  }

  // If githooks are not selected, continue without moving them
  if (process.env.TESTING === 'true') {
    return finished();
  }

  return cleanup();
};

// Callback => moveTempFilesToRoot
const cleanup = () => {
  fs.readdir('.', (err, files) => {
    // If packages.js was set, remove them from the directory
    if (packagesSet) {
      files.push(`./${config.directory.tempDirectory}/packages.js`);
    }

    Helpers.removeFiles(files, moveTempFilesToRoot);
  });
};

// Callback => finished
const moveTempFilesToRoot = () => {
  Helpers.moveTempFiles(finished);
};

const finished = () => {
  Helpers.emptyLog();
  console.log('🎉  Completed');
}

module.exports.start = start;
module.exports.quickStart = quickStart;
<|endoftext|>


<commit_before>var CoreObject = require('core-object');
var Promise    = require('ember-cli/lib/ext/promise');
var ssh2       = require('ssh2');
var fs         = require('fs');
var path       = require('path');
var untildify  = require('untildify');
var readFile   = Promise.denodeify(fs.readFile);

var ACTIVE_REVISION_EXT = '.active-revision';

// GENERAL TODO: Figure out how to handle pipeline failure instead of
// just doing Promise.reject

module.exports = CoreObject.extend({
  init: function(options) {
    var plugin = options.plugin;

    this._plugin = plugin;
    this._client = new ssh2.Client();
  },

  upload: function(options) {
    var that           = this;
    var plugin         = this._plugin;
    var allowOverwrite = options.allowOverwrite;
    var revisionKey    = options.revisionKey;
    var filePath       = options.filePath;
    var filename       = path.join(options.remoteDir, options.filePattern + ':' + revisionKey);
    var promisesArray  = [];

    options.autoClose = false;

    options['hosts'].forEach(function (host) {
      options['host'] = host;
      var promise = that.fetchRevisions(options).then(function(revisions) {
        return that._validateRevision(revisions, revisionKey, allowOverwrite);
      })
      .then(readFile.bind(that, filePath))
      .then(function(fileContents) {
        return that._writeFile(fileContents, filename);
      })
      .then(function() {
        plugin.log('✔  ' + filename, { verbose: true });
        // that._client.end();

        return Promise.resolve();
      });
      promisesArray.push(promise);
    });
    return Promise.all(promisesArray);
  },

  activate: function(options) {
    var that          = this;
    var plugin        = that._plugin;
    var remoteDir     = options.remoteDir;
    var revisionKey   = options.revisionKey;
    var revisionPath  = path.join(options.remoteDir, options.filePattern + ":" + revisionKey);
    var indexPath     = path.join(options.remoteDir, options.filePattern);
    var promisesArray = [];
    plugin.log('✔  Running revision activation...', { verbose: true });

    options['hosts'].forEach(function (host) {
      options['host'] = host;
      var promise = that.fetchRevisions(options).then(function(revisions) {
        var revisionExists = that._revisionExists(revisions, revisionKey);

        if (revisionExists) {
          return Promise.all([
            that._copyFile(revisionPath, indexPath),
            that._markActiveRevision(remoteDir, revisionKey)
          ])
          .then(function() {
            plugin.log('✔  ' + revisionPath + " => " + indexPath, { verbose: true });
            return Promise.resolve();
          })
          .catch(function(err) {
            that._client.end();
            return Promise.reject(err);
          })
        } else {
          return Promise.reject('REVISION <' + revisionKey + '> NOT FOUND!');
        }
      });
      promisesArray.push(promise);
    });
    return Promise.all(promisesArray);
  },

  fetchRevisions: function(options) {
    var that   = this;
    var plugin = that._plugin;

    return that._establishSftp(options).then(function(sftp) {
      return new Promise(function(resolve, reject) {
        sftp.readdir(options.remoteDir, function(err, list) {
          if (err) {
            that._client.end();
            reject(err);
          }
          else {
            var revisions = that._extractRevisionsFromFileList(list, options.filePattern);

            if (options.autoClose) {
              that._client.end();
            }

            resolve(revisions);
          }
        });
      });
    });
  },

  _establishSftp: function(options) {
    var that   = this;
    var plugin = that._plugin;
    var client = that._client;

    return that._connect(options).then(function() {
      return new Promise(function(resolve, reject) {
        plugin.log('Attempting to establish an SFTP session', { verbose: true });
        client.sftp(function(err, sftp) {
          if (err) {
            client.end();
            reject(err);
          }
          else {
            plugin.log('SFTP session established', { verbose: true });
            that._sftp = sftp;
            resolve(sftp);
          }
        });
      });
    });
  },

  _connect: function(options) {
    var plugin = this._plugin;
    var client = this._client;
    var ssh_config = {
      host: options.host,
      username: options.username,
      port: options.port || '22',
      agent: options.agent,
      passphrase: options.passphrase,
      privateKey: options.privateKeyFile ? fs.readFileSync(untildify(options.privateKeyFile)) : null
    };

    return new Promise(function(resolve, reject) {
      client.on('ready', function () {
        plugin.log('Successfully connected to remote host', { verbose: true });
        resolve();
      });

      client.on('error', function (error) {
        reject(error);
      });

      plugin.log('Attempting to connect to remote host: ' +
        ssh_config.username + '@' + ssh_config.host + ':' + ssh_config.port,
        { verbose: true });

      client.connect(ssh_config);
    });
  },

  _extractRevisionsFromFileList: function(fileList, filePattern) {
    var revisionRegex = new RegExp(filePattern + ':(.*)');
    var filename, current;
    var revisions = fileList.filter(function(item) {
      filename = item.filename;

      if (filename.indexOf(ACTIVE_REVISION_EXT) !== -1) {
        current = filename.split('.')[0];
      }

      return revisionRegex.test(filename);
    })
    .map(function(rev) {
      var revision = revisionRegex.exec(rev.filename)[1];
      var active = revision === current;

      return {
        revision: revision,
        timestamp: new Date(rev.attrs.mtime * 1000), // convert unix timestamp to JS date
        active: active
      };
    })
    .sort(function(a, b) {
      return b.timestamp - a.timestamp;
    });

    return revisions;
  },

  _validateRevision: function(revisions, revisionKey, allowOverwrite) {
    var revisionExists = this._revisionExists(revisions, revisionKey);

    if (revisionExists && !allowOverwrite) {
      return Promise.reject('REVISION <' + revisionKey + '> ALREADY UPLOADED! (set `allowOverwrite: true` if you want to support overwriting revisions)');
    }

    return Promise.resolve();
  },

  _revisionExists: function(revisions, revisionKey) {
    var revisionExists = false;

    for (var i = 0, len = revisions.length; i < len; i++) {
      if (revisions[i].revision === revisionKey) {
        revisionExists = true;
        break;
      }
    }

    return revisionExists;
  },

  _writeFile: function(fileContents, filename) {
    var that   = this;
    var plugin = that._plugin;

    return new Promise(function(resolve, reject) {
      var stream = that._sftp.createWriteStream(filename);
      stream.on('error', reject);
      stream.on('end', reject);
      stream.on('close', resolve);

      plugin.log('Writing ' + filename + ' to remote host', { verbose: true });

      stream.write(fileContents);
      stream.end();
    });
  },

  _copyFile: function(fromFile, toFile) {
    var client = this._client;

    return new Promise(function(resolve, reject) {
      client.exec('cp ' + fromFile + ' ' + toFile, function(err) {
        if (err) {
          reject(err);
        } else {
          var str = '✔  Copied file ' + fromFile + ' to ' + toFile;
          plugin.log(str, { verbose: true });
          resolve();
        }
      });
    });
  },

  _markActiveRevision: function(remoteDir, revisionKey) {
    var client = this._client;

    return new Promise(function(resolve, reject) {
      client.exec('rm ' + path.join(remoteDir, '*' + ACTIVE_REVISION_EXT) +
        ' && touch ' + path.join(remoteDir, revisionKey + ACTIVE_REVISION_EXT),
        function(err) {
          if (err) {
            reject(err);
          } else {
            resolve();
          }
      });
    });
  }
});
<commit_msg>added plugin variable to print more output<commit_after>var CoreObject = require('core-object');
var Promise    = require('ember-cli/lib/ext/promise');
var ssh2       = require('ssh2');
var fs         = require('fs');
var path       = require('path');
var untildify  = require('untildify');
var readFile   = Promise.denodeify(fs.readFile);

var ACTIVE_REVISION_EXT = '.active-revision';

// GENERAL TODO: Figure out how to handle pipeline failure instead of
// just doing Promise.reject

module.exports = CoreObject.extend({
  init: function(options) {
    var plugin = options.plugin;

    this._plugin = plugin;
    this._client = new ssh2.Client();
  },

  upload: function(options) {
    var that           = this;
    var plugin         = this._plugin;
    var allowOverwrite = options.allowOverwrite;
    var revisionKey    = options.revisionKey;
    var filePath       = options.filePath;
    var filename       = path.join(options.remoteDir, options.filePattern + ':' + revisionKey);
    var promisesArray  = [];

    options.autoClose = false;

    options['hosts'].forEach(function (host) {
      options['host'] = host;
      var promise = that.fetchRevisions(options).then(function(revisions) {
        return that._validateRevision(revisions, revisionKey, allowOverwrite);
      })
      .then(readFile.bind(that, filePath))
      .then(function(fileContents) {
        return that._writeFile(fileContents, filename);
      })
      .then(function() {
        plugin.log('✔  ' + filename, { verbose: true });
        // that._client.end();

        return Promise.resolve();
      });
      promisesArray.push(promise);
    });
    return Promise.all(promisesArray);
  },

  activate: function(options) {
    var that          = this;
    var plugin        = that._plugin;
    var remoteDir     = options.remoteDir;
    var revisionKey   = options.revisionKey;
    var revisionPath  = path.join(options.remoteDir, options.filePattern + ":" + revisionKey);
    var indexPath     = path.join(options.remoteDir, options.filePattern);
    var promisesArray = [];
    plugin.log('✔  Running revision activation...', { verbose: true });

    options['hosts'].forEach(function (host) {
      options['host'] = host;
      var promise = that.fetchRevisions(options).then(function(revisions) {
        var revisionExists = that._revisionExists(revisions, revisionKey);

        if (revisionExists) {
          return Promise.all([
            that._copyFile(revisionPath, indexPath),
            that._markActiveRevision(remoteDir, revisionKey)
          ])
          .then(function() {
            plugin.log('✔  ' + revisionPath + " => " + indexPath, { verbose: true });
            return Promise.resolve();
          })
          .catch(function(err) {
            that._client.end();
            return Promise.reject(err);
          })
        } else {
          return Promise.reject('REVISION <' + revisionKey + '> NOT FOUND!');
        }
      });
      promisesArray.push(promise);
    });
    return Promise.all(promisesArray);
  },

  fetchRevisions: function(options) {
    var that   = this;
    var plugin = that._plugin;

    return that._establishSftp(options).then(function(sftp) {
      return new Promise(function(resolve, reject) {
        sftp.readdir(options.remoteDir, function(err, list) {
          if (err) {
            that._client.end();
            reject(err);
          }
          else {
            var revisions = that._extractRevisionsFromFileList(list, options.filePattern);

            if (options.autoClose) {
              that._client.end();
            }

            resolve(revisions);
          }
        });
      });
    });
  },

  _establishSftp: function(options) {
    var that   = this;
    var plugin = that._plugin;
    var client = that._client;

    return that._connect(options).then(function() {
      return new Promise(function(resolve, reject) {
        plugin.log('Attempting to establish an SFTP session', { verbose: true });
        client.sftp(function(err, sftp) {
          if (err) {
            client.end();
            reject(err);
          }
          else {
            plugin.log('SFTP session established', { verbose: true });
            that._sftp = sftp;
            resolve(sftp);
          }
        });
      });
    });
  },

  _connect: function(options) {
    var plugin = this._plugin;
    var client = this._client;
    var ssh_config = {
      host: options.host,
      username: options.username,
      port: options.port || '22',
      agent: options.agent,
      passphrase: options.passphrase,
      privateKey: options.privateKeyFile ? fs.readFileSync(untildify(options.privateKeyFile)) : null
    };

    return new Promise(function(resolve, reject) {
      client.on('ready', function () {
        plugin.log('Successfully connected to remote host', { verbose: true });
        resolve();
      });

      client.on('error', function (error) {
        reject(error);
      });

      plugin.log('Attempting to connect to remote host: ' +
        ssh_config.username + '@' + ssh_config.host + ':' + ssh_config.port,
        { verbose: true });

      client.connect(ssh_config);
    });
  },

  _extractRevisionsFromFileList: function(fileList, filePattern) {
    var revisionRegex = new RegExp(filePattern + ':(.*)');
    var filename, current;
    var revisions = fileList.filter(function(item) {
      filename = item.filename;

      if (filename.indexOf(ACTIVE_REVISION_EXT) !== -1) {
        current = filename.split('.')[0];
      }

      return revisionRegex.test(filename);
    })
    .map(function(rev) {
      var revision = revisionRegex.exec(rev.filename)[1];
      var active = revision === current;

      return {
        revision: revision,
        timestamp: new Date(rev.attrs.mtime * 1000), // convert unix timestamp to JS date
        active: active
      };
    })
    .sort(function(a, b) {
      return b.timestamp - a.timestamp;
    });

    return revisions;
  },

  _validateRevision: function(revisions, revisionKey, allowOverwrite) {
    var revisionExists = this._revisionExists(revisions, revisionKey);

    if (revisionExists && !allowOverwrite) {
      return Promise.reject('REVISION <' + revisionKey + '> ALREADY UPLOADED! (set `allowOverwrite: true` if you want to support overwriting revisions)');
    }

    return Promise.resolve();
  },

  _revisionExists: function(revisions, revisionKey) {
    var revisionExists = false;

    for (var i = 0, len = revisions.length; i < len; i++) {
      if (revisions[i].revision === revisionKey) {
        revisionExists = true;
        break;
      }
    }

    return revisionExists;
  },

  _writeFile: function(fileContents, filename) {
    var that   = this;
    var plugin = that._plugin;

    return new Promise(function(resolve, reject) {
      var stream = that._sftp.createWriteStream(filename);
      stream.on('error', reject);
      stream.on('end', reject);
      stream.on('close', resolve);

      plugin.log('Writing ' + filename + ' to remote host', { verbose: true });

      stream.write(fileContents);
      stream.end();
    });
  },

  _copyFile: function(fromFile, toFile) {
    var client = this._client;
    var plugin = that._plugin;

    return new Promise(function(resolve, reject) {
      client.exec('cp ' + fromFile + ' ' + toFile, function(err) {
        if (err) {
          reject(err);
        } else {
          var str = '✔  Copied file ' + fromFile + ' to ' + toFile;
          plugin.log(str, { verbose: true });
          resolve();
        }
      });
    });
  },

  _markActiveRevision: function(remoteDir, revisionKey) {
    var client = this._client;

    return new Promise(function(resolve, reject) {
      client.exec('rm ' + path.join(remoteDir, '*' + ACTIVE_REVISION_EXT) +
        ' && touch ' + path.join(remoteDir, revisionKey + ACTIVE_REVISION_EXT),
        function(err) {
          if (err) {
            reject(err);
          } else {
            resolve();
          }
      });
    });
  }
});
<|endoftext|>


<commit_before>'use strict';

const grizzly = require('grizzly');
const jessy = require('jessy');
const isUndefined = (a) => typeof a === 'undefined';

module.exports = tag;

function tag(version, info, chlog, emitter, callback) {
    if (!info.release && !isUndefined(info.release))
        return callback();

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

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

        emitter.emit('data', 'Error releasing on github. Trying again.\n');
        tag(version, info, chlog, emitter, callback);
    });
}

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

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

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

<commit_msg>feature(tag) add ability to emit tag<commit_after>'use strict';

const grizzly = require('grizzly');
const jessy = require('jessy');
const isUndefined = (a) => typeof a === 'undefined';

module.exports = tag;

function tag(version, info, chlog, emitter, callback) {
    if (!info.release && !isUndefined(info.release))
        return callback();

    const tag = 'v' + version;
    const user = getUser(info);
    const repo = getRepoName(info);
    const name = info.name + ' ' + tag;
    const body = chlog;

    emitter.emit('data', `${user}/{repo}@${tag}\n`);
    emitter.emit('data', `${body}\n`);

    const data = {
        user,
        repo,
        tag,
        name,
        body,
    };

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

        emitter.emit('data', 'Error releasing on github. Trying again.\n');
        tag(version, info, chlog, emitter, callback);
    });
}

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

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

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

<|endoftext|>


<commit_before>/**
 * Copyright © 2009-2012 A. Matías Quezada
 */

(function() {

	var aliases = {};

	function setNamespace(ns, obj) {
		var index = ns.lastIndexOf('.')

		if (index == -1)
			use.root[ns] = obj;
		else {
			var parent = ns.substr(0, index);
			var prop = ns.substr(index + 1);
			resolveNamespace(parent)[prop] = obj;
		}
	}

	function resolveNamespace(ns) {
		if (aliases.hasOwnProperty(ns))
			ns = aliases[ns];

		var path = ns.split('.');

		var current = use.root;
		for (var i = 0; i < path.length; i++)
			current = current[path[i]] = current[path[i]] || {};

		return current;
	}

	function use(var_args) {
		var namespaces = [];

		for (var i = 0; i < arguments.length; i++)
			namespaces[i] = resolveNamespace(arguments[i]);

		return {
			on: function(callback) {
				callback.apply(use.root, namespaces);
			}
		};
	}

	use.alias = function(name, target) {
		var pack = resolveNamespace(name);
		aliases[name] = target;

		if (pack) {
			setNamespace(target, pack);
			setNamespace(name, null);
		}
	};

	use.isCommonJS = typeof window === 'undefined';

	use.root = {};
	this.use = use;

	if (use.isCommonJS)
		module.exports = use;

})();
<commit_msg>Fixed use: by default injects on global scope, also global scope is passed to the module function<commit_after>/**
 * Copyright © 2009-2012 A. Matías Quezada
 */

(function() {

	var aliases = {};

	function setNamespace(ns, obj) {
		var index = ns.lastIndexOf('.')

		if (index == -1)
			use.root[ns] = obj;
		else {
			var parent = ns.substr(0, index);
			var prop = ns.substr(index + 1);
			resolveNamespace(parent)[prop] = obj;
		}
	}

	function resolveNamespace(ns) {
		if (aliases.hasOwnProperty(ns))
			ns = aliases[ns];

		var path = ns.split('.');

		var current = use.root;
		for (var i = 0; i < path.length; i++)
			current = current[path[i]] = current[path[i]] || {};

		return current;
	}

	function use(var_args) {
		var namespaces = [];

		for (var i = 0; i < arguments.length; i++)
			namespaces[i] = resolveNamespace(arguments[i]);

		return {
			on: function(callback) {
				callback.apply(null, namespaces);
			}
		};
	}

	use.alias = function(name, target) {
		var pack = resolveNamespace(name);
		aliases[name] = target;

		if (pack) {
			setNamespace(target, pack);
			setNamespace(name, null);
		}
	};

	use.isCommonJS = typeof window === 'undefined';

	use.root = this;
	this.use = use;

	if (use.isCommonJS)
		module.exports = use;

})();
<|endoftext|>


<commit_before>var SMSGHError = require('./error')
var utils = require('./utils')
var httpClient = require('./httpClient')

function callbackWrapper (cb) {
  if (!cb || typeof cb !== 'function') {
    throw new SMSGHError('Provide callback for api request')
  }

  return function (err, res) {
    if (err) return cb(err, null)

    return cb(null, res.body)
  }
}

function USP (auth, token) {
  if (!auth) {
    throw new SMSGHError('Provide the auth object for authentication')
  }

  if (!(this instanceof USP)) return new USP(auth)
  this.defaultHeaders = {
    'Authorization': 'Basic ' + auth.basicAuth,
    'Cotent-Type': 'application/json',
    'Accept': 'application/json'
  }
}

USP.prototype.topupAirtime = function (network, amount, number, cb) {
  network = USP.NETWORK_IDS[network.toLowerCase()]
  var self = this

  if (!utils.isValidTelephoneNumber(number)) {
    throw new SMSGHError('Number `' + number + ' is invalid ')
  }

  cb = callbackWrapper(cb)

  httpClient.post({
    url: USP.BASE_URL + 'usp/airtime',
    headers: this.defaultHeaders,
    data: {
      network: network.toString(),
      amount: amount,
      phone: number,
      token: self.token
    }
  }, cb)
}

USP.prototype.payDSTV = function (account, amount, cb) {
  if (arguments.length < 2) {
    throw new SMSGHError('Provide a an account and amount')
  }
  var self = this
  cb = callbackWrapper(cb)

  httpClient.post({
    url: USP.BASE_URL + 'usp/dstv',
    headers: this.defaultHeaders,
    data: {
      account: account,
      amount: amount,
      token: self.token
    }
  }, cb)
}

USP.prototype.querySurflineDevice = function (number, cb) {
  if (!utils.isValidTelephoneNumber(number)) {
    throw new SMSGHError('Number `' + number + '` is invalid ')
  }

  cb = callbackWrapper(cb)

  httpClient.post({
    url: USP.BASE_URL + 'usp/surfline?' + number,
    headers: this.defaultHeaders,
    data: {}
  }, cb)
}

USP.prototype.bundleSurflinePlus = function (device, amount, cb) {
  if (amount > 50 || !~[1, 5, 10, 20, 50].indexOf(amount)) {
    throw new SMSGHError('Make sure the specified amount is in the range of 1,5,10,20,50')
  }
  var self = this
  cb = callbackWrapper(cb)

  httpClient.post({
    url: USP.BASE_URL + 'usp/surflineplus',
    header: this.defaultHeaders,
    data: {
      device: device.toString(),
      amount: amount,
      token: self.token
    }
  }, cb)
}

USP.prototype.bundleSurfline = function (device, amount, bundle, cb) {
  if (amount > 50 || !~[1, 5, 10, 20, 50].indexOf(amount)) {
    throw new SMSGHError('Make sure the specified amount is in the range of 1,5,10,20,50')
  }

  cb = callbackWrapper(cb)
  var self = this
  httpClient.post({
    url: USP.BASE_URL + 'usp/surflineplus',
    header: this.defaultHeaders,
    data: {
      device: device.toString(),
      amount: amount,
      bundle: bundle,
      token: self.token
    }
  }, cb)
}

USP.prototype.vodafoneInternet = function (account, amount, cb) {
  cb = callbackWrapper(cb)
  var self = this
  httpClient.post({
    url: USP.BASE_URL + 'usp/vodafone-internet',
    header: this.defaultHeaders,
    data: {
      account: account,
      amount: amount,
      token: self.token
    }
  }, cb)
}

USP.prototype.payVodafoneBills = function (account, amount, service, cb) {
  if (service !== 'postpaid' || service !== 'broadband') {
    throw new SMSGHError('The service should be either postpaid or broadband')
  }

  cb = callbackWrapper(cb)
  var self = this
  httpClient.post({
    url: USP.BASE_URL + 'usp/vodafone',
    header: this.defaultHeaders,
    data: {
      account: account,
      amount: amount,
      service: service
    }
  }, cb)
}

USP.prototype.getAccountBalance = function (cb) {
  cb = callbackWrapper(cb)

  httpClient.get({
    url: USP + 'usp/account/' + self.token,
    header: this.defaultHeaders
  }, cb)
}

USP.NETWORK_IDS = {
  airtel: 62006,
  vodafone: 62002,
  expresso: 62004,
  mtn: 62001,
  globacom: 62007,
  tigo: 62003
}

USP.BASE_URL = 'https://api.smsgh.com/'

module.exports = USP
<commit_msg>fix reference to this<commit_after>var SMSGHError = require('./error')
var utils = require('./utils')
var httpClient = require('./httpClient')

function callbackWrapper (cb) {
  if (!cb || typeof cb !== 'function') {
    throw new SMSGHError('Provide callback for api request')
  }

  return function (err, res) {
    if (err) return cb(err, null)

    return cb(null, res.body)
  }
}

function USP (auth, token) {
  if (!auth) {
    throw new SMSGHError('Provide the auth object for authentication')
  }

  if (!(this instanceof USP)) return new USP(auth)
  this.defaultHeaders = {
    'Authorization': 'Basic ' + auth.basicAuth,
    'Cotent-Type': 'application/json',
    'Accept': 'application/json'
  }
}

USP.prototype.topupAirtime = function (network, amount, number, cb) {
  network = USP.NETWORK_IDS[network.toLowerCase()]
  var self = this

  if (!utils.isValidTelephoneNumber(number)) {
    throw new SMSGHError('Number `' + number + ' is invalid ')
  }

  cb = callbackWrapper(cb)

  httpClient.post({
    url: USP.BASE_URL + 'usp/airtime',
    headers: self.defaultHeaders,
    data: {
      network: network.toString(),
      amount: amount,
      phone: number,
      token: self.token
    }
  }, cb)
}

USP.prototype.payDSTV = function (account, amount, cb) {
  if (arguments.length < 2) {
    throw new SMSGHError('Provide a an account and amount')
  }
  var self = this
  cb = callbackWrapper(cb)

  httpClient.post({
    url: USP.BASE_URL + 'usp/dstv',
    headers: self.defaultHeaders,
    data: {
      account: account,
      amount: amount,
      token: self.token
    }
  }, cb)
}

USP.prototype.querySurflineDevice = function (number, cb) {
  if (!utils.isValidTelephoneNumber(number)) {
    throw new SMSGHError('Number `' + number + '` is invalid ')
  }
  var self = this
  cb = callbackWrapper(cb)

  httpClient.post({
    url: USP.BASE_URL + 'usp/surfline?' + number,
    headers: self.defaultHeaders,
    data: {}
  }, cb)
}

USP.prototype.bundleSurflinePlus = function (device, amount, cb) {
  if (amount > 50 || !~[1, 5, 10, 20, 50].indexOf(amount)) {
    throw new SMSGHError('Make sure the specified amount is in the range of 1,5,10,20,50')
  }
  var self = this
  cb = callbackWrapper(cb)

  httpClient.post({
    url: USP.BASE_URL + 'usp/surflineplus',
    header: self.defaultHeaders,
    data: {
      device: device.toString(),
      amount: amount,
      token: self.token
    }
  }, cb)
}

USP.prototype.bundleSurfline = function (device, amount, bundle, cb) {
  if (amount > 50 || !~[1, 5, 10, 20, 50].indexOf(amount)) {
    throw new SMSGHError('Make sure the specified amount is in the range of 1,5,10,20,50')
  }

  cb = callbackWrapper(cb)
  var self = this
  httpClient.post({
    url: USP.BASE_URL + 'usp/surflineplus',
    header: self.defaultHeaders,
    data: {
      device: device.toString(),
      amount: amount,
      bundle: bundle,
      token: self.token
    }
  }, cb)
}

USP.prototype.vodafoneInternet = function (account, amount, cb) {
  cb = callbackWrapper(cb)
  var self = this
  httpClient.post({
    url: USP.BASE_URL + 'usp/vodafone-internet',
    header: self.defaultHeaders,
    data: {
      account: account,
      amount: amount,
      token: self.token
    }
  }, cb)
}

USP.prototype.payVodafoneBills = function (account, amount, service, cb) {
  if (service !== 'postpaid' || service !== 'broadband') {
    throw new SMSGHError('The service should be either postpaid or broadband')
  }

  cb = callbackWrapper(cb)
  var self = this
  httpClient.post({
    url: USP.BASE_URL + 'usp/vodafone',
    header: self.defaultHeaders,
    data: {
      account: account,
      amount: amount,
      service: service
    }
  }, cb)
}

USP.prototype.getAccountBalance = function (cb) {
  cb = callbackWrapper(cb)
  var self = this
  httpClient.get({
    url: USP + 'usp/account/' + self.token,
    header: self.defaultHeaders
  }, cb)
}

USP.NETWORK_IDS = {
  airtel: 62006,
  vodafone: 62002,
  expresso: 62004,
  mtn: 62001,
  globacom: 62007,
  tigo: 62003
}

USP.BASE_URL = 'https://api.smsgh.com/'

module.exports = USP
<|endoftext|>


<commit_before>var debug = require('debug')('zmq-zap:zap'),
	net = require('net');

var ZAP = function(options) {
	this._options = options || {};
	this._mechanisms = {};
}

ZAP.prototype._captureReturnPath = function(data) {
	var returnPath = [];

	var frame = data.shift();
	if (frame) {
		while (frame && (frame.length != 0)) {
			returnPath.push(frame);
			frame = data.shift();
		}
		returnPath.push(frame);
	}

	return returnPath;
}

ZAP.prototype._parseRequestData = function(data) {
	var req;
	if (data && (data.length >= 6)) {
		req = {
			version: new Buffer(data.shift()).toString('utf8'),
			requestId: new Buffer(data.shift()).toString('utf8'),
			domain: new Buffer(data.shift()).toString('utf8'),
			address: new Buffer(data.shift()).toString('utf8'),
			identity: new Buffer(data.shift()).toString('utf8'),
			mechanism: new Buffer(data.shift()).toString('utf8'),
			credentials: data.slice(0)
		};
	}
	return req;
}

ZAP.prototype._validateRequest = function(req, mech) {
	if (req.version != "1.0") return false;
	if (!req.requestId) return false;
	if (!net.isIP(req.address)) return false;

	if (mech && (typeof mech.validate === 'function')) return mech.validate(req);
	else return true;
}

ZAP.prototype._generateResponse = function(req, returnPath, statusCode, message, userId, metadata) {
	if (!message && statusCode) {
		switch (statusCode) {
			case 200:
				message = "OK";
				break;
			case 300:
				message = "ERR";
				break;
			case 400:
				message = "AUTHFAIL";
				break;
			case 500:
				message = "INTERR";
				break;
		}
	}

	if (req && req.version && req.requestId && returnPath && statusCode) {
		debug('Authentication response: %s', req ? JSON.stringify({
			version: req.version,
			requestId: req.requestId,
			statusCode: statusCode,
			message: message,
			userId: userId,
			metadata: metadata
		}, true, 2) : 'undefined');

		return (returnPath || []).splice(0).concat([
			new Buffer(req.version, 'utf8'),
			new Buffer(req.requestId, 'utf8'),
			new Buffer(statusCode.toString(), 'utf8'),
			(message ? new Buffer(message, 'utf8') : new Buffer(0)),
			(((statusCode == 200) && userId) ? new Buffer(userId, 'utf8') : new Buffer(0)),
			(((statusCode == 200) && (metadata)) ? metadata : new Buffer(0))
		]);
	} else {
		return;
	}
}

ZAP.prototype.use = function(mechanism) {
	if (!mechanism) throw new Error('Invalid mechanism');
	if ((typeof mechanism.name !== 'string') || !mechanism.name.length) throw new Error("Invalid mechanism name");
	if (typeof mechanism.authenticate !== 'function') throw new Error('Invalid mechanism authenticate handler');

	this._mechanisms[mechanism.name] = mechanism;
}

ZAP.prototype.authenticate = function(data, callback) {
	if (!data) {
		callback(new Error("Invalid Message"));
		return;
	}

	var data = Array.prototype.slice.call(data); // This forces data to be an array (for when 'arguments' is passed in directly)

	var returnPath = this._captureReturnPath(data),
		req = this._parseRequestData(data),
		mech;

	if (req) mech = this._mechanisms[req.mechanism];

	if (req && this._validateRequest(req, mech)) {
		debug('Authentication request: %s', JSON.stringify(req, true, 2));

		if (mech) {
			mech.authenticate(req, function(err, user, message, metadata) {
				var statusCode, userId, meta;

				if (err) {
					statusCode = 500;
					if (!message) message = err.message;
				} else if (user) {
					statusCode = 200;
					userId = (user !== true) ? user : undefined;
					meta = metadata;
				} else {
					statusCode = 400;
				}

				var res = this._generateResponse(req, returnPath, statusCode, message, userId, meta);
				callback(err, res);
			}.bind(this));
		} else {
			var res = this._generateResponse(req, returnPath, 500, "NO AUTHENTICATOR");
			callback(new Error("No Authenticator"), res);
		}
	} else {
		var res = this._generateResponse(req, returnPath, 300, "INVALID MESSAGE");
		callback(new Error("Invalid Message"), res);
	}
}

module.exports = ZAP;
<commit_msg>Return parsed request in authenticate callback<commit_after>var debug = require('debug')('zmq-zap:zap'),
	net = require('net');

var ZAP = function(options) {
	this._options = options || {};
	this._mechanisms = {};
}

ZAP.prototype._captureReturnPath = function(data) {
	var returnPath = [];

	var frame = data.shift();
	if (frame) {
		while (frame && (frame.length != 0)) {
			returnPath.push(frame);
			frame = data.shift();
		}
		returnPath.push(frame);
	}

	return returnPath;
}

ZAP.prototype._parseRequestData = function(data) {
	var req;
	if (data && (data.length >= 6)) {
		req = {
			version: new Buffer(data.shift()).toString('utf8'),
			requestId: new Buffer(data.shift()).toString('utf8'),
			domain: new Buffer(data.shift()).toString('utf8'),
			address: new Buffer(data.shift()).toString('utf8'),
			identity: new Buffer(data.shift()).toString('utf8'),
			mechanism: new Buffer(data.shift()).toString('utf8'),
			credentials: data.slice(0)
		};
	}
	return req;
}

ZAP.prototype._validateRequest = function(req, mech) {
	if (req.version != "1.0") return false;
	if (!req.requestId) return false;
	if (!net.isIP(req.address)) return false;

	if (mech && (typeof mech.validate === 'function')) return mech.validate(req);
	else return true;
}

ZAP.prototype._generateResponse = function(req, returnPath, statusCode, message, userId, metadata) {
	if (!message && statusCode) {
		switch (statusCode) {
			case 200:
				message = "OK";
				break;
			case 300:
				message = "ERR";
				break;
			case 400:
				message = "AUTHFAIL";
				break;
			case 500:
				message = "INTERR";
				break;
		}
	}

	if (req && req.version && req.requestId && returnPath && statusCode) {
		debug('Authentication response: %s', req ? JSON.stringify({
			version: req.version,
			requestId: req.requestId,
			statusCode: statusCode,
			message: message,
			userId: userId,
			metadata: metadata
		}, true, 2) : 'undefined');

		return (returnPath || []).splice(0).concat([
			new Buffer(req.version, 'utf8'),
			new Buffer(req.requestId, 'utf8'),
			new Buffer(statusCode.toString(), 'utf8'),
			(message ? new Buffer(message, 'utf8') : new Buffer(0)),
			(((statusCode == 200) && userId) ? new Buffer(userId, 'utf8') : new Buffer(0)),
			(((statusCode == 200) && (metadata)) ? metadata : new Buffer(0))
		]);
	} else {
		return;
	}
}

ZAP.prototype.use = function(mechanism) {
	if (!mechanism) throw new Error('Invalid mechanism');
	if ((typeof mechanism.name !== 'string') || !mechanism.name.length) throw new Error("Invalid mechanism name");
	if (typeof mechanism.authenticate !== 'function') throw new Error('Invalid mechanism authenticate handler');

	this._mechanisms[mechanism.name] = mechanism;
}

ZAP.prototype.authenticate = function(data, callback) {
	if (!data) {
		callback(new Error("Invalid Message"));
		return;
	}

	var data = Array.prototype.slice.call(data); // This forces data to be an array (for when 'arguments' is passed in directly)

	var returnPath = this._captureReturnPath(data),
		req = this._parseRequestData(data),
		mech;

	if (req) mech = this._mechanisms[req.mechanism];

	if (req && this._validateRequest(req, mech)) {
		debug('Authentication request: %s', JSON.stringify(req, true, 2));

		if (mech) {
			mech.authenticate(req, function(err, user, message, metadata) {
				var statusCode, userId, meta;

				if (err) {
					statusCode = 500;
					if (!message) message = err.message;
				} else if (user) {
					statusCode = 200;
					userId = (user !== true) ? user : undefined;
					meta = metadata;
				} else {
					statusCode = 400;
				}

				var res = this._generateResponse(req, returnPath, statusCode, message, userId, meta);
				callback(err, res, req);
			}.bind(this));
		} else {
			var res = this._generateResponse(req, returnPath, 500, "NO AUTHENTICATOR");
			callback(new Error("No Authenticator"), res, req);
		}
	} else {
		var res = this._generateResponse(req, returnPath, 300, "INVALID MESSAGE");
		callback(new Error("Invalid Message"), res, req);
	}
}

module.exports = ZAP;
<|endoftext|>