<commit_before>'use strict';

var Typeahead = require('suggestions');
var debounce = require('lodash.debounce');
var extend = require('xtend');
var EventEmitter = require('events').EventEmitter;
var exceptions = require('./exceptions');
var MapboxClient = require('mapbox/lib/services/geocoding');

/**
 * A geocoder component using Mapbox Geocoding API
 * @class MapboxGeocoder
 *
 * @param {Object} options
 * @param {String} options.accessToken Required.
 * @param {Number} [options.zoom=16] On geocoded result what zoom level should the map animate to when a `bbox` isn't found in the response. If a `bbox` is found the map will fit to the `bbox`.
 * @param {Boolean} [options.flyTo=true] If false, animating the map to a selected result is disabled.
 * @param {String} [options.placeholder="Search"] Override the default placeholder attribute value.
 * @param {Object} [options.proximity] a proximity argument: this is
 * a geographical point given as an object with latitude and longitude
 * properties. Search results closer to this point will be given
 * higher priority.
 * @param {Array} [options.bbox] a bounding box argument: this is
 * a bounding box given as an array in the format [minX, minY, maxX, maxY].
 * Search results will be limited to the bounding box.
 * @param {string} [options.types] a comma seperated list of types that filter
 * results to match those specified. See https://www.mapbox.com/developers/api/geocoding/#filter-type
 * for available types.
 * @param {string} [options.country] a comma separated list of country codes to
 * limit results to specified country or countries.
 * @param {Number} [options.minLength=2] Minimum number of characters to enter before results are shown.
 * @param {Number} [options.limit=5] Maximum number of results to show.
 * @param {string} [options.language] Specify the language to use for response text and query result weighting. Options are IETF language tags comprised of a mandatory ISO 639-1 language code and optionally one or more IETF subtags for country or script. More than one value can also be specified, separated by commas.
 * @example
 * var geocoder = new MapboxGeocoder({ accessToken: mapboxgl.accessToken });
 * map.addControl(geocoder);
 * @return {MapboxGeocoder} `this`
 */
function MapboxGeocoder(options) {
  this._eventEmitter = new EventEmitter();
  this.options = extend({}, this.options, options);
}

MapboxGeocoder.prototype = {

  options: {
    placeholder: 'Search',
    zoom: 16,
    flyTo: true,
    minLength: 2,
    limit: 5
  },

  onAdd: function(map) {
    this._map = map;
    this.mapboxClient = new MapboxClient(this.options.accessToken);
    this._onChange = this._onChange.bind(this);
    this._onKeyDown = this._onKeyDown.bind(this);
    this._onQueryResult = this._onQueryResult.bind(this);
    this._clear = this._clear.bind(this);

    var el = this.container = document.createElement('div');
    el.className = 'mapboxgl-ctrl-geocoder mapboxgl-ctrl';

    var icon = document.createElement('span');
    icon.className = 'geocoder-icon geocoder-icon-search';

    this._inputEl = document.createElement('input');
    this._inputEl.type = 'text';
    this._inputEl.placeholder = this.options.placeholder;

    this._inputEl.addEventListener('keydown', this._onKeyDown);
    this._inputEl.addEventListener('change', this._onChange);

    var actions = document.createElement('div');
    actions.classList.add('geocoder-pin-right');

    this._clearEl = document.createElement('button');
    this._clearEl.className = 'geocoder-icon geocoder-icon-close';
    this._clearEl.setAttribute('aria-label', 'Clear');
    this._clearEl.addEventListener('click', this._clear);

    this._loadingEl = document.createElement('span');
    this._loadingEl.className = 'geocoder-icon geocoder-icon-loading';

    actions.appendChild(this._clearEl);
    actions.appendChild(this._loadingEl);

    el.appendChild(icon);
    el.appendChild(this._inputEl);
    el.appendChild(actions);

    this._typeahead = new Typeahead(this._inputEl, [], {
      filter: false,
      minLength: this.options.minLength,
      limit: this.options.limit
    });
    this._typeahead.getItemValue = function(item) { return item.place_name; };

    return el;
  },

  onRemove: function() {
    this.container.parentNode.removeChild(this.container);
    this._map = null;
    return this;
  },

  _onKeyDown: debounce(function(e) {
    if (!e.target.value) {
      return this._clearEl.style.display = 'none';
    }

    // TAB, ESC, LEFT, RIGHT, ENTER, UP, DOWN
    if (e.metaKey || [9, 27, 37, 39, 13, 38, 40].indexOf(e.keyCode) !== -1) return;

    if (e.target.value.length >= this.options.minLength) {
      this._geocode(e.target.value);
    }
  }, 200),

  _onChange: function() {
    if (this._inputEl.value) this._clearEl.style.display = 'block';
    var selected = this._typeahead.selected;
    if (selected) {
      if (this.options.flyTo) {
        if (!exceptions[selected.id] &&
            (selected.bbox && selected.context && selected.context.length <= 3 ||
            selected.bbox && !selected.context)) {
          var bbox = selected.bbox;
          this._map.fitBounds([[bbox[0], bbox[1]],[bbox[2], bbox[3]]]);
        } else if (exceptions[selected.id]) {
          // Certain geocoder search results return (and therefore zoom to fit)
          // an unexpectedly large bounding box: for example, both Russia and the
          // USA span both sides of -180/180, or France includes the island of
          // Reunion in the Indian Ocean. An incomplete list of these exceptions
          // at ./exceptions.json provides "reasonable" bounding boxes as a
          // short-term solution; this may be amended as necessary.
          this._map.fitBounds(exceptions[selected.id].bbox);
        } else {
          this._map.flyTo({
            center: selected.center,
            zoom: this.options.zoom
          });
        }
      }
      this._eventEmitter.emit('result', { result: selected });
    }
  },

  _geocode: function(searchInput) {
    this._loadingEl.style.display = 'block';
    this._eventEmitter.emit('loading', { query: searchInput });
    var request = this.mapboxClient.geocodeForward(searchInput, this.options);

    request.then(function (response) {
      this._loadingEl.style.display = 'none';
      var res = response.entity;
      if (res.features.length) {
        this._clearEl.style.display = 'block';
      } else {
        this._clearEl.style.display = 'none';
        this._typeahead.selected = null;
      }

      this._eventEmitter.emit('results', res);
      this._typeahead.update(res.features);
    }.bind(this));

    request.catch(function (err) {
      this._loadingEl.style.display = 'none';
      this._eventEmitter.emit('error', { error: err });
    }.bind(this));

    return request;
  },

  _clear: function(ev) {
    if (ev) ev.preventDefault();
    this._inputEl.value = '';
    this._typeahead.selected = null;
    this._typeahead.clear();
    this._onChange();
    this._inputEl.focus();
    this._clearEl.style.display = 'none';
    this._eventEmitter.emit('clear');
  },

  _onQueryResult: function(response) {
    var results = response.entity;
    if (!results.features.length) return;
    var result = results.features[0];
    this._typeahead.selected = result;
    this._inputEl.value = result.place_name;
    this._onChange();
  },

  /**
   * Set & query the input
   * @param {string} searchInput location name or other search input
   * @returns {MapboxGeocoder} this
   */
  query: function(searchInput) {
    this._geocode(searchInput).then(this._onQueryResult);
    return this;
  },

  /**
   * Set input
   * @param {string} searchInput location name or other search input
   * @returns {MapboxGeocoder} this
   */
  setInput: function(searchInput) {
    // Set input value to passed value and clear everything else.
    this._inputEl.value = searchInput;
    this._typeahead.selected = null;
    this._typeahead.clear();
    this._onChange();
    return this;
  },

  /**
   * Set proximity
   * @param {Object} proximity The new options.proximity value. This is a geographical point given as an object with latitude and longitude properties.
   * @returns {MapboxGeocoder} this
   */
  setProximity: function(proximity) {
    this.options.proximity = proximity;
    return this;
  },

  /**
   * Get proximity
   * @returns {Object} The geocoder proximity
   */
  getProximity: function() {
    return this.options.proximity;
  },

  /**
   * Subscribe to events that happen within the plugin.
   * @param {String} type name of event. Available events and the data passed into their respective event objects are:
   *
   * - __clear__ `Emitted when the input is cleared`
   * - __loading__ `{ query } Emitted when the geocoder is looking up a query`
   * - __results__ `{ results } Fired when the geocoder returns a response`
   * - __result__ `{ result } Fired when input is set`
   * - __error__ `{ error } Error as string
   * @param {Function} fn function that's called when the event is emitted.
   * @returns {MapboxGeocoder} this;
   */
  on: function(type, fn) {
    this._eventEmitter.on(type, fn);
    return this;
  },

  /**
   * Remove an event
   * @returns {MapboxGeocoder} this
   * @param {String} type Event name.
   * @param {Function} fn Function that should unsubscribe to the event emitted.
   */
  off: function(type, fn) {
    this._eventEmitter.removeListener(type, fn);
    return this;
  }
};

module.exports = MapboxGeocoder;
<commit_msg>check for shadowRoot retargeting for keypressdown event (#134)<commit_after>'use strict';

var Typeahead = require('suggestions');
var debounce = require('lodash.debounce');
var extend = require('xtend');
var EventEmitter = require('events').EventEmitter;
var exceptions = require('./exceptions');
var MapboxClient = require('mapbox/lib/services/geocoding');

/**
 * A geocoder component using Mapbox Geocoding API
 * @class MapboxGeocoder
 *
 * @param {Object} options
 * @param {String} options.accessToken Required.
 * @param {Number} [options.zoom=16] On geocoded result what zoom level should the map animate to when a `bbox` isn't found in the response. If a `bbox` is found the map will fit to the `bbox`.
 * @param {Boolean} [options.flyTo=true] If false, animating the map to a selected result is disabled.
 * @param {String} [options.placeholder="Search"] Override the default placeholder attribute value.
 * @param {Object} [options.proximity] a proximity argument: this is
 * a geographical point given as an object with latitude and longitude
 * properties. Search results closer to this point will be given
 * higher priority.
 * @param {Array} [options.bbox] a bounding box argument: this is
 * a bounding box given as an array in the format [minX, minY, maxX, maxY].
 * Search results will be limited to the bounding box.
 * @param {string} [options.types] a comma seperated list of types that filter
 * results to match those specified. See https://www.mapbox.com/developers/api/geocoding/#filter-type
 * for available types.
 * @param {string} [options.country] a comma separated list of country codes to
 * limit results to specified country or countries.
 * @param {Number} [options.minLength=2] Minimum number of characters to enter before results are shown.
 * @param {Number} [options.limit=5] Maximum number of results to show.
 * @param {string} [options.language] Specify the language to use for response text and query result weighting. Options are IETF language tags comprised of a mandatory ISO 639-1 language code and optionally one or more IETF subtags for country or script. More than one value can also be specified, separated by commas.
 * @example
 * var geocoder = new MapboxGeocoder({ accessToken: mapboxgl.accessToken });
 * map.addControl(geocoder);
 * @return {MapboxGeocoder} `this`
 */
function MapboxGeocoder(options) {
  this._eventEmitter = new EventEmitter();
  this.options = extend({}, this.options, options);
}

MapboxGeocoder.prototype = {

  options: {
    placeholder: 'Search',
    zoom: 16,
    flyTo: true,
    minLength: 2,
    limit: 5
  },

  onAdd: function(map) {
    this._map = map;
    this.mapboxClient = new MapboxClient(this.options.accessToken);
    this._onChange = this._onChange.bind(this);
    this._onKeyDown = this._onKeyDown.bind(this);
    this._onQueryResult = this._onQueryResult.bind(this);
    this._clear = this._clear.bind(this);

    var el = this.container = document.createElement('div');
    el.className = 'mapboxgl-ctrl-geocoder mapboxgl-ctrl';

    var icon = document.createElement('span');
    icon.className = 'geocoder-icon geocoder-icon-search';

    this._inputEl = document.createElement('input');
    this._inputEl.type = 'text';
    this._inputEl.placeholder = this.options.placeholder;

    this._inputEl.addEventListener('keydown', this._onKeyDown);
    this._inputEl.addEventListener('change', this._onChange);

    var actions = document.createElement('div');
    actions.classList.add('geocoder-pin-right');

    this._clearEl = document.createElement('button');
    this._clearEl.className = 'geocoder-icon geocoder-icon-close';
    this._clearEl.setAttribute('aria-label', 'Clear');
    this._clearEl.addEventListener('click', this._clear);

    this._loadingEl = document.createElement('span');
    this._loadingEl.className = 'geocoder-icon geocoder-icon-loading';

    actions.appendChild(this._clearEl);
    actions.appendChild(this._loadingEl);

    el.appendChild(icon);
    el.appendChild(this._inputEl);
    el.appendChild(actions);

    this._typeahead = new Typeahead(this._inputEl, [], {
      filter: false,
      minLength: this.options.minLength,
      limit: this.options.limit
    });
    this._typeahead.getItemValue = function(item) { return item.place_name; };

    return el;
  },

  onRemove: function() {
    this.container.parentNode.removeChild(this.container);
    this._map = null;
    return this;
  },

  _onKeyDown: debounce(function(e) {
    // if target has shadowRoot, then get the actual active element inside the shadowRoot
    var target = e.target.shadowRoot ? e.target.shadowRoot.activeElement : e.target;
    if (!target.value) {
      return this._clearEl.style.display = 'none';
    }

    // TAB, ESC, LEFT, RIGHT, ENTER, UP, DOWN
    if (e.metaKey || [9, 27, 37, 39, 13, 38, 40].indexOf(e.keyCode) !== -1) return;

    if (target.value.length >= this.options.minLength) {
      this._geocode(target.value);
    }
  }, 200),

  _onChange: function() {
    if (this._inputEl.value) this._clearEl.style.display = 'block';
    var selected = this._typeahead.selected;
    if (selected) {
      if (this.options.flyTo) {
        if (!exceptions[selected.id] &&
            (selected.bbox && selected.context && selected.context.length <= 3 ||
            selected.bbox && !selected.context)) {
          var bbox = selected.bbox;
          this._map.fitBounds([[bbox[0], bbox[1]],[bbox[2], bbox[3]]]);
        } else if (exceptions[selected.id]) {
          // Certain geocoder search results return (and therefore zoom to fit)
          // an unexpectedly large bounding box: for example, both Russia and the
          // USA span both sides of -180/180, or France includes the island of
          // Reunion in the Indian Ocean. An incomplete list of these exceptions
          // at ./exceptions.json provides "reasonable" bounding boxes as a
          // short-term solution; this may be amended as necessary.
          this._map.fitBounds(exceptions[selected.id].bbox);
        } else {
          this._map.flyTo({
            center: selected.center,
            zoom: this.options.zoom
          });
        }
      }
      this._eventEmitter.emit('result', { result: selected });
    }
  },

  _geocode: function(searchInput) {
    this._loadingEl.style.display = 'block';
    this._eventEmitter.emit('loading', { query: searchInput });
    var request = this.mapboxClient.geocodeForward(searchInput, this.options);

    request.then(function (response) {
      this._loadingEl.style.display = 'none';
      var res = response.entity;
      if (res.features.length) {
        this._clearEl.style.display = 'block';
      } else {
        this._clearEl.style.display = 'none';
        this._typeahead.selected = null;
      }

      this._eventEmitter.emit('results', res);
      this._typeahead.update(res.features);
    }.bind(this));

    request.catch(function (err) {
      this._loadingEl.style.display = 'none';
      this._eventEmitter.emit('error', { error: err });
    }.bind(this));

    return request;
  },

  _clear: function(ev) {
    if (ev) ev.preventDefault();
    this._inputEl.value = '';
    this._typeahead.selected = null;
    this._typeahead.clear();
    this._onChange();
    this._inputEl.focus();
    this._clearEl.style.display = 'none';
    this._eventEmitter.emit('clear');
  },

  _onQueryResult: function(response) {
    var results = response.entity;
    if (!results.features.length) return;
    var result = results.features[0];
    this._typeahead.selected = result;
    this._inputEl.value = result.place_name;
    this._onChange();
  },

  /**
   * Set & query the input
   * @param {string} searchInput location name or other search input
   * @returns {MapboxGeocoder} this
   */
  query: function(searchInput) {
    this._geocode(searchInput).then(this._onQueryResult);
    return this;
  },

  /**
   * Set input
   * @param {string} searchInput location name or other search input
   * @returns {MapboxGeocoder} this
   */
  setInput: function(searchInput) {
    // Set input value to passed value and clear everything else.
    this._inputEl.value = searchInput;
    this._typeahead.selected = null;
    this._typeahead.clear();
    this._onChange();
    return this;
  },

  /**
   * Set proximity
   * @param {Object} proximity The new options.proximity value. This is a geographical point given as an object with latitude and longitude properties.
   * @returns {MapboxGeocoder} this
   */
  setProximity: function(proximity) {
    this.options.proximity = proximity;
    return this;
  },

  /**
   * Get proximity
   * @returns {Object} The geocoder proximity
   */
  getProximity: function() {
    return this.options.proximity;
  },

  /**
   * Subscribe to events that happen within the plugin.
   * @param {String} type name of event. Available events and the data passed into their respective event objects are:
   *
   * - __clear__ `Emitted when the input is cleared`
   * - __loading__ `{ query } Emitted when the geocoder is looking up a query`
   * - __results__ `{ results } Fired when the geocoder returns a response`
   * - __result__ `{ result } Fired when input is set`
   * - __error__ `{ error } Error as string
   * @param {Function} fn function that's called when the event is emitted.
   * @returns {MapboxGeocoder} this;
   */
  on: function(type, fn) {
    this._eventEmitter.on(type, fn);
    return this;
  },

  /**
   * Remove an event
   * @returns {MapboxGeocoder} this
   * @param {String} type Event name.
   * @param {Function} fn Function that should unsubscribe to the event emitted.
   */
  off: function(type, fn) {
    this._eventEmitter.removeListener(type, fn);
    return this;
  }
};

module.exports = MapboxGeocoder;
<|endoftext|>


<commit_before>/*jslint indent: 2*/
/*global require: true, module: true*/

(function () {

  'use strict';

  var vary = require('vary'),
    defaults = {
      origin: '*',
      methods: 'GET,HEAD,PUT,PATCH,POST,DELETE'
    };

  function configureOrigin(options, req) {
    if (!options.origin) {
      return {
        key: 'Access-Control-Allow-Origin',
        value: '*'
      };
    } else {
      return [
        {
          key: 'Access-Control-Allow-Origin',
          value: options.origin === true ? req.headers.origin : options.origin
        },
        {
          key: 'Vary',
          value: 'Origin'
        }
      ];
    }
  }

  function configureMethods(options) {
    var methods = options.methods || defaults.methods;
    if (methods.join) {
      methods = options.methods.join(','); // .methods is an array, so turn it into a string
    }
    return {
      key: 'Access-Control-Allow-Methods',
      value: methods
    };
  }

  function configureCredentials(options) {
    if (options.credentials === true) {
      return {
        key: 'Access-Control-Allow-Credentials',
        value: 'true'
      };
    }
    return null;
  }

  function configureAllowedHeaders(options, req) {
    var headers = options.allowedHeaders || options.headers;
    if (!headers) {
      headers = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers
    } else if (headers.join) {
      headers = headers.join(','); // .headers is an array, so turn it into a string
    }
    if (headers && headers.length) {
      return {
        key: 'Access-Control-Allow-Headers',
        value: headers
      };
    }
    return null;
  }

  function configureExposedHeaders(options, req) {
    var headers = options.exposedHeaders;
    if (!headers) {
      return null;
    } else if (headers.join) {
      headers = headers.join(','); // .headers is an array, so turn it into a string
    }
    if (headers && headers.length) {
      return {
        key: 'Access-Control-Expose-Headers',
        value: headers
      };
    }
    return null;
  }

  function configureMaxAge(options) {
    var maxAge = options.maxAge && options.maxAge.toString();
    if (maxAge && maxAge.length) {
      return {
        key: 'Access-Control-Max-Age',
        value: maxAge
      };
    }
    return null;
  }

  function applyHeaders(headers, res) {
    for (var i = 0, n = headers.length; i < n; i++) {
      var header = headers[i];
      if (header) {
        if (Array.isArray(header)) {
          applyHeaders(header, res);
        } else if (header.key === 'Vary' && header.value) {
          vary(res, header.value);
        } else if (header.value) {
          res.setHeader(header.key, header.value);
        }
      }
    }
  }

  function cors(options, req, res, next) {
    var headers = [],
      method = req.method && req.method.toUpperCase && req.method.toUpperCase();

    if (method === 'OPTIONS') {
      // preflight
      headers.push(configureOrigin(options, req));
      headers.push(configureCredentials(options, req));
      headers.push(configureMethods(options, req));
      headers.push(configureAllowedHeaders(options, req));
      headers.push(configureMaxAge(options, req));
      applyHeaders(headers, res);
      res.statusCode = 204;
      res.end();
    } else {
      // actual response
      headers.push(configureOrigin(options, req));
      headers.push(configureCredentials(options, req));
      headers.push(configureExposedHeaders(options, req));
      applyHeaders(headers, res);
      next();
    }
  }

  function middlewareWrapper(o) {
    // if no options were passed in, use the defaults
    if (!o) {
      o = {};
    }
    if (o.origin === undefined) {
      o.origin = defaults.origin;
    }
    if (o.methods === undefined) {
      o.methods = defaults.methods;
    }

    // if options are static (either via defaults or custom options passed in), wrap in a function
    var optionsCallback = null;
    if (typeof o === 'function') {
      optionsCallback = o;
    } else {
      /*jslint unparam: true*/ // `req` is part of the signature, but isn't used for this stub
      optionsCallback = function (req, cb) {
        cb(null, o);
      };
      /*jslint unparam: false*/
    }

    return function (req, res, next) {
      optionsCallback(req, function (err, options) {
        if (err) {
          next(err);
        } else {
          var originCallback = null;
          if (options.origin && typeof options.origin === 'function') {
            originCallback = options.origin;
          } else if (options.origin) {
            /*jslint unparam: true*/ // `origin` is part of the signature, but isn't used for this stub
            originCallback = function (origin, cb) {
              cb(null, options.origin);
            };
            /*jslint unparam: false*/
          }

          if (originCallback) {
            originCallback(req.headers.origin, function (err, origin) {
              if (err || !origin) {
                next(err);
              } else {
                var corsOptions = Object.create(options);
                corsOptions.origin = origin;
                cors(corsOptions, req, res, next);
              }
            });
          } else {
            next();
          }
        }
      });
    };
  }

  // can pass either an options hash, an options delegate, or nothing
  module.exports = middlewareWrapper;

}());
<commit_msg>Fix "Vary: origin" header added for "*"<commit_after>/*jslint indent: 2*/
/*global require: true, module: true*/

(function () {

  'use strict';

  var vary = require('vary'),
    defaults = {
      origin: '*',
      methods: 'GET,HEAD,PUT,PATCH,POST,DELETE'
    };

  function configureOrigin(options, req) {
    if (!options.origin || options.origin === '*') {
      return {
        key: 'Access-Control-Allow-Origin',
        value: '*'
      };
    } else {
      return [
        {
          key: 'Access-Control-Allow-Origin',
          value: options.origin === true ? req.headers.origin : options.origin
        },
        {
          key: 'Vary',
          value: 'Origin'
        }
      ];
    }
  }

  function configureMethods(options) {
    var methods = options.methods || defaults.methods;
    if (methods.join) {
      methods = options.methods.join(','); // .methods is an array, so turn it into a string
    }
    return {
      key: 'Access-Control-Allow-Methods',
      value: methods
    };
  }

  function configureCredentials(options) {
    if (options.credentials === true) {
      return {
        key: 'Access-Control-Allow-Credentials',
        value: 'true'
      };
    }
    return null;
  }

  function configureAllowedHeaders(options, req) {
    var headers = options.allowedHeaders || options.headers;
    if (!headers) {
      headers = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers
    } else if (headers.join) {
      headers = headers.join(','); // .headers is an array, so turn it into a string
    }
    if (headers && headers.length) {
      return {
        key: 'Access-Control-Allow-Headers',
        value: headers
      };
    }
    return null;
  }

  function configureExposedHeaders(options, req) {
    var headers = options.exposedHeaders;
    if (!headers) {
      return null;
    } else if (headers.join) {
      headers = headers.join(','); // .headers is an array, so turn it into a string
    }
    if (headers && headers.length) {
      return {
        key: 'Access-Control-Expose-Headers',
        value: headers
      };
    }
    return null;
  }

  function configureMaxAge(options) {
    var maxAge = options.maxAge && options.maxAge.toString();
    if (maxAge && maxAge.length) {
      return {
        key: 'Access-Control-Max-Age',
        value: maxAge
      };
    }
    return null;
  }

  function applyHeaders(headers, res) {
    for (var i = 0, n = headers.length; i < n; i++) {
      var header = headers[i];
      if (header) {
        if (Array.isArray(header)) {
          applyHeaders(header, res);
        } else if (header.key === 'Vary' && header.value) {
          vary(res, header.value);
        } else if (header.value) {
          res.setHeader(header.key, header.value);
        }
      }
    }
  }

  function cors(options, req, res, next) {
    var headers = [],
      method = req.method && req.method.toUpperCase && req.method.toUpperCase();

    if (method === 'OPTIONS') {
      // preflight
      headers.push(configureOrigin(options, req));
      headers.push(configureCredentials(options, req));
      headers.push(configureMethods(options, req));
      headers.push(configureAllowedHeaders(options, req));
      headers.push(configureMaxAge(options, req));
      applyHeaders(headers, res);
      res.statusCode = 204;
      res.end();
    } else {
      // actual response
      headers.push(configureOrigin(options, req));
      headers.push(configureCredentials(options, req));
      headers.push(configureExposedHeaders(options, req));
      applyHeaders(headers, res);
      next();
    }
  }

  function middlewareWrapper(o) {
    // if no options were passed in, use the defaults
    if (!o) {
      o = {};
    }
    if (o.origin === undefined) {
      o.origin = defaults.origin;
    }
    if (o.methods === undefined) {
      o.methods = defaults.methods;
    }

    // if options are static (either via defaults or custom options passed in), wrap in a function
    var optionsCallback = null;
    if (typeof o === 'function') {
      optionsCallback = o;
    } else {
      /*jslint unparam: true*/ // `req` is part of the signature, but isn't used for this stub
      optionsCallback = function (req, cb) {
        cb(null, o);
      };
      /*jslint unparam: false*/
    }

    return function (req, res, next) {
      optionsCallback(req, function (err, options) {
        if (err) {
          next(err);
        } else {
          var originCallback = null;
          if (options.origin && typeof options.origin === 'function') {
            originCallback = options.origin;
          } else if (options.origin) {
            /*jslint unparam: true*/ // `origin` is part of the signature, but isn't used for this stub
            originCallback = function (origin, cb) {
              cb(null, options.origin);
            };
            /*jslint unparam: false*/
          }

          if (originCallback) {
            originCallback(req.headers.origin, function (err, origin) {
              if (err || !origin) {
                next(err);
              } else {
                var corsOptions = Object.create(options);
                corsOptions.origin = origin;
                cors(corsOptions, req, res, next);
              }
            });
          } else {
            next();
          }
        }
      });
    };
  }

  // can pass either an options hash, an options delegate, or nothing
  module.exports = middlewareWrapper;

}());
<|endoftext|>


<commit_before>// Dependencies
var ChildProcess = require("child_process")
  , Exec = ChildProcess.exec
  , Ul = require("ul")
  , OArgv = require("oargv")
  ;

/**
 * Diable
 * Daemonizes processes, the current process being the default target (unless
 * a different path is provided).
 *
 * Usage:
 *
 * ```js
 * // Daemonizes the current process
 * Diable();
 *
 * // Daemonizes the current process by adding the '--foo bar' cli arguments.
 * Diable({
 *   args: {
 *      "foo": "bar"
 *   }
 * });
 *
 * // Daemonizes a provided path
 * Diable("path/to/some/script.js", {
 *   // some options
 * });
 *
 * // Daemonizes a provided path
 * Diable("path/to/some/script.js", {
 *   // some options
 * });
 *
 * // Daemonizes a different process handling the stdio streams
 * Diable("", "some-command", {
 *    stdio: [stdin, stdout, stderr]
 * });
 * ```
 *
 * @name Diable
 * @function
 * @param {String} path The path to the script to daemonize (default: the current process path).
 * @param {String} exec The executable to run (default: `process.execPath`).
 * @param {Object} options An object which will be passed to the `exec` function. It is extended with:
 *  - `force` (Boolean): A flag to force daemonizing even the process is a daemon already (default: `false`).
 *  - `exit` (Boolean): A flag to control the process exit (default: `true`).
 *  - `args` (String|Object): An arguments string or an object which will be passed to [OArgv](https://github.com/ionicabizau/node-oargv) and stringified.
 * @return {Null|Proc} `null` if the process was not daemonized, the daemon process otherwise. A daemon cannot be daemonized by itself unless `options.force` is true.
 */
function Diable(path, exec, options) {

    // Diable(options);
    if (typeof path === "object") {
        options = path;
        path = null;
    // Diable(path, options);
    } else if (typeof exec === "object") {
        options = exec;
        exec = null;
    }

    // Get the script path
    path = typeof path === "string" ? path : process.argv[1];

    // Get the exec path
    exec = exec || process.execPath;

    // Merge the options
    options = Ul.merge(options, {
        args: ""
      , detached: true
      , cwd: process.cwd()
      , force: false
      , exit: true
      , env: {
            __is_daemon: true
        }
    });

    // Check if the process is already a daemon
    if (!options.force && path === process.argv[1] && Diable.isDaemon()) {
        return null;
    }

    // Stringify the arguments
    if (typeof options.args === "object") {
        options.args = OArgv(options.args);
    }

    // Build the command to run
    var command = [exec, path, options.args].join(" ").trim();
    delete options.args;

    var opts = {
        exit: options.exit
      , force: options.force
    };
    delete options.exit;
    delete options.force;

    var proc = Diable.daemonize(command, options)
    if (opts.exit || (path === process.argv[1] && opts.exit)) {
        process.exit();
    }

    return proc;
}

/**
 * daemonize
 * Low level for daemonizing the things. It's used internally.
 * Also, it can be useful in specific cases.
 *
 * @name daemonize
 * @function
 * @param {String} command The command to run and daemonize.
 * @param {Object} options The object passed to the `exec` function.
 * @return {Process} The daemon process.
 */
Diable.daemonize = function (command, options) {
    var proc = Exec(command, options);
    proc.unref();
    return proc;
};

/**
 * isDaemon
 * Checks if the current process is a daemon started by `diable`.
 *
 * @name isDaemon
 * @function
 * @return {Boolean} `true` if the process is a daemon, `false` otherwise.
 */
Diable.isDaemon = function () {
    return process.env.__is_daemon ? true : false;
};

module.exports = Diable;
<commit_msg>Use Spawn instead of Exec<commit_after>// Dependencies
var ChildProcess = require("child_process")
  , Spawn = ChildProcess.spawn
  , Ul = require("ul")
  ;

/**
 * Diable
 * Daemonizes processes, the current process being the default target (unless
 * a different path is provided).
 *
 * Usage:
 *
 * ```js
 * // Daemonizes the current process
 * Diable();
 *
 * // Daemonizes the current process by adding the '--foo bar' cli arguments.
 * Diable({
 *   args: {
 *      "foo": "bar"
 *   }
 * });
 *
 * // Daemonizes a provided path
 * Diable("path/to/some/script.js", {
 *   // some options
 * });
 *
 * // Daemonizes a provided path
 * Diable("path/to/some/script.js", {
 *   // some options
 * });
 *
 * // Daemonizes a different process handling the stdio streams
 * Diable("", "some-command", {
 *    stdio: [stdin, stdout, stderr]
 * });
 * ```
 *
 * @name Diable
 * @function
 * @param {String} path The path to the script to daemonize (default: the current process path).
 * @param {String} exec The executable to run (default: `process.execPath`).
 * @param {Object} options An object which will be passed to the `exec` function. It is extended with:
 *  - `force` (Boolean): A flag to force daemonizing even the process is a daemon already (default: `false`).
 *  - `exit` (Boolean): A flag to control the process exit (default: `true`).
 *  - `args` (Array): An array with the additional cli arguments.
 * @return {Null|Proc} `null` if the process was not daemonized, the daemon process otherwise. A daemon cannot be daemonized by itself unless `options.force` is true.
 */
function Diable(path, exec, options) {

    // Diable(options);
    if (typeof path === "object") {
        options = path;
        path = null;
    // Diable(path, options);
    } else if (typeof exec === "object") {
        options = exec;
        exec = null;
    }

    // Get the script path
    path = typeof path === "string" ? path : process.argv[1];

    // Get the exec path
    exec = exec || process.execPath;

    // Merge the options
    options = Ul.merge(options, {
        args: []
      , detached: true
      , cwd: process.cwd()
      , force: false
      , exit: true
      , env: Ul.merge({
            __is_daemon: true
        }, process.env)
    });

    // Check if the process is already a daemon
    if (!options.force && path === process.argv[1] && Diable.isDaemon()) {
        return null;
    }

    var opts = {
        exit: options.exit
      , force: options.force
      , args: options.args
    };

    delete options.exit;
    delete options.force;
    delete options.args;

    var proc = Diable.daemonize(exec, [path].concat(opts.args), options);
    if (opts.exit || (path === process.argv[1] && opts.exit)) {
        process.exit();
    }

    return proc;
}

/**
 * isDaemon
 * Checks if the current process is a daemon started by `diable`.
 *
 * @name isDaemon
 * @function
 * @return {Boolean} `true` if the process is a daemon, `false` otherwise.
 */
Diable.isDaemon = function () {
    return process.env.__is_daemon ? true : false;
};

/**
 * daemonize
 * Low level for daemonizing the things. It's used internally.
 * Also, it can be useful in specific cases.
 *
 * @name daemonize
 * @function
 * @param {String} app The executable application.
 * @param {Array} args The spawn arguments (default: `[]`).
 * @param {Object} options The object passed to the `spawn` function (default: `{}`).
 * @return {Process} The daemon process.
 */
Diable.daemonize = function (app, args, options) {
    args = args || [];
    options = options || {};
    var proc = Spawn(app, args, options);
    proc.unref();
    return proc;
};

module.exports = Diable;
<|endoftext|>


<commit_before>// Dependencies
var Http = require("http")
  , Ul = require("ul")
  , Url = require("url")
  , QueryString = require("querystring")
  ;

var JsonRequest = module.exports = function (options, callback) {

    // Handle options as string
    if (typeof options === "string") {
        options = {
            url: options
        };
    }

    var parsed = Url.parse(options.url)
      , defaults = Ul.clone(parsed)
      , request = null
      , _done = false
      , body = ""
      ;

    defaults.method = "GET";
    defaults.headers = { "Content-Type": "application/json" };

    // Merge options
    options = Ul.merge(defaults, options);

    // Unique callback
    function opt_callback(err, data) {
        if (_done) { return; }
        _done = true;
        callback(err, data);
    }

    // Handle post data
    if (options.data) {
        options.data = QueryString.stringify(options.data);
        options.headers["Content-Length"] = options.data.length;
    }

    // Create the request
    request = Http.request(options, function(res) {
        res.setEncoding("utf8");
        body = ""
        res.on("data", function (data) {
            body += data.toString();
        }).on("error", function (e) {
            opt_callback(e, null);
        }).on("end", function () {
            try {
                body = JSON.parse(body);
            } catch (e) {}
            opt_callback(null, body);
        });
    }).on("error", function (e) {
        opt_callback(e, null);
    });

    // Handle post data
    if (options.data) {
        request.write(options.data);
    }

    request.end();
};
<commit_msg>JSDoc comment<commit_after>// Dependencies
var Http = require("http")
  , Ul = require("ul")
  , Url = require("url")
  , QueryString = require("querystring")
  ;

/**
 * JsonRequest
 * Creates an HTTP request using the options passed in the first parameter.
 * Then the callback function is called (with `error` and `data` parameters).
 *
 * @name JsonRequest
 * @function
 * @param {String|Object} options A string being the request url or an object containing the following fields:
 * @param {Function} callback The callback function.
 * @return {Object} The request object.
 */
var JsonRequest = module.exports = function (options, callback) {

    // Handle options as string
    if (typeof options === "string") {
        options = {
            url: options
        };
    }

    var parsed = Url.parse(options.url)
      , defaults = Ul.clone(parsed)
      , request = null
      , _done = false
      , body = ""
      ;

    defaults.method = "GET";
    defaults.headers = { "Content-Type": "application/json" };

    // Merge options
    options = Ul.merge(defaults, options);

    // Unique callback
    function opt_callback(err, data) {
        if (_done) { return; }
        _done = true;
        callback(err, data);
    }

    // Handle post data
    if (options.data) {
        options.data = QueryString.stringify(options.data);
        options.headers["Content-Length"] = options.data.length;
    }

    // Create the request
    request = Http.request(options, function(res) {
        res.setEncoding("utf8");
        body = ""
        res.on("data", function (data) {
            body += data.toString();
        }).on("error", function (e) {
            opt_callback(e, null);
        }).on("end", function () {
            try {
                body = JSON.parse(body);
            } catch (e) {}
            opt_callback(null, body);
        });
    }).on("error", function (e) {
        opt_callback(e, null);
    });

    // Handle post data
    if (options.data) {
        request.write(options.data);
    }

    request.end();
};
<|endoftext|>


<commit_before>require("es6-shim");

var IS_TEST_ENV = global.IS_TEST_ENV || false;
var net = require("net");
var Emitter = require("events").EventEmitter;
var priv = new Map();

function EtherPort(opts) {
  Emitter.call(this);

  if (typeof opts === "undefined") {
    throw new Error("Expected port number or port object");
  }
  if (typeof opts === "number") {
    opts = {
      port: opts
    };
  }

  // Alias used in state.flushTo
  var etherport = this;

  this.path = "Listening on port: " + opts.port;
  this.name = "EtherPort";

  var state = {
    queue: [],
    socket: null,
    flushTo: function(socket) {
      if (this.socket === null) {
        this.socket = socket;
        etherport.emit("open");
      }
      if (this.queue.length) {
        this.queue.forEach(function(buffer) {
          this.socket.write(buffer);
        }, this);

        this.queue.length = 0;
      }
    }
  };

  var tcp = net.createServer(function(socket) {
    state.flushTo(socket);
  });

  tcp.on("connection", function(socket) {
    state.flushTo(socket);

    socket.on("data", function(data) {
      this.emit("data", data);
    }.bind(this));
  }.bind(this));

  tcp.listen(opts.port);

  priv.set(this, state);
}

EtherPort.prototype = Object.create(Emitter.prototype, {
  constructor: {
    value: EtherPort
  }
});

EtherPort.prototype.write = function(buffer) {
  var state = priv.get(this);

  if (state.socket === null) {
    state.queue.push(buffer);
  } else {
    state.socket.write(buffer);
  }
};

if (IS_TEST_ENV) {
  EtherPort.__mock = function(mockNet) {
    if (!EtherPort.__mock.net) {
      EtherPort.__mock.net = net;
      net = mockNet;
    }
  };

  EtherPort.__leak = function() {
    return priv;
  };

  EtherPort.__reset = function() {
    net = EtherPort.__mock.net;
    EtherPort.__mock.net = null;
  };
}

module.exports = EtherPort;

<commit_msg>Only conditionally load es6-shim<commit_after>/**
 * Global Environment Dependencies
 */
/* jshint -W079 */
if (!Object.assign || !Map) {
  require("es6-shim");
}

var IS_TEST_ENV = global.IS_TEST_ENV || false;
var net = require("net");
var Emitter = require("events").EventEmitter;
var priv = new Map();

function EtherPort(opts) {
  Emitter.call(this);

  if (typeof opts === "undefined") {
    throw new Error("Expected port number or port object");
  }
  if (typeof opts === "number") {
    opts = {
      port: opts
    };
  }

  // Alias used in state.flushTo
  var etherport = this;

  this.path = "Listening on port: " + opts.port;
  this.name = "EtherPort";

  var state = {
    queue: [],
    socket: null,
    flushTo: function(socket) {
      if (this.socket === null) {
        this.socket = socket;
        etherport.emit("open");
      }
      if (this.queue.length) {
        this.queue.forEach(function(buffer) {
          this.socket.write(buffer);
        }, this);

        this.queue.length = 0;
      }
    }
  };

  var tcp = net.createServer(function(socket) {
    state.flushTo(socket);
  });

  tcp.on("connection", function(socket) {
    state.flushTo(socket);

    socket.on("data", function(data) {
      this.emit("data", data);
    }.bind(this));
  }.bind(this));

  tcp.listen(opts.port);

  priv.set(this, state);
}

EtherPort.prototype = Object.create(Emitter.prototype, {
  constructor: {
    value: EtherPort
  }
});

EtherPort.prototype.write = function(buffer) {
  var state = priv.get(this);

  if (state.socket === null) {
    state.queue.push(buffer);
  } else {
    state.socket.write(buffer);
  }
};

if (IS_TEST_ENV) {
  EtherPort.__mock = function(mockNet) {
    if (!EtherPort.__mock.net) {
      EtherPort.__mock.net = net;
      net = mockNet;
    }
  };

  EtherPort.__leak = function() {
    return priv;
  };

  EtherPort.__reset = function() {
    net = EtherPort.__mock.net;
    EtherPort.__mock.net = null;
  };
}

module.exports = EtherPort;

<|endoftext|>


<commit_before>var $ = require('jquery');

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var Enemy = require("./enemies.js");
var Bluecifer = require('./bluecifer');

var bluecifer = new Bluecifer (150, 150, 50, 41);

$('#game-over').css('visibility', 'visible');

var themeSong = document.getElementById("theme-song");

var enemy = new Enemy();
var enemy2 = new Enemy();
var enemy3 = new Enemy();

function drawAirport () {
  var image = new Image();
  image.src = "IMGS/dia-photo.jpg";
  var airport = {};
  airport.x = 150;
  airport.y = 340;
  airport.width = 30;
  airport.height = 30;
  ctx.drawImage(image, airport.x, airport.y, airport.width, airport.height);
  airportCollision(airport, bluecifer);
  return this;
}

function newEnemy () {
  enemy.draw(ctx);
  collision(enemy, bluecifer);
  enemy.moveLeftRandom();
}

function newEnemy2 () {
  enemy2.draw(ctx);
  collision(enemy2, bluecifer);
  setTimeout(function() {
    enemy2.moveLeftRandom();
    return enemy2;
  }, 3000);
}

function newEnemy3 () {
  enemy3.draw(ctx);
  collision(enemy3, bluecifer);
  setTimeout(function() {
    enemy3.moveLeftRandom();
    return enemy3;
  }, 6000);
}

function collision(a, b) {
  if (((a.y + a.height) < (b.y)) || (a.y > (b.y + b.height)) || ((a.x + a.width) < b.x) || (a.x > (b.x + b.width))) {
  //if there is no collision
  }
  else {
    themeSong.pause();
    $('#game-over').css('visibility', 'visible');
    resetGame();
  }
} //end of collision function

function airportCollision (a, b) {
  if (((a.y + a.height) < (b.y)) || (a.y > (b.y + b.height)) || ((a.x + a.width) < b.x) || (a.x > (b.x + b.width))) {
  //if there is no collision
  }
  else {
    themeSong.pause();
    alert("You win!");
    resetGame();
  }
} //end of airportCollision function

function repeat () {
  setTimeout(function() {
    requestAnimationFrame(repeat);
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    bluecifer.draw(ctx);
    bluecifer.gravity();
    newEnemy();
    newEnemy2();
    newEnemy3();
    detectFloorCollision();
  }, 1000 / 50);
    keepScore();
} //end of big repeat function

$(document).on("click", function () {
  themeSong.play();
  $('#game-over').css('visibility', 'hidden');
  repeat();
});

var scoreCounter = 0;

function keepScore() {
    var currentScore = scoreCounter++;
    if (currentScore <= 100){
   $('#game-score').text("000" + currentScore);
 }else if (currentScore <= 1000){
  $('#game-score').text("00" + currentScore);
}else if (currentScore <= 10000){
  $('#game-score').text("0" + currentScore);
  drawAirport();
}else{
  $('#game-score').text(currentScore);
  }
}

function detectFloorCollision () {
  if (bluecifer.y > 350) {
    themeSong.pause();
    resetGame();
    bluecifer.y = 300;
  }
}

$(document).on("keydown", function (key) {
  if (key.which === 32) {
    if ($('#game-over').css('visibility', 'hidden')) {
      bluecifer.moveUp();
      detectCeilingCollision();
    }
    else {
      resetGame();
    }
  } //end of if statement for space bar
  else if (key.which === 13) {
    themeSong.pause();
  } // end of if statement for enter key
  else if (key.which === 85) {
    var code = prompt("Enter cheat code");
    cheat(code);
  }
}); //end of entire function

function detectCeilingCollision () {
  if (bluecifer.y < 0) {
    bluecifer.y = bluecifer.y + 20;
  }
}

function cheat (code) {
  console.log(code);
}

function resetGame () {
  alert("Game over! Your score was " + scoreCounter);
  location.reload();
  $('#game-over').css('visibility', 'hidden');
  repeat();
}
<commit_msg>added conditional to cheat code function<commit_after>var $ = require('jquery');

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var Enemy = require("./enemies.js");
var Bluecifer = require('./bluecifer');

var bluecifer = new Bluecifer (150, 150, 50, 41);

$('#game-over').css('visibility', 'visible');

var themeSong = document.getElementById("theme-song");

var enemy = new Enemy();
var enemy2 = new Enemy();
var enemy3 = new Enemy();

function drawAirport () {
  var image = new Image();
  image.src = "IMGS/dia-photo.jpg";
  var airport = {};
  airport.x = 150;
  airport.y = 340;
  airport.width = 30;
  airport.height = 30;
  ctx.drawImage(image, airport.x, airport.y, airport.width, airport.height);
  airportCollision(airport, bluecifer);
  return this;
}

function newEnemy () {
  enemy.draw(ctx);
  collision(enemy, bluecifer);
  enemy.moveLeftRandom();
}

function newEnemy2 () {
  enemy2.draw(ctx);
  collision(enemy2, bluecifer);
  setTimeout(function() {
    enemy2.moveLeftRandom();
    return enemy2;
  }, 3000);
}

function newEnemy3 () {
  enemy3.draw(ctx);
  collision(enemy3, bluecifer);
  setTimeout(function() {
    enemy3.moveLeftRandom();
    return enemy3;
  }, 6000);
}

function collision(a, b) {
  if (((a.y + a.height) < (b.y)) || (a.y > (b.y + b.height)) || ((a.x + a.width) < b.x) || (a.x > (b.x + b.width))) {
  //if there is no collision
  }
  else {
    themeSong.pause();
    $('#game-over').css('visibility', 'visible');
    resetGame();
  }
} //end of collision function

function airportCollision (a, b) {
  if (((a.y + a.height) < (b.y)) || (a.y > (b.y + b.height)) || ((a.x + a.width) < b.x) || (a.x > (b.x + b.width))) {
  //if there is no collision
  }
  else {
    themeSong.pause();
    alert("You win!");
    resetGame();
  }
} //end of airportCollision function

function repeat () {
  setTimeout(function() {
    requestAnimationFrame(repeat);
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    bluecifer.draw(ctx);
    bluecifer.gravity();
    newEnemy();
    newEnemy2();
    newEnemy3();
    detectFloorCollision();
  }, 1000 / 50);
    keepScore();
} //end of big repeat function

$(document).on("click", function () {
  themeSong.play();
  $('#game-over').css('visibility', 'hidden');
  repeat();
});

var scoreCounter = 0;

function keepScore() {
    var currentScore = scoreCounter++;
    if (currentScore <= 100){
   $('#game-score').text("000" + currentScore);
 }else if (currentScore <= 1000){
  $('#game-score').text("00" + currentScore);
}else if (currentScore <= 10000){
  $('#game-score').text("0" + currentScore);
  drawAirport();
}else{
  $('#game-score').text(currentScore);
  }
}

function detectFloorCollision () {
  if (bluecifer.y > 350) {
    themeSong.pause();
    resetGame();
    bluecifer.y = 300;
  }
}

$(document).on("keydown", function (key) {
  if (key.which === 32) {
    if ($('#game-over').css('visibility', 'hidden')) {
      bluecifer.moveUp();
      detectCeilingCollision();
    }
    else {
      resetGame();
    }
  } //end of if statement for space bar
  else if (key.which === 13) {
    themeSong.pause();
  } // end of if statement for enter key
  else if (key.which === 85) {
    var code = prompt("Enter cheat code");
    cheat(code);
  }
}); //end of entire function

function detectCeilingCollision () {
  if (bluecifer.y < 0) {
    bluecifer.y = bluecifer.y + 20;
  }
}

function cheat (code) {
  if (code === "dogs") {
    alert("hi");
  }
}

function resetGame () {
  alert("Game over! Your score was " + scoreCounter);
  location.reload();
  $('#game-over').css('visibility', 'hidden');
  repeat();
}
<|endoftext|>


<commit_before>'use strict'

const passport = require('passport')
const Passport = require('passport').Passport
const framework = require('./framework/koa')()

passport.framework(framework)

class KoaPassport extends Passport {
  constructor() {
    super(this)
    this.framework(framework)
  }
}

// Export default singleton.
module.exports = passport

// Expose constructor
module.exports.KoaPassport = KoaPassport
<commit_msg>Fix invalid super call<commit_after>'use strict'

const passport = require('passport')
const Passport = require('passport').Passport
const framework = require('./framework/koa')()

passport.framework(framework)

class KoaPassport extends Passport {
  constructor() {
    super()
    this.framework(framework)
  }
}

// Export default singleton.
module.exports = passport

// Expose constructor
module.exports.KoaPassport = KoaPassport
<|endoftext|>


<commit_before>var util = require('util'),
    fs   = require('fs'),
    path = require('path'),
    mocha = require('mocha'),
    _ = require('lodash'),
    handlebars = require('handlebars'),
    moment = require('moment'),
    less = require('less');

var Base = mocha.reporters.Base,
    utils = mocha.utils,
    cursor = Base.cursor,
    color = Base.color;

var reportsDir = path.join(process.cwd(), 'reports'),
    reportJsonFile = path.join(reportsDir, 'reports.json'),
    reportHtmlFile = path.join(reportsDir, 'mochawesome.html');
    reportCssFile = path.join(reportsDir, 'mochawesome.css');

module.exports = Mochawesome;

createStylesheet();

// Load templates
// TODO: load all files in templates directory instead of specific ones
var mochawesomeReport = fs.readFileSync(path.join(__dirname, '..', 'templates', 'mochawesome.mu'), {
  encoding: 'utf8'
});

var _summary = fs.readFileSync(path.join(__dirname, '..', 'templates', '_summary.mu'), {
  encoding: 'utf8'
});

var _suite = fs.readFileSync(path.join(__dirname, '..', 'templates', '_suite.mu'), {
  encoding: 'utf8'
});

var _test = fs.readFileSync(path.join(__dirname, '..', 'templates', '_test.mu'), {
  encoding: 'utf8'
});

// TODO: if filename begins with underscore, register it as a partial
handlebars.registerPartial('_summary', _summary);
handlebars.registerPartial('_suite', _suite);
handlebars.registerPartial('_test', _test);

// Compile template
var mochawesomeReportTmp = handlebars.compile(mochawesomeReport);

/**
 * Initialize a new reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function Mochawesome (runner) {
  var self = this;
  Base.call(this, runner);

  var allSuites = {},
      allTests = [],
      allFailures = [],
      allPasses = [];

  runner.on('suite', function (suite) {
    // ignore the root suite
    if (!suite.root) {
      // top level suite
      if (suite.parent.root) {
        allSuites[suite.title] = {};
      }

      // nested suite 1 level deep only
      if (!suite.parent.root && suite.parent.parent.root) {
        parentSuite = allSuites[suite.parent.title];
        if (!parentSuite.childSuites) {
          parentSuite.childSuites = {};
        }
        parentSuite.childSuites[suite.title] = {};
      }
    }
  });

  runner.on('suite end', function (suite) {
    // ignore the root suite
    if (!suite.root) {

      var allTests = suite.tests.map(cleanTest);
      var passingTests = allTests.filter(filterTest.bind(self, true));
      var failingTests = allTests.filter(filterTest.bind(self, false));

      // TODO: account for child suites in suite totals
      var suiteObj = {
        title: suite.title,
        fullTitle: suite.fullTitle(),
        file: suite.file.replace(process.cwd(), ''),
        fullFile: suite.file,
        tests: allTests,
        passes: passingTests,
        failures: failingTests,
        totalTests: suite.tests.length,
        totalPasses: passingTests.length,
        totalFailures: failingTests.length
      };

      // top level suite
      if (suite.parent.root) {
        allSuites[suite.title] = _.merge(allSuites[suite.title], suiteObj);
      }

      // nested suite 1 level deep only
      if (!suite.parent.root && suite.parent.parent.root) {
        parentSuite = allSuites[suite.parent.title];
        parentSuite.childSuites[suite.title] = suiteObj;
      }
    }
  });

  runner.on('test end', function (test) {
    allTests.push(test);
  });

  runner.on('pass', function (test) {
    allPasses.push(test);
  });

  runner.on('fail', function (test){
    allFailures.push(test);
  });

  runner.on('end', function () {

    // unless we render client-side, this has to be updated client-side
    // self.stats.endDateStr = moment(self.stats.end).fromNow();

    var obj = {
      stats: self.stats,
      suites: allSuites,
      tests: allTests.map(cleanTest),
      passes: allPasses.map(cleanTest),
      failures: allFailures.map(cleanTest)
    };

    saveToFile('json', obj);
    saveToFile('html', obj);
  });
}

/**
 * Return a plain-object representation of `test`
 * free of cyclic properties etc.
 *
 * @param {Object} test
 * @return {Object}
 * @api private
 */

function cleanTest (test) {
  return {
    title: test.title,
    fullTitle: test.fullTitle(),
    duration: test.duration,
    state: test.state,
    pass: test.state === 'passed',
    fail: test.state === 'failed',
    code: utils.clean(test.fn.toString()),
    err: test.err
  }
}

function filterTest (passes, test) {
  return test.state === (passes ? 'passed' : 'failed');
}

/**
 * Save data out to files
 *
 * @param {String} json, html
 * @param {Object}
 * @api private
 */

function createStylesheet () {
  var stylesheet = fs.readFileSync(path.join(__dirname, '..', 'templates', 'styles', 'mochawesome.less'), {
    encoding: 'utf8'
  });

  var stylesPath = path.join(__dirname, '..', 'templates', 'styles');
  var bsPath = path.join(__dirname, '..', 'node_modules', 'bootstrap', 'less');

  var parser = new(less.Parser)({
    paths: [stylesPath, bsPath], // Specify search paths for @import directives
  });

  parser.parse(stylesheet, function(e, tree) {
    if (e) console.log(e);
    var outCss = tree.toCSS({
      compress: true
    });
    saveToFile('css', outCss);
  });
}

function saveToFile (filetype, inData) {
  var outData, outFile, writeFile;
  var outMsg = '';
  switch (filetype) {
  case 'json':
    outData = JSON.stringify(inData, null, 2);
    outFile = reportJsonFile;
    break;
  case 'html':
    outData = mochawesomeReportTmp(inData);
    outFile = reportHtmlFile;
    outMsg = "\nopen " + outFile.replace(process.cwd(),'').replace('/', '') + "\n";
    break;
  case 'css':
    outData = inData;
    outFile = reportCssFile;
    break;
  }

  try {
    if (!fs.existsSync(reportsDir)) {
      fs.mkdirSync(reportsDir);
    };
    writeFile = fs.openSync(outFile, 'w');
    fs.writeSync(writeFile, outData);
    fs.close(writeFile);
    util.print("Saved " + outFile + "\n" + outMsg);

  } catch (err) {
    console.log(err);
    util.print("\nError: Unable to save " + outFile + "\n");
  }

}<commit_msg>handle nested describes<commit_after>var util = require('util'),
    fs   = require('fs'),
    path = require('path'),
    mocha = require('mocha'),
    _ = require('lodash'),
    handlebars = require('handlebars'),
    moment = require('moment'),
    less = require('less');

var Base = mocha.reporters.Base,
    utils = mocha.utils,
    cursor = Base.cursor,
    color = Base.color;

var reportsDir = path.join(process.cwd(), 'reports'),
    reportJsonFile = path.join(reportsDir, 'reports.json'),
    reportHtmlFile = path.join(reportsDir, 'mochawesome.html');
    reportCssFile = path.join(reportsDir, 'mochawesome.css');

module.exports = Mochawesome;

createStylesheet();

// Load templates
// TODO: load all files in templates directory instead of specific ones
var mochawesomeReport = fs.readFileSync(path.join(__dirname, '..', 'templates', 'mochawesome.mu'), {
  encoding: 'utf8'
});

var _summary = fs.readFileSync(path.join(__dirname, '..', 'templates', '_summary.mu'), {
  encoding: 'utf8'
});

var _suite = fs.readFileSync(path.join(__dirname, '..', 'templates', '_suite.mu'), {
  encoding: 'utf8'
});

var _test = fs.readFileSync(path.join(__dirname, '..', 'templates', '_test.mu'), {
  encoding: 'utf8'
});

// TODO: if filename begins with underscore, register it as a partial
handlebars.registerPartial('_summary', _summary);
handlebars.registerPartial('_suite', _suite);
handlebars.registerPartial('_test', _test);

// Compile template
var mochawesomeReportTmp = handlebars.compile(mochawesomeReport);

/**
 * Initialize a new reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function Mochawesome (runner) {
  var self = this;
  Base.call(this, runner);

  var allSuites = {},
      allTests = [],
      allFailures = [],
      allPasses = [],
      endCalled = false;

  runner.on('test end', function (test) {
    allTests.push(test);
  });

  runner.on('pass', function (test) {
    allPasses.push(test);
  });

  runner.on('fail', function (test){
    allFailures.push(test);
  });

  runner.on('end', function () {
    if (!endCalled) {
      endCalled = true; // end gets called more than once for some reason so this ensures we only do this once

      allSuites = self.runner.suite;
      removeAllPropsFromObjExcept(allSuites, ['suites', 'root']);
      cleanSuiteObj(allSuites);

      // unless we render client-side, this has to be updated client-side
      // self.stats.endDateStr = moment(self.stats.end).fromNow();

      var obj = {
        stats: self.stats,
        suites: allSuites.suites,
        tests: allTests.map(cleanTest),
        passes: allPasses.map(cleanTest),
        failures: allFailures.map(cleanTest)
      };

      saveToFile('json', obj);
      saveToFile('html', obj);
    }
  });
}

/**
 * Return a plain-object representation of `test`
 * free of cyclic properties etc.
 *
 * @param {Object} test
 * @return {Object}
 * @api private
 */

function cleanTest (test) {
  return {
    title: test.title,
    fullTitle: test.fullTitle(),
    duration: test.duration,
    state: test.state,
    pass: test.state === 'passed',
    fail: test.state === 'failed',
    code: utils.clean(test.fn.toString()),
    err: test.err
  }
}

function removeAllPropsFromObjExcept(obj, propsToKeep) {
  _.forOwn(obj, function(val, prop) {
    if (propsToKeep.indexOf(prop) === -1) {
      delete obj[prop];
    }
  });
}

/**
 * Save data out to files
 *
 * @param {String} json, html
 * @param {Object}
 * @api private
 */

function createStylesheet () {
  var stylesheet = fs.readFileSync(path.join(__dirname, '..', 'templates', 'styles', 'mochawesome.less'), {
    encoding: 'utf8'
  });

  var stylesPath = path.join(__dirname, '..', 'templates', 'styles');
  var bsPath = path.join(__dirname, '..', 'node_modules', 'bootstrap', 'less');

  var parser = new(less.Parser)({
    paths: [stylesPath, bsPath], // Specify search paths for @import directives
  });

  parser.parse(stylesheet, function(e, tree) {
    if (e) console.log(e);
    var outCss = tree.toCSS({
      compress: true
    });
    saveToFile('css', outCss);
  });
}

function saveToFile (filetype, inData) {
  var outData, outFile, writeFile;
  var outMsg = '';
  switch (filetype) {
  case 'json':
    outData = JSON.stringify(inData, null, 2);
    outFile = reportJsonFile;
    break;
  case 'html':
    outData = mochawesomeReportTmp(inData);
    outFile = reportHtmlFile;
    outMsg = "\nopen " + outFile.replace(process.cwd(),'').replace('/', '') + "\n";
    break;
  case 'css':
    outData = inData;
    outFile = reportCssFile;
    break;
  }

  try {
    if (!fs.existsSync(reportsDir)) {
      fs.mkdirSync(reportsDir);
    };
    writeFile = fs.openSync(outFile, 'w');
    fs.writeSync(writeFile, outData);
    fs.close(writeFile);
    util.print("Saved " + outFile + "\n" + outMsg);

  } catch (err) {
    console.log(err);
    util.print("\nError: Unable to save " + outFile + "\n");
  }
}

function formatSuiteObject (suite) {
  var cleanTests = _.map(suite.tests, cleanTest);
  var passingTests = _.where(cleanTests, {state: 'passed'});
  var failingTests = _.where(cleanTests, {state: 'failed'});

  suite.tests = cleanTests;
  // suite.fullTitle = suite.fullTitle();
  file: suite.file.replace(process.cwd(), '');
  fullFile: suite.file;
  passes: passingTests;
  failures: failingTests;
  totalTests: suite.tests.length;
  totalPasses: passingTests.length;
  totalFailures: failingTests.length;

  removeAllPropsFromObjExcept(suite, [
    'title',
    'tests',
    'suites',
    'fullTitle',
    'file',
    'fullFile',
    'passes',
    'failures',
    'totalTests',
    'totalPasses',
    'totalFailures'
  ]);
}

function cleanSuiteObj (suite) {
  var queue = [],
      next = suite;
  while (next) {
    console.log("cleaning suite:", next.title);
    if (next.suites.length) {
      _.each(next.suites, function(suite, i) {
        formatSuiteObject(suite);
        queue.push(suite);
      });
    }
    next = queue.shift();
  }
}<|endoftext|>


<commit_before>"use strict";

const parse = require("github-calendar-parser")
    , $ = require("elly")
    , addSubtractDate = require("add-subtract-date")
    , formatoid = require("formatoid")
    ;

const DATE_FORMAT1 = "MMM D, YYYY"
    , DATE_FORMAT2 = "MMMM D"
    ;

/**
 * GitHubCalendar
 * Brings the contributions calendar from GitHub (provided username) into your page.
 *
 * @name GitHubCalendar
 * @function
 * @param {String|HTMLElement} container The calendar container (query selector or the element itself).
 * @param {String} username The GitHub username.
 * @param {Object} options An object containing the following fields:
 *
 *    - `summary_text` (String): The text that appears under the calendar (defaults to: `"Summary of
 *      pull requests, issues opened, and commits made by <username>"`).
 *    - `proxy` (Function): A function that receives as argument an url (string) and should return the proxied url.
 *      The default is using [@izuzak](https://github.com/izuzak)'s [`urlreq`](https://github.com/izuzak/urlreq).
 *    - `global_stats` (Boolean): If `false`, the global stats (total, longest and current streaks) will not be calculated and displayed. By default this is enabled.
 *    - `responsive` (Boolean): If `true`, the graph is changed to scale with the container. Custom CSS should be applied to the element to scale it appropriately. By default this is disabled.
 *
 * @return {Promise} A promise returned by the `fetch()` call.
 */
module.exports = function GitHubCalendar (container, username, options) {

    container = $(container);

    options = options || {};
    options.summary_text = options.summary_text || `Summary of pull requests, issues opened, and commits made by <a href="https://github.com/${username}" target="blank">@${username}</a>`;

    if (options.global_stats === false) {
        container.style.minHeight = "175px";
    }

    // We need a proxy for CORS
    // Thanks, @izuzak (https://github.com/izuzak/urlreq)
    options.proxy = options.proxy || function (url) {
        return "https://urlreq.appspot.com/req?method=GET&url=" + url;
    };

    let fetchCalendar = () => fetch(options.proxy("https://github.com/" + username)).then(response => {
        return response.text()
    }).then(body => {
        let div = document.createElement("div");
        div.innerHTML = body;
        let cal = div.querySelector(".js-yearly-contributions");
        $(".position-relative h2", cal).remove();
        cal.querySelector(".float-left.text-gray").innerHTML = options.summary_text;

        // If 'include-fragment' with spinner img loads instead of the svg, fetchCalendar again
        if (cal.querySelector("include-fragment")) {
            setTimeout(fetchCalendar, 500);
        } else {
            // If options includes responsive, SVG element has to be manipulated to be made responsive
            if (options.responsive === true) {
                let svg = cal.querySelector("svg.js-calendar-graph-svg");
                // Get the width/height properties and use them to create the viewBox
                let width = svg.getAttribute("width");
                let height = svg.getAttribute("height");
                // Remove height property entirely
                svg.removeAttribute("height");
                // Width property should be set to 100% to fill entire container
                svg.setAttribute("width", "100%");
                // Add a viewBox property based on the former width/height
                svg.setAttribute("viewBox", "0 0 " + width + " " + height);
            }

            if (options.global_stats !== false) {
                let parsed = parse($("svg", cal).outerHTML)
                  , currentStreakInfo = parsed.current_streak
                                      ? `${formatoid(parsed.current_streak_range[0], DATE_FORMAT2)} – ${formatoid(parsed.current_streak_range[1], DATE_FORMAT2)}`
                                      : parsed.last_contributed
                                      ? `Last contributed in ${formatoid(parsed.last_contributed, DATE_FORMAT2)}.`
                                      : "Rock - Hard Place"
                  , longestStreakInfo = parsed.longest_streak
                                      ? `${formatoid(parsed.longest_streak_range[0], DATE_FORMAT2)} – ${formatoid(parsed.longest_streak_range[1], DATE_FORMAT2)}`
                                      : parsed.last_contributed
                                      ? `Last contributed in ${formatoid(parsed.last_contributed, DATE_FORMAT2)}.`
                                      : "Rock - Hard Place"
                  , firstCol = $("
", {
                        "class": "contrib-column contrib-column-first table-column"
                      , html: `Contributions in the last year
                               ${parsed.last_year} total
                               ${formatoid(addSubtractDate.subtract(new Date(), 1, "year"), DATE_FORMAT1)} – ${formatoid(new Date(), DATE_FORMAT1)}`
                    })
                  , secondCol = $("
", {
                        "class": "contrib-column table-column"
                      , html: `Longest streak
                               ${parsed.longest_streak} days
                               ${longestStreakInfo}`
                    })
                  , thirdCol = $("
", {
                        "class": "contrib-column table-column"
                      , html: `Current streak
                               ${parsed.current_streak} days
                               ${currentStreakInfo}`
                    })
                  ;

                cal.appendChild(firstCol);
                cal.appendChild(secondCol);
                cal.appendChild(thirdCol);
            }

            container.innerHTML = cal.innerHTML;
        }
    }).catch(e => console.error(e));

    return fetchCalendar();
}

<commit_msg>Use faster loading GitHub contributions URL<commit_after>"use strict";

const parse = require("github-calendar-parser")
    , $ = require("elly")
    , addSubtractDate = require("add-subtract-date")
    , formatoid = require("formatoid")
    ;

const DATE_FORMAT1 = "MMM D, YYYY"
    , DATE_FORMAT2 = "MMMM D"
    ;

/**
 * GitHubCalendar
 * Brings the contributions calendar from GitHub (provided username) into your page.
 *
 * @name GitHubCalendar
 * @function
 * @param {String|HTMLElement} container The calendar container (query selector or the element itself).
 * @param {String} username The GitHub username.
 * @param {Object} options An object containing the following fields:
 *
 *    - `summary_text` (String): The text that appears under the calendar (defaults to: `"Summary of
 *      pull requests, issues opened, and commits made by <username>"`).
 *    - `proxy` (Function): A function that receives as argument an url (string) and should return the proxied url.
 *      The default is using [@izuzak](https://github.com/izuzak)'s [`urlreq`](https://github.com/izuzak/urlreq).
 *    - `global_stats` (Boolean): If `false`, the global stats (total, longest and current streaks) will not be calculated and displayed. By default this is enabled.
 *    - `responsive` (Boolean): If `true`, the graph is changed to scale with the container. Custom CSS should be applied to the element to scale it appropriately. By default this is disabled.
 *
 * @return {Promise} A promise returned by the `fetch()` call.
 */
module.exports = function GitHubCalendar (container, username, options) {

    container = $(container);

    options = options || {};
    options.summary_text = options.summary_text || `Summary of pull requests, issues opened, and commits made by <a href="https://github.com/${username}" target="blank">@${username}</a>`;

    if (options.global_stats === false) {
        container.style.minHeight = "175px";
    }

    // We need a proxy for CORS
    // Thanks, @izuzak (https://github.com/izuzak/urlreq)
    options.proxy = options.proxy || function (url) {
        return "https://urlreq.appspot.com/req?method=GET&url=" + url;
    };

    let fetchCalendar = () => fetch(options.proxy("https://github.com/users/" + username + "/contributions")).then(response => {
        return response.text()
    }).then(body => {
        let div = document.createElement("div");
        div.innerHTML = body;
        let cal = div.querySelector(".js-yearly-contributions");
        $(".position-relative h2", cal).remove();
        cal.querySelector(".float-left.text-gray").innerHTML = options.summary_text;

        // If 'include-fragment' with spinner img loads instead of the svg, fetchCalendar again
        if (cal.querySelector("include-fragment")) {
            setTimeout(fetchCalendar, 500);
        } else {
            // If options includes responsive, SVG element has to be manipulated to be made responsive
            if (options.responsive === true) {
                let svg = cal.querySelector("svg.js-calendar-graph-svg");
                // Get the width/height properties and use them to create the viewBox
                let width = svg.getAttribute("width");
                let height = svg.getAttribute("height");
                // Remove height property entirely
                svg.removeAttribute("height");
                // Width property should be set to 100% to fill entire container
                svg.setAttribute("width", "100%");
                // Add a viewBox property based on the former width/height
                svg.setAttribute("viewBox", "0 0 " + width + " " + height);
            }

            if (options.global_stats !== false) {
                let parsed = parse($("svg", cal).outerHTML)
                  , currentStreakInfo = parsed.current_streak
                                      ? `${formatoid(parsed.current_streak_range[0], DATE_FORMAT2)} – ${formatoid(parsed.current_streak_range[1], DATE_FORMAT2)}`
                                      : parsed.last_contributed
                                      ? `Last contributed in ${formatoid(parsed.last_contributed, DATE_FORMAT2)}.`
                                      : "Rock - Hard Place"
                  , longestStreakInfo = parsed.longest_streak
                                      ? `${formatoid(parsed.longest_streak_range[0], DATE_FORMAT2)} – ${formatoid(parsed.longest_streak_range[1], DATE_FORMAT2)}`
                                      : parsed.last_contributed
                                      ? `Last contributed in ${formatoid(parsed.last_contributed, DATE_FORMAT2)}.`
                                      : "Rock - Hard Place"
                  , firstCol = $("
", {
                        "class": "contrib-column contrib-column-first table-column"
                      , html: `Contributions in the last year
                               ${parsed.last_year} total
                               ${formatoid(addSubtractDate.subtract(new Date(), 1, "year"), DATE_FORMAT1)} – ${formatoid(new Date(), DATE_FORMAT1)}`
                    })
                  , secondCol = $("
", {
                        "class": "contrib-column table-column"
                      , html: `Longest streak
                               ${parsed.longest_streak} days
                               ${longestStreakInfo}`
                    })
                  , thirdCol = $("
", {
                        "class": "contrib-column table-column"
                      , html: `Current streak
                               ${parsed.current_streak} days
                               ${currentStreakInfo}`
                    })
                  ;

                cal.appendChild(firstCol);
                cal.appendChild(secondCol);
                cal.appendChild(thirdCol);
            }

            container.innerHTML = cal.innerHTML;
        }
    }).catch(e => console.error(e));

    return fetchCalendar();
}

<|endoftext|>


<commit_before>var webfinger = require('webfinger').webfinger;
var ProtoNoSupportError = require('./errors/protonosupporterror');
var NoDataError = require('./errors/nodataerror');

function Resolver() {
}

Resolver.prototype.resolve = function(identifier, type, cb) {
  if (typeof type == 'function') {
    cb = type;
    type = undefined;
  }

  webfinger(identifier, type, { webfingerOnly: true }, function(err, jrd) {
    if (err) { return cb(new ProtoNoSupportError(err.message)); }
    var rec = {}
      , services = {}
      , links = jrd.links
      , link, i, len;
    if (jrd.subject) { rec.subject = jrd.subject; }
    if (jrd.aliases) {
      rec.aliases = jrd.aliases;
    }
    if (jrd.properties) {
      rec.attributes = jrd.properties;
    }
    if (links) {
      for (i = 0, len = links.length; i < len; ++i) {
        link = links[i];
        services[link.rel] = (services[link.rel] || []).concat({
          location: link.href,
          mediaType: link.type
        });
      }
      rec.services = services;
    }

    return cb(null, rec);
  });
}

Resolver.prototype.resolveAliases = function(identifier, cb) {
  this.resolve(identifier, function(err, rec) {
    if (err) { return cb(err); }
    if (!rec.aliases || rec.aliases.length == 0) {
      return cb(new NoDataError('No aliases in resource descriptor'));
    }

    return cb(null, rec.aliases);
  });
}

Resolver.prototype.resolveAttributes = function(identifier, cb) {
  this.resolve(identifier, function(err, rec) {
    if (err) { return cb(err); }
    if (!rec.attributes) {
      return cb(new NoDataError('No properties in resource descriptor'));
    }

    return cb(null, rec.attributes);
  });
}

Resolver.prototype.resolveServices = function(identifier, type, cb) {
  if (typeof type == 'function') {
    cb = type;
    type = undefined;
  }

  this.resolve(identifier, type, function(err, rec) {
    if (err) { return cb(err); }
    if (!rec.services || rec.services.length == 0) {
      return cb(new NoDataError('No link relations in resource descriptor'));
    }

    var services = rec.services
      , instances;
    if (type) {
      instances = services[type];
      if (!instances) { return cb(new NoDataError('Link relation not found: ' + type)); }
      return cb(null, instances);
    }
    return cb(null, rec.services);
  });
}

/**
 * Creates a WebFinger resolver.
 *
 * References:
 *  - [WebFinger](https://tools.ietf.org/html/rfc7033)
 *
 * @api public
 */
module.exports = function() {
  return new Resolver();
}
<commit_msg>Add comments.<commit_after>var webfinger = require('webfinger').webfinger;
var ProtoNoSupportError = require('./errors/protonosupporterror');
var NoDataError = require('./errors/nodataerror');

function Resolver() {
}

Resolver.prototype.resolve = function(identifier, type, cb) {
  if (typeof type == 'function') {
    cb = type;
    type = undefined;
  }

  webfinger(identifier, type, { webfingerOnly: true }, function(err, jrd) {
    if (err) { return cb(new ProtoNoSupportError(err.message)); }
    var rec = {}
      , services = {}
      , links = jrd.links
      , link, i, len;
    if (jrd.subject) { rec.subject = jrd.subject; }
    if (jrd.aliases) {
      rec.aliases = jrd.aliases;
    }
    if (jrd.properties) {
      rec.attributes = jrd.properties;
    }
    if (links) {
      for (i = 0, len = links.length; i < len; ++i) {
        link = links[i];
        services[link.rel] = (services[link.rel] || []).concat({
          location: link.href,
          mediaType: link.type
        });
      }
      rec.services = services;
    }

    return cb(null, rec);
  });
}

Resolver.prototype.resolveAliases = function(identifier, cb) {
  this.resolve(identifier, function(err, rec) {
    if (err) { return cb(err); }
    if (!rec.aliases || rec.aliases.length == 0) {
      return cb(new NoDataError('No aliases in resource descriptor'));
    }

    return cb(null, rec.aliases);
  });
}

Resolver.prototype.resolveAttributes = function(identifier, cb) {
  this.resolve(identifier, function(err, rec) {
    if (err) { return cb(err); }
    if (!rec.attributes) {
      return cb(new NoDataError('No properties in resource descriptor'));
    }

    return cb(null, rec.attributes);
  });
}

Resolver.prototype.resolveServices = function(identifier, type, cb) {
  if (typeof type == 'function') {
    cb = type;
    type = undefined;
  }

  this.resolve(identifier, type, function(err, rec) {
    if (err) { return cb(err); }
    if (!rec.services || rec.services.length == 0) {
      return cb(new NoDataError('No link relations in resource descriptor'));
    }

    var services = rec.services
      , instances;
    if (type) {
      instances = services[type];
      if (!instances) { return cb(new NoDataError('Link relation not found: ' + type)); }
      return cb(null, instances);
    }
    return cb(null, rec.services);
  });
}

/**
 * Creates a WebFinger resolver.
 *
 * For compatibility purposes, it is important to note that up to [draft-02](https://tools.ietf.org/html/draft-ietf-appsawg-webfinger-02)
 * of WebFinger, the specification utilized [Web Host Metadata](https://tools.ietf.org/html/rfc6415)
 * and `lrdd` relations for resource-based discovery.  As of [draft-03](https://tools.ietf.org/html/draft-ietf-appsawg-webfinger-03),
 * the specification diverged significantly and moved away from Web Host
 * Metadata, simplifying the protocol to use a well-known WebFinger endpoint.
 * If compatibility with the Web Host Metadata is desired, please install the
 * `fingro-lrdd` package.
 *
 * References:
 *  - [WebFinger](https://tools.ietf.org/html/rfc7033)
 *
 * @api public
 */
module.exports = function() {
  return new Resolver();
}
<|endoftext|>


<commit_before>const Schema = require('./schema');
const SchemaConverterFactory = require('./converters');

Schema.prototype.to = function(type, options, context) {
  const converter = SchemaConverterFactory.create(type, options);
  return converter.convert(this, context);
};

module.exports = Schema;
<commit_msg>fix style<commit_after>const Schema = require('./schema');
const SchemaConverterFactory = require('./converters');

Schema.prototype.to = function (type, options, context) {
  const converter = SchemaConverterFactory.create(type, options);
  return converter.convert(this, context);
};

module.exports = Schema;
<|endoftext|>


<commit_before>'use strict';

const Async = require('async');
const Boom = require('boom');

const DENY = 0,
    PERMIT = 1,
    UNDETERMINED = 3;

const internals = {};

exports.register = (server, options, next) => {

    server.ext('onPostAuth', (request, reply) => {

        if (request.route.settings.plugins.rbac) {
            return internals.evaluatePolicy(request.route.settings.plugins.rbac, request.auth.credentials, (err, result) => {

                if (err) {
                    return reply(err);
                }

                if (result === DENY) {
                    return reply(Boom.unauthorized('No permissions to access this resource'));
                }

                if (result === UNDETERMINED) {
                    return reply(Boom.unauthorized('Could not evaluate access rights to resource'));
                }

                reply.continue();
            });
        }

        reply.continue();
    });

    next();
};

exports.register.attributes = {
    pkg: require('../package.json')
};

/**
 * Evaluate a single Policy of PolicySet
 *
 **/
internals.evaluatePolicy = (item, information, callback) => {

    if (!item) {
        return callback(Boom.badImplementation('RBAC configuration error: null item'));
    }

    if (!item.apply) {
        item.apply = 'permit-overrides';
    }

    if (!(item.apply instanceof Function)) {
        if (!internals.combineAlg[item.apply]) {
            return callback(Boom.badImplementation('RBAC error: combinatory algorithm does not exist: ' + item.apply));
        }

        item.apply = internals.combineAlg[item.apply];
    }

    internals.evaluateTarget(item.target, information, (err, applies) => {

        if (err) {
            return callback(err);
        }

        if (!applies) {
            return callback(null, UNDETERMINED);
        }

        // Policy set
        if (item.policies) {

            return item.apply(item.policies, information, internals.evaluatePolicy, callback);
        }

        // Policy
        if (item.rules) {

            return item.apply(item.rules, information, internals.evaluateRule, callback);
        }

        // Rule
        internals.evaluateRule(item, information, callback);
    });
};

/**
 * Evaluate a single rule.
 *
 * {
 *    'target': ['any-of', item1, ..., itemN],
 *    'effect': PERMIT, DENY
 * }
 **/
internals.evaluateRule = (rule, information, callback) => {

    if (!rule) {
        return callback(Boom.badImplementation('RBAC rule is missing'));
    }

    internals.evaluateTarget(rule.target, information, (err, applies) => {

        if (err) {
            return callback(err);
        }

        if (!applies) {
            return callback(null, UNDETERMINED);
        }

        switch (rule.effect) {
            case 'permit':
            case PERMIT:
                return callback(null, PERMIT);
            case 'deny':
            case DENY:
                return callback(null, DENY);
            default:
                return callback(Boom.badImplementation('RBAC rule error: invalid effect ' + rule.effect));
        }
    });
};

/**
 * Evaluate a target
 * ['any-of', {type: 'username', value:'francisco'}, {type: 'group', value:'admin'}]
 * ['all-of', {type: 'username', value:'francisco'}, {type: 'group', value:'admin'}]
 **/
internals.evaluateTarget = (target, information, callback) => {

    if (!target) {
        // Applies by default, when no target is defined
        return callback(null, true);
    }

    if (!(target instanceof Array) || target.length < 2) {
        return callback(Boom.badImplementation('RBAC target error: invalid format. Should be an array with match type and items ["all-of", item1, item2, ..., itemN]'));
    }

    for (let i = 1; i < target.length; i++) {
        const result = internals._targetApplies(target[i].value, information[target[i].type]);

        if (result && target[0] === 'any-of') {
            return callback(null, true);
        }

        if (!result && target[0] === 'all-of') {
            return callback(null, false);
        }
    }

    return callback(null, target[0] === 'all-of');
};

internals._targetApplies = (target, value) => {

    if (target === value) {
        return true;
    }

    if (value instanceof Array) {
        if (value.indexOf(target) !== -1) {
            return true;
        }
    }

    return false;
};

/**
 * Combinator algorithms:
 *
 *   - permit-overrides - If at least one permit is evaluated, then permit
 *   - deny-overrides - If at least one deny is evaluated, then deny
 *   - only-one-applicable -
 *   - first-applicable - Only evaluate the first applicable rule
 **/
internals.combineAlg = {};

internals.combineAlg['permit-overrides'] = (items, information, fn, callback) => {

    if (!items || items.length === 0) {
        return callback(null, UNDETERMINED);
    }

    const tasks = [];

    for (let i = 0; i < items.length; i++) {
        tasks.push(fn.bind(null, items[i], information));
    }

    Async.parallel(tasks, (err, results) => {

        if (err) {
            return callback(err);
        }

        for (let i = 0; i < results.length; i++) {
            if (results[i] === PERMIT) {
                return callback(null, PERMIT);
            }
        }

        callback(null, DENY);
    });
};

internals.combineAlg['deny-overrides'] = (items, information, fn, callback) => {

    if (!items || items.length === 0) {
        return callback(null, UNDETERMINED);
    }

    const tasks = [];

    for (let i = 0; i < items.length; i++) {
        tasks.push(fn.bind(null, items[i], information));
    }

    Async.parallel(tasks, (err, results) => {

        if (err) {
            return callback(err);
        }

        for (let i = 0; i < results.length; i++) {
            if (results[i] === DENY) {
                return callback(null, DENY);
            }
        }

        callback(null, PERMIT);
    });
};

if (['test', 'development'].indexOf(process.env.NODE_ENV) !== -1) {

    // To run the lab tests
    exports.evaluateTarget = internals.evaluateTarget;
    exports.evaluatePolicy = internals.evaluatePolicy;
    exports.evaluateRule = internals.evaluateRule;

    exports.PERMIT = PERMIT;
    exports.DENY = DENY;
    exports.UNDETERMINED = UNDETERMINED;
}
<commit_msg>Retrieval of policy in case config is function<commit_after>'use strict';

const Async = require('async');
const Boom = require('boom');

const DENY = 0,
    PERMIT = 1,
    UNDETERMINED = 3;

const internals = {};

exports.register = (server, options, next) => {

    server.ext('onPostAuth', (request, reply) => {

        if (request.route.settings.plugins.rbac) {

            return internals.retrievePolicy(request, (err, policy) => {

                if (err) {
                    return reply(err);
                }

                internals.evaluatePolicy(request.route.settings.plugins.rbac, request.auth.credentials, (err, result) => {

                    if (err) {
                        return reply(err);
                    }

                    if (result === DENY) {
                        return reply(Boom.unauthorized('No permissions to access this resource'));
                    }

                    if (result === UNDETERMINED) {
                        return reply(Boom.unauthorized('Could not evaluate access rights to resource'));
                    }

                    reply.continue();
                });
            });
        }

        reply.continue();
    });

    next();
};

exports.register.attributes = {
    pkg: require('../package.json')
};

/**
 * If the configuration is a function, then this function should retrieve the access policy (e.g.: from a database).
 * Otherwise, it is assumed that the configuration is the access policy itself.
 *
 * The callback signature is function (err, policy) {}
 **/
internals.retrievePolicy = (request, callback) => {

    if (request.route.settings.plugins.rbac instanceof Function) {
        request.route.settings.plugins.rbac(reqeust, callback);
    }
    else {

        callback(null, request.route.settings.plugins.rbac);
    }
};

/**
 * Evaluate a single Policy of PolicySet
 *
 **/
internals.evaluatePolicy = (item, information, callback) => {

    if (!item) {
        return callback(Boom.badImplementation('RBAC configuration error: null item'));
    }

    if (!item.apply) {
        item.apply = 'permit-overrides';
    }

    if (!(item.apply instanceof Function)) {
        if (!internals.combineAlg[item.apply]) {
            return callback(Boom.badImplementation('RBAC error: combinatory algorithm does not exist: ' + item.apply));
        }

        item.apply = internals.combineAlg[item.apply];
    }

    internals.evaluateTarget(item.target, information, (err, applies) => {

        if (err) {
            return callback(err);
        }

        if (!applies) {
            return callback(null, UNDETERMINED);
        }

        // Policy set
        if (item.policies) {

            return item.apply(item.policies, information, internals.evaluatePolicy, callback);
        }

        // Policy
        if (item.rules) {

            return item.apply(item.rules, information, internals.evaluateRule, callback);
        }

        // Rule
        internals.evaluateRule(item, information, callback);
    });
};

/**
 * Evaluate a single rule.
 *
 * {
 *    'target': ['any-of', item1, ..., itemN],
 *    'effect': PERMIT, DENY
 * }
 **/
internals.evaluateRule = (rule, information, callback) => {

    if (!rule) {
        return callback(Boom.badImplementation('RBAC rule is missing'));
    }

    internals.evaluateTarget(rule.target, information, (err, applies) => {

        if (err) {
            return callback(err);
        }

        if (!applies) {
            return callback(null, UNDETERMINED);
        }

        switch (rule.effect) {
            case 'permit':
            case PERMIT:
                return callback(null, PERMIT);
            case 'deny':
            case DENY:
                return callback(null, DENY);
            default:
                return callback(Boom.badImplementation('RBAC rule error: invalid effect ' + rule.effect));
        }
    });
};

/**
 * Evaluate a target
 * ['any-of', {type: 'username', value:'francisco'}, {type: 'group', value:'admin'}]
 * ['all-of', {type: 'username', value:'francisco'}, {type: 'group', value:'admin'}]
 **/
internals.evaluateTarget = (target, information, callback) => {

    if (!target) {
        // Applies by default, when no target is defined
        return callback(null, true);
    }

    if (!(target instanceof Array) || target.length < 2) {
        return callback(Boom.badImplementation('RBAC target error: invalid format. Should be an array with match type and items ["all-of", item1, item2, ..., itemN]'));
    }

    for (let i = 1; i < target.length; i++) {
        const result = internals._targetApplies(target[i].value, information[target[i].type]);

        if (result && target[0] === 'any-of') {
            return callback(null, true);
        }

        if (!result && target[0] === 'all-of') {
            return callback(null, false);
        }
    }

    return callback(null, target[0] === 'all-of');
};

internals._targetApplies = (target, value) => {

    if (target === value) {
        return true;
    }

    if (value instanceof Array) {
        if (value.indexOf(target) !== -1) {
            return true;
        }
    }

    return false;
};

/**
 * Combinator algorithms:
 *
 *   - permit-overrides - If at least one permit is evaluated, then permit
 *   - deny-overrides - If at least one deny is evaluated, then deny
 *   - only-one-applicable -
 *   - first-applicable - Only evaluate the first applicable rule
 **/
internals.combineAlg = {};

internals.combineAlg['permit-overrides'] = (items, information, fn, callback) => {

    if (!items || items.length === 0) {
        return callback(null, UNDETERMINED);
    }

    const tasks = [];

    for (let i = 0; i < items.length; i++) {
        tasks.push(fn.bind(null, items[i], information));
    }

    Async.parallel(tasks, (err, results) => {

        if (err) {
            return callback(err);
        }

        for (let i = 0; i < results.length; i++) {
            if (results[i] === PERMIT) {
                return callback(null, PERMIT);
            }
        }

        callback(null, DENY);
    });
};

internals.combineAlg['deny-overrides'] = (items, information, fn, callback) => {

    if (!items || items.length === 0) {
        return callback(null, UNDETERMINED);
    }

    const tasks = [];

    for (let i = 0; i < items.length; i++) {
        tasks.push(fn.bind(null, items[i], information));
    }

    Async.parallel(tasks, (err, results) => {

        if (err) {
            return callback(err);
        }

        for (let i = 0; i < results.length; i++) {
            if (results[i] === DENY) {
                return callback(null, DENY);
            }
        }

        callback(null, PERMIT);
    });
};

if (['test', 'development'].indexOf(process.env.NODE_ENV) !== -1) {

    // To run the lab tests
    exports.evaluateTarget = internals.evaluateTarget;
    exports.evaluatePolicy = internals.evaluatePolicy;
    exports.evaluateRule = internals.evaluateRule;

    exports.PERMIT = PERMIT;
    exports.DENY = DENY;
    exports.UNDETERMINED = UNDETERMINED;
}
<|endoftext|>