<commit_before>'use strict';

var fs = require('fs');
var data;
var buf = module.exports = new Buffer(8);
var colPalette = require('./color-map');

var rs = fs.readFile(__dirname + '/../img/palette-bitmap.bmp', function(err, data){

  if (err) return console.log('error buffering bitmap', err);
    paletteInfo.length = data.readUInt32LE(2);//11078
    paletteInfo.width = data.readUInt32LE(18);//100
    paletteInfo.height = data.readUInt32LE(22);//100
    paletteInfo.bitsPerPix = data.readUInt32LE(28);//8 in palette, 24 in non
    paletteInfo.type = data.toString('utf8', 0, 2);//B

    CPalette.darken(data);

    colPalette.darken(data);

    fs.writeFile(__dirname + '/../img/darkenImage.bmp', data, function() {
        if (err) return console.log(err);

        CPalette.invert(data);

            colPalette.invert(data);

            fs.writeFile(__dirname + '/../img/invertImage.bmp', data, function() {
               if (err) return console.log(err);
        });
    });
});

exports.data = data;

<commit_msg>Update buffer.js<commit_after>'use strict';

var fs = require('fs');
var data;
var buf = module.exports = new Buffer(8);
var colPalette = require('./color-map');

var rs = fs.readFile(__dirname + '/../img/palette-bitmap.bmp', function(err, data){

  if (err) return console.log('error buffering bitmap', err);

    colPalette.darken(data);

    fs.writeFile(__dirname + '/../img/darkenImage.bmp', data, function() {
        if (err) return console.log(err);

        CPalette.invert(data);

            colPalette.invert(data);

            fs.writeFile(__dirname + '/../img/invertImage.bmp', data, function() {
               if (err) return console.log(err);
        });
    });
});

exports.data = data;

<|endoftext|>


<commit_before>var derp = require('./derp'),
  glob = require('glob'),
  fs = require('fs'),
  path = require('path'),
  JSZip = require('jszip'),
  Minimatch = require('minimatch').Minimatch,
  isWindows = require('os').platform() === 'win32',
  async = require('async');

module.exports = function bundle(config, fn){
  // run npm install
  // create manifest
  // create zip and add all files to it
  // write zip to config.out
  derp.sync(config,
    // derp.run('npm install', config.src),
    module.exports.manifest, module.exports.patch, module.exports.zip, fn);
};

module.exports.patch = function(config, fn){
  var debug = require('debug')('lone:bundle:patch'),
    DiffMatchPatch = require('diff-match-patch'),
    dmp = new DiffMatchPatch();

  if(!isWindows){
    debug('not windows.  dont need to patch');
    return fn(null, config);
  }

  [
    [
      path.resolve(config.src + '/node_modules/bson/ext/index.js'),
      path.resolve(__dirname + '/../patch/bson.patch')
    ],
    [
      path.resolve(config.src + '/node_modules/mongodb/node_modules/kerberos/index.js'),
      path.resolve(__dirname + '/../patch/kerberos.patch')
    ]
  ].map(function(item){
    if(!fs.existsSync(item[0])){
      return debug('dont need to patch', item[0]);
    }
    debug('applying', item[0], item[1]);
    var src = item[0],
      patch = fs.readFileSync(item[1], 'utf-8'),
      p, fresh;
    if(isWindows){
      patch = patch.replace(/\r/g, '');
    }
    p = dmp.patch_fromText(patch);

    fresh = dmp.patch_apply(p,
      fs.readFileSync(src, 'utf-8'));

    debug('fresh', fresh[0]);
    fs.writeFileSync(src, fresh[0]);
  });

  debug('complete');
  return fn(null, config);
};

module.exports.manifest = function bundle_manifest(config, fn){
  var debug = require('debug')('lone:bundle:manifest'),
    manifest = {files: [], directories: []},
    ignore = [];

  // Already ran the manifest
  if(config.manifest) return fn(null, config);

  function addIgnore(pattern){
    debug('ignore', pattern);
    ignore.push(new Minimatch(pattern, {flipNegate: true}));
  }
  config.ignore.push.apply(config.ignore, ['node_modules/lone/**']);

  config.ignore.map(addIgnore);
  glob('{*,**/*}', {cwd: config.src, root: config.src, mark: true, strict: true}, function (err, files){
    if(err) return fn(err);

    manifest.files = files.filter(function(p){
      var gIgnore = ignore.some(function(i){
        return i.match(p);
      });

      if(gIgnore === true) return false;
      if(p.charAt(p.length - 1) === '/'){
        manifest.directories.push(p);
        return false;
      }
      return true;
    });
    config.manifest = manifest;
    debug('files collected', config.manifest.files.length);

    fn(null, config);
  });
};

module.exports.zip = function bundle_zip(config, fn){
  var zip = new JSZip(null, {type: 'nodebuffer'}),
    debug = require('debug')('lone:bundle:zip');

  debug('reading files');

  async.parallel(config.manifest.files.map(function(p){
    return function(cb){
      fs.readFile(config.src + '/' + p, function(err, data){
        if(err) return cb(err);

        zip.file(p, data);
        debug('added', derp.relativity(p));
        cb(null);
      });
    };
  }), function(err){
    if(err) return fn(err);
    debug('writing', derp.relativity(config.bundle));
    fs.writeFile(config.bundle, zip.generate({type:'nodebuffer'}), function(err){
      if(err) return fn(err);
      fn(null, config);
    });
  });
};
<commit_msg>add limit to bundling to get around EMFILE errors<commit_after>var derp = require('./derp'),
  glob = require('glob'),
  fs = require('fs'),
  path = require('path'),
  JSZip = require('jszip'),
  Minimatch = require('minimatch').Minimatch,
  isWindows = require('os').platform() === 'win32',
  async = require('async');

module.exports = function bundle(config, fn){
  // run npm install
  // create manifest
  // create zip and add all files to it
  // write zip to config.out
  derp.sync(config,
    // derp.run('npm install', config.src),
    module.exports.manifest, module.exports.patch, module.exports.zip, fn);
};

module.exports.patch = function(config, fn){
  var debug = require('debug')('lone:bundle:patch'),
    DiffMatchPatch = require('diff-match-patch'),
    dmp = new DiffMatchPatch();

  if(!isWindows){
    debug('not windows.  dont need to patch');
    return fn(null, config);
  }

  [
    [
      path.resolve(config.src + '/node_modules/bson/ext/index.js'),
      path.resolve(__dirname + '/../patch/bson.patch')
    ],
    [
      path.resolve(config.src + '/node_modules/mongodb/node_modules/kerberos/index.js'),
      path.resolve(__dirname + '/../patch/kerberos.patch')
    ]
  ].map(function(item){
    if(!fs.existsSync(item[0])){
      return debug('dont need to patch', item[0]);
    }
    debug('applying', item[0], item[1]);
    var src = item[0],
      patch = fs.readFileSync(item[1], 'utf-8'),
      p, fresh;
    if(isWindows){
      patch = patch.replace(/\r/g, '');
    }
    p = dmp.patch_fromText(patch);

    fresh = dmp.patch_apply(p,
      fs.readFileSync(src, 'utf-8'));

    debug('fresh', fresh[0]);
    fs.writeFileSync(src, fresh[0]);
  });

  debug('complete');
  return fn(null, config);
};

module.exports.manifest = function bundle_manifest(config, fn){
  var debug = require('debug')('lone:bundle:manifest'),
    manifest = {files: [], directories: []},
    ignore = [];

  // Already ran the manifest
  if(config.manifest) return fn(null, config);

  function addIgnore(pattern){
    debug('ignore', pattern);
    ignore.push(new Minimatch(pattern, {flipNegate: true}));
  }
  config.ignore.push.apply(config.ignore, ['node_modules/lone/**']);

  config.ignore.map(addIgnore);
  glob('{*,**/*}', {cwd: config.src, root: config.src, mark: true, strict: true}, function (err, files){
    if(err) return fn(err);

    manifest.files = files.filter(function(p){
      var gIgnore = ignore.some(function(i){
        return i.match(p);
      });

      if(gIgnore === true) return false;
      if(p.charAt(p.length - 1) === '/'){
        manifest.directories.push(p);
        return false;
      }
      return true;
    });
    config.manifest = manifest;
    debug('files collected', config.manifest.files.length);

    fn(null, config);
  });
};

module.exports.zip = function bundle_zip(config, fn){
  var zip = new JSZip(null, {type: 'nodebuffer'}),
    debug = require('debug')('lone:bundle:zip');

  debug('reading files');

  async.parallelLimit(config.manifest.files.map(function(p){
    return function(cb){
      fs.readFile(config.src + '/' + p, function(err, data){
        if(err) return cb(err);

        zip.file(p, data);
        debug('added', derp.relativity(p));
        cb(null);
      });
    };
  }), 100, function(err){
    if(err) return fn(err);
    debug('writing', derp.relativity(config.bundle));
    fs.writeFile(config.bundle, zip.generate({type:'nodebuffer'}), function(err){
      if(err) return fn(err);
      fn(null, config);
    });
  });
};
<|endoftext|>


<commit_before>var defaults = require('./defaults.js');
var util = require('util');
var events = require('events');
var http = require('http');
var https = require('https');
var WebSocket = require('ws');

function Chrome(options, notifier) {
    var self = this;
    // options
    options = options || {};
    self.host = options.host || defaults.HOST;
    self.port = options.port || defaults.PORT;
    self.protocol = options.protocol;
    self.chooseTab = options.chooseTab || function () { return 0; };
    // locals
    events.EventEmitter.call(this);
    self.notifier = notifier;
    self.callbacks = {};
    self.nextCommandId = 1;
    // operations
    connectToChrome.call(self);
}

util.inherits(Chrome, events.EventEmitter);

// callback(err, fromChrome, protocol)
Chrome.Protocol = function (options, callback) {
    if (typeof options === 'function') {
        callback = options;
        options = undefined;
    }
    options = options || {};
    var fallbackProtocol = require('./protocol.json');
    // attempt to fetch the protocol directly from the Chromium repository
    // according to the current version; fallback to the hardcoded version
    //
    // Thanks to Paul Irish.
    // (see https://github.com/cyrus-and/chrome-remote-interface/issues/10#issuecomment-146032907)
    Chrome.Version(options, function (err, info) {
        if (err) {
            callback(null, false, fallbackProtocol);
        } else {
            var version = info['WebKit-Version'];
            var match = version.match(/\s\(@(\b[0-9a-f]{5,40}\b)/);
            var hash = match[1];
            var fromChromiumDotOrg = (hash <= 202666);
            var template = (fromChromiumDotOrg ?
                'https://src.chromium.org/blink/trunk/Source/devtools/protocol.json?p=%s':
                'https://chromium.googlesource.com/chromium/src/+/%s/third_party/WebKit/Source/devtools/protocol.json?format=TEXT');
            var url = util.format(template, hash);
            var request = https.get(url, function (response) {
                var data = '';
                response.on('data', function (chunk) {
                    data += chunk;
                });
                response.on('end', function () {
                    if (response.statusCode === 200) {
                        try {
                            // the file is served base64 encoded from googlesource.com
                            if (!fromChromiumDotOrg) {
                                data = new Buffer(data, 'base64').toString();
                            }
                            callback(null, true, JSON.parse(data));
                        } catch (err) {
                            callback(null, false, fallbackProtocol);
                        }
                    } else {
                        callback(null, false, fallbackProtocol);
                    }
                });
            });
            request.on('error', function (err) {
                callback(null, false, fallbackProtocol);
            });
        }
    });
};

Chrome.List = function (options, callback) {
    if (typeof options === 'function') {
        callback = options;
        options = undefined;
    }
    options = options || {};
    options.path = '/json/list';
    devToolsInterface(options, function (error, status, data) {
        if (error) {
            callback(error);
        } else {
            if (status === 200) {
                var tabs = JSON.parse(data);
                callback(null, tabs);
            } else {
                callback(new Error(data));
            }
        }
    });
};

Chrome.New = function (options, callback) {
    if (typeof options === 'function') {
        callback = options;
        options = undefined;
    }
    options = options || {};
    options.path = '/json/new';
    if (Object.prototype.hasOwnProperty.call(options, 'url')) {
        options.path += '?' + options.url;
    }
    devToolsInterface(options, function (error, status, data) {
        if (error) {
            callback(error);
        } else {
            if (status === 200) {
                var tab = JSON.parse(data);
                callback(null, tab);
            } else {
                callback(new Error(data));
            }
        }
    });
};

Chrome.Activate = function (options, callback) {
    if (typeof options === 'function') {
        callback = options;
        options = undefined;
    }
    options = options || {};
    options.path = '/json/activate/' + options.id;
    devToolsInterface(options, function (error, status, data) {
        if (error) {
            callback(error);
        } else {
            if (status === 200) {
                callback(null);
            } else {
                callback(new Error(data));
            }
        }
    });
};

Chrome.Close = function (options, callback) {
    if (typeof options === 'function') {
        callback = options;
        options = undefined;
    }
    options = options || {};
    options.path = '/json/close/' + options.id;
    devToolsInterface(options, function (error, status, data) {
        if (error) {
            callback(error);
        } else {
            if (status === 200) {
                callback(null);
            } else {
                callback(new Error(data));
            }
        }
    });
};

Chrome.Version = function (options, callback) {
    if (typeof options === 'function') {
        callback = options;
        options = undefined;
    }
    options = options || {};
    options.path = '/json/version';
    devToolsInterface(options, function (error, status, data) {
        if (error) {
            callback(error);
        } else {
            if (status === 200) {
                var versionInfo = JSON.parse(data);
                callback(null, versionInfo);
            } else {
                callback(new Error(data));
            }
        }
    });
};

Chrome.prototype.inspect = function (depth, options) {
    options.customInspect = false;
    return util.inspect(this, options);
};

Chrome.prototype.send = function (method, params, callback) {
    var self = this;
    var id = self.nextCommandId++;
    if (typeof params === 'function') {
        callback = params;
        params = undefined;
    }
    var message = {'id': id, 'method': method, 'params': params};
    self.ws.send(JSON.stringify(message));
    // register a command response callback or use a dummy callback to ensure
    // that the 'ready' event is correctly fired
    self.callbacks[id] = callback || function () {};
};

Chrome.prototype.close = function () {
    var self = this;
    self.ws.removeAllListeners();
    self.ws.close();
};

function prepareHelp(type, object) {
    var help = {
        'type': type
    };
    for (var field in object) {
        help[field] = object[field];
    }
    return help;
}

function addCommand(domainName, command) {
    var self = this;
    self[domainName][command.name] = function (params, callback) {
        self.send(domainName + '.' + command.name, params, callback);
    };
    self[domainName][command.name].help = prepareHelp('command', command);
}

function addEvent(domainName, event) {
    var self = this;
    self[domainName][event.name] = function (handler) {
        self.on(domainName + '.' + event.name, handler);
    };
    self[domainName][event.name].help = prepareHelp('event', event);
}

function addType(domainName, type) {
    var self = this;
    self[domainName][type.id] = type;
}

function addCommandShorthands() {
    var self = this;
    for (var domainIdx in self.protocol.domains) {
        var domain = self.protocol.domains[domainIdx];
        var domainName = domain.domain;
        self[domainName] = {};
        // add commands
        var commands = domain.commands;
        if (commands) {
            for (var commandIdx in commands) {
                var command = commands[commandIdx];
                addCommand.call(self, domainName, command);
            }
        }
        // add events
        var events = domain.events;
        if (events) {
            for (var eventIdx in events) {
                var event = events[eventIdx];
                addEvent.call(self, domainName, event);
            }
        }
        // add types
        var types = domain.types;
        if (types) {
            for (var typeIdx in types) {
                var type = types[typeIdx];
                addType.call(self, domainName, type);
            }
        }
    }
}

function connectToChrome() {
    var self = this;
    var options = {'host': self.host, 'port': self.port};
    var continueConnection = function () {
        // build the API from the protocol descriptor
        addCommandShorthands.call(self);
        Chrome.List(options, function (err, tabs) {
            if (err) {
                self.notifier.emit('error', err);
            } else {
                var tabError;
                var tab;
                if (typeof self.chooseTab === 'object') {
                    tab = self.chooseTab;
                } else {
                    tab = tabs[self.chooseTab(tabs)];
                }
                if (tab) {
                    var tabDebuggerUrl = tab.webSocketDebuggerUrl;
                    if (tabDebuggerUrl) {
                        connectToWebSocket.call(self, tabDebuggerUrl);
                    } else {
                        // a WebSocket is already connected to this tab?
                        tabError = new Error('Tab does not support inspection');
                        self.notifier.emit('error', tabError);
                    }
                } else {
                    tabError = new Error('Invalid tab index');
                    self.notifier.emit('error', tabError);
                }
            }
        });
    };
    // fetch the protocol
    if (self.protocol === null) {
        // try fetching the protocol from Chrome falling back to the hardcoded
        // version otherwise
        Chrome.Protocol(options, function (err, fromChrome, protocol) {
            if (err) {
                self.notifier.emit('error', err);
            } else {
                self.protocol = protocol;
                continueConnection();
            }
        });
    } else {
        // use the one provided falling back to the hardcoded version otherwise
        self.protocol = self.protocol || require('./protocol.json');
        continueConnection();
    }
}

function connectToWebSocket(url) {
    var self = this;
    self.ws = new WebSocket(url);
    self.ws.on('open', function () {
        self.notifier.emit('connect', self);
    });
    self.ws.on('message', function (data) {
        var message = JSON.parse(data);
        // command response
        if (message.id) {
            var callback = self.callbacks[message.id];
            if (callback) {
                if (message.result) {
                    callback(false, message.result);
                } else if (message.error) {
                    callback(true, message.error);
                }
                // unregister command response callback
                delete self.callbacks[message.id];
                // notify when there are no more pending commands
                if (Object.keys(self.callbacks).length === 0) {
                    self.emit('ready');
                }
            }
        }
        // event
        else if (message.method) {
            self.emit('event', message);
            self.emit(message.method, message.params);
        }
    });
    self.ws.on('error', function (err) {
        self.notifier.emit('error', err);
    });
}

// httpOptions.path must be specified; callback(err, status, data)
function devToolsInterface(httpOptions, callback) {
    httpOptions.host = httpOptions.host || defaults.HOST;
    httpOptions.port = httpOptions.port || defaults.PORT;
    var request = http.get(httpOptions, function (response) {
        var data = '';
        response.on('data', function (chunk) {
            data += chunk;
        });
        response.on('end', function () {
            callback(null, response.statusCode, data);
        });
    });
    request.on('error', function (err) {
        callback(err);
    });
}

module.exports = Chrome;
<commit_msg>Simplify the DevTools wrapper usage<commit_after>var defaults = require('./defaults.js');
var util = require('util');
var events = require('events');
var http = require('http');
var https = require('https');
var WebSocket = require('ws');

function Chrome(options, notifier) {
    var self = this;
    // options
    options = options || {};
    self.host = options.host || defaults.HOST;
    self.port = options.port || defaults.PORT;
    self.protocol = options.protocol;
    self.chooseTab = options.chooseTab || function () { return 0; };
    // locals
    events.EventEmitter.call(this);
    self.notifier = notifier;
    self.callbacks = {};
    self.nextCommandId = 1;
    // operations
    connectToChrome.call(self);
}

util.inherits(Chrome, events.EventEmitter);

// callback(err, fromChrome, protocol)
Chrome.Protocol = function (options, callback) {
    if (typeof options === 'function') {
        callback = options;
        options = undefined;
    }
    options = options || {};
    var fallbackProtocol = require('./protocol.json');
    // attempt to fetch the protocol directly from the Chromium repository
    // according to the current version; fallback to the hardcoded version
    //
    // Thanks to Paul Irish.
    // (see https://github.com/cyrus-and/chrome-remote-interface/issues/10#issuecomment-146032907)
    Chrome.Version(options, function (err, info) {
        if (err) {
            callback(null, false, fallbackProtocol);
        } else {
            var version = info['WebKit-Version'];
            var match = version.match(/\s\(@(\b[0-9a-f]{5,40}\b)/);
            var hash = match[1];
            var fromChromiumDotOrg = (hash <= 202666);
            var template = (fromChromiumDotOrg ?
                'https://src.chromium.org/blink/trunk/Source/devtools/protocol.json?p=%s':
                'https://chromium.googlesource.com/chromium/src/+/%s/third_party/WebKit/Source/devtools/protocol.json?format=TEXT');
            var url = util.format(template, hash);
            var request = https.get(url, function (response) {
                var data = '';
                response.on('data', function (chunk) {
                    data += chunk;
                });
                response.on('end', function () {
                    if (response.statusCode === 200) {
                        try {
                            // the file is served base64 encoded from googlesource.com
                            if (!fromChromiumDotOrg) {
                                data = new Buffer(data, 'base64').toString();
                            }
                            callback(null, true, JSON.parse(data));
                        } catch (err) {
                            callback(null, false, fallbackProtocol);
                        }
                    } else {
                        callback(null, false, fallbackProtocol);
                    }
                });
            });
            request.on('error', function (err) {
                callback(null, false, fallbackProtocol);
            });
        }
    });
};

Chrome.List = function (options, callback) {
    if (typeof options === 'function') {
        callback = options;
        options = undefined;
    }
    options = options || {};
    options.path = '/json/list';
    devToolsInterface(options, function (error, tabs) {
        if (error) {
            callback(error);
        } else {
            callback(null, JSON.parse(tabs));
        }
    });
};

Chrome.New = function (options, callback) {
    if (typeof options === 'function') {
        callback = options;
        options = undefined;
    }
    options = options || {};
    options.path = '/json/new';
    if (Object.prototype.hasOwnProperty.call(options, 'url')) {
        options.path += '?' + options.url;
    }
    devToolsInterface(options, function (error, tab) {
        if (error) {
            callback(error);
        } else {
            callback(null, JSON.parse(tab));
        }
    });
};

Chrome.Activate = function (options, callback) {
    if (typeof options === 'function') {
        callback = options;
        options = undefined;
    }
    options = options || {};
    options.path = '/json/activate/' + options.id;
    devToolsInterface(options, function (error) {
        if (error) {
            callback(error);
        } else {
            callback(null);
        }
    });
};

Chrome.Close = function (options, callback) {
    if (typeof options === 'function') {
        callback = options;
        options = undefined;
    }
    options = options || {};
    options.path = '/json/close/' + options.id;
    devToolsInterface(options, function (error) {
        if (error) {
            callback(error);
        } else {
            callback(null);
        }
    });
};

Chrome.Version = function (options, callback) {
    if (typeof options === 'function') {
        callback = options;
        options = undefined;
    }
    options = options || {};
    options.path = '/json/version';
    devToolsInterface(options, function (error, versionInfo) {
        if (error) {
            callback(error);
        } else {
            callback(null, JSON.parse(versionInfo));
        }
    });
};

Chrome.prototype.inspect = function (depth, options) {
    options.customInspect = false;
    return util.inspect(this, options);
};

Chrome.prototype.send = function (method, params, callback) {
    var self = this;
    var id = self.nextCommandId++;
    if (typeof params === 'function') {
        callback = params;
        params = undefined;
    }
    var message = {'id': id, 'method': method, 'params': params};
    self.ws.send(JSON.stringify(message));
    // register a command response callback or use a dummy callback to ensure
    // that the 'ready' event is correctly fired
    self.callbacks[id] = callback || function () {};
};

Chrome.prototype.close = function () {
    var self = this;
    self.ws.removeAllListeners();
    self.ws.close();
};

function prepareHelp(type, object) {
    var help = {
        'type': type
    };
    for (var field in object) {
        help[field] = object[field];
    }
    return help;
}

function addCommand(domainName, command) {
    var self = this;
    self[domainName][command.name] = function (params, callback) {
        self.send(domainName + '.' + command.name, params, callback);
    };
    self[domainName][command.name].help = prepareHelp('command', command);
}

function addEvent(domainName, event) {
    var self = this;
    self[domainName][event.name] = function (handler) {
        self.on(domainName + '.' + event.name, handler);
    };
    self[domainName][event.name].help = prepareHelp('event', event);
}

function addType(domainName, type) {
    var self = this;
    self[domainName][type.id] = type;
}

function addCommandShorthands() {
    var self = this;
    for (var domainIdx in self.protocol.domains) {
        var domain = self.protocol.domains[domainIdx];
        var domainName = domain.domain;
        self[domainName] = {};
        // add commands
        var commands = domain.commands;
        if (commands) {
            for (var commandIdx in commands) {
                var command = commands[commandIdx];
                addCommand.call(self, domainName, command);
            }
        }
        // add events
        var events = domain.events;
        if (events) {
            for (var eventIdx in events) {
                var event = events[eventIdx];
                addEvent.call(self, domainName, event);
            }
        }
        // add types
        var types = domain.types;
        if (types) {
            for (var typeIdx in types) {
                var type = types[typeIdx];
                addType.call(self, domainName, type);
            }
        }
    }
}

function connectToChrome() {
    var self = this;
    var options = {'host': self.host, 'port': self.port};
    var continueConnection = function () {
        // build the API from the protocol descriptor
        addCommandShorthands.call(self);
        Chrome.List(options, function (err, tabs) {
            if (err) {
                self.notifier.emit('error', err);
            } else {
                var tabError;
                var tab;
                if (typeof self.chooseTab === 'object') {
                    tab = self.chooseTab;
                } else {
                    tab = tabs[self.chooseTab(tabs)];
                }
                if (tab) {
                    var tabDebuggerUrl = tab.webSocketDebuggerUrl;
                    if (tabDebuggerUrl) {
                        connectToWebSocket.call(self, tabDebuggerUrl);
                    } else {
                        // a WebSocket is already connected to this tab?
                        tabError = new Error('Tab does not support inspection');
                        self.notifier.emit('error', tabError);
                    }
                } else {
                    tabError = new Error('Invalid tab index');
                    self.notifier.emit('error', tabError);
                }
            }
        });
    };
    // fetch the protocol
    if (self.protocol === null) {
        // try fetching the protocol from Chrome falling back to the hardcoded
        // version otherwise
        Chrome.Protocol(options, function (err, fromChrome, protocol) {
            if (err) {
                self.notifier.emit('error', err);
            } else {
                self.protocol = protocol;
                continueConnection();
            }
        });
    } else {
        // use the one provided falling back to the hardcoded version otherwise
        self.protocol = self.protocol || require('./protocol.json');
        continueConnection();
    }
}

function connectToWebSocket(url) {
    var self = this;
    self.ws = new WebSocket(url);
    self.ws.on('open', function () {
        self.notifier.emit('connect', self);
    });
    self.ws.on('message', function (data) {
        var message = JSON.parse(data);
        // command response
        if (message.id) {
            var callback = self.callbacks[message.id];
            if (callback) {
                if (message.result) {
                    callback(false, message.result);
                } else if (message.error) {
                    callback(true, message.error);
                }
                // unregister command response callback
                delete self.callbacks[message.id];
                // notify when there are no more pending commands
                if (Object.keys(self.callbacks).length === 0) {
                    self.emit('ready');
                }
            }
        }
        // event
        else if (message.method) {
            self.emit('event', message);
            self.emit(message.method, message.params);
        }
    });
    self.ws.on('error', function (err) {
        self.notifier.emit('error', err);
    });
}

// httpOptions.path must be specified; callback(err, data)
function devToolsInterface(httpOptions, callback) {
    httpOptions.host = httpOptions.host || defaults.HOST;
    httpOptions.port = httpOptions.port || defaults.PORT;
    var request = http.get(httpOptions, function (response) {
        var data = '';
        response.on('data', function (chunk) {
            data += chunk;
        });
        response.on('end', function () {
            if (response.statusCode === 200) {
                callback(null, data);
            } else {
                callback(new Error(data));
            }
        });
    });
    request.on('error', function (err) {
        callback(err);
    });
}

module.exports = Chrome;
<|endoftext|>


<commit_before>var Emitter = require( 'events' ).EventEmitter
var inherit = require( 'bloodline' )
var Inspector = require( 'inspector' )
var URL = require( 'url' )
var path = require( 'path' )
var log = require( 'debug' )( 'ZEUGBERG:CHROME' )
var async = require( 'async' )

/**
 * Chrome/Window Frame
 * @return {Chrome}
 */
function Chrome( options ) {

  if( !(this instanceof Chrome) )
    return new Chrome( options )

  Emitter.call( this )

  this.frame = null
  this.devTools = null
  this.inspector = null

  this._isResizing = null

}

Chrome.setTimeout = global.setTimeout.bind( global )
Chrome.clearTimeout = global.clearTimeout.bind( global )

/**
 * Options for Window.open()
 * @type {Object}
 */
Chrome.options = {
  frame: false,
  toolbar: false,
  width: 1024,
  height: 768,
}

/**
 * Chrome prototype
 * @type {Object}
 */
Chrome.prototype = {

  constructor: Chrome,

  attachEvents: function() {

    this.frame.on( 'loading', this.onLoading.bind( this ) )
    this.frame.on( 'loaded', this.onLoaded.bind( this ) )
    this.frame.on( 'document-start', this.onDocumentStart.bind( this ) )
    this.frame.on( 'document-end', this.onDocumentEnd.bind( this ) )
    this.frame.on( 'devtools-opened', this.onDevToolsOpened.bind( this ) )
    this.frame.on( 'devtools-closed', this.onDevToolsClosed.bind( this ) )
    this.frame.on( 'resize', this.onResize.bind( this ) )
    this.frame.on( 'capturepagedone', this.onCapturePage.bind( this ) )
    this.frame.on( 'new-win-policy', this.onNewWinPolicy.bind( this ) )
    this.frame.on( 'close', this.onClose.bind( this ) )
    this.frame.on( 'closed', this.onClosed.bind( this ) )

    return this

  },

  attachWindowEvents: function() {
    with( this.frame.window ) {
      addEventListener( 'DOMContentLoaded', this.onDOMContentLoaded.bind( this ) )
      addEventListener( 'load', this.onLoad.bind( this ) )
    }
  },

  attachDebugger: function() {

    if( this.devTools != null )
      return this

    this.devTools = this.frame.showDevTools()
    this.devTools.show( global.argv.debug )

    return this

  },

  attachInspector: function( location, filename ) {

    var self = this
    var remotePort = 9222

    var inspector = this.inspector = new Inspector(
      remotePort, location.hostname, filename,
      function() {
        log( 'INSPECTOR:ATTACHED' )
        self.emit( 'inspector:attached' )
        async.parallel([
          function( done ) { inspector.Network.enable( done ) },
          function( done ) { inspector.Page.enable( done ) },
          function( done ) { inspector.Profiler.enable( done ) },
        ], function( error, results ) {
          if( error != null ) {
            self.emit( 'error', error )
            return
          }
          log( 'INSPECTOR:ENABLED' )
          self.emit( 'inspector:enabled' )
        })
      }
    )

    this.inspector.on( 'error', function( error ) {
      log( 'INSPECTOR:ERROR', error )
      self.emit( 'error', error )
    })

    // Listen for network events, and pick the first
    // document type response after 'loading' event,
    // as it's the page's navigation response
    this.once( 'inspector:enabled', function() {
      this.inspector.Network.on( 'responseReceived', function( event ) {
        if( self.loading && event.type === 'Document' ) {
          self.emit( 'response', event.response )
        }
      })
    })

    // TODO:
    // - [ ] set up HAR recording
    // - [ ] set up JS/CPU profiling

  },

  get location() {
    if( this.frame != null )
      return this.frame.window.location.href
  },

  set location( value ) {
    if( this.frame != null )
      this.frame.window.location.href = value
    // TODO:
    // - [ ] Handle relative paths
  },

  onLoading: function() {
    this.loading = true
    log( 'LOADING' )
  },

  onDOMContentLoaded: function() {
    log( 'DOMCONTENTLOADED' )
  },

  onLoad: function() {
    log( 'LOAD' )
  },

  onLoaded: function() {
    this.loading = false
    log( 'LOADED' )
    this.emit( 'loaded' )
  },

  onDocumentStart: function() {
    log( 'DOCUMENT:START' )
    this.attachDebugger()
    this.attachWindowEvents()
    this.emit( 'attachEvents' )
  },

  onDocumentEnd: function() {
    log( 'DOCUMENT:END' )
  },

  onDevToolsOpened: function( url ) {

    log( 'DEVTOOLS:OPENED', url )

    var self = this
    var location = URL.parse( url, true )
    var dirname = path.join( __dirname, '..' )
    var filename = 'file://' + dirname + '/about:blank'

    this.attachInspector( location, filename )

  },

  onDevToolsClosed: function() {
    log( 'DEVTOOLS:CLOSED' )
    // Remove the ref to the closed window
    this.devTools = null
    // TODO:
    // - [ ] shutdown the inspector
  },

  onResize: function( width, height ) {
    log( 'RESIZE', width, height )
    var self = this
    Chrome.clearTimeout( this._isResizing )
    this._isResizing = Chrome.setTimeout( function() {
      process.nextTick( function() {
        window.requestAnimationFrame( function() {
          log( 'RESIZED' )
          self.emit( 'resized' )
        })
      })
    }, 100 )
  },

  onCapturePage: function() {
    log( 'CAPTURE_PAGE' )
  },

  // Emitted when a new window is requested from this window
  // or a child iframe, e.g. user clicks a link with _blank target.
  onNewWinPolicy: function( frame, url, policy ) {
    log( 'NEW_WIN_POLICY', url )
    // Force the new (popup) window
    // to open in the current window
    // See nw.js wiki for details
    policy.forceCurrent()
    // NOTE: .forceCurrent() would prematurely terminate a test
    // if the opened frame calls window.close() on itself
    // TODO:
    // - [ ] Handle popups properly
  },

  onClose: function() {
    log( 'CLOSE' )
    // Don't leave any unattached
    // DevTools windows behind
    if( this.devTools != null )
      this.devTools.close( true )
    // Enforce close
    // (without 'true' it will loop endlessly,
    // calling 'onClose' over and over)
    this.close( true )
  },

  onClosed: function() {
    log( 'CLOSED' )
  },

  open: function( path ) {

    if( this.frame != null )
      return this

    var GUI = window.require( 'nw.gui' )
    var location = path || 'about:blank'

    this.frame = GUI.Window.open( location, Chrome.options )
    this.frame.show( global.argv.debug )
    this.attachEvents()

    return this

  },

  close: function( force ) {

    if( this.frame == null )
      return this

    this.frame.close( force )
    this.frame = null

    return this

  },

}

inherit( Chrome, Emitter )
// Exports
module.exports = Chrome
<commit_msg>Moved get/set location in lib/chrome<commit_after>var Emitter = require( 'events' ).EventEmitter
var inherit = require( 'bloodline' )
var Inspector = require( 'inspector' )
var URL = require( 'url' )
var path = require( 'path' )
var log = require( 'debug' )( 'ZEUGBERG:CHROME' )
var async = require( 'async' )

/**
 * Chrome/Window Frame
 * @return {Chrome}
 */
function Chrome( options ) {

  if( !(this instanceof Chrome) )
    return new Chrome( options )

  Emitter.call( this )

  this.frame = null
  this.devTools = null
  this.inspector = null

  this._isResizing = null

}

Chrome.setTimeout = global.setTimeout.bind( global )
Chrome.clearTimeout = global.clearTimeout.bind( global )

/**
 * Options for Window.open()
 * @type {Object}
 */
Chrome.options = {
  frame: false,
  toolbar: false,
  width: 1024,
  height: 768,
}

/**
 * Chrome prototype
 * @type {Object}
 */
Chrome.prototype = {

  constructor: Chrome,

  get location() {
    if( this.frame != null )
      return this.frame.window.location.href
  },

  set location( value ) {
    if( this.frame != null )
      this.frame.window.location.href = value
    // TODO:
    // - [ ] Handle relative paths
  },

  attachEvents: function() {

    this.frame.on( 'loading', this.onLoading.bind( this ) )
    this.frame.on( 'loaded', this.onLoaded.bind( this ) )
    this.frame.on( 'document-start', this.onDocumentStart.bind( this ) )
    this.frame.on( 'document-end', this.onDocumentEnd.bind( this ) )
    this.frame.on( 'devtools-opened', this.onDevToolsOpened.bind( this ) )
    this.frame.on( 'devtools-closed', this.onDevToolsClosed.bind( this ) )
    this.frame.on( 'resize', this.onResize.bind( this ) )
    this.frame.on( 'capturepagedone', this.onCapturePage.bind( this ) )
    this.frame.on( 'new-win-policy', this.onNewWinPolicy.bind( this ) )
    this.frame.on( 'close', this.onClose.bind( this ) )
    this.frame.on( 'closed', this.onClosed.bind( this ) )

    return this

  },

  attachWindowEvents: function() {
    with( this.frame.window ) {
      addEventListener( 'DOMContentLoaded', this.onDOMContentLoaded.bind( this ) )
      addEventListener( 'load', this.onLoad.bind( this ) )
    }
  },

  attachDebugger: function() {

    if( this.devTools != null )
      return this

    this.devTools = this.frame.showDevTools()
    this.devTools.show( global.argv.debug )

    return this

  },

  attachInspector: function( location, filename ) {

    var self = this
    var remotePort = 9222

    var inspector = this.inspector = new Inspector(
      remotePort, location.hostname, filename,
      function() {
        log( 'INSPECTOR:ATTACHED' )
        self.emit( 'inspector:attached' )
        async.parallel([
          function( done ) { inspector.Network.enable( done ) },
          function( done ) { inspector.Page.enable( done ) },
          function( done ) { inspector.Profiler.enable( done ) },
        ], function( error, results ) {
          if( error != null ) {
            self.emit( 'error', error )
            return
          }
          log( 'INSPECTOR:ENABLED' )
          self.emit( 'inspector:enabled' )
        })
      }
    )

    this.inspector.on( 'error', function( error ) {
      log( 'INSPECTOR:ERROR', error )
      self.emit( 'error', error )
    })

    // Listen for network events, and pick the first
    // document type response after 'loading' event,
    // as it's the page's navigation response
    this.once( 'inspector:enabled', function() {
      this.inspector.Network.on( 'responseReceived', function( event ) {
        if( self.loading && event.type === 'Document' ) {
          self.emit( 'response', event.response )
        }
      })
    })

    // TODO:
    // - [ ] set up HAR recording
    // - [ ] set up JS/CPU profiling

  },

  onLoading: function() {
    this.loading = true
    log( 'LOADING' )
  },

  onDOMContentLoaded: function() {
    log( 'DOMCONTENTLOADED' )
  },

  onLoad: function() {
    log( 'LOAD' )
  },

  onLoaded: function() {
    this.loading = false
    log( 'LOADED' )
    this.emit( 'loaded' )
  },

  onDocumentStart: function() {
    log( 'DOCUMENT:START' )
    this.attachDebugger()
    this.attachWindowEvents()
    this.emit( 'attachEvents' )
  },

  onDocumentEnd: function() {
    log( 'DOCUMENT:END' )
  },

  onDevToolsOpened: function( url ) {

    log( 'DEVTOOLS:OPENED', url )

    var self = this
    var location = URL.parse( url, true )
    var dirname = path.join( __dirname, '..' )
    var filename = 'file://' + dirname + '/about:blank'

    this.attachInspector( location, filename )

  },

  onDevToolsClosed: function() {
    log( 'DEVTOOLS:CLOSED' )
    // Remove the ref to the closed window
    this.devTools = null
    // TODO:
    // - [ ] shutdown the inspector
  },

  onResize: function( width, height ) {
    log( 'RESIZE', width, height )
    var self = this
    Chrome.clearTimeout( this._isResizing )
    this._isResizing = Chrome.setTimeout( function() {
      process.nextTick( function() {
        window.requestAnimationFrame( function() {
          log( 'RESIZED' )
          self.emit( 'resized' )
        })
      })
    }, 100 )
  },

  onCapturePage: function() {
    log( 'CAPTURE_PAGE' )
  },

  // Emitted when a new window is requested from this window
  // or a child iframe, e.g. user clicks a link with _blank target.
  onNewWinPolicy: function( frame, url, policy ) {
    log( 'NEW_WIN_POLICY', url )
    // Force the new (popup) window
    // to open in the current window
    // See nw.js wiki for details
    policy.forceCurrent()
    // NOTE: .forceCurrent() would prematurely terminate a test
    // if the opened frame calls window.close() on itself
    // TODO:
    // - [ ] Handle popups properly
  },

  onClose: function() {
    log( 'CLOSE' )
    // Don't leave any unattached
    // DevTools windows behind
    if( this.devTools != null )
      this.devTools.close( true )
    // Enforce close
    // (without 'true' it will loop endlessly,
    // calling 'onClose' over and over)
    this.close( true )
  },

  onClosed: function() {
    log( 'CLOSED' )
  },

  open: function( path ) {

    if( this.frame != null )
      return this

    var GUI = window.require( 'nw.gui' )
    var location = path || 'about:blank'

    this.frame = GUI.Window.open( location, Chrome.options )
    this.frame.show( global.argv.debug )
    this.attachEvents()

    return this

  },

  close: function( force ) {

    if( this.frame == null )
      return this

    this.frame.close( force )
    this.frame = null

    return this

  },

}

inherit( Chrome, Emitter )
// Exports
module.exports = Chrome
<|endoftext|>


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

var client = function (config) {
	var protocol = (undefined === config.secure || config.secure) ?
						'https' : 'http';
	var host = config.username + '.highrisehq.com';
	var token = config.token;

	var authorizationHeader = {};
	if (config.authorization === 'basic') {
		authorizationHeader = 'Basic ' +
				new Buffer(token + ':X', 'ascii').toString('base64');
	}
	else {
		authorizationHeader = 'Bearer ' + token;
	}

	return {
		send: function (method, path, xmlbody, cb) {
			var callback = typeof xmlbody === 'function' ? xmlbody : cb;
			var postdata = typeof xmlbody === 'string' ? xmlbody : null;
			var options = {
				host: host,
				path: path,
				method: method,
				headers: {
					'Authorization' : authorizationHeader
				}
			};

			if (postdata) {
				options.headers['Content-Length'] = postdata.length;
				options.headers['Content-Type'] = 'application/xml';
			}

			var req = require(protocol).request(options, function (res) {
				var data = '';
				res.on('data', function (chunk) {
					data += chunk;
				});
				res.on('end', function () {
					if (res.statusCode >= 400 && res.statusCode < 600 ||
						res.statusCode < 10) {
						callback(res.statusCode);
					} else {
						res.data = data;
						callback(null, res);
					}
				});
			});
			req.on('error', function (e) {
				callback(e.message);
			});
			req.end(postdata);
		},
		get_items: function (url, callback, item_factory, arr_name, item_name) {
			var client = this;

			this.send('GET', url, function (err, res) {
				if (err) {
					callback(err);
				} else {
					xml2js.parseString(res.data, function (err, res) {
						if (err) {
							callback(err);
						} else {
							var items = [];
							if (res[arr_name] && res[arr_name][item_name]) {
								for (var i = 0;
									i < res[arr_name][item_name].length; ++i) {
									var p = new item_factory(client,
										res[arr_name][item_name][i]);
									items.push(p);
								}
							}
							callback(null, items);
						}
					});
				}
			});
		},
		create_item: function (path, data, callback, item_factory) {
			var client = this;

			this.send('POST', path, data, function (err, res) {
				if (err) {
					callback(err);
				} else {
					xml2js.parseString(res.data, function (err, res) {
						if (err) {
							callback(err);
						} else {
							callback(null, new item_factory(client, res));
						}
					});
				}
			});
		},
		get_item: function (url, callback, item_factory) {
			var client = this;

			this.send('GET', url, function (err, res) {
				if (err) {
					callback(err);
				} else {
					xml2js.parseString(res.data, function (err, res) {
						if (err) {
							callback(err);
						} else {
							callback(null, new item_factory(client, res));
						}
					});
				}
			});
		}
	};
};

var highrise = function (config) {
	this.client = new client(config);
	this.account = new (require('./account'))(this.client);
	this.cases = new (require('./cases'))(this.client);
	this.case = new (require('./case'))(this.client);
	this.category = new (require('./category'))(this.client);
	this.categories = new (require('./categories'))(this.client);
	this.comment = new (require('./comment'))(this.client);
	this.companies = new (require('./companies'))(this.client);
	this.company = new (require('./company'))(this.client);
	this.deal = new (require('./deal'))(this.client);
	this.deals = new (require('./deals'))(this.client);
	this.group = new (require('./group'))(this.client);
	this.groups = new (require('./groups'))(this.client);
	this.deletions = new (require('./deletions'))(this.client);
	this.membership = new (require('./membership'))(this.client);
	this.memberships = new (require('./memberships'))(this.client);
	this.party = new (require('./party'))(this.client);
	this.parties = new (require('./parties'))(this.client);
	this.people = new (require('./people'))(this.client);
	this.person = new (require('./person'))(this.client);
	this.note = new (require('./note'))(this.client);
	this.notes = new (require('./notes'))(this.client);
	this.subject_field = new (require('./subject_field'))(this.client);
	this.subject_fields = new (require('./subject_fields'))(this.client);
	this.task = new (require('./task'))(this.client);
	this.tasks = new (require('./tasks'))(this.client);
	this.user = new (require('./user'))(this.client);
	this.users = new (require('./users'))(this.client);
};

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

var client = function (config) {
	var protocol = (undefined === config.secure || config.secure) ?
						'https' : 'http';
	var host = config.username + '.highrisehq.com';
	var token = config.token;

	var authorizationHeader = {};
	if (config.authorization === 'basic') {
		authorizationHeader = 'Basic ' +
				new Buffer(token + ':X', 'ascii').toString('base64');
	}
	else {
		authorizationHeader = 'Bearer ' + token;
	}

	return {
		send: function (method, path, xmlbody, cb) {
			var callback = typeof xmlbody === 'function' ? xmlbody : cb;
			var postdata = typeof xmlbody === 'string' ? xmlbody : null;
			var options = {
				host: host,
				path: path,
				method: method,
				headers: {
					'Authorization' : authorizationHeader
				}
			};

			if (postdata) {
				options.headers['Content-Length'] = postdata.length;
				options.headers['Content-Type'] = 'application/xml';
			}

			var req = require(protocol).request(options, function (res) {
				var data = '';
				res.on('data', function (chunk) {
					data += chunk;
				});
				res.on('end', function () {
					if (res.statusCode >= 400 && res.statusCode < 600 ||
						res.statusCode < 10) {
						callback(res.statusCode);
					} else {
						res.data = data;
						callback(null, res);
					}
				});
			});
			req.on('error', function (e) {
				callback(e.message);
			});
			req.end(postdata);
		},
		get_items: function (url, callback, item_factory, arr_name, item_name) {
			var client = this;

			this.send('GET', url, function (err, res) {
				if (err) {
					callback(err);
				} else {
					xml2js.parseString(res.data, function (err, res) {
						if (err) {
							callback(err);
						} else {
							var items = [];
							if (res[arr_name] && res[arr_name][item_name]) {
								for (var i = 0;
									i < res[arr_name][item_name].length; ++i) {
									var p = new item_factory(client,
										res[arr_name][item_name][i]);
									items.push(p);
								}
							}
							callback(null, items);
						}
					});
				}
			});
		},
		create_item: function (path, data, callback, item_factory) {
			var client = this;

			this.send('POST', path, data, function (err, res) {
				if (err) {
					callback(err);
				} else {
					xml2js.parseString(res.data, function (err, res) {
						if (err) {
							callback(err);
						} else {
							callback(null, new item_factory(client, res));
						}
					});
				}
			});
		},
		get_item: function (url, callback, item_factory) {
			var client = this;

			this.send('GET', url, function (err, res) {
				if (err) {
					callback(err);
				} else {
					xml2js.parseString(res.data, function (err, res) {
						if (err) {
							callback(err);
						} else {
							callback(null, new item_factory(client, res));
						}
					});
				}
			});
		}
	};
};

var highrise = function (config) {
	this.client = new client(config);
	this.account = new (require('./account'))(this.client);
	this.cases = new (require('./cases'))(this.client);
	this.case = new (require('./case'))(this.client);
	this.category = new (require('./category'))(this.client);
	this.categories = new (require('./categories'))(this.client);
	this.comment = new (require('./comment'))(this.client);
	this.companies = new (require('./companies'))(this.client);
	this.company = new (require('./company'))(this.client);
	this.deal = new (require('./deal'))(this.client);
	this.deals = new (require('./deals'))(this.client);
	this.group = new (require('./group'))(this.client);
	this.groups = new (require('./groups'))(this.client);
	this.deletions = new (require('./deletions'))(this.client);
	this.membership = new (require('./membership'))(this.client);
	this.memberships = new (require('./memberships'))(this.client);
	this.party = new (require('./party'))(this.client);
	this.parties = new (require('./parties'))(this.client);
	this.people = new (require('./people'))(this.client);
	this.person = new (require('./person'))(this.client);
	this.note = new (require('./note'))(this.client);
	this.notes = new (require('./notes'))(this.client);
	this.subject_field = new (require('./subject_field'))(this.client);
	this.subject_fields = new (require('./subject_fields'))(this.client);
	this.task = new (require('./task'))(this.client);
	this.tasks = new (require('./tasks'))(this.client);
	this.user = new (require('./user'))(this.client);
	this.users = new (require('./users'))(this.client);
};

module.exports = highrise;
<|endoftext|>


<commit_before>'use strict';
var request = require('request');

const TASK_TYPES = [
  'categorization',
  'transcription',
  'comparison',
  'annotation',
  'polygonannotation',
  'lineannotation',
  'datacollection',
  'audiotranscription',
  'pointannotation',
  'cuboidannotation',
  'segmentannotation'
];
var SCALE_ENDPOINT = 'https://api.scale.com/v1/';
var DEFAULT_LIMIT = 100;
var DEFAULT_OFFSET = 0;

/**
 * A client object configured to make Scaleapi requests.
 * operations on a database as a user. The client object is
 * created by the {@link module:scaleapi.createClient} function.
 * @namespace ScaleClient
 */

/**
 * Creates a ScaleClient to make requests such as task creation, deletion,
 * or lookups. The constructor takes a configuration object with the following
 * named parameters.
 * @constructor
 * @param {string} apiKey- your Scale API key
 * @returns {ScaleClient} a client for making Scale requests
 */
function ScaleClient(apiKey) {
  if (!(this instanceof ScaleClient)) {
    return new ScaleClient(apiKey);
  }

  if (!apiKey) {
    throw new ScaleException('missing api key');
  }
  this.apiKey = apiKey;
}

/**
 * Fetches a task.
 * @method scaleapi.ScaleClient#fetchTask
 * @param {string} taskId - the task id
 * @param {function} cb - callback called with (err, task)
 */
ScaleClient.prototype.fetchTask = function(taskId, cb) {
  getrequest('task/' + taskId, this.apiKey, {}, (err, json) => {
    cb && cb(err, new Task(this, json));
  });
};

/**
 * Cancels a task.
 * @method scaleapi.ScaleClient#cancelTask
 * @param {string} taskId - the task id
 * @param {function} cb - callback called with (err, task)
 */
ScaleClient.prototype.cancelTask = function(taskId, cb) {
  postrequest('task/' + taskId + '/cancel', this.apiKey, {}, (err, json) => {
    cb && cb(err, new Task(this, json));
  });
};

/**
 * Fetches a list of tasks. Takes a set of parameters, and a callback function.
 * Callback is called with a list of tasks, which also has properties
 * tasks.total (number of tasks retrieved), tasks.limit, tasks.offset,
 * tasks.hasMore (whether or not there are more tasks)
 *
 * Returns up to 100 at a time, use offset to paginate tasks and fetch more.
 *
 * @method scaleapi.ScaleClient#tasks
 * @param {Object} params - task retrieval parameters
 * @param {string} params.start_time - ISO date representing beginning of date range
 * @param {string} params.end_time - ISO date representing end of date range
 * @param {string} params.status - fetch only tasks with status: 'completed', 'pending', or 'canceled'
 * @param {string} params.type - fetch only tasks of this type
 * @param {string} params.project - fetch only tasks of this project
 * @param {string} params.batch - fetch only tasks of this batch
 * @param {Number} params.limit - max number of results
 * @param {Number} params.offset - number of results to skip
 * @param {function} cb - callback called with (err, tasks)
 */
ScaleClient.prototype.tasks = function(params, cb) {
  var allowedKwargs = ['start_time', 'end_time', 'status', 'type', 'project', 'batch', 'limit', 'offset'];
  Object.keys(params).forEach(property => {
    if (allowedKwargs.indexOf(property) < 0) {
      cb && cb(
        new ScaleInvalidRequest('Illegal parameter ' + property + ' for ScaleClient.tasks')
      );
    }
  });
  if (allowedKwargs.limit === undefined) {
    allowedKwargs.limit = DEFAULT_LIMIT;
  }
  if (allowedKwargs.offset === undefined) {
    allowedKwargs.offset = DEFAULT_OFFSET;
  }
  getrequest('tasks', this.apiKey, params, (err, json) => {
    if (err) {
      cb && cb(err);
      return;
    }
    json.docs = json.docs.map(json => new Task(this, json));
    cb && cb(err, json);
  });
};

ScaleClient.prototype.createTask = function(taskType, params, cb) {
  let endpoint = `task/${taskType}`;
  return postrequest(endpoint, this.apiKey, params, (err, json) => {
    if (err) {
      cb && cb(err);
      return;
    }
    cb && cb(err, new Task(this, json));
  });
}

TASK_TYPES.forEach(function(taskType) {
  ScaleClient.prototype['create' + capitalizeFirstLetter(taskType) + 'Task'] = function(params, cb) {
    return this.createTask(taskType, params, cb);
  };
});

/**
 * A task object, containing task information.
 * @namespace Task
 */
function Task(client, json) {
  this.client = client;
  this.id = json['task_id'];
  Object.assign(this, json);
}

/**
 * Refreshes a task, updating its information..
 *
 * @method scaleapi.Task#refresh
 * @param {function} cb - callback called with (err, updatedTask)
 */
Task.prototype.refresh = function(cb) {
  this.client.fetchTask(this.id, (err, task) => {
    if (err) {
      cb && cb(err);
      return;
    }
    Object.assign(this, task);
    cb && cb(null, this);
  });
};

/**
 * Cancels a task.
 *
 * @method scaleapi.Task#cancel
 * @param {function} cb - callback called with (err, canceledTask)
 */
Task.prototype.cancel = function(cb) {
  this.client.cancelTask(this.id, cb);
};

function getrequest(endpoint, apiKey, params, cb) {
  request.get({
    url: SCALE_ENDPOINT + endpoint,
    qs: params,
    json: true,
    auth: {
      user: apiKey,
      pass: '',
      sendImmediately: true
    }
  },
  function(error, response, body) {
    var err = null;
    if (error || response.statusCode !== 200) {
      err = new ScaleException(body && body['error'], response.statusCode);
    }
    cb && cb(err, body);
  });
}

function postrequest(endpoint, apiKey, payload, cb) {
  request.post({
    url: SCALE_ENDPOINT + endpoint,
    json: payload,
    auth: {
      user: apiKey,
      pass: '',
      sendImmediately: true
    }
  }, function(error, response, body) {
    try {
      var err = null;
      if (error || response.statusCode != 200) {
        err = new ScaleException(body && body['error'], response.statusCode);
      }
      cb && cb(err, body);
    } catch (e) {
      cb && cb(e, body);
    }
  });
}

function capitalizeFirstLetter(str) {
  return str.substr(0,1).toUpperCase() + str.substr(1);
}

function ScaleException(message, errcode) {
  this.message = message;
  this.errcode = errcode;
}
ScaleException.prototype = Object.create(Error.prototype);
ScaleException.prototype.constructor = ScaleException;

function ScaleInvalidRequest(message) {
  ScaleException.call(this);
  this.message = message;
}
ScaleInvalidRequest.prototype = Object.create(ScaleException.prototype);
ScaleInvalidRequest.prototype.constructor = ScaleInvalidRequest;

module.exports = {
  ScaleClient: ScaleClient,
  ScaleException: ScaleException,
  ScaleInvalidRequest: ScaleInvalidRequest
};
<commit_msg>update params for task endpoint<commit_after>'use strict';
var request = require('request');

const TASK_TYPES = [
  'categorization',
  'transcription',
  'comparison',
  'annotation',
  'polygonannotation',
  'lineannotation',
  'datacollection',
  'audiotranscription',
  'pointannotation',
  'cuboidannotation',
  'segmentannotation'
];
var SCALE_ENDPOINT = 'https://api.scale.com/v1/';
var DEFAULT_LIMIT = 100;
var DEFAULT_OFFSET = 0;

/**
 * A client object configured to make Scaleapi requests.
 * operations on a database as a user. The client object is
 * created by the {@link module:scaleapi.createClient} function.
 * @namespace ScaleClient
 */

/**
 * Creates a ScaleClient to make requests such as task creation, deletion,
 * or lookups. The constructor takes a configuration object with the following
 * named parameters.
 * @constructor
 * @param {string} apiKey- your Scale API key
 * @returns {ScaleClient} a client for making Scale requests
 */
function ScaleClient(apiKey) {
  if (!(this instanceof ScaleClient)) {
    return new ScaleClient(apiKey);
  }

  if (!apiKey) {
    throw new ScaleException('missing api key');
  }
  this.apiKey = apiKey;
}

/**
 * Fetches a task.
 * @method scaleapi.ScaleClient#fetchTask
 * @param {string} taskId - the task id
 * @param {function} cb - callback called with (err, task)
 */
ScaleClient.prototype.fetchTask = function(taskId, cb) {
  getrequest('task/' + taskId, this.apiKey, {}, (err, json) => {
    cb && cb(err, new Task(this, json));
  });
};

/**
 * Cancels a task.
 * @method scaleapi.ScaleClient#cancelTask
 * @param {string} taskId - the task id
 * @param {function} cb - callback called with (err, task)
 */
ScaleClient.prototype.cancelTask = function(taskId, cb) {
  postrequest('task/' + taskId + '/cancel', this.apiKey, {}, (err, json) => {
    cb && cb(err, new Task(this, json));
  });
};

/**
 * Fetches a list of tasks. Takes a set of parameters, and a callback function.
 * Callback is called with a list of tasks, which also has properties
 * tasks.total (number of tasks retrieved), tasks.limit, tasks.offset,
 * tasks.hasMore (whether or not there are more tasks)
 *
 * Returns up to 100 at a time, use offset to paginate tasks and fetch more.
 *
 * @method scaleapi.ScaleClient#tasks
 * @param {Object} params - task retrieval parameters
 * @param {string} params.start_time - ISO date representing beginning of creation date range
 * @param {string} params.end_time - ISO date representing end of creation date range
 * @param {string} params.completed_after - ISO date representing beginning of completion date range
 * @param {string} params.completed_before - ISO date representing end of completion date range
 * @param {string} params.status - fetch only tasks with status: 'completed', 'pending', or 'canceled'
 * @param {string} params.type - fetch only tasks of this type
 * @param {string} params.project - fetch only tasks of this project
 * @param {string} params.batch - fetch only tasks of this batch
 * @param {Number} params.limit - max number of results
 * @param {Number} params.offset - number of results to skip
 * @param {function} cb - callback called with (err, tasks)
 */
ScaleClient.prototype.tasks = function(params, cb) {
  var allowedKwargs = ['start_time', 'end_time', 'status', 'type', 'project', 'batch', 'limit', 'offset', 'completed_after', 'completed_before'];
  Object.keys(params).forEach(property => {
    if (allowedKwargs.indexOf(property) < 0) {
      cb && cb(
        new ScaleInvalidRequest('Illegal parameter ' + property + ' for ScaleClient.tasks')
      );
    }
  });
  if (allowedKwargs.limit === undefined) {
    allowedKwargs.limit = DEFAULT_LIMIT;
  }
  if (allowedKwargs.offset === undefined) {
    allowedKwargs.offset = DEFAULT_OFFSET;
  }
  getrequest('tasks', this.apiKey, params, (err, json) => {
    if (err) {
      cb && cb(err);
      return;
    }
    json.docs = json.docs.map(json => new Task(this, json));
    cb && cb(err, json);
  });
};

ScaleClient.prototype.createTask = function(taskType, params, cb) {
  let endpoint = `task/${taskType}`;
  return postrequest(endpoint, this.apiKey, params, (err, json) => {
    if (err) {
      cb && cb(err);
      return;
    }
    cb && cb(err, new Task(this, json));
  });
}

TASK_TYPES.forEach(function(taskType) {
  ScaleClient.prototype['create' + capitalizeFirstLetter(taskType) + 'Task'] = function(params, cb) {
    return this.createTask(taskType, params, cb);
  };
});

/**
 * A task object, containing task information.
 * @namespace Task
 */
function Task(client, json) {
  this.client = client;
  this.id = json['task_id'];
  Object.assign(this, json);
}

/**
 * Refreshes a task, updating its information..
 *
 * @method scaleapi.Task#refresh
 * @param {function} cb - callback called with (err, updatedTask)
 */
Task.prototype.refresh = function(cb) {
  this.client.fetchTask(this.id, (err, task) => {
    if (err) {
      cb && cb(err);
      return;
    }
    Object.assign(this, task);
    cb && cb(null, this);
  });
};

/**
 * Cancels a task.
 *
 * @method scaleapi.Task#cancel
 * @param {function} cb - callback called with (err, canceledTask)
 */
Task.prototype.cancel = function(cb) {
  this.client.cancelTask(this.id, cb);
};

function getrequest(endpoint, apiKey, params, cb) {
  request.get({
    url: SCALE_ENDPOINT + endpoint,
    qs: params,
    json: true,
    auth: {
      user: apiKey,
      pass: '',
      sendImmediately: true
    }
  },
  function(error, response, body) {
    var err = null;
    if (error || response.statusCode !== 200) {
      err = new ScaleException(body && body['error'], response.statusCode);
    }
    cb && cb(err, body);
  });
}

function postrequest(endpoint, apiKey, payload, cb) {
  request.post({
    url: SCALE_ENDPOINT + endpoint,
    json: payload,
    auth: {
      user: apiKey,
      pass: '',
      sendImmediately: true
    }
  }, function(error, response, body) {
    try {
      var err = null;
      if (error || response.statusCode != 200) {
        err = new ScaleException(body && body['error'], response.statusCode);
      }
      cb && cb(err, body);
    } catch (e) {
      cb && cb(e, body);
    }
  });
}

function capitalizeFirstLetter(str) {
  return str.substr(0,1).toUpperCase() + str.substr(1);
}

function ScaleException(message, errcode) {
  this.message = message;
  this.errcode = errcode;
}
ScaleException.prototype = Object.create(Error.prototype);
ScaleException.prototype.constructor = ScaleException;

function ScaleInvalidRequest(message) {
  ScaleException.call(this);
  this.message = message;
}
ScaleInvalidRequest.prototype = Object.create(ScaleException.prototype);
ScaleInvalidRequest.prototype.constructor = ScaleInvalidRequest;

module.exports = {
  ScaleClient: ScaleClient,
  ScaleException: ScaleException,
  ScaleInvalidRequest: ScaleInvalidRequest
};
<|endoftext|>


<commit_before>// if node
var Stream = require('stream').Stream;
var EventEmitter = require('events').EventEmitter;
var BufferReadStream = require('streamers').BufferReadStream;
var WebSocket = require('ws');

var util = require('./util');
var BinaryStream = require('./stream').BinaryStream;

// end node

function BinaryClient(socket, options) {
  if (!(this instanceof BinaryClient)) return new BinaryClient(socket, options);

  EventEmitter.call(this);

  var self = this;

  this._options = util.extend({
    chunkSize: 40960
  }, options);

  this.streams = {};

  if(typeof socket === 'string') {
    this._nextId = 0;
    this._socket = new WebSocket(socket);
  } else {
    // Use odd numbered ids for server originated streams
    this._nextId = 1;
    this._socket = socket;
  }

  //this._socket.binaryType = 'arraybuffer';

  this._socket.addEventListener('open', function(){
    self.emit('open');
  });
  this._socket.addEventListener('ping', function(data, flags){
    self.emit('ping', data, flags);
  });
  this._socket.addEventListener('pong', function(data, flags){
    self.emit('pong', data, flags);
  });
  // if node
  this._socket.on('drain', function(){
    var ids = Object.keys(self.streams);
    for (var i = 0, ii = ids.length; i < ii; i++) {
      self.streams[ids[i]]._onDrain();
    }
  });
  // end node
  this._socket.addEventListener('error', function(error){
    var ids = Object.keys(self.streams);
    for (var i = 0, ii = ids.length; i < ii; i++) {
      self.streams[ids[i]]._onError(error);
    }
    self.emit('error', error);
  });
  this._socket.addEventListener('close', function(code, message){
    var ids = Object.keys(self.streams);
    for (var i = 0, ii = ids.length; i < ii; i++) {
      self.streams[ids[i]]._onClose();
    }
    self.emit('close', code, message);
  });
  this._socket.addEventListener('message', function(data, flags){
    self.lastActive = Date.now();
    util.setZeroTimeout(function(){

      // Message format
      // [type, payload, bonus ]
      //
      // Reserved
      // [ 0  , X , X ]
      //
      //
      // New stream
      // [ 1  , Meta , new streamId ]
      //
      //
      // Data
      // [ 2  , Data , streamId ]
      //
      //
      // Pause
      // [ 3  , null , streamId ]
      //
      //
      // Resume
      // [ 4  , null , streamId ]
      //
      //
      // End
      // [ 5  , null , streamId ]
      //
      //
      // Close
      // [ 6  , null , streamId ]
      //
      // 7
      // [ 7  , Notification , streamId ]
      //
      // 8
      // [ 8  , Message ]
      //

      data = data.data;

      try {
          data = util.unpack(data);
      } catch (ex) {
          return self.emit('error', new Error('Received unparsable message: ' + ex));
      }
      if (!(data instanceof Array))
          return self.emit('error', new Error('Received non-array message'));
      if (data.length != 3)
          return self.emit('error', new Error('Received message with wrong part count: ' + data.length));
      if ('number' != typeof data[0])
          return self.emit('error', new Error('Received message with non-number type: ' + data[0]));

      switch(data[0]) {
        case 0:
          // Reserved
          break;
        case 1:
          var meta = data[1];
          var streamId = data[2];
          var binaryStream = self._receiveStream(streamId);
          self.emit('stream', binaryStream, meta);
          break;
        case 2:
          var payload = data[1];
          var streamId = data[2];
          var binaryStream = self.streams[streamId];
          if(binaryStream) {
            binaryStream._onData(payload);
          } else {
            self.emit('warn', new Error('Received `data` message for unknown stream: ' + streamId));
          }
          break;
        case 3:
          var streamId = data[2];
          var binaryStream = self.streams[streamId];
          if(binaryStream) {
            binaryStream._onPause();
          } else {
            self.emit('warn', new Error('Received `pause` message for unknown stream: ' + streamId));
          }
          break;
        case 4:
          var streamId = data[2];
          var binaryStream = self.streams[streamId];
          if(binaryStream) {
            binaryStream._onResume();
          } else {
            self.emit('error', new Error('Received `resume` message for unknown stream: ' + streamId));
          }
          break;
        case 5:
          var streamId = data[2];
          var binaryStream = self.streams[streamId];
          if(binaryStream) {
            binaryStream._onEnd();
          } else {
            self.emit('warn', new Error('Received `end` message for unknown stream: ' + streamId));
          }
          break;
        case 6:
          var streamId = data[2];
          var binaryStream = self.streams[streamId];
          if(binaryStream) {
            binaryStream._onClose();
          } else {
            self.emit('warn', new Error('Received `close` message for unknown stream: ' + streamId));
          }
          break;
        case 7:
          var streamId = data[2];
          var binaryStream = self.streams[streamId];
          if(binaryStream) {
            var event = data[1];
            binaryStream._onNotification(event);
          } else {
            self.emit('warn', new Error('Received `notification` message for unknown stream: ' + streamId));
          }
          break;
        case 8:
          var message = data[1];
          self.emit('message', message);
          break;
        default:
          self.emit('warn', new Error('Unrecognized message type received: ' + data[0]));
      }
    });
  });
}

util.inherits(BinaryClient, EventEmitter);

BinaryClient.prototype.ping = function(data){
  return this._socket.ping(data, {}, true);
}

BinaryClient.prototype.pong = function(data){
  return this._socket.pong(data, {}, true);
}

BinaryClient.prototype.sendMessage = function(message){
  var data = util.pack([8, message, 0]);
  return this._socket.send(data, {binary: true});
}

BinaryClient.prototype.send = function(data, meta){
  var stream = this.createStream(meta);
  if(data instanceof Stream) {
    data.pipe(stream);
  } else if (util.isNode === true) {
    if(Buffer.isBuffer(data)) {
      (new BufferReadStream(data, {chunkSize: this._options.chunkSize})).pipe(stream);
    } else {
      stream.write(data);
    }
  } else if (util.isNode !== true) {
    if(data.constructor == Blob || data.constructor == File) {
      (new BlobReadStream(data, {chunkSize: this._options.chunkSize})).pipe(stream);
    } else if (data.constructor == ArrayBuffer) {
      var blob;
      if(binaryFeatures.useArrayBufferView) {
        data = new Uint8Array(data);
      }
      if(binaryFeatures.useBlobBuilder) {
        var builder = new BlobBuilder();
        builder.append(data);
        blob = builder.getBlob()
      } else {
        blob = new Blob([data]);
      }
      (new BlobReadStream(blob, {chunkSize: this._options.chunkSize})).pipe(stream);
    } else if (typeof data === 'object' && 'BYTES_PER_ELEMENT' in data) {
      var blob;
      if(!binaryFeatures.useArrayBufferView) {
        // Warn
        data = data.buffer;
      }
      if(binaryFeatures.useBlobBuilder) {
        var builder = new BlobBuilder();
        builder.append(data);
        blob = builder.getBlob()
      } else {
        blob = new Blob([data]);
      }
      (new BlobReadStream(blob, {chunkSize: this._options.chunkSize})).pipe(stream);
    } else {
      stream.write(data);
    }
  }
  return stream;
};

BinaryClient.prototype._receiveStream = function(streamId){
  var self = this;
  var binaryStream = new BinaryStream(this._socket, streamId, false);
  binaryStream.on('close', function(){
    delete self.streams[streamId];
  });
  this.streams[streamId] = binaryStream;
  return binaryStream;
};

BinaryClient.prototype.createStream = function(meta){
  if(this._socket.readyState !== WebSocket.OPEN) {
    throw new Error('Client is not yet connected or has closed');
    return;
  }
  var self = this;
  var streamId = this._nextId;
  this._nextId += 2;
  var binaryStream = new BinaryStream(this._socket, streamId, true, meta);
  binaryStream.on('close', function(){
    delete self.streams[streamId];
  });
  this.streams[streamId] = binaryStream;
  return binaryStream;
};

BinaryClient.prototype.close = BinaryClient.prototype.destroy = function() {
  this._socket.close();
};

exports.BinaryClient = BinaryClient;
<commit_msg>Make unkown stream warning<commit_after>// if node
var Stream = require('stream').Stream;
var EventEmitter = require('events').EventEmitter;
var BufferReadStream = require('streamers').BufferReadStream;
var WebSocket = require('ws');

var util = require('./util');
var BinaryStream = require('./stream').BinaryStream;

// end node

function BinaryClient(socket, options) {
  if (!(this instanceof BinaryClient)) return new BinaryClient(socket, options);

  EventEmitter.call(this);

  var self = this;

  this._options = util.extend({
    chunkSize: 40960
  }, options);

  this.streams = {};

  if(typeof socket === 'string') {
    this._nextId = 0;
    this._socket = new WebSocket(socket);
  } else {
    // Use odd numbered ids for server originated streams
    this._nextId = 1;
    this._socket = socket;
  }

  //this._socket.binaryType = 'arraybuffer';

  this._socket.addEventListener('open', function(){
    self.emit('open');
  });
  this._socket.addEventListener('ping', function(data, flags){
    self.emit('ping', data, flags);
  });
  this._socket.addEventListener('pong', function(data, flags){
    self.emit('pong', data, flags);
  });
  // if node
  this._socket.on('drain', function(){
    var ids = Object.keys(self.streams);
    for (var i = 0, ii = ids.length; i < ii; i++) {
      self.streams[ids[i]]._onDrain();
    }
  });
  // end node
  this._socket.addEventListener('error', function(error){
    var ids = Object.keys(self.streams);
    for (var i = 0, ii = ids.length; i < ii; i++) {
      self.streams[ids[i]]._onError(error);
    }
    self.emit('error', error);
  });
  this._socket.addEventListener('close', function(code, message){
    var ids = Object.keys(self.streams);
    for (var i = 0, ii = ids.length; i < ii; i++) {
      self.streams[ids[i]]._onClose();
    }
    self.emit('close', code, message);
  });
  this._socket.addEventListener('message', function(data, flags){
    self.lastActive = Date.now();
    util.setZeroTimeout(function(){

      // Message format
      // [type, payload, bonus ]
      //
      // Reserved
      // [ 0  , X , X ]
      //
      //
      // New stream
      // [ 1  , Meta , new streamId ]
      //
      //
      // Data
      // [ 2  , Data , streamId ]
      //
      //
      // Pause
      // [ 3  , null , streamId ]
      //
      //
      // Resume
      // [ 4  , null , streamId ]
      //
      //
      // End
      // [ 5  , null , streamId ]
      //
      //
      // Close
      // [ 6  , null , streamId ]
      //
      // 7
      // [ 7  , Notification , streamId ]
      //
      // 8
      // [ 8  , Message ]
      //

      data = data.data;

      try {
          data = util.unpack(data);
      } catch (ex) {
          return self.emit('error', new Error('Received unparsable message: ' + ex));
      }
      if (!(data instanceof Array))
          return self.emit('error', new Error('Received non-array message'));
      if (data.length != 3)
          return self.emit('error', new Error('Received message with wrong part count: ' + data.length));
      if ('number' != typeof data[0])
          return self.emit('error', new Error('Received message with non-number type: ' + data[0]));

      switch(data[0]) {
        case 0:
          // Reserved
          break;
        case 1:
          var meta = data[1];
          var streamId = data[2];
          var binaryStream = self._receiveStream(streamId);
          self.emit('stream', binaryStream, meta);
          break;
        case 2:
          var payload = data[1];
          var streamId = data[2];
          var binaryStream = self.streams[streamId];
          if(binaryStream) {
            binaryStream._onData(payload);
          } else {
            self.emit('warn', new Error('Received `data` message for unknown stream: ' + streamId));
          }
          break;
        case 3:
          var streamId = data[2];
          var binaryStream = self.streams[streamId];
          if(binaryStream) {
            binaryStream._onPause();
          } else {
            self.emit('warn', new Error('Received `pause` message for unknown stream: ' + streamId));
          }
          break;
        case 4:
          var streamId = data[2];
          var binaryStream = self.streams[streamId];
          if(binaryStream) {
            binaryStream._onResume();
          } else {
            self.emit('warn', new Error('Received `resume` message for unknown stream: ' + streamId));
          }
          break;
        case 5:
          var streamId = data[2];
          var binaryStream = self.streams[streamId];
          if(binaryStream) {
            binaryStream._onEnd();
          } else {
            self.emit('warn', new Error('Received `end` message for unknown stream: ' + streamId));
          }
          break;
        case 6:
          var streamId = data[2];
          var binaryStream = self.streams[streamId];
          if(binaryStream) {
            binaryStream._onClose();
          } else {
            self.emit('warn', new Error('Received `close` message for unknown stream: ' + streamId));
          }
          break;
        case 7:
          var streamId = data[2];
          var binaryStream = self.streams[streamId];
          if(binaryStream) {
            var event = data[1];
            binaryStream._onNotification(event);
          } else {
            self.emit('warn', new Error('Received `notification` message for unknown stream: ' + streamId));
          }
          break;
        case 8:
          var message = data[1];
          self.emit('message', message);
          break;
        default:
          self.emit('warn', new Error('Unrecognized message type received: ' + data[0]));
      }
    });
  });
}

util.inherits(BinaryClient, EventEmitter);

BinaryClient.prototype.ping = function(data){
  return this._socket.ping(data, {}, true);
}

BinaryClient.prototype.pong = function(data){
  return this._socket.pong(data, {}, true);
}

BinaryClient.prototype.sendMessage = function(message){
  var data = util.pack([8, message, 0]);
  return this._socket.send(data, {binary: true});
}

BinaryClient.prototype.send = function(data, meta){
  var stream = this.createStream(meta);
  if(data instanceof Stream) {
    data.pipe(stream);
  } else if (util.isNode === true) {
    if(Buffer.isBuffer(data)) {
      (new BufferReadStream(data, {chunkSize: this._options.chunkSize})).pipe(stream);
    } else {
      stream.write(data);
    }
  } else if (util.isNode !== true) {
    if(data.constructor == Blob || data.constructor == File) {
      (new BlobReadStream(data, {chunkSize: this._options.chunkSize})).pipe(stream);
    } else if (data.constructor == ArrayBuffer) {
      var blob;
      if(binaryFeatures.useArrayBufferView) {
        data = new Uint8Array(data);
      }
      if(binaryFeatures.useBlobBuilder) {
        var builder = new BlobBuilder();
        builder.append(data);
        blob = builder.getBlob()
      } else {
        blob = new Blob([data]);
      }
      (new BlobReadStream(blob, {chunkSize: this._options.chunkSize})).pipe(stream);
    } else if (typeof data === 'object' && 'BYTES_PER_ELEMENT' in data) {
      var blob;
      if(!binaryFeatures.useArrayBufferView) {
        // Warn
        data = data.buffer;
      }
      if(binaryFeatures.useBlobBuilder) {
        var builder = new BlobBuilder();
        builder.append(data);
        blob = builder.getBlob()
      } else {
        blob = new Blob([data]);
      }
      (new BlobReadStream(blob, {chunkSize: this._options.chunkSize})).pipe(stream);
    } else {
      stream.write(data);
    }
  }
  return stream;
};

BinaryClient.prototype._receiveStream = function(streamId){
  var self = this;
  var binaryStream = new BinaryStream(this._socket, streamId, false);
  binaryStream.on('close', function(){
    delete self.streams[streamId];
  });
  this.streams[streamId] = binaryStream;
  return binaryStream;
};

BinaryClient.prototype.createStream = function(meta){
  if(this._socket.readyState !== WebSocket.OPEN) {
    throw new Error('Client is not yet connected or has closed');
    return;
  }
  var self = this;
  var streamId = this._nextId;
  this._nextId += 2;
  var binaryStream = new BinaryStream(this._socket, streamId, true, meta);
  binaryStream.on('close', function(){
    delete self.streams[streamId];
  });
  this.streams[streamId] = binaryStream;
  return binaryStream;
};

BinaryClient.prototype.close = BinaryClient.prototype.destroy = function() {
  this._socket.close();
};

exports.BinaryClient = BinaryClient;
<|endoftext|>


<commit_before>const event = require('./event');
const recorder = require('./recorder');
const assertThrown = require('./assert/throws');
const { getParamNames, isAsyncFunction } = require('./utils');

const injectHook = function (inject, suite) {
  try {
    inject();
  } catch (err) {
    recorder.throw(err);
  }
  recorder.catch((err) => {
    event.emit(event.test.failed, suite, err);
    throw err;
  });
  return recorder.promise();
};

/**
 * Wraps test function, injects support objects from container,
 * starts promise chain with recorder, performs before/after hooks
 * through event system.
 */
module.exports.test = (test) => {
  const testFn = test.fn;
  if (!testFn) {
    return test;
  }

  test.steps = [];
  test.timeout(0);
  test.async = true;

  test.fn = function (done) {
    recorder.errHandler((err) => {
      recorder.session.start('teardown');
      recorder.cleanAsyncErr();
      if (test.throws) { // check that test should actually fail
        try {
          assertThrown(err, test.throws);
          event.emit(event.test.passed, test);
          event.emit(event.test.finished, test);
          recorder.add(() => done());
          return;
        } catch (newErr) {
          err = newErr;
        }
      }
      event.emit(event.test.failed, test, err);
      event.emit(event.test.finished, test);
      recorder.add(() => done(err));
    });

    if (isAsyncFunction(testFn)) {
      event.emit(event.test.started, test);
      testFn.apply(test, getInjectedArguments(testFn, test)).then((res) => {
        recorder.add('fire test.passed', () => {
          event.emit(event.test.passed, test);
          event.emit(event.test.finished, test);
        });
        recorder.add('finish test', () => done());
        recorder.catch();
      }).catch((e) => {
        recorder.throw(e);
        recorder.catch((e) => {
          const err = (recorder.getAsyncErr() === null) ? e : recorder.getAsyncErr();
          recorder.session.start('teardown');
          recorder.cleanAsyncErr();
          event.emit(event.test.failed, test, err);
          event.emit(event.test.finished, test);
          recorder.add(() => done(err));
        });
      });
      return;
    }
    try {
      event.emit(event.test.started, test);
      testFn.apply(test, getInjectedArguments(testFn, test));
    } catch (err) {
      recorder.throw(err);
    } finally {
      recorder.add('fire test.passed', () => {
        event.emit(event.test.passed, test);
        event.emit(event.test.finished, test);
      });
      recorder.add('finish test', () => done());
      recorder.catch();
    }
  };
  return test;
};

/**
 * Injects arguments to function from controller
 */
module.exports.injected = function (fn, suite, hookName) {
  return function (done) {
    recorder.errHandler((err) => {
      recorder.session.start('teardown');
      recorder.cleanAsyncErr();
      event.emit(event.test.failed, suite, err);
      if (hookName === 'after') event.emit(event.test.after, suite);
      if (hookName === 'afterSuite') event.emit(event.suite.after, suite);
      recorder.add(() => done(err));
    });

    if (!fn) throw new Error('fn is not defined');

    if (isAsyncFunction(fn)) {
      event.emit(event.hook.started, suite);
      recorder.startUnlessRunning();
      this.test.body = fn.toString();
      fn.apply(this, getInjectedArguments(fn)).then(() => {
        recorder.add('fire hook.passed', () => event.emit(event.hook.passed, suite));
        recorder.add(`finish ${hookName} hook`, () => done());
        recorder.catch();
      }).catch((e) => {
        recorder.throw(e);
        recorder.catch((e) => {
          const err = (recorder.getAsyncErr() === null) ? e : recorder.getAsyncErr();
          recorder.session.start('teardown');
          recorder.cleanAsyncErr();
          event.emit(event.test.failed, suite, err);
          if (hookName === 'after') event.emit(event.test.after, suite);
          if (hookName === 'afterSuite') event.emit(event.suite.after, suite);
          recorder.add(() => done(err));
        });
      });
      return;
    }

    try {
      event.emit(event.hook.started, suite);
      recorder.startUnlessRunning();
      this.test.body = fn.toString();
      const res = fn.apply(this, getInjectedArguments(fn));
    } catch (err) {
      recorder.throw(err);
    } finally {
      recorder.add('fire hook.passed', () => event.emit(event.hook.passed, suite));
      recorder.add(`finish ${hookName} hook`, () => done());
      recorder.catch();
    }
  };
};

/**
 * Starts promise chain, so helpers could enqueue their hooks
 */
module.exports.setup = function (suite) {
  return injectHook(() => {
    recorder.startUnlessRunning();
    event.emit(event.test.before, suite && suite.ctx && suite.ctx.currentTest);
  }, suite);
};

module.exports.teardown = function (suite) {
  return injectHook(() => {
    recorder.startUnlessRunning();
    event.emit(event.test.after, suite && suite.ctx && suite.ctx.currentTest);
  }, suite);
};

module.exports.suiteSetup = function (suite) {
  return injectHook(() => {
    recorder.startUnlessRunning();
    event.emit(event.suite.before, suite);
  }, suite);
};

module.exports.suiteTeardown = function (suite) {
  return injectHook(() => {
    recorder.startUnlessRunning();
    event.emit(event.suite.after, suite);
  }, suite);
};

const getInjectedArguments = (fn, test) => {
  const container = require('./container');
  const testArguments = [];
  const params = getParamNames(fn) || [];
  const objects = container.support();
  for (const key in params) {
    const obj = params[key];
    if (test && test.inject && test.inject[obj]) {
      testArguments.push(test.inject[obj]);
      continue;
    }
    if (!objects[obj]) {
      throw new Error(`Object of type ${obj} is not defined in container`);
    }
    testArguments.push(container.support(obj));
  }
  return testArguments;
};

module.exports.getInjectedArguments = getInjectedArguments;
<commit_msg>Fix issue 1161 (#1721)<commit_after>const event = require('./event');
const recorder = require('./recorder');
const assertThrown = require('./assert/throws');
const { getParamNames, isAsyncFunction } = require('./utils');

const injectHook = function (inject, suite) {
  try {
    inject();
  } catch (err) {
    recorder.throw(err);
  }
  recorder.catch((err) => {
    event.emit(event.test.failed, suite, err);
    throw err;
  });
  return recorder.promise();
};

/**
 * Wraps test function, injects support objects from container,
 * starts promise chain with recorder, performs before/after hooks
 * through event system.
 */
module.exports.test = (test) => {
  const testFn = test.fn;
  if (!testFn) {
    return test;
  }

  test.steps = [];
  test.timeout(0);
  test.async = true;

  test.fn = function (done) {
    recorder.errHandler((err) => {
      recorder.session.start('teardown');
      recorder.cleanAsyncErr();
      if (test.throws) { // check that test should actually fail
        try {
          assertThrown(err, test.throws);
          event.emit(event.test.passed, test);
          event.emit(event.test.finished, test);
          recorder.add(() => done());
          return;
        } catch (newErr) {
          err = newErr;
        }
      }
      event.emit(event.test.failed, test, err);
      event.emit(event.test.finished, test);
      recorder.add(() => done(err));
    });

    if (isAsyncFunction(testFn)) {
      event.emit(event.test.started, test);
      testFn.apply(test, getInjectedArguments(testFn, test)).then((res) => {
        recorder.add('fire test.passed', () => {
          event.emit(event.test.passed, test);
          event.emit(event.test.finished, test);
        });
        recorder.add('finish test', () => done());
        recorder.catch();
      }).catch((e) => {
        recorder.throw(e);
        recorder.catch((e) => {
          const err = (recorder.getAsyncErr() === null) ? e : recorder.getAsyncErr();
          recorder.session.start('teardown');
          recorder.cleanAsyncErr();
          event.emit(event.test.failed, test, err);
          event.emit(event.test.finished, test);
          recorder.add(() => done(err));
        });
      });
      return;
    }
    try {
      event.emit(event.test.started, test);
      testFn.apply(test, getInjectedArguments(testFn, test));
    } catch (err) {
      recorder.throw(err);
    } finally {
      recorder.add('fire test.passed', () => {
        event.emit(event.test.passed, test);
        event.emit(event.test.finished, test);
      });
      recorder.add('finish test', () => done());
      recorder.catch();
    }
  };
  return test;
};

/**
 * Injects arguments to function from controller
 */
module.exports.injected = function (fn, suite, hookName) {
  return function (done) {

    const errHandler = (err) => {
      recorder.session.start('teardown');
      recorder.cleanAsyncErr();
      event.emit(event.test.failed, suite, err);
      if (hookName === 'after') event.emit(event.test.after, suite);
      if (hookName === 'afterSuite') event.emit(event.suite.after, suite);
      recorder.add(() => done(err));
    };

    recorder.errHandler((err) => {
      errHandler(err);
    });

    if (!fn) throw new Error('fn is not defined');

      event.emit(event.hook.started, suite);
    if (!recorder.isRunning()) {
      recorder.start();
      recorder.errHandler((err) => {
        errHandler(err);
      });
    }

      this.test.body = fn.toString();

    if (isAsyncFunction(fn)) {
      fn.apply(this, getInjectedArguments(fn)).then(() => {
        recorder.add('fire hook.passed', () => event.emit(event.hook.passed, suite));
        recorder.add(`finish ${hookName} hook`, () => done());
        recorder.catch();
      }).catch((e) => {
        recorder.throw(e);
        recorder.catch((e) => {
          const err = (recorder.getAsyncErr() === null) ? e : recorder.getAsyncErr();
          errHandler(err);
        });
      });
      return;
    }

    try {
      fn.apply(this, getInjectedArguments(fn));
      recorder.add('fire hook.passed', () => event.emit(event.hook.passed, suite));
      recorder.add(`finish ${hookName} hook`, () => done());
      recorder.catch();
    } catch (err) {
      recorder.throw(err);
      recorder.catch((e) => {
        const err = (recorder.getAsyncErr() === null) ? e : recorder.getAsyncErr();
        errHandler(err);
      });
    }
  };
};

/**
 * Starts promise chain, so helpers could enqueue their hooks
 */
module.exports.setup = function (suite) {
  return injectHook(() => {
    recorder.startUnlessRunning();
    event.emit(event.test.before, suite && suite.ctx && suite.ctx.currentTest);
  }, suite);
};

module.exports.teardown = function (suite) {
  return injectHook(() => {
    recorder.startUnlessRunning();
    event.emit(event.test.after, suite && suite.ctx && suite.ctx.currentTest);
  }, suite);
};

module.exports.suiteSetup = function (suite) {
  return injectHook(() => {
    recorder.startUnlessRunning();
    event.emit(event.suite.before, suite);
  }, suite);
};

module.exports.suiteTeardown = function (suite) {
  return injectHook(() => {
    recorder.startUnlessRunning();
    event.emit(event.suite.after, suite);
  }, suite);
};

const getInjectedArguments = (fn, test) => {
  const container = require('./container');
  const testArguments = [];
  const params = getParamNames(fn) || [];
  const objects = container.support();
  for (const key in params) {
    const obj = params[key];
    if (test && test.inject && test.inject[obj]) {
      testArguments.push(test.inject[obj]);
      continue;
    }
    if (!objects[obj]) {
      throw new Error(`Object of type ${obj} is not defined in container`);
    }
    testArguments.push(container.support(obj));
  }
  return testArguments;
};

module.exports.getInjectedArguments = getInjectedArguments;
<|endoftext|>