<commit_before>'use strict';

var pm2 = require('pm2');
var pmx = require('pmx');
var request = require('request');

// Get the configuration from PM2
var conf = pmx.initModule();

// initialize buffer and queue_max opts
// buffer seconds can be between 1 and 5
conf.buffer_seconds = (conf.buffer_seconds > 0 && conf.buffer_seconds < 5) ? conf.buffer_seconds : 2;

// queue max can be between 10 and 100
conf.queue_max = (conf.queue_max > 9 && conf.queue_max <= 100) ? conf.queue_max : 10;

// create the message queue
var messages = [];

// create the suppressed object for sending suppression messages
var suppressed = {
    isSuppressed: false,
    date: new Date().getTime()
};

// Function to send event to Telegram
function sendTelegram(message) {

    var name = message.name;
    var event = message.event;
    var description = message.description;
    var timestamp = message.timestamp;

    // If a Telegram URL is not set, we do not want to continue and nofify the user that it needs to be set. URL must be formatted as ' https://api.telegram.org/bot<TOKEN>/sendMessage'
    if (!conf.telegram_url) return console.error("There is no telegram URL set, please set the telegram URL: 'pm2 set pm2-telegram-notify:telegram_url https://telegram_url'");

 // checks for event name and timestamps
  if (((event == 'log' && messages[0].event =='error')  && (timestamp <= messages[0].timestamp)) || event == 'exception'){

    //Check for description's content
    if (description.length > 30) {
    //Text for sending to telegram, must be <string>
     var length = 4096;
     var text  = (name + ' - ' + (event == 'log' && 'error') +  ' - ' +  description + messages[0].description);
     var cuttedDesc = text.substring(0, length);

      // Options for the post request
      var options = {
          method: 'post',
          headers: {'content-type' : 'application/x-www-form-urlencoded'},
          body: "chat_id="+conf.chat_id+"&text="+cuttedDesc,
          json: true,
          url: conf.telegram_url
      };

     // Finally, make the post request to the Telegram
     request(options, function(err, res, body) {
         if (err) return console.error(err);
         console.log(body)
     });
    }
  }
}

// Function to get the next buffer of messages (buffer length = 1s)
function bufferMessage() {
    var nextMessage = messages.shift();

    if (!conf.buffer) { return nextMessage; }

    nextMessage.buffer = [nextMessage.description];

    // continue shifting elements off the queue while they are the same event and timestamp so they can be buffered together into a single request
    while (messages.length
        && (messages[0].timestamp >= nextMessage.timestamp && messages[0].timestamp < (nextMessage.timestamp  + conf.buffer_seconds))
        && messages[0].event === nextMessage.event) {

        // append description to our buffer and shift the message off the queue and discard it
        nextMessage.buffer.push(messages[0].description);
        messages.shift();

    }

    // join the buffer with newlines
    nextMessage.description = nextMessage.buffer.join("\n");

    // delete the buffer from memory
    delete nextMessage.buffer;

    return nextMessage;
}

// Function to process the message queue
function processQueue() {

    // If we have a message in the message queue, removed it from the queue and send it to telegram
    if (messages.length > 0) {
        sendTelegram(bufferMessage());
    }

    // If there are over conf.queue_max messages in the queue, send the suppression message if it has not been sent and delete all the messages in the queue after this amount (default: 100)
    if (messages.length > conf.queue_max) {
        if (!suppressed.isSuppressed) {
            suppressed.isSuppressed = true;
            suppressed.date = new Date().getTime();
            sendTelegram({
                name: 'pm2-telegram-notify',
                event: 'suppressed',
                description: 'Messages are being suppressed due to rate limiting.'
            });
        }
        messages.splice(conf.queue_max, messages.length);
    }

    // If the suppression message has been sent over 1 minute ago, we need to reset it back to false
    if (suppressed.isSuppressed && suppressed.date < (new Date().getTime() - 60000)) {
            suppressed.isSuppressed = false;
    }

    // Wait 10 seconds and then process the next message in the queue
     setTimeout(function() {
         processQueue();
     }, 10000);
}

// Start listening on the PM2 BUS
pm2.launchBus(function(err, bus) {

    // Listen for process logs
    if (conf.log) {
        bus.on('log:out', function(data) {
            if (data.process.name !== 'pm2-telegram-notify') {
                messages.push({
                    name: data.process.name,
                    event: 'log',
                    description: data.data,
                    timestamp: Math.floor(Date.now() / 100000),
                });
            }
        });
    }

    // Listen for process errors
    if (conf.error) {
        bus.on('log:err', function(data) {
            if (data.process.name !== 'pm2-telegram-notify') {
                messages.push({
                    name: data.process.name,
                    event: 'error',
                    description: data.data,
                    timestamp: Math.floor(Date.now() / 99999),
                });
            }
        });
    }

    // Listen for PM2 kill
    if (conf.kill) {
        bus.on('pm2:kill', function(data) {
            messages.push({
                name: 'PM2',
                event: 'kill',
                description: data.msg,
                timestamp: Math.floor(Date.now() / 100000),
            });
        });
    }

    // Listen for process exceptions
    if (conf.exception) {
        bus.on('process:exception', function(data) {
            if (data.process.name !== 'pm2-telegram-notify') {
                messages.push({
                    name: data.process.name,
                    event: 'exception',
                    description: JSON.stringify(data.data),
                    timestamp: Math.floor(Date.now() / 100000),
                });
            }
        });
    }

    // Listen for PM2 events
    bus.on('process:event', function(data) {
        if (conf[data.event]) {
            if (data.process.name !== 'pm2-telegram-notify') {
                messages.push({
                    name: data.process.name,
                    event: data.event,
                    description: 'The following event has occured on the PM2 process ' + data.process.name + ': ' + data.event,
                    timestamp: Math.floor(Date.now() / 100000),
                });
            }
        }
    });

    // Start the message processing
    processQueue();

});
<commit_msg>Buffer timing changed<commit_after>'use strict';

var pm2 = require('pm2');
var pmx = require('pmx');
var request = require('request');

// Get the configuration from PM2
var conf = pmx.initModule();

// initialize buffer and queue_max opts
// buffer seconds can be between 0 and 5
conf.buffer_seconds = (conf.buffer_seconds > 0 && conf.buffer_seconds < 5) ? conf.buffer_seconds : 2;

// queue max can be between 10 and 100
conf.queue_max = (conf.queue_max > 9 && conf.queue_max <= 100) ? conf.queue_max : 10;

// create the message queue
var messages = [];

// create the suppressed object for sending suppression messages
var suppressed = {
    isSuppressed: false,
    date: new Date().getTime()
};

// Function to send event to Telegram
function sendTelegram(message) {

    var name = message.name;
    var event = message.event;
    var description = message.description;
    var timestamp = message.timestamp;

    // If a Telegram URL is not set, we do not want to continue and nofify the user that it needs to be set. URL must be formatted as ' https://api.telegram.org/bot<TOKEN>/sendMessage'
    if (!conf.telegram_url) return console.error("There is no telegram URL set, please set the telegram URL: 'pm2 set pm2-telegram-notify:telegram_url https://telegram_url'");

 // checks for event name and timestamps
  if (((event == 'log' && messages[0].event =='error')  && (timestamp <= messages[0].timestamp)) || event == 'exception'){

    //Check for description's content
    if (description.length > 30) {
    //Text for sending to telegram, must be <string>
     var length = 4096;
     var text  = (name + ' - ' + (event == 'log' && 'error') +  ' - ' +  description + messages[0].description);
     var cuttedDesc = text.substring(0, length);

      // Options for the post request
      var options = {
          method: 'post',
          headers: {'content-type' : 'application/x-www-form-urlencoded'},
          body: "chat_id="+conf.chat_id+"&text="+cuttedDesc,
          json: true,
          url: conf.telegram_url
      };

     // Finally, make the post request to the Telegram
     request(options, function(err, res, body) {
         if (err) return console.error(err);
         console.log(body)
     });
    }
  }
}

// Function to get the next buffer of messages (buffer length = 1s)
function bufferMessage() {
    var nextMessage = messages.shift();

    if (!conf.buffer) { return nextMessage; }

    nextMessage.buffer = [nextMessage.description];

    // continue shifting elements off the queue while they are the same event and timestamp so they can be buffered together into a single request
    while (messages.length
        && (messages[0].timestamp >= nextMessage.timestamp && messages[0].timestamp < (nextMessage.timestamp  + conf.buffer_seconds))
        && messages[0].event === nextMessage.event) {

        // append description to our buffer and shift the message off the queue and discard it
        nextMessage.buffer.push(messages[0].description);
        messages.shift();

    }

    // join the buffer with newlines
    nextMessage.description = nextMessage.buffer.join("\n");

    // delete the buffer from memory
    delete nextMessage.buffer;

    return nextMessage;
}

// Function to process the message queue
function processQueue() {

    // If we have a message in the message queue, removed it from the queue and send it to telegram
    if (messages.length > 0) {
        sendTelegram(bufferMessage());
    }

    // If there are over conf.queue_max messages in the queue, send the suppression message if it has not been sent and delete all the messages in the queue after this amount (default: 100)
    if (messages.length > conf.queue_max) {
        if (!suppressed.isSuppressed) {
            suppressed.isSuppressed = true;
            suppressed.date = new Date().getTime();
            sendTelegram({
                name: 'pm2-telegram-notify',
                event: 'suppressed',
                description: 'Messages are being suppressed due to rate limiting.'
            });
        }
        messages.splice(conf.queue_max, messages.length);
    }

    // If the suppression message has been sent over 1 minute ago, we need to reset it back to false
    if (suppressed.isSuppressed && suppressed.date < (new Date().getTime() - 60000)) {
            suppressed.isSuppressed = false;
    }

    // Wait 10 seconds and then process the next message in the queue
     setTimeout(function() {
         processQueue();
     }, 10000);
}

// Start listening on the PM2 BUS
pm2.launchBus(function(err, bus) {

    // Listen for process logs
    if (conf.log) {
        bus.on('log:out', function(data) {
            if (data.process.name !== 'pm2-telegram-notify') {
                messages.push({
                    name: data.process.name,
                    event: 'log',
                    description: data.data,
                    timestamp: Math.floor(Date.now() / 100000),
                });
            }
        });
    }

    // Listen for process errors
    if (conf.error) {
        bus.on('log:err', function(data) {
            if (data.process.name !== 'pm2-telegram-notify') {
                messages.push({
                    name: data.process.name,
                    event: 'error',
                    description: data.data,
                    timestamp: Math.floor(Date.now() / 99999),
                });
            }
        });
    }

    // Listen for PM2 kill
    if (conf.kill) {
        bus.on('pm2:kill', function(data) {
            messages.push({
                name: 'PM2',
                event: 'kill',
                description: data.msg,
                timestamp: Math.floor(Date.now() / 100000),
            });
        });
    }

    // Listen for process exceptions
    if (conf.exception) {
        bus.on('process:exception', function(data) {
            if (data.process.name !== 'pm2-telegram-notify') {
                messages.push({
                    name: data.process.name,
                    event: 'exception',
                    description: JSON.stringify(data.data),
                    timestamp: Math.floor(Date.now() / 100000),
                });
            }
        });
    }

    // Listen for PM2 events
    bus.on('process:event', function(data) {
        if (conf[data.event]) {
            if (data.process.name !== 'pm2-telegram-notify') {
                messages.push({
                    name: data.process.name,
                    event: data.event,
                    description: 'The following event has occured on the PM2 process ' + data.process.name + ': ' + data.event,
                    timestamp: Math.floor(Date.now() / 100000),
                });
            }
        }
    });

    // Start the message processing
    processQueue();

});
<|endoftext|>


<commit_before>/**
 * This is the hive node.js API, it allows you to start hive from inside another node app.
 */

var architect = require('architect')
  , findComponents = require('./lib/findComponents')

module.exports.load = function(dir, cb) {
  var componentDir, components
  componentDir = dir+'/node_modules'
  components = findComponents(componentDir)

  architect.createApp(components, cb)
}<commit_msg>Document hive.load<commit_after>/**
 * This is the hive node.js API, it allows you to start hive from inside another node app.
 */

var architect = require('architect')
  , findComponents = require('./lib/findComponents')

/**
 * @param dir {String} The hive instance directory to use
 * @param cb {Function} (err, architectApp)
 */
module.exports.load = function(dir, cb) {
  var componentDir, components
  componentDir = dir+'/node_modules'
  components = findComponents(componentDir)

  architect.createApp(components, cb)
}<|endoftext|>


<commit_before>/*
 * Created brightSPARK Labs
 * www.brightsparklabs.com
 */

'use strict';

// -----------------------------------------------------------------------------
// MODULES
// -----------------------------------------------------------------------------

var es       = require('event-stream');
var exec     = require('sync-exec');
var gutil    = require('gulp-util');
var moment   = require('moment');

// -----------------------------------------------------------------------------
// EXPORTS
// -----------------------------------------------------------------------------

module.exports = function() {
    // format to pass to 'git log'
    var headerFormat = "\\newpage%n%n\
-------------------------------------------------------------------%n\
**Document Control**%n\
---------------------  --------------------------------------------%n\
Last Modified On:      %ci%n%n\
Last Modified By:      %cn%n%n\
Generated On:          <%%= date %%>%n%n\
Generated From:        <%%= file.relative %%>%n%n\
Version Identifier:    %h%n%n\
--------------------------------------------------------------------%n\
%n\\newpage%n%n"

    var gitCommand = 'git --no-pager log -n1 --pretty=tformat:\'' +
                        headerFormat +'\'';

    return es.map(function(file, cb){
        var headerText = exec(gitCommand + ' ' + file.path).stdout;
        headerText = headerText || '';
        var data = {
            date : moment().format('YYYY-MM-DD HH:mm:ss ZZ'),
            file : file
        };
        file.contents = Buffer.concat([
            new Buffer(gutil.template(headerText, data)),
            file.contents
        ]);
        cb(null, file);
    });
};

<commit_msg>INC-66: Do not include 'Generated On' date in header as it prevents consistent artifact generation<commit_after>/*
 * Created brightSPARK Labs
 * www.brightsparklabs.com
 */

'use strict';

// -----------------------------------------------------------------------------
// MODULES
// -----------------------------------------------------------------------------

var es       = require('event-stream');
var exec     = require('sync-exec');
var gutil    = require('gulp-util');
var moment   = require('moment');

// -----------------------------------------------------------------------------
// EXPORTS
// -----------------------------------------------------------------------------

module.exports = function() {
    // format to pass to 'git log'
    var headerFormat = "\\newpage%n%n\
-------------------------------------------------------------------%n\
**Document Control**%n\
---------------------  --------------------------------------------%n\
Last Modified On:      %ci%n%n\
Last Modified By:      %cn%n%n\
Generated From:        <%%= file.relative %%>%n%n\
Version Identifier:    %h%n%n\
--------------------------------------------------------------------%n\
%n\\newpage%n%n"

    var gitCommand = 'git --no-pager log -n1 --pretty=tformat:\'' +
                        headerFormat +'\'';

    return es.map(function(file, cb){
        var headerText = exec(gitCommand + ' ' + file.path).stdout;
        headerText = headerText || '';
        var data = {
            file : file
        };
        file.contents = Buffer.concat([
            new Buffer(gutil.template(headerText, data)),
            file.contents
        ]);
        cb(null, file);
    });
};

<|endoftext|>


<commit_before>(function(root, factory) {
    if (typeof exports === 'object') {
        module.exports = factory(require('unexpected'));
    } else if (typeof define === 'function' && define.amd) {
        define(['unexpected'], factory);
    } else {
        root.expect = factory(root.weknowhow.expect);
    }
})(this, function(unexpected) {
    function extend(obj) {
        var args = Array.prototype.slice.call(arguments, 1);
        args.forEach(function(source) {
            if (source) {
                for (var prop in source) {
                    obj[prop] = source[prop];
                }
            }
        });
        return obj;
    }

    function expandFlags(pattern, flags) {
        return pattern
            .replace(/\[(!?)([^\]]+)\] ?/g, function(match, negate, flag) {
                return Boolean(flags[flag]) !== Boolean(negate)
                    ? flag + ' '
                    : '';
            })
            .trim();
    }

    var flags = {
        not: ['to', 'be', 'have', 'include', 'only'],
        to: ['be', 'have', 'include', 'only', 'not'],
        only: ['have'],
        have: ['own'],
        be: ['an', 'a']
    };

    var assertions = ['ok', 'within', 'empty', 'above', 'greaterThan'];

    function defineNextStep(prop, parent, stepFlags) {
        stepFlags = stepFlags || flags;

        Object.defineProperty(parent, prop, {
            get: function() {
                var obj = new ExpectFacade(parent.subject, stepFlags[prop]);
                obj.flags = extend({}, parent.flags);
                obj.flags[prop] = true;

                if (typeof ExpectFacade.prototype[prop] === 'function') {
                    var fn = function() {
                        ExpectFacade.prototype[prop].apply(obj, arguments);

                        // allow chaining with .and.
                        defineNextStep('and', obj, { and: flags.to });

                        return obj;
                    };

                    assertions
                        .concat(flags[prop] || [])
                        .forEach(function(flag) {
                            defineNextStep(flag, fn);
                        });

                    fn.flags = obj.flags;
                    fn.subject = obj.subject;

                    return fn;
                }

                return obj;
            }
        });
    }

    function ExpectFacade(subject, nextSteps) {
        var that = this;

        this.flags = {};
        this.subject = subject;

        if (nextSteps) {
            nextSteps.forEach(function(prop) {
                defineNextStep(prop, that);
            });
        }
    }

    ExpectFacade.prototype.withArgs = function() {
        var result = new ExpectFacade(this.subject, Object.keys(flags));
        var subject = this.subject;
        result.flags = this.flags;
        var args = arguments;
        result.subject = function() {
            return subject.apply(null, args);
        };
        return result;
    };

    [
        { name: 'ok', assertion: 'to be ok' },
        { name: 'be', assertion: 'to be' },
        { name: 'equal', assertion: 'to be' },
        { name: 'a', assertion: 'to be a' },
        { name: 'an', assertion: 'to be an' },
        { name: 'eql', assertion: 'to equal' },
        { name: 'match', assertion: 'to match' },
        { name: 'contain', assertion: 'to contain' },
        { name: 'string', assertion: 'to contain' }, // TODO: expect('foobar').to.include.string('foo')
        { name: 'length', assertion: 'to have length' },
        { name: 'empty', assertion: 'to be empty' },
        { name: 'throwError', assertion: 'to throw', useExpectIt: true },
        { name: 'throwException', assertion: 'to throw', useExpectIt: true },
        { name: 'within', assertion: 'to be within' },
        { name: 'greaterThan', assertion: 'to be greater than' },
        { name: 'above', assertion: 'to be above' },
        { name: 'lessThan', assertion: 'to be less than' },
        { name: 'below', assertion: 'to be below' }
    ].forEach(function(methodDefinition) {
        ExpectFacade.prototype[methodDefinition.name] = function() {
            var args = Array.prototype.slice.call(arguments);
            var assertion = expandFlags(
                '[not] ' + methodDefinition.assertion,
                this.flags
            );

            if (
                methodDefinition.useExpectIt &&
                args.length === 1 &&
                typeof args[0] === 'function'
            ) {
                args[0] = unexpected.it(args[0]);
            }

            unexpected.apply(
                unexpected,
                [this.subject, assertion].concat(args)
            );
        };
    });

    ['property', 'properties'].forEach(function(methodName) {
        ExpectFacade.prototype[methodName] = function() {
            var args = Array.prototype.slice.call(arguments);
            var assertion = expandFlags(
                '[not] to have [own] ' + methodName,
                this.flags
            );

            unexpected.apply(
                unexpected,
                [this.subject, assertion].concat(args)
            );
        };
    });

    ['key', 'keys'].forEach(function(methodName) {
        ExpectFacade.prototype[methodName] = function() {
            var args = Array.prototype.slice.call(arguments);
            var assertion = expandFlags(
                '[not] to [only] have ' + methodName,
                this.flags
            );

            unexpected.apply(
                unexpected,
                [this.subject, assertion].concat(args)
            );
        };
    });

    ExpectFacade.prototype.fail = function() {
        var args = Array.prototype.slice.call(arguments);
        return unexpected.fail.apply(unexpected, args);
    };

    function expect() {
        if (arguments.length > 1) {
            unexpected.apply(null, arguments);
        } else {
            return new ExpectFacade(arguments[0], Object.keys(flags));
        }
    }

    expect.fail = function() {
        var args = Array.prototype.slice.call(arguments);
        return unexpected.fail.apply(unexpected, args);
    };
    expect.outputFormat = unexpected.outputFormat;

    expect.addAssertion = function(
        assertionName,
        unexpectedAssertionName,
        customAssertion
    ) {
        unexpected.addAssertion(unexpectedAssertionName, customAssertion);
        ExpectFacade.prototype[assertionName] = function() {
            var args = Array.prototype.slice.call(arguments);
            var assertion = expandFlags(unexpectedAssertionName, this.flags);

            unexpected.apply(
                unexpected,
                [this.subject, assertion].concat(args)
            );
        };
    };

    expect.version = '0.0.0';

    expect.unexpected = unexpected;

    return expect;
});
<commit_msg>Be explicit for the assertions attached to the dual purpose "be".<commit_after>(function(root, factory) {
    if (typeof exports === 'object') {
        module.exports = factory(require('unexpected'));
    } else if (typeof define === 'function' && define.amd) {
        define(['unexpected'], factory);
    } else {
        root.expect = factory(root.weknowhow.expect);
    }
})(this, function(unexpected) {
    function extend(obj) {
        var args = Array.prototype.slice.call(arguments, 1);
        args.forEach(function(source) {
            if (source) {
                for (var prop in source) {
                    obj[prop] = source[prop];
                }
            }
        });
        return obj;
    }

    function expandFlags(pattern, flags) {
        return pattern
            .replace(/\[(!?)([^\]]+)\] ?/g, function(match, negate, flag) {
                return Boolean(flags[flag]) !== Boolean(negate)
                    ? flag + ' '
                    : '';
            })
            .trim();
    }

    var flags = {
        not: ['to', 'be', 'have', 'include', 'only'],
        to: ['be', 'have', 'include', 'only', 'not'],
        only: ['have'],
        have: ['own'],
        be: []
    };
    var flagsAssertions = {
        be: ['a', 'an', 'ok', 'within', 'empty', 'above', 'greaterThan']
    };

    function defineNextStep(prop, parent, stepFlags) {
        stepFlags = stepFlags || flags;

        Object.defineProperty(parent, prop, {
            get: function() {
                var obj = new ExpectFacade(parent.subject, stepFlags[prop]);
                obj.flags = extend({}, parent.flags);
                obj.flags[prop] = true;

                if (typeof ExpectFacade.prototype[prop] === 'function') {
                    var fn = function() {
                        ExpectFacade.prototype[prop].apply(obj, arguments);

                        // allow chaining with .and.
                        defineNextStep('and', obj, { and: flags.to });

                        return obj;
                    };

                    if (flagsAssertions[prop]) {
                        var assertions = flagsAssertions[prop];
                        assertions
                            .concat(flags[prop] || [])
                            .forEach(function(flag) {
                                defineNextStep(flag, fn);
                            });
                    }

                    fn.flags = obj.flags;
                    fn.subject = obj.subject;

                    return fn;
                }

                return obj;
            }
        });
    }

    function ExpectFacade(subject, nextSteps) {
        var that = this;

        this.flags = {};
        this.subject = subject;

        if (nextSteps) {
            nextSteps.forEach(function(prop) {
                defineNextStep(prop, that);
            });
        }
    }

    ExpectFacade.prototype.withArgs = function() {
        var result = new ExpectFacade(this.subject, Object.keys(flags));
        var subject = this.subject;
        result.flags = this.flags;
        var args = arguments;
        result.subject = function() {
            return subject.apply(null, args);
        };
        return result;
    };

    [
        { name: 'ok', assertion: 'to be ok' },
        { name: 'be', assertion: 'to be' },
        { name: 'equal', assertion: 'to be' },
        { name: 'a', assertion: 'to be a' },
        { name: 'an', assertion: 'to be an' },
        { name: 'eql', assertion: 'to equal' },
        { name: 'match', assertion: 'to match' },
        { name: 'contain', assertion: 'to contain' },
        { name: 'string', assertion: 'to contain' }, // TODO: expect('foobar').to.include.string('foo')
        { name: 'length', assertion: 'to have length' },
        { name: 'empty', assertion: 'to be empty' },
        { name: 'throwError', assertion: 'to throw', useExpectIt: true },
        { name: 'throwException', assertion: 'to throw', useExpectIt: true },
        { name: 'within', assertion: 'to be within' },
        { name: 'greaterThan', assertion: 'to be greater than' },
        { name: 'above', assertion: 'to be above' },
        { name: 'lessThan', assertion: 'to be less than' },
        { name: 'below', assertion: 'to be below' }
    ].forEach(function(methodDefinition) {
        ExpectFacade.prototype[methodDefinition.name] = function() {
            var args = Array.prototype.slice.call(arguments);
            var assertion = expandFlags(
                '[not] ' + methodDefinition.assertion,
                this.flags
            );

            if (
                methodDefinition.useExpectIt &&
                args.length === 1 &&
                typeof args[0] === 'function'
            ) {
                args[0] = unexpected.it(args[0]);
            }

            unexpected.apply(
                unexpected,
                [this.subject, assertion].concat(args)
            );
        };
    });

    ['property', 'properties'].forEach(function(methodName) {
        ExpectFacade.prototype[methodName] = function() {
            var args = Array.prototype.slice.call(arguments);
            var assertion = expandFlags(
                '[not] to have [own] ' + methodName,
                this.flags
            );

            unexpected.apply(
                unexpected,
                [this.subject, assertion].concat(args)
            );
        };
    });

    ['key', 'keys'].forEach(function(methodName) {
        ExpectFacade.prototype[methodName] = function() {
            var args = Array.prototype.slice.call(arguments);
            var assertion = expandFlags(
                '[not] to [only] have ' + methodName,
                this.flags
            );

            unexpected.apply(
                unexpected,
                [this.subject, assertion].concat(args)
            );
        };
    });

    ExpectFacade.prototype.fail = function() {
        var args = Array.prototype.slice.call(arguments);
        return unexpected.fail.apply(unexpected, args);
    };

    function expect() {
        if (arguments.length > 1) {
            unexpected.apply(null, arguments);
        } else {
            return new ExpectFacade(arguments[0], Object.keys(flags));
        }
    }

    expect.fail = function() {
        var args = Array.prototype.slice.call(arguments);
        return unexpected.fail.apply(unexpected, args);
    };
    expect.outputFormat = unexpected.outputFormat;

    expect.addAssertion = function(
        assertionName,
        unexpectedAssertionName,
        customAssertion
    ) {
        unexpected.addAssertion(unexpectedAssertionName, customAssertion);
        ExpectFacade.prototype[assertionName] = function() {
            var args = Array.prototype.slice.call(arguments);
            var assertion = expandFlags(unexpectedAssertionName, this.flags);

            unexpected.apply(
                unexpected,
                [this.subject, assertion].concat(args)
            );
        };
    };

    expect.version = '0.0.0';

    expect.unexpected = unexpected;

    return expect;
});
<|endoftext|>


<commit_before>var Generator = require('generate-js'),
    Joi = require('joi'),
    async = require('async');

var EndPoint = Generator.generate(function EndPoint(options) {
    var _ = this;

    _.defineProperties(options);
    _.debug = false;
});

EndPoint.Joi = Joi;

EndPoint.definePrototype({
    incomingSchema: Joi.object(),
    outgoingSchema: Joi.object(),
    run: function run(data, done) {
        var _ = this;

        function validateIncoming(next) {
            _.debug && console.log("validateIncoming", data);
            Joi.validate(data, _.incomingSchema, _.validateOptions, next);
        }

        function runIncoming(data, next) {
            _.debug && console.log("runIncoming", data);
            _.incoming(data, next);
        }

        function validateOutgoing(data, next) {
            console.log("validateOutgoing", data);
            Joi.validate(data, _.outgoingSchema, _.validateOptions, next);
        }

        function runOutgoing(data, next) {
            _.debug && console.log("runOutgoing", data);
            _.outgoing(data, next);
        }

        async.waterfall([
            validateIncoming,
            runIncoming,
            validateOutgoing,
            runOutgoing
        ], done);
    },

    incoming: function incoming(data, done) {
        var _ = this;

        done(null, data);
    },

    outgoing: function outgoing(data, done) {
        var _ = this;

        done(null, data);
    }
});

module.exports = EndPoint;
<commit_msg>Add smarter default behaviour for validateOptions.<commit_after>var Generator = require('generate-js'),
    Joi = require('joi'),
    async = require('async');

var EndPoint = Generator.generate(function EndPoint(options) {
    var _ = this;

    options.validateOptions = options.validateOptions || {
        abortEarly: false,
        stripUnknown: true
    };

    _.defineProperties(options);
    _.debug = false;
});

EndPoint.Joi = Joi;

EndPoint.definePrototype({
    incomingSchema: Joi.object(),
    outgoingSchema: Joi.object(),
    run: function run(data, done) {
        var _ = this;

        function validateIncoming(next) {
            _.debug && console.log("validateIncoming", data);
            Joi.validate(data, _.incomingSchema, _.validateOptions, next);
        }

        function runIncoming(data, next) {
            _.debug && console.log("runIncoming", data);
            _.incoming(data, next);
        }

        function validateOutgoing(data, next) {
            console.log("validateOutgoing", data);
            Joi.validate(data, _.outgoingSchema, _.validateOptions, next);
        }

        function runOutgoing(data, next) {
            _.debug && console.log("runOutgoing", data);
            _.outgoing(data, next);
        }

        async.waterfall([
            validateIncoming,
            runIncoming,
            validateOutgoing,
            runOutgoing
        ], done);
    },

    incoming: function incoming(data, done) {
        var _ = this;

        done(null, data);
    },

    outgoing: function outgoing(data, done) {
        var _ = this;

        done(null, data);
    }
});

module.exports = EndPoint;
<|endoftext|>


<commit_before>var window = require("global/window")
var once = require("once")
var parseHeaders = require('parse-headers')

var messages = {
    "0": "Internal XMLHttpRequest Error",
    "4": "4xx Client Error",
    "5": "5xx Server Error"
}

var XHR = window.XMLHttpRequest || noop
var XDR = "withCredentials" in (new XHR()) ? XHR : window.XDomainRequest

module.exports = createXHR

function createXHR(options, callback) {
    if (typeof options === "string") {
        options = { uri: options }
    }

    options = options || {}
    callback = once(callback)

    var xhr = options.xhr || null

    if (!xhr) {
        if (options.cors || options.useXDR) {
            xhr = new XDR()
        }else{
            xhr = new XHR()
        }
    }

    var uri = xhr.url = options.uri || options.url;
    var method = xhr.method = options.method || "GET"
    var body = options.body || options.data
    var headers = xhr.headers = options.headers || {}
    var sync = !!options.sync
    var isJson = false
    var key

    if ("json" in options) {
        isJson = true
        headers["Accept"] = "application/json"
        if (method !== "GET" && method !== "HEAD") {
            headers["Content-Type"] = "application/json"
            body = JSON.stringify(options.json)
        }
    }

    xhr.onreadystatechange = readystatechange
    xhr.onload = load
    xhr.onerror = error
    // IE9 must have onprogress be set to a unique function.
    xhr.onprogress = function () {
        // IE must die
    }
    // hate IE
    xhr.ontimeout = noop
    xhr.open(method, uri, !sync)
                                    //backward compatibility
    if (options.withCredentials || (options.cors && options.withCredentials !== false)) {
        xhr.withCredentials = true
    }

    // Cannot set timeout with sync request
    if (!sync) {
        xhr.timeout = "timeout" in options ? options.timeout : 5000
    }

    if (xhr.setRequestHeader) {
        for(key in headers){
            if(headers.hasOwnProperty(key)){
                xhr.setRequestHeader(key, headers[key])
            }
        }
    } else if (options.headers) {
        throw new Error("Headers cannot be set on an XDomainRequest object");
    }

    if ("responseType" in options) {
        xhr.responseType = options.responseType
    }

    if ("beforeSend" in options &&
        typeof options.beforeSend === "function"
    ) {
        options.beforeSend(xhr)
    }

    xhr.send(body)

    return xhr

    function readystatechange() {
        if (xhr.readyState === 4) {
            load()
        }
    }

    function load() {
        var error = null
        var response = {
            body: null,
            statusCode: null,
            statusText: xhr.statusText,
            headers: parseHeaders(xhr.getAllResponseHeaders())
        }

        var status = response.statusCode = xhr.status
        // Chrome with requestType=blob throws errors arround when even testing access to responseText
        var body = null

        if (xhr.response) {
            body = response.body = xhr.response
        } else if (xhr.responseType === 'text' || !xhr.responseType) {
            body = response.body = xhr.responseText || xhr.responseXML
        }

        if (status === 1223) {
            status = 204
        }

        if (status === 0 || (status >= 400 && status < 600)) {
            var message = (typeof body === "string" ? body : false) ||
                messages[String(status).charAt(0)]
            error = new Error(message)
            error.statusCode = status
        }

        response.statusCode = status;

        if (isJson) {
            try {
                body = response.body = JSON.parse(body)
            } catch (e) {}
        }

        callback(error, response, body)
    }

    function error(evt) {
        callback(evt, xhr)
    }
}

function noop() {}

function parseHeaders(headers) {
    var response = {}

    return response
}
<commit_msg>remove tmp method<commit_after>var window = require("global/window")
var once = require("once")
var parseHeaders = require('parse-headers')

var messages = {
    "0": "Internal XMLHttpRequest Error",
    "4": "4xx Client Error",
    "5": "5xx Server Error"
}

var XHR = window.XMLHttpRequest || noop
var XDR = "withCredentials" in (new XHR()) ? XHR : window.XDomainRequest

module.exports = createXHR

function createXHR(options, callback) {
    if (typeof options === "string") {
        options = { uri: options }
    }

    options = options || {}
    callback = once(callback)

    var xhr = options.xhr || null

    if (!xhr) {
        if (options.cors || options.useXDR) {
            xhr = new XDR()
        }else{
            xhr = new XHR()
        }
    }

    var uri = xhr.url = options.uri || options.url;
    var method = xhr.method = options.method || "GET"
    var body = options.body || options.data
    var headers = xhr.headers = options.headers || {}
    var sync = !!options.sync
    var isJson = false
    var key

    if ("json" in options) {
        isJson = true
        headers["Accept"] = "application/json"
        if (method !== "GET" && method !== "HEAD") {
            headers["Content-Type"] = "application/json"
            body = JSON.stringify(options.json)
        }
    }

    xhr.onreadystatechange = readystatechange
    xhr.onload = load
    xhr.onerror = error
    // IE9 must have onprogress be set to a unique function.
    xhr.onprogress = function () {
        // IE must die
    }
    // hate IE
    xhr.ontimeout = noop
    xhr.open(method, uri, !sync)
                                    //backward compatibility
    if (options.withCredentials || (options.cors && options.withCredentials !== false)) {
        xhr.withCredentials = true
    }

    // Cannot set timeout with sync request
    if (!sync) {
        xhr.timeout = "timeout" in options ? options.timeout : 5000
    }

    if (xhr.setRequestHeader) {
        for(key in headers){
            if(headers.hasOwnProperty(key)){
                xhr.setRequestHeader(key, headers[key])
            }
        }
    } else if (options.headers) {
        throw new Error("Headers cannot be set on an XDomainRequest object");
    }

    if ("responseType" in options) {
        xhr.responseType = options.responseType
    }

    if ("beforeSend" in options &&
        typeof options.beforeSend === "function"
    ) {
        options.beforeSend(xhr)
    }

    xhr.send(body)

    return xhr

    function readystatechange() {
        if (xhr.readyState === 4) {
            load()
        }
    }

    function load() {
        var error = null
        var response = {
            body: null,
            statusCode: null,
            statusText: xhr.statusText,
            headers: parseHeaders(xhr.getAllResponseHeaders())
        }

        var status = response.statusCode = xhr.status
        // Chrome with requestType=blob throws errors arround when even testing access to responseText
        var body = null

        if (xhr.response) {
            body = response.body = xhr.response
        } else if (xhr.responseType === 'text' || !xhr.responseType) {
            body = response.body = xhr.responseText || xhr.responseXML
        }

        if (status === 1223) {
            status = 204
        }

        if (status === 0 || (status >= 400 && status < 600)) {
            var message = (typeof body === "string" ? body : false) ||
                messages[String(status).charAt(0)]
            error = new Error(message)
            error.statusCode = status
        }

        response.statusCode = status;

        if (isJson) {
            try {
                body = response.body = JSON.parse(body)
            } catch (e) {}
        }

        callback(error, response, body)
    }

    function error(evt) {
        callback(evt, xhr)
    }
}

function noop() {}
<|endoftext|>


<commit_before>"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

var React = require('react')
var actioncable = require('actioncable')

var ActionCableProvider = React.createClass({
  getChildContext: function () {
    return {
      cable: this.cable
    }
  },

  componentWillMount: function () {
    if (this.props.cable) {
      this.cable = this.props.cable
    } else {
      this.cable = actioncable.createConsumer(this.props.url)
    }
  },

  componentWillUnmount: function () {
    if (!this.props.cable && this.cable) {
      this.cable.disconnect()
    }
  },

  componentWillReceiveProps: function (nextProps) {
    // Props not changed
    if (this.props.cable === nextProps.cable &&
        this.props.url === nextProps.url) {
      return
    }

    // cable is created by self, disconnect it
    this.componentWillUnmount()

    // create or assign cable
    this.componentWillMount()
  },

  render: function () {
    return this.props.children
  }
})

ActionCableProvider.propTypes = {
  cable: React.PropTypes.object,
  url: React.PropTypes.string,
  children: React.PropTypes.any
}

ActionCableProvider.childContextTypes = {
  cable: React.PropTypes.object.isRequired
}

var ActionCable = React.createClass({
  componentDidMount () {
    const self = this
    const {
      onReceive, onInitialized, onConnected, onDisconnected, onRejected
    } = this.props

    this.cable = this.context.cable.subscriptions.create(
      this.props.channel,
      {
        received (data) {
          onReceived && onReceived(data)
        },
        initialized () {
          onInitialized && onInitialized()
        },
        connected () {
          onConnected && onConnected()
        },
        disconnect () {
          onDisconnected && onDisconnected()
        },
        rejected () {
          onRejected && onRejected()
        }
      }
    )
  },

  componentWillUnmount () {
    if (this.cable) {
      this.context.cable.subscriptions.remove(this.cable)
      this.cable = null
    }
  },

  send (data) {
    if (!this.cable) {
      throw new Error('ActionCable component unloaded')
    }

    this.cable.send(data)
  },

  perform (action, data) {
    if (!this.cable) {
      throw new Error('ActionCable component unloaded')
    }

    this.cable.perform(action, data)
  },

  render: function () {
    return null
  }
})

ActionCable.propTypes = {
  onReceive: React.PropTypes.func,
  onInitialized: React.PropTypes.func,
  onConnected: React.PropTypes.func,
  onDisconnected: React.PropTypes.func,
  onRejected: React.PropTypes.func,
}
ActionCable.contextTypes = {
  cable: React.PropTypes.object.isRequired
}

exports.ActionCable = ActionCableProvider.ActionCable = ActionCable

exports.default = module.exports = ActionCableProvider
<commit_msg>Fix variable error<commit_after>"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

var React = require('react')
var actioncable = require('actioncable')

var ActionCableProvider = React.createClass({
  getChildContext: function () {
    return {
      cable: this.cable
    }
  },

  componentWillMount: function () {
    if (this.props.cable) {
      this.cable = this.props.cable
    } else {
      this.cable = actioncable.createConsumer(this.props.url)
    }
  },

  componentWillUnmount: function () {
    if (!this.props.cable && this.cable) {
      this.cable.disconnect()
    }
  },

  componentWillReceiveProps: function (nextProps) {
    // Props not changed
    if (this.props.cable === nextProps.cable &&
        this.props.url === nextProps.url) {
      return
    }

    // cable is created by self, disconnect it
    this.componentWillUnmount()

    // create or assign cable
    this.componentWillMount()
  },

  render: function () {
    return this.props.children
  }
})

ActionCableProvider.propTypes = {
  cable: React.PropTypes.object,
  url: React.PropTypes.string,
  children: React.PropTypes.any
}

ActionCableProvider.childContextTypes = {
  cable: React.PropTypes.object.isRequired
}

var ActionCable = React.createClass({
  componentDidMount () {
    var self = this;
    var _props = this.props,
        onReceived = _props.onReceived,
        onInitialized = _props.onInitialized,
        onConnected = _props.onConnected,
        onDisconnected = _props.onDisconnected,
        onRejected = _props.onRejected;

    this.cable = this.context.cable.subscriptions.create(
      this.props.channel,
      {
        received (data) {
          onReceived && onReceived(data)
        },
        initialized () {
          onInitialized && onInitialized()
        },
        connected () {
          onConnected && onConnected()
        },
        disconnect () {
          onDisconnected && onDisconnected()
        },
        rejected () {
          onRejected && onRejected()
        }
      }
    )
  },

  componentWillUnmount () {
    if (this.cable) {
      this.context.cable.subscriptions.remove(this.cable)
      this.cable = null
    }
  },

  send (data) {
    if (!this.cable) {
      throw new Error('ActionCable component unloaded')
    }

    this.cable.send(data)
  },

  perform (action, data) {
    if (!this.cable) {
      throw new Error('ActionCable component unloaded')
    }

    this.cable.perform(action, data)
  },

  render: function () {
    return null
  }
})

ActionCable.propTypes = {
  onReceived: React.PropTypes.func,
  onInitialized: React.PropTypes.func,
  onConnected: React.PropTypes.func,
  onDisconnected: React.PropTypes.func,
  onRejected: React.PropTypes.func,
}
ActionCable.contextTypes = {
  cable: React.PropTypes.object.isRequired
}

exports.ActionCable = ActionCableProvider.ActionCable = ActionCable

exports.default = module.exports = ActionCableProvider
<|endoftext|>


<commit_before>var Runner = require("./lib/runner");
var _ = require("underscore")._;
var fs = require("fs");
var Table = require("./lib/table");
var util = require("util");
var assert = require("assert");
var Document = require("./lib/document");
var ArgTypes = require("./lib/arg_types");
var Args = require("args-js");
var path = require("path");
var self;

var Massive = function(args){

  this.scriptsDir = args.scripts || process.cwd() + "/db";

  var runner = new Runner(args.connectionString);
  _.extend(this,runner);

  this.tables = [];
  this.queryFiles = [];
  //console.log("Massive online", this);
}

Massive.prototype.run = function(){
  var args = ArgTypes.queryArgs(arguments);
  this.query(args);
}

Massive.prototype.loadQueries = function() {
  walkSqlFiles(this,this.scriptsDir);
};

Massive.prototype.loadTables = function(next){
  var tableSql = __dirname + "/lib/scripts/tables.sql";
  var self = this;
  this.executeSqlFile({file : tableSql}, function(err,tables){
    if(err){
      next(err,null);
    }else{
      _.each(tables, function(table){
        var table = new Table({
          name : table.name,
          pk : table.pk,
          db : self
        });
        //pin to namespace
        self[table.name] =table;
        //add to table collection
        self.tables.push(table);
      });
      next(null,self);
    }
  });
}

Massive.prototype.saveDoc = function(collection, doc, next){
  //does the table exist?
  if(!this[collection]){
    var sql = this.documentTableSql(collection);
    var self = this;
    this.query(sql, function(err,res){
      if(err){
        console.log(err)
        next(err,null);
      }else{
       //add the table
       self[collection] = new Table({
         pk : "id",
         name : collection,
         db : self
       });

       //call save again
       self.saveDoc(collection,doc,next);
     }
    });
  }else{
    //hand off to the table
    this[collection].saveDoc(doc,next);
  }
};

Massive.prototype.documentTableSql = function(tableName){
  var docSqlFile = __dirname + "/lib/scripts/create_document_table.sql";
  var sql = fs.readFileSync(docSqlFile, {encoding: 'utf-8'});
  sql = util.format(sql, tableName, tableName,tableName);
  return sql;
};

//A recursive directory walker that would love to be refactored
var walkSqlFiles = function(rootObject, rootDir){
  var dirs = fs.readdirSync(rootDir);

  //loop the directories found
  _.each(dirs, function(item){

    //parsing with path is a friendly way to get info about this dir or file
    var parsed = path.parse(item);

    //is this a SQL file?
    if(parsed.ext === ".sql"){

      //why yes it is! Build the abspath so we can read the file
      var filePath = path.join(rootDir,item);

      //pull in the SQL - don't worry this only happens once, when
      //massive is loaded using connect()
      var sql = fs.readFileSync(filePath, {encoding : "utf-8"});

      //set a property on our root object, and grab a handy variable reference:
      var newProperty = assignScriptAsFunction(rootObject, parsed.name);

      //I don't know what I'm doing, but it works
      newProperty.sql = sql;
      newProperty.db = self;
      newProperty.filePath = filePath;
      self.queryFiles.push(newProperty);

    }else if(parsed.ext !== ''){
      //ignore it
    }else{

      //this is a directory so shift things and move on down
      //set a property on our root object, then use *that*
      //as the root in the next call
      rootObject[parsed.name] = {};

      //set the path to walk so we have a correct root directory
      var pathToWalk = path.join(rootDir,item);

      //recursive call - do it all again
      walkSqlFiles(rootObject[parsed.name],pathToWalk);
    }
  });
}

var assignScriptAsFunction = function (rootObject, propertyName) {
   rootObject[propertyName] = function(args, next) {
    args || (args = {});
    //if args is a function, it's our callback
    if(_.isFunction(args)){
      next = args;
      //set args to an empty array
      args = [];
    }
    //JA - use closure to assign stuff from properties before they are invented
    //(sorta, I think...):
    var sql = rootObject[propertyName].sql;
    var db = rootObject[propertyName].db;
    var params = _.isArray(args) ? args : [args];

    //execute the query on invocation
    db.query(sql,params,{}, next);
  }
  return rootObject[propertyName];
}

//connects Massive to the DB
exports.connect = function(args, next){
  assert((args.connectionString || args.db), "Need a connectionString or db (name of database on localhost) at the very least.");

  //override if there's a db name passed in
  if(args.db){
    args.connectionString = "postgres://localhost/"+args.db;
  }

  var massive = new  Massive(args);

  //load up the tables, queries, and commands
  massive.loadTables(function(err,db){
    self = db;
    assert(!err, err);
    //synchronous
    db.loadQueries();
    next(null,db);
  });
};
<commit_msg>add try/catch back #29<commit_after>var Runner = require("./lib/runner");
var _ = require("underscore")._;
var fs = require("fs");
var Table = require("./lib/table");
var util = require("util");
var assert = require("assert");
var Document = require("./lib/document");
var ArgTypes = require("./lib/arg_types");
var Args = require("args-js");
var path = require("path");
var self;

var Massive = function(args){

  this.scriptsDir = args.scripts || process.cwd() + "/db";

  var runner = new Runner(args.connectionString);
  _.extend(this,runner);

  this.tables = [];
  this.queryFiles = [];
  //console.log("Massive online", this);
}

Massive.prototype.run = function(){
  var args = ArgTypes.queryArgs(arguments);
  this.query(args);
}

Massive.prototype.loadQueries = function() {
  walkSqlFiles(this,this.scriptsDir);
};

Massive.prototype.loadTables = function(next){
  var tableSql = __dirname + "/lib/scripts/tables.sql";
  var self = this;
  this.executeSqlFile({file : tableSql}, function(err,tables){
    if(err){
      next(err,null);
    }else{
      _.each(tables, function(table){
        var table = new Table({
          name : table.name,
          pk : table.pk,
          db : self
        });
        //pin to namespace
        self[table.name] =table;
        //add to table collection
        self.tables.push(table);
      });
      next(null,self);
    }
  });
}

Massive.prototype.saveDoc = function(collection, doc, next){
  //does the table exist?
  if(!this[collection]){
    var sql = this.documentTableSql(collection);
    var self = this;
    this.query(sql, function(err,res){
      if(err){
        console.log(err)
        next(err,null);
      }else{
       //add the table
       self[collection] = new Table({
         pk : "id",
         name : collection,
         db : self
       });

       //call save again
       self.saveDoc(collection,doc,next);
     }
    });
  }else{
    //hand off to the table
    this[collection].saveDoc(doc,next);
  }
};

Massive.prototype.documentTableSql = function(tableName){
  var docSqlFile = __dirname + "/lib/scripts/create_document_table.sql";
  var sql = fs.readFileSync(docSqlFile, {encoding: 'utf-8'});
  sql = util.format(sql, tableName, tableName,tableName);
  return sql;
};

//A recursive directory walker that would love to be refactored
var walkSqlFiles = function(rootObject, rootDir){
  var dirs;
  try {
    dirs = fs.readdirSync(rootDir);
  } catch (ex) {
     return;
  }

  //loop the directories found
  _.each(dirs, function(item){

    //parsing with path is a friendly way to get info about this dir or file
    var parsed = path.parse(item);

    //is this a SQL file?
    if(parsed.ext === ".sql"){

      //why yes it is! Build the abspath so we can read the file
      var filePath = path.join(rootDir,item);

      //pull in the SQL - don't worry this only happens once, when
      //massive is loaded using connect()
      var sql = fs.readFileSync(filePath, {encoding : "utf-8"});

      //set a property on our root object, and grab a handy variable reference:
      var newProperty = assignScriptAsFunction(rootObject, parsed.name);

      //I don't know what I'm doing, but it works
      newProperty.sql = sql;
      newProperty.db = self;
      newProperty.filePath = filePath;
      self.queryFiles.push(newProperty);

    }else if(parsed.ext !== ''){
      //ignore it
    }else{

      //this is a directory so shift things and move on down
      //set a property on our root object, then use *that*
      //as the root in the next call
      rootObject[parsed.name] = {};

      //set the path to walk so we have a correct root directory
      var pathToWalk = path.join(rootDir,item);

      //recursive call - do it all again
      walkSqlFiles(rootObject[parsed.name],pathToWalk);
    }
  });
}

//it's less congested now...
var assignScriptAsFunction = function (rootObject, propertyName) {
   rootObject[propertyName] = function(args, next) {
    args || (args = {});
    //if args is a function, it's our callback
    if(_.isFunction(args)){
      next = args;
      //set args to an empty array
      args = [];
    }
    //JA - use closure to assign stuff from properties before they are invented
    //(sorta, I think...):
    var sql = rootObject[propertyName].sql;
    var db = rootObject[propertyName].db;
    var params = _.isArray(args) ? args : [args];

    //execute the query on invocation
    db.query(sql,params,{}, next);
  }
  return rootObject[propertyName];
}

//connects Massive to the DB
exports.connect = function(args, next){
  assert((args.connectionString || args.db), "Need a connectionString or db (name of database on localhost) at the very least.");

  //override if there's a db name passed in
  if(args.db){
    args.connectionString = "postgres://localhost/"+args.db;
  }

  var massive = new  Massive(args);

  //load up the tables, queries, and commands
  massive.loadTables(function(err,db){
    self = db;
    assert(!err, err);
    //synchronous
    db.loadQueries();
    next(null,db);
  });
};
<|endoftext|>


<commit_before>var isType = exports.isType = function isType(type) {
    return function(arg) {
        if (type === 'Array' && Array.isArray) {
            return Array.isArray(arg);
        }
        return Object.prototype.toString.call(arg) === "[object " + type + "]";
    }
}

exports.isString = isType('String');
exports.isArray = isType('Array');
exports.isFunction = isType('Function');
exports.isObject = isType('Object');<commit_msg>format<commit_after>var isType = exports.isType = function isType(type) {
    return function(arg) {
        if (type === 'Array' && Array.isArray) {
            return Array.isArray(arg);
        }
        return Object.prototype.toString.call(arg) === "[object " + type + "]";
    }
};

exports.isString = isType('String');
exports.isArray = isType('Array');
exports.isFunction = isType('Function');
exports.isObject = isType('Object');<|endoftext|>


<commit_before>/*!
 * base-argv <https://github.com/jonschlinkert/base-argv>
 *
 * Copyright (c) 2015, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

var minimist = require('minimist');
var toTasks = require('./lib/to-tasks');
var utils = require('./lib/utils');

module.exports = function(options) {
  return function(app) {
    var opts = utils.extend({}, options);
    opts.commands = app.commands || [];

    // add `keys` from base-config plugin (map-config)
    if (app.config && Array.isArray(app.config.keys)) {
      opts.commands = utils.union(opts.commands, app.config.keys);
    }
    // add `keys` from base-cli plugin (map-config)
    if (app.cli && Array.isArray(app.cli.keys)) {
      opts.commands = utils.union(opts.commands, app.cli.keys);
    }

    opts.tasks = app.tasks;
    app.define('argv', processArgv(opts));
  };
};

function processArgv(options) {
  var opts = utils.extend({}, options);
  var commands = opts.commands;
  var tasks = opts.tasks;
  var prop = opts.prop;

  return function(argv) {
    argv = !utils.isObject(argv)
      ? minimist(utils.arrayify(argv))
      : argv;

    var res = {};
    res.argv = utils.extend({}, argv);
    res._ = [];
    res.tasks = [];
    res.commands = {};
    res.options = {};
    if (prop) res[prop] = [];

    var appKeys = (prop && opts.hasOwnProperty(prop))
      ? Object.keys(opts[prop])
      : [];

    var taskKeys = !Array.isArray(tasks)
      ? (tasks ? Object.keys(tasks) : [])
      : tasks;

    var arr = argv._;
    var len = arr.length, i = -1;

    while (++i < len) {
      var ele = arr[i];

      if (/,/.test(ele) && !/[.|:]/.test(ele)) {
        res.tasks = utils.union(res.tasks, ele.split(','));
        continue;
      }

      if (isApp(appKeys, ele) || isTask(taskKeys, ele)) {
        if (prop) {
          var obj = toTasks(ele, opts, prop);
          res[prop] = res[prop].concat(obj);
        } else {
          res.tasks = utils.union(res.tasks, ele.split(','));
        }
        continue;
      }
      res._.push(ele);
    }

    for (var key in argv) {
      if (key === '_') {
        continue;
      }

      var argvArr = utils.arrayify(argv[key]);
      var expanded = utils.expandArgs(argvArr)[0];

      if (isCommand(commands, key)) {
        res.commands[key] = expanded;
      } else {
        res.options[key] = expanded;
      }
    }
    return res;
  };
}

module.exports.processArgv = processArgv;

/**
 * Utils
 */

function isApp(apps, key) {
  return is(apps, key);
}

function isCommand(commands, key) {
  return is(commands, key);
}

function isTask(tasks, key) {
  return is(tasks, key);
}

function is(arr, key, ch) {
  if (!arr) return false;
  if (arr.indexOf(key) > -1) {
    return true;
  }
  var seg = key.split(/\W/).shift();
  return arr.indexOf(seg) > -1;
}
<commit_msg>make `generators` the default prop<commit_after>/*!
 * base-argv <https://github.com/jonschlinkert/base-argv>
 *
 * Copyright (c) 2015, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

var minimist = require('minimist');
var toTasks = require('./lib/to-tasks');
var utils = require('./lib/utils');

module.exports = function(options) {
  return function(app) {
    var opts = utils.extend({}, options);
    opts.commands = app.commands || [];

    // add `keys` from base-config plugin (map-config)
    if (app.config && Array.isArray(app.config.keys)) {
      opts.commands = utils.union(opts.commands, app.config.keys);
    }
    // add `keys` from base-cli plugin (map-config)
    if (app.cli && Array.isArray(app.cli.keys)) {
      opts.commands = utils.union(opts.commands, app.cli.keys);
    }

    opts.tasks = app.tasks;
    app.define('argv', processArgv(opts));
  };
};

function processArgv(options) {
  var opts = utils.extend({}, options);
  var commands = opts.commands;
  var tasks = opts.tasks;
  var prop = opts.prop || 'generators';

  return function(argv) {
    argv = !utils.isObject(argv)
      ? minimist(utils.arrayify(argv))
      : argv;

    var res = {};
    res.argv = utils.extend({}, argv);
    res._ = [];
    res.tasks = [];
    res.commands = {};
    res.options = {};
    if (prop) res[prop] = [];

    var appKeys = (prop && opts.hasOwnProperty(prop))
      ? Object.keys(opts[prop])
      : [];

    var taskKeys = !Array.isArray(tasks)
      ? (tasks ? Object.keys(tasks) : [])
      : tasks;

    var arr = argv._;
    var len = arr.length, i = -1;

    while (++i < len) {
      var ele = arr[i];

      if (/,/.test(ele) && !/[.|:]/.test(ele)) {
        res.tasks = utils.union(res.tasks, ele.split(','));
        continue;
      }

      if (isApp(appKeys, ele) || isTask(taskKeys, ele)) {
        if (prop) {
          var obj = toTasks(ele, opts, prop);
          res[prop] = res[prop].concat(obj);
        } else {
          res.tasks = utils.union(res.tasks, ele.split(','));
        }
        continue;
      }
      res._.push(ele);
    }

    for (var key in argv) {
      if (key === '_') {
        continue;
      }

      var argvArr = utils.arrayify(argv[key]);
      var expanded = utils.expandArgs(argvArr)[0];

      if (isCommand(commands, key)) {
        res.commands[key] = expanded;
      } else {
        res.options[key] = expanded;
      }
    }
    return res;
  };
}

module.exports.processArgv = processArgv;

/**
 * Utils
 */

function isApp(apps, key) {
  return is(apps, key);
}

function isCommand(commands, key) {
  return is(commands, key);
}

function isTask(tasks, key) {
  return is(tasks, key);
}

function is(arr, key, ch) {
  if (!arr) return false;
  if (arr.indexOf(key) > -1) {
    return true;
  }
  var seg = key.split(/\W/).shift();
  return arr.indexOf(seg) > -1;
}
<|endoftext|>


<commit_before>var OMGGIF = require('omggif');
var clamp = require('clamp');

function GIFGenerator(renderer, opts, callback) {

    opts = opts || {};
    this.recalculatePalettePerFrame = opts.recalculatePalettePerFrame;

    this.renderer = renderer;
    this.generating = false;
    //this.current = 0;
    this.frames = opts.frame || 100;
    this.delay = opts.delay || 5;

    this.renderTarget = opts.renderTarget;

    this.size = opts.size || {width: 500, height: 500};

    this.callback = callback;

    this.denominator = 16;
    this.quantizedLevels = 256 / this.denominator;
}

GIFGenerator.prototype.buildPalette = function(data) {

    var skip = Math.ceil((data.length / 4) / 10000);
    var step = 4 * skip;

    var superPalette = [];
    var indexPalette = [];

    for (var j = 0, jl = data.length; j < jl; j += step) {

        var r = Math.floor(data[j + 0] / this.denominator) * this.denominator;
        var g = Math.floor(data[j + 1] / this.denominator) * this.denominator;
        var b = Math.floor(data[j + 2] / this.denominator) * this.denominator;
        var color = r << 16 | g << 8 | b << 0;

        var index = indexPalette.indexOf(color);

       if (index === -1) {
            superPalette.push([color, 1, r, g, b]);
            indexPalette.push(color);
        }
        else {
            superPalette[index][1]++;
        }
    }

    superPalette.sort(function(a, b) {
        return b[1] - a[1];
    });

    var palette = superPalette.slice(0, 256);

    this.globalPaletteMap = new Uint8Array(Math.pow(this.quantizedLevels, 3));

    var cursor = 0;
    for (var ir = 0; ir < 256; ir+=this.denominator) {
        for (var ig = 0; ig < 256; ig+=this.denominator) {
            for (var ib = 0; ib < 256; ib+=this.denominator) {

                this.globalPaletteMap[cursor] = this.findClosestIndex(ir, ig, ib, palette);
                cursor++;
            }
        }
    }
    this.palette = palette;
};

GIFGenerator.prototype.init = function() {

    this.generating = true;

    var canvas = document.createElement('canvas');
    canvas.width =  this.size.width; //this.renderer.domElement.width;
    canvas.height =  this.size.height; //this.renderer.domElement.height;

    var context2d = canvas.getContext('2d');

    var buffer = new Uint8Array(canvas.width * canvas.height * this.frames * 5);
    var gif = new OMGGIF.GifWriter(buffer, canvas.width, canvas.height, {
        loop: 0
    });

    var pixels = new Uint8Array(canvas.width * canvas.height);

    if (this.renderTarget)
    {
        var context3d = this.renderer.getContext();
        var imageDataArray = new Uint8Array(this.size.width * this.size.height * 4);
        var imageData = context2d.createImageData(this.size.width, this.size.height);

        this.context3d = context3d;
        this.imageDataArray = imageDataArray;
        this.imageData = imageData;
    }

    this.canvas = canvas;
    this.context2d = context2d;
    this.buffer = buffer;
    this.pixels = pixels;

    this.gif = gif;
};

GIFGenerator.prototype.finish = function() {

        // return buffer.slice( 0, gif.end() );
        var string = '';

        for (var i = 0, l = this.gif.end(); i < l; i++) {
            string += String.fromCharCode(this.buffer[i]);
        }
        this.callback('data:image/gif;base64,' + btoa(string));

        this.generating = false;
};

GIFGenerator.prototype.findClosestIndex = function(r, g, b, palette) {
    var distance = Infinity;
    var closestIndex = -1;

    var tempDistance;
    for (var i = 0; i < palette.length; i++) {
        tempDistance = Math.abs(r - palette[i][2]) + Math.abs(g - palette[i][3]) + Math.abs(b - palette[i][4]);
        if (tempDistance < distance) {
            distance = tempDistance;
            closestIndex = i;
        }
    }
    return closestIndex;
};

GIFGenerator.prototype.rgb2index = function(r, g, b) {
    r = Math.floor(r / this.denominator);
    g = Math.floor(g / this.denominator);
    b = Math.floor(b / this.denominator);

    return r * this.quantizedLevels * this.quantizedLevels + g * this.quantizedLevels + b;
}

GIFGenerator.prototype.addFrame = function(recalculatePalette) {

    if (this.renderTarget) {

        this.renderer.setRenderTarget(this.renderTarget);
        this.context3d.readPixels(0, 0, this.size.width, this.size.height, this.context3d.RGBA, this.context3d.UNSIGNED_BYTE, this.imageDataArray);

        this.imageData.data.set(this.imageDataArray);
        this.context2d.putImageData(this.imageData, 0, 0);

    } else {

        this.context2d.drawImage(this.renderer.domElement, 0, 0);
    }

    var data = this.context2d.getImageData(0, 0, this.canvas.width, this.canvas.height).data;

    if (!this.globalPaletteMap || this.recalculatePalettePerFrame || recalculatePalette) {
        this.buildPalette(data);
    }

    var ditherStrength = 5;
    var width = this.size.width;

    for (var i = 0, k = 0, l = data.length; i < l; i += 4, k++) {
        var index = ~~(k + k / width);

        var r = Math.floor(clamp(data[i + 0] + ((index % 2) - 1) * ditherStrength, 0, 255) / this.denominator) * this.denominator;
        var g = Math.floor(clamp(data[i + 1] + (((index + 1) % 2) - 1) * ditherStrength, 0, 255) / this.denominator) * this.denominator;
        var b = Math.floor(clamp(data[i + 2] + (((index + 2) % 2) - 1) * ditherStrength, 0, 255) / this.denominator) * this.denominator;

        //var r = Math.floor(data[i + 0] / this.denominator) * this.denominator;
        //var g = Math.floor(data[i + 1] / this.denominator) * this.denominator;
        //var b = Math.floor(data[i + 2] / this.denominator) * this.denominator;

        this.pixels[k] = this.globalPaletteMap[this.rgb2index(r, g, b)];
    }

    var powof2 = 1;
    while (powof2 < this.palette.length) powof2 <<= 1;
    this.palette.length = powof2;

    this.gif.addFrame(0, 0, this.canvas.width, this.canvas.height, this.pixels, {
        palette: new Uint32Array(this.palette.map(function(element) {
            return element? element[0] : 0;
        })),
        delay: this.delay
    });
};

module.exports = GIFGenerator;
<commit_msg>updated generate gif to write to a rendertarget double the size<commit_after>var OMGGIF = require('omggif');
var clamp = require('clamp');

function GIFGenerator(renderer, opts, callback) {

    opts = opts || {};
    this.recalculatePalettePerFrame = opts.recalculatePalettePerFrame;

    this.renderer = renderer;
    this.generating = false;
    //this.current = 0;
    this.frames = opts.frame || 100;
    this.delay = opts.delay || 5;

    this.renderTarget = opts.renderTarget;

    this.size = opts.size || {width: 500, height: 500};
    this.doubleSize = {width: this.size.width * 2, height: this.size.height * 2};

    this.callback = callback;

    this.denominator = 16;
    this.quantizedLevels = 256 / this.denominator;
}

GIFGenerator.prototype.buildPalette = function(data) {

    var skip = Math.ceil((data.length / 4) / 10000);
    var step = 4 * skip;

    var superPalette = [];
    var indexPalette = [];

    for (var j = 0, jl = data.length; j < jl; j += step) {

        var r = Math.floor(data[j + 0] / this.denominator) * this.denominator;
        var g = Math.floor(data[j + 1] / this.denominator) * this.denominator;
        var b = Math.floor(data[j + 2] / this.denominator) * this.denominator;
        var color = r << 16 | g << 8 | b << 0;

        var index = indexPalette.indexOf(color);

       if (index === -1) {
            superPalette.push([color, 1, r, g, b]);
            indexPalette.push(color);
        }
        else {
            superPalette[index][1]++;
        }
    }

    superPalette.sort(function(a, b) {
        return b[1] - a[1];
    });

    var palette = superPalette.slice(0, 256);

    this.globalPaletteMap = new Uint8Array(Math.pow(this.quantizedLevels, 3));

    var cursor = 0;
    for (var ir = 0; ir < 256; ir+=this.denominator) {
        for (var ig = 0; ig < 256; ig+=this.denominator) {
            for (var ib = 0; ib < 256; ib+=this.denominator) {

                this.globalPaletteMap[cursor] = this.findClosestIndex(ir, ig, ib, palette);
                cursor++;
            }
        }
    }
    this.palette = palette;
};

GIFGenerator.prototype.init = function() {

    this.generating = true;

    var canvas = document.createElement('canvas');
    canvas.width =  this.size.width; //this.renderer.domElement.width;
    canvas.height =  this.size.height; //this.renderer.domElement.height;

    var context2d = canvas.getContext('2d');

    var buffer = new Uint8Array(this.size.width * this.size.height * this.frames * 5);
    var gif = new OMGGIF.GifWriter(buffer, this.size.width, this.size.height, {
        loop: 0
    });

    var pixels = new Uint8Array(this.size.width * this.size.height);

    if (this.renderTarget)
    {
        var context3d = this.renderer.getContext();
        var imageDataArraySource = new Uint8Array(this.doubleSize.width * this.doubleSize.height * 4);
        var imageDataArrayDest = new Uint8Array(this.size.width * this.size.height * 4);

        var imageData = context2d.createImageData(this.size.width, this.size.height);

        this.context3d = context3d;
        this.imageDataArraySource = imageDataArraySource;
        this.imageDataArrayDest = imageDataArrayDest;
        this.imageData = imageData;
    }

    this.canvas = canvas;
    this.context2d = context2d;
    this.buffer = buffer;
    this.pixels = pixels;

    this.gif = gif;
};

GIFGenerator.prototype.finish = function() {

        // return buffer.slice( 0, gif.end() );
        var string = '';

        for (var i = 0, l = this.gif.end(); i < l; i++) {
            string += String.fromCharCode(this.buffer[i]);
        }
        this.callback('data:image/gif;base64,' + btoa(string));

        this.generating = false;
};

GIFGenerator.prototype.findClosestIndex = function(r, g, b, palette) {
    var distance = Infinity;
    var closestIndex = -1;

    var tempDistance;
    for (var i = 0; i < palette.length; i++) {
        tempDistance = Math.abs(r - palette[i][2]) + Math.abs(g - palette[i][3]) + Math.abs(b - palette[i][4]);
        if (tempDistance < distance) {
            distance = tempDistance;
            closestIndex = i;
        }
    }
    return closestIndex;
};

GIFGenerator.prototype.rgb2index = function(r, g, b) {
    r = Math.floor(r / this.denominator);
    g = Math.floor(g / this.denominator);
    b = Math.floor(b / this.denominator);

    return r * this.quantizedLevels * this.quantizedLevels + g * this.quantizedLevels + b;
}

GIFGenerator.prototype.addFrame = function(recalculatePalette) {

    if (this.renderTarget) {

        this.renderer.setRenderTarget(this.renderTarget);
        this.context3d.readPixels(0, 0, this.doubleSize.width, this.doubleSize.height, this.context3d.RGBA, this.context3d.UNSIGNED_BYTE, this.imageDataArraySource);

        var srcWidth = this.doubleSize.width;
        var srcHeight = this.doubleSize.height;

        var destWidth = this.size.width;
        var destHeight = this.size.height;

        function getSrcIndex(destIndex, offsetX, offsetY) {
            var destPixelIndex = ~~(destIndex / 4);
            var destX = destPixelIndex % destWidth;
            var destY = ~~(destPixelIndex / destWidth);

            var srcX = destX * 2 + offsetX;
            var srcY = destY * 2 + offsetY;
            var srcPixelIndex = srcY * srcWidth + srcX;

            var srcIndex = srcPixelIndex * 4 + (destIndex % 4);
            return srcIndex;
        }

        var l =  this.imageDataArrayDest.length;
        for (var i = 0; i < l; i++) {
            this.imageDataArrayDest[i] = ~~((this.imageDataArraySource[getSrcIndex(i, 0, 0)] +
            this.imageDataArraySource[getSrcIndex(i, 1, 0)] +
            this.imageDataArraySource[getSrcIndex(i, 0, 1)] +
            this.imageDataArraySource[getSrcIndex(i, 1, 1)]) / 4);
        }

        this.imageData.data.set(this.imageDataArrayDest);
        this.context2d.putImageData(this.imageData, 0, 0);

    } else {

        this.context2d.drawImage(this.renderer.domElement, 0, 0);
    }

    var data = this.context2d.getImageData(0, 0, this.size.width, this.size.height).data;

    if (!this.globalPaletteMap || this.recalculatePalettePerFrame || recalculatePalette) {
        this.buildPalette(data);
    }

    var ditherStrength = 8;
    var width = this.size.width;

    for (var i = 0, k = 0, l = data.length; i < l; i += 4, k++) {
        var index = ~~(k + k / width);

        var r = Math.floor(clamp(data[i + 0] + ((index % 2) - 1) * ditherStrength, 0, 255) / this.denominator) * this.denominator;
        var g = Math.floor(clamp(data[i + 1] + (((index + 1) % 2) - 1) * ditherStrength, 0, 255) / this.denominator) * this.denominator;
        var b = Math.floor(clamp(data[i + 2] + (((index + 2) % 2) - 1) * ditherStrength, 0, 255) / this.denominator) * this.denominator;

        //var r = Math.floor(data[i + 0] / this.denominator) * this.denominator;
        //var g = Math.floor(data[i + 1] / this.denominator) * this.denominator;
        //var b = Math.floor(data[i + 2] / this.denominator) * this.denominator;

        this.pixels[k] = this.globalPaletteMap[this.rgb2index(r, g, b)];
    }

    var powof2 = 1;
    while (powof2 < this.palette.length) powof2 <<= 1;
    this.palette.length = powof2;

    this.gif.addFrame(0, 0, this.size.width, this.size.height, this.pixels, {
        palette: new Uint32Array(this.palette.map(function(element) {
            return element? element[0] : 0;
        })),
        delay: this.delay
    });
};

module.exports = GIFGenerator;
<|endoftext|>


<commit_before>'use strict';

/**
 * Simplified http request.
 * (C) 2013-2014 MediaSmart Mobile.
 */

// requires
var http = require('http');
var https = require('https');
var urlLib = require('url');

/**
 * Access a URL, send to callback. Parameters:
 *	- url: the URL to access.
 *	- params: optional additional parameters, currently supported:
 *		- retries: number of times to retry in case of error, default none.
 *	- callback(error, body): error is null only if result is 200.
 *		If there is an error, the body can contain the following attributes:
 *		- statusCode: if status code is not 200.
 *		- readingResponse: if response could not be read.
 */
exports.get = function(url, params, callback)
{
	if (typeof params == 'function')
	{
		callback = params;
		params = {};
	}
	params = params || {};
	var options = urlLib.parse(url);
	send(options, params, callback);
};

/**
 * Post to a URL, send to callback. Parameters:
 *	- url: the URL to access.
 *	- json: the object to send, can be a JSON string.
 *	- params: optional additional parameters, currently supported:
 *		- retries: number of times to retry in case of error, default none.
 *	- callback(error, body): error is null only if result is 200.
 *		If there is an error, the body can contain the following attributes:
 *		- statusCode: if status code is not 200.
 *		- readingResponse: if response could not be read.
 */
exports.post = function(url, json, params, callback)
{
	if (typeof params == 'function')
	{
		callback = params;
		params = {};
	}
	params = params || {};
	var options = urlLib.parse(url);
	options.method = 'POST';
	if (typeof json == 'object')
	{
		params.body = JSON.stringify(json);
		options.headers = {
			'Content-Type': 'application/json',
			'Content-Length': params.body.length,
		};
	}
	else
	{
		params.body = json;
		options.headers = {
			'Content-Type': 'text/plain',
			'Content-Length': params.body.length,
		};
	}
	send(options, params, callback);
};

function send(options, params, callback)
{
	callback = callback || function() {};
	options.headers = options.headers || {};
	options.headers['user-agent'] = 'node.js basic-request bot';
	options.agent = null;
	sendWithRetries(params.retries, options, params, callback);
}

function sendWithRetries(retries, options, params, callback)
{
	var finished = false;
	var protocol = http;
	if (options.protocol == 'https:')
	{
		protocol = https;
	}
	var request = protocol.get(options, function(response)
	{
		if (response.statusCode == 301 || response.statusCode == 302)
		{
			// follow redirection
			var location = response.headers.location;
			request.abort();
			return exports.get(location, callback);
		}
		if (response.statusCode != 200)
		{
			finished = true;
			request.abort();
			return callback('Invalid status code ' + response.statusCode, {statusCode: response.statusCode});
		}
		var body = '';
		response.on('data', function (chunk)
		{
			body += chunk;
		});
		response.on('error', function(error)
		{
			finished = true;
			return callback('Error reading response: ' + error, {readingResponse: true});
		});
		response.on('end', function()
		{
			if (finished)
			{
				return;
			}
			request.end();
			return callback(null, body);
		});
	});
	request.on('error', function(error)
	{
		finished = true;
		return callback('Error sending request: ' + error, {sendingRequest: true});
	});
	if (params.body)
	{
		request.write(params.body);
	}
	request.end();
}

// show API if invoked directly
if (__filename == process.argv[1])
{
	console.log('Use in your code as:');
	console.log('  request.get(url, function(error, body) {});');
}

<commit_msg>Refactor slightly.<commit_after>'use strict';

/**
 * Simplified http request.
 * (C) 2013-2014 MediaSmart Mobile.
 */

// requires
var http = require('http');
var https = require('https');
var urlLib = require('url');

/**
 * Access a URL, send to callback. Parameters:
 *	- url: the URL to access.
 *	- params: optional additional parameters, currently supported:
 *		- retries: number of times to retry in case of error, default none.
 *	- callback(error, body): error is null only if result is 200.
 *		If there is an error, the body can contain the following attributes:
 *		- statusCode: if status code is not 200.
 *		- readingResponse: if response could not be read.
 */
exports.get = function(url, params, callback)
{
	if (typeof params == 'function')
	{
		callback = params;
		params = {};
	}
	params = params || {};
	var options = urlLib.parse(url);
	send(options, params, callback);
};

/**
 * Post to a URL, send to callback. Parameters:
 *	- url: the URL to access.
 *	- json: the object to send, can be a JSON string.
 *	- params: optional additional parameters, currently supported:
 *		- retries: number of times to retry in case of error, default none.
 *	- callback(error, body): error is null only if result is 200.
 *		If there is an error, the body can contain the following attributes:
 *		- statusCode: if status code is not 200.
 *		- readingResponse: if response could not be read.
 */
exports.post = function(url, json, params, callback)
{
	var options = urlLib.parse(url);
	options.method = 'POST';
	sendBody(options, json, params, callback);
};

function sendBody(options, json, params, callback)
{
	if (typeof params == 'function')
	{
		callback = params;
		params = {};
	}
	params = params || {};
	if (typeof json == 'object')
	{
		params.body = JSON.stringify(json);
		options.headers = {
			'Content-Type': 'application/json',
			'Content-Length': params.body.length,
		};
	}
	else
	{
		params.body = json;
		options.headers = {
			'Content-Type': 'text/plain',
			'Content-Length': params.body.length,
		};
	}
	send(options, params, callback);
}

function send(options, params, callback)
{
	callback = callback || function() {};
	options.headers = options.headers || {};
	options.headers['user-agent'] = 'node.js basic-request bot';
	options.agent = null;
	sendWithRetries(params.retries, options, params, callback);
}

function sendWithRetries(retries, options, params, callback)
{
	var finished = false;
	var protocol = http;
	if (options.protocol == 'https:')
	{
		protocol = https;
	}
	var request = protocol.get(options, function(response)
	{
		if (response.statusCode == 301 || response.statusCode == 302)
		{
			// follow redirection
			var location = response.headers.location;
			request.abort();
			return exports.get(location, callback);
		}
		if (response.statusCode != 200)
		{
			finished = true;
			request.abort();
			return callback('Invalid status code ' + response.statusCode, {statusCode: response.statusCode});
		}
		var body = '';
		response.on('data', function (chunk)
		{
			body += chunk;
		});
		response.on('error', function(error)
		{
			finished = true;
			return callback('Error reading response: ' + error, {readingResponse: true});
		});
		response.on('end', function()
		{
			if (finished)
			{
				return;
			}
			request.end();
			return callback(null, body);
		});
	});
	request.on('error', function(error)
	{
		finished = true;
		return callback('Error sending request: ' + error, {sendingRequest: true});
	});
	if (params.body)
	{
		request.write(params.body);
	}
	request.end();
}

// show API if invoked directly
if (__filename == process.argv[1])
{
	console.log('Use in your code as:');
	console.log('  request.get(url, function(error, body) {});');
}

<|endoftext|>