<commit_before>const Twilio = require("twilio")

const getRecipients = require("./recipients")
const toNumber = require("./phone-number")
const pick = (obj, ...keys) => keys.reduce((a, k) => ((a[k] = obj[k]), a), {})

const DEFAULT_MESSAGE =
  "Hey {{name}}, this is your friendly neighborhood SecretSantaBot telling you that you need to buy a gift for {{recipient}}!"

const twilio = (client, dry) => {
  const send = async (newMessage) => {
    try {
      return {
        status: "sent",
        message: dry
          ? newMessage
          : pick(await client.messages.create(newMessage), "sid", "from", "to"),
      }
    } catch (e) {
      e.originalMessage = newMessage
      throw e
    }
  }

  const resend = async ({ sid, to }) => {
    const message = await client.messages(sid).fetch()
    return send({
      ...message,
      // send message to a different number this time
      to: toNumber(to || message.to),
    })
  }

  const sendAll = (messages) => Promise.allSettled(messages.map((m) => send(m)))

  return { sendAll, resend }
}

const validateParticipants = (participants) => {
  if (!participants || !participants.length) {
    throw new Error("Participants must be a non-empty array")
  }

  for (const p of participants) {
    const participantErr = (m) => new Error(`${m}: ${JSON.stringify(p)}`)
    if (!p.name || !p.number)
      throw participantErr("All participants need a name and number")
    if (p.skip && !participants.some((pp) => p.skip.includes(pp.name)))
      throw participantErr("Skip must be a valid name of a participant")
  }
}

const validateMessage = (message) => {
  if (!message?.includes("{{name}}") || !message?.includes("{{recipient}}")) {
    throw new Error("Message must contain `{{name}}` and `{{recipient}}`")
  }
}

module.exports = async ({
  // Dry run or not
  dry,
  // Twilio auth
  accountSid,
  accountToken,
  // Twilio from number
  from,
  // Array of participants
  participants,
  // Message text to send
  message = DEFAULT_MESSAGE,
  // If resending a message supply a message sid
  // and optionally a new to number
  sid,
  to,
}) => {
  const client = new Twilio(accountSid, accountToken)

  if (sid) {
    return twilio(client, dry).resend({ sid, to })
  }

  validateParticipants(participants)
  validateMessage(message)

  const results = await twilio(client, dry).sendAll(
    getRecipients(participants).map((p) => ({
      from: toNumber(from),
      to: toNumber(p.number),
      body: message
        .replace("{{name}}", p.name)
        .replace("{{recipient}}", p.recipient),
    }))
  )

  const allError = results.every((r) => r.status === "rejected")

  if (allError) {
    throw results[0].reason
  }

  return results.map((r) => {
    if (r.status === "fulfilled") {
      return r.value
    }
    const res = {
      status: "error",
      error: r.reason,
    }
    /* istanbul ignore else */
    if (res?.error?.originalMessage) {
      res.message = res.error.originalMessage
      delete res.error.originalMessage
    }
    return res
  })
}
<commit_msg>Removes "from" field limitation of being a number. (#22)<commit_after>const Twilio = require("twilio")

const getRecipients = require("./recipients")
const toNumber = require("./phone-number")
const pick = (obj, ...keys) => keys.reduce((a, k) => ((a[k] = obj[k]), a), {})

const DEFAULT_MESSAGE =
  "Hey {{name}}, this is your friendly neighborhood SecretSantaBot telling you that you need to buy a gift for {{recipient}}!"

const twilio = (client, dry) => {
  const send = async (newMessage) => {
    try {
      return {
        status: "sent",
        message: dry
          ? newMessage
          : pick(await client.messages.create(newMessage), "sid", "from", "to"),
      }
    } catch (e) {
      e.originalMessage = newMessage
      throw e
    }
  }

  const resend = async ({ sid, to }) => {
    const message = await client.messages(sid).fetch()
    return send({
      ...message,
      // send message to a different number this time
      to: toNumber(to || message.to),
    })
  }

  const sendAll = (messages) => Promise.allSettled(messages.map((m) => send(m)))

  return { sendAll, resend }
}

const validateParticipants = (participants) => {
  if (!participants || !participants.length) {
    throw new Error("Participants must be a non-empty array")
  }

  for (const p of participants) {
    const participantErr = (m) => new Error(`${m}: ${JSON.stringify(p)}`)
    if (!p.name || !p.number)
      throw participantErr("All participants need a name and number")
    if (p.skip && !participants.some((pp) => p.skip.includes(pp.name)))
      throw participantErr("Skip must be a valid name of a participant")
  }
}

const validateMessage = (message) => {
  if (!message?.includes("{{name}}") || !message?.includes("{{recipient}}")) {
    throw new Error("Message must contain `{{name}}` and `{{recipient}}`")
  }
}

module.exports = async ({
  // Dry run or not
  dry,
  // Twilio auth
  accountSid,
  accountToken,
  // Twilio from number
  from,
  // Array of participants
  participants,
  // Message text to send
  message = DEFAULT_MESSAGE,
  // If resending a message supply a message sid
  // and optionally a new to number
  sid,
  to,
}) => {
  const client = new Twilio(accountSid, accountToken)

  if (sid) {
    return twilio(client, dry).resend({ sid, to })
  }

  validateParticipants(participants)
  validateMessage(message)

  const results = await twilio(client, dry).sendAll(
    getRecipients(participants).map((p) => ({
      from: from,
      to: toNumber(p.number),
      body: message
        .replace("{{name}}", p.name)
        .replace("{{recipient}}", p.recipient),
    }))
  )

  const allError = results.every((r) => r.status === "rejected")

  if (allError) {
    throw results[0].reason
  }

  return results.map((r) => {
    if (r.status === "fulfilled") {
      return r.value
    }
    const res = {
      status: "error",
      error: r.reason,
    }
    /* istanbul ignore else */
    if (res?.error?.originalMessage) {
      res.message = res.error.originalMessage
      delete res.error.originalMessage
    }
    return res
  })
}
<|endoftext|>


<commit_before>'use strict';

class TeamcityReporter {
    constructor(emitter, reporterOptions, options) {
        this.reporterOptions = reporterOptions;
        this.options = options;
        const events = 'start beforeIteration iteration beforeItem item beforePrerequest prerequest beforeScript script beforeRequest request beforeTest test beforeAssertion assertion console exception beforeDone done'.split(' ');
        events.forEach((e) => { if (typeof this[e] == 'function') emitter.on(e, (err, args) => this[e](err, args)) });
    }

    start(err, args) {
        console.log(`##teamcity[testSuiteStarted name='${this.options.collection.name}']`);
    }

    beforeItem(err, args) {
        this.currItem = {name: args.item.name, passed: true, failedAssertions: []};
        console.log(`##teamcity[testStarted name='${this.currItem.name}' captureStandardOutput='true']`);
    }

    beforeRequest(err, args) {
        console.log(args.request.method, args.request.url.toString());
    }

    request(err, args) {
        if (err) {
            console.log('request error');
        } else {
            const sizeObj = args.response.size();
            const size = sizeObj && (sizeObj.header || 0) + (sizeObj.body || 0) || 0;
            console.log(`Response code: ${args.response.code}, duration: ${args.response.responseTime}ms, size: ${size} bytes`);
            this.currItem.response = args.response;
        }
    }

    assertion(err, args) {
        if (err) {
            this.currItem.passed = false;
            this.currItem.failedAssertions.push(args.assertion);
        }
    }

    item(err, args) {
        if (!this.currItem.passed) {
            const msg = this.currItem.failedAssertions.join(", ");
            const details = `Response code: ${this.currItem.response.code}, reason: ${this.currItem.response.reason()}`;
            console.log(`##teamcity[testFailed name='${args.item.name}' message='${msg}' details='${msg}\n${details}']`);
            let body;
            try { body = JSON.parse(this.currItem.response) } catch (e) { body = '' };
            console.log('Response body:', body);
        }
        console.log(`##teamcity[testFinished name='${args.item.name}' duration='${this.currItem.response.responseTime}']`);
    }

    done(err, args) {
        console.log(`##teamcity[testSuiteFinished name='${this.options.collection.name}']`);
    }
}

module.exports = TeamcityReporter;
<commit_msg>Remove line break from testFailed message because TC does not like it<commit_after>'use strict';

class TeamcityReporter {
    constructor(emitter, reporterOptions, options) {
        this.reporterOptions = reporterOptions;
        this.options = options;
        const events = 'start beforeIteration iteration beforeItem item beforePrerequest prerequest beforeScript script beforeRequest request beforeTest test beforeAssertion assertion console exception beforeDone done'.split(' ');
        events.forEach((e) => { if (typeof this[e] == 'function') emitter.on(e, (err, args) => this[e](err, args)) });
    }

    start(err, args) {
        console.log(`##teamcity[testSuiteStarted name='${this.options.collection.name}']`);
    }

    beforeItem(err, args) {
        this.currItem = {name: args.item.name, passed: true, failedAssertions: []};
        console.log(`##teamcity[testStarted name='${this.currItem.name}' captureStandardOutput='true']`);
    }

    beforeRequest(err, args) {
        console.log(args.request.method, args.request.url.toString());
    }

    request(err, args) {
        if (err) {
            console.log('request error');
        } else {
            const sizeObj = args.response.size();
            const size = sizeObj && (sizeObj.header || 0) + (sizeObj.body || 0) || 0;
            console.log(`Response code: ${args.response.code}, duration: ${args.response.responseTime}ms, size: ${size} bytes`);
            this.currItem.response = args.response;
        }
    }

    assertion(err, args) {
        if (err) {
            this.currItem.passed = false;
            this.currItem.failedAssertions.push(args.assertion);
        }
    }

    item(err, args) {
        if (!this.currItem.passed) {
            const msg = this.currItem.failedAssertions.join(", ");
            const details = `Response code: ${this.currItem.response.code}, reason: ${this.currItem.response.reason()}`;
            console.log(`##teamcity[testFailed name='${args.item.name}' message='${msg}' details='${msg} - ${details}']`);
            let body;
            try { body = JSON.parse(this.currItem.response) } catch (e) { body = '' };
            console.log('Response body:', body);
        }
        console.log(`##teamcity[testFinished name='${args.item.name}' duration='${this.currItem.response.responseTime}']`);
    }

    done(err, args) {
        console.log(`##teamcity[testSuiteFinished name='${this.options.collection.name}']`);
    }
}

module.exports = TeamcityReporter;
<|endoftext|>


<commit_before>'use strict';

var defineProperties = Object.defineProperties
  , map              = require('es5-ext/lib/Object/map')

  , toString, codes, properties, init;

toString = function (code, str) {
	return '\x1b[' + code[0] + 'm' + (str || "") + '\x1b[' + code[1] + 'm';
};

codes = {
	// styles
	bold:      [1, 22],
	italic:    [3, 23],
	underline: [4, 24],
	inverse:   [7, 27],
	strike:    [9, 29]
};

['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'].forEach(
	function (color, index) {
		// foreground
		codes[color] = [30 + index, 39];
		// background
		codes['bg' + color[0].toUpperCase() + color.slice(1)] = [40 + index, 49];
	}
);
codes.gray = [90, 39];

properties = map(codes, function (code) {
	return {
		get: function () {
			this.style.push(code);
			return this;
		},
		enumerable: true
	};
});
properties.bright = {
	get: function () {
		this._bright = true;
		return this;
	},
	enumerable: true
};
properties.bgBright = {
	get: function () {
		this._bgBright = true;
		return this;
	},
	enumerable: true
};

init = function () {
	var o = defineProperties(function self(msg) {
		return self.style.reduce(function (msg, code) {
			if ((self._bright && (code[0] >= 30) && (code[0] < 38)) ||
					(self._bgBright && (code[0] >= 40) && (code[0] < 48))) {
				code = [code[0] + 60, code[1]];
			}
			return toString(code, msg);
		}, msg);
	}, properties);
	o.style = [];
	return o[this];
};

module.exports = defineProperties(function (msg) {
	return msg;
}, map(properties, function (code, name) {
	return {
		get: init.bind(name),
		enumerable: true
	};
}));
<commit_msg>Use descriptor factory<commit_after>'use strict';

var defineProperties = Object.defineProperties
  , d                = require('es5-ext/lib/Object/descriptor')
  , map              = require('es5-ext/lib/Object/map')

  , toString, codes, properties, init;

toString = function (code, str) {
	return '\x1b[' + code[0] + 'm' + (str || "") + '\x1b[' + code[1] + 'm';
};

codes = {
	// styles
	bold:      [1, 22],
	italic:    [3, 23],
	underline: [4, 24],
	inverse:   [7, 27],
	strike:    [9, 29]
};

['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'].forEach(
	function (color, index) {
		// foreground
		codes[color] = [30 + index, 39];
		// background
		codes['bg' + color[0].toUpperCase() + color.slice(1)] = [40 + index, 49];
	}
);
codes.gray = [90, 39];

properties = map(codes, function (code) {
	return {
		get: function () {
			this.style.push(code);
			return this;
		},
		enumerable: true
	};
});
properties.bright = {
	get: function () {
		this._bright = true;
		return this;
	},
	enumerable: true
};
properties.bgBright = {
	get: function () {
		this._bgBright = true;
		return this;
	},
	enumerable: true
};

init = function () {
	var o = defineProperties(function self(msg) {
		return self.style.reduce(function (msg, code) {
			if ((self._bright && (code[0] >= 30) && (code[0] < 38)) ||
					(self._bgBright && (code[0] >= 40) && (code[0] < 48))) {
				code = [code[0] + 60, code[1]];
			}
			return toString(code, msg);
		}, msg);
	}, properties);
	o.style = [];
	return o[this];
};

module.exports = defineProperties(function (msg) {
	return msg;
}, map(properties, function (code, name) {
	return d.gs('ce', init.bind(name));
}));
<|endoftext|>


<commit_before>'use strict';
try {

var util = require('util');
var Memcached = require('memcached');
var debug = require('debug')('loopback:connector:memcached');
var Connector = require('loopback-connector').Connector;
var NAME = 'memcached';
var client = null;
var _debug = false;

var log = function() {
  console.log(arguments);
  //if (_debug) {
  //  debug.apply(debug, arguments);
  //}
};

/**
 * Constructor for Memcached connector
 * @param {Object} settings The settings object
 * @param {DataSource} dataSource The data source
 * instance
 * @constructo
 */
var MemcachedDB = function(dataSource) {
  if (!(this instanceof MemcachedDB)) {
    return new MemcachedDB(dataSource);
  }

  Connector.call(this, NAME, dataSource.settings);

  this.name = NAME;
  this.settings = dataSource.settings;
  _debug = dataSource.settings.debug || debug.enabled;

  this.connect();

  if (this.debug) {
    debug('Settings %j', dataSource.settings);
  }
};

util.inherits(MemcachedDB, Connector);

MemcachedDB.prototype.connect = function(fn) {
  client = new Memcached(this.settings.hosts, this.settings.options);

  client.on('issue', function onIsse(e) {
    if (this.debug) {
      debug('Issue!', e);
    }
  }.bind(this))
  .on('failure', function onFailure(e) {
    if (this.debug) {
      debug('Failure!', e);
    }
  }.bind(this))
  .on('reconnecting', function onReconnecting(i) {
    if (this.debug) {
      debug('reconnecting...', i);
    }
  }.bind(this))
  .on('reconnected', function onReconnected(i) {
    if (this.debug) {
      debug('reconnected!', i);
    }
  }.bind(this))
  .on('remove', function(i) {
    if (this.debug) {
      debug('Removed server from consistent hashing', i);
    }
  }.bind(this));
};

MemcachedDB.prototype.getTypes = function onGetTypes() {
  return ['db', 'nosql', 'memcached'];
};

MemcachedDB.prototype.serialize = function onFormat(data) {
  return (typeof(data) === 'object') ? JSON.stringify(data) : data;
};

MemcachedDB.prototype.deserialize = function onFormat(data) {
  return (typeof(data) === 'object') ? JSON.parse(data) : data;
};

MemcachedDB.prototype.updateAttributes = function(model, id, data, callback) {
  log('updateAttributes', id, data);
  client.replace(id, data, data.ttl, function(e, res) {
    console.log(e, res);
  });
};

MemcachedDB.prototype.find = function(model, id, callback) {
  log('find', model, id);

  if (typeof (id) === 'undefined') {
    return callback(new Error("Please specify a cache id"));
  }

  var self = this;
  client.get(id, function(e, res) {
    callback(e, [res]);
  });
};

MemcachedDB.prototype.findById = function(id, callback) {
  log('index::findById', arguments.length, arguments);
  this.find(id, callback)
};

MemcachedDB.prototype.findOne = function(id, callback) {
  log('index::findOne', arguments.length, arguments);
  this.find(id, callback);
};

MemcachedDB.prototype.all = function(model, filter, callback) {
  console.log('index::all', arguments);

  var filterKeys = Object.keys(filter);
  if (filterKeys && filterKeys.length > 0) {
    var id = (filter.where && filter.where.id) ? filter.where.id : filter.id;
    this.find(model, id, callback);
    return;
  }

  // possibly trying to find a random item
  process.nextTick(function() {
     callback(new Error('This operation is not supported'));
  });
};

MemcachedDB.prototype.save = function onSave(model, data, callback) {
  log('index::save');
  transaction.set(data.id, data, data.ttl, callback);
};

/**
CRUD Ops isn't really needed, but seeing how it could
work with Memcached.
*/
MemcachedDB.prototype.exists = function onExists(id, callback) {
  log('exists %d', id);
  client.get(id, function(e, item) {
    callback(e, !!(!e && item));
  });
};

MemcachedDB.prototype.create = function onCreate(name, data, callback) {
  log('create', arguments);
  if (typeof (data) === 'undefined' || typeof (data.id) === 'undefined') {
    return callback(new Error("Missing data or record id (id)"));
  }

  log('create', data);
  var self = this;
  client.set(data.id, data, data.ttl, function(e, cb) {
    callback(e, data);
  });
};

MemcachedDB.prototype.upsert = function onUpsert(model, callback) {
  log('upsert');
  this.create(model, callback);
};

MemcachedDB.prototype.updateOrCreate = function onUpdateOrCreate(model, data, callback) {
  log('index::updateOrCreate', arguments);
  this.create(model, data, callback);
};

// Add or update
MemcachedDB.prototype.updateAll = function onUpdateAll(id, data, callback) {
  log('updateAll', arguments);
  this.create(data, callback);
};

MemcachedDB.prototype.update = function doUpdate() {
  console.log(arguments);
};

// Get a count on # of items in cache
MemcachedDB.prototype.count = function onCount(model, callback, where) {
  log('index::count', arguments);
  client.stats(function(e, res) {
    callback(e, (!e && res && res.length) ? res[0].curr_items : null);
  });
};

MemcachedDB.prototype.destroy = function onDestroy(model, id, callback) {
  log('destroy', arguments);
  client.del(id, callback);
};

// destroy all items
MemcachedDB.prototype.destroyAll = function onDestroyAll(model, data, callback) {
  if (data && data.id) {
    return this.destroy(model, data.id, callback);
  }

  client.flush(callback);
};

MemcachedDB.prototype.deleteById = function onDeleteById(id, callback) {
  log('deleteById', arguments);
  client.del(id, callback);
};

/**
 * Initialize the MemcachedDB connector for the given data source
 * @param {DataSource} dataSource The data source instance
 * @param {Function} [callback] The callback function
 */
exports.initialize = function initializeDataSource(dataSource, fn) {
  var settings = dataSource.settings;
  var connector = new MemcachedDB(dataSource);

  dataSource.connector = connector;
  dataSource.dataSource = dataSource;

  if (typeof(fn) === 'function') {
    process.nextTick(fn);
  }
};

} catch (e) {
  console.log(e);
}<commit_msg>Updated logging<commit_after>'use strict';
try {

var util = require('util');
var Memcached = require('memcached');
var debug = require('debug')('loopback:connector:memcached');
var Connector = require('loopback-connector').Connector;
var NAME = 'memcached';
var client = null;
var _debug = false;

var log = function() {
  if (_debug) {
   debug.apply(debug, arguments);
  }
};

/**
 * Constructor for Memcached connector
 * @param {Object} settings The settings object
 * @param {DataSource} dataSource The data source
 * instance
 * @constructo
 */
var MemcachedDB = function(dataSource) {
  if (!(this instanceof MemcachedDB)) {
    return new MemcachedDB(dataSource);
  }

  Connector.call(this, NAME, dataSource.settings);

  this.name = NAME;
  this.settings = dataSource.settings;
  _debug = dataSource.settings.debug || debug.enabled;

  this.connect();

  if (this.debug) {
    debug('Settings %j', dataSource.settings);
  }
};

util.inherits(MemcachedDB, Connector);

MemcachedDB.prototype.connect = function(fn) {
  client = new Memcached(this.settings.hosts, this.settings.options);

  client.on('issue', function onIsse(e) {
    log('Issue!', e);
  }.bind(this))
  .on('failure', function onFailure(e) {
    log('Failure!', e);
  }.bind(this))
  .on('reconnecting', function onReconnecting(i) {
    log('reconnecting...', i);
  }.bind(this))
  .on('reconnected', function onReconnected(i) {
    log('reconnected!', i);
  }.bind(this))
  .on('remove', function(i) {
    log('Removed server from consistent hashing', i);
  }.bind(this));
};

MemcachedDB.prototype.getTypes = function onGetTypes() {
  return ['db', 'nosql', 'memcached'];
};

MemcachedDB.prototype.serialize = function onFormat(data) {
  return (typeof(data) === 'object') ? JSON.stringify(data) : data;
};

MemcachedDB.prototype.deserialize = function onFormat(data) {
  return (typeof(data) === 'object') ? JSON.parse(data) : data;
};

MemcachedDB.prototype.updateAttributes = function(model, id, data, callback) {
  log('updateAttributes', id, data);
  client.replace(id, data, data.ttl, function(e, res) {
    callback(e, res);
  });
};

MemcachedDB.prototype.find = function(model, id, callback) {
  log('find', model, id);

  if (typeof (id) === 'undefined') {
    return callback(new Error("Please specify a cache id"));
  }

  var self = this;
  client.get(id, function(e, res) {
    callback(e, [res]);
  });
};

MemcachedDB.prototype.findById = function(id, callback) {
  log('index::findById', arguments.length, arguments);
  this.find(id, callback)
};

MemcachedDB.prototype.findOne = function(id, callback) {
  log('index::findOne', arguments.length, arguments);
  this.find(id, callback);
};

MemcachedDB.prototype.all = function(model, filter, callback) {
  log('index::all', arguments);

  var filterKeys = Object.keys(filter);
  if (filterKeys && filterKeys.length > 0) {
    var id = (filter.where && filter.where.id) ? filter.where.id : filter.id;
    this.find(model, id, callback);
    return;
  }

  // possibly trying to find a random item
  process.nextTick(function() {
     callback(new Error('This operation is not supported'));
  });
};

MemcachedDB.prototype.save = function onSave(model, data, callback) {
  log('index::save');
  transaction.set(data.id, data, data.ttl, callback);
};

/**
CRUD Ops isn't really needed, but seeing how it could
work with Memcached.
*/
MemcachedDB.prototype.exists = function onExists(id, callback) {
  log('exists %d', id);
  client.get(id, function(e, item) {
    callback(e, !!(!e && item));
  });
};

MemcachedDB.prototype.create = function onCreate(name, data, callback) {
  log('create', arguments);
  if (typeof (data) === 'undefined' || typeof (data.id) === 'undefined') {
    return callback(new Error("Missing data or record id (id)"));
  }

  log('create', data);
  client.set(data.id, data, data.ttl, function(e, cb) {
    callback(e, data);
  });
};

MemcachedDB.prototype.upsert = function onUpsert(model, callback) {
  log('upsert');
  this.create(model, callback);
};

MemcachedDB.prototype.updateOrCreate = function onUpdateOrCreate(model, data, callback) {
  log('index::updateOrCreate', arguments);
  this.create(model, data, callback);
};

// Add or update
MemcachedDB.prototype.updateAll = function onUpdateAll(id, data, callback) {
  log('updateAll', arguments);
  this.create(data, callback);
};

MemcachedDB.prototype.update = function doUpdate() {
  log('update'arguments);
};

// Get a count on # of items in cache
MemcachedDB.prototype.count = function onCount(model, callback, where) {
  log('index::count', arguments);
  client.stats(function(e, res) {
    callback(e, (!e && res && res.length) ? res[0].curr_items : null);
  });
};

MemcachedDB.prototype.destroy = function onDestroy(model, id, callback) {
  log('destroy', arguments);
  client.del(id, callback);
};

// destroy all items
MemcachedDB.prototype.destroyAll = function onDestroyAll(model, data, callback) {
  if (data && data.id) {
    return this.destroy(model, data.id, callback);
  }

  client.flush(callback);
};

MemcachedDB.prototype.deleteById = function onDeleteById(id, callback) {
  log('deleteById', arguments);
  client.del(id, callback);
};

/**
 * Initialize the MemcachedDB connector for the given data source
 * @param {DataSource} dataSource The data source instance
 * @param {Function} [callback] The callback function
 */
exports.initialize = function initializeDataSource(dataSource, fn) {
  var settings = dataSource.settings;
  var connector = new MemcachedDB(dataSource);

  dataSource.connector = connector;
  dataSource.dataSource = dataSource;

  if (typeof(fn) === 'function') {
    process.nextTick(fn);
  }
};

} catch (e) {
  console.log(e);
}<|endoftext|>


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

    angular
            .module('tierraDeColoresApp')
            .controller('FacturaProductoController', FacturaProductoController);

    FacturaProductoController.$inject = ['$scope', 'BaseURL', '$http', 'cookieService', 'ngDialog', 'NgTableParams', 'toaster', '$timeout', 'facturaProductoService', '$state', '$stateParams'];

    function FacturaProductoController($scope, BaseURL, $http, cookieService, ngDialog, NgTableParams, toaster, $timeout, facturaProductoService, $state, $stateParams) {
        var vm = this;
        /*VARIABLES*/
        vm._facturaProducto = {
            "idFacturaProducto": null,
            "proveedor": null,
            "monto": null,
            "fechaFactura": "",
            "fechaCreacion": "",
            "fechaModificacion": null,
            "usuarioCreacion": null,
            "usuarioModificacion": null,
            "estado": true,
            "observaciones": null,
            "estadoLocal": null,
            "numeroFactura": "",
            "carga": null
        };
        /*METODOS*/
        vm.actualizarFacturaProducto = actualizarFacturaProducto;
        vm.agregarFacturaProducto = agregarFacturaProducto;
        vm.agregarProductoFactura = agregarProductoFactura;
        vm.confirmarActualizarFacturaProducto = confirmarActualizarFacturaProducto;
        vm.confirmarFinalizarCargaFactura = confirmarFinalizarCargaFactura;
        vm.detallesFacturaProducto = detallesFacturaProducto;
        vm.finalizarCargaFactura = finalizarCargaFactura;
        vm.listaFacturaProducto = listaFacturaProducto;

        function actualizarFacturaProducto() {
            facturaProductoService
                    .update($scope.ngDialogData.toUpdate)
                    .then(function (datos) {
                        ngDialog.closeAll();
                        if (datos.status === 200) {
                            $timeout(function timer() {
                                $state.go($state.current, {}, {reload: true});
                            }, 1000);
                        } else {
                            toaster.pop({
                                type: 'error',
                                title: 'Error',
                                body: "¡Op's algo paso!, comunicate con el administrador.",
                                showCloseButton: false
                            });
                        }
                    });
        }

        function agregarFacturaProducto(facturaProducto) {
            facturaProductoService
                    .add(facturaProducto)
                    .then(function (datos) {
                        if (datos.status === 200) {
                            toaster.pop({
                                type: 'success',
                                title: 'Exito',
                                body: 'Factura de producto agregada con exito.',
                                showCloseButton: false
                            });
                            $timeout(function timer() {
                                $state.go('panel_factura_producto', {"idFactura": datos.data.msg});
                            }, 2000);
                        } else {
                            toaster.pop({
                                type: 'error',
                                title: 'Error',
                                body: "¡Op's algo paso!, comunicate con el administrador.",
                                showCloseButton: false
                            });
                        }
                    });
        }

        function agregarProductoFactura() {
            $state.go('add_producto_factura', {"idFactura": $stateParams.idFactura});
        }

        function confirmarActualizarFacturaProducto(toUpdate) {
            ngDialog.open({
                template: 'views/factura_producto/modal-confirmar-actualizacion.html',
                className: 'ngdialog-theme-advertencia',
                showClose: false,
                controller: 'FacturaProductoController as vm',
                closeByDocument: false,
                closeByEscape: true,
                data: {
                    'toUpdate': toUpdate
                }
            });
        }

        function confirmarFinalizarCargaFactura() {
            ngDialog.open({
                template: 'views/factura_producto/modal-confirmar-finalizar-carga-factura.html',
                className: 'ngdialog-theme-advertencia',
                showClose: false,
                controller: 'FacturaProductoController',
                closeByDocument: false,
                closeByEscape: true
            });
        }

        function detallesFacturaProducto() {
            facturaProductoService
                    .detail($stateParams.idFactura)
                    .then(function (datos) {
                        if (datos.status === 200) {
                            if (datos.data.carga === false) {
                                $state.go('productos');
                            } else {
                                $scope.detalle = datos.data;
                                var splited = datos.data.fechaFactura.split("-");
                                var date = new Date(splited[0], splited[1] - 1, splited[2]);
                                $scope.detalle.fechaFactura = date;
                            }
                        }
                    });
        }

        function finalizarCargaFactura() {
            facturaProductoService
                    .finish($stateParams.idFactura)
                    .then(function (datos) {
                        ngDialog.closeAll();
                        if (datos.status === 200) {
                            toaster.pop({
                                type: 'success',
                                title: 'Exito',
                                body: 'Carga finalizada.',
                                showCloseButton: false
                            });
                            $timeout(function timer() {
                                $state.go('productos');
                            }, 2000);
                        } else {
                            toaster.pop({
                                type: 'error',
                                title: 'Error',
                                body: "¡Op's algo paso!, comunicate con el administrador.",
                                showCloseButton: false
                            });
                        }
                    });
        }

        function listaFacturaProducto() {
            var token = cookieService.get('token');
            token.then(function (data) {
                $scope.tableFacturaProductos = new NgTableParams({
                    page: 1,
                    count: 11
                }, {
                    getData: function (params) {
                        return $http({
                            url: BaseURL + "facturaProducto/list/paged",
                            method: 'get',
                            headers: {
                                'Authorization': 'Bearer ' + data,
                                'Content-type': 'application/json'
                            },
                            params: {
                                page: params.page() - 1,
                                size: params.count()
                            }
                        }).then(function successCallback(response) {
                            params.total(response.data.totalElements);
                            return response.data.content;
                        }, function errorCallback(response) {
                        });
                    }
                });
            });
        }

    }

})();<commit_msg>vm agregado para metodo de confirmar cargar de factura<commit_after>(function () {
    'use strict';

    angular
            .module('tierraDeColoresApp')
            .controller('FacturaProductoController', FacturaProductoController);

    FacturaProductoController.$inject = ['$scope', 'BaseURL', '$http', 'cookieService', 'ngDialog', 'NgTableParams', 'toaster', '$timeout', 'facturaProductoService', '$state', '$stateParams'];

    function FacturaProductoController($scope, BaseURL, $http, cookieService, ngDialog, NgTableParams, toaster, $timeout, facturaProductoService, $state, $stateParams) {
        var vm = this;
        /*VARIABLES*/
        vm._facturaProducto = {
            "idFacturaProducto": null,
            "proveedor": null,
            "monto": null,
            "fechaFactura": "",
            "fechaCreacion": "",
            "fechaModificacion": null,
            "usuarioCreacion": null,
            "usuarioModificacion": null,
            "estado": true,
            "observaciones": null,
            "estadoLocal": null,
            "numeroFactura": "",
            "carga": null
        };
        /*METODOS*/
        vm.actualizarFacturaProducto = actualizarFacturaProducto;
        vm.agregarFacturaProducto = agregarFacturaProducto;
        vm.agregarProductoFactura = agregarProductoFactura;
        vm.confirmarActualizarFacturaProducto = confirmarActualizarFacturaProducto;
        vm.confirmarFinalizarCargaFactura = confirmarFinalizarCargaFactura;
        vm.detallesFacturaProducto = detallesFacturaProducto;
        vm.finalizarCargaFactura = finalizarCargaFactura;
        vm.listaFacturaProducto = listaFacturaProducto;

        function actualizarFacturaProducto() {
            facturaProductoService
                    .update($scope.ngDialogData.toUpdate)
                    .then(function (datos) {
                        ngDialog.closeAll();
                        if (datos.status === 200) {
                            $timeout(function timer() {
                                $state.go($state.current, {}, {reload: true});
                            }, 1000);
                        } else {
                            toaster.pop({
                                type: 'error',
                                title: 'Error',
                                body: "¡Op's algo paso!, comunicate con el administrador.",
                                showCloseButton: false
                            });
                        }
                    });
        }

        function agregarFacturaProducto(facturaProducto) {
            facturaProductoService
                    .add(facturaProducto)
                    .then(function (datos) {
                        if (datos.status === 200) {
                            toaster.pop({
                                type: 'success',
                                title: 'Exito',
                                body: 'Factura de producto agregada con exito.',
                                showCloseButton: false
                            });
                            $timeout(function timer() {
                                $state.go('panel_factura_producto', {"idFactura": datos.data.msg});
                            }, 2000);
                        } else {
                            toaster.pop({
                                type: 'error',
                                title: 'Error',
                                body: "¡Op's algo paso!, comunicate con el administrador.",
                                showCloseButton: false
                            });
                        }
                    });
        }

        function agregarProductoFactura() {
            $state.go('add_producto_factura', {"idFactura": $stateParams.idFactura});
        }

        function confirmarActualizarFacturaProducto(toUpdate) {
            ngDialog.open({
                template: 'views/factura_producto/modal-confirmar-actualizacion.html',
                className: 'ngdialog-theme-advertencia',
                showClose: false,
                controller: 'FacturaProductoController as vm',
                closeByDocument: false,
                closeByEscape: true,
                data: {
                    'toUpdate': toUpdate
                }
            });
        }

        function confirmarFinalizarCargaFactura() {
            ngDialog.open({
                template: 'views/factura_producto/modal-confirmar-finalizar-carga-factura.html',
                className: 'ngdialog-theme-advertencia',
                showClose: false,
                controller: 'FacturaProductoController as vm',
                closeByDocument: false,
                closeByEscape: true
            });
        }

        function detallesFacturaProducto() {
            facturaProductoService
                    .detail($stateParams.idFactura)
                    .then(function (datos) {
                        if (datos.status === 200) {
                            if (datos.data.carga === false) {
                                $state.go('productos');
                            } else {
                                $scope.detalle = datos.data;
                                var splited = datos.data.fechaFactura.split("-");
                                var date = new Date(splited[0], splited[1] - 1, splited[2]);
                                $scope.detalle.fechaFactura = date;
                            }
                        }
                    });
        }

        function finalizarCargaFactura() {
            facturaProductoService
                    .finish($stateParams.idFactura)
                    .then(function (datos) {
                        ngDialog.closeAll();
                        if (datos.status === 200) {
                            toaster.pop({
                                type: 'success',
                                title: 'Exito',
                                body: 'Carga finalizada.',
                                showCloseButton: false
                            });
                            $timeout(function timer() {
                                $state.go('productos');
                            }, 2000);
                        } else {
                            toaster.pop({
                                type: 'error',
                                title: 'Error',
                                body: "¡Op's algo paso!, comunicate con el administrador.",
                                showCloseButton: false
                            });
                        }
                    });
        }

        function listaFacturaProducto() {
            var token = cookieService.get('token');
            token.then(function (data) {
                $scope.tableFacturaProductos = new NgTableParams({
                    page: 1,
                    count: 11
                }, {
                    getData: function (params) {
                        return $http({
                            url: BaseURL + "facturaProducto/list/paged",
                            method: 'get',
                            headers: {
                                'Authorization': 'Bearer ' + data,
                                'Content-type': 'application/json'
                            },
                            params: {
                                page: params.page() - 1,
                                size: params.count()
                            }
                        }).then(function successCallback(response) {
                            params.total(response.data.totalElements);
                            return response.data.content;
                        }, function errorCallback(response) {
                        });
                    }
                });
            });
        }

    }

})();<|endoftext|>


<commit_before>"use strict";

const gitUp = require("git-up");

/**
 * gitUrlParse
 * Parses a Git url.
 *
 * @name gitUrlParse
 * @function
 * @param {String} url The Git url to parse.
 * @return {GitUrl} The `GitUrl` object containing:
 *
 *  - `protocols` (Array): An array with the url protocols (usually it has one element).
 *  - `port` (null|Number): The domain port.
 *  - `resource` (String): The url domain (including subdomains).
 *  - `user` (String): The authentication user (usually for ssh urls).
 *  - `pathname` (String): The url pathname.
 *  - `hash` (String): The url hash.
 *  - `search` (String): The url querystring value.
 *  - `href` (String): The input url.
 *  - `protocol` (String): The git url protocol.
 *  - `token` (String): The oauth token (could appear in the https urls).
 *  - `source` (String): The Git provider (e.g. `"github.com"`).
 *  - `owner` (String): The repository owner.
 *  - `name` (String): The repository name.
 *  - `full_name` (String): The owner and name values in the `owner/name` format.
 *  - `toString` (Function): A function to stringify the parsed url into another url type.
 *  - `organization` (String): The organization the owner belongs to. This is CloudForge specific.
 *
 */
function gitUrlParse(url) {

    if (typeof url !== "string") {
        throw new Error("The url must be a string.");
    }

    let urlInfo = gitUp(url)
      , sourceParts = urlInfo.resource.split(".")
      , splits = null
      ;

    urlInfo.toString = function (type) {
        return gitUrlParse.stringify(this, type);
    };

    urlInfo.source = sourceParts.length > 2
                   ? sourceParts.slice(-2).join(".")
                   : urlInfo.source = urlInfo.resource
                   ;

    urlInfo.name = urlInfo.pathname.substring(1).replace(/\.git$/, "");
    urlInfo.owner = urlInfo.user;
    urlInfo.organization = urlInfo.owner;

    switch (urlInfo.source) {
        case "cloudforge.com":
            urlInfo.owner = urlInfo.user;
            urlInfo.organization = sourceParts[0];
            break;
        default:
            splits = urlInfo.name.split("/");
            if (splits.length === 2) {
                urlInfo.owner = splits[0];
                urlInfo.name = splits[1];
            }
            break;
    }

    urlInfo.full_name = urlInfo.owner;
    if (urlInfo.name) {
        urlInfo.full_name && (urlInfo.full_name += "/");
        urlInfo.full_name += urlInfo.name;
    }

    return urlInfo;
}

/**
 * stringify
 * Stringifies a `GitUrl` object.
 *
 * @name stringify
 * @function
 * @param {GitUrl} obj The parsed Git url object.
 * @param {String} type The type of the stringified url (default `obj.protocol`).
 * @return {String} The stringified url.
 */
gitUrlParse.stringify = function (obj, type) {
    type = type || obj.protocol;
    const port = obj.port ? `:${obj.port}` : '';
    const user = obj.user || 'git';
    switch (type) {
        case "ssh":
            if (port)
                return `ssh://${user}@${obj.resource}${port}/${obj.full_name}.git`;
            else
                return `${user}@${obj.resource}:${obj.full_name}.git`;
        case "git+ssh":
        case "ssh+git":
            return `${type}://${user}@${obj.resource}${port}/${obj.full_name}.git`;
        case "http":
        case "https":
            let token = "";
            if (obj.token) {
              token = buildToken(obj);
            }
            return `${type}://${token}${obj.resource}${port}/${obj.full_name}`;
        default:
            return obj.href;
    }
};

/*!
 * buildToken
 * Builds OAuth token prefix (helper function)
 *
 * @name buildToken
 * @function
 * @param {GitUrl} obj The parsed Git url object.
 * @return {String} token prefix
 */
function buildToken(obj) {
    switch (obj.source) {
      case "bitbucket.org":
        return `x-token-auth:${obj.token}@`;
      default:
        return `${obj.token}@`
    }
}

module.exports = gitUrlParse;
<commit_msg>Handling weird protocols in the stringify method<commit_after>"use strict";

const gitUp = require("git-up");

/**
 * gitUrlParse
 * Parses a Git url.
 *
 * @name gitUrlParse
 * @function
 * @param {String} url The Git url to parse.
 * @return {GitUrl} The `GitUrl` object containing:
 *
 *  - `protocols` (Array): An array with the url protocols (usually it has one element).
 *  - `port` (null|Number): The domain port.
 *  - `resource` (String): The url domain (including subdomains).
 *  - `user` (String): The authentication user (usually for ssh urls).
 *  - `pathname` (String): The url pathname.
 *  - `hash` (String): The url hash.
 *  - `search` (String): The url querystring value.
 *  - `href` (String): The input url.
 *  - `protocol` (String): The git url protocol.
 *  - `token` (String): The oauth token (could appear in the https urls).
 *  - `source` (String): The Git provider (e.g. `"github.com"`).
 *  - `owner` (String): The repository owner.
 *  - `name` (String): The repository name.
 *  - `full_name` (String): The owner and name values in the `owner/name` format.
 *  - `toString` (Function): A function to stringify the parsed url into another url type.
 *  - `organization` (String): The organization the owner belongs to. This is CloudForge specific.
 *
 */
function gitUrlParse(url) {

    if (typeof url !== "string") {
        throw new Error("The url must be a string.");
    }

    let urlInfo = gitUp(url)
      , sourceParts = urlInfo.resource.split(".")
      , splits = null
      ;

    urlInfo.toString = function (type) {
        return gitUrlParse.stringify(this, type);
    };

    urlInfo.source = sourceParts.length > 2
                   ? sourceParts.slice(-2).join(".")
                   : urlInfo.source = urlInfo.resource
                   ;

    urlInfo.name = urlInfo.pathname.substring(1).replace(/\.git$/, "");
    urlInfo.owner = urlInfo.user;
    urlInfo.organization = urlInfo.owner;

    switch (urlInfo.source) {
        case "cloudforge.com":
            urlInfo.owner = urlInfo.user;
            urlInfo.organization = sourceParts[0];
            break;
        default:
            splits = urlInfo.name.split("/");
            if (splits.length === 2) {
                urlInfo.owner = splits[0];
                urlInfo.name = splits[1];
            }
            break;
    }

    urlInfo.full_name = urlInfo.owner;
    if (urlInfo.name) {
        urlInfo.full_name && (urlInfo.full_name += "/");
        urlInfo.full_name += urlInfo.name;
    }

    return urlInfo;
}

/**
 * stringify
 * Stringifies a `GitUrl` object.
 *
 * @name stringify
 * @function
 * @param {GitUrl} obj The parsed Git url object.
 * @param {String} type The type of the stringified url (default `obj.protocol`).
 * @return {String} The stringified url.
 */
gitUrlParse.stringify = function (obj, type) {
    type = type || ((obj.protocols && obj.protocols.length) ? obj.protocols.join('+') : obj.protocol);
    const port = obj.port ? `:${obj.port}` : '';
    const user = obj.user || 'git';
    switch (type) {
        case "ssh":
            if (port)
                return `ssh://${user}@${obj.resource}${port}/${obj.full_name}.git`;
            else
                return `${user}@${obj.resource}:${obj.full_name}.git`;
        case "git+ssh":
        case "ssh+git":
            return `${type}://${user}@${obj.resource}${port}/${obj.full_name}.git`;
        case "http":
        case "https":
            let token = "";
            if (obj.token) {
              token = buildToken(obj);
            }
            return `${type}://${token}${obj.resource}${port}/${obj.full_name}`;
        default:
            return obj.href;
    }
};

/*!
 * buildToken
 * Builds OAuth token prefix (helper function)
 *
 * @name buildToken
 * @function
 * @param {GitUrl} obj The parsed Git url object.
 * @return {String} token prefix
 */
function buildToken(obj) {
    switch (obj.source) {
      case "bitbucket.org":
        return `x-token-auth:${obj.token}@`;
      default:
        return `${obj.token}@`
    }
}

module.exports = gitUrlParse;
<|endoftext|>


<commit_before>"use strict";

var Recipe = require('./recipe');

var steps = {
    'deploy to github': require('./steps/deploy-to-github.js'),
    'deploy to s3': require('./steps/deploy-to-s3.js'),
    'less': require('./steps/less'),
    'js': require('./steps/browserify'),
    'watch': require('./steps/watch'),
    'dev server': require('./steps/dev-server.js'),
    'pages': require('./steps/pages.js'),
    'js config': require('./steps/js-config.js'),
    'write bootstrap': require('./steps/write-bootstrap.js'),
    'make build dir': require('./steps/make-build-dir'),
    'copy includes': require('./steps/copy-includes')
};

module.exports = function(){
    return new Recipe()
        .step('make build dir', steps['make build dir'])
        .step('copy includes', steps['copy includes'])
        .task('build', ['make build dir', 'copy includes']);
};

module.exports.Recipe = Recipe;
module.exports.Cookbook = require('./cookbook');

module.exports.steps = steps;

// mott quickstart ->
 // * set up package.json
 // * add index.html
 // * add simple mott.js
module.exports.starter = function(){
    return module.exports('mott starter')
        .step('less', steps.less)
        .step('js', steps.js)
        .step('watch', steps.watch)
        .step('run', steps['dev server'])
        .step('pages', steps.pages)
        .step('js config', steps['js config'])

        .task('build', ['js config', 'js', 'less', 'pages'])
        .task('run', ['build', 'run', 'watch'])

        .provide('config', {
            'url': 'http://localhost:8080'
        });
};

// var recipe = mott.recipe('single-page');
// New mini:
// var mott = require('mott');
// new mott.Cookbook({apps: {'web': mott.recipe('single-pager').configure()}}).cli();

// Ideal mini?
// require('mott').cli();
<commit_msg>Update built in recipes for no more step registry<commit_after>"use strict";

var Recipe = require('./recipe');

var steps = {
    'deploy to github': require('./steps/deploy-to-github.js'),
    'deploy to s3': require('./steps/deploy-to-s3.js'),
    'less': require('./steps/less'),
    'js': require('./steps/browserify'),
    'watch': require('./steps/watch'),
    'dev server': require('./steps/dev-server.js'),
    'pages': require('./steps/pages.js'),
    'js config': require('./steps/js-config.js'),
    'write bootstrap': require('./steps/write-bootstrap.js'),
    'make build dir': require('./steps/make-build-dir'),
    'copy includes': require('./steps/copy-includes')
};

module.exports = function(){
    return new Recipe()
        .task('build', [steps['make build dir'], steps['copy includes']]);
};

module.exports.Recipe = Recipe;
module.exports.Cookbook = require('./cookbook');

module.exports.steps = steps;

// mott quickstart ->
 // * set up package.json
 // * add index.html
 // * add simple mott.js
module.exports.starter = function(){
    return module.exports('mott starter')
        .task('build', [steps['js config'], steps.js, steps.less, steps.pages])
        .task('run', ['build', steps['dev server'], steps.watch])

        .provide('config', {
            'url': 'http://localhost:8080'
        });
};

// var recipe = mott.recipe('single-page');
// New mini:
// var mott = require('mott');
// new mott.Cookbook({apps: {'web': mott.recipe('single-pager').configure()}}).cli();

// Ideal mini?
// require('mott').cli();
<|endoftext|>


<commit_before>var Promise = require('bluebird');
var semver = require('semver');
var conf = require('npmconf');
var npmConfLoad = Promise.promisify(conf.load);
var chalk = require('chalk');
var nyg = require('nyg');
var varName = require('variable-name');
var path = require('path');
var npm = require('npm');
var fs = require('fs');
var xtend = require('xtend');
var loadJson = Promise.promisify(require('./loadJson'));
var spawn = require('npm-execspawn');
var open = require('opn');

var argv = require('yargs')
  .alias('t', 'test')
  .alias('u', 'user')
  .describe('t', 'generate index.js and test.js files')
  .describe('u', 'an organization override for GitHub URLs')
  .argv;

var target = process.cwd();

var usePkgJson = false;
var useNygConf = false;

var hasPkgJson = false;
var hasNygConf = false;

function hasFile(file) {
  try {
    fs.statSync(file);
    return true;
  } catch (e) {
    return false;
  }
}

//console.log(__dirname)

hasPkgJson = hasFile(target + "/package.json");

var configs = {
  nyg: {
    configPath: path.join(__dirname, '../', 'nyg-cfg.json')
  },
  pkg: {
    configPath: target + '/package.json'
  },
  npm: {},
  git: {}
};

var modulePrompts = [
  {
    'name': 'location'
    , 'message': 'Where would you like to put the module?'
    , 'default': path.basename(target)
  },
  {
    'name': 'name'
    , 'message': 'Module name:'
    , 'default': path.basename(target)
  },
  {
    'name': 'description'
    , 'message': 'Module description:'
  },
  {
    'name': 'tags'
    , 'message': 'Module tags:'
  },
  {
    'name': 'stability'
    , 'type': 'list'
    , 'message': 'Module stability:'
    , 'default': 'experimental'
    , 'choices': [
      'deprecated'
      , 'experimental'
      , 'unstable'
      , 'stable'
      , 'frozen'
      , 'locked'
    ]
  }
];

function getNygConfig() {
  return loadJson(configs.nyg.configPath)
    .then(function (data) {
      configs.nyg = xtend(configs.nyg, data);
      return configs;
    })
    .catch(function (err) {
      'use strict';
      console.warn(chalk.bgYellow("WARN"), chalk.magenta("could not open " + configs.nyg.configPath));
      console.warn(chalk.dim(err.message));
    })
}

function getPkgJson() {
  if(!hasPkgJson) return {};
  return loadJson(configs.pkg.configPath)
    .then(function (data) {
      configs.pkg = xtend(configs.pkg, data);
      return configs;
    })
    .catch(function (err) {
      'use strict';
      console.warn(chalk.bgYellow("WARN"), chalk.magenta("could not open " + configs.pkg.configPath));
      console.warn(chalk.dim(err.message));
    })
}

function getNpmConfig() {
  return npmConfLoad({})
    .then(function (config) {
      // configs.npm = xtend(configs.npm, data);
      // console.log('conf: ',conf);
      var data = {
        user: {
          name: config.get('init.author.name')
          , site: config.get('init.author.url') || ''
          , email: config.get('init.author.email')
          , github: config.get('init.author.github')
          , username: config.get('username')
        }
      };

      if (typeof argv.u === 'string') {
        data.org = {name: argv.u, github: argv.u};
        console.log(chalk.green('Creating module under organization ' + chalk.bold(data.org.name)))
      } else if (argv.u) {
        return done('--user specified, but without an organization!')
      }

      if (!data.user.name) return bail('npm config set init.author.name "Your Name"');
      if (!data.user.email) return bail('npm config set init.author.email "me@example.com"');
      if (!data.user.github) return bail('npm config set init.author.github "your-github-handle"');

      //default org to user
      if (!data.org) {
        data.org = {
          name: data.user.name,
          github: data.user.github
        }
      }

      if (!data.user.url) {
        data.user.url = 'https://github.com/' + data.user.github
      }

      configs.npm = xtend(configs.npm, data);

      return configs;
    })
    .catch(function (err) {
      'use strict';
      console.warn(chalk.bgYellow("WARN"), chalk.magenta("could not open npm config"));
      console.warn(chalk.dim(err.message));
    })
}

module.exports = function(opts) {
  if (opts.prompts) modulePrompts = modulePrompts.concat(opts.prompts);

  Promise.all([getNygConfig(), getPkgJson(), getNpmConfig()])
  .then(function (data) {
    if(configs.nyg.useDefaultDir){
      modulePrompts[0].default = configs.nyg.defaultDir;
    }else if(!configs.nyg.useDefaultDir && hasPkgJson){
      modulePrompts[0].default = process.cwd().replace(path.basename(process.cwd()), '');
    }else{
      modulePrompts[0].default = process.cwd();
    }
    startPrompts(configs, opts.globs, opts.callback);
  })
};

function startPrompts(data, extraGlobs, cb) {

  var globs = [
    {base: '../templates/', glob: '*'},
    {base: '../templates/test', glob: '*', output: '/test'}
  ];

  if (extraGlobs) {
    // assign relative path to base
    extraGlobs.forEach((g) => g.base = path.relative(__dirname, g.base));
    globs = globs.concat(extraGlobs);
  }

  var gen = nyg(modulePrompts, globs)
    .on('postprompt', function () {
      var done = gen.async();
      configs.outputDir = path.join(gen.config.get('location'), gen.config.get('name'));

      // check if directory exists
      fs.access(configs.outputDir, function(err) {
        if (!err) {
          var contents = fs.readdirSync(configs.outputDir);
          contents.forEach(function(item, index) {
            (item.indexOf('.') === 0) && contents.splice(index, 1);
          });
          if (contents.length) {
            console.warn(chalk.bgRed('ERROR:'), chalk.red(`directory ${configs.outputDir} already exists and is not empty.`));
            gen.end();
          }
          done();
        } else {
          fs.mkdir(configs.outputDir, function() {
            console.log(chalk.bgYellow('CREATED DIR:'), chalk.yellow(configs.outputDir));
            gen.chdir(configs.outputDir);
            done();
          })
        }

        gen.config.set('name', dequote(gen.config.get('name')));
        gen.config.set('testDescription', escape(gen.config.get('description')).replace(/\\"+/g, '\"'));
        gen.config.set('description', dequote(gen.config.get('description')));
        gen.config.set('varName', varName(gen.config.get('name')));
        gen.config.set('tags', JSON.stringify(gen.config.get('tags').split(' ').map(function (str) {
          return dequote(str).trim();
        }).filter(Boolean), null, 2));
        gen.config.set('devDependencies', '{\n    "tape": "*"\n  }');
        gen.config.set('user', {
          "name": configs.npm.user.name,
          "email": configs.npm.user.email,
          "url": configs.npm.user.email
        });
        gen.config.set('org', configs.npm.org);
      });
    })
    .on('postinstall', function () {
      open(configs.outputDir);
      cb && cb(configs.outputDir);

      var cmd = 'ghrepo --color';
      var child = spawn(cmd, {cwd: configs.outputDir, stdio: 'inherit' });
      child.on('exit', function (err) {
        if (err === 0) {
          var location = gen.config.get('location');
          gen.prompt({
            type: "confirm",
            name: "doInstall",
            message: "Would you like to install this module in an existing project?",
            default: true
          },function(data){
            if(data.doInstall){
              gen.prompt({
                'name': 'installLocation'
                , 'message': 'Where would you like to install it?'  //where would you like the module to live?
                , 'default': process.cwd()
              }, function(answers){
                var cmd = 'npm install git+'+configs.npm.user.url+'/'+gen.config.get('name')+' --save';
                var installProc = spawn(cmd, {cwd: answers.installLocation});
                installProc.on('exit', function (err) {
                  process.exit(0);
                });
                installProc.stdout.pipe(process.stdout);
                installProc.stderr.pipe(process.stderr);
                process.stdin.pipe(installProc.stdin);
              });
            }else{
              process.exit(0);
            }
          });

        } else {
          console.log('git command failed');
          process.exit(1)
        }
      });
      /*child.stdout.pipe(process.stdout);
      child.stderr.pipe(process.stderr);
      process.stdin.pipe(child.stdin);*/
    })
    .run();
}

function bail(cmd) {
  console.log('');
  console.log('Missing configuration option, please run the following using your own value:');
  console.log('');
  console.log('  > ' + cmd);
  console.log('');
}

function dequote(str) {
  return str.replace(/\"+/g, '\\"');
}<commit_msg>post install functionality<commit_after>var Promise = require('bluebird');
var semver = require('semver');
var conf = require('npmconf');
var npmConfLoad = Promise.promisify(conf.load);
var chalk = require('chalk');
var nyg = require('nyg');
var varName = require('variable-name');
var path = require('path');
var npm = require('npm');
var fs = require('fs');
var xtend = require('xtend');
var loadJson = Promise.promisify(require('./loadJson'));
var spawn = require('npm-execspawn');
var open = require('opn');

var argv = require('yargs')
  .alias('t', 'test')
  .alias('u', 'user')
  .describe('t', 'generate index.js and test.js files')
  .describe('u', 'an organization override for GitHub URLs')
  .argv;

var target = process.cwd();

var usePkgJson = false;
var useNygConf = false;

var hasPkgJson = false;
var hasNygConf = false;

function hasFile(file) {
  try {
    fs.statSync(file);
    return true;
  } catch (e) {
    return false;
  }
}

//console.log(__dirname)

hasPkgJson = hasFile(target + "/package.json");

var configs = {
  nyg: {
    configPath: path.join(__dirname, '../', 'nyg-cfg.json')
  },
  pkg: {
    configPath: target + '/package.json'
  },
  npm: {},
  git: {}
};

var modulePrompts = [
  {
    'name': 'location'
    , 'message': 'Where would you like to put the module?'
    , 'default': path.basename(target)
  },
  {
    'name': 'name'
    , 'message': 'Module name:'
    , 'default': path.basename(target)
  },
  {
    'name': 'description'
    , 'message': 'Module description:'
  },
  {
    'name': 'tags'
    , 'message': 'Module tags:'
  },
  {
    'name': 'stability'
    , 'type': 'list'
    , 'message': 'Module stability:'
    , 'default': 'experimental'
    , 'choices': [
      'deprecated'
      , 'experimental'
      , 'unstable'
      , 'stable'
      , 'frozen'
      , 'locked'
    ]
  }
];

function getNygConfig() {
  return loadJson(configs.nyg.configPath)
    .then(function (data) {
      configs.nyg = xtend(configs.nyg, data);
      return configs;
    })
    .catch(function (err) {
      'use strict';
      console.warn(chalk.bgYellow("WARN"), chalk.magenta("could not open " + configs.nyg.configPath));
      console.warn(chalk.dim(err.message));
    })
}

function getPkgJson() {
  if(!hasPkgJson) return {};
  return loadJson(configs.pkg.configPath)
    .then(function (data) {
      configs.pkg = xtend(configs.pkg, data);
      return configs;
    })
    .catch(function (err) {
      'use strict';
      console.warn(chalk.bgYellow("WARN"), chalk.magenta("could not open " + configs.pkg.configPath));
      console.warn(chalk.dim(err.message));
    })
}

function getNpmConfig() {
  return npmConfLoad({})
    .then(function (config) {
      // configs.npm = xtend(configs.npm, data);
      // console.log('conf: ',conf);
      var data = {
        user: {
          name: config.get('init.author.name')
          , site: config.get('init.author.url') || ''
          , email: config.get('init.author.email')
          , github: config.get('init.author.github')
          , username: config.get('username')
        }
      };

      if (typeof argv.u === 'string') {
        data.org = {name: argv.u, github: argv.u};
        console.log(chalk.green('Creating module under organization ' + chalk.bold(data.org.name)))
      } else if (argv.u) {
        return done('--user specified, but without an organization!')
      }

      if (!data.user.name) return bail('npm config set init.author.name "Your Name"');
      if (!data.user.email) return bail('npm config set init.author.email "me@example.com"');
      if (!data.user.github) return bail('npm config set init.author.github "your-github-handle"');

      //default org to user
      if (!data.org) {
        data.org = {
          name: data.user.name,
          github: data.user.github
        }
      }

      if (!data.user.url) {
        data.user.url = 'https://github.com/' + data.user.github
      }

      configs.npm = xtend(configs.npm, data);

      return configs;
    })
    .catch(function (err) {
      'use strict';
      console.warn(chalk.bgYellow("WARN"), chalk.magenta("could not open npm config"));
      console.warn(chalk.dim(err.message));
    })
}

module.exports = function(opts) {
  if (opts.prompts) {
    modulePrompts = modulePrompts.concat(opts.prompts);
  }

  Promise.all([getNygConfig(), getPkgJson(), getNpmConfig()])
  .then(function (data) {
    if(configs.nyg.useDefaultDir){
      modulePrompts[0].default = configs.nyg.defaultDir;
    }else if(!configs.nyg.useDefaultDir && hasPkgJson){
      modulePrompts[0].default = process.cwd().replace(path.basename(process.cwd()), '');
    }else{
      modulePrompts[0].default = process.cwd();
    }
    startPrompts(configs, opts);
  })
};

function startPrompts(data, opts) {
  var extraGlobs = opts.globs;
  var cb = opts.callback;
  var isPostPublish = opts.isPostPublish;
  var globs;

  if (isPostPublish) {
    var currPath = process.cwd();
    globs = [
      {base: '../templates/', glob: '*'},
      {base: currPath, glob: '*', output: '/'}
    ];
    globs.forEach((g) => g.base = path.relative(__dirname, g.base));
  } else {
    globs = [
      {base: '../templates/', glob: '*'},
      {base: '../templates/test', glob: '*', output: '/test'}
    ];
  }

  if (extraGlobs) {
    // assign relative path to base
    extraGlobs.forEach((g) => g.base = path.relative(__dirname, g.base));
    globs = globs.concat(extraGlobs);
  }

  var gen = nyg(modulePrompts, globs)
    .on('postprompt', function () {
      var done = gen.async();

      if (isPostPublish) {
        gen.config.set('type', opts.type);
      }

      configs.outputDir = path.join(gen.config.get('location'), gen.config.get('name'));

      // check if directory exists
      fs.access(configs.outputDir, function(err) {
        if (!err) {
          var contents = fs.readdirSync(configs.outputDir);
          contents.forEach(function(item, index) {
            (item.indexOf('.') === 0) && contents.splice(index, 1);
          });
          if (contents.length) {
            console.log(' ');
            console.warn(chalk.bgRed('ERROR:'), chalk.red(`Directory ${configs.outputDir} already exists and is not empty.`));
            console.log(' ');

            gen.end();
          } else {
            gen.chdir(configs.outputDir);
            done();
          }

        } else {
          fs.mkdir(configs.outputDir, function() {
            console.log(' ');
            console.log(chalk.bgYellow('CREATED DIRECTORY:'), chalk.yellow(configs.outputDir));
            console.log(' ');

            gen.chdir(configs.outputDir);
            done();
          })
        }

        gen.config.set('name', dequote(gen.config.get('name')));
        gen.config.set('testDescription', escape(gen.config.get('description')).replace(/\\"+/g, '\"'));
        gen.config.set('description', dequote(gen.config.get('description')));
        gen.config.set('varName', varName(gen.config.get('name')));
        gen.config.set('tags', JSON.stringify(gen.config.get('tags').split(' ').map(function (str) {
          return dequote(str).trim();
        }).filter(Boolean), null, 2));
        gen.config.set('devDependencies', '{\n    "tape": "*"\n  }');
        gen.config.set('user', {
          "name": configs.npm.user.name,
          "email": configs.npm.user.email,
          "url": configs.npm.user.email
        });
        gen.config.set('org', configs.npm.org);
      });
    })
    .on('postinstall', function () {
      open(configs.outputDir);
      cb && cb(configs.outputDir);

      var cmd = 'ghrepo --color';
      var child = spawn(cmd, {cwd: configs.outputDir, stdio: 'inherit' });
      child.on('exit', function (err) {
        if (err === 0) {
          var location = gen.config.get('location');
          gen.prompt({
            type: "confirm",
            name: "doInstall",
            message: "Would you like to install this module in an existing project?",
            default: true
          },function(data){
            if(data.doInstall){
              gen.prompt({
                'name': 'installLocation'
                , 'message': 'Where would you like to install it?'  //where would you like the module to live?
                , 'default': process.cwd()
              }, function(answers){
                var cmd = 'npm install git+'+configs.npm.user.url+'/'+gen.config.get('name')+' --save';
                var installProc = spawn(cmd, {cwd: answers.installLocation});
                installProc.on('exit', function (err) {
                  process.exit(0);
                });
                installProc.stdout.pipe(process.stdout);
                installProc.stderr.pipe(process.stderr);
                process.stdin.pipe(installProc.stdin);
              });
            }else{
              process.exit(0);
            }
          });

        } else {
          console.log('git command failed');
          process.exit(1)
        }
      });
      /*child.stdout.pipe(process.stdout);
      child.stderr.pipe(process.stderr);
      process.stdin.pipe(child.stdin);*/
    })
    .run();
}

function bail(cmd) {
  console.log('');
  console.log('Missing configuration option, please run the following using your own value:');
  console.log('');
  console.log('  > ' + cmd);
  console.log('');
}

function dequote(str) {
  return str.replace(/\"+/g, '\\"');
}<|endoftext|>


<commit_before>/**
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
*/

var child_process = require('child_process');
var fs = require('fs');
var path = require('path');
var Q = require('q');
var which = require('which');
var iswin32 = 'win32' === process.platform;

function extend(dst, src) {
    for (var k in src) {
        dst[k] = src[k];
    }
    return dst;
}

// On Windows, spawn() for batch files requires absolute path & having the extension.
function resolveWindowsExe(cmd) {
    var winExtensions = ['.exe', '.cmd', '.bat', '.js', '.vbs'];
    function isValidExe(c) {
        return winExtensions.indexOf(path.extname(c)) !== -1 && fs.existsSync(c);
    }
    if (isValidExe(cmd)) {
        return cmd;
    }
    try {
        cmd = which.sync(cmd);
    } catch (e) {
        // just ignore which's whining
    }
    if (!isValidExe(cmd)) {
        winExtensions.some(function(ext) {
            if (fs.existsSync(cmd + ext)) {
                cmd = cmd + ext;
                return true;
            }
        });
    }
    return cmd;
}

function maybeQuote(a) {
    if (a.indexOf(' ') != -1) {
        a = '"' + a + '"';
    }
    return a;
}

/**
 * A windows-compatible spawn method. Succeeds for child exit code === 0.
 * @param {string} cmd
 * @param {string[]} [args]
 * @param {opts} [opts]
 * @param {function} [callback] - standard Node callback, omit if you want to use a promise.
 * @returns {Q.promise|undefined} - returns a promise or undefined if a callback is passed.
 *
 * @typedef {Object} opts
 * @property {boolean} [printCommand=false] - Whether to log the command
 * @property {string} stdio -
 *     'default' is to capture output and returning it as a string to success (same as exec).
 *     'ignore' means don't bother capturing it.
 *     'inherit' means pipe the input & output. This is required for anything that prompts.
 * @property {object} env - Map of extra environment variables.
 * @property {string} cwd - Working directory for the command.
 */
exports.spawn = function(cmd, args, opts, callback) {
    var spawnOpts = {}
        ,d = Q.defer()
        ,callback = Array.prototype.slice.call(arguments, -1)[0]
    ;

    // if we have a callback we'll use that. Else we'll work with a Q.promise
    callback = 'function' === typeof callback ? callback : null;
    // if we got opts but no args
    if (!(args instanceof Array) && typeof args === 'object') {
        opts = args; args = [];
    }
    args = args || [];
    opts = opts || {};

    if (iswin32) {
        cmd = resolveWindowsExe(cmd);
        // If we couldn't find the file, likely we'll end up failing,
        // but for things like "del", cmd will do the trick.
        if (path.extname(cmd) != '.exe' && cmd.indexOf(' ') != -1) {
            // We need to use /s to ensure that spaces are parsed properly with cmd spawned content
            args = [['/s', '/c', '"'+[cmd].concat(args).map(function(a){if (/^[^"].* .*[^"]/.test(a)) return '"'+a+'"'; return a;}).join(" ")+'"'].join(" ")];
            cmd = 'cmd';
            spawnOpts.windowsVerbatimArguments = true;
        } else if (!fs.existsSync(cmd)) {
            // We need to use /s to ensure that spaces are parsed properly with cmd spawned content
            args = ['/s', '/c', cmd].concat(args);
        }
    }

    if (opts.stdio == 'ignore') {
        spawnOpts.stdio = 'ignore';
    } else if (opts.stdio == 'inherit') {
        spawnOpts.stdio = 'inherit';
    }
    if (opts.cwd) {
        spawnOpts.cwd = opts.cwd;
    }
    if (opts.env) {
        spawnOpts.env = extend(extend({}, process.env), opts.env);
    }

    if (opts.printCommand) {
        console.log('Running command: ' + maybeQuote(cmd) + ' ' + args.map(maybeQuote).join(' '));
    }

    var child = child_process.spawn(cmd, args, spawnOpts);
    var capturedOut = '';
    var capturedErr = '';

    if (child.stdout) {
        child.stdout.setEncoding('utf8');
        child.stdout.on('data', function(data) {
            capturedOut += data;
        });
    }
    if (child.stderr) {
        child.stderr.setEncoding('utf8');
        child.stderr.on('data', function(data) {
            capturedErr += data;
        });
    }

    child.on('close', whenDone);
    child.on('error', whenDone);

    function whenDone(arg) {
        child.removeListener('close', whenDone);
        child.removeListener('error', whenDone);
        var code = typeof arg == 'number' ? arg : arg && arg.code;

        if (code === 0) {
            d.resolve(capturedOut.trim());
        } else {
            var errMsg = cmd + ': Command failed with exit code ' + code;
            if (capturedErr) {
                errMsg += ' Error output:\n' + capturedErr.trim();
            }
            var err = new Error(errMsg);
            err.code = code;
            d.reject(err);
        }
    }

    return d.promise.nodeify(callback);
};
<commit_msg>Convert file extension to lowercase before doing comparisons.<commit_after>/**
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
*/

var child_process = require('child_process');
var fs = require('fs');
var path = require('path');
var Q = require('q');
var which = require('which');
var iswin32 = 'win32' === process.platform;
var log = console.log;

function extend(dst, src) {
    for (var k in src) {
        dst[k] = src[k];
    }
    return dst;
}

// On Windows, spawn() for batch files requires absolute path & having the extension.
function resolveWindowsExe(cmd) {
    var winExtensions = ['.exe', '.cmd', '.bat', '.js', '.vbs'];
    function isValidExe(c) {
        return winExtensions.indexOf(path.extname(c).toLowerCase()) !== -1 && fs.existsSync(c);
    }
    if (isValidExe(cmd)) {
        return cmd;
    }
    try {
        cmd = which.sync(cmd);
    } catch (e) {
        // just ignore which's whining
    }
    if (!isValidExe(cmd)) {
        winExtensions.some(function(ext) {
            if (fs.existsSync(cmd + ext)) {
                cmd = cmd + ext;
                return true;
            }
        });
    }
    return cmd;
}

function maybeQuote(a) {
    if (a.indexOf(' ') != -1) {
        a = '"' + a + '"';
    }
    return a;
}

/**
 * A windows-compatible spawn method. Succeeds for child exit code === 0.
 * @param {string} cmd
 * @param {string[]} [args]
 * @param {opts} [opts]
 * @param {function} [callback] - standard Node callback, omit if you want to use a promise.
 * @returns {Q.promise|undefined} - returns a promise or undefined if a callback is passed.
 *
 * @typedef {Object} opts
 * @property {boolean} [printCommand=false] - Whether to log the command
 * @property {string} stdio -
 *     'default' is to capture output and returning it as a string to success (same as exec).
 *     'ignore' means don't bother capturing it.
 *     'inherit' means pipe the input & output. This is required for anything that prompts.
 * @property {object} env - Map of extra environment variables.
 * @property {string} cwd - Working directory for the command.
 */
exports.spawn = function(cmd, args, opts, callback) {
    var spawnOpts = {}
        ,d = Q.defer()
        ,callback = Array.prototype.slice.call(arguments, -1)[0]
    ;

    // if we have a callback we'll use that. Else we'll work with a Q.promise
    callback = 'function' === typeof callback ? callback : null;
    // if we got opts but no args
    if (!(args instanceof Array) && typeof args === 'object') {
        opts = args; args = [];
    }
    args = args || [];
    opts = opts || {};

    if (iswin32) {
        cmd = resolveWindowsExe(cmd);
        // If we couldn't find the file, likely we'll end up failing,
        // but for things like "del", cmd will do the trick.
        if (path.extname(cmd).toLowerCase() !== '.exe' && cmd.indexOf(' ') != -1) {
            // We need to use /s to ensure that spaces are parsed properly with cmd spawned content
            args = [['/s', '/c', '"'+[cmd].concat(args).map(function(a){if (/^[^"].* .*[^"]/.test(a)) return '"'+a+'"'; return a;}).join(" ")+'"'].join(" ")];
            cmd = 'cmd';
            spawnOpts.windowsVerbatimArguments = true;
        } else if (!fs.existsSync(cmd)) {
            // We need to use /s to ensure that spaces are parsed properly with cmd spawned content
            args = ['/s', '/c', cmd].concat(args);
        }
    }

    if (opts.stdio == 'ignore') {
        spawnOpts.stdio = 'ignore';
    } else if (opts.stdio == 'inherit') {
        spawnOpts.stdio = 'inherit';
    }
    if (opts.cwd) {
        spawnOpts.cwd = opts.cwd;
    }
    if (opts.env) {
        spawnOpts.env = extend(extend({}, process.env), opts.env);
    }

    if (opts.printCommand) {
        console.log('Running command: ' + maybeQuote(cmd) + ' ' + args.map(maybeQuote).join(' '));
    }

    var child = child_process.spawn(cmd, args, spawnOpts);
    var capturedOut = '';
    var capturedErr = '';

    if (child.stdout) {
        child.stdout.setEncoding('utf8');
        child.stdout.on('data', function(data) {
            capturedOut += data;
        });
    }
    if (child.stderr) {
        child.stderr.setEncoding('utf8');
        child.stderr.on('data', function(data) {
            capturedErr += data;
        });
    }

    child.on('close', whenDone);
    child.on('error', whenDone);

    function whenDone(arg) {
        child.removeListener('close', whenDone);
        child.removeListener('error', whenDone);
        var code = typeof arg == 'number' ? arg : arg && arg.code;

        if (code === 0) {
            d.resolve(capturedOut.trim());
        } else {
            var errMsg = cmd + ': Command failed with exit code ' + code;
            if (capturedErr) {
                errMsg += ' Error output:\n' + capturedErr.trim();
            }
            var err = new Error(errMsg);
            err.code = code;
            d.reject(err);
        }
    }

    return d.promise.nodeify(callback);
};
<|endoftext|>


<commit_before>'use strict';

(function () {

  // Stored options
  var vendorPrefixes, obfuscate = true, minify = false, optionsSet = false;
  var existingClassNames = [];
  var shouldNotHaveValueSuffix = /^(opacity)$/;
  var whitespace = /[\n\r\s]/g;
  var indent = '  ';
  var messagePrefix = 'ReactStyleSheets: ';

  var headTag = document.getElementsByTagName('head')[0];

  if (!headTag) {
    throw new Error(
      messagePrefix + 'Could not locate head tag. Ensure your javascript is included after the closing head tag.'
    );
  }

  var styleTag = document.createElement('style');
  styleTag.setAttribute('type', 'text/css');
  headTag.appendChild(styleTag);

  var doubleColonStyles = [
    'before',
    'after',
    'firstLetter',
    'firstLine',
    'selection'
  ];

  var nestedStyles = [
    'active',
    'after',
    'before',
    'checked',
    'disabled',
    'empty',
    'enabled',
    'firstChild',
    'firstLetter',
    'firstLine',
    'firstOfType',
    'focus',
    'hover',
    'inRange',
    'invalid',
    // 'lang', // Takes arguments
    'lastChild',
    'lastOfType',
    'link',
    // 'not', // Takes arguments
    // 'nthChild', // Takes arguments
    // 'nthLastChild', // Takes arguments
    // 'nthLastOfType', // Takes arguments
    // 'nthOfType', // Takes arguments
    'onlyOfType',
    'onlyChild',
    'optional',
    'outOfRange',
    'readOnly',
    'readWrite',
    'required',
    'root',
    'selection',
    'target',
    'valid',
    'visited'
  ];

  function warn (message) {
    if (typeof console !== 'undefined' && typeof console.warn === 'function') {
      console.warn(messagePrefix + message);
    }
  }

  function toSpinalCase (value) {
    return value.replace(/(^|[a-z])([A-Z])/g, '$1-$2').toLowerCase();
  }

  function formatValue (key, value) {
    if (Array.isArray(value)) {
      return value.map(formatValue.bind(null, key)).join(' ');
    } else if (typeof value === 'number') {
      if (value === 0 || shouldNotHaveValueSuffix.test(key)) {
        return value;
      }

      return value + 'px';
    }

    return value;
  }

  function createStyles (tag, style) {
    var prefix = '\n' + tag + ' {\n';
    var nested = '';

    if (tag.indexOf('-') >= 0) {
      throw new Error(
        messagePrefix + 'Found "-" in a tag or class name. Tag and class names must be camelcase.'
      );
    }

    for (var key in style) {
      if (key.indexOf('-') >= 0) {
        throw new Error(
          messagePrefix + 'Found "-" in a style property name. Style property names must be defined in camelcase.'
        );
      }

      var value = style[key];

      // Vendor prefixes
      if (key in vendorPrefixes) {
        for (var i = 0; i < vendorPrefixes[key].length; i += 1) {
          var vendorKey = '-' + vendorPrefixes[key][i] + '-' + key;
          prefix += indent + toSpinalCase(vendorKey) + ': ' + formatValue(vendorKey, value) + ';\n';
        }

        prefix += indent + toSpinalCase(key) + ': ' + formatValue(key, value) + ';\n';
      // Nested styles
      } else if (nestedStyles.indexOf(key) >= 0) {
        if (typeof value !== 'object') {
          throw new Error(messagePrefix + 'Nested styles such as hover must be an object.');
        }

        var colon = doubleColonStyles.indexOf(key) >= 0 ? '::' : ':';
        nested += createStyles(tag + colon + key, value);
      // Sub styles e.g. {margin: {left, right}}
      } else if (typeof value === 'object' && !Array.isArray(value)) {
        for (var subKey in value) {
          var keySubKey = key + '-' + subKey;
          prefix += indent + toSpinalCase(keySubKey) + ': ' + formatValue(keySubKey, value[subKey]) + ';\n';
        }
      // Basic values & arrays
      } else {
        prefix += indent + toSpinalCase(key) + ': ' + formatValue(key, value) + ';\n';
      }
    }

    return prefix + '}\n' + nested;
  }

  function generateRandomString (length) {
    var concat = '';

    for (var i = 0; i < length; i += 1) {
      concat += String.fromCharCode(97 + Math.floor(Math.random() * 26));
    }

    return concat;
  }

  function generateClassName () {
    var obfuscatedClassName = generateRandomString(5);

    while (existingClassNames.indexOf(obfuscatedClassName) >= 0) {
      obfuscatedClassName = generateRandomString(5);
    }

    return obfuscatedClassName;
  }

  function removeWhitespace (value) {
    return minify ? value.replace(whitespace, '') : value;
  }

  var ReactStyleSheets = {
    setOptions: function (options) {
      if (optionsSet) {
        warn('You tried to set options more than once. This is not advised.');
      }

      if (typeof options !== 'object') {
        throw new Error(messagePrefix + 'Options must be an object.');
      }

      if (typeof options.vendorPrefixes !== 'undefined') {
        if (typeof options.vendorPrefixes !== 'object' || Array.isArray(options.vendorPrefixes)) {
          throw new Error(
            messagePrefix +
            'vendorPrefixes must be an object with style property names as keys, ' +
            'and arrays of prefixes as values.'
          );
        } else {
          vendorPrefixes = options.vendorPrefixes;
        }
      }

      if (typeof options.obfuscate !== 'undefined') {
        obfuscate = options.obfuscate;
      }

      if (typeof options.minify !== 'undefined') {
        minify = options.minify;
      }

      optionsSet = true;
    },
    createTagStyleString: function (styles) {
      var concat = '';

      for (var tag in styles) {
        concat += createStyles(tag, styles[tag]);
      }

      return removeWhitespace(concat);
    },
    createClassStyleString: function (styles) {
      var concat = '';

      for (var className in styles) {
        var obfuscatedClassName = obfuscate ? generateClassName() : className;

        concat += createStyles('.' + className, styles[obfuscatedClassName]);

        existingClassNames.push(obfuscatedClassName);
      }

      return removeWhitespace(concat);
    },
    createGlobalTagStyles: function (styles) {
      var styleString = ReactStyleSheets.createTagStyleString(styles);
      styleTag.innerHTML = styleTag.innerHTML + removeWhitespace(styleString);
    },
    createUniqueClassStyles: function (styles) {
      var classNames = {};
      var concat = '';

      for (var className in styles) {
        var obfuscatedClassName = obfuscate ? generateClassName() : className;

        concat += createStyles('.' + obfuscatedClassName, styles[className]);

        classNames[className] = obfuscatedClassName;
        existingClassNames.push(obfuscatedClassName);
      }

      styleTag.innerHTML = styleTag.innerHTML + removeWhitespace(concat);

      return classNames;
    }
  };

  module.exports = ReactStyleSheets;

})();
<commit_msg>Include original className in obfuscation<commit_after>'use strict';

(function () {

  // Stored options
  var vendorPrefixes, obfuscate = true, minify = false, optionsSet = false;
  var existingClassNames = [];
  var shouldNotHaveValueSuffix = /^(opacity)$/;
  var whitespace = /[\n\r\s]/g;
  var indent = '  ';
  var messagePrefix = 'ReactStyleSheets: ';

  var headTag = document.getElementsByTagName('head')[0];

  if (!headTag) {
    throw new Error(
      messagePrefix + 'Could not locate head tag. Ensure your javascript is included after the closing head tag.'
    );
  }

  var styleTag = document.createElement('style');
  styleTag.setAttribute('type', 'text/css');
  headTag.appendChild(styleTag);

  var doubleColonStyles = [
    'before',
    'after',
    'firstLetter',
    'firstLine',
    'selection'
  ];

  var nestedStyles = [
    'active',
    'after',
    'before',
    'checked',
    'disabled',
    'empty',
    'enabled',
    'firstChild',
    'firstLetter',
    'firstLine',
    'firstOfType',
    'focus',
    'hover',
    'inRange',
    'invalid',
    // 'lang', // Takes arguments
    'lastChild',
    'lastOfType',
    'link',
    // 'not', // Takes arguments
    // 'nthChild', // Takes arguments
    // 'nthLastChild', // Takes arguments
    // 'nthLastOfType', // Takes arguments
    // 'nthOfType', // Takes arguments
    'onlyOfType',
    'onlyChild',
    'optional',
    'outOfRange',
    'readOnly',
    'readWrite',
    'required',
    'root',
    'selection',
    'target',
    'valid',
    'visited'
  ];

  function warn (message) {
    if (typeof console !== 'undefined' && typeof console.warn === 'function') {
      console.warn(messagePrefix + message);
    }
  }

  function toSpinalCase (value) {
    return value.replace(/(^|[a-z])([A-Z])/g, '$1-$2').toLowerCase();
  }

  function formatValue (key, value) {
    if (Array.isArray(value)) {
      return value.map(formatValue.bind(null, key)).join(' ');
    } else if (typeof value === 'number') {
      if (value === 0 || shouldNotHaveValueSuffix.test(key)) {
        return value;
      }

      return value + 'px';
    }

    return value;
  }

  function createStyles (tag, style) {
    var prefix = '\n' + tag + ' {\n';
    var nested = '';

    if (tag.indexOf('-') >= 0) {
      throw new Error(
        messagePrefix + 'Found "-" in a tag or class name. Tag and class names must be camelcase.'
      );
    }

    for (var key in style) {
      if (key.indexOf('-') >= 0) {
        throw new Error(
          messagePrefix + 'Found "-" in a style property name. Style property names must be defined in camelcase.'
        );
      }

      var value = style[key];

      // Vendor prefixes
      if (key in vendorPrefixes) {
        for (var i = 0; i < vendorPrefixes[key].length; i += 1) {
          var vendorKey = '-' + vendorPrefixes[key][i] + '-' + key;
          prefix += indent + toSpinalCase(vendorKey) + ': ' + formatValue(vendorKey, value) + ';\n';
        }

        prefix += indent + toSpinalCase(key) + ': ' + formatValue(key, value) + ';\n';
      // Nested styles
      } else if (nestedStyles.indexOf(key) >= 0) {
        if (typeof value !== 'object') {
          throw new Error(messagePrefix + 'Nested styles such as hover must be an object.');
        }

        var colon = doubleColonStyles.indexOf(key) >= 0 ? '::' : ':';
        nested += createStyles(tag + colon + key, value);
      // Sub styles e.g. {margin: {left, right}}
      } else if (typeof value === 'object' && !Array.isArray(value)) {
        for (var subKey in value) {
          var keySubKey = key + '-' + subKey;
          prefix += indent + toSpinalCase(keySubKey) + ': ' + formatValue(keySubKey, value[subKey]) + ';\n';
        }
      // Basic values & arrays
      } else {
        prefix += indent + toSpinalCase(key) + ': ' + formatValue(key, value) + ';\n';
      }
    }

    return prefix + '}\n' + nested;
  }

  function generateRandomString (length) {
    var concat = '';

    for (var i = 0; i < length; i += 1) {
      concat += String.fromCharCode(97 + Math.floor(Math.random() * 26));
    }

    return concat;
  }

  function generateClassName (className) {
    var obfuscatedClassName = className + '_' + generateRandomString(5);

    while (existingClassNames.indexOf(obfuscatedClassName) >= 0) {
      obfuscatedClassName = className + '_' + generateRandomString(5);
    }

    return obfuscatedClassName;
  }

  function removeWhitespace (value) {
    return minify ? value.replace(whitespace, '') : value;
  }

  var ReactStyleSheets = {
    setOptions: function (options) {
      if (optionsSet) {
        warn('You tried to set options more than once. This is not advised.');
      }

      if (typeof options !== 'object') {
        throw new Error(messagePrefix + 'Options must be an object.');
      }

      if (typeof options.vendorPrefixes !== 'undefined') {
        if (typeof options.vendorPrefixes !== 'object' || Array.isArray(options.vendorPrefixes)) {
          throw new Error(
            messagePrefix +
            'vendorPrefixes must be an object with style property names as keys, ' +
            'and arrays of prefixes as values.'
          );
        } else {
          vendorPrefixes = options.vendorPrefixes;
        }
      }

      if (typeof options.obfuscate !== 'undefined') {
        obfuscate = options.obfuscate;
      }

      if (typeof options.minify !== 'undefined') {
        minify = options.minify;
      }

      optionsSet = true;
    },
    createTagStyleString: function (styles) {
      var concat = '';

      for (var tag in styles) {
        concat += createStyles(tag, styles[tag]);
      }

      return removeWhitespace(concat);
    },
    createClassStyleString: function (styles) {
      var concat = '';

      for (var className in styles) {
        var obfuscatedClassName = obfuscate ? generateClassName() : className;

        concat += createStyles('.' + className, styles[obfuscatedClassName]);

        existingClassNames.push(obfuscatedClassName);
      }

      return removeWhitespace(concat);
    },
    createGlobalTagStyles: function (styles) {
      var styleString = ReactStyleSheets.createTagStyleString(styles);
      styleTag.innerHTML = styleTag.innerHTML + removeWhitespace(styleString);
    },
    createUniqueClassStyles: function (styles) {
      var classNames = {};
      var concat = '';

      for (var className in styles) {
        var obfuscatedClassName = obfuscate ? generateClassName(className) : className;

        concat += createStyles('.' + obfuscatedClassName, styles[className]);

        classNames[className] = obfuscatedClassName;
        existingClassNames.push(obfuscatedClassName);
      }

      styleTag.innerHTML = styleTag.innerHTML + removeWhitespace(concat);

      return classNames;
    }
  };

  module.exports = ReactStyleSheets;

})();
<|endoftext|>