<commit_before>// Node/npm deps
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);

// Main app URL
app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});

// CSS/JS
app.use('/css', express.static(__dirname + '/css'));
app.use('/js', express.static(__dirname + '/js'));

/**
 * Someone connected.
 */
io.on('connection', function(socket){
  console.log('user: connected');

  /**
   * A new shape appears!
   */
  socket.on('add', function(props){
    console.log('ADD', props);
    io.emit('add', props);
  });

  /**
   * A shape is being dragged.
   */
  socket.on('change', function(props){
    console.log('CHANGE', props);
    io.emit('change', props);
  });

  /**
   * Someone got bored.
   */
  socket.on('disconnect', function(){
    console.log('user: disconnected');
    io.emit('status', 'someone left');
  });
});

/**
 * Listen for users to connect
 */
http.listen(3000, function(){
  console.log('Listening on port 3000');
});
<commit_msg>:construction: try to use heroku's port<commit_after>// Node/npm deps
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var port = process.env.PORT || 3000;

// Main app URL
app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});

// CSS/JS
app.use('/css', express.static(__dirname + '/css'));
app.use('/js', express.static(__dirname + '/js'));

/**
 * Someone connected.
 */
io.on('connection', function(socket){
  console.log('user: connected');

  /**
   * A new shape appears!
   */
  socket.on('add', function(props){
    console.log('ADD', props);
    io.emit('add', props);
  });

  /**
   * A shape is being dragged.
   */
  socket.on('change', function(props){
    console.log('CHANGE', props);
    io.emit('change', props);
  });

  /**
   * Someone got bored.
   */
  socket.on('disconnect', function(){
    console.log('user: disconnected');
    io.emit('status', 'someone left');
  });
});

/**
 * Listen for users to connect
 */
http.listen(port, function(){
  console.log('Listening on port ' + port);
});
<|endoftext|>


<commit_before>'use strict';

const version = '0.0.0';

const esprima = require('esprima');
const walk = require( 'esprima-walk' ).walkAddParent;
const escodegen = require('escodegen');

// Iterations count for detection the infinite loop.
const LOOP_ITERATIONS_COUNT = 300;
const INFINITE_LOOP_EXCEPTION_MESSAGE = 'Perhabs there is some infinite loop in the code';

module.exports = JSJail();

function JSJail() {

    let t = {};

    t.version = version;
    t.run = run;

    return t;

    /**
     * Runs your code into the JS-jail.
     *
     * @public
     * @param code
     * @param environment
     */
    function run(code, environment) {

        const ast = esprima.parse(code);

        if (window) {

            makeStubDeclarations(ast, Object.getOwnPropertyNames(window));

        }

        wrapAllLoops(ast);

        code = escodegen.generate(ast);

        let names = [];
        let values = [];

        if (environment) {

            names = Object.keys(environment);
            names.forEach(function (key) {

                values.push(environment[key]);

            });

        }

        // Add code as last parameter of function for apply call.
        names.push(code);

        const f = Function.apply(this, names);

        f.apply(this, values);

    }

    /**
     * This method is for struggle with some possible infinite loops.
     *
     * @private
     * @param {Object} ast The AST of source code.
     */
    function wrapAllLoops(ast) {

        const loopStatements = ["ForInStatement", "WhileStatement", "DoWhileStatement"];
        const beforeLoopBody = "var a = 0;";
        const innerLoopBody = "if (a === " + LOOP_ITERATIONS_COUNT +
                               ") { throw new Error('" + INFINITE_LOOP_EXCEPTION_MESSAGE + "') }; a++;";

        walk(ast, function (node) {

            var result = loopStatements.indexOf(node.type);

            if (result != -1) {

                node.parent.body.unshift(esprima.parse(beforeLoopBody));
                node.body.body.unshift(esprima.parse(innerLoopBody));

            }

        });

    }

    /**
     * Makes stubs of variables for avoid the changing of outside environment which has these variables too.
     *
     * @private
     * @param {Array} variables The name list of variables for stubs.
     * @param {Object} ast The AST of source code.
     */
    function makeStubDeclarations(ast, variables) {

        variables.forEach(function(name) {

            let stub = 'var ' + name + ';';
            ast.body.unshift(esprima.parse(stub));

        });

    }

}<commit_msg>add init method<commit_after>'use strict';

const version = '0.0.0';

const esprima = require('esprima');
const walk = require( 'esprima-walk' ).walkAddParent;
const escodegen = require('escodegen');

// Iterations count for detection the infinite loop.
const LOOP_ITERATIONS_COUNT = 300;
const INFINITE_LOOP_EXCEPTION_MESSAGE = 'Perhabs there is some infinite loop in the code';

module.exports = JSJail();

function JSJail() {

    let code;

    let t = {};

    t.version = version;
    t.init = init;
    t.run = run;

    return t;

    /**
     * Initializes your code for a further execution into the jail.
     *
     * @param _code The code which will execute by 'run' method.
     */
    function init(_code) {

        const ast = esprima.parse(_code);

        if (window) {

            makeStubDeclarations(ast, Object.getOwnPropertyNames(window));

        }

        wrapAllLoops(ast);

        code = escodegen.generate(ast);

    }

    /**
     * Runs your code into the JS-jail.
     *
     * @public
     * @param environment
     */
    function run(environment) {

        if (!code) {

            throw new Error('At first the code to execute must initialize by init method!');

        }

        let names = [];
        let values = [];

        // Separates environment into two arrays: names and values to the following initialization of Function object.
        if (environment) {

            names = Object.keys(environment);
            names.forEach(function (key) {

                values.push(environment[key]);

            });

        }

        // Add code as the last parameter of function for an apply call.
        names.push(code);

        const f = Function.apply(this, names);

        f.apply(this, values);

    }

    /**
     * This method is for struggle with some possible infinite loops.
     *
     * @private
     * @param {Object} ast The AST of source code.
     */
    function wrapAllLoops(ast) {

        const loopStatements = ["ForOfStatement", "ForStatement", "ForInStatement", "WhileStatement", "DoWhileStatement"];
        const beforeLoopBody = "var a = 0;";
        const innerLoopBody = "if (a === " + LOOP_ITERATIONS_COUNT +
                               ") { throw new Error('" + INFINITE_LOOP_EXCEPTION_MESSAGE + "') }; a++;";

        walk(ast, function (node) {

            var result = loopStatements.indexOf(node.type);

            if (result != -1) {

                node.parent.body.unshift(esprima.parse(beforeLoopBody));
                node.body.body.unshift(esprima.parse(innerLoopBody));

            }

        });

    }

    /**
     * Makes stubs of variables for avoid the changing of outside environment which has these variables too.
     *
     * @private
     * @param {Array} variables The name list of variables for stubs.
     * @param {Object} ast The AST of source code.
     */
    function makeStubDeclarations(ast, variables) {

        variables.forEach(function(name) {

            let stub = 'var ' + name + ';';
            ast.body.unshift(esprima.parse(stub));

        });

    }

}<|endoftext|>


<commit_before>;(function (root) {
  'use strict'

  var _ = {

    util: {

      asc: function asc(a, b) {
        return a > b
      },
      desc: function desc(a, b) {
        return a < b
      },
      truthy: function truthy(value) {
        return value === true
      },
      firstOr: function firstOr(arr, value) {
        return arr.length ? arr[0] : value
      }

    },

    chain: function chain(arr) {
      function chainer(collection) {
        var self = {
          get: function get() {
            return collection
          }
        }

        for (var method in _) {
          if (typeof _[method] === 'function') {
            (function (oldMethod) {
              self[method] = function () {
                var args = _.toArray(arguments)
                args.unshift(collection)

                return chainer(oldMethod.apply(null, args))
              }
            })(_[method])
          } else {
            self[method] = _[method]
          }
        }

        return self
      }

      return chainer(arr)
    },

    contains: function contains(arr, value) {
      return Boolean(~arr.indexOf(value))
    },

    reduce: function reduce(arr, callback, initalValue) {
      return arguments.length > 2
        ? arr.reduce(callback, initalValue)
        : arr.reduce(callback)
    },

    each: function each(arr, callback) {
      return _.reduce(arr, function (collection, value, index, arr) {
        callback(value, index, arr)
      }, undefined)
    },

    map: function map(arr, callback) {
      return _.reduce(arr, function (collection, value, index, arr) {
        collection.push(callback(value, index, arr))

        return collection
      }, [])
    },

    filter: function filter(arr, callback) {
      return _.reduce(arr, function (collection, value, index, arr) {

        if (_.util.truthy(callback(value, index, arr)))
          collection.push(value)

        return collection
      }, [])
    },

    some: function some(arr, callback) {
      return _.chain(arr)
        .map(callback)
        .filter(_.util.truthy)
        .get()
        .length > 0
    },

    every: function every(arr, callback) {
      return _.chain(arr)
        .map(callback)
        .filter(_.util.truthy)
        .get()
        .length === arr.length
    },

    flatten: function flatten(arr) {
      return _.reduce(arr, function (collection, value) {
        return collection.concat(value)
      }, [])
    },

    unique: function unique(arr) {
      return _.reduce(arr, function (collection, value) {

        if (!_.contains(collection, value))
          collection.push(value)

        return collection
      }, [])
    },

    toArray: function toArray(arrlike) {
      return Array.prototype.slice.call(arrlike)
    },

    groupBy: function groupBy(arr, key) {
      return _.chain(arr)
        .extract(key)
        .unique()
        .map(function (group) {
          return _.filter(arr, function (item) {
            return item[key] === group
          })
        })
        .get()
    },

    indexes: function indexes(arr) {
      return _.map(arr, function (_, index) {
        return index
      })
    },

    extract: function extract(arr, key) {
      return _.map(arr, function (item) {
        return item[key]
      })
    },

    head: function head(arr) {
      return _.util.firstOr(arr, undefined)
    },

    tail: function tail(arr) {
      return _.filter(arr, function (_, i) {
        return i > 0
      })
    },

    take: function take(arr, until) {
      return _.filter(arr, function (_, i) {
        return i < until
      })
    },

    find: function find(arr, callback) {
      return _.chain(arr)
        .filter(callback)
        .head()
        .get()
    },

    fill: function fill(arr, target) {
      return _.map(arr, function (value, index, arr) {
        return typeof target === 'function'
          ? target(value, index, arr)
          : target
      })
    },

    reverse: function reverse(arr) {
      return _.chain(arr)
        .indexes()
        .sort(_.util.desc)
        .map(function (index) {
          return arr[index]
        })
        .get()
    },

    sort: function sort(arr, callback) {
      return arr.sort(callback)
    },

    max: function max(arr) {
      return _.reduce(arr, function (current, value) {
        return current < value
          ? value
          : current
      }, _.util.firstOr(arr, Infinity))
    },

    min: function min(arr) {
      return _.reduce(arr, function (current, value) {
        return current > value
          ? value
          : current
      }, _.util.firstOr(arr, -Infinity))
    },
  }

  // If it's a nodejs enviroment, export it. Othewise assume enviroment is a browser.
  if (module && module.exports) {
    module.exports = _
  } else {
    root._ = root.reduceIt = _
  }

}(this));<commit_msg>Removing function name repetition<commit_after>;(function (root) {
  'use strict'

  var _ = {

    util: {

      asc: function (a, b) {
        return a > b
      },
      desc: function (a, b) {
        return a < b
      },
      truthy: function (value) {
        return value === true
      },
      firstOr: function (arr, value) {
        return arr.length ? arr[0] : value
      }

    },

    chain: function (arr) {
      function chainer(collection) {
        var self = {
          get: function () {
            return collection
          }
        }

        for (var method in _) {
          if (typeof _[method] === 'function') {
            (function (oldMethod) {
              self[method] = function () {
                var args = _.toArray(arguments)
                args.unshift(collection)

                return chainer(oldMethod.apply(null, args))
              }
            })(_[method])
          } else {
            self[method] = _[method]
          }
        }

        return self
      }

      return chainer(arr)
    },

    contains: function (arr, value) {
      return Boolean(~arr.indexOf(value))
    },

    reduce: function (arr, callback, initalValue) {
      return arguments.length > 2
        ? arr.reduce(callback, initalValue)
        : arr.reduce(callback)
    },

    each: function (arr, callback) {
      return _.reduce(arr, function (collection, value, index, arr) {
        callback(value, index, arr)
      }, undefined)
    },

    map: function (arr, callback) {
      return _.reduce(arr, function (collection, value, index, arr) {
        collection.push(callback(value, index, arr))

        return collection
      }, [])
    },

    filter: function (arr, callback) {
      return _.reduce(arr, function (collection, value, index, arr) {

        if (_.util.truthy(callback(value, index, arr)))
          collection.push(value)

        return collection
      }, [])
    },

    some: function (arr, callback) {
      return _.chain(arr)
        .map(callback)
        .filter(_.util.truthy)
        .get()
        .length > 0
    },

    every: function (arr, callback) {
      return _.chain(arr)
        .map(callback)
        .filter(_.util.truthy)
        .get()
        .length === arr.length
    },

    flatten: function (arr) {
      return _.reduce(arr, function (collection, value) {
        return collection.concat(value)
      }, [])
    },

    unique: function (arr) {
      return _.reduce(arr, function (collection, value) {

        if (!_.contains(collection, value))
          collection.push(value)

        return collection
      }, [])
    },

    toArray: function (arrlike) {
      return Array.prototype.slice.call(arrlike)
    },

    groupBy: function (arr, key) {
      return _.chain(arr)
        .extract(key)
        .unique()
        .map(function (group) {
          return _.filter(arr, function (item) {
            return item[key] === group
          })
        })
        .get()
    },

    indexes: function (arr) {
      return _.map(arr, function (_, index) {
        return index
      })
    },

    extract: function (arr, key) {
      return _.map(arr, function (item) {
        return item[key]
      })
    },

    head: function (arr) {
      return _.util.firstOr(arr, undefined)
    },

    tail: function (arr) {
      return _.filter(arr, function (_, i) {
        return i > 0
      })
    },

    take: function (arr, until) {
      return _.filter(arr, function (_, i) {
        return i < until
      })
    },

    find: function (arr, callback) {
      return _.chain(arr)
        .filter(callback)
        .head()
        .get()
    },

    fill: function (arr, target) {
      return _.map(arr, function (value, index, arr) {
        return typeof target === 'function'
          ? target(value, index, arr)
          : target
      })
    },

    reverse: function (arr) {
      return _.chain(arr)
        .indexes()
        .sort(_.util.desc)
        .map(function (index) {
          return arr[index]
        })
        .get()
    },

    sort: function (arr, callback) {
      return arr.sort(callback)
    },

    max: function (arr) {
      return _.reduce(arr, function (current, value) {
        return current < value
          ? value
          : current
      }, _.util.firstOr(arr, Infinity))
    },

    min: function (arr) {
      return _.reduce(arr, function (current, value) {
        return current > value
          ? value
          : current
      }, _.util.firstOr(arr, -Infinity))
    },
  }

  // If it's a nodejs enviroment, export it. Othewise assume enviroment is a browser.
  if (module && module.exports) {
    module.exports = _
  } else {
    root._ = root.reduceIt = _
  }

}(this));<|endoftext|>


<commit_before>/**
 * index.js
 */
"use strict";
{
  /* api */
  const {Input, Output} = require("./modules/native-message");
  const {concatArgs, isString, throwErr} = require("./modules/common");
  const {
    convUriToFilePath, createDir, createFile, getFileNameFromFilePath,
    getFileTimestamp, isDir, isExecutable, isFile, removeDir, readFile,
  } = require("./modules/file-util");
  const {execFile} = require("child_process");
  const os = require("os");
  const path = require("path");
  const process = require("process");

  /* constants */
  const {
    EDITOR_CONFIG_GET, EDITOR_CONFIG_RES, HOST, LABEL, LOCAL_FILE_VIEW,
    PROCESS_CHILD, TMP_FILES, TMP_FILES_PB, TMP_FILES_PB_REMOVE,
    TMP_FILE_CREATE, TMP_FILE_DATA_PORT, TMP_FILE_GET, TMP_FILE_RES,
  } = require("./modules/constant");
  const APP = `${process.pid}`;
  const CHAR = "utf8";
  const CMD_ARGS = "cmdArgs";
  const DIR_TMP = [os.tmpdir(), LABEL, APP];
  const DIR_TMP_FILES = [...DIR_TMP, TMP_FILES];
  const DIR_TMP_FILES_PB = [...DIR_TMP, TMP_FILES_PB];
  const EDITOR_PATH = "editorPath";
  const FILE_AFTER_ARGS = "fileAfterCmdArgs";

  /* variables */
  const vars = {
    [CMD_ARGS]: [],
    [EDITOR_PATH]: "",
    [FILE_AFTER_ARGS]: false,
  };

  /**
   * host message
   * @param {*} message - message
   * @param {string} status - status
   * @returns {Object} - host message object
   */
  const hostMsg = (message, status) => ({
    [HOST]: {
      message, status,
      pid: APP,
    },
  });

  /**
   * handle rejection
   * @param {*} e - Error or any
   * @returns {boolean} - false
   */
  const handleReject = e => {
    e = (new Output()).encode(hostMsg(e, "error"));
    e && process.stdout.write(e);
    return false;
  };

  /* child process */
  /**
   * spawn child process
   * @param {string} file - file path
   * @param {string} app - app path
   * @returns {Object} - Promise.<ChildProcess>
   */
  const spawnChildProcess = async (file, app = vars[EDITOR_PATH]) => {
    if (await !isFile(file)) {
      return writeStdout(hostMsg(`${file} is not a file.`, "warn"));
    }
    if (await !isExecutable(app)) {
      return writeStdout(hostMsg(`${app} is not executable.`, "warn"));
    }
    let args = vars[CMD_ARGS] || [];
    const pos = vars[FILE_AFTER_ARGS] || false;
    const argA = pos && args || [file.replace(/\\/g, "\\\\")];
    const argB = pos && [file.replace(/\\/g, "\\\\")] || args;
    const opt = {
      cwd: null,
      encoding: CHAR,
      env: process.env,
    };
    args = await concatArgs(argA, argB);
    return execFile(app, args, opt, (e, stdout, stderr) => {
      if (e) {
        e = (new Output()).encode(e);
        e && process.stderr.write(e);
      }
      if (stderr) {
        stderr = (new Output()).encode(
          hostMsg(`${stderr}: ${app}`, `${PROCESS_CHILD}_stderr`)
        );
        stderr && process.stdout.write(stderr);
      }
      if (stdout) {
        stdout = (new Output()).encode(
          hostMsg(`${stdout}: ${app}`, `${PROCESS_CHILD}_stdout`)
        );
        stdout && process.stdout.write(stdout);
      }
    });
  };

  /* output */
  /**
   * write stdout
   * @param {*} msg - message
   * @returns {Object} - Promise.<?Function>
   */
  const writeStdout = async msg => {
    msg = await (new Output()).encode(msg);
    return msg && process.stdout.write(msg) || null;
  };

  /**
   * port app status
   * @returns {Object} - Promise.<AsyncFunction>
   */
  const portAppStatus = async () =>
    writeStdout(hostMsg(EDITOR_CONFIG_GET, "ready"));

  /**
   * port editor config
   * @param {string} data - editor config
   * @param {string} editorConfig - editor config file path
   * @returns {Object} - Promise.<?AsyncFunction>
   */
  const portEditorConfig = async (data, editorConfig) => {
    let msg;
    try {
      data = data && JSON.parse(data);
      if (data) {
        const {editorPath} = data;
        const editorName = await getFileNameFromFilePath(editorPath);
        const executable = await isExecutable(editorPath);
        const items = Object.keys(data);
        if (items.length) {
          for (const item of items) {
            vars[item] = data[item];
          }
        }
        msg = {
          [EDITOR_CONFIG_RES]: {
            editorConfig, editorName, editorPath, executable,
          },
        };
      }
    } catch (e) {
      msg = hostMsg(`${e}: ${editorConfig}`, "error");
    }
    return msg && writeStdout(msg) || null;
  };

  /**
   * port file data
   * @param {Object} obj - file data
   * @returns {Object} - Promise.<?AsyncFunction>
   */
  const portFileData = async (obj = {}) => {
    const {data, filePath} = obj;
    let msg;
    if (data && await isString(filePath)) {
      data.filePath = filePath;
      msg = {
        [TMP_FILE_DATA_PORT]: {data, filePath},
      };
    }
    return msg && writeStdout(msg) || null;
  };

  /**
   * port temporary file
   * @param {Object} obj - temporary file data object
   * @returns {Object} - Promise.<?AsyncFunction>
   */
  const portTmpFile = async (obj = {}) => {
    const msg = Object.keys(obj).length && {
      [TMP_FILE_RES]: obj,
    };
    return msg && writeStdout(msg) || null;
  };

  /* temporary files */
  /**
   * remove private temporary files
   * @param {boolean} bool - remove
   * @returns {void} - Promise.<void>
   */
  const removePrivateTmpFiles = async bool => {
    if (bool) {
      const dir = path.join(...DIR_TMP_FILES_PB);
      await removeDir(dir);
      await !isDir(dir) && await createDir(DIR_TMP_FILES_PB);
    }
  };

  /**
   * create temporary file
   * @param {Object} obj - temporary file data object
   * @returns {Object} - Promise.<Object>, temporary file data
   */
  const createTmpFile = async (obj = {}) => {
    const {data, value} = obj;
    let filePath;
    if (data) {
      const {dir, fileName, host, tabId, windowId} = data;
      const arr = dir && windowId && tabId && host &&
                    [...DIR_TMP, dir, windowId, tabId, host];
      const dPath = arr && await createDir(arr);
      filePath = dPath === path.join(...arr) && fileName &&
                   await createFile(path.join(dPath, fileName), value);
    }
    return data && filePath && {data, filePath} || null;
  };

  /**
   * append file timestamp
   * @param {Object} data - temporary file data
   * @returns {Object} - Promise.<Object>, temporary file data
   */
  const appendTimestamp = async (data = {}) => {
    const {filePath} = data;
    data.timestamp = filePath && await getFileTimestamp(filePath) || 0;
    return data;
  };

  /**
   * extract temporary file data
   * @param {Array} arr - array containing temporary file data and value
   * @returns {Object} - Promise.<Object>, temporary file data object
   */
  const extractTmpFileData = async (arr = []) => {
    let obj;
    if (Array.isArray(arr) && arr.length) {
      const [data, value] = arr;
      obj = {data, value};
    }
    return obj || null;
  };

  /**
   * get temporary file
   * @param {Object} obj - temporary file data
   * @returns {Object} - Promise.<AsyncFunction>
   */
  const getTmpFile = async (obj = {}) => {
    const {filePath} = obj;
    const func = [];
    if (filePath) {
      func.push(appendTimestamp(obj));
      func.push(readFile(filePath));
    }
    return Promise.all(func).then(extractTmpFileData);
  };

  /* local files */
  /**
   * get editor config
   * @param {string} filePath - editor config file path
   * @returns {Object} - Promise.<Array>
   */
  const getEditorConfig = async filePath => {
    const func = [];
    filePath = await isString(filePath) && filePath.length && filePath ||
               path.resolve(path.join(".", "editorconfig.json"));
    if (await isFile(filePath)) {
      const data = await readFile(filePath);
      func.push(portEditorConfig(data, filePath));
    } else {
      func.push(writeStdout(hostMsg(`${filePath} is not a file.`, "warn")));
      func.push(writeStdout({[EDITOR_CONFIG_RES]: null}));
    }
    return Promise.all(func);
  };

  /**
   * view local file
   * @param {string} uri - local file uri
   * @returns {Object} - Promise.<?AsyncFunction>
   */
  const viewLocalFile = async uri => {
    const file = await convUriToFilePath(uri);
    return file && spawnChildProcess(file) || null;
  };

  /* handlers */
  /**
   * handle created temporary file
   * @param {Object} obj - temporary file data
   * @returns {Object} - Promise.<Array>
   */
  const handleCreatedTmpFile = async (obj = {}) => {
    const {filePath} = obj;
    const func = [];
    if (filePath) {
      func.push(spawnChildProcess(filePath));
      func.push(portFileData(obj));
    }
    return Promise.all(func);
  };

  /**
   * handle message
   * @param {*} msg - message
   * @returns {Object} - Promise.<Array>
   */
  const handleMsg = async msg => {
    const func = [];
    const items = msg && Object.keys(msg);
    if (items && items.length) {
      for (const item of items) {
        const obj = msg[item];
        switch (item) {
          case EDITOR_CONFIG_GET:
            func.push(getEditorConfig(obj));
            break;
          case LOCAL_FILE_VIEW:
            func.push(viewLocalFile(obj));
            break;
          case TMP_FILE_CREATE:
            func.push(createTmpFile(obj).then(handleCreatedTmpFile));
            break;
          case TMP_FILE_GET:
            func.push(getTmpFile(obj).then(portTmpFile));
            break;
          case TMP_FILES_PB_REMOVE:
            func.push(removePrivateTmpFiles(obj));
            break;
          default:
            func.push(
              writeStdout(hostMsg(`No handler found for ${item}.`, "warn"))
            );
        }
      }
    } else {
      func.push(writeStdout(hostMsg(`No handler found for ${msg}.`, "warn")));
    }
    return Promise.all(func);
  };

  /* input */
  const input = new Input();

  /**
   * read stdin
   * @param {string|Buffer} chunk - chunk
   * @returns {Object} - ?Promise.<Array>
   */
  const readStdin = chunk => {
    const arr = input.decode(chunk);
    const func = [];
    Array.isArray(arr) && arr.length && arr.forEach(msg => {
      msg && func.push(handleMsg(msg));
    });
    return func.length && Promise.all(func).catch(handleReject) || null;
  };

  /* exit */
  /**
   * handle exit
   * @param {number} code - exit code
   * @returns {void}
   */
  const handleExit = code => {
    const msg = (new Output()).encode(hostMsg(`exit ${code || 0}`, "exit"));
    removeDir(path.join(...DIR_TMP));
    msg && process.stdout.write(msg);
  };

  /* process */
  process.on("exit", handleExit);
  process.on("uncaughtException", throwErr);
  process.on("unhandleRejection", handleReject);
  process.stdin.on("data", readStdin);

  /* startup */
  Promise.all([
    createDir(DIR_TMP_FILES),
    createDir(DIR_TMP_FILES_PB),
  ]).then(portAppStatus).catch(handleReject);
}
<commit_msg>Move output handlers upper<commit_after>/**
 * index.js
 */
"use strict";
{
  /* api */
  const {Input, Output} = require("./modules/native-message");
  const {concatArgs, isString, throwErr} = require("./modules/common");
  const {
    convUriToFilePath, createDir, createFile, getFileNameFromFilePath,
    getFileTimestamp, isDir, isExecutable, isFile, removeDir, readFile,
  } = require("./modules/file-util");
  const {execFile} = require("child_process");
  const os = require("os");
  const path = require("path");
  const process = require("process");

  /* constants */
  const {
    EDITOR_CONFIG_GET, EDITOR_CONFIG_RES, HOST, LABEL, LOCAL_FILE_VIEW,
    PROCESS_CHILD, TMP_FILES, TMP_FILES_PB, TMP_FILES_PB_REMOVE,
    TMP_FILE_CREATE, TMP_FILE_DATA_PORT, TMP_FILE_GET, TMP_FILE_RES,
  } = require("./modules/constant");
  const APP = `${process.pid}`;
  const CHAR = "utf8";
  const CMD_ARGS = "cmdArgs";
  const DIR_TMP = [os.tmpdir(), LABEL, APP];
  const DIR_TMP_FILES = [...DIR_TMP, TMP_FILES];
  const DIR_TMP_FILES_PB = [...DIR_TMP, TMP_FILES_PB];
  const EDITOR_PATH = "editorPath";
  const FILE_AFTER_ARGS = "fileAfterCmdArgs";

  /* variables */
  const vars = {
    [CMD_ARGS]: [],
    [EDITOR_PATH]: "",
    [FILE_AFTER_ARGS]: false,
  };

  /**
   * host message
   * @param {*} message - message
   * @param {string} status - status
   * @returns {Object} - host message object
   */
  const hostMsg = (message, status) => ({
    [HOST]: {
      message, status,
      pid: APP,
    },
  });

  /**
   * handle rejection
   * @param {*} e - Error or any
   * @returns {boolean} - false
   */
  const handleReject = e => {
    e = (new Output()).encode(hostMsg(e, "error"));
    e && process.stdout.write(e);
    return false;
  };

  /* output */
  /**
   * write stdout
   * @param {*} msg - message
   * @returns {Object} - Promise.<?Function>
   */
  const writeStdout = async msg => {
    msg = await (new Output()).encode(msg);
    return msg && process.stdout.write(msg) || null;
  };

  /**
   * port app status
   * @returns {Object} - Promise.<AsyncFunction>
   */
  const portAppStatus = async () =>
    writeStdout(hostMsg(EDITOR_CONFIG_GET, "ready"));

  /**
   * port editor config
   * @param {string} data - editor config
   * @param {string} editorConfig - editor config file path
   * @returns {Object} - Promise.<?AsyncFunction>
   */
  const portEditorConfig = async (data, editorConfig) => {
    let msg;
    try {
      data = data && JSON.parse(data);
      if (data) {
        const {editorPath} = data;
        const editorName = await getFileNameFromFilePath(editorPath);
        const executable = await isExecutable(editorPath);
        const items = Object.keys(data);
        if (items.length) {
          for (const item of items) {
            vars[item] = data[item];
          }
        }
        msg = {
          [EDITOR_CONFIG_RES]: {
            editorConfig, editorName, editorPath, executable,
          },
        };
      }
    } catch (e) {
      msg = hostMsg(`${e}: ${editorConfig}`, "error");
    }
    return msg && writeStdout(msg) || null;
  };

  /**
   * port file data
   * @param {Object} obj - file data
   * @returns {Object} - Promise.<?AsyncFunction>
   */
  const portFileData = async (obj = {}) => {
    const {data, filePath} = obj;
    let msg;
    if (data && await isString(filePath)) {
      data.filePath = filePath;
      msg = {
        [TMP_FILE_DATA_PORT]: {data, filePath},
      };
    }
    return msg && writeStdout(msg) || null;
  };

  /**
   * port temporary file
   * @param {Object} obj - temporary file data object
   * @returns {Object} - Promise.<?AsyncFunction>
   */
  const portTmpFile = async (obj = {}) => {
    const msg = Object.keys(obj).length && {
      [TMP_FILE_RES]: obj,
    };
    return msg && writeStdout(msg) || null;
  };

  /* child process */
  /**
   * spawn child process
   * @param {string} file - file path
   * @param {string} app - app path
   * @returns {Object} - Promise.<ChildProcess>
   */
  const spawnChildProcess = async (file, app = vars[EDITOR_PATH]) => {
    if (await !isFile(file)) {
      return writeStdout(hostMsg(`${file} is not a file.`, "warn"));
    }
    if (await !isExecutable(app)) {
      return writeStdout(hostMsg(`${app} is not executable.`, "warn"));
    }
    let args = vars[CMD_ARGS] || [];
    const pos = vars[FILE_AFTER_ARGS] || false;
    const argA = pos && args || [file.replace(/\\/g, "\\\\")];
    const argB = pos && [file.replace(/\\/g, "\\\\")] || args;
    const opt = {
      cwd: null,
      encoding: CHAR,
      env: process.env,
    };
    args = await concatArgs(argA, argB);
    return execFile(app, args, opt, (e, stdout, stderr) => {
      if (e) {
        e = (new Output()).encode(e);
        e && process.stderr.write(e);
      }
      if (stderr) {
        stderr = (new Output()).encode(
          hostMsg(`${stderr}: ${app}`, `${PROCESS_CHILD}_stderr`)
        );
        stderr && process.stdout.write(stderr);
      }
      if (stdout) {
        stdout = (new Output()).encode(
          hostMsg(`${stdout}: ${app}`, `${PROCESS_CHILD}_stdout`)
        );
        stdout && process.stdout.write(stdout);
      }
    });
  };

  /* temporary files */
  /**
   * remove private temporary files
   * @param {boolean} bool - remove
   * @returns {void} - Promise.<void>
   */
  const removePrivateTmpFiles = async bool => {
    if (bool) {
      const dir = path.join(...DIR_TMP_FILES_PB);
      await removeDir(dir);
      await !isDir(dir) && await createDir(DIR_TMP_FILES_PB);
    }
  };

  /**
   * create temporary file
   * @param {Object} obj - temporary file data object
   * @returns {Object} - Promise.<Object>, temporary file data
   */
  const createTmpFile = async (obj = {}) => {
    const {data, value} = obj;
    let filePath;
    if (data) {
      const {dir, fileName, host, tabId, windowId} = data;
      const arr = dir && windowId && tabId && host &&
                    [...DIR_TMP, dir, windowId, tabId, host];
      const dPath = arr && await createDir(arr);
      filePath = dPath === path.join(...arr) && fileName &&
                   await createFile(path.join(dPath, fileName), value);
    }
    return data && filePath && {data, filePath} || null;
  };

  /**
   * append file timestamp
   * @param {Object} data - temporary file data
   * @returns {Object} - Promise.<Object>, temporary file data
   */
  const appendTimestamp = async (data = {}) => {
    const {filePath} = data;
    data.timestamp = filePath && await getFileTimestamp(filePath) || 0;
    return data;
  };

  /**
   * extract temporary file data
   * @param {Array} arr - array containing temporary file data and value
   * @returns {Object} - Promise.<Object>, temporary file data object
   */
  const extractTmpFileData = async (arr = []) => {
    let obj;
    if (Array.isArray(arr) && arr.length) {
      const [data, value] = arr;
      obj = {data, value};
    }
    return obj || null;
  };

  /**
   * get temporary file
   * @param {Object} obj - temporary file data
   * @returns {Object} - Promise.<AsyncFunction>
   */
  const getTmpFile = async (obj = {}) => {
    const {filePath} = obj;
    const func = [];
    if (filePath) {
      func.push(appendTimestamp(obj));
      func.push(readFile(filePath));
    }
    return Promise.all(func).then(extractTmpFileData);
  };

  /* local files */
  /**
   * get editor config
   * @param {string} filePath - editor config file path
   * @returns {Object} - Promise.<Array>
   */
  const getEditorConfig = async filePath => {
    const func = [];
    filePath = await isString(filePath) && filePath.length && filePath ||
               path.resolve(path.join(".", "editorconfig.json"));
    if (await isFile(filePath)) {
      const data = await readFile(filePath);
      func.push(portEditorConfig(data, filePath));
    } else {
      func.push(writeStdout(hostMsg(`${filePath} is not a file.`, "warn")));
      func.push(writeStdout({[EDITOR_CONFIG_RES]: null}));
    }
    return Promise.all(func);
  };

  /**
   * view local file
   * @param {string} uri - local file uri
   * @returns {Object} - Promise.<?AsyncFunction>
   */
  const viewLocalFile = async uri => {
    const file = await convUriToFilePath(uri);
    return file && spawnChildProcess(file) || null;
  };

  /* handlers */
  /**
   * handle created temporary file
   * @param {Object} obj - temporary file data
   * @returns {Object} - Promise.<Array>
   */
  const handleCreatedTmpFile = async (obj = {}) => {
    const {filePath} = obj;
    const func = [];
    if (filePath) {
      func.push(spawnChildProcess(filePath));
      func.push(portFileData(obj));
    }
    return Promise.all(func);
  };

  /**
   * handle message
   * @param {*} msg - message
   * @returns {Object} - Promise.<Array>
   */
  const handleMsg = async msg => {
    const func = [];
    const items = msg && Object.keys(msg);
    if (items && items.length) {
      for (const item of items) {
        const obj = msg[item];
        switch (item) {
          case EDITOR_CONFIG_GET:
            func.push(getEditorConfig(obj));
            break;
          case LOCAL_FILE_VIEW:
            func.push(viewLocalFile(obj));
            break;
          case TMP_FILE_CREATE:
            func.push(createTmpFile(obj).then(handleCreatedTmpFile));
            break;
          case TMP_FILE_GET:
            func.push(getTmpFile(obj).then(portTmpFile));
            break;
          case TMP_FILES_PB_REMOVE:
            func.push(removePrivateTmpFiles(obj));
            break;
          default:
            func.push(
              writeStdout(hostMsg(`No handler found for ${item}.`, "warn"))
            );
        }
      }
    } else {
      func.push(writeStdout(hostMsg(`No handler found for ${msg}.`, "warn")));
    }
    return Promise.all(func);
  };

  /* input */
  const input = new Input();

  /**
   * read stdin
   * @param {string|Buffer} chunk - chunk
   * @returns {Object} - ?Promise.<Array>
   */
  const readStdin = chunk => {
    const arr = input.decode(chunk);
    const func = [];
    Array.isArray(arr) && arr.length && arr.forEach(msg => {
      msg && func.push(handleMsg(msg));
    });
    return func.length && Promise.all(func).catch(handleReject) || null;
  };

  /* exit */
  /**
   * handle exit
   * @param {number} code - exit code
   * @returns {void}
   */
  const handleExit = code => {
    const msg = (new Output()).encode(hostMsg(`exit ${code || 0}`, "exit"));
    removeDir(path.join(...DIR_TMP));
    msg && process.stdout.write(msg);
  };

  /* process */
  process.on("exit", handleExit);
  process.on("uncaughtException", throwErr);
  process.on("unhandleRejection", handleReject);
  process.stdin.on("data", readStdin);

  /* startup */
  Promise.all([
    createDir(DIR_TMP_FILES),
    createDir(DIR_TMP_FILES_PB),
  ]).then(portAppStatus).catch(handleReject);
}
<|endoftext|>


<commit_before>var env = process.env.RACK_ENV;

var express = require('express')
  , compression = require('compression')
  , Twitter = require('twitter')
  , fs = require('fs')
  , _ = require('lodash')
  , Q = require('q')
  , app = express();

var apicache = require('apicache').options({ debug: true }).middleware;

var client = new Twitter({
  consumer_key: process.env.TWITTER_CONSUMER_KEY,
  consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
  access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY,
  access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET,
});

app.use(compression()); //gzip!

app.use(function(req, res, next){
  var whitelist = ['localhost:4000', 'localhost:8080', 'slowsbarbq.com']
  var host = req.get('host');

  whitelist.forEach(function(val, key){
    if (host.indexOf(val) > -1){
      res.setHeader('Access-Control-Allow-Origin', host);
    }
  })

  res.setHeader('Access-Control-Allow-Origin', '*');

  next();
});

app.get("/cards/:handle", apicache('20 minutes'), function(req, res, next){

  console.time('getEmbends'); // Track how long this takes!
  var startTime = Date.now();

  timeline(req.params.handle)
    .then(function(data){
      console.timeEnd('getEmbends'); // How long did it take?
      var endTime = Date.now()

      res.send({
        'created_at': endTime,
        'generation_time': (endTime - startTime) + 'ms',
        'cached_until': endTime + (20 * 60 * 1000),
        'cards': data
      })
    }, function(error){
      res.status(500).send({'error': data})
    })

})

app.use(function(req, res, next){ res.sendfile('./public/index.html'); })

var port = process.env.PORT || 8080;
app.listen(port);

console.log("listening on port " + port);

////////
/// helpers ============================

function settled(results) {
  var embeds = [];
  results.forEach(function (result) {
    if (result.state === "fulfilled") {
      console.log('got embed code for ', result.value.url);
      embeds.push({
        url: result.value.url,
        html: result.value.html
      });
    } else {
      console.log('error: ', result.reason);
    }
  });
  return embeds;
}

function withMedia(tweets) {
  return _.filter(tweets, function(t) {
    if(t.entities.media) {
      return t;
    }
  });
}

function embed(tweet){
  var defer = Q.defer();

  var params = {
    id: tweet.id_str,
    omit_script: true,
    hide_thread: true
  }
  //console.log(params)
  client.get('statuses/oembed', params, function(error, tweets, response){
    if (error) {
      console.log('cannot get embed code for ', tweet.id_str)
      defer.reject(error);
    } else {
      defer.resolve(tweets);
    }
  });
  return defer.promise;
}

function timeline(handle){
  var defer = Q.defer();
  var maxCards = 10;
  var params = {
    screen_name: handle,
    trim_user: true,
    count: 100,
    include_rts: true,
    include_entities: true
  };

  client.get('statuses/user_timeline', params, function(error, tweets, response){
    if (!error) {
      var _embeds = [];

      withMedia(tweets).forEach(function(tweet){
        if(_embeds.length < maxCards) {
          _embeds.push(embed(tweet));
        }
      })

      Q.allSettled(_embeds)
      .then(settled)
      .done(function(embeds){
        console.log('all done')
        defer.resolve(embeds)
      });

    } else {
      defer.reject(error);
    }
  });

  return defer.promise;
}
<commit_msg>smaller tweets by default<commit_after>var env = process.env.RACK_ENV;

var express = require('express')
  , compression = require('compression')
  , Twitter = require('twitter')
  , fs = require('fs')
  , _ = require('lodash')
  , Q = require('q')
  , app = express();

var apicache = require('apicache').options({ debug: true }).middleware;

var client = new Twitter({
  consumer_key: process.env.TWITTER_CONSUMER_KEY,
  consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
  access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY,
  access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET,
});

app.use(compression()); //gzip!

app.use(function(req, res, next){
  var whitelist = ['localhost:4000', 'localhost:8080', 'slowsbarbq.com']
  var host = req.get('host');

  whitelist.forEach(function(val, key){
    if (host.indexOf(val) > -1){
      res.setHeader('Access-Control-Allow-Origin', host);
    }
  })

  res.setHeader('Access-Control-Allow-Origin', '*');

  next();
});

app.get("/media/:handle", apicache('20 minutes'), function(req, res, next){
  console.time('getMedia'); // Track how long this takes!
  var startTime = Date.now();

  console.log(req.params.handle)
  media_timeline(req.params.handle)
    .then(function(data){
      console.timeEnd('getMedia'); // How long did it take?
      var endTime = Date.now()

      res.send({
        'created_at': endTime,
        'generation_time': (endTime - startTime) + 'ms',
        'cached_until': endTime + (20 * 60 * 1000),
        'tweets': data
      })
    }, function(error){
      res.status(500).send({'error': data})
    })

});

app.get("/cards/:handle", apicache('20 minutes'), function(req, res, next){

  console.time('getEmbends'); // Track how long this takes!
  var startTime = Date.now();

  timeline(req.params.handle)
    .then(function(data){
      console.timeEnd('getEmbends'); // How long did it take?
      var endTime = Date.now()

      res.send({
        'created_at': endTime,
        'generation_time': (endTime - startTime) + 'ms',
        'cached_until': endTime + (20 * 60 * 1000),
        'cards': data
      })
    }, function(error){
      res.status(500).send({'error': data})
    })

})

app.use(function(req, res, next){ res.sendfile('./public/index.html'); })

var port = process.env.PORT || 8080;
app.listen(port);

console.log("listening on port " + port);

////////
/// helpers ============================

function settled(results) {
  var embeds = [];
  results.forEach(function (result) {
    if (result.state === "fulfilled") {
      console.log('got embed code for ', result.value.url);
      embeds.push({
        url: result.value.url,
        html: result.value.html
      });
    } else {
      console.log('error: ', result.reason);
    }
  });
  return embeds;
}

function withMedia(tweets) {
  return _.filter(tweets, function(t) {
    if(t.entities.media) {
      return t;
    }
  });
}

function embed(tweet){
  var defer = Q.defer();

  var params = {
    id: tweet.id_str,
    omit_script: true,
    hide_thread: true,
    maxwidth: 350
  }
  //console.log(params)
  client.get('statuses/oembed', params, function(error, tweets, response){
    if (error) {
      console.log('cannot get embed code for ', tweet.id_str)
      defer.reject(error);
    } else {
      defer.resolve(tweets);
    }
  });
  return defer.promise;
}

function timeline(handle){
  var defer = Q.defer();
  var maxCards = 10;
  var params = {
    screen_name: handle,
    trim_user: true,
    count: 100,
    include_rts: true,
    include_entities: true
  };

  client.get('statuses/user_timeline', params, function(error, tweets, response){
    if (!error) {
      var _embeds = [];

      withMedia(tweets).forEach(function(tweet){
        if(_embeds.length < maxCards) {
          _embeds.push(embed(tweet));
        }
      })

      Q.allSettled(_embeds)
      .then(settled)
      .done(function(embeds){
        console.log('all done')
        defer.resolve(embeds)
      });

    } else {
      defer.reject(error);
    }
  });

  return defer.promise;
}

function media_timeline(handle){
  var defer = Q.defer();
  var maxCards = 10;
  var params = {
    screen_name: handle,
    trim_user: true,
    count: 100,
    include_rts: true,
    include_entities: true
  };

  client.get('statuses/user_timeline', params, function(error, tweets, response){

    if (!error) {
      var _tweets = [];

      withMedia(tweets).forEach(function(tweet){
        if(_tweets.length < maxCards) {
          _tweets.push(tweet);
        }
      })

      defer.resolve(_tweets)

    } else {
      defer.reject(error);
    }
  });

  return defer.promise;
}
<|endoftext|>


<commit_before>/**
 * @file gulpfile.js
 *
 * Defines tasks that can be run on gulp.
 *
 * Summary:

 *
 `test` - runs all the tests on node and the browser (mocha and karma)
 *

 *
 `test:node`
 *
 `test:node:nofail` - internally used for watching (due to bug on gulp-mocha)
 *
 `test:browser`
 *
`
 *
 `watch:test` - watch for file changes and run tests
 *

 *
 `watch:test:node`
 *
 `watch:test:browser`
 *
`
 *
 `browser` - generate files needed for browser (browserify)
 *

 *
 `browser:uncompressed` - build uncomprssed browser bundle (`bitcore-*.js`)
 *
 `browser:compressed` - build compressed browser bundle (`bitcore-*.min.js`)
 *
 `browser:maketests` - build `tests.js`, needed for testing without karma
 *
`
 *
 `lint` - run `jshint`
 *
 `coverage` - run `istanbul` with mocha to generate a report of test coverage
 *
 `coveralls` - updates coveralls info
 *
 `release` - automates release process (only for maintainers)
 *

 */
'use strict';

var gulp = require('gulp');

var coveralls = require('gulp-coveralls');
var gutil = require('gulp-util');
var jshint = require('gulp-jshint');
var mocha = require('gulp-mocha');
var rename = require('gulp-rename');
var runsequence = require('run-sequence');
runsequence.use(gulp);
var shell = require('gulp-shell');
var uglify = require('gulp-uglify');
var bump = require('gulp-bump');
var git = require('gulp-git');

function ignoreerror() {
  /* jshint ignore:start */ // using `this` in this context is weird
  this.emit('end');
  /* jshint ignore:end */
}

function startGulp(name, opts) {

  opts = opts || {};
  var browser = !opts.skipBrowser;
  var isSubmodule = name ? true : false;
  var fullname = name ? 'bitcore-' + name : 'bitcore';
  var files = ['lib/**/*.js'];
  var tests = ['test/**/*.js'];
  var alljs = files.concat(tests);

  var buildPath = './node_modules/bitcore-build/';
  var buildModulesPath = buildPath + 'node_modules/';
  var buildBinPath = buildPath + 'node_modules/.bin/';

  /**
   * testing
   */
  var testmocha = function() {
    return gulp.src(tests).pipe(new mocha({
      reporter: 'spec'
    }));
  };

  var testkarma = shell.task([
    buildModulesPath + 'karma/bin/karma start ' + buildPath + 'karma.conf.js'
  ]);

  gulp.task('test:node', testmocha);

  gulp.task('test:node:nofail', function() {
    return testmocha().on('error', ignoreerror);
  });

  gulp.task('test:browser', ['browser:uncompressed', 'browser:maketests'], testkarma);

  if (browser) {
    gulp.task('test', function(callback) {
      runsequence(['test:node'], ['test:browser'], callback);
    });
  } else {
    gulp.task('test', ['test:node']);
  }

  /**
   * file generation
   */
  if (browser) {

    var browserifyCommand;

    if (isSubmodule) {
      browserifyCommand = buildBinPath + 'browserify --require ./index.js:' + fullname + ' --external bitcore -o ' + fullname + '.js';
    } else {
      browserifyCommand = buildBinPath + 'browserify --require ./index.js:bitcore -o bitcore.js';
    }

    gulp.task('browser:uncompressed', shell.task([
      browserifyCommand
    ]));

    gulp.task('browser:compressed', ['browser:uncompressed'], function() {
      return gulp.src(fullname + '.js')
        .pipe(uglify({
          mangle: true,
          compress: true
        }))
        .pipe(rename(fullname + '.min.js'))
        .pipe(gulp.dest('.'))
        .on('error', gutil.log);
    });

    gulp.task('browser:maketests', shell.task([
      'find test/ -type f -name "*.js" | xargs ' + buildBinPath + 'browserify -t brfs -o tests.js'
    ]));

    gulp.task('browser', function(callback) {
      runsequence(['browser:compressed'], ['browser:maketests'], callback);
    });
  }

  /**
   * code quality and documentation
   */

  gulp.task('lint', function() {
    return gulp.src(alljs)
      .pipe(jshint())
      .pipe(jshint.reporter('default'));
  });

  gulp.task('plato', shell.task([buildBinPath + 'plato -d report -r -l .jshintrc -t ' + fullname + ' lib']));

  gulp.task('coverage', shell.task([buildBinPath + './istanbul cover ' + buildBinPath + '_mocha -- --recursive']));

  gulp.task('coveralls', ['coverage'], function() {
    gulp.src('coverage/lcov.info').pipe(coveralls());
  });

  /**
   * watch tasks
   */

  gulp.task('watch:test', function() {
    // todo: only run tests that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['test']);
  });

  gulp.task('watch:test:node', function() {
    // todo: only run tests that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['test:node']);
  });

  if (browser) {
    gulp.task('watch:test:browser', function() {
      // todo: only run tests that are linked to file changes by doing
      // something smart like reading through the require statements
      return gulp.watch(alljs, ['test:browser']);
    });
  }

  gulp.task('watch:coverage', function() {
    // todo: only run tests that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['coverage']);
  });

  gulp.task('watch:lint', function() {
    // todo: only lint files that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['lint']);
  });

  if (browser) {
    gulp.task('watch:browser', function() {
      return gulp.watch(alljs, ['browser']);
    });
  }

  /**
   * Release automation
   */

  gulp.task('release:install', function() {
    return shell.task([
      'npm install',
    ]);
  });

  var releaseFiles = ['./package.json'];
  if (browser) {
    releaseFiles.push('./bower.json');
  }

  var bump_version = function(importance) {
    return gulp.src(releaseFiles)
      .pipe(bump({
        type: importance
      }))
      .pipe(gulp.dest('./'));
  };

  gulp.task('release:checkout-releases', function(cb) {
    var tempBranch = 'releases/' + new Date().getTime() + '-build';
    git.branch(tempBranch, {
      args: ''
    }, function() {
      git.checkout(tempBranch, {
        args: ''
      }, cb);
    });
  });

  gulp.task('release:merge-master', function(cb) {
    git.merge('master', {
      args: ''
    }, cb);
  });

  gulp.task('release:checkout-master', function(cb) {
    git.checkout('master', {
      args: ''
    }, cb);
  });

  var buildFiles = ['./package.json'];
  if (browser) {
    buildFiles.push(fullname + '.js');
    buildFiles.push(fullname + '.min.js');
    buildFiles.push('./bower.json');
  }
  gulp.task('release:add-built-files', function() {
    return gulp.src(buildFiles)
      .pipe(git.add({
        args: '-f'
      }));
  });

  gulp.task('release:build-commit', ['release:add-built-files'], function() {
    var pjson = require('../../package.json');
    return gulp.src(buildFiles)
      .pipe(git.commit('Build: ' + pjson.version, {
        args: ''
      }));
  });

  gulp.task('release:version-commit', function() {
    var pjson = require('../../package.json');
    return gulp.src(releaseFiles)
      .pipe(git.commit('Bump package version to ' + pjson.version, {
        args: ''
      }));
  });

  gulp.task('release:push', function(cb) {
    git.push('bitpay', 'master', {
      args: ''
    }, cb);
  });

  gulp.task('release:push-tag', function(cb) {
    var pjson = require('../../package.json');
    var name = 'v' + pjson.version;
    git.tag(name, 'Release ' + name, function() {
      git.push('bitpay', name, cb);
    });
  });

  gulp.task('release:publish', shell.task([
    'npm publish'
  ]));

  // requires https://hub.github.com/
  var release = function(importance, cb) {
    var bumper = 'release:bump:' + importance;
    return runsequence(
      // Checkout the release temporal branch
      'release:checkout-releases',
      // Run npm install
      'release:install',
      // Run tests with gulp test
      'test',
      // build browser files
      'browser',
      // Update package.json and bower.json
      bumper,
      // Commit
      'release:build-commit',
      // Run git push bitpay $VERSION
      'release:push-tag',
      // Run npm publish
      'release:publish',
      // Checkout the `master` branch
      'release:checkout-master',
      // Bump package.json and bower.json, again
      bumper,
      // Version commit with no binary files to master
      'release:version-commit',
      // Push to master
      'release:push',
      cb);
  };

  ['patch', 'minor', 'major'].forEach(function(importance) {
    gulp.task('release:' + importance, function(cb) {
      release(importance, cb);
    });
    gulp.task('release:bump:' + importance, function() {
      bump_version(importance);
    });
  });
  gulp.task('release', ['release:patch']);

}

module.exports = startGulp;
<commit_msg>bower build bugfix<commit_after>/**
 * @file gulpfile.js
 *
 * Defines tasks that can be run on gulp.
 *
 * Summary:

 *
 `test` - runs all the tests on node and the browser (mocha and karma)
 *

 *
 `test:node`
 *
 `test:node:nofail` - internally used for watching (due to bug on gulp-mocha)
 *
 `test:browser`
 *
`
 *
 `watch:test` - watch for file changes and run tests
 *

 *
 `watch:test:node`
 *
 `watch:test:browser`
 *
`
 *
 `browser` - generate files needed for browser (browserify)
 *

 *
 `browser:uncompressed` - build uncomprssed browser bundle (`bitcore-*.js`)
 *
 `browser:compressed` - build compressed browser bundle (`bitcore-*.min.js`)
 *
 `browser:maketests` - build `tests.js`, needed for testing without karma
 *
`
 *
 `lint` - run `jshint`
 *
 `coverage` - run `istanbul` with mocha to generate a report of test coverage
 *
 `coveralls` - updates coveralls info
 *
 `release` - automates release process (only for maintainers)
 *

 */
'use strict';

var gulp = require('gulp');

var coveralls = require('gulp-coveralls');
var gutil = require('gulp-util');
var jshint = require('gulp-jshint');
var mocha = require('gulp-mocha');
var rename = require('gulp-rename');
var runsequence = require('run-sequence');
runsequence.use(gulp);
var shell = require('gulp-shell');
var uglify = require('gulp-uglify');
var bump = require('gulp-bump');
var git = require('gulp-git');

function ignoreerror() {
  /* jshint ignore:start */ // using `this` in this context is weird
  this.emit('end');
  /* jshint ignore:end */
}

function startGulp(name, opts) {

  opts = opts || {};
  var browser = !opts.skipBrowser;
  var isSubmodule = name ? true : false;
  var fullname = name ? 'bitcore-' + name : 'bitcore';
  var files = ['lib/**/*.js'];
  var tests = ['test/**/*.js'];
  var alljs = files.concat(tests);

  var buildPath = './node_modules/bitcore-build/';
  var buildModulesPath = buildPath + 'node_modules/';
  var buildBinPath = buildPath + 'node_modules/.bin/';

  /**
   * testing
   */
  var testmocha = function() {
    return gulp.src(tests).pipe(new mocha({
      reporter: 'spec'
    }));
  };

  var testkarma = shell.task([
    buildModulesPath + 'karma/bin/karma start ' + buildPath + 'karma.conf.js'
  ]);

  gulp.task('test:node', testmocha);

  gulp.task('test:node:nofail', function() {
    return testmocha().on('error', ignoreerror);
  });

  gulp.task('test:browser', ['browser:uncompressed', 'browser:maketests'], testkarma);

  if (browser) {
    gulp.task('test', function(callback) {
      runsequence(['test:node'], ['test:browser'], callback);
    });
  } else {
    gulp.task('test', ['test:node']);
  }

  /**
   * file generation
   */
  if (browser) {

    var browserifyCommand;

    if (isSubmodule) {
      browserifyCommand = buildBinPath + 'browserify --require ./index.js:' + fullname + ' --external bitcore -o ' + fullname + '.js';
    } else {
      browserifyCommand = buildBinPath + 'browserify --require ./index.js:bitcore -o bitcore.js';
    }

    gulp.task('browser:uncompressed', shell.task([
      browserifyCommand
    ]));

    gulp.task('browser:compressed', ['browser:uncompressed'], function() {
      return gulp.src(fullname + '.js')
        .pipe(uglify({
          mangle: true,
          compress: true
        }))
        .pipe(rename(fullname + '.min.js'))
        .pipe(gulp.dest('.'))
        .on('error', gutil.log);
    });

    gulp.task('browser:maketests', shell.task([
      'find test/ -type f -name "*.js" | xargs ' + buildBinPath + 'browserify -t brfs -o tests.js'
    ]));

    gulp.task('browser', function(callback) {
      runsequence(['browser:compressed'], ['browser:maketests'], callback);
    });
  }

  /**
   * code quality and documentation
   */

  gulp.task('lint', function() {
    return gulp.src(alljs)
      .pipe(jshint())
      .pipe(jshint.reporter('default'));
  });

  gulp.task('plato', shell.task([buildBinPath + 'plato -d report -r -l .jshintrc -t ' + fullname + ' lib']));

  gulp.task('coverage', shell.task([buildBinPath + './istanbul cover ' + buildBinPath + '_mocha -- --recursive']));

  gulp.task('coveralls', ['coverage'], function() {
    gulp.src('coverage/lcov.info').pipe(coveralls());
  });

  /**
   * watch tasks
   */

  gulp.task('watch:test', function() {
    // todo: only run tests that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['test']);
  });

  gulp.task('watch:test:node', function() {
    // todo: only run tests that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['test:node']);
  });

  if (browser) {
    gulp.task('watch:test:browser', function() {
      // todo: only run tests that are linked to file changes by doing
      // something smart like reading through the require statements
      return gulp.watch(alljs, ['test:browser']);
    });
  }

  gulp.task('watch:coverage', function() {
    // todo: only run tests that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['coverage']);
  });

  gulp.task('watch:lint', function() {
    // todo: only lint files that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['lint']);
  });

  if (browser) {
    gulp.task('watch:browser', function() {
      return gulp.watch(alljs, ['browser']);
    });
  }

  /**
   * Release automation
   */

  gulp.task('release:install', function() {
    return shell.task([
      'npm install',
    ]);
  });

  var releaseFiles = ['./package.json'];
  if (browser) {
    releaseFiles.push('./bower.json');
  }

  var bump_version = function(importance) {
    return gulp.src(releaseFiles)
      .pipe(bump({
        type: importance
      }))
      .pipe(gulp.dest('./'));
  };

  gulp.task('release:checkout-releases', function(cb) {
    var tempBranch = 'releases/' + new Date().getTime() + '-build';
    git.branch(tempBranch, {
      args: ''
    }, function() {
      git.checkout(tempBranch, {
        args: ''
      }, cb);
    });
  });

  gulp.task('release:checkout-master', function(cb) {
    git.checkout('master', {
      args: ''
    }, cb);
  });

  var buildFiles = ['./package.json'];
  if (browser) {
    buildFiles.push(fullname + '.js');
    buildFiles.push(fullname + '.min.js');
    buildFiles.push('./bower.json');
  }
  gulp.task('release:add-built-files', function() {
    return gulp.src(buildFiles)
      .pipe(git.add({
        args: '-f'
      }));
  });

  gulp.task('release:build-commit', ['release:add-built-files'], function() {
    var pjson = require('../../package.json');
    return gulp.src(buildFiles)
      .pipe(git.commit('Build: ' + pjson.version, {
        args: ''
      }));
  });

  gulp.task('release:version-commit', function() {
    var pjson = require('../../package.json');
    return gulp.src(releaseFiles)
      .pipe(git.commit('Bump package version to ' + pjson.version, {
        args: ''
      }));
  });

  gulp.task('release:push', function(cb) {
    git.push('bitpay', 'master', {
      args: ''
    }, cb);
  });

  gulp.task('release:push-tag', function(cb) {
    var pjson = require('../../package.json');
    var name = 'v' + pjson.version;
    git.tag(name, 'Release ' + name, function() {
      git.push('bitpay', name, cb);
    });
  });

  gulp.task('release:publish', shell.task([
    'npm publish'
  ]));

  // requires https://hub.github.com/
  var release = function(importance, cb) {
    var bumper = 'release:bump:' + importance;
    return runsequence(
      // Checkout the release temporal branch
      'release:checkout-releases',
      // Run npm install
      'release:install',
      // Run tests with gulp test
      'test',
      // build browser files
      'browser',
      // Update package.json and bower.json
      bumper,
      // Commit
      'release:build-commit',
      // Run git push bitpay $VERSION
      'release:push-tag',
      // Run npm publish
      'release:publish',
      // Checkout the `master` branch
      'release:checkout-master',
      // Bump package.json and bower.json, again
      bumper,
      // Version commit with no binary files to master
      'release:version-commit',
      // Push to master
      'release:push',
      cb);
  };

  ['patch', 'minor', 'major'].forEach(function(importance) {
    gulp.task('release:' + importance, function(cb) {
      release(importance, cb);
    });
    gulp.task('release:bump:' + importance, function() {
      bump_version(importance);
    });
  });
  gulp.task('release', ['release:patch']);

}

module.exports = startGulp;
<|endoftext|>


<commit_before>module.exports = {
  assign: require('./lib/assign'),
  actions: require('./lib/actions'),
  store: require('./lib/store'),
  promise: require('./lib/promise'),
};
<commit_msg>Reorder<commit_after>module.exports = {
  assign: require('./lib/assign'),
  actions: require('./lib/actions'),
  promise: require('./lib/promise'),
  store: require('./lib/store')
};
<|endoftext|>


<commit_before>"use strict"

const wcwidth = require('./width')
const {
  padRight,
  padCenter,
  padLeft,
  splitIntoLines,
  splitLongWords,
  truncateString
} = require('./utils')

const DEFAULT_HEADING_TRANSFORM = key => key.toUpperCase()

const DEFAULT_DATA_TRANSFORM = (cell, column, index) => cell

const DEFAULTS = Object.freeze({
  maxWidth: Infinity,
  minWidth: 0,
  columnSplitter: ' ',
  truncate: false,
  truncateMarker: '…',
  preserveNewLines: false,
  paddingChr: ' ',
  showHeaders: true,
  headingTransform: DEFAULT_HEADING_TRANSFORM,
  dataTransform: DEFAULT_DATA_TRANSFORM
})

module.exports = function(items, options = {}) {

  let columnConfigs = options.config || {}
  delete options.config // remove config so doesn't appear on every column.

  let maxLineWidth = options.maxLineWidth || Infinity
  if (maxLineWidth === 'auto') maxLineWidth = process.stdout.columns || Infinity
  delete options.maxLineWidth // this is a line control option, don't pass it to column

  // Option defaults inheritance:
  // options.config[columnName] => options => DEFAULTS
  options = mixin({}, DEFAULTS, options)

  options.config = options.config || Object.create(null)

  options.spacing = options.spacing || '\n' // probably useless
  options.preserveNewLines = !!options.preserveNewLines
  options.showHeaders = !!options.showHeaders;
  options.columns = options.columns || options.include // alias include/columns, prefer columns if supplied
  let columnNames = options.columns || [] // optional user-supplied columns to include

  items = toArray(items, columnNames)

  // if not suppled column names, automatically determine columns from data keys
  if (!columnNames.length) {
    items.forEach(function(item) {
      for (let columnName in item) {
        if (columnNames.indexOf(columnName) === -1) columnNames.push(columnName)
      }
    })
  }

  // initialize column defaults (each column inherits from options.config)
  let columns = columnNames.reduce((columns, columnName) => {
    let column = Object.create(options)
    columns[columnName] = mixin(column, columnConfigs[columnName])
    return columns
  }, Object.create(null))

  // sanitize column settings
  columnNames.forEach(columnName => {
    let column = columns[columnName]
    column.name = columnName
    column.maxWidth = Math.ceil(column.maxWidth)
    column.minWidth = Math.ceil(column.minWidth)
    column.truncate = !!column.truncate
    column.align = column.align || 'left'
  })

  // sanitize data
  items = items.map(item => {
    let result = Object.create(null)
    columnNames.forEach(columnName => {
      // null/undefined -> ''
      result[columnName] = item[columnName] != null ? item[columnName] : ''
      // toString everything
      result[columnName] = '' + result[columnName]
      if (columns[columnName].preserveNewLines) {
        // merge non-newline whitespace chars
        result[columnName] = result[columnName].replace(/[^\S\n]/gmi, ' ')
      } else {
        // merge all whitespace chars
        result[columnName] = result[columnName].replace(/\s/gmi, ' ')
      }
    })
    return result
  })

  // transform data cells
  columnNames.forEach(columnName => {
    let column = columns[columnName]
    items = items.map((item, index) => {
      let col = Object.create(column)
      item[columnName] = column.dataTransform(item[columnName], col, index)

      let changedKeys = Object.keys(col)
      // disable default heading transform if we wrote to column.name
      if (changedKeys.indexOf('name') !== -1) {
        if (column.headingTransform !== DEFAULT_HEADING_TRANSFORM) return
        column.headingTransform = heading => heading
      }
      changedKeys.forEach(key => column[key] = col[key])
      return item
    })
  })

  // add headers
  let headers = {}
  if(options.showHeaders) {
    columnNames.forEach(columnName => {
      let column = columns[columnName]
      headers[columnName] = column.headingTransform(column.name)
    })
    items.unshift(headers)
  }
  // get actual max-width between min & max
  // based on length of data in columns
  columnNames.forEach(columnName => {
    let column = columns[columnName]
    column.width = items
    .map(item => item[columnName])
    .reduce((min, cur) => {
      return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur))))
    }, 0)
  })

  // split long words so they can break onto multiple lines
  columnNames.forEach(columnName => {
    let column = columns[columnName]
    items = items.map(item => {
      item[columnName] = splitLongWords(item[columnName], column.width, column.truncateMarker)
      return item
    })
  })

  // wrap long lines. each item is now an array of lines.
  columnNames.forEach(columnName => {
    let column = columns[columnName]
    items = items.map((item, index) => {
      let cell = item[columnName]
      item[columnName] = splitIntoLines(cell, column.width)

      // if truncating required, only include first line + add truncation char
      if (column.truncate && item[columnName].length > 1) {
        item[columnName] = splitIntoLines(cell, column.width - wcwidth(column.truncateMarker))
        let firstLine = item[columnName][0]
        if (!endsWith(firstLine, column.truncateMarker)) item[columnName][0] += column.truncateMarker
        item[columnName] = item[columnName].slice(0, 1)
      }
      return item
    })
  })

  // recalculate column widths from truncated output/lines
  columnNames.forEach(columnName => {
    let column = columns[columnName]
    column.width = items.map(item => {
      return item[columnName].reduce((min, cur) => {
        return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur))))
      }, 0)
    }).reduce((min, cur) => {
      return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, cur)))
    }, 0)
  })

  let rows = createRows(items, columns, columnNames, options.paddingChr) // merge lines into rows
  // conceive output
  return rows.reduce((output, row) => {
    return output.concat(row.reduce((rowOut, line) => {
      return rowOut.concat(line.join(options.columnSplitter))
    }, []))
  }, [])
  .map(line => truncateString(line, maxLineWidth))
  .join(options.spacing)
}

/**
 * Convert wrapped lines into rows with padded values.
 *
 * @param Array items data to process
 * @param Array columns column width settings for wrapping
 * @param Array columnNames column ordering
 * @return Array items wrapped in arrays, corresponding to lines
 */

function createRows(items, columns, columnNames, paddingChr) {
  return items.map(item => {
    let row = []
    let numLines = 0
    columnNames.forEach(columnName => {
      numLines = Math.max(numLines, item[columnName].length)
    })
    // combine matching lines of each rows
    for (let i = 0; i < numLines; i++) {
      row[i] = row[i] || []
      columnNames.forEach(columnName => {
        let column = columns[columnName]
        let val = item[columnName][i] || '' // || '' ensures empty columns get padded
        if (column.align === 'right') row[i].push(padLeft(val, column.width, paddingChr))
        else if (column.align === 'center' || column.align === 'centre') row[i].push(padCenter(val, column.width, paddingChr))
        else row[i].push(padRight(val, column.width, paddingChr))
      })
    }
    return row
  })
}

/**
 * Object.assign
 *
 * @return Object Object with properties mixed in.
 */

function mixin(...args) {
  if (Object.assign) return Object.assign(...args)
  return ObjectAssign(...args)
}

function ObjectAssign(target, firstSource) {
  "use strict";
  if (target === undefined || target === null)
    throw new TypeError("Cannot convert first argument to object");

  var to = Object(target);

  var hasPendingException = false;
  var pendingException;

  for (var i = 1; i < arguments.length; i++) {
    var nextSource = arguments[i];
    if (nextSource === undefined || nextSource === null)
      continue;

    var keysArray = Object.keys(Object(nextSource));
    for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
      var nextKey = keysArray[nextIndex];
      try {
        var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
        if (desc !== undefined && desc.enumerable)
          to[nextKey] = nextSource[nextKey];
      } catch (e) {
        if (!hasPendingException) {
          hasPendingException = true;
          pendingException = e;
        }
      }
    }

    if (hasPendingException)
      throw pendingException;
  }
  return to;
}

/**
 * Adapted from String.prototype.endsWith polyfill.
 */

function endsWith(target, searchString, position) {
  position = position || target.length;
  position = position - searchString.length;
  let lastIndex = target.lastIndexOf(searchString);
  return lastIndex !== -1 && lastIndex === position;
}

function toArray(items, columnNames) {
  if (Array.isArray(items)) return items
  let rows = []
  for (let key in items) {
    let item = {}
    item[columnNames[0] || 'key'] = key
    item[columnNames[1] || 'value'] = items[key]
    rows.push(item)
  }
  return rows
}
<commit_msg>Add support for hiding individual column headers<commit_after>"use strict"

const wcwidth = require('./width')
const {
  padRight,
  padCenter,
  padLeft,
  splitIntoLines,
  splitLongWords,
  truncateString
} = require('./utils')

const DEFAULT_HEADING_TRANSFORM = key => key.toUpperCase()

const DEFAULT_DATA_TRANSFORM = (cell, column, index) => cell

const DEFAULTS = Object.freeze({
  maxWidth: Infinity,
  minWidth: 0,
  columnSplitter: ' ',
  truncate: false,
  truncateMarker: '…',
  preserveNewLines: false,
  paddingChr: ' ',
  showHeaders: true,
  headingTransform: DEFAULT_HEADING_TRANSFORM,
  dataTransform: DEFAULT_DATA_TRANSFORM
})

module.exports = function(items, options = {}) {

  let columnConfigs = options.config || {}
  delete options.config // remove config so doesn't appear on every column.

  let maxLineWidth = options.maxLineWidth || Infinity
  if (maxLineWidth === 'auto') maxLineWidth = process.stdout.columns || Infinity
  delete options.maxLineWidth // this is a line control option, don't pass it to column

  // Option defaults inheritance:
  // options.config[columnName] => options => DEFAULTS
  options = mixin({}, DEFAULTS, options)

  options.config = options.config || Object.create(null)

  options.spacing = options.spacing || '\n' // probably useless
  options.preserveNewLines = !!options.preserveNewLines
  options.showHeaders = !!options.showHeaders;
  options.columns = options.columns || options.include // alias include/columns, prefer columns if supplied
  let columnNames = options.columns || [] // optional user-supplied columns to include

  items = toArray(items, columnNames)

  // if not suppled column names, automatically determine columns from data keys
  if (!columnNames.length) {
    items.forEach(function(item) {
      for (let columnName in item) {
        if (columnNames.indexOf(columnName) === -1) columnNames.push(columnName)
      }
    })
  }

  // initialize column defaults (each column inherits from options.config)
  let columns = columnNames.reduce((columns, columnName) => {
    let column = Object.create(options)
    columns[columnName] = mixin(column, columnConfigs[columnName])
    return columns
  }, Object.create(null))

  // sanitize column settings
  columnNames.forEach(columnName => {
    let column = columns[columnName]
    column.name = columnName
    column.maxWidth = Math.ceil(column.maxWidth)
    column.minWidth = Math.ceil(column.minWidth)
    column.truncate = !!column.truncate
    column.align = column.align || 'left'
  })

  // sanitize data
  items = items.map(item => {
    let result = Object.create(null)
    columnNames.forEach(columnName => {
      // null/undefined -> ''
      result[columnName] = item[columnName] != null ? item[columnName] : ''
      // toString everything
      result[columnName] = '' + result[columnName]
      if (columns[columnName].preserveNewLines) {
        // merge non-newline whitespace chars
        result[columnName] = result[columnName].replace(/[^\S\n]/gmi, ' ')
      } else {
        // merge all whitespace chars
        result[columnName] = result[columnName].replace(/\s/gmi, ' ')
      }
    })
    return result
  })

  // transform data cells
  columnNames.forEach(columnName => {
    let column = columns[columnName]
    items = items.map((item, index) => {
      let col = Object.create(column)
      item[columnName] = column.dataTransform(item[columnName], col, index)

      let changedKeys = Object.keys(col)
      // disable default heading transform if we wrote to column.name
      if (changedKeys.indexOf('name') !== -1) {
        if (column.headingTransform !== DEFAULT_HEADING_TRANSFORM) return
        column.headingTransform = heading => heading
      }
      changedKeys.forEach(key => column[key] = col[key])
      return item
    })
  })

  // add headers
  let headers = {}
  if(options.showHeaders) {
    columnNames.forEach(columnName => {
      let column = columns[columnName]

      if(!column.showHeaders){
        headers[columnName] = '';
        return;
      }

      headers[columnName] = column.headingTransform(column.name)
    })
    items.unshift(headers)
  }
  // get actual max-width between min & max
  // based on length of data in columns
  columnNames.forEach(columnName => {
    let column = columns[columnName]
    column.width = items
    .map(item => item[columnName])
    .reduce((min, cur) => {
      return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur))))
    }, 0)
  })

  // split long words so they can break onto multiple lines
  columnNames.forEach(columnName => {
    let column = columns[columnName]
    items = items.map(item => {
      item[columnName] = splitLongWords(item[columnName], column.width, column.truncateMarker)
      return item
    })
  })

  // wrap long lines. each item is now an array of lines.
  columnNames.forEach(columnName => {
    let column = columns[columnName]
    items = items.map((item, index) => {
      let cell = item[columnName]
      item[columnName] = splitIntoLines(cell, column.width)

      // if truncating required, only include first line + add truncation char
      if (column.truncate && item[columnName].length > 1) {
        item[columnName] = splitIntoLines(cell, column.width - wcwidth(column.truncateMarker))
        let firstLine = item[columnName][0]
        if (!endsWith(firstLine, column.truncateMarker)) item[columnName][0] += column.truncateMarker
        item[columnName] = item[columnName].slice(0, 1)
      }
      return item
    })
  })

  // recalculate column widths from truncated output/lines
  columnNames.forEach(columnName => {
    let column = columns[columnName]
    column.width = items.map(item => {
      return item[columnName].reduce((min, cur) => {
        return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, wcwidth(cur))))
      }, 0)
    }).reduce((min, cur) => {
      return Math.max(min, Math.min(column.maxWidth, Math.max(column.minWidth, cur)))
    }, 0)
  })

  let rows = createRows(items, columns, columnNames, options.paddingChr) // merge lines into rows
  // conceive output
  return rows.reduce((output, row) => {
    return output.concat(row.reduce((rowOut, line) => {
      return rowOut.concat(line.join(options.columnSplitter))
    }, []))
  }, [])
  .map(line => truncateString(line, maxLineWidth))
  .join(options.spacing)
}

/**
 * Convert wrapped lines into rows with padded values.
 *
 * @param Array items data to process
 * @param Array columns column width settings for wrapping
 * @param Array columnNames column ordering
 * @return Array items wrapped in arrays, corresponding to lines
 */

function createRows(items, columns, columnNames, paddingChr) {
  return items.map(item => {
    let row = []
    let numLines = 0
    columnNames.forEach(columnName => {
      numLines = Math.max(numLines, item[columnName].length)
    })
    // combine matching lines of each rows
    for (let i = 0; i < numLines; i++) {
      row[i] = row[i] || []
      columnNames.forEach(columnName => {
        let column = columns[columnName]
        let val = item[columnName][i] || '' // || '' ensures empty columns get padded
        if (column.align === 'right') row[i].push(padLeft(val, column.width, paddingChr))
        else if (column.align === 'center' || column.align === 'centre') row[i].push(padCenter(val, column.width, paddingChr))
        else row[i].push(padRight(val, column.width, paddingChr))
      })
    }
    return row
  })
}

/**
 * Object.assign
 *
 * @return Object Object with properties mixed in.
 */

function mixin(...args) {
  if (Object.assign) return Object.assign(...args)
  return ObjectAssign(...args)
}

function ObjectAssign(target, firstSource) {
  "use strict";
  if (target === undefined || target === null)
    throw new TypeError("Cannot convert first argument to object");

  var to = Object(target);

  var hasPendingException = false;
  var pendingException;

  for (var i = 1; i < arguments.length; i++) {
    var nextSource = arguments[i];
    if (nextSource === undefined || nextSource === null)
      continue;

    var keysArray = Object.keys(Object(nextSource));
    for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
      var nextKey = keysArray[nextIndex];
      try {
        var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
        if (desc !== undefined && desc.enumerable)
          to[nextKey] = nextSource[nextKey];
      } catch (e) {
        if (!hasPendingException) {
          hasPendingException = true;
          pendingException = e;
        }
      }
    }

    if (hasPendingException)
      throw pendingException;
  }
  return to;
}

/**
 * Adapted from String.prototype.endsWith polyfill.
 */

function endsWith(target, searchString, position) {
  position = position || target.length;
  position = position - searchString.length;
  let lastIndex = target.lastIndexOf(searchString);
  return lastIndex !== -1 && lastIndex === position;
}

function toArray(items, columnNames) {
  if (Array.isArray(items)) return items
  let rows = []
  for (let key in items) {
    let item = {}
    item[columnNames[0] || 'key'] = key
    item[columnNames[1] || 'value'] = items[key]
    rows.push(item)
  }
  return rows
}
<|endoftext|>


<commit_before>"use strict";

var modelToFhir = require('./lib/modelToFhir');
var resourceUtil = require('./lib/resourceUtil');

exports.modelToFHIR = modelToFhir.modelToFHIR;

exports.contentToFHIR = modelToFhir.contentToFHIR;

exports.countResources = resourceUtil.countResources;
<commit_msg>add an interface for section<commit_after>"use strict";

var modelToFhir = require('./lib/modelToFhir');
var resourceUtil = require('./lib/resourceUtil');

exports.sectionToFHIR = modelToFhir.sectionToBundle;

exports.modelToFHIR = modelToFhir.modelToFHIR;

exports.contentToFHIR = modelToFhir.contentToFHIR;

exports.countResources = resourceUtil.countResources;
<|endoftext|>


<commit_before>var events = require('events');
var spawn = require('child_process').spawn;
var ps = require('ps-tree');
var util = require('util');
var xtend = require('xtend');
var os = require('os');

var kill = function(pid) {
	if (os.platform() === 'win32') {
		try {
			process.kill(pid);
		} catch (err) {
			// do nothing
		}
		return;
	}
	ps(pid, function(_, pids) {
		pids = (pids || []).map(function(item) {
			return parseInt(item.PID, 10);
		});

		pids.push(pid);

		pids.forEach(function(pid) {
			try {
				process.kill(pid);
			} catch (err) {
				// do nothing
			}
		});
	});
};

var Monitor = function(command, opts) {
	events.EventEmitter.call(this);

	this.id = null; // for respawn-group

	this.status = 'stopped';
	this.command = command;
	this.cwd = opts.cwd || '.';
	this.env = opts.env || {};
	this.uid = opts.uid;
	this.gid = opts.gid;
	this.pid = 0;
	this.stdio = opts.stdio;
	this.windowsVerbatimArguments = opts.windowsVerbatimArguments;

	this.crashed = false;
	this.sleep = opts.sleep || 1000;
	this.maxRestarts = opts.maxRestarts || 10;

	this.child = null;
	this.started = null;
	this.timeout = null;
};

util.inherits(Monitor, events.EventEmitter);

Monitor.prototype.stop = function(cb) {
	if (this.status === 'stopped' || this.status === 'stopping') return cb && cb();
	this.status = 'stopping';

	clearTimeout(this.timeout);

	if (cb) {
		if (this.child) this.child.on('exit', cb);
		else process.nextTick(cb);
	}

	if (this.child) kill(this.child.pid);
	else this._stopped();
};

Monitor.prototype.start = function() {
	if (this.status === 'running') return;

	var self = this;
	var restarts = 0;
	var clock = 60000;

	var loop = function() {
		var child = spawn(self.command[0], self.command.slice(1), {
			cwd: self.cwd,
			env: xtend(process.env, self.env),
			uid: self.uid,
			gid: self.gid,
			stdio: self.stdio,
			windowsVerbatimArguments: self.windowsVerbatimArguments
		});

		self.started = new Date();
		self.status = 'running';
		self.child = child;
		self.pid = child.pid;
		self.emit('spawn', child);

		child.setMaxListeners(0);

		if (child.stdout) {
			child.stdout.on('data', function(data) {
				self.emit('stdout', data);
			});
		}

		if (child.stderr) {
			child.stderr.on('data', function(data) {
				self.emit('stderr', data);
			});
		}

		var clear = function() {
			if (self.child !== child) return false;
			self.child = null;
			self.pid = 0;
			return true;
		};

		child.on('error', function(err) {
			self.emit('warn', err); // too opionated? maybe just forward err
			if (!clear()) return;
			if (self.status === 'stopping') return self._stopped();
			self._crash();
		});

		child.on('exit', function(code, signal) {
			self.emit('exit', code, signal);
			if (!clear()) return;
			if (self.status === 'stopping') return self._stopped();

			clock -= (Date.now() - (self.started ? self.started.getTime() : 0));

			if (clock <= 0) {
				clock = 60000;
				restarts = 0;
			}

			if (++restarts > self.maxRestarts && self.maxRestarts != -1) return self._crash();

			self.status = 'sleeping';
			self.emit('sleep');

			self.timeout = setTimeout(loop, self.sleep);
		});
	};

	clearTimeout(this.timeout);
	loop();

	if (this.status === 'running') this.emit('start');
};

Monitor.prototype.toJSON = function() {
	var doc = {
		id: this.id,
		status: this.status,
		started: this.started,
		pid: this.pid,
		command: this.command,
		cwd: this.cwd,
		env: this.env
	};

	if (!doc.id) delete doc.id;
	if (!doc.pid) delete doc.pid;
	if (!doc.started) delete doc.started;

	return doc;
};

Monitor.prototype._crash = function() {
	if (this.status !== 'running') return;
	this.status = 'crashed';
	this.emit('crash');
	if (this.status === 'crashed') this._stopped();
};

Monitor.prototype._stopped = function() {
	if (this.status === 'stopped') return;
	if (this.status !== 'crashed') this.status = 'stopped';
	this.started = null;
	this.emit('stop');
};

var respawn = function(command, opts) {
	if (!Array.isArray(command)) return respawn(command.command, command);
	return new Monitor(command, opts || {});
};

module.exports = respawn;<commit_msg>use taskkill on windows to kill the tree<commit_after>var events = require('events');
var spawn = require('child_process').spawn;
var exec = require('child_process').exec;
var ps = require('ps-tree');
var util = require('util');
var xtend = require('xtend');
var os = require('os');

var kill = function(pid) {
	if (os.platform() === 'win32') {
		exec('taskkill /pid ' + pid + ' /T /F');
		return;
	}
	ps(pid, function(_, pids) {
		pids = (pids || []).map(function(item) {
			return parseInt(item.PID, 10);
		});

		pids.push(pid);

		pids.forEach(function(pid) {
			try {
				process.kill(pid);
			} catch (err) {
				// do nothing
			}
		});
	});
};

var Monitor = function(command, opts) {
	events.EventEmitter.call(this);

	this.id = null; // for respawn-group

	this.status = 'stopped';
	this.command = command;
	this.cwd = opts.cwd || '.';
	this.env = opts.env || {};
	this.uid = opts.uid;
	this.gid = opts.gid;
	this.pid = 0;
	this.stdio = opts.stdio;
	this.windowsVerbatimArguments = opts.windowsVerbatimArguments;

	this.crashed = false;
	this.sleep = opts.sleep || 1000;
	this.maxRestarts = opts.maxRestarts || 10;

	this.child = null;
	this.started = null;
	this.timeout = null;
};

util.inherits(Monitor, events.EventEmitter);

Monitor.prototype.stop = function(cb) {
	if (this.status === 'stopped' || this.status === 'stopping') return cb && cb();
	this.status = 'stopping';

	clearTimeout(this.timeout);

	if (cb) {
		if (this.child) this.child.on('exit', cb);
		else process.nextTick(cb);
	}

	if (this.child) kill(this.child.pid);
	else this._stopped();
};

Monitor.prototype.start = function() {
	if (this.status === 'running') return;

	var self = this;
	var restarts = 0;
	var clock = 60000;

	var loop = function() {
		var child = spawn(self.command[0], self.command.slice(1), {
			cwd: self.cwd,
			env: xtend(process.env, self.env),
			uid: self.uid,
			gid: self.gid,
			stdio: self.stdio,
			windowsVerbatimArguments: self.windowsVerbatimArguments
		});

		self.started = new Date();
		self.status = 'running';
		self.child = child;
		self.pid = child.pid;
		self.emit('spawn', child);

		child.setMaxListeners(0);

		if (child.stdout) {
			child.stdout.on('data', function(data) {
				self.emit('stdout', data);
			});
		}

		if (child.stderr) {
			child.stderr.on('data', function(data) {
				self.emit('stderr', data);
			});
		}

		var clear = function() {
			if (self.child !== child) return false;
			self.child = null;
			self.pid = 0;
			return true;
		};

		child.on('error', function(err) {
			self.emit('warn', err); // too opionated? maybe just forward err
			if (!clear()) return;
			if (self.status === 'stopping') return self._stopped();
			self._crash();
		});

		child.on('exit', function(code, signal) {
			self.emit('exit', code, signal);
			if (!clear()) return;
			if (self.status === 'stopping') return self._stopped();

			clock -= (Date.now() - (self.started ? self.started.getTime() : 0));

			if (clock <= 0) {
				clock = 60000;
				restarts = 0;
			}

			if (++restarts > self.maxRestarts && self.maxRestarts != -1) return self._crash();

			self.status = 'sleeping';
			self.emit('sleep');

			self.timeout = setTimeout(loop, self.sleep);
		});
	};

	clearTimeout(this.timeout);
	loop();

	if (this.status === 'running') this.emit('start');
};

Monitor.prototype.toJSON = function() {
	var doc = {
		id: this.id,
		status: this.status,
		started: this.started,
		pid: this.pid,
		command: this.command,
		cwd: this.cwd,
		env: this.env
	};

	if (!doc.id) delete doc.id;
	if (!doc.pid) delete doc.pid;
	if (!doc.started) delete doc.started;

	return doc;
};

Monitor.prototype._crash = function() {
	if (this.status !== 'running') return;
	this.status = 'crashed';
	this.emit('crash');
	if (this.status === 'crashed') this._stopped();
};

Monitor.prototype._stopped = function() {
	if (this.status === 'stopped') return;
	if (this.status !== 'crashed') this.status = 'stopped';
	this.started = null;
	this.emit('stop');
};

var respawn = function(command, opts) {
	if (!Array.isArray(command)) return respawn(command.command, command);
	return new Monitor(command, opts || {});
};

module.exports = respawn;<|endoftext|>