<commit_before>var appDir = Ti.Filesystem.resourcesDirectory,
	_require = require,
	path;

module.exports = function(dirname) {
	return function(p) {
		var newPath, modulePath;

		if (p.indexOf('/') === 0) {
			newPath = p;
		} else if (p.indexOf('../') === 0 || p.indexOf('./') === 0) {
			newPath = path.resolve(dirname, p);
		} else {
			newPath = 'node_modules/' + p;
		}
		newPath = path.resolve(newPath).substring(1);

		modulePath = loadAsFile(newPath) || loadAsDirectory(newPath);
		if (modulePath) {
			Ti.API.trace("require('" + p + "') --> require('" + newPath + "')");
			return _require(modulePath);
		} else {
			throw new Error('Failed to load module ' + p + ' at ' + newPath + ' (resolved as ' + modulePath + ')');
		}
	};
};

function loadAsFile(filepath) {
	var file = getLoadableFile(filepath) || getLoadableFile(filepath + '.js');
	if (file) {
		return filepath;
	}
}

function loadAsDirectory(filepath) {
	if (!Ti.Filesystem.getFile(appDir, filepath).isDirectory()) {
		return;
	}

	// require from the package.json "main" path
	var packageJsonFile = Ti.Filesystem.getFile(appDir, filepath + '/package.json');
	if (packageJsonFile.exists()) {
		var json = JSON.parse(packageJsonFile.read().text);
		if (json.main) {
			return filepath + '/' + json.main.replace(/\.js$/, '');
		}
	}

	// load from index.js in the directory
	var indexFile = Ti.Filesystem.getFile(appDir, filepath + '/index.js');
	if (indexFile.exists()) {
		return filepath + '/index';
	}
}

function getLoadableFile(filepath) {
	var file = Ti.Filesystem.getFile(appDir, filepath);
	if (file.exists() && !file.isDirectory()) {
		return file;
	}
}

// process shim
var process = {
	cwd: function() {
		return '/';
	}
};

// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
path = (function() {
	var exports = {};

	function normalizeArray(parts, allowAboveRoot) {
		// if the path tries to go above the root, `up` ends up > 0
		var up = 0;
		for (var i = parts.length - 1; i >= 0; i--) {
			var last = parts[i];
			if (last === '.') {
				parts.splice(i, 1);
			} else if (last === '..') {
				parts.splice(i, 1);
				up++;
			} else if (up) {
				parts.splice(i, 1);
				up--;
			}
		}

		// if the path is allowed to go above the root, restore leading ..s
		if (allowAboveRoot) {
			for (; up--; up) {
				parts.unshift('..');
			}
		}

		return parts;
	}

	function filter (xs, f) {
		if (xs.filter) { return xs.filter(f); }
		var res = [];
		for (var i = 0; i < xs.length; i++) {
			if (f(xs[i], i, xs)) { res.push(xs[i]); }
		}
		return res;
	}

	exports.resolve = function() {
		var resolvedPath = '',
			resolvedAbsolute = false;

		for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
			var path = (i >= 0) ? arguments[i] : process.cwd();

			// Skip empty and invalid entries
			if (typeof path !== 'string') {
				throw new TypeError('Arguments to path.resolve must be strings');
			} else if (!path) {
				continue;
			}

			resolvedPath = path + '/' + resolvedPath;
			resolvedAbsolute = path.charAt(0) === '/';
		}

		// At this point the path should be resolved to a full absolute path, but
		// handle relative paths to be safe (might happen when process.cwd() fails)

		// Normalize the path
		resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
			return !!p;
		}), !resolvedAbsolute).join('/');

		return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
	};

	return exports;
})();
<commit_msg>improved module failure message<commit_after>var appDir = Ti.Filesystem.resourcesDirectory,
	_require = require,
	path;

module.exports = function(dirname) {
	return function(p) {
		var newPath, modulePath;

		if (p.indexOf('/') === 0) {
			newPath = p;
		} else if (p.indexOf('../') === 0 || p.indexOf('./') === 0) {
			newPath = path.resolve(dirname, p);
		} else {
			newPath = 'node_modules/' + p;
		}
		newPath = path.resolve(newPath).substring(1);

		modulePath = loadAsFile(newPath) || loadAsDirectory(newPath);
		if (modulePath) {
			Ti.API.trace("require('" + p + "') --> require('" + newPath + "')");
			return _require(modulePath);
		} else {
			// or should I try `_require(newPath)` and let the Titanium handle the error?
			throw new Error('Failed to load module "' + p + '".\n\nCould not resolve "' + newPath + '" to a valid path.');
		}
	};
};

function loadAsFile(filepath) {
	var file = getLoadableFile(filepath) || getLoadableFile(filepath + '.js');
	if (file) {
		return filepath;
	}
}

function loadAsDirectory(filepath) {
	if (!Ti.Filesystem.getFile(appDir, filepath).isDirectory()) {
		return;
	}

	// require from the package.json "main" path
	var packageJsonFile = Ti.Filesystem.getFile(appDir, filepath + '/package.json');
	if (packageJsonFile.exists()) {
		var json = JSON.parse(packageJsonFile.read().text);
		if (json.main) {
			return filepath + '/' + json.main.replace(/\.js$/, '');
		}
	}

	// load from index.js in the directory
	var indexFile = Ti.Filesystem.getFile(appDir, filepath + '/index.js');
	if (indexFile.exists()) {
		return filepath + '/index';
	}
}

function getLoadableFile(filepath) {
	var file = Ti.Filesystem.getFile(appDir, filepath);
	if (file.exists() && !file.isDirectory()) {
		return file;
	}
}

// process shim
var process = {
	cwd: function() {
		return '/';
	}
};

// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
path = (function() {
	var exports = {};

	function normalizeArray(parts, allowAboveRoot) {
		// if the path tries to go above the root, `up` ends up > 0
		var up = 0;
		for (var i = parts.length - 1; i >= 0; i--) {
			var last = parts[i];
			if (last === '.') {
				parts.splice(i, 1);
			} else if (last === '..') {
				parts.splice(i, 1);
				up++;
			} else if (up) {
				parts.splice(i, 1);
				up--;
			}
		}

		// if the path is allowed to go above the root, restore leading ..s
		if (allowAboveRoot) {
			for (; up--; up) {
				parts.unshift('..');
			}
		}

		return parts;
	}

	function filter (xs, f) {
		if (xs.filter) { return xs.filter(f); }
		var res = [];
		for (var i = 0; i < xs.length; i++) {
			if (f(xs[i], i, xs)) { res.push(xs[i]); }
		}
		return res;
	}

	exports.resolve = function() {
		var resolvedPath = '',
			resolvedAbsolute = false;

		for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
			var path = (i >= 0) ? arguments[i] : process.cwd();

			// Skip empty and invalid entries
			if (typeof path !== 'string') {
				throw new TypeError('Arguments to path.resolve must be strings');
			} else if (!path) {
				continue;
			}

			resolvedPath = path + '/' + resolvedPath;
			resolvedAbsolute = path.charAt(0) === '/';
		}

		// At this point the path should be resolved to a full absolute path, but
		// handle relative paths to be safe (might happen when process.cwd() fails)

		// Normalize the path
		resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
			return !!p;
		}), !resolvedAbsolute).join('/');

		return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
	};

	return exports;
})();
<|endoftext|>


<commit_before>
/**
 * Exports the current runtime environment, by processing
 * the query-params of the URL (window.location.search
 *
 *  currently supported settings are
 *

 *
browser

 *
cordova

 *
android

 *
ios

 *

 *
 *  @exports {Object} a singleton object with information about the runtime setting:
 *
{
 *  			isBrowserEnv: [true|false],
 *  			isCordovaEnv: [true|false],
 *  			platform: ["browser" | "android" | "ios" | "node" | "default"],
 *  		}

 */
define(['mmirf/paramsParseFunc'], function(paramsParseFunc) {

	var ctx = typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : typeof global !== 'undefined' ? global : this;
	var paramsStr = ctx && ctx.location? ctx.location.search : '?env=node';
	var params = paramsParseFunc( paramsStr );

	var isBrowserEnv;
	var isCordovaEnv;
	var isNodeEnv;
	var envSetting = '';
	var envParamSetting = '';

	if(typeof cordova !== 'undefined'){
		envSetting = cordova.platformId? cordova.platformId : envSetting;
		isCordovaEnv = true;
	}

	if(params.has('env')){

		envParamSetting = params['env'];
		envSetting = !envSetting? envParamSetting : envSetting;
	}

	if(envSetting){

		if(envSetting === 'browser'){
			isBrowserEnv = true;
		}
		else {
			isBrowserEnv = false;
		}

		if(envSetting === 'cordova' || envSetting === 'android' || envSetting === 'ios' || envSetting === 'windows'){
			isCordovaEnv = true;
//			isBrowserEnv = false;
		}
		else {
			isCordovaEnv = false;
		}

		if(envSetting === 'node'){
			isNodeEnv = true;
		}
		else {
			isNodeEnv = false;
		}
	}
	else {
		isBrowserEnv = true;
		isCordovaEnv = false;
		isNodeEnv = false;
	}

	var env;
	if(isBrowserEnv){
		env = 'browser';
	} else {

		//if available, use plugin cordova-plugin-device for detecting specific env
		if(typeof device !== 'undefined' && device.platform){

			isCordovaEnv = true;
			var platform = device.platform;
			if(/\bios\b/i.test(platform)){
				env = 'ios';
			} else if(/\bandroid\b/i.test(platform)){
				env = 'android';
			} else if(/\bwindows\b/i.test(platform)){
				env = 'windows';
			} else if(/\bbrowser\b/i.test(platform)){
				isBrowserEnv = true;
				isCordovaEnv = false;//FIXME quick-fix for indicating that browser implementations should be used instead of cordova-impl. TODO handle this correctly in mmir lib, i.e. do not simply use env.isCordovaEnv
				env = 'browser';
				//NOTE for electron, device.platform is 'browser' -> check for electron via cordova.platformId
				if(typeof cordova !== 'undefined'){
					if(/\belectron\b/i.test(cordova.platformId)){
						env = 'electron';
					}
				}
			} else {//TODO handle other platforms
				console.warn('mmir.env: Unknown platform "'+platform+'"');
				env = 'default';
			}

		} else if(typeof navigator !== 'undefined') {

			//fallback: use UserAgent for detecting env
			var userAgent = navigator.userAgent;
			if(/(iPad|iPhone|iPod)/ig.test(userAgent)){
				env = 'ios';
			} else if(/android/i.test(userAgent)){
				env = 'android';
			} else if(/MSAppHost/i.test(userAgent)){
				env = 'windows';
			} else if(/\bElectron\b/i.test(userAgent)){
				env = 'electron';
			} else {//TODO handle other platforms
				console.warn('mmir.env: Unknown platform for userAgent "'+userAgent+'"');
				env = 'default';
			}

		} else if(isNodeEnv) {
			env = 'node';
		} else {//TODO handle other platforms
			console.warn('mmir.env: Unknown platform');
			env = 'default';
		}

	}

	return {
		isBrowserEnv: isBrowserEnv,
		isCordovaEnv: isCordovaEnv,
		isNodeEnv: isNodeEnv,
		envSetting: envSetting,
		platform: env
//	, params : params
	};
});
<commit_msg>updated docs w.r.t. node environment<commit_after>
/**
 * Exports the current runtime environment, by processing
 * the query-params of the URL (window.location.search
 *
 *  currently supported settings are
 *

 *
browser

 *
cordova

 *
android

 *
ios

 *
node

 *

 *
 * @name EnvDetect
 * @class
 * @memberOf mmir.tools
 * @static
 * @hideconstructor
 *
 * @requires mmirf/paramsParseFunc
 *
 * @exports {Object} a singleton object with information about the runtime setting:
 *
{
 *  			isBrowserEnv: [true|false],
 *  			isCordovaEnv: [true|false],
 *  			isNodeEnv: [true|false],
 *  			platform: ["browser" | "android" | "ios" | "node" | "default"],
 *  			envSetting: ["browser" | "android" | "ios" | "node" | "default" | string],
 *  		}

 *
 */
define(['mmirf/paramsParseFunc'], function(paramsParseFunc) {

	var ctx = typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : typeof global !== 'undefined' ? global : this;
	var paramsStr = ctx && ctx.location? ctx.location.search : '?env=node';
	var params = paramsParseFunc( paramsStr );

	var isBrowserEnv;
	var isCordovaEnv;
	var isNodeEnv;
	var envSetting = '';
	var envParamSetting = '';

	if(typeof cordova !== 'undefined'){
		envSetting = cordova.platformId? cordova.platformId : envSetting;
		isCordovaEnv = true;
	}

	if(params.has('env')){

		envParamSetting = params['env'];
		envSetting = !envSetting? envParamSetting : envSetting;
	}

	if(envSetting){

		if(envSetting === 'browser'){
			isBrowserEnv = true;
		}
		else {
			isBrowserEnv = false;
		}

		if(envSetting === 'cordova' || envSetting === 'android' || envSetting === 'ios' || envSetting === 'windows'){
			isCordovaEnv = true;
//			isBrowserEnv = false;
		}
		else {
			isCordovaEnv = false;
		}

		if(envSetting === 'node'){
			isNodeEnv = true;
		}
		else {
			isNodeEnv = false;
		}
	}
	else {
		isBrowserEnv = true;
		isCordovaEnv = false;
		isNodeEnv = false;
	}

	var env;
	if(isBrowserEnv){
		env = 'browser';
	} else {

		//if available, use plugin cordova-plugin-device for detecting specific env
		if(typeof device !== 'undefined' && device.platform){

			isCordovaEnv = true;
			var platform = device.platform;
			if(/\bios\b/i.test(platform)){
				env = 'ios';
			} else if(/\bandroid\b/i.test(platform)){
				env = 'android';
			} else if(/\bwindows\b/i.test(platform)){
				env = 'windows';
			} else if(/\bbrowser\b/i.test(platform)){
				isBrowserEnv = true;
				isCordovaEnv = false;//FIXME quick-fix for indicating that browser implementations should be used instead of cordova-impl. TODO handle this correctly in mmir lib, i.e. do not simply use env.isCordovaEnv
				env = 'browser';
				//NOTE for electron, device.platform is 'browser' -> check for electron via cordova.platformId
				if(typeof cordova !== 'undefined'){
					if(/\belectron\b/i.test(cordova.platformId)){
						env = 'electron';
					}
				}
			} else {//TODO handle other platforms
				console.warn('mmir.env: Unknown platform "'+platform+'"');
				env = 'default';
			}

		} else if(typeof navigator !== 'undefined') {

			//fallback: use UserAgent for detecting env
			var userAgent = navigator.userAgent;
			if(/(iPad|iPhone|iPod)/ig.test(userAgent)){
				env = 'ios';
			} else if(/android/i.test(userAgent)){
				env = 'android';
			} else if(/MSAppHost/i.test(userAgent)){
				env = 'windows';
			} else if(/\bElectron\b/i.test(userAgent)){
				env = 'electron';
			} else {//TODO handle other platforms
				console.warn('mmir.env: Unknown platform for userAgent "'+userAgent+'"');
				env = 'default';
			}

		} else if(isNodeEnv) {
			env = 'node';
		} else {//TODO handle other platforms
			console.warn('mmir.env: Unknown platform');
			env = 'default';
		}

	}

	return {
		isBrowserEnv: isBrowserEnv,
		isCordovaEnv: isCordovaEnv,
		isNodeEnv: isNodeEnv,
		envSetting: envSetting,
		platform: env
//	, params : params
	};
});
<|endoftext|>


<commit_before>var forEach = require('lodash.foreach');
var merge = require('lodash.merge');

var StyleResolverMixin = {
  getStateStyles: function (states) {
    if (!states) {
      return;
    }

    var stateStyles;

    if (this.state.active) {
      stateStyles = states.active;
    } else if (this.state.focus) {
      stateStyles = states.focus;
    } else if (this.state.hover) {
      stateStyles = states.hover;
    }

    return stateStyles;
  },

  getBreakpointStyles: function (styles) {
    var breakpointStyles = merge({}, styles);
    var componentBreakpoints = this.props.breakpoints;

    if (this.state && this.state.breakpoints) {
      componentBreakpoints = this.state.breakpoints;
    }

    forEach(styles.breakpoints, function (breakpoint, key) {
      if (componentBreakpoints && componentBreakpoints[key]) {
        var activeBreakpoint = breakpoint;

        if (!activeBreakpoint) {
          return;
        }

        merge(
          breakpointStyles,
          activeBreakpoint
        );
      }
    }, this);

    breakpointStyles.breakpoints = null;

    return breakpointStyles;
  },

  getModifierStyles: function (styles) {
    var modifierStyles = merge({}, styles.standard);

    forEach(styles.modifiers, function (modifier, key) {
      if (this.props[key]) {
        var modifierValue = this.props[key];
        var activeModifier;

        if (typeof modifierValue === 'string') {
          activeModifier = modifier[modifierValue];
        } else if (modifierValue === true || modifierValue === false) {
          activeModifier = modifier;
        } else {
          return;
        }

        if (!activeModifier) {
          return;
        }

        merge(
          modifierStyles,
          activeModifier
        );
      }
    }, this);

    return modifierStyles;
  },

  getStaticStyles: function (styles) {
    var elementStyles = this.getModifierStyles(styles);
    var mediaQueryStyles = this.getBreakpointStyles(elementStyles);

    return merge(
      {},
      mediaQueryStyles,
      this.props.style,
      this.getStateStyles(mediaQueryStyles.states)
    );
  },

  buildStyles: function (styles, computedStyleFunc) {
    var staticStyles = this.getStaticStyles(styles);
    var computedStyles;

    if (computedStyleFunc) {
      computedStyles = computedStyleFunc(staticStyles);
    }

    return merge({}, staticStyles, computedStyles);
  }
};

module.exports = StyleResolverMixin;
<commit_msg>Replace computed callback with style obj methods<commit_after>var forEach = require('lodash.foreach');
var merge = require('lodash.merge');

var StyleResolverMixin = {
  getStateStyles: function (states) {
    if (!states) {
      return;
    }

    var stateStyles;

    if (this.state.active) {
      stateStyles = states.active;
    } else if (this.state.focus) {
      stateStyles = states.focus;
    } else if (this.state.hover) {
      stateStyles = states.hover;
    }

    return stateStyles;
  },

  getBreakpointStyles: function (styles) {
    var breakpointStyles = merge({}, styles);
    var componentBreakpoints = this.props.breakpoints;

    if (this.state && this.state.breakpoints) {
      componentBreakpoints = this.state.breakpoints;
    }

    forEach(styles.breakpoints, function (breakpoint, key) {
      if (componentBreakpoints && componentBreakpoints[key]) {
        var activeBreakpoint = breakpoint;

        if (!activeBreakpoint) {
          return;
        }

        merge(
          breakpointStyles,
          activeBreakpoint
        );
      }
    }, this);

    breakpointStyles.breakpoints = null;

    return breakpointStyles;
  },

  getModifierStyles: function (styles) {
    var modifierStyles = merge({}, styles.standard);

    forEach(styles.modifiers, function (modifier, key) {
      if (this.props[key]) {
        var modifierValue = this.props[key];
        var activeModifier;

        if (typeof modifierValue === 'string') {
          activeModifier = modifier[modifierValue];
        } else if (modifierValue === true || modifierValue === false) {
          activeModifier = modifier;
        } else {
          return;
        }

        if (!activeModifier) {
          return;
        }

        merge(
          modifierStyles,
          activeModifier
        );
      }
    }, this);

    return modifierStyles;
  },

  getStaticStyles: function (styles) {
    var elementStyles = this.getModifierStyles(styles);
    var mediaQueryStyles = this.getBreakpointStyles(elementStyles);

    return merge(
      {},
      mediaQueryStyles,
      this.props.style,
      this.getStateStyles(mediaQueryStyles.states),
      { states: null }
    );
  },

  getComputedStyles: function (styles) {
    var computedStyles = {};

    forEach(styles, function (style) {
      if (typeof style === 'function') {
        var computedRule = style(styles);

        for (prop in computedRule) {
          computedStyles[prop] = computedRule[prop];
        }
      }
    });

    return merge(
      {},
      styles,
      computedStyles
    );
  },

  buildStyles: function (styles, computedStyleFunc) {
    var staticStyles = this.getStaticStyles(styles);

    return this.getComputedStyles(staticStyles);
  }
};

module.exports = StyleResolverMixin;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
 *
 *                   _.---.._
 *      _        _.-' \  \    ''-.
 *    .'  '-,_.-'   /  /  /       '''.
 *   (       _                     o  :
 *    '._ .-'  '-._         \  \-  ---]
 *                  '-.___.-')  )..-'
 *                           (_/
 *
 */
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var verror = require('verror');

/**
 * Queue used to serialize state transitions
 */
function TransitionQueue(options) {
    EventEmitter.call(this);
    var self = this;
    this._queue = [];
    this._log = options.log;
    this._emitter = new EventEmitter();

    this._isPause = false; /* lock used to pause the queue */
    this._isExec = false; /* lock used to ensure serial execution */
    this._req = null; /* the currently executing request */

    var log = self._log;
    self._emitter.on('push', function () {
        if (self._isExec) {
            log.info({
                queue_length: self._queue.length,
                curr_req: self._req.transition,
                new_req: self._queue[self._queue.length - 1].transition
            }, 'waiting for current transition to finish before ' +
            'executing pushed req');
            return;
        } else {
            exec(self);
        }
    });
}

function exec(self) {
    var log = self._log;
    if (self._isExec) {
        log.info('TransitionQueue.exec: already executing other req, exiting');
        return;
    }
    self._isExec = true;
    var req = self._queue.shift();
    self._req = req;
    if (!req) {
        log.info('TransitionQueue.exec: no request, exiting');
        self._isExec = false;
        return;
    }

    req.invoke(req.ctx, function (err) {
        log.info({
            transition: req.transition,
            err: err
        }, 'finished transition');
        if (err) {
            self.emit('execError',
                new verror.VError(err, 'transition queue exec error'));
        }
        if (self._queue.length > 0 && !self._isPause) {
            log.info({
                queue_length: self._queue.length,
                paused: self._isPause
            }, 'more elements in the queue, continuing exec');
            exec(self);

        } else {
            log.info({
                queue_length: self._queue.length,
                paused: self._isPause
            }, 'no more elements in queue or queue paused.');
            self._isExec = false;
        }
    });

}

module.exports = TransitionQueue;
util.inherits(TransitionQueue, EventEmitter);

TransitionQueue.prototype.push = function push(req) {
    var self = this;
    var log = self._log;

    self._log.info({
        isPaused: self._isPause,
        isExec: self._isExec,
        queueLength: self._queue.length,
        req: req.transition
    }, 'TransitionQueue.push: entering');

    if (self._isPause) {
        log.info({req: req.transition},
            'TransitionQueue.push: queue paused, dropping request');
        return;
    }
    log.info({
        req: req.transition
    }, 'pushing request');
    self._queue.push(req);
    self._emitter.emit('push');
};

TransitionQueue.prototype.pause = function pause() {
    var self = this;
    self._log.info({
        isPaused: self._isPause,
        isExec: self._isExec,
        queueLength: self._queue.length
    }, 'TransitionQueue.pause: entering');
    self._isPause = true;
};

TransitionQueue.prototype.clear = function clear() {
    var self = this;
    self._log.info({
        isPaused: self._isPause,
        isExec: self._isExec,
        queueLength: self._queue.length
    }, 'TransitionQueue.clear: entering');
    self._queue = [];
};

TransitionQueue.prototype.resume = function resume() {
    var self = this;
    self._log.info({
        isPaused: self._isPause,
        isExec: self._isExec,
        queueLength: self._queue.length
    }, 'TransitionQueue.resume: entering');
    self._isPause = false;
    exec(self);
};
<commit_msg>set isExec flag to false when executing more requests to prevent deadlock<commit_after>/*
 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
 *
 *                   _.---.._
 *      _        _.-' \  \    ''-.
 *    .'  '-,_.-'   /  /  /       '''.
 *   (       _                     o  :
 *    '._ .-'  '-._         \  \-  ---]
 *                  '-.___.-')  )..-'
 *                           (_/
 *
 */
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var verror = require('verror');

/**
 * Queue used to serialize state transitions
 */
function TransitionQueue(options) {
    EventEmitter.call(this);
    var self = this;
    this._queue = [];
    this._log = options.log;
    this._emitter = new EventEmitter();

    this._isPause = false; /* lock used to pause the queue */
    this._isExec = false; /* lock used to ensure serial execution */
    this._req = null; /* the currently executing request */

    var log = self._log;
    self._emitter.on('push', function () {
        if (self._isExec) {
            log.info({
                queue_length: self._queue.length,
                curr_req: self._req.transition,
                new_req: self._queue[self._queue.length - 1].transition
            }, 'waiting for current transition to finish before ' +
            'executing pushed req');
            return;
        } else {
            exec(self);
        }
    });
}

function exec(self) {
    var log = self._log;
    if (self._isExec) {
        log.info('TransitionQueue.exec: already executing other req, exiting');
        return;
    }
    self._isExec = true;
    var req = self._queue.shift();
    self._req = req;
    if (!req) {
        log.info('TransitionQueue.exec: no request, exiting');
        self._isExec = false;
        return;
    }

    req.invoke(req.ctx, function (err) {
        log.info({
            transition: req.transition,
            err: err
        }, 'finished transition');
        if (err) {
            self.emit('execError',
                new verror.VError(err, 'transition queue exec error'));
        }
        if (self._queue.length > 0 && !self._isPause) {
            log.info({
                queue_length: self._queue.length,
                paused: self._isPause
            }, 'more elements in the queue, continuing exec');
            self._isExec = false;
            exec(self);

        } else {
            log.info({
                queue_length: self._queue.length,
                paused: self._isPause
            }, 'no more elements in queue or queue paused.');
            self._isExec = false;
        }
    });

}

module.exports = TransitionQueue;
util.inherits(TransitionQueue, EventEmitter);

TransitionQueue.prototype.push = function push(req) {
    var self = this;
    var log = self._log;

    self._log.info({
        isPaused: self._isPause,
        isExec: self._isExec,
        queueLength: self._queue.length,
        req: req.transition
    }, 'TransitionQueue.push: entering');

    if (self._isPause) {
        log.info({req: req.transition},
            'TransitionQueue.push: queue paused, dropping request');
        return;
    }
    log.info({
        req: req.transition
    }, 'pushing request');
    self._queue.push(req);
    self._emitter.emit('push');
};

TransitionQueue.prototype.pause = function pause() {
    var self = this;
    self._log.info({
        isPaused: self._isPause,
        isExec: self._isExec,
        queueLength: self._queue.length
    }, 'TransitionQueue.pause: entering');
    self._isPause = true;
};

TransitionQueue.prototype.clear = function clear() {
    var self = this;
    self._log.info({
        isPaused: self._isPause,
        isExec: self._isExec,
        queueLength: self._queue.length
    }, 'TransitionQueue.clear: entering');
    self._queue = [];
};

TransitionQueue.prototype.resume = function resume() {
    var self = this;
    self._log.info({
        isPaused: self._isPause,
        isExec: self._isExec,
        queueLength: self._queue.length
    }, 'TransitionQueue.resume: entering');
    self._isPause = false;
    exec(self);
};
<|endoftext|>


<commit_before>/**
 * @file textUnMute command
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license MIT
 */

exports.exec = async (Bastion, message, args) => {
  try {
    let user = message.mentions.users.first();
    if (!user) {
      /**
      * The command was ran with invalid parameters.
      * @fires commandUsage
      */
      return Bastion.emit('commandUsage', message, this.help);
    }

    let member = await message.guild.fetchMember(user.id);
    if (message.author.id !== message.guild.ownerID && message.member.highestRole.comparePositionTo(member.highestRole) <= 0) return Bastion.log.info(Bastion.strings.error(message.guild.language, 'lowerRole', true));

    let permissionOverwrites = message.channel.permissionOverwrites.get(user.id);
    if (permissionOverwrites) {
      await permissionOverwrites.delete();

      let reason = args.slice(1).join(' ');
      if (reason.length < 1) {
        reason = 'No reason given';
      }

      message.channel.send({
        embed: {
          color: Bastion.colors.GREEN,
          title: 'Text unmuted',
          fields: [
            {
              name: 'User',
              value: user.tag,
              inline: true
            },
            {
              name: 'ID',
              value: user.id,
              inline: true
            },
            {
              name: 'Reason',
              value: reason,
              inline: false
            }
          ]
        }
      }).catch(e => {
        Bastion.log.error(e);
      });

      /**
      * Logs moderation events if it is enabled
      * @fires moderationLog
      */
      Bastion.emit('moderationLog', message.guild, message.author, this.help.name, user, reason, {
        channel: message.channel
      });
    }
  }
  catch (e) {
    Bastion.log.error(e);
  }
};

exports.config = {
  aliases: [ 'tum' ],
  enabled: true
};

exports.help = {
  name: 'textUnMute',
  botPermission: 'MANAGE_ROLES',
  userTextPermission: 'MANAGE_ROLES',
  userVoicePermission: '',
  usage: 'textUnMute @user-mention [Reason]',
  example: [ 'textUnMute @user#0001 Reason for the unmute.' ]
};
<commit_msg>Simplified output message - textUnMute command<commit_after>/**
 * @file textUnMute command
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license MIT
 */

exports.exec = async (Bastion, message, args) => {
  try {
    let user = message.mentions.users.first();
    if (!user) {
      /**
      * The command was ran with invalid parameters.
      * @fires commandUsage
      */
      return Bastion.emit('commandUsage', message, this.help);
    }

    let member = await message.guild.fetchMember(user.id);
    if (message.author.id !== message.guild.ownerID && message.member.highestRole.comparePositionTo(member.highestRole) <= 0) return Bastion.log.info(Bastion.strings.error(message.guild.language, 'lowerRole', true));

    let permissionOverwrites = message.channel.permissionOverwrites.get(user.id);
    if (permissionOverwrites) {
      await permissionOverwrites.delete();

      let reason = args.slice(1).join(' ');
      if (reason.length < 1) {
        reason = 'No reason given';
      }

      message.channel.send({
        embed: {
          color: Bastion.colors.GREEN,
          description: `${message.author.tag} text-unmuted ${user.tag} with reason **${reason}**`
        }
      }).catch(e => {
        Bastion.log.error(e);
      });

      /**
      * Logs moderation events if it is enabled
      * @fires moderationLog
      */
      Bastion.emit('moderationLog', message.guild, message.author, this.help.name, user, reason, {
        channel: message.channel
      });
    }
  }
  catch (e) {
    Bastion.log.error(e);
  }
};

exports.config = {
  aliases: [ 'tum' ],
  enabled: true
};

exports.help = {
  name: 'textUnMute',
  botPermission: 'MANAGE_ROLES',
  userTextPermission: 'MANAGE_ROLES',
  userVoicePermission: '',
  usage: 'textUnMute @user-mention [Reason]',
  example: [ 'textUnMute @user#0001 Reason for the unmute.' ]
};
<|endoftext|>


<commit_before>var React = require('react/addons'),
	classnames = require('classnames'),
	Tappable = require('react-tappable'),
	Navigation = require('../mixins/Navigation');

module.exports = React.createClass({
	displayName: 'KeypadButton',
	mixins: [Navigation],
	propTypes: {
		action: React.PropTypes.func,
		aux: React.PropTypes.bool,
		className: React.PropTypes.string,
		delete: React.PropTypes.bool,
		disabled: React.PropTypes.bool,
		primaryLabel: React.PropTypes.string,
		secondaryLabel: React.PropTypes.string,
		value: React.PropTypes.string
	},
	getDefaultProps: function() {
		return {
			action: function() {},
			className: '',
			secondaryLabel: ''
		};
	},
	render: function() {

		var className = classnames({
			'Keypad-button': true,
			'is-auxiliary': this.props.aux || this.props.delete,
			'disabled': this.props.disabled
		});

		var primaryLabel = this.props.primaryLabel ?
{this.props.primaryLabel}
 : null;
		var secondaryLabel = this.props.secondaryLabel ?
{this.props.secondaryLabel}
 : null;
		var icon = this.props.icon ?  : null;

		return (

				<Tappable onTap={this.props.action} className={className} component="div">
					{icon}
					{primaryLabel}
					{secondaryLabel}
				</Tappable>

		);
	}
});
<commit_msg>KeypadButton: remove unused navigation mixin<commit_after>var React = require('react/addons'),
	classnames = require('classnames'),
	Tappable = require('react-tappable')

module.exports = React.createClass({
	displayName: 'KeypadButton',
	propTypes: {
		action: React.PropTypes.func,
		aux: React.PropTypes.bool,
		className: React.PropTypes.string,
		delete: React.PropTypes.bool,
		disabled: React.PropTypes.bool,
		primaryLabel: React.PropTypes.string,
		secondaryLabel: React.PropTypes.string,
		value: React.PropTypes.string
	},
	getDefaultProps: function() {
		return {
			action: function() {},
			className: '',
			secondaryLabel: ''
		};
	},
	render: function() {

		var className = classnames({
			'Keypad-button': true,
			'is-auxiliary': this.props.aux || this.props.delete,
			'disabled': this.props.disabled
		});

		var primaryLabel = this.props.primaryLabel ?
{this.props.primaryLabel}
 : null;
		var secondaryLabel = this.props.secondaryLabel ?
{this.props.secondaryLabel}
 : null;
		var icon = this.props.icon ?  : null;

		return (

				<Tappable onTap={this.props.action} className={className} component="div">
					{icon}
					{primaryLabel}
					{secondaryLabel}
				</Tappable>

		);
	}
});
<|endoftext|>


<commit_before>'use babel'

const Interact = require('interact.js')
let Clipboard
try {
  Clipboard = require('electron').clipboard
} catch (_) {
  Clipboard = require('clipboard')
}
import {CompositeDisposable} from 'atom'
import {Message} from './message-element'

export default class BottomPanel {
  constructor(scope) {
    this.subscriptions = new CompositeDisposable

    this.visibility = false
    this.visibleMessages = 0
    this.alwaysTakeMinimumSpace = atom.config.get('linter.alwaysTakeMinimumSpace')
    this.errorPanelHeight = atom.config.get('linter.errorPanelHeight')
    this.configVisibility = atom.config.get('linter.showErrorPanel')
    this.scope = scope
    this.editorMessages = new Map()
    this.messages = new Map()

    const element = document.createElement('linter-panel') // TODO(steelbrain): Make this a `div`
    element.tabIndex = '-1'
    this.messagesElement = document.createElement('div')
    element.appendChild(this.messagesElement)
    this.panel = atom.workspace.addBottomPanel({item: element, visible: false, priority: 500})
    Interact(element).resizable({edges: {top: true}})
      .on('resizemove', event => {
        event.target.style.height = `${event.rect.height}px`
      })
      .on('resizeend', event => {
        atom.config.set('linter.errorPanelHeight', event.target.clientHeight)
      })
    element.addEventListener('keydown', function(e) {
      if (e.which === 67 && e.ctrlKey) {
        Clipboard.writeText(getSelection().toString())
      }
    })

    this.subscriptions.add(atom.config.onDidChange('linter.alwaysTakeMinimumSpace', ({newValue}) => {
      this.alwaysTakeMinimumSpace = newValue
      this.updateHeight()
    }))

    this.subscriptions.add(atom.config.onDidChange('linter.errorPanelHeight', ({newValue}) => {
      this.errorPanelHeight = newValue
      this.updateHeight()
    }))

    this.subscriptions.add(atom.config.onDidChange('linter.showErrorPanel', ({newValue}) => {
      this.configVisibility = newValue
      this.updateVisibility()
    }))

    this.subscriptions.add(atom.workspace.observeActivePaneItem(paneItem => {
      this.paneVisibility = paneItem === atom.workspace.getActiveTextEditor()
      this.updateVisibility()
    }))

    // Container for messages with no filePath
    const defaultContainer = document.createElement('div')
    this.editorMessages.set(null, defaultContainer)
    this.messagesElement.appendChild(defaultContainer)
    if (scope !== 'Project') {
      defaultContainer.setAttribute('hidden', true)
    }
  }
  setMessages({added, removed}) {
    if (removed.length) {
      this.removeMessages(removed)
    }
    if (added.length) {
      let activeFile = atom.workspace.getActiveTextEditor()
      activeFile = activeFile ? activeFile.getPath() : undefined
      added.forEach(message => {
        if (!this.editorMessages.has(message.filePath)) {
          const container = document.createElement('div')
          this.editorMessages.set(message.filePath, container)
          this.messagesElement.appendChild(container)
          if (!(this.scope === 'Project' || activeFile === message.filePath)) {
            container.setAttribute('hidden', true)
          }
        }
        const messageElement = Message.fromMessage(message)
        this.messages.set(message, messageElement)
        this.editorMessages.get(message.filePath).appendChild(messageElement)
        if (messageElement.updateVisibility(this.scope).visibility) {
          this.visibleMessages++
        }
      })
    }

    this.editorMessages.forEach((child, key) => {
      // Never delete the default container
      if (key !== null && !child.childNodes.length) {
        child.remove()
        this.editorMessages.delete(key)
      }
    })

    this.updateVisibility()
  }
  removeMessages(messages) {
    messages.forEach(message => {
      const messageElement = this.messages.get(message)
      this.messages.delete(message)
      messageElement.remove()
      if (messageElement.visibility) {
        this.visibleMessages--
      }
    })
  }
  refresh(scope) {
    if (scope) {
      this.scope = scope
    } else scope = this.scope
    this.visibleMessages = 0

    this.messages.forEach(messageElement => {
      if (messageElement.updateVisibility(scope).visibility && scope === 'Line') {
        this.visibleMessages++
      }
    })

    if (scope === 'File') {
      let activeFile = atom.workspace.getActiveTextEditor()
      activeFile = activeFile ? activeFile.getPath() : undefined
      this.editorMessages.forEach((messagesElement, filePath) => {
        if (filePath === activeFile) {
          messagesElement.removeAttribute('hidden')
          this.visibleMessages = messagesElement.childNodes.length
        } else messagesElement.setAttribute('hidden', true)
      })
    } else if (scope === 'Project') {
      this.visibleMessages = this.messages.size
      this.editorMessages.forEach(messageElement => {
        messageElement.removeAttribute('hidden')
      })
    }

    this.updateVisibility()
  }
  updateHeight() {
    let height = this.errorPanelHeight

    if (this.alwaysTakeMinimumSpace) {
      // Add `1px` for the top border.
      height = Math.min(this.messagesElement.clientHeight + 1, height)
    }

    this.messagesElement.parentNode.style.height = `${height}px`
  }
  getVisibility() {
    return this.visibility
  }
  updateVisibility() {
    this.visibility = this.configVisibility && this.paneVisibility && this.visibleMessages > 0

    if (this.visibility) {
      this.panel.show()
      this.updateHeight()
    } else {
      this.panel.hide()
    }
  }
  dispose() {
    this.subscriptions.dispose()
    this.messages.clear()
    try {
      this.panel.destroy()
    } catch (err) {
      // Atom fails weirdly sometimes when doing this
    }
  }
}
<commit_msg>:new: Use Atom clipboard API<commit_after>'use babel'

const Interact = require('interact.js')
import {CompositeDisposable} from 'atom'
import {Message} from './message-element'

export default class BottomPanel {
  constructor(scope) {
    this.subscriptions = new CompositeDisposable

    this.visibility = false
    this.visibleMessages = 0
    this.alwaysTakeMinimumSpace = atom.config.get('linter.alwaysTakeMinimumSpace')
    this.errorPanelHeight = atom.config.get('linter.errorPanelHeight')
    this.configVisibility = atom.config.get('linter.showErrorPanel')
    this.scope = scope
    this.editorMessages = new Map()
    this.messages = new Map()

    const element = document.createElement('linter-panel') // TODO(steelbrain): Make this a `div`
    element.tabIndex = '-1'
    this.messagesElement = document.createElement('div')
    element.appendChild(this.messagesElement)
    this.panel = atom.workspace.addBottomPanel({item: element, visible: false, priority: 500})
    Interact(element).resizable({edges: {top: true}})
      .on('resizemove', event => {
        event.target.style.height = `${event.rect.height}px`
      })
      .on('resizeend', event => {
        atom.config.set('linter.errorPanelHeight', event.target.clientHeight)
      })
    element.addEventListener('keydown', function(e) {
      if (e.which === 67 && e.ctrlKey) {
        atom.clipboard.write(getSelection().toString())
      }
    })

    this.subscriptions.add(atom.config.onDidChange('linter.alwaysTakeMinimumSpace', ({newValue}) => {
      this.alwaysTakeMinimumSpace = newValue
      this.updateHeight()
    }))

    this.subscriptions.add(atom.config.onDidChange('linter.errorPanelHeight', ({newValue}) => {
      this.errorPanelHeight = newValue
      this.updateHeight()
    }))

    this.subscriptions.add(atom.config.onDidChange('linter.showErrorPanel', ({newValue}) => {
      this.configVisibility = newValue
      this.updateVisibility()
    }))

    this.subscriptions.add(atom.workspace.observeActivePaneItem(paneItem => {
      this.paneVisibility = paneItem === atom.workspace.getActiveTextEditor()
      this.updateVisibility()
    }))

    // Container for messages with no filePath
    const defaultContainer = document.createElement('div')
    this.editorMessages.set(null, defaultContainer)
    this.messagesElement.appendChild(defaultContainer)
    if (scope !== 'Project') {
      defaultContainer.setAttribute('hidden', true)
    }
  }
  setMessages({added, removed}) {
    if (removed.length) {
      this.removeMessages(removed)
    }
    if (added.length) {
      let activeFile = atom.workspace.getActiveTextEditor()
      activeFile = activeFile ? activeFile.getPath() : undefined
      added.forEach(message => {
        if (!this.editorMessages.has(message.filePath)) {
          const container = document.createElement('div')
          this.editorMessages.set(message.filePath, container)
          this.messagesElement.appendChild(container)
          if (!(this.scope === 'Project' || activeFile === message.filePath)) {
            container.setAttribute('hidden', true)
          }
        }
        const messageElement = Message.fromMessage(message)
        this.messages.set(message, messageElement)
        this.editorMessages.get(message.filePath).appendChild(messageElement)
        if (messageElement.updateVisibility(this.scope).visibility) {
          this.visibleMessages++
        }
      })
    }

    this.editorMessages.forEach((child, key) => {
      // Never delete the default container
      if (key !== null && !child.childNodes.length) {
        child.remove()
        this.editorMessages.delete(key)
      }
    })

    this.updateVisibility()
  }
  removeMessages(messages) {
    messages.forEach(message => {
      const messageElement = this.messages.get(message)
      this.messages.delete(message)
      messageElement.remove()
      if (messageElement.visibility) {
        this.visibleMessages--
      }
    })
  }
  refresh(scope) {
    if (scope) {
      this.scope = scope
    } else scope = this.scope
    this.visibleMessages = 0

    this.messages.forEach(messageElement => {
      if (messageElement.updateVisibility(scope).visibility && scope === 'Line') {
        this.visibleMessages++
      }
    })

    if (scope === 'File') {
      let activeFile = atom.workspace.getActiveTextEditor()
      activeFile = activeFile ? activeFile.getPath() : undefined
      this.editorMessages.forEach((messagesElement, filePath) => {
        if (filePath === activeFile) {
          messagesElement.removeAttribute('hidden')
          this.visibleMessages = messagesElement.childNodes.length
        } else messagesElement.setAttribute('hidden', true)
      })
    } else if (scope === 'Project') {
      this.visibleMessages = this.messages.size
      this.editorMessages.forEach(messageElement => {
        messageElement.removeAttribute('hidden')
      })
    }

    this.updateVisibility()
  }
  updateHeight() {
    let height = this.errorPanelHeight

    if (this.alwaysTakeMinimumSpace) {
      // Add `1px` for the top border.
      height = Math.min(this.messagesElement.clientHeight + 1, height)
    }

    this.messagesElement.parentNode.style.height = `${height}px`
  }
  getVisibility() {
    return this.visibility
  }
  updateVisibility() {
    this.visibility = this.configVisibility && this.paneVisibility && this.visibleMessages > 0

    if (this.visibility) {
      this.panel.show()
      this.updateHeight()
    } else {
      this.panel.hide()
    }
  }
  dispose() {
    this.subscriptions.dispose()
    this.messages.clear()
    try {
      this.panel.destroy()
    } catch (err) {
      // Atom fails weirdly sometimes when doing this
    }
  }
}
<|endoftext|>


<commit_before>var path                = require("path");
var _                   = require("lodash");
var webpack             = require("webpack");
var ExtractTextPlugin   = require("extract-text-webpack-plugin");
var CompileConcatPlugin = require("./webpack.compile-concat-plugin");

let headerSassExtractTextPlugin   = new ExtractTextPlugin(1, "header.scss", {allChunks: true});
let footerSassExtractTextPlugin   = new ExtractTextPlugin(2, "footer.scss", {allChunks: true});
let externalSassExtractTextPlugin = new ExtractTextPlugin(3, "modules.scss", {allChunks: true});

module.exports = makeConfig;

var baseConfig = {
  output: {
    filename: "[name].bundle.js"
  },
  resolve: {
    root: [process.cwd()],
    extensions: ["", ".js", ".es6", ".json"],
    modulesDirectories: [
      "node_modules/interstellar-core/node_modules",
      "node_modules"
    ],
    fallback: [
      path.join(process.cwd(), "node_modules"),
      path.join(process.cwd(), "node_modules", "interstellar-core", "node_modules")
    ]
  },
  resolveLoader: {
    root: path.join(__dirname, "..", "node_modules")
  },
  module: {
    loaders: [
      {
        test: /\.es6$/,
        loader: 'babel-loader?stage=1'
      },
      {
        test: /\.json$/,
        loader: 'json'
      },
      {
        test: /\.header\.scss$/,
        loader: headerSassExtractTextPlugin.extract("raw"),
        include: path.resolve(process.cwd(), "styles")
      },
      {
        test: /\.footer\.scss$/,
        loader: footerSassExtractTextPlugin.extract("raw"),
        include: path.resolve(process.cwd(), "styles")
      },
      {
        test: /\.scss$/,
        loader: externalSassExtractTextPlugin.extract("raw"),
        exclude: path.resolve(process.cwd(), "styles")
      }
    ]
  },
  plugins: [
    // Ignore native modules (ex. ed25519)
    new webpack.IgnorePlugin(/\.node/),
    headerSassExtractTextPlugin,
    footerSassExtractTextPlugin,
    externalSassExtractTextPlugin,
    new CompileConcatPlugin([
      path.resolve(process.cwd(), '.tmp/webpacked/header.scss'),
      path.resolve(process.cwd(), '.tmp/webpacked/modules.scss'),
      path.resolve(process.cwd(), '.tmp/webpacked/footer.scss')
    ], path.resolve(process.cwd(), '.tmp/webpacked/main.css')),
    new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.bundle.js")

  ]
};

var configForApp = function() {
  return {
    entry: {
      main: "./main.es6",
      head: "./head.es6",
      vendor: ["interstellar-core"]
    },
    output: {
      path: './.tmp/webpacked'
    }
  };
};

var environments = {
  dev: {
    devtool: "eval",
    noInfo: true
  },
  tst: {
    devtool: "inline-source-map"
  },
  stg: {
    devtool: "source-map"
  },
  prd: {
    devtool: "source-map",
    plugins: [
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.OccurenceOrderPlugin(),
      new webpack.optimize.UglifyJsPlugin({
        // TODO investigate more to make this option don't break Angular DI
        mangle: false
      })
    ]
  }
};

function makeConfig(env, options) {
  var result = {};

  merge(result, baseConfig);

  if(env) {
    merge(result, environments[env]);
  }

  merge(result, configForApp());
  merge(result, options || {});

  return result;
}

// Does a simple deep merge using lodash
function merge(object, source) {
  return _.merge(object, source, function(a, b) {
    return _.isArray(a) ? a.concat(b) : undefined;
  });
}
<commit_msg>INTERSTELLAR_ENV variable<commit_after>var path                = require("path");
var _                   = require("lodash");
var webpack             = require("webpack");
var ExtractTextPlugin   = require("extract-text-webpack-plugin");
var CompileConcatPlugin = require("./webpack.compile-concat-plugin");

let headerSassExtractTextPlugin   = new ExtractTextPlugin(1, "header.scss", {allChunks: true});
let footerSassExtractTextPlugin   = new ExtractTextPlugin(2, "footer.scss", {allChunks: true});
let externalSassExtractTextPlugin = new ExtractTextPlugin(3, "modules.scss", {allChunks: true});

module.exports = makeConfig;

var baseConfig = {
  output: {
    filename: "[name].bundle.js"
  },
  resolve: {
    root: [process.cwd()],
    extensions: ["", ".js", ".es6", ".json"],
    modulesDirectories: [
      "node_modules/interstellar-core/node_modules",
      "node_modules"
    ],
    fallback: [
      path.join(process.cwd(), "node_modules"),
      path.join(process.cwd(), "node_modules", "interstellar-core", "node_modules")
    ]
  },
  resolveLoader: {
    root: path.join(__dirname, "..", "node_modules")
  },
  module: {
    loaders: [
      {
        test: /\.es6$/,
        loader: 'babel-loader?stage=1'
      },
      {
        test: /\.json$/,
        loader: 'json'
      },
      {
        test: /\.header\.scss$/,
        loader: headerSassExtractTextPlugin.extract("raw"),
        include: path.resolve(process.cwd(), "styles")
      },
      {
        test: /\.footer\.scss$/,
        loader: footerSassExtractTextPlugin.extract("raw"),
        include: path.resolve(process.cwd(), "styles")
      },
      {
        test: /\.scss$/,
        loader: externalSassExtractTextPlugin.extract("raw"),
        exclude: path.resolve(process.cwd(), "styles")
      }
    ]
  },
  plugins: [
    // Ignore native modules (ex. ed25519)
    new webpack.IgnorePlugin(/\.node/),
    headerSassExtractTextPlugin,
    footerSassExtractTextPlugin,
    externalSassExtractTextPlugin,
    new CompileConcatPlugin([
      path.resolve(process.cwd(), '.tmp/webpacked/header.scss'),
      path.resolve(process.cwd(), '.tmp/webpacked/modules.scss'),
      path.resolve(process.cwd(), '.tmp/webpacked/footer.scss')
    ], path.resolve(process.cwd(), '.tmp/webpacked/main.css')),
    new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.bundle.js")
  ]
};

var configForApp = function() {
  return {
    entry: {
      main: "./main.es6",
      head: "./head.es6",
      vendor: ["interstellar-core"]
    },
    output: {
      path: './.tmp/webpacked'
    }
  };
};

var environments = {
  dev: {
    devtool: "eval",
    noInfo: true
  },
  tst: {
    devtool: "inline-source-map"
  },
  stg: {
    devtool: "source-map"
  },
  prd: {
    devtool: "source-map",
    plugins: [
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.OccurenceOrderPlugin(),
      new webpack.optimize.UglifyJsPlugin({
        // TODO investigate more to make this option don't break Angular DI
        mangle: false
      })
    ]
  }
};

function makeConfig(env, options) {
  var result = {};

  merge(result, baseConfig);

  if(env) {
    merge(result, environments[env]);
  }

  merge(result, configForApp());
  merge(result, options || {});

  result.plugins.push(new webpack.DefinePlugin({
    INTERSTELLAR_ENV: JSON.stringify(env)
  }));

  return result;
}

// Does a simple deep merge using lodash
function merge(object, source) {
  return _.merge(object, source, function(a, b) {
    return _.isArray(a) ? a.concat(b) : undefined;
  });
}
<|endoftext|>


<commit_before>var logger      = require("../util/Logger.js").getLogger()
var DBHelper    = require("../database/Helper.js").DBHelper

var bcrypt          = require("bcrypt")
var passport        = require('passport')
var LocalStrategy   = require('passport-local').Strategy

passport.use(new LocalStrategy(
    function(login, password, done) {

        process.nextTick(function () {

            DBHelper.User.findOne({login: login}, function (err, admin) {

                if (err) {
                    return done(err)
                }

                if (!admin) {
                    return done(null, false, {message: 'Unknown user'})
                }

                bcrypt.compare(password, admin.password, function(err, res) {
                    if(err) {
                        return done(err)
                    }
                    if(!res) {
                        return done(null, false, {message: 'Invalid password'})
                    }
                    return done(null, admin)
                })
            })
        })
    }

))

passport.serializeUser(function(user, done) {
    done(null, user.login)
})

passport.deserializeUser(function(login, done) {
    DBHelper.User.findOne({login: login}, function (err, user) {
        done(err, user)
    })
})

function UsersService(app) {

    return function() {

        /**
         * Login
         */
        app.post('/login', function(req, res, next) {
            passport.authenticate('local', function(err, user, info) {
                if (err) {
                    return next(err)
                }
                if (!user) {
                    if(info.message = 'Invalid password') {
                        var ip = req.ip
                        var ips = req.ips.length>0 ? req.ips : undefined
                        var ipsList = ''
                        if(ips) {
                            ipsList = '(' + ips.join('; ') + ')'
                        }
                        logger.warn('Authentication as [' + req.body.login + '] failed from ip: ' + ip + ipsList)
                    }
                    return res.redirect('/admin')
                }
                req.logIn(user, function(err) {
                    if (err) {
                        return next(err)
                    }
                    return res.redirect('/admin')
                })
            })(req, res, next)
        })

        /**
         * To know if this is the first login or if the user is authenticated
         */
        app.get("/status", function(req, res) {

            var status = {}

            if(req.user) {
                status.isAuthenticated = true
                return res.send(status)
            }

            DBHelper.User.find({}, function(err, users) {

                if(err) {
                    return res.error(err)
                }

                status.isFirstLogin = users.length === 0
                res.send(status)

            })
        })

        /**
         * Logout
         */
        app.get('/logout', function(req, res){
            req.logOut()
            res.redirect('/')
        })

        /**
         * Return a user
         */
        app.get("/user/:login", function(req, res) {

            var login = req.param("login")

            DBHelper.User.findOne({login: login}, function(err, user) {
                if(err) {
                    res.error(err)
                } else {
                    res.send(user)
                }
            })
        })

        /**
         * Return every users
         */
        app.get("/getUsers", function(req, res) {

            DBHelper.User.find({}, {sort: [['login','asc']]}, function(err, user) {
                if(err) {
                    res.error(err)
                } else {
                    res.send(user)
                }
            })
        })

        /**
         * Search for users
         */
        app.post("/search", function(req, res) {

            var login = req.body.login

            var query = {login: {$regex : login, $options: 'i'}}

            DBHelper.User.find(query, function(err, users) {
                if(err) {
                    res.error(err)
                } else {
                    res.send(users)
                }
            })
        })

    }
}

module.exports = UsersService<commit_msg>reverted previous "delete obsolete user WS"<commit_after>var logger      = require("../util/Logger.js").getLogger()
var DBHelper    = require("../database/Helper.js").DBHelper

var bcrypt          = require("bcrypt")
var passport        = require('passport')
var LocalStrategy   = require('passport-local').Strategy

passport.use(new LocalStrategy(
    function(login, password, done) {

        process.nextTick(function () {

            DBHelper.User.findOne({login: login}, function (err, admin) {

                if (err) {
                    return done(err)
                }

                if (!admin) {
                    return done(null, false, {message: 'Unknown user'})
                }

                bcrypt.compare(password, admin.password, function(err, res) {
                    if(err) {
                        return done(err)
                    }
                    if(!res) {
                        return done(null, false, {message: 'Invalid password'})
                    }
                    return done(null, admin)
                })
            })
        })
    }

))

passport.serializeUser(function(user, done) {
    done(null, user.login)
})

passport.deserializeUser(function(login, done) {
    DBHelper.User.findOne({login: login}, function (err, user) {
        done(err, user)
    })
})

function UsersService(app) {

    return function() {

        /**
         * Create a new user
         */
        app.post("/", function(req, res) {

            var user = req.body

            DBHelper.User.find({}, function(err, users) {
                if(err) {
                    return res.error(err)
                }
                if(users.length === 0 || req.isAuthenticated()) {
                    if(user && user.name && user.pass1 && user.pass2) {
                        if(user.pass1.length >= 4 && user.pass1 === user.pass2) {

                            bcrypt.genSalt(10, function(err, salt) {
                                bcrypt.hash(user.pass1, salt, function(err, hash) {

                                    var newUser = {
                                        login       : user.name,
                                        password    : hash
                                    }

                                    DBHelper.User.save(newUser, function(err, savedUser) {
                                        if(err) {
                                            return res.error(err)
                                        }
                                        if(req.user) {
                                            res.redirect('/admin')
                                        } else {
                                            res.redirect('/')
                                        }
                                    })
                                })
                            })
                        } else {
                            res.error(new Error("Passwords mismatch"))
                        }
                    } else {
                        res.error(new Error("Incomplete data"))
                    }
                } else {
                    res.error(new Error("Unauthorized request"), 401)
                }
            })

        })

        /**
         * Login
         */
        app.post('/login', function(req, res, next) {
            passport.authenticate('local', function(err, user, info) {
                if (err) {
                    return next(err)
                }
                if (!user) {
                    if(info.message = 'Invalid password') {
                        var ip = req.ip
                        var ips = req.ips.length>0 ? req.ips : undefined
                        var ipsList = ''
                        if(ips) {
                            ipsList = '(' + ips.join('; ') + ')'
                        }
                        logger.warn('Authentication as [' + req.body.login + '] failed from ip: ' + ip + ipsList)
                    }
                    return res.redirect('/admin')
                }
                req.logIn(user, function(err) {
                    if (err) {
                        return next(err)
                    }
                    return res.redirect('/admin')
                })
            })(req, res, next)
        })

        /**
         * To know if this is the first login or if the user is authenticated
         */
        app.get("/status", function(req, res) {

            var status = {}

            if(req.user) {
                status.isAuthenticated = true
                return res.send(status)
            }

            DBHelper.User.find({}, function(err, users) {

                if(err) {
                    return res.error(err)
                }

                status.isFirstLogin = users.length === 0
                res.send(status)

            })
        })

        /**
         * Logout
         */
        app.get('/logout', function(req, res){
            req.logOut()
            res.redirect('/')
        })

        /**
         * Return a user
         */
        app.get("/user/:login", function(req, res) {

            var login = req.param("login")

            DBHelper.User.findOne({login: login}, function(err, user) {
                if(err) {
                    res.error(err)
                } else {
                    res.send(user)
                }
            })
        })

        /**
         * Return every users
         */
        app.get("/getUsers", function(req, res) {

            DBHelper.User.find({}, {sort: [['login','asc']]}, function(err, user) {
                if(err) {
                    res.error(err)
                } else {
                    res.send(user)
                }
            })
        })

        /**
         * Search for users
         */
        app.post("/search", function(req, res) {

            var login = req.body.login

            var query = {login: {$regex : login, $options: 'i'}}

            DBHelper.User.find(query, function(err, users) {
                if(err) {
                    res.error(err)
                } else {
                    res.send(users)
                }
            })
        })

    }
}

module.exports = UsersService<|endoftext|>


<commit_before>import DiffMatchPatch from 'diff-match-patch';
import TextPositionAnchor from 'dom-anchor-text-position';

// The DiffMatchPatch bitap has a hard 32-character pattern length limit.
const CONTEXT_LENGTH = 32;

export default class TextQuoteAnchor {
  constructor(root, exact, context = {}) {
    if (root === undefined) {
      throw new Error('missing required parameter "root"');
    }
    if (exact === undefined) {
      throw new Error('missing required parameter "exact"');
    }
    this.root = root;
    this.exact = exact;
    this.prefix = context.prefix;
    this.suffix = context.suffix;
  }

  static fromRange(root, range) {
    if (range === undefined) {
      throw new Error('missing required parameter "range"');
    }

    let position = TextPositionAnchor.fromRange(root, range);
    return this.fromPositionAnchor(position);
  }

  static fromSelector(root, selector = {}) {
    return new TextQuoteAnchor(root, selector.exact, selector);
  }

  static fromPositionAnchor(anchor) {
    let root = anchor.root;

    let {start, end} = anchor;
    let exact = root.textContent.substr(start, end - start);

    let prefixStart = Math.max(0, start - CONTEXT_LENGTH);
    let prefix = root.textContent.substr(prefixStart, start - prefixStart);

    let suffixEnd = Math.min(root.textContent.length, end + CONTEXT_LENGTH);
    let suffix = root.textContent.substr(end, suffixEnd - end);

    return new TextQuoteAnchor(root, exact, {prefix, suffix});
  }

  toRange(options) {
    return this.toPositionAnchor(options).toRange();
  }

  toSelector() {
    let selector = {
      type: 'TextQuoteSelector',
      exact: this.exact,
    };
    if (this.prefix !== undefined) selector.prefix = this.prefix;
    if (this.suffix !== undefined) selector.suffix = this.suffix;
    return selector;
  }

  toPositionAnchor(options = {}) {
    let {hint} = options;
    let root = this.root;
    let dmp = new DiffMatchPatch();

    dmp.Match_Distance = root.textContent.length * 2;

    // Work around a hard limit of the DiffMatchPatch bitap implementation.
    // The search pattern must be no more than 32 characters.
    let slices = this.exact.match(/(.|[\r\n]){1,32}/g);
    let loc = (hint === undefined) ? ((root.textContent.length / 2) | 0) : hint;
    let start = -1;
    let end = -1;

    // If the prefix is known then search for that first.
    if (this.prefix !== undefined) {
      let result = dmp.match_main(root.textContent, this.prefix, loc);
      if (result > -1) loc = end = start = result + this.prefix.length;
    }

    // If the prefix was not found, search for the first slice.
    if (start === -1) {
      let firstSlice = slices.shift();
      let result = dmp.match_main(root.textContent, firstSlice, loc);
      if (result > -1) {
        start = result;
        loc = end = start + firstSlice.length;
      } else {
        throw new Error('no match found');
      }
    }

    // Create a fold function that will reduce slices to positional extents.
    let foldSlices = (acc, slice) => {
      let result = dmp.match_main(root.textContent, slice, acc.loc);
      if (result === -1) {
        throw new Error('no match found');
      }

      // The next slice should follow this one closely.
      acc.loc = result + slice.length;

      // Expand the start and end to a quote that includes all the slices.
      acc.start = Math.min(acc.start, result);
      acc.end = Math.max(acc.end, result + slice.length);

      return acc;
    };

    // Use the fold function to establish the full quote extents.
    // Expect the slices to be close to one another.
    // This distance is deliberately generous for now.
    dmp.Match_Distance = 64;
    let acc = slices.reduce(foldSlices, {
      start: start,
      end: end,
      loc: loc,
    });

    return new TextPositionAnchor(root, acc.start, acc.end);
  }
}
<commit_msg>Be more careful with the start and end boundaries<commit_after>import DiffMatchPatch from 'diff-match-patch';
import TextPositionAnchor from 'dom-anchor-text-position';

// The DiffMatchPatch bitap has a hard 32-character pattern length limit.
const CONTEXT_LENGTH = 32;

export default class TextQuoteAnchor {
  constructor(root, exact, context = {}) {
    if (root === undefined) {
      throw new Error('missing required parameter "root"');
    }
    if (exact === undefined) {
      throw new Error('missing required parameter "exact"');
    }
    this.root = root;
    this.exact = exact;
    this.prefix = context.prefix;
    this.suffix = context.suffix;
  }

  static fromRange(root, range) {
    if (range === undefined) {
      throw new Error('missing required parameter "range"');
    }

    let position = TextPositionAnchor.fromRange(root, range);
    return this.fromPositionAnchor(position);
  }

  static fromSelector(root, selector = {}) {
    return new TextQuoteAnchor(root, selector.exact, selector);
  }

  static fromPositionAnchor(anchor) {
    let root = anchor.root;

    let {start, end} = anchor;
    let exact = root.textContent.substr(start, end - start);

    let prefixStart = Math.max(0, start - CONTEXT_LENGTH);
    let prefix = root.textContent.substr(prefixStart, start - prefixStart);

    let suffixEnd = Math.min(root.textContent.length, end + CONTEXT_LENGTH);
    let suffix = root.textContent.substr(end, suffixEnd - end);

    return new TextQuoteAnchor(root, exact, {prefix, suffix});
  }

  toRange(options) {
    return this.toPositionAnchor(options).toRange();
  }

  toSelector() {
    let selector = {
      type: 'TextQuoteSelector',
      exact: this.exact,
    };
    if (this.prefix !== undefined) selector.prefix = this.prefix;
    if (this.suffix !== undefined) selector.suffix = this.suffix;
    return selector;
  }

  toPositionAnchor(options = {}) {
    let {hint} = options;
    let root = this.root;
    let dmp = new DiffMatchPatch();

    dmp.Match_Distance = root.textContent.length * 2;

    // Work around a hard limit of the DiffMatchPatch bitap implementation.
    // The search pattern must be no more than 32 characters.
    let slices = this.exact.match(/(.|[\r\n]){1,32}/g);
    let loc = (hint === undefined) ? ((root.textContent.length / 2) | 0) : hint;
    let start = Number.POSITIVE_INFINITY;
    let end = Number.NEGATIVE_INFINITY;
    let result = -1;

    // If the prefix is known then search for that first.
    if (this.prefix !== undefined) {
      let result = dmp.match_main(root.textContent, this.prefix, loc);
      if (result > -1) loc = result + this.prefix.length;
    }

    // If the prefix was not found, search for the first slice.
    if (result === -1) {
      let firstSlice = slices.shift();
      result = dmp.match_main(root.textContent, firstSlice, loc);
      if (result > -1) {
        start = result;
        loc = end = start + firstSlice.length;
      } else {
        throw new Error('no match found');
      }
    }

    // Create a fold function that will reduce slices to positional extents.
    let foldSlices = (acc, slice) => {
      let result = dmp.match_main(root.textContent, slice, acc.loc);
      if (result === -1) {
        throw new Error('no match found');
      }

      // The next slice should follow this one closely.
      acc.loc = result + slice.length;

      // Expand the start and end to a quote that includes all the slices.
      acc.start = Math.min(acc.start, result);
      acc.end = Math.max(acc.end, result + slice.length);

      return acc;
    };

    // Use the fold function to establish the full quote extents.
    // Expect the slices to be close to one another.
    // This distance is deliberately generous for now.
    dmp.Match_Distance = 64;
    let acc = slices.reduce(foldSlices, {
      start: start,
      end: end,
      loc: loc,
    });

    return new TextPositionAnchor(root, acc.start, acc.end);
  }
}
<|endoftext|>


<commit_before>/* @flow weak */
const formats = {
  '.woff': 'woff',
  '.eot': 'eot',
  '.ttf': 'truetype',
  '.svg': 'svg'
}

const extensions = Object.keys(formats)

export default function checkFontFormat(src) {
  for (let i = 0, len = extensions.length; i < len; ++i) {
    const extension = extensions[i]
    if (src.indexOf(extension) !== -1) {
      return formats[extension]
    }
  }
  // TODO: warning: wrong font format
  return false
}
<commit_msg>test error<commit_after>/* @flow weak */
const formats = {
  '.woff': 'woff',
  '.eot': 'eot',
  '.ttf': 'truetype',
  '.svg': 'svg'
}

const extensions = Object.keys(formats)

export default function checkFontFormat(src) {
  for (let i = 0, len = extensions.length; i < len; ++i) {
    const extension = extensions[i]
    if (src.indexOf(extension) !== -1) {
      return formats[extension]
    }
  }
  // TODO: warning: wrong font format
  return undefined
}
<|endoftext|>


<commit_before>const {app, BrowserWindow} = require('electron')
const path = require('path')
const url = require('url')

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win

function createWindow () {
  // Create the browser window.
  win = new BrowserWindow({width: 1080, height: 1920,frame: false})

  // and load the index.html of the app.
  win.loadURL(url.format({
    pathname: path.join(__dirname, 'system/index.html'),
    protocol: 'file:',
    slashes: true
  }))

  // Open the DevTools.
  win.webContents.openDevTools()

  // Emitted when the window is closed.
  win.on('closed', () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    win = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (win === null) {
    createWindow()
  }
})
<commit_msg>hiding dev tools<commit_after>const {app, BrowserWindow} = require('electron')
const path = require('path')
const url = require('url')

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win

function createWindow () {
  // Create the browser window.
  win = new BrowserWindow({width: 1080, height: 1920,frame: false})

  // and load the index.html of the app.
  win.loadURL(url.format({
    pathname: path.join(__dirname, 'system/index.html'),
    protocol: 'file:',
    slashes: true
  }))

  // Open the DevTools.
  //win.webContents.openDevTools()

  // Emitted when the window is closed.
  win.on('closed', () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    win = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (win === null) {
    createWindow()
  }
})
<|endoftext|>


<commit_before>var RadiodanClient  = require('./lib/radiodan-client'),
    MessagingClient = require('./lib/messaging-client');

module.exports.create = function (opts) {
  opts = opts || {};

  var client = MessagingClient.create(opts);
  return RadiodanClient.create(client);
};
<commit_msg>Allow caller to set custom log level<commit_after>var RadiodanClient  = require('./lib/radiodan-client'),
    MessagingClient = require('./lib/messaging-client'),
    logger = require('./lib/utils').logger;

module.exports.create = function (opts) {
  opts = opts || {};

  var client = MessagingClient.create(opts);
  return RadiodanClient.create(client);
};

module.exports.setLogLevel = function (level) {
  logger.setLevel(level);
};
<|endoftext|>