<commit_before>const Eris = require('eris'), //The bot's api library
    chalk = require('chalk'), //Used to make the console have pretty colours
    fs = require('fs'), //For reading/writing to a file
    axios = require('axios'), //HTTP client for requests to and from websites
    options = require('./options/options.json'),
    CommandLoader = require('./utils/commandLoader.js'),
    utils = require('./utils/utils.js'),
    Database = require('./utils/database.js'),
    //List of playing status's for the bot to use
    playing = require('./lists/playing.json'),
    processCmd = require('./utils/commandHandler.js'),
    UsageChecker = require('./utils/usageChecker.js'),
    //This isn't normally needed but PM2 doesn't work with chalk unless I do this
    colour = new chalk.constructor({
        enabled: true
    }),
    //Unflipped tables for use with the auto-table-unfipper
    unflippedTables = ["┬─┬ ︵ /(.□. \\\\)", "┬─┬ノ( º _ ºノ)", "┬─┬ ノ( ゜-゜ノ)", "┬─┬ ノ( ^_^ノ)", "┬──┬ ¯\\\\_(ツ)", "(╯°□°）╯︵ /(.□. \\\\)"];

let urls = ['https://www.twitch.tv/winningthewaronpants'], //Twitch URLS the bot pulls from to link to in the Streaming Status
    //Bot Constructor Creation check https://abal.moe/Eris/Client.html for more info
    bot = new Eris(options.token, {
        getAllUsers: true,
        messageLimit: 0,
        maxShards: 8,
        autoReconnect: true,
        disableEveryone: true,
        disabledEvents: {
            VOICE_STATE_UPDATE: true,
            TYPING_START: true,
            GUILD_EMOJI_UPDATE: true,
            GUILD_INTEGRATIONS_UPDATE: true,
            GUILD_BAN_ADD: true,
            GUILD_BAN_REMOVE: true,
            MESSAGE_UPDATE: true,
            CHANNEL_CREATE: true,
            CHANNEL_DELETE: true
        }
    });

//Make Promises faster and more efficent by using BlueBirds Implmentation of them
global.Promise = require('bluebird'),
//Console Log Colours
botC = colour.magenta.bold,
userC = colour.cyan.bold,
serverC = colour.black.bold,
channelC = colour.green.bold,
miscC = colour.blue.bold,
warningC = colour.yellow.bold,
errorC = colour.red.bold;

//Ready Event
bot.on("ready", () => {
    //Sets the status's of every shard seperately
    utils.setRandomStatus(bot, playing, urls)
    //This stuff below is sent to the console when the bot is ready
    console.log(botC(bot.user.username + " is now Ready."));
    console.log('Current # of Commands Loaded: ' + warningC(Object.keys(commands).length))
    console.log("Users: " + userC(bot.users.size) + " | Channels: " + channelC(Object.keys(bot.channelGuildMap).length) + " | Servers: " + serverC(bot.guilds.size))
    //Run inactivity checker and output the number of inactive servers
    UsageChecker.checkInactivity(bot).then(response => console.log(botC(response))).catch(err => console.log(errorC(err)));
})

//On Message Creation Event
bot.on("messageCreate", msg => {
    //If bot isn't ready or if the message author is a bot who isn't Kimi do nothing with the message
    if (!bot.ready || (msg.author.bot && msg.author.id !== "174669219659513856")) return;
    else if (msg.author.id !== '87600987040120832') return;
    else {
        //If used in guild and the guild has a custom prefix set the msgPrefix as such otherwise grab the default prefix
        let msgPrefix = msg.channel.guild && Database.getPrefix(msg.channel.guild.id) != undefined ? Database.getPrefix(msg.channel.guild.id) : options.prefix;
        //Use Eval on the message if it starts with sudo and used by Mei
        if (msg.content.split(" ")[0] === "sudo" && msg.author.id === "87600987040120832") {
            evalText(msg, msg.content.substring((msg.content.split(" ")[0].substring(1)).length + 2));
            return;
        }
        //If stuff that isn't a command is used in a PM treat it as using cleverbot by adding the correct prefix as well as the 'chat' command text to the message
        if (!msg.channel.guild && !msg.content.startsWith(options.prefix)) msg.content = msgPrefix + "chat " + msg.content;
        //If used in a Guild
        if (msg.channel.guild) {
            //If Message is a tableFlip and the Guild has tableflip(tableunflip) on return an unflipped table
            if (msg.content === "(╯°□°）╯︵ ┻━┻") Database.checkSetting(msg.channel.guild.id, 'tableflip').then(() => bot.createMessage(msg.channel.id, tablesUnFlipped[~~(Math.random() * (unflippedTables.length))])).catch(err => utils.fileLog(err))
                //Check if message starts with a bot user mention and if so replace with the correct prefix and the 'chat' command text
            if (msg.content.replace(/<@!/g, "<@").startsWith(bot.user.mention)) msg.content = msg.content.replace(/<@!/g, "<@").replace(bot.user.mention, msgPrefix + "chat");
            //Prefix command override so that prefix can be used with the default command prefix to prevent forgotten prefixes
            if (msg.content.startsWith(options.prefix + "prefix")) msg.content = msg.content.replace(options.prefix, msgPrefix)
        }
        //If the message stats with the set prefix
        if (msg.content.startsWith(msgPrefix)) {
            let formatedMsg = msg.content.substring(msgPrefix.length, msg.content.length), //Format message to remove command prefix
                cmdTxt = formatedMsg.split(" ")[0].toLowerCase(), //Get command from the formated message
                args = formatedMsg.substring((formatedMsg.split(" ")[0]).length + 1); //Get arguments from the formated message
            if (commandAliases.hasOwnProperty(cmdTxt)) cmdTxt = commandAliases[cmdTxt]; //If the cmdTxt is an alias of the command
            if (cmdTxt === 'channelmute') processCmd(msg, args, commands[cmdTxt], bot); //Override channelCheck if cmd is channelmute to unmute a muted channel
            //Check if a Command was used and runs the corresponding code depending on if it was used in a Guild or not, if in guild checks for muted channel and disabled command
            else if (commands.hasOwnProperty(cmdTxt)) Database.checkChannel(msg.channel.id).then(() => Database.checkCommand(msg.channel.guild.id, cmdTxt).then(() => processCmd(msg, args, commands[cmdTxt], bot)))
        }
    }
});

function evalText(msg, args) {
    let result;
    //Trys to run eval on the text and output either an error or the result if applicable
    try {
        result = eval("try{" + args + "}catch(err){utils.fileLog(err);bot.createMessage(msg.channel.id, \"```\"+err+\"```\");}");
    } catch (e) {
        utils.fileLog(e);
        bot.createMessage(msg.channel.id, "```" + e + "```");
    }
    if (result && typeof result !== "object") bot.createMessage(msg.channel.id, result);
    else if (result && typeof result === "object") bot.createMessage(msg.channel.id, "```xl\n" + result + "```");
}

//New Guild Member Event
bot.on("guildMemberAdd", (guild, member) => {
    //Checks to make sure guild and a member was sent
    if (guild && member) {
        //Checks to see if the guild has a welcome set and if so replaces the correct strings with the correct info
        Database.checkSetting(guild.id, 'welcome').then(response => {
            let message = response.response.replace(/\[GuildName]/g, guild.name).replace(/\[ChannelName]/g, guild.channels.get(response.channel.toString()).name).replace(/\[ChannelMention]/g, guild.channels.get(response.channel.toString()).mention).replace(/\[UserName]/g, member.user.username).replace(/\[UserMention]/g, member.user.mention);
            bot.createMessage(response.channel, message);
        }).catch(err => utils.fileLog(err));
    }
})

//Guild Member Left Event
bot.on("guildMemberRemove", (guild, member) => {
    //Checks to make sure guild and a member was sent
    if (guild && member) {
        //Checks to see if the guild has a leave set and if so replaces the correct strings with the correct info
        Database.checkSetting(guild.id, 'leave').then(response => {
            let message = response.response.replace(/\[GuildName]/g, guild.name).replace(/\[ChannelName]/g, guild.channels.get(response.channel.toString()).name).replace(/\[ChannelMention]/g, guild.channels.get(response.channel.toString()).mention).replace(/\[UserName]/g, member.user.username);
            bot.createMessage(response.channel, message)
        }).catch(err => utils.fileLog(err))
    }
})

//Guild Joined Event
bot.on('guildCreate', guild => {
    //Post Guild Count
    postGuildCount()
    //Add guild to UsageChecker database
    UsageChecker.addToUsageCheck(guild.id);
})

//Guild Left Event
bot.on('guildDelete', guild => {
    //Post Guild Count
    postGuildCount()
    //Remove Guild from Database and log if error
    Database.removeGuild(guild.id).catch(err => utils.fileLog(err))
    //Remove guild from guildPrefix array if it exists in it
    Database.removeGuildfromJson(guild.id)
    //Remove from UsageChecker database
    UsageChecker.removeFromUsageCheck(guild.id);
})

//Load Commands then Connect(Logs any errors to console and file)
CommandLoader.load().then(() => {
    bot.connect().then(console.log(warningC("Logged in using Token")))
}).catch(err => utils.fileLog(err));

//Posts Guild Count to Discord Bots and Carbonitex
function postGuildCount() {
    //Check that the bot is ready so premature guild creates won't cause a crash
    if (bot.ready) {
        //Post Guild Count to Discord Bots and if error log to file and console
        axios({
            method: 'post',
            url: "https://bots.discord.pw/api/bots/" + bot.user.id + "/stats",
            headers: {
                "Authorization": options.bot_key,
                "content-type": "application/json"
            },
            data: {
                "server_count": bot.guilds.size
            }
        }).catch(err => utils.fileLog(err));
        //Post Guild Count to Carbonitex and if error log to file and console
        axios({
            method: 'post',
            url: "https://www.carbonitex.net/discord/data/botdata.php",
            headers: {
                "content-type": "application/json"
            },
            data: {
                "key": options.carbon_key,
                "servercount": bot.guilds.size
            }
        }).catch(err => utils.fileLog(err));
    }
}

//Changes the bots status every 10mins
setInterval(() => utils.setRandomStatus(bot, playing, urls), 6e+5);

//Changes the bots avatar every 2hrs
setInterval(() => {
    //Reads avatar directory and randomly picks an avatar to switch to
    fs.readdir(`${__dirname}/avatars/`, (err, files) => {
        if (err) utils.fileLog(err)
        else {
            let avatar = files[~~(Math.random() * (files.length))];
            //Reads the avatar image file and changes the bots avatar to it
            fs.readFile(`${__dirname}/avatars/${avatar}`, (err, image) => {
                if (err) utils.fileLog(err)
                else {
                    let data = "data:image/jpg;base64," + image.toString('base64');
                    bot.editSelf({
                        avatar: data
                    }).then(() => console.log(botC('Changed avatar to ' + avatar))).catch(err => utils.fileLog(err));
                }
            })
        }
    });
}, 7.2e+6);

//Bot Error Event
bot.on("error", err => utils.fileLog(err)) //Logs error to file and console

//Bot Warn Event(Outputs issues that aren't major)
bot.on("warn", (warn, id) => {
    console.log(warningC(warn, id));
})

//Debug event only used to find errors and usually disabled
//bot.on("debug", console.log)

//Shard Resume Event
bot.on('shardResume', id => {
    console.log(botC("@" + bot.user.username) + " - " + warningC("SHARD #" + id + "RECONNECTED"));
})

//Shard Disconnect Event
bot.on("shardDisconnect", (err, id) => {
    console.log(botC("@" + bot.user.username) + " - " + warningC("SHARD #" + id + "DISCONNECTED"));
    utils.fileLog(err); //Logs reason/error to file and console
})

//Whole Bot Disconnect Event
bot.on("disconnect", err => {
    console.log(botC("@" + bot.user.username) + " - " + errorC("DISCONNECTED"));
    utils.fileLog(err); //Logs Disconnect reason/error to file and console
    process.exit(0);
})<commit_msg>Fixed the use of an old var name<commit_after>const Eris = require('eris'), //The bot's api library
    chalk = require('chalk'), //Used to make the console have pretty colours
    fs = require('fs'), //For reading/writing to a file
    axios = require('axios'), //HTTP client for requests to and from websites
    options = require('./options/options.json'),
    CommandLoader = require('./utils/commandLoader.js'),
    utils = require('./utils/utils.js'),
    Database = require('./utils/database.js'),
    //List of playing status's for the bot to use
    playing = require('./lists/playing.json'),
    processCmd = require('./utils/commandHandler.js'),
    UsageChecker = require('./utils/usageChecker.js'),
    //This isn't normally needed but PM2 doesn't work with chalk unless I do this
    colour = new chalk.constructor({
        enabled: true
    }),
    //Unflipped tables for use with the auto-table-unfipper
    unflippedTables = ["┬─┬ ︵ /(.□. \\\\)", "┬─┬ノ( º _ ºノ)", "┬─┬ ノ( ゜-゜ノ)", "┬─┬ ノ( ^_^ノ)", "┬──┬ ¯\\\\_(ツ)", "(╯°□°）╯︵ /(.□. \\\\)"];

let urls = ['https://www.twitch.tv/winningthewaronpants'], //Twitch URLS the bot pulls from to link to in the Streaming Status
    //Bot Constructor Creation check https://abal.moe/Eris/Client.html for more info
    bot = new Eris(options.token, {
        getAllUsers: true,
        messageLimit: 0,
        maxShards: 8,
        autoReconnect: true,
        disableEveryone: true,
        disabledEvents: {
            VOICE_STATE_UPDATE: true,
            TYPING_START: true,
            GUILD_EMOJI_UPDATE: true,
            GUILD_INTEGRATIONS_UPDATE: true,
            GUILD_BAN_ADD: true,
            GUILD_BAN_REMOVE: true,
            MESSAGE_UPDATE: true,
            CHANNEL_CREATE: true,
            CHANNEL_DELETE: true
        }
    });

//Make Promises faster and more efficent by using BlueBirds Implmentation of them
global.Promise = require('bluebird'),
//Console Log Colours
botC = colour.magenta.bold,
userC = colour.cyan.bold,
serverC = colour.black.bold,
channelC = colour.green.bold,
miscC = colour.blue.bold,
warningC = colour.yellow.bold,
errorC = colour.red.bold;

//Ready Event
bot.on("ready", () => {
    //Sets the status's of every shard seperately
    utils.setRandomStatus(bot, playing, urls)
    //This stuff below is sent to the console when the bot is ready
    console.log(botC(bot.user.username + " is now Ready."));
    console.log('Current # of Commands Loaded: ' + warningC(Object.keys(commands).length))
    console.log("Users: " + userC(bot.users.size) + " | Channels: " + channelC(Object.keys(bot.channelGuildMap).length) + " | Servers: " + serverC(bot.guilds.size))
    //Run inactivity checker and output the number of inactive servers
    UsageChecker.checkInactivity(bot).then(response => console.log(botC(response))).catch(err => console.log(errorC(err)));
})

//On Message Creation Event
bot.on("messageCreate", msg => {
    //If bot isn't ready or if the message author is a bot who isn't Kimi do nothing with the message
    if (!bot.ready || (msg.author.bot && msg.author.id !== "174669219659513856")) return;
    else if (msg.author.id !== '87600987040120832') return;
    else {
        //If used in guild and the guild has a custom prefix set the msgPrefix as such otherwise grab the default prefix
        let msgPrefix = msg.channel.guild && Database.getPrefix(msg.channel.guild.id) != undefined ? Database.getPrefix(msg.channel.guild.id) : options.prefix;
        //Use Eval on the message if it starts with sudo and used by Mei
        if (msg.content.split(" ")[0] === "sudo" && msg.author.id === "87600987040120832") {
            evalText(msg, msg.content.substring((msg.content.split(" ")[0].substring(1)).length + 2));
            return;
        }
        //If stuff that isn't a command is used in a PM treat it as using cleverbot by adding the correct prefix as well as the 'chat' command text to the message
        if (!msg.channel.guild && !msg.content.startsWith(options.prefix)) msg.content = msgPrefix + "chat " + msg.content;
        //If used in a Guild
        if (msg.channel.guild) {
            //If Message is a tableFlip and the Guild has tableflip(tableunflip) on return an unflipped table
            if (msg.content === "(╯°□°）╯︵ ┻━┻") Database.checkSetting(msg.channel.guild.id, 'tableflip').then(() => bot.createMessage(msg.channel.id, unflippedTables[~~(Math.random() * (unflippedTables.length))])).catch(err => utils.fileLog(err))
                //Check if message starts with a bot user mention and if so replace with the correct prefix and the 'chat' command text
            if (msg.content.replace(/<@!/g, "<@").startsWith(bot.user.mention)) msg.content = msg.content.replace(/<@!/g, "<@").replace(bot.user.mention, msgPrefix + "chat");
            //Prefix command override so that prefix can be used with the default command prefix to prevent forgotten prefixes
            if (msg.content.startsWith(options.prefix + "prefix")) msg.content = msg.content.replace(options.prefix, msgPrefix)
        }
        //If the message stats with the set prefix
        if (msg.content.startsWith(msgPrefix)) {
            let formatedMsg = msg.content.substring(msgPrefix.length, msg.content.length), //Format message to remove command prefix
                cmdTxt = formatedMsg.split(" ")[0].toLowerCase(), //Get command from the formated message
                args = formatedMsg.substring((formatedMsg.split(" ")[0]).length + 1); //Get arguments from the formated message
            if (commandAliases.hasOwnProperty(cmdTxt)) cmdTxt = commandAliases[cmdTxt]; //If the cmdTxt is an alias of the command
            if (cmdTxt === 'channelmute') processCmd(msg, args, commands[cmdTxt], bot); //Override channelCheck if cmd is channelmute to unmute a muted channel
            //Check if a Command was used and runs the corresponding code depending on if it was used in a Guild or not, if in guild checks for muted channel and disabled command
            else if (commands.hasOwnProperty(cmdTxt)) Database.checkChannel(msg.channel.id).then(() => Database.checkCommand(msg.channel.guild.id, cmdTxt).then(() => processCmd(msg, args, commands[cmdTxt], bot)))
        }
    }
});

function evalText(msg, args) {
    let result;
    //Trys to run eval on the text and output either an error or the result if applicable
    try {
        result = eval("try{" + args + "}catch(err){utils.fileLog(err);bot.createMessage(msg.channel.id, \"```\"+err+\"```\");}");
    } catch (e) {
        utils.fileLog(e);
        bot.createMessage(msg.channel.id, "```" + e + "```");
    }
    if (result && typeof result !== "object") bot.createMessage(msg.channel.id, result);
    else if (result && typeof result === "object") bot.createMessage(msg.channel.id, "```xl\n" + result + "```");
}

//New Guild Member Event
bot.on("guildMemberAdd", (guild, member) => {
    //Checks to make sure guild and a member was sent
    if (guild && member) {
        //Checks to see if the guild has a welcome set and if so replaces the correct strings with the correct info
        Database.checkSetting(guild.id, 'welcome').then(response => {
            let message = response.response.replace(/\[GuildName]/g, guild.name).replace(/\[ChannelName]/g, guild.channels.get(response.channel.toString()).name).replace(/\[ChannelMention]/g, guild.channels.get(response.channel.toString()).mention).replace(/\[UserName]/g, member.user.username).replace(/\[UserMention]/g, member.user.mention);
            bot.createMessage(response.channel, message);
        }).catch(err => utils.fileLog(err));
    }
})

//Guild Member Left Event
bot.on("guildMemberRemove", (guild, member) => {
    //Checks to make sure guild and a member was sent
    if (guild && member) {
        //Checks to see if the guild has a leave set and if so replaces the correct strings with the correct info
        Database.checkSetting(guild.id, 'leave').then(response => {
            let message = response.response.replace(/\[GuildName]/g, guild.name).replace(/\[ChannelName]/g, guild.channels.get(response.channel.toString()).name).replace(/\[ChannelMention]/g, guild.channels.get(response.channel.toString()).mention).replace(/\[UserName]/g, member.user.username);
            bot.createMessage(response.channel, message)
        }).catch(err => utils.fileLog(err))
    }
})

//Guild Joined Event
bot.on('guildCreate', guild => {
    //Post Guild Count
    postGuildCount()
    //Add guild to UsageChecker database
    UsageChecker.addToUsageCheck(guild.id);
})

//Guild Left Event
bot.on('guildDelete', guild => {
    //Post Guild Count
    postGuildCount()
    //Remove Guild from Database and log if error
    Database.removeGuild(guild.id).catch(err => utils.fileLog(err))
    //Remove guild from guildPrefix array if it exists in it
    Database.removeGuildfromJson(guild.id)
    //Remove from UsageChecker database
    UsageChecker.removeFromUsageCheck(guild.id);
})

//Load Commands then Connect(Logs any errors to console and file)
CommandLoader.load().then(() => {
    bot.connect().then(console.log(warningC("Logged in using Token")))
}).catch(err => utils.fileLog(err));

//Posts Guild Count to Discord Bots and Carbonitex
function postGuildCount() {
    //Check that the bot is ready so premature guild creates won't cause a crash
    if (bot.ready) {
        //Post Guild Count to Discord Bots and if error log to file and console
        axios({
            method: 'post',
            url: "https://bots.discord.pw/api/bots/" + bot.user.id + "/stats",
            headers: {
                "Authorization": options.bot_key,
                "content-type": "application/json"
            },
            data: {
                "server_count": bot.guilds.size
            }
        }).catch(err => utils.fileLog(err));
        //Post Guild Count to Carbonitex and if error log to file and console
        axios({
            method: 'post',
            url: "https://www.carbonitex.net/discord/data/botdata.php",
            headers: {
                "content-type": "application/json"
            },
            data: {
                "key": options.carbon_key,
                "servercount": bot.guilds.size
            }
        }).catch(err => utils.fileLog(err));
    }
}

//Changes the bots status every 10mins
setInterval(() => utils.setRandomStatus(bot, playing, urls), 6e+5);

//Changes the bots avatar every 2hrs
setInterval(() => {
    //Reads avatar directory and randomly picks an avatar to switch to
    fs.readdir(`${__dirname}/avatars/`, (err, files) => {
        if (err) utils.fileLog(err)
        else {
            let avatar = files[~~(Math.random() * (files.length))];
            //Reads the avatar image file and changes the bots avatar to it
            fs.readFile(`${__dirname}/avatars/${avatar}`, (err, image) => {
                if (err) utils.fileLog(err)
                else {
                    let data = "data:image/jpg;base64," + image.toString('base64');
                    bot.editSelf({
                        avatar: data
                    }).then(() => console.log(botC('Changed avatar to ' + avatar))).catch(err => utils.fileLog(err));
                }
            })
        }
    });
}, 7.2e+6);

//Bot Error Event
bot.on("error", err => utils.fileLog(err)) //Logs error to file and console

//Bot Warn Event(Outputs issues that aren't major)
bot.on("warn", (warn, id) => {
    console.log(warningC(warn, id));
})

//Debug event only used to find errors and usually disabled
//bot.on("debug", console.log)

//Shard Resume Event
bot.on('shardResume', id => {
    console.log(botC("@" + bot.user.username) + " - " + warningC("SHARD #" + id + "RECONNECTED"));
})

//Shard Disconnect Event
bot.on("shardDisconnect", (err, id) => {
    console.log(botC("@" + bot.user.username) + " - " + warningC("SHARD #" + id + "DISCONNECTED"));
    utils.fileLog(err); //Logs reason/error to file and console
})

//Whole Bot Disconnect Event
bot.on("disconnect", err => {
    console.log(botC("@" + bot.user.username) + " - " + errorC("DISCONNECTED"));
    utils.fileLog(err); //Logs Disconnect reason/error to file and console
    process.exit(0);
})<|endoftext|>


<commit_before>'use strict';

var css = require('css');
var findFile = require('find-file');
var fs = require('fs');
var parseImport = require('parse-import');

/**
 * Inline stylesheet using `@import`
 *
 * @param {Object} style
 * @param {Object} opts
 * @api public
 */

function Import(style, opts) {
    opts = opts || {};
    this.opts = opts;
    this.path = opts.path || process.cwd();
    this.rules = style.rules || [];
}

/**
 * Process stylesheet
 *
 * @api public
 */

Import.prototype.process = function () {
    var rules = [];
    var self = this;

    this.rules.forEach(function (rule) {
        if (rule.type !== 'import') {
            return rules.push(rule);
        }

        var content;
        var data = parseImport(rule.import);
        var file = self._check(data.path);
        var media = data.condition;
        var res;

        content = self._read(file);

        if (!media || !media.length) {
            res = content.rules;
        } else {
            res = {
                type: 'media',
                media: media,
                rules: content.rules
            };
        }

        rules = rules.concat(res);
    });

    return rules;
};

/**
 * Read the contents of a file
 *
 * @param {String} file
 * @api private
 */

Import.prototype._read = function (file) {
    var data = fs.readFileSync(file, this.opts.encoding || 'utf8');
    var style = css.parse(data).stylesheet;

    return style;
};

/**
 * Check if a file exists
 *
 * @param {String} name
 * @api private
 */

Import.prototype._check = function (name) {
    var file = findFile(name, this.path, false)[0];

    if (!file) {
        throw new Error('failed to find ' + name);
    }

    return file;
};

/**
 * Module exports
 */

module.exports = function (opts) {
    return function (style) {
        var inline = new Import(style, opts);
        var rules = inline.process();

        style.rules = rules;
    };
};
<commit_msg>Use options object instead of arguments on `find-file`<commit_after>'use strict';

var css = require('css');
var findFile = require('find-file');
var fs = require('fs');
var parseImport = require('parse-import');

/**
 * Inline stylesheet using `@import`
 *
 * @param {Object} style
 * @param {Object} opts
 * @api public
 */

function Import(style, opts) {
    opts = opts || {};
    this.opts = opts;
    this.path = opts.path || process.cwd();
    this.rules = style.rules || [];
}

/**
 * Process stylesheet
 *
 * @api public
 */

Import.prototype.process = function () {
    var rules = [];
    var self = this;

    this.rules.forEach(function (rule) {
        if (rule.type !== 'import') {
            return rules.push(rule);
        }

        var content;
        var data = parseImport(rule.import);
        var file = self._check(data.path);
        var media = data.condition;
        var res;

        content = self._read(file);

        if (!media || !media.length) {
            res = content.rules;
        } else {
            res = {
                type: 'media',
                media: media,
                rules: content.rules
            };
        }

        rules = rules.concat(res);
    });

    return rules;
};

/**
 * Read the contents of a file
 *
 * @param {String} file
 * @api private
 */

Import.prototype._read = function (file) {
    var data = fs.readFileSync(file, this.opts.encoding || 'utf8');
    var style = css.parse(data).stylesheet;

    return style;
};

/**
 * Check if a file exists
 *
 * @param {String} name
 * @api private
 */

Import.prototype._check = function (name) {
    var file = findFile(name, { path: this.path, global: false })[0];

    if (!file) {
        throw new Error('failed to find ' + name);
    }

    return file;
};

/**
 * Module exports
 */

module.exports = function (opts) {
    return function (style) {
        var inline = new Import(style, opts);
        var rules = inline.process();

        style.rules = rules;
    };
};
<|endoftext|>


<commit_before>
/*!
 * socket.io-node
 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var crypto = require('crypto')
  , Store = require('../store')
  , assert = require('assert');

/**
 * Exports the constructor.
 */

exports = module.exports = Redis;
Redis.Client = Client;

/**
 * Redis store.
 * Options:
 *     - nodeId (fn) gets an id that uniquely identifies this node
 *     - redis (fn) redis constructor, defaults to redis
 *     - redisPub (object) options to pass to the pub redis client
 *     - redisSub (object) options to pass to the sub redis client
 *     - redisClient (object) options to pass to the general redis client
 *     - pack (fn) custom packing, defaults to JSON or msgpack if installed
 *     - unpack (fn) custom packing, defaults to JSON or msgpack if installed
 *
 * @api public
 */

function Redis (opts) {
  opts = opts || {};

  // node id to uniquely identify this node
  var nodeId = opts.nodeId || function () {
    // by default, we generate a random id
    return Math.abs(Math.random() * Math.random() * Date.now() | 0);
  };

  this.nodeId = nodeId();

  // packing / unpacking mechanism
  if (opts.pack) {
    this.pack = opts.pack;
    this.unpack = opts.unpack;
  } else {
    try {
      var msgpack = require('msgpack');
      this.pack = msgpack.pack;
      this.unpack = msgpack.unpack;
    } catch (e) {
      this.pack = JSON.stringify;
      this.unpack = JSON.parse;
    }
  }

  var redis = opts.redis || require('redis')
    , RedisClient = redis.RedisClient;

  // initialize a pubsub client and a regular client
  if (opts.redisPub instanceof RedisClient) {
    this.pub = opts.redisPub;
  } else {
    opts.redisPub || (opts.redisPub = {});
    this.pub = redis.createClient(opts.redisPub.port, opts.redisPub.host, opts.redisPub);
  }
  if (opts.redisSub instanceof RedisClient) {
    this.sub = opts.redisSub;
  } else {
    opts.redisSub || (opts.redisSub = {});
    this.sub = redis.createClient(opts.redisSub.port, opts.redisSub.host, opts.redisSub);
  }
  if (opts.redisClient instanceof RedisClient) {
    this.cmd = opts.redisClient;
  } else {
    opts.redisClient || (opts.redisClient = {});
    this.cmd = redis.createClient(opts.redisClient.port, opts.redisClient.host, opts.redisClient);
  }

  Store.call(this, opts);

  this.sub.setMaxListeners(0);
  this.setMaxListeners(0);
};

/**
 * Inherits from Store.
 */

Redis.prototype.__proto__ = Store.prototype;

/**
 * Publishes a message.
 *
 * @api private
 */

Redis.prototype.publish = function (name) {
  var args = Array.prototype.slice.call(arguments, 1);
  this.pub.publish(name, this.pack({ nodeId: this.nodeId, args: args }));
  this.emit.apply(this, ['publish', name].concat(args));
};

/**
 * Subscribes to a channel
 *
 * @api private
 */

Redis.prototype.subscribe = function (name, consumer, fn) {
  this.sub.subscribe(name);

  if (consumer || fn) {
    var self = this;

    self.sub.on('subscribe', function subscribe (ch) {
      if (name == ch) {
        function message (ch, msg) {
          if (name == ch) {
            msg = self.unpack(msg);

            // we check that the message consumed wasnt emitted by this node
            if (self.nodeId != msg.nodeId) {
              consumer.apply(null, msg.args);
            }
          }
        };

        self.sub.on('message', message);

        self.on('unsubscribe', function unsubscribe (ch) {
          if (name == ch) {
            self.sub.removeListener('message', message);
            self.removeListener('unsubscribe', unsubscribe);
          }
        });

        self.sub.removeListener('subscribe', subscribe);

        fn && fn();
      }
    });
  }

  this.emit('subscribe', name, consumer, fn);
};

/**
 * Unsubscribes
 *
 * @api private
 */

Redis.prototype.unsubscribe = function (name, fn) {
  this.sub.unsubscribe(name);

  if (fn) {
    var client = this.sub;

    client.on('unsubscribe', function unsubscribe (ch) {
      if (name == ch) {
        fn();
        client.removeListener('unsubscribe', unsubscribe);
      }
    });
  }

  this.emit('unsubscribe', name, fn);
};

/**
 * Destroys the store
 *
 * @api public
 */

Redis.prototype.destroy = function () {
  Store.prototype.destroy.call(this);

  this.pub.end();
  this.sub.end();
  this.cmd.end();
};

/**
 * Client constructor
 *
 * @api private
 */

function Client (store, id) {
  Store.Client.call(this, store, id);
};

/**
 * Inherits from Store.Client
 */

Client.prototype.__proto__ = Store.Client;

/**
 * Redis hash get
 *
 * @api private
 */

Client.prototype.get = function (key, fn) {
  this.store.cmd.hget(this.id, key, fn);
  return this;
};

/**
 * Redis hash set
 *
 * @api private
 */

Client.prototype.set = function (key, value, fn) {
  this.store.cmd.hset(this.id, key, value, fn);
  return this;
};

/**
 * Redis hash del
 *
 * @api private
 */

Client.prototype.del = function (key, fn) {
  this.store.cmd.hdel(this.id, key, fn);
  return this;
};

/**
 * Redis hash has
 *
 * @api private
 */

Client.prototype.has = function (key, fn) {
  this.store.cmd.hexists(this.id, key, function (err, has) {
    if (err) return fn(err);
    fn(null, !!has);
  });
  return this;
};

/**
 * Destroys client
 *
 * @param {Number} number of seconds to expire data
 * @api private
 */

Client.prototype.destroy = function (expiration) {
  if ('number' != typeof expiration) {
    this.store.cmd.del(this.id);
  } else {
    this.store.cmd.expire(this.id, expiration);
  }

  return this;
};
<commit_msg>Redis Store: removed unneeded module ('assert')<commit_after>/*!
 * socket.io-node
 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var crypto = require('crypto')
  , Store = require('../store');

/**
 * Exports the constructor.
 */

exports = module.exports = Redis;
Redis.Client = Client;

/**
 * Redis store.
 * Options:
 *     - nodeId (fn) gets an id that uniquely identifies this node
 *     - redis (fn) redis constructor, defaults to redis
 *     - redisPub (object) options to pass to the pub redis client
 *     - redisSub (object) options to pass to the sub redis client
 *     - redisClient (object) options to pass to the general redis client
 *     - pack (fn) custom packing, defaults to JSON or msgpack if installed
 *     - unpack (fn) custom packing, defaults to JSON or msgpack if installed
 *
 * @api public
 */

function Redis (opts) {
  opts = opts || {};

  // node id to uniquely identify this node
  var nodeId = opts.nodeId || function () {
    // by default, we generate a random id
    return Math.abs(Math.random() * Math.random() * Date.now() | 0);
  };

  this.nodeId = nodeId();

  // packing / unpacking mechanism
  if (opts.pack) {
    this.pack = opts.pack;
    this.unpack = opts.unpack;
  } else {
    try {
      var msgpack = require('msgpack');
      this.pack = msgpack.pack;
      this.unpack = msgpack.unpack;
    } catch (e) {
      this.pack = JSON.stringify;
      this.unpack = JSON.parse;
    }
  }

  var redis = opts.redis || require('redis')
    , RedisClient = redis.RedisClient;

  // initialize a pubsub client and a regular client
  if (opts.redisPub instanceof RedisClient) {
    this.pub = opts.redisPub;
  } else {
    opts.redisPub || (opts.redisPub = {});
    this.pub = redis.createClient(opts.redisPub.port, opts.redisPub.host, opts.redisPub);
  }
  if (opts.redisSub instanceof RedisClient) {
    this.sub = opts.redisSub;
  } else {
    opts.redisSub || (opts.redisSub = {});
    this.sub = redis.createClient(opts.redisSub.port, opts.redisSub.host, opts.redisSub);
  }
  if (opts.redisClient instanceof RedisClient) {
    this.cmd = opts.redisClient;
  } else {
    opts.redisClient || (opts.redisClient = {});
    this.cmd = redis.createClient(opts.redisClient.port, opts.redisClient.host, opts.redisClient);
  }

  Store.call(this, opts);

  this.sub.setMaxListeners(0);
  this.setMaxListeners(0);
};

/**
 * Inherits from Store.
 */

Redis.prototype.__proto__ = Store.prototype;

/**
 * Publishes a message.
 *
 * @api private
 */

Redis.prototype.publish = function (name) {
  var args = Array.prototype.slice.call(arguments, 1);
  this.pub.publish(name, this.pack({ nodeId: this.nodeId, args: args }));
  this.emit.apply(this, ['publish', name].concat(args));
};

/**
 * Subscribes to a channel
 *
 * @api private
 */

Redis.prototype.subscribe = function (name, consumer, fn) {
  this.sub.subscribe(name);

  if (consumer || fn) {
    var self = this;

    self.sub.on('subscribe', function subscribe (ch) {
      if (name == ch) {
        function message (ch, msg) {
          if (name == ch) {
            msg = self.unpack(msg);

            // we check that the message consumed wasnt emitted by this node
            if (self.nodeId != msg.nodeId) {
              consumer.apply(null, msg.args);
            }
          }
        };

        self.sub.on('message', message);

        self.on('unsubscribe', function unsubscribe (ch) {
          if (name == ch) {
            self.sub.removeListener('message', message);
            self.removeListener('unsubscribe', unsubscribe);
          }
        });

        self.sub.removeListener('subscribe', subscribe);

        fn && fn();
      }
    });
  }

  this.emit('subscribe', name, consumer, fn);
};

/**
 * Unsubscribes
 *
 * @api private
 */

Redis.prototype.unsubscribe = function (name, fn) {
  this.sub.unsubscribe(name);

  if (fn) {
    var client = this.sub;

    client.on('unsubscribe', function unsubscribe (ch) {
      if (name == ch) {
        fn();
        client.removeListener('unsubscribe', unsubscribe);
      }
    });
  }

  this.emit('unsubscribe', name, fn);
};

/**
 * Destroys the store
 *
 * @api public
 */

Redis.prototype.destroy = function () {
  Store.prototype.destroy.call(this);

  this.pub.end();
  this.sub.end();
  this.cmd.end();
};

/**
 * Client constructor
 *
 * @api private
 */

function Client (store, id) {
  Store.Client.call(this, store, id);
};

/**
 * Inherits from Store.Client
 */

Client.prototype.__proto__ = Store.Client;

/**
 * Redis hash get
 *
 * @api private
 */

Client.prototype.get = function (key, fn) {
  this.store.cmd.hget(this.id, key, fn);
  return this;
};

/**
 * Redis hash set
 *
 * @api private
 */

Client.prototype.set = function (key, value, fn) {
  this.store.cmd.hset(this.id, key, value, fn);
  return this;
};

/**
 * Redis hash del
 *
 * @api private
 */

Client.prototype.del = function (key, fn) {
  this.store.cmd.hdel(this.id, key, fn);
  return this;
};

/**
 * Redis hash has
 *
 * @api private
 */

Client.prototype.has = function (key, fn) {
  this.store.cmd.hexists(this.id, key, function (err, has) {
    if (err) return fn(err);
    fn(null, !!has);
  });
  return this;
};

/**
 * Destroys client
 *
 * @param {Number} number of seconds to expire data
 * @api private
 */

Client.prototype.destroy = function (expiration) {
  if ('number' != typeof expiration) {
    this.store.cmd.del(this.id);
  } else {
    this.store.cmd.expire(this.id, expiration);
  }

  return this;
};
<|endoftext|>


<commit_before>/*
 * mockserver
 * http://mock-server.com
 *
 * Copyright (c) 2014 James Bloom
 * Licensed under the Apache License, Version 2.0
 */

module.exports = (function () {

    var mockServer;
    var port;
    var artifactoryHost = 'oss.sonatype.org';
    var artifactoryPath = '/content/repositories/releases/org/mock-server/mockserver-netty/';

    var Q = require('q');
    var http = require('http');

    function defer() {
        return (global.protractor ? protractor.promise : Q).defer();
    }

    function checkStarted(request, retries, promise, verbose) {
        var deferred = promise || defer();

        var req = http.request(request);

        req.once('response', function (response) {
            var body = '';

            response.on('data', function (chunk) {
                body += chunk;
            });

            response.on('end', function () {
                deferred.resolve({
                    statusCode: response.statusCode,
                    body: body
                });
            });
        });

        req.once('error', function (error) {
            if (retries > 0) {
                setTimeout(function () {
                    verbose && console.log("waiting for MockServer to start retries remaining: " + retries);
                    checkStarted(request, retries - 1, promise, verbose);
                }, 100);
            } else {
                verbose && console.log("MockServer failed to start");
                deferred.reject(error);
            }
        });

        req.end();

        return deferred.promise;
    }

    function checkStopped(request, retries, promise, verbose) {
        var deferred = promise || defer();

        var req = http.request(request);

        req.once('response', function (response) {
            var body = '';

            response.on('data', function (chunk) {
                body += chunk;
            });

            response.on('end', function () {
                if (retries > 0) {
                    verbose && console.log("waiting for MockServer to stop retries remaining: " + retries);
                    setTimeout(function () {
                        checkStopped(request, retries - 1, promise, verbose)
                    }, 100);
                } else {
                    verbose && console.log("MockServer failed to stop");
                    deferred.reject();
                }
            });
        });

        req.once('error', function () {
            deferred.resolve();
        });

        req.end();

        return deferred.promise;
    }

    function sendRequest(request) {
        var deferred = defer();

        var callback = function (response) {
            var body = '';

            if (response.statusCode === 400 || response.statusCode === 404) {
                deferred.reject(response.statusCode);
            }

            response.on('data', function (chunk) {
                body += chunk;
            });

            response.on('end', function () {
                deferred.resolve({
                    statusCode: response.statusCode,
                    headers: response.headers,
                    body: body
                });
            });
        };

        var req = http.request(request, callback);
        req.end();

        return deferred.promise;
    }

    function start_mockserver(options) {
        var deferred = defer();

        if (!options) {
            deferred.reject(new Error("options is falsy, it must be defined to specify the port(s) required to start the MockServer"))
        }

        if (options.artifactoryHost) {
            artifactoryHost = options.artifactoryHost;
        }

        if (options.artifactoryPath) {
            artifactoryPath = options.artifactoryPath;
        }

        var startupRetries = 100; // wait for 10 seconds

        // double check the jar has already been downloaded
        require('./downloadJar').downloadJar('3.10.6', artifactoryHost, artifactoryPath).then(function () {

            var spawn = require('child_process').spawn;
            var glob = require('glob');
            var commandLineOptions = ['-Dfile.encoding=UTF-8'];
            if (options.trace) {
                commandLineOptions.push('-Dmockserver.logLevel=TRACE');
            } else if (options.verbose) {
                commandLineOptions.push('-Dmockserver.logLevel=INFO');
            } else {
                commandLineOptions.push('-Dmockserver.logLevel=WARN');
            }
            if (options.javaDebugPort) {
                commandLineOptions.push('-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=' + options.javaDebugPort);
                startupRetries = 500;
            }
            commandLineOptions.push('-jar');
            commandLineOptions.push(glob.sync('**/mockserver-netty-*-jar-with-dependencies.jar'));
            if (options.serverPort) {
                commandLineOptions.push("-serverPort");
                commandLineOptions.push(options.serverPort);
                port = port || options.serverPort;
            }
            if (options.proxyPort) {
                commandLineOptions.push("-proxyPort");
                commandLineOptions.push(options.proxyPort);
                port = port || options.proxyPort;
            }
            if (options.proxyRemotePort) {
                commandLineOptions.push("-proxyRemotePort");
                commandLineOptions.push(options.proxyRemotePort);
            }
            if (options.proxyRemoteHost) {
                commandLineOptions.push("-proxyRemoteHost");
                commandLineOptions.push(options.proxyRemoteHost);
            }
            if (options.verbose) {
                console.log('Running \'java ' + commandLineOptions.join(' ') + '\'');
            }
            mockServer = spawn('java', commandLineOptions, {
                stdio: ['ignore', (options.verbose ? process.stdout : 'ignore'), process.stderr]
            });

        }).then(function () {
            return checkStarted({
                method: 'PUT',
                host: "localhost",
                path: "/reset",
                port: port
            }, startupRetries, deferred, options.verbose);
        }, function (error) {
            deferred.reject(error);
        });

        return deferred.promise;
    }

    function stop_mockserver(options) {
        var deferred = defer();
        if (options.serverPort) {
            port = port || options.serverPort;
        }
        if (options.proxyPort) {
            port = port  || options.proxyPort;
        }
        if (options.verbose) {
            console.log('Using port \'' + port + '\' to stop MockServer and MockServer Proxy');
        }
        sendRequest({
            method: 'PUT',
            host: "localhost",
            path: "/stop",
            port: port
        }).then(function () {
            mockServer && mockServer.kill();
            checkStopped({
                method: 'PUT',
                host: "localhost",
                path: "/reset",
                port: port
            }, 100, deferred, options && options.verbose); // wait for 10 seconds
        });
        return deferred.promise;
    }

    return {
        start_mockserver: start_mockserver,
        stop_mockserver: stop_mockserver
    };
})();
<commit_msg>#12 fixing missing function for protractor tests<commit_after>/*
 * mockserver
 * http://mock-server.com
 *
 * Copyright (c) 2014 James Bloom
 * Licensed under the Apache License, Version 2.0
 */

module.exports = (function () {

    var mockServer;
    var port;
    var artifactoryHost = 'oss.sonatype.org';
    var artifactoryPath = '/content/repositories/releases/org/mock-server/mockserver-netty/';

    var Q = require('q');
    var http = require('http');

    function defer() {
        var promise = (global.protractor ? protractor.promise : Q);
        var deferred = promise.defer();

        if (global.protractor) {
            deferred.resolve = deferred.fulfill;
        }
        return deferred;
    }

    function checkStarted(request, retries, promise, verbose) {
        var deferred = promise || defer();

        var req = http.request(request);

        req.once('response', function (response) {
            var body = '';

            response.on('data', function (chunk) {
                body += chunk;
            });

            response.on('end', function () {
                deferred.resolve({
                    statusCode: response.statusCode,
                    body: body
                });
            });
        });

        req.once('error', function (error) {
            if (retries > 0) {
                setTimeout(function () {
                    verbose && console.log("waiting for MockServer to start retries remaining: " + retries);
                    checkStarted(request, retries - 1, promise, verbose);
                }, 100);
            } else {
                verbose && console.log("MockServer failed to start");
                deferred.reject(error);
            }
        });

        req.end();

        return deferred.promise;
    }

    function checkStopped(request, retries, promise, verbose) {
        var deferred = promise || defer();

        var req = http.request(request);

        req.once('response', function (response) {
            var body = '';

            response.on('data', function (chunk) {
                body += chunk;
            });

            response.on('end', function () {
                if (retries > 0) {
                    verbose && console.log("waiting for MockServer to stop retries remaining: " + retries);
                    setTimeout(function () {
                        checkStopped(request, retries - 1, promise, verbose)
                    }, 100);
                } else {
                    verbose && console.log("MockServer failed to stop");
                    deferred.reject();
                }
            });
        });

        req.once('error', function () {
            deferred.resolve();
        });

        req.end();

        return deferred.promise;
    }

    function sendRequest(request) {
        var deferred = defer();

        var callback = function (response) {
            var body = '';

            if (response.statusCode === 400 || response.statusCode === 404) {
                deferred.reject(response.statusCode);
            }

            response.on('data', function (chunk) {
                body += chunk;
            });

            response.on('end', function () {
                deferred.resolve({
                    statusCode: response.statusCode,
                    headers: response.headers,
                    body: body
                });
            });
        };

        var req = http.request(request, callback);
        req.end();

        return deferred.promise;
    }

    function start_mockserver(options) {
        var deferred = defer();

        if (!options) {
            deferred.reject(new Error("options is falsy, it must be defined to specify the port(s) required to start the MockServer"))
        }

        if (options.artifactoryHost) {
            artifactoryHost = options.artifactoryHost;
        }

        if (options.artifactoryPath) {
            artifactoryPath = options.artifactoryPath;
        }

        var startupRetries = 100; // wait for 10 seconds

        // double check the jar has already been downloaded
        require('./downloadJar').downloadJar('3.10.6', artifactoryHost, artifactoryPath).then(function () {

            var spawn = require('child_process').spawn;
            var glob = require('glob');
            var commandLineOptions = ['-Dfile.encoding=UTF-8'];
            if (options.trace) {
                commandLineOptions.push('-Dmockserver.logLevel=TRACE');
            } else if (options.verbose) {
                commandLineOptions.push('-Dmockserver.logLevel=INFO');
            } else {
                commandLineOptions.push('-Dmockserver.logLevel=WARN');
            }
            if (options.javaDebugPort) {
                commandLineOptions.push('-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=' + options.javaDebugPort);
                startupRetries = 500;
            }
            commandLineOptions.push('-jar');
            commandLineOptions.push(glob.sync('**/mockserver-netty-*-jar-with-dependencies.jar'));
            if (options.serverPort) {
                commandLineOptions.push("-serverPort");
                commandLineOptions.push(options.serverPort);
                port = port || options.serverPort;
            }
            if (options.proxyPort) {
                commandLineOptions.push("-proxyPort");
                commandLineOptions.push(options.proxyPort);
                port = port || options.proxyPort;
            }
            if (options.proxyRemotePort) {
                commandLineOptions.push("-proxyRemotePort");
                commandLineOptions.push(options.proxyRemotePort);
            }
            if (options.proxyRemoteHost) {
                commandLineOptions.push("-proxyRemoteHost");
                commandLineOptions.push(options.proxyRemoteHost);
            }
            if (options.verbose) {
                console.log('Running \'java ' + commandLineOptions.join(' ') + '\'');
            }
            mockServer = spawn('java', commandLineOptions, {
                stdio: ['ignore', (options.verbose ? process.stdout : 'ignore'), process.stderr]
            });

        }).then(function () {
            return checkStarted({
                method: 'PUT',
                host: "localhost",
                path: "/reset",
                port: port
            }, startupRetries, deferred, options.verbose);
        }, function (error) {
            deferred.reject(error);
        });

        return deferred.promise;
    }

    function stop_mockserver(options) {
        var deferred = defer();
        if (options.serverPort) {
            port = port || options.serverPort;
        }
        if (options.proxyPort) {
            port = port  || options.proxyPort;
        }
        if (options.verbose) {
            console.log('Using port \'' + port + '\' to stop MockServer and MockServer Proxy');
        }
        sendRequest({
            method: 'PUT',
            host: "localhost",
            path: "/stop",
            port: port
        }).then(function () {
            mockServer && mockServer.kill();
            checkStopped({
                method: 'PUT',
                host: "localhost",
                path: "/reset",
                port: port
            }, 100, deferred, options && options.verbose); // wait for 10 seconds
        });
        return deferred.promise;
    }

    return {
        start_mockserver: start_mockserver,
        stop_mockserver: stop_mockserver
    };
})();
<|endoftext|>


<commit_before>
/**
 * Dependencies
 */

var clone = require('clone');
var each = require('each');
var styles = require('./styles');
var svgAttributes = require('svg-attributes');

/**
 * Element Types
 */

var types = [ 'labels',
              'segments',
              'segments_front',
              'segment_labels',
              'segment_label_containers',
              'stops_merged',
              'stops_pattern',
              'places',
              'places_icon',
              'multipoints_merged',
              'multipoints_pattern'
            ];

/**
 * Add transform
 */

svgAttributes.push('transform');

/**
 * Expose `Styler`
 */

module.exports = Styler;

/**
 * Styler object
 */

function Styler(styles) {
  if (!(this instanceof Styler)) return new Styler(styles);

  // reset styles
  this.reset();

  // load styles
  if (styles) this.load(styles);
}

/**
 * Clear all current styles
 */

Styler.prototype.clear = function () {
  types.forEach(function (type) {
    this[type] = {};
  }, this);
};

/**
 * Reset to the predefined styles
 */

Styler.prototype.reset = function () {
  types.forEach(function (type) {
    this[type] = clone(styles[type]);
  }, this);
};

/**
 * Load rules
 *
 * @param {Object} a set of style rules
 */

Styler.prototype.load = function(styles) {
  var self = this;
  each(types, function(type) {
    if (styles[type]) {
      each(styles[type], function (key, val) {
        self[type][key] = (self[type][key] || []).concat(val);
      });
    }
  });
};

/**
 * Render pattern
 *
 * @param {Display} display
 * @param {Pattern} pattern
 */

Styler.prototype.renderSegment = function(display, segment) {
  this.applyAttrAndStyle(
    display,
    segment.lineGraph,
    this.segments
  );
  this.applyAttrAndStyle(
    display,
    segment.lineGraphFront,
    this.segments_front
  );
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {Point} Transitive Point object
 */

Styler.prototype.renderPoint = function(display, point) {
  if(point.getType() === 'STOP') this.renderStop(display, point);
  if(point.getType() === 'PLACE') this.renderPlace(display, point);
  if(point.getType() === 'MULTI') this.renderMultiPoint(display, point);
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {Stop} Transitive Stop object
 */

Styler.prototype.renderStop = function(display, stop) {

  this.applyAttrAndStyle(
    display,
    stop.patternMarkers,//stop.svgGroup.selectAll('.transitive-stop-marker-pattern'),
    this.stops_pattern
  );

  this.applyAttrAndStyle(
    display,
    stop.mergedMarker,//svgGroup.selectAll('.transitive-stop-marker-merged'),
    this.stops_merged
  );

  this.applyAttrAndStyle(
    display,
    stop.svgGroup.selectAll('.transitive-stop-label'),
    this.labels
  );
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {Place} Transitive Place object
 */

Styler.prototype.renderPlace = function(display, place) {
  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-circle'),
    this.places
  );

  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-icon'),
    this.places_icon
  );

  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-label'),
    this.labels
  );
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {MultiPoint} Transitive MultiPoint object
 */

Styler.prototype.renderMultiPoint = function(display, multipoint) {

  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multipoint-marker-pattern'),
    this.multipoints_pattern
  );

  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multipoint-marker-merged'),
    this.multipoints_merged
  );

  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multi-label'),
    this.labels
  );
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {Point} Transitive Point object
 */

Styler.prototype.renderPointLabel = function(display, point) {
  if(point.getType() === 'STOP') this.renderStopLabel(display, point);
  if(point.getType() === 'PLACE') this.renderPlaceLabel(display, point);
  if(point.getType() === 'MULTI') this.renderMultiPointLabel(display, point);
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {Stop} Transitive Stop object
 */

Styler.prototype.renderStopLabel = function(display, stop) {

  this.applyAttrAndStyle(
    display,
    stop.svgGroup.selectAll('.transitive-stop-label'),
    this.labels
  );
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {Place} Transitive Place object
 */

Styler.prototype.renderPlaceLabel = function(display, place) {

  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-label'),
    this.labels
  );
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {MultiPoint} Transitive MultiPoint object
 */

Styler.prototype.renderMultiPointLabel = function(display, multipoint) {

  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multi-label'),
    this.labels
  );
};

Styler.prototype.renderSegmentLabel = function(display, segment) {

  this.applyAttrAndStyle(
    display,
    segment.label.svgGroup.selectAll('.transitive-segment-label-container'),
    this.segment_label_containers
  );
  this.applyAttrAndStyle(
    display,
    segment.label.svgGroup.selectAll('.transitive-segment-label'),
    this.segment_labels
  );
};

/**
 * Check if it's an attribute or a style and apply accordingly
 *
 * @param {Display} the Display object
 * @param {Object} a D3 list of elements
 * @param {Object} the list of attributes
 */

Styler.prototype.applyAttrAndStyle = function(display, elements, attributes) {
  var self = this;
  each(attributes, function(name, rules) {
    var fn = svgAttributes.indexOf(name) === -1
      ? 'style'
      : 'attr';

    elements[fn](name, function(data, index) {
      return self.compute(rules, display, data, index);
    });
  });
};

/**
 * Compute a style rule based on the current display and data
 *
 * @param {Array} array of rules
 * @param {Object} the Display object
 * @param {Object} data associated with this object
 * @param {Number} index of this object
 */

Styler.prototype.compute = function(rules, display, data, index) {
  var computed, self = this;
  each(rules, function(rule) {
    var val = isFunction(rule)
      ? rule.call(self, display, data, index, styles.utils)
      : rule;
    if (val !== undefined && val !== null) computed = val;
  });
  return computed;
};

/**
 * Is function?
 */

function isFunction(val) {
  return Object.prototype.toString.call(val) === '[object Function]';
}
<commit_msg>Remove usage of each on heavy loops<commit_after>var clone = require('clone');
var each = require('each');
var svgAttributes = require('svg-attributes');

var styles = require('./styles');

/**
 * Element Types
 */

var types = [
  'labels',
  'segments',
  'segments_front',
  'segment_labels',
  'segment_label_containers',
  'stops_merged',
  'stops_pattern',
  'places',
  'places_icon',
  'multipoints_merged',
  'multipoints_pattern'
];

/**
 * Add transform
 */

svgAttributes.push('transform');

/**
 * Expose `Styler`
 */

module.exports = Styler;

/**
 * Styler object
 */

function Styler(styles) {
  if (!(this instanceof Styler)) return new Styler(styles);

  // reset styles
  this.reset();

  // load styles
  if (styles) this.load(styles);
}

/**
 * Clear all current styles
 */

Styler.prototype.clear = function() {
  for (var i in types) {
    this[types[i]] = {};
  }
};

/**
 * Reset to the predefined styles
 */

Styler.prototype.reset = function() {
  for (var i in types) {
    var type = types[i];
    this[type] = clone(styles[type]);
  }
};

/**
 * Load rules
 *
 * @param {Object} a set of style rules
 */

Styler.prototype.load = function(styles) {
  var self = this;
  for (var i in types) {
    var type = types[i];
    if (styles[type]) {
      for (var key in styles[type]) {
        this[type][key] = (this[type][key] || []).concat(styles[type][key]);
      }
    }
  }
};

/**
 * Render pattern
 *
 * @param {Display} display
 * @param {Pattern} pattern
 */

Styler.prototype.renderSegment = function(display, segment) {
  this.applyAttrAndStyle(
    display,
    segment.lineGraph,
    this.segments
  );
  this.applyAttrAndStyle(
    display,
    segment.lineGraphFront,
    this.segments_front
  );
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {Point} Transitive Point object
 */

Styler.prototype.renderPoint = function(display, point) {
  if (point.getType() === 'STOP') this.renderStop(display, point);
  if (point.getType() === 'PLACE') this.renderPlace(display, point);
  if (point.getType() === 'MULTI') this.renderMultiPoint(display, point);
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {Stop} Transitive Stop object
 */

Styler.prototype.renderStop = function(display, stop) {
  this.applyAttrAndStyle(
    display,
    stop.patternMarkers, //stop.svgGroup.selectAll('.transitive-stop-marker-pattern'),
    this.stops_pattern
  );

  this.applyAttrAndStyle(
    display,
    stop.mergedMarker, //svgGroup.selectAll('.transitive-stop-marker-merged'),
    this.stops_merged
  );

  this.applyAttrAndStyle(
    display,
    stop.svgGroup.selectAll('.transitive-stop-label'),
    this.labels
  );
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {Place} Transitive Place object
 */

Styler.prototype.renderPlace = function(display, place) {
  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-circle'),
    this.places
  );

  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-icon'),
    this.places_icon
  );

  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-label'),
    this.labels
  );
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {MultiPoint} Transitive MultiPoint object
 */

Styler.prototype.renderMultiPoint = function(display, multipoint) {
  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multipoint-marker-pattern'),
    this.multipoints_pattern
  );

  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multipoint-marker-merged'),
    this.multipoints_merged
  );

  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multi-label'),
    this.labels
  );
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {Point} Transitive Point object
 */

Styler.prototype.renderPointLabel = function(display, point) {
  if (point.getType() === 'STOP') this.renderStopLabel(display, point);
  if (point.getType() === 'PLACE') this.renderPlaceLabel(display, point);
  if (point.getType() === 'MULTI') this.renderMultiPointLabel(display, point);
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {Stop} Transitive Stop object
 */

Styler.prototype.renderStopLabel = function(display, stop) {
  this.applyAttrAndStyle(
    display,
    stop.svgGroup.selectAll('.transitive-stop-label'),
    this.labels
  );
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {Place} Transitive Place object
 */

Styler.prototype.renderPlaceLabel = function(display, place) {
  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-label'),
    this.labels
  );
};

/**
 * Render elements against these rules
 *
 * @param {Display} a D3 list of elements
 * @param {MultiPoint} Transitive MultiPoint object
 */

Styler.prototype.renderMultiPointLabel = function(display, multipoint) {
  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multi-label'),
    this.labels
  );
};

Styler.prototype.renderSegmentLabel = function(display, segment) {
  this.applyAttrAndStyle(
    display,
    segment.label.svgGroup.selectAll('.transitive-segment-label-container'),
    this.segment_label_containers
  );
  this.applyAttrAndStyle(
    display,
    segment.label.svgGroup.selectAll('.transitive-segment-label'),
    this.segment_labels
  );
};

/**
 * Check if it's an attribute or a style and apply accordingly
 *
 * @param {Display} the Display object
 * @param {Object} a D3 list of elements
 * @param {Object} the list of attributes
 */

Styler.prototype.applyAttrAndStyle = function(display, elements, attributes) {
  for (var name in attributes) {
    var rules = attributes[name];
    var fn = svgAttributes.indexOf(name) === -1 ? 'style' : 'attr';

    this.applyRules(display, elements, name, rules, fn);
  }
};

/**
 * Apply style/attribute rules to a list of elements
 *
 * @param {Display} display object
 * @param {Object} elements
 * @param {String} rule name
 * @param {Array} rules
 * @param {String} style/attr
 */

Styler.prototype.applyRules = function(display, elements, name, rules, fn) {
  var self = this;
  elements[fn](name, function(data, index) {
    return self.compute(rules, display, data, index);
  });
};

/**
 * Compute a style rule based on the current display and data
 *
 * @param {Array} array of rules
 * @param {Object} the Display object
 * @param {Object} data associated with this object
 * @param {Number} index of this object
 */

Styler.prototype.compute = function(rules, display, data, index) {
  var computed, self = this;
  for (var i in rules) {
    var rule = rules[i];
    var val = isFunction(rule) ? rule.call(self, display, data, index, styles.utils) :
      rule;
    if (val !== undefined && val !== null) computed = val;
  }
  return computed;
};

/**
 * Is function?
 */

function isFunction(val) {
  return Object.prototype.toString.call(val) === '[object Function]';
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

const AWS = require('aws-sdk');
const { queue, waterfall, map, retryable } = require('async');
const invariant = require('invariant');
const path = require('path');
const fs = require('fs');
const mime = require('mime');
const colors = require('colors/safe');
const zlib = require('zlib');
const zopfli = require('node-zopfli');
const temp = require('temp').track();
const getUsage = require('command-line-usage');
const { countingStream } = require('stream-toolkit');
const writeConfig = require('./write-config');

const optionList = [{
  name: 'env',
  alias: 'e',
  type: String,
  description: 'Specifies environment to deploy to, e.g. qa',
}, {
  name: 'dry',
  alias: 'd',
  type: Boolean,
  description: 'Dry run - skip the upload',
}];

const options = require('command-line-args')(optionList);

if (! options.env) {
  console.log(getUsage([{
    header: 'Omni dist uploader',
    content: 'Compresses dist assets and uploads them to the S3 bucket',
  }, {
    header: 'Options',
    optionList,
  }]));
  process.exit(2);
}

const ZIP_OPTS = { level: 9 };
const QUEUE_CONCURRENCY = 50;  // safeguard. concurrency rocks
const UPLOAD_RETRIES = { times: 1000, interval: 100 };
const NOZIP_MIME_TEST = /^(image\/png|application\/font-woff)/; // woffs already zipped
const CACHE_CONTROL_INDEX = 'no-cache';  // keep history buffer. http://stackoverflow.com/a/18516720
const CACHE_CONTROL_OTHERS = 'public, max-age=31536000';  // 1 year

const config = require(path.resolve(`ci/${options.env}.json`)); // eslint-disable-line import/no-dynamic-require
const isProductionEnv = options.env.startsWith('staging') || options.env.startsWith('production');
const compressionAlgo = isProductionEnv ? 'zopfli' : 'zlib';

if (config.region) {
  AWS.config.update({ region: config.region });
}

if (config.accessKeyId) {
  console.log('Will use custom accessKey.\n');
  AWS.config.update({
    accessKeyId: config.accessKeyId,
    secretAccessKey: config.secretAccessKey,
  });
}

const s3 = new AWS.S3();

writeConfig(options.env);

options.dry && console.log('DRY RUN! No upload will actually happen.\n');
isProductionEnv &&
    console.log(`This production build will use ${compressionAlgo}, which is slower to compress!\n`);

const copyQueue = queue(copyWorker, QUEUE_CONCURRENCY);
const uploadQueue = queue(retryable(UPLOAD_RETRIES, uploadWorker), QUEUE_CONCURRENCY);
const absoluteFolder = path.resolve('dist');

const indexCopyTask = {  // index.html comes last
  file: 'index.html',
  folder: absoluteFolder,
};

let filesCount;
let originalSizeAll = 0;
let compressedSizeAll = 0;

// post-upload flow: runs after uploads have finished
uploadQueue.drain = () => {
  if (copyQueue.length() || uploadQueue.length() ||
      copyQueue.running() || uploadQueue.running()) return;  // tasks remain!
  copyQueue.push(indexCopyTask);
  uploadQueue.drain = () => {
    const original = originalSizeAll / 1000000;  // B to MB
    const compressed = compressedSizeAll / 1000000;
    console.log(
        '\nAll done.' +
        ` Source: ${original.toFixed(2)}MB,` +
        ` Uploaded: ${compressed.toFixed(2)}MB.`);
    uploadQueue.drain = () => {};
    process.exit(0);
  };
};

// main flow: lists S3 objects, lists files, populates copyQueue
waterfall([
  ! options.dry ? (callback) => {
    s3.listObjectsV2({
      Bucket: config.bucket,
    }, callback);
  } : null,
  (objects, callback) => {
    callback = callback || objects;  // if listObjectsV2 didn't happen in the prior step
    objects = typeof objects === 'function' ? null : objects;
    fs.readdir(absoluteFolder, (err, files) => {
      callback(err, objects, files);
    });
  },
  (objects, files, callback) => {
    if (objects) {
      console.info('Pre-upload bucket object count:', objects.KeyCount);
      console.info('Existing objects listing:');
      objects.Contents.map(i => i.Key).forEach((filename) =>
        console.info(`  ${filename}`));
    }
    callback(null, files);
  },
  (files, callback) => {
    console.log(`\nUpload to S3 (${options.env}) is starting...\n`);
    const index = files.splice(files.indexOf('index.html'), 1);
    invariant(index[0] === 'index.html', 'index.html should be present');
    filesCount = files.length + 1;
    map(files, (file, _callback) => {
      copyQueue.push({
        file,
        folder: absoluteFolder,
      }, (err) => {
        if (! err) console.info(progress(), 'Crunched:', file);
        _callback(err);
      });
    }, callback);
  }
].filter(i => i), (err) => {
  if (err) {
    console.error(colors.red('Error!'), err);
    process.exit(1);
  }
});

// copyWorker: streams files to a temporary location while compressing
function copyWorker(task, callback) {
  const { folder, file } = task;
  const filePath = path.join(folder, file);
  const mimeType = mime.lookup(file);
  const isZippable = ! NOZIP_MIME_TEST.test(mimeType);
  const { createGzip } = isProductionEnv ? zopfli : zlib;
  const counter = countingStream();
  const inStream = fs.createReadStream(filePath).pipe(counter);
  temp.open('omniupload', (err, tempFile) => {
    if (err) return callback(err);
    const outStream = fs.createWriteStream(tempFile.path);
    isZippable ?
      inStream.pipe(createGzip(ZIP_OPTS)).pipe(outStream) :
      inStream.pipe(outStream);
    outStream.on('finish', () => {
      originalSizeAll += counter.bytes;
      uploadQueue.push({
        file,
        mimeType,
        path: tempFile.path,
        encoding: isZippable ? 'gzip' : undefined,
        originalSize: counter.bytes,
      }, (_err) => {
        if (_err) {
          console.error(colors.red('Error!'), file, _err);
          process.exit(1);
        }
      });
      callback();
    });
  });
}

// uploadWorker: uploads each file to S3
function uploadWorker(task, callback) {
  const { file, mimeType, encoding, originalSize } = task;
  fs.stat(task.path, (err, { size }) => {
    if (err) return callback(err);
    const ratio = (size / originalSize).toFixed(2);
    let details = `(${mimeType})`;
    details += encoding ? ` (${encoding}, ratio ${ratio})` : '';
    if (options.dry) {
      console.info(progress(), 'Would upload:', file, details);
      callback();
    } else {
      s3.putObject({
        Bucket: config.bucket,
        CacheControl: file.endsWith('index.html') ?
            CACHE_CONTROL_INDEX :
            CACHE_CONTROL_OTHERS,
        ContentLength: size,
        ContentType: mimeType,
        ContentEncoding: encoding,
        Key: file,
        Body: fs.createReadStream(task.path),
        ACL: 'public-read',
      }, (_err) => {
        if (_err) {
          console.info(progress(), 'Errored, retrying:', file);
        } else {
          console.info(progress(), 'Uploaded:', file, details);
          compressedSizeAll += size;
        }
        callback(_err);
      });
    }
  });
}

// progress: returns progression through both queues as a percentage
function progress() {
  const waiting =
      copyQueue.length() + uploadQueue.length() + copyQueue.running() + uploadQueue.running();
  const perc = Math.round(100 - ((waiting / filesCount) * 100));
  return `${perc.toString()}%`;
}
<commit_msg>Made zopfli optional via cli flag, rearranged options<commit_after>#!/usr/bin/env node

const AWS = require('aws-sdk');
const { queue, waterfall, map, retryable } = require('async');
const invariant = require('invariant');
const path = require('path');
const fs = require('fs');
const mime = require('mime');
const colors = require('colors/safe');
const zlib = require('zlib');
const zopfli = require('node-zopfli');
const temp = require('temp').track();
const getUsage = require('command-line-usage');
const { countingStream } = require('stream-toolkit');
const writeConfig = require('./write-config');

const optionList = [{
  name: 'dry',
  alias: 'd',
  type: Boolean,
  description: 'Dry run - skip the upload',
}, {
  name: 'env',
  alias: 'e',
  type: String,
  description: 'Specifies environment to deploy to, e.g. qa',
}, {
  name: 'zopfli',
  alias: 'z',
  type: Boolean,
  description: 'Use zopfli instead of gzip to compress',
}];

const options = require('command-line-args')(optionList);

if (! options.env) {
  console.log(getUsage([{
    header: 'Omni dist uploader',
    content: 'Compresses dist assets and uploads them to the S3 bucket',
  }, {
    header: 'Options',
    optionList,
  }]));
  process.exit(2);
}

const ZIP_OPTS = { level: 9 };
const QUEUE_CONCURRENCY = 50;  // safeguard. concurrency rocks
const UPLOAD_RETRIES = { times: 1000, interval: 100 };
const NOZIP_MIME_TEST = /^(image\/png|application\/font-woff)/; // woffs already zipped
const CACHE_CONTROL_INDEX = 'no-cache';  // keep history buffer. http://stackoverflow.com/a/18516720
const CACHE_CONTROL_OTHERS = 'public, max-age=31536000';  // 1 year

const config = require(path.resolve(`ci/${options.env}.json`)); // eslint-disable-line import/no-dynamic-require

if (config.region) {
  AWS.config.update({ region: config.region });
}

if (config.accessKeyId) {
  console.log('Will use custom accessKey.\n');
  AWS.config.update({
    accessKeyId: config.accessKeyId,
    secretAccessKey: config.secretAccessKey,
  });
}

const s3 = new AWS.S3();

writeConfig(options.env);

options.dry && console.log('DRY RUN! No upload will actually happen.\n');
options.zopfli &&
    console.log(`This production build will use zopfli, which is slower to compress!\n`);

const copyQueue = queue(copyWorker, QUEUE_CONCURRENCY);
const uploadQueue = queue(retryable(UPLOAD_RETRIES, uploadWorker), QUEUE_CONCURRENCY);
const absoluteFolder = path.resolve('dist');

const indexCopyTask = {  // index.html comes last
  file: 'index.html',
  folder: absoluteFolder,
};

let filesCount;
let originalSizeAll = 0;
let compressedSizeAll = 0;

// post-upload flow: runs after uploads have finished
uploadQueue.drain = () => {
  if (copyQueue.length() || uploadQueue.length() ||
      copyQueue.running() || uploadQueue.running()) return;  // tasks remain!
  copyQueue.push(indexCopyTask);
  uploadQueue.drain = () => {
    const original = originalSizeAll / 1000000;  // B to MB
    const compressed = compressedSizeAll / 1000000;
    console.log(
        '\nAll done.' +
        ` Source: ${original.toFixed(2)}MB,` +
        ` Uploaded: ${compressed.toFixed(2)}MB.`);
    uploadQueue.drain = () => {};
    process.exit(0);
  };
};

// main flow: lists S3 objects, lists files, populates copyQueue
waterfall([
  ! options.dry ? (callback) => {
    s3.listObjectsV2({
      Bucket: config.bucket,
    }, callback);
  } : null,
  (objects, callback) => {
    callback = callback || objects;  // if listObjectsV2 didn't happen in the prior step
    objects = typeof objects === 'function' ? null : objects;
    fs.readdir(absoluteFolder, (err, files) => {
      callback(err, objects, files);
    });
  },
  (objects, files, callback) => {
    if (objects) {
      console.info('Pre-upload bucket object count:', objects.KeyCount);
      console.info('Existing objects listing:');
      objects.Contents.map(i => i.Key).forEach((filename) =>
        console.info(`  ${filename}`));
    }
    callback(null, files);
  },
  (files, callback) => {
    console.log(`\nUpload to S3 (${options.env}) is starting...\n`);
    const index = files.splice(files.indexOf('index.html'), 1);
    invariant(index[0] === 'index.html', 'index.html should be present');
    filesCount = files.length + 1;
    map(files, (file, _callback) => {
      copyQueue.push({
        file,
        folder: absoluteFolder,
      }, (err) => {
        if (! err) console.info(progress(), 'Crunched:', file);
        _callback(err);
      });
    }, callback);
  }
].filter(i => i), (err) => {
  if (err) {
    console.error(colors.red('Error!'), err);
    process.exit(1);
  }
});

// copyWorker: streams files to a temporary location while compressing
function copyWorker(task, callback) {
  const { folder, file } = task;
  const filePath = path.join(folder, file);
  const mimeType = mime.lookup(file);
  const isZippable = ! NOZIP_MIME_TEST.test(mimeType);
  const { createGzip } = options.zopfli ? zopfli : zlib;
  const counter = countingStream();
  const inStream = fs.createReadStream(filePath).pipe(counter);
  temp.open('omniupload', (err, tempFile) => {
    if (err) return callback(err);
    const outStream = fs.createWriteStream(tempFile.path);
    isZippable ?
      inStream.pipe(createGzip(ZIP_OPTS)).pipe(outStream) :
      inStream.pipe(outStream);
    outStream.on('finish', () => {
      originalSizeAll += counter.bytes;
      uploadQueue.push({
        file,
        mimeType,
        path: tempFile.path,
        encoding: isZippable ? 'gzip' : undefined,
        originalSize: counter.bytes,
      }, (_err) => {
        if (_err) {
          console.error(colors.red('Error!'), file, _err);
          process.exit(1);
        }
      });
      callback();
    });
  });
}

// uploadWorker: uploads each file to S3
function uploadWorker(task, callback) {
  const { file, mimeType, encoding, originalSize } = task;
  fs.stat(task.path, (err, { size }) => {
    if (err) return callback(err);
    const ratio = (size / originalSize).toFixed(2);
    let details = `(${mimeType})`;
    details += encoding ? ` (${encoding}, ratio ${ratio})` : '';
    if (options.dry) {
      console.info(progress(), 'Would upload:', file, details);
      callback();
    } else {
      s3.putObject({
        Bucket: config.bucket,
        CacheControl: file.endsWith('index.html') ?
            CACHE_CONTROL_INDEX :
            CACHE_CONTROL_OTHERS,
        ContentLength: size,
        ContentType: mimeType,
        ContentEncoding: encoding,
        Key: file,
        Body: fs.createReadStream(task.path),
        ACL: 'public-read',
      }, (_err) => {
        if (_err) {
          console.info(progress(), 'Errored, retrying:', file);
        } else {
          console.info(progress(), 'Uploaded:', file, details);
          compressedSizeAll += size;
        }
        callback(_err);
      });
    }
  });
}

// progress: returns progression through both queues as a percentage
function progress() {
  const waiting =
      copyQueue.length() + uploadQueue.length() + copyQueue.running() + uploadQueue.running();
  const perc = Math.round(100 - ((waiting / filesCount) * 100));
  return `${perc.toString()}%`;
}
<|endoftext|>


<commit_before>var hackfile = function(src) {
  if (Buffer.isBuffer(src)) src = src.toString()

  var lines = src.replace(/\s+$/, '').split('\n')

  var indent = lines.reduce(function(indent, line) {
    return indent || (line.match(/(\s+)\S/) || [])[1]
  }, null)

  var latest = null
  var result = {}

  lines.forEach(function(line) {
    if (!line.trim()) return

    var indented = line.indexOf(indent) === 0

    if (/^\s/.test(line) && !indented) throw new SyntaxError('Inconsistent indentation')
    if (!latest && indented) throw new SyntaxError('Unnamed indentation group not allowed')

    if (indented) return result[latest].push(line.trim().split(/\s+/))

    latest = line.trim()
    result[latest] = []
  })

  return result
}

module.exports = hackfile
<commit_msg>First method of parsing hackfile according to new spec, a bit wasteful though<commit_after>var hackfile = function(src) {
  if (Buffer.isBuffer(src)) src = src.toString()

  var lines = src.replace(/\s+$/, '').split('\n')

  var indent = lines.reduce(function(indent, line) {
    return indent || (line.match(/(\s+)\S/) || [])[1]
  }, null)

  var latest = null
  var result = {}

  lines.forEach(function(line) {
    if (!line.trim()) return

    var indented = line.indexOf(indent) === 0

    if (/^\s/.test(line) && !indented) throw new SyntaxError('Inconsistent indentation')
    if (!latest && indented) throw new SyntaxError('Unnamed indentation group not allowed')

    if (indented) return result[latest].push(line.trim())

    latest_line = line.trim().split(/\s+/)
    latest = latest_line.splice(0, 1)

    result[latest] = []
    if (latest_line.length > 1) result[latest].push(latest_line.join(" "))
  })

  return result
}

module.exports = hackfile
<|endoftext|>


<commit_before>// closure
var serviceHandler = function(service) {
  /*
   * Below are the supported options for the serviceHandler:
   *
   * - data (object): request data payload
   * - params (object): use to replace the tokens in the url
   * - query (object): use to build the query string appended to the url
   * - callback (function): callback to use, with a default which emits 'success' or 'error'
   *   event depending on res.ok value
   * - edit (function): callback to use, to tweak req if needed.
   */
  return function(options) {
    options = options || {};
    var data = options.data || {};
    var params = options.params || {};
    var query = options.query || {};
    var callback = options.callback || null;
    var edit = options.edit || null;

    var req = this.request(service, data, params, query);

    // edit request if function defined
    if (edit && "function" === typeof edit) {
      edit(req);
    }

    var resolver = {};

    var p = new Promise(function (resolve, reject) {
      resolver = {
        resolve: resolve,
        reject: reject
      };
    });

    req.end(callback ? callback : function(res) {
      resolver[!res.error ? "resolve" : "reject"](res);
    });

    return p;
  };
};

function Api(config) {
  this.config = config;

  // create a hash-liked object where all the services handlers are registered
  this.api = Object.create(null);

  for (var name in config.services) {
    if (!Object.prototype.hasOwnProperty(this, name)) {
      // syntatic sugar: install a service handler available on
      // the api instance with service name
      this.api[name] = serviceHandler(name).bind(this);
    }
  }
}

Api.prototype = {
  paramsPattern: /:(\w+)/g,

  service: function(id) {
    return this.config.services[id];
  },

  url: function(id) {
    var url = this.config.baseUrl;
    var resource = this.service(id);

    // from time being it"s a simple map
    if (resource) {
      var path;

      if (typeof resource === "string") {
        path = resource;
      }

      if (typeof resource === "object" && resource.path !== undefined) {
        path = resource.path;
      }

      if (!path) {
        throw new Error("path is not defined for route $" + id);
      }

      url += path[0] === "/" ? path : "/" + path;
    }

    return url;
  },

  replaceUrl: function(url, params) {
    var tokens = url.match(this.paramsPattern);

    if (!tokens || !tokens.length) {
      return url;
    }

    for (var i = 0, len = tokens.length; i < len; i += 1) {
      var token = tokens[i];
      var name = token.substring(1);
      if (params[name]) {
        url = url.replace(token, params[name]);
      }
    }
    return url;
  },

  buildUrlQuery: function(query) {
    if (!query) {
      return "";
    }

    var queryString;

    if (typeof query === "string") {
      queryString = query;
    } else {
      var queryArgs = [];
      for (var queryArg in query) {
        queryArgs.push(queryArg + "=" + query[queryArg]);
      }
      queryString = queryArgs.join("&");
    }
    return queryString ? "?" + queryString : "";
  },

  buildUrl: function(id, params, query) {
    var url = this.url(id);

    if (params) {
      url = this.replaceUrl(url, params);
    }

    if (query) {
      url += this.buildUrlQuery(query);
    }

    return url;
  },

  request: function(id, data, params, query) {
    var service = this.service(id);
    var method = (typeof service === "string" ? "get" : service.method ||
      "get").toLowerCase();
    // fix for delete being a reserved word
    if (method === "delete") {
      method = "del";
    }

    if (!this.agent) {
      throw new Error("missing superagent or any api compatible agent.");
    }

    var request = this.agent[method];
    if (!request) {
      throw new Error("Invalid method [" + service.method + "]");
    }

    var _req = request(this.buildUrl(id, params, query), data);

    // add global headers
    this._setHeaders(_req, this.config.headers);

    // add global options to request headers
    this._setOptions(_req, this.config.options);

    // add service options to request headers
    this._setOptions(_req, service.options);

    // add service headers
    this._setHeaders(_req, service.headers);

    // add runtime headers
    this._setHeaders(_req, this.headers);

    // set credentials
    if (this.config.withCredentials) {
      _req.withCredentials();
    }

    return _req;
  },

  addHeader: function(name, value) {
    this.headers = this.headers || {};
    this.headers[name] = value;
  },

  removeHeader: function(name) {
    if (this.headers && this.headers[name]) {
      delete this.headers[name];
    }
  },

  _setHeaders: function(req, headers) {
    for (var header in headers) {
      req.set(header, headers[header]);
    }
  },

  _setOptions: function(req, options) {
    for (var option in options) {
      req[option](options[option]);
    }
  }
};

export default Api;
<commit_msg>feat(buildUrl): do not prepend baseUrl if path is already an url<commit_after>// closure
var serviceHandler = function(service) {
  /*
   * Below are the supported options for the serviceHandler:
   *
   * - data (object): request data payload
   * - params (object): use to replace the tokens in the url
   * - query (object): use to build the query string appended to the url
   * - callback (function): callback to use, with a default which emits 'success' or 'error'
   *   event depending on res.ok value
   * - edit (function): callback to use, to tweak req if needed.
   */
  return function(options) {
    options = options || {};
    var data = options.data || {};
    var params = options.params || {};
    var query = options.query || {};
    var callback = options.callback || null;
    var edit = options.edit || null;

    var req = this.request(service, data, params, query);

    // edit request if function defined
    if (edit && "function" === typeof edit) {
      edit(req);
    }

    var resolver = {};

    var p = new Promise(function (resolve, reject) {
      resolver = {
        resolve: resolve,
        reject: reject
      };
    });

    req.end(callback ? callback : function(res) {
      resolver[!res.error ? "resolve" : "reject"](res);
    });

    return p;
  };
};

function Api(config) {
  this.config = config;

  // create a hash-liked object where all the services handlers are registered
  this.api = Object.create(null);

  for (var name in config.services) {
    if (!Object.prototype.hasOwnProperty(this, name)) {
      // syntatic sugar: install a service handler available on
      // the api instance with service name
      this.api[name] = serviceHandler(name).bind(this);
    }
  }
}

Api.prototype = {
  paramsPattern: /:(\w+)/g,

  service: function(id) {
    return this.config.services[id];
  },

  url: function(id) {
    var url = this.config.baseUrl;
    var resource = this.service(id);

    // from time being it"s a simple map
    if (resource) {
      var path;

      if (typeof resource === "string") {
        path = resource;
      }

      if (typeof resource === "object" && resource.path !== undefined) {
        path = resource.path;
      }

      if (!path) {
        throw new Error("path is not defined for route $" + id);
      }

      if (path.match(/^https?:\/\//)) {
        url = path;
      }
      else {
        url += path[0] === "/" ? path : "/" + path;
      }
    }

    return url;
  },

  replaceUrl: function(url, params) {
    var tokens = url.match(this.paramsPattern);

    if (!tokens || !tokens.length) {
      return url;
    }

    for (var i = 0, len = tokens.length; i < len; i += 1) {
      var token = tokens[i];
      var name = token.substring(1);
      if (params[name]) {
        url = url.replace(token, params[name]);
      }
    }
    return url;
  },

  buildUrlQuery: function(query) {
    if (!query) {
      return "";
    }

    var queryString;

    if (typeof query === "string") {
      queryString = query;
    } else {
      var queryArgs = [];
      for (var queryArg in query) {
        queryArgs.push(queryArg + "=" + query[queryArg]);
      }
      queryString = queryArgs.join("&");
    }
    return queryString ? "?" + queryString : "";
  },

  buildUrl: function(id, params, query) {
    var url = this.url(id);

    if (params) {
      url = this.replaceUrl(url, params);
    }

    if (query) {
      url += this.buildUrlQuery(query);
    }

    return url;
  },

  request: function(id, data, params, query) {
    var service = this.service(id);
    var method = (typeof service === "string" ? "get" : service.method ||
      "get").toLowerCase();
    // fix for delete being a reserved word
    if (method === "delete") {
      method = "del";
    }

    if (!this.agent) {
      throw new Error("missing superagent or any api compatible agent.");
    }

    var request = this.agent[method];
    if (!request) {
      throw new Error("Invalid method [" + service.method + "]");
    }

    var _req = request(this.buildUrl(id, params, query), data);

    // add global headers
    this._setHeaders(_req, this.config.headers);

    // add global options to request headers
    this._setOptions(_req, this.config.options);

    // add service options to request headers
    this._setOptions(_req, service.options);

    // add service headers
    this._setHeaders(_req, service.headers);

    // add runtime headers
    this._setHeaders(_req, this.headers);

    // set credentials
    if (this.config.withCredentials) {
      _req.withCredentials();
    }

    return _req;
  },

  addHeader: function(name, value) {
    this.headers = this.headers || {};
    this.headers[name] = value;
  },

  removeHeader: function(name) {
    if (this.headers && this.headers[name]) {
      delete this.headers[name];
    }
  },

  _setHeaders: function(req, headers) {
    for (var header in headers) {
      req.set(header, headers[header]);
    }
  },

  _setOptions: function(req, options) {
    for (var option in options) {
      req[option](options[option]);
    }
  }
};

export default Api;
<|endoftext|>


<commit_before>// Read and eval library
eval(require('fs').readFileSync('./node_modules/diacritical/diacritical.js', 'utf8'));

// The diacritical.js file defines a class 'Diacritical' which is all we want to export
exports.Diacritical = Diacritical;

<commit_msg>exported instantiated object<commit_after>// Read and eval library
eval(require('fs').readFileSync('./node_modules/diacritical/diacritical.js', 'utf8'));

// The diacritical.js file defines a class 'Diacritical' which is all we want to export
exports.Diacritical = new Diacritical();

<|endoftext|>