<commit_before>'use strict';

/**
 * Simple wrapper to selected github api functions.
 * @param {*} event -
 * @param {*} context -
 * @param {*} callback -
*/
exports.handler = (event, context, callback) => {
  /**
   * Copy response to results and continue with next page.
   * @param {*} error -
   * @param {*} response -
   */
  function copyAndContinue(error, response) {
    if (error) {
      return false;
    }
    response.map(item => { results.push(item); });
    if (github.hasNextPage(response)) {
      github.getNextPage(response, { 'user-agent': 'alexisargyris' }, copyAndContinue)
    } else { cb(null, results); }
  }
  /**
   * Checks if target exists in list.
   * @param {*} target -
   * @param {*} list -
   */
  function existsItemInList(target, list) {
    for (var index in list) {
      if (target === list[index].path) return index;
    }
    return -1;
  }

  let GitHubApi = require('github');
  let Promise = require('bluebird');
  let MarkdownIt = require('markdown-it');
  let creds = require('./creds.js').creds;
  let github;
  let results = [];
  let cb;
  let user;
  let token;
  let textDecodeError = '<η αποκωδικοποίηση του κείμενου απέτυχε>';
  let srcRootPath = 'src/';
  let defaultPage; // default value is 'undefined'
  let defaultPerPage = 100;
  let errorMissingParams = 'Required parameter is missing';

  // If no command was provided, then exit immediately.
  if ((event === undefined) || (event.cmd === undefined) || (event.cmd === '')) {
    callback(new Error('Missing cmd parameter'))
  } else {
    // Init github api.
    user = creds.user;
    token = creds.token;
    github = new GitHubApi({
      // required
      version: '3.0.0',
      // optional
      debug: true,
      protocol: 'https',
      host: 'api.github.com',
      pathPrefix: '',
      timeout: 5000,
      headers: {
        'user-agent': user
      }
    });
    github.authenticate({
      type: 'oauth',
      token: token
    });
    // Main switch.
    switch (event.cmd) {
      /**
       * Get repos of authenticated user.
       */
      case 'list':
        Promise.promisify(github.repos.getAll)({ per_page: 100 })
          .then(response => { callback(null, response) })
          .catch(error => { callback(error) });
        break;
      /**
       * Get commits of repo.
       * @param {string} reponame - the repo's name
       * @param {number} [page=undefined] - the number of the page being requested
       * @param {number} [per_page=100] - the number of commits a page should contain
       */
      case 'single':
        // If required params are missing, then exit immediately.
        if (event.reponame === undefined) { callback(new Error(errorMissingParams)) }
        else {
          cb = callback;
          results.length = 0;
          Promise.promisify(github.repos.getCommits)({
            owner: user,
            repo: event.reponame,
            page: (event.page === undefined) ? defaultPage : event.page,
            per_page: (event.per_page === undefined) ? defaultPerPage : event.per_page
          })
            .then(response => { copyAndContinue(null, response) })
            .catch(error => { callback(error) });
        }
        break;
      /**
       * Get contents of commit.
       * @param {string} reponame - the repo's name
       * @param {string} commitsha - the commit's id
       */
      case 'details':
        let commit = {};
        let docContent = '';
        let getContentPrms = Promise.promisify(github.repos.getContent);

        // If required params are missing, then exit immediately.
        if ((event.reponame === undefined) || (event.commitsha === undefined)) { callback(new Error(errorMissingParams)); }
        else {
          // get the commit
          Promise.promisify(github.repos.getCommit)({
            owner: user,
            repo: event.reponame,
            sha: event.commitsha
          })
            .then(response => {
              // get all files starting with 'src/' touched by the commit
              commit = response;
              return Promise.map(commit.files, (file, index, length) => {
                // check if this file starts with 'src'
                if (file.filename.startsWith(srcRootPath)) {
                  return getContentPrms({
                    owner: user,
                    repo: event.reponame,
                    path: file.filename,
                    ref: event.commitsha
                  })
                    .then(result => {
                      // store the file's content
                      file.content = new Buffer(result.content, 'base64').toString('utf8');
                    })
                }
                else { return Promise.resolve() }
              })
            })
            .then(() => {
              // get the commit's whole tree of files
              return Promise.promisify(github.gitdata.getTree)({
                owner: user,
                repo: event.reponame,
                sha: event.commitsha,
                recursive: true
              });
            })
            .then(tree => {
              // get all tree files starting with 'src/'
              // TODO some of these files must have already been downloaded in the previous step. Why do it twice?
              return Promise.map(tree.tree, (file, index, length) => {
                // check if this file starts with 'src'
                if (file.path.startsWith(srcRootPath)) {
                  return getContentPrms({
                    owner: user,
                    repo: event.reponame,
                    path: file.path,
                    ref: event.commitsha
                  })
                    .then(result => {
                      let cnt = new Buffer(result.content, 'base64').toString('utf8');
                      // concatenate all files to form a single doc
                      docContent += '\n\n# ' + file.path + '\n\n' + cnt + '\n\n';
                    })
                }
                else { return Promise.resolve() }
              })
            })
            .then(() => {
              // convert markdown content to html and store it
              commit.doc = new MarkdownIt().render(docContent);
              callback(null, commit)
            })
            .catch(error => { debugger; callback(error) });
        }
        break;
      default:
    }
  }
}

/*
  exports.handler({
    // 'cmd': 'getRepos'

    // 'cmd': 'getCommits',
    // 'reponame': 'amomonaima',
    // 'page': 1,
    // 'per_page': 1

    // 'cmd': 'getCommit',
    // 'reponame': 'amomonaima',
    // 'commitsha': 'c01511d565bd0b446353e3d5d99ea8848223ccfa'
  });
*/
<commit_msg>changed command names and fixed a bug<commit_after>'use strict';

/**
 * Simple wrapper to selected github api functions.
 * @param {*} event -
 * @param {*} context -
 * @param {*} callback -
*/
exports.handler = (event, context, callback) => {
  /**
   * Copy response to results and continue with next page.
   * @param {*} error -
   * @param {*} response -
   */
  function copyAndContinue(error, response) {
    if (error) {
      return false;
    }
    response.map(item => { results.push(item); });
    if (github.hasNextPage(response)) {
      github.getNextPage(response, { 'user-agent': 'alexisargyris' }, copyAndContinue)
    } else { cb(null, results); }
  }
  /**
   * Checks if target exists in list.
   * @param {*} target -
   * @param {*} list -
   */
  function existsItemInList(target, list) {
    for (var index in list) {
      if (target === list[index].path) return index;
    }
    return -1;
  }

  let GitHubApi = require('github');
  let Promise = require('bluebird');
  let MarkdownIt = require('markdown-it');
  let creds = require('./creds.js').creds;
  let github;
  let results = [];
  let cb;
  let user;
  let token;
  let textDecodeError = '<η αποκωδικοποίηση του κείμενου απέτυχε>';
  let srcRootPath = 'src/';
  let defaultPage; // default value is 'undefined'
  let defaultPerPage = 100;
  let errorMissingParams = 'Required parameter is missing';

  // If no command was provided, then exit immediately.
  if ( (event === undefined) || (event.cmd === undefined) || (event.cmd === '') ) {
    callback(new Error('Missing cmd parameter'))
  } else if ( (event.cmd !== 'sources') && (event.cmd !== 'list') && (event.cmd !== 'single') ) {
    callback(new Error('Unknown command'))
  } else {
    // Init github api.
    user = creds.user;
    token = creds.token;
    github = new GitHubApi({
      // required
      version: '3.0.0',
      // optional
      debug: true,
      protocol: 'https',
      host: 'api.github.com',
      pathPrefix: '',
      timeout: 5000,
      headers: {
        'user-agent': user
      }
    });
    github.authenticate({
      type: 'oauth',
      token: token
    });
    // Main switch.
    switch (event.cmd) {
      /**
       * Get repos of authenticated user.
       */
      case 'sources':
        Promise.promisify(github.repos.getAll)({ per_page: 100 })
          .then(response => { callback(null, response) })
          .catch(error => { callback(error) });
        break;
      /**
       * Get commits of repo.
       * @param {string} reponame - the repo's name
       * @param {number} [page=undefined] - the number of the page being requested
       * @param {number} [per_page=100] - the number of commits a page should contain
       */
      case 'list':
        // If required params are missing, then exit immediately.
        if (event.reponame === undefined) { callback(new Error(errorMissingParams)) }
        else {
          cb = callback;
          results.length = 0;
          Promise.promisify(github.repos.getCommits)({
            owner: user,
            repo: event.reponame,
            page: (event.page === undefined) ? defaultPage : event.page,
            per_page: (event.per_page === undefined) ? defaultPerPage : event.per_page
          })
            .then(response => { copyAndContinue(null, response) })
            .catch(error => { callback(error) });
        }
        break;
      /**
       * Get contents of commit.
       * @param {string} reponame - the repo's name
       * @param {string} commitsha - the commit's id
       * @return {Object} a commit object as returned from github with the following additional information:
       *  1. In each commit.files with a path starting with srcRootPath, a 'content' property is added holding the file's content in its original Markdown format.
       *  2. At the top level, a 'doc' property is added holding a concatenation of ???? in HTML format (converted from the original Markdown).
       */
      case 'single':
        let commit = {};
        let docContent = '';
        let getContentPrms = Promise.promisify(github.repos.getContent);

        // If required params are missing, then exit immediately.
        if ((event.reponame === undefined) || (event.commitsha === undefined)) { callback(new Error(errorMissingParams)); }
        else {
          // get the commit
          Promise.promisify(github.repos.getCommit)({
            owner: user,
            repo: event.reponame,
            sha: event.commitsha
          })
            .then(response => {
              // store the response as the result
              commit = response;
              // get the content of all files touched by the commit, if their path starts with srcRootPath (note: order of execution doesn't matter).
              return Promise.map(commit.files, (file, index, length) => {
                // check if this file starts with 'src'
                if (file.filename.startsWith(srcRootPath)) {
                  return getContentPrms({
                    owner: user,
                    repo: event.reponame,
                    path: file.filename,
                    ref: event.commitsha
                  })
                    .then(result => {
                      // store the file's content
                      file.content = new Buffer(result.content, 'base64').toString('utf8');
                    })
                }
                else { return Promise.resolve() }
              })
            })
            .then(() => {
              // now, to build the 'doc' property, start by getting the commit's whole tree of files
              return Promise.promisify(github.gitdata.getTree)({
                owner: user,
                repo: event.reponame,
                sha: event.commitsha,
                recursive: true
              });
            })
            .then(tree => {
              // for each item in the tree (note: order of execution matters)
              return Promise.mapSeries(tree.tree, (file, index, length) => {
                // check if the item starts with srcRootPath and is a 'blob' (file), i.e. not a dir
                if ( (file.path.startsWith(srcRootPath)) && (file.type === 'blob') ) {
                  // get its contents
                  return getContentPrms({
                    owner: user,
                    repo: event.reponame,
                    path: file.path,
                    ref: event.commitsha
                  })
                    .then(result => {
                      let cnt = new Buffer(result.content, 'base64').toString('utf8');
                      // concatenate all files to form a single doc
                      docContent += '\n\n# ' + file.path + '\n\n' + cnt + '\n\n';
                    })
                }
                else { return Promise.resolve() }
              })
            })
            .then(() => {
              // convert markdown content to html and store it
              commit.doc = new MarkdownIt().render(docContent);
              callback(null, commit)
            })
            .catch(error => { debugger; callback(error) });
        }
        break;
      default:
    }
  }
}

/*
  exports.handler({
    // 'cmd': 'sources'

    // 'cmd': 'list',
    // 'reponame': 'amomonaima',
    // 'page': 1,
    // 'per_page': 1

    'cmd': 'single',
    'reponame': 'amomonaima',
    'commitsha': '72ffb6a9ac328c34245a9fee0292c8dd03a62c11'
  });
*/
<|endoftext|>


<commit_before>'use strict'

// ---
// ---
// ---

try {
	module.exports = window.angular || require('angular') || {}

	if (!module.exports.module) {
		module.exports = window.angular || {}
	}
} catch (e) {
	try {
		module.exports = require('angular') || {}

		if (!module.exports.module) {
			module.exports = window.angular || {}
		}
	} catch (e) {
		module.exports = {}
	}
}

// ---
<commit_msg>Code-quality improvements.<commit_after>'use strict'

try {
	module.exports = window.angular || require('angular') || {}

	if (!module.exports.module) {
		module.exports = window.angular || {}
	}
} catch (e) {
	try {
		module.exports = require('angular') || {}

		if (!module.exports.module) {
			module.exports = window.angular || {}
		}
	} catch (e) {
		module.exports = {}
	}
}
<|endoftext|>


<commit_before>import easingTypes, {easeInOutQuad} from 'tween-functions';
import requestAnimationFrame from 'raf';

// additive is the new iOS 8 default. In most cases it simulates a physics-
// looking overshoot behavior (especially with easeInOut. You can test that in
// the example
let DEFAULT_STACK_BEHAVIOR = 'ADDITIVE';
let DEFAULT_EASING = easeInOutQuad;
let DEFAULT_DURATION = 300;
let DEFAULT_DELAY = 0;

let stackBehavior = {
  ADDITIVE: 'ADDITIVE',
  DESTRUCTIVE: 'DESTRUCTIVE',
};
let Mixin = {
  getInitialState: function() {
    return {
      tweenQueue: [],
    };
  },

  tweenState: function(path, {easing, duration, delay, beginValue, endValue, onEnd, stackBehavior: configSB}) {
    this.setState(state => {
      let cursor = state;
      let stateName;
      // see comment below on pash hash
      let pathHash;
      if (typeof path === 'string') {
        stateName = path;
        pathHash = path;
      } else {
        for (let i = 0; i < path.length - 1; i++) {
          cursor = cursor[path[i]];
        }
        stateName = path[path.length - 1];
        pathHash = path.join('|');
      }
      // see the reasoning for these defaults at the top of file
      let newConfig = {
        easing: easing || DEFAULT_EASING,
        duration: duration == null ? DEFAULT_DURATION : duration,
        delay: delay == null ? DEFAULT_DELAY : delay,
        beginValue: beginValue == null ? cursor[stateName] : beginValue,
        endValue: endValue,
        onEnd: onEnd,
        stackBehavior: configSB || DEFAULT_STACK_BEHAVIOR,
      };

      let newTweenQueue = state.tweenQueue;
      if (newConfig.stackBehavior === stackBehavior.DESTRUCTIVE) {
        newTweenQueue = state.tweenQueue.filter(item => item.pathHash !== pathHash);
      }

      // we store path hash, so that during value retrieval we can use hash
      // comparison to find the path. See the kind of shitty thing you have to
      // do when you don't have value comparison for collections?
      newTweenQueue.push({
        pathHash: pathHash,
        config: newConfig,
        initTime: Date.now() + newConfig.delay,
      });

      // sorry for mutating. For perf reasons we don't want to deep clone.
      // guys, can we please all start using persistent collections so that
      // we can stop worrying about nonesense like this
      cursor[stateName] = newConfig.endValue;
      if (newTweenQueue.length === 1) {
        this.startRaf();
      }

      // this will also include the above mutated update
      return {tweenQueue: newTweenQueue};
    });
  },

  getTweeningValue: function(path) {
    let state = this.state;

    let tweeningValue;
    let pathHash;
    if (typeof path === 'string') {
      tweeningValue = state[path];
      pathHash = path;
    } else {
      tweeningValue = state;
      for (let i = 0; i < path.length; i++) {
        tweeningValue = tweeningValue[path[i]];
      }
      pathHash = path.join('|');
    }
    let now = Date.now();

    for (let i = 0; i < state.tweenQueue.length; i++) {
      let item = state.tweenQueue[i];
      if (item.pathHash !== pathHash) {
        continue;
      }

      let progressTime = now - item.initTime > item.config.duration ?
        item.config.duration :
        Math.max(0, now - item.initTime);
      // `now - item.initTime` can be negative if initTime is scheduled in the
      // future by a delay. In this case we take 0

      let contrib = -item.config.endValue + item.config.easing(
        progressTime,
        item.config.beginValue,
        item.config.endValue,
        item.config.duration,
        // TODO: some funcs accept a 5th param
      );
      tweeningValue += contrib;
    }

    return tweeningValue;
  },

  _rafCb: function() {
    let state = this.state;
    if (state.tweenQueue.length === 0) {
      return;
    }

    let now = Date.now();
    let newTweenQueue = [];

    for (let i = 0; i < state.tweenQueue.length; i++) {
      let item = state.tweenQueue[i];
      if (now - item.initTime < item.config.duration) {
        newTweenQueue.push(item);
      } else {
        item.config.onEnd && item.config.onEnd();
      }
    }

    // onEnd might trigger a parent callback that removes this component
    if (!this.isMounted()) {
      return;
    }

    this.setState({
      tweenQueue: newTweenQueue,
    });

    requestAnimationFrame(this._rafCb);
  },

  startRaf: function() {
    requestAnimationFrame(this._rafCb);
  },
};

export default {
  Mixin,
  easingTypes,
  stackBehavior,
};
<commit_msg>Remove `this.isMounted()` check<commit_after>import easingTypes, {easeInOutQuad} from 'tween-functions';
import requestAnimationFrame from 'raf';

// additive is the new iOS 8 default. In most cases it simulates a physics-
// looking overshoot behavior (especially with easeInOut. You can test that in
// the example
let DEFAULT_STACK_BEHAVIOR = 'ADDITIVE';
let DEFAULT_EASING = easeInOutQuad;
let DEFAULT_DURATION = 300;
let DEFAULT_DELAY = 0;

let stackBehavior = {
  ADDITIVE: 'ADDITIVE',
  DESTRUCTIVE: 'DESTRUCTIVE',
};
let Mixin = {
  _rafID: null,

  getInitialState: function() {
    return {
      tweenQueue: [],
    };
  },

  componentWillUnmount: function() {
    requestAnimationFrame.cancel(this._rafID);
    this._rafID = -1;
  },

  tweenState: function(path, {easing, duration, delay, beginValue, endValue, onEnd, stackBehavior: configSB}) {
    this.setState(state => {
      let cursor = state;
      let stateName;
      // see comment below on pash hash
      let pathHash;
      if (typeof path === 'string') {
        stateName = path;
        pathHash = path;
      } else {
        for (let i = 0; i < path.length - 1; i++) {
          cursor = cursor[path[i]];
        }
        stateName = path[path.length - 1];
        pathHash = path.join('|');
      }
      // see the reasoning for these defaults at the top of file
      let newConfig = {
        easing: easing || DEFAULT_EASING,
        duration: duration == null ? DEFAULT_DURATION : duration,
        delay: delay == null ? DEFAULT_DELAY : delay,
        beginValue: beginValue == null ? cursor[stateName] : beginValue,
        endValue: endValue,
        onEnd: onEnd,
        stackBehavior: configSB || DEFAULT_STACK_BEHAVIOR,
      };

      let newTweenQueue = state.tweenQueue;
      if (newConfig.stackBehavior === stackBehavior.DESTRUCTIVE) {
        newTweenQueue = state.tweenQueue.filter(item => item.pathHash !== pathHash);
      }

      // we store path hash, so that during value retrieval we can use hash
      // comparison to find the path. See the kind of shitty thing you have to
      // do when you don't have value comparison for collections?
      newTweenQueue.push({
        pathHash: pathHash,
        config: newConfig,
        initTime: Date.now() + newConfig.delay,
      });

      // sorry for mutating. For perf reasons we don't want to deep clone.
      // guys, can we please all start using persistent collections so that
      // we can stop worrying about nonesense like this
      cursor[stateName] = newConfig.endValue;
      if (newTweenQueue.length === 1) {
        this._rafID = requestAnimationFrame(this._rafCb);
      }

      // this will also include the above mutated update
      return {tweenQueue: newTweenQueue};
    });
  },

  getTweeningValue: function(path) {
    let state = this.state;

    let tweeningValue;
    let pathHash;
    if (typeof path === 'string') {
      tweeningValue = state[path];
      pathHash = path;
    } else {
      tweeningValue = state;
      for (let i = 0; i < path.length; i++) {
        tweeningValue = tweeningValue[path[i]];
      }
      pathHash = path.join('|');
    }
    let now = Date.now();

    for (let i = 0; i < state.tweenQueue.length; i++) {
      let item = state.tweenQueue[i];
      if (item.pathHash !== pathHash) {
        continue;
      }

      let progressTime = now - item.initTime > item.config.duration ?
        item.config.duration :
        Math.max(0, now - item.initTime);
      // `now - item.initTime` can be negative if initTime is scheduled in the
      // future by a delay. In this case we take 0

      let contrib = -item.config.endValue + item.config.easing(
        progressTime,
        item.config.beginValue,
        item.config.endValue,
        item.config.duration,
        // TODO: some funcs accept a 5th param
      );
      tweeningValue += contrib;
    }

    return tweeningValue;
  },

  _rafCb: function() {
    let state = this.state;
    if (state.tweenQueue.length === 0) {
      return;
    }

    let now = Date.now();
    let newTweenQueue = [];

    for (let i = 0; i < state.tweenQueue.length; i++) {
      let item = state.tweenQueue[i];
      if (now - item.initTime < item.config.duration) {
        newTweenQueue.push(item);
      } else {
        item.config.onEnd && item.config.onEnd();
      }
    }

    // onEnd might trigger a parent callback that removes this component
    // -1 means we've canceled it in componentWillUnmount
    if (this._rafID === -1) {
      return;
    }

    this.setState({
      tweenQueue: newTweenQueue,
    });

    this._rafID = requestAnimationFrame(this._rafCb);
  },
};

export default {
  Mixin,
  easingTypes,
  stackBehavior,
};
<|endoftext|>


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

var EventEmitter = require('events').EventEmitter;
var uuid = require('uuid');
var extend = require('cog/extend');
var FastMap = require('collections/fast-map');
var vc = require('vectorclock');

/**
  # rtc-signaller

  The `rtc-signaller` module provides a transportless signalling
  mechanism for WebRTC.

  ## Purpose

  The signaller provides set of client-side tools that assist with the
  setting up an `PeerConnection` and helping them communicate. All that is
  required for the signaller to operate is a suitable messenger.

  A messenger is a simple object that implements node
  [EventEmitter](http://nodejs.org/api/events.html) style `on` events for
  `open`, `close`, `message` events, and also a `send` method by which
  data will be send "over-the-wire".

  By using this approach, we can conduct signalling over any number of
  mechanisms:

  - local, in memory message passing
  - via WebSockets and higher level abstractions (such as
    [primus](https://github.com/primus/primus))
  - also over WebRTC data-channels (very meta, and admittedly a little
    complicated).

  ## Getting Started

  To work with the signaller, you first need a messenger of some kind. If you
  have run up a version of the
  [rtc-switchboard](https://github.com/rtc-io/rtc-switchboard) somewhere then
  the following example should work:

  <<< examples/signalling-via-switchboard.js

  While the example above demonstrates communication between two endpoints
  via websockets, it does not go into detail on setting up a WebRTC peer
  connection (as that is significantly more involved).  If you are looking for
  an easy way to do this, I'd recommend checking out
  [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect) or
  [rtc-glue](https://github.com/rtc-io/rtc-glue).

  ## Signal Flow Diagrams

  Displayed below are some diagrams how the signalling flow between peers
  behaves.  In each of the diagrams we illustrate three peers (A, B and C)
  participating discovery and coordinating RTCPeerConnection handshakes.

  In each case, only the interaction between the clients is represented not
  how a signalling server
  (such as [rtc-switchboard](https://github.com/rtc-io/rtc-switchboard)) would
  pass on broadcast messages, etc.  This is done for two reasons:

  1. It is out of scope of this documentation.
  2. The `rtc-signaller` has been designed to work without having to rely on
     any intelligence in the server side signalling component.  In the
     instance that a signaller broadcasts all messages to all connected peers
     then `rtc-signaller` should be smart enough to make sure everything works
     as expected.

  ### Peer Discovery / Announcement

  This diagram illustrates the process of how peer `A` announces itself to
  peers `B` and `C`, and in turn they announce themselves.

  ![](https://raw.github.com/rtc-io/rtc-signaller/master/docs/announce.png)

  ### Editing / Updating the Diagrams

  Each of the diagrams has been generated using
  [mscgen](http://www.mcternan.me.uk/mscgen/index.html) and the source for
  these documents can be found in the `docs/` folder of this repository.

  ## Reference

  The `rtc-signaller` module is designed to be used primarily in a functional
  way and when called it creates a new signaller that will enable
  you to communicate with other peers via your messaging network.

  ```js
  // create a signaller from something that knows how to send messages
  var signaller = require('rtc-signaller')(messenger);
  ```

**/
var sig = module.exports = function(messenger, opts) {

  // create the signaller
  var signaller = new EventEmitter();

  // initialise the id
  var id = signaller.id = uuid.v4();

  // initialise the attributes
  var attributes = signaller.attributes = {
    id: id
  };

  // create the peers map
  var peers = signaller.peers = new FastMap();

  // create our locks map
  var locks = signaller.locks = new FastMap();

  // initialise the data event name
  var dataEvent = (opts || {}).dataEvent || 'data';
  var writeMethod = (opts || {}).writeMethod || 'write';
  var closeMethod = (opts || {}).closeMethod || 'close';

  // extract the write and close function references
  var write = messenger[writeMethod];
  var close = messenger[closeMethod];

  // create the processor
  var processor = require('./processor')(signaller);

  // if the messenger doesn't provide a valid write method, then complain
  if (typeof write != 'function') {
    throw new Error('provided messenger does not implement a "' +
      writeMethod + '" write method');
  }

  function prepareArg(arg) {
    if (typeof arg == 'object' && (! (arg instanceof String))) {
      return JSON.stringify(arg);
    }
    else if (typeof arg == 'function') {
      return null;
    }

    return arg;
  }

  /**
    ### signaller#send(data)

    Send data over the messenging interface.
  **/
  var send = signaller.send = function() {
    // iterate over the arguments and stringify as required
    var args = [].slice.call(arguments);
    var dataline = args.map(prepareArg).filter(Boolean).join('|');

    // send the data over the messenger
    return write.call(messenger, dataline);
  };

  /**
    ### signaller#announce(data?)

    The `announce` function of the signaller will pass an `/announce` message
    through the messenger network.  When no additional data is supplied to
    this function then only the id of the signaller is sent to all active
    members of the messenging network.

    As a unique it is generally insufficient information to determine whether
    a peer is a good match for another (for instance,  you might be looking
    for other parties by name or role) it is generally a good idea to provide
    some additional information during this announce call:

    ```js
    signaller.announce({ role: 'translator' });
    ```

    __NOTE:__ In some particular messenger types may attach or infer
    additional data during the announce phase.  For instance, socket.io
    connections are generally organised into rooms which is inferred
    information that limits the messaging scope.
  **/
  signaller.announce = function(data, sender) {
    // update internal attributes
    extend(attributes, data, { id: id });

    // send the attributes over the network
    return (sender || send)('/announce', attributes);
  };

  /**
    ### signaller#leave()

    Leave the messenger mesh
  **/
  signaller.leave = function() {
    // send the leave signal
    send('/leave', { id: id });

    // call the close method
    if (typeof close == 'function') {
      close.call(messenger);
    }
  };

  /**
    ### signaller#lock(targetId, opts?, callback?)

    Attempt to get a temporary exclusive lock on the communication
    channel between the local signaller and the specified target peer id.
  **/
  signaller.lock = function(targetId, opts, callback) {
    var peer = peers.get(targetId);
    var lockid = uuid.v4();
    var label;

    function handleLockResult(src, result) {
      var ok = result && result.ok;

      // if the source does not match the target then abort
      if ((! src) || (src.id !== targetId)) {
        return;
      }

      // if the result label is not a match, then abort
      if ((! result) || (result.label !== label)) {
        return;
      }

      // don't listen for any further lock result messages
      signaller.removeListener('lockresult', handleLockResult);

      // if we don't have an error condition, create a local lock
      if (ok) {
        locks.set(label, lockid);
      }

      callback(ok ? null : new Error('could not acquire lock'));
    }

    // check for no label being supplied
    if (typeof opts == 'function') {
      callback = opts;
      opts = {};
    }

    // ensure we have a callback
    callback = callback || function() {};

    // if the peer is not known, then we cannot initiate a lock
    if (! peer) {
      return callback(new Error('unknown target id - cannot initiate lock'));
    }

    // create a default label if none provided
    label = (opts || {}).label || (opts || {}).name || 'default';

    // if we have a local lock already in place, then return ok
    if (locks.get(label)) {
      return callback();
    }

    // ensure we have locks for the peer
    peer.locks = peer.locks || new FastMap();

    // if a remote lock is in place, error out
    if (peer.locks.get(label)) {
      return callback(new Error('remote lock in place, cannot request lock'));
    }

    // wait for the lock result
    signaller.on('lockresult', handleLockResult);

    // send the lock message
    signaller.to(targetId).send('/lock', label, lockid);
  };

  /**
    ### signaller#to(targetId)

    The to method returns an encapsulated

  **/
  signaller.to = function(targetId) {
    // create a sender that will prepend messages with /to|targetId|
    var sender = function() {
      // get the peer (yes when send is called to make sure it hasn't left)
      var peer = signaller.peers.get(targetId);
      var args = [
        '/to',
        targetId,
        { id: signaller.id, clock: peer.clock }
      ].concat([].slice.call(arguments));

      if (! peer) {
        return;
      }

      // increment the peer clock, using the role of the local
      // signaller.  If the peer role is 0, then the signallers role is 1
      // and using xor (^) will generate the correct index
      vc.increment(peer, ['a', 'b'][peer.roleIdx ^ 1]);

      // write on next tick to ensure clock updates are handled correctly
      setTimeout(function() {
        // include the current clock value in with the payload
        write.call(
          messenger,
          args.map(prepareArg).filter(Boolean).join('|')
        );
      }, 0);
    };

    return {
      announce: function(data) {
        return signaller.announce(data, sender);
      },

      send: sender,
    }
  };

  /**

    ### signaller#unlock(targetId, opts?)

  **/
  signaller.unlock = function(targetId, opts, callback) {
    var peer = peers.get(targetId);
    var label;

    function handleUnlockResult(src, result) {
      var ok = result && result.ok;

      // if not the correct source then abort
      if ((! src) || (src.id !== targetId)) {
        return;
      }

      // if this is not an unlock result for this label, then abort
      if ((! result) || (result.label !== label)) {
        return;
      }

      // remove the listener
      signaller.removeListener('unlockresult', handleUnlockResult);

      // if ok, remove our local lock
      if (ok) {
        locks.delete(label);
      }

      // trigger the callback
      callback(ok ? null : new Error('could not release lock: ' + label));
    }

    // handle the no opts case
    if (typeof opts == 'function') {
      callback = opts;
      opts = {};
    }

    // ensure we have a callback
    callback = callback || function() {};

    // set a default label value
    label = (opts || {}).label || (opts || {}).name || 'default';

    // if we have the peer and local lock then action the unlock
    if (peer && locks.get(label)) {
      signaller.on('unlockresult', handleUnlockResult);
      signaller.to(targetId).send('/unlock', label, locks.get(label));
    }
    else {
      return callback(new Error('no local lock with label ' + label));
    }
  };

  // handle message data events
  messenger.on(dataEvent, processor);

  return signaller;
};

sig.loadPrimus = require('./primus-loader');<commit_msg>Throw an error if attempting to send a message to an unknown peer<commit_after>/* jshint node: true */
'use strict';

var EventEmitter = require('events').EventEmitter;
var uuid = require('uuid');
var extend = require('cog/extend');
var FastMap = require('collections/fast-map');
var vc = require('vectorclock');

/**
  # rtc-signaller

  The `rtc-signaller` module provides a transportless signalling
  mechanism for WebRTC.

  ## Purpose

  The signaller provides set of client-side tools that assist with the
  setting up an `PeerConnection` and helping them communicate. All that is
  required for the signaller to operate is a suitable messenger.

  A messenger is a simple object that implements node
  [EventEmitter](http://nodejs.org/api/events.html) style `on` events for
  `open`, `close`, `message` events, and also a `send` method by which
  data will be send "over-the-wire".

  By using this approach, we can conduct signalling over any number of
  mechanisms:

  - local, in memory message passing
  - via WebSockets and higher level abstractions (such as
    [primus](https://github.com/primus/primus))
  - also over WebRTC data-channels (very meta, and admittedly a little
    complicated).

  ## Getting Started

  To work with the signaller, you first need a messenger of some kind. If you
  have run up a version of the
  [rtc-switchboard](https://github.com/rtc-io/rtc-switchboard) somewhere then
  the following example should work:

  <<< examples/signalling-via-switchboard.js

  While the example above demonstrates communication between two endpoints
  via websockets, it does not go into detail on setting up a WebRTC peer
  connection (as that is significantly more involved).  If you are looking for
  an easy way to do this, I'd recommend checking out
  [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect) or
  [rtc-glue](https://github.com/rtc-io/rtc-glue).

  ## Signal Flow Diagrams

  Displayed below are some diagrams how the signalling flow between peers
  behaves.  In each of the diagrams we illustrate three peers (A, B and C)
  participating discovery and coordinating RTCPeerConnection handshakes.

  In each case, only the interaction between the clients is represented not
  how a signalling server
  (such as [rtc-switchboard](https://github.com/rtc-io/rtc-switchboard)) would
  pass on broadcast messages, etc.  This is done for two reasons:

  1. It is out of scope of this documentation.
  2. The `rtc-signaller` has been designed to work without having to rely on
     any intelligence in the server side signalling component.  In the
     instance that a signaller broadcasts all messages to all connected peers
     then `rtc-signaller` should be smart enough to make sure everything works
     as expected.

  ### Peer Discovery / Announcement

  This diagram illustrates the process of how peer `A` announces itself to
  peers `B` and `C`, and in turn they announce themselves.

  ![](https://raw.github.com/rtc-io/rtc-signaller/master/docs/announce.png)

  ### Editing / Updating the Diagrams

  Each of the diagrams has been generated using
  [mscgen](http://www.mcternan.me.uk/mscgen/index.html) and the source for
  these documents can be found in the `docs/` folder of this repository.

  ## Reference

  The `rtc-signaller` module is designed to be used primarily in a functional
  way and when called it creates a new signaller that will enable
  you to communicate with other peers via your messaging network.

  ```js
  // create a signaller from something that knows how to send messages
  var signaller = require('rtc-signaller')(messenger);
  ```

**/
var sig = module.exports = function(messenger, opts) {

  // create the signaller
  var signaller = new EventEmitter();

  // initialise the id
  var id = signaller.id = uuid.v4();

  // initialise the attributes
  var attributes = signaller.attributes = {
    id: id
  };

  // create the peers map
  var peers = signaller.peers = new FastMap();

  // create our locks map
  var locks = signaller.locks = new FastMap();

  // initialise the data event name
  var dataEvent = (opts || {}).dataEvent || 'data';
  var writeMethod = (opts || {}).writeMethod || 'write';
  var closeMethod = (opts || {}).closeMethod || 'close';

  // extract the write and close function references
  var write = messenger[writeMethod];
  var close = messenger[closeMethod];

  // create the processor
  var processor = require('./processor')(signaller);

  // if the messenger doesn't provide a valid write method, then complain
  if (typeof write != 'function') {
    throw new Error('provided messenger does not implement a "' +
      writeMethod + '" write method');
  }

  function prepareArg(arg) {
    if (typeof arg == 'object' && (! (arg instanceof String))) {
      return JSON.stringify(arg);
    }
    else if (typeof arg == 'function') {
      return null;
    }

    return arg;
  }

  /**
    ### signaller#send(data)

    Send data over the messenging interface.
  **/
  var send = signaller.send = function() {
    // iterate over the arguments and stringify as required
    var args = [].slice.call(arguments);
    var dataline = args.map(prepareArg).filter(Boolean).join('|');

    // send the data over the messenger
    return write.call(messenger, dataline);
  };

  /**
    ### signaller#announce(data?)

    The `announce` function of the signaller will pass an `/announce` message
    through the messenger network.  When no additional data is supplied to
    this function then only the id of the signaller is sent to all active
    members of the messenging network.

    As a unique it is generally insufficient information to determine whether
    a peer is a good match for another (for instance,  you might be looking
    for other parties by name or role) it is generally a good idea to provide
    some additional information during this announce call:

    ```js
    signaller.announce({ role: 'translator' });
    ```

    __NOTE:__ In some particular messenger types may attach or infer
    additional data during the announce phase.  For instance, socket.io
    connections are generally organised into rooms which is inferred
    information that limits the messaging scope.
  **/
  signaller.announce = function(data, sender) {
    // update internal attributes
    extend(attributes, data, { id: id });

    // send the attributes over the network
    return (sender || send)('/announce', attributes);
  };

  /**
    ### signaller#leave()

    Leave the messenger mesh
  **/
  signaller.leave = function() {
    // send the leave signal
    send('/leave', { id: id });

    // call the close method
    if (typeof close == 'function') {
      close.call(messenger);
    }
  };

  /**
    ### signaller#lock(targetId, opts?, callback?)

    Attempt to get a temporary exclusive lock on the communication
    channel between the local signaller and the specified target peer id.
  **/
  signaller.lock = function(targetId, opts, callback) {
    var peer = peers.get(targetId);
    var lockid = uuid.v4();
    var label;

    function handleLockResult(src, result) {
      var ok = result && result.ok;

      // if the source does not match the target then abort
      if ((! src) || (src.id !== targetId)) {
        return;
      }

      // if the result label is not a match, then abort
      if ((! result) || (result.label !== label)) {
        return;
      }

      // don't listen for any further lock result messages
      signaller.removeListener('lockresult', handleLockResult);

      // if we don't have an error condition, create a local lock
      if (ok) {
        locks.set(label, lockid);
      }

      callback(ok ? null : new Error('could not acquire lock'));
    }

    // check for no label being supplied
    if (typeof opts == 'function') {
      callback = opts;
      opts = {};
    }

    // ensure we have a callback
    callback = callback || function() {};

    // if the peer is not known, then we cannot initiate a lock
    if (! peer) {
      return callback(new Error('unknown target id - cannot initiate lock'));
    }

    // create a default label if none provided
    label = (opts || {}).label || (opts || {}).name || 'default';

    // if we have a local lock already in place, then return ok
    if (locks.get(label)) {
      return callback();
    }

    // ensure we have locks for the peer
    peer.locks = peer.locks || new FastMap();

    // if a remote lock is in place, error out
    if (peer.locks.get(label)) {
      return callback(new Error('remote lock in place, cannot request lock'));
    }

    // wait for the lock result
    signaller.on('lockresult', handleLockResult);

    // send the lock message
    signaller.to(targetId).send('/lock', label, lockid);
  };

  /**
    ### signaller#to(targetId)

    The to method returns an encapsulated

  **/
  signaller.to = function(targetId) {
    // create a sender that will prepend messages with /to|targetId|
    var sender = function() {
      // get the peer (yes when send is called to make sure it hasn't left)
      var peer = signaller.peers.get(targetId);
      var args;

      if (! peer) {
        throw new Error('Unknown peer: ' + targetId);
      }

      args = [
        '/to',
        targetId,
        { id: signaller.id, clock: peer.clock }
      ].concat([].slice.call(arguments));

      // increment the peer clock, using the role of the local
      // signaller.  If the peer role is 0, then the signallers role is 1
      // and using xor (^) will generate the correct index
      vc.increment(peer, ['a', 'b'][peer.roleIdx ^ 1]);

      // write on next tick to ensure clock updates are handled correctly
      setTimeout(function() {
        // include the current clock value in with the payload
        write.call(
          messenger,
          args.map(prepareArg).filter(Boolean).join('|')
        );
      }, 0);
    };

    return {
      announce: function(data) {
        return signaller.announce(data, sender);
      },

      send: sender,
    }
  };

  /**

    ### signaller#unlock(targetId, opts?)

  **/
  signaller.unlock = function(targetId, opts, callback) {
    var peer = peers.get(targetId);
    var label;

    function handleUnlockResult(src, result) {
      var ok = result && result.ok;

      // if not the correct source then abort
      if ((! src) || (src.id !== targetId)) {
        return;
      }

      // if this is not an unlock result for this label, then abort
      if ((! result) || (result.label !== label)) {
        return;
      }

      // remove the listener
      signaller.removeListener('unlockresult', handleUnlockResult);

      // if ok, remove our local lock
      if (ok) {
        locks.delete(label);
      }

      // trigger the callback
      callback(ok ? null : new Error('could not release lock: ' + label));
    }

    // handle the no opts case
    if (typeof opts == 'function') {
      callback = opts;
      opts = {};
    }

    // ensure we have a callback
    callback = callback || function() {};

    // set a default label value
    label = (opts || {}).label || (opts || {}).name || 'default';

    // if we have the peer and local lock then action the unlock
    if (peer && locks.get(label)) {
      signaller.on('unlockresult', handleUnlockResult);
      signaller.to(targetId).send('/unlock', label, locks.get(label));
    }
    else {
      return callback(new Error('no local lock with label ' + label));
    }
  };

  // handle message data events
  messenger.on(dataEvent, processor);

  return signaller;
};

sig.loadPrimus = require('./primus-loader');<|endoftext|>


<commit_before>'use strict';
var childProcess = require('child_process');
var stripAnsi = require('strip-ansi');
var shell = process.env.SHELL || '/bin/sh';
var path = process.env.PATH;
var user = process.env.USER;
var opts = {encoding: 'utf8'};

module.exports = function (cb) {
	if (process.platform === 'win32') {
		setImmediate(cb, null, path);
		return;
	}

	pathFromShell(function (err, p1) {
		if (err) {
			cb(err);
			return;
		}

		pathFromSudo(function (err, p2) {
			if (err) {
				cb(err);
				return;
			}

			// return the longest found path
			cb(null, longest([p1, p2, path]));
		});
	});
};

module.exports.sync = function () {
	if (process.platform === 'win32') {
		return path;
	}

	var p1 = pathFromShellSync();
	var p2 = pathFromSudoSync();

	// return the longest found path
	return longest([p1, p2, path]);
};

function pathFromShell(cb) {
	childProcess.execFile(shell, ['-i', '-c', 'echo "$PATH"'], opts, function (err, stdout) {
		if (err) {
			cb(err);
			return;
		}

		cb(null, clean(stdout));
	});
}

function pathFromShellSync() {
	return clean(childProcess.execFileSync(shell, ['-i', '-c', 'echo "$PATH"'], opts));
}

function pathFromSudo(cb) {
	childProcess.exec('sudo -Hiu ' + user + ' echo "$PATH"', opts, function (err, stdout) {
		if (err) {
			// may fail with 'sudo: must be setuid root'
			cb(null, '');
		}

		cb(null, clean(stdout));
	});
}

function pathFromSudoSync() {
	try {
		return clean(childProcess.execSync('sudo -Hiu ' + user + ' echo "$PATH"', opts));
	} catch (err) {
		// may fail with 'sudo: must be setuid root'
		return '';
	}
}

function clean(str) {
	return stripAnsi(str.trim());
}

function longest(arr) {
	return arr.reduce(function (a, b) {
		return a.length > b.length ? a : b;
	});
}
<commit_msg>don't cache process.env.PATH<commit_after>'use strict';
var childProcess = require('child_process');
var stripAnsi = require('strip-ansi');
var shell = process.env.SHELL || '/bin/sh';
var user = process.env.USER;
var opts = {encoding: 'utf8'};

module.exports = function (cb) {
	if (process.platform === 'win32') {
		setImmediate(cb, null, process.env.PATH);
		return;
	}

	pathFromShell(function (err, p1) {
		if (err) {
			cb(err);
			return;
		}

		pathFromSudo(function (err, p2) {
			if (err) {
				cb(err);
				return;
			}

			// return the longest found path
			cb(null, longest([p1, p2, process.env.PATH]));
		});
	});
};

module.exports.sync = function () {
	if (process.platform === 'win32') {
		return process.env.PATH;
	}

	var p1 = pathFromShellSync();
	var p2 = pathFromSudoSync();

	// return the longest found path
	return longest([p1, p2, process.env.PATH]);
};

function pathFromShell(cb) {
	childProcess.execFile(shell, ['-i', '-c', 'echo "$PATH"'], opts, function (err, stdout) {
		if (err) {
			cb(err);
			return;
		}

		cb(null, clean(stdout));
	});
}

function pathFromShellSync() {
	return clean(childProcess.execFileSync(shell, ['-i', '-c', 'echo "$PATH"'], opts));
}

function pathFromSudo(cb) {
	childProcess.exec('sudo -Hiu ' + user + ' echo "$PATH"', opts, function (err, stdout) {
		if (err) {
			// may fail with 'sudo: must be setuid root'
			cb(null, '');
		}

		cb(null, clean(stdout));
	});
}

function pathFromSudoSync() {
	try {
		return clean(childProcess.execSync('sudo -Hiu ' + user + ' echo "$PATH"', opts));
	} catch (err) {
		// may fail with 'sudo: must be setuid root'
		return '';
	}
}

function clean(str) {
	return stripAnsi(str.trim());
}

function longest(arr) {
	return arr.reduce(function (a, b) {
		return a.length > b.length ? a : b;
	});
}
<|endoftext|>


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

var counterSchema = new mongoose.Schema({
    model: {
        type: String,
        require: true
    },
    field: {
        type: String,
        require: true
    },
    c: {
        type: Number,
        default: 0
    }
});
counterSchema.index({ field: 1, model: 1 }, { unique: true, required: true, index: -1 });
var Counter = mongoose.connection.model('MAIC-Counter', counterSchema);

module.exports = exports = function (schema, options) {
    var settings = {
            model: null,
            field: '_id',
            startAt: 0,
            incrementBy: 1,
            incrementOnUpdate: false
        },
        fields = {},
        ready = false;

    switch (typeof(options)) {
        case 'String':
            settings.model = options;
            break;
        case 'Object':
            extend(settings, options);
            break;
    }

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

    Counter.findOne(
        { model: settings.model, field: settings.field },
        function (err, res) {
            if (!res) {
                var counter = new Counter({ model: settings.model, field: settings.field, c: settings.startAt });
                counter.save(function () {
                    ready = true;
                });
            }
            else
                ready = true;
        }
    );

    schema.pre('save', function (next) {
        var doc = this;
        (function save() {
            if (ready) {
                Counter.collection.findAndModify(
                    { model: settings.model, field: settings.field },
                    null,
                    { $inc: { c: settings.incrementBy } },
                    { new: true, upsert: true },
                    function (err, res) {
                        if (err) return next(err);
                        if (typeof(doc[settings.field]) !== 'number' || settings.incrementOnUpdate)
                            doc[settings.field] = res.c - 1;
                        next();
                    }
                );
            }
            else
                setTimeout(save, 5);
        })();
    });
};<commit_msg>Fixing random issues I've found while testing.<commit_after>var mongoose = require('mongoose'),
    extend = require('extend');

var counterSchema = new mongoose.Schema({
    model: {
        type: String,
        require: true
    },
    field: {
        type: String,
        require: true
    },
    c: {
        type: Number,
        default: 0
    }
});
counterSchema.index({ field: 1, model: 1 }, { unique: true, required: true, index: -1 });
var Counter = mongoose.connection.model('MAIC-Counter', counterSchema);

module.exports = exports = function (schema, options) {
    var settings = {
            model: null,
            field: '_id',
            startAt: 0,
            incrementBy: 1,
            incrementOnUpdate: false
        },
        fields = {},
        ready = false;

    switch (typeof(options)) {
        case 'string':
            settings.model = options;
            break;
        case 'object':
            extend(settings, options);
            break;
    }

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

    Counter.findOne(
        { model: settings.model, field: settings.field },
        function (err, res) {
            if (!res) {
                var counter = new Counter({ model: settings.model, field: settings.field, c: settings.startAt });
                counter.save(function () {
                    ready = true;
                });
            }
            else
                ready = true;
        }
    );

    schema.pre('save', function (next) {
        var doc = this;
        (function save() {
            if (ready) {
                Counter.collection.findAndModify(
                    { model: settings.model, field: settings.field },
                    null,
                    { $inc: { c: settings.incrementBy } },
                    { new: true, upsert: true },
                    function (err, res) {
                        if (err) return next(err);
                        if (typeof(doc[settings.field]) !== 'number' || settings.incrementOnUpdate)
                            doc[settings.field] = res.c - 1;
                        next();
                    }
                );
            }
            else
                setTimeout(save, 5);
        })();
    });
};
<|endoftext|>


<commit_before>'use strict';

module.exports = {

  rules: {

    /* Possible errors */

    'callback-return': [2, [
      'callback',
      'next',
      'done',
    ]],
    'no-catch-shadow': 2,
    'no-cond-assign': 2,
    'no-constant-condition': 2,
    'no-control-regex': 2,
    'no-debugger': 2,
    'no-delete-var': 2,
    'no-dupe-args': 2,
    'no-dupe-keys': 2,
    'no-duplicate-case': 2,
    'no-empty': 2,
    'no-empty-character-class': 2,
    'no-ex-assign': 2,
    'no-extra-boolean-cast': 1,
    'no-extra-parens': [1,
      'all',
      {
        conditionalAssign: false,
        nestedBinaryExpressions: false,
        returnAssign: false,
      },
    ],
    'no-extra-semi': 2,
    'no-func-assign': 2,
    'no-inner-declarations': 1,
    'no-invalid-regexp': 2,
    'no-irregular-whitespace': 2,
    'no-label-var': 2,
    'no-obj-calls': 2,
    'no-prototype-builtins': 2,
    'no-regex-spaces': 1,
    'no-shadow': 2,
    'no-shadow-restricted-names': 2,
    'no-sparse-arrays': 2,
    'no-undef': [2,
      { typeof: true },
    ],
    'no-undef-init': 1,
    'no-unexpected-multiline': 2,
    'no-unreachable': 2,
    'no-unsafe-finally': 2,
    'no-unsafe-negation': 1,
    'no-unused-vars': [1, {
      vars: 'all',
      args: 'after-used',
    }],
    'no-use-before-define': [2,
      'nofunc',
    ],
    'strict': 2,
    'use-isnan': 2,
    'valid-typeof': [2, { requireStringLiterals: true }],

    /* Best practices */

    'accessor-pairs': 2,
    'array-callback-return': 2,
    'block-scoped-var': 2,
    'comma-dangle': [1, {
      arrays: 'always-multiline',
      objects: 'always-multiline',
      imports: 'always-multiline',
      exports: 'always-multiline',
      functions: 'ignore',
    }],
    'complexity': [1, 7],
    'consistent-return': 1,
    'curly': [2, 'multi-line'],
    'default-case': 1,
    'dot-location': [1,
      'property',
    ],
    'dot-notation': 1,
    'eqeqeq': [1, 'smart'],
    'func-name-matching': 1,
    'guard-for-in': 1,
    'no-caller': 2,
    'no-console': 1,
    'no-div-regex': 1,
    'no-global-assign': 2,
    'no-else-return': 1,
    'no-empty-function': 1,
    'no-empty-pattern': 2,
    'no-eval': 2,
    'no-extend-native': 2,
    'no-extra-bind': 2,
    'no-fallthrough': 2,
    'no-floating-decimal': 1,
    'no-implicit-coercion': 1,
    'no-implied-eval': 2,
    'no-invalid-this': 1,
    'no-iterator': 2,
    'no-labels': 2,
    'no-lone-blocks': 1,
    'no-loop-func': 2,
    'no-magic-numbers': [1, {
      enforceConst: true,
      ignore: [-1, 0, 1, 2, 7, 12, 24, 30, 60],
      ignoreArrayIndexes: true,
    }],
    'no-multi-spaces': 1,
    'no-multi-str': 1,
    'no-new': 1,
    'no-new-func': 2,
    'no-new-wrappers': 2,
    'no-octal': 2,
    'no-octal-escape': 2,
    'no-proto': 2,
    'no-redeclare': 2,
    'no-restricted-properties': 0,
    'no-return-assign': 1,
    'no-script-url': 2,
    'no-self-assign': [2, { props: true }],
    'no-self-compare': 2,
    'no-sequences': 2,
    'no-throw-literal': 2,
    'no-unmodified-loop-condition': 2,
    'no-unused-expressions': 2,
    'no-useless-call': 2,
    'no-useless-concat': 2,
    'no-warning-comments': 1,
    'no-with': 2,
    'radix': 2,
    'require-jsdoc': 0,
    'valid-jsdoc': [1, {
      requireReturn: false,
      requireParamDescription: false,
      requireReturnDescription: false,
    }],
    'wrap-iife': 1,
    'yoda': 1,

    /* Stylistic consistency */

    'array-bracket-spacing': 1,
    'block-spacing': 1,
    'brace-style': 1,
    'camelcase': 0,
    'comma-spacing': 1,
    'comma-style': 1,
    'computed-property-spacing': 1,
    'consistent-this': [1, 'self'],
    'eol-last': 1,
    'func-call-spacing': 1,
    'func-names': 1, // when env is Node >=6 you can use [1, 'as-needed']
    'id-blacklist': [1,
      'obj', 'object',
      'num', 'number',
      'str', 'string',
      'bool', 'boolean',
      'val',
    ],
    'id-length': [1, {
      min: 3,
      exceptions: ['_', '$', '$q', 'cb', 'db', 'fs', 'i', 'id', 'x', 'y', 'S3'],
    }],
    'indent': [1,
      2,
      { SwitchCase: 1 },
    ],
    'jsx-quotes': 1,
    'key-spacing': [1, {
      afterColon: true,
      mode: 'minimum',
    }],
    'keyword-spacing': 1,
    'linebreak-style': 1,
    'lines-around-comment': [1, {
      beforeBlockComment: true,
      allowBlockStart: true,
      allowObjectStart: true,
      allowArrayStart: true,
    }],
    'lines-around-directive': 1,
    'line-comment-position': 0,
    'max-depth': [1, 5],
    'max-len': [1, {
      code: 120,
      ignoreComments: true,
      ignoreStrings: true,
      ignoreTemplateLiterals: true,
      ignoreTrailingComments: true,
      ignoreUrls: true,
    }],
    'max-lines': [1, {
      skipBlankLines: true,
      skipComments: true,
    }],
    'max-nested-callbacks': [1, 5],
    'max-params': [1, 5],
    'max-statements': [1, 16],
    'new-cap': 1,
    'new-parens': 1,
    'newline-per-chained-call': 0,
    'no-array-constructor': 2,
    'no-bitwise': 2,
    'no-continue': 1,
    'no-lonely-if': 1,
    'no-mixed-operators': 1,
    'no-mixed-spaces-and-tabs': 1,
    'no-multiple-empty-lines': 1,
    'no-nested-ternary': 2,
    'no-new-object': 2,
    'no-tabs': 1,
    'no-trailing-spaces': 1,
    'no-underscore-dangle': [1, {
      allow: ['_id'],
    }],
    'no-unneeded-ternary': 2,
    'no-whitespace-before-property': 1,
    'object-curly-newline': 0,
    'object-curly-spacing': [1, 'always'],
    'object-property-newline': [1, { allowMultiplePropertiesPerLine: true }],
    'one-var-declaration-per-line': 1,
    'operator-linebreak': [1, 'before'],
    'quote-props': [1, 'consistent-as-needed'],
    'quotes': [1, 'single', 'avoid-escape'],
    'semi': [1, 'always'],
    'semi-spacing': 1,
    'sort-keys': 0,
    'space-before-blocks': 1,
    'space-before-function-paren': [1, {
      anonymous: 'always',
      named: 'never',
    }],
    'space-in-parens': 1,
    'space-infix-ops': 1,
    'space-unary-ops': 1,
    'spaced-comment': 1,
    'unicode-bom': 1,
    'wrap-regex': 1,

  },

};
<commit_msg>add 'os' as exception to id-length<commit_after>'use strict';

module.exports = {

  rules: {

    /* Possible errors */

    'callback-return': [2, [
      'callback',
      'next',
      'done',
    ]],
    'no-catch-shadow': 2,
    'no-cond-assign': 2,
    'no-constant-condition': 2,
    'no-control-regex': 2,
    'no-debugger': 2,
    'no-delete-var': 2,
    'no-dupe-args': 2,
    'no-dupe-keys': 2,
    'no-duplicate-case': 2,
    'no-empty': 2,
    'no-empty-character-class': 2,
    'no-ex-assign': 2,
    'no-extra-boolean-cast': 1,
    'no-extra-parens': [1,
      'all',
      {
        conditionalAssign: false,
        nestedBinaryExpressions: false,
        returnAssign: false,
      },
    ],
    'no-extra-semi': 2,
    'no-func-assign': 2,
    'no-inner-declarations': 1,
    'no-invalid-regexp': 2,
    'no-irregular-whitespace': 2,
    'no-label-var': 2,
    'no-obj-calls': 2,
    'no-prototype-builtins': 2,
    'no-regex-spaces': 1,
    'no-shadow': 2,
    'no-shadow-restricted-names': 2,
    'no-sparse-arrays': 2,
    'no-undef': [2,
      { typeof: true },
    ],
    'no-undef-init': 1,
    'no-unexpected-multiline': 2,
    'no-unreachable': 2,
    'no-unsafe-finally': 2,
    'no-unsafe-negation': 1,
    'no-unused-vars': [1, {
      vars: 'all',
      args: 'after-used',
    }],
    'no-use-before-define': [2,
      'nofunc',
    ],
    'strict': 2,
    'use-isnan': 2,
    'valid-typeof': [2, { requireStringLiterals: true }],

    /* Best practices */

    'accessor-pairs': 2,
    'array-callback-return': 2,
    'block-scoped-var': 2,
    'comma-dangle': [1, {
      arrays: 'always-multiline',
      objects: 'always-multiline',
      imports: 'always-multiline',
      exports: 'always-multiline',
      functions: 'ignore',
    }],
    'complexity': [1, 7],
    'consistent-return': 1,
    'curly': [2, 'multi-line'],
    'default-case': 1,
    'dot-location': [1,
      'property',
    ],
    'dot-notation': 1,
    'eqeqeq': [1, 'smart'],
    'func-name-matching': 1,
    'guard-for-in': 1,
    'no-caller': 2,
    'no-console': 1,
    'no-div-regex': 1,
    'no-global-assign': 2,
    'no-else-return': 1,
    'no-empty-function': 1,
    'no-empty-pattern': 2,
    'no-eval': 2,
    'no-extend-native': 2,
    'no-extra-bind': 2,
    'no-fallthrough': 2,
    'no-floating-decimal': 1,
    'no-implicit-coercion': 1,
    'no-implied-eval': 2,
    'no-invalid-this': 1,
    'no-iterator': 2,
    'no-labels': 2,
    'no-lone-blocks': 1,
    'no-loop-func': 2,
    'no-magic-numbers': [1, {
      enforceConst: true,
      ignore: [-1, 0, 1, 2, 7, 12, 24, 30, 60],
      ignoreArrayIndexes: true,
    }],
    'no-multi-spaces': 1,
    'no-multi-str': 1,
    'no-new': 1,
    'no-new-func': 2,
    'no-new-wrappers': 2,
    'no-octal': 2,
    'no-octal-escape': 2,
    'no-proto': 2,
    'no-redeclare': 2,
    'no-restricted-properties': 0,
    'no-return-assign': 1,
    'no-script-url': 2,
    'no-self-assign': [2, { props: true }],
    'no-self-compare': 2,
    'no-sequences': 2,
    'no-throw-literal': 2,
    'no-unmodified-loop-condition': 2,
    'no-unused-expressions': 2,
    'no-useless-call': 2,
    'no-useless-concat': 2,
    'no-warning-comments': 1,
    'no-with': 2,
    'radix': 2,
    'require-jsdoc': 0,
    'valid-jsdoc': [1, {
      requireReturn: false,
      requireParamDescription: false,
      requireReturnDescription: false,
    }],
    'wrap-iife': 1,
    'yoda': 1,

    /* Stylistic consistency */

    'array-bracket-spacing': 1,
    'block-spacing': 1,
    'brace-style': 1,
    'camelcase': 0,
    'comma-spacing': 1,
    'comma-style': 1,
    'computed-property-spacing': 1,
    'consistent-this': [1, 'self'],
    'eol-last': 1,
    'func-call-spacing': 1,
    'func-names': 1, // when env is Node >=6 you can use [1, 'as-needed']
    'id-blacklist': [1,
      'obj', 'object',
      'num', 'number',
      'str', 'string',
      'bool', 'boolean',
      'val',
    ],
    'id-length': [1, {
      min: 3,
      exceptions: ['_', '$', '$q', 'cb', 'db', 'fs', 'i', 'id', 'os', 'x', 'y', 'S3'],
    }],
    'indent': [1,
      2,
      { SwitchCase: 1 },
    ],
    'jsx-quotes': 1,
    'key-spacing': [1, {
      afterColon: true,
      mode: 'minimum',
    }],
    'keyword-spacing': 1,
    'linebreak-style': 1,
    'lines-around-comment': [1, {
      beforeBlockComment: true,
      allowBlockStart: true,
      allowObjectStart: true,
      allowArrayStart: true,
    }],
    'lines-around-directive': 1,
    'line-comment-position': 0,
    'max-depth': [1, 5],
    'max-len': [1, {
      code: 120,
      ignoreComments: true,
      ignoreStrings: true,
      ignoreTemplateLiterals: true,
      ignoreTrailingComments: true,
      ignoreUrls: true,
    }],
    'max-lines': [1, {
      skipBlankLines: true,
      skipComments: true,
    }],
    'max-nested-callbacks': [1, 5],
    'max-params': [1, 5],
    'max-statements': [1, 16],
    'new-cap': 1,
    'new-parens': 1,
    'newline-per-chained-call': 0,
    'no-array-constructor': 2,
    'no-bitwise': 2,
    'no-continue': 1,
    'no-lonely-if': 1,
    'no-mixed-operators': 1,
    'no-mixed-spaces-and-tabs': 1,
    'no-multiple-empty-lines': 1,
    'no-nested-ternary': 2,
    'no-new-object': 2,
    'no-tabs': 1,
    'no-trailing-spaces': 1,
    'no-underscore-dangle': [1, {
      allow: ['_id'],
    }],
    'no-unneeded-ternary': 2,
    'no-whitespace-before-property': 1,
    'object-curly-newline': 0,
    'object-curly-spacing': [1, 'always'],
    'object-property-newline': [1, { allowMultiplePropertiesPerLine: true }],
    'one-var-declaration-per-line': 1,
    'operator-linebreak': [1, 'before'],
    'quote-props': [1, 'consistent-as-needed'],
    'quotes': [1, 'single', 'avoid-escape'],
    'semi': [1, 'always'],
    'semi-spacing': 1,
    'sort-keys': 0,
    'space-before-blocks': 1,
    'space-before-function-paren': [1, {
      anonymous: 'always',
      named: 'never',
    }],
    'space-in-parens': 1,
    'space-infix-ops': 1,
    'space-unary-ops': 1,
    'spaced-comment': 1,
    'unicode-bom': 1,
    'wrap-regex': 1,

  },

};
<|endoftext|>


<commit_before>const { EventEmitter } = require('events')
const flowdock = require('flowdock')
const format = require('./format')

const isFlowSelected = flows => flow =>
  flows.indexOf(flow.id) >= 0 || flows.indexOf(flow.parameterized_name) >= 0

const callRes = (session, method, ...args) =>
  new Promise((resolve, reject) =>
    session[method](...args, (err, body, res) =>
      err ? reject(err) : resolve(res)))

const call = (...args) =>
  callRes(...args).then(res => res.body)

const getRawState = session =>
  callRes(session, 'flows')
    .then(res => ({
      userId: res.headers['flowdock-user'],
      flows: res.body
    }))

function Flowdock (config) {
  const emitter = new EventEmitter()
  const session = new flowdock.Session(config.token)
  const onError = err => emitter.emit('error', err)
  const state = {}

  const onEvent = event =>
    event.user !== state.userId && emitter.emit(`raw:${event.event}`, event)

  const onLoad = state => {
    const flows = state.flows
      .filter(config.flows ? isFlowSelected(config.flows) : flow => flow.joined)
      .map(flow => flow.id)

    if (state.stream) {
      state.stream.removeAllListeners()
    }

    state.stream = session.stream(flows, config.streamConfig)
      .on('message', onEvent)
      .on('error', onError)
  }

  const onMessage = message =>
    emitter.emit('message', format.message(state)(message))

  const onJoinUser = message =>
    state.usersById[message.user] = format.user(message.content.user)

  const reload = () => {
    getRawState(session)
      .then(format.state)
      .then(state => emitter.emit('load', state))
      .catch(onError)
  }

  emitter.on('load', newState => Object.assign(state, newState))
  emitter.on('load', onLoad)
  emitter.on('raw:message', onMessage)
  emitter.on('raw:backend.join.user', onJoinUser)
  emitter.on('raw:flow-add', reload)
  emitter.on('raw:source-remove', reload)

  emitter.mention = user => `@${user.name}`
  emitter.address = (user, text) => `${emitter.mention(user)}, ${text}`

  emitter.isMentioned = (user, message) =>
    message.raw.tags.includes(`:user:${user.id}`)

  const sendFlow = (message, text) =>
    call(session, 'threadMessage', message.raw.flow, message.raw.thread_id, text, [])

  const sendPrivate = (message, text) =>
    call(session, 'privateMessage', message.author.id, text, [])

  emitter.send = (message, text) =>
    (message.raw.to ? sendPrivate : sendFlow)(message, text)
      .then(format.message(state))

  const editFlow = (message, text) => {
    const flowObject = state.flowsById[message.raw.flow]
    const flow = flowObject.parameterized_name
    const org = flowObject.organization.parameterized_name

    return call(session, 'editMessage', flow, org, message.id, { content: text })
  }

  const editPrivate = (message, text) =>
    call(session, 'put', `/private/${message.raw.to}/messages/${message.id}`, { content: text })

  emitter.edit = (message, text) =>
    (message.raw.to ? editPrivate : editFlow)(message, text)
      .then(() => Object.assign({}, message, { text }))

  reload()

  return emitter
}

module.exports = Flowdock
<commit_msg>More loose flow matching<commit_after>const { EventEmitter } = require('events')
const flowdock = require('flowdock')
const format = require('./format')

const flowPath = flow =>
  `${flow.organization.parameterized_name}/${flow.parameterized_name}`

const findFlow = identifier => flow =>
  flow.id === identifier ||
    flow.parameterized_name === identifier ||
    flowPath(flow) === identifier ||
    flow.name.toLowerCase() === identifier.toLowerCase()

const isFlowSelected = flows => flow =>
  flows.find(identifier => findFlow(identifier)(flow))

const callRes = (session, method, ...args) =>
  new Promise((resolve, reject) =>
    session[method](...args, (err, body, res) =>
      err ? reject(err) : resolve(res)))

const call = (...args) =>
  callRes(...args).then(res => res.body)

const getRawState = session =>
  callRes(session, 'flows')
    .then(res => ({
      userId: res.headers['flowdock-user'],
      flows: res.body
    }))

function Flowdock (config) {
  const emitter = new EventEmitter()
  const session = new flowdock.Session(config.token)
  const onError = err => emitter.emit('error', err)
  const state = {}

  const onEvent = event =>
    event.user !== state.userId && emitter.emit(`raw:${event.event}`, event)

  const onLoad = state => {
    const flows = state.flows
      .filter(config.flows ? isFlowSelected(config.flows) : flow => flow.joined)
      .map(flow => flow.id)

    if (state.stream) {
      state.stream.removeAllListeners()
    }

    state.stream = session.stream(flows, config.streamConfig)
      .on('message', onEvent)
      .on('error', onError)
  }

  const onMessage = message =>
    emitter.emit('message', format.message(state)(message))

  const onJoinUser = message =>
    state.usersById[message.user] = format.user(message.content.user)

  const reload = () => {
    getRawState(session)
      .then(format.state)
      .then(state => emitter.emit('load', state))
      .catch(onError)
  }

  emitter.on('load', newState => Object.assign(state, newState))
  emitter.on('load', onLoad)
  emitter.on('raw:message', onMessage)
  emitter.on('raw:backend.join.user', onJoinUser)
  emitter.on('raw:flow-add', reload)
  emitter.on('raw:source-remove', reload)

  emitter.mention = user => `@${user.name}`
  emitter.address = (user, text) => `${emitter.mention(user)}, ${text}`

  emitter.isMentioned = (user, message) =>
    message.raw.tags.includes(`:user:${user.id}`)

  const sendFlow = (message, text) =>
    call(session, 'threadMessage', message.raw.flow, message.raw.thread_id, text, [])

  const sendPrivate = (message, text) =>
    call(session, 'privateMessage', message.author.id, text, [])

  emitter.send = (message, text) =>
    (message.raw.to ? sendPrivate : sendFlow)(message, text)
      .then(format.message(state))

  const editFlow = (message, text) => {
    const flowObject = state.flowsById[message.raw.flow]
    const flow = flowObject.parameterized_name
    const org = flowObject.organization.parameterized_name

    return call(session, 'editMessage', flow, org, message.id, { content: text })
  }

  const editPrivate = (message, text) =>
    call(session, 'put', `/private/${message.raw.to}/messages/${message.id}`, { content: text })

  emitter.edit = (message, text) =>
    (message.raw.to ? editPrivate : editFlow)(message, text)
      .then(() => Object.assign({}, message, { text }))

  reload()

  return emitter
}

module.exports = Flowdock
<|endoftext|>


<commit_before>// @flow

/**
 * `autocomplete` type prompt
 */

var ansiEscapes = require('ansi-escapes');
var chalk = require('chalk');
var figures = require('figures');
var Base = require('inquirer/lib/prompts/base');
var Choices = require('inquirer/lib/objects/choices');
var observe = require('inquirer/lib/utils/events');
var utils = require('inquirer/lib/utils/readline');
var Paginator = require('inquirer/lib/utils/paginator');
var runAsync = require('run-async');
var { takeWhile } = require('rxjs/operators');

class AutocompletePrompt extends Base {
  constructor(
    questions /*: Array<any> */,
    rl /*: readline$Interface */,
    answers /*: Array<any> */
  ) {
    super(questions, rl, answers);

    if (!this.opt.source) {
      this.throwParamError('source');
    }

    this.currentChoices = [];

    this.firstRender = true;
    this.selected = 0;

    // Make sure no default is set (so it won't be printed)
    this.opt.default = null;

    this.paginator = new Paginator();
  }

  /**
   * Start the Inquiry session
   * @param  {Function} cb      Callback when prompt is done
   * @return {this}
   */
  _run(cb /*: Function */) /*: this*/ {
    this.done = cb;

    if (this.rl.history instanceof Array) {
      this.rl.history = [];
    }

    var events = observe(this.rl);

    const dontHaveAnswer = () => !this.answer;

    events.line
      .pipe(takeWhile(dontHaveAnswer))
      .forEach(this.onSubmit.bind(this));
    events.keypress
      .pipe(takeWhile(dontHaveAnswer))
      .forEach(this.onKeypress.bind(this));

    // Call once at init
    this.search(undefined);

    return this;
  }

  /**
   * Render the prompt to screen
   * @return {undefined}
   */
  render(error /*: ?string */) {
    // Render question
    var content = this.getQuestion();
    var bottomContent = '';

    if (this.firstRender) {
      var suggestText = this.opt.suggestOnly ? ', tab to autocomplete' : '';
      content += chalk.dim(
        '(Use arrow keys or type to search' + suggestText + ')'
      );
    }
    // Render choices or answer depending on the state
    if (this.status === 'answered') {
      content += chalk.cyan(this.shortAnswer || this.answerName || this.answer);
    } else if (this.searching) {
      content += this.rl.line;
      bottomContent += '  ' + chalk.dim('Searching...');
    } else if (this.currentChoices.length) {
      var choicesStr = listRender(this.currentChoices, this.selected);
      content += this.rl.line;
      bottomContent += this.paginator.paginate(
        choicesStr,
        this.selected,
        this.opt.pageSize
      );
    } else {
      content += this.rl.line;
      bottomContent += '  ' + chalk.yellow('No results...');
    }

    if (error) {
      bottomContent += '\n' + chalk.red('>> ') + error;
    }

    this.firstRender = false;

    this.screen.render(content, bottomContent);
  }

  /**
   * When user press `enter` key
   */
  onSubmit(line /* : string */) {
    if (typeof this.opt.validate === 'function' && this.opt.suggestOnly) {
      var validationResult = this.opt.validate(line);
      if (validationResult !== true) {
        this.render(
          validationResult || 'Enter something, tab to autocomplete!'
        );
        return;
      }
    }

    var choice = {};
    if (this.currentChoices.length <= this.selected && !this.opt.suggestOnly) {
      this.rl.write(line);
      this.search(line);
      return;
    }

    if (this.opt.suggestOnly) {
      choice.value = line || this.rl.line;
      this.answer = line || this.rl.line;
      this.answerName = line || this.rl.line;
      this.shortAnswer = line || this.rl.line;
      this.rl.line = '';
    } else {
      choice = this.currentChoices.getChoice(this.selected);
      this.answer = choice.value;
      this.answerName = choice.name;
      this.shortAnswer = choice.short;
    }

    runAsync(this.opt.filter, (err, value) => {
      choice.value = value;
      this.answer = value;

      if (this.opt.suggestOnly) {
        this.shortAnswer = value;
      }

      this.status = 'answered';
      // Rerender prompt
      this.render();
      this.screen.done();
      this.done(choice.value);
    })(choice.value);
  }

  search(searchTerm /* : ?string */) {
    var self = this;
    self.selected = 0;

    // Only render searching state after first time
    if (self.searchedOnce) {
      self.searching = true;
      self.currentChoices = new Choices([]);
      self.render(); // Now render current searching state
    } else {
      self.searchedOnce = true;
    }

    self.lastSearchTerm = searchTerm;
    var thisPromise = self.opt.source(self.answers, searchTerm);

    // Store this promise for check in the callback
    self.lastPromise = thisPromise;

    return thisPromise.then(function inner(choices) {
      // If another search is triggered before the current search finishes, don't set results
      if (thisPromise !== self.lastPromise) return;

      choices = new Choices(
        choices.filter(function(choice) {
          return choice.type !== 'separator';
        })
      );

      self.currentChoices = choices;
      self.searching = false;
      self.render();
    });
  }

  ensureSelectedInRange() {
    var selectedIndex = Math.min(this.selected, this.currentChoices.length); // Not above currentChoices length - 1
    this.selected = Math.max(selectedIndex, 0); // Not below 0
  }

  /**
   * When user type
   */

  onKeypress(e /* : {key: { name: string }, value: string} */) {
    var len;
    var keyName = (e.key && e.key.name) || undefined;

    if (keyName === 'tab' && this.opt.suggestOnly) {
      if (this.currentChoices.getChoice(this.selected)) {
        this.rl.write(ansiEscapes.cursorLeft);
        var autoCompleted = this.currentChoices.getChoice(this.selected).value;
        this.rl.write(ansiEscapes.cursorForward(autoCompleted.length));
        this.rl.line = autoCompleted;
        this.render();
      }
    } else if (keyName === 'down') {
      len = this.currentChoices.length;
      this.selected = this.selected < len - 1 ? this.selected + 1 : 0;
      this.ensureSelectedInRange();
      this.render();
      utils.up(this.rl, 2);
    } else if (keyName === 'up') {
      len = this.currentChoices.length;
      this.selected = this.selected > 0 ? this.selected - 1 : len - 1;
      this.ensureSelectedInRange();
      this.render();
    } else {
      this.render(); // Render input automatically
      // Only search if input have actually changed, not because of other keypresses
      if (this.lastSearchTerm !== this.rl.line) {
        this.search(this.rl.line); // Trigger new search
      }
    }
  }
}

/**
 * Function for rendering list choices
 * @param  {Number} pointer Position of the pointer
 * @return {String}         Rendered content
 */
function listRender(choices, pointer /*: string */) /*: string */ {
  var output = '';
  var separatorOffset = 0;

  choices.forEach(function(choice, i) {
    if (choice.type === 'separator') {
      separatorOffset++;
      output += '  ' + choice + '\n';
      return;
    }

    var isSelected = i - separatorOffset === pointer;
    var line = (isSelected ? figures.pointer + ' ' : '  ') + choice.name;

    if (isSelected) {
      line = chalk.cyan(line);
    }
    output += line + ' \n';
  });

  return output.replace(/\n$/, '');
}

module.exports = AutocompletePrompt;
<commit_msg>Allow validation to be async<commit_after>// @flow

/**
 * `autocomplete` type prompt
 */

var ansiEscapes = require('ansi-escapes');
var chalk = require('chalk');
var figures = require('figures');
var Base = require('inquirer/lib/prompts/base');
var Choices = require('inquirer/lib/objects/choices');
var observe = require('inquirer/lib/utils/events');
var utils = require('inquirer/lib/utils/readline');
var Paginator = require('inquirer/lib/utils/paginator');
var runAsync = require('run-async');
var { takeWhile } = require('rxjs/operators');

class AutocompletePrompt extends Base {
  constructor(
    questions /*: Array<any> */,
    rl /*: readline$Interface */,
    answers /*: Array<any> */
  ) {
    super(questions, rl, answers);

    if (!this.opt.source) {
      this.throwParamError('source');
    }

    this.currentChoices = [];

    this.firstRender = true;
    this.selected = 0;

    // Make sure no default is set (so it won't be printed)
    this.opt.default = null;

    this.paginator = new Paginator();
  }

  /**
   * Start the Inquiry session
   * @param  {Function} cb      Callback when prompt is done
   * @return {this}
   */
  _run(cb /*: Function */) /*: this*/ {
    this.done = cb;

    if (this.rl.history instanceof Array) {
      this.rl.history = [];
    }

    var events = observe(this.rl);

    const dontHaveAnswer = () => !this.answer;

    events.line
      .pipe(takeWhile(dontHaveAnswer))
      .forEach(this.onSubmit.bind(this));
    events.keypress
      .pipe(takeWhile(dontHaveAnswer))
      .forEach(this.onKeypress.bind(this));

    // Call once at init
    this.search(undefined);

    return this;
  }

  /**
   * Render the prompt to screen
   * @return {undefined}
   */
  render(error /*: ?string */) {
    // Render question
    var content = this.getQuestion();
    var bottomContent = '';

    if (this.firstRender) {
      var suggestText = this.opt.suggestOnly ? ', tab to autocomplete' : '';
      content += chalk.dim(
        '(Use arrow keys or type to search' + suggestText + ')'
      );
    }
    // Render choices or answer depending on the state
    if (this.status === 'answered') {
      content += chalk.cyan(this.shortAnswer || this.answerName || this.answer);
    } else if (this.searching) {
      content += this.rl.line;
      bottomContent += '  ' + chalk.dim('Searching...');
    } else if (this.currentChoices.length) {
      var choicesStr = listRender(this.currentChoices, this.selected);
      content += this.rl.line;
      bottomContent += this.paginator.paginate(
        choicesStr,
        this.selected,
        this.opt.pageSize
      );
    } else {
      content += this.rl.line;
      bottomContent += '  ' + chalk.yellow('No results...');
    }

    if (error) {
      bottomContent += '\n' + chalk.red('>> ') + error;
    }

    this.firstRender = false;

    this.screen.render(content, bottomContent);
  }

  /**
   * When user press `enter` key
   */
  onSubmit(line /* : string */) {
    if (typeof this.opt.validate === 'function' && this.opt.suggestOnly) {
      const checkValidationResult = validationResult => {
        if (validationResult !== true) {
          this.render(
            validationResult || 'Enter something, tab to autocomplete!'
          );
        } else {
          this.onSubmitAfterValidation(line);
        }
      };

      var validationResult = this.opt.validate(line);
      if (isPromise(validationResult)) {
        validationResult.then(checkValidationResult);
      } else {
        checkValidationResult(validationResult);
      }
    } else {
      this.onSubmitAfterValidation(line);
    }
  }

  onSubmitAfterValidation(line /* : string */) {
    var choice = {};
    if (this.currentChoices.length <= this.selected && !this.opt.suggestOnly) {
      this.rl.write(line);
      this.search(line);
      return;
    }

    if (this.opt.suggestOnly) {
      choice.value = line || this.rl.line;
      this.answer = line || this.rl.line;
      this.answerName = line || this.rl.line;
      this.shortAnswer = line || this.rl.line;
      this.rl.line = '';
    } else {
      choice = this.currentChoices.getChoice(this.selected);
      this.answer = choice.value;
      this.answerName = choice.name;
      this.shortAnswer = choice.short;
    }

    runAsync(this.opt.filter, (err, value) => {
      choice.value = value;
      this.answer = value;

      if (this.opt.suggestOnly) {
        this.shortAnswer = value;
      }

      this.status = 'answered';
      // Rerender prompt
      this.render();
      this.screen.done();
      this.done(choice.value);
    })(choice.value);
  }

  search(searchTerm /* : ?string */) {
    var self = this;
    self.selected = 0;

    // Only render searching state after first time
    if (self.searchedOnce) {
      self.searching = true;
      self.currentChoices = new Choices([]);
      self.render(); // Now render current searching state
    } else {
      self.searchedOnce = true;
    }

    self.lastSearchTerm = searchTerm;
    var thisPromise = self.opt.source(self.answers, searchTerm);

    // Store this promise for check in the callback
    self.lastPromise = thisPromise;

    return thisPromise.then(function inner(choices) {
      // If another search is triggered before the current search finishes, don't set results
      if (thisPromise !== self.lastPromise) return;

      choices = new Choices(
        choices.filter(function(choice) {
          return choice.type !== 'separator';
        })
      );

      self.currentChoices = choices;
      self.searching = false;
      self.render();
    });
  }

  ensureSelectedInRange() {
    var selectedIndex = Math.min(this.selected, this.currentChoices.length); // Not above currentChoices length - 1
    this.selected = Math.max(selectedIndex, 0); // Not below 0
  }

  /**
   * When user type
   */

  onKeypress(e /* : {key: { name: string }, value: string} */) {
    var len;
    var keyName = (e.key && e.key.name) || undefined;

    if (keyName === 'tab' && this.opt.suggestOnly) {
      if (this.currentChoices.getChoice(this.selected)) {
        this.rl.write(ansiEscapes.cursorLeft);
        var autoCompleted = this.currentChoices.getChoice(this.selected).value;
        this.rl.write(ansiEscapes.cursorForward(autoCompleted.length));
        this.rl.line = autoCompleted;
        this.render();
      }
    } else if (keyName === 'down') {
      len = this.currentChoices.length;
      this.selected = this.selected < len - 1 ? this.selected + 1 : 0;
      this.ensureSelectedInRange();
      this.render();
      utils.up(this.rl, 2);
    } else if (keyName === 'up') {
      len = this.currentChoices.length;
      this.selected = this.selected > 0 ? this.selected - 1 : len - 1;
      this.ensureSelectedInRange();
      this.render();
    } else {
      this.render(); // Render input automatically
      // Only search if input have actually changed, not because of other keypresses
      if (this.lastSearchTerm !== this.rl.line) {
        this.search(this.rl.line); // Trigger new search
      }
    }
  }
}

/**
 * Function for rendering list choices
 * @param  {Number} pointer Position of the pointer
 * @return {String}         Rendered content
 */
function listRender(choices, pointer /*: string */) /*: string */ {
  var output = '';
  var separatorOffset = 0;

  choices.forEach(function(choice, i) {
    if (choice.type === 'separator') {
      separatorOffset++;
      output += '  ' + choice + '\n';
      return;
    }

    var isSelected = i - separatorOffset === pointer;
    var line = (isSelected ? figures.pointer + ' ' : '  ') + choice.name;

    if (isSelected) {
      line = chalk.cyan(line);
    }
    output += line + ' \n';
  });

  return output.replace(/\n$/, '');
}

function isPromise(value) {
  return typeof value === 'object' && typeof value.then === 'function';
}

module.exports = AutocompletePrompt;
<|endoftext|>


<commit_before>var express = require('express')
  , app     = express()
  , server  = require('http').createServer(app)
  , io      = require('socket.io')(server)
  , users   = [];

// declare path for static files
app.use(express.static(__dirname + '/public'));

// serve chat ui on get request
app.get('/', function(req, res){
	res.sendFile('index.html');
});

// listen for new connection
io.on('connection', function(client){

  client.emit('online users', users);

  // listen for username when logged in
  client.on('login', function(data){
    client.username = data;
    users.push(client.username);
    console.log('+ ' + client.username + ' logged in');
    io.emit('new user', client.username);
  });

  // listen for disconnect
  client.on('disconnect', function(){
    var userIndex = users.indexOf(client.username);
    users.splice(userIndex, 1);
    io.emit('online users', users);
    console.log('- ' + client.username + ' logged out');

    // send farewell message
    io.emit('message', {
      name: client.username,
      message: '... has left the building...'
    });
  });

  // listen for new messages
  client.on('new message', function(data){
    io.emit('message', data);
  });

});

// listen for requests on 8000
server.listen(8000, function(){
  console.log('Server listening on port 8000');
});
<commit_msg>add array for last 10 messages<commit_after>var express = require('express')
  , app     = express()
  , server  = require('http').createServer(app)
  , io      = require('socket.io')(server)
  , msgs    = []
  , users   = [];

// declare path for static files
app.use(express.static(__dirname + '/public'));

// serve chat ui on get request
app.get('/', function(req, res){
	res.sendFile('index.html');
});

// listen for new connection
io.on('connection', function(client){

  client.emit('online users', users);

  // listen for username when logged in
  client.on('login', function(data){
    client.username = data;
    users.push(client.username);
    console.log('+ ' + client.username + ' logged in');
    io.emit('new user', client.username);
    msgs.forEach(function(msg){
      client.emit('message', msg);
    });
  });

  // listen for disconnect
  client.on('disconnect', function(){
    var userIndex = users.indexOf(client.username);
    users.splice(userIndex, 1);
    io.emit('online users', users);
    console.log('- ' + client.username + ' logged out');

    // send farewell message
    io.emit('message', {
      name: client.username,
      message: '... has left the building...'
    });
  });

  // listen for new messages
  client.on('new message', function(data){
    io.emit('message', data);
    msgs.push(data);
    while (msgs.length > 10) {
      msgs.shift();
    }
  });

});

// listen for requests on 8000
server.listen(8000, function(){
  console.log('Server listening on port 8000');
});
<|endoftext|>


<commit_before>require('console.mute');
var fs = require('fs');
var _  = require('lodash');

module.exports = {
  parseCategories     : parseCategories,
  fixPluginName       : fixPluginName,
  camelize            : camelize,
  fixPluginCategories : fixPluginCategories,
  copy                : copy,
  getUniqueItems      : getUniqueItems,
  debugLog            : debugLog
}

/**
* @param {String} user's input
*/
function parseCategories(input) {
  this.options.categories = input.split(',');
}

/** Function that validate the Spinner name
* @returns {String}
*/
function fixPluginName(name, ReplaceSymbol) {
  name = name.toLowerCase().trim();
  return name.replace(/ /g, ReplaceSymbol);
}

/** Function that validate the Categories
* @returns {String}
*/
function fixPluginCategories(list) {
  list = list.replace(/ /g, '').toLowerCase().trim();
  var arrayCategories = list.split(',');
  return JSON.stringify(arrayCategories);
}

/** Function that converts a string into camel case using javascript regex
 * @author Christian C. Salvadó
 * @see http://stackoverflow.com/questions/2970525/converting-any-string-into-camel-case
 * @param {string} user's input
 * @returns {string} camelCase
*/
function camelize(str) {
  return str.replace(/(?:^\w|[A-Z]|\b\w)/g, function (letter, index) {
    return index === 0 ? letter.toLowerCase() : letter.toUpperCase();
  }).replace(/\s+/g, '');
}

/** Function copy files
* @param {object} self
* @param {string} fn  function which is going to be invoked
* @param {string} origin
* @param {string} destination location - files to copy
* @param {boolean} [data] internally it uses copy or copyTpl
*/
function copy(self, fn, origin, destination, data){
  self.fs[fn](
    self.templatePath(origin),
    self.destinationPath(destination),
    data
  );
}

/** Get unique values from object Example: Dependencies inside Modules
* @param {object} items
* @param {string} key
* @returns {object} items
*/
function getUniqueItems(items, key){
  items = _.map(items, key);
  items = _.flatten(items);
  items = _.uniq(items);
  return  _.compact(items);
}

/** MAnages koapp-cli logs
* @param {string} message
* @param {boolean} debug
*/
function debugLog(message, debug){
  if(!debug) debug = false;
  if(!debug) console.log(message);
  else{
    console.resume();
    console.log(message);
    console.mute();
  }
}
<commit_msg>Remove parse categories<commit_after>require('console.mute');
var fs = require('fs');
var _  = require('lodash');

module.exports = {
  fixPluginName       : fixPluginName,
  camelize            : camelize,
  fixPluginCategories : fixPluginCategories,
  copy                : copy,
  getUniqueItems      : getUniqueItems,
  debugLog            : debugLog
}

/** Function that validate the Spinner name
* @returns {String}
*/
function fixPluginName(name, ReplaceSymbol) {
  name = name.toLowerCase().trim();
  return name.replace(/ /g, ReplaceSymbol);
}

/** Function that validate the Categories
* @returns {String}
*/
function fixPluginCategories(list) {
  list = list.replace(/ /g, '').toLowerCase().trim();
  var arrayCategories = list.split(',');
  return JSON.stringify(arrayCategories);
}

/** Function that converts a string into camel case using javascript regex
 * @author Christian C. Salvadó
 * @see http://stackoverflow.com/questions/2970525/converting-any-string-into-camel-case
 * @param {string} user's input
 * @returns {string} camelCase
*/
function camelize(str) {
  return str.replace(/(?:^\w|[A-Z]|\b\w)/g, function (letter, index) {
    return index === 0 ? letter.toLowerCase() : letter.toUpperCase();
  }).replace(/\s+/g, '');
}

/** Function copy files
* @param {object} self
* @param {string} fn  function which is going to be invoked
* @param {string} origin
* @param {string} destination location - files to copy
* @param {boolean} [data] internally it uses copy or copyTpl
*/
function copy(self, fn, origin, destination, data){
  self.fs[fn](
    self.templatePath(origin),
    self.destinationPath(destination),
    data
  );
}

/** Get unique values from object Example: Dependencies inside Modules
* @param {object} items
* @param {string} key
* @returns {object} items
*/
function getUniqueItems(items, key){
  items = _.map(items, key);
  items = _.flatten(items);
  items = _.uniq(items);
  return  _.compact(items);
}

/** MAnages koapp-cli logs
* @param {string} message
* @param {boolean} debug
*/
function debugLog(message, debug){
  if(!debug) debug = false;
  if(!debug) console.log(message);
  else{
    console.resume();
    console.log(message);
    console.mute();
  }
}
<|endoftext|>


<commit_before>import _fetch from 'isomorphic-fetch'

const defaultHeaders = {
  'content-type': 'application/json',
  'accept': 'application/json'
}

function fetch (url, options = {
  method: 'get',
  headers: null,
  body: null
}) {
  options.method = (options.method || 'get').toLowerCase()
  options.headers = Object.assign({}, defaultHeaders, options.headers)
  if (options.method === 'get' || options.method === 'head') {
    delete options.body
  } else if (options.body) {
    options.body = JSON.stringify(options.body)
  }
  return _fetch(url, options)
    .then(response => {
      return response.json()
        .then(data => {
          if (response.ok) {
            return data
          }
          return Promise.reject({
            status: response.status,
            statusText: response.statusText,
            response: data
          })
        })
    })
}

['get', 'post', 'put', 'patch', 'delete'].forEach(method => {
  fetch[method] = (url, body) => fetch(url, { method, body })
})

export default fetch
<commit_msg>Implemented supporting options for convenient methods<commit_after>import _fetch from 'isomorphic-fetch'

const defaultHeaders = {
  'content-type': 'application/json',
  'accept': 'application/json'
}

function fetch (url, options = {
  method: 'get',
  headers: null,
  body: null
}) {
  options.method = (options.method || 'get').toLowerCase()
  options.headers = Object.assign({}, defaultHeaders, options.headers)
  if (options.method === 'get' || options.method === 'head') {
    delete options.body
  } else if (options.body) {
    options.body = JSON.stringify(options.body)
  }
  return _fetch(url, options)
    .then(response => {
      return response.json()
        .then(data => {
          if (response.ok) {
            return data
          }
          return Promise.reject({
            status: response.status,
            statusText: response.statusText,
            response: data
          })
        })
    })
}

['get', 'post', 'put', 'patch', 'delete', 'head'].forEach(method => {
  fetch[method] = (url, body, options = {}) => {
    options.method = method
    if (body) {
      if (method === 'get' || method === 'head') {
        options = body
      } else {
        options.body = body
      }
    }
    return fetch(url, options)
  }
})

export default fetch
<|endoftext|>