<commit_before>/*
 * grunt-html-head-urls-min-toggle
 * https://github.com/pinestec/html-head-urls-min-toggle
 *
 * Copyright (c) 2017 Michael Hartung
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

	// Please see the Grunt documentation for more information regarding task
	// creation: http://gruntjs.com/creating-tasks
	grunt.registerMultiTask('html_head_urls_min_toggle',
	    'Point the html-head href and src urls to minified sources and vice versa.', function() {
		    // Check the entire "this" object or comment out...
		    // grunt.log.write("\n" + JSON.stringify(this) + "\n\n");

		    grunt.log.write("CURRENT NAME ARGS: \"" + this.nameArgs + "\"\n");
		    var spot_nameArgs_RegExp = new RegExp("^html_head_urls_min_toggle\\:[\\w-]*targets?[\\w-]*$", "i");
		    if (this.nameArgs.search(spot_nameArgs_RegExp) !== -1) {
			    if (this.data.min_targets.length > 0 || this.data.regular_targets.length > 0) {
				    var global_functions = require('./html_head_urls_min_toggle__global_functions.js');
			    }
			    if (this.data.min_targets.length > 0) {
				    if (this.data.min_targets.length === 1) {
					    grunt.log.write("\nOne file specified to switch all it's \"head links\" to \"minified sources\"...:\n");
				    } else {
					    grunt.log.write("\n" + this.data.min_targets.length +
					        " Files specified to switch all their \"head links\" to \"minified sources\"...:\n");
				    }
				    for (var i = 0; i < this.data.min_targets.length; i++) {
					    grunt.log.write("\t" + (i + 1) + ": \"" + this.data.min_targets[i] + "\"");
					    if (global_functions.toggle_all_head_links('min', this.data.min_targets[i])) {
						    grunt.log.write("\t- o.k.\n");
					    } else {
						    grunt.log.write("\t- >>> Failed...! <<<\n");
					    }
				    }
			    } else {
				    grunt.log
				        .write("\n>>> NO \"HTML Files\" listed to switch their \"head links\" to \"minified sources\"... <<<\n");
			    }
			    grunt.log.write("\n");
			    if (this.data.regular_targets.length > 0) {
				    if (this.data.regular_targets.length === 1) {
					    grunt.log.write("One file specified to switch all it's \"head links\" to \"regular sources\"...\n");
				    } else {
					    grunt.log.write(this.data.regular_targets.length +
					        " Files specified to switch all their \"head links\" to \"regular sources\"...\n");
				    }
				    for (var i = 0; i < this.data.regular_targets.length; i++) {
					    grunt.log.write("\t" + (i + 1) + ": \"" + this.data.regular_targets[i] + "\"");
					    if (global_functions.toggle_all_head_links('regular', this.data.regular_targets[i])) {
						    grunt.log.write("\t- o.k.\n");
					    } else {
						    grunt.log.write("\t- >>> Failed...! <<<\n");
					    }

				    }
			    } else {
				    grunt.log
				        .write("\n>>> NO \"HTML Files\" listed to switch their \"head links\" to \"regular sources\"... <<<\n");
			    }
		    } else {
			    // Merge task-specific and/or target-specific options with these
			    // defaults.
			    var options = this.options({
			      punctuation : '.',
			      separator : ', '
			    });
			    // Iterate over all specified file groups.
			    this.files.forEach(function(current_file) {
				    // grunt.log.write("\nDESTINATION: \"" + current_file.dest +
				    // "\"");
				    // grunt.log.write("\nSOURCE: \"" + current_file.src +
				    // "\"\n\n");
				    // Concat specified files.
				    var src = current_file.src.filter(function(filepath) {
					    // Warn on and remove invalid source files (if nonull was
					    // set).
					    if (!grunt.file.exists(filepath)) {
						    grunt.log.warn('Source file "' + filepath + '" not found.');
						    return false;
					    } else {
						    return true;
					    }
				    }).map(function(filepath) {
					    // Read file source.
					    return grunt.file.read(filepath);
				    }).join(grunt.util.normalizelf(options.separator));

				    // Handle options.
				    src += options.punctuation;

				    // Write the destination file.
				    grunt.file.write(current_file.dest, src);

				    // Print a success message.
				    grunt.log.writeln('File "' + current_file.dest + '" created.');
			    });
		    }
	    });

};
<commit_msg>Try and catch seems to work nicely... - MH - PT<commit_after>/*
 * grunt-html-head-urls-min-toggle
 * https://github.com/pinestec/html-head-urls-min-toggle
 *
 * Copyright (c) 2017 Michael Hartung
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

	// Please see the Grunt documentation for more information regarding task
	// creation: http://gruntjs.com/creating-tasks
	grunt.registerMultiTask('html_head_urls_min_toggle',
	    'Point the html-head href and src urls to minified sources and vice versa.', function() {
		    // Check the entire "this" object or comment out...
		    // grunt.log.write("\n" + JSON.stringify(this) + "\n\n");

		    grunt.log.write("CURRENT NAME ARGS: \"" + this.nameArgs + "\"\n");
		    var spot_nameArgs_RegExp = new RegExp("^html_head_urls_min_toggle\\:[\\w-]*targets?[\\w-]*$", "i");
		    if (this.nameArgs.search(spot_nameArgs_RegExp) !== -1) {
			    try {
				    var min_targets_array = this.data.min_targets;
			    } catch (exception) {
				    var min_targets_array = [];
			    }
			    try {
				    var regular_targets_array = this.data.regular_targets;
			    } catch (exception) {
				    var regular_targets_array = [];
			    }
			    if (min_targets_array.length > 0 || regular_targets_array.length > 0) {
				    var global_functions = require('./html_head_urls_min_toggle__global_functions.js');
			    }
			    if (min_targets_array.length > 0) {
				    if (min_targets_array.length === 1) {
					    grunt.log.write("\nOne file specified to switch all it's \"head links\" to \"minified sources\"...:\n");
				    } else {
					    grunt.log.write("\n" + min_targets_array.length +
					        " Files specified to switch all their \"head links\" to \"minified sources\"...:\n");
				    }
				    for (var i = 0; i < min_targets_array.length; i++) {
					    grunt.log.write("\t" + (i + 1) + ": \"" + min_targets_array[i] + "\"");
					    if (global_functions.toggle_all_head_links('min', min_targets_array[i])) {
						    grunt.log.write("\t- o.k.\n");
					    } else {
						    grunt.log.write("\t- >>> Failed...! <<<\n");
					    }
				    }
			    } else {
				    grunt.log
				        .write("\n>>> NO \"HTML Files\" listed to switch their \"head links\" to \"minified sources\"... <<<\n");
			    }
			    grunt.log.write("\n");
			    if (regular_targets_array.length > 0) {
				    if (regular_targets_array.length === 1) {
					    grunt.log.write("One file specified to switch all it's \"head links\" to \"regular sources\"...\n");
				    } else {
					    grunt.log.write(regular_targets_array.length +
					        " Files specified to switch all their \"head links\" to \"regular sources\"...\n");
				    }
				    for (var i = 0; i < regular_targets_array.length; i++) {
					    grunt.log.write("\t" + (i + 1) + ": \"" + regular_targets_array[i] + "\"");
					    if (global_functions.toggle_all_head_links('regular', regular_targets_array[i])) {
						    grunt.log.write("\t- o.k.\n");
					    } else {
						    grunt.log.write("\t- >>> Failed...! <<<\n");
					    }

				    }
			    } else {
				    grunt.log
				        .write("\n>>> NO \"HTML Files\" listed to switch their \"head links\" to \"regular sources\"... <<<\n");
			    }
		    } else {
			    // Merge task-specific and/or target-specific options with these
			    // defaults.
			    var options = this.options({
			      punctuation : '.',
			      separator : ', '
			    });
			    // Iterate over all specified file groups.
			    this.files.forEach(function(current_file) {
				    // grunt.log.write("\nDESTINATION: \"" + current_file.dest +
				    // "\"");
				    // grunt.log.write("\nSOURCE: \"" + current_file.src +
				    // "\"\n\n");
				    // Concat specified files.
				    var src = current_file.src.filter(function(filepath) {
					    // Warn on and remove invalid source files (if nonull was
					    // set).
					    if (!grunt.file.exists(filepath)) {
						    grunt.log.warn('Source file "' + filepath + '" not found.');
						    return false;
					    } else {
						    return true;
					    }
				    }).map(function(filepath) {
					    // Read file source.
					    return grunt.file.read(filepath);
				    }).join(grunt.util.normalizelf(options.separator));

				    // Handle options.
				    src += options.punctuation;

				    // Write the destination file.
				    grunt.file.write(current_file.dest, src);

				    // Print a success message.
				    grunt.log.writeln('File "' + current_file.dest + '" created.');
			    });
		    }
	    });

};
<|endoftext|>


<commit_before>//External modules
var path = require('path');
var util = require("util");

// Module Compile
exports.init = function (grunt) {
    'use strict';

    var module = require(path.join(path.dirname(__dirname), "default")).init(grunt);
    var configuration = {};

    module.registerTask("addOptimizationFiles", "Adding optimization files", function () {
        var appNoCacheFileFrom = path.resolve(process.cwd(), configuration.default.options.baseUrl, "app.nocache.js");
        var appNoCacheFileTo = path.resolve(process.cwd(), configuration.default.options.dir, "app.nocache.js");
        grunt.file.write(appNoCacheFileTo, grunt.file.read(appNoCacheFileFrom));
    });

    util._extend(module, {
        name: path.basename(__dirname),
        run: function () {
            this.getConfiguration();

            if (this.isNotEmptyObject(this.environment.libraries)) {
                configuration.default.options = this.mergeObjects(configuration.default.options, this.parseLibraries(this.environment.libraries));
            }

            if (this.isNotEmptyObject(this.environment.reqModules) || this.isNotEmptyObject(this.lastConfigurations.compile.default.jsMapping)) {
                this.smartMerge(configuration.default.options, this.parseRequireModules(this.environment.reqModules, this.lastConfigurations.compile.default.jsMapping));
            }

            if (this.isNotEmptyObject(this.environment.packages)) {
                this.parsePackages(this.environment.packages, configuration.default.options.packages);
            }

            if (this.isNotEmptyObject(this.environment.base)) {
                configuration.default.options = this.mergeObjects(configuration.default.options, this.parseBaseLibs(this.environment.base));
            }

            if (this.isNotEmptyObject(this.environment.shim)) {
                configuration.default.options = this.mergeObjects(configuration.default.options, this.parseShim(this.environment.shim));
            }

            if (typeof configuration.default != "undefined" && typeof configuration.default.options.dir != "undefined") {
                this.makeClear(configuration.default.options.dir);
            }

            // Set SourcePath
            configuration.default.options.sourcePath = this.lastConfigurations.compile.default.sourcePath;

            // For Debug ->
            grunt.log.debug(JSON.stringify(configuration));

            // Make bundles
            configuration.default.options.done = function (done, output) {
                var bundles = require('rjs-build-analysis').parse(output);
                var output = {};
                if (bundles.hasOwnProperty("bundles") && grunt.util.kindOf(bundles.bundles) == "array") {
                    bundles.bundles.forEach(function (bundle) {
                        output[(bundle.parent.substr(0, bundle.parent.lastIndexOf('/main')) || bundle.parent)] = bundle.children.map(function (bnd) {
                            return (bnd.substr(0, bnd.lastIndexOf('.')) || bnd);
                        });
                    });
                }
                module.configuration.bundles = module.mergeObjects(module.configuration.bundles || {}, output);
                done();
            };

            var newConfig = {};
            if(grunt.util.kindOf(configuration.default.options.modules) == "array" && configuration.default.options.modules.length > 0) {
                for(var i = 0; i < configuration.default.options.modules.length; i++){
                    var optModule = grunt.util._.clone(configuration.default.options.modules[i]);
                    newConfig[optModule.name] = grunt.util._.clone(configuration.default, true);

                    var excludes = [];
                    if(optModule.exclude && optModule.exclude.length > 0){
                        optModule.exclude.forEach(function(mdl){
                            if(newConfig[optModule.name].options.packages.indexOf(mdl) > -1){
                                excludes.push(mdl);
                            }else{
                                newConfig[optModule.name].options.paths[mdl] = "empty:";
                            }
                        });
                    }

                    this.smartMerge(newConfig[optModule.name].options, {
                        name: optModule.name,
                        include: optModule.include,
                        exclude: excludes,
                        insertRequire: optModule.insertRequire,
                        out: path.resolve(newConfig[optModule.name].options.dir, optModule.name, "main.js"),
                        create: true
                    });

                    grunt.file.mkdir(
                        path.resolve(newConfig[optModule.name].options.dir, optModule.name)
                    );

                    delete newConfig[optModule.name].options.modules;
                    delete newConfig[optModule.name].options.dir;
                }
            }

            this.configuration = configuration;

            // Setting configuration
            this.loadPlugin("grunt-contrib-requirejs");
            this.runTask("requirejs", newConfig, Object.keys(newConfig));

            this.runTask("addOptimizationFiles", {default: {}}, []);
        },
        getConfiguration: function () {
            // Load default configuration
            var configFile = path.resolve(__dirname, "config/default.json");
            if (grunt.file.exists(configFile)) {
                try {
                    configuration = grunt.file.readJSON(configFile);
                    grunt.log.debug(this.name + " plugin default configuration is loaded!");
                } catch (ex) {
                    grunt.log.error("[ERROR] " + this.name + " plugin default configuration has error!");
                    configuration = {};
                }
            }

            // Load user created configuration
            var userFile = path.resolve(process.cwd(), "config/build", this.name + ".js");
            if (grunt.file.exists(userFile)) {
                var config = require(userFile)(grunt);

                //Parsing configuration
                configuration = this.mergeObjects(configuration, this.parse(config));
            } else {
                grunt.log.debug(this.name + " user configuration not found, continue");
            }

            return configuration;
        },
        parse: function (configuration) {
            var parsed = {};

            // Parsing
            if (configuration.hasOwnProperty("source")) {
                parsed.baseUrl = path.resolve(process.cwd(), configuration.source);
            }

            if (configuration.hasOwnProperty("target")) {
                parsed.dir = path.resolve(process.cwd(), configuration.target);
            }

            // Fix for RequireJS
            return {
                default: {
                    options: parsed
                }
            };
        },
        parseLibraries: function (source) {
            var parsed = {
                modules: [],
                packages: [],
                paths: {}
            };

            for (var libraryName in source) {
                var library = source[libraryName];

                // Check each library and library name
                if (library) {
                    var includes = [];
                    var excludes = [];
                    var includeRequire = [];

                    // Check packages
                    if (this.isNotEmptyObject(library.packages)) {
                        for (var packageName in library.packages) {
                            var pkg = library.packages[packageName];

                            if (typeof pkg == "boolean") {
                                excludes.push(packageName);
                            } else {
                                includes.push(packageName);

                                includeRequire.push(
                                    pkg.requireName ? pkg.requireName : packageName
                                );

                                if (pkg.replace) {
                                    parsed.paths = this.mergeObjects(parsed.paths, pkg.replace);
                                }
                            }
                        }
                    }

                    parsed.modules.push({
                        name: libraryName,
                        include: includes,
                        exclude: excludes,
                        insertRequire: includeRequire,
                        create: true
                    });

                    parsed.packages.push(libraryName);
                }

                parsed.packages = parsed.packages.concat(includes);
            }

            return parsed;
        },
        parseBaseLibs: function (libs) {
            var paths = {};
            for (var lib in libs) {
                paths[lib] = "empty:";
            }
            return {
                paths: paths
            };
        },
        parsePackages: function (packages, confPackages) {
            var parsed = confPackages || [];

            for (var packageName in packages) {
                var pkg = packages[packageName];

                if (pkg) {
                    parsed.push(packageName);
                    if (pkg.replace) {
                        parsed.paths = this.mergeObjects(parsed.paths, pkg.replace);
                    }
                }
            }

            confPackages = parsed;
        },
        parseRequireModules: function (reqModules, jsMapping) {
            var paths = {};
            var srcPath = path.resolve(process.cwd(), this.lastConfigurations.compile.default.sourcePath) + path.sep;

            if (this.isNotEmptyObject(reqModules)) {
                for (var lib in reqModules) {
                    var reqModulePath = reqModules[lib]
                        .replace("{path.fromKelper}", this.modulePath)
                        .replace("{path.fromSource}", path.resolve(process.cwd(), this.lastConfigurations.compile.default.sourcePath))
                        .replace("{path.fromRoot}", process.cwd());
                    paths[lib] = path.normalize(reqModulePath);
                }
            }

            var ret = grunt.util._.clone(paths);
            if (this.isNotEmptyObject(jsMapping)) {
                if (jsMapping.files && jsMapping.files.length > 0) {
                    jsMapping.files.forEach(function (map) {
                        var files = grunt.file.expand(path.resolve(srcPath, map));
                        files.forEach(function (file) {
                            var fileMap = path.relative(
                                srcPath,
                                file.replace(/\.js$/i, "")
                            ).replace(/\\/g, "/");
                            paths[fileMap] = path.resolve(srcPath, fileMap).replace(/\\/g, "/");
                        });
                    });
                }
            }

            return {
                paths: paths,
                stubModules: Object.keys(ret),
                sourceDir: srcPath
            }
        },
        parseShim: function (shims) {
            return {
                shim: shims
            }
        }
    });

    return module;
};<commit_msg>Update<commit_after>//External modules
var path = require('path');
var util = require("util");

// Module Compile
exports.init = function (grunt) {
    'use strict';

    var module = require(path.join(path.dirname(__dirname), "default")).init(grunt);
    var configuration = {};

    util._extend(module, {
        name: path.basename(__dirname),
        run: function () {
            this.getConfiguration();

            if (this.isNotEmptyObject(this.environment.libraries)) {
                configuration.default.options = this.mergeObjects(configuration.default.options, this.parseLibraries(this.environment.libraries));
            }

            if (this.isNotEmptyObject(this.environment.reqModules) || this.isNotEmptyObject(this.lastConfigurations.compile.default.jsMapping)) {
                this.smartMerge(configuration.default.options, this.parseRequireModules(this.environment.reqModules, this.lastConfigurations.compile.default.jsMapping));
            }

            if (this.isNotEmptyObject(this.environment.packages)) {
                this.parsePackages(this.environment.packages, configuration.default.options.packages);
            }

            if (this.isNotEmptyObject(this.environment.base)) {
                configuration.default.options = this.mergeObjects(configuration.default.options, this.parseBaseLibs(this.environment.base));
            }

            if (this.isNotEmptyObject(this.environment.shim)) {
                configuration.default.options = this.mergeObjects(configuration.default.options, this.parseShim(this.environment.shim));
            }

            if (typeof configuration.default != "undefined" && typeof configuration.default.options.dir != "undefined") {
                this.makeClear(configuration.default.options.dir);
            }

            // Set SourcePath
            configuration.default.options.sourcePath = this.lastConfigurations.compile.default.sourcePath;

            // For Debug ->
            grunt.log.debug(JSON.stringify(configuration));

            // Make bundles
            configuration.default.options.done = function (done, output) {
                var bundles = require('rjs-build-analysis').parse(output);
                var output = {};
                if (bundles.hasOwnProperty("bundles") && grunt.util.kindOf(bundles.bundles) == "array") {
                    bundles.bundles.forEach(function (bundle) {
                        output[(bundle.parent.substr(0, bundle.parent.lastIndexOf('/main')) || bundle.parent)] = bundle.children.map(function (bnd) {
                            return (bnd.substr(0, bnd.lastIndexOf('.')) || bnd);
                        });
                    });
                }
                module.configuration.bundles = module.mergeObjects(module.configuration.bundles || {}, output);
                done();
            };

            var newConfig = grunt.util._.clone(configuration);
            if(grunt.util.kindOf(configuration.default.options.modules) == "array" && configuration.default.options.modules.length > 0) {
                for(var i = 0; i < configuration.default.options.modules.length; i++){
                    var optModule = grunt.util._.clone(configuration.default.options.modules[i], true);
                    newConfig[optModule.name] = grunt.util._.clone(configuration.default, true);

                    var excludes = [];
                    if(optModule.exclude && optModule.exclude.length > 0){
                        optModule.exclude.forEach(function(mdl){
                            if(newConfig[optModule.name].options.packages.indexOf(mdl) > -1){
                                excludes.push(mdl);
                            }else{
                                newConfig[optModule.name].options.paths[mdl] = "empty:";
                            }
                        });
                    }

                    this.smartMerge(newConfig[optModule.name].options, {
                        name: optModule.name,
                        include: optModule.include,
                        exclude: excludes,
                        insertRequire: optModule.insertRequire,
                        out: path.resolve(newConfig[optModule.name].options.dir, optModule.name, "main.js"),
                        create: true
                    });

                    grunt.file.mkdir(
                        path.resolve(newConfig[optModule.name].options.dir, optModule.name)
                    );

                    delete newConfig[optModule.name].options.modules;
                    delete newConfig[optModule.name].options.dir;
                }
                delete newConfig["default"].options.modules;
            }

            this.configuration = configuration;

            // Setting configuration
            this.loadPlugin("grunt-contrib-requirejs");

            return this.runTask("requirejs", newConfig, Object.keys(newConfig));
        },
        getConfiguration: function () {
            // Load default configuration
            var configFile = path.resolve(__dirname, "config/default.json");
            if (grunt.file.exists(configFile)) {
                try {
                    configuration = grunt.file.readJSON(configFile);
                    grunt.log.debug(this.name + " plugin default configuration is loaded!");
                } catch (ex) {
                    grunt.log.error("[ERROR] " + this.name + " plugin default configuration has error!");
                    configuration = {};
                }
            }

            // Load user created configuration
            var userFile = path.resolve(process.cwd(), "config/build", this.name + ".js");
            if (grunt.file.exists(userFile)) {
                var config = require(userFile)(grunt);

                //Parsing configuration
                configuration = this.mergeObjects(configuration, this.parse(config));
            } else {
                grunt.log.debug(this.name + " user configuration not found, continue");
            }

            return configuration;
        },
        parse: function (configuration) {
            var parsed = {};

            // Parsing
            if (configuration.hasOwnProperty("source")) {
                parsed.baseUrl = path.resolve(process.cwd(), configuration.source);
            }

            if (configuration.hasOwnProperty("target")) {
                parsed.dir = path.resolve(process.cwd(), configuration.target);
            }

            // Fix for RequireJS
            return {
                default: {
                    options: parsed
                }
            };
        },
        parseLibraries: function (source) {
            var parsed = {
                modules: [],
                packages: [],
                paths: {}
            };

            for (var libraryName in source) {
                var library = source[libraryName];

                // Check each library and library name
                if (library) {
                    var includes = [];
                    var excludes = [];
                    var includeRequire = [];

                    // Check packages
                    if (this.isNotEmptyObject(library.packages)) {
                        for (var packageName in library.packages) {
                            var pkg = library.packages[packageName];

                            if (typeof pkg == "boolean") {
                                excludes.push(packageName);
                            } else {
                                includes.push(packageName);

                                includeRequire.push(
                                    pkg.requireName ? pkg.requireName : packageName
                                );

                                if (pkg.replace) {
                                    parsed.paths = this.mergeObjects(parsed.paths, pkg.replace);
                                }
                            }
                        }
                    }

                    parsed.modules.push({
                        name: libraryName,
                        include: includes,
                        exclude: excludes,
                        insertRequire: includeRequire,
                        create: true
                    });

                    parsed.packages.push(libraryName);
                }

                parsed.packages = parsed.packages.concat(includes);
            }

            return parsed;
        },
        parseBaseLibs: function (libs) {
            var paths = {};
            for (var lib in libs) {
                paths[lib] = "empty:";
            }
            return {
                paths: paths
            };
        },
        parsePackages: function (packages, confPackages) {
            var parsed = confPackages || [];

            for (var packageName in packages) {
                var pkg = packages[packageName];

                if (pkg) {
                    parsed.push(packageName);
                    if (pkg.replace) {
                        parsed.paths = this.mergeObjects(parsed.paths, pkg.replace);
                    }
                }
            }

            confPackages = parsed;
        },
        parseRequireModules: function (reqModules, jsMapping) {
            var paths = {};
            var srcPath = path.resolve(process.cwd(), this.lastConfigurations.compile.default.sourcePath) + path.sep;

            if (this.isNotEmptyObject(reqModules)) {
                for (var lib in reqModules) {
                    var reqModulePath = reqModules[lib]
                        .replace("{path.fromKelper}", this.modulePath)
                        .replace("{path.fromSource}", path.resolve(process.cwd(), this.lastConfigurations.compile.default.sourcePath))
                        .replace("{path.fromRoot}", process.cwd());
                    paths[lib] = path.normalize(reqModulePath);
                }
            }

            var ret = grunt.util._.clone(paths);
            if (this.isNotEmptyObject(jsMapping)) {
                if (jsMapping.files && jsMapping.files.length > 0) {
                    jsMapping.files.forEach(function (map) {
                        var files = grunt.file.expand(path.resolve(srcPath, map));
                        files.forEach(function (file) {
                            var fileMap = path.relative(
                                srcPath,
                                file.replace(/\.js$/i, "")
                            ).replace(/\\/g, "/");
                            paths[fileMap] = path.resolve(srcPath, fileMap).replace(/\\/g, "/");
                        });
                    });
                }
            }

            return {
                paths: paths,
                stubModules: Object.keys(ret),
                sourceDir: srcPath
            }
        },
        parseShim: function (shims) {
            return {
                shim: shims
            }
        }
    });

    return module;
};<|endoftext|>


<commit_before>/* eslint-disable global-require */
const vm = require('vm');
const assert = require('assert');
const h = require('react').createElement;
const prerender = require('./prerender');
const pkg = require('../../package.json');

function evalModule(code) {
  const target = {};
  vm.runInNewContext(code, {
    require,
    module: target,
  });
  return target.exports;
}

module.exports = async function renderLoadingScreen(compilation) {
  const NodeTemplatePlugin = require('webpack/lib/node/NodeTemplatePlugin');
  const NodeTargetPlugin = require('webpack/lib/node/NodeTargetPlugin');
  const LoaderTargetPlugin = require('webpack/lib/LoaderTargetPlugin');
  const LibraryTemplatePlugin = require('webpack/lib/LibraryTemplatePlugin');
  const ExternalsPlugin = require('webpack/lib/ExternalsPlugin');
  const SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin');

  const compiler = compilation.createChildCompiler('PrerenderLoadingScreen', {
    filename: '__loading-[name].js',
  });

  // Compile the template to nodejs javascript
  new NodeTemplatePlugin().apply(compiler);
  new NodeTargetPlugin().apply(compiler);
  new LibraryTemplatePlugin('LOADING_SCREEN', 'commonjs2').apply(compiler);
  new LoaderTargetPlugin('node').apply(compiler);
  const dependencies = Object.keys(pkg.dependencies);
  new ExternalsPlugin('commonjs', (context, request, callback) => {
    if (dependencies.some((dep) => request === dep || request.startsWith(`${dep}/`))) {
      callback(null, `commonjs ${request}`);
    } else {
      callback();
    }
  }).apply(compiler);

  const inputPath = require.resolve('../../src/components/LoadingScreen');
  new SingleEntryPlugin(compiler.context, inputPath, 'LoadingScreen').apply(compiler);

  const [entries, childCompilation] = await new Promise((resolve, reject) => {
    compiler.runAsChild((err, ...results) => {
      if (err) {
        reject(err);
      } else {
        resolve(results);
      }
    });
  });

  const mainChunk = entries[0];
  const mainJsFiles = mainChunk.files.filter((f) => f.endsWith('.js'));
  assert.strictEqual(mainJsFiles.length, 1, 'Loading screen build must output a single file.');
  const mainAsset = childCompilation.assets[mainJsFiles[0]];
  mainChunk.files.forEach((file) => {
    delete childCompilation.assets[file];
  });

  const code = mainAsset.source();
  const LoadingScreen = evalModule(code).default;
  return prerender(h(LoadingScreen));
};
<commit_msg>build: prevent outputting prerender bundles<commit_after>/* eslint-disable global-require */
const vm = require('vm');
const assert = require('assert');
const h = require('react').createElement;
const prerender = require('./prerender');
const pkg = require('../../package.json');

function evalModule(code) {
  const target = {};
  vm.runInNewContext(code, {
    require,
    module: target,
  });
  return target.exports;
}

module.exports = async function renderLoadingScreen(compilation) {
  const NodeTemplatePlugin = require('webpack/lib/node/NodeTemplatePlugin');
  const NodeTargetPlugin = require('webpack/lib/node/NodeTargetPlugin');
  const LoaderTargetPlugin = require('webpack/lib/LoaderTargetPlugin');
  const LibraryTemplatePlugin = require('webpack/lib/LibraryTemplatePlugin');
  const ExternalsPlugin = require('webpack/lib/ExternalsPlugin');
  const SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin');

  const compiler = compilation.createChildCompiler('PrerenderLoadingScreen', {
    filename: '__loading-[name].js',
  });

  // Compile the template to nodejs javascript
  new NodeTemplatePlugin().apply(compiler);
  new NodeTargetPlugin().apply(compiler);
  new LibraryTemplatePlugin('LOADING_SCREEN', 'commonjs2').apply(compiler);
  new LoaderTargetPlugin('node').apply(compiler);
  const dependencies = Object.keys(pkg.dependencies);
  new ExternalsPlugin('commonjs', (context, request, callback) => {
    if (dependencies.some((dep) => request === dep || request.startsWith(`${dep}/`))) {
      callback(null, `commonjs ${request}`);
    } else {
      callback();
    }
  }).apply(compiler);

  const inputPath = require.resolve('../../src/components/LoadingScreen');
  new SingleEntryPlugin(compiler.context, inputPath, 'LoadingScreen').apply(compiler);

  const [entries, childCompilation] = await new Promise((resolve, reject) => {
    compiler.runAsChild((err, ...results) => {
      if (err) {
        reject(err);
      } else {
        resolve(results);
      }
    });
  });

  const mainChunk = entries[0];
  const mainJsFiles = mainChunk.files.filter((f) => f.endsWith('.js'));
  assert.strictEqual(mainJsFiles.length, 1, 'Loading screen build must output a single file.');
  const mainAsset = childCompilation.assets[mainJsFiles[0]];
  mainChunk.files.forEach((file) => {
    delete childCompilation.assets[file];
    delete compilation.assets[file];
  });

  const code = mainAsset.source();
  const LoadingScreen = evalModule(code).default;
  return prerender(h(LoadingScreen));
};
<|endoftext|>


<commit_before>var dgram  = require('dgram')
  , sys    = require('sys')
  , net    = require('net')
  , msgpack = require('msgpack')
  , config = require('./config')
  , redis  = require('redis')

/* enums for message types and message levels */

var types = Object.freeze({
  LOG: 1,
  COUNTER: 2,
  TIMER: 3,
  DELETE_LOG: 4,
});

var levels = Object.freeze({
  DEBUG: 10,
  INFO: 20,
  WARNING: 30,
  ERROR: 40,
  FATAL: 50
});

var messagesReceived = 0;
var messagesReceivedPrev = 0;
var logMessages = {};
var counters = {};
var timers = {};
var debugInt, flushInt, logInt, trimInt, statsInt, server;

function redisErrback(err, ret) {
  if (err) {
    sys.log("redis error: " + err);
  }
}

/* Connect to redis, using the configuration options provided, falling
 * back on sane defaults.  Sets a few message handlers to deal with errors
 * and report the status of the connection.
 */

function redisConnect(config) {
  var port = Number(config.redis.port || 6379),
      host = config.redis.host || "localhost",
      options = config.redisOptions || {};

  var client = redis.createClient(port, host, options);

  client.on("end", function() {
    sys.log("end event received from Redis client.");
  });

  client.on("error", function(err) {
    sys.log("Redis error: " + err.message);
    /* if this was connection refused, lets exit */
    if (err.message.match(/ECONNREFUSED/)) {
      process.exit(-1);
    }
  });

  client.on("connect", function() {
    sys.log("connected to Redis server on " +
      (config.redis.host || 'localhost') + ":" +
      Number(config.redis.port || 6379));
  });

  return client;
}

/* Trim the logs in redis, flushing any records that have been trimmed.
 * Because this relies on a few synchronous round trips to redis per logger,
 * it's run on its own interval.
 */

function trimLogs(redisClient, config) {
  var logd = config.redis.prefix || 'logd';
  var defaultSize = config.logSize['default'] || 100000;

  /* fetch a list of all of the paths to truncate */
  redisClient.smembers(logd + ':paths', function(err, paths) {
    for(var i=0; i<paths.length; i++) {
      var path = paths[i];
      var size = Number(config.logSize[path] || defaultSize);
      /* for every log, we have to truncate the main list, but we also need to
       * fetch the discarded items at the same time in order to delete the keys
       * for those messages and remove them from any sets they might have
       * belonged to
       */
      redisClient.multi()
        .sort(logd + ':log:' + path, 'BY', 'nosort', 'LIMIT', size, -1, 'GET',
              logd + ':log:' + path + ':*', 'GET', '#')
        .ltrim(logd + ':log:' + path, 0, size-1)
        .exec(function(path) { return function(err, ret){
          /* remove each log item from the main db and from each level, which
           * are known without fetching a list.
           */
          var removedItems = ret[0];
          if (!removedItems) return;
          var multi = redisClient.multi();
          var dmulti = redisClient.multi();

          for(var j=0; j<removedItems.length; j+=2) {
            var msg = removedItems[j], key = removedItems[j+1];
            dmulti.del(logd + ':log:' + path + ':' + key);
            try {
              var msgbuf = new Buffer(msg.length);
              msgbuf.write(msg);
              var msgobj = msgpack.unpack(msgbuf);
              multi
                .zrem(logd + ':log:' + path + ':name:' + msgobj.name, key)
                .zrem(logd + ':log:' + path + ':level:' + msgobj.level, key);
            } catch(e) {
              sys.log(e);
            }
          }
          sys.log("Deleted " + removedItems.length/2 + " items from " + path);
          dmulti.exec(redisErrback);
          multi.exec(redisErrback);
      }; }(path));
    }
  });
}

/* Delete a log and all support data for a given log on a path. */
function deleteLog(redisClient, config, path) {
  var logd = config.redis.prefix || 'logd';
  var base = logd + ':log:' + path;
  redisClient.lrange(base, 0, -1, function(err, keys) {
    var multi = redisClient.multi();
    for (var i=0; i<keys.length; i++) {
      var key = keys[i];
      multi.del(base + ':' + key);
    }
    multi.del(base);
    multi.del(base + ':next');
    multi.exec(redisErrback);
  });
  redisClient.lrange(base + ':' + 'names', 0, -1, function(err, keys) {
    /* FIXME: We are going to just keep level names here, which means we also
     * need to store a set of them;  similar to how we have log:names, we need
     * log:levels.  For now, we assume the python levelnames.
     */
    var multi = redisClient.multi();
    multi
      .del(base + ':level:INFO')
      .del(base + ':level:DEBUG')
      .del(base + ':level:WARNING')
      .del(base + ':level:ERROR')
      .del(base + ':level:CRITICAL');
    for (var i=0; i<keys.length; i++) {
      multi.del(base + ':name:' + keys[i]);
    }
    multi.del(base + ':names');
    multi.exec(redisErrback);
  });
}

/* send stats to graphite */

function sendStats(config, stats) {
  var port = Number(config.graphite.port || 2003)
    , host = config.graphite.host || 'localhost';

  try {
    var graphite = net.createConnection(port, host);
    graphite.addListener('error', function(connectionException){
      if (config.debug) {
        sys.log(connectionException);
      }
    });
    graphite.on('connect', function() {
      this.write(stats);
      this.end();
    });
  } catch(e) {
    if (config.debug) {
      sys.log(e);
    }
  }
}

/* read the config file and run the server */
config.configFile(process.argv[2], function (config, oldConfig) {
  if (!config.debug && debugInt) {
    clearInterval(debugInt);
    debugInt = false;
  }

  if (config.debug) {
    if (debugInt) {
      clearInterval(debugInt);
    }
    debugInt = setInterval(function () {
      sys.log("counters: " + sys.inspect(counters));
      sys.log("timers: " + sys.inspect(timers));
    }, config.debugInterval || 10000);
  }

  if (typeof config.logSize == 'undefined') {
    config.logSize = {'default': 100000};
  }

  if (typeof config.redis == 'undefined') {
    sys.log("no redis config, using defaults.");
    config.redis = {};
  }

  if (typeof config.graphite == 'undefined') {
    sys.log("no graphite config, using defaults.");
    config.graphite = {};
  }

  var redisClient = redisConnect(config);

  if (server === undefined) {
    var port = Number(config.port || 8126);
    /* listen on a datagram socket and add messages to local data structures to
     * be flushed out at a configurable interval.
     */
    server = dgram.createSocket('udp4', function (msg, rinfo) {
      var blob = msgpack.unpack(msg);
      if (!blob) {
        sys.log("Error with message " + msg);
        return;
      }
      if (config.debug) {
        sys.log(sys.inspect(msg));
      }

      switch (blob.id) {
        case types.LOG:
          /* TODO: do we care about this? this doubles the amt of
           * msgpack/unpack we have to do, but it allows us to always know
           * which ip sent us some information
           */
          messagesReceived++;
          blob.ip = rinfo.address;
          if (! logMessages[blob.path]) {
            logMessages[blob.path] = [];
          }
          logMessages[blob.path].push(blob);
          break;
        case types.COUNTER:
          /* statsd like counter */
          var sampleRate = blob.rate || 1;
          if (! counters[blob.key]) {
            counters[blob.key] = 0;
          }
          counters[blob.key] += Number((blob.value || 1) * (1 / sampleRate));
          break;
        case types.TIMER:
          /* statsd like timer */
          if (! timers[blob.key]) {
            timers[blob.key] = [];
          }
          timers[blob.key].push(blob.value);
          break;
        case types.DELETE_LOG:
          deleteLog(redisClient, blob.path);
        default: break;
      }
    });

    server.on("listening", function() {
      sys.log("logd listening on port " + port);
    });

    server.bind(port);
  }

  /* every second, print if we've received messages or not */
  var logInterval = Number(config.logInterval || 1000);

  logInt = setInterval(function() {
    if (messagesReceived != messagesReceivedPrev) {
      dmsg = messagesReceived - messagesReceivedPrev;
      messagesReceivedPrev = messagesReceived;
      sys.log("Received " + dmsg + " messages in 1s (" + messagesReceived + " total).");
    }
  }, logInterval);

  /* every second, flush local stats & messages to redis */
  var flushInterval = Number(config.flushInterval || 1000);

  flushInt = setInterval(function() {
    /* flush log messages */
    var messages, logger, size, msg;
    var allsize = Number(config.logSize['all'] || 250000);
    var logd = config.redis.prefix || 'logd';

    for (path in logMessages) {
      if (!logMessages[path] || !logMessages[path].length) continue;

      var base = logd + ':log:' + path;

      /* ids for these messages are simple monotonically increasing integers.
       * fetch the value for the next id from the database and add the cached
       * messages.
       */
      redisClient.get(base + ':next', function(base, path) {
          return function(err, next) {
            var messages = logMessages[path];
            var count = 0;
            var multi = redisClient.multi();
            next = Number(next);

            /* if there was no "next" setting, then this logger didn't exist yet.
             * add it to the list of paths and give it a next val
             */
            if (!next) {
              next = 1;
              redisClient.multi()
                .sadd('logd:paths', path)
                .set(base + ':next', next)
                .exec();
            }

            /* add the messages to the path's lists & ordered sets */
            for( ; count < messages.length; count++, next++) {
              msg = messages[count];
              msg.id = next;
              //  https://github.com/mranney/node_redis/pull/119
              //  fixed in 0.6.5
              var packed = msgpack.pack(msg);
              //var bufpacked = new Buffer(packed.length);
              //packed.copy(bufpacked)
              multi
                .set(base + ':' + next, packed)
                .lpush(base, next)
                .zadd(base + ':level:' + msg.level, -msg.time, next)
                .zadd(base + ':name:' + msg.name, -msg.time, next)
                .sadd(base + ':names', msg.name);
            }

            /* clear local cache, increment the in-redis next val, and flush */
            /*
            if (!count) {
              debugger;
            }
            */
            multi.incrby(base + ':next', count);
            multi.exec(redisErrback);
            logMessages[path] = [];
          };
        }(base, path)
      );
    }

  }, flushInterval);

  var trimInterval = Number(config.trimInterval || 10000);

  trimInt = setInterval(function() {
    trimLogs(redisClient, config);
  }, trimInterval)

  /* Every 10 seconds, flush stats to graphite.  This code is exactly
   * the same as the statsd code, as even the local storage is identical.
   */
  var statsInterval = Number(config.statsInterval || 10000);

  statsInt = setInterval(function() {
    var statString = '';
    var ts = Math.round(new Date().getTime() / 1000);
    var numStats = 0;
    var key;

    for (key in counters) {
      var value = counters[key] / (flushInterval / 1000);
      var message = 'stats.' + key + ' ' + value + ' ' + ts + "\n";
      message += 'stats.counts.' + key + ' ' + counters[key] + ' ' + ts + "\n";
      statString += message;
      counters[key] = 0;

      numStats += 1;
    }

    for (key in timers) {
      if (timers[key].length > 0) {
        var pctThreshold = config.percentThreshold || 90;
        var values = timers[key].sort(function (a,b) { return a-b; });
        var count = values.length;
        var min = values[0];
        var max = values[count - 1];

        var mean = min;
        var maxAtThreshold = max;

        if (count > 1) {
          var thresholdIndex = Math.round(((100 - pctThreshold) / 100) * count);
          var numInThreshold = count - thresholdIndex;
          values = values.slice(0, numInThreshold);
          maxAtThreshold = values[numInThreshold - 1];

          // average the remaining timings
          var sum = 0;
          for (var i = 0; i < numInThreshold; i++) {
            sum += values[i];
          }

          mean = sum / numInThreshold;
        }

        timers[key] = [];

        var message = "";
        message += 'stats.timers.' + key + '.mean ' + mean + ' ' + ts + "\n";
        message += 'stats.timers.' + key + '.upper ' + max + ' ' + ts + "\n";
        message += 'stats.timers.' + key + '.upper_' + pctThreshold + ' ' + maxAtThreshold + ' ' + ts + "\n";
        message += 'stats.timers.' + key + '.lower ' + min + ' ' + ts + "\n";
        message += 'stats.timers.' + key + '.count ' + count + ' ' + ts + "\n";
        statString += message;

        numStats += 1;
      }
    }

    statString += 'stats.numStats ' + numStats + ' ' + ts + "\n";
    if (numStats) {
      if (config.debug) {
        sys.log("Sending stats string: \n" + statString);
      }
      sendStats(config, statString);
    }

  }, statsInterval);

});

<commit_msg>do not exit logd when redis goes away<commit_after>var dgram  = require('dgram')
  , sys    = require('sys')
  , net    = require('net')
  , msgpack = require('msgpack')
  , config = require('./config')
  , redis  = require('redis')

/* enums for message types and message levels */

var types = Object.freeze({
  LOG: 1,
  COUNTER: 2,
  TIMER: 3,
  DELETE_LOG: 4,
});

var levels = Object.freeze({
  DEBUG: 10,
  INFO: 20,
  WARNING: 30,
  ERROR: 40,
  FATAL: 50
});

var messagesReceived = 0;
var messagesReceivedPrev = 0;
var logMessages = {};
var counters = {};
var timers = {};
var debugInt, flushInt, logInt, trimInt, statsInt, server;

function redisErrback(err, ret) {
  if (err) {
    sys.log("redis error: " + err);
  }
}

/* Connect to redis, using the configuration options provided, falling
 * back on sane defaults.  Sets a few message handlers to deal with errors
 * and report the status of the connection.
 */

function redisConnect(config) {
  var port = Number(config.redis.port || 6379),
      host = config.redis.host || "localhost",
      options = config.redisOptions || {};

  var client = redis.createClient(port, host, options);

  client.on("end", function() {
    sys.log("end event received from Redis client.");
  });

  client.on("error", function(err) {
    sys.log("Redis error: " + err.message);
    /* if this was connection refused, lets exit */
    if (err.message.match(/ECONNREFUSED/)) {
      // process.exit(-1);
    }
  });

  client.on("connect", function() {
    sys.log("connected to Redis server on " +
      (config.redis.host || 'localhost') + ":" +
      Number(config.redis.port || 6379));
  });

  return client;
}

/* Trim the logs in redis, flushing any records that have been trimmed.
 * Because this relies on a few synchronous round trips to redis per logger,
 * it's run on its own interval.
 */

function trimLogs(redisClient, config) {
  var logd = config.redis.prefix || 'logd';
  var defaultSize = config.logSize['default'] || 100000;

  /* fetch a list of all of the paths to truncate */
  redisClient.smembers(logd + ':paths', function(err, paths) {
    for(var i=0; i<paths.length; i++) {
      var path = paths[i];
      var size = Number(config.logSize[path] || defaultSize);
      /* for every log, we have to truncate the main list, but we also need to
       * fetch the discarded items at the same time in order to delete the keys
       * for those messages and remove them from any sets they might have
       * belonged to
       */
      redisClient.multi()
        .sort(logd + ':log:' + path, 'BY', 'nosort', 'LIMIT', size, -1, 'GET',
              logd + ':log:' + path + ':*', 'GET', '#')
        .ltrim(logd + ':log:' + path, 0, size-1)
        .exec(function(path) { return function(err, ret){
          /* remove each log item from the main db and from each level, which
           * are known without fetching a list.
           */
          var removedItems = ret[0];
          if (!removedItems) return;
          var multi = redisClient.multi();
          var dmulti = redisClient.multi();

          for(var j=0; j<removedItems.length; j+=2) {
            var msg = removedItems[j], key = removedItems[j+1];
            dmulti.del(logd + ':log:' + path + ':' + key);
            try {
              var msgbuf = new Buffer(msg.length);
              msgbuf.write(msg);
              var msgobj = msgpack.unpack(msgbuf);
              multi
                .zrem(logd + ':log:' + path + ':name:' + msgobj.name, key)
                .zrem(logd + ':log:' + path + ':level:' + msgobj.level, key);
            } catch(e) {
              sys.log(e);
            }
          }
          sys.log("Deleted " + removedItems.length/2 + " items from " + path);
          dmulti.exec(redisErrback);
          multi.exec(redisErrback);
      }; }(path));
    }
  });
}

/* Delete a log and all support data for a given log on a path. */
function deleteLog(redisClient, config, path) {
  var logd = config.redis.prefix || 'logd';
  var base = logd + ':log:' + path;
  redisClient.lrange(base, 0, -1, function(err, keys) {
    var multi = redisClient.multi();
    for (var i=0; i<keys.length; i++) {
      var key = keys[i];
      multi.del(base + ':' + key);
    }
    multi.del(base);
    multi.del(base + ':next');
    multi.exec(redisErrback);
  });
  redisClient.lrange(base + ':' + 'names', 0, -1, function(err, keys) {
    /* FIXME: We are going to just keep level names here, which means we also
     * need to store a set of them;  similar to how we have log:names, we need
     * log:levels.  For now, we assume the python levelnames.
     */
    var multi = redisClient.multi();
    multi
      .del(base + ':level:INFO')
      .del(base + ':level:DEBUG')
      .del(base + ':level:WARNING')
      .del(base + ':level:ERROR')
      .del(base + ':level:CRITICAL');
    for (var i=0; i<keys.length; i++) {
      multi.del(base + ':name:' + keys[i]);
    }
    multi.del(base + ':names');
    multi.exec(redisErrback);
  });
}

/* send stats to graphite */

function sendStats(config, stats) {
  var port = Number(config.graphite.port || 2003)
    , host = config.graphite.host || 'localhost';

  try {
    var graphite = net.createConnection(port, host);
    graphite.addListener('error', function(connectionException){
      if (config.debug) {
        sys.log(connectionException);
      }
    });
    graphite.on('connect', function() {
      this.write(stats);
      this.end();
    });
  } catch(e) {
    if (config.debug) {
      sys.log(e);
    }
  }
}

/* read the config file and run the server */
config.configFile(process.argv[2], function (config, oldConfig) {
  if (!config.debug && debugInt) {
    clearInterval(debugInt);
    debugInt = false;
  }

  if (config.debug) {
    if (debugInt) {
      clearInterval(debugInt);
    }
    debugInt = setInterval(function () {
      sys.log("counters: " + sys.inspect(counters));
      sys.log("timers: " + sys.inspect(timers));
    }, config.debugInterval || 10000);
  }

  if (typeof config.logSize == 'undefined') {
    config.logSize = {'default': 100000};
  }

  if (typeof config.redis == 'undefined') {
    sys.log("no redis config, using defaults.");
    config.redis = {};
  }

  if (typeof config.graphite == 'undefined') {
    sys.log("no graphite config, using defaults.");
    config.graphite = {};
  }

  var redisClient = redisConnect(config);

  if (server === undefined) {
    var port = Number(config.port || 8126);
    /* listen on a datagram socket and add messages to local data structures to
     * be flushed out at a configurable interval.
     */
    server = dgram.createSocket('udp4', function (msg, rinfo) {
      var blob = msgpack.unpack(msg);
      if (!blob) {
        sys.log("Error with message " + msg);
        return;
      }
      if (config.debug) {
        sys.log(sys.inspect(msg));
      }

      switch (blob.id) {
        case types.LOG:
          /* TODO: do we care about this? this doubles the amt of
           * msgpack/unpack we have to do, but it allows us to always know
           * which ip sent us some information
           */
          messagesReceived++;
          blob.ip = rinfo.address;
          if (! logMessages[blob.path]) {
            logMessages[blob.path] = [];
          }
          logMessages[blob.path].push(blob);
          break;
        case types.COUNTER:
          /* statsd like counter */
          var sampleRate = blob.rate || 1;
          if (! counters[blob.key]) {
            counters[blob.key] = 0;
          }
          counters[blob.key] += Number((blob.value || 1) * (1 / sampleRate));
          break;
        case types.TIMER:
          /* statsd like timer */
          if (! timers[blob.key]) {
            timers[blob.key] = [];
          }
          timers[blob.key].push(blob.value);
          break;
        case types.DELETE_LOG:
          deleteLog(redisClient, blob.path);
        default: break;
      }
    });

    server.on("listening", function() {
      sys.log("logd listening on port " + port);
    });

    server.bind(port);
  }

  /* every second, print if we've received messages or not */
  var logInterval = Number(config.logInterval || 1000);

  logInt = setInterval(function() {
    if (messagesReceived != messagesReceivedPrev) {
      dmsg = messagesReceived - messagesReceivedPrev;
      messagesReceivedPrev = messagesReceived;
      sys.log("Received " + dmsg + " messages in 1s (" + messagesReceived + " total).");
    }
  }, logInterval);

  /* every second, flush local stats & messages to redis */
  var flushInterval = Number(config.flushInterval || 1000);

  flushInt = setInterval(function() {
    /* flush log messages */
    var messages, logger, size, msg;
    var allsize = Number(config.logSize['all'] || 250000);
    var logd = config.redis.prefix || 'logd';

    for (path in logMessages) {
      if (!logMessages[path] || !logMessages[path].length) continue;

      var base = logd + ':log:' + path;

      /* ids for these messages are simple monotonically increasing integers.
       * fetch the value for the next id from the database and add the cached
       * messages.
       */
      redisClient.get(base + ':next', function(base, path) {
          return function(err, next) {
            var messages = logMessages[path];
            var count = 0;
            var multi = redisClient.multi();
            next = Number(next);

            /* if there was no "next" setting, then this logger didn't exist yet.
             * add it to the list of paths and give it a next val
             */
            if (!next) {
              next = 1;
              redisClient.multi()
                .sadd('logd:paths', path)
                .set(base + ':next', next)
                .exec();
            }

            /* add the messages to the path's lists & ordered sets */
            for( ; count < messages.length; count++, next++) {
              msg = messages[count];
              msg.id = next;
              //  https://github.com/mranney/node_redis/pull/119
              //  fixed in 0.6.5
              var packed = msgpack.pack(msg);
              //var bufpacked = new Buffer(packed.length);
              //packed.copy(bufpacked)
              multi
                .set(base + ':' + next, packed)
                .lpush(base, next)
                .zadd(base + ':level:' + msg.level, -msg.time, next)
                .zadd(base + ':name:' + msg.name, -msg.time, next)
                .sadd(base + ':names', msg.name);
            }

            /* clear local cache, increment the in-redis next val, and flush */
            /*
            if (!count) {
              debugger;
            }
            */
            multi.incrby(base + ':next', count);
            multi.exec(redisErrback);
            logMessages[path] = [];
          };
        }(base, path)
      );
    }

  }, flushInterval);

  var trimInterval = Number(config.trimInterval || 10000);

  trimInt = setInterval(function() {
    trimLogs(redisClient, config);
  }, trimInterval)

  /* Every 10 seconds, flush stats to graphite.  This code is exactly
   * the same as the statsd code, as even the local storage is identical.
   */
  var statsInterval = Number(config.statsInterval || 10000);

  statsInt = setInterval(function() {
    var statString = '';
    var ts = Math.round(new Date().getTime() / 1000);
    var numStats = 0;
    var key;

    for (key in counters) {
      var value = counters[key] / (flushInterval / 1000);
      var message = 'stats.' + key + ' ' + value + ' ' + ts + "\n";
      message += 'stats.counts.' + key + ' ' + counters[key] + ' ' + ts + "\n";
      statString += message;
      counters[key] = 0;

      numStats += 1;
    }

    for (key in timers) {
      if (timers[key].length > 0) {
        var pctThreshold = config.percentThreshold || 90;
        var values = timers[key].sort(function (a,b) { return a-b; });
        var count = values.length;
        var min = values[0];
        var max = values[count - 1];

        var mean = min;
        var maxAtThreshold = max;

        if (count > 1) {
          var thresholdIndex = Math.round(((100 - pctThreshold) / 100) * count);
          var numInThreshold = count - thresholdIndex;
          values = values.slice(0, numInThreshold);
          maxAtThreshold = values[numInThreshold - 1];

          // average the remaining timings
          var sum = 0;
          for (var i = 0; i < numInThreshold; i++) {
            sum += values[i];
          }

          mean = sum / numInThreshold;
        }

        timers[key] = [];

        var message = "";
        message += 'stats.timers.' + key + '.mean ' + mean + ' ' + ts + "\n";
        message += 'stats.timers.' + key + '.upper ' + max + ' ' + ts + "\n";
        message += 'stats.timers.' + key + '.upper_' + pctThreshold + ' ' + maxAtThreshold + ' ' + ts + "\n";
        message += 'stats.timers.' + key + '.lower ' + min + ' ' + ts + "\n";
        message += 'stats.timers.' + key + '.count ' + count + ' ' + ts + "\n";
        statString += message;

        numStats += 1;
      }
    }

    statString += 'stats.numStats ' + numStats + ' ' + ts + "\n";
    if (numStats) {
      if (config.debug) {
        sys.log("Sending stats string: \n" + statString);
      }
      sendStats(config, statString);
    }

  }, statsInterval);

});

<|endoftext|>


<commit_before>function LogPacket(type, message, secret) {
	if (typeof(type) !== 'number') {
		throw new Error('invalid argument: type must be a number');
	}

	if (typeof(message) !== 'string') {
		throw new Error('invalid argument: message must be a string');
	}

	if (typeof(secret) !== 'undefined' && typeof(secret) !== 'string') {
		throw new Error('invalid argument: secret must be undefined or a string');
	}

	this._type = type;
	this._message = message;
}

LogPacket.prototype.getType = function() {
	return (typeof(this._type) === 'number') ? this._type : 0x00;
};

LogPacket.prototype.getMessage = function() {
	return (typeof(this._message) === 'string') ? this._message : false;
};

LogPacket.parse = function(buf, secret) {
	if (!(buf instanceof Buffer)) {
		throw new Error('invalid argument: buf must be a buffer');
	}

	if (typeof(secret) !== 'undefined' && typeof(secret) !== 'string') {
		throw new Error('invalid argument: secret must be undefined or a string');
	}

	if (buf.length < 7) throw new Error('packet too short (' + buf.length.toString() + ' < 7)');

	for (var i = 0; i < 4; i++) {
		if (buf[i] !== 0xFF) throw new Error('invalid header value');
	}

	if (buf[buf.length - 2] !== 0x0a || buf[buf.length - 1] !== 0x00) {
		throw new Error('invalid footer value');
	}

	var type = buf[4],
	    offset = 5;

	if (type === 0x53) {
		if (typeof(secret) === 'string') {
			offset += Buffer.byteLength(secret);
		} else {
			throw new Error('missing secret for packet type 0x53');
		}
	} else if (type !== 0x52) {
		throw new Error('invalid packet type ' + type.toString(16));
	}

	if (offset >= (buf.length - 2)) {
		throw new Error('packet too short to contain secret (invalid secret?)');
	}

	var msgbuf = buf.slice(offset, buf.length - 2);

	var message = msgbuf.toString();

	return new LogPacket(type, message, secret);
};

module.exports = LogPacket;
<commit_msg>Add extra error type for message being too short<commit_after>function LogPacket(type, message, secret) {
	if (typeof(type) !== 'number') {
		throw new Error('invalid argument: type must be a number');
	}

	if (typeof(message) !== 'string') {
		throw new Error('invalid argument: message must be a string');
	}

	if (typeof(secret) !== 'undefined' && typeof(secret) !== 'string') {
		throw new Error('invalid argument: secret must be undefined or a string');
	}

	this._type = type;
	this._message = message;
}

LogPacket.prototype.getType = function() {
	return (typeof(this._type) === 'number') ? this._type : 0x00;
};

LogPacket.prototype.getMessage = function() {
	return (typeof(this._message) === 'string') ? this._message : false;
};

LogPacket.parse = function(buf, secret) {
	if (!(buf instanceof Buffer)) {
		throw new Error('invalid argument: buf must be a buffer');
	}

	if (typeof(secret) !== 'undefined' && typeof(secret) !== 'string') {
		throw new Error('invalid argument: secret must be undefined or a string');
	}

	if (buf.length < 7) throw new Error('packet too short (' + buf.length.toString() + ' < 7)');

	for (var i = 0; i < 4; i++) {
		if (buf[i] !== 0xFF) throw new Error('invalid header value');
	}

	if (buf[buf.length - 2] !== 0x0a || buf[buf.length - 1] !== 0x00) {
		throw new Error('invalid footer value');
	}

	var type = buf[4],
	    offset = 5;

	if (type === 0x53) {
		if (typeof(secret) === 'string') {
			offset += Buffer.byteLength(secret);
		} else {
			throw new Error('missing secret for packet type 0x53');
		}
	} else if (type !== 0x52) {
		throw new Error('invalid packet type ' + type.toString(16));
	}

	if (offset >= (buf.length - 2)) {
		if (typeof(secret) === 'string') {
			throw new Error('packet too short to contain secret (invalid secret?)');
		} else {
			throw new Error('packet is empty');
		}
	}

	var msgbuf = buf.slice(offset, buf.length - 2);

	var message = msgbuf.toString();

	return new LogPacket(type, message, secret);
};

module.exports = LogPacket;
<|endoftext|>


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

(function(global, undefined) { "use strict";
var POW_2_24 = 5.960464477539063e-8,
    POW_2_32 = 4294967296,
    POW_2_53 = 9007199254740992;

function encode(value) {
  var data = new ArrayBuffer(256);
  var dataView = new DataView(data);
  var lastLength;
  var offset = 0;

  function ensureSpace(length) {
    var newByteLength = data.byteLength;
    var requiredLength = offset + length;
    while (newByteLength < requiredLength)
      newByteLength <<= 1;
    if (newByteLength !== data.byteLength) {
      var oldDataView = dataView;
      data = new ArrayBuffer(newByteLength);
      dataView = new DataView(data);
      var uint32count = (offset + 3) >> 2;
      for (var i = 0; i < uint32count; ++i)
        dataView.setUint32(i << 2, oldDataView.getUint32(i << 2));
    }

    lastLength = length;
    return dataView;
  }
  function write() {
    offset += lastLength;
  }
  function writeFloat64(value) {
    write(ensureSpace(8).setFloat64(offset, value));
  }
  function writeUint8(value) {
    write(ensureSpace(1).setUint8(offset, value));
  }
  function writeUint8Array(value) {
    var dataView = ensureSpace(value.length);
    for (var i = 0; i < value.length; ++i)
      dataView.setUint8(offset + i, value[i]);
    write();
  }
  function writeUint16(value) {
    write(ensureSpace(2).setUint16(offset, value));
  }
  function writeUint32(value) {
    write(ensureSpace(4).setUint32(offset, value));
  }
  function writeUint64(value) {
    var low = value % POW_2_32;
    var high = (value - low) / POW_2_32;
    var dataView = ensureSpace(8);
    dataView.setUint32(offset, high);
    dataView.setUint32(offset + 4, low);
    write();
  }
  function writeTypeAndLength(type, length) {
    if (length < 24) {
      writeUint8(type << 5 | length);
    } else if (length < 0x100) {
      writeUint8(type << 5 | 24);
      writeUint8(length);
    } else if (length < 0x10000) {
      writeUint8(type << 5 | 25);
      writeUint16(length);
    } else if (length < 0x100000000) {
      writeUint8(type << 5 | 26);
      writeUint32(length);
    } else {
      writeUint8(type << 5 | 27);
      writeUint64(length);
    }
  }

  function encodeItem(value) {
    var i;

    if (value === false)
      return writeUint8(0xf4);
    if (value === true)
      return writeUint8(0xf5);
    if (value === null)
      return writeUint8(0xf6);
    if (value === undefined)
      return writeUint8(0xf7);

    switch (typeof value) {
      case "number":
        if (Math.floor(value) === value) {
          if (0 <= value && value <= POW_2_53)
            return writeTypeAndLength(0, value);
          if (-POW_2_53 <= value && value < 0)
            return writeTypeAndLength(1, -(value + 1));
        }
        writeUint8(0xfb);
        return writeFloat64(value);

      case "string":
        var utf8data = [];
        for (i = 0; i < value.length; ++i) {
          var charCode = value.charCodeAt(i);
          if (charCode < 0x80) {
            utf8data.push(charCode);
          } else if (charCode < 0x800) {
            utf8data.push(0xc0 | charCode >> 6);
            utf8data.push(0x80 | charCode & 0x3f);
          } else if (charCode < 0xd800) {
            utf8data.push(0xe0 | charCode >> 12);
            utf8data.push(0x80 | (charCode >> 6)  & 0x3f);
            utf8data.push(0x80 | charCode & 0x3f);
          } else {
            charCode = (charCode & 0x3ff) << 10;
            charCode |= value.charCodeAt(++i) & 0x3ff;
            charCode += 0x10000;

            utf8data.push(0xf0 | charCode >> 18);
            utf8data.push(0x80 | (charCode >> 12)  & 0x3f);
            utf8data.push(0x80 | (charCode >> 6)  & 0x3f);
            utf8data.push(0x80 | charCode & 0x3f);
          }
        }

        writeTypeAndLength(3, utf8data.length);
        return writeUint8Array(utf8data);

      default:
        var length;
        if (Array.isArray(value)) {
          length = value.length;
          writeTypeAndLength(4, length);
          for (i = 0; i < length; ++i)
            encodeItem(value[i]);
        } else if (value instanceof Uint8Array) {
          writeTypeAndLength(2, value.length);
          writeUint8Array(value);
        } else {
          var keys = Object.keys(value);
          length = keys.length;
          writeTypeAndLength(5, length);
          for (i = 0; i < length; ++i) {
            var key = keys[i];
            encodeItem(key);
            encodeItem(value[key]);
          }
        }
    }
  }

  encodeItem(value);

  if ("slice" in data)
    return data.slice(0, offset);

  var ret = new ArrayBuffer(offset);
  var retView = new DataView(ret);
  for (var i = 0; i < offset; ++i)
    retView.setUint8(i, dataView.getUint8(i));
  return ret;
}

function decode(data, tagger, simpleValue) {
  var dataView = new DataView(data);
  var offset = 0;

  if (typeof tagger !== "function")
    tagger = function(value) { return value; };
  if (typeof simpleValue !== "function")
    simpleValue = function() { return undefined; };

  function read(value, length) {
    offset += length;
    return value;
  }
  function readArrayBuffer(length) {
    return read(new Uint8Array(data, offset, length), length);
  }
  function readFloat16() {
    var tempArrayBuffer = new ArrayBuffer(4);
    var tempDataView = new DataView(tempArrayBuffer);
    var value = readUint16();

    var sign = value & 0x8000;
    var exponent = value & 0x7c00;
    var fraction = value & 0x03ff;

    if (exponent === 0x7c00)
      exponent = 0xff << 10;
    else if (exponent !== 0)
      exponent += (127 - 15) << 10;
    else if (fraction !== 0)
      return fraction * POW_2_24;

    tempDataView.setUint32(0, sign << 16 | exponent << 13 | fraction << 13);
    return tempDataView.getFloat32(0);
  }
  function readFloat32() {
    return read(dataView.getFloat32(offset), 4);
  }
  function readFloat64() {
    return read(dataView.getFloat64(offset), 8);
  }
  function readUint8() {
    return read(dataView.getUint8(offset), 1);
  }
  function readUint16() {
    return read(dataView.getUint16(offset), 2);
  }
  function readUint32() {
    return read(dataView.getUint32(offset), 4);
  }
  function readUint64() {
    return readUint32() * POW_2_32 + readUint32();
  }
  function readBreak() {
    if (dataView.getUint8(offset) !== 0xff)
      return false;
    offset += 1;
    return true;
  }
  function readLength(additionalInformation) {
    if (additionalInformation < 24)
      return additionalInformation;
    if (additionalInformation === 24)
      return readUint8();
    if (additionalInformation === 25)
      return readUint16();
    if (additionalInformation === 26)
      return readUint32();
    if (additionalInformation === 27)
      return readUint64();
    if (additionalInformation === 31)
      return -1;
    throw "Invalid length encoding";
  }
  function readIndefiniteStringLength(majorType) {
    var initialByte = readUint8();
    if (initialByte === 0xff)
      return -1;
    var length = readLength(initialByte & 0x1f);
    if (length < 0 || (initialByte >> 5) !== majorType)
      throw "Invalid indefinite length element";
    return length;
  }

  function appendUtf16data(utf16data, length) {
    for (var i = 0; i < length; ++i) {
      var value = readUint8();
      if (value & 0x80) {
        if (value < 0xe0) {
          value = (value & 0x1f) <<  6
                | (readUint8() & 0x3f);
          length -= 1;
        } else if (value < 0xf0) {
          value = (value & 0x0f) << 12
                | (readUint8() & 0x3f) << 6
                | (readUint8() & 0x3f);
          length -= 2;
        } else {
          value = (value & 0x0f) << 18
                | (readUint8() & 0x3f) << 12
                | (readUint8() & 0x3f) << 6
                | (readUint8() & 0x3f);
          length -= 3;
        }
      }

      if (value < 0x10000) {
        utf16data.push(value);
      } else {
        value -= 0x10000;
        utf16data.push(0xd800 | (value >> 10));
        utf16data.push(0xdc00 | (value & 0x3ff));
      }
    }
  }

  function decodeItem() {
    var initialByte = readUint8();
    var majorType = initialByte >> 5;
    var additionalInformation = initialByte & 0x1f;
    var i;
    var length;

    if (majorType === 7) {
      switch (additionalInformation) {
        case 25:
          return readFloat16();
        case 26:
          return readFloat32();
        case 27:
          return readFloat64();
      }
    }

    length = readLength(additionalInformation);
    if (length < 0 && (majorType < 2 || 6 < majorType))
      throw "Invalid length";

    switch (majorType) {
      case 0:
        return length;
      case 1:
        return -1 - length;
      case 2:
        if (length < 0) {
          var elements = [];
          var fullArrayLength = 0;
          while ((length = readIndefiniteStringLength(majorType)) >= 0) {
            fullArrayLength += length;
            elements.push(readArrayBuffer(length));
          }
          var fullArray = new Uint8Array(fullArrayLength);
          var fullArrayOffset = 0;
          for (i = 0; i < elements.length; ++i) {
            fullArray.set(elements[i], fullArrayOffset);
            fullArrayOffset += elements[i].length;
          }
          return fullArray;
        }
        return readArrayBuffer(length);
      case 3:
        var utf16data = [];
        if (length < 0) {
          while ((length = readIndefiniteStringLength(majorType)) >= 0)
            appendUtf16data(utf16data, length);
        } else
          appendUtf16data(utf16data, length);
        return String.fromCharCode.apply(null, utf16data);
      case 4:
        var retArray;
        if (length < 0) {
          retArray = [];
          while (!readBreak())
            retArray.push(decodeItem());
        } else {
          retArray = new Array(length);
          for (i = 0; i < length; ++i)
            retArray[i] = decodeItem();
        }
        return retArray;
      case 5:
        var retObject = {};
        for (i = 0; i < length || length < 0 && !readBreak(); ++i) {
          var key = decodeItem();
          retObject[key] = decodeItem();
        }
        return retObject;
      case 6:
        return tagger(decodeItem(), length);
      case 7:
        switch (length) {
          case 20:
            return false;
          case 21:
            return true;
          case 22:
            return null;
          case 23:
            return undefined;
          default:
            return simpleValue(length);
        }
    }
  }

  var ret = decodeItem();
  if (offset !== data.byteLength)
    throw "Remaining bytes";
  return ret;
}

var obj = { encode: encode, decode: decode };

if (typeof define === "function" && define.amd)
  define("cbor/cbor", obj);
else if (!global.CBOR)
  global.CBOR = obj;

})(this);
<commit_msg>Rename functions to better match their purpose<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Patrick Gansterer <paroga@paroga.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

(function(global, undefined) { "use strict";
var POW_2_24 = 5.960464477539063e-8,
    POW_2_32 = 4294967296,
    POW_2_53 = 9007199254740992;

function encode(value) {
  var data = new ArrayBuffer(256);
  var dataView = new DataView(data);
  var lastLength;
  var offset = 0;

  function prepareWrite(length) {
    var newByteLength = data.byteLength;
    var requiredLength = offset + length;
    while (newByteLength < requiredLength)
      newByteLength <<= 1;
    if (newByteLength !== data.byteLength) {
      var oldDataView = dataView;
      data = new ArrayBuffer(newByteLength);
      dataView = new DataView(data);
      var uint32count = (offset + 3) >> 2;
      for (var i = 0; i < uint32count; ++i)
        dataView.setUint32(i << 2, oldDataView.getUint32(i << 2));
    }

    lastLength = length;
    return dataView;
  }
  function commitWrite() {
    offset += lastLength;
  }
  function writeFloat64(value) {
    commitWrite(prepareWrite(8).setFloat64(offset, value));
  }
  function writeUint8(value) {
    commitWrite(prepareWrite(1).setUint8(offset, value));
  }
  function writeUint8Array(value) {
    var dataView = prepareWrite(value.length);
    for (var i = 0; i < value.length; ++i)
      dataView.setUint8(offset + i, value[i]);
    commitWrite();
  }
  function writeUint16(value) {
    commitWrite(prepareWrite(2).setUint16(offset, value));
  }
  function writeUint32(value) {
    commitWrite(prepareWrite(4).setUint32(offset, value));
  }
  function writeUint64(value) {
    var low = value % POW_2_32;
    var high = (value - low) / POW_2_32;
    var dataView = prepareWrite(8);
    dataView.setUint32(offset, high);
    dataView.setUint32(offset + 4, low);
    commitWrite();
  }
  function writeTypeAndLength(type, length) {
    if (length < 24) {
      writeUint8(type << 5 | length);
    } else if (length < 0x100) {
      writeUint8(type << 5 | 24);
      writeUint8(length);
    } else if (length < 0x10000) {
      writeUint8(type << 5 | 25);
      writeUint16(length);
    } else if (length < 0x100000000) {
      writeUint8(type << 5 | 26);
      writeUint32(length);
    } else {
      writeUint8(type << 5 | 27);
      writeUint64(length);
    }
  }

  function encodeItem(value) {
    var i;

    if (value === false)
      return writeUint8(0xf4);
    if (value === true)
      return writeUint8(0xf5);
    if (value === null)
      return writeUint8(0xf6);
    if (value === undefined)
      return writeUint8(0xf7);

    switch (typeof value) {
      case "number":
        if (Math.floor(value) === value) {
          if (0 <= value && value <= POW_2_53)
            return writeTypeAndLength(0, value);
          if (-POW_2_53 <= value && value < 0)
            return writeTypeAndLength(1, -(value + 1));
        }
        writeUint8(0xfb);
        return writeFloat64(value);

      case "string":
        var utf8data = [];
        for (i = 0; i < value.length; ++i) {
          var charCode = value.charCodeAt(i);
          if (charCode < 0x80) {
            utf8data.push(charCode);
          } else if (charCode < 0x800) {
            utf8data.push(0xc0 | charCode >> 6);
            utf8data.push(0x80 | charCode & 0x3f);
          } else if (charCode < 0xd800) {
            utf8data.push(0xe0 | charCode >> 12);
            utf8data.push(0x80 | (charCode >> 6)  & 0x3f);
            utf8data.push(0x80 | charCode & 0x3f);
          } else {
            charCode = (charCode & 0x3ff) << 10;
            charCode |= value.charCodeAt(++i) & 0x3ff;
            charCode += 0x10000;

            utf8data.push(0xf0 | charCode >> 18);
            utf8data.push(0x80 | (charCode >> 12)  & 0x3f);
            utf8data.push(0x80 | (charCode >> 6)  & 0x3f);
            utf8data.push(0x80 | charCode & 0x3f);
          }
        }

        writeTypeAndLength(3, utf8data.length);
        return writeUint8Array(utf8data);

      default:
        var length;
        if (Array.isArray(value)) {
          length = value.length;
          writeTypeAndLength(4, length);
          for (i = 0; i < length; ++i)
            encodeItem(value[i]);
        } else if (value instanceof Uint8Array) {
          writeTypeAndLength(2, value.length);
          writeUint8Array(value);
        } else {
          var keys = Object.keys(value);
          length = keys.length;
          writeTypeAndLength(5, length);
          for (i = 0; i < length; ++i) {
            var key = keys[i];
            encodeItem(key);
            encodeItem(value[key]);
          }
        }
    }
  }

  encodeItem(value);

  if ("slice" in data)
    return data.slice(0, offset);

  var ret = new ArrayBuffer(offset);
  var retView = new DataView(ret);
  for (var i = 0; i < offset; ++i)
    retView.setUint8(i, dataView.getUint8(i));
  return ret;
}

function decode(data, tagger, simpleValue) {
  var dataView = new DataView(data);
  var offset = 0;

  if (typeof tagger !== "function")
    tagger = function(value) { return value; };
  if (typeof simpleValue !== "function")
    simpleValue = function() { return undefined; };

  function commitRead(length, value) {
    offset += length;
    return value;
  }
  function readArrayBuffer(length) {
    return commitRead(length, new Uint8Array(data, offset, length));
  }
  function readFloat16() {
    var tempArrayBuffer = new ArrayBuffer(4);
    var tempDataView = new DataView(tempArrayBuffer);
    var value = readUint16();

    var sign = value & 0x8000;
    var exponent = value & 0x7c00;
    var fraction = value & 0x03ff;

    if (exponent === 0x7c00)
      exponent = 0xff << 10;
    else if (exponent !== 0)
      exponent += (127 - 15) << 10;
    else if (fraction !== 0)
      return fraction * POW_2_24;

    tempDataView.setUint32(0, sign << 16 | exponent << 13 | fraction << 13);
    return tempDataView.getFloat32(0);
  }
  function readFloat32() {
    return commitRead(4, dataView.getFloat32(offset));
  }
  function readFloat64() {
    return commitRead(8, dataView.getFloat64(offset));
  }
  function readUint8() {
    return commitRead(1, dataView.getUint8(offset));
  }
  function readUint16() {
    return commitRead(2, dataView.getUint16(offset));
  }
  function readUint32() {
    return commitRead(4, dataView.getUint32(offset));
  }
  function readUint64() {
    return readUint32() * POW_2_32 + readUint32();
  }
  function readBreak() {
    if (dataView.getUint8(offset) !== 0xff)
      return false;
    offset += 1;
    return true;
  }
  function readLength(additionalInformation) {
    if (additionalInformation < 24)
      return additionalInformation;
    if (additionalInformation === 24)
      return readUint8();
    if (additionalInformation === 25)
      return readUint16();
    if (additionalInformation === 26)
      return readUint32();
    if (additionalInformation === 27)
      return readUint64();
    if (additionalInformation === 31)
      return -1;
    throw "Invalid length encoding";
  }
  function readIndefiniteStringLength(majorType) {
    var initialByte = readUint8();
    if (initialByte === 0xff)
      return -1;
    var length = readLength(initialByte & 0x1f);
    if (length < 0 || (initialByte >> 5) !== majorType)
      throw "Invalid indefinite length element";
    return length;
  }

  function appendUtf16Data(utf16data, length) {
    for (var i = 0; i < length; ++i) {
      var value = readUint8();
      if (value & 0x80) {
        if (value < 0xe0) {
          value = (value & 0x1f) <<  6
                | (readUint8() & 0x3f);
          length -= 1;
        } else if (value < 0xf0) {
          value = (value & 0x0f) << 12
                | (readUint8() & 0x3f) << 6
                | (readUint8() & 0x3f);
          length -= 2;
        } else {
          value = (value & 0x0f) << 18
                | (readUint8() & 0x3f) << 12
                | (readUint8() & 0x3f) << 6
                | (readUint8() & 0x3f);
          length -= 3;
        }
      }

      if (value < 0x10000) {
        utf16data.push(value);
      } else {
        value -= 0x10000;
        utf16data.push(0xd800 | (value >> 10));
        utf16data.push(0xdc00 | (value & 0x3ff));
      }
    }
  }

  function decodeItem() {
    var initialByte = readUint8();
    var majorType = initialByte >> 5;
    var additionalInformation = initialByte & 0x1f;
    var i;
    var length;

    if (majorType === 7) {
      switch (additionalInformation) {
        case 25:
          return readFloat16();
        case 26:
          return readFloat32();
        case 27:
          return readFloat64();
      }
    }

    length = readLength(additionalInformation);
    if (length < 0 && (majorType < 2 || 6 < majorType))
      throw "Invalid length";

    switch (majorType) {
      case 0:
        return length;
      case 1:
        return -1 - length;
      case 2:
        if (length < 0) {
          var elements = [];
          var fullArrayLength = 0;
          while ((length = readIndefiniteStringLength(majorType)) >= 0) {
            fullArrayLength += length;
            elements.push(readArrayBuffer(length));
          }
          var fullArray = new Uint8Array(fullArrayLength);
          var fullArrayOffset = 0;
          for (i = 0; i < elements.length; ++i) {
            fullArray.set(elements[i], fullArrayOffset);
            fullArrayOffset += elements[i].length;
          }
          return fullArray;
        }
        return readArrayBuffer(length);
      case 3:
        var utf16data = [];
        if (length < 0) {
          while ((length = readIndefiniteStringLength(majorType)) >= 0)
            appendUtf16Data(utf16data, length);
        } else
          appendUtf16Data(utf16data, length);
        return String.fromCharCode.apply(null, utf16data);
      case 4:
        var retArray;
        if (length < 0) {
          retArray = [];
          while (!readBreak())
            retArray.push(decodeItem());
        } else {
          retArray = new Array(length);
          for (i = 0; i < length; ++i)
            retArray[i] = decodeItem();
        }
        return retArray;
      case 5:
        var retObject = {};
        for (i = 0; i < length || length < 0 && !readBreak(); ++i) {
          var key = decodeItem();
          retObject[key] = decodeItem();
        }
        return retObject;
      case 6:
        return tagger(decodeItem(), length);
      case 7:
        switch (length) {
          case 20:
            return false;
          case 21:
            return true;
          case 22:
            return null;
          case 23:
            return undefined;
          default:
            return simpleValue(length);
        }
    }
  }

  var ret = decodeItem();
  if (offset !== data.byteLength)
    throw "Remaining bytes";
  return ret;
}

var obj = { encode: encode, decode: decode };

if (typeof define === "function" && define.amd)
  define("cbor/cbor", obj);
else if (!global.CBOR)
  global.CBOR = obj;

})(this);
<|endoftext|>


<commit_before>"using strict";
var chatBox = document.getElementById("chatBox");
var tabs = document.getElementById("tabs");
function addSpan(span, name) {
	span.appendChild(document.createElement("br"));
	if (name){
		var tab = tabMap[name];
		var tabBox = tab[0];
	}else{
		var tabBox = chatBox;
	}
	if (tabBox == chatBox){
		var scroll = Math.abs(chatBox.scrollTop - chatBox.scrollHeight + chatBox.offsetHeight) < 2;
		chatBox.appendChild(span);
		if (scroll) chatBox.scrollTop = chatBox.scrollHeight;
	}else{
		tabBox.appendChild(span);
		tab[1].style.fontWeight = "bold";
	}
}
function chat(msg, fontcolor, name) {
	var span = document.createElement("span");
	if (fontcolor in tabMap) name = fontcolor;
	else if (fontcolor) span.style.color = fontcolor;
	span.appendChild(document.createTextNode(msg));
	addSpan(span, name);
}
module.exports = chat;
var tabMap = {};
chat.addTab = function(name, div){
	var span = document.createElement("span");
	var tabBox = div || document.createElement("div");
	tabBox.id = "chatBox";
	tabMap[name] = [tabBox, span];
	span.className = "tab";
	span.appendChild(document.createTextNode(name));
	span.addEventListener("click", function(){
		this.style.fontWeight = "";
		if (chatBox != tabBox){
			chatBox.parentElement.insertBefore(tabBox, chatBox);
			chatBox.remove();
			chatBox = tabBox;
		}
		chatBox.scrollTop = chatBox.scrollHeight;
	});
	tabs.appendChild(document.createTextNode(" "));
	tabs.appendChild(span);
}
chat.addTab("Main", chatBox);
chat.addTab("System");
chat.addTab("Stats");
chat.addSpan = addSpan;
chat.clear = function(name){
	if (name){
		var tab = tabMap[name];
		var tabBox = tab[0];
	}else{
		var tabBox = chatBox;
	}
	while (tabBox.firstChild) tabBox.firstChild.remove();
}
<commit_msg>All messages appear in Main<commit_after>"using strict";
var chatBox = document.getElementById("chatBox");
var tabs = document.getElementById("tabs");
function addSpan(span, name) {
	if (name){
		var tab = tabMap[name];
		var tabBox = tab[0];
	}else{
		var tabBox = chatBox;
	}
	if (tabBox != tabMap.Main[0]){
		addSpan(span.cloneNode(true), "Main")
	}
	span.appendChild(document.createElement("br"));
	if (tabBox == chatBox){
		var scroll = Math.abs(chatBox.scrollTop - chatBox.scrollHeight + chatBox.offsetHeight) < 2;
		chatBox.appendChild(span);
		if (scroll) chatBox.scrollTop = chatBox.scrollHeight;
	}else{
		tabBox.appendChild(span);
		tab[1].style.fontWeight = "bold";
	}
}
function chat(msg, fontcolor, name) {
	var span = document.createElement("span");
	if (fontcolor in tabMap) name = fontcolor;
	else if (fontcolor) span.style.color = fontcolor;
	span.appendChild(document.createTextNode(msg));
	addSpan(span, name);
}
module.exports = chat;
var tabMap = {};
chat.addTab = function(name, div){
	var span = document.createElement("span");
	var tabBox = div || document.createElement("div");
	tabBox.id = "chatBox";
	tabMap[name] = [tabBox, span];
	span.className = "tab";
	span.appendChild(document.createTextNode(name));
	span.addEventListener("click", function(){
		this.style.fontWeight = "";
		if (chatBox != tabBox){
			chatBox.parentElement.insertBefore(tabBox, chatBox);
			chatBox.remove();
			chatBox = tabBox;
		}
		chatBox.scrollTop = chatBox.scrollHeight;
	});
	tabs.appendChild(document.createTextNode(" "));
	tabs.appendChild(span);
}
chat.addTab("Main", chatBox);
chat.addTab("System");
chat.addTab("Stats");
chat.addSpan = addSpan;
chat.clear = function(name){
	if (name){
		var tab = tabMap[name];
		var tabBox = tab[0];
	}else{
		var tabBox = chatBox;
	}
	while (tabBox.firstChild) tabBox.firstChild.remove();
}
<|endoftext|>