<commit_before>define(['js/core/Module', "json!doc/index", "js/core/List", "documentation/model/Class", "underscore"], function(Module, classIndex, List, Class, _) {

    return Module.inherit("app.module.DocumentationClass", {

        defaults: {
            classes: List,
            doc: null,
            searchString: ""
        },

        _initializationComplete: function() {
            for (var i = 0; i < classIndex.length; i++) {
                this.$.classes.add(this.$.api.createEntity(Class, classIndex[i]));
            }
        },
        initialize: function(){
            this.set('filterDocs', function(doc, index, filterList){
                return !filterList.$.searchString || doc.$.id.toLowerCase().indexOf(filterList.$.searchString.toLowerCase()) > -1;
            });
        },

        hasCurrentDocumentation: function() {
            return !!this.$.doc;
        }.onChange('doc'),

        showClass: function(routeContext, fqClassName) {

            var self = this;
            this.$.api.createEntity(Class, fqClassName).fetch(null, function(err, classDoc) {

                self.set('doc', err ? null : classDoc);
                routeContext.callback(err);

                if (self.runsInBrowser()) {
                    window.scrollTo(window.scrollX, 0);
                }
            })

        }.async()
    });
});<commit_msg>added calculated method showType<commit_after>define(['js/core/Module', "json!doc/index", "js/core/List", "documentation/model/Class", "underscore"], function(Module, classIndex, List, Class, _) {

    return Module.inherit("app.module.DocumentationClass", {

        defaults: {
            classes: List,
            doc: null,
            searchString: ""
        },

        showMethodTypes: function() {

            var type = (this.get('showPublic.checked') ? 2 : 0) + (this.get('showProtected.checked') ? 1 : 0);

            return ['', 'protected', 'public', 'all'][type];

        }.on(['showPublic', 'change:checked'], ['showProtected', 'change:checked']),

        _initializationComplete: function() {
            for (var i = 0; i < classIndex.length; i++) {
                this.$.classes.add(this.$.api.createEntity(Class, classIndex[i]));
            }
        },
        initialize: function(){
            this.set('filterDocs', function(doc, index, filterList){
                return !filterList.$.searchString || doc.$.id.toLowerCase().indexOf(filterList.$.searchString.toLowerCase()) > -1;
            });
        },

        hasCurrentDocumentation: function() {
            return !!this.$.doc;
        }.onChange('doc'),

        showClass: function(routeContext, fqClassName) {

            var self = this;
            this.$.api.createEntity(Class, fqClassName).fetch(null, function(err, classDoc) {

                self.set('doc', err ? null : classDoc);
                routeContext.callback(err);

                if (self.runsInBrowser()) {
                    window.scrollTo(window.scrollX, 0);
                }
            })

        }.async()
    });
});<|endoftext|>


<commit_before>/**
 * Created by Téo on 11/04/2016.
 */
'use strict';

controllers.controller('ModifyProfilCtrl',['$rootScope','$scope', '$location','ModifyProfilServ','ProfilServ','ConnexionServ','$cookies','$http',
    function($rootScope,$scope, $location,ModifyProfilServ,ProfilServ/*,ConnexionServ*/,$cookies,$http) {

    $scope.return = function() {
        $location.path('/profil');
    };

    ProfilServ.getProfil(
        function success(response) {
            $scope.id = response.id;
            $scope.name  = response.name;
            $scope.firstName = response.firstName;
            $scope.pseudo = response.pseudo;
        },
        function error(errorResponse) {
            if(errorResponse.status==401){
                alert("Session interrompue")
                console.log("Utilisateur non authentifié.");
            }

            console.log("Error:" + JSON.stringify(errorResponse));
            $location.path('/');
        }
    );

    $scope.submit = function () {

        if ($scope.password == null) {
            var userModification = {
                id: $scope.id,
                name: $scope.name,
                firstName: $scope.firstName,
                avatar: ""
            };
        }
        else {
            var userModification = {
                id: $scope.id,
                name: $scope.name,
                firstName: $scope.firstName,
                avatar: "",
                password : $scope.password
            };
        }

        var pseudo = $scope.pseudo;
        var password = $scope.password;

        ModifyProfilServ.modifyProfil(userModification,
        function success(response) {
            //alert($scope.challenge.question);
            console.log("Success:" + JSON.stringify(response));
            if ($scope.password != null) {
                $cookies.put("username", pseudo);
                $http.defaults.headers.common['Authorization'] = "Basic " + btoa(pseudo + ":" + password);
            }
            $location.path('/profil');
        },
        function error() {

            if(errorResponse.status==401){
                alert("Session interrompue")
                console.log("Utilisateur non authentifié.");
                $location.path('/');
            }
            else {
                $scope.errorMessage = "Erreur côté serveur.";
                console.log("Error:" + JSON.stringify(errorResponse));
                $location.path('/');
            }
        }
    );

    };

}])<commit_msg>add rerror in parameter <commit_after>/**
 * Created by Téo on 11/04/2016.
 */
'use strict';

controllers.controller('ModifyProfilCtrl',['$rootScope','$scope', '$location','ModifyProfilServ','ProfilServ','ConnexionServ','$cookies','$http',
    function($rootScope,$scope, $location,ModifyProfilServ,ProfilServ/*,ConnexionServ*/,$cookies,$http) {

    $scope.return = function() {
        $location.path('/profil');
    };

    ProfilServ.getProfil(
        function success(response) {
            $scope.id = response.id;
            $scope.name  = response.name;
            $scope.firstName = response.firstName;
            $scope.pseudo = response.pseudo;
        },
        function error(errorResponse) {
            if(errorResponse.status==401){
                alert("Session interrompue")
                console.log("Utilisateur non authentifié.");
            }

            console.log("Error:" + JSON.stringify(errorResponse));
            $location.path('/');
        }
    );

    $scope.submit = function () {

        if ($scope.password == null) {
            var userModification = {
                id: $scope.id,
                name: $scope.name,
                firstName: $scope.firstName,
                avatar: ""
            };
        }
        else {
            var userModification = {
                id: $scope.id,
                name: $scope.name,
                firstName: $scope.firstName,
                avatar: "",
                password : $scope.password
            };
        }

        var pseudo = $scope.pseudo;
        var password = $scope.password;

        ModifyProfilServ.modifyProfil(userModification,
        function success(response) {
            //alert($scope.challenge.question);
            console.log("Success:" + JSON.stringify(response));
            if ($scope.password != null) {
                $cookies.put("username", pseudo);
                $http.defaults.headers.common['Authorization'] = "Basic " + btoa(pseudo + ":" + password);
            }
            $location.path('/profil');
        },
        function error(errorResponse) {
            console.log(errorResponse);

            if(errorResponse.status==401){
                alert("Session interrompue")
                console.log("Utilisateur non authentifié.");
                $location.path('/');
            }
            else {
                $scope.errorMessage = "Erreur côté serveur.";
                console.log("Error:" + JSON.stringify(errorResponse));
                $location.path('/');
            }
        }
    );

    };

}])<|endoftext|>


<commit_before>/*!
 * LockNLoad - 2009 Max Aller <nanodeath@gmail.com>
 * ---------
 * A convenient inversion of control container
 *
 * Released under the MIT license.
 *
 * http://github.com/nanodeath/LockNLoad
 * http://blog.maxaller.name/tag/locknload/
*/
/**
 * Example:
 * LNL.loadConfig({
 * 	"celebratory_object": {
 * 		class: "Confetti",
 * 		args: [], // optional, constructor arguments
 * 		lifecycle: "prototype", // singleton or prototype
 *		props: { // properties -- variables and methods to set
 *			"color": "red", // sets your_object.color = "red"
 *			"quantity()": 20 // calls your_object.setQuantity(20)
 *		}
 * 	},
 * 	"censor_function": {
 * 		function: "SimpleCensor", // functions are always singletons
 * 		args: ["_", ['darn', 'dang', 'fudge', 'phooie']] // _ arguments will be merged into this
 * 	}
 * });
 *
 * var celebrate = LNL.$("celebratory_object_1");
 * celebrate.color == "red"
 * celebrate.getQuantity() == 20;
 *
 * var censor = LNL.$("censor_function");
 * censor("That darn cat!") == "That **** cat!";
 */
(function(){
    var window = this, undefined, _LNL, LNL = window.LNL = {}, func = "function", object = "object";

    var DEFAULT_GROUP = "default";

    var ObjectDatabase = {};

    function EmptyClass(){}

    var Specifications = {};

	// Clear out everything -- this was added to help singleton test cases work after multiple runs
	LNL.reset = function(){
		Specifications = {};
		ObjectDatabase = {};
	}

    LNL.loadConfig = function(specification, overwrite){
		if(overwrite !== true){
			// TODO: add some checks in here to make sure we don't overwrite any
			// existing specs.  We should throw an exception if we try.
			extend(true, Specifications, specification);
		} else {
			extend(true, Specifications, specification);
		}

    };

	LNL.version = 0.15;

	// this is a property of the spec object itself
    var SPEC_TYPE = {
        CLASS: "class",
		FUNCTION: "function",
		VALUE: "value"
    }

	// this is in the "lifecycle" attribute of the spec
	var SPEC_LIFECYCLE = {
		SINGLETON: "singleton",
		PROTOTYPE: "prototype"
	}

    function getLifecycle(spec){
		for(type in SPEC_LIFECYCLE){
			var value = SPEC_LIFECYCLE[type];
			if(spec.lifecycle == value){
				return value;
			}
		}
		return null;
    }

	function getType(spec){
		for(type in SPEC_TYPE){
			var value = SPEC_TYPE[type];
			if(spec[value]){
				return SPEC_TYPE[type];
			}
		}
		return null;
	}

	// array1: [_, hello, _, day!], array2: [oh, good]; #=> ['oh', 'hello', 'good', 'day!']
	function weaveArrays(array1, array2){
		var ret = [];
		for(var i = 0, j = 0, l_i = array1.length, l_j = array2.length; i < l_i; i++){
			if(array1[i] == "_"){
				if (j < l_j) {
					ret.push(array2[j++]);
				} else {
					ret.push(undefined);
				}
			} else {
				ret.push(array1[i]);
			}
		}
		return ret;
	}

	function getSpec(id){
        try {
            return Specifications[id];
        }
        catch (e) {
			throwError("specification not found", id);
        }
	}

	function applyConstructor(slate, spec){
		var constructor = spec['class'];
        if (typeof(constructor) == "string") {
            constructor = spec['class'] = eval(constructor);
        }

		var constructor_args = spec.args ? spec.args : [];
		constructor.prototype.constructor.apply(slate, constructor_args);
	}

	function applyProperties(slate, spec){
		for (var setter in spec.props) {
        	var isMethod = setter.indexOf("()") == setter.length - 2;
			if(isMethod){
				var method_name = setter.slice(0, -2);
				method_name = "set" + method_name.charAt(0).toUpperCase() + method_name.slice(1);
				var method = slate[method_name];
				if(!method){
					throwError("does not have method " + method_name, id);
				}
				var args = spec.props[setter];
				if(!(args instanceof Array)){
					args = [args];
				}
				method.apply(slate, args);
			} else {
				slate[setter] = spec.props[setter];
			}
        }
	}

	/**
	 * This instantiates a new object with the provided id.
	 * @param {Object} id
	 */
	function instantiate(id){
        var ret = null;

		var spec = getSpec(id);

		// If we found a specification for the object
        if (spec) {
			// And that specification is for a Class object
			switch(getType(spec)){
				case SPEC_TYPE.CLASS:
					var slate = new EmptyClass();

					applyConstructor(slate, spec);
		            applyProperties(slate, spec);

	                return slate;
				case SPEC_TYPE.FUNCTION:
					var func = spec['function'];
	                if (typeof(func) == "string") {
	                    func = spec['function'] = eval(func);
	                }
					if(spec.args){
						var orig_func = func;
						func = function(){
							var args = weaveArrays(spec.args, arguments);
							return orig_func.apply(this, args);
						}
					}
	                return func;
				case SPEC_TYPE.VALUE:
					return spec['value'];
			}
        }
		return null;
	}

	/**
	 * Private function for retrieving a particular object from the internal
	 * object database.  One instance of the object is acquired and put into
	 * the database and kept.  When requested, the same instance is always
	 * returned.
	 * @param {Object} id
	 */
    function fetchFromDB(id){
        var obj = null;

		if(ObjectDatabase[id] == null){
			obj = instantiate(id);
			if(obj){
				ObjectDatabase[id] = obj;
				return obj;
			}
		}
		return ObjectDatabase[id];
    }

	/**
	 * This is the main function that you'll be interacting with.
	 * Pass in the ID of the object you want, and optionally the group
	 * associated with the object (when its specification was loaded).
	 * @param {String} id identifier for the particular instance you want
	 */
    LNL.get = LNL.$ = function(id){
        var spec = getSpec(id);

        if (spec) {
			var lifecycle = getLifecycle(spec);
			var type = getType(spec);

			// Validation of type/lifecycle combinations
			if(type == SPEC_TYPE.VALUE){
				if (lifecycle) {
					throwError("value specs can't specify lifecycle.  Primitives are always 'prototype' and complex types are always 'singleton'", id);
				} else {
					var realType = typeof spec.value;
					if(realType == func || realType == object){
						lifecycle = "singleton";
					} else {
						lifecycle = "prototype";
					}
				}
			} else if(type == SPEC_TYPE.FUNCTION && lifecycle == SPEC_LIFECYCLE.PROTOTYPE){
				throwError("function prototypes not supported (yet)", id);
			}

            switch (lifecycle) {
                case SPEC_LIFECYCLE.PROTOTYPE:
					return instantiate(id);
                default:
					return fetchFromDB(id);
            }
        }
    }

	// extend, borrowed from jQuery
	var extend = function() {
		// copy reference to target object
		var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

		// Handle a deep copy situation
		if ( typeof target === "boolean" ) {
			deep = target;
			target = arguments[1] || {};
			// skip the boolean and the target
			i = 2;
		}

		// Handle case when target is a string or something (possible in deep copy)
		if ( typeof target !== "object" && toString.call(obj) !== "[object Function]" )
			target = {};

		for ( ; i < length; i++ )
			// Only deal with non-null/undefined values
			if ( (options = arguments[ i ]) != null )
				// Extend the base object
				for ( var name in options ) {
					var src = target[ name ], copy = options[ name ];

					// Prevent never-ending loop
					if ( target === copy )
						continue;

					// Recurse if we're merging object values
					if ( deep && copy && typeof copy === object && !copy.nodeType )
						target[ name ] = extend( deep,
							// Never move original objects, clone them
							src || ( copy.length != null ? [ ] : { } )
						, copy );

					// Don't bring in undefined values
					else if ( copy !== undefined )
						target[ name ] = copy;

				}

		// Return the modified object
		return target;
	};

	function throwError(message, id){
		var errorMessage = ["LNL: "];
		var spec = false;
		if(id){
			errorMessage.push(id);
			spec = true;

			errorMessage.push(": ");
		}
		errorMessage.push(message);
		throw new Error(errorMessage.join(""));
	}
})();
<commit_msg>Overwrite behavior for loadConfig now in an enum.<commit_after>/*!
 * LockNLoad - 2009 Max Aller <nanodeath@gmail.com>
 * ---------
 * A convenient inversion of control container
 *
 * Released under the MIT license.
 *
 * http://github.com/nanodeath/LockNLoad
 * http://blog.maxaller.name/tag/locknload/
*/
/**
 * Example:
 * LNL.loadConfig({
 * 	"celebratory_object": {
 * 		class: "Confetti",
 * 		args: [], // optional, constructor arguments
 * 		lifecycle: "prototype", // singleton or prototype
 *		props: { // properties -- variables and methods to set
 *			"color": "red", // sets your_object.color = "red"
 *			"quantity()": 20 // calls your_object.setQuantity(20)
 *		}
 * 	},
 * 	"censor_function": {
 * 		function: "SimpleCensor", // functions are always singletons
 * 		args: ["_", ['darn', 'dang', 'fudge', 'phooie']] // _ arguments will be merged into this
 * 	}
 * });
 *
 * var celebrate = LNL.$("celebratory_object_1");
 * celebrate.color == "red"
 * celebrate.getQuantity() == 20;
 *
 * var censor = LNL.$("censor_function");
 * censor("That darn cat!") == "That **** cat!";
 */
(function(){
    var window = this, undefined, _LNL, LNL = window.LNL = {}, func = "function", object = "object";

    var DEFAULT_GROUP = "default";

    var ObjectDatabase = {};

    function EmptyClass(){}

    var Specifications = {};

	// Clear out everything -- this was added to help singleton test cases work after multiple runs
	LNL.reset = function(){
		Specifications = {};
		ObjectDatabase = {};
	}

	LNL.OVERWRITE = {
		ERROR: 0,
		SKIP: 1,
		IGNORE: 2
	};

	/**
	 *
	 * @param {Object} specification
	 * @param {Object} overwrite_behavior options are in LNL.OVERWRITE
	 */
    LNL.loadConfig = function(specification, overwrite_behavior){
		switch(overwrite_behavior){
			case LNL.OVERWRITE.SKIP:
				// TODO: skip nodes that already have specifications
				extend(true, Specifications, specification);
				break;
			case LNL.OVERWRITE.IGNORE:
				extend(true, Specifications, specification);
				break;
			default:
				// TODO: throw errors as expected
				extend(true, Specifications, specification);
		}
    };

	LNL.version = 0.15;

	// this is a property of the spec object itself
    var SPEC_TYPE = {
        CLASS: "class",
		FUNCTION: "function",
		VALUE: "value"
    }

	// this is in the "lifecycle" attribute of the spec
	var SPEC_LIFECYCLE = {
		SINGLETON: "singleton",
		PROTOTYPE: "prototype"
	}

    function getLifecycle(spec){
		for(type in SPEC_LIFECYCLE){
			var value = SPEC_LIFECYCLE[type];
			if(spec.lifecycle == value){
				return value;
			}
		}
		return null;
    }

	function getType(spec){
		for(type in SPEC_TYPE){
			var value = SPEC_TYPE[type];
			if(spec[value]){
				return SPEC_TYPE[type];
			}
		}
		return null;
	}

	// array1: [_, hello, _, day!], array2: [oh, good]; #=> ['oh', 'hello', 'good', 'day!']
	function weaveArrays(array1, array2){
		var ret = [];
		for(var i = 0, j = 0, l_i = array1.length, l_j = array2.length; i < l_i; i++){
			if(array1[i] == "_"){
				if (j < l_j) {
					ret.push(array2[j++]);
				} else {
					ret.push(undefined);
				}
			} else {
				ret.push(array1[i]);
			}
		}
		return ret;
	}

	function getSpec(id){
        try {
            return Specifications[id];
        }
        catch (e) {
			throwError("specification not found", id);
        }
	}

	function applyConstructor(slate, spec){
		var constructor = spec['class'];
        if (typeof(constructor) == "string") {
            constructor = spec['class'] = eval(constructor);
        }

		var constructor_args = spec.args ? spec.args : [];
		constructor.prototype.constructor.apply(slate, constructor_args);
	}

	function applyProperties(slate, spec){
		for (var setter in spec.props) {
        	var isMethod = setter.indexOf("()") == setter.length - 2;
			if(isMethod){
				var method_name = setter.slice(0, -2);
				method_name = "set" + method_name.charAt(0).toUpperCase() + method_name.slice(1);
				var method = slate[method_name];
				if(!method){
					throwError("does not have method " + method_name, id);
				}
				var args = spec.props[setter];
				if(!(args instanceof Array)){
					args = [args];
				}
				method.apply(slate, args);
			} else {
				slate[setter] = spec.props[setter];
			}
        }
	}

	/**
	 * This instantiates a new object with the provided id.
	 * @param {Object} id
	 */
	function instantiate(id){
        var ret = null;

		var spec = getSpec(id);

		// If we found a specification for the object
        if (spec) {
			// And that specification is for a Class object
			switch(getType(spec)){
				case SPEC_TYPE.CLASS:
					var slate = new EmptyClass();

					applyConstructor(slate, spec);
		            applyProperties(slate, spec);

	                return slate;
				case SPEC_TYPE.FUNCTION:
					var func = spec['function'];
	                if (typeof(func) == "string") {
	                    func = spec['function'] = eval(func);
	                }
					if(spec.args){
						var orig_func = func;
						func = function(){
							var args = weaveArrays(spec.args, arguments);
							return orig_func.apply(this, args);
						}
					}
	                return func;
				case SPEC_TYPE.VALUE:
					return spec['value'];
			}
        }
		return null;
	}

	/**
	 * Private function for retrieving a particular object from the internal
	 * object database.  One instance of the object is acquired and put into
	 * the database and kept.  When requested, the same instance is always
	 * returned.
	 * @param {Object} id
	 */
    function fetchFromDB(id){
        var obj = null;

		if(ObjectDatabase[id] == null){
			obj = instantiate(id);
			if(obj){
				ObjectDatabase[id] = obj;
				return obj;
			}
		}
		return ObjectDatabase[id];
    }

	/**
	 * This is the main function that you'll be interacting with.
	 * Pass in the ID of the object you want, and optionally the group
	 * associated with the object (when its specification was loaded).
	 * @param {String} id identifier for the particular instance you want
	 */
    LNL.get = LNL.$ = function(id){
        var spec = getSpec(id);

        if (spec) {
			var lifecycle = getLifecycle(spec);
			var type = getType(spec);

			// Validation of type/lifecycle combinations
			if(type == SPEC_TYPE.VALUE){
				if (lifecycle) {
					throwError("value specs can't specify lifecycle.  Primitives are always 'prototype' and complex types are always 'singleton'", id);
				} else {
					var realType = typeof spec.value;
					if(realType == func || realType == object){
						lifecycle = "singleton";
					} else {
						lifecycle = "prototype";
					}
				}
			} else if(type == SPEC_TYPE.FUNCTION && lifecycle == SPEC_LIFECYCLE.PROTOTYPE){
				throwError("function prototypes not supported (yet)", id);
			}

            switch (lifecycle) {
                case SPEC_LIFECYCLE.PROTOTYPE:
					return instantiate(id);
                default:
					return fetchFromDB(id);
            }
        }
    }

	// extend, borrowed from jQuery
	var extend = function() {
		// copy reference to target object
		var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

		// Handle a deep copy situation
		if ( typeof target === "boolean" ) {
			deep = target;
			target = arguments[1] || {};
			// skip the boolean and the target
			i = 2;
		}

		// Handle case when target is a string or something (possible in deep copy)
		if ( typeof target !== "object" && toString.call(obj) !== "[object Function]" )
			target = {};

		for ( ; i < length; i++ )
			// Only deal with non-null/undefined values
			if ( (options = arguments[ i ]) != null )
				// Extend the base object
				for ( var name in options ) {
					var src = target[ name ], copy = options[ name ];

					// Prevent never-ending loop
					if ( target === copy )
						continue;

					// Recurse if we're merging object values
					if ( deep && copy && typeof copy === object && !copy.nodeType )
						target[ name ] = extend( deep,
							// Never move original objects, clone them
							src || ( copy.length != null ? [ ] : { } )
						, copy );

					// Don't bring in undefined values
					else if ( copy !== undefined )
						target[ name ] = copy;

				}

		// Return the modified object
		return target;
	};

	function throwError(message, id){
		var errorMessage = ["LNL: "];
		var spec = false;
		if(id){
			errorMessage.push(id);
			spec = true;

			errorMessage.push(": ");
		}
		errorMessage.push(message);
		throw new Error(errorMessage.join(""));
	}
})();
<|endoftext|>


<commit_before>/**
 * @flow
 * @providesModule XDL
 */

import { install as installSourceMapSupport } from 'source-map-support';

if (process.env.NODE_ENV !== 'production') {
  installSourceMapSupport();
}

module.exports = {
  get Analytics() { return require('./Analytics'); },
  get Android() { return require('./Android'); },
  get Api() { return require('./Api').default; },
  get Binaries() { return require('./Binaries'); },
  get Config() { return require('./Config').default; },
  get Credentials() { return require('./Credentials'); },
  get Detach() { return require('./detach/Detach'); },
  get Diagnostics() { return require('./Diagnostics'); },
  get Doctor() { return require('./project/Doctor'); },
  get Env() { return require('./Env'); },
  get ExponentTools() { return require('./detach/ExponentTools'); },
  get Diagnostics() { return require('./Diagnostics'); },
  get Doctor() { return require('./project/Doctor'); },
  get Env() { return require('./Env'); },
  get ErrorCode() { return require('./ErrorCode').default; },
  get Exp() { return require('./Exp'); },
  get FileSystem() { return require('./FileSystem'); },
  get Intercom() { return require('./Intercom'); },
  get IosPodsTools() { return require('./detach/IosPodsTools'); },
  get IosShellApp() { return require('./detach/IosShellApp'); },
  get Logger() { return require('./Logger').default; },
  get NotificationCode() { return require('./NotificationCode').default; },
  get Project() { return require('./Project'); },
  get ProjectSettings() { return require('./ProjectSettings'); },
  get ProjectUtils() { return require('./project/ProjectUtils'); },
  get Simulator() { return require('./Simulator'); },
  get UrlUtils() { return require('./UrlUtils'); },
  get User() { return require('./User').default; },
  get UserSettings() { return require('./UserSettings').default; },
  get Versions() { return require('./Versions'); },
  get XDLError() { return require('./XDLError').default; },
};
<commit_msg>Fix import issue<commit_after>/**
 * @flow
 * @providesModule XDL
 */

import { install as installSourceMapSupport } from 'source-map-support';

if (process.env.NODE_ENV !== 'production') {
  installSourceMapSupport();
}

module.exports = {
  get Analytics() { return require('./Analytics'); },
  get Android() { return require('./Android'); },
  get Api() { return require('./Api').default; },
  get Binaries() { return require('./Binaries'); },
  get Config() { return require('./Config').default; },
  get Credentials() { return require('./Credentials'); },
  get Detach() { return require('./detach/Detach'); },
  get Diagnostics() { return require('./Diagnostics'); },
  get Doctor() { return require('./project/Doctor'); },
  get Env() { return require('./Env'); },
  get ExponentTools() { return require('./detach/ExponentTools'); },
  get ErrorCode() { return require('./ErrorCode').default; },
  get Exp() { return require('./Exp'); },
  get FileSystem() { return require('./FileSystem'); },
  get Intercom() { return require('./Intercom'); },
  get IosPodsTools() { return require('./detach/IosPodsTools'); },
  get IosShellApp() { return require('./detach/IosShellApp'); },
  get Logger() { return require('./Logger').default; },
  get NotificationCode() { return require('./NotificationCode').default; },
  get Project() { return require('./Project'); },
  get ProjectSettings() { return require('./ProjectSettings'); },
  get ProjectUtils() { return require('./project/ProjectUtils'); },
  get Simulator() { return require('./Simulator'); },
  get UrlUtils() { return require('./UrlUtils'); },
  get User() { return require('./User'); },
  get UserSettings() { return require('./UserSettings').default; },
  get Versions() { return require('./Versions'); },
  get XDLError() { return require('./XDLError').default; },
};
<|endoftext|>


<commit_before>/**
 * @file 日志处理
 * @author xiaowu
 * @email fe.xiaowu@gmail.com
 */

'use strict';

import 'colors';

/**
 * 输出错误日志
 *
 * @param  {string||Object} str 信息
 */
function error(str) {
    if ('object' === typeof str) {
        str = JSON.stringify(str);
    }
    console.error(String('【check-version】: ' + str).red);
}

/**
 * 输出成功日志
 *
 * @param  {string||Object} str 信息
 */
function success(str) {
    if ('object' === typeof str) {
        str = JSON.stringify(str);
    }
    console.log(String('【check-version】: ' + str).green);
}

/**
 * 发送日志方法
 *
 * @param  {Object} options 配置对象
 * @param  {Object} data    数据对象
 *
 * @return {Promise}         Promise
 */
function send(options = {}, data = {}) {
    return new Promise((resolve, reject) => {
        if (data.update.length) {
            success(`当前有${data.update.length}个更新.`);
        }
        else {
            success(`当前无更新`);
        }

        // 美好的分隔线
        success(`-------------`);

        // 循环输出
        data.all.forEach(val => {
            // 如果有上次的版本号
            // 如果上次为null，那么则说明这次不是null了，这次更新了，则提示下
            if (val.prevVersion || val.prevVersion === null) {
                success(`${val.name} : ${val.prevVersion} => ${val.version}`);
            }
            else {
                success(`${val.name} : ${val.version}`);
            }
        });

        resolve(data);
    });
}

export {
    send as default,
    send,
    success,
    error
};
<commit_msg>[fix] 修复jsdoc注释报错<commit_after>/**
 * @file 日志处理
 * @author xiaowu
 * @email fe.xiaowu@gmail.com
 */

'use strict';

import 'colors';

/**
 * 输出错误日志
 *
 * @param  {string|Object} str 信息
 */
function error(str) {
    if ('object' === typeof str) {
        str = JSON.stringify(str);
    }
    console.error(String('【check-version】: ' + str).red);
}

/**
 * 输出成功日志
 *
 * @param  {string|Object} str 信息
 */
function success(str) {
    if ('object' === typeof str) {
        str = JSON.stringify(str);
    }
    console.log(String('【check-version】: ' + str).green);
}

/**
 * 发送日志方法
 *
 * @param  {Object} options 配置对象
 * @param  {Object} data    数据对象
 *
 * @return {Promise}         Promise
 */
function send(options = {}, data = {}) {
    return new Promise((resolve, reject) => {
        if (data.update.length) {
            success(`当前有${data.update.length}个更新.`);
        }
        else {
            success(`当前无更新`);
        }

        // 美好的分隔线
        success(`-------------`);

        // 循环输出
        data.all.forEach(val => {
            // 如果有上次的版本号
            // 如果上次为null，那么则说明这次不是null了，这次更新了，则提示下
            if (val.prevVersion || val.prevVersion === null) {
                success(`${val.name} : ${val.prevVersion} => ${val.version}`);
            }
            else {
                success(`${val.name} : ${val.version}`);
            }
        });

        resolve(data);
    });
}

export {
    send as default,
    send,
    success,
    error
};
<|endoftext|>


<commit_before>// @flow
import * as I from 'immutable'
import * as Constants from '../../constants/teams'
import * as ChatConstants from '../../constants/chat'
import * as SearchConstants from '../../constants/search'
import * as ChatTypes from '../../constants/types/flow-types-chat'
import * as RpcTypes from '../../constants/types/flow-types'
import * as Saga from '../../util/saga'
import * as Creators from './creators'
import * as ChatCreators from '../chat/creators'
import engine from '../../engine'
import {replaceEntity} from '../entities'
import {call, put, select, all} from 'redux-saga/effects'
import {usernameSelector} from '../../constants/selectors'
import {isMobile} from '../../constants/platform'
import {navigateTo} from '../route-tree'
import {chatTab, teamsTab} from '../../constants/tabs'
import map from 'lodash/map'

import type {AnnotatedTeamList} from '../../constants/types/flow-types'
import type {SagaGenerator} from '../../constants/types/saga'
import type {TypedState} from '../../constants/reducer'

const _createNewTeam = function*(action: Constants.CreateNewTeam) {
  const {payload: {name}} = action
  yield put(Creators.setTeamCreationError(''))
  try {
    yield call(RpcTypes.teamsTeamCreateRpcPromise, {
      param: {name, sendChatNotification: true},
    })

    // No error if we get here.
    yield put(navigateTo([isMobile ? chatTab : teamsTab]))
  } catch (error) {
    yield put(Creators.setTeamCreationError(error.desc))
  }
}

const _joinTeam = function*(action: Constants.JoinTeam) {
  const {payload: {teamname}} = action
  yield all(put(Creators.setTeamJoinError('')), put(Creators.setTeamJoinSuccess(false)))
  try {
    yield call(RpcTypes.teamsTeamAcceptInviteOrRequestAccessRpcPromise, {
      param: {tokenOrName: teamname},
    })

    // Success
    yield put(Creators.setTeamJoinSuccess(true))
  } catch (error) {
    yield put(Creators.setTeamJoinError(error.desc))
  }
}

const _leaveTeam = function(action: Constants.LeaveTeam) {
  const {payload: {teamname}} = action
  return call(RpcTypes.teamsTeamLeaveRpcPromise, {
    param: {name: teamname},
  })
}

const _addPeopleToTeam = function*(action: Constants.AddPeopleToTeam) {
  const {payload: {role, teamname}} = action
  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[teamname, true]])))
  const ids = yield select(SearchConstants.getUserInputItemIds, {searchKey: 'addToTeamSearch'})
  for (const id of ids) {
    yield call(RpcTypes.teamsTeamAddMemberRpcPromise, {
      param: {
        name: teamname,
        email: '',
        username: id,
        role: role && RpcTypes.TeamsTeamRole[role],
        sendChatNotification: true,
      },
    })
  }
  yield put((dispatch: Dispatch) => dispatch(Creators.getDetails(teamname))) // getDetails will unset loading
}

const _inviteByEmail = function*(action: Constants.InviteToTeamByEmail) {
  const {payload: {invitees, role, teamname}} = action
  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[teamname, true]])))
  // Invitees is a string containing newlines/whitespace, and we want emails to iterate
  // over. Email addresses can't contain spaces/commas, so split on comma or whitespace.
  // e.g. '1\n2,3\n4 5' => [1, 2, 3, 4, 5]
  const emails = invitees.split(/[,\s+]+/)
  for (const email of emails) {
    yield call(RpcTypes.teamsTeamAddMemberRpcPromise, {
      param: {
        name: teamname,
        email,
        username: null,
        role: role && RpcTypes.TeamsTeamRole[role],
        sendChatNotification: true,
      },
    })
  }
  yield put((dispatch: Dispatch) => dispatch(Creators.getDetails(teamname))) // getDetails will unset loading
}

const _addToTeam = function*(action: Constants.AddToTeam) {
  const {payload: {name, email, username, role, sendChatNotification}} = action
  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[name, true]])))
  try {
    yield call(RpcTypes.teamsTeamAddMemberRpcPromise, {
      param: {
        name,
        email,
        username,
        role: role && RpcTypes.TeamsTeamRole[role],
        sendChatNotification,
      },
    })
  } finally {
    // TODO handle error, but for now make sure loading is unset
    yield put((dispatch: Dispatch) => dispatch(Creators.getDetails(name))) // getDetails will unset loading
  }
}

const _editMembership = function*(action: Constants.EditMembership) {
  const {payload: {name, username, role}} = action
  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[name, true]])))
  try {
    yield call(RpcTypes.teamsTeamEditMemberRpcPromise, {
      param: {name, username, role: RpcTypes.TeamsTeamRole[role]},
    })
  } finally {
    yield put((dispatch: Dispatch) => dispatch(Creators.getDetails(name))) // getDetails will unset loading
  }
}

const _removeMemberOrPendingInvite = function*(action: Constants.RemoveMemberOrPendingInvite) {
  const {payload: {name, username, email}} = action

  // disallow call with both username & email
  if (!!username && !!email) {
    const errMsg = 'Supplied both email and username to removeMemberOrPendingInvite'
    console.error(errMsg)
    throw new Error(errMsg)
  }

  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[name, true]])))
  try {
    yield call(RpcTypes.teamsTeamRemoveMemberRpcPromise, {param: {name, username, email}})
  } finally {
    yield put((dispatch: Dispatch) => dispatch(Creators.getDetails(name))) // getDetails will unset loading
  }
}

const _ignoreRequest = function*(action: Constants.IgnoreRequest) {
  const {payload: {name, username}} = action
  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[name, true]])))
  try {
    yield call(RpcTypes.teamsTeamIgnoreRequestRpcPromise, {
      param: {
        name,
        username,
      },
    })
  } finally {
    // TODO handle error, but for now make sure loading is unset
    yield put((dispatch: Dispatch) => dispatch(Creators.getDetails(name))) // getDetails will unset loading
  }
}

function getPendingConvParticipants(state: TypedState, conversationIDKey: ChatConstants.ConversationIDKey) {
  if (!ChatConstants.isPendingConversationIDKey(conversationIDKey)) return null

  return state.chat.pendingConversations.get(conversationIDKey)
}

const _createNewTeamFromConversation = function*(
  action: Constants.CreateNewTeamFromConversation
): SagaGenerator<any, any> {
  const {payload: {conversationIDKey, name}} = action
  const me = yield select(usernameSelector)
  const inbox = yield select(ChatConstants.getInbox, conversationIDKey)
  let participants

  if (inbox) {
    participants = inbox.get('participants')
  } else {
    participants = yield select(getPendingConvParticipants, conversationIDKey)
  }

  if (participants) {
    const createRes = yield call(RpcTypes.teamsTeamCreateRpcPromise, {
      param: {name, sendChatNotification: true},
    })
    for (const username of participants.toArray()) {
      if (!createRes.creatorAdded || username !== me) {
        yield call(RpcTypes.teamsTeamAddMemberRpcPromise, {
          param: {
            email: '',
            name,
            role: username === me ? RpcTypes.TeamsTeamRole.admin : RpcTypes.TeamsTeamRole.writer,
            sendChatNotification: true,
            username,
          },
        })
      }
    }
  }
}

const _getDetails = function*(action: Constants.GetDetails): SagaGenerator<any, any> {
  const teamname = action.payload.teamname
  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[teamname, true]])))
  try {
    const results: RpcTypes.TeamDetails = yield call(RpcTypes.teamsTeamGetRpcPromise, {
      param: {
        name: teamname,
      },
    })

    // Get requests to join
    const requests: RpcTypes.TeamJoinRequest[] = yield call(RpcTypes.teamsTeamListRequestsRpcPromise)
    requests.sort((a, b) => a.username.localeCompare(b.username))

    const requestMap = requests.reduce((reqMap, req) => {
      if (!reqMap[req.name]) {
        reqMap[req.name] = I.List()
      }
      reqMap[req.name] = reqMap[req.name].push({username: req.username})
      return reqMap
    }, {})

    const infos = []
    let memberNames = I.Set()
    const types = ['admins', 'owners', 'readers', 'writers']
    const typeMap = {
      admins: 'admin',
      owners: 'owner',
      readers: 'reader',
      writers: 'writer',
    }
    types.forEach(type => {
      const details = results.members[type] || []
      details.forEach(({username}) => {
        infos.push(
          Constants.makeMemberInfo({
            type: typeMap[type],
            username,
          })
        )
        memberNames = memberNames.add(username)
      })
    })

    const invitesMap = map(results.annotatedActiveInvites, invite =>
      Constants.makeInviteInfo({
        name: invite.type.c === 4 ? `${invite.name}@${invite.type.sbs}` : invite.name,
        role: Constants.teamRoleByEnum[invite.role],
      })
    )

    // if we have no requests for this team, make sure we don't hold on to any old ones
    if (!requestMap[teamname]) {
      yield put(replaceEntity(['teams', 'teamNameToRequests'], I.Map([[teamname, I.Set()]])))
    }

    yield all([
      put(replaceEntity(['teams', 'teamNameToMembers'], I.Map([[teamname, I.Set(infos)]]))),
      put(replaceEntity(['teams', 'teamNameToMemberUsernames'], I.Map([[teamname, memberNames]]))),
      put(replaceEntity(['teams', 'teamNameToRequests'], I.Map(requestMap))),
      put(replaceEntity(['teams', 'teamNameToInvites'], I.Map([[teamname, I.Set(invitesMap)]]))),
    ])
  } finally {
    yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[teamname, false]])))
  }
}

const _getChannels = function*(action: Constants.GetChannels): SagaGenerator<any, any> {
  const teamname = action.payload.teamname
  const results: ChatTypes.GetTLFConversationsLocalRes = yield call(
    ChatTypes.localGetTLFConversationsLocalRpcPromise,
    {
      param: {
        membersType: ChatTypes.CommonConversationMembersType.team,
        tlfName: teamname,
        topicType: ChatTypes.CommonTopicType.chat,
      },
    }
  )

  const convIDs = []
  const convIDToChannelInfo = {}

  const convs = results.convs || []
  convs.forEach(conv => {
    const convID = ChatConstants.conversationIDToKey(conv.convID)
    convIDs.push(convID)
    convIDToChannelInfo[convID] = Constants.makeChannelInfo({
      channelname: conv.channel,
      description: conv.headline,
      participants: I.Set(conv.participants || []),
    })
  })

  yield all([
    put(replaceEntity(['teams', 'teamNameToConvIDs'], I.Map([[teamname, I.Set(convIDs)]]))),
    put(replaceEntity(['teams', 'convIDToChannelInfo'], I.Map(convIDToChannelInfo))),
  ])
}

const _getTeams = function*(action: Constants.GetTeams): SagaGenerator<any, any> {
  const username = yield select(usernameSelector)
  yield put(replaceEntity(['teams'], I.Map([['loaded', false]])))
  try {
    const results: AnnotatedTeamList = yield call(RpcTypes.teamsTeamListRpcPromise, {
      param: {
        userAssertion: username,
      },
    })

    const teams = results.teams || []
    const teamnames = teams.map(team => team.fqName)
    yield put(replaceEntity(['teams'], I.Map({teamnames: I.Set(teamnames)})))
  } finally {
    yield put(replaceEntity(['teams'], I.Map([['loaded', true]])))
  }
}

const _toggleChannelMembership = function*(
  action: Constants.ToggleChannelMembership
): SagaGenerator<any, any> {
  const {teamname, channelname} = action.payload
  const {conversationIDKey, participants, you} = yield select((state: TypedState) => {
    const conversationIDKey = Constants.getConversationIDKeyFromChannelName(state, channelname)
    return {
      conversationIDKey,
      participants: conversationIDKey ? Constants.getParticipants(state, conversationIDKey) : I.Set(),
      you: usernameSelector(state),
    }
  })

  if (participants.get(you)) {
    yield call(ChatTypes.localLeaveConversationLocalRpcPromise, {
      param: {
        convID: ChatConstants.keyToConversationID(conversationIDKey),
      },
    })
  } else {
    yield call(ChatTypes.localJoinConversationLocalRpcPromise, {
      param: {
        tlfName: teamname,
        topicName: channelname,
        topicType: ChatTypes.CommonTopicType.chat,
        visibility: RpcTypes.CommonTLFVisibility.private,
      },
    })
  }

  // reload
  yield put(Creators.getChannels(teamname))
}

function* _createChannel(action: Constants.CreateChannel) {
  const {payload: {channelname, description, teamname}} = action
  const result = yield call(ChatTypes.localNewConversationLocalRpcPromise, {
    param: {
      identifyBehavior: RpcTypes.TlfKeysTLFIdentifyBehavior.chatGui,
      membersType: ChatTypes.CommonConversationMembersType.team,
      tlfName: teamname,
      tlfVisibility: RpcTypes.CommonTLFVisibility.private,
      topicType: ChatTypes.CommonTopicType.chat,
      topicName: channelname,
    },
  })

  const newConversationIDKey = result ? ChatConstants.conversationIDToKey(result.conv.info.id) : null
  if (!newConversationIDKey) {
    console.warn('No convoid from newConvoRPC')
    return null
  }

  // Select the new channel
  yield put(ChatCreators.selectConversation(newConversationIDKey, false))

  // If we were given a description, set it
  if (description) {
    yield call(ChatTypes.localPostHeadlineNonblockRpcPromise, {
      param: {
        conversationID: result.conv.info.id,
        tlfName: teamname,
        tlfPublic: false,
        headline: description,
        clientPrev: null,
        identifyBehavior: RpcTypes.TlfKeysTLFIdentifyBehavior.chatGui,
      },
    })
  }
}

function* _setupTeamHandlers(): SagaGenerator<any, any> {
  yield put((dispatch: Dispatch) => {
    engine().setIncomingHandler('keybase.1.NotifyTeam.teamChanged', () => {
      dispatch(Creators.getTeams())
    })
    engine().setIncomingHandler('keybase.1.NotifyTeam.teamDeleted', () => {
      dispatch(Creators.getTeams())
    })
  })
}

const teamsSaga = function*(): SagaGenerator<any, any> {
  yield Saga.safeTakeEveryPure('teams:leaveTeam', _leaveTeam)
  yield Saga.safeTakeEveryPure('teams:createNewTeam', _createNewTeam)
  yield Saga.safeTakeEvery('teams:joinTeam', _joinTeam)
  yield Saga.safeTakeEvery('teams:getDetails', _getDetails)
  yield Saga.safeTakeEvery('teams:createNewTeamFromConversation', _createNewTeamFromConversation)
  yield Saga.safeTakeEvery('teams:getChannels', _getChannels)
  yield Saga.safeTakeEvery('teams:getTeams', _getTeams)
  yield Saga.safeTakeEvery('teams:toggleChannelMembership', _toggleChannelMembership)
  yield Saga.safeTakeEvery('teams:createChannel', _createChannel)
  yield Saga.safeTakeEvery('teams:setupTeamHandlers', _setupTeamHandlers)
  yield Saga.safeTakeEvery('teams:addToTeam', _addToTeam)
  yield Saga.safeTakeEvery('teams:addPeopleToTeam', _addPeopleToTeam)
  yield Saga.safeTakeEvery('teams:inviteToTeamByEmail', _inviteByEmail)
  yield Saga.safeTakeEvery('teams:ignoreRequest', _ignoreRequest)
  yield Saga.safeTakeEvery('teams:editMembership', _editMembership)
  yield Saga.safeTakeEvery('teams:removeMemberOrPendingInvite', _removeMemberOrPendingInvite)
}

export default teamsSaga
<commit_msg>Update to use bulk invite RPC<commit_after>// @flow
import * as I from 'immutable'
import * as Constants from '../../constants/teams'
import * as ChatConstants from '../../constants/chat'
import * as SearchConstants from '../../constants/search'
import * as ChatTypes from '../../constants/types/flow-types-chat'
import * as RpcTypes from '../../constants/types/flow-types'
import * as Saga from '../../util/saga'
import * as Creators from './creators'
import * as ChatCreators from '../chat/creators'
import engine from '../../engine'
import {replaceEntity} from '../entities'
import {call, put, select, all} from 'redux-saga/effects'
import {usernameSelector} from '../../constants/selectors'
import {isMobile} from '../../constants/platform'
import {navigateTo} from '../route-tree'
import {chatTab, teamsTab} from '../../constants/tabs'
import map from 'lodash/map'

import type {AnnotatedTeamList} from '../../constants/types/flow-types'
import type {SagaGenerator} from '../../constants/types/saga'
import type {TypedState} from '../../constants/reducer'

const _createNewTeam = function*(action: Constants.CreateNewTeam) {
  const {payload: {name}} = action
  yield put(Creators.setTeamCreationError(''))
  try {
    yield call(RpcTypes.teamsTeamCreateRpcPromise, {
      param: {name, sendChatNotification: true},
    })

    // No error if we get here.
    yield put(navigateTo([isMobile ? chatTab : teamsTab]))
  } catch (error) {
    yield put(Creators.setTeamCreationError(error.desc))
  }
}

const _joinTeam = function*(action: Constants.JoinTeam) {
  const {payload: {teamname}} = action
  yield all(put(Creators.setTeamJoinError('')), put(Creators.setTeamJoinSuccess(false)))
  try {
    yield call(RpcTypes.teamsTeamAcceptInviteOrRequestAccessRpcPromise, {
      param: {tokenOrName: teamname},
    })

    // Success
    yield put(Creators.setTeamJoinSuccess(true))
  } catch (error) {
    yield put(Creators.setTeamJoinError(error.desc))
  }
}

const _leaveTeam = function(action: Constants.LeaveTeam) {
  const {payload: {teamname}} = action
  return call(RpcTypes.teamsTeamLeaveRpcPromise, {
    param: {name: teamname},
  })
}

const _addPeopleToTeam = function*(action: Constants.AddPeopleToTeam) {
  const {payload: {role, teamname}} = action
  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[teamname, true]])))
  const ids = yield select(SearchConstants.getUserInputItemIds, {searchKey: 'addToTeamSearch'})
  for (const id of ids) {
    yield call(RpcTypes.teamsTeamAddMemberRpcPromise, {
      param: {
        name: teamname,
        email: '',
        username: id,
        role: role && RpcTypes.TeamsTeamRole[role],
        sendChatNotification: true,
      },
    })
  }
  yield put((dispatch: Dispatch) => dispatch(Creators.getDetails(teamname))) // getDetails will unset loading
}

const _inviteByEmail = function*(action: Constants.InviteToTeamByEmail) {
  const {payload: {invitees, role, teamname}} = action
  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[teamname, true]])))
  yield call(RpcTypes.teamsTeamAddEmailsBulkRpcPromise, {
    param: {
      name: teamname,
      emails: invitees,
      role: role && RpcTypes.TeamsTeamRole[role],
    },
  })
  yield put((dispatch: Dispatch) => dispatch(Creators.getDetails(teamname))) // getDetails will unset loading
}

const _addToTeam = function*(action: Constants.AddToTeam) {
  const {payload: {name, email, username, role, sendChatNotification}} = action
  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[name, true]])))
  try {
    yield call(RpcTypes.teamsTeamAddMemberRpcPromise, {
      param: {
        name,
        email,
        username,
        role: role && RpcTypes.TeamsTeamRole[role],
        sendChatNotification,
      },
    })
  } finally {
    // TODO handle error, but for now make sure loading is unset
    yield put((dispatch: Dispatch) => dispatch(Creators.getDetails(name))) // getDetails will unset loading
  }
}

const _editMembership = function*(action: Constants.EditMembership) {
  const {payload: {name, username, role}} = action
  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[name, true]])))
  try {
    yield call(RpcTypes.teamsTeamEditMemberRpcPromise, {
      param: {name, username, role: RpcTypes.TeamsTeamRole[role]},
    })
  } finally {
    yield put((dispatch: Dispatch) => dispatch(Creators.getDetails(name))) // getDetails will unset loading
  }
}

const _removeMemberOrPendingInvite = function*(action: Constants.RemoveMemberOrPendingInvite) {
  const {payload: {name, username, email}} = action

  // disallow call with both username & email
  if (!!username && !!email) {
    const errMsg = 'Supplied both email and username to removeMemberOrPendingInvite'
    console.error(errMsg)
    throw new Error(errMsg)
  }

  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[name, true]])))
  try {
    yield call(RpcTypes.teamsTeamRemoveMemberRpcPromise, {param: {name, username, email}})
  } finally {
    yield put((dispatch: Dispatch) => dispatch(Creators.getDetails(name))) // getDetails will unset loading
  }
}

const _ignoreRequest = function*(action: Constants.IgnoreRequest) {
  const {payload: {name, username}} = action
  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[name, true]])))
  try {
    yield call(RpcTypes.teamsTeamIgnoreRequestRpcPromise, {
      param: {
        name,
        username,
      },
    })
  } finally {
    // TODO handle error, but for now make sure loading is unset
    yield put((dispatch: Dispatch) => dispatch(Creators.getDetails(name))) // getDetails will unset loading
  }
}

function getPendingConvParticipants(state: TypedState, conversationIDKey: ChatConstants.ConversationIDKey) {
  if (!ChatConstants.isPendingConversationIDKey(conversationIDKey)) return null

  return state.chat.pendingConversations.get(conversationIDKey)
}

const _createNewTeamFromConversation = function*(
  action: Constants.CreateNewTeamFromConversation
): SagaGenerator<any, any> {
  const {payload: {conversationIDKey, name}} = action
  const me = yield select(usernameSelector)
  const inbox = yield select(ChatConstants.getInbox, conversationIDKey)
  let participants

  if (inbox) {
    participants = inbox.get('participants')
  } else {
    participants = yield select(getPendingConvParticipants, conversationIDKey)
  }

  if (participants) {
    const createRes = yield call(RpcTypes.teamsTeamCreateRpcPromise, {
      param: {name, sendChatNotification: true},
    })
    for (const username of participants.toArray()) {
      if (!createRes.creatorAdded || username !== me) {
        yield call(RpcTypes.teamsTeamAddMemberRpcPromise, {
          param: {
            email: '',
            name,
            role: username === me ? RpcTypes.TeamsTeamRole.admin : RpcTypes.TeamsTeamRole.writer,
            sendChatNotification: true,
            username,
          },
        })
      }
    }
  }
}

const _getDetails = function*(action: Constants.GetDetails): SagaGenerator<any, any> {
  const teamname = action.payload.teamname
  yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[teamname, true]])))
  try {
    const results: RpcTypes.TeamDetails = yield call(RpcTypes.teamsTeamGetRpcPromise, {
      param: {
        name: teamname,
      },
    })

    // Get requests to join
    const requests: RpcTypes.TeamJoinRequest[] = yield call(RpcTypes.teamsTeamListRequestsRpcPromise)
    requests.sort((a, b) => a.username.localeCompare(b.username))

    const requestMap = requests.reduce((reqMap, req) => {
      if (!reqMap[req.name]) {
        reqMap[req.name] = I.List()
      }
      reqMap[req.name] = reqMap[req.name].push({username: req.username})
      return reqMap
    }, {})

    const infos = []
    let memberNames = I.Set()
    const types = ['admins', 'owners', 'readers', 'writers']
    const typeMap = {
      admins: 'admin',
      owners: 'owner',
      readers: 'reader',
      writers: 'writer',
    }
    types.forEach(type => {
      const details = results.members[type] || []
      details.forEach(({username}) => {
        infos.push(
          Constants.makeMemberInfo({
            type: typeMap[type],
            username,
          })
        )
        memberNames = memberNames.add(username)
      })
    })

    const invitesMap = map(results.annotatedActiveInvites, invite =>
      Constants.makeInviteInfo({
        name: invite.type.c === 4 ? `${invite.name}@${invite.type.sbs}` : invite.name,
        role: Constants.teamRoleByEnum[invite.role],
      })
    )

    // if we have no requests for this team, make sure we don't hold on to any old ones
    if (!requestMap[teamname]) {
      yield put(replaceEntity(['teams', 'teamNameToRequests'], I.Map([[teamname, I.Set()]])))
    }

    yield all([
      put(replaceEntity(['teams', 'teamNameToMembers'], I.Map([[teamname, I.Set(infos)]]))),
      put(replaceEntity(['teams', 'teamNameToMemberUsernames'], I.Map([[teamname, memberNames]]))),
      put(replaceEntity(['teams', 'teamNameToRequests'], I.Map(requestMap))),
      put(replaceEntity(['teams', 'teamNameToInvites'], I.Map([[teamname, I.Set(invitesMap)]]))),
    ])
  } finally {
    yield put(replaceEntity(['teams', 'teamNameToLoading'], I.Map([[teamname, false]])))
  }
}

const _getChannels = function*(action: Constants.GetChannels): SagaGenerator<any, any> {
  const teamname = action.payload.teamname
  const results: ChatTypes.GetTLFConversationsLocalRes = yield call(
    ChatTypes.localGetTLFConversationsLocalRpcPromise,
    {
      param: {
        membersType: ChatTypes.CommonConversationMembersType.team,
        tlfName: teamname,
        topicType: ChatTypes.CommonTopicType.chat,
      },
    }
  )

  const convIDs = []
  const convIDToChannelInfo = {}

  const convs = results.convs || []
  convs.forEach(conv => {
    const convID = ChatConstants.conversationIDToKey(conv.convID)
    convIDs.push(convID)
    convIDToChannelInfo[convID] = Constants.makeChannelInfo({
      channelname: conv.channel,
      description: conv.headline,
      participants: I.Set(conv.participants || []),
    })
  })

  yield all([
    put(replaceEntity(['teams', 'teamNameToConvIDs'], I.Map([[teamname, I.Set(convIDs)]]))),
    put(replaceEntity(['teams', 'convIDToChannelInfo'], I.Map(convIDToChannelInfo))),
  ])
}

const _getTeams = function*(action: Constants.GetTeams): SagaGenerator<any, any> {
  const username = yield select(usernameSelector)
  yield put(replaceEntity(['teams'], I.Map([['loaded', false]])))
  try {
    const results: AnnotatedTeamList = yield call(RpcTypes.teamsTeamListRpcPromise, {
      param: {
        userAssertion: username,
      },
    })

    const teams = results.teams || []
    const teamnames = teams.map(team => team.fqName)
    yield put(replaceEntity(['teams'], I.Map({teamnames: I.Set(teamnames)})))
  } finally {
    yield put(replaceEntity(['teams'], I.Map([['loaded', true]])))
  }
}

const _toggleChannelMembership = function*(
  action: Constants.ToggleChannelMembership
): SagaGenerator<any, any> {
  const {teamname, channelname} = action.payload
  const {conversationIDKey, participants, you} = yield select((state: TypedState) => {
    const conversationIDKey = Constants.getConversationIDKeyFromChannelName(state, channelname)
    return {
      conversationIDKey,
      participants: conversationIDKey ? Constants.getParticipants(state, conversationIDKey) : I.Set(),
      you: usernameSelector(state),
    }
  })

  if (participants.get(you)) {
    yield call(ChatTypes.localLeaveConversationLocalRpcPromise, {
      param: {
        convID: ChatConstants.keyToConversationID(conversationIDKey),
      },
    })
  } else {
    yield call(ChatTypes.localJoinConversationLocalRpcPromise, {
      param: {
        tlfName: teamname,
        topicName: channelname,
        topicType: ChatTypes.CommonTopicType.chat,
        visibility: RpcTypes.CommonTLFVisibility.private,
      },
    })
  }

  // reload
  yield put(Creators.getChannels(teamname))
}

function* _createChannel(action: Constants.CreateChannel) {
  const {payload: {channelname, description, teamname}} = action
  const result = yield call(ChatTypes.localNewConversationLocalRpcPromise, {
    param: {
      identifyBehavior: RpcTypes.TlfKeysTLFIdentifyBehavior.chatGui,
      membersType: ChatTypes.CommonConversationMembersType.team,
      tlfName: teamname,
      tlfVisibility: RpcTypes.CommonTLFVisibility.private,
      topicType: ChatTypes.CommonTopicType.chat,
      topicName: channelname,
    },
  })

  const newConversationIDKey = result ? ChatConstants.conversationIDToKey(result.conv.info.id) : null
  if (!newConversationIDKey) {
    console.warn('No convoid from newConvoRPC')
    return null
  }

  // Select the new channel
  yield put(ChatCreators.selectConversation(newConversationIDKey, false))

  // If we were given a description, set it
  if (description) {
    yield call(ChatTypes.localPostHeadlineNonblockRpcPromise, {
      param: {
        conversationID: result.conv.info.id,
        tlfName: teamname,
        tlfPublic: false,
        headline: description,
        clientPrev: null,
        identifyBehavior: RpcTypes.TlfKeysTLFIdentifyBehavior.chatGui,
      },
    })
  }
}

function* _setupTeamHandlers(): SagaGenerator<any, any> {
  yield put((dispatch: Dispatch) => {
    engine().setIncomingHandler('keybase.1.NotifyTeam.teamChanged', () => {
      dispatch(Creators.getTeams())
    })
    engine().setIncomingHandler('keybase.1.NotifyTeam.teamDeleted', () => {
      dispatch(Creators.getTeams())
    })
  })
}

const teamsSaga = function*(): SagaGenerator<any, any> {
  yield Saga.safeTakeEveryPure('teams:leaveTeam', _leaveTeam)
  yield Saga.safeTakeEveryPure('teams:createNewTeam', _createNewTeam)
  yield Saga.safeTakeEvery('teams:joinTeam', _joinTeam)
  yield Saga.safeTakeEvery('teams:getDetails', _getDetails)
  yield Saga.safeTakeEvery('teams:createNewTeamFromConversation', _createNewTeamFromConversation)
  yield Saga.safeTakeEvery('teams:getChannels', _getChannels)
  yield Saga.safeTakeEvery('teams:getTeams', _getTeams)
  yield Saga.safeTakeEvery('teams:toggleChannelMembership', _toggleChannelMembership)
  yield Saga.safeTakeEvery('teams:createChannel', _createChannel)
  yield Saga.safeTakeEvery('teams:setupTeamHandlers', _setupTeamHandlers)
  yield Saga.safeTakeEvery('teams:addToTeam', _addToTeam)
  yield Saga.safeTakeEvery('teams:addPeopleToTeam', _addPeopleToTeam)
  yield Saga.safeTakeEvery('teams:inviteToTeamByEmail', _inviteByEmail)
  yield Saga.safeTakeEvery('teams:ignoreRequest', _ignoreRequest)
  yield Saga.safeTakeEvery('teams:editMembership', _editMembership)
  yield Saga.safeTakeEvery('teams:removeMemberOrPendingInvite', _removeMemberOrPendingInvite)
}

export default teamsSaga
<|endoftext|>


<commit_before>if (typeof importScripts === 'function') {
  var boot = function(e) {
    if (e.data.api === 'MS_LaunchWorker')  {
      self.removeEventListener('message', boot, false);
      self[e.data.asm_js_module_name]({ __ms_module_id__: e.data.mod_id,
                                        __ms_browser_language__: e.data.browser_language,
                                        TOTAL_MEMORY: e.data.asm_js_memory });
    }
    if (!self["performance"])
      self["performance"] = {};
    if (!self["performance"]["now"])
      self["performance"]["now"] = function() { return Date.now(); }
  };
  self.addEventListener('message', boot, false);
}
<commit_msg>work in progress<commit_after>if(typeof importScripts==='function'){var b=function(e){if(e.data.api==='MS_LaunchWorker'){self.removeEventListener('message',b,false);self[e.data.asm_js_module_name]({__ms_module_id__:e.data.mod_id,__ms_browser_language__:e.data.browser_language,TOTAL_MEMORY:e.data.asm_js_memory});}};self.addEventListener('message',b,false);}
<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc function
 * @name mytodoApp.controller:MainCtrl
 * @description
 * # MainCtrl
 * Controller of the mytodoApp
 */
angular.module('mytodoApp')
  .controller('MainCtrl', function ($scope) {
  	$scope.todos = ['Item 1', 'Item 2', 'Item 3'];
  	$scope.addTodo = function() {
  		$scope.todos.push($scope.todo);
  		$scope.todo = '';
  	};
  });
<commit_msg>Step 6<commit_after>'use strict';

/**
 * @ngdoc function
 * @name mytodoApp.controller:MainCtrl
 * @description
 * # MainCtrl
 * Controller of the mytodoApp
 */
angular.module('mytodoApp')
  .controller('MainCtrl', function ($scope) {
  	$scope.todos = ['Item 1', 'Item 2', 'Item 3'];
  	$scope.addTodo = function() {
  		$scope.todos.push($scope.todo);
  		$scope.todo = '';
  	};
  	$scope.removeTodo = function (index) {
  		$scope.todos.splice(index, 1);
  	};
  });
<|endoftext|>


<commit_before>'use strict'

var StringDecoder = require('string_decoder').StringDecoder
var decoder = new StringDecoder()
var ReplyError = require('./replyError')
var bufferPool = new Buffer(32 * 1024)
var bufferOffset = 0
var interval = null
var counter = 0
var notDecreased = 0

/**
 * Used for lengths and numbers only, faster perf on arrays / bulks
 * @param parser
 * @returns {*}
 */
function parseSimpleNumbers (parser) {
  var offset = parser.offset
  var length = parser.buffer.length
  var number = 0
  var sign = false

  if (parser.buffer[offset] === 45) {
    sign = true
    offset++
  }

  while (offset < length) {
    var c1 = parser.buffer[offset++]
    if (c1 === 13 && parser.buffer[offset] === 10) { // \r\n
      parser.offset = offset + 1
      return sign ? -number : number
    }
    number = (number * 10) + (c1 - 48)
  }
}

/**
 * Used for integer numbers in case of the returnNumbers option
 * @param parser
 * @returns {*}
 */
function parseStringNumbers (parser) {
  var offset = parser.offset
  var length = parser.buffer.length
  var number = ''

  if (parser.buffer[offset] === 45) {
    number += '-'
    offset++
  }

  while (offset < length) {
    var c1 = parser.buffer[offset++]
    if (c1 === 13 && parser.buffer[offset] === 10) { // \r\n
      parser.offset = offset + 1
      return number
    }
    number += c1 - 48
  }
}

/**
 * Returns a string or buffer of the provided offset start and
 * end ranges. Checks `optionReturnBuffers`.
 * @param parser
 * @param start
 * @param end
 * @returns {*}
 */
function convertBufferRange (parser, start, end) {
  // If returnBuffers is active, all return values are returned as buffers besides numbers and errors
  parser.offset = end + 2
  if (parser.optionReturnBuffers === true) {
    return parser.buffer.slice(start, end)
  }

  return parser.buffer.toString('utf-8', start, end)
}

/**
 * Parse a '+' redis simple string response but forward the offsets
 * onto convertBufferRange to generate a string.
 * @param parser
 * @returns {*}
 */
function parseSimpleStringViaOffset (parser) {
  var start = parser.offset
  var offset = parser.offset
  var length = parser.buffer.length
  var buffer = parser.buffer

  while (offset < length) {
    if (buffer[offset++] === 10) { // \r\n
      return convertBufferRange(parser, start, offset - 2)
    }
  }
}

/**
 * Returns the string length via parseSimpleNumbers
 * @param parser
 * @returns {*}
 */
function parseLength (parser) {
  var string = parseSimpleNumbers(parser)
  if (string !== undefined) {
    return +string
  }
}

/**
 * Parse a ':' redis integer response
 * @param parser
 * @returns {*}
 */
function parseInteger (parser) {
  // If stringNumbers is activated the parser always returns numbers as string
  // This is important for big numbers (number > Math.pow(2, 53)) as js numbers
  // are 64bit floating point numbers with reduced precision
  if (parser.optionStringNumbers) {
    return parseStringNumbers(parser)
  }
  return parseSimpleNumbers(parser)
}

/**
 * Parse a '$' redis bulk string response
 * @param parser
 * @returns {*}
 */
function parseBulkString (parser) {
  var length = parseLength(parser)
  if (length === undefined) {
    return
  }
  if (length === -1) {
    return null
  }
  var offsetEnd = parser.offset + length
  if (offsetEnd + 2 > parser.buffer.length) {
    parser.bigStrSize = offsetEnd + 2
    parser.bigOffset = parser.offset
    parser.totalChunkSize = parser.buffer.length
    parser.bufferCache.push(parser.buffer)
    return
  }

  return convertBufferRange(parser, parser.offset, offsetEnd)
}

/**
 * Parse a '-' redis error response
 * @param parser
 * @returns {Error}
 */
function parseError (parser) {
  var string = parseSimpleStringViaOffset(parser)
  if (string !== undefined) {
    if (parser.optionReturnBuffers === true) {
      string = string.toString()
    }
    return new ReplyError(string)
  }
}

/**
 * Parsing error handler, resets parser buffer
 * @param parser
 * @param error
 */
function handleError (parser, error) {
  parser.buffer = null
  parser.returnFatalError(error)
}

/**
 * Parse a '*' redis array response
 * @param parser
 * @returns {*}
 */
function parseArray (parser) {
  var length = parseLength(parser)
  if (length === undefined) {
    return
  }
  if (length === -1) {
    return null
  }

  var responses = new Array(length)
  var bufferLength = parser.buffer.length
  for (var i = 0; i < length; i++) {
    if (parser.offset >= bufferLength) {
      return
    }
    var response = parseType(parser, parser.buffer[parser.offset++])
    if (response === undefined) {
      return
    }
    responses[i] = response
  }

  return responses
}

/**
 * Called the appropriate parser for the specified type.
 * @param parser
 * @param type
 * @returns {*}
 */
function parseType (parser, type) {
  switch (type) {
    case 36: // $
      return parseBulkString(parser)
    case 58: // :
      return parseInteger(parser)
    case 43: // +
      return parseSimpleStringViaOffset(parser)
    case 42: // *
      return parseArray(parser)
    case 45: // -
      return parseError(parser)
    default:
      const err = new ReplyError('Protocol error, got ' + JSON.stringify(String.fromCharCode(type)) + ' as reply type byte', 20)
      err.offset = parser.offset
      err.buffer = JSON.stringify(parser.buffer)
      return handleError(parser, err)
  }
}

// All allowed options including their typeof value
var optionTypes = {
  returnError: 'function',
  returnFatalError: 'function',
  returnReply: 'function',
  returnBuffers: 'boolean',
  stringNumbers: 'boolean',
  name: 'string'
}

/**
 * Javascript Redis Parser
 * @param options
 * @constructor
 */
function JavascriptRedisParser (options) {
  if (!(this instanceof JavascriptRedisParser)) {
    return new JavascriptRedisParser(options)
  }
  if (!options || !options.returnError || !options.returnReply) {
    throw new TypeError('Please provide all return functions while initiating the parser')
  }
  for (var key in options) {
    if (optionTypes.hasOwnProperty(key) && typeof options[key] !== optionTypes[key]) {
      throw new TypeError('The options argument contains the property "' + key + '" that is either unkown or of a wrong type')
    }
  }
  if (options.name === 'hiredis') {
    /* istanbul ignore next: hiredis is only supported for legacy usage */
    try {
      var Hiredis = require('./hiredis')
      console.error(new TypeError('Using hiredis is discouraged. Please use the faster JS parser by removing the name option.').stack.replace('Error', 'Warning'))
      return new Hiredis(options)
    } catch (e) {
      console.error(new TypeError('Hiredis is not installed. Please remove the `name` option. The (faster) JS parser is used instead.').stack.replace('Error', 'Warning'))
    }
  }
  this.optionReturnBuffers = !!options.returnBuffers
  this.optionStringNumbers = !!options.stringNumbers
  this.returnError = options.returnError
  this.returnFatalError = options.returnFatalError || options.returnError
  this.returnReply = options.returnReply
  this.name = 'javascript'
  this.offset = 0
  this.buffer = null
  this.bigStrSize = 0
  this.bigOffset = 0
  this.totalChunkSize = 0
  this.bufferCache = []
}

/**
 * Concat a bulk string containing multiple chunks
 * @param parser
 * @param buffer
 * @returns {String}
 */
function concatBulkString (parser) {
  var list = parser.bufferCache
  // The first chunk might contain the whole bulk string including the \r
  var chunks = list.length
  var offset = parser.bigStrSize - parser.totalChunkSize
  parser.offset = offset
  if (offset === 1) {
    if (chunks === 2) {
      return list[0].toString('utf8', parser.bigOffset, list[0].length - 1)
    }
  } else {
    chunks++
  }
  var res = decoder.write(list[0].slice(parser.bigOffset))
  for (var i = 1; i < chunks - 2; i++) {
    // We are only safe to fully add up elements that are neither the first nor any of the last two elements
    res += decoder.write(list[i])
  }
  res += decoder.end(list[i].slice(0, offset === 1 ? list[i].length - 1 : offset - 2))
  return res
}

/**
 * Decrease the bufferPool size over time
 * @returns {undefined}
 */
function decreaseBufferPool () {
  if (bufferPool.length > 50 * 1024) {
    // Balance between increasing and decreasing the bufferPool
    if (counter === 1 || notDecreased > counter * 2) {
      // Decrease the bufferPool by 10% by removing the first 10% of the current pool
      var sliceLength = Math.floor(bufferPool.length / 10)
      if (bufferOffset <= sliceLength) {
        bufferOffset = 0
      } else {
        bufferOffset -= sliceLength
      }
      bufferPool = bufferPool.slice(sliceLength, bufferPool.length)
    } else {
      notDecreased++
      counter--
    }
  } else {
    clearInterval(interval)
    counter = 0
    notDecreased = 0
    interval = null
  }
}

/**
 * Concat the collected chunks from parser.bufferCache
 * @param parser
 * @param length
 * @returns {Buffer}
 */
function concatBuffer (parser, length) {
  var list = parser.bufferCache
  var pos = bufferOffset
  length -= parser.offset
  if (bufferPool.length < length + bufferOffset) {
    // Increase the bufferPool size
    var multiplier = length > 1024 * 1024 * 75 ? 2 : 3
    if (bufferOffset > 1024 * 1024 * 120) {
      bufferOffset = 1024 * 1024 * 50
    }
    bufferPool = new Buffer(length * multiplier + bufferOffset)
    bufferOffset = 0
    counter++
    pos = 0
    if (interval === null) {
      interval = setInterval(decreaseBufferPool, 50).unref()
    }
  }
  list[0].copy(bufferPool, pos, parser.offset, list[0].length)
  pos += list[0].length - parser.offset
  for (var i = 1; i < list.length; i++) {
    list[i].copy(bufferPool, pos)
    pos += list[i].length
  }
  var buffer = bufferPool.slice(bufferOffset, length + bufferOffset)
  bufferOffset += length
  return buffer
}

/**
 * Parse the redis buffer
 * @param buffer
 * @returns {undefined}
 */
JavascriptRedisParser.prototype.execute = function (buffer) {
  if (this.buffer === null) {
    this.buffer = buffer
    this.offset = 0
  } else if (this.bigStrSize === 0) {
    var oldLength = this.buffer.length
    var remainingLength = oldLength - this.offset
    var newBuffer = new Buffer(remainingLength + buffer.length)
    this.buffer.copy(newBuffer, 0, this.offset, oldLength)
    buffer.copy(newBuffer, remainingLength, 0, buffer.length)
    this.buffer = newBuffer
    this.offset = 0
  } else if (this.totalChunkSize + buffer.length >= this.bigStrSize) {
    this.bufferCache.push(buffer)
    // The returned type might be Array * (42) and in that case we can't improve the parsing currently
    if (this.optionReturnBuffers === false && this.buffer[this.offset] === 36) {
      this.returnReply(concatBulkString(this))
      this.buffer = buffer
    } else { // This applies for arrays too
      this.buffer = concatBuffer(this, this.totalChunkSize + buffer.length)
      this.offset = 0
    }
    this.bigStrSize = 0
    this.totalChunkSize = 0
    this.bufferCache = []
  } else {
    this.bufferCache.push(buffer)
    this.totalChunkSize += buffer.length
    return
  }

  while (this.offset < this.buffer.length) {
    var offset = this.offset
    var type = this.buffer[this.offset++]
    var response = parseType(this, type)
    if (response === undefined) {
      this.offset = offset
      return
    }

    if (type === 45) {
      this.returnError(response) // Errors -
    } else {
      this.returnReply(response) // Strings + // Integers : // Bulk strings $ // Arrays *
    }
  }

  this.buffer = null
}

module.exports = JavascriptRedisParser
<commit_msg>Move comments out of functions<commit_after>'use strict'

var StringDecoder = require('string_decoder').StringDecoder
var decoder = new StringDecoder()
var ReplyError = require('./replyError')
var bufferPool = new Buffer(32 * 1024)
var bufferOffset = 0
var interval = null
var counter = 0
var notDecreased = 0

/**
 * Used for lengths and numbers only, faster perf on arrays / bulks
 * @param parser
 * @returns {*}
 */
function parseSimpleNumbers (parser) {
  var offset = parser.offset
  var length = parser.buffer.length
  var number = 0
  var sign = false

  if (parser.buffer[offset] === 45) {
    sign = true
    offset++
  }

  while (offset < length) {
    var c1 = parser.buffer[offset++]
    if (c1 === 13 && parser.buffer[offset] === 10) { // \r\n
      parser.offset = offset + 1
      return sign ? -number : number
    }
    number = (number * 10) + (c1 - 48)
  }
}

/**
 * Used for integer numbers in case of the returnNumbers option
 * @param parser
 * @returns {*}
 */
function parseStringNumbers (parser) {
  var offset = parser.offset
  var length = parser.buffer.length
  var number = ''

  if (parser.buffer[offset] === 45) {
    number += '-'
    offset++
  }

  while (offset < length) {
    var c1 = parser.buffer[offset++]
    if (c1 === 13 && parser.buffer[offset] === 10) { // \r\n
      parser.offset = offset + 1
      return number
    }
    number += c1 - 48
  }
}

/**
 * Returns a string or buffer of the provided offset start and
 * end ranges. Checks `optionReturnBuffers`.
 *
 * If returnBuffers is active, all return values are returned as buffers besides numbers and errors
 *
 * @param parser
 * @param start
 * @param end
 * @returns {*}
 */
function convertBufferRange (parser, start, end) {
  parser.offset = end + 2
  if (parser.optionReturnBuffers === true) {
    return parser.buffer.slice(start, end)
  }

  return parser.buffer.toString('utf-8', start, end)
}

/**
 * Parse a '+' redis simple string response but forward the offsets
 * onto convertBufferRange to generate a string.
 * @param parser
 * @returns {*}
 */
function parseSimpleStringViaOffset (parser) {
  var start = parser.offset
  var offset = parser.offset
  var length = parser.buffer.length
  var buffer = parser.buffer

  while (offset < length) {
    if (buffer[offset++] === 10) { // \r\n
      return convertBufferRange(parser, start, offset - 2)
    }
  }
}

/**
 * Returns the string length via parseSimpleNumbers
 * @param parser
 * @returns {*}
 */
function parseLength (parser) {
  var string = parseSimpleNumbers(parser)
  if (string !== undefined) {
    return +string
  }
}

/**
 * Parse a ':' redis integer response
 *
 * If stringNumbers is activated the parser always returns numbers as string
 * This is important for big numbers (number > Math.pow(2, 53)) as js numbers
 * are 64bit floating point numbers with reduced precision
 *
 * @param parser
 * @returns {*}
 */
function parseInteger (parser) {
  if (parser.optionStringNumbers) {
    return parseStringNumbers(parser)
  }
  return parseSimpleNumbers(parser)
}

/**
 * Parse a '$' redis bulk string response
 * @param parser
 * @returns {*}
 */
function parseBulkString (parser) {
  var length = parseLength(parser)
  if (length === undefined) {
    return
  }
  if (length === -1) {
    return null
  }
  var offsetEnd = parser.offset + length
  if (offsetEnd + 2 > parser.buffer.length) {
    parser.bigStrSize = offsetEnd + 2
    parser.bigOffset = parser.offset
    parser.totalChunkSize = parser.buffer.length
    parser.bufferCache.push(parser.buffer)
    return
  }

  return convertBufferRange(parser, parser.offset, offsetEnd)
}

/**
 * Parse a '-' redis error response
 * @param parser
 * @returns {Error}
 */
function parseError (parser) {
  var string = parseSimpleStringViaOffset(parser)
  if (string !== undefined) {
    if (parser.optionReturnBuffers === true) {
      string = string.toString()
    }
    return new ReplyError(string)
  }
}

/**
 * Parsing error handler, resets parser buffer
 * @param parser
 * @param error
 */
function handleError (parser, error) {
  parser.buffer = null
  parser.returnFatalError(error)
}

/**
 * Parse a '*' redis array response
 * @param parser
 * @returns {*}
 */
function parseArray (parser) {
  var length = parseLength(parser)
  if (length === undefined) {
    return
  }
  if (length === -1) {
    return null
  }

  var responses = new Array(length)
  var bufferLength = parser.buffer.length
  for (var i = 0; i < length; i++) {
    if (parser.offset >= bufferLength) {
      return
    }
    var response = parseType(parser, parser.buffer[parser.offset++])
    if (response === undefined) {
      return
    }
    responses[i] = response
  }

  return responses
}

/**
 * Called the appropriate parser for the specified type.
 * @param parser
 * @param type
 * @returns {*}
 */
function parseType (parser, type) {
  switch (type) {
    case 36: // $
      return parseBulkString(parser)
    case 58: // :
      return parseInteger(parser)
    case 43: // +
      return parseSimpleStringViaOffset(parser)
    case 42: // *
      return parseArray(parser)
    case 45: // -
      return parseError(parser)
    default:
      const err = new ReplyError('Protocol error, got ' + JSON.stringify(String.fromCharCode(type)) + ' as reply type byte', 20)
      err.offset = parser.offset
      err.buffer = JSON.stringify(parser.buffer)
      return handleError(parser, err)
  }
}

// All allowed options including their typeof value
var optionTypes = {
  returnError: 'function',
  returnFatalError: 'function',
  returnReply: 'function',
  returnBuffers: 'boolean',
  stringNumbers: 'boolean',
  name: 'string'
}

/**
 * Javascript Redis Parser
 * @param options
 * @constructor
 */
function JavascriptRedisParser (options) {
  if (!(this instanceof JavascriptRedisParser)) {
    return new JavascriptRedisParser(options)
  }
  if (!options || !options.returnError || !options.returnReply) {
    throw new TypeError('Please provide all return functions while initiating the parser')
  }
  for (var key in options) {
    if (optionTypes.hasOwnProperty(key) && typeof options[key] !== optionTypes[key]) {
      throw new TypeError('The options argument contains the property "' + key + '" that is either unkown or of a wrong type')
    }
  }
  if (options.name === 'hiredis') {
    /* istanbul ignore next: hiredis is only supported for legacy usage */
    try {
      var Hiredis = require('./hiredis')
      console.error(new TypeError('Using hiredis is discouraged. Please use the faster JS parser by removing the name option.').stack.replace('Error', 'Warning'))
      return new Hiredis(options)
    } catch (e) {
      console.error(new TypeError('Hiredis is not installed. Please remove the `name` option. The (faster) JS parser is used instead.').stack.replace('Error', 'Warning'))
    }
  }
  this.optionReturnBuffers = !!options.returnBuffers
  this.optionStringNumbers = !!options.stringNumbers
  this.returnError = options.returnError
  this.returnFatalError = options.returnFatalError || options.returnError
  this.returnReply = options.returnReply
  this.name = 'javascript'
  this.offset = 0
  this.buffer = null
  this.bigStrSize = 0
  this.bigOffset = 0
  this.totalChunkSize = 0
  this.bufferCache = []
}

/**
 * Concat a bulk string containing multiple chunks
 *
 * Notes:
 * 1) The first chunk might contain the whole bulk string including the \r
 * 2) We are only safe to fully add up elements that are neither the first nor any of the last two elements
 *
 * @param parser
 * @param buffer
 * @returns {String}
 */
function concatBulkString (parser) {
  var list = parser.bufferCache
  var chunks = list.length
  var offset = parser.bigStrSize - parser.totalChunkSize
  parser.offset = offset
  if (offset === 1) {
    if (chunks === 2) {
      return list[0].toString('utf8', parser.bigOffset, list[0].length - 1)
    }
  } else {
    chunks++
  }
  var res = decoder.write(list[0].slice(parser.bigOffset))
  for (var i = 1; i < chunks - 2; i++) {
    res += decoder.write(list[i])
  }
  res += decoder.end(list[i].slice(0, offset === 1 ? list[i].length - 1 : offset - 2))
  return res
}

/**
 * Decrease the bufferPool size over time
 * @returns {undefined}
 */
function decreaseBufferPool () {
  if (bufferPool.length > 50 * 1024) {
    // Balance between increasing and decreasing the bufferPool
    if (counter === 1 || notDecreased > counter * 2) {
      // Decrease the bufferPool by 10% by removing the first 10% of the current pool
      var sliceLength = Math.floor(bufferPool.length / 10)
      if (bufferOffset <= sliceLength) {
        bufferOffset = 0
      } else {
        bufferOffset -= sliceLength
      }
      bufferPool = bufferPool.slice(sliceLength, bufferPool.length)
    } else {
      notDecreased++
      counter--
    }
  } else {
    clearInterval(interval)
    counter = 0
    notDecreased = 0
    interval = null
  }
}

/**
 * Concat the collected chunks from parser.bufferCache
 * @param parser
 * @param length
 * @returns {Buffer}
 */
function concatBuffer (parser, length) {
  var list = parser.bufferCache
  var pos = bufferOffset
  length -= parser.offset
  if (bufferPool.length < length + bufferOffset) {
    // Increase the bufferPool size
    var multiplier = length > 1024 * 1024 * 75 ? 2 : 3
    if (bufferOffset > 1024 * 1024 * 120) {
      bufferOffset = 1024 * 1024 * 50
    }
    bufferPool = new Buffer(length * multiplier + bufferOffset)
    bufferOffset = 0
    counter++
    pos = 0
    if (interval === null) {
      interval = setInterval(decreaseBufferPool, 50).unref()
    }
  }
  list[0].copy(bufferPool, pos, parser.offset, list[0].length)
  pos += list[0].length - parser.offset
  for (var i = 1; i < list.length; i++) {
    list[i].copy(bufferPool, pos)
    pos += list[i].length
  }
  var buffer = bufferPool.slice(bufferOffset, length + bufferOffset)
  bufferOffset += length
  return buffer
}

/**
 * Parse the redis buffer
 * @param buffer
 * @returns {undefined}
 */
JavascriptRedisParser.prototype.execute = function execute (buffer) {
  if (this.buffer === null) {
    this.buffer = buffer
    this.offset = 0
  } else if (this.bigStrSize === 0) {
    var oldLength = this.buffer.length
    var remainingLength = oldLength - this.offset
    var newBuffer = new Buffer(remainingLength + buffer.length)
    this.buffer.copy(newBuffer, 0, this.offset, oldLength)
    buffer.copy(newBuffer, remainingLength, 0, buffer.length)
    this.buffer = newBuffer
    this.offset = 0
  } else if (this.totalChunkSize + buffer.length >= this.bigStrSize) {
    this.bufferCache.push(buffer)
    // The returned type might be Array * (42) and in that case we can't improve the parsing currently
    if (this.optionReturnBuffers === false && this.buffer[this.offset] === 36) {
      this.returnReply(concatBulkString(this))
      this.buffer = buffer
    } else { // This applies for arrays too
      this.buffer = concatBuffer(this, this.totalChunkSize + buffer.length)
      this.offset = 0
    }
    this.bigStrSize = 0
    this.totalChunkSize = 0
    this.bufferCache = []
  } else {
    this.bufferCache.push(buffer)
    this.totalChunkSize += buffer.length
    return
  }

  while (this.offset < this.buffer.length) {
    var offset = this.offset
    var type = this.buffer[this.offset++]
    var response = parseType(this, type)
    if (response === undefined) {
      this.offset = offset
      return
    }

    if (type === 45) {
      this.returnError(response)
    } else {
      this.returnReply(response)
    }
  }

  this.buffer = null
}

module.exports = JavascriptRedisParser
<|endoftext|>


<commit_before>/**
 * @module Lyria
 */
define('lyria/log', ['root'], function(root) {
  'use strict';

  /**
   * @class Log
   */
  var Log = (function() {

    var Log = {};

    Log.Connector = null;

    Log.Plugins = {};

    Log.Plugins.Console = {
      e: function() {
        if (root.console && root.console.error) {
          return root.console.error.apply(console, arguments);
        }
      },
      w: function() {
        if (root.console && root.console.warn) {
          return root.console.warn.apply(console, arguments);
        }
      },
      i: function() {
        if (root.console && root.console.info) {
          return root.console.info.apply(console, arguments);
        }
      },
      d: function() {
        if (root.console && root.console.log) {
          return root.console.log.apply(console, arguments);
        }
      },
      v: function() {
        if (root.console && root.console.log) {
          return root.console.log.apply(console, arguments);
        }
      }
    };

    Log.Connector = Log.Plugins.Console;

    Log.logLevelMap = {
      'error': ['e'],
      'warn': ['w', 'e'],
      'info': ['i', 'w', 'e'],
      'debug': ['d', 'i', 'w', 'e'],
      'verbose': ['v', 'd', 'i', 'w', 'e']
    };

    Log.logLevel = 'verbose';

    var logFunctions = ['v', 'd', 'i', 'w', 'e'];

    for (var i = 0, j = logFunctions.length; i < j; i++) {

      (function(iterator) {
        Log[iterator] = function() {
          if (Log.logLevelMap[Log.logLevel].indexOf(iterator) >= 0) {
            Log.Connector[iterator].apply(this, arguments);
          }
        };
      })(logFunctions[i]);

    }

    return Log;

  })();

  // Map shorthand functions to Log.i
  root.log = root.out = Log.i;

  return Log;
});<commit_msg>Updated properties to be more consistent<commit_after>/**
 * @module Lyria
 */
define('lyria/log', ['root'], function(root) {
  'use strict';

  /**
   * @class Log
   */
  var Log = (function() {

    var Log = {};

    Log.connector = null;

    Log.plugins = {};

    Log.plugins.console = {
      e: function() {
        if (root.console && root.console.error) {
          return root.console.error.apply(console, arguments);
        }
      },
      w: function() {
        if (root.console && root.console.warn) {
          return root.console.warn.apply(console, arguments);
        }
      },
      i: function() {
        if (root.console && root.console.info) {
          return root.console.info.apply(console, arguments);
        }
      },
      d: function() {
        if (root.console && root.console.log) {
          return root.console.log.apply(console, arguments);
        }
      },
      v: function() {
        if (root.console && root.console.log) {
          return root.console.log.apply(console, arguments);
        }
      }
    };

    Log.connector = Log.plugins.console;

    Log.logLevelMap = {
      'error': ['e'],
      'warn': ['w', 'e'],
      'info': ['i', 'w', 'e'],
      'debug': ['d', 'i', 'w', 'e'],
      'verbose': ['v', 'd', 'i', 'w', 'e']
    };

    Log.logLevel = 'verbose';

    var logFunctions = ['v', 'd', 'i', 'w', 'e'];

    for (var i = 0, j = logFunctions.length; i < j; i++) {

      (function(iterator) {
        Log[iterator] = function() {
          if (Log.logLevelMap[Log.logLevel].indexOf(iterator) >= 0) {
            Log.connector[iterator].apply(this, arguments);
          }
        };
      })(logFunctions[i]);

    }

    return Log;

  })();

  // Map shorthand functions to Log.i
  root.log = root.out = Log.i;

  return Log;
});<|endoftext|>