<commit_before>var net = require('net');
var http = require('http');
var extend = require('extend');
var LRU = require('lru-cache');
var { parse: parseUrl } = require('url');
var getServer = require('hagent').create(function() {
  return net.createServer({ pauseOnConnect: true });
}, 51500);
var formatHeaders = require('hparser').formatHeaders;
var common = require('../util/common');

var socketProto = net.Socket.prototype;
var originConnect = socketProto.connect;
var SPEC_HOST_RE = /.whistle-policy(?:-(internal|capture|tunnel|connect)(?:-([a-z\d]+))?)?$/;
var lru = new LRU({ max: 5120, maxAge: 30000 });
var PROXY_ID_HEADER;
var proxyIp;
var proxyPort;

function toNumber(x) {
  x = Number(x);
  return x >= 0 ? x : false;
}

function isPipeName(s) {
  return typeof s === 'string' && toNumber(s) === false;
}

function normalizeArgs(args) {
  if (args.length === 0) {
    return [{}, null];
  }

  var arg0 = args[0];
  if (Array.isArray(arg0)) {
    return arg0;
  }
  var options = {};
  if (typeof arg0 === 'object' && arg0 !== null) {
    // (options[...][, cb])
    options = arg0;
  } else if (isPipeName(arg0)) {
    // (path[...][, cb])
    options.path = arg0;
  } else {
    // ([port][, host][...][, cb])
    options.port = arg0;
    if (args.length > 1 && typeof args[1] === 'string') {
      options.host = args[1];
    }
  }

  var cb = args[args.length - 1];
  if (typeof cb !== 'function') {
    return [options, null];
  }
  return [options, cb];
}

function createSocket(opts, cb) {
  var done;
  var client;
  var headers = common.lowerCaseify(opts.headers);
  var handleCb = function(err, socket, res) {
    if (!done) {
      done = true;
      cb && cb(err, socket, res);
    }
    if (err && client) {
      client.destroy();
      client = null;
    }
  };
  if (opts.isHttp) {
    headers['x-whistle-policy'] = 'capture';
  } else if ( opts.isConnect) {
    headers['x-whistle-policy'] = 'connect';
  } else if (!headers['x-whistle-policy']) {
    headers['x-whistle-policy'] = 'tunnel';
  }
  if (opts.reqId && typeof opts.reqId === 'string') {
    headers['x-whistle-plugin-request-id'] = opts.reqId;
  }
  if (opts.isInternal) {
    headers[PROXY_ID_HEADER] = '1';
  }
  opts.path = opts.path || (opts.host + ':' + (opts.port || 80));
  headers.host = opts.path;
  var clientIp = common.removeIPV6Prefix(opts.clientIp);
  var clientPort = opts.clientPort;
  if (clientIp && net.isIP(clientIp)) {
    headers['x-forwarded-for'] = clientIp;
  }
  if (clientPort > 0 && clientPort < 65536) {
    headers['x-whistle-client-port'] = clientPort;
  }
  headers['x-whistle-request-tunnel-ack'] = '1';
  client = http.request({
    host: proxyIp,
    port: proxyPort,
    method: 'CONNECT',
    agent: false,
    path: opts.path,
    headers: headers
  });
  client.once('connect', function(res, socket) {
    socket.on('error', handleCb);
    if (res.statusCode !== 200) {
      var err = new Error('Tunneling socket could not be established, statusCode=' + res.statusCode);
      err.statusCode = res.statusCode;
      socket.destroy();
      return handleCb(err);
    }
    if (res.headers['x-whistle-allow-tunnel-ack']) {
      socket.write('1');
    }
    handleCb(null, socket, res);
  });
  client.on('error', handleCb);
  client.end();
}

module.exports = function(options, cb) {
  PROXY_ID_HEADER = options.PROXY_ID_HEADER;
  proxyIp = options.proxyIp;
  proxyPort = options.proxyPort;

  getServer(function(server, port) {
    var tempServerOpts = {
      host: '127.0.0.1',
      port: port
    };
    server.on('connection', function(socket) {
      var destroyed;
      var sock;
      var destroy = function() {
        if (!destroyed) {
          destroyed = true;
          socket.destroy();
          sock && sock.destroy();
        }
      };
      var handleProxy = function (connOpts) {
        createSocket(connOpts, function(err, sock) {
          if (err) {
            return destroy();
          }
          sock.on('error', destroy);
          socket.pipe(sock).pipe(socket);
          socket.resume();
        });
      };
      var key = `${socket.remotePort}:${port}`;
      var opts = lru.peek(key);
      if (opts) {
        lru.del(key);
        handleProxy(opts);
      } else {
        lru.set(key, handleProxy);
      }
    });
    var handleTempCache = function(socket, opts) {
      socket.once('connect', function() {
        var key = `${socket.localPort}:${port}`;
        var handler = lru.get(key);
        if (typeof handler === 'function') {
          lru.del(key);
          handler(opts);
        } else {
          lru.set(key, opts);
        }
      });
      return socket;
    };
    var connect = function(opts, cb) {
      var socket = net.connect(tempServerOpts, cb);
      handleTempCache(socket, opts);
      socket.on('error', common.noop);
      return socket;
    };
    var request = function(opts, cb) {
      if (typeof opts === 'string') {
        opts = { url: opts };
      } else {
        opts = extend({}, opts);
      }
      opts.url = common.setProtocol(opts.url);
      var uri = parseUrl(opts.url);
      var client;
      if (common.isConnect(uri)) {
        client = connect({
          host: uri.hostname,
          port: uri.port,
          headers: opts.proxyHeaders
        }, cb);
        client.isConnect = true;
        client.isTunnel = true;
        return client;
      }
      var protocol = uri.protocol;
      var isHttp = protocol === 'https:' || protocol === 'http:';
      var isWs = common.isWebSocket(uri, opts.headers);
      if (!isHttp && !isWs) {
        return cb && cb(new Error('Bad URL'));
      }

      var rawNames = {};
      var headers = common.lowerCaseify(opts.headers, rawNames);
      var isHttps = protocol === 'https:' || protocol === 'wss:';
      if (isWs) {
        headers.connection = 'Upgrade';
        headers.upgrade = 'websocket';
        rawNames.connection = 'Connection';
        rawNames.upgrade = 'Upgrade';
      }
      client = http.request({
        path: opts.url || '/',
        method: opts.method,
        agent: null,
        createConnection: function() {
          return connect({
            host: uri.host || 'localhost',
            port: uri.port || (isHttps ? 443 : 80),
            headers: opts.proxyHeaders,
            isHttp: true,
            isInternal: opts.isInternal,
            clientIp: opts.clientIp,
            clientPort: opts.clientPort
          });
        },
        headers: formatHeaders(headers, rawNames)
      }, cb);
      client.isHttps = isHttps;
      client.isHttp = isHttp;
      client.isWebSocket = isWs;
      return client;
    };
    socketProto.connect = function() {
      var args = normalizeArgs(arguments);
      var opts = args[0];
      var cb = args[1];
      if (!opts || !SPEC_HOST_RE.test(opts.host)) {
        return originConnect.apply(this, arguments);
      }
      var policy = RegExp.$1;
      var reqId = RegExp.$2;
      var host = opts.host.slice(0, -RegExp['$&'].length);
      originConnect.call(this, tempServerOpts, cb);
      handleTempCache(this, {
        host: host || 'localhost',
        port: opts.port,
        reqId: reqId,
        headers: opts.proxyHeaders,
        isInternal: policy === 'internal',
        isTunnel: !policy || policy === 'tunnel',
        isConnect: policy === 'connect',
        clientIp: opts.clientIp,
        clientPort: opts.clientPort
      });
      return this;
    };
    cb({
      connect: connect,
      request: request
    });
  });
};
<commit_msg>refactor: handle errors<commit_after>var net = require('net');
var http = require('http');
var extend = require('extend');
var LRU = require('lru-cache');
var { parse: parseUrl } = require('url');
var getServer = require('hagent').create(function() {
  return net.createServer({ pauseOnConnect: true });
}, 51500);
var formatHeaders = require('hparser').formatHeaders;
var common = require('../util/common');

var socketProto = net.Socket.prototype;
var originConnect = socketProto.connect;
var SPEC_HOST_RE = /.whistle-policy(?:-(internal|capture|tunnel|connect)(?:-([a-z\d]+))?)?$/;
var lru = new LRU({ max: 5120, maxAge: 30000 });
var PROXY_ID_HEADER;
var proxyIp;
var proxyPort;

function toNumber(x) {
  x = Number(x);
  return x >= 0 ? x : false;
}

function isPipeName(s) {
  return typeof s === 'string' && toNumber(s) === false;
}

function normalizeArgs(args) {
  if (args.length === 0) {
    return [{}, null];
  }

  var arg0 = args[0];
  if (Array.isArray(arg0)) {
    return arg0;
  }
  var options = {};
  if (typeof arg0 === 'object' && arg0 !== null) {
    // (options[...][, cb])
    options = arg0;
  } else if (isPipeName(arg0)) {
    // (path[...][, cb])
    options.path = arg0;
  } else {
    // ([port][, host][...][, cb])
    options.port = arg0;
    if (args.length > 1 && typeof args[1] === 'string') {
      options.host = args[1];
    }
  }

  var cb = args[args.length - 1];
  if (typeof cb !== 'function') {
    return [options, null];
  }
  return [options, cb];
}

function createSocket(opts, cb) {
  var done;
  var client;
  var headers = common.lowerCaseify(opts.headers);
  var handleCb = function(err, socket, res) {
    if (!done) {
      done = true;
      cb && cb(err, socket, res);
    }
    if (err && client) {
      client.destroy();
      client = null;
    }
  };
  if (opts.isHttp) {
    headers['x-whistle-policy'] = 'capture';
  } else if ( opts.isConnect) {
    headers['x-whistle-policy'] = 'connect';
  } else if (!headers['x-whistle-policy']) {
    headers['x-whistle-policy'] = 'tunnel';
  }
  if (opts.reqId && typeof opts.reqId === 'string') {
    headers['x-whistle-plugin-request-id'] = opts.reqId;
  }
  if (opts.isInternal) {
    headers[PROXY_ID_HEADER] = '1';
  }
  opts.path = opts.path || (opts.host + ':' + (opts.port || 80));
  headers.host = opts.path;
  var clientIp = common.removeIPV6Prefix(opts.clientIp);
  var clientPort = opts.clientPort;
  if (clientIp && net.isIP(clientIp)) {
    headers['x-forwarded-for'] = clientIp;
  }
  if (clientPort > 0 && clientPort < 65536) {
    headers['x-whistle-client-port'] = clientPort;
  }
  headers['x-whistle-request-tunnel-ack'] = '1';
  client = http.request({
    host: proxyIp,
    port: proxyPort,
    method: 'CONNECT',
    agent: false,
    path: opts.path,
    headers: headers
  });
  client.once('connect', function(res, socket) {
    socket.on('error', handleCb);
    if (res.statusCode !== 200) {
      var err = new Error('Tunneling socket could not be established, statusCode=' + res.statusCode);
      err.statusCode = res.statusCode;
      socket.destroy();
      return handleCb(err);
    }
    if (res.headers['x-whistle-allow-tunnel-ack']) {
      socket.write('1');
    }
    handleCb(null, socket, res);
  });
  client.on('error', handleCb);
  client.end();
}

module.exports = function(options, cb) {
  PROXY_ID_HEADER = options.PROXY_ID_HEADER;
  proxyIp = options.proxyIp;
  proxyPort = options.proxyPort;

  getServer(function(server, port) {
    var tempServerOpts = {
      host: '127.0.0.1',
      port: port
    };
    server.on('connection', function(socket) {
      var destroyed;
      var sock;
      var destroy = function() {
        if (!destroyed) {
          destroyed = true;
          socket.destroy();
          sock && sock.destroy();
        }
      };
      var handleProxy = function (connOpts) {
        createSocket(connOpts, function(err, sock) {
          if (err) {
            return destroy();
          }
          sock.on('error', destroy);
          socket.pipe(sock).pipe(socket);
          socket.resume();
        });
      };
      var key = `${socket.remotePort}:${port}`;
      var opts = lru.peek(key);
      if (opts) {
        lru.del(key);
        handleProxy(opts);
      } else {
        lru.set(key, handleProxy);
      }
    });
    var handleTempCache = function(socket, opts) {
      socket.once('connect', function() {
        var key = `${socket.localPort}:${port}`;
        var handler = lru.get(key);
        if (typeof handler === 'function') {
          lru.del(key);
          handler(opts);
        } else {
          lru.set(key, opts);
        }
      });
      return socket;
    };
    var connect = function(opts, cb) {
      var socket = net.connect(tempServerOpts, cb);
      handleTempCache(socket, opts);
      socket.on('error', common.noop);
      return socket;
    };
    var request = function(opts, cb) {
      if (typeof opts === 'string') {
        opts = { url: opts };
      } else {
        opts = extend({}, opts);
      }
      opts.url = common.setProtocol(opts.url);
      var uri = parseUrl(opts.url);
      var client;
      if (common.isConnect(uri)) {
        client = connect({
          host: uri.hostname,
          port: uri.port,
          headers: opts.proxyHeaders
        }, cb);
        client.isConnect = true;
        client.isTunnel = true;
        return client;
      }
      var protocol = uri.protocol;
      var isHttp = protocol === 'https:' || protocol === 'http:';
      var isWs = common.isWebSocket(uri, opts.headers);
      if (!isHttp && !isWs) {
        return cb && cb(new Error('Bad URL'));
      }

      var rawNames = {};
      var headers = common.lowerCaseify(opts.headers, rawNames);
      var isHttps = protocol === 'https:' || protocol === 'wss:';
      if (isWs) {
        headers.connection = 'Upgrade';
        headers.upgrade = 'websocket';
        rawNames.connection = 'Connection';
        rawNames.upgrade = 'Upgrade';
      }
      client = http.request({
        path: opts.url || '/',
        method: opts.method,
        agent: null,
        createConnection: function() {
          return connect({
            host: uri.host || 'localhost',
            port: uri.port || (isHttps ? 443 : 80),
            headers: opts.proxyHeaders,
            isHttp: true,
            isInternal: opts.isInternal,
            clientIp: opts.clientIp,
            clientPort: opts.clientPort
          });
        },
        headers: formatHeaders(headers, rawNames)
      }, cb);
      client.isHttps = isHttps;
      client.isHttp = isHttp;
      client.isWebSocket = isWs;
      client.on('error', common.noop);
      return client;
    };
    socketProto.connect = function() {
      var args = normalizeArgs(arguments);
      var opts = args[0];
      var cb = args[1];
      if (!opts || !SPEC_HOST_RE.test(opts.host)) {
        return originConnect.apply(this, arguments);
      }
      var policy = RegExp.$1;
      var reqId = RegExp.$2;
      var host = opts.host.slice(0, -RegExp['$&'].length);
      originConnect.call(this, tempServerOpts, cb);
      handleTempCache(this, {
        host: host || 'localhost',
        port: opts.port,
        reqId: reqId,
        headers: opts.proxyHeaders,
        isInternal: policy === 'internal',
        isTunnel: !policy || policy === 'tunnel',
        isConnect: policy === 'connect',
        clientIp: opts.clientIp,
        clientPort: opts.clientPort
      });
      return this;
    };
    cb({
      connect: connect,
      request: request
    });
  });
};
<|endoftext|>


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

/**
 * Module dependencies.
 */

var fs = require('fs')
  , Log = require('log')
  , repl = require('./repl')
  , utils = require('../utils')
  , os;

// COMPAT:
try {
  os = require('os');
} catch (err) {
  // ignore
}

/**
 * Enable stat tracking with the given `options`.
 *
 * Options:
 *
 *  - `connections`  enable connection statistics
 *  - `requests`     enable request statistics
 *
 * @param {Object} options
 * @return {Function}
 * @api public
 */

module.exports = function(options){
  options = options || {};
  stats.enableInWorker = options.connections || options.requests;

  function stats(master){
    var server = master.server;
    master.connectionStats = options.connections;
    master.requestStats = options.requests;

    // worker stats
    if (master.isWorker) {
      // connections
      if (options.connections) {
        server.on('connection', function(sock){
          var data = { remoteAddress: req.socket.remoteAddress };
          master.call('reportStats', 'connection', data);
          sock.on('close', function(){
            master.call('reportStats', 'disconnection', data);
          });
        });
      }

      // requests
      if (options.requests) {
        server.on('request', function(req, res){
          var data = {
              remoteAddress: req.socket.remoteAddress
            , headers: req.headers
            , httpVersion: req.httpVersion
            , method: req.method
            , url: req.url
          };
          master.call('reportStats', 'request', data);
        });
      }
    // master stats
    } else {
      master.stats = {
          start: new Date
        , restarts: 0
        , workersSpawned: 0
        , workersKilled: 0
      };

      // 0.4.x
      if (os) {
        master.stats.totalmem = os.totalmem();
        master.stats.freemem = os.freemem();
      }

      // worker stats
      master.reportStats = function(worker, type, data){
        master.emit('client ' + type, worker, data);
        switch (type) {
          case 'connection':
            worker.stats.connectionsTotal++;
            worker.stats.connectionsActive++;
            break;
          case 'disconnection':
            worker.stats.connectionsActive--;
            break;
          case 'request':
            worker.stats.requestsTotal++;
        }
      };

      // total workers spawned
      master.on('worker', function(worker){
        ++master.stats.workersSpawned;
        worker.stats = {
            start: new Date
          , connectionsTotal: 0
          , connectionsActive: 0
          , requestsTotal: 0
        };
      });

      // total worker deaths
      master.on('worker killed', function(worker){
        ++master.stats.workersKilled;
      });

      // restarting
      master.on('restarting', function(data){
        ++master.stats.restarts;
        data.stats = master.stats;
      });

      // restart
      master.on('restart', function(data){
        master.stats = data.stats;
        master.stats.start = new Date(master.stats.start);
      });
    }
  }

  return stats;
};

/**
 * REPL statistics command.
 */

repl.define('stats', function(master, sock){
  var active = master.children.length
    , total = master.stats.workersSpawned
    , deaths = master.stats.workersKilled
    , restarts = master.stats.restarts;

  // master stats
  sock.title('Master');
  if (os) sock.row('os', os.type() + ' ' + os.release());
  sock.row('state', master.state);
  sock.row('started', master.stats.start.toUTCString());
  sock.row('uptime', utils.formatDateRange(new Date, master.stats.start));
  sock.row('restarts', restarts);
  sock.row('workers', active);
  sock.row('deaths', deaths);

  // resources
  if (os) {
    sock.title('Resources');
    sock.row('load average', os.loadavg().map(function(n){ return n.toFixed(2); }).join(' '));
    sock.row('cores utilized', active + ' / ' + os.cpus().length);
    var free = utils.formatBytes(master.stats.freemem);
    var total = utils.formatBytes(master.stats.totalmem);
    sock.row('memory at boot (free / total)', free + ' / ' + total);
    var free = utils.formatBytes(os.freemem());
    var total = utils.formatBytes(os.totalmem());
    sock.row('memory now (free / total)', free + ' / ' + total);
  }

  // worker stats
  sock.title('Workers');

  // connections
  if (master.connectionStats) {
    sock.row('connections total', sum(master.children, 'connectionsTotal'));
    sock.row('connections active', sum(master.children, 'connectionsActive'));
  }

  // requests
  if (master.requestStats) {
    sock.row('requests total', sum(master.children, 'requestsTotal'));
  }

  master.children.forEach(function(worker){
    var stats = ''
      , piped = [];

    // uptime
    stats += utils.formatDateRange(new Date, worker.stats.start);

    // connections
    if (master.connectionStats) {
      piped.push(worker.stats.connectionsActive);
      piped.push(worker.stats.connectionsTotal);
    }

    // requests
    if (master.requestStats) {
      piped.push(worker.stats.requestsTotal);
    }

    if (piped.length) {
      stats += ' ' + piped.join('\033[90m|\033[0m');
    }

    sock.row(worker.id, stats);
  });
  sock.write('\n');
}, 'Display server statistics');

/**
 * Return sum of each `prop` in `arr`.
 *
 * @param {Array} arr
 * @param {String} prop
 * @return {Number}
 * @api private
 */

function sum(arr, prop){
  return arr.reduce(function(sum, obj){
    return sum + obj.stats[prop];
  }, 0);
};
<commit_msg>typo in last commit<commit_after>
/*!
 * Cluster - stats
 * Copyright (c) 2011 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var fs = require('fs')
  , Log = require('log')
  , repl = require('./repl')
  , utils = require('../utils')
  , os;

// COMPAT:
try {
  os = require('os');
} catch (err) {
  // ignore
}

/**
 * Enable stat tracking with the given `options`.
 *
 * Options:
 *
 *  - `connections`  enable connection statistics
 *  - `requests`     enable request statistics
 *
 * @param {Object} options
 * @return {Function}
 * @api public
 */

module.exports = function(options){
  options = options || {};
  stats.enableInWorker = options.connections || options.requests;

  function stats(master){
    var server = master.server;
    master.connectionStats = options.connections;
    master.requestStats = options.requests;

    // worker stats
    if (master.isWorker) {
      // connections
      if (options.connections) {
        server.on('connection', function(sock){
          var data = { remoteAddress: sock.remoteAddress };
          master.call('reportStats', 'connection', data);
          sock.on('close', function(){
            master.call('reportStats', 'disconnection', data);
          });
        });
      }

      // requests
      if (options.requests) {
        server.on('request', function(req, res){
          var data = {
              remoteAddress: req.socket.remoteAddress
            , headers: req.headers
            , httpVersion: req.httpVersion
            , method: req.method
            , url: req.url
          };
          master.call('reportStats', 'request', data);
        });
      }
    // master stats
    } else {
      master.stats = {
          start: new Date
        , restarts: 0
        , workersSpawned: 0
        , workersKilled: 0
      };

      // 0.4.x
      if (os) {
        master.stats.totalmem = os.totalmem();
        master.stats.freemem = os.freemem();
      }

      // worker stats
      master.reportStats = function(worker, type, data){
        master.emit('client ' + type, worker, data);
        switch (type) {
          case 'connection':
            worker.stats.connectionsTotal++;
            worker.stats.connectionsActive++;
            break;
          case 'disconnection':
            worker.stats.connectionsActive--;
            break;
          case 'request':
            worker.stats.requestsTotal++;
        }
      };

      // total workers spawned
      master.on('worker', function(worker){
        ++master.stats.workersSpawned;
        worker.stats = {
            start: new Date
          , connectionsTotal: 0
          , connectionsActive: 0
          , requestsTotal: 0
        };
      });

      // total worker deaths
      master.on('worker killed', function(worker){
        ++master.stats.workersKilled;
      });

      // restarting
      master.on('restarting', function(data){
        ++master.stats.restarts;
        data.stats = master.stats;
      });

      // restart
      master.on('restart', function(data){
        master.stats = data.stats;
        master.stats.start = new Date(master.stats.start);
      });
    }
  }

  return stats;
};

/**
 * REPL statistics command.
 */

repl.define('stats', function(master, sock){
  var active = master.children.length
    , total = master.stats.workersSpawned
    , deaths = master.stats.workersKilled
    , restarts = master.stats.restarts;

  // master stats
  sock.title('Master');
  if (os) sock.row('os', os.type() + ' ' + os.release());
  sock.row('state', master.state);
  sock.row('started', master.stats.start.toUTCString());
  sock.row('uptime', utils.formatDateRange(new Date, master.stats.start));
  sock.row('restarts', restarts);
  sock.row('workers', active);
  sock.row('deaths', deaths);

  // resources
  if (os) {
    sock.title('Resources');
    sock.row('load average', os.loadavg().map(function(n){ return n.toFixed(2); }).join(' '));
    sock.row('cores utilized', active + ' / ' + os.cpus().length);
    var free = utils.formatBytes(master.stats.freemem);
    var total = utils.formatBytes(master.stats.totalmem);
    sock.row('memory at boot (free / total)', free + ' / ' + total);
    var free = utils.formatBytes(os.freemem());
    var total = utils.formatBytes(os.totalmem());
    sock.row('memory now (free / total)', free + ' / ' + total);
  }

  // worker stats
  sock.title('Workers');

  // connections
  if (master.connectionStats) {
    sock.row('connections total', sum(master.children, 'connectionsTotal'));
    sock.row('connections active', sum(master.children, 'connectionsActive'));
  }

  // requests
  if (master.requestStats) {
    sock.row('requests total', sum(master.children, 'requestsTotal'));
  }

  master.children.forEach(function(worker){
    var stats = ''
      , piped = [];

    // uptime
    stats += utils.formatDateRange(new Date, worker.stats.start);

    // connections
    if (master.connectionStats) {
      piped.push(worker.stats.connectionsActive);
      piped.push(worker.stats.connectionsTotal);
    }

    // requests
    if (master.requestStats) {
      piped.push(worker.stats.requestsTotal);
    }

    if (piped.length) {
      stats += ' ' + piped.join('\033[90m|\033[0m');
    }

    sock.row(worker.id, stats);
  });
  sock.write('\n');
}, 'Display server statistics');

/**
 * Return sum of each `prop` in `arr`.
 *
 * @param {Array} arr
 * @param {String} prop
 * @return {Number}
 * @api private
 */

function sum(arr, prop){
  return arr.reduce(function(sum, obj){
    return sum + obj.stats[prop];
  }, 0);
};
<|endoftext|>


<commit_before>'use strict';

var assign       = require('lodash-node/modern/objects/assign');
var pkg          = require(process.cwd() + '/package');
var deps         = assign(pkg['devDependencies'], pkg['dependencies']);
var path         = require('path');
var Registry     = require('./preprocessors/registry');
var requireLocal = require('./utilities/require-local');

var registry;

module.exports.setupRegistry = function(app) {
  registry = new Registry(deps, app);

  registry.add('css', 'broccoli-sass', 'scss');
  registry.add('css', 'broccoli-ruby-sass', ['scss', 'sass']);
  registry.add('css', 'broccoli-less-single', 'less');
  registry.add('css', 'broccoli-stylus-single', 'styl');

  registry.add('minify-css', 'broccoli-csso', null);

  registry.add('js', 'broccoli-coffee', 'coffee');
  registry.add('js', 'broccoli-ember-script', 'em');
  registry.add('js', 'broccoli-sweetjs', 'js');

  registry.add('template', 'broccoli-ember-hbs-template-compiler', ['hbs', 'handlebars']);
  registry.add('template', 'broccoli-emblem-compiler', ['embl', 'emblem']);

  return registry;
};

module.exports.isType = function(file, type) {
  var plugins   = registry.registry[type] || [];
  var extension = path.extname(file).replace('.', '');

  for (var i = 0; i < plugins.length; i++) {
    if (extension === plugins[i].ext) {
      return true;
    }
  }
};

module.exports.preprocessMinifyCss = function(tree, options) {
  var plugin = registry.load('minify-css');

  if (!plugin) {
    var compiler = require('broccoli-clean-css');
    return compiler(tree, options);
  }

  return requireLocal(plugin.name).call(null, tree, options);
};

module.exports.preprocessCss = function(tree, inputPath, outputPath) {
  var plugin = registry.load('css');

  if (!plugin) {
    var compiler = require('broccoli-static-compiler');
    var fileMover = require('broccoli-file-mover');

    var styles = compiler(tree, {
      srcDir: inputPath,
      destDir: outputPath
    });

    // when our application is named `app` there is no
    // need to move the static css file.
    if (registry.app.name === 'app') {
      return styles;
    }

    return fileMover(styles, {
      srcFile: 'assets/app.css',
      destFile: 'assets/' + registry.app.name + '.css'
    });
  }

  return plugin.toTree.apply(plugin, arguments);
};

module.exports.preprocessTemplates = function(tree) {
  var plugin = registry.load('template');

  if (!plugin) {
    throw new Error('Missing template processor');
  }

  return requireLocal(plugin.name).call(null, tree, {
    extensions: plugin.ext,
    module: true
  });
};

module.exports.preprocessJs = function(tree, inputPath, outputPath, options) {
  var plugin = registry.load('js');

  if (!plugin) { return tree; }

  if (plugin.name.indexOf('coffee') !== -1 || plugin.name.indexOf('ember-script') !== -1) {
    options = options || {};
    options.bare = true;
    options.srcDir = inputPath;
    options.destDir = outputPath;
  }

  return requireLocal(plugin.name).call(null, tree, options);
};
<commit_msg>relative path fix in prepreocessors.js<commit_after>'use strict';

var assign       = require('lodash-node/modern/objects/assign');
var pkg          = require(process.cwd() + '/package');
var deps         = assign(pkg['devDependencies'], pkg['dependencies']);
var path         = require('path');
var Registry     = require('./preprocessors/registry');
var requireLocal = require('./utilities/require-local');

var registry;

module.exports.setupRegistry = function(app) {
  registry = new Registry(deps, app);

  registry.add('css', 'broccoli-sass', 'scss');
  registry.add('css', 'broccoli-ruby-sass', ['scss', 'sass']);
  registry.add('css', 'broccoli-less-single', 'less');
  registry.add('css', 'broccoli-stylus-single', 'styl');

  registry.add('minify-css', 'broccoli-csso', null);

  registry.add('js', 'broccoli-coffee', 'coffee');
  registry.add('js', 'broccoli-ember-script', 'em');
  registry.add('js', 'broccoli-sweetjs', 'js');

  registry.add('template', 'broccoli-ember-hbs-template-compiler', ['hbs', 'handlebars']);
  registry.add('template', 'broccoli-emblem-compiler', ['embl', 'emblem']);

  return registry;
};

module.exports.isType = function(file, type) {
  var plugins   = registry.registry[type] || [];
  var extension = path.extname(file).replace('.', '');

  for (var i = 0; i < plugins.length; i++) {
    if (extension === plugins[i].ext) {
      return true;
    }
  }
};

module.exports.preprocessMinifyCss = function(tree, options) {
  var plugin = registry.load('minify-css');

  if (!plugin) {
    var compiler = require('broccoli-clean-css');
    return compiler(tree, options);
  }

  return requireLocal(plugin.name).call(null, tree, options);
};

module.exports.preprocessCss = function(tree, inputPath, outputPath) {
  var plugin = registry.load('css');

  if (!plugin) {
    var compiler = require('broccoli-static-compiler');
    var fileMover = require('broccoli-file-mover');

    var styles = compiler(tree, {
      srcDir: inputPath,
      destDir: outputPath
    });

    // when our application is named `app` there is no
    // need to move the static css file.
    if (registry.app.name === 'app') {
      return styles;
    }

    return fileMover(styles, {
      srcFile: outputPath + '/app.css',
      destFile: outputPath + '/' + registry.app.name + '.css'
    });
  }

  return plugin.toTree.apply(plugin, arguments);
};

module.exports.preprocessTemplates = function(tree) {
  var plugin = registry.load('template');

  if (!plugin) {
    throw new Error('Missing template processor');
  }

  return requireLocal(plugin.name).call(null, tree, {
    extensions: plugin.ext,
    module: true
  });
};

module.exports.preprocessJs = function(tree, inputPath, outputPath, options) {
  var plugin = registry.load('js');

  if (!plugin) { return tree; }

  if (plugin.name.indexOf('coffee') !== -1 || plugin.name.indexOf('ember-script') !== -1) {
    options = options || {};
    options.bare = true;
    options.srcDir = inputPath;
    options.destDir = outputPath;
  }

  return requireLocal(plugin.name).call(null, tree, options);
};
<|endoftext|>


<commit_before>const OBJECT_PROTOTYPE_KEYS = Object.getOwnPropertyNames(Object.prototype);
const ARRAY_PROTOTYPE_KEYS = Object.getOwnPropertyNames(Array.prototype);

module.exports = function(data){
  if (!data || data.length < 1) return {};

  let d = {},
    keys = Object.keys(data);

  for (let i = 0; i < keys.length; i++) {
    let key = keys[i],
      value = data[key],
      current = d,
      keyParts = key
        .replace(new RegExp(/\[/g), '.')
        .replace(new RegExp(/\]/g), '')
        .split('.');

    for (let index = 0; index < keyParts.length; index++){
      let k = keyParts[index];

      // Ensure we don't allow prototype pollution
      if (OBJECT_PROTOTYPE_KEYS.includes(k) || (ARRAY_PROTOTYPE_KEYS.includes(k) && Array.isArray(current)) {
        continue;
      }

      if (index >= keyParts.length - 1){
        current[k] = value;
      } else {
        if (!current[k]) current[k] = !isNaN(keyParts[index + 1]) ? [] : {};
        current = current[k];
      }
    }
  }

  return d;
};
<commit_msg>Fix typo<commit_after>const OBJECT_PROTOTYPE_KEYS = Object.getOwnPropertyNames(Object.prototype);
const ARRAY_PROTOTYPE_KEYS = Object.getOwnPropertyNames(Array.prototype);

module.exports = function(data){
  if (!data || data.length < 1) return {};

  let d = {},
    keys = Object.keys(data);

  for (let i = 0; i < keys.length; i++) {
    let key = keys[i],
      value = data[key],
      current = d,
      keyParts = key
        .replace(new RegExp(/\[/g), '.')
        .replace(new RegExp(/\]/g), '')
        .split('.');

    for (let index = 0; index < keyParts.length; index++){
      let k = keyParts[index];

      // Ensure we don't allow prototype pollution
      if (OBJECT_PROTOTYPE_KEYS.includes(k) || (ARRAY_PROTOTYPE_KEYS.includes(k) && Array.isArray(current))) {
        continue;
      }

      if (index >= keyParts.length - 1){
        current[k] = value;
      } else {
        if (!current[k]) current[k] = !isNaN(keyParts[index + 1]) ? [] : {};
        current = current[k];
      }
    }
  }

  return d;
};
<|endoftext|>


<commit_before>'use babel'

/* @flow */

import {Range, Emitter, CompositeDisposable} from 'atom'
import {visitSource} from './helpers'
import type {Point, Disposable, TextEditor} from 'atom'
import type {Intention$List, Declaration} from './types'

type Intentions$List = {textEditor: TextEditor, bufferPosition: Point}

export class ProviderList {
  emitter: Emitter;
  subscriptions: CompositeDisposable;
  grammarScopes: Array<string>;

  constructor() {
    this.emitter = new Emitter()
    this.subscriptions = new CompositeDisposable()
    this.grammarScopes = ['*']

    this.subscriptions.add(this.emitter)
  }
  async getIntentions({textEditor, bufferPosition}: Intentions$List): Promise<Array<Intention$List>> {
    const results = await this.requestDeclarations({textEditor, bufferPosition})
    if (Array.isArray(results)) {
      let result
      for (const entry of results) {
        const range = Range.fromObject(entry.range)
        if (range.containsPoint(bufferPosition)) {
          result = entry
          break
        }
      }
      if (result) {
        return [{
          priority: 100,
          icon: 'alignment-align',
          title: 'Jump to declaration',
          selected: function() {
            visitSource(result.source.filePath, result.source.position)
          }
        }]
      }
    }
    return []
  }
  async requestDeclarations({textEditor, bufferPosition}: Intentions$List): Promise<Array<Declaration>> {
    const event = {promise: Promise.resolve([]), parameters: {textEditor, visibleRange: [[bufferPosition.row, 0], [bufferPosition.row, Infinity]]}}
    this.emitter.emit('should-provide-declarations', event)
    return await event.promise
  }
  onShouldProvideDeclarations(callback: Function): Disposable {
    return this.emitter.on('should-provide-declarations', callback)
  }
  dispose() {
    this.subscriptions.dispose()
  }
}
<commit_msg>:fire: Cleanup provider-list<commit_after>'use babel'

/* @flow */

import {Range, Emitter, CompositeDisposable} from 'atom'
import {visitSource} from './helpers'
import type {Point, Disposable, TextEditor} from 'atom'
import type {Intention$List, Declaration} from './types'

type Intentions$List = {textEditor: TextEditor, bufferPosition: Point}

export class ProviderList {
  emitter: Emitter;
  subscriptions: CompositeDisposable;
  grammarScopes: Array<string>;

  constructor() {
    this.emitter = new Emitter()
    this.subscriptions = new CompositeDisposable()
    this.grammarScopes = ['*']

    this.subscriptions.add(this.emitter)
  }
  async getIntentions({textEditor, bufferPosition}: Intentions$List): Promise<Array<Intention$List>> {
    const results = await this.requestDeclarations({textEditor, bufferPosition})
    if (Array.isArray(results)) {
      for (const entry of results) {
        const range = Range.fromObject(entry.range)
        if (range.containsPoint(bufferPosition)) {
          return [{
            priority: 100,
            icon: 'alignment-align',
            title: 'Jump to declaration',
            selected: function() {
              visitSource(entry.source.filePath, entry.source.position)
            }
          }]
        }
      }
    }
    return []
  }
  async requestDeclarations({textEditor, bufferPosition}: Intentions$List): Promise<Array<Declaration>> {
    const event = {promise: Promise.resolve([]), parameters: {textEditor, visibleRange: [[bufferPosition.row, 0], [bufferPosition.row, Infinity]]}}
    this.emitter.emit('should-provide-declarations', event)
    return await event.promise
  }
  onShouldProvideDeclarations(callback: Function): Disposable {
    return this.emitter.on('should-provide-declarations', callback)
  }
  dispose() {
    this.subscriptions.dispose()
  }
}
<|endoftext|>


<commit_before>$(function() {
  var animationTimeout = 1000;

  function loadQuote(id) {
    $.getJSON("quote", {id: id})
     .done(function(quote) {
      if (hasQuoteOnScreenAlready(quote))
        loadQuote();
      else if (id)
        renderQuote(quote)
      else
        setTimeout(function() {renderQuote(quote)}, 15000);
    })
     .fail(function() {
       setTimeout(loadQuote, 5000);
     });
  }

  function renderQuote(quote) {
    $("blockquote").fadeOut(animationTimeout, function() {
      $(this).find(".content").html(quote.c).end()
             .find(".author").html(quote.a).end()
             .fadeIn(animationTimeout);
      window.location.hash = quote.id;
      loadQuote();
    });
  }

  function hasQuoteOnScreenAlready(quote) {
    return $(".content").text() == quote.c.replace(/
/g, "") && $(".author").text() == quote.a;
  }

  loadQuote(window.location.hash);
});
<commit_msg>render quote right away if no quotes are visible<commit_after>$(function() {
  var animationTimeout = 1000;

  function loadQuote(id) {
    $.getJSON("quote", {id: id})
     .done(function(quote) {
      if (hasQuoteOnScreenAlready(quote))
        loadQuote();
      else if (id || $("blockquote").is(":not(:visible)"))
        renderQuote(quote)
      else
        setTimeout(function() {renderQuote(quote)}, 15000);
    })
     .fail(function() {
       setTimeout(loadQuote, 5000);
     });
  }

  function renderQuote(quote) {
    $("blockquote").fadeOut(animationTimeout, function() {
      $(this).find(".content").html(quote.c).end()
             .find(".author").html(quote.a).end()
             .fadeIn(animationTimeout);
      window.location.hash = quote.id;
      loadQuote();
    });
  }

  function hasQuoteOnScreenAlready(quote) {
    return $(".content").text() == quote.c.replace(/
/g, "") && $(".author").text() == quote.a;
  }

  loadQuote(window.location.hash);
});
<|endoftext|>


<commit_before>var latestCallback = null,
	result = '';
var encodeContent = function(anything, isFirst) {
	if (typeof anything === 'undefined')
		return '';
	if ((anything instanceof RegExp) || (typeof anything === 'function'))
		return (isFirst ? '' : ',') + 'eval(' + anything + ')';
	return (isFirst ? '' : ',') + 'JSON.parse(\'' + (JSON.stringify(anything) ||
		'').replace(/'/g, '\\u0027').replace(/"/g, '\\u0022').replace(/\\n/g, '\\\\n') +
		'\')';
};
exports.getResult = function(sourceCodeArray, mode) {
	var QUNIT_TEMPLATE =
		'<!DOCTYPE html><meta charset="utf-8"><title>mode_here</title><link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css">

Test Code

';
	return QUNIT_TEMPLATE.replace(/script_here/, result).replace(/source_here/,
		JSON.stringify(sourceCodeArray)).replace(/mode_here/, mode);
};

var testLib = exports.testLib = {
	test: function(description, testCodeFunction) {
		result += 'test(\'' + description + '\',function(){\n';
		if (latestCallback && latestCallback.setup)
			latestCallback.setup();
		testCodeFunction();
		if (latestCallback && latestCallback.teardown)
			latestCallback.teardown();
		result += "\n});\n";
	},
	module: function(name, callback) {
		result += 'module(\'' + name + '\');\n';
		latestCallback = callback;
	},
	ok: function(bool, description) {
		result += '  ok(' + !! bool + ',\'' + (description || '') + '\');\n';
	},
	throws: function(block, expect, message) {
		var serializedTemp, temp = null;
		try {
			block();
		} catch (e) {
			temp = e;
		}
		if (temp == null)
			serializedTemp = '';
		else if (temp instanceof Error)
			serializedTemp = 'throw new Error("' + temp.message + '")';
		else {
			var temp2 = JSON.parse(JSON.stringify(temp));
			delete temp2.line;
			delete temp2.sourceURL;
			delete temp2.sourceId;
			delete temp2.stack;
			delete temp2.stackArray;
			serializedTemp = 'throw ' + JSON.stringify(temp2);
		}

		result += ['  throws(function(){', serializedTemp, '}', encodeContent(expect),
			encodeContent(message), ');\n'
		].join('');
	}
};

var equalFunctionBuilder = function(name) {
	return function(actual, expect, description) {
		result += '  ' + name + '(' + encodeContent(actual, true) + encodeContent(
			expect) + encodeContent(description) + ');\n';
	};
};
var autoFunctionBuilder = function(name) {
	var not = name.substr(0, 3) === 'not';
	return function(func, expect /*arguments*/ ) {
		var args = Array.prototype.slice.call(arguments, 2);
		var argString = JSON.stringify(args);
		if (argString)
			argString = argString.substr(1, argString.length - 2);
		var message = ['call(', argString, not ? ') !== ' : ') === ', JSON.stringify(
			expect)];
		testLib[name](func.apply(null, args), expect, message.join(''));
	}
}
var allFunctions = ['deepEqual', 'equal', 'notDeepEqual', 'notEqual',
	'notPropEqual', 'notStrictEqual', 'propEqual', 'strictEqual'
];
for (var i = 0, ii = allFunctions.length; i < ii; i++) {
	testLib[allFunctions[i]] = equalFunctionBuilder(allFunctions[i]);
	var capFirst = allFunctions[i][0].toUpperCase() + allFunctions[i].substring(1);
	testLib['auto' + capFirst] = autoFunctionBuilder(allFunctions[i]);
}
testLib.auto = testLib.autoDeepEqual;
<commit_msg>edit css<commit_after>var latestCallback = null,
	result = '';
var encodeContent = function(anything, isFirst) {
	if (typeof anything === 'undefined')
		return '';
	if ((anything instanceof RegExp) || (typeof anything === 'function'))
		return (isFirst ? '' : ',') + 'eval(' + anything + ')';
	return (isFirst ? '' : ',') + 'JSON.parse(\'' + (JSON.stringify(anything) ||
		'').replace(/'/g, '\\u0027').replace(/"/g, '\\u0022').replace(/\\n/g, '\\\\n') +
		'\')';
};
exports.getResult = function(sourceCodeArray, mode) {
	var QUNIT_TEMPLATE =
		'<!DOCTYPE html><meta charset="utf-8"><title>mode_here</title><link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css">

Test Code

';
	return QUNIT_TEMPLATE.replace(/script_here/, result).replace(/source_here/,
		JSON.stringify(sourceCodeArray)).replace(/mode_here/, mode);
};

var testLib = exports.testLib = {
	test: function(description, testCodeFunction) {
		result += 'test(\'' + description + '\',function(){\n';
		if (latestCallback && latestCallback.setup)
			latestCallback.setup();
		testCodeFunction();
		if (latestCallback && latestCallback.teardown)
			latestCallback.teardown();
		result += "\n});\n";
	},
	module: function(name, callback) {
		result += 'module(\'' + name + '\');\n';
		latestCallback = callback;
	},
	ok: function(bool, description) {
		result += '  ok(' + !! bool + ',\'' + (description || '') + '\');\n';
	},
	throws: function(block, expect, message) {
		var serializedTemp, temp = null;
		try {
			block();
		} catch (e) {
			temp = e;
		}
		if (temp == null)
			serializedTemp = '';
		else if (temp instanceof Error)
			serializedTemp = 'throw new Error("' + temp.message + '")';
		else {
			var temp2 = JSON.parse(JSON.stringify(temp));
			delete temp2.line;
			delete temp2.sourceURL;
			delete temp2.sourceId;
			delete temp2.stack;
			delete temp2.stackArray;
			serializedTemp = 'throw ' + JSON.stringify(temp2);
		}

		result += ['  throws(function(){', serializedTemp, '}', encodeContent(expect),
			encodeContent(message), ');\n'
		].join('');
	}
};

var equalFunctionBuilder = function(name) {
	return function(actual, expect, description) {
		result += '  ' + name + '(' + encodeContent(actual, true) + encodeContent(
			expect) + encodeContent(description) + ');\n';
	};
};
var autoFunctionBuilder = function(name) {
	var not = name.substr(0, 3) === 'not';
	return function(func, expect /*arguments*/ ) {
		var args = Array.prototype.slice.call(arguments, 2);
		var argString = JSON.stringify(args);
		if (argString)
			argString = argString.substr(1, argString.length - 2);
		var message = ['call(', argString, not ? ') !== ' : ') === ', JSON.stringify(
			expect)];
		testLib[name](func.apply(null, args), expect, message.join(''));
	}
}
var allFunctions = ['deepEqual', 'equal', 'notDeepEqual', 'notEqual',
	'notPropEqual', 'notStrictEqual', 'propEqual', 'strictEqual'
];
for (var i = 0, ii = allFunctions.length; i < ii; i++) {
	testLib[allFunctions[i]] = equalFunctionBuilder(allFunctions[i]);
	var capFirst = allFunctions[i][0].toUpperCase() + allFunctions[i].substring(1);
	testLib['auto' + capFirst] = autoFunctionBuilder(allFunctions[i]);
}
testLib.auto = testLib.autoDeepEqual;
<|endoftext|>


<commit_before>const U256 = require('./u256.js')
const Address = require('./address.js')
const Block = require('./block.js')
const fakeBlockChain = require('./fakeBlockChain.js')

module.exports = class Environment {
  constructor (data) {
    const defaults = {
      block: new Block(),
      blockchain: fakeBlockChain,
      // gas tank
      gasPrice: 0,
      gasLeft: 1000000,
      gasRefund: 0,
      // call infromation
      address: new Address('0x0000000000000000000000000000000000000000'),
      origin: new Address('0x0000000000000000000000000000000000000000'),
      caller: new Address('0x0000000000000000000000000000000000000000'),
      callValue: new U256(0),
      callData: new Uint8Array(),
      // the ROM
      code: new Uint8Array(), // the current running code
      // output calls
      logs: [],
      selfDestructAddress: new Address('0x0000000000000000000000000000000000000000'),
      // more output calls
      returnValue: new Uint8Array()
    }

    this.state = new Map()

    Object.assign(this, defaults, data || {})
  }

  addAccount (address, trie) {
    let account = new Map()
    account.set('nonce', trie.nonce || new U256(0))
    account.set('balance', trie.balance || new U256(0))
    account.set('code', trie.code || new Uint8Array())
    account.set('storage', trie.storage || new Map())
    this.state.set(address.toString(), account)
  }

  getBalance (address) {
    const account = this.state.get(address.toString())
    if (account) {
      return account.get('balance')
    } else {
      return new U256()
    }
  }

  getCode (address) {
    const account = this.state.get(address.toString())
    if (account) {
      return account.get('code')
    } else {
      return Uint8Array.from(new Buffer([]))
    }
  }

  getBlockHash (height) {
    return this.blockchain.getBlock(height).hash()
  }

  // kernal
  create (code, value) {
    // STUB
  }

  call (gas, address, value, data) {
    // STUB
    return // result
  }

  callCode (gas, address, value, data) {
    // STUB
    return // result
  }

  delegateCall (gas, address, data) {
    // STUB
    return // result
  }
}
<commit_msg>Environment: return failure in call*/create<commit_after>const U256 = require('./u256.js')
const Address = require('./address.js')
const Block = require('./block.js')
const fakeBlockChain = require('./fakeBlockChain.js')

module.exports = class Environment {
  constructor (data) {
    const defaults = {
      block: new Block(),
      blockchain: fakeBlockChain,
      // gas tank
      gasPrice: 0,
      gasLeft: 1000000,
      gasRefund: 0,
      // call infromation
      address: new Address('0x0000000000000000000000000000000000000000'),
      origin: new Address('0x0000000000000000000000000000000000000000'),
      caller: new Address('0x0000000000000000000000000000000000000000'),
      callValue: new U256(0),
      callData: new Uint8Array(),
      // the ROM
      code: new Uint8Array(), // the current running code
      // output calls
      logs: [],
      selfDestructAddress: new Address('0x0000000000000000000000000000000000000000'),
      // more output calls
      returnValue: new Uint8Array()
    }

    this.state = new Map()

    Object.assign(this, defaults, data || {})
  }

  addAccount (address, trie) {
    let account = new Map()
    account.set('nonce', trie.nonce || new U256(0))
    account.set('balance', trie.balance || new U256(0))
    account.set('code', trie.code || new Uint8Array())
    account.set('storage', trie.storage || new Map())
    this.state.set(address.toString(), account)
  }

  getBalance (address) {
    const account = this.state.get(address.toString())
    if (account) {
      return account.get('balance')
    } else {
      return new U256()
    }
  }

  getCode (address) {
    const account = this.state.get(address.toString())
    if (account) {
      return account.get('code')
    } else {
      return Uint8Array.from(new Buffer([]))
    }
  }

  getBlockHash (height) {
    return this.blockchain.getBlock(height).hash()
  }

  // kernal
  create (code, value) {
    // STUB
    return [ 1, Address.zero() ]
  }

  call (gas, address, value, data) {
    // STUB
    return [ 1, new Uint8Array() ]
  }

  callCode (gas, address, value, data) {
    // STUB
    return [ 1, new Uint8Array() ]
  }

  delegateCall (gas, address, data) {
    // STUB
    return [ 1, new Uint8Array() ]
  }
}
<|endoftext|>


<commit_before>/**
 * @providesModule react-native-localytics
 * @flow
 */
import type { CustomerParams } from './VOOLocalyticsTypes';

export function tagPurchased(params = {}) {
  console.error('tagPurchased is not implemented on Android');
}
export function tagAddedToCard(params = {}) {
  console.error('tagAddedToCard is not implemented on Android');
}
export function tagStartedCheckout(params = {}) {
  console.error('tagStartedCheckout is not implemented on Android');
}
export function tagCompletedCheckout(params = {}) {
  console.error('tagCompletedCheckout is not implemented on Android');
}

export function tagCustomerRegistered(params: CustomerParams = {}) {
  console.error('tagCustomerRegistered is not implemented on Android');
}

export function tagCustomerLoggedIn(params: CustomerParams = {}) {
  console.error('tagCustomerLoggedIn is not implemented on Android');
}

export function tagCustomerLoggedOut(params?: Object = {}) {
  console.error('tagCustomerLoggedOut is not implemented on Android');
}

export function tagEvent(eventName: string, attributes?: Object) {
  console.error('tagEvent is not implemented on Android');
}

export function setCustomerId(id: string): void {
  console.error('setCustomerId is not implemented on Android');
}

export function setCustomerFirstName(name: string): void {
  console.error('setCustomerFirstName is not implemented on Android');
}

export function setCustomerLastName(name: string): void {
  console.error('setCustomerLastName is not implemented on Android');
}

export function setCustomerFullName(name: string): void {
  console.error('setCustomerFullName is not implemented on Android');
}

export function setCustomerEmail(email: string): void {
  console.error('setCustomerEmail is not implemented on Android');
}

export function setLocation(coords: Coordinates): void {
  console.error('setLocation is not implemented on Android');
}
<commit_msg>Added android error messages<commit_after>/**
 * @providesModule react-native-localytics
 * @flow
 */
import type {
  CustomerParams,
  ItemParams,
  CheckoutParams,
  Coordinates,
  ContentParams,
  SearchParams,
  ShareParams,
  RatingParams,
  InvitationParams
} from './VOOLocalyticsTypes';

export function tagPurchased(params = {}) {
  console.error('tagPurchased is not implemented on Android');
}
export function tagAddedToCard(params = {}) {
  console.error('tagAddedToCard is not implemented on Android');
}
export function tagStartedCheckout(params = {}) {
  console.error('tagStartedCheckout is not implemented on Android');
}
export function tagCompletedCheckout(params = {}) {
  console.error('tagCompletedCheckout is not implemented on Android');
}

export function tagCustomerRegistered(params: CustomerParams = {}) {
  console.error('tagCustomerRegistered is not implemented on Android');
}

export function tagCustomerLoggedIn(params: CustomerParams = {}) {
  console.error('tagCustomerLoggedIn is not implemented on Android');
}

export function tagCustomerLoggedOut(params?: Object = {}) {
  console.error('tagCustomerLoggedOut is not implemented on Android');
}

export function tagEvent(eventName: string, attributes?: Object) {
  console.error('tagEvent is not implemented on Android');
}

export function setCustomerId(id: string): void {
  console.error('setCustomerId is not implemented on Android');
}

export function setCustomerFirstName(name: string): void {
  console.error('setCustomerFirstName is not implemented on Android');
}

export function setCustomerLastName(name: string): void {
  console.error('setCustomerLastName is not implemented on Android');
}

export function setCustomerFullName(name: string): void {
  console.error('setCustomerFullName is not implemented on Android');
}

export function setCustomerEmail(email: string): void {
  console.error('setCustomerEmail is not implemented on Android');
}

export function setLocation(coords: Coordinates): void {
  console.error('setLocation is not implemented on Android');
}
export function tagContentViewed(content: ContentParams = {}): void {
  console.error('tagContentViewed is not implemented on Android');
}

export function tagSearched(search: SearchParams = {}): void {
  console.error('tagSearched is not implemented on Android');
}

export function tagShared(search: ShareParams = {}): void {
  console.error('tagShared is not implemented on Android');
}

export function tagContentRated(rating: RatingParams = {}): void {
  console.error('tagContentRated is not implemented on Android');
}

export function tagInvited(method:string, attributes?: Object): void {
  console.error('tagInvited is not implemented on Android');
}<|endoftext|>


<commit_before>var Conversation = function(speciesList) {
	this.lastAnswer = null;
	this.lastAction = Date.now();
	this.firstmessage = true;
	this.inFindingProcess = false;

	this.speciesList = speciesList;

	let commonNames = speciesList.map((obj)=>obj.triname);
	let scientificNames = speciesList.map((obj)=>obj.sciname);
  this.speciesNames = commonNames.concat(scientificNames);

	this.location = null;
	this.species = null;

	this.isActive = function(){
			let diff = this.lastAction - Date.now();
			let fiveMinInMs = 1000 * 60 * 5;
			return diff <= fiveMinInMs;

	};
	this.setLocation = function(location){
		this.location = location
	};
	this.processMessage = function(message) {
		console.log("Input> " + message);
    this.lastAction = Date.now();
		var splitedMessage = message.split(/[ ,]+/);

		if(this.firstmessage || match(splitedMessage,["hey", "moin", "hallo", "hi", "servus"])) {
			this.firstmessage = false;
			var startText = 'Hey du, ich bin BioDiv und kann weiterhelfen, wenn du seltene Muscheln / Säugetiere oder Fische in deiner Umgebung gesichtet hast. ';

			var answerOptions = ["Hilfe", "Fund melden"];

			return { answer: startText, answerOptions: answerOptions };
		}
		let yes = ["ja", "ok", "jo", "jup"];
		let no = ["nein", "nö", "ne", "auf gar keinen fall", "halt die fresse"];

    if(match(splitedMessage, yes.concat(no))) {
			var userAnswer = message;
			var answerOptions = [];

			this.lastAnswer = null;
			if(match(splitedMessage, yes)) {
				var jaText = "Ich halte Dich auf dem Laufenden. 👍";
				return { answer: jaText, answerOptions: answerOptions };
			} else {
				var neinText = "Ok, frag' einfach, wenn du wissen willst, wie der Status ist. 😁 Ich bin bis auf weiteres stumm. 🙈🙊🙉";
				return { answer: neinText, answerOptions: answerOptions };
			}

		}

		if(match([message], ["Fund melden"])) {
			var answerOptions = [];

			var helpText = 'ℹ Alles klar du, dann lass uns loslegen und deinen Fund zusammen aufnehmen! Was für eine Spezies hast du denn gesehen?';

      this.inFindingProcess = true;

			return { answer: helpText, answerOptions: answerOptions };
		}

		if(this.inFindingProcess){

    	console.log(splitedMessage);
    	console.log(this.speciesCommonNames);
    	console.log(this.speciesSientificNames);

    	if(match([message],["Location set"])){
        return {
          answer: "Nun weiß ich schon wo du dich befindest, Vielleicht möchtest du noch mehr angeben?",
          answerOptions: ["Nachweisquallität", "Nachweismethode", "Fund speichern"]
        };
			}
			else if(match(splitedMessage,["Nachweismethode"])){
        return {
          answer: "Okay welche der folgenden Nachweismethoden wurde verwendet?",
          answerOptions: [""]
        };
			}
			else if(match(splitedMessage,["Nachweisquallität"])){
        return {
          answer: "Wie war die genaue Nachweisquallität?",
          answerOptions: ["Nachweisquallität", "Nachweismethode"]
        };
			}
    	else if(match([message],this.speciesNames)){

				let potentialSpecies = this.speciesList.filter((species)=> {

					let nameSplits = species.triname.split(" ");
					nameSplits = nameSplits.concat(species.sciname.split(" "));

          nameSplits = nameSplits.filter((name)=> name.toLowerCase().trim() !="muschel" && name.toLowerCase().trim()!= "mussel")
          nameSplits = nameSplits.filter((name)=> name.toLowerCase().trim() !="clam");
          nameSplits = nameSplits.filter((name)=> name.toLowerCase().trim() !="fisch" && name.toLowerCase().trim()!= "fish")
					console.log("nameSplits",nameSplits);
					return match(splitedMessage,nameSplits )
        });

				console.log("potentialSpecies", potentialSpecies);

				if(potentialSpecies.length == 0 ){
          return {
            answer: "Irgendwas ist hier schief gelaufen :( Ich konnte irgendwie keine Spezies finden ... "
          };
				}
				else if (potentialSpecies.length == 1 ){
          return {
            answer: "Sehr schön, hab ich verstanden du hast " + message + " bei dir gesehen. " +
            "\n Es wäre super wenn du mir noch deinen Standort zeigen könntest?",
            locationRequest: true
          };
				}else {
          return {
            answer: "Huch da brauch ich noch ein wenig mehr Infos.\nEs gibt mehrere Spezies, bitte wähle die richtige aus: ",
            answerOptions: potentialSpecies.map((species)=>species.triname)
          };
				}

			}

    	else if(this.speciesName == null){

        console.log("Choose species text ", this.speciesCommonNames);
        return {
          answer: "Leider habe ich dich nicht so recht verstanden, hier einige Vorschläge was für Spezies ich so im Angebot hätte",
          answerOptions: this.speciesList.map((species)=>species.triname)
        }

			}

		}

		return {
      answer: "Ich konnte dich leider nicht verstehen... 😰",
      answerOptions: ["Hilfe"]
    }

	};

	return this;
};

function match(splitedMessage, keyWords) {

	for(var word in splitedMessage) {
		for(var keyWord in keyWords) {
			var lowerCaseWord = splitedMessage[word].toLowerCase();
			var lowerCaseKeyword = keyWords[keyWord].toLowerCase();

			if(lowerCaseWord == lowerCaseKeyword) {
				return true;
			}
		}
	}

	return false;
}

module.exports = Conversation;
<commit_msg>- enhance species detection<commit_after>var Conversation = function(speciesList) {
	this.lastAnswer = null;
	this.lastAction = Date.now();
	this.firstmessage = true;
	this.inFindingProcess = false;

	this.speciesList = speciesList;

	let commonNames = speciesList.map((obj)=>obj.triname);
	let scientificNames = speciesList.map((obj)=>obj.sciname);
  this.speciesNames = commonNames.concat(scientificNames);

  this.speciesNames.map((name)=>name.split(" "));
  this.speciesNames  = [].concat.apply([], this.speciesNames);

  this.speciesNames= this.speciesNames.filter((name)=> name.toLowerCase().trim() !="muschel" && name.toLowerCase().trim()!= "mussel")
  this.speciesNames = this.speciesNames.filter((name)=> name.toLowerCase().trim() !="clam");
  this.speciesNames = this.speciesNames.filter((name)=> name.toLowerCase().trim() !="fisch" && name.toLowerCase().trim()!= "fish")

	this.location = null;
	this.species = null;

	this.isActive = function(){
			let diff = this.lastAction - Date.now();
			let fiveMinInMs = 1000 * 60 * 5;
			return diff <= fiveMinInMs;

	};
	this.setLocation = function(location){
		this.location = location
	};
	this.processMessage = function(message) {
		console.log("Input> " + message);
    this.lastAction = Date.now();
		var splitedMessage = message.split(/[ ,]+/);

		if(this.firstmessage || match(splitedMessage,["hey", "moin", "hallo", "hi", "servus"])) {
			this.firstmessage = false;
			var startText = 'Hey du, ich bin BioDiv und kann weiterhelfen, wenn du seltene Muscheln / Säugetiere oder Fische in deiner Umgebung gesichtet hast. ';

			var answerOptions = ["Hilfe", "Fund melden"];

			return { answer: startText, answerOptions: answerOptions };
		}
		let yes = ["ja", "ok", "jo", "jup"];
		let no = ["nein", "nö", "ne", "auf gar keinen fall", "halt die fresse"];

    if(match(splitedMessage, yes.concat(no))) {
			var userAnswer = message;
			var answerOptions = [];

			this.lastAnswer = null;
			if(match(splitedMessage, yes)) {
				var jaText = "Ich halte Dich auf dem Laufenden. 👍";
				return { answer: jaText, answerOptions: answerOptions };
			} else {
				var neinText = "Ok, frag' einfach, wenn du wissen willst, wie der Status ist. 😁 Ich bin bis auf weiteres stumm. 🙈🙊🙉";
				return { answer: neinText, answerOptions: answerOptions };
			}

		}

		if(match([message], ["Fund melden"])) {
			var answerOptions = [];

			var helpText = 'ℹ Alles klar du, dann lass uns loslegen und deinen Fund zusammen aufnehmen! Was für eine Spezies hast du denn gesehen?';

      this.inFindingProcess = true;

			return { answer: helpText, answerOptions: answerOptions };
		}

		if(this.inFindingProcess){

    	console.log(splitedMessage);
    	console.log(this.speciesCommonNames);
    	console.log(this.speciesSientificNames);

    	if(match([message],["Location set"])){
        return {
          answer: "Nun weiß ich schon wo du dich befindest, Vielleicht möchtest du noch mehr angeben?",
          answerOptions: ["Nachweisquallität", "Nachweismethode", "Fund speichern"]
        };
			}
			else if(match(splitedMessage,["Nachweismethode"])){
        return {
          answer: "Okay welche der folgenden Nachweismethoden wurde verwendet?",
          answerOptions: [""]
        };
			}
			else if(match(splitedMessage,["Nachweisquallität"])){
        return {
          answer: "Wie war die genaue Nachweisquallität?",
          answerOptions: ["Nachweisquallität", "Nachweismethode"]
        };
			}
    	else if(match(splitedMessage,this.speciesNames)){

				let potentialSpecies = this.speciesList.filter((species)=> {

					let nameSplits = species.triname.split(" ");
					nameSplits = nameSplits.concat(species.sciname.split(" "));

          nameSplits = nameSplits.filter((name)=> name.toLowerCase().trim() !="muschel" && name.toLowerCase().trim()!= "mussel")
          nameSplits = nameSplits.filter((name)=> name.toLowerCase().trim() !="clam");
          nameSplits = nameSplits.filter((name)=> name.toLowerCase().trim() !="fisch" && name.toLowerCase().trim()!= "fish")
					console.log("nameSplits",nameSplits);
					return match(splitedMessage,nameSplits )
        });

				console.log("potentialSpecies", potentialSpecies);

				if(potentialSpecies.length == 0 ){
          return {
            answer: "Irgendwas ist hier schief gelaufen :( Ich konnte irgendwie keine Spezies finden ... "
          };
				}
				else if (potentialSpecies.length == 1 ){
          return {
            answer: "Sehr schön, hab ich verstanden du hast " + message + " bei dir gesehen. " +
            "\n Es wäre super wenn du mir noch deinen Standort zeigen könntest?",
            locationRequest: true
          };
				}else {
          return {
            answer: "Huch da brauch ich noch ein wenig mehr Infos.\nEs gibt mehrere Spezies, bitte wähle die richtige aus: ",
            answerOptions: potentialSpecies.map((species)=>species.triname)
          };
				}

			}

    	else if(this.speciesName == null){

        console.log("Choose species text ", this.speciesCommonNames);
        return {
          answer: "Leider habe ich dich nicht so recht verstanden, hier einige Vorschläge was für Spezies ich so im Angebot hätte",
          answerOptions: this.speciesList.map((species)=>species.triname)
        }

			}

		}

		return {
      answer: "Ich konnte dich leider nicht verstehen... 😰",
      answerOptions: ["Hilfe"]
    }

	};

	return this;
};

function match(splitedMessage, keyWords) {

	for(var word in splitedMessage) {
		for(var keyWord in keyWords) {
			var lowerCaseWord = splitedMessage[word].toLowerCase();
			var lowerCaseKeyword = keyWords[keyWord].toLowerCase();

			if(lowerCaseWord == lowerCaseKeyword) {
				return true;
			}
		}
	}

	return false;
}

module.exports = Conversation;
<|endoftext|>


<commit_before>'use strict';
/*
  Many thanks to https://github.com/howdyai/botkit/blob/master/slack_bot.js
  Where most of this was stolen from
*/

const excuse = require('huh');
const os = require('os');

const hi = (bot, message) => {
  bot.api.reactions.add({
    timestamp: message.ts,
    channel: message.channel,
    name: 'robot_face',
  }, function(err) {
    if (err) {
      bot.botkit.log('Failed to add emoji reaction :(', err);
    }
  });
  bot.reply(message, 'Hello.');
};

const shutdown = (bot, message) => {
  bot.startConversation(message, function(err, convo) {
    convo.ask('Are you sure you want me to shutdown?', [
      {
        pattern: bot.utterances.yes,
        callback: function(response, convo) {
          convo.say("Alright Sir, if you'll not be needing me, I'll close down for awhile");
          convo.next();
          setTimeout(function() {
            process.exit();
          }, 3000);
        }
      },
      {
        pattern: bot.utterances.no,
        default: true,
        callback: function(response, convo) {
          convo.say('*ZORGBORT LIVES!*');
          convo.next();
        }
      }
    ]);
  });
};

const uptime = (bot, message) => {
  const formatUptime = function(uptime) {
    var unit = 'second';
    if (uptime > 60) {
      uptime = uptime / 60;
      unit = 'minute';
    }
    if (uptime > 60) {
      uptime = uptime / 60;
      unit = 'hour';
    }
    if (uptime != 1) {
      unit = unit + 's';
    }

    uptime = uptime + ' ' + unit;
    return uptime;
  };
  const hostname = os.hostname();
  const uptime = formatUptime(process.uptime());
  const reponse = ':robot_face: I am a bot named <@' + bot.identity.name +
          '>. I have been running for ' + uptime + ' on ' + hostname + '.';
  bot.reply(message, reponse);
};

const defaultExcuse = (bot, message) => {
  const msg = message.text;
  const reason = excuse.get('en');
  bot.reply(message, `Sorry, I don't know how to _${msg}_. It must be *${reason}!*`);
};

const mention = ['direct_message', 'direct_mention', 'mention'];
module.exports = bot => {
  bot.hears(['hello', 'hi', 'howdy', 'sup', 'howzit'], mention, hi);
  bot.hears(['shutdown', 'powerdown'], mention, shutdown);
  bot.hears(['uptime', 'identify yourself', 'who are you', 'what is your name'], mention, uptime);
  bot.hears('', mention, defaultExcuse);
};
<commit_msg>Wave when people say hello<commit_after>'use strict';
/*
  Many thanks to https://github.com/howdyai/botkit/blob/master/slack_bot.js
  Where most of this was stolen from
*/

const excuse = require('huh');
const os = require('os');

const hi = (bot, message) => {
  bot.api.reactions.add({
    timestamp: message.ts,
    channel: message.channel,
    name: 'robot_face',
  }, function(err) {
    if (err) {
      bot.botkit.log('Failed to add emoji reaction :(', err);
    }
  });
  bot.reply(message, 'Hello.');
};

const indirectHi = (bot, message) => {
  bot.api.reactions.add({
    timestamp: message.ts,
    channel: message.channel,
    name: 'wave',
  }, function(err) {
    if (err) {
      bot.botkit.log('Failed to add emoji reaction :(', err);
    }
  });
};

const shutdown = (bot, message) => {
  bot.startConversation(message, function(err, convo) {
    convo.ask('Are you sure you want me to shutdown?', [
      {
        pattern: bot.utterances.yes,
        callback: function(response, convo) {
          convo.say("Alright Sir, if you'll not be needing me, I'll close down for awhile");
          convo.next();
          setTimeout(function() {
            process.exit();
          }, 3000);
        }
      },
      {
        pattern: bot.utterances.no,
        default: true,
        callback: function(response, convo) {
          convo.say('*ZORGBORT LIVES!*');
          convo.next();
        }
      }
    ]);
  });
};

const uptime = (bot, message) => {
  const formatUptime = function(uptime) {
    var unit = 'second';
    if (uptime > 60) {
      uptime = uptime / 60;
      unit = 'minute';
    }
    if (uptime > 60) {
      uptime = uptime / 60;
      unit = 'hour';
    }
    if (uptime != 1) {
      unit = unit + 's';
    }

    uptime = uptime + ' ' + unit;
    return uptime;
  };
  const hostname = os.hostname();
  const uptime = formatUptime(process.uptime());
  const reponse = ':robot_face: I am a bot named <@' + bot.identity.name +
          '>. I have been running for ' + uptime + ' on ' + hostname + '.';
  bot.reply(message, reponse);
};

const defaultExcuse = (bot, message) => {
  const msg = message.text;
  const reason = excuse.get('en');
  bot.reply(message, `Sorry, I don't know how to _${msg}_. It must be *${reason}!*`);
};

const mention = ['direct_message', 'direct_mention', 'mention'];
module.exports = bot => {
  bot.hears(['hello', 'hi', 'howdy', 'sup', 'howzit'], mention, hi);
  bot.hears(['hello', 'hi', 'howdy', 'sup', 'howzit', 'good morning'], 'message_received', indirectHi);
  bot.hears(['shutdown', 'powerdown'], mention, shutdown);
  bot.hears(['uptime', 'identify yourself', 'who are you', 'what is your name'], mention, uptime);
  bot.hears('', mention, defaultExcuse);
};
<|endoftext|>


<commit_before>import React from 'react';
import autosize from 'autosize';
import { t, props } from 'tcomb-react';

const UPDATE = 'autosize:update',
  DESTROY = 'autosize:destroy',
  RESIZED = 'autosize:resized';

export const Props = {
  rows: t.maybe(t.Integer),
  maxRows: t.maybe(t.Integer),
  onResize: t.maybe(t.Function)
};

/** A light replacement for built-in textarea component
 * which automaticaly adjusts its height to match the content
 * @param onResize - called whenever the textarea resizes
 * @param rows - minimum number of visible rows
 * @param maxRows - maximum number of visible rows
 */
@props(Props, { strict: false })
export default class TextareaAutosize extends React.Component {

  static defaultProps = {
    rows: 1,
    maxRows: 5
  };

  state = {
    maxHeight: null
  }

  componentDidMount() {
    const { value, defaultValue, onResize } = this.props;

    autosize(this.textarea);

    if (this.hasReachedMaxRows(value || defaultValue)) {
      this.updateMaxHeight(value || defaultValue);

      // this trick is needed to force "autosize" to activate the scrollbar
      this.dispatchEvent(DESTROY);
      setTimeout(() => autosize(this.textarea));
    }

    if (onResize) {
      this.textarea.addEventListener(RESIZED, this.props.onResize);
    }
  }

  componentWillUnmount() {
    if (this.props.onResize) {
      this.textarea.removeEventListener(RESIZED, this.props.onResize);
    }
    this.dispatchEvent(DESTROY);
  }

  dispatchEvent = (EVENT_TYPE) => {
    const event = document.createEvent('Event');
    event.initEvent(EVENT_TYPE, true, false);

    this.textarea.dispatchEvent(event);
  };

  getValue = ({ valueLink, value }) => valueLink ? valueLink.value : value;

  hasReachedMaxRows = (value) => {
    const { maxRows } = this.props;

    const numberOfRows = (value || '').split('\n').length;

    return t.Number.is(maxRows) && numberOfRows >= maxRows;
  }

  updateMaxHeight = (value) => {
    const {
      props: { maxRows },
      state: { maxHeight }
    } = this;

    const hasReachedMaxRows = this.hasReachedMaxRows(value);

    if (!maxHeight && hasReachedMaxRows) {
      const numberOfRows = (value || '').split('\n').length;
      const computedStyle = window.getComputedStyle(this.textarea);

      const paddingTop = parseFloat(computedStyle.getPropertyValue('padding-top'), 10);
      const paddingBottom = parseFloat(computedStyle.getPropertyValue('padding-top'), 10);
      const verticalPadding = (paddingTop || 0) + (paddingBottom || 0);

      const borderTopWidth = parseInt(computedStyle.getPropertyValue('border-top-width'), 10);
      const borderBottomWidth = parseInt(computedStyle.getPropertyValue('border-bottom-width'), 10);
      const verticalBorderWidth = (borderTopWidth || 0) + (borderBottomWidth || 0);

      const height = this.textarea.offsetHeight - verticalPadding - verticalBorderWidth;

      this.setState({
        maxHeight: height / numberOfRows * maxRows
      });

      return true;
    } else if (maxHeight && !hasReachedMaxRows) {
      this.setState({ maxHeight: null });

      return false;
    }

  }

  onChange = e => {
    this.updateMaxHeight(e.target.value);
    this.props.onChange && this.props.onChange(e);
  }

  getLocals = () => {
    const {
      props: { onResize, maxRows, onChange, style, ...props }, // eslint-disable-line no-unused-vars
      state: { maxHeight }
    } = this;

    return {
      ...props,
      style: maxHeight ? { ...style, maxHeight } : style,
      onChange: this.onChange
    };
  }

  render() {
    const { children, ...locals } = this.getLocals();
    return (
      <textarea {...locals} ref={(ref) => { this.textarea = ref; }}>
        {children}
      </textarea>
    );
  }

  componentDidUpdate(prevProps) {
    if (this.getValue(prevProps) !== this.getValue(this.props)) {
      this.dispatchEvent(UPDATE);
    }
  }

}
<commit_msg>remove defaultProp for maxRows<commit_after>import React from 'react';
import autosize from 'autosize';
import { t, props } from 'tcomb-react';

const UPDATE = 'autosize:update',
  DESTROY = 'autosize:destroy',
  RESIZED = 'autosize:resized';

export const Props = {
  rows: t.maybe(t.Integer),
  maxRows: t.maybe(t.Integer),
  onResize: t.maybe(t.Function)
};

/** A light replacement for built-in textarea component
 * which automaticaly adjusts its height to match the content
 * @param onResize - called whenever the textarea resizes
 * @param rows - minimum number of visible rows
 * @param maxRows - maximum number of visible rows
 */
@props(Props, { strict: false })
export default class TextareaAutosize extends React.Component {

  static defaultProps = {
    rows: 1
  };

  state = {
    maxHeight: null
  }

  componentDidMount() {
    const { value, defaultValue, onResize } = this.props;

    autosize(this.textarea);

    if (this.hasReachedMaxRows(value || defaultValue)) {
      this.updateMaxHeight(value || defaultValue);

      // this trick is needed to force "autosize" to activate the scrollbar
      this.dispatchEvent(DESTROY);
      setTimeout(() => autosize(this.textarea));
    }

    if (onResize) {
      this.textarea.addEventListener(RESIZED, this.props.onResize);
    }
  }

  componentWillUnmount() {
    if (this.props.onResize) {
      this.textarea.removeEventListener(RESIZED, this.props.onResize);
    }
    this.dispatchEvent(DESTROY);
  }

  dispatchEvent = (EVENT_TYPE) => {
    const event = document.createEvent('Event');
    event.initEvent(EVENT_TYPE, true, false);

    this.textarea.dispatchEvent(event);
  };

  getValue = ({ valueLink, value }) => valueLink ? valueLink.value : value;

  hasReachedMaxRows = (value) => {
    const { maxRows } = this.props;

    const numberOfRows = (value || '').split('\n').length;

    return t.Number.is(maxRows) && numberOfRows >= maxRows;
  }

  updateMaxHeight = (value) => {
    const {
      props: { maxRows },
      state: { maxHeight }
    } = this;

    const hasReachedMaxRows = this.hasReachedMaxRows(value);

    if (!maxHeight && hasReachedMaxRows) {
      const numberOfRows = (value || '').split('\n').length;
      const computedStyle = window.getComputedStyle(this.textarea);

      const paddingTop = parseFloat(computedStyle.getPropertyValue('padding-top'), 10);
      const paddingBottom = parseFloat(computedStyle.getPropertyValue('padding-top'), 10);
      const verticalPadding = (paddingTop || 0) + (paddingBottom || 0);

      const borderTopWidth = parseInt(computedStyle.getPropertyValue('border-top-width'), 10);
      const borderBottomWidth = parseInt(computedStyle.getPropertyValue('border-bottom-width'), 10);
      const verticalBorderWidth = (borderTopWidth || 0) + (borderBottomWidth || 0);

      const height = this.textarea.offsetHeight - verticalPadding - verticalBorderWidth;

      this.setState({
        maxHeight: height / numberOfRows * maxRows
      });

      return true;
    } else if (maxHeight && !hasReachedMaxRows) {
      this.setState({ maxHeight: null });

      return false;
    }

  }

  onChange = e => {
    this.updateMaxHeight(e.target.value);
    this.props.onChange && this.props.onChange(e);
  }

  getLocals = () => {
    const {
      props: { onResize, maxRows, onChange, style, ...props }, // eslint-disable-line no-unused-vars
      state: { maxHeight }
    } = this;

    return {
      ...props,
      style: maxHeight ? { ...style, maxHeight } : style,
      onChange: this.onChange
    };
  }

  render() {
    const { children, ...locals } = this.getLocals();
    return (
      <textarea {...locals} ref={(ref) => { this.textarea = ref; }}>
        {children}
      </textarea>
    );
  }

  componentDidUpdate(prevProps) {
    if (this.getValue(prevProps) !== this.getValue(this.props)) {
      this.dispatchEvent(UPDATE);
    }
  }

}
<|endoftext|>


<commit_before>/**
 * @ngdoc directive
 * @name ui.svg.uiSvgZoom
 * @requires ui.svg.d3
 */
(function (app) {

    app.directive('uiSvgZoom', [
        'd3',
        function (d3) {
            return {
                restrict: 'A',
                link: function (scope, el, attr) {

                    var $svg = $(el).closest('svg');

                    var zoom = d3.behavior.zoom()
                        .scaleExtent([0.25, 10])
                        .on("zoom", function () {
                            d3.select(el[0]).attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
                        });

                    d3.select($svg[0]).call(zoom);
                }
            }
        }
    ])

})(angular.module('thinkingmedia.ui.svg'));<commit_msg>small fix for zoom<commit_after>/**
 * @ngdoc directive
 * @name ui.svg.uiSvgZoom
 *
 * @description
 *
 * Applies the d3 Zoom behavior to an element by updating a transform.
 *
 * @requires ui.svg.d3
 * @element g
 * @restrict A
 */
(function (app) {

    app.directive('uiSvgZoom', [
        'd3',
        function (d3) {
            return {
                restrict: 'A',
                link: function (scope, el, attr) {

                    var zoom = d3.behavior.zoom()
                        .scaleExtent([0.25, 10])
                        .on("zoom", function () {
                            d3.select(el[0]).attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
                        });

                    var $svg = el.closest('svg');
                    if($svg.length > 0) {
                        d3.select($svg[0]).call(zoom);
                    }
                }
            }
        }
    ])

})(angular.module('thinkingmedia.ui.svg'));<|endoftext|>