<commit_before>var merge = require('lodash/merge'),
    Promise = require('bluebird'),
    forIn = require('lodash/forIn'),
    spawn = require('child_process').spawn,
    path = require('path');

// TODO: improve error handling
module.exports = function npm(npmArgs, npmConfig, options) {
    var baseConfig = {progress: false},
        env = process.env;

    options = options || {};
    npmArgs = npmArgs || [];
    npmConfig = npmConfig || {};

    forIn(merge(baseConfig, npmConfig), function (value, key) {
        env['npm_config_' + key] = value;
    });

    options.env = merge(options.env || {}, env);

    return new Promise(function runNpm(resolve, reject) {
        var cp = spawn(path.resolve(__dirname, '../../node_modules/.bin/npm'), npmArgs, options);

        cp.on('error', function (error) {
            return reject(error);
        });

        cp.on('exit', function (code, signal) {
            if (code && code !== 0) {
                return reject(code);
            }

            return resolve(code || signal);
        });
    });
};
<commit_msg>:art: add ability for npm utility to capture output of npm<commit_after>var merge = require('lodash/merge'),
    Promise = require('bluebird'),
    forIn = require('lodash/forIn'),
    spawn = require('child_process').spawn,
    path = require('path');

// TODO: improve error handling
module.exports = function npm(npmArgs, npmConfig, options) {
    var baseConfig = {progress: false},
        env = process.env,
        captureOutput;

    options = options || {};
    npmArgs = npmArgs || [];
    npmConfig = npmConfig || {};

    captureOutput = options.captureOutput || false;
    delete options.captureOutput;

    forIn(merge(baseConfig, npmConfig), function (value, key) {
        env['npm_config_' + key] = value;
    });

    options.env = merge(options.env || {}, env);

    return new Promise(function runNpm(resolve, reject) {
        var cp = spawn(path.resolve(__dirname, '../../node_modules/.bin/npm'), npmArgs, options),
            output, ws, isString;

        if (captureOutput) {
            isString = require('lodash/isString');
            ws = require('stream').Writable({decodeStrings: false});
            output = '';

            ws._write = function (chunk, enc, next) {
                if (!isString(chunk)) {
                    output += chunk.toString();
                } else {
                    output += chunk;
                }

                next();
            };

            cp.stdout.pipe(ws);
        }

        cp.on('error', function (error) {
            return reject(error);
        });

        cp.on('exit', function (code, signal) {
            if (code && code !== 0) {
                return reject(code);
            }

            if (captureOutput && output) {
                return resolve(output);
            }

            return resolve(code || signal);
        });
    });
};

{'fraction_non_alphanumeric': 0.1491108071135431, 'fraction_numerical': 0.0006839945280437756, 'mean_word_length': 2.0310880829015545, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5475907', 'n_tokens_mistral': 844, 'n_tokens_neox': 784, 'n_words': 190}