<commit_before>var async = require('async');

// MemcachedTransaction: a wrapper around 3rdEden's node-memcached module to provide transactional behavior.

// currently supported mutations: 'set', 'del', 'touch'

function MemcachedTransaction(client, options) {
	this.queue = {};    // { key: operation }  operation to be executed per key
	this.cache = {};    // guaranteed to be the latest version of a value, if it's in here
	this.client = client;
	this.options = options || {};

	this.debug = null;

	if (this.options.debug) {
		if (this.options.debug === true) {
			this.debug = console.info;
		} else if (typeof this.options.debug === 'function') {
			this.debug = this.options.debug;
		}
	}
}

module.exports = MemcachedTransaction;

MemcachedTransaction.prototype.get = function (key, cb) {
	var cache = this.cache;

	var op = this.queue[key];
	if (op && op.type === 'del') {
		// this value is scheduled to be deleted, so consider it non-existing and return undefined

		if (cb) {
			cb(null, undefined);
		}
		return;
	}

	var value = cache[key];

	if (value !== undefined) {
		// there is a known uptodate value for this key, so return it instantly

		if (cb) {
			cb(null, value);
		}
		return;
	}

	// get the value from memcached and cache it

	if (this.debug) {
		this.debug('MemcachedTransaction: getting key', key);
	}

	this.client.get(key, function (error, value) {
		if (error) {
			if (cb) {
				cb(error);
			}
		} else {
			cache[key] = value;

			if (cb) {
				cb(null, value);
			}
		}
	});
};

MemcachedTransaction.prototype.getMulti = function (keys, cb) {
	var cache = this.cache;
	var value, result = {};
	var lookup = [];

	// for each key, check if we really need to fetch it, or if there is a known state

	for (var i = 0, len = keys.length; i < len; i++) {
		var key = keys[i];
		var op = this.queue[key];

		if (op && op.type === 'del') {
			// this value is scheduled to be deleted, so consider it non-existing and return undefined

			result[key] = undefined;
		} else {
			value = cache[key];

			if (value === undefined) {
				// prepare for fetching from memcached

				lookup.push(key);
			} else {
				// there is a known uptodate value for this key, so return it instantly

				result[key] = value;
			}
		}
	}

	// if there is nothing to look up from memcached, return all known results

	if (lookup.length === 0) {
		if (cb) {
			cb(null, result);
		}
		return;
	}

	// get the unknown values from memcached and cache them

	if (this.debug) {
		this.debug('MemcachedTransaction: getting keys', lookup);
	}

	this.client.getMulti(lookup, function (error, values) {
		if (error) {
			if (cb) {
				cb(error);
			}
			return;
		}

		for (var key in values) {
			var value = values[key];

			result[key] = value;
			cache[key] = value;
		}

		if (cb) {
			cb(null, result);
		}
	});
};

MemcachedTransaction.prototype.set = function (key, value, ttl, cb) {
	this.queue[key] = { type: 'set', key: key, value: value, ttl: ttl };
	this.cache[key] = value;

	if (cb) {
		cb();
	}
};

MemcachedTransaction.prototype.del = function (key, cb) {
	this.queue[key] = { type: 'del', key: key };
	delete this.cache[key];

	if (cb) {
		cb();
	}
};

MemcachedTransaction.prototype.increment = function (key, amount, cb) {
	return this.client.increment(key, amount, cb);
};

MemcachedTransaction.prototype.inc = MemcachedTransaction.prototype.increment;

MemcachedTransaction.prototype.decrement = function (key, amount, cb) {
	return this.client.decrement(key, amount, cb);
};

MemcachedTransaction.prototype.dec = MemcachedTransaction.prototype.decrement;

MemcachedTransaction.prototype.touch = function (key, ttl, cb) {
	var op = this.queue[key];

	if (op) {
		switch (op.type) {
		case 'set':
			op.ttl = ttl;
			break;
		case 'del':
			// noop
			break;
		}
	} else {
		this.queue[key] = { type: 'touch', key: key, ttl: ttl };
	}

	if (cb) {
		cb();
	}
};

MemcachedTransaction.prototype._exec = function (op, cb) {
	if (this.options.simulate) {
		console.info('Executing', op);
		if (cb) {
			cb();
		}
		return;
	}

	switch (op.type) {
	case 'set':
		if (this.debug) {
			this.debug('MemcachedTransaction: setting key', op.key, 'to value', op.value, 'with TTL', op.ttl || 0);
		}

		this.client.set(op.key, op.value, op.ttl || 0, cb);
		break;
	case 'del':
		if (this.debug) {
			this.debug('MemcachedTransaction: deleting key', op.key);
		}

		this.client.del(op.key, cb);
		break;
	case 'touch':
		if (this.debug) {
			this.debug('MemcachedTransaction: touching key', op.key, 'with TTL', op.ttl || 0);
		}

		this.client.command(function touch(noreply) {
			return {
				command: ['touch', op.key, op.ttl || 0].join(' '),
				key: op.key,
				type: 'touch',
				callback: cb
			};
		});
		break;
	default:
		if (cb) {
			cb('Unknown operation type: ' + op.type);
		}
		break;
	}
};

MemcachedTransaction.prototype.commit = function (cb) {
	var ops = [];
	for (var key in this.queue) {
		ops.push(this.queue[key]);
	}

	var len = ops.length;

	// hot code paths: length 0 and 1

	if (len === 0) {
		return cb ? cb() : null;
	}

	if (len === 1) {
		return this._exec(ops[0], cb);
	}

	// more than 1 operation

	var that = this;

	async.forEachSeries(
		ops,
		function (op, callback) {
			that._exec(op, callback);
		},
		function (error) {
			if (cb) {
				cb(error);
			}
		}
	);
};

MemcachedTransaction.prototype.rollBack = function (cb) {
	this.queue = {};
	this.cache = {};

	if (cb) {
		cb();
	}
};

<commit_msg>* Removed extra line<commit_after>var async = require('async');

// MemcachedTransaction: a wrapper around 3rdEden's node-memcached module to provide transactional behavior.

// currently supported mutations: 'set', 'del', 'touch'

function MemcachedTransaction(client, options) {
	this.queue = {};    // { key: operation }  operation to be executed per key
	this.cache = {};    // guaranteed to be the latest version of a value, if it's in here
	this.client = client;
	this.options = options || {};

	this.debug = null;

	if (this.options.debug) {
		if (this.options.debug === true) {
			this.debug = console.info;
		} else if (typeof this.options.debug === 'function') {
			this.debug = this.options.debug;
		}
	}
}

module.exports = MemcachedTransaction;

MemcachedTransaction.prototype.get = function (key, cb) {
	var cache = this.cache;

	var op = this.queue[key];
	if (op && op.type === 'del') {
		// this value is scheduled to be deleted, so consider it non-existing and return undefined

		if (cb) {
			cb(null, undefined);
		}
		return;
	}

	var value = cache[key];

	if (value !== undefined) {
		// there is a known uptodate value for this key, so return it instantly

		if (cb) {
			cb(null, value);
		}
		return;
	}

	// get the value from memcached and cache it

	if (this.debug) {
		this.debug('MemcachedTransaction: getting key', key);
	}

	this.client.get(key, function (error, value) {
		if (error) {
			if (cb) {
				cb(error);
			}
		} else {
			cache[key] = value;

			if (cb) {
				cb(null, value);
			}
		}
	});
};

MemcachedTransaction.prototype.getMulti = function (keys, cb) {
	var cache = this.cache;
	var value, result = {};
	var lookup = [];

	// for each key, check if we really need to fetch it, or if there is a known state

	for (var i = 0, len = keys.length; i < len; i++) {
		var key = keys[i];
		var op = this.queue[key];

		if (op && op.type === 'del') {
			// this value is scheduled to be deleted, so consider it non-existing and return undefined

			result[key] = undefined;
		} else {
			value = cache[key];

			if (value === undefined) {
				// prepare for fetching from memcached

				lookup.push(key);
			} else {
				// there is a known uptodate value for this key, so return it instantly

				result[key] = value;
			}
		}
	}

	// if there is nothing to look up from memcached, return all known results

	if (lookup.length === 0) {
		if (cb) {
			cb(null, result);
		}
		return;
	}

	// get the unknown values from memcached and cache them

	if (this.debug) {
		this.debug('MemcachedTransaction: getting keys', lookup);
	}

	this.client.getMulti(lookup, function (error, values) {
		if (error) {
			if (cb) {
				cb(error);
			}
			return;
		}

		for (var key in values) {
			var value = values[key];

			result[key] = value;
			cache[key] = value;
		}

		if (cb) {
			cb(null, result);
		}
	});
};

MemcachedTransaction.prototype.set = function (key, value, ttl, cb) {
	this.queue[key] = { type: 'set', key: key, value: value, ttl: ttl };
	this.cache[key] = value;

	if (cb) {
		cb();
	}
};

MemcachedTransaction.prototype.del = function (key, cb) {
	this.queue[key] = { type: 'del', key: key };
	delete this.cache[key];

	if (cb) {
		cb();
	}
};

MemcachedTransaction.prototype.increment = function (key, amount, cb) {
	return this.client.increment(key, amount, cb);
};

MemcachedTransaction.prototype.inc = MemcachedTransaction.prototype.increment;

MemcachedTransaction.prototype.decrement = function (key, amount, cb) {
	return this.client.decrement(key, amount, cb);
};

MemcachedTransaction.prototype.dec = MemcachedTransaction.prototype.decrement;

MemcachedTransaction.prototype.touch = function (key, ttl, cb) {
	var op = this.queue[key];

	if (op) {
		switch (op.type) {
		case 'set':
			op.ttl = ttl;
			break;
		case 'del':
			// noop
			break;
		}
	} else {
		this.queue[key] = { type: 'touch', key: key, ttl: ttl };
	}

	if (cb) {
		cb();
	}
};

MemcachedTransaction.prototype._exec = function (op, cb) {
	if (this.options.simulate) {
		console.info('Executing', op);
		if (cb) {
			cb();
		}
		return;
	}

	switch (op.type) {
	case 'set':
		if (this.debug) {
			this.debug('MemcachedTransaction: setting key', op.key, 'to value', op.value, 'with TTL', op.ttl || 0);
		}

		this.client.set(op.key, op.value, op.ttl || 0, cb);
		break;
	case 'del':
		if (this.debug) {
			this.debug('MemcachedTransaction: deleting key', op.key);
		}

		this.client.del(op.key, cb);
		break;
	case 'touch':
		if (this.debug) {
			this.debug('MemcachedTransaction: touching key', op.key, 'with TTL', op.ttl || 0);
		}

		this.client.command(function touch(noreply) {
			return {
				command: ['touch', op.key, op.ttl || 0].join(' '),
				key: op.key,
				type: 'touch',
				callback: cb
			};
		});
		break;
	default:
		if (cb) {
			cb('Unknown operation type: ' + op.type);
		}
		break;
	}
};

MemcachedTransaction.prototype.commit = function (cb) {
	var ops = [];
	for (var key in this.queue) {
		ops.push(this.queue[key]);
	}

	var len = ops.length;

	// hot code paths: length 0 and 1

	if (len === 0) {
		return cb ? cb() : null;
	}

	if (len === 1) {
		return this._exec(ops[0], cb);
	}

	// more than 1 operation

	var that = this;

	async.forEachSeries(
		ops,
		function (op, callback) {
			that._exec(op, callback);
		},
		function (error) {
			if (cb) {
				cb(error);
			}
		}
	);
};

MemcachedTransaction.prototype.rollBack = function (cb) {
	this.queue = {};
	this.cache = {};

	if (cb) {
		cb();
	}
};

<|endoftext|>


<commit_before>/**
 * @file This is a tweetable quotes tag plugin for the Hexo static site generator.
 * @copyright Chathu Vishwajith 2015-2016
 * @author Chathu Vishwajith
 * @license MIT
 */

 // Strict mode.
 'use strict';

// Package modules.
const assign = require('object-assign');
const path = require('path');
const nunjucks = require('nunjucks');
const querystring = require('querystring');

// Configuration
hexo.config.tweetableQuote = assign({
	quote_font_color    : '#258fb8',
	quote_font_size : '1.7em',
	link_font_color : '#6e7b8d',
	link_font_size : '1.0em'
}, hexo.config.tweetableQuote);

nunjucks.configure(__dirname, {watch: false});

hexo.extend.tag.register('tweetableQuote', function(args) {

	let quote = args[0];
	let author = args[1];
	let tweetURL = 'https://twitter.com/intent/tweet?'+querystring.stringify({
		"text":quote+" - "+author,
		"via":"iamchathu",
		"related" : "iamchathu"
	});
	tweetURL = tweetURL + ";url=" + "{{% url %}}";

	const data = {
		"quote": quote,
		"author": author,
		"tweetURL":tweetURL,
		"quote_font_color":hexo.config.tweetableQuote.quote_font_color,
		"quote_font_size":hexo.config.tweetableQuote.quote_font_size,
		"link_font_size":hexo.config.tweetableQuote.link_font_size,
		"link_font_color":hexo.config.tweetableQuote.link_font_color,
	};

	return new Promise(function (resolve, reject) {
		nunjucks.render('tweetable-quote.njk', data, function (err, res) {
			if (err) {
				return reject(err);
			}
			resolve(res);
		});
	});

},{async: true});
<commit_msg>Add twitter account details to config<commit_after>/**
 * @file This is a tweetable quotes tag plugin for the Hexo static site generator.
 * @copyright Chathu Vishwajith 2015-2016
 * @author Chathu Vishwajith
 * @license MIT
 */

 // Strict mode.
 'use strict';

// Package modules.
const assign = require('object-assign');
const path = require('path');
const nunjucks = require('nunjucks');
const querystring = require('querystring');

// Configuration
hexo.config.tweetableQuote = assign({
	quote_font_color    : '#258fb8',
	quote_font_size : '1.7em',
	link_font_color : '#6e7b8d',
	link_font_size : '1.0em',
	via_twitter_account : '',
	related_twitter_accounts : ''
}, hexo.config.tweetableQuote);

nunjucks.configure(__dirname, {watch: false});

hexo.extend.tag.register('tweetableQuote', function(args) {

	let quote = args[0];
	let author = args[1];
	let tweetURL = 'https://twitter.com/intent/tweet?'+querystring.stringify({
		"text":quote+" - "+author,
		"via":hexo.config.tweetableQuote.via_twitter_account,
		"related" : hexo.config.tweetableQuote.related_twitter_accounts
	});

	const data = {
		"quote": quote,
		"author": author,
		"tweetURL":tweetURL,
		"quote_font_color":hexo.config.tweetableQuote.quote_font_color,
		"quote_font_size":hexo.config.tweetableQuote.quote_font_size,
		"link_font_size":hexo.config.tweetableQuote.link_font_size,
		"link_font_color":hexo.config.tweetableQuote.link_font_color,
	};

	return new Promise(function (resolve, reject) {
		nunjucks.render('tweetable-quote.njk', data, function (err, res) {
			if (err) {
				return reject(err);
			}
			resolve(res);
		});
	});

},{async: true});
<|endoftext|>


<commit_before>var memwatch = require('memwatch');
var winston = require('winston');
var _ = require('lodash');

var allocations = {};
var snoitacolla = {};

function updateHeapDiff(diff) {
  var oldValue;
  var newValue;
  diff.change.details.forEach(function(data) {
    if (allocations[data.what] !== undefined) {
      oldValue = allocations[data.what];
      snoitacolla[oldValue].pop(snoitacolla[oldValue].indexOf(oldValue));
      if (!snoitacolla[oldValue].length) {
        delete snoitacolla[oldValue];
      }
    } else {
      oldValue = 0;
    }
    newValue = oldValue + data["+"] - data["-"];
    allocations[data.what] = newValue;
    if (!snoitacolla[newValue]) snoitacolla[newValue] = [];
    snoitacolla[newValue].push(data.what);
  });
}

function topHeapAllocations(howMany) {
  howMany = howMany || 6;
  var result = [];
  // annoyingly, we have to convert the keys to integers first
  var keys = [];
  Object.keys(snoitacolla).forEach(function(key) { keys.push(parseInt(key, 10)); });
  // sort greatest to least
  keys.sort(function(a,b) {return b-a;});

  keys.slice(0, howMany).forEach(function(key) {
    result.push([key, snoitacolla[key]]);
  });
  return result;
}

function MemLogger(options) {
  var _options = {};
  if (!options.componentName) {
    throw new Error('MemLogger should have a componentName option');
  }
  _options.logger = new(winston.Logger)({
    transports: [
      new(winston.transports.Console)()
    ]
  });
  _options.logfileRoot = '/var/log/node/';
  _options.logfilename = {
    'leak': _options.logfileRoot + options.componentName + '-mLeak.log';
    'stats': _options.logfileRoot + options.componentName + '-mStats.log';
  }
  _options.doMemoryStats = true;
  _options.hdInterval = 1000 * 60 * 15;
  this._options = _.assign(_options, options);
}

MemLogger.prototype.init = function() {
  var self = this;
  self.hd = new memwatch.HeapDiff();
  self.lastHD = Date.now();
  var memLeakLogger = new(winston.Logger)({
    transports: [
      new(winston.transports.File)({
        filename: this._options.logfilename.leak
      })
    ]
  });

  memwatch.on('leak', function(info) {
    self._options.logger.error(' >>>>>>>>>> MEMORY LEAK DETECTED', info);
    memLeakLogger.error(info);
    updateHeapDiff(self.hd.end());
    self.hd = new memwatch.HeapDiff();
    self.lastHD = Date.now();
    self.tha = topHeapAllocations(10);
    self._options.logger.info(' >>>>>>>>>> top 10 heap allocations', self.tha );
    memLeakLogger.info(' >>>>>>>>>> top 10 heap allocations', self.tha );
  });

  if (self._options.doMemoryStats) {
    var memStatsLogger = new(winston.Logger)({
      transports: [
        new(winston.transports.File)({
          filename: this._options.logfilename.stats
        })
      ]
    });
    memwatch.on('stats', function(stats) {

      if (stats.type === 'inc') {
        self._options.logger.info(' >>>>>>>>>> post incremental gc sample', stats);
        memStatsLogger.info(' >>>>>>>>>> post incremental gc sample', stats);
      } else {
        if ((Date.now() - self.lastHD) > self._options.hdInterval) {
          updateHeapDiff(self.hd.end());
          self.hd = new memwatch.HeapDiff();
          self.lastHD = Date.now();
          self.tha = topHeapAllocations(10);
          self._options.logger.info(' >>>>>>>>>> heap allocations', self.tha );
          memStatsLogger.info(' >>>>>>>>>> heap allocations', self.tha );
        }
        self._options.logger.info(' >>>>>>>>>> post full gc', stats );
        memStatsLogger.info(' >>>>>>>>>> post full gc', stats );
      }
    });
  }
}
module.exports = MemLogger;<commit_msg>fix log file structure<commit_after>var memwatch = require('memwatch');
var winston = require('winston');
var _ = require('lodash');

var allocations = {};
var snoitacolla = {};

function updateHeapDiff(diff) {
  var oldValue;
  var newValue;
  diff.change.details.forEach(function(data) {
    if (allocations[data.what] !== undefined) {
      oldValue = allocations[data.what];
      snoitacolla[oldValue].pop(snoitacolla[oldValue].indexOf(oldValue));
      if (!snoitacolla[oldValue].length) {
        delete snoitacolla[oldValue];
      }
    } else {
      oldValue = 0;
    }
    newValue = oldValue + data["+"] - data["-"];
    allocations[data.what] = newValue;
    if (!snoitacolla[newValue]) snoitacolla[newValue] = [];
    snoitacolla[newValue].push(data.what);
  });
}

function topHeapAllocations(howMany) {
  howMany = howMany || 6;
  var result = [];
  // annoyingly, we have to convert the keys to integers first
  var keys = [];
  Object.keys(snoitacolla).forEach(function(key) { keys.push(parseInt(key, 10)); });
  // sort greatest to least
  keys.sort(function(a,b) {return b-a;});

  keys.slice(0, howMany).forEach(function(key) {
    result.push([key, snoitacolla[key]]);
  });
  return result;
}

function MemLogger(options) {
  var _options = {};
  if (!options.componentName) {
    throw new Error('MemLogger should have a componentName option');
  }
  _options.logger = new(winston.Logger)({
    transports: [
      new(winston.transports.Console)()
    ]
  });
  _options.logfileRoot = '/var/log/node/';
  _options.logfilename = {
    'leak': _options.logfileRoot + options.componentName + '-mLeak.log',
    'stats': _options.logfileRoot + options.componentName + '-mStats.log'
  }
  _options.doMemoryStats = true;
  _options.hdInterval = 1000 * 60 * 15;
  this._options = _.assign(_options, options);
}

MemLogger.prototype.init = function() {
  var self = this;
  self.hd = new memwatch.HeapDiff();
  self.lastHD = Date.now();
  var memLeakLogger = new(winston.Logger)({
    transports: [
      new(winston.transports.File)({
        filename: this._options.logfilename.leak
      })
    ]
  });

  memwatch.on('leak', function(info) {
    self._options.logger.error(' >>>>>>>>>> MEMORY LEAK DETECTED', info);
    memLeakLogger.error(info);
    updateHeapDiff(self.hd.end());
    self.hd = new memwatch.HeapDiff();
    self.lastHD = Date.now();
    self.tha = topHeapAllocations(10);
    self._options.logger.info(' >>>>>>>>>> top 10 heap allocations', self.tha );
    memLeakLogger.info(' >>>>>>>>>> top 10 heap allocations', self.tha );
  });

  if (self._options.doMemoryStats) {
    var memStatsLogger = new(winston.Logger)({
      transports: [
        new(winston.transports.File)({
          filename: this._options.logfilename.stats
        })
      ]
    });
    memwatch.on('stats', function(stats) {

      if (stats.type === 'inc') {
        self._options.logger.info(' >>>>>>>>>> post incremental gc sample', stats);
        memStatsLogger.info(' >>>>>>>>>> post incremental gc sample', stats);
      } else {
        if ((Date.now() - self.lastHD) > self._options.hdInterval) {
          updateHeapDiff(self.hd.end());
          self.hd = new memwatch.HeapDiff();
          self.lastHD = Date.now();
          self.tha = topHeapAllocations(10);
          self._options.logger.info(' >>>>>>>>>> heap allocations', self.tha );
          memStatsLogger.info(' >>>>>>>>>> heap allocations', self.tha );
        }
        self._options.logger.info(' >>>>>>>>>> post full gc', stats );
        memStatsLogger.info(' >>>>>>>>>> post full gc', stats );
      }
    });
  }
}
module.exports = MemLogger;<|endoftext|>


<commit_before>'use strict';

var errcode = require('err-code');
var retry = require('retry');
var Promise = require('bluebird');

var emptyFunc = function () {};

function promiseRetry(fn, options) {
    var operation = retry.operation(options);

    return new Promise(function (resolve, reject) {
        operation.attempt(function () {
            var promise;

            promise = Promise.try(function () {
                return fn(function (err) {
                    if (err && err.code === 'EPROMISERETRY') {
                        err = err.original;
                    }

                    throw errcode('Retrying', 'EPROMISERETRY', {
                        original: err
                    });
                });
            });

            promise.then(resolve, function (err) {
                if (err && err.code === 'EPROMISERETRY') {
                    err = err.original;

                    if (operation.retry(err)) {
                        throw err;
                    }
                }

                reject(err);
            })
            .done(emptyFunc, emptyFunc);
        });
    });
}

module.exports = promiseRetry;
<commit_msg>Simplify.<commit_after>'use strict';

var errcode = require('err-code');
var retry = require('retry');
var Promise = require('bluebird');

function promiseRetry(fn, options) {
    var operation = retry.operation(options);

    return new Promise(function (resolve, reject) {
        operation.attempt(function () {
            var promise;

            promise = Promise.try(function () {
                return fn(function (err) {
                    if (err && err.code === 'EPROMISERETRY') {
                        err = err.original;
                    }

                    throw errcode('Retrying', 'EPROMISERETRY', {
                        original: err
                    });
                });
            });

            promise.done(resolve, function (err) {
                if (err && err.code === 'EPROMISERETRY') {
                    err = err.original;

                    if (operation.retry(err)) {
                        return;
                    }
                }

                reject(err);
            });
        });
    });
}

module.exports = promiseRetry;
<|endoftext|>


<commit_before>#! /usr/bin/env node

// TODO Clean up some depedencies
// Some things like shelljs, isThere, and minimist could probably go away

var path = require('path');
var fs = require('fs');
var child_process = require('child_process');

var shell = require('shelljs');
var Promise = require('bluebird');
var rimraf = require('rimraf');
var md5 = require('md5');
var LineByLineReader = require('line-by-line');
var isThere = require('is-there');
var minimist = require('minimist');
var npm = require('npm'); // Can't seem to Promisify npm commands...
var targz = require('targz');

var compress = Promise.promisify(targz.compress);
var decompress = Promise.promisify(targz.decompress);

var argv = minimist(process.argv.slice(2));

var cacheDir = path.join(__dirname, '.cache');

if (argv.c) {
  console.log('Clearing cache...');
  rimraf.sync(cacheDir);
  console.log('Finished');
  process.exit(0);
}

var scriptName = argv._[0];
var scriptPath = path.join(process.cwd(), scriptName);
var scriptDir = path.dirname(scriptPath);
var scriptNodeModules = path.join(scriptDir, 'node_modules');

var start = new Date();

// Cache file gz compression level
// Between 0 and 9, 0 being none and 9 being max compression
// We prefer speed, so keep it low
var gzCompressionLevel = 3;

readArgs()
  .then(loadDependenciesFromCache)
  .then(runScript)
  .then(removeScriptNodeModules)
  .catch(function(err) {
    console.log('Error: ', err);
  })
  .finally(function() {
    //console.log('Finished after: ', (new Date() - start));
  })

function runScript() {
  return new Promise(function(resolve, reject) {
    var args = process.argv.slice(3);
    child_process.fork(scriptPath, args)
    .on('close', function() {
      resolve();
    })
    .on('error', function(err) {
      reject(err);
    });
  });
}

function readArgs() {
  var args = [];

  return readLines(scriptPath, function(line) {
    line = line.replace(/\s/g, '');

    if (startsWith(line, '#') || line.length === 0) {
      // Skip the initial shebang and any blank lines
      return;
    }

    if (startsWith(line, '//!')) {
      // Argument!
      var argLine = line.slice('3').split('@');
      args.push({
        name: argLine[0],
        version: argLine[1]
      });

    } else if (startsWith(line, '//')) {
      // Comment, can skip
      return;

    } else {
      // Real code = finished reading all the arguments
      return false;
    }

  }).then(function() {
    return args;
  });
}

function startsWith(str, prefix) {
  return (str.substring(0, prefix.length) === prefix);
}

function removeScriptNodeModules() {
  rimraf.sync(scriptNodeModules);
}

function installDependencies(args) {
  return new Promise(function(resolve, reject) {
    npm.load(undefined, function(err) {
      if (err) {
        return reject(err);
      }

      resolve(Promise.map(args, installDependency));
    });
  });
}

function installDependency(arg) {
  return new Promise(function(resolve, reject) {
    var dep = arg.name;
    if (arg.version) {
      dep += '@' + arg.version;
    }

    npm.commands.install([dep], function(err) {
      if (err) {
        return reject(err);
      }

      resolve(arg);
    });
  });
}

function getCacheFile(args) {
  var hash = md5(JSON.stringify(args));
  return path.resolve(cacheDir, hash + '.tar.gz');
}

function loadDependenciesFromCache(args) {
  if (args.length === 0) {
      return Promise.resolve();
  }

  var cacheFile = getCacheFile(args);

  if (isThere(cacheFile)) {
    return decompress({
      src: cacheFile,
      dest: scriptNodeModules
    });
  } else {
    return installDependencies(args)
      .then(function() {
        shell.mkdir('-p', cacheDir); // Make sure cache directory exists first
        // And cache the dependencies for later
        return compress({
          src: scriptNodeModules,
          dest: cacheFile,
          gz: {
            level: gzCompressionLevel
          }
        });
      });
  }
}

function clearCache() {
  rimraf.sync(scriptNodeModules);
}

function readLines(file, lineFn) {
  return new Promise(function(resolve, reject) {
    var lr = new LineByLineReader(file);
    var closed = false;

    lr.on('error', function (err) {
      reject(err);
    });

    lr.on('line', function (line) {
      if (closed) {
        return;
      }

      if (lineFn(line) === false) {
        closed = true;
        lr.close();
      }
    });

    lr.on('end', function () {
      resolve();
    });
  });
}
<commit_msg>Minor typos<commit_after>#! /usr/bin/env node

// TODO Clean up some dependencies
// Some things like shelljs, isThere, and minimist could probably go away

var path = require('path');
var fs = require('fs');
var child_process = require('child_process');

var shell = require('shelljs');
var Promise = require('bluebird');
var rimraf = require('rimraf');
var md5 = require('md5');
var LineByLineReader = require('line-by-line');
var isThere = require('is-there');
var minimist = require('minimist');
var npm = require('npm'); // Can't seem to Promisify npm commands...
var targz = require('targz');

var compress = Promise.promisify(targz.compress);
var decompress = Promise.promisify(targz.decompress);

var argv = minimist(process.argv.slice(2));

var cacheDir = path.join(__dirname, '.cache');

if (argv.c) {
  console.log('Clearing cache...');
  rimraf.sync(cacheDir);
  console.log('Finished');
  process.exit(0);
}

var scriptName = argv._[0];
var scriptPath = path.join(process.cwd(), scriptName);
var scriptDir = path.dirname(scriptPath);
var scriptNodeModules = path.join(scriptDir, 'node_modules');

var start = new Date();

// Cache file gz compression level
// Between 0 and 9, 0 being none and 9 being max compression
// We prefer speed, so keep it low
var gzCompressionLevel = 3;

readArgs()
  .then(loadDependenciesFromCache)
  .then(runScript)
  .then(removeScriptNodeModules)
  .catch(function(err) {
    console.log('Error: ', err);
  })
  .finally(function() {
    //console.log('Finished after: ', (new Date() - start));
  });

function runScript() {
  return new Promise(function(resolve, reject) {
    var args = process.argv.slice(3);
    child_process.fork(scriptPath, args)
    .on('close', function() {
      resolve();
    })
    .on('error', function(err) {
      reject(err);
    });
  });
}

function readArgs() {
  var args = [];

  return readLines(scriptPath, function(line) {
    line = line.replace(/\s/g, '');

    if (startsWith(line, '#') || line.length === 0) {
      // Skip the initial shebang and any blank lines
      return;
    }

    if (startsWith(line, '//!')) {
      // Argument!
      var argLine = line.slice('3').split('@');
      args.push({
        name: argLine[0],
        version: argLine[1]
      });

    } else if (startsWith(line, '//')) {
      // Comment, can skip
      return;

    } else {
      // Real code = finished reading all the arguments
      return false;
    }

  }).then(function() {
    return args;
  });
}

function startsWith(str, prefix) {
  return (str.substring(0, prefix.length) === prefix);
}

function removeScriptNodeModules() {
  rimraf.sync(scriptNodeModules);
}

function installDependencies(args) {
  return new Promise(function(resolve, reject) {
    npm.load(undefined, function(err) {
      if (err) {
        return reject(err);
      }

      resolve(Promise.map(args, installDependency));
    });
  });
}

function installDependency(arg) {
  return new Promise(function(resolve, reject) {
    var dep = arg.name;
    if (arg.version) {
      dep += '@' + arg.version;
    }

    npm.commands.install([dep], function(err) {
      if (err) {
        return reject(err);
      }

      resolve(arg);
    });
  });
}

function getCacheFile(args) {
  var hash = md5(JSON.stringify(args));
  return path.resolve(cacheDir, hash + '.tar.gz');
}

function loadDependenciesFromCache(args) {
  if (args.length === 0) {
      return Promise.resolve();
  }

  var cacheFile = getCacheFile(args);

  if (isThere(cacheFile)) {
    return decompress({
      src: cacheFile,
      dest: scriptNodeModules
    });
  } else {
    return installDependencies(args).then(function() {
      shell.mkdir('-p', cacheDir); // Make sure cache directory exists first
      // And cache the dependencies for later
      return compress({
        src: scriptNodeModules,
        dest: cacheFile,
        gz: {
          level: gzCompressionLevel
        }
      });
    });
  }
}

function clearCache() {
  rimraf.sync(scriptNodeModules);
}

function readLines(file, lineFn) {
  return new Promise(function(resolve, reject) {
    var lr = new LineByLineReader(file);
    var closed = false;

    lr.on('error', function (err) {
      reject(err);
    });

    lr.on('line', function (line) {
      if (closed) {
        return;
      }

      if (lineFn(line) === false) {
        closed = true;
        lr.close();
      }
    });

    lr.on('end', function () {
      resolve();
    });
  });
}
<|endoftext|>


<commit_before>'use strict'

const EventEmitter = require('events').EventEmitter
const Parser = require('node-expat').Parser

class XMLStream extends EventEmitter {
  constructor (stream, options) {
    super()
    options = options || {}
    this.encoding = options.encoding || 'UTF-8'
    this.stream = stream
    this.parser = new Parser(this.encoding)
    this.stream.pipe(this.parser)
    this.explicitText = options.explicitText
    this.explicitArrays = options.explicitArrays
    this.disableAutotrim = options.disableAutotrim
    this._attachEvents()
    this._root = {}
    this._elementTree = [{
      isRoot: true,
      element: this._root,
      children: null
    }]
  }

  _attachEvents () {
    const stream = this.stream
    const parser = this.parser
    stream.on('error', this._handleError.bind(this))
    parser.on('error', this._handleError.bind(this))
    parser.on('close', this._handleClose.bind(this))
    parser.on('startElement', this._handleStartElement.bind(this))
    parser.on('endElement', this._handleEndElement.bind(this))
    parser.on('text', this._handleText.bind(this))
    parser.on('end', this._handleEnd.bind(this))
  }

  _handleEnd () {
    this.emit('end', this._root)
  }

  _handleClose () {
    this.emit('close')
  }

  _handleError (err) {
    // We are only emitting one error.
    if (this._errored) return
    this._errored = true
    this.emit('error', err)
    this.parser.destroy()
  }

  _getLastElementFromTree () {
    const tree = this._elementTree
    return tree[tree.length - 1]
  }

  _handleStartElement (name, attrs) {
    const newElement = {
      $: attrs
    }

    const parent = this._getLastElementFromTree()

    this._elementTree.push({
      isRoot: false,
      element: newElement,
      children: [],
      parent: parent,
      name: name
    })

    const current = this._getLastElementFromTree()

    if (!parent.isRoot) {
      if (!parent.element[name]) {
        parent.element[name] = []
        parent.children.push(name)
      }
      let newLen = parent.element[name].push(newElement)
      current.childIndex = newLen - 1
    } else {
      this._root[name] = newElement
    }
  }

  _handleEndElement (endName) {
    const oldElement = this._elementTree.pop()
    const name = oldElement.name
    const children = oldElement.children
    const parent = oldElement.parent
    const childIndex = oldElement.childIndex
    let el = oldElement.element

    if (name !== endName) {
      return this._handleError(new Error(`parser ended element '${endName}', which is not the element we are building ('${name}')`))
    }

    if (!this.explicitArrays) {
      for (let i = 0; i < children.length; i++) {
        let child = children[i]
        if (el[child].length === 1) {
          el[child] = el[child][0]
        }
      }
    }

    if (!this.disableAutotrim) {
      el._ = el._.trim()
    }

    if (!this.explicitText) {
      let hasProps = false
      for (let a in el.$) {
        if (el.$.hasOwnProperty(a)) {
          hasProps = true
          break
        }
      }
      if (!hasProps && !children.length) {
        el = el._
        // We also need to set this child on the parent.
        if (!parent.isRoot) {
          parent.element[name][childIndex] = el
        }
      }
    }

    this.emit('element', el, name)
    this.emit('element: ' + name, el, name)
  }

  _handleText (text) {
    const curel = this._getLastElementFromTree().element
    curel._ = curel._ || ''
    curel._ += text
  }

  pause () {
    this.stream.pause()
  }

  resume () {
    this.stream.resume()
  }
}

module.exports = XMLStream
<commit_msg>all elements will have text<commit_after>'use strict'

const EventEmitter = require('events').EventEmitter
const Parser = require('node-expat').Parser

class XMLStream extends EventEmitter {
  constructor (stream, options) {
    super()
    options = options || {}
    this.encoding = options.encoding || 'UTF-8'
    this.stream = stream
    this.parser = new Parser(this.encoding)
    this.stream.pipe(this.parser)
    this.explicitText = options.explicitText
    this.explicitArrays = options.explicitArrays
    this.disableAutotrim = options.disableAutotrim
    this._attachEvents()
    this._root = {}
    this._elementTree = [{
      isRoot: true,
      element: this._root,
      children: null
    }]
  }

  _attachEvents () {
    const stream = this.stream
    const parser = this.parser
    stream.on('error', this._handleError.bind(this))
    parser.on('error', this._handleError.bind(this))
    parser.on('close', this._handleClose.bind(this))
    parser.on('startElement', this._handleStartElement.bind(this))
    parser.on('endElement', this._handleEndElement.bind(this))
    parser.on('text', this._handleText.bind(this))
    parser.on('end', this._handleEnd.bind(this))
  }

  _handleEnd () {
    this.emit('end', this._root)
  }

  _handleClose () {
    this.emit('close')
  }

  _handleError (err) {
    // We are only emitting one error.
    if (this._errored) return
    this._errored = true
    this.emit('error', err)
    this.parser.destroy()
  }

  _getLastElementFromTree () {
    const tree = this._elementTree
    return tree[tree.length - 1]
  }

  _handleStartElement (name, attrs) {
    const newElement = {
      $: attrs
    }

    const parent = this._getLastElementFromTree()

    this._elementTree.push({
      isRoot: false,
      element: newElement,
      children: [],
      parent: parent,
      name: name
    })

    const current = this._getLastElementFromTree()

    if (!parent.isRoot) {
      if (!parent.element[name]) {
        parent.element[name] = []
        parent.children.push(name)
      }
      let newLen = parent.element[name].push(newElement)
      current.childIndex = newLen - 1
    } else {
      this._root[name] = newElement
    }
  }

  _handleEndElement (endName) {
    const oldElement = this._elementTree.pop()
    const name = oldElement.name
    const children = oldElement.children
    const parent = oldElement.parent
    const childIndex = oldElement.childIndex
    let el = oldElement.element

    if (name !== endName) {
      return this._handleError(new Error(`parser ended element '${endName}', which is not the element we are building ('${name}')`))
    }

    if (!this.explicitArrays) {
      for (let i = 0; i < children.length; i++) {
        let child = children[i]
        if (el[child].length === 1) {
          el[child] = el[child][0]
        }
      }
    }

    if (!el._) {
      el._ = ''
    }

    if (!this.disableAutotrim) {
      el._ = el._.trim()
    }

    if (!this.explicitText) {
      let hasProps = false
      for (let a in el.$) {
        if (el.$.hasOwnProperty(a)) {
          hasProps = true
          break
        }
      }
      if (!hasProps && !children.length) {
        el = el._
        // We also need to set this child on the parent.
        if (!parent.isRoot) {
          parent.element[name][childIndex] = el
        }
      }
    }

    this.emit('element', el, name)
    this.emit('element: ' + name, el, name)
  }

  _handleText (text) {
    const curel = this._getLastElementFromTree().element
    curel._ = curel._ || ''
    curel._ += text
  }

  pause () {
    this.stream.pause()
  }

  resume () {
    this.stream.resume()
  }
}

module.exports = XMLStream
<|endoftext|>


<commit_before>module.exports = {
  name: 'accounting'
};

// module.exports = {
//   name: 'accounting',

//   init: function() {
//     this.treePaths['addon'] = 'src';
//   }
// };
<commit_msg>Remove commented code<commit_after>module.exports = {
  name: 'accounting'
};
<|endoftext|>


<commit_before>var models = require('./models');
<commit_msg>Remove index.js<commit_after><|endoftext|>


<commit_before>/* jshint asi:true */

var axios = require('axios');

var MLab = function (options) {
  if (!(this instanceof MLab)) {
    return new MLab(options);
  }
  this._key = options.key
  this._host = options.host || 'https://api.mlab.com'
  this._uri = options.uri || '/api'
  this._version = options.version || '1'
  this._database = options.database
  this._basePath = [this._host, this._uri, this._version].join('/')
  var ap = {
    baseURL: this._host,
    timeout: options.timeout || 10000,
    headers: { 'X-Requested-With': 'XMLHttpRequest' }
  }
  ap.onUploadProgress = options.onUploadProgress
  ap.onDownloadProgress = options.onDownloadProgress
  this.axios = axios.create(ap)
  this.listDatabases()
    .then(function (response) {
      if (response.message === 'Please provide a valid API key.') throw new Error('Invalid API key');
    })
    .catch(function (error) {
      throw new Error('No DB connection');
    })
}

    MLab.prototype.setDatabase = function (database) {
      if ((typeof database !== 'string') || (database === undefined)) {
        throw new Error('database name is required');
      }
      this._database = database
    }

    MLab.prototype.makePath = function (uri, params) {
      realUri = Array.isArray(uri) ? uri.join('/') : uri;
      return [params && params.path ? params.path : this._basePath, 'databases', params && params.database ? params.database : this._database, realUri].join('/')
    };

    MLab.prototype.specialCharChanger = function (str) {
      return str.replace(/ /gi, '%20').replace(/"/gi, '%22');
    };

    MLab.prototype.meters2radians = function (meters) {
      return meters / 6378100
    };

    MLab.prototype.doParams = function (params) {
      var ap = { apiKey: this._key }
      if (params.query) ap.q = JSON.stringify(params.query)
      if (params.count) ap.c = true
      if (params.fields) ap.f = JSON.stringify(params.fields)
      if (params.findOne) ap.fo = true
      if (params.sort) ap.s = JSON.stringify(params.sort)
      if (params.skip) ap.sk = params.skip
      if (params.limit) ap.l = params.limit
      if (params.all) ap.m = true
      if (params.upsert) ap.u = true
      return ap
    }

    MLab.prototype.listDatabases = function () {
      return this.axios.get(this._basePath + '/databases', {
        params: { apiKey: this._key }
      })
    };

    MLab.prototype.listCollections = function (database) {
      return this.axios.get(this.makePath('collections', { database: database }), {
        params: { apiKey: this._key }
      })
    };

    MLab.prototype.listDocuments = function (options) {
      if ((typeof options.collection !== 'string') || (options.collection === undefined))
        throw new Error('collection is required');

      return this.axios.get(this.makePath(['collections', options.collection], { database: options.database }), {
        params: this.doParams(options)
      })
    };

    MLab.prototype.insertDocuments = function (options) {
      if ((typeof options.collection !== 'string') || (options.collection === undefined))
        throw new Error('collection is required');

      if (!Array.isArray(options.data) || (options.data === undefined))
        throw new Error('data is required');

      return this.axios.post(this.makePath(['collections', options.collection], { database: options.database }), options.data, {
        params: { apiKey: this._key }
      })
    };

    MLab.prototype.updateDocuments = function (options) {
      if ((typeof options.collection !== 'string') || (options.collection === undefined))
        throw new Error('collection is required');

      if (options.data === undefined)
        throw new Error('data is required');

      return this.axios.put(this.makePath(['collections', options.collection], { database: options.database }), { "$set": options.data }, {
        params: this.doParams(options)
      })
    };

    MLab.prototype.deleteDocuments = function (options) {
      if ((typeof options.collection !== 'string') || (options.collection === undefined))
        throw new Error('collection is required');

      return this.axios.put(this.makePath(['collections', options.collection], { database: options.database }), options.data || [], {
        params: this.doParams(options)
      })
    };

    MLab.prototype.viewDocument = function (options) {
      if ((typeof options.collection !== 'string') || (options.collection === undefined))
        throw new Error('collection is required');

      if (typeof options.id !== 'string' || options.id === null) throw new Error('document id is required');

      return this.axios.get(this.makePath(['collections', options.collection, options.id], { database: options.database }), {
        params: { apiKey: this._key }
      })
    };

    MLab.prototype.insertDocument = function (options) {
      if ((typeof options.collection !== 'string') || (options.collection === undefined))
        throw new Error('collection is required');

      if (options.data === null) throw new Error('document id is required');

      return this.axios.post(this.makePath(['collections', options.collection], { database: options.database }), options.data, {
        params: { apiKey: this._key }
      })
    };

    MLab.prototype.updateDocument = function (options) {
      if ((typeof options.collection !== 'string') || (options.collection === undefined))
        throw new Error('collection is required');

      if (typeof options.id !== 'string' || options.id === null) throw new Error('document id is required');

      if (options.data === null) throw new Error('document id is required');

      return this.axios.put(this.makePath(['collections', options.collection, options.id], { database: options.database }), options.data, {
        params: { apiKey: this._key }
      })
    };

    MLab.prototype.deleteDocument = function (options) {
      if ((typeof options.collection !== 'string') || (options.collection === undefined))
        throw new Error('collection is required');

      if (typeof options.id !== 'string' || options.id === null) throw new Error('document id is required');

      return this.axios.delete(this.makePath(['collections', options.collection, options.id], { database: options.database }), {
        params: { apiKey: this._key }
      })
    };

    MLab.prototype.runCommand = function (options) {
      if (options.commands === null) throw new Error('commands is required');

      return this.axios.post(this.makePath('runCommand', { database: options.database }), options.commands, {
        params: { apiKey: this._key }
      })

    };

    MLab.prototype.multiple = function (requests) {
      return axios.all(requests.map(function (request) {
        return this[request.func].apply(request.params)
      }))
    }

module.exports = MLab;<commit_msg>updateDocument fixed<commit_after>/* jshint asi:true */

var axios = require('axios');

var MLab = function (options) {
  if (!(this instanceof MLab)) {
    return new MLab(options);
  }
  this._key = options.key
  this._host = options.host || 'https://api.mlab.com'
  this._uri = options.uri || '/api'
  this._version = options.version || '1'
  this._database = options.database
  this._basePath = [this._host, this._uri, this._version].join('/')
  var ap = {
    baseURL: this._host,
    timeout: options.timeout || 10000,
    headers: { 'X-Requested-With': 'XMLHttpRequest' },
  }
  ap.onUploadProgress = options.onUploadProgress
  ap.onDownloadProgress = options.onDownloadProgress
  this.axios = axios.create(ap)
  this.listDatabases()
    .then(function (response) {
      if (response.message === 'Please provide a valid API key.') throw new Error('Invalid API key');
    })
    .catch(function (error) {
      throw new Error('No DB connection');
    })
}

MLab.prototype.setDatabase = function (database) {
  if ((typeof database !== 'string') || (database === undefined)) {
    throw new Error('database name is required');
  }
  this._database = database
}

MLab.prototype.makePath = function (uri, params) {
  realUri = Array.isArray(uri) ? uri.join('/') : uri;
  return [params && params.path ? params.path : this._basePath, 'databases', params && params.database ? params.database : this._database, realUri].join('/')
};

MLab.prototype.specialCharChanger = function (str) {
  return str.replace(/ /gi, '%20').replace(/"/gi, '%22');
};

MLab.prototype.meters2radians = function (meters) {
  return meters / 6378100
};

MLab.prototype.doParams = function (params) {
  var ap = { apiKey: this._key }
  if (params.query) ap.q = JSON.stringify(params.query)
  if (params.count) ap.c = true
  if (params.fields) ap.f = JSON.stringify(params.fields)
  if (params.findOne) ap.fo = true
  if (params.sort) ap.s = JSON.stringify(params.sort)
  if (params.skip) ap.sk = params.skip
  if (params.limit) ap.l = params.limit
  if (params.all) ap.m = true
  if (params.upsert) ap.u = true
  return ap
}

MLab.prototype.listDatabases = function () {
  return this.axios.get(this._basePath + '/databases', {
    params: { apiKey: this._key }
  })
};

MLab.prototype.listCollections = function (database) {
  return this.axios.get(this.makePath('collections', { database: database }), {
    params: { apiKey: this._key }
  })
};

MLab.prototype.listDocuments = function (options) {
  if ((typeof options.collection !== 'string') || (options.collection === undefined))
    throw new Error('collection is required');

  return this.axios.get(this.makePath(['collections', options.collection], { database: options.database }), {
    params: this.doParams(options)
  })
};

MLab.prototype.insertDocuments = function (options) {
  if ((typeof options.collection !== 'string') || (options.collection === undefined))
    throw new Error('collection is required');

  if (!Array.isArray(options.data) || (options.data === undefined))
    throw new Error('data is required');

  return this.axios.post(this.makePath(['collections', options.collection], { database: options.database }), options.data, {
    params: { apiKey: this._key }
  })
};

MLab.prototype.updateDocuments = function (options) {
  if ((typeof options.collection !== 'string') || (options.collection === undefined))
    throw new Error('collection is required');

  if (options.data === undefined)
    throw new Error('data is required');

  return this.axios.put(this.makePath(['collections', options.collection], { database: options.database }), { "$set": options.data }, {
    params: this.doParams(options)
  })
};

MLab.prototype.deleteDocuments = function (options) {
  if ((typeof options.collection !== 'string') || (options.collection === undefined))
    throw new Error('collection is required');

  return this.axios.put(this.makePath(['collections', options.collection], { database: options.database }), options.data || [], {
    params: this.doParams(options)
  })
};

MLab.prototype.viewDocument = function (options) {
  if ((typeof options.collection !== 'string') || (options.collection === undefined))
    throw new Error('collection is required');

  if (typeof options.id !== 'string' || options.id === null) throw new Error('document id is required');

  return this.axios.get(this.makePath(['collections', options.collection, options.id], { database: options.database }), {
    params: { apiKey: this._key }
  })
};

MLab.prototype.insertDocument = function (options) {
  if ((typeof options.collection !== 'string') || (options.collection === undefined))
    throw new Error('collection is required');

  if (options.data === null) throw new Error('document id is required');

  return this.axios.post(this.makePath(['collections', options.collection], { database: options.database }), options.data, {
    params: { apiKey: this._key }
  })
};

MLab.prototype.updateDocument = function (options) {
  if ((typeof options.collection !== 'string') || (options.collection === undefined))
    throw new Error('collection is required');

  if (typeof options.id !== 'string' || options.id === null) throw new Error('document id is required');
  if (options.data === null) throw new Error('document data is required');
  return this.axios.put(this.makePath(['collections', options.collection, options.id], { database: options.database }), options.updateObject, {
    params: { apiKey: this._key }
  })
};

MLab.prototype.deleteDocument = function (options) {
  if ((typeof options.collection !== 'string') || (options.collection === undefined))
    throw new Error('collection is required');

  if (typeof options.id !== 'string' || options.id === null) throw new Error('document id is required');

  return this.axios.delete(this.makePath(['collections', options.collection, options.id], { database: options.database }), {
    params: { apiKey: this._key }
  })
};

MLab.prototype.runCommand = function (options) {
  if (options.commands === null) throw new Error('commands is required');

  return this.axios.post(this.makePath('runCommand', { database: options.database }), options.commands, {
    params: { apiKey: this._key }
  })

};

MLab.prototype.multiple = function (requests) {
  return axios.all(requests.map(function (request) {
    return this[request.func].apply(request.params)
  }))
}

module.exports = MLab;<|endoftext|>


<commit_before>import { ElementObserver, ObserverCollection } from 'viewprt';

const debounceCollection = [];
const defaultScrollResizeHandler = (handler) => handler;

export default (element, options = {}) => {
	const {
		threshold = 0,
		scrollResizeHandler = defaultScrollResizeHandler,
		onEnter = () => {},
		onExit = () => {},
		once = false
	} = options;

	let resolvedHandler = debounceCollection.find(
		({ handleScrollResize }) => scrollResizeHandler === handleScrollResize
	);

	if (typeof resolvedHandler === 'undefined') {
		resolvedHandler = new ObserverCollection({
			handleScrollResize: scrollResizeHandler
		});
		debounceCollection.push(resolvedHandler);
	}

	const elementObserver = new ElementObserver(element, {
		onEnter(element_) {
			onEnter(element_);
		},
		onExit(element_) {
			onExit(element_);
		},
		offset: threshold,
		once: once,
		observerCollection: resolvedHandler
	});

	return {
		destroy: elementObserver.destroy.bind(elementObserver)
	};
};
<commit_msg>Properly handle ES module<commit_after>import viewprt from 'viewprt';

const { ElementObserver, ObserverCollection } = viewprt;

const debounceCollection = [];
const defaultScrollResizeHandler = (handler) => handler;

export default (element, options = {}) => {
	const {
		threshold = 0,
		scrollResizeHandler = defaultScrollResizeHandler,
		onEnter = () => {},
		onExit = () => {},
		once = false
	} = options;

	let resolvedHandler = debounceCollection.find(
		({ handleScrollResize }) => scrollResizeHandler === handleScrollResize
	);

	if (typeof resolvedHandler === 'undefined') {
		resolvedHandler = new ObserverCollection({
			handleScrollResize: scrollResizeHandler
		});
		debounceCollection.push(resolvedHandler);
	}

	const elementObserver = new ElementObserver(element, {
		onEnter(element_) {
			onEnter(element_);
		},
		onExit(element_) {
			onExit(element_);
		},
		offset: threshold,
		once: once,
		observerCollection: resolvedHandler
	});

	return {
		destroy: elementObserver.destroy.bind(elementObserver)
	};
};
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var path = require('path');

module.exports = {
  name: 'ember-highcharts',

  setupPreprocessorRegistry: function(type, registry) {
    var options = getOptions(this.parent && this.parent.options && this.parent.options['babel']);

    var plugin = {
      name   : 'ember-cli-babel',
      ext    : 'js',
      toTree : function(tree) {
        return require('broccoli-babel-transpiler')(tree, options);
      }
    };

    registry.add('js', plugin);
  },

  treeForVendor: function() {
    return this.treeGenerator(path.join(__dirname, 'bower_components'));
  },

  included: function(app) {
    this._super.included(app);

    var options = app.options.emberHighCharts || {includeHighCharts: true};

    if (options.includeHighCharts) {
      app.import('vendor/highcharts-release/highcharts.src.js');
    }

    if (options.includeHighStock) {
      app.import('vendor/highstock-release/highstock.src.js');
    }

    if (options.includeHighMaps) {
      app.import('vendor/highmaps-release/highmaps.src.js');
    }
  }
};

function getOptions(options) {
  options = options || {};

  // Ensure modules aren't compiled unless explicitly set to compile
  options.blacklist = options.blacklist || ['es6.modules'];

  if (options.compileModules === true) {
    if (options.blacklist.indexOf('es6.modules') >= 0) {
      options.blacklist.splice(options.blacklist.indexOf('es6.modules'), 1);
    }

    delete options.compileModules;
  } else {
    if (options.blacklist.indexOf('es6.modules') < 0) {
      options.blacklist.push('es6.modules');
    }
  }

  // Ember-CLI inserts its own 'use strict' directive
  options.blacklist.push('useStrict');

  return options;
}
<commit_msg>do not include addon's bower_components<commit_after>/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-highcharts',

  setupPreprocessorRegistry: function(type, registry) {
    var options = getOptions(this.parent && this.parent.options && this.parent.options['babel']);

    var plugin = {
      name   : 'ember-cli-babel',
      ext    : 'js',
      toTree : function(tree) {
        return require('broccoli-babel-transpiler')(tree, options);
      }
    };

    registry.add('js', plugin);
  },

  included: function(app) {
    this._super.included(app);

    var options = app.options.emberHighCharts || {includeHighCharts: true};

    if (options.includeHighCharts) {
      app.import('vendor/highcharts-release/highcharts.src.js');
    }

    if (options.includeHighStock) {
      app.import('vendor/highstock-release/highstock.src.js');
    }

    if (options.includeHighMaps) {
      app.import('vendor/highmaps-release/highmaps.src.js');
    }
  }
};

function getOptions(options) {
  options = options || {};

  // Ensure modules aren't compiled unless explicitly set to compile
  options.blacklist = options.blacklist || ['es6.modules'];

  if (options.compileModules === true) {
    if (options.blacklist.indexOf('es6.modules') >= 0) {
      options.blacklist.splice(options.blacklist.indexOf('es6.modules'), 1);
    }

    delete options.compileModules;
  } else {
    if (options.blacklist.indexOf('es6.modules') < 0) {
      options.blacklist.push('es6.modules');
    }
  }

  // Ember-CLI inserts its own 'use strict' directive
  options.blacklist.push('useStrict');

  return options;
}
<|endoftext|>


<commit_before>var fs = require('fs');
var _ = require('lodash');
module.exports = function(poptions) {
    var module = {};
    var that = this;
    that.options = {};
    that.songs = [];
    // that.forced = [];
    that.forced_index = -1;
    that.forced_count = 0;
    that.pl_index = -1;
    that.pl = [];
    /**
     * Sets the necessary options for this module
     * @param {object} options {folder:'path_to_folder', 'shuffle':bool, song_types:['mp4', 'mp3', 'etc']}
     */
    function setOptions(options) {
        if (typeof options === 'object') {
            that.options.song_src = options.song_src || '';
            that.options.shuffle = options.shuffle || false;
            that.options.song_types = options.song_types || ['mp3', 'mp4', 'ogg', 'oggv'];
            that.options.forced = options.forced || {
                force: false
            };
            setSongs(that.options.song_src);
        }
    }
    /**
     * Sets the folder to be used, and gets the songs according to
     * options.song_types
     * @param {string || array} string: pfolder_path the path of the folder to be used || array: array of file_paths
     */

    /**
     * Sets the songs to be used and gets the songs according to options.song_types
     * @param {string || array} song_src string: pfolder_path the path of the folder to be used || array: array of file_paths
     */
    function setSongs(song_src) {
        that.options.song_src = song_src;
        var files;
        if (Array.isArray(that.options.song_src)) {
            files = song_src;
        } else if (existsSync(that.options.song_src)) {
            files = fs.readdirSync(that.options.song_src);
            files = _.map(files, function(f) {
                return song_src + '/' + f;
            });
        } else {
            throw new Error('Song source should be an array or a valid folder path');
        }
        that.songs = [];
        that.songsForced = [];
        for (var i = 0; i < files.length; i++) {
            console.log(files[i], i);
            if (that.options.song_types.indexOf(files[i].src.split('.').pop()) > -1) {
                var songToAdd = {
                    'path': files[i].src,
                    'attr': files[i].attr,
                    'last_played': '',
                    'played': false
                };
                if (that.options.forced.force && files[i].src.match(that.options.forced.expression)) {
                    that.songsForced.push(songToAdd);
                } else {
                    that.songs.push();
                }
            }
        }
        that.options.shuffle ? shuffleOn() : shuffleOff();
    }
    /**
     * Turns shuffle on and returns the options.shuffle status;
     * @return {bool} options.shuffle value
     */
    function shuffleOn() {
        that.pl = _.shuffle(that.songs);
        that.options.shuffle = true;
        return that.options.shuffle;
    }
    /**
     * Turns shuffle off and returns the options.shuffle status;
     * @return {bool} options.shuffle value
     */
    function shuffleOff() {
        that.pl = that.songs;
        that.options.shuffle = false;
    }

    function getNextForced() {
        if (that.pl_index % that.options.forced.every === 0 &&
            that.forced_count < that.options.forced.count) {
            that.forced_index = that.forced_index >= that.songsForced.index + 1 ? 0 : that.forced_index + 1;
            that.forced_count++;
            return {
                'use': true,
                'song': {
                    path: that.songsForced[that.forced_index],
                    last_played: new Date(),
                    played: true
                }
            };
        } else {
            that.forced_count = 0;
            return {
                'use': false
            };
        }
    }
    /**
     * Gets the next song to play according to the options
     * @return {object} {'path':'song_path',last_played:'date', played:'bool'}
     */
    function getNextSong() {
        var selected_song;
        var nextForced = getNextForced();
        if (nextForced.use)
            return nextForced.song;
        if (that.pl.length < 1)
            return {};
        if (that.pl_index + 1 >= that.pl.length) {
            that.pl_index = 0;
            that.songs = _.map(that.songs, function setPlayedFalse(s) {
                s.played = false;
                return s;
            });
            if (that.options.shuffle)
                shuffleOn();
        } else {
            that.pl_index++;
        }
        selected_song = that.pl[that.pl_index];
        if (selected_song.played) {
            getNextSong();
        } else {
            that.pl[that.pl_index].last_played = new Date();
            that.pl[that.pl_index].played = true;
            _.chain(that.songs)
                .find({
                    path: selected_song.path
                })
                .merge({
                    last_played: that.pl[that.pl_index].last_played,
                    played: true
                });
            return selected_song;
        }
    }
    /**
     * Returns the array of songs ordered as read
     * @return {array} Songs
     */
    function getSongs() {
        return that.songs;
    }
    /**
     * Returns the playlist being used
     * @return {object} {playlist[array], index[integer]}
     */
    function getPlayList() {
        return {
            playlist: that.pl,
            index: that.pl_index
        };
    }
    setOptions(poptions);

    module.setOptions = setOptions;
    module.shuffleOn = shuffleOn;
    module.shuffleOff = shuffleOff;
    module.getNextSong = getNextSong;
    module.getSongs = getSongs;
    module.getPlayList = getPlayList;

    return module;
};
/**
 * Determines if a folder exists synchronously
 * @param  {string} directory
 * @return {bool}           if folder exists
 */
function existsSync(directory) {
    try {
        fs.statSync(directory);
        return true;
    } catch (e) {
        return false;
    }
}
<commit_msg>Adding forced property<commit_after>var fs = require('fs');
var _ = require('lodash');
module.exports = function(poptions) {
    var module = {};
    var that = this;
    that.options = {};
    that.songs = [];
    // that.forced = [];
    that.forced_index = -1;
    that.forced_count = 0;
    that.pl_index = -1;
    that.pl = [];
    /**
     * Sets the necessary options for this module
     * @param {object} options {folder:'path_to_folder', 'shuffle':bool, song_types:['mp4', 'mp3', 'etc']}
     */
    function setOptions(options) {
        if (typeof options === 'object') {
            that.options.song_src = options.song_src || '';
            that.options.shuffle = options.shuffle || false;
            that.options.song_types = options.song_types || ['mp3', 'mp4', 'ogg', 'oggv'];
            that.options.forced = options.forced || {
                force: false
            };
            setSongs(that.options.song_src);
        }
    }
    /**
     * Sets the folder to be used, and gets the songs according to
     * options.song_types
     * @param {string || array} string: pfolder_path the path of the folder to be used || array: array of file_paths
     */

    /**
     * Sets the songs to be used and gets the songs according to options.song_types
     * @param {string || array} song_src string: pfolder_path the path of the folder to be used || array: array of file_paths
     */
    function setSongs(song_src) {
        that.options.song_src = song_src;
        var files;
        if (Array.isArray(that.options.song_src)) {
            files = song_src;
        } else if (existsSync(that.options.song_src)) {
            files = fs.readdirSync(that.options.song_src);
            files = _.map(files, function(f) {
                return song_src + '/' + f;
            });
        } else {
            throw new Error('Song source should be an array or a valid folder path');
        }
        that.songs = [];
        that.songsForced = [];
        for (var i = 0; i < files.length; i++) {
            if (that.options.song_types.indexOf(files[i].split('.').pop()) > -1) {
                var songToAdd = {
                    'path': files[i],
                    'last_played': '',
                    'played': false
                };
                if (that.options.forced.force && files[i].match(that.options.forced.expression)) {
                    that.songsForced.push(songToAdd);
                } else {
                    that.songs.push(songToAdd);
                }
            }
        }
        that.options.shuffle ? shuffleOn() : shuffleOff();
    }
    /**
     * Turns shuffle on and returns the options.shuffle status;
     * @return {bool} options.shuffle value
     */
    function shuffleOn() {
        that.pl = _.shuffle(that.songs);
        that.options.shuffle = true;
        return that.options.shuffle;
    }
    /**
     * Turns shuffle off and returns the options.shuffle status;
     * @return {bool} options.shuffle value
     */
    function shuffleOff() {
        that.pl = that.songs;
        that.options.shuffle = false;
    }

    function getNextForced() {
        if (that.pl_index % that.options.forced.every === 0 &&
            that.forced_count < that.options.forced.count) {
            that.forced_index = that.forced_index + 1 >= that.songsForced.length ? 0 : that.forced_index + 1;
            that.forced_count++;
            return {
                'use': true,
                'song': that.songsForced[that.forced_index]
            };
        } else {
            that.forced_count = 0;
            return {
                'use': false
            };
        }
    }
    /**
     * Gets the next song to play according to the options
     * @return {object} {'path':'song_path',last_played:'date', played:'bool'}
     */
    function getNextSong() {
        var selected_song;
        var nextForced = getNextForced();
        if (nextForced.use)
            return nextForced.song;
        if (that.pl.length < 1)
            return {};
        if (that.pl_index + 1 >= that.pl.length) {
            that.pl_index = 0;
            that.songs = _.map(that.songs, function setPlayedFalse(s) {
                s.played = false;
                return s;
            });
            if (that.options.shuffle)
                shuffleOn();
        } else {
            that.pl_index++;
        }
        selected_song = that.pl[that.pl_index];
        if (selected_song.played) {
            getNextSong();
        } else {
            that.pl[that.pl_index].last_played = new Date();
            that.pl[that.pl_index].played = true;
            _.chain(that.songs)
                .find({
                    path: selected_song.path
                })
                .merge({
                    last_played: that.pl[that.pl_index].last_played,
                    played: true
                });
            return selected_song;
        }
    }
    /**
     * Returns the array of songs ordered as read
     * @return {array} Songs
     */
    function getSongs() {
        return that.songs;
    }
    /**
     * Returns the playlist being used
     * @return {object} {playlist[array], index[integer]}
     */
    function getPlayList() {
        return {
            playlist: that.pl,
            index: that.pl_index
        };
    }
    setOptions(poptions);

    module.setOptions = setOptions;
    module.shuffleOn = shuffleOn;
    module.shuffleOff = shuffleOff;
    module.getNextSong = getNextSong;
    module.getSongs = getSongs;
    module.getPlayList = getPlayList;

    return module;
};
/**
 * Determines if a folder exists synchronously
 * @param  {string} directory
 * @return {bool}           if folder exists
 */
function existsSync(directory) {
    try {
        fs.statSync(directory);
        return true;
    } catch (e) {
        return false;
    }
}
<|endoftext|>


<commit_before>var fs = require('fs'),
    events = require('events'),
    path = require('path'),
    analysis = require('./lib/analysis.js'),
    Watcher = require('watch-fs').Watcher,
    util = require('util')

exports.Freud = Freud
exports.createFreud = createFreud

function Freud(source, target, options) {
  if (!(this instanceof Freud)) return new Freud(source, target, options)

  this.source = path.normalize(source)
  this.target = path.normalize(target)
  this.processed = []
  this.rules = []
  this.options = options || {}
  this.listener = null
  this.version = require(path.join(__dirname, 'package.json')).version

  return this
}

util.inherits(Freud, events.EventEmitter)

Freud.prototype.doUnlink = function (filename, stats) {
  filename = path.basename(filename)
  var dummyFile = {
    name: filename,
    fullPath: path.join(this.source + filename),
    extension: filename.split('.').pop(),
    write: true,
    stats: undefined,
    data: ''
  }
  this.processFile(dummyFile, parseFile.bind(this))

  function parseFile(file) {
    analysis.unlink(this.target, file.name, checkUnlink.bind(this))

    function checkUnlink(err, didUnlink) {
      if (!err && didUnlink) return this.emit('unlinked', file.name)
      this.emit('error', new Error('file unlink error'))
    }
  }
}

Freud.prototype.recompile = function (filename) {
  var extension = filename.split('.').pop();
  if (this.rules[extension] || this.rules['*:before'] || this.rules['*:after']) {
    return this.compileFile(filename, recompileFile.bind(this))
  }
  this.copyFile(filename)

  function recompileFile(filename, written) {
    this.emit('recompiled', filename);
    if (!written) this.emit('blocked', filename)
  }
}

Freud.prototype.listen = function (extension, callback) {
  if (!Array.isArray(extension)) extension = [extension]
  this.attachListeners(extension, callback)
}

Freud.prototype.attachListeners = function (extensions, callback) {

  extensions.forEach(doAttach.bind(this))

  function doAttach(extension) {
    extension = extension === '*' ? '*:before' : extension
    extension = extension === '/*' ? '/*:before' : extension
    extension = this.options.ignoreCase ? extension.toLowerCase() : extension

    this.rules[extension] = this.rules[extension] || []
    this.rules[extension].push(callback)
    this.emit('extensionAdded', extension)
  }
}

Freud.prototype.go = function (cb) {
  var noRecurseRegexp = new RegExp(this.source + '/?$')
  this.listener = new Watcher({
    paths: this.source,
    filters: {
      includeDir: function (dirName) {
        return noRecurseRegexp.test(dirName)
      },
      includeFile: function (fileName) {
        if (!this.options.monitorDot && /^\./.test(fileName)) return false
        if (!this.options.monitorSquiggle && /~$/.test(fileName)) return false
        return true
      }.bind(this)
    }
  })

  this.listener.on('delete', this.doUnlink.bind(this))
  this.listener.on('create', this.eventResponse.bind(this))
  this.listener.on('change', this.eventResponse.bind(this))

  this.listener.start(listenerStarted.bind(this))

  function listenerStarted(err) {
    if (err) return cb && cb(err)
    this.emit('started', this)
    cb && cb()
  }
}

Freud.prototype.copyFile = function (filename) {
  this.emit('copying')
  var endFileStream = fs.createWriteStream(path.join(this.target, filename))

  endFileStream.on('finish', function () {
    this.emit('copied', filename)
  }.bind(this))

  fs.createReadStream(path.join(this.source, filename)).pipe(endFileStream)
}

Freud.prototype.eventResponse = function (filename, stats) {
  filename = path.basename(filename)

  var extension = filename.split('.').pop()
  extension = this.options.ignoreCase ? extension.toLowerCase() : extension
  if (this.rules[extension] || this.rules['*:before'] || this.rules['*:after']) {
    return this.compileFile(filename, fileCompiled.bind(this))
  }

  this.copyFile(filename)

  function fileCompiled(filename, written) {
    this.emit('compiled', filename)
    if (!written) this.emit('blocked', filename)
  }
}

Freud.prototype.processFile = function (file, callback) {
  var rules = [].concat(
      (this.rules['*:before'] || [])
      .concat(
      (this.rules[this.options.ignoreCase ? file.extension.toLowerCase() : file.extension] || [])
      .concat(
      (this.rules['*:after'] || []))
    ))
  if (!rules.length) return callback(file)
  analysis.executeRules(rules, file, callback)
}

Freud.prototype.compileFile = function (filename, callback) {
  this.emit('compiling', filename)
  analysis.getFile(this.source, filename, function (file) {
    this.processFile(file, putFile.bind(this))
  }.bind(this))

  function putFile(file) {
    if (!file.write) return callback(file.name, false)

    analysis.putFile(this.target, file, function () {
      callback(file.name, true)
    }.bind(this))
  }
}

Freud.prototype.stop = function (cb) {
  this.listener && this.listener.stop()
  this.emit('stopped')

  cb && cb()
}

function createFreud(source, destination, options) {
  return new Freud(source, destination, options)
}
<commit_msg>until theres a watcher that pushes stats<commit_after>var fs = require('fs'),
    events = require('events'),
    path = require('path'),
    analysis = require('./lib/analysis.js'),
    Watcher = require('watch-fs').Watcher,
    util = require('util')

exports.Freud = Freud
exports.createFreud = createFreud

function Freud(source, target, options) {
  if (!(this instanceof Freud)) return new Freud(source, target, options)

  this.source = path.normalize(source)
  this.target = path.normalize(target)
  this.processed = []
  this.rules = []
  this.options = options || {}
  this.listener = null
  this.version = require(path.join(__dirname, 'package.json')).version

  return this
}

util.inherits(Freud, events.EventEmitter)

Freud.prototype.doUnlink = function (filename) {
  filename = path.basename(filename)
  var dummyFile = {
    name: filename,
    fullPath: path.join(this.source + filename),
    extension: filename.split('.').pop(),
    write: true,
    stats: undefined,
    data: ''
  }
  this.processFile(dummyFile, parseFile.bind(this))

  function parseFile(file) {
    analysis.unlink(this.target, file.name, checkUnlink.bind(this))

    function checkUnlink(err, didUnlink) {
      if (!err && didUnlink) return this.emit('unlinked', file.name)
      this.emit('error', new Error('file unlink error'))
    }
  }
}

Freud.prototype.recompile = function (filename) {
  var extension = filename.split('.').pop();
  if (this.rules[extension] || this.rules['*:before'] || this.rules['*:after']) {
    return this.compileFile(filename, recompileFile.bind(this))
  }
  this.copyFile(filename)

  function recompileFile(filename, written) {
    this.emit('recompiled', filename);
    if (!written) this.emit('blocked', filename)
  }
}

Freud.prototype.listen = function (extension, callback) {
  if (!Array.isArray(extension)) extension = [extension]
  this.attachListeners(extension, callback)
}

Freud.prototype.attachListeners = function (extensions, callback) {

  extensions.forEach(doAttach.bind(this))

  function doAttach(extension) {
    extension = extension === '*' ? '*:before' : extension
    extension = extension === '/*' ? '/*:before' : extension
    extension = this.options.ignoreCase ? extension.toLowerCase() : extension

    this.rules[extension] = this.rules[extension] || []
    this.rules[extension].push(callback)
    this.emit('extensionAdded', extension)
  }
}

Freud.prototype.go = function (cb) {
  var noRecurseRegexp = new RegExp(this.source + '/?$')
  this.listener = new Watcher({
    paths: this.source,
    filters: {
      includeDir: function (dirName) {
        return noRecurseRegexp.test(dirName)
      },
      includeFile: function (fileName) {
        if (!this.options.monitorDot && /^\./.test(fileName)) return false
        if (!this.options.monitorSquiggle && /~$/.test(fileName)) return false
        return true
      }.bind(this)
    }
  })

  this.listener.on('delete', this.doUnlink.bind(this))
  this.listener.on('create', this.eventResponseWrap.bind(this))
  this.listener.on('change', this.eventResponseWrap.bind(this))

  this.listener.start(listenerStarted.bind(this))

  function listenerStarted(err) {
    if (err) return cb && cb(err)
    this.emit('started', this)
    cb && cb()
  }
}

Freud.prototype.copyFile = function (filename) {
  this.emit('copying')
  var endFileStream = fs.createWriteStream(path.join(this.target, filename))

  endFileStream.on('finish', function () {
    this.emit('copied', filename)
  }.bind(this))

  fs.createReadStream(path.join(this.source, filename)).pipe(endFileStream)
}

Freud.prototype.eventResponseWrap = function (filename) {
  fs.stat(filename, function (err, stats) {
    this.eventResponse(filename, stats)
  }.bind(this))
}

Freud.prototype.eventResponse = function (filename, stats) {
  filename = path.basename(filename)

  var extension = filename.split('.').pop()
  extension = this.options.ignoreCase ? extension.toLowerCase() : extension
  if (this.rules[extension] || this.rules['*:before'] || this.rules['*:after']) {
    return this.compileFile(filename, fileCompiled.bind(this))
  }

  this.copyFile(filename)

  function fileCompiled(filename, written) {
    this.emit('compiled', filename)
    if (!written) this.emit('blocked', filename)
  }
}

Freud.prototype.processFile = function (file, callback) {
  var rules = [].concat(
      (this.rules['*:before'] || [])
      .concat(
      (this.rules[this.options.ignoreCase ? file.extension.toLowerCase() : file.extension] || [])
      .concat(
      (this.rules['*:after'] || []))
    ))
  if (!rules.length) return callback(file)
  analysis.executeRules(rules, file, callback)
}

Freud.prototype.compileFile = function (filename, callback) {
  this.emit('compiling', filename)
  analysis.getFile(this.source, filename, function (file) {
    this.processFile(file, putFile.bind(this))
  }.bind(this))

  function putFile(file) {
    if (!file.write) return callback(file.name, false)

    analysis.putFile(this.target, file, function () {
      callback(file.name, true)
    }.bind(this))
  }
}

Freud.prototype.stop = function (cb) {
  this.listener && this.listener.stop()
  this.emit('stopped')

  cb && cb()
}

function createFreud(source, destination, options) {
  return new Freud(source, destination, options)
}
<|endoftext|>


<commit_before>/**
 * Babel plugin to transform React className property values to CSS Module style
 * lookups
 */
export default function ({Plugin, parse, types: t}) {
  const optionsKey = 'react-cssmoduleify';
  let cssModuleId;

  function warn(...args) {
    console.warn(...args);
    console.warn(
      'Please report this at https://github.com/walmartreact/' +
      'babel-plugin-react-cssmoduleify/issues'
    );
  }

  function isValidOptions(options) {
    return typeof options === 'object' && options.path && options.cssmodule;
  }

  /**
   * Enforces plugin options to be defined and returns them.
   */
  function getPluginOptions(file) {
    if (!file.opts || !file.opts.extra) {
      return;
    }

    var pluginOptions = file.opts.extra[optionsKey];

    if (!isValidOptions(pluginOptions)) {
      throw new Error(
        'babel-plugin-react-css-modules requires that you specify extras["' +
        optionsKey + '"] in .babelrc ' + 'or in your Babel Node API call ' +
        'options with "path" and "cssmodule" keys.'
      );
    }
    return pluginOptions;
  }

  /**
  * Transform an AST Node representing a literal string property to an
  * appropriate CSS module-style memberExpression
  *
  * { className: 'hello'} => className: _styles['hello'] }
  * { className: 'hello world'} => className: _styles['hello'] + ' ' + _styles['world'] }
  */
  const mutateStringPropertyToCSSModule = (prop) => {
    const parts = prop.value.value.split(' ').map(v => {
      return t.memberExpression(
        cssModuleId,
        t.literal(v),
        true
      )
    });

    if (parts.length === 1) {
      prop.value = parts[0];
    } else {
      prop.value = parts.reduce((ast, cur, i) => {
        if (!ast) return cur;

        return t.binaryExpression(
          '+',
          t.binaryExpression('+', ast, t.literal(' ')),
          cur
        )
      })
    }
  };

  const isClassnames = (node, scope) => {
    const reClassnames = /classnames/i;

    if (node.type !== 'CallExpression') {
      return false;
    }

    const identifierName = (
      node.callee.type === 'Identifier' ? node.callee.name
      : node.callee.object ? node.callee.object.name
      : node.callee.type === 'SequenceExpression' ? node.callee.expressions[1].object.name
      : 'TODO'
    );

    if (!identifierName || identifierName === 'TODO') {
      return false;
    }

    const definition = scope.getBinding(identifierName);
    // follow the variable declaration to a require
    if (definition.path.node.type === 'VariableDeclarator') {
      const {init} = definition.path.node;
      if (init.type !== 'CallExpression') {
        return false;
      }
      if (/require|_interopRequireDefault/.test(init.callee.name)) {
        return reClassnames.test(init.arguments[0].name);
      }
    }

    // TODO: track `import` statements
    return false;
  };

  const convertStringKeysToComputedProperties = (node) => {
    node.properties.forEach(p => {
      // ensure we're idempotent
      if (
        p.key.type === 'MemberExpression' &&
        p.object === cssModuleId ||
        !p.key.value
      ) {
        return;
      }
      p.key = t.memberExpression(
        cssModuleId,
        t.literal(p.key.value),
        true
      );
      p.computed = true;
    });
    return node;
  };

  const mutateClassnamesCall = (node, scope) => {
    node.arguments = node.arguments.map(v => {
      if (v.type === 'Identifier') {
        let bindings;
        while (!(bindings = scope.bindings[v.name]) && scope.parent) {
          scope = scope.parent;
        }

        if (!bindings) {
          return t.memberExpression(
            cssModuleId,
            t.literal(v.name),
            true
          );
        }
        v = bindings.path.node;
        if (v.type === 'VariableDeclarator') {
          v = v.init;
        }
      }

      if (v.type === 'CallExpression') return v;

      if (
        v.type === 'Literal' ||
        v.type === 'BinaryExpression' ||
        v.type === 'ConditionalExpression'
      ) {
        return t.memberExpression(cssModuleId, v, true);
      }

      if (v.type === 'ObjectExpression') {
        return convertStringKeysToComputedProperties(v);
      }

      if (v.type === 'MemberExpression') {
        return v;
      }

      warn('WARNING(TODO): handle mutating classnames call for %s.', v.type);
      return v;
    });
  };

  const computedOrIdentifier = (node) =>
    t.logicalExpression(
      '||',
      t.memberExpression(cssModuleId, node, true),
      node
    );

  const _handleBinaryExpression = (node) => {
    if (node.value === '') return node;

    if (
      node.type === 'MemberExpression'
    ) {
      if (
        node.object.name === 'props' || (
          node.object.property &&
          node.object.property.name === 'props'
        )
      ) {
        return node;
      }

      return t.memberExpression(
        cssModuleId,
        node,
        true
      );
    }

    if (node.type === 'ConditionalExpression') {
      node.consequent = _handleBinaryExpression(node.consequent);
      node.alternate = _handleBinaryExpression(node.alternate);
      return node;
    }

    const parts = node.value.split(' ');
    if (parts.length === 1) {
      return t.memberExpression(
        cssModuleId,
        t.literal(parts[0]),
        true
      );
    }

    return parts.reduce((ast, n) => {
      if (n === '') {
        return ast;
      }

      if (!ast) {
        return typeof n === 'object' ? n
          : t.binaryExpression('+',
              t.memberExpression(
                cssModuleId,
                t.literal(n),
                true
              ),
              t.literal(' ')
            );
      }

      return t.binaryExpression(
        '+',
        t.binaryExpression('+', ast, t.literal(' ')),
        t.binaryExpression('+', t.literal(n), t.literal(' '))
      )
    }, null);
  }

  const handleBinaryExpressionProp = (prop, node, scope, file) => {
    if (prop.value.left.type === 'Literal' || prop.value.right.type === 'Literal') {
      const left = _handleBinaryExpression(prop.value.left);
      const right = _handleBinaryExpression(prop.value.right);
      prop.value.left = left;
      prop.value.right = right;
    }
    else {
      warn('Unhandled BinaryExpression property at %s#%s.', file.opts.filename, prop.loc.start.row);
    }

    return prop;

    if (prop.value.right.type !== 'Literal') {
      prop.value.right = t.memberExpression(
        cssModuleId,
        prop.value.right,
        true
      );
    }
    else {
      prop.value.right = handleProp({key: {name: 'className'}, value: prop.value.right}, node, scope, file).value;
    }
  }

  const handleProp = (prop, node, scope, file) => {
    // pick up className, activeClassName, hoverClassName, etc
    if (!/classname/i.test(prop.key.name)) return prop;

    if (prop.value.type === 'Identifier') {
      const binding = scope.bindings[prop.value.name];

      if (!binding) {
        prop.value = computedOrIdentifier(prop.value);
        return prop;
      }

      const {path} = binding;
      if (path.node.init.value) {
        mutateStringPropertyToCSSModule(prop);
      }
      else if (isClassnames(path.node.init, scope)) {
        mutateClassnamesCall(path.node.init, scope);
      }

      return prop;
    }

    if (prop.value.value) {
      mutateStringPropertyToCSSModule(prop);
    }
    else if (isClassnames(prop.value, scope)) {
      mutateClassnamesCall(prop.value, scope);
    }
    else if (prop.value.type === 'BinaryExpression') {
      return handleBinaryExpressionProp(prop, node, scope, file);
    }
    else if (prop.value.type === 'ConditionalExpression') {
      prop.value.consequent = handleProp(
        {key: {name: 'className'},
         value: prop.value.consequent
        }, node, scope, file).value;

      prop.value.alternate = handleProp(
        {key: {name: 'className'},
         value: prop.value.alternate
        }, node, scope, file).value;

      return prop;
    } else if (prop.value.type === 'CallExpression') {
      // simplistic `myIdentifier.join(' ')` detection
      // transforms to `myIdentifier.map(a => _cssmodules[a]).join(' ')`
      if (
        // TODO: could lookup the callee.object value and follow the Identifier
        // or ensure it is an ArrayExpresion
        prop.value.callee.property.name === 'join' &&
        prop.value.arguments[0].value === ' '
      ) {
        prop.value = t.callExpression(
          t.memberExpression(
            t.callExpression(
              t.memberExpression(
                prop.value.callee.object,
                t.identifier('map')
              ),
              [t.arrowFunctionExpression(
                [t.identifier('a')],
                t.memberExpression(cssModuleId, t.identifier('a'), true)
              )]
            ),
            prop.value.callee.property
          ),
          prop.value.arguments
        );
      }
      return prop;
    } else {
      if (
        prop.value.type === 'MemberExpression' ||
        prop.value.type === 'CallExpression' ||
        prop.value.type === 'Literal' && prop.value.value === ''
      ) {
        return prop;
      }

      warn(
        '\n\n' +
        '==================================================\n' +
        'WARNING: unhandled className in %s#%s.\n',
        file.opts.filename,
        node.loc.start.line
      );
    }

    return prop;
  };

  return new Plugin('css-moduleify-plugin', {
    visitor: {
      CallExpression(node, parent, scope, file) {
        if (!this.state.shouldTransform) return;

        if (
          !node.callee.property || (
            node.callee.property.name !== 'createElement' ||
            node.callee.object.name === 'document'
          )
        ) return;

        const {properties} = node.arguments[1];
        if (properties) {
          node.arguments[1].properties = properties.map(prop => handleProp(prop, node, scope, file));
          return;
        } else {
          // an ObjectSpreadProperty was used in the source
          if (
            node.arguments[1].type === 'CallExpression' &&
            node.arguments[1].callee.name.indexOf('extends') !== -1
          ) {
            node.arguments[1].arguments = node.arguments[1].arguments.map(prop => {
              if (prop.type === 'ObjectExpression') {
                prop.properties = prop.properties.map(prop => handleProp(prop, node, scope, file));
              }

              return prop;
            });
          }
        }
      },

      Program: {
        enter (node, parent, scope, file) {
          const opts = getPluginOptions(file);

          if (new RegExp(opts.path).test(file.opts.filename)) {
            // console.log('Program file', file.opts.filename);
            this.state.shouldTransform = true;
            cssModuleId = scope.generateUidIdentifier('cssmodule');
          }
        },

        exit(node, parent, scope, file) {
          if (this.state.shouldTransform !== true) return;

          const {cssmodule} = getPluginOptions(file);

          const cssRequire = t.variableDeclaration('var', [
            t.variableDeclarator(
              cssModuleId,
              t.callExpression(
                t.identifier('require'),
                [t.literal(process.cwd() + '/' + cssmodule)]
              )
            )
          ]);
          let insertIndex;
          node.body.find((n, i) => {
            const result = n.type === 'VariableDeclaration'
              && n.declarations[0].init.type === 'CallExpression'
              && n.declarations[0].init.callee.name === 'require';

            insertIndex = i;
            return result;
          });

          node.body.splice(insertIndex, 0, cssRequire);
        }
      }
    }
  });
}

<commit_msg>Destroy the old\!<commit_after><|endoftext|>