<commit_before>var _ = require('lodash');
var async = require('async');
var fs = require('fs-extra');

var RunListHelper = require('../src/RunListHelper');
var NodeRunner = require('../src/RunWrappers/Node');
var DockerRunner = require('../src/RunWrappers/Docker');
var DockerComposeRunner = require('../src/RunWrappers/DockerCompose');
var CmdHelper = require('../src/CmdHelper');

var runningServices = [];
var notRunningServices = [];

module.exports = {
  name: 'run',
  description: 'Runs all of the microservices (or subset based on regex pattern)',
  usage: '[-r <repoPattern>] [-t <tag>] [-d]',
  requiresNvm: true,
  options: [
    {
      name: 'tag',
      alias: 't',
      type: 'string',
      desc: 'Filter by a tag defined within bosco-service.json',
    },
    {
      name: 'watch',
      alias: 'w',
      type: 'string',
      desc: 'Watch the applications started with run for changes that match this regular expression',
    },
    {
      name: 'list',
      alias: 'l',
      type: 'string',
      desc: 'Start a list of repos (comma separated)',
    },
    {
      name: 'deps-only',
      alias: 'd',
      type: 'boolean',
      desc: 'Only start the dependencies of the current repo, not itself',
    },
    {
      name: 'show',
      type: 'boolean',
      desc: 'Display the dependency tree but do not start the services',
    },
    {
      name: 'docker-only',
      type: 'boolean',
      desc: 'Only start docker dependencies',
    },
    {
      name: 'team-only',
      type: 'boolean',
      desc: 'Only start app or service dependencies in the current team',
    },
  ],
};

function cmd(bosco, args, allDone) {
  var done = allDone ? allDone : function() {};
  var repoPattern = bosco.options.repo;
  var repoRegex = new RegExp(repoPattern);
  var watchPattern = bosco.options.watch || '$a';
  var watchRegex = new RegExp(watchPattern);
  var repoTag = bosco.options.tag;

  var repos;
  if (bosco.options.list) {
    repos = bosco.options.list.split(',');
  } else {
    CmdHelper.checkInService(bosco);
    repos = bosco.getRepos();
  }

  function initialiseRunners(next) {
    var runners = [NodeRunner, DockerRunner, DockerComposeRunner];
    async.map(runners, function loadRunner(runner, cb) {
      runner.init(bosco, cb);
    }, next);
  }

  function disconnectRunners(next) {
    var runners = [NodeRunner, DockerRunner];
    async.map(runners, function loadRunner(runner, cb) {
      runner.disconnect(cb);
    }, next);
  }

  function getRunList(next) {
    RunListHelper.getRunList(bosco, repos, repoRegex, watchRegex, repoTag, false, next);
  }

  function startRunnableServices(next) {
    var alreadyRunning = 0;

    function runService(runConfig, cb) {
      var type = runConfig.service && runConfig.service.type;

      if (!type || type === 'unknown' || type === 'skip') {
        return cb();
      }

      if (type === 'docker') {
        if (_.includes(runningServices, runConfig.name)) {
          if (bosco.options.verbose) {
            bosco.warn('Service ' + runConfig.name.green + ' is already running ...');
          } else {
            alreadyRunning++;
          }
          return cb();
        }
        if (bosco.options.verbose) {
          bosco.log('Running docker service ' + runConfig.name.green + ' ...');
        }
        return DockerRunner.start(runConfig, function(err) {
          // Log errors from docker but do not stop all tasks
          if (err) {
            bosco.error('There was an error running ' + runConfig.name + ': ' + err);
          }
          cb();
        });
      }

      if (type === 'docker-compose') {
        if (bosco.options.verbose) {
          bosco.log('Running docker-compose ' + runConfig.name.green + ' ...');
        }
        return DockerComposeRunner.start(runConfig, cb);
      }

      if (type === 'node') {
        if (_.includes(runningServices, runConfig.name)) {
          if (bosco.options.verbose) {
            bosco.warn('Service ' + runConfig.name.green + ' is already running ...');
          } else {
            alreadyRunning++;
          }
          return cb();
        }
        if (bosco.options.verbose) {
          bosco.log('Running node service ' + runConfig.name.green + ' ...');
        }
        return NodeRunner.start(runConfig, cb);
      }

      if (_.includes(runningServices, runConfig.name)) {
        if (bosco.options.verbose) {
          bosco.warn('Service ' + runConfig.name.green + ' is already running ...');
        } else {
          alreadyRunning++;
        }
        return cb();
      }

      bosco.warn('Service ' + runConfig.name.orange + ' could not be run because it was of an unknown type: ' + type.red);

      return cb();
    }

    function runServices(runList, cb) {
      if (runList.services.length < 1) {
        cb();
        return;
      }
      bosco.log('Launching ' + (runList.services.length + '').green + ' ' + runList.type.cyan + ' processes with parallel limit of ' + (runList.limit + '').cyan + ' ...');
      async.mapLimit(runList.services, runList.limit, runService, function(err) {
        if (alreadyRunning > 0 && !bosco.options.verbose) {
          bosco.log('Did not start ' + ('' + alreadyRunning).cyan + ' services that were already running.  Use --verbose to see more detail.');
        }
        cb(err);
      });
    }

    getRunList(function(err, runList) {
      if (err) return next(err);
      var dockerServices = _.filter(runList, function(i) { return i.service.type === 'docker' && _.startsWith(i.name, 'infra-'); });
      var dockerComposeServices = _.filter(runList, function(i) { return i.service.type === 'docker-compose'; });
      var nodeServices = _.filter(runList, function(i) { return _.startsWith(i.name, 'service-') && i.service.type !== 'skip'; });
      var nodeApps = _.filter(runList, function(i) { return _.startsWith(i.name, 'app-') && i.service.type !== 'skip'; });
      var unknownServices = _.filter(runList, function(i) { return !_.includes(['docker', 'docker-compose', 'node', 'skip'], i.service.type); });
      if (unknownServices.length > 0) {
        bosco.error('Unable to run services of un-recognised type: ' + _.map(unknownServices, 'name').join(', ').cyan + '. Check their bosco-service.json configuration.');
        bosco.error('This may be due to either out of date cached content, or missing github org configuration, try the following:');
        /* eslint-disable no-console */
        console.log('');
        console.log('bosco config set github:org tes');
        console.log('bosco run --nocache');
        console.log('');
        /* eslint-enable no-console */
      }
      async.mapSeries([
          {services: dockerServices, type: 'docker', limit: bosco.concurrency.cpu},
          {services: dockerComposeServices, type: 'docker-compose', limit: bosco.concurrency.cpu},
          {services: nodeServices, type: 'service', limit: bosco.concurrency.cpu},
          {services: nodeApps, type: 'app', limit: bosco.concurrency.cpu},
      ], runServices, next);
    });
  }

  function stopNotRunningServices(next) {
    bosco.log('Removing stopped/dead services');
    async.each(notRunningServices, function(service, cb) {
      NodeRunner.stop({name: service}, cb);
    }, next);
  }

  function getRunningServices(next) {
    NodeRunner.listRunning(false, function(err, nodeRunning) {
      DockerRunner.list(false, function(err, dockerRunning) {
        var flatDockerRunning = _.map(_.flatten(dockerRunning), function(item) { return item.replace('/', ''); });
        runningServices = _.union(nodeRunning, flatDockerRunning);
        next();
      });
    });
  }

  function getStoppedServices(next) {
    NodeRunner.listNotRunning(false, function(err, nodeNotRunning) {
      notRunningServices = nodeNotRunning;
      next();
    });
  }

  function ensurePM2(next) {
    // Ensure that the ~/.pm2 folders exist
    var folders = [
      process.env.HOME + '/.pm2/logs',
      process.env.HOME + '/.pm2/pids',
    ];

    async.map(folders, function(folder, cb) {
      fs.mkdirp(folder, cb);
    }, function(err) {
      next(err);
    });
  }

  if (bosco.options.show) {
    bosco.log('Dependency tree for current repo filter:');
    return RunListHelper.getRunList(bosco, repos, repoRegex, watchRegex, repoTag, true, done);
  }

  bosco.log('Run each microservice ... ');

  async.series([ensurePM2, initialiseRunners, getRunningServices, getStoppedServices, stopNotRunningServices, startRunnableServices, disconnectRunners], function(err) {
    if (err) {
      bosco.error(err);
      return done();
    }

    bosco.log('All services started.');
    if (!_.includes(args, 'cdn')) return done();

    var cdn = require('./cdn');
    cdn.cmd(bosco, [], function() {});
  });
}

module.exports.cmd = cmd;
<commit_msg>Un-tesify help messages<commit_after>var _ = require('lodash');
var async = require('async');
var fs = require('fs-extra');

var RunListHelper = require('../src/RunListHelper');
var NodeRunner = require('../src/RunWrappers/Node');
var DockerRunner = require('../src/RunWrappers/Docker');
var DockerComposeRunner = require('../src/RunWrappers/DockerCompose');
var CmdHelper = require('../src/CmdHelper');

var runningServices = [];
var notRunningServices = [];

module.exports = {
  name: 'run',
  description: 'Runs all of the microservices (or subset based on regex pattern)',
  usage: '[-r <repoPattern>] [-t <tag>] [-d]',
  requiresNvm: true,
  options: [
    {
      name: 'tag',
      alias: 't',
      type: 'string',
      desc: 'Filter by a tag defined within bosco-service.json',
    },
    {
      name: 'watch',
      alias: 'w',
      type: 'string',
      desc: 'Watch the applications started with run for changes that match this regular expression',
    },
    {
      name: 'list',
      alias: 'l',
      type: 'string',
      desc: 'Start a list of repos (comma separated)',
    },
    {
      name: 'deps-only',
      alias: 'd',
      type: 'boolean',
      desc: 'Only start the dependencies of the current repo, not itself',
    },
    {
      name: 'show',
      type: 'boolean',
      desc: 'Display the dependency tree but do not start the services',
    },
    {
      name: 'docker-only',
      type: 'boolean',
      desc: 'Only start docker dependencies',
    },
    {
      name: 'team-only',
      type: 'boolean',
      desc: 'Only start app or service dependencies in the current team',
    },
  ],
};

function cmd(bosco, args, allDone) {
  var done = allDone ? allDone : function() {};
  var repoPattern = bosco.options.repo;
  var repoRegex = new RegExp(repoPattern);
  var watchPattern = bosco.options.watch || '$a';
  var watchRegex = new RegExp(watchPattern);
  var repoTag = bosco.options.tag;

  var repos;
  if (bosco.options.list) {
    repos = bosco.options.list.split(',');
  } else {
    CmdHelper.checkInService(bosco);
    repos = bosco.getRepos();
  }

  function initialiseRunners(next) {
    var runners = [NodeRunner, DockerRunner, DockerComposeRunner];
    async.map(runners, function loadRunner(runner, cb) {
      runner.init(bosco, cb);
    }, next);
  }

  function disconnectRunners(next) {
    var runners = [NodeRunner, DockerRunner];
    async.map(runners, function loadRunner(runner, cb) {
      runner.disconnect(cb);
    }, next);
  }

  function getRunList(next) {
    RunListHelper.getRunList(bosco, repos, repoRegex, watchRegex, repoTag, false, next);
  }

  function startRunnableServices(next) {
    var alreadyRunning = 0;

    function runService(runConfig, cb) {
      var type = runConfig.service && runConfig.service.type;

      if (!type || type === 'unknown' || type === 'skip') {
        return cb();
      }

      if (type === 'docker') {
        if (_.includes(runningServices, runConfig.name)) {
          if (bosco.options.verbose) {
            bosco.warn('Service ' + runConfig.name.green + ' is already running ...');
          } else {
            alreadyRunning++;
          }
          return cb();
        }
        if (bosco.options.verbose) {
          bosco.log('Running docker service ' + runConfig.name.green + ' ...');
        }
        return DockerRunner.start(runConfig, function(err) {
          // Log errors from docker but do not stop all tasks
          if (err) {
            bosco.error('There was an error running ' + runConfig.name + ': ' + err);
          }
          cb();
        });
      }

      if (type === 'docker-compose') {
        if (bosco.options.verbose) {
          bosco.log('Running docker-compose ' + runConfig.name.green + ' ...');
        }
        return DockerComposeRunner.start(runConfig, cb);
      }

      if (type === 'node') {
        if (_.includes(runningServices, runConfig.name)) {
          if (bosco.options.verbose) {
            bosco.warn('Service ' + runConfig.name.green + ' is already running ...');
          } else {
            alreadyRunning++;
          }
          return cb();
        }
        if (bosco.options.verbose) {
          bosco.log('Running node service ' + runConfig.name.green + ' ...');
        }
        return NodeRunner.start(runConfig, cb);
      }

      if (_.includes(runningServices, runConfig.name)) {
        if (bosco.options.verbose) {
          bosco.warn('Service ' + runConfig.name.green + ' is already running ...');
        } else {
          alreadyRunning++;
        }
        return cb();
      }

      bosco.warn('Service ' + runConfig.name.orange + ' could not be run because it was of an unknown type: ' + type.red);

      return cb();
    }

    function runServices(runList, cb) {
      if (runList.services.length < 1) {
        cb();
        return;
      }
      bosco.log('Launching ' + (runList.services.length + '').green + ' ' + runList.type.cyan + ' processes with parallel limit of ' + (runList.limit + '').cyan + ' ...');
      async.mapLimit(runList.services, runList.limit, runService, function(err) {
        if (alreadyRunning > 0 && !bosco.options.verbose) {
          bosco.log('Did not start ' + ('' + alreadyRunning).cyan + ' services that were already running.  Use --verbose to see more detail.');
        }
        cb(err);
      });
    }

    getRunList(function(err, runList) {
      if (err) return next(err);
      var dockerServices = _.filter(runList, function(i) { return i.service.type === 'docker' && _.startsWith(i.name, 'infra-'); });
      var dockerComposeServices = _.filter(runList, function(i) { return i.service.type === 'docker-compose'; });
      var nodeServices = _.filter(runList, function(i) { return _.startsWith(i.name, 'service-') && i.service.type !== 'skip'; });
      var nodeApps = _.filter(runList, function(i) { return _.startsWith(i.name, 'app-') && i.service.type !== 'skip'; });
      var unknownServices = _.filter(runList, function(i) { return !_.includes(['docker', 'docker-compose', 'node', 'skip'], i.service.type); });
      if (unknownServices.length > 0) {
        bosco.error('Unable to run services of un-recognised type: ' + _.map(unknownServices, 'name').join(', ').cyan + '. Check their bosco-service.json configuration.');
        bosco.error('This may be due to either out of date cached content, or missing github configuration for your organisation, try the following:');
        /* eslint-disable no-console */
        console.log('');
        console.log('bosco config set github:org <organisation>');
        console.log('bosco run --nocache');
        console.log('');
        /* eslint-enable no-console */
      }
      async.mapSeries([
          {services: dockerServices, type: 'docker', limit: bosco.concurrency.cpu},
          {services: dockerComposeServices, type: 'docker-compose', limit: bosco.concurrency.cpu},
          {services: nodeServices, type: 'service', limit: bosco.concurrency.cpu},
          {services: nodeApps, type: 'app', limit: bosco.concurrency.cpu},
      ], runServices, next);
    });
  }

  function stopNotRunningServices(next) {
    bosco.log('Removing stopped/dead services');
    async.each(notRunningServices, function(service, cb) {
      NodeRunner.stop({name: service}, cb);
    }, next);
  }

  function getRunningServices(next) {
    NodeRunner.listRunning(false, function(err, nodeRunning) {
      DockerRunner.list(false, function(err, dockerRunning) {
        var flatDockerRunning = _.map(_.flatten(dockerRunning), function(item) { return item.replace('/', ''); });
        runningServices = _.union(nodeRunning, flatDockerRunning);
        next();
      });
    });
  }

  function getStoppedServices(next) {
    NodeRunner.listNotRunning(false, function(err, nodeNotRunning) {
      notRunningServices = nodeNotRunning;
      next();
    });
  }

  function ensurePM2(next) {
    // Ensure that the ~/.pm2 folders exist
    var folders = [
      process.env.HOME + '/.pm2/logs',
      process.env.HOME + '/.pm2/pids',
    ];

    async.map(folders, function(folder, cb) {
      fs.mkdirp(folder, cb);
    }, function(err) {
      next(err);
    });
  }

  if (bosco.options.show) {
    bosco.log('Dependency tree for current repo filter:');
    return RunListHelper.getRunList(bosco, repos, repoRegex, watchRegex, repoTag, true, done);
  }

  bosco.log('Run each microservice ... ');

  async.series([ensurePM2, initialiseRunners, getRunningServices, getStoppedServices, stopNotRunningServices, startRunnableServices, disconnectRunners], function(err) {
    if (err) {
      bosco.error(err);
      return done();
    }

    bosco.log('All services started.');
    if (!_.includes(args, 'cdn')) return done();

    var cdn = require('./cdn');
    cdn.cmd(bosco, [], function() {});
  });
}

module.exports.cmd = cmd;
<|endoftext|>


<commit_before>Template.compose.rendered = function () {
  $('.action-label').css('opacity', 0);
  $('.action-label').css('overflow', 'hidden');
  $('.action-icon-mouseover').css('opacity', 0);
};

Template.compose.helpers({
  mouseActive: function () {
    return Session.get('showCompose');
  },
  proposalDrafting: function () {
    if (Meteor.settings.public.app.config.proposalDrafting == false) {
      return false;
    }
    return true;
  }
});

Template.compose.events({
  'mouseover #action-hotspace': function () {
    Session.set('showCompose', true)
    animationIntro();
  },
  'mouseleave #action-hotspace': function () {
    Session.set('showCompose', false)
    animationExit();
  },
  'click #action-hotspace': function () {
    Modules.both.createContract();
  }
});

let animationIntro = () => {
  $('.action-icon-mouseleave').velocity({'opacity': 0}, Modules.client.animationSettings);
  $('.action-icon-mouseover').velocity({'opacity': 1, complete: function () {} }, Modules.client.animationSettings);
  $('.action-label').velocity({'opacity': 1, 'margin-left': '-135px', 'width': '120px'}, Modules.client.animationSettings);
}

let animationExit = () => {
  $('.action-icon-mouseleave').velocity({'opacity': 1}, Modules.client.animationSettings);
  $('.action-icon-mouseover').velocity({'opacity': 0}, Modules.client.animationSettings);
  $('.action-label').velocity({'opacity': 0, 'margin-left': -115, 'width': '0px'}, Modules.client.animationSettings);
}
<commit_msg>add imports, rp Modules.both w imp<commit_after>import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { Session } from 'meteor/session';
import { $ } from 'meteor/jquery';

import { createContract } from '/imports/startup/both/modules/Contract';

Template.compose.onRendered = function onRender() {
  $('.action-label').css('opacity', 0);
  $('.action-label').css('overflow', 'hidden');
  $('.action-icon-mouseover').css('opacity', 0);
};

Template.compose.helpers({
  mouseActive: function () {
    return Session.get('showCompose');
  },
  proposalDrafting: function () {
    if (Meteor.settings.public.app.config.proposalDrafting == false) {
      return false;
    }
    return true;
  }
});

Template.compose.events({
  'mouseover #action-hotspace': function () {
    Session.set('showCompose', true)
    animationIntro();
  },
  'mouseleave #action-hotspace': function () {
    Session.set('showCompose', false)
    animationExit();
  },
  'click #action-hotspace': function () {
    createContract();
  }
});

let animationIntro = () => {
  $('.action-icon-mouseleave').velocity({'opacity': 0}, Modules.client.animationSettings);
  $('.action-icon-mouseover').velocity({'opacity': 1, complete: function () {} }, Modules.client.animationSettings);
  $('.action-label').velocity({'opacity': 1, 'margin-left': '-135px', 'width': '120px'}, Modules.client.animationSettings);
}

let animationExit = () => {
  $('.action-icon-mouseleave').velocity({'opacity': 1}, Modules.client.animationSettings);
  $('.action-icon-mouseover').velocity({'opacity': 0}, Modules.client.animationSettings);
  $('.action-label').velocity({'opacity': 0, 'margin-left': -115, 'width': '0px'}, Modules.client.animationSettings);
}
<|endoftext|>


<commit_before>/*!========================================================================
 * listgroup.js v1.1.0
 * http://rickardn.github.io/listgroup.js
 * ========================================================================
 * Copyright 2014 Rickard Nilsson
 * Licensed under MIT (https://github.com/rickardn/listgroup.js/blob/master/LICENSE)
 * ======================================================================== */

+function ($) {
    "use strict";

    // LISTGROUP PUBLIC CLASS DEFINITION
    // =======================
    var ListGroup = function (element, options) {
        this.$element = $(element);
        this.options = options || {};
        this.init();
    };

    ListGroup.prototype.init = function() {
        var me = this;
        var $element = this.$element;
        var options = this.options;

        if (options.toggle)
            $element.data('toggle', options.toggle);

        $element.on('click', '.list-group-item', function () {
            var $item = $(this);

            if (!$item.hasClass('disabled')) {

                if ($element.data('toggle') == 'buttons')
                    $item.toggleClass('active');
                else
                    me.unselect('*')
                      .select($item);

                if (options.click)
                    options.click.apply(this);
            }

            $item.blur();
            return false;
        });
    };

    ListGroup.prototype.select = function (item) {
        if (item instanceof $)
            item.addClass('active');

        if (typeof item === 'string')
            item = [item];

        if (Array.isArray(item)) {
            for (var i in item) {
                var val = item[i];
                this.$element
                    .find('.list-group-item[data-value=\'' + val + '\']')
                    .addClass('active');
            }
        }
        return this;
    };

    ListGroup.prototype.unselect = function (selector) {
        this.$element
                .find('.list-group-item')
                .filter(selector || '*')
                    .removeClass('active');
        return this;
    };

    // SELECTLIST PUBLIC CLASS DEFINITION
    // =======================
    var SelectList = function(element, options) {
        this.$element = $(element);
        this.options = options;
        this.$listGroup = this.createListGroup();
    };

    SelectList.prototype.select = function (values) {
        if (values instanceof $) {
            var vals = [];
            values.each(function(i, element) {
                vals.push($(element).val());
            });
            values = vals;
        }

        this.$element.val(values)
                     .change();
    };

    SelectList.prototype.unselect = function(values) {
        var value = this.$element.val();

        if (!Array.isArray(value)) value = [value];
        if (!Array.isArray(values)) values = [values];

        for (var i in values)
            value.pop(values[i]);

        this.$element.val(value)
                     .change();
    };

    SelectList.prototype.createListGroup = function() {
        var $select = this.$element;

        var $listGroup = $('<ul>').addClass('list-group');

        if ($select.attr('multiple'))
            $listGroup.attr('data-toggle', 'buttons');

        $select.find('option').each(function (i, item) {
            var $item = $(item);

            var $new = $('<a>')
                        .attr('href', '#')
                        .addClass('list-group-item')
                        .attr('data-value', $item.val())
                        .text($item.text());

            if ($item.is(':disabled'))
                $new.addClass('disabled');

            $listGroup.append($new);
        });

        $select.change(function () {
            $listGroup.listgroup({
                unselect: '*',
                select: $select.val()
            });
        });

        $listGroup.listgroup({
            select: $select.val(),
            click: function () {
                var values = [];
                $listGroup.find('.list-group-item.active').each(function(i, item) {
                    var value = $(item).data('value');
                    values.push(value);
                });
                if (values.length == 1) values = values[0];
                $select.val(values);
            }
        });
        $select.before($listGroup);
        this.$listGroup = $listGroup;

        $select.hide();

        return $listGroup;
    };

    // LIST GROUP PLUGIN DEFINITION
    // =======================
    $.fn.listgroup = function (option) {
        return this.each(function (i, element) {
            var $element = $(element);

            var list = $element.data('listgroup');
            if (!list)
                $element.data('listgroup', (list = $element.is('select')
                    ? new SelectList(element, option)
                    : new ListGroup(element, option)));

            if (option) {

                if (option.unselect)
                    list.unselect(option.unselect);

                if (option.select)
                    list.select(option.select);
            }
        });
    };

    $(function () {
        $('.list-group').listgroup();
    });
}(jQuery);
<commit_msg>Setting data- attributes visible in the dom instead of hidden<commit_after>/*!========================================================================
 * listgroup.js v1.1.0
 * http://rickardn.github.io/listgroup.js
 * ========================================================================
 * Copyright 2014 Rickard Nilsson
 * Licensed under MIT (https://github.com/rickardn/listgroup.js/blob/master/LICENSE)
 * ======================================================================== */

+function ($) {
    "use strict";

    // LISTGROUP PUBLIC CLASS DEFINITION
    // =======================
    var ListGroup = function (element, options) {
        this.$element = $(element);
        this.options = options || {};
        this.init();
    };

    ListGroup.prototype.init = function() {
        var me = this;
        var $element = this.$element;
        var options = this.options;

        if (options.toggle)
            $element.attr('data-toggle', options.toggle);

        $element.on('click', '.list-group-item', function () {
            var $item = $(this);

            if (!$item.hasClass('disabled')) {

                if ($element.data('toggle') == 'buttons')
                    $item.toggleClass('active');
                else
                    me.unselect('*')
                      .select($item);

                if (options.click)
                    options.click.apply(this);
            }

            $item.blur();
            return false;
        });
    };

    ListGroup.prototype.select = function (item) {
        if (item instanceof $)
            item.addClass('active');

        if (typeof item === 'string')
            item = [item];

        if (Array.isArray(item)) {
            for (var i in item) {
                var val = item[i];
                this.$element
                    .find('.list-group-item[data-value=\'' + val + '\']')
                    .addClass('active');
            }
        }
        return this;
    };

    ListGroup.prototype.unselect = function (selector) {
        this.$element
                .find('.list-group-item')
                .filter(selector || '*')
                    .removeClass('active');
        return this;
    };

    // SELECTLIST PUBLIC CLASS DEFINITION
    // =======================
    var SelectList = function(element, options) {
        this.$element = $(element);
        this.options = options;
        this.$listGroup = this.createListGroup();
    };

    SelectList.prototype.select = function (values) {
        if (values instanceof $) {
            var vals = [];
            values.each(function(i, element) {
                vals.push($(element).val());
            });
            values = vals;
        }

        this.$element.val(values)
                     .change();
    };

    SelectList.prototype.unselect = function(values) {
        var value = this.$element.val();

        if (!Array.isArray(value)) value = [value];
        if (!Array.isArray(values)) values = [values];

        for (var i in values)
            value.pop(values[i]);

        this.$element.val(value)
                     .change();
    };

    SelectList.prototype.createListGroup = function() {
        var $select = this.$element;

        var $listGroup = $('<ul>').addClass('list-group');

        if ($select.attr('multiple'))
            $listGroup.attr('data-toggle', 'buttons');

        $select.find('option').each(function (i, item) {
            var $item = $(item);

            var $new = $('<a>')
                        .attr('href', '#')
                        .addClass('list-group-item')
                        .attr('data-value', $item.val())
                        .text($item.text());

            if ($item.is(':disabled'))
                $new.addClass('disabled');

            $listGroup.append($new);
        });

        $select.change(function () {
            $listGroup.listgroup({
                unselect: '*',
                select: $select.val()
            });
        });

        $listGroup.listgroup({
            select: $select.val(),
            click: function () {
                var values = [];
                $listGroup.find('.list-group-item.active').each(function(i, item) {
                    var value = $(item).data('value');
                    values.push(value);
                });
                if (values.length == 1) values = values[0];
                $select.val(values);
            }
        });
        $select.before($listGroup);
        this.$listGroup = $listGroup;

        $select.hide();

        return $listGroup;
    };

    // LIST GROUP PLUGIN DEFINITION
    // =======================
    $.fn.listgroup = function (option) {
        return this.each(function (i, element) {
            var $element = $(element);

            var list = $element.data('listgroup');
            if (!list)
                $element.data('listgroup', (list = $element.is('select')
                    ? new SelectList(element, option)
                    : new ListGroup(element, option)));

            if (option) {

                if (option.unselect)
                    list.unselect(option.unselect);

                if (option.select)
                    list.select(option.select);
            }
        });
    };

    $(function () {
        $('.list-group').listgroup();
    });
}(jQuery);
<|endoftext|>


<commit_before>/**
 * Sourced from: https://gist.github.com/parasyte/9712366
 * Extend a class prototype with the provided mixin descriptors.
 * Designed as a faster replacement for John Resig's Simple Inheritance.
 * @name extend
 * @memberOf external:Object#
 * @function
 * @param {Object[]} mixins... Each mixin is a dictionary of functions, or a
 * previously extended class whose methods will be applied to the target class
 * prototype.
 * @return {Object}
 * @example
 * var Person = Object.extend({
 *     "init" : function (isDancing) {
 *         this.dancing = isDancing;
 *     },
 *     "dance" : function () {
 *         return this.dancing;
 *     }
 * });
 *
 * var Ninja = Person.extend({
 *     "init" : function () {
 *         // Call the super constructor, passing a single argument
 *         this._super(Person, "init", [false]);
 *     },
 *     "dance" : function () {
 *         // Call the overridden dance() method
 *         return this._super(Person, "dance");
 *     },
 *     "swingSword" : function () {
 *         return true;
 *     }
 * });
 *
 * var Pirate = Person.extend(Ninja, {
 *     "init" : function () {
 *         // Call the super constructor, passing a single argument
 *         this._super(Person, "init", [true]);
 *     }
 * });
 *
 * var p = new Person(true);
 * console.log(p.dance()); // => true
 *
 * var n = new Ninja();
 * console.log(n.dance()); // => false
 * console.log(n.swingSword()); // => true
 *
 * var r = new Pirate();
 * console.log(r.dance()); // => true
 * console.log(r.swingSword()); // => true
 *
 * console.log(
 *     p instanceof Person &&
 *     n instanceof Ninja &&
 *     n instanceof Person &&
 *     r instanceof Pirate &&
 *     r instanceof Person
 * ); // => true
 *
 * console.log(r instanceof Ninja); // => false
 */
(function () {
    Object.defineProperty(Object.prototype, "extend", {
        "value" : function () {
            var methods = {};
            var mixins = Array.prototype.slice.call(arguments, 0);

            /**
             * The class constructor which calls the user `init` constructor.
             * @ignore
             */
            function Class() {
                // Call the user constructor
                this.init.apply(this, arguments);
                return this;
            }

            // Apply superClass
            Class.prototype = Object.create(this.prototype);

            // Apply all mixin methods to the class prototype
            mixins.forEach(function (mixin) {
                apply_methods(Class, methods, mixin.__methods__ || mixin);
            });

            // Verify constructor exists
            if (!("init" in Class.prototype)) {
                throw new TypeError(
                    "extend: Class is missing a constructor named `init`"
                );
            }

            // Apply syntactic sugar for accessing methods on super classes
            Object.defineProperty(Class.prototype, "_super", {
                "value" : _super
            });

            // Create a hidden property on the class itself
            // List of methods, used for applying classes as mixins
            Object.defineProperty(Class, "__methods__", {
                "value" : methods
            });

            return Class;
        }
    });

    /**
     * Apply methods to the class prototype.
     * @ignore
     */
    function apply_methods(Class, methods, descriptor) {
        Object.keys(descriptor).forEach(function (method) {
            methods[method] = descriptor[method];

            if (typeof(descriptor[method]) !== "function") {
                throw new TypeError(
                    "extend: Method `" + method + "` is not a function"
                );
            }

            Object.defineProperty(Class.prototype, method, {
                "configurable" : true,
                "value" : descriptor[method]
            });
        });
    }

    /**
     * Special method that acts as a proxy to the super class.
     * @name _super
     * @ignore
     */
    function _super(superClass, method, args) {
        return superClass.prototype[method].apply(this, args);
    }
})();
<commit_msg>Performance: Prevent V8 deopt by iterating `arguments` instead of slicing it.<commit_after>/**
 * Sourced from: https://gist.github.com/parasyte/9712366
 * Extend a class prototype with the provided mixin descriptors.
 * Designed as a faster replacement for John Resig's Simple Inheritance.
 * @name extend
 * @memberOf external:Object#
 * @function
 * @param {Object[]} mixins... Each mixin is a dictionary of functions, or a
 * previously extended class whose methods will be applied to the target class
 * prototype.
 * @return {Object}
 * @example
 * var Person = Object.extend({
 *     "init" : function (isDancing) {
 *         this.dancing = isDancing;
 *     },
 *     "dance" : function () {
 *         return this.dancing;
 *     }
 * });
 *
 * var Ninja = Person.extend({
 *     "init" : function () {
 *         // Call the super constructor, passing a single argument
 *         this._super(Person, "init", [false]);
 *     },
 *     "dance" : function () {
 *         // Call the overridden dance() method
 *         return this._super(Person, "dance");
 *     },
 *     "swingSword" : function () {
 *         return true;
 *     }
 * });
 *
 * var Pirate = Person.extend(Ninja, {
 *     "init" : function () {
 *         // Call the super constructor, passing a single argument
 *         this._super(Person, "init", [true]);
 *     }
 * });
 *
 * var p = new Person(true);
 * console.log(p.dance()); // => true
 *
 * var n = new Ninja();
 * console.log(n.dance()); // => false
 * console.log(n.swingSword()); // => true
 *
 * var r = new Pirate();
 * console.log(r.dance()); // => true
 * console.log(r.swingSword()); // => true
 *
 * console.log(
 *     p instanceof Person &&
 *     n instanceof Ninja &&
 *     n instanceof Person &&
 *     r instanceof Pirate &&
 *     r instanceof Person
 * ); // => true
 *
 * console.log(r instanceof Ninja); // => false
 */
(function () {
    Object.defineProperty(Object.prototype, "extend", {
        "value" : function () {
            var methods = {};
            var mixins = new Array(arguments.length);
            for (var i = 0; i < arguments.length; i++) {
                mixins.push(arguments[i]);
            }

            /**
             * The class constructor which calls the user `init` constructor.
             * @ignore
             */
            function Class() {
                // Call the user constructor
                this.init.apply(this, arguments);
                return this;
            }

            // Apply superClass
            Class.prototype = Object.create(this.prototype);

            // Apply all mixin methods to the class prototype
            mixins.forEach(function (mixin) {
                apply_methods(Class, methods, mixin.__methods__ || mixin);
            });

            // Verify constructor exists
            if (!("init" in Class.prototype)) {
                throw new TypeError(
                    "extend: Class is missing a constructor named `init`"
                );
            }

            // Apply syntactic sugar for accessing methods on super classes
            Object.defineProperty(Class.prototype, "_super", {
                "value" : _super
            });

            // Create a hidden property on the class itself
            // List of methods, used for applying classes as mixins
            Object.defineProperty(Class, "__methods__", {
                "value" : methods
            });

            return Class;
        }
    });

    /**
     * Apply methods to the class prototype.
     * @ignore
     */
    function apply_methods(Class, methods, descriptor) {
        Object.keys(descriptor).forEach(function (method) {
            methods[method] = descriptor[method];

            if (typeof(descriptor[method]) !== "function") {
                throw new TypeError(
                    "extend: Method `" + method + "` is not a function"
                );
            }

            Object.defineProperty(Class.prototype, method, {
                "configurable" : true,
                "value" : descriptor[method]
            });
        });
    }

    /**
     * Special method that acts as a proxy to the super class.
     * @name _super
     * @ignore
     */
    function _super(superClass, method, args) {
        return superClass.prototype[method].apply(this, args);
    }
})();
<|endoftext|>


<commit_before>var _ = require('lodash');
var async = require('async');
var NodeRunner = require('../src/RunWrappers/Node');
var DockerRunner = require('../src/RunWrappers/Docker');
var mkdirp = require('mkdirp');
var runningServices = [];
var notRunningServices = [];

module.exports = {
    name: 'run',
    description: 'Runs all of the microservices (or subset based on regex pattern)',
    example: 'bosco run -r <repoPattern> -t <tag>',
    cmd: cmd,
    options: [{
        option: 'tag',
        syntax: ['-t, --tag [tag]', 'Filter by a tag defined within bosco-service.json']
    },
    {
        option: 'watch',
        syntax: ['-w, --watch', 'Watch the applications started with run for changes']
    },
    {
        option: 'list',
        syntax: ['-l, --list [list]', 'Start a list of repos (comma separated).']
    },
    {
        option: 'cdn',
        syntax: ['-c, --cdn', 'Run bosco cdn as a service']
    }
    ]
}

function cmd(bosco, args, cb) {

    var repoPattern = bosco.options.repo;
    var repoRegex = new RegExp(repoPattern);
    var watchPattern = bosco.options.watch || '$a';
    var watchRegex = new RegExp(watchPattern);
    var repoTag = bosco.options.tag;

    var repos;
    if(bosco.options.list) {
        repos = bosco.options.list.split(',');
    } else {
        repos = bosco.getRepos();
    }

    var initialiseRunners = function(next) {
        var runners = [NodeRunner, DockerRunner];
        async.map(runners, function loadRunner(runner, cb) {
            runner.init(bosco, cb);
        }, next);
    }

     var disconnectRunners = function(next) {
        var runners = [NodeRunner, DockerRunner];
        async.map(runners, function loadRunner(runner, cb) {
            runner.disconnect(cb);
        }, next);
    }

    var getRunConfig = function(repo) {

        var pkg, svc,
            repoPath = bosco.getRepoPath(repo),
            watch = repo.match(watchRegex) ? true : false,
            packageJson = [repoPath, 'package.json'].join('/'),
            boscoService = [repoPath, 'bosco-service.json'].join('/'),
            svcConfig = {
                name: repo,
                cwd: repoPath,
                watch: watch,
                service: {}
            };

        if (bosco.exists(packageJson)) {
            pkg = require(packageJson);
            if (pkg.scripts && pkg.scripts.start) {
                svcConfig = _.extend(svcConfig, {
                    service: {
                        type: 'node',
                        start: pkg.scripts.start
                    }
                });
            }
        }

        if (bosco.exists(boscoService)) {
            svc = require(boscoService);
            svcConfig = _.extend(svcConfig, {
                tags: svc.tags,
                order: svc.order
            });
            if (svc.service) {
                svcConfig.service = _.extend(svcConfig.service, svc.service);
            }
        }

        return svcConfig;

    }

    var getRunList = function(next) {

        var depTree = {};
        var revDepTree = {};
        var repoList = [];
        var runList = [];
        var svcConfig;
        var addDependencies = function(dependent, dependsOn) {
            dependsOn.forEach(function(dependency) {
                if(!_.contains(repoList, dependency)) repoList.push(dependency); // Ensures we then check the dependcies of depencies

                revDepTree[dependency] = revDepTree[dependency] || [];
                revDepTree[dependency].push(dependent);
            });
        }

        // First build the tree and filtered core list
        repos.forEach(function(repo) {
            svcConfig = getRunConfig(repo);
            depTree[svcConfig.name] = svcConfig;
            if ((!repoTag && repo.match(repoRegex)) || (repoTag && _.contains(svcConfig.tags, repoTag))) {
                repoList.push(repo);
            }
        });

        // If we are running the cdn at the same time.
        if (bosco.options.cdn) {
          svcConfig = {
            name: 'bosco-cdn',
            cwd: __dirname.substring(0, __dirname.indexOf('/commands')),
            watch: false,
            service: {
              type: 'node',
              start: 'node bin/bosco.js -- cdn'
            }
          }
          runList.push(svcConfig);
        }

        // Now iterate, but use the dependency tree to build the run list
        while (repoList.length > 0) {
            var currentRepo = repoList.shift();
            svcConfig = depTree[currentRepo];
            if (!svcConfig) return next(new Error('Trying to run ' + currentRepo + ' which does not exist on the list of repos. This is a dependency for ' + revDepTree[currentRepo]));

            if (svcConfig.service) {
                runList.push(svcConfig);
                if (svcConfig.service.dependsOn) {
                    addDependencies(currentRepo, svcConfig.service.dependsOn);
                }
            }
        }

        // Uniq and sort
        runList = _.chain(runList)
            .uniq(function(item) { return item.name; })
            .sortBy(function(item) {
                if (item.order) return item.order;
                return item.service.type === 'docker' ? 100 : 500
            }).value();

        next(null, runList);

    }

    var startRunnableServices = function(next) {

        getRunList(function(err, runList) {
            if (err) return next(err);

            async.mapSeries(runList, function(runConfig, cb) {
                if (runConfig.service && runConfig.service.type == 'docker') {
                    if (_.contains(runningServices, runConfig.name)) {
                        bosco.warn('Service ' + runConfig.name.green + ' is already running ...');
                        return cb();
                    }
                    bosco.log('Running docker service ' + runConfig.name.green + ' ...');
                    return DockerRunner.start(runConfig, cb);
                }

                if (runConfig.service && runConfig.service.type == 'node') {
                    if (_.contains(runningServices, runConfig.name)) {
                        bosco.warn('Service ' + runConfig.name.green + ' is already running ...');
                        return cb();
                    }
                    return NodeRunner.start(runConfig, cb);
                }
                cb();
            }, next);
        })

    }

    var stopNotRunningServices = function(next) {
        bosco.log('Removing stopped/dead services');

        async.each(notRunningServices, function(service, cb){
            NodeRunner.stop({name: service}, cb);
        }, next);
    };

    var getRunningServices = function(next) {
        NodeRunner.listRunning(false, function(err, nodeRunning) {
            DockerRunner.list(false, function(err, dockerRunning) {
                dockerRunning = _.map(_.flatten(dockerRunning), function(item) { return item.replace('/',''); });
                runningServices = _.union(nodeRunning, dockerRunning);
                next();
            });
        });
    }

    var getStoppedServices = function(next) {
        NodeRunner.listNotRunning(false, function(err, nodeNotRunning) {
            notRunningServices = nodeNotRunning;
            next();
        });
    };

    var ensurePM2 = function(next) {

        // Ensure that the ~/.pm2 folders exist
        var folders = [
            process.env.HOME + '/.pm2/logs',
            process.env.HOME + '/.pm2/pids'
        ];

        async.map(folders, function(folder, cb) {
            mkdirp(folder, function (err) {
                cb(err);
            });
        },function(err) {
            next(err);
        });

    }

    bosco.log('Run each microservice ... ');

    async.series([ensurePM2, initialiseRunners, getRunningServices, getStoppedServices, stopNotRunningServices, startRunnableServices, disconnectRunners], function(err) {
        if (err) {
            bosco.error(err);
            if (cb) cb();

            return;
        }

        bosco.log('All services started.');
        if(_.contains(args, 'cdn')) {
            var cdn = require('./cdn');
            cdn.cmd(bosco, [], function() {});
        } else {
            if(cb) return cb();
        }
    })

}
<commit_msg>Remove run-cdn for now, just use ```bosco run -t summary cdn```<commit_after>var _ = require('lodash');
var async = require('async');
var NodeRunner = require('../src/RunWrappers/Node');
var DockerRunner = require('../src/RunWrappers/Docker');
var mkdirp = require('mkdirp');
var runningServices = [];
var notRunningServices = [];

module.exports = {
    name: 'run',
    description: 'Runs all of the microservices (or subset based on regex pattern)',
    example: 'bosco run -r <repoPattern> -t <tag>',
    cmd: cmd,
    options: [{
        option: 'tag',
        syntax: ['-t, --tag [tag]', 'Filter by a tag defined within bosco-service.json']
    },
    {
        option: 'watch',
        syntax: ['-w, --watch', 'Watch the applications started with run for changes']
    },
    {
        option: 'list',
        syntax: ['-l, --list [list]', 'Start a list of repos (comma separated).']
    }
    ]
}

function cmd(bosco, args, cb) {

    var repoPattern = bosco.options.repo;
    var repoRegex = new RegExp(repoPattern);
    var watchPattern = bosco.options.watch || '$a';
    var watchRegex = new RegExp(watchPattern);
    var repoTag = bosco.options.tag;

    var repos;
    if(bosco.options.list) {
        repos = bosco.options.list.split(',');
    } else {
        repos = bosco.getRepos();
    }

    var initialiseRunners = function(next) {
        var runners = [NodeRunner, DockerRunner];
        async.map(runners, function loadRunner(runner, cb) {
            runner.init(bosco, cb);
        }, next);
    }

     var disconnectRunners = function(next) {
        var runners = [NodeRunner, DockerRunner];
        async.map(runners, function loadRunner(runner, cb) {
            runner.disconnect(cb);
        }, next);
    }

    var getRunConfig = function(repo) {

        var pkg, svc,
            repoPath = bosco.getRepoPath(repo),
            watch = repo.match(watchRegex) ? true : false,
            packageJson = [repoPath, 'package.json'].join('/'),
            boscoService = [repoPath, 'bosco-service.json'].join('/'),
            svcConfig = {
                name: repo,
                cwd: repoPath,
                watch: watch,
                service: {}
            };

        if (bosco.exists(packageJson)) {
            pkg = require(packageJson);
            if (pkg.scripts && pkg.scripts.start) {
                svcConfig = _.extend(svcConfig, {
                    service: {
                        type: 'node',
                        start: pkg.scripts.start
                    }
                });
            }
        }

        if (bosco.exists(boscoService)) {
            svc = require(boscoService);
            svcConfig = _.extend(svcConfig, {
                tags: svc.tags,
                order: svc.order
            });
            if (svc.service) {
                svcConfig.service = _.extend(svcConfig.service, svc.service);
            }
        }

        return svcConfig;

    }

    var getRunList = function(next) {

        var depTree = {};
        var revDepTree = {};
        var repoList = [];
        var runList = [];
        var svcConfig;
        var addDependencies = function(dependent, dependsOn) {
            dependsOn.forEach(function(dependency) {
                if(!_.contains(repoList, dependency)) repoList.push(dependency); // Ensures we then check the dependcies of depencies

                revDepTree[dependency] = revDepTree[dependency] || [];
                revDepTree[dependency].push(dependent);
            });
        }

        // First build the tree and filtered core list
        repos.forEach(function(repo) {
            svcConfig = getRunConfig(repo);
            depTree[svcConfig.name] = svcConfig;
            if ((!repoTag && repo.match(repoRegex)) || (repoTag && _.contains(svcConfig.tags, repoTag))) {
                repoList.push(repo);
            }
        });

        // Now iterate, but use the dependency tree to build the run list
        while (repoList.length > 0) {
            var currentRepo = repoList.shift();
            svcConfig = depTree[currentRepo];
            if (!svcConfig) return next(new Error('Trying to run ' + currentRepo + ' which does not exist on the list of repos. This is a dependency for ' + revDepTree[currentRepo]));

            if (svcConfig.service) {
                runList.push(svcConfig);
                if (svcConfig.service.dependsOn) {
                    addDependencies(currentRepo, svcConfig.service.dependsOn);
                }
            }
        }

        // Uniq and sort
        runList = _.chain(runList)
            .uniq(function(item) { return item.name; })
            .sortBy(function(item) {
                if (item.order) return item.order;
                return item.service.type === 'docker' ? 100 : 500
            }).value();

        next(null, runList);

    }

    var startRunnableServices = function(next) {

        getRunList(function(err, runList) {
            if (err) return next(err);

            async.mapSeries(runList, function(runConfig, cb) {
                if (runConfig.service && runConfig.service.type == 'docker') {
                    if (_.contains(runningServices, runConfig.name)) {
                        bosco.warn('Service ' + runConfig.name.green + ' is already running ...');
                        return cb();
                    }
                    bosco.log('Running docker service ' + runConfig.name.green + ' ...');
                    return DockerRunner.start(runConfig, cb);
                }

                if (runConfig.service && runConfig.service.type == 'node') {
                    if (_.contains(runningServices, runConfig.name)) {
                        bosco.warn('Service ' + runConfig.name.green + ' is already running ...');
                        return cb();
                    }
                    return NodeRunner.start(runConfig, cb);
                }
                cb();
            }, next);
        })

    }

    var stopNotRunningServices = function(next) {
        bosco.log('Removing stopped/dead services');

        async.each(notRunningServices, function(service, cb){
            NodeRunner.stop({name: service}, cb);
        }, next);
    };

    var getRunningServices = function(next) {
        NodeRunner.listRunning(false, function(err, nodeRunning) {
            DockerRunner.list(false, function(err, dockerRunning) {
                dockerRunning = _.map(_.flatten(dockerRunning), function(item) { return item.replace('/',''); });
                runningServices = _.union(nodeRunning, dockerRunning);
                next();
            });
        });
    }

    var getStoppedServices = function(next) {
        NodeRunner.listNotRunning(false, function(err, nodeNotRunning) {
            notRunningServices = nodeNotRunning;
            next();
        });
    };

    var ensurePM2 = function(next) {

        // Ensure that the ~/.pm2 folders exist
        var folders = [
            process.env.HOME + '/.pm2/logs',
            process.env.HOME + '/.pm2/pids'
        ];

        async.map(folders, function(folder, cb) {
            mkdirp(folder, function (err) {
                cb(err);
            });
        },function(err) {
            next(err);
        });

    }

    bosco.log('Run each microservice ... ');

    async.series([ensurePM2, initialiseRunners, getRunningServices, getStoppedServices, stopNotRunningServices, startRunnableServices, disconnectRunners], function(err) {
        if (err) {
            bosco.error(err);
            if (cb) cb();

            return;
        }

        bosco.log('All services started.');
        if(_.contains(args, 'cdn')) {
            var cdn = require('./cdn');
            cdn.cmd(bosco, [], function() {});
        } else {
            if(cb) return cb();
        }
    })

}
<|endoftext|>


<commit_before>var RestClient = require('rest-facade').Client;
var MetadataUpdater = require('./MetadataUpdater');

/**
 * @class
 * Abstracts interaction with the users endpoint.
 * @constructor
 */
var UsersManager = function (options){
  var clientOptions = {
    headers: { 'Authorization': 'Bearer ' + options.accessToken },
    query: { convertCase: 'snakeCase', repeatParams: false }
  };

  this.resource = new RestClient(options.baseUrl + '/users/:userId', clientOptions);
  this.metadataUpdater = new MetadataUpdater(options);
};

/**
 * Create a new user.
 *
 * @method
 * @param   {Object}    data    User data.
 * @param   {Function}  [cb]    Callback function.
 * @return  {Promise}           User creation promise.
 */
UsersManager.prototype.create = function (data, cb) {
  return this.resource.create(data, cb);
};

/**
 * Get all users.
 *
 * @method
 * @param   {Function}  [cb]  Callback function.
 * @return  {Promise}         UsersManager retrieval promise.
 */
UsersManager.prototype.getAll = function () {
  return this.resource.getAll.apply(this.resource, arguments);
};

/**
 * Get a user by its id.
 *
 * @method
 * @param   {any}       id    The user id.
 * @param   {Function}  [cb]  Callback function.
 * @return  {Promise}         User retrieval promise.
 */
UsersManager.prototype.get = function () {
  return this.resource.get.apply(this.resource, arguments);
};

/**
 * Update a user by its id.
 *
 * @method
 * @param   {any}       params  The user id.
 * @param   {Object}    data    New user data.
 * @param   {Function}  [cb]    Callback function
 * @return  {Promise}           User update promise.
 */
UsersManager.prototype.update = function () {
  return this.resource.update.apply(this.resource, arguments);
};

/**
 * Delete a user by its id.
 *
 * @method
 * @return  {Promise}           User delete promise.
 */
UsersManager.prototype.delete = function () {
  return this.resource.delete.apply(this.resource, arguments);
};

UsersManager.prototype.updateAppMetadata = function(id, updatedMetadata, cb){
  return this.metadataUpdater.update(id, {
    updatedMetadata: updatedMetadata,
    type: 'app_metadata'
  }, cb);
};

UsersManager.prototype.updateUserMetadata = function(id, updatedMetadata, cb){
  return this.metadataUpdater.update(id, {
    updatedMetadata: updatedMetadata,
    type: 'user_metadata'
  }, cb);
};

module.exports = UsersManager;
<commit_msg>Add deleteAll method to the UsersManager<commit_after>var RestClient = require('rest-facade').Client;
var MetadataUpdater = require('./MetadataUpdater');
var ArgumentError = require('./exceptions').ArgumentError;

/**
 * @class
 * Abstracts interaction with the users endpoint.
 * @constructor
 */
var UsersManager = function (options){
  var clientOptions = {
    headers: { 'Authorization': 'Bearer ' + options.accessToken },
    query: { convertCase: 'snakeCase', repeatParams: false }
  };

  this.resource = new RestClient(options.baseUrl + '/users/:userId', clientOptions);
  this.metadataUpdater = new MetadataUpdater(options);
};

/**
 * Create a new user.
 *
 * @method
 * @param   {Object}    data    User data.
 * @param   {Function}  [cb]    Callback function.
 * @return  {Promise}           User creation promise.
 */
UsersManager.prototype.create = function (data, cb) {
  return this.resource.create(data, cb);
};

/**
 * Get all users.
 *
 * @method
 * @param   {Function}  [cb]  Callback function.
 * @return  {Promise}         UsersManager retrieval promise.
 */
UsersManager.prototype.getAll = function () {
  return this.resource.getAll.apply(this.resource, arguments);
};

/**
 * Get a user by its id.
 *
 * @method
 * @param   {any}       id    The user id.
 * @param   {Function}  [cb]  Callback function.
 * @return  {Promise}         User retrieval promise.
 */
UsersManager.prototype.get = function () {
  return this.resource.get.apply(this.resource, arguments);
};

/**
 * Update a user by its id.
 *
 * @method
 * @param   {any}       params  The user id.
 * @param   {Object}    data    New user data.
 * @param   {Function}  [cb]    Callback function
 * @return  {Promise}           User update promise.
 */
UsersManager.prototype.update = function () {
  return this.resource.update.apply(this.resource, arguments);
};

/**
 * Delete a user by its id.
 *
 * @method
 * @return  {Promise}           User delete promise.
 */
UsersManager.prototype.delete = function (params) {
  if (typeof params !== 'object') {
    throw new ArgumentError('You must provide an id for the delete method');
  }

  return this.resource.delete.apply(this.resource, arguments);
};

/**
 * Delete all users.
 *
 * @method
 * @return  {Promise}
 */
UsersManager.prototype.deleteAll = function (cb) {
  if (typeof cb !== 'function') {
    throw new ArgumentError('The deleteAll method only accepts a callback as argument');
  }

  return this.resource.delete.apply(this.resource, arguments);
};

UsersManager.prototype.updateAppMetadata = function(id, updatedMetadata, cb){
  return this.metadataUpdater.update(id, {
    updatedMetadata: updatedMetadata,
    type: 'app_metadata'
  }, cb);
};

UsersManager.prototype.updateUserMetadata = function(id, updatedMetadata, cb){
  return this.metadataUpdater.update(id, {
    updatedMetadata: updatedMetadata,
    type: 'user_metadata'
  }, cb);
};

module.exports = UsersManager;
<|endoftext|>


<commit_before>const logger = require('../../../logger')();
const rp = require('request-promise');
const cheerio = require('cheerio');
const mongo = require('../../../mongo');
const iconv = require('iconv-lite');

module.exports = {
    // return true the task will be add to manager
    async beforeAddTask(task) {
        return true;
    },
    // set task.status 'success' or 'failed'
    // only task.result will persist to db, even though task failed
    async doTask(task) {
        try {
            let headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
                "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
                "Accept-Encoding": "gzip, deflate, br",
                "Accept-Language": "zh-CN,zh;q=0.8",
            };

            let res = await rp.get({
                uri: `http://yxpjwnet.com/page/${task.params.page}.html`,
                headers,
                encoding: null,
                gzip: true,
                followRedirect: false,
                simple: false,
                resolveWithFullResponse: true
            });

            if (res.statusCode == 302) {
                task.result = [];
                task.status = 'success';
                return;
            }

            if (res.statusCode != 200) {
                throw new Error(`error status code ${res.statusCode}`);
            }

            let $ = cheerio.load(iconv.decode(res.body, 'gb2312'));

            task.result = [];
            $('article').each((i, ele)=> {
                task.result.push({
                    type: $('h2>a', ele).prop('href').split('/')[1],
                    title: $('h2>a', ele).prop('title'),
                    url: $('h2>a', ele).prop('href'),
                    time: $('p.time', ele).text(),
                    note: $('p.note', ele).text(),
                    image: $('img', ele).prop('src')
                })
            });
            task.status = 'success';
        } catch (e) {
            task.status = 'failed';
            task.result = e.message;
        }
    },
    async success(task, tm) {
        let needNextPage = true;
        // write fuli_list
        await mongo.persist(async(client)=> {
            for (let i in task.result) {
                let result = await client.collection('fuli_list').updateOne(
                    {url: task.result[i].url},
                    task.result[i],
                    {upsert: true}
                );
                if (result.upsertedCount == 0) {
                    needNextPage = false;
                    logger.error(`${task.result[i].name} ${task.result[i].time} already added`);
                } else {
                    // add detail task
                    await tm.prependTask({
                        type: 'fuli/p0/detail',
                        params: {
                            _id: result.upsertedId._id,
                            url: task.result[i].url,
                            page: 1
                        }
                    });
                    // add cover download task
                    let sps = task.result[i].image.split('.');
                    await tm.prependTask({
                        type: 'download',
                        params: {
                            url: task.result[i].image,
                            path: `fuli/${result.upsertedId._id}.${sps[sps.length - 1]}`,
                            // Referer: "http://yxpjwnet.com/"
                        }
                    });
                }
            }

            if (needNextPage && task.result.length > 0) {
                await tm.addTask({
                    type: task.type,
                    params: {
                        page: task.params.page + 1
                    }
                });
            }
        });
    },
    async failed(task, tm) {
        // 设置重试的次数限制
        let retry = task.retry || 1;
        if (retry >= 3) {
            // failed, do nothing
            // TODO: maybe try later
        } else {
            tm.addTask({
                type: task.type,
                retry: retry + 1,
                params: task.params
            });
        }
    }
};
<commit_msg>name to title<commit_after>const logger = require('../../../logger')();
const rp = require('request-promise');
const cheerio = require('cheerio');
const mongo = require('../../../mongo');
const iconv = require('iconv-lite');

module.exports = {
    // return true the task will be add to manager
    async beforeAddTask(task) {
        return true;
    },
    // set task.status 'success' or 'failed'
    // only task.result will persist to db, even though task failed
    async doTask(task) {
        try {
            let headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
                "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
                "Accept-Encoding": "gzip, deflate, br",
                "Accept-Language": "zh-CN,zh;q=0.8",
            };

            let res = await rp.get({
                uri: `http://yxpjwnet.com/page/${task.params.page}.html`,
                headers,
                encoding: null,
                gzip: true,
                followRedirect: false,
                simple: false,
                resolveWithFullResponse: true
            });

            if (res.statusCode == 302) {
                task.result = [];
                task.status = 'success';
                return;
            }

            if (res.statusCode != 200) {
                throw new Error(`error status code ${res.statusCode}`);
            }

            let $ = cheerio.load(iconv.decode(res.body, 'gb2312'));

            task.result = [];
            $('article').each((i, ele)=> {
                task.result.push({
                    type: $('h2>a', ele).prop('href').split('/')[1],
                    title: $('h2>a', ele).prop('title'),
                    url: $('h2>a', ele).prop('href'),
                    time: $('p.time', ele).text(),
                    note: $('p.note', ele).text(),
                    image: $('img', ele).prop('src')
                })
            });
            task.status = 'success';
        } catch (e) {
            task.status = 'failed';
            task.result = e.message;
        }
    },
    async success(task, tm) {
        let needNextPage = true;
        // write fuli_list
        await mongo.persist(async(client)=> {
            for (let i in task.result) {
                let result = await client.collection('fuli_list').updateOne(
                    {url: task.result[i].url},
                    task.result[i],
                    {upsert: true}
                );
                if (result.upsertedCount == 0) {
                    needNextPage = false;
                    logger.error(`${task.result[i].title} ${task.result[i].time} already added`);
                } else {
                    // add detail task
                    await tm.prependTask({
                        type: 'fuli/p0/detail',
                        params: {
                            _id: result.upsertedId._id,
                            url: task.result[i].url,
                            page: 1
                        }
                    });
                    // add cover download task
                    let sps = task.result[i].image.split('.');
                    await tm.prependTask({
                        type: 'download',
                        params: {
                            url: task.result[i].image,
                            path: `fuli/${result.upsertedId._id}.${sps[sps.length - 1]}`,
                            // Referer: "http://yxpjwnet.com/"
                        }
                    });
                }
            }

            if (needNextPage && task.result.length > 0) {
                await tm.addTask({
                    type: task.type,
                    params: {
                        page: task.params.page + 1
                    }
                });
            }
        });
    },
    async failed(task, tm) {
        // 设置重试的次数限制
        let retry = task.retry || 1;
        if (retry >= 3) {
            // failed, do nothing
            // TODO: maybe try later
        } else {
            tm.addTask({
                type: task.type,
                retry: retry + 1,
                params: task.params
            });
        }
    }
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {

	//Loads all grunt tasks matching the ['grunt-*', '@*/grunt-*'] patterns.
	require('load-grunt-tasks')(grunt);

	var now = new Date(); // Used for git commit message.

	grunt.initConfig({

		pkg: grunt.file.readJSON('package.json'),

		watch: {
			options: {
				livereload: true,
			},
			scss: {
				files: ['css/sass/*.scss', 'css/sass/**/*.scss'],
				tasks: ['compass', 'combine_mq', 'cssmin'],
				options: {
					spawn: false
				}
			},
			scripts: {
				files: ['js/config.js', 'js/modules/**/*.js', 'Gruntfile.js'],
				tasks: ['jshint', 'requirejs']
			},
			src: {
				files: [
					'**/*.php',
					'**/*.css',
					'js/**/*.js',
					'css/sass/**/*.scss',
					'package.json',
					'**/*.png',
					'**/*.jpg',
					'**/*.gif',
					'Gruntfile.js',
					'!node_modules/*',
				],
				tasks: ['gitadd', 'gitcommit']
			}
		},

		gitadd: {
			task: {
				options: {
					force: true
				},
				files: {
					src: ['*']
				}
			}
		},

		gitcommit: {
			your_target: {
				options: {
					cwd: '../../',
					message: 'Repo updated on: ' + grunt.template.today()
				},
				files: [{
					src: ['**/**/**'],
					expand: true,
					cwd: 'themes/digitalportfolio'
				}]
			}
		},

		compass: {
			dist: {
				options: {
					config: 'config.rb',
					sassDir: 'css/sass',
					cssDir: 'css',
					environment: 'development'
				}
			}
		},

		combine_mq: {
			options: {
				beautify: true
			},
			main: {
				src: 'style.css',
				dest: 'style.css'
			}
		},

		cssmin: {
			target: {
				files: [{
					expand: true,
					cwd: 'css/sass',
					src: ['*.css']
				}]
			}
		},

		jshint: {
			all: ['Gruntfile.js']
		},

		requirejs: {
			compile: {
				options: {
					baseUrl: 'js',
					name: 'config',
					paths: {
						jquery: 'libraries/jquery-1.11.3.min',
						app: 'modules/app'
					},
					out: 'js/optimize.min.js'
				}
			}
		}
	});
	grunt.registerTask('default', [
		'grunt-contrib-grunt-git',
		'grunt-contrib-cssmin',
		'grunt-contrib-combine-mq',
		'grunt-contrib-compass',
		'grunt-contrib-jshint',
		'grunt-contrib-requirejs'
	]);
};<commit_msg>Repo updated on: Sun Dec 20 2015 14:01:56<commit_after>module.exports = function(grunt) {

	//Loads all grunt tasks matching the ['grunt-*', '@*/grunt-*'] patterns.
	require('load-grunt-tasks')(grunt);

	var now = new Date(); // Used for git commit message.

	grunt.initConfig({

		pkg: grunt.file.readJSON('package.json'),

		watch: {
			options: {
				livereload: true,
			},
			scss: {
				files: ['css/sass/*.scss', 'css/sass/**/*.scss'],
				tasks: ['compass', 'combine_mq', 'cssmin'],
				options: {
					spawn: false
				}
			},
			scripts: {
				files: ['js/config.js', 'js/modules/**/*.js', 'Gruntfile.js'],
				tasks: ['jshint', 'requirejs']
			},
			src: {
				files: [
					'**/*.php',
					'**/*.css',
					'js/**/*.js',
					'css/sass/**/*.scss',
					'package.json',
					'**/*.png',
					'**/*.jpg',
					'**/*.gif',
					'Gruntfile.js',
					'!node_modules/*',
				],
				tasks: ['gitadd', 'gitcommit']
			}
		},

		gitadd: {
			task: {
				options: {
					force: true
				},
				files: {
					src: ['*']
				}
			}
		},

		gitcommit: {
			your_target: {
				options: {
					cwd: '../../',
					message: 'Repo updated on: ' + grunt.template.today()
				},
				files: [{
					src: ['**/**/**'],
					expand: true,
					cwd: 'themes/digitalportfolio/**/*'
				}]
			}
		},

		compass: {
			dist: {
				options: {
					config: 'config.rb',
					sassDir: 'css/sass',
					cssDir: 'css',
					environment: 'development'
				}
			}
		},

		combine_mq: {
			options: {
				beautify: true
			},
			main: {
				src: 'style.css',
				dest: 'style.css'
			}
		},

		cssmin: {
			target: {
				files: [{
					expand: true,
					cwd: 'css/sass',
					src: ['*.css']
				}]
			}
		},

		jshint: {
			all: ['Gruntfile.js']
		},

		requirejs: {
			compile: {
				options: {
					baseUrl: 'js',
					name: 'config',
					paths: {
						jquery: 'libraries/jquery-1.11.3.min',
						app: 'modules/app'
					},
					out: 'js/optimize.min.js'
				}
			}
		}
	});
	grunt.registerTask('default', [
		'grunt-contrib-grunt-git',
		'grunt-contrib-cssmin',
		'grunt-contrib-combine-mq',
		'grunt-contrib-compass',
		'grunt-contrib-jshint',
		'grunt-contrib-requirejs'
	]);
};<|endoftext|>


<commit_before>import babelTraverse from 'babel-traverse';

/**
 * Utility for AST.
 */
export default class ASTUtil {
  /**
   * sanitize node.
   * change node type to `Identifier` and empty comment.
   * @param {ASTNode} node - target node.
   */
  static sanitize(node) {
    if (!node) return;
    node.type = 'Identifier';
    node.name = '_';
    node.leadingComments = [];
    node.trailingComments = [];
  }

  /**
   * traverse ast nodes.
   * @param {AST} ast - target AST.
   * @param {function(node: Object, parent: Object)} callback - this is called with each node.
   */
  static traverse(ast, callback) {
    babelTraverse(ast, {
      noScope: true,
      enter: function(path){
        callback.call(this, path.node, path.parent);
      }
    });
  }

  /**
   * find file path in import declaration by name.
   * e.g. can find ``./foo/bar.js`` from ``import Bar from './foo/bar.js'`` by ``Bar``.
   * @param {AST} ast - target AST.
   * @param {string} name - identifier name.
   * @returns {string|null} file path.
   */
  static findPathInImportDeclaration(ast, name) {
    let path = null;

    babelTraverse(ast, {
      noScope: true,
      enter: function(_path){
        const node = _path.node;
        if (node.type !== 'ImportDeclaration') return;

        for (let spec of node.specifiers) {
          let localName = spec.local.name;
          if (localName === name) {
            path = node.source.value;
            _path.stop();
          }
        }
      }
    });

    return path;
  }

  /**
   * find VariableDeclaration node which has NewExpression.
   * @param {string} name - variable name.
   * @param {AST} ast - find in this ast.
   * @returns {ASTNode|null} found ast node.
   */
  static findVariableDeclarationAndNewExpressionNode(name, ast) {
    if (!name) return null;

    for (let node of ast.program.body) {
      if (node.type === 'VariableDeclaration' &&
        node.declarations[0].init &&
        node.declarations[0].init.type === 'NewExpression' &&
        node.declarations[0].id.name === name) {
        return node;
      }
    }

    return null;
  }

  /**
   * find ClassDeclaration node.
   * @param {string} name - class name.
   * @param {AST} ast - find in this ast.
   * @returns {ASTNode|null} found ast node.
   */
  static findClassDeclarationNode(name, ast) {
    if (!name) return null;

    for (let node of ast.program.body) {
      if (node.type === 'ClassDeclaration' && node.id.name === name) return node;
    }

    return null;
  }

  /**
   * find FunctionDeclaration node.
   * @param {string} name - function name.
   * @param {AST} ast - find in this ast.
   * @returns {ASTNode|null} found ast node.
   */
  static findFunctionDeclarationNode(name, ast) {
    if (!name) return null;

    for (let node of ast.program.body) {
      if (node.type === 'FunctionDeclaration' && node.id.name === name) return node;
    }

    return null;
  }

  /**
   * find VariableDeclaration node.
   * @param {string} name - variable name.
   * @param {AST} ast - find in this ast.
   * @returns {ASTNode|null} found ast node.
   */
  static findVariableDeclarationNode(name, ast) {
    if (!name) return null;

    for (let node of ast.program.body) {
      if (node.type === 'VariableDeclaration' && node.declarations[0].id.name === name) return node;
    }

    return null;
  }

  /**
   * create VariableDeclaration node which has NewExpression.
   * @param {string} name - variable name.
   * @param {string} className - class name.
   * @param {Object} loc - location.
   * @returns {ASTNode} created node.
   */
  static createVariableDeclarationAndNewExpressionNode(name, className, loc) {
    let node = {
      type: 'VariableDeclaration',
      kind: 'let',
      loc: loc,
      declarations: [
        {
          type: 'VariableDeclarator',
          id: {type: 'Identifier', name: name},
          init: {type: 'NewExpression', callee: {type: 'Identifier', name: className}}
        }
      ]
    };

    return node;
  }

  /**
   * flatten name of MemberExpression.
   * @param {ASTNode} memberExpression - MemberExpression Node.
   * @returns {string} flatten node name.
   */
  static flattenMemberExpression(memberExpression) {
    const names = [];
    let object = memberExpression;
    while (object) {
      if (object.name) {
        names.push(object.name);
        break;
      } else {
        names.push(object.property.name);
        object = object.object;
      }
    }
    return names.reverse().join('.');
  }
}
<commit_msg>fix(traverse): `this` object in tarverse<commit_after>import babelTraverse from 'babel-traverse';

/**
 * Utility for AST.
 */
export default class ASTUtil {
  /**
   * sanitize node.
   * change node type to `Identifier` and empty comment.
   * @param {ASTNode} node - target node.
   */
  static sanitize(node) {
    if (!node) return;
    node.type = 'Identifier';
    node.name = '_';
    node.leadingComments = [];
    node.trailingComments = [];
  }

  /**
   * traverse ast nodes.
   * @param {AST} ast - target AST.
   * @param {function(node: Object, parent: Object)} callback - this is called with each node.
   */
  static traverse(ast, callback) {
    babelTraverse(ast, {
      noScope: true,
      enter: function(path){
        callback.call(path, path.node, path.parent);
      }
    });
  }

  /**
   * find file path in import declaration by name.
   * e.g. can find ``./foo/bar.js`` from ``import Bar from './foo/bar.js'`` by ``Bar``.
   * @param {AST} ast - target AST.
   * @param {string} name - identifier name.
   * @returns {string|null} file path.
   */
  static findPathInImportDeclaration(ast, name) {
    let path = null;

    babelTraverse(ast, {
      noScope: true,
      enter: function(_path){
        const node = _path.node;
        if (node.type !== 'ImportDeclaration') return;

        for (let spec of node.specifiers) {
          let localName = spec.local.name;
          if (localName === name) {
            path = node.source.value;
            _path.stop();
          }
        }
      }
    });

    return path;
  }

  /**
   * find VariableDeclaration node which has NewExpression.
   * @param {string} name - variable name.
   * @param {AST} ast - find in this ast.
   * @returns {ASTNode|null} found ast node.
   */
  static findVariableDeclarationAndNewExpressionNode(name, ast) {
    if (!name) return null;

    for (let node of ast.program.body) {
      if (node.type === 'VariableDeclaration' &&
        node.declarations[0].init &&
        node.declarations[0].init.type === 'NewExpression' &&
        node.declarations[0].id.name === name) {
        return node;
      }
    }

    return null;
  }

  /**
   * find ClassDeclaration node.
   * @param {string} name - class name.
   * @param {AST} ast - find in this ast.
   * @returns {ASTNode|null} found ast node.
   */
  static findClassDeclarationNode(name, ast) {
    if (!name) return null;

    for (let node of ast.program.body) {
      if (node.type === 'ClassDeclaration' && node.id.name === name) return node;
    }

    return null;
  }

  /**
   * find FunctionDeclaration node.
   * @param {string} name - function name.
   * @param {AST} ast - find in this ast.
   * @returns {ASTNode|null} found ast node.
   */
  static findFunctionDeclarationNode(name, ast) {
    if (!name) return null;

    for (let node of ast.program.body) {
      if (node.type === 'FunctionDeclaration' && node.id.name === name) return node;
    }

    return null;
  }

  /**
   * find VariableDeclaration node.
   * @param {string} name - variable name.
   * @param {AST} ast - find in this ast.
   * @returns {ASTNode|null} found ast node.
   */
  static findVariableDeclarationNode(name, ast) {
    if (!name) return null;

    for (let node of ast.program.body) {
      if (node.type === 'VariableDeclaration' && node.declarations[0].id.name === name) return node;
    }

    return null;
  }

  /**
   * create VariableDeclaration node which has NewExpression.
   * @param {string} name - variable name.
   * @param {string} className - class name.
   * @param {Object} loc - location.
   * @returns {ASTNode} created node.
   */
  static createVariableDeclarationAndNewExpressionNode(name, className, loc) {
    let node = {
      type: 'VariableDeclaration',
      kind: 'let',
      loc: loc,
      declarations: [
        {
          type: 'VariableDeclarator',
          id: {type: 'Identifier', name: name},
          init: {type: 'NewExpression', callee: {type: 'Identifier', name: className}}
        }
      ]
    };

    return node;
  }

  /**
   * flatten name of MemberExpression.
   * @param {ASTNode} memberExpression - MemberExpression Node.
   * @returns {string} flatten node name.
   */
  static flattenMemberExpression(memberExpression) {
    const names = [];
    let object = memberExpression;
    while (object) {
      if (object.name) {
        names.push(object.name);
        break;
      } else {
        names.push(object.property.name);
        object = object.object;
      }
    }
    return names.reverse().join('.');
  }
}
<|endoftext|>