<commit_before>#!/usr/bin/env node
var arkjs = require("arkjs");
var crypto = require("crypto");
var figlet = require("figlet");
var colors = require("colors");
var request = require("request");
var vorpal = require("vorpal")();

var server;
var network;

var networks = {
  testnet:{
    nethash:"4befbd4cd1f2f10cbe69ac0b494b5ce070595ed23ee7abd386867c4edcdaf3bd",
    peers:[
      "5.39.9.245:4000",
      "5.39.9.246:4000",
      "5.39.9.247:4000",
      "5.39.9.248:4000",
      "5.39.9.249:4000"
    ]
  }
};

function postTransaction(transaction, cb){
  request(
    {
      url: 'http://'+server+'/peer/transactions',
      headers: {
        nethash: network.nethash,
        version: '1.0.0',
        port:1
      },
      method: 'POST',
      json: true,
      body: {transactions:[transaction]}
    },
    cb
  )
}

vorpal
  .command('connect testnet', 'Connect to testnet')
  .action(function(args, callback) {
		var self = this;
    network=networks.testnet;
    server=network.peers[Math.floor(Math.random()*1000)%network.peers.length];
    request.get('http://'+server+'/api/blocks/getHeight', function(err, response, body){
      self.log("Node: " + server + ", height: " + JSON.parse(body).height);
      self.delimiter('ark testnet>');
      callback();
    });
  });

vorpal
  .command('connect node <url>', 'Connect to a server. For example "connect node 5.39.9.251:4000"')
  .action(function(args, callback) {
		var self = this;
    server=args.url;
    request.get('http://'+server+'/api/blocks/getNethash', function(err, response, body){
      self.log("Connected to network " + JSON.parse(body).nethash);
      self.delimiter('ark '+server+'>');
      callback();
    });
    request.get('http://'+server+'/api/blocks/getHeight', function(err, response, body){
      self.log("Node height ", JSON.parse(body).height);
    });
  });

vorpal
  .command('disconnect', 'Disconnect from server or network')
  .action(function(args, callback) {
		var self = this;
    self.log("Disconnected from "+server);
    self.delimiter('ark>');
    server=null;
    network=null;
    callback();
  });

vorpal
  .command('account status <address>', 'Get account status')
  .action(function(args, callback) {
    var self = this;
    if(!server){
      self.log("please connect to node or network before");
      return callback();
    }
    var address=args.address;
    request.get('http://'+server+'/api/accounts?address='+address, function(err, response, body){
      var a = JSON.parse(body).account;
      for(var i in a){
        if(!a[i] || a[i].length==0) delete a[i];
      }
      request.get('http://'+server+'/api/delegates/get/?publicKey='+a.publicKey, function(err, response, body){
        var body = JSON.parse(body);
        if(body.success){
          var delegate=body.delegate;
          for(var j in delegate){
            a[j]=delegate[j];
          }
        }
        self.log(a);
        callback();
      });
    });
  });

vorpal
  .command('account send <amount> <recipient>', 'Send <amount> ark to <recipient>')
  .action(function(args, callback) {
		var self = this;
    if(!server){
      self.log("please connect to node or network before");
      return callback();
    }
    return this.prompt({
      type: 'password',
      name: 'passphrase',
      message: 'passphrase: ',
    }, function(result){
      if (result.passphrase) {
        var transaction = require("arkjs").transaction.createTransaction(args.recipient, parseInt(args.amount*100000000), null, result.passphrase);
        postTransaction(transaction, function(err, response, body){
          if(body.success){
            self.log(colors.green("Transaction sent successfully with id "+body.transactionIds[0]));
          }
          else{
            self.log(colors.red("Failed to send transaction: "+body.error));
          }
          callback();
        });
      } else {
        self.log('Aborted.');
        callback();
      }
    });
  });

vorpal
  .command('account delegate <username>', 'Register new delegate with <username> ')
  .action(function(args, callback) {
		var self = this;
    if(!server){
      self.log("please connect to node or network before");
      return callback();
    }
    return this.prompt({
      type: 'password',
      name: 'passphrase',
      message: 'passphrase: ',
    }, function(result){
      if (result.passphrase) {
        var transaction = require("arkjs").delegate.createDelegate(result.passphrase, args.username);
        postTransaction(transaction, function(err, response, body){
          if(body.success){
            self.log(colors.green("Transaction sent successfully with id "+body.transactionIds[0]));
          }
          else{
            self.log(colors.red("Failed to send transaction: "+body.error));
          }
          callback();
        });
      } else {
        self.log('Aborted.');
        callback();
      }
    });
  });

vorpal
  .command('account create', 'Generate a new random cold account')
  .action(function(args, callback) {
		var self = this;
    var passphrase = require("bip39").generateMnemonic();
		self.log("Seed    - private:",passphrase);
		self.log("WIF     - private:",require("arkjs").crypto.getKeys(passphrase).toWIF());
		self.log("Address - public :",require("arkjs").crypto.getKeys(passphrase).getAddress());
		callback();
  });

vorpal
  .command('message sign <message>', 'Sign a message')
  .action(function(args, callback) {
		var self = this;
    return this.prompt({
      type: 'password',
      name: 'passphrase',
      message: 'passphrase: ',
    }, function(result){
      if (result.passphrase) {
        var hash = crypto.createHash('sha256');
        hash = hash.update(new Buffer(args.message,"utf-8")).digest();
        self.log("public key: ",require("arkjs").crypto.getKeys(result.passphrase).publicKey);
        self.log("address   : ",require("arkjs").crypto.getKeys(result.passphrase).getAddress());
        self.log("signature : ",require("arkjs").crypto.getKeys(result.passphrase).sign(hash).toDER().toString("hex"));

      } else {
        self.log('Aborted.');
        callback();
      }
    });
  });

vorpal
  .command('message verify <message> <publickey>', 'Verify the <message> signed by the owner of <publickey> (you will be prompted to provide the signature)')
  .action(function(args, callback) {
		var self = this;
    return this.prompt({
      type: 'input',
      name: 'signature',
      message: 'signature: ',
    }, function(result){
      if (result.signature) {
        try{
          var hash = crypto.createHash('sha256');
          hash = hash.update(new Buffer(args.message,"utf-8")).digest();
          var signature = new Buffer(result.signature, "hex");
        	var publickey= new Buffer(args.publickey, "hex");
        	var ecpair = require("arkjs").ECPair.fromPublicKeyBuffer(publickey);
        	var ecsignature = require("arkjs").ECSignature.fromDER(signature);
        	var res = ecpair.verify(hash, ecsignature);
          self.log(res);
        }
        catch(error){
          self.log("Failed: ", error);
        }
        callback();
      } else {
        self.log('Aborted.');
        callback();
      }
    });

  });

vorpal.history('ark-client');

vorpal.log(colors.cyan(figlet.textSync("Ark Client","Slant")));

vorpal
  .delimiter('ark>')
  .show();
<commit_msg>handle case of cold accoutn<commit_after>#!/usr/bin/env node
var arkjs = require("arkjs");
var crypto = require("crypto");
var figlet = require("figlet");
var colors = require("colors");
var request = require("request");
var vorpal = require("vorpal")();

var server;
var network;

var networks = {
  testnet:{
    nethash:"4befbd4cd1f2f10cbe69ac0b494b5ce070595ed23ee7abd386867c4edcdaf3bd",
    peers:[
      "5.39.9.245:4000",
      "5.39.9.246:4000",
      "5.39.9.247:4000",
      "5.39.9.248:4000",
      "5.39.9.249:4000"
    ]
  }
};

function postTransaction(transaction, cb){
  request(
    {
      url: 'http://'+server+'/peer/transactions',
      headers: {
        nethash: network.nethash,
        version: '1.0.0',
        port:1
      },
      method: 'POST',
      json: true,
      body: {transactions:[transaction]}
    },
    cb
  )
}

vorpal
  .command('connect testnet', 'Connect to testnet')
  .action(function(args, callback) {
		var self = this;
    network=networks.testnet;
    server=network.peers[Math.floor(Math.random()*1000)%network.peers.length];
    request.get('http://'+server+'/api/blocks/getHeight', function(err, response, body){
      self.log("Node: " + server + ", height: " + JSON.parse(body).height);
      self.delimiter('ark testnet>');
      callback();
    });
  });

vorpal
  .command('connect node <url>', 'Connect to a server. For example "connect node 5.39.9.251:4000"')
  .action(function(args, callback) {
		var self = this;
    server=args.url;
    request.get('http://'+server+'/api/blocks/getNethash', function(err, response, body){
      self.log("Connected to network " + JSON.parse(body).nethash);
      self.delimiter('ark '+server+'>');
      callback();
    });
    request.get('http://'+server+'/api/blocks/getHeight', function(err, response, body){
      self.log("Node height ", JSON.parse(body).height);
    });
  });

vorpal
  .command('disconnect', 'Disconnect from server or network')
  .action(function(args, callback) {
		var self = this;
    self.log("Disconnected from "+server);
    self.delimiter('ark>');
    server=null;
    network=null;
    callback();
  });

vorpal
  .command('account status <address>', 'Get account status')
  .action(function(args, callback) {
    var self = this;
    if(!server){
      self.log("please connect to node or network before");
      return callback();
    }
    var address=args.address;
    request.get('http://'+server+'/api/accounts?address='+address, function(err, response, body){
      var a = JSON.parse(body).account;
      if(!a){
        self.log("Unknown on the blockchain");
        return callback();
      }
      for(var i in a){
        if(!a[i] || a[i].length==0) delete a[i];
      }
      request.get('http://'+server+'/api/delegates/get/?publicKey='+a.publicKey, function(err, response, body){
        var body = JSON.parse(body);
        if(body.success){
          var delegate=body.delegate;
          for(var j in delegate){
            a[j]=delegate[j];
          }
        }
        self.log(a);
        callback();
      });
    });
  });

vorpal
  .command('account send <amount> <recipient>', 'Send <amount> ark to <recipient>')
  .action(function(args, callback) {
		var self = this;
    if(!server){
      self.log("please connect to node or network before");
      return callback();
    }
    return this.prompt({
      type: 'password',
      name: 'passphrase',
      message: 'passphrase: ',
    }, function(result){
      if (result.passphrase) {
        var transaction = require("arkjs").transaction.createTransaction(args.recipient, parseInt(args.amount*100000000), null, result.passphrase);
        postTransaction(transaction, function(err, response, body){
          if(body.success){
            self.log(colors.green("Transaction sent successfully with id "+body.transactionIds[0]));
          }
          else{
            self.log(colors.red("Failed to send transaction: "+body.error));
          }
          callback();
        });
      } else {
        self.log('Aborted.');
        callback();
      }
    });
  });

vorpal
  .command('account delegate <username>', 'Register new delegate with <username> ')
  .action(function(args, callback) {
		var self = this;
    if(!server){
      self.log("please connect to node or network before");
      return callback();
    }
    return this.prompt({
      type: 'password',
      name: 'passphrase',
      message: 'passphrase: ',
    }, function(result){
      if (result.passphrase) {
        var transaction = require("arkjs").delegate.createDelegate(result.passphrase, args.username);
        postTransaction(transaction, function(err, response, body){
          if(body.success){
            self.log(colors.green("Transaction sent successfully with id "+body.transactionIds[0]));
          }
          else{
            self.log(colors.red("Failed to send transaction: "+body.error));
          }
          callback();
        });
      } else {
        self.log('Aborted.');
        callback();
      }
    });
  });

vorpal
  .command('account create', 'Generate a new random cold account')
  .action(function(args, callback) {
		var self = this;
    var passphrase = require("bip39").generateMnemonic();
		self.log("Seed    - private:",passphrase);
		self.log("WIF     - private:",require("arkjs").crypto.getKeys(passphrase).toWIF());
		self.log("Address - public :",require("arkjs").crypto.getKeys(passphrase).getAddress());
		callback();
  });

vorpal
  .command('message sign <message>', 'Sign a message')
  .action(function(args, callback) {
		var self = this;
    return this.prompt({
      type: 'password',
      name: 'passphrase',
      message: 'passphrase: ',
    }, function(result){
      if (result.passphrase) {
        var hash = crypto.createHash('sha256');
        hash = hash.update(new Buffer(args.message,"utf-8")).digest();
        self.log("public key: ",require("arkjs").crypto.getKeys(result.passphrase).publicKey);
        self.log("address   : ",require("arkjs").crypto.getKeys(result.passphrase).getAddress());
        self.log("signature : ",require("arkjs").crypto.getKeys(result.passphrase).sign(hash).toDER().toString("hex"));

      } else {
        self.log('Aborted.');
        callback();
      }
    });
  });

vorpal
  .command('message verify <message> <publickey>', 'Verify the <message> signed by the owner of <publickey> (you will be prompted to provide the signature)')
  .action(function(args, callback) {
		var self = this;
    return this.prompt({
      type: 'input',
      name: 'signature',
      message: 'signature: ',
    }, function(result){
      if (result.signature) {
        try{
          var hash = crypto.createHash('sha256');
          hash = hash.update(new Buffer(args.message,"utf-8")).digest();
          var signature = new Buffer(result.signature, "hex");
        	var publickey= new Buffer(args.publickey, "hex");
        	var ecpair = require("arkjs").ECPair.fromPublicKeyBuffer(publickey);
        	var ecsignature = require("arkjs").ECSignature.fromDER(signature);
        	var res = ecpair.verify(hash, ecsignature);
          self.log(res);
        }
        catch(error){
          self.log("Failed: ", error);
        }
        callback();
      } else {
        self.log('Aborted.');
        callback();
      }
    });

  });

vorpal.history('ark-client');

vorpal.log(colors.cyan(figlet.textSync("Ark Client","Slant")));

vorpal
  .delimiter('ark>')
  .show();
<|endoftext|>


<commit_before>const R        = require('ramda')
const Bluebird = require('bluebird')
const urarse   = require('urarse')
const assert   = require('assert')
const Status   = require('./lib/status.js')

function run(router, message) {

  return Bluebird.resolve(
    router.route(message.command)( message, Status )
  )
}

function CommandListener(event_source, handler) {

  assert.ok(R.is(Object, event_source), 'event_source is required')

  assert.ok(
    R.is(Function, event_source.listen)
  , 'event_source must have a "listen" function'
  )

  assert.ok(
    R.equals('function', typeof handler)
  , 'handler must be a function'
  )

  return event_source.listen((message) =>
    Bluebird.resolve(handler(message, Status)).then((status) =>
      event_source.ack(message, status))
  )

}

module.exports = CommandListener
<commit_msg>export RabbitMQ event source<commit_after>const R        = require('ramda')
const Bluebird = require('bluebird')
const urarse   = require('urarse')
const assert   = require('assert')
const Status   = require('./lib/status.js')
const RabbitMQ = require('./lib/event-source/rabbitmq.js')

function run(router, message) {

  return Bluebird.resolve(
    router.route(message.command)( message, Status )
  )
}

function CommandListener(event_source, handler) {

  assert.ok(R.is(Object, event_source), 'event_source is required')

  assert.ok(
    R.is(Function, event_source.listen)
  , 'event_source must have a "listen" function'
  )

  assert.ok(
    R.equals('function', typeof handler)
  , 'handler must be a function'
  )

  return event_source.listen((message) =>
    Bluebird.resolve(handler(message, Status)).then((status) =>
      event_source.ack(message, status))
  )

}

CommandListener.EventSource = {
  RabbitMQ
}

module.exports = CommandListener
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013 Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the MIT License.
 * See the accompanying LICENSE file for terms.
 */
/*jshint node:true */
'use strict';

var resolve = require('path').resolve,
    log = require('./lib/log'),
    nopt = require('nopt'),

    options = {'help': Boolean, 'version': Boolean, 'debug': Boolean},
    aliases = {h: '--help', v: '--version', d: '--debug'},
    getapp = require('./lib/readpkg'),
    getmoj = require('./lib/readpkg-mojito'),
    bundled; // package name map

function getmeta(cwd) {
    var app,
        mojito,
        cli = require('./package'),
        meta = {};

    log.debug('%s v%s at %s', cli.name, cli.version, __dirname);
    meta.cli = {
        name: cli.name,
        binname: Object.keys(cli.bin)[0],
        version: cli.version,
        commands: Object.keys(bundled)
    };

    meta.app = getapp(cwd);

    if (meta.app) {
        meta.mojito = getmoj(cwd);
    }
    return meta;
}

function altcmd(opts) {
    var cmd;
    if (opts.version) {
        cmd = 'version';
    } else if (opts.help) {
        cmd = 'help';
    } else {
        log.error('No command...');
        cmd = 'help';
    }
    return cmd;
}

function load(pathname) {
    var mod;
    try {
        mod = require(pathname);
    } catch(err) {
        log.debug('unable to require %s', pathname);
    }
    return mod;
}

function exec(cmd, args, opts, meta, cb) {
    var mod,
        mojito_cmds = meta.mojito && meta.mojito.commands;

    if (bundled.hasOwnProperty(cmd)) {
        log.debug('runnning bundled command %s', bundled[cmd]);
        mod = load(bundled[cmd]);
        mod(args, opts, meta, cb);

    } else if (mojito_cmds && mojito_cmds.indexOf(cmd)) {
        log.debug('runnning legacy mojito command %s', cmd);
        mod = load(resolve(mojito_cmds.path, cmd));
        mod.run(args, opts, cb);

    } else {
        log.error('Unable to execute command %s', cmd);
    }
}

function main(argv, cwd, cb) {
    var opts = nopt(options, aliases, argv, 0),
        args = opts.argv.remain,
        cmd = (args.shift() || '').toLowerCase();

    if (opts.debug) {
        log.level = 'debug';
    }

    // treat lone --help and --version flags like commands
    if (!cmd) {
        cmd = altcmd(opts);
    }

    log.debug('cmd: %s, opts: %j', cmd, opts);
    exec(cmd, args, opts, getmeta(cwd), cb);
    return cmd;
}

bundled = {
    'create': 'mojito-create',
    'help': './commands/help',
    'info': './commands/info',
    'version': './commands/version'
};

module.exports = main;
module.exports.log = log;
module.exports.load = load;
module.exports.getmeta = getmeta;
<commit_msg>rm unused<commit_after>/**
 * Copyright (c) 2013 Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the MIT License.
 * See the accompanying LICENSE file for terms.
 */
/*jshint node:true */
'use strict';

var resolve = require('path').resolve,
    log = require('./lib/log'),
    nopt = require('nopt'),

    options = {'help': Boolean, 'version': Boolean, 'debug': Boolean},
    aliases = {h: '--help', v: '--version', d: '--debug'},
    getapp = require('./lib/readpkg'),
    getmoj = require('./lib/readpkg-mojito'),
    bundled; // package name map

function getmeta(cwd) {
    var cli = require('./package'),
        meta = {};

    log.debug('%s v%s at %s', cli.name, cli.version, __dirname);
    meta.cli = {
        name: cli.name,
        binname: Object.keys(cli.bin)[0],
        version: cli.version,
        commands: Object.keys(bundled)
    };

    meta.app = getapp(cwd);

    if (meta.app) {
        meta.mojito = getmoj(cwd);
    }
    return meta;
}

function altcmd(opts) {
    var cmd;
    if (opts.version) {
        cmd = 'version';
    } else if (opts.help) {
        cmd = 'help';
    } else {
        log.error('No command...');
        cmd = 'help';
    }
    return cmd;
}

function load(pathname) {
    var mod;
    try {
        mod = require(pathname);
    } catch(err) {
        log.debug('unable to require %s', pathname);
    }
    return mod;
}

function exec(cmd, args, opts, meta, cb) {
    var mod,
        mojito_cmds = meta.mojito && meta.mojito.commands;

    if (bundled.hasOwnProperty(cmd)) {
        log.debug('runnning bundled command %s', bundled[cmd]);
        mod = load(bundled[cmd]);
        mod(args, opts, meta, cb);

    } else if (mojito_cmds && mojito_cmds.indexOf(cmd)) {
        log.debug('runnning legacy mojito command %s', cmd);
        mod = load(resolve(mojito_cmds.path, cmd));
        mod.run(args, opts, cb);

    } else {
        log.error('Unable to execute command %s', cmd);
    }
}

function main(argv, cwd, cb) {
    var opts = nopt(options, aliases, argv, 0),
        args = opts.argv.remain,
        cmd = (args.shift() || '').toLowerCase();

    if (opts.debug) {
        log.level = 'debug';
    }

    // treat lone --help and --version flags like commands
    if (!cmd) {
        cmd = altcmd(opts);
    }

    log.debug('cmd: %s, opts: %j', cmd, opts);
    exec(cmd, args, opts, getmeta(cwd), cb);
    return cmd;
}

bundled = {
    'create': 'mojito-create',
    'help': './commands/help',
    'info': './commands/info',
    'version': './commands/version'
};

module.exports = main;
module.exports.log = log;
module.exports.load = load;
module.exports.getmeta = getmeta;
<|endoftext|>


<commit_before>var gutil   = require("gulp-util");
var through = require("through2");
var markdox = require("markdox");

gulpError = function(message) {
	return new gutil.PluginError('gulp-markdox', message)
}

module.exports = function (options) {
	"use strict";

  if (!options || typeof options !== 'object') {
    options = {};
  }

	function gulpMarkdox(file, enc, callback) {
		var self = this;
		/*jshint validthis:true*/

		// Do nothing if no contents
		if (file.isNull()) {
			this.push(file);
			return callback();
		}

		// accepting streams is optional
		if (file.isStream()) {
			this.emit("error", gulpError("Streams are not supported"));
			return callback();
		}

		// we only support buffers
		if (file.isBuffer()) {
			markdox.process(file.path, options, function(err, result) {
				if (err) {
					this.emit("error", gulpError(err));
					return callback();
				}
				file.contents = new Buffer(result);
				self.push(file);
				return callback();
			});
		}
	}

	return through.obj(gulpMarkdox);
};
<commit_msg>Update index.js<commit_after>var gutil   = require("gulp-util");
var through = require("through2");
var markdox = require("markdox");

gulpError = function(message) {
	return new gutil.PluginError('gulp-markdox', message)
}

module.exports = function (options) {
	"use strict";

  if (!options || typeof options !== 'object') {
    options = {};
  }

	function gulpMarkdox(file, enc, callback) {
		var self = this;
		/*jshint validthis:true*/

		// Do nothing if no contents
		if (file.isNull()) {
			this.push(file);
			return callback();
		}

		// accepting streams is optional
		if (file.isStream()) {
			this.emit("error", gulpError("Streams are not supported"));
			return callback();
		}

		// we only support buffers
		if (file.isBuffer()) {
			markdox.process(file.path, options, function(err, result) {
				if (err) {
					self.emit("error", gulpError(err));
					return callback();
				}
				file.contents = new Buffer(result);
				self.push(file);
				return callback();
			});
		}
	}

	return through.obj(gulpMarkdox);
};
<|endoftext|>


<commit_before>// Module Scope
var mongoose = require('mongoose'),
    extend = require('extend'),
    counterSchema,
    Counter;

// Initialize plugin by creating counter collection in database.
exports.initialize = function (connection) {

    try {
        Counter = connection.model('mongoose-auto-increment');
    } catch (ex) {
        if (ex.name === 'MissingSchemaError') {
            // Create new counter schema.
            counterSchema = new mongoose.Schema({
                model: {
                    type: String,
                    require: true
                },
                field: {
                    type: String,
                    require: true
                },
                count: {
                    type: Number,
                    default: 0
                }
            });

            // Create a unique index using the "field" and "model" fields.
            counterSchema.index({ field: 1, model: 1 }, { unique: true, required: true, index: -1 });

            // Create model using new schema.
            Counter = connection.model('Mongoose-Auto-Increment', counterSchema);
        }
        else
            throw ex;
    }

};

// The function to use when invoking the plugin on a custom schema.
exports.plugin = function (schema, options) {

    // If we don't have reference to the counterSchema or the Counter model then the plugin was most likely not
    // initialized properly so throw an error.
    if (!counterSchema || !Counter) throw new Error("mongoose-auto-increment has not been initialized");

    // Default settings and plugin scope variables.
    var settings = {
            model: null, // The model to configure the plugin for.
            field: '_id', // The field the plugin should track.
            startAt: 0, // The number the count should start at.
            incrementBy: 1 // The number by which to increment the count each time.
        },
        fields = {}, // A hash of fields to add properties to in Mongoose.
        ready = false; // True if the counter collection has been updated and the document is ready to be saved.

    switch (typeof(options)) {
        // If string, the user chose to pass in just the model name.
        case 'string':
            settings.model = options;
            break;
        // If object, the user passed in a hash of options.
        case 'object':
            extend(settings, options);
            break;
    }

    // Add properties for field in schema.
    fields[settings.field] = {
        type: Number,
        unique: true,
        require: true
    };
    schema.add(fields);

    // Find the counter for this model and the relevant field.
    Counter.findOne(
        { model: settings.model, field: settings.field },
        function (err, counter) {
            if (!counter) {
                // If no counter exists then create one and save it.
                counter = new Counter({ model: settings.model, field: settings.field, count: settings.startAt - settings.incrementBy });
                counter.save(function () {
                    ready = true;
                });
            }
            else
                ready = true;
        }
    );

    // Declare a function to get the next counter for the model/schema.
    var nextCount = function (callback) {
        Counter.findOne({
            model: settings.model,
            field: settings.field
        }, function (err, counter) {
            if (err) return callback(err);
            callback(null, counter === null ? settings.startAt : counter.count + settings.incrementBy);
        });
    };
    // Add nextCount as both a method on documents and a static on the schema for convenience.
    schema.method('nextCount', nextCount);
    schema.static('nextCount', nextCount);

    // Declare a function to reset counter at the start value - increment value.
    var resetCount = function (callback) {
        Counter.findOneAndUpdate(
            { model: settings.model, field: settings.field },
            { count: settings.startAt - settings.incrementBy },
            { new: true }, // new: true specifies that the callback should get the updated counter.
            function (err, updatedCounter) {
                if (err) return callback(err);
                callback(null, updatedCounter);
            }
        );
    };
    // Add resetCount as both a method on documents and a static on the schema for convenience.
    schema.method('resetCount', resetCount);
    schema.static('resetCount', resetCount);

    // Every time documents in this schema are saved, run this logic.
    schema.pre('save', function (next) {
        // Get reference to the document being saved.
        var doc = this;

        // If the document already has the field we're interested in and that field is a number OR the user specified
        // that we should increment even on document updates, then run this logic.
        if (typeof(doc[settings.field]) !== 'number') {
            (function save() {
                // If read, run increment logic.
                if (ready) {
                    // Find the counter collection for this model and field and update it.
                    Counter.findOneAndUpdate(
                        { model: settings.model, field: settings.field },
                        { $inc: { count: settings.incrementBy } },
                        { new: true }, // new: true specifies that the callback should get the updated counter.
                        function (err, updatedCounter) {
                            if (err) return next(err);
                            doc[settings.field] = updatedCounter.count;
                            next();
                        }
                    );
                }
                // If not ready then set a 5 millisecond timer and try to save again. It will keep doing this until
                // the counter collection is ready.
                else
                    setTimeout(save, 5);
            })();
        }
        // If the document does not have the field we're interested in or that field isn't a number AND the user did
        // not specify that we should increment on updates, then just continue the save without any increment logic.
        else
            next();
    });
};
<commit_msg>Modified function to do proper calculations. Pull-request author did not realize that the count is incremented before save, not after. Meaning, in order for the first ID to be equal to startAt we must set the initial count to startAt - incrementBy. Then on save the first ID will be the count + incrementBy ( = startAt).<commit_after>// Module Scope
var mongoose = require('mongoose'),
    extend = require('extend'),
    counterSchema,
    Counter;

// Initialize plugin by creating counter collection in database.
exports.initialize = function (connection) {

    try {
        Counter = connection.model('mongoose-auto-increment');
    } catch (ex) {
        if (ex.name === 'MissingSchemaError') {
            // Create new counter schema.
            counterSchema = new mongoose.Schema({
                model: {
                    type: String,
                    require: true
                },
                field: {
                    type: String,
                    require: true
                },
                count: {
                    type: Number,
                    default: 0
                }
            });

            // Create a unique index using the "field" and "model" fields.
            counterSchema.index({ field: 1, model: 1 }, { unique: true, required: true, index: -1 });

            // Create model using new schema.
            Counter = connection.model('Mongoose-Auto-Increment', counterSchema);
        }
        else
            throw ex;
    }

};

// The function to use when invoking the plugin on a custom schema.
exports.plugin = function (schema, options) {

    // If we don't have reference to the counterSchema or the Counter model then the plugin was most likely not
    // initialized properly so throw an error.
    if (!counterSchema || !Counter) throw new Error("mongoose-auto-increment has not been initialized");

    // Default settings and plugin scope variables.
    var settings = {
            model: null, // The model to configure the plugin for.
            field: '_id', // The field the plugin should track.
            startAt: 0, // The number the count should start at.
            incrementBy: 1 // The number by which to increment the count each time.
        },
        fields = {}, // A hash of fields to add properties to in Mongoose.
        ready = false; // True if the counter collection has been updated and the document is ready to be saved.

    switch (typeof(options)) {
        // If string, the user chose to pass in just the model name.
        case 'string':
            settings.model = options;
            break;
        // If object, the user passed in a hash of options.
        case 'object':
            extend(settings, options);
            break;
    }

    // Add properties for field in schema.
    fields[settings.field] = {
        type: Number,
        unique: true,
        require: true
    };
    schema.add(fields);

    // Find the counter for this model and the relevant field.
    Counter.findOne(
        { model: settings.model, field: settings.field },
        function (err, counter) {
            if (!counter) {
                // If no counter exists then create one and save it.
                counter = new Counter({ model: settings.model, field: settings.field, count: settings.startAt - settings.incrementBy });
                counter.save(function () {
                    ready = true;
                });
            }
            else
                ready = true;
        }
    );

    // Declare a function to get the next counter for the model/schema.
    var nextCount = function (callback) {
        Counter.findOne({
            model: settings.model,
            field: settings.field
        }, function (err, counter) {
            if (err) return callback(err);
            callback(null, counter === null ? settings.startAt : counter.count + settings.incrementBy);
        });
    };
    // Add nextCount as both a method on documents and a static on the schema for convenience.
    schema.method('nextCount', nextCount);
    schema.static('nextCount', nextCount);

    // Declare a function to reset counter at the start value - increment value.
    var resetCount = function (callback) {
        Counter.findOneAndUpdate(
            { model: settings.model, field: settings.field },
            { count: settings.startAt - settings.incrementBy },
            { new: true }, // new: true specifies that the callback should get the updated counter.
            function (err) {
                if (err) return callback(err);
                callback(null, settings.startAt);
            }
        );
    };
    // Add resetCount as both a method on documents and a static on the schema for convenience.
    schema.method('resetCount', resetCount);
    schema.static('resetCount', resetCount);

    // Every time documents in this schema are saved, run this logic.
    schema.pre('save', function (next) {
        // Get reference to the document being saved.
        var doc = this;

        // If the document already has the field we're interested in and that field is a number OR the user specified
        // that we should increment even on document updates, then run this logic.
        if (typeof(doc[settings.field]) !== 'number') {
            (function save() {
                // If read, run increment logic.
                if (ready) {
                    // Find the counter collection for this model and field and update it.
                    Counter.findOneAndUpdate(
                        { model: settings.model, field: settings.field },
                        { $inc: { count: settings.incrementBy } },
                        { new: true }, // new: true specifies that the callback should get the updated counter.
                        function (err, updatedCounter) {
                            if (err) return next(err);
                            doc[settings.field] = updatedCounter.count;
                            next();
                        }
                    );
                }
                // If not ready then set a 5 millisecond timer and try to save again. It will keep doing this until
                // the counter collection is ready.
                else
                    setTimeout(save, 5);
            })();
        }
        // If the document does not have the field we're interested in or that field isn't a number AND the user did
        // not specify that we should increment on updates, then just continue the save without any increment logic.
        else
            next();
    });
};
<|endoftext|>


<commit_before>//Required modules
var sparkFunctions = require('./spark-functions.js');

//Morse code array
var charCodes=new Array(37);

charCodes["a"]="._";
charCodes["b"]="_...";
charCodes["c"]="_._.";
charCodes["d"]="_..";
charCodes["e"]=".";
charCodes["f"]=".._.";
charCodes["g"]="__.";
charCodes["h"]="....";
charCodes["i"]="..";
charCodes["j"]=".___";
charCodes["k"]="_._";
charCodes["l"]="._..";
charCodes["m"]="__";
charCodes["n"]="_.";
charCodes["o"]="___";
charCodes["p"]=".__.";
charCodes["q"]="__._";
charCodes["r"]="._.";
charCodes["s"]="...";
charCodes["t"]="_";
charCodes["u"]=".._";
charCodes["v"]="..._";
charCodes["w"]=".__";
charCodes["x"]="_.._";
charCodes["y"]="_.__";
charCodes["z"]="__..";
charCodes["1"]=".____";
charCodes["2"]="..___";
charCodes["3"]="...__";
charCodes["4"]="...._";
charCodes["5"]=".....";
charCodes["6"]="_....";
charCodes["7"]="__...";
charCodes["8"]="___..";
charCodes["9"]="____.";
charCodes["0"]="_____";
charCodes[" "]= " ";

function convertToMorse(text) {
	console.log("In convertToMorse:" + text);
	for(var i = 0; i < text.length; i++) {
		console.log("Length:" + text.length);
		console.log(text.charAt(i));
		console.log("convertToMorse: " + String(charCodes[text.charAt(i)]));

		//Call dot(), dash() or space() depending on sequence of characters

		for(var j = 0; j < charCodes[text.charAt(i)].length; j++) {
			if(j == ".") {
				sparkFunctions.dot();
				console.log(".");
			}
			else if(j == "_") {
				console.log("-");
				sparkFunctions.dash();
			}
			else if(j == " ") {
				console.log("_");
				sparkFunctions.space();
			}
		}
	}
}

exports.convertToMorse = convertToMorse;<commit_msg>Testing morse conversion<commit_after>//Required modules
var sparkFunctions = require('./spark-functions.js');

//Morse code array
var charCodes=new Array(37);

charCodes["a"]="._";
charCodes["b"]="_...";
charCodes["c"]="_._.";
charCodes["d"]="_..";
charCodes["e"]=".";
charCodes["f"]=".._.";
charCodes["g"]="__.";
charCodes["h"]="....";
charCodes["i"]="..";
charCodes["j"]=".___";
charCodes["k"]="_._";
charCodes["l"]="._..";
charCodes["m"]="__";
charCodes["n"]="_.";
charCodes["o"]="___";
charCodes["p"]=".__.";
charCodes["q"]="__._";
charCodes["r"]="._.";
charCodes["s"]="...";
charCodes["t"]="_";
charCodes["u"]=".._";
charCodes["v"]="..._";
charCodes["w"]=".__";
charCodes["x"]="_.._";
charCodes["y"]="_.__";
charCodes["z"]="__..";
charCodes["1"]=".____";
charCodes["2"]="..___";
charCodes["3"]="...__";
charCodes["4"]="...._";
charCodes["5"]=".....";
charCodes["6"]="_....";
charCodes["7"]="__...";
charCodes["8"]="___..";
charCodes["9"]="____.";
charCodes["0"]="_____";
charCodes[" "]= " ";

function convertToMorse(text) {
	console.log("In convertToMorse:" + text);
	for(var i = 0; i < text.length; i++) {

		//Call dot(), dash() or space() depending on sequence of characters
		letter = text.charAt(i);
		for(var j = 0; j < charCodes[letter].length; j++) {
			code = charCodes[letter].charAt(j)
			console.log(code);
			if(code == ".") {
				sparkFunctions.dot();
				console.log(".");
			}
			else if(code == "_") {
				console.log("-");
				sparkFunctions.dash();
			}
			else if(code == " ") {
				console.log("_");
				sparkFunctions.space();
			}
		}
	}
}

exports.convertToMorse = convertToMorse;<|endoftext|>


<commit_before>'use strict';

// Gotta set a few config variables here since AWS Lambda restricts ENV values
// to a limiting format (like not allowing commas).
const config = {
  TEXT_CHECKIN: '@ NYC Office',
  TEXT_CHECKOUT: ':wave: Heading out, have a good night'
};

const https = require('https');
const url = require('url');

exports.handler = (event, context, callback) => {
  getWeather()
    .then(weather => getMessage(event, weather))
    .then(sendMessage)
    .then(body => callback(null, body))
    .catch(callback);
}

function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min)) + min;
}

function getMessage(event, weather) {
  let message = { username: process.env.USERNAME };

  if (event.clickType === 'SINGLE') {
    message.text = config.TEXT_CHECKIN || 'Checking in';
  } else if (event.clickType === 'DOUBLE') {
    message.text = config.TEXT_CHECKOUT || 'Checking out';
  } else if (event.clickType === 'LONG') {
    const emojis = ['poultry_leg', 'hamburger', 'pizza', 'taco', 'burrito', 'ramen', 'sushi', 'chicken'];
    const emoji = emojis[getRandomInt(0, emojis.length - 1)];
    message.text = `:${emoji}: Grabbing lunch`;
  } else {
    return Promise.reject(Error('Invalid clickType'));
  }

  if (weather && event.clickType !== 'LONG') {
    message.attachments = [{
      fallback: weather.summary,
      fields: [
        {
          title: 'Currently',
          value: `${weather.emoji} ${weather.summary} (${Math.round(weather.apparentTemperature)}°)`,
          short: false
        }
      ],
    }]
  }

  return message;
}

function getWeather() {
  if (!process.env.DARK_SKY_KEY) return Promise.resolve(null);

  const options = {
    hostname: 'api.darksky.net',
    path: `/forecast/${process.env.DARK_SKY_KEY}/${process.env.LATITUDE},${process.env.LONGITUDE}`
  }

  const iconEmoji = {
    "clear-day": ":sunny:",
    "clear-night": ":crescent_moon:",
    "rain": ":umbrella_with_rain_drops:",
    "snow": ":snowflake:",
    "sleet": ":rain_cloud:",
    "wind": ":wind_blowing_face:",
    "fog": ":fog:",
    "cloudy": ":cloud:",
    "partly-cloudy-day": ":partly_sunny:",
    "partly-cloudy-night": ":partly_sunny:"
  };

  return new Promise((resolve, reject) => {
    // res: https://darksky.net/dev/docs/response
    const req = https.request(options, res => {
      let body = '';
      res.setEncoding('utf8');
      res.on('data', chunk => body += chunk);
      res.on('end', () => {
        body = JSON.parse(body);
        resolve({
          summary: body.currently.summary,
          apparentTemperature: body.currently.apparentTemperature,
          emoji: iconEmoji[body.currently.icon]
        });
      });
    });

    req.on('error', reject);
    req.end();
  });
}

function sendMessage(message) {
  const parts = url.parse(process.env.WEBHOOK);
  const options = {
    hostname: parts.host,
    path: parts.path,
    method: 'POST'
  };

  return new Promise((resolve, reject) => {
    const req = https.request(options, res => {
      let body = '';
      res.setEncoding('utf8');
      res.on('data', chunk => body += chunk);
      res.on('end', () => resolve(body));
    });

    req.on('error', reject);
    req.write(JSON.stringify(message));
    req.end();
  });
}<commit_msg>Replace office name with emoji<commit_after>'use strict';

// Gotta set a few config variables here since AWS Lambda restricts ENV values
// to a limiting format (like not allowing commas).
const config = {
  TEXT_CHECKIN: '@ :orbital:',
  TEXT_CHECKOUT: ':wave: Heading out, have a good night'
};

const https = require('https');
const url = require('url');

exports.handler = (event, context, callback) => {
  getWeather()
    .then(weather => getMessage(event, weather))
    .then(sendMessage)
    .then(body => callback(null, body))
    .catch(callback);
}

function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min)) + min;
}

function getMessage(event, weather) {
  let message = { username: process.env.USERNAME };

  if (event.clickType === 'SINGLE') {
    message.text = config.TEXT_CHECKIN || 'Checking in';
  } else if (event.clickType === 'DOUBLE') {
    message.text = config.TEXT_CHECKOUT || 'Checking out';
  } else if (event.clickType === 'LONG') {
    const emojis = ['poultry_leg', 'hamburger', 'pizza', 'taco', 'burrito', 'ramen', 'sushi', 'chicken'];
    const emoji = emojis[getRandomInt(0, emojis.length - 1)];
    message.text = `:${emoji}: Grabbing lunch`;
  } else {
    return Promise.reject(Error('Invalid clickType'));
  }

  if (weather && event.clickType !== 'LONG') {
    message.attachments = [{
      fallback: weather.summary,
      fields: [
        {
          title: 'Currently',
          value: `${weather.emoji} ${weather.summary} (${Math.round(weather.apparentTemperature)}°)`,
          short: false
        }
      ],
    }]
  }

  return message;
}

function getWeather() {
  if (!process.env.DARK_SKY_KEY) return Promise.resolve(null);

  const options = {
    hostname: 'api.darksky.net',
    path: `/forecast/${process.env.DARK_SKY_KEY}/${process.env.LATITUDE},${process.env.LONGITUDE}`
  }

  const iconEmoji = {
    "clear-day": ":sunny:",
    "clear-night": ":crescent_moon:",
    "rain": ":umbrella_with_rain_drops:",
    "snow": ":snowflake:",
    "sleet": ":rain_cloud:",
    "wind": ":wind_blowing_face:",
    "fog": ":fog:",
    "cloudy": ":cloud:",
    "partly-cloudy-day": ":partly_sunny:",
    "partly-cloudy-night": ":partly_sunny:"
  };

  return new Promise((resolve, reject) => {
    // res: https://darksky.net/dev/docs/response
    const req = https.request(options, res => {
      let body = '';
      res.setEncoding('utf8');
      res.on('data', chunk => body += chunk);
      res.on('end', () => {
        body = JSON.parse(body);
        resolve({
          summary: body.currently.summary,
          apparentTemperature: body.currently.apparentTemperature,
          emoji: iconEmoji[body.currently.icon]
        });
      });
    });

    req.on('error', reject);
    req.end();
  });
}

function sendMessage(message) {
  const parts = url.parse(process.env.WEBHOOK);
  const options = {
    hostname: parts.host,
    path: parts.path,
    method: 'POST'
  };

  return new Promise((resolve, reject) => {
    const req = https.request(options, res => {
      let body = '';
      res.setEncoding('utf8');
      res.on('data', chunk => body += chunk);
      res.on('end', () => resolve(body));
    });

    req.on('error', reject);
    req.write(JSON.stringify(message));
    req.end();
  });
}<|endoftext|>


<commit_before>MORSE = {
    "A": ".-",
    "B": "-...",
    "C": "-.-.",
    "D": "-..",
    "E": ".",
    "F": "..-.",
    "G": "--.",
    "H": "....",
    "I": "..",
    "J": ".---",
    "K": "-.-",
    "L": ".-..",
    "M": "--",
    "N": "-.",
    "O": "---",
    "P": ".--.",
    "Q": "--.-",
    "R": ".-.",
    "S": "...",
    "T": "-",
    "U": "..-",
    "V": "...-",
    "W": ".--",
    "X": "-..-",
    "Y": "-.--",
    "Z": "--..",
    // Numbers
    "1": ".----",
    "2": "..---",
    "3": "...--",
    "4": "....-",
    "5": ".....",
    "6": "-....",
    "7": "--...",
    "8": "---..",
    "9": "----.",
    "0": "-----"
};

jQuery(document).ready(function() {
  var audioCtx;

	function play_morse() {
	  if (audioCtx === undefined) {
      audioCtx = new AudioContext();
    } else {
      audioCtx.close();
      audioCtx = new AudioContext();
    }

		oscillator = audioCtx.createOscillator();
		oscillator.frequency.value = 750; // value in hertz

		var gainNode = audioCtx.createGain();
		gainNode.gain.value = 0;
		oscillator.connect(gainNode);
		gainNode.connect(audioCtx.destination);

		oscillator.start(0);

		var data = $('.input_morse').val().toUpperCase();
		var text = $('.morsecode');

		text.val('');
		text.show();

		var t = 0;
		var dot = 1.2 / 20;

		for(var i = 0; i < data.length; i++) {
			if(data[i] == ' ') {
				text.val(text.val() + ' ');
				t += dot * 3;
			} else if(MORSE[data[i]] !== undefined) {
				var code = MORSE[data[i]];
				for(var j = 0; j < code.length; j++) {
					switch(code[j]) {
						case '.':
							gainNode.gain.setValueAtTime(1.0, t);
							t += dot;
							gainNode.gain.setValueAtTime(0.0, t);
							break;
						case '-':
							gainNode.gain.setValueAtTime(1.0, t);
							t += dot * 3;
							gainNode.gain.setValueAtTime(0.0, t);
							break;
					}
					text.val(text.val() + code[j]);

					t += 3 * dot;
				}
				text.val(text.val() + ' ');
			}
		}
	}

	$('.play').on('click', function() {
		play_morse();
	});
	$('.morsecode').hide();
});
<commit_msg>Fix tabs/spaces indents<commit_after>MORSE = {
    "A": ".-",
    "B": "-...",
    "C": "-.-.",
    "D": "-..",
    "E": ".",
    "F": "..-.",
    "G": "--.",
    "H": "....",
    "I": "..",
    "J": ".---",
    "K": "-.-",
    "L": ".-..",
    "M": "--",
    "N": "-.",
    "O": "---",
    "P": ".--.",
    "Q": "--.-",
    "R": ".-.",
    "S": "...",
    "T": "-",
    "U": "..-",
    "V": "...-",
    "W": ".--",
    "X": "-..-",
    "Y": "-.--",
    "Z": "--..",
    // Numbers
    "1": ".----",
    "2": "..---",
    "3": "...--",
    "4": "....-",
    "5": ".....",
    "6": "-....",
    "7": "--...",
    "8": "---..",
    "9": "----.",
    "0": "-----"
};

jQuery(document).ready(function() {
  var audioCtx;

  function play_morse() {
    if (audioCtx === undefined) {
      audioCtx = new AudioContext();
    } else {
      audioCtx.close();
      audioCtx = new AudioContext();
    }

    oscillator = audioCtx.createOscillator();
    oscillator.frequency.value = 750; // value in hertz

    var gainNode = audioCtx.createGain();
    gainNode.gain.value = 0;
    oscillator.connect(gainNode);
    gainNode.connect(audioCtx.destination);

    oscillator.start(0);

    var data = $('.input_morse').val().toUpperCase();
    var text = $('.morsecode');

    text.val('');
    text.show();

    var t = 0;
    var dot = 1.2 / 20;

    for(var i = 0; i < data.length; i++) {
      if(data[i] == ' ') {
        text.val(text.val() + ' ');
        t += dot * 3;
      } else if(MORSE[data[i]] !== undefined) {
        var code = MORSE[data[i]];
        for(var j = 0; j < code.length; j++) {
          switch(code[j]) {
            case '.':
              gainNode.gain.setValueAtTime(1.0, t);
              t += dot;
              gainNode.gain.setValueAtTime(0.0, t);
              break;
            case '-':
              gainNode.gain.setValueAtTime(1.0, t);
              t += dot * 3;
              gainNode.gain.setValueAtTime(0.0, t);
              break;
          }
          text.val(text.val() + code[j]);

          t += 3 * dot;
        }
        text.val(text.val() + ' ');
      }
    }
  }

  $('.play').on('click', function() {
    play_morse();
  });
  $('.morsecode').hide();
});
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var rootStack;

module.exports = function (gulp) {
  if (gulp.chroot) {
    throw new Error('gulp.chroot already exists');
  }
  rootStack = [process.cwd()];
  gulp.chroot = function(root, cb) {
    rootStack.push(root);
    cb();
    rootStack.pop(root);
  };
  shim(gulp, 'task', function(task) {
    return function (name, deps, fn) {
      var childRoot = path.join.apply(path, rootStack);
      var parentRoot = path.join.apply(path, rootStack.slice(0, rootStack.length - 1))
      if (!Array.isArray(deps)) {
        fn = deps;
        deps = [];
      }
      return task.call(this, name, deps, fnWrapper);
      function fnWrapper() {
        console.log(childRoot);
        console.log(parentRoot);
        process.chdir(childRoot);
        if (typeof fn === 'function') {
          fn.apply(this, arguments);
        }
        process.chdir(parentRoot);
      }
    };
  });
};

function shim (obj, meth, rep) {
    obj[meth] = rep(obj[meth]);
}
<commit_msg>remove noisy log<commit_after>'use strict';

var path = require('path');
var rootStack;

module.exports = function (gulp) {
  if (gulp.chroot) {
    throw new Error('gulp.chroot already exists');
  }
  rootStack = [process.cwd()];
  gulp.chroot = function(root, cb) {
    rootStack.push(root);
    cb();
    rootStack.pop(root);
  };
  shim(gulp, 'task', function(task) {
    return function (name, deps, fn) {
      var childRoot = path.join.apply(path, rootStack);
      var parentRoot = path.join.apply(path, rootStack.slice(0, rootStack.length - 1))
      if (!Array.isArray(deps)) {
        fn = deps;
        deps = [];
      }
      return task.call(this, name, deps, fnWrapper);
      function fnWrapper() {
        process.chdir(childRoot);
        if (typeof fn === 'function') {
          fn.apply(this, arguments);
        }
        process.chdir(parentRoot);
      }
    };
  });
};

function shim (obj, meth, rep) {
    obj[meth] = rep(obj[meth]);
}
<|endoftext|>


<commit_before>/**
 *
 *
 *
 */

var port=process.env.PORT || 8080;
var basicauth=process.env.basicauth || 'nickolanack:nick';
console.log('Running bridge with custom http server: '+port+', and '+basicauth+' for server connections');
var http=require('http');

var Bridge= require('node-rproxy').Bridge;
var TinyServer=require('tinywebjs');

new Bridge({server:(new TinyServer({port:port, documentRoot:__dirname+'/html/'}}).addHandler('count',function(request, response){

	response.end('Cool It worked');

})).server,
basicauth:basicauth});
<commit_msg>trigger deploy<commit_after>/**
 *
 *
 *
 */

var port=process.env.PORT || 8080;
var basicauth=process.env.basicauth || 'nickolanack:nick';
console.log('Running bridge with custom http server: '+port+', and '+basicauth+' for server connections');
var http=require('http');

var Bridge= require('node-rproxy').Bridge;
var TinyServer=require('tinywebjs');

new Bridge({server:(new TinyServer({port:port, documentRoot:__dirname+'/html/'}}).addHandler('count',function(request, response){

	response.end('Cool It worked!!');

})).server,
basicauth:basicauth});
<|endoftext|>


<commit_before>let fs = require("fs");
let serveStatic = require('serve-static');
let sanitizeOptions = require('./util/options').sanitizeOptions;
let findEncoding = require('./util/encoding-selection').findEncoding;
let mime = serveStatic.mime;

module.exports = expressStaticGzipMiddleware;

/**
 * Generates a middleware function to serve pre-compressed files. It is build on top of serveStatic.
 * The pre-compressed files need to be placed next to the original files, in the provided `root` directory.
 * @param { string } root: directory to staticly serve files from
 * @param { expressStaticGzip.ExpressStaticGzipOptions } options: options to change module behaviour
 * @returns express middleware function
 */
function expressStaticGzipMiddleware(root, options) {
    let opts = sanitizeOptions(options);
    let serveStaticMiddleware = serveStatic(root, opts.serveStatic || null);
    let compressions = [];
    let files = {};

    registerCompressionsFromOptions();
    parseRootDirForCompressedFiles();

    return expressStaticGzip;

    function expressStaticGzip(req, res, next) {
        changeUrlFromDirectoryToIndexFile(req);

        var clientsAcceptedEncodings = req.header("accept-encoding");

        var fileWithMatchingPath = files[decodeURIComponent(req.path)];
        if (fileWithMatchingPath) {
            // The Vary Header is required for caching proxies to work properly
            res.setHeader("Vary", "Accept-Encoding");

            var compression = findEncoding(clientsAcceptedEncodings, fileWithMatchingPath.compressions, opts.orderPreference);
            if (compression) {
                convertToCompressedRequest(req, res, compression);
            }
        }

        serveStaticMiddleware(req, res, next);
    }

    function registerCompressionsFromOptions() {
        if (opts.customCompressions && opts.customCompressions.length > 0) {
            for (var i = 0; i < opts.customCompressions.length; i++) {
                var customCompression = opts.customCompressions[i];
                registerCompression(customCompression.encodingName, customCompression.fileExtension);
            }
        }

        if (opts.enableBrotli) {
            registerCompression("br", "br");
        }

        registerCompression("gzip", "gz");
    }

    function convertToCompressedRequest(req, res, compression) {
        var type = mime.lookup(req.path);
        var charset = mime.charsets.lookup(type);
        var search = req.url.split('?').splice(1).join('?');

        if (search !== "") {
            search = "?" + search;
        }

        req.url = req.path + compression.fileExtension + search;
        res.setHeader("Content-Encoding", compression.encodingName);
        res.setHeader("Content-Type", type + (charset ? "; charset=" + charset : ""));
    }

    function changeUrlFromDirectoryToIndexFile(req) {
        if (opts.index && req.url.endsWith("/")) {
            req.url += opts.index;
        }
    }

    function parseRootDirForCompressedFiles() {
        if (compressions.length > 0) {
            findCompressedFilesInDirectory(root);
        }
    }

    function findCompressedFilesInDirectory(directoryPath) {
        if (!fs.existsSync(directoryPath))  return;

        var filesInDirectory = fs.readdirSync(directoryPath);
        for (var i = 0; i < filesInDirectory.length; i++) {
            var filePath = directoryPath + "/" + filesInDirectory[i];
            var stats = fs.statSync(filePath);
            if (stats.isDirectory()) {
                findCompressedFilesInDirectory(filePath);
            } else {
                addMatchingCompressionsToFile(filesInDirectory[i], filePath);
            }
        }
    }

    /**
     * Takes a filename and checks if there is any compression type matching the file extension.
     * Adds all matching compressions to the file.
     * @param {string} fileName
     * @param {string} fillFilePath
     */
    function addMatchingCompressionsToFile(fileName, fullFilePath) {
        for (var i = 0; i < compressions.length; i++) {
            if (fileName.endsWith(compressions[i].fileExtension)) {
                addCompressionToFile(fullFilePath, compressions[i]);
                return;
            }
        }
    }

    /**
     * Adds the compression to the file's list of available compressions
     * @param {string} filePath
     * @param {Compression} compression
     */
    function addCompressionToFile(filePath, compression) {
        var srcFilePath = filePath.replace(root, "").replace(compression.fileExtension, "");
        var existingFile = files[srcFilePath];
        if (!existingFile) {
            files[srcFilePath] = { compressions: [compression] };
        } else {
            existingFile.compressions.push(compression);
        }
    }

    /**
     * Registers a new compression to the module.
     * @param {string} encodingName
     * @param {string} fileExtension
     */
    function registerCompression(encodingName, fileExtension) {
        if (!findCompressionByName(encodingName)) {
            compressions.push(new Compression(encodingName, fileExtension));
        }
    }

    /**
     * @param {string} encodingName
     * @param {string} fileExtension
     * @returns {{encodingName:string, fileExtension:string}}
     */
    function Compression(encodingName, fileExtension) {
        this.encodingName = encodingName;
        this.fileExtension = "." + fileExtension;
    }

    /**
     * @param {string} encodingName
     * @returns {{encodingName:string, fileExtension:string}}
     */
    function findCompressionByName(encodingName) {
        for (var i = 0; i < compressions.length; i++) {
            if (compressions[i].encodingName === encodingName) {
                return compressions[i];
            }
        }

        return null;
    }
}
<commit_msg>fix: Read "accept-encoding" directly from headers object This is nodejs native, and enables use in non-express environments<commit_after>let fs = require("fs");
let serveStatic = require('serve-static');
let sanitizeOptions = require('./util/options').sanitizeOptions;
let findEncoding = require('./util/encoding-selection').findEncoding;
let mime = serveStatic.mime;

module.exports = expressStaticGzipMiddleware;

/**
 * Generates a middleware function to serve pre-compressed files. It is build on top of serveStatic.
 * The pre-compressed files need to be placed next to the original files, in the provided `root` directory.
 * @param { string } root: directory to staticly serve files from
 * @param { expressStaticGzip.ExpressStaticGzipOptions } options: options to change module behaviour
 * @returns express middleware function
 */
function expressStaticGzipMiddleware(root, options) {
    let opts = sanitizeOptions(options);
    let serveStaticMiddleware = serveStatic(root, opts.serveStatic || null);
    let compressions = [];
    let files = {};

    registerCompressionsFromOptions();
    parseRootDirForCompressedFiles();

    return expressStaticGzip;

    function expressStaticGzip(req, res, next) {
        changeUrlFromDirectoryToIndexFile(req);

        var clientsAcceptedEncodings = req.headers["accept-encoding"];

        var fileWithMatchingPath = files[decodeURIComponent(req.path)];
        if (fileWithMatchingPath) {
            // The Vary Header is required for caching proxies to work properly
            res.setHeader("Vary", "Accept-Encoding");

            var compression = findEncoding(clientsAcceptedEncodings, fileWithMatchingPath.compressions, opts.orderPreference);
            if (compression) {
                convertToCompressedRequest(req, res, compression);
            }
        }

        serveStaticMiddleware(req, res, next);
    }

    function registerCompressionsFromOptions() {
        if (opts.customCompressions && opts.customCompressions.length > 0) {
            for (var i = 0; i < opts.customCompressions.length; i++) {
                var customCompression = opts.customCompressions[i];
                registerCompression(customCompression.encodingName, customCompression.fileExtension);
            }
        }

        if (opts.enableBrotli) {
            registerCompression("br", "br");
        }

        registerCompression("gzip", "gz");
    }

    function convertToCompressedRequest(req, res, compression) {
        var type = mime.lookup(req.path);
        var charset = mime.charsets.lookup(type);
        var search = req.url.split('?').splice(1).join('?');

        if (search !== "") {
            search = "?" + search;
        }

        req.url = req.path + compression.fileExtension + search;
        res.setHeader("Content-Encoding", compression.encodingName);
        res.setHeader("Content-Type", type + (charset ? "; charset=" + charset : ""));
    }

    function changeUrlFromDirectoryToIndexFile(req) {
        if (opts.index && req.url.endsWith("/")) {
            req.url += opts.index;
        }
    }

    function parseRootDirForCompressedFiles() {
        if (compressions.length > 0) {
            findCompressedFilesInDirectory(root);
        }
    }

    function findCompressedFilesInDirectory(directoryPath) {
        if (!fs.existsSync(directoryPath))  return;

        var filesInDirectory = fs.readdirSync(directoryPath);
        for (var i = 0; i < filesInDirectory.length; i++) {
            var filePath = directoryPath + "/" + filesInDirectory[i];
            var stats = fs.statSync(filePath);
            if (stats.isDirectory()) {
                findCompressedFilesInDirectory(filePath);
            } else {
                addMatchingCompressionsToFile(filesInDirectory[i], filePath);
            }
        }
    }

    /**
     * Takes a filename and checks if there is any compression type matching the file extension.
     * Adds all matching compressions to the file.
     * @param {string} fileName
     * @param {string} fillFilePath
     */
    function addMatchingCompressionsToFile(fileName, fullFilePath) {
        for (var i = 0; i < compressions.length; i++) {
            if (fileName.endsWith(compressions[i].fileExtension)) {
                addCompressionToFile(fullFilePath, compressions[i]);
                return;
            }
        }
    }

    /**
     * Adds the compression to the file's list of available compressions
     * @param {string} filePath
     * @param {Compression} compression
     */
    function addCompressionToFile(filePath, compression) {
        var srcFilePath = filePath.replace(root, "").replace(compression.fileExtension, "");
        var existingFile = files[srcFilePath];
        if (!existingFile) {
            files[srcFilePath] = { compressions: [compression] };
        } else {
            existingFile.compressions.push(compression);
        }
    }

    /**
     * Registers a new compression to the module.
     * @param {string} encodingName
     * @param {string} fileExtension
     */
    function registerCompression(encodingName, fileExtension) {
        if (!findCompressionByName(encodingName)) {
            compressions.push(new Compression(encodingName, fileExtension));
        }
    }

    /**
     * @param {string} encodingName
     * @param {string} fileExtension
     * @returns {{encodingName:string, fileExtension:string}}
     */
    function Compression(encodingName, fileExtension) {
        this.encodingName = encodingName;
        this.fileExtension = "." + fileExtension;
    }

    /**
     * @param {string} encodingName
     * @returns {{encodingName:string, fileExtension:string}}
     */
    function findCompressionByName(encodingName) {
        for (var i = 0; i < compressions.length; i++) {
            if (compressions[i].encodingName === encodingName) {
                return compressions[i];
            }
        }

        return null;
    }
}
<|endoftext|>


<commit_before>/*
docs: http://api.yandex.ru/speechkit/cloud-api/doc/index.xml
*/

var YandexASR = function(options){

    var request = require('request');
    var qs = require('querystring');
    var fs = require('fs');
    var path = require('path');

    var yandex_asr_url = 'http://asr.yandex.net/asr_xml?';
    var yandex_developer_key = null;
    var yandex_user_uuid = null;
    var yandex_recognize_file = null;
    var yandex_recognize_filetype = 'audio/x-mpeg-3';
    var yandex_topic = 'freeform';
    var yandex_lang = 'ru-RU';

    var init = function(options){
        yandex_developer_key = options['developer_key'];
        yandex_user_uuid = options['uuid'];
        yandex_recognize_file = options['file'];
        yandex_recognize_filetype = (options['filetype'])?options['filetype']:'audio/x-mpeg-3';
        yandex_topic = (options['topic'])?options['topic']:'freeform';
        yandex_lang = (options['lang'])?options['lang']:'ru-RU';
    }(options);

    var params = {
        uuid: yandex_user_uuid,
        key: yandex_developer_key,
        topic: yandex_topic,
        lang: yandex_lang
    };

    var full_url = yandex_asr_url + qs.stringify(params);

    var recognize = function(callback){

        var r = request.post({
                url: full_url,
                headers: {
                    'Transfer-Encoding': 'chunked'
                }
            },
            function (err, httpResponse, body) {
                callback(err, httpResponse, body)
            }
        );

        var form = r.form();
        form.append('Content-Type', yandex_recognize_filetype);
        form.append('audio', fs.createReadStream(path.join(__dirname, yandex_recognize_file)));
    }

    return {
        recognize: recognize,
    }
};

module.exports = YandexASR;<commit_msg>change filepath<commit_after>/*
docs: http://api.yandex.ru/speechkit/cloud-api/doc/index.xml
*/

var YandexASR = function(options){

    var request = require('request');
    var qs = require('querystring');
    var fs = require('fs');
    var path = require('path');

    var yandex_asr_url = 'http://asr.yandex.net/asr_xml?';
    var yandex_developer_key = null;
    var yandex_user_uuid = null;
    var yandex_recognize_file = null;
    var yandex_recognize_filetype = 'audio/x-mpeg-3';
    var yandex_topic = 'freeform';
    var yandex_lang = 'ru-RU';

    var init = function(options){
        yandex_developer_key = options['developer_key'];
        yandex_user_uuid = options['uuid'];
        yandex_recognize_file = options['file'];
        yandex_recognize_filetype = (options['filetype'])?options['filetype']:'audio/x-mpeg-3';
        yandex_topic = (options['topic'])?options['topic']:'freeform';
        yandex_lang = (options['lang'])?options['lang']:'ru-RU';
    }(options);

    var params = {
        uuid: yandex_user_uuid,
        key: yandex_developer_key,
        topic: yandex_topic,
        lang: yandex_lang
    };

    var full_url = yandex_asr_url + qs.stringify(params);

    var recognize = function(callback){

        var r = request.post({
                url: full_url,
                headers: {
                    'Transfer-Encoding': 'chunked'
                }
            },
            function (err, httpResponse, body) {
                callback(err, httpResponse, body)
            }
        );

        var form = r.form();
        form.append('Content-Type', yandex_recognize_filetype);
        form.append('audio', fs.createReadStream(yandex_recognize_file));
    }

    return {
        recognize: recognize,
    }
};

module.exports = YandexASR;<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var Request = require('hyper-path');
var Emitter = require('component-emitter');
var debug = require('debug')('hyper-map');

/**
 * Expose the HyperMap
 */

module.exports = HyperMap;

/**
 * Create a HyperMap Client
 *
 * @param {Object?} resources
 * @param {Object?} errors
 */

function HyperMap(resources, errors) {
  this._resources = resources || {};
  this._errors = errors || {};
  this._completed = {};
  this.size = 0;
  for (var r in resources) {
    if (!resources.hasOwnProperty(r)) continue;
    this._completed[r] = true;
    this.size++;
  }
}
Emitter(HyperMap.prototype);

/**
 * Lookup a resource with the path and scope
 *
 * @param {String} path
 * @param {Object?} scope
 * @param {String?} delim
 * @return {Object}
 * @api public
 */

HyperMap.prototype.get = function(path, scope, delim) {
  var self = this;

  var client = createClient(self);
  var req = new Request(path, client, delim);
  req.scope(scope || {});

  return req.get(function(err, value) {
    if (err) throw err;
    return {
      completed: client.completed,
      value: value,
      request: req
    };
  });
};

/**
 * Set the value of a resource
 *
 * @param {String} href
 * @param {Object} value
 * @return {SyncClient}
 * @api public
 */

HyperMap.prototype.set = function(href, value) {
  this._resources[href] = value;
  if (!this._completed[href]) this.size++;
  this._completed[href] = true;
  return this;
};

/**
 * Set the error response for a resource
 *
 * @param {String} href
 * @param {Error} err
 * @return {SyncClient}
 * @api public
 */

HyperMap.prototype.error = function(href, err) {
  this._errors[href] = err;
  if (!this._completed[href]) this.size++;
  this._completed[href] = true;
  return this;
};

/**
 * Remove a resource from the store
 *
 * @param {String} href
 * @return {SyncClient}
 * @api public
 */

HyperMap.prototype.delete = function(href) {
  if (this._completed[href]) this.size--;
  delete this._resources[href];
  delete this._completed[href];
  delete this._errors[href];
  return this;
};

function createClient(map) {
  var client = {
    completed: true
  };
  client.root = root;
  client.get = get;

  return client;

  function root(cb) {
    return get('.', cb);
  }

  function get(href, cb) {
    map.emit('request', href);
    client.completed = client.completed && !!map._completed[href];
    var err = map._errors[href] || void 0;
    var val = map._resources[href];
    debug('fetching cache for ' + href, err, val);
    return cb(err, val);
  }
}
<commit_msg>pass false to shouldResolve<commit_after>/**
 * Module dependencies
 */

var Request = require('hyper-path');
var Emitter = require('component-emitter');
var debug = require('debug')('hyper-map');

/**
 * Expose the HyperMap
 */

module.exports = HyperMap;

/**
 * Create a HyperMap Client
 *
 * @param {Object?} resources
 * @param {Object?} errors
 */

function HyperMap(resources, errors) {
  this._resources = resources || {};
  this._errors = errors || {};
  this._completed = {};
  this.size = 0;
  for (var r in resources) {
    if (!resources.hasOwnProperty(r)) continue;
    this._completed[r] = true;
    this.size++;
  }
}
Emitter(HyperMap.prototype);

/**
 * Lookup a resource with the path and scope
 *
 * @param {String} path
 * @param {Object?} scope
 * @param {String?} delim
 * @return {Object}
 * @api public
 */

HyperMap.prototype.get = function(path, scope, delim) {
  var self = this;

  var client = createClient(self);
  var req = new Request(path, client, delim);
  req.scope(scope || {});

  return req.get(function(err, value) {
    if (err) throw err;
    return {
      completed: client.completed,
      value: value,
      request: req
    };
  });
};

/**
 * Set the value of a resource
 *
 * @param {String} href
 * @param {Object} value
 * @return {HyperMap}
 * @api public
 */

HyperMap.prototype.set = function(href, value) {
  this._resources[href] = value;
  if (!this._completed[href]) this.size++;
  this._completed[href] = true;
  return this;
};

/**
 * Set the error response for a resource
 *
 * @param {String} href
 * @param {Error} err
 * @return {HyperMap}
 * @api public
 */

HyperMap.prototype.error = function(href, err) {
  this._errors[href] = err;
  if (!this._completed[href]) this.size++;
  this._completed[href] = true;
  return this;
};

/**
 * Remove a resource from the store
 *
 * @param {String} href
 * @return {HyperMap}
 * @api public
 */

HyperMap.prototype.delete = function(href) {
  if (this._completed[href]) this.size--;
  delete this._resources[href];
  delete this._completed[href];
  delete this._errors[href];
  return this;
};

function createClient(map) {
  var client = {
    completed: true,
    requests: []
  };
  client.root = root;
  client.get = get;

  return client;

  function root(cb) {
    return get('.', cb);
  }

  function get(href, cb) {
    map.emit('request', href);
    client.requests.push(href);
    client.completed = client.completed && !!map._completed[href];
    var err = map._errors[href] || void 0;
    var val = map._resources[href];
    debug('fetching cache for ' + href, err, val);
    return cb(err, val, null, null, false);
  }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
// Dependencies
var moment = require("moment");
var sugar = require("sugar");
var colors = require("colors");

// Check for CLI argument
process.argv.splice(0, 2);
if (process.argv.length > 0) {

    // Attempt to parse the date
    var date = process.argv.join(" ");
    var parsedDate = Date.create(date);
    if (parsedDate != "Invalid Date"){

        // Date could be parsed, parse the date to git date format
        var dateString = moment(parsedDate).format("ddd MMM DD hh:mm:ss YYYY ZZ");

    } else {
        console.log("fatal: Could not parse \"" + date + "\" into a valid date");
    }

} else {

    // Show documentation

}
<commit_msg>Display new dates neatly<commit_after>#!/usr/bin/env node
// Dependencies
var moment = require("moment");
var sugar = require("sugar");
var colors = require("colors");

// Check for CLI argument
process.argv.splice(0, 2);
if (process.argv.length > 0) {

    // Attempt to parse the date
    var date = process.argv.join(" ");
    var parsedDate = Date.create(date);
    if (parsedDate != "Invalid Date"){

        // Date could be parsed, parse the date to git date format
        var dateString = moment(parsedDate).format("ddd MMM DD hh:mm:ss YYYY ZZ");
        console.log("\nModified previous commit:\n\tAUTHOR_DATE " + colors.grey(dateString) + "\n\tCOMMITTER_DATE " + colors.grey(dateString) + "\n");

    } else {
        console.log("fatal: Could not parse \"" + date + "\" into a valid date");
    }

} else {

    // Show documentation

}
<|endoftext|>


<commit_before>var mongoose = require("mongoose");
var q = require("q");
var _ = require("underscore");

// Enable mpath structures on any `schema`.
var enable = module.exports.enable = function(schema) {
    schema.plugin(function() {
        schema.add({
            mpath:{
                type:String,
                index:true
            },
            parentId:{
                type:String,
                index:true
            }
        });
    });
}

// Attach `child` to `parent`.  Passing true in `isLeaf` improves performance for leaf nodes because no check needs
// to be done to rewrite the paths of child nodes.  When a `parent` is not passed, it implies the `child` is to be made
// a root.
var attach = module.exports.attach = function(child, parent, isLeaf) {
    var childPath;
    // Compute the mpath for the `child` node.  Is there is no `parent`, the mpath is empty, if the `parent` is a root, then
    // the mpath is equal to the `parent` id, otherwise it is the `parent` mpath plus it's id
    if (!parent) {
        childPath = "";
    }
    else if (!parent.mpath) {
        childPath = "/"+parent.id;
    }
    else {
        childPath = parent.mpath+"/"+parent.id;
    }
    // If the `child` is a leaf, just set the mpath, save it, and complete the promise
    if (isLeaf) {
        child.mpath = childPath;
        child.parentId = parent?parent.id:undefined;
        return q.ninvoke(child, "save").then(function() {
            return child;
        });

    }
    else {
        // If the `child` is not a leaf, then find all it's descendants and recompute their mpaths, but still return
        // the `child` once all the save promises are resolved.
        return getDescendants(child)
            .then(function(descendants) {
                var promises = descendants.map(function(descendant) {
                    descendant.mpath = descendant.mpath.replace(child.mpath, childPath);
                    return q.ninvoke(descendant, "save");
                });
                child.mpath = childPath;
                child.parentId = parent?parent.id:undefined;
                promises.push(q.ninvoke(child, "save"));
                return q.all(promises);
            })
            .then(function() {
                return child;
            });

    }
};

// Detach a `child` from it's parent.  This is done by simply "attaching" it to a undefined parent
var detach = module.exports.detach = function(child) {
    return attach(child);
};

// Make a copy of `root`, assigning the copy to the same parent.  Note that `root` does not actually need to be a root
// node, it is just the root of the tree of nodes that should be copied.
var copy = module.exports.copy = function(root, options) {
    var objects = [];
    // Convert the `node` to a deep POJO representing this tree.  This function is called recursively to process the
    // entire tree rooted at `node`
    function toDeepObject(node) {
        var copy;
        if (options.copy) {
            copy = options.copy(node);
        }
        else {
            copy = new node.constructor(node.toObject());
            copy._id = new mongoose.Types.ObjectId();
        }
        var object = copy.toObject();
        object.children = {};
        for (var id in node.children) {
            var child = node.children[id];
            if (options.filterChild(child)) {
                var childObject = toDeepObject(child);
                childObject.parent = object;
                object.children[id] = childObject;
            }
        }
        return object;
    }
    // Reset the parent id and mpaths of `object` and all it's child objects.  This method is intended to be called with
    // the output of toDeepObject
    function reId(object) {
        if (object.parent) {
            object.parentId = object.parent._id.toString();
            if (object.parent.mpath) {
                object.mpath = object.parent.mpath+"/"+object.parent._id.toString();
            }
            else {
                object.mpath = "/"+object.parent._id.toString();
            }
        }
        objects.push(object);
        for (var id in object.children) {
            reId(object.children[id]);
        }
    }
    // Start the promise chaining by getting the descendant tree of `root`
    return buildDescendantTree(root)
        .then(function(root) {
            // Convert `root` to a deep object and reset the parent id and mpath values
            reId(toDeepObject(root));
            // Delete the child and parent properties of the deep `object`.  Once parent id and mpath properties have
            // been computed, there is no further need to maintain the references, in fact they need to be removed
            // before bulk insert.
            objects.forEach(function(object) {
                delete object.children;
                delete object.parent;
            })
            // Bulk insert the `objects` using mongo's direct driver call.  This is efficient, but will not run any
            // middleware
            return q
                .ninvoke(root.constructor.collection, "insert", objects)
                .then(function(copies) {
                    return mongoose
                        .model(root.constructor.modelName)
                        .findOne(
                            {
                                _id:copies[0]._id.toString()
                            },
                            "")
                        .exec();
                })
                .then(function(rootCopy) {
                    return buildDescendantTree(rootCopy);
                })
        })
}

// Find all descendants of `root`.  This does not return a tree structure, just the nodes that would comprise such a tree
var getDescendants = module.exports.getDescendants = function(root, options) {
    options = options?options:{};
    var query = options.query?options.query:{};
    query.mpath = new RegExp("^"+(root.mpath?root.mpath:"")+"\/"+root.id);
    var op = root.constructor.find(query, options.fields?options.fields:"");
    if (options.lean) {
        op = op.lean();
    }
    return op.exec();
}

// Delete all descendants of `root`
var removeDescendants = module.exports.removeDescendants = function(root, options) {
    options = options?options:{};
    var query = options.query?options.query:{};
    query.mpath = new RegExp("^"+(root.mpath?root.mpath:"")+"\/"+root.id);
    var op = root.constructor
        .find(query)
        .remove();
    if (options.lean) {
        op = op.lean();
    }
    return op.exec();
}

// Get all children of `root`
var getChildren = module.exports.getChildren = function(root, options) {
    options = options?options:{};
    var query = options.query?options.query:{};
    query.parentId = root.id;
    var op = root.constructor.find(query, options.fields?options.fields:"");
    if (options.lean) {
        op = op.lean();
    }
    return op.exec();
}

// Given an array of `nodes`, construct the set of trees containing all the `nodes` such that the number of roots is
// minimized.  In the common case, this is used to convert the output of `getDescendants()` into a tree structure
var buildTrees = module.exports.buildTree = function(nodes) {
    var nodeMap = {};
    nodes.forEach(function(node) {
        nodeMap[node.id] = node;
        node.children = {};
    });
    nodes.forEach(function(node) {
        var parent = nodeMap[node.parentId];
        if (parent) {
            parent.children[node.id] = node;
            node.parent = parent;
        }
    });
    nodes.forEach(function(node) {
        if (node.parent) {
            delete nodeMap[node.id];
        }
    });
    return _.values(nodeMap);
}

// Get all descendants of `root` structured as a tree
var buildDescendantTree = module.exports.buildDescendantTree = function(root, options) {
    return getDescendants(root, options)
        .then(function(documents) {
            documents.push(root);
            buildTrees(documents);
            return root;
        })
}

// Get all children of `root` structured as a tree
var buildChildrenTree = module.exports.buildChildrenTree = function(root, options) {
    return getChildren(root, options)
        .then(function(documents) {
            documents.push(root);
            buildTrees(documents);
            return root;
        })
}

// Get all ancestors of all of the `documents` structured as a set of trees.  Note that the number of returned trees may
// be less than the number of passed `documents` because different child nodes may have common ancestors.  In a single root
// hierarchy (where all paths lead to the same root), this method will always return one tree.  If any of the `documents`
// have children, or descendants, integrate these into the overall ancestor tree, but do not include any children of
// any of the ancestors of the `documents`
var buildAncestorTree = module.exports.buildAncestorTree = function(documents) {
    var idSet = {};
    var descendants = [];
    if (!documents) {
        return [];
    }
    documents = [].concat(documents);
    if (documents.length==0) {
        return [];
    }
    function getDescendants(document) {
        if (document.children) {
            _.values(document.children).forEach(function(child) {
                descendants.push(child);
                getDescendants(child);
            })
        }
    }
    documents.forEach(function(document) {
        getDescendants(document);
        if (document.mpath) {
            document.mpath
                .split("/")
                .forEach(function(id) {
                    idSet[id] = true;
                });
        }
    })
    delete idSet[""];

    var op = documents[0].constructor
        .find({
            _id:{
                $in:_.keys(idSet)
            }
        })
    if (options.lean) {
        op = op.lean();
    }
    return op
        .exec()
        .then(function(ancestors) {
            documents = documents.concat(descendants);
            documents = documents.concat(ancestors);
            return buildTrees(documents);
        }
    )
}
<commit_msg>Add options param to buildAncestorTree method<commit_after>var mongoose = require("mongoose");
var q = require("q");
var _ = require("underscore");

// Enable mpath structures on any `schema`.
var enable = module.exports.enable = function(schema) {
    schema.plugin(function() {
        schema.add({
            mpath:{
                type:String,
                index:true
            },
            parentId:{
                type:String,
                index:true
            }
        });
    });
}

// Attach `child` to `parent`.  Passing true in `isLeaf` improves performance for leaf nodes because no check needs
// to be done to rewrite the paths of child nodes.  When a `parent` is not passed, it implies the `child` is to be made
// a root.
var attach = module.exports.attach = function(child, parent, isLeaf) {
    var childPath;
    // Compute the mpath for the `child` node.  Is there is no `parent`, the mpath is empty, if the `parent` is a root, then
    // the mpath is equal to the `parent` id, otherwise it is the `parent` mpath plus it's id
    if (!parent) {
        childPath = "";
    }
    else if (!parent.mpath) {
        childPath = "/"+parent.id;
    }
    else {
        childPath = parent.mpath+"/"+parent.id;
    }
    // If the `child` is a leaf, just set the mpath, save it, and complete the promise
    if (isLeaf) {
        child.mpath = childPath;
        child.parentId = parent?parent.id:undefined;
        return q.ninvoke(child, "save").then(function() {
            return child;
        });

    }
    else {
        // If the `child` is not a leaf, then find all it's descendants and recompute their mpaths, but still return
        // the `child` once all the save promises are resolved.
        return getDescendants(child)
            .then(function(descendants) {
                var promises = descendants.map(function(descendant) {
                    descendant.mpath = descendant.mpath.replace(child.mpath, childPath);
                    return q.ninvoke(descendant, "save");
                });
                child.mpath = childPath;
                child.parentId = parent?parent.id:undefined;
                promises.push(q.ninvoke(child, "save"));
                return q.all(promises);
            })
            .then(function() {
                return child;
            });

    }
};

// Detach a `child` from it's parent.  This is done by simply "attaching" it to a undefined parent
var detach = module.exports.detach = function(child) {
    return attach(child);
};

// Make a copy of `root`, assigning the copy to the same parent.  Note that `root` does not actually need to be a root
// node, it is just the root of the tree of nodes that should be copied.
var copy = module.exports.copy = function(root, options) {
    var objects = [];
    // Convert the `node` to a deep POJO representing this tree.  This function is called recursively to process the
    // entire tree rooted at `node`
    function toDeepObject(node) {
        var copy;
        if (options.copy) {
            copy = options.copy(node);
        }
        else {
            copy = new node.constructor(node.toObject());
            copy._id = new mongoose.Types.ObjectId();
        }
        var object = copy.toObject();
        object.children = {};
        for (var id in node.children) {
            var child = node.children[id];
            if (options.filterChild(child)) {
                var childObject = toDeepObject(child);
                childObject.parent = object;
                object.children[id] = childObject;
            }
        }
        return object;
    }
    // Reset the parent id and mpaths of `object` and all it's child objects.  This method is intended to be called with
    // the output of toDeepObject
    function reId(object) {
        if (object.parent) {
            object.parentId = object.parent._id.toString();
            if (object.parent.mpath) {
                object.mpath = object.parent.mpath+"/"+object.parent._id.toString();
            }
            else {
                object.mpath = "/"+object.parent._id.toString();
            }
        }
        objects.push(object);
        for (var id in object.children) {
            reId(object.children[id]);
        }
    }
    // Start the promise chaining by getting the descendant tree of `root`
    return buildDescendantTree(root)
        .then(function(root) {
            // Convert `root` to a deep object and reset the parent id and mpath values
            reId(toDeepObject(root));
            // Delete the child and parent properties of the deep `object`.  Once parent id and mpath properties have
            // been computed, there is no further need to maintain the references, in fact they need to be removed
            // before bulk insert.
            objects.forEach(function(object) {
                delete object.children;
                delete object.parent;
            })
            // Bulk insert the `objects` using mongo's direct driver call.  This is efficient, but will not run any
            // middleware
            return q
                .ninvoke(root.constructor.collection, "insert", objects)
                .then(function(copies) {
                    return mongoose
                        .model(root.constructor.modelName)
                        .findOne(
                            {
                                _id:copies[0]._id.toString()
                            },
                            "")
                        .exec();
                })
                .then(function(rootCopy) {
                    return buildDescendantTree(rootCopy);
                })
        })
}

// Find all descendants of `root`.  This does not return a tree structure, just the nodes that would comprise such a tree
var getDescendants = module.exports.getDescendants = function(root, options) {
    options = options?options:{};
    var query = options.query?options.query:{};
    query.mpath = new RegExp("^"+(root.mpath?root.mpath:"")+"\/"+root.id);
    var op = root.constructor.find(query, options.fields?options.fields:"");
    if (options.lean) {
        op = op.lean();
    }
    return op.exec();
}

// Delete all descendants of `root`
var removeDescendants = module.exports.removeDescendants = function(root, options) {
    options = options?options:{};
    var query = options.query?options.query:{};
    query.mpath = new RegExp("^"+(root.mpath?root.mpath:"")+"\/"+root.id);
    var op = root.constructor
        .find(query)
        .remove();
    if (options.lean) {
        op = op.lean();
    }
    return op.exec();
}

// Get all children of `root`
var getChildren = module.exports.getChildren = function(root, options) {
    options = options?options:{};
    var query = options.query?options.query:{};
    query.parentId = root.id;
    var op = root.constructor.find(query, options.fields?options.fields:"");
    if (options.lean) {
        op = op.lean();
    }
    return op.exec();
}

// Given an array of `nodes`, construct the set of trees containing all the `nodes` such that the number of roots is
// minimized.  In the common case, this is used to convert the output of `getDescendants()` into a tree structure
var buildTrees = module.exports.buildTree = function(nodes) {
    var nodeMap = {};
    nodes.forEach(function(node) {
        nodeMap[node.id] = node;
        node.children = {};
    });
    nodes.forEach(function(node) {
        var parent = nodeMap[node.parentId];
        if (parent) {
            parent.children[node.id] = node;
            node.parent = parent;
        }
    });
    nodes.forEach(function(node) {
        if (node.parent) {
            delete nodeMap[node.id];
        }
    });
    return _.values(nodeMap);
}

// Get all descendants of `root` structured as a tree
var buildDescendantTree = module.exports.buildDescendantTree = function(root, options) {
    return getDescendants(root, options)
        .then(function(documents) {
            documents.push(root);
            buildTrees(documents);
            return root;
        })
}

// Get all children of `root` structured as a tree
var buildChildrenTree = module.exports.buildChildrenTree = function(root, options) {
    return getChildren(root, options)
        .then(function(documents) {
            documents.push(root);
            buildTrees(documents);
            return root;
        })
}

// Get all ancestors of all of the `documents` structured as a set of trees.  Note that the number of returned trees may
// be less than the number of passed `documents` because different child nodes may have common ancestors.  In a single root
// hierarchy (where all paths lead to the same root), this method will always return one tree.  If any of the `documents`
// have children, or descendants, integrate these into the overall ancestor tree, but do not include any children of
// any of the ancestors of the `documents`
var buildAncestorTree = module.exports.buildAncestorTree = function(documents, options) {
    var idSet = {};
    var descendants = [];
    if (!documents) {
        return [];
    }
    documents = [].concat(documents);
    if (documents.length==0) {
        return [];
    }
    function getDescendants(document) {
        if (document.children) {
            _.values(document.children).forEach(function(child) {
                descendants.push(child);
                getDescendants(child);
            })
        }
    }
    documents.forEach(function(document) {
        getDescendants(document);
        if (document.mpath) {
            document.mpath
                .split("/")
                .forEach(function(id) {
                    idSet[id] = true;
                });
        }
    })
    delete idSet[""];

    var op = documents[0].constructor
        .find({
            _id:{
                $in:_.keys(idSet)
            }
        })
    if (options.lean) {
        op = op.lean();
    }
    return op
        .exec()
        .then(function(ancestors) {
            documents = documents.concat(descendants);
            documents = documents.concat(ancestors);
            return buildTrees(documents);
        }
    )
}
<|endoftext|>