<commit_before>/******************************************************************************
 * Module dependencies
 */
var express             = require('express')
  , __                  = require('express-resource')
  , async               = require('async')
  , path                = require('path')
  , _                   = require('underscore')
  , lingo               = require('lingo')
  ;

//project related dependencies
var asyncFs             = require('./util/async_fs')
  , dadt                = require('./util/dadt')
  , config              = require('./config')

  , CONTROLLER_NAME_REGEXP   = config.CONTROLLER_NAME_REGEXP
  ;

/******************************************************************************
 * Rocket template name space
 */
var rocket_tmpl         = {};

    rocket_tmpl.header  = function() {

      var args            = Array.prototype.slice.call(arguments)
        , controller_name = args.shift().replace(/[.,-;\s]+/g, '_')

        , header            = []

        , require_configuration =  global.require_configuration  || {}
        ;

      return header.join('\n');

    };

    rocket_tmpl.footer  = function() {

      var args            = Array.prototype.slice.call(arguments)
        , controller_name = args.shift().replace(/[.,-;\s]+/g, '_')

        , footer          = []

        , require_configuration =  global.require_configuration  || {}
        ;

      footer.push("<script>");
      footer.push("var _b = " + JSON.stringify(args) + "; ");
      footer.push("var require = " + JSON.stringify(require_configuration) + ";");
      footer.push("require.deps || (require.deps = []);");
      footer.push("require.deps.push('" + controller_name + "_client" + "')");
      footer.push("</script>");
      footer.push("<script src=\"//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.1/require.min.js\"></script>");
      footer.push("<script>window.define||document.write('<script src=\"/js/rocket/vendors/require.min.js\"><\\/script>')</script>")
      footer.push("<script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js\"></script>")
      footer.push("<script src=\"/js/" + controller_name + "_client.js?" + require_configuration.urlArgs + "\"></script>")
      footer.push("<script>require(['" + controller_name + "_client" + "'], function(m) { m && m.init && m.init.apply(m, _b); })</script>")

      return footer.join('\n');

    };

/******************************************************************************
 * Destroy all the routes associated with a given controller
 *
 * @param app {Object} The `app` object as returned by express, connect, or
 * rocket.
 *
 * @param routes_dadt {Object} The root of routes' dadt data structure.
 *
 * @param controller_name {String} The name of the controller
 */
function destroyControllerRoutes(app, routes_dadt, controller_name) {

  var routes = routes_dadt.get(controller_name).get('routes')
    ;

  if (routes) {

    for (var route in routes.values) {

      app.remove(route);

    }

  }

  delete app.resources[controller_info.name];
  controller_info.set('routes', dadt.createNode());

}

/******************************************************************************
 * Builds a wrapper function sending raw json as a response if no view is found
 * or a rendered view
 *
 * @param controller_info {dadtNode} The dadtNode containing the controller
 *                                   info.
 *
 * @param method_func {Function} The method function.
 */
function buildWrapper(controller_info, method_func) {

  return function(req, res, next) {

    var view_file   = controller_info.get('view')

      , layout_node = controller_info.parent.get('layout')
      , __          = !layout_node && controller_info.parent.parent && (layout_node = controller_info.parent.parent.get('layout'))
      , layout      = (typeof layout_node !== 'undefined' ? layout_node.get('view') : true)

      , oSend       = res.send
      , oRender     = res.render
      ;

    res._boot_options || (res._boot_options = {});

    //check if we have a view & if that we do not have an XHR-Request.
    //If the view is missing or if we have an XHR-Request, skip view rendering.
    if (!req.xhr && view_file) {

      //restore the original `res.send` function when `res.render` is called.
      res.render = function() {

        res.send = oSend;
        return oRender.apply(res, arguments);
      };

      //replace the original send function to be able to automatically render
      //the wanted view.
      res.send = function(obj) {

        obj = obj || {};

        obj.layout = layout

        obj.controller = obj.controller || controller_info.parent.get('name');

        obj.rocket = obj.rocket || rocket_tmpl;

        res.send = oSend;

        obj.boot_options = _.extend(res._boot_options, obj.boot_options);

        res.render(view_file, obj);

      };

    }

    method_func(req, res, next);

  };

}

/******************************************************************************
 * Builds and set up the routes of the given controller. Removing the previous
 * routes if necessary.
 *
 * @param app {Object} The app object as returned by express, connect, or
 * rocket.
 *
 * @param controller_info {Object} The dadt node containing the controller info.
 *
 * @param controller {Object} The controller object to route.
 */
function buildRoutes(app, controller_info, controller) {

  var wrapped_funcs = {}
    , split         = []

    , resource
    , load
    , name = controller_info.get('name')

    , controller_path = controller_info.get('path')
    ;

  for (var key in controller) {

    if (key.substr(0,1) === '_') {

      if (key === '_load' && typeof controller[key] === 'function') {

        //if the method name is `_load`  and it is a function ... save it.

        loader = controller[key];

      }

      //ignore keys beginning with a `_` unless it is `_load`
      continue;

    }

    controller_info.setIfNone(key, dadt.createNode());
    innerNode = controller_info.get(key);

    if (typeof controller[key] === 'object' && controller[key] !== null) {

      var verbs       = _.functions(controller[key])
        , route       = (name === 'root' ? path.join('/', key) : path.join('/', name,  key))
        , param       = ':' + lingo.en.singularize(name)
        , route_param = path.join(route, param)
        ;

      innerNode.set('name', [name, key].join('.'));

      for (var i = 0, ii = verbs.length; i < ii; i++) {

        var current_verb  = verbs[i]
          , method        = controller[key][current_verb]
          ;

        if (['get', 'post', 'put', 'del'].indexOf(current_verb) !== -1) {

          innerNode.setIfNone(current_verb, dadt.createNode());

          var wrapped           = undefined
            , current_verb_node = innerNode.get(current_verb)
            ;

          wrapped = buildWrapper(current_verb_node, method);

          current_verb_node.set('handler', wrapped);

          require.cache[controller_path].exports[key][current_verb] = wrapped;

          app[current_verb](route, wrapped);
          app[current_verb](route_param, wrapped);

          controller_info.get('routes').setIfNone(route, true);
          controller_info.get('routes').setIfNone(route_param, true);

        }

      }

    } else if(typeof controller[key] === 'function') {

      var wrapped     = undefined
        , key_node    = controller_info.get(key)
        , route       = (name === 'root' ? path.join('/', key) : path.join('/', name,  key))
        , param       = ':' + lingo.en.singularize(name)
        , route_param = path.join(route, param)
        ;

      wrapped = buildWrapper(innerNode, controller[key]);

      innerNode.set('handler', wrapped);
      require.cache[controller_path].exports[key] = wrapped;

      //if the function is a custom controller method ...
      if (['index', 'show', 'new', 'create', 'edit', 'update', 'destroy'].indexOf(key) === -1) {

        app.all(route, wrapped);
        app.all(route_param, wrapped);

        controller_info.get('routes').setIfNone(route, true);
        controller_info.get('routes').setIfNone(route_param, true);

      } else {

        app.remove(route);
        app.remove(route_param);

        wrapped_funcs[key] = wrapped;
      }

    }

  }

  if(name === 'root') {

    resource = app.resource(wrapped_funcs);

  } else {

    resource = app.resource(name, wrapped_funcs);

  }

  if(typeof load !== 'undefined') {

    resource.load(load);

  }

  for (var verb in resource.routes) {

    for (var url in resource.routes[verb]) {

      controller_info.get('routes').setIfNone(url, true);

    }

  }

}

/******************************************************************************
 * Function called either when a new controller file is found or when a change
 * is detected. It takes care of clearing the `require` cache and creating the
 * controllers dadt node.
 *
 *
 * @param app {Object} The app object as returned by express, connect, or
 *                         rocket.
 *
 * @param controller_info {Object} The dadt node containing the controller info.
 *
 * @param controller_path {Object} The path of the current
 *                                 controller file.
 *
 * @param callback {Function} A callback of the form `function(err)`.
 *
 */
function loadController() {

  var args            = Array.prototype.slice.call(arguments)

    , app             = args.shift()

    , controller_info = args.shift()

    , controller_path = args.shift()

    , callback        = args.pop()

    , controller
    ;

  controller = require(controller_path);

  buildRoutes(app, controller_info, controller);

  if (callback) {
      callback(null);
  }
}

/******************************************************************************
 * Sets up the listeners on the `controllers` directory and calls
 * `loadController`.
 *
 * This function is also called each time a new controller file is found.
 *
 *
 * @param app {Object} The app object as returned by express, connect, or
 * rocket.
 *
 * @param routes_dadt {Object} The root of routes' dadt data structure.
 *
 * @param controller_file {Object} The FileEventEmitter object of the current
 * controller file.
 *
 * @param matches {Array} Array of the matched patterns of the RegExp selecting
 * this controller file.
 *
 *
 * @param callback {Function} A callback of the form `function(err)`
 *
 */
function setupController(app, routes_dadt, controller_file, matches, callback) {

  var controller_name = matches[1]

    , controller_path = controller_file.path

    , reload
    ;

  routes_dadt.setIfNone(controller_name, dadt.createNode());

  controller_info = routes_dadt.get(controller_name);

  controller_info.set('routes', dadt.createNode());

  controller_name = lingo.camelcase(controller_name.replace(/_/g, ' '));

  controller_info.set('name', controller_name);

  controller_info.set('path', controller_path);

  reload = async.apply(
    loadController
    , app
    , controller_info
    , controller_path
  )

  controller_file.on('change', function(curr, prev) {

    if (curr.nlink > 0) {

      if (require.cache[controller_path]) {

        delete require.cache[controller_path];

      }

      destroyControllerRoutes(app, routes_dadt, controller_name);

      reload();

    }

  });

  controller_file.on('destroy', function() {

    controller_file.unwatch();
    destroyControllerRoutes(app, routes_dadt, controller_name)

  });

  reload(callback);

}

/******************************************************************************
 * Setups the controllers, also watches the `controllers` directory for new
 * files and calls `setupController` accordingly.
 *
 * @param app {Object} The app object as returned by express, connect, or
 * rocket.
 *
 * @param routes_dadt {Object} The root of routes' dadt data structure.
 *
 * @param controllers {Object} The FileEventEmitter object of the `controllers`
 * folder.
 *
 * @param callback {Function} A callback of the form `function(err)`
 */
exports.setup = function setup_controller() {

  var args        = Array.prototype.slice.call(arguments)

    , app         = args.shift()
    , routes_dadt = args.shift()

    , controllers = args.shift()

    , callback    = args.pop()
    ;

  app.rocket_routes = routes_dadt;

  app.use(express.methodOverride());

  asyncFs.mapDir(

      controllers.path

    , [ CONTROLLER_NAME_REGEXP , async.apply(setupController, app, routes_dadt) ]

    , callback

  );

}<commit_msg>FIXED - Unpacked RequireJS Modules Loading<commit_after>/******************************************************************************
 * Module dependencies
 */
var express             = require('express')
  , __                  = require('express-resource')
  , async               = require('async')
  , path                = require('path')
  , _                   = require('underscore')
  , lingo               = require('lingo')
  ;

//project related dependencies
var asyncFs             = require('./util/async_fs')
  , dadt                = require('./util/dadt')
  , config              = require('./config')

  , CONTROLLER_NAME_REGEXP   = config.CONTROLLER_NAME_REGEXP
  ;

/******************************************************************************
 * Rocket template name space
 */
var rocket_tmpl         = {};

    rocket_tmpl.header  = function() {

      var args            = Array.prototype.slice.call(arguments)
        , controller_name = args.shift().replace(/[.,-;\s]+/g, '_')

        , header            = []

        , require_configuration =  global.require_configuration  || {}
        ;

      return header.join('\n');

    };

    rocket_tmpl.footer  = function() {

      var args            = Array.prototype.slice.call(arguments)
        , controller_name = args.shift().replace(/[.,-;\s]+/g, '_')

        , footer          = []

        , require_configuration =  global.require_configuration  || {}
        ;

      footer.push("<script>");
      footer.push("var _b = " + JSON.stringify(args) + "; ");
      footer.push("var require = " + JSON.stringify(require_configuration) + ";");
      footer.push("require.deps || (require.deps = []);");
      footer.push("require.deps.push('" + controller_name + "_client" + "')");
      footer.push("</script>");
      footer.push("<script src=\"//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.1/require.min.js\"></script>");
      footer.push("<script>window.define||document.write('<script src=\"/js/rocket/vendors/require.min.js\"><\\/script>')</script>")
      footer.push("<script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js\"></script>")

      if (process.env['NODE_ENV'] === 'production')
        footer.push("<script src=\"/js/" + controller_name + "_client.js?" + require_configuration.urlArgs + "\"></script>")

      footer.push("<script>require(['" + controller_name + "_client" + "'], function(m) { m && m.init && m.init.apply(m, _b); })</script>")

      return footer.join('\n');

    };

/******************************************************************************
 * Destroy all the routes associated with a given controller
 *
 * @param app {Object} The `app` object as returned by express, connect, or
 * rocket.
 *
 * @param routes_dadt {Object} The root of routes' dadt data structure.
 *
 * @param controller_name {String} The name of the controller
 */
function destroyControllerRoutes(app, routes_dadt, controller_name) {

  var routes = routes_dadt.get(controller_name).get('routes')
    ;

  if (routes) {

    for (var route in routes.values) {

      app.remove(route);

    }

  }

  delete app.resources[controller_info.name];
  controller_info.set('routes', dadt.createNode());

}

/******************************************************************************
 * Builds a wrapper function sending raw json as a response if no view is found
 * or a rendered view
 *
 * @param controller_info {dadtNode} The dadtNode containing the controller
 *                                   info.
 *
 * @param method_func {Function} The method function.
 */
function buildWrapper(controller_info, method_func) {

  return function(req, res, next) {

    var view_file   = controller_info.get('view')

      , layout_node = controller_info.parent.get('layout')
      , __          = !layout_node && controller_info.parent.parent && (layout_node = controller_info.parent.parent.get('layout'))
      , layout      = (typeof layout_node !== 'undefined' ? layout_node.get('view') : true)

      , oSend       = res.send
      , oRender     = res.render
      ;

    res._boot_options || (res._boot_options = {});

    //check if we have a view & if that we do not have an XHR-Request.
    //If the view is missing or if we have an XHR-Request, skip view rendering.
    if (!req.xhr && view_file) {

      //restore the original `res.send` function when `res.render` is called.
      res.render = function() {

        res.send = oSend;
        return oRender.apply(res, arguments);
      };

      //replace the original send function to be able to automatically render
      //the wanted view.
      res.send = function(obj) {

        obj = obj || {};

        obj.layout = layout

        obj.controller = obj.controller || controller_info.parent.get('name');

        obj.rocket = obj.rocket || rocket_tmpl;

        res.send = oSend;

        obj.boot_options = _.extend(res._boot_options, obj.boot_options);

        res.render(view_file, obj);

      };

    }

    method_func(req, res, next);

  };

}

/******************************************************************************
 * Builds and set up the routes of the given controller. Removing the previous
 * routes if necessary.
 *
 * @param app {Object} The app object as returned by express, connect, or
 * rocket.
 *
 * @param controller_info {Object} The dadt node containing the controller info.
 *
 * @param controller {Object} The controller object to route.
 */
function buildRoutes(app, controller_info, controller) {

  var wrapped_funcs = {}
    , split         = []

    , resource
    , load
    , name = controller_info.get('name')

    , controller_path = controller_info.get('path')
    ;

  for (var key in controller) {

    if (key.substr(0,1) === '_') {

      if (key === '_load' && typeof controller[key] === 'function') {

        //if the method name is `_load`  and it is a function ... save it.

        loader = controller[key];

      }

      //ignore keys beginning with a `_` unless it is `_load`
      continue;

    }

    controller_info.setIfNone(key, dadt.createNode());
    innerNode = controller_info.get(key);

    if (typeof controller[key] === 'object' && controller[key] !== null) {

      var verbs       = _.functions(controller[key])
        , route       = (name === 'root' ? path.join('/', key) : path.join('/', name,  key))
        , param       = ':' + lingo.en.singularize(name)
        , route_param = path.join(route, param)
        ;

      innerNode.set('name', [name, key].join('.'));

      for (var i = 0, ii = verbs.length; i < ii; i++) {

        var current_verb  = verbs[i]
          , method        = controller[key][current_verb]
          ;

        if (['get', 'post', 'put', 'del'].indexOf(current_verb) !== -1) {

          innerNode.setIfNone(current_verb, dadt.createNode());

          var wrapped           = undefined
            , current_verb_node = innerNode.get(current_verb)
            ;

          wrapped = buildWrapper(current_verb_node, method);

          current_verb_node.set('handler', wrapped);

          require.cache[controller_path].exports[key][current_verb] = wrapped;

          app[current_verb](route, wrapped);
          app[current_verb](route_param, wrapped);

          controller_info.get('routes').setIfNone(route, true);
          controller_info.get('routes').setIfNone(route_param, true);

        }

      }

    } else if(typeof controller[key] === 'function') {

      var wrapped     = undefined
        , key_node    = controller_info.get(key)
        , route       = (name === 'root' ? path.join('/', key) : path.join('/', name,  key))
        , param       = ':' + lingo.en.singularize(name)
        , route_param = path.join(route, param)
        ;

      wrapped = buildWrapper(innerNode, controller[key]);

      innerNode.set('handler', wrapped);
      require.cache[controller_path].exports[key] = wrapped;

      //if the function is a custom controller method ...
      if (['index', 'show', 'new', 'create', 'edit', 'update', 'destroy'].indexOf(key) === -1) {

        app.all(route, wrapped);
        app.all(route_param, wrapped);

        controller_info.get('routes').setIfNone(route, true);
        controller_info.get('routes').setIfNone(route_param, true);

      } else {

        app.remove(route);
        app.remove(route_param);

        wrapped_funcs[key] = wrapped;
      }

    }

  }

  if(name === 'root') {

    resource = app.resource(wrapped_funcs);

  } else {

    resource = app.resource(name, wrapped_funcs);

  }

  if(typeof load !== 'undefined') {

    resource.load(load);

  }

  for (var verb in resource.routes) {

    for (var url in resource.routes[verb]) {

      controller_info.get('routes').setIfNone(url, true);

    }

  }

}

/******************************************************************************
 * Function called either when a new controller file is found or when a change
 * is detected. It takes care of clearing the `require` cache and creating the
 * controllers dadt node.
 *
 *
 * @param app {Object} The app object as returned by express, connect, or
 *                         rocket.
 *
 * @param controller_info {Object} The dadt node containing the controller info.
 *
 * @param controller_path {Object} The path of the current
 *                                 controller file.
 *
 * @param callback {Function} A callback of the form `function(err)`.
 *
 */
function loadController() {

  var args            = Array.prototype.slice.call(arguments)

    , app             = args.shift()

    , controller_info = args.shift()

    , controller_path = args.shift()

    , callback        = args.pop()

    , controller
    ;

  controller = require(controller_path);

  buildRoutes(app, controller_info, controller);

  if (callback) {
      callback(null);
  }
}

/******************************************************************************
 * Sets up the listeners on the `controllers` directory and calls
 * `loadController`.
 *
 * This function is also called each time a new controller file is found.
 *
 *
 * @param app {Object} The app object as returned by express, connect, or
 * rocket.
 *
 * @param routes_dadt {Object} The root of routes' dadt data structure.
 *
 * @param controller_file {Object} The FileEventEmitter object of the current
 * controller file.
 *
 * @param matches {Array} Array of the matched patterns of the RegExp selecting
 * this controller file.
 *
 *
 * @param callback {Function} A callback of the form `function(err)`
 *
 */
function setupController(app, routes_dadt, controller_file, matches, callback) {

  var controller_name = matches[1]

    , controller_path = controller_file.path

    , reload
    ;

  routes_dadt.setIfNone(controller_name, dadt.createNode());

  controller_info = routes_dadt.get(controller_name);

  controller_info.set('routes', dadt.createNode());

  controller_name = lingo.camelcase(controller_name.replace(/_/g, ' '));

  controller_info.set('name', controller_name);

  controller_info.set('path', controller_path);

  reload = async.apply(
    loadController
    , app
    , controller_info
    , controller_path
  )

  controller_file.on('change', function(curr, prev) {

    if (curr.nlink > 0) {

      if (require.cache[controller_path]) {

        delete require.cache[controller_path];

      }

      destroyControllerRoutes(app, routes_dadt, controller_name);

      reload();

    }

  });

  controller_file.on('destroy', function() {

    controller_file.unwatch();
    destroyControllerRoutes(app, routes_dadt, controller_name)

  });

  reload(callback);

}

/******************************************************************************
 * Setups the controllers, also watches the `controllers` directory for new
 * files and calls `setupController` accordingly.
 *
 * @param app {Object} The app object as returned by express, connect, or
 * rocket.
 *
 * @param routes_dadt {Object} The root of routes' dadt data structure.
 *
 * @param controllers {Object} The FileEventEmitter object of the `controllers`
 * folder.
 *
 * @param callback {Function} A callback of the form `function(err)`
 */
exports.setup = function setup_controller() {

  var args        = Array.prototype.slice.call(arguments)

    , app         = args.shift()
    , routes_dadt = args.shift()

    , controllers = args.shift()

    , callback    = args.pop()
    ;

  app.rocket_routes = routes_dadt;

  app.use(express.methodOverride());

  asyncFs.mapDir(

      controllers.path

    , [ CONTROLLER_NAME_REGEXP , async.apply(setupController, app, routes_dadt) ]

    , callback

  );

}<|endoftext|>


<commit_before>"use strict";
module.exports = {
  createArrayBuffer(source) {
    const view = new Uint8Array(new ArrayBuffer(source.length));
    for (let i = 0; i < view.length; i++)
      view[i] = source[i];
    return view.buffer;
  },
  createBuffer(source) {
    if (source instanceof Float32Array) {
      const buf = new Buffer(source.length * 4);
      for (let i = 0; i < source.length; i++) {
        buf.writeFloatLE(source[i], i * 4);
      }
      return buf;
    }

    const view = new Uint8Array(source);
    const buf = new Buffer(view.length);
    for (let i = 0; i < view.length; i++)
      buf[i] = view[i];
    return buf;
  },
  bindGatewayEventHandlers(source, event, map) {
    if (!event.type)
      throw new Error("Invalid event");

    if (!(event.type in map))
      return;

    for (let k in map) {
      if (typeof map[k] !== "function")
        throw new Error(`Invalid handler ${k} for event ${event.type}`);
      map[k] = map[k].bind(source);
    }

    if (map[event.type](event.data))
      event.handled = true;
  },
  privatify(target) {
    for (var k in target) {
      if (k[0] != "_")
        continue;
      Object.defineProperty(target, k, {enumerable: false});
    }
  },
  reorderObjects(array, target, position) {
    array = array.slice();
    array.sort((a, b) => (a.position > b.position));
    const from = Math.max(array.findIndex(c => (c.id == target.id)), 0);
    const to = Math.min(Math.max(position, 0), array.length - 1);

    if (from == to) return;

    const remove = (i) => array.splice(i, 1)[0];
    const insert = (i, v) => array.splice(i, 0, v);

    insert(to, remove(from));

    const updated = array.map((c, i) => ({id: c.valueOf(), position: i}));
    const changes = to > from ?
      updated.slice(from, to + 1) :
      updated.slice(to, from + 1);

    return changes;
  },
  imageToDataURL(buffer) {
    if (!buffer || !(buffer instanceof Buffer)) return null;

    const types = {
      0xFFD8FF: "image/jpg",
      0x89504E: "image/png"
    };

    const magic = buffer.readUIntBE(0, 3);
    const type = types[magic];
    if (!type) return null;

    return `data:${type};base64,` + buffer.toString("base64");
  },
  timestampFromSnowflake(id) {
    return id ? (+id / 4194304) + 1420070400000 : 0;
  },
  convertMentions(mentions) {
    if (!mentions) return mentions;
    if (mentions.map) return mentions.map(m => m.valueOf());
    return [mentions.valueOf()];
  }
};
<commit_msg>Optimize and rework internal event handling<commit_after>"use strict";
module.exports = {
  createArrayBuffer(source) {
    const view = new Uint8Array(new ArrayBuffer(source.length));
    for (let i = 0; i < view.length; i++)
      view[i] = source[i];
    return view.buffer;
  },
  createBuffer(source) {
    if (source instanceof Float32Array) {
      const buf = new Buffer(source.length * 4);
      for (let i = 0; i < source.length; i++) {
        buf.writeFloatLE(source[i], i * 4);
      }
      return buf;
    }

    const view = new Uint8Array(source);
    const buf = new Buffer(view.length);
    for (let i = 0; i < view.length; i++)
      buf[i] = view[i];
    return buf;
  },
  bindGatewayEventHandlers(source, event, map) {
    if (!event.type)
      throw new Error("Invalid event ${event.type}");

    let handler = map[event.type];
    if (!handler) return;

    if (typeof handler !== "function")
      throw new Error(`Invalid handler ${handler} for event ${event.type}`);

    handler = handler.bind(source);

    if (handler(event.data, event))
      event.handled = true;
  },
  privatify(target) {
    for (var k in target) {
      if (k[0] != "_")
        continue;
      Object.defineProperty(target, k, {enumerable: false});
    }
  },
  reorderObjects(array, target, position) {
    array = array.slice();
    array.sort((a, b) => (a.position > b.position));
    const from = Math.max(array.findIndex(c => (c.id == target.id)), 0);
    const to = Math.min(Math.max(position, 0), array.length - 1);

    if (from == to) return;

    const remove = (i) => array.splice(i, 1)[0];
    const insert = (i, v) => array.splice(i, 0, v);

    insert(to, remove(from));

    const updated = array.map((c, i) => ({id: c.valueOf(), position: i}));
    const changes = to > from ?
      updated.slice(from, to + 1) :
      updated.slice(to, from + 1);

    return changes;
  },
  imageToDataURL(buffer) {
    if (!buffer || !(buffer instanceof Buffer)) return null;

    const types = {
      0xFFD8FF: "image/jpg",
      0x89504E: "image/png"
    };

    const magic = buffer.readUIntBE(0, 3);
    const type = types[magic];
    if (!type) return null;

    return `data:${type};base64,` + buffer.toString("base64");
  },
  timestampFromSnowflake(id) {
    return id ? (+id / 4194304) + 1420070400000 : 0;
  },
  convertMentions(mentions) {
    if (!mentions) return mentions;
    if (mentions.map) return mentions.map(m => m.valueOf());
    return [mentions.valueOf()];
  }
};
<|endoftext|>


<commit_before>/**
 * Configures and starts a Keystone app in encapsulated mode.
 *
 * Connects to the database, runs updates and listens for incoming requests.
 *
 * Events are fired during initialisation to allow customisation, including:
 *
 *   - onMount
 *   - onStart
 *   - onHttpServerCreated
 *   - onHttpsServerCreated
 *
 * If the events argument is a function, it is assumed to be the started event.
 *
 *
 * ####Options:
 *
 * Keystone supports the following options specifically for running in encapsulated mode:
 *
 *   - name
 *   - port
 *   - views
 *   - view engine
 *   - compress
 *   - favico
 *   - less
 *   - static
 *   - headless
 *   - logger
 *   - cookie secret
 *   - session
 *   - 404
 *   - 500
 *   - routes
 *   - locals
 *   - auto update
 *   - ssl
 *   - sslport
 *   - sslkey
 *   - sslcert
 *
 *
 * @api public
 */

var fs = require('fs'),
    debug = require('debug')('keystone:core:start');

var dashes = '\n------------------------------------------------\n';

function start(events) {

	// Validate arguments

	if ('function' === typeof events) {
		events = { onStart: events };
	}

	if (!events) events = {};

	// Ensure Keystone has been initialised

	if (!this.app) {
		throw new Error('KeystoneJS Initialisaton Error:\n\napp must be initialised. Call keystone.init() or keystone.connect(new Express()) first.\n\n');
	}

	// Localise references to this for closures

	var keystone = this,
		app = this.app;

	// Maintain passed in onMount binding but override to start http servers
	// (call user-defined onMount first if present)

	var onMount = events.onMount;

	events.onMount = function() {

		onMount && onMount();

		var startupMessages = ['KeystoneJS Started:'],
			waitForServers = 2;

		// Log the startup messages and calls the onStart method

		var serverStarted = function() {
			waitForServers--;
			if (waitForServers) return;
			if (keystone.get('logger')) {
				console.log(dashes + startupMessages.join('\n') + dashes);
			}
			debug('server starting');
			events.onStart && events.onStart();
		};

		// Create the http server and listens to the specified port with default port specified

		var host = keystone.get('host'),
			port = keystone.get('port'),
			listen = keystone.get('listen'),
			ssl = keystone.get('ssl');

		if (ssl !== 'only') {
			var httpReadyMsg = keystone.get('name') + ' is ready on ';

			if (host) {
				httpReadyMsg += 'http://' + host;
				if (port) {
					httpReadyMsg += ':' + port;
				} else {
					httpReadyMsg += ':3000';
				}
			} else if (port){
				httpReadyMsg += 'port ' + port;
			} else {
				httpReadyMsg += 'port 3000';
			}

			var httpStarted = function(msg) {
				return function() {
					startupMessages.push(msg);
					serverStarted();
				};
			};

			keystone.httpServer = app.listen(port || 3000, httpStarted(httpReadyMsg));
			events.onHttpServerCreated && events.onHttpServerCreated();
		} else {
			waitForServers--;
		}

		if (ssl) {

			debug('start the ssl server');
			var sslOpts = {};

			if (keystone.get('ssl cert') && fs.existsSync(keystone.getPath('ssl cert'))) {
				sslOpts.cert = fs.readFileSync(keystone.getPath('ssl cert'));
			}
			if (keystone.get('ssl key') && fs.existsSync(keystone.getPath('ssl key'))) {
				sslOpts.key = fs.readFileSync(keystone.getPath('ssl key'));
			}
			if (keystone.get('ssl ca') && fs.existsSync(keystone.getPath('ssl ca'))) {
				sslOpts.ca = fs.readFileSync(keystone.getPath('ssl ca'));
			}

			if (!sslOpts.key || !sslOpts.cert) {

				if (ssl === 'only') {
					console.log(keystone.get('name') + ' failed to start: invalid ssl configuration');
					process.exit();
				} else {
					startupMessages.push('Warning: Invalid SSL Configuration');
					serverStarted();
				}

			} else {

				var httpsStarted = function(msg) {
					return function() {
						startupMessages.push(msg);
						serverStarted();
					};
				};

				keystone.httpsServer = https.createServer(sslOpts, app);
				events.onHttpsServerCreated && events.onHttpsServerCreated();

				var sslHost = keystone.get('ssl host') || host,
					sslPort = keystone.get('ssl port') || 3001;

				var httpsReadyMsg = (ssl === 'only') ? keystone.get('name') + ' (SSL) is ready on ' : 'SSL Server is ready on ';

				if (sslHost) {
					keystone.httpsServer.listen(sslPort, sslHost, httpsStarted(httpsReadyMsg + 'https://' + sslHost + ':' + sslPort));
				} else {
					var httpsPortMsg = (keystone.get('ssl port')) ? 'port: ' + keystone.get('ssl port') : 'default port 3001';
					keystone.httpsServer.listen(sslPort, httpsStarted(httpsReadyMsg + httpsPortMsg));
				}

			}

		} else {
			waitForServers--;
		}

		process.on('uncaughtException', function(e) {
			if (e.code === 'EADDRINUSE') {
				console.log(dashes +
					keystone.get('name') + ' failed to start: address already in use\n' +
					'Please check you are not already running a server on the specified port.\n');
				process.exit();
			}/* else if (e.code === 'ECONNRESET') {
				// Connection reset by peer, ignore it instead of exiting server with a throw.
				// Disabled for release 0.2.16 while further research is being done.
				console.log('Connection reset by peer');
				console.log(e);
			} */else {
				console.log(e.stack || e);
				process.exit(1);
			}
		});

	};

	debug('mount the express app');
	this.mount(events);

	return this;

}

module.exports = start;
<commit_msg>unix sockets<commit_after>/**
 * Configures and starts a Keystone app in encapsulated mode.
 *
 * Connects to the database, runs updates and listens for incoming requests.
 *
 * Events are fired during initialisation to allow customisation, including:
 *
 *   - onMount
 *   - onStart
 *   - onHttpServerCreated
 *   - onHttpsServerCreated
 *
 * If the events argument is a function, it is assumed to be the started event.
 *
 *
 * ####Options:
 *
 * Keystone supports the following options specifically for running in encapsulated mode:
 *
 *   - name
 *   - port
 *   - views
 *   - view engine
 *   - compress
 *   - favico
 *   - less
 *   - static
 *   - headless
 *   - logger
 *   - cookie secret
 *   - session
 *   - 404
 *   - 500
 *   - routes
 *   - locals
 *   - auto update
 *   - ssl
 *   - sslport
 *   - sslkey
 *   - sslcert
 *
 *
 * @api public
 */

var fs = require('fs'),
    debug = require('debug')('keystone:core:start');

var dashes = '\n------------------------------------------------\n';

function start(events) {

	// Validate arguments

	if ('function' === typeof events) {
		events = { onStart: events };
	}

	if (!events) events = {};

	// Ensure Keystone has been initialised

	if (!this.app) {
		throw new Error('KeystoneJS Initialisaton Error:\n\napp must be initialised. Call keystone.init() or keystone.connect(new Express()) first.\n\n');
	}

	// Localise references to this for closures

	var keystone = this,
		app = this.app;

	// Maintain passed in onMount binding but override to start http servers
	// (call user-defined onMount first if present)

	var onMount = events.onMount;

	events.onMount = function() {

		onMount && onMount();

		var startupMessages = ['KeystoneJS Started:'],
			waitForServers = 3;

		// Log the startup messages and calls the onStart method

		var serverStarted = function() {
			waitForServers--;
			if (waitForServers) return;
			if (keystone.get('logger')) {
				console.log(dashes + startupMessages.join('\n') + dashes);
			}
			debug('server starting');
			events.onStart && events.onStart();
		};

		// Create the http server and listens to the specified port with default port specified

		var host = keystone.get('host'),
			port = keystone.get('port'),
			listen = keystone.get('listen'),
			ssl = keystone.get('ssl'),
			unixSocket = keystone.get('unix socket');

		if (ssl !== 'only' && !unixSocket) {
			var httpReadyMsg = keystone.get('name') + ' is ready on ';

			if (host) {
				httpReadyMsg += 'http://' + host;
				if (port) {
					httpReadyMsg += ':' + port;
				} else {
					httpReadyMsg += ':3000';
				}
			} else if (port){
				httpReadyMsg += 'port ' + port;
			} else {
				httpReadyMsg += 'port 3000';
			}

			var httpStarted = function(msg) {
				return function() {
					startupMessages.push(msg);
					serverStarted();
				};
			};

			keystone.httpServer = app.listen(port || 3000, httpStarted(httpReadyMsg));
			events.onHttpServerCreated && events.onHttpServerCreated();
		} else {
			waitForServers--;
		}

		if (ssl && !unixSocket) {

			debug('start the ssl server');
			var sslOpts = {};

			if (keystone.get('ssl cert') && fs.existsSync(keystone.getPath('ssl cert'))) {
				sslOpts.cert = fs.readFileSync(keystone.getPath('ssl cert'));
			}
			if (keystone.get('ssl key') && fs.existsSync(keystone.getPath('ssl key'))) {
				sslOpts.key = fs.readFileSync(keystone.getPath('ssl key'));
			}
			if (keystone.get('ssl ca') && fs.existsSync(keystone.getPath('ssl ca'))) {
				sslOpts.ca = fs.readFileSync(keystone.getPath('ssl ca'));
			}

			if (!sslOpts.key || !sslOpts.cert) {

				if (ssl === 'only') {
					console.log(keystone.get('name') + ' failed to start: invalid ssl configuration');
					process.exit();
				} else {
					startupMessages.push('Warning: Invalid SSL Configuration');
					serverStarted();
				}

			} else {

				var httpsStarted = function(msg) {
					return function() {
						startupMessages.push(msg);
						serverStarted();
					};
				};

				keystone.httpsServer = https.createServer(sslOpts, app);
				events.onHttpsServerCreated && events.onHttpsServerCreated();

				var sslHost = keystone.get('ssl host') || host,
					sslPort = keystone.get('ssl port') || 3001;

				var httpsReadyMsg = (ssl === 'only') ? keystone.get('name') + ' (SSL) is ready on ' : 'SSL Server is ready on ';

				if (sslHost) {
					keystone.httpsServer.listen(sslPort, sslHost, httpsStarted(httpsReadyMsg + 'https://' + sslHost + ':' + sslPort));
				} else {
					var httpsPortMsg = (keystone.get('ssl port')) ? 'port: ' + keystone.get('ssl port') : 'default port 3001';
					keystone.httpsServer.listen(sslPort, httpsStarted(httpsReadyMsg + httpsPortMsg));
				}

			}

		} else {
			waitForServers--;
		}

		if(unixSocket) {
			var unixSocketStarted = function(msg) {
				return function() {
					startupMessages.push(msg);
					serverStarted();
				};
			};
			var httpReadyMsg = keystone.get('name') + ' is ready on ' + unixSocket;
			fs.unlink(unixSocket, function(err) {
				keystone.httpServer = app.listen(unixSocket, unixSocketStarted(httpReadyMsg));
				events.onSocketServerCreated && events.onSocketServerCreated();
				fs.chmod(unixSocket,0x777,function(){
					// set permissions
				});
			});

		} else {
			waitForServers--;
		}

		process.on('uncaughtException', function(e) {
			if (e.code === 'EADDRINUSE') {
				console.log(dashes +
					keystone.get('name') + ' failed to start: address already in use\n' +
					'Please check you are not already running a server on the specified port.\n');
				process.exit();
			}/* else if (e.code === 'ECONNRESET') {
				// Connection reset by peer, ignore it instead of exiting server with a throw.
				// Disabled for release 0.2.16 while further research is being done.
				console.log('Connection reset by peer');
				console.log(e);
			} */else {
				console.log(e.stack || e);
				process.exit(1);
			}
		});

	};

	debug('mount the express app');
	this.mount(events);

	return this;

}

module.exports = start;
<|endoftext|>


<commit_before>var _clone = require("lodash-node/modern/objects/clone"),
    _mapValues = require("lodash-node/modern/objects/mapValues"),
    _forOwn = require("lodash-node/modern/objects/forOwn"),
    _intersection = require("lodash-node/modern/arrays/intersection"),
    _keys = require("lodash-node/modern/objects/keys"),
    _map = require("lodash-node/modern/collections/map"),
    _each = require("lodash-node/modern/collections/forEach"),
    _size = require("lodash-node/modern/collections/size"),
    _findKey = require("lodash-node/modern/objects/findKey"),
    _uniq = require("lodash-node/modern/arrays/uniq");

var Dispatcher = function(stores) {
  this.stores = stores;
  this.currentDispatch = null;
  this.waitingToDispatch = [];

  for (var key in stores) {
    if (stores.hasOwnProperty(key)) {
      stores[key].dispatcher = this;
    }
  }
};

Dispatcher.prototype.dispatch = function(action) {
  if (this.currentDispatch) {
    throw new Error("Cannot dispatch an action while another action is being dispatched");
  }

  this.waitingToDispatch = _clone(this.stores);

  this.currentDispatch = _mapValues(this.stores, function() {
    return { resolved: false, waitingOn: [], waitCallback: null };
  });

  try {
    this.doDispatchLoop(action);
  } finally {
    this.currentDispatch = null;
  }
};

Dispatcher.prototype.doDispatchLoop = function(action) {
  var dispatch, canBeDispatchedTo,
      removeFromDispatchQueue = [], dispatchedThisLoop = [];

  _forOwn(this.waitingToDispatch, function(value, key) {
    dispatch = this.currentDispatch[key];
    canBeDispatchedTo = !dispatch.waitingOn.length ||
      !_intersection(dispatch.waitingOn, _keys(this.waitingToDispatch)).length;
    if (canBeDispatchedTo) {
      if (dispatch.waitCallback) {
        var stores = _map(dispatch.waitingOn, function(key) {
          return this.stores[key];
        }, this);
        var fn = dispatch.waitCallback;
        dispatch.waitCallback = null;
        dispatch.waitingOn = [];
        dispatch.resolved = true;
        fn.apply(null, stores);
      } else {
        dispatch.resolved = true;
        this.stores[key].__handleAction__(action);
      }

      dispatchedThisLoop.push(key);

      if (this.currentDispatch[key].resolved) {
        removeFromDispatchQueue.push(key);
      }
    }
  }, this);

  if (!dispatchedThisLoop.length) {
    var storesWithCircularWaits = _keys(this.waitingToDispatch).join(", ");
    throw new Error("Indirect circular wait detected among: " + storesWithCircularWaits);
  }

  _each(removeFromDispatchQueue, function(key) {
    delete this.waitingToDispatch[key];
  }, this);

  if (_size(this.waitingToDispatch)) {
    this.doDispatchLoop(action);
  }
};

Dispatcher.prototype.waitForStores = function(store, stores, fn) {
  if (!this.currentDispatch) {
    throw new Error("Cannot wait unless an action is being dispatched");
  }

  var waitingStoreName = _findKey(this.stores, function(val) {
    return val === store;
  });

  if (stores.indexOf(waitingStoreName) > -1) {
    throw new Error("A store cannot wait on itself");
  }

  var dispatch = this.currentDispatch[waitingStoreName];

  if (dispatch.waitingOn.length) {
    throw new Error(waitingStoreName + " already waiting on stores");
  }

  _each(stores, function(storeName) {
    var storeDispatch = this.currentDispatch[storeName];
    if (!this.stores[storeName]) {
      throw new Error("Cannot wait for non-existant store " + storeName);
    }
    if (storeDispatch.waitingOn.indexOf(waitingStoreName) > -1) {
      throw new Error("Circular wait detected between " + waitingStoreName + " and " + storeName);
    }
  }, this);

  dispatch.resolved = false;
  dispatch.waitingOn = _uniq(dispatch.waitingOn.concat(stores));
  dispatch.waitCallback = fn;
};

module.exports = Dispatcher;
<commit_msg>Add null or undefined check when dispatching an action<commit_after>var _clone = require("lodash-node/modern/objects/clone"),
    _mapValues = require("lodash-node/modern/objects/mapValues"),
    _forOwn = require("lodash-node/modern/objects/forOwn"),
    _intersection = require("lodash-node/modern/arrays/intersection"),
    _keys = require("lodash-node/modern/objects/keys"),
    _map = require("lodash-node/modern/collections/map"),
    _each = require("lodash-node/modern/collections/forEach"),
    _size = require("lodash-node/modern/collections/size"),
    _findKey = require("lodash-node/modern/objects/findKey"),
    _uniq = require("lodash-node/modern/arrays/uniq");

var Dispatcher = function(stores) {
  this.stores = stores;
  this.currentDispatch = null;
  this.waitingToDispatch = [];

  for (var key in stores) {
    if (stores.hasOwnProperty(key)) {
      stores[key].dispatcher = this;
    }
  }
};

Dispatcher.prototype.dispatch = function(action) {
  if (action === undefined || action === null) {  //check for null or undefined action
    throw new Error("Dispatched action is null or undefined");
  }

  if (this.currentDispatch) {
    throw new Error("Cannot dispatch an action while another action is being dispatched");
  }

  this.waitingToDispatch = _clone(this.stores);

  this.currentDispatch = _mapValues(this.stores, function() {
    return { resolved: false, waitingOn: [], waitCallback: null };
  });

  try {
    this.doDispatchLoop(action);
  } finally {
    this.currentDispatch = null;
  }
};

Dispatcher.prototype.doDispatchLoop = function(action) {
  var dispatch, canBeDispatchedTo,
      removeFromDispatchQueue = [], dispatchedThisLoop = [];

  _forOwn(this.waitingToDispatch, function(value, key) {
    dispatch = this.currentDispatch[key];
    canBeDispatchedTo = !dispatch.waitingOn.length ||
      !_intersection(dispatch.waitingOn, _keys(this.waitingToDispatch)).length;
    if (canBeDispatchedTo) {
      if (dispatch.waitCallback) {
        var stores = _map(dispatch.waitingOn, function(key) {
          return this.stores[key];
        }, this);
        var fn = dispatch.waitCallback;
        dispatch.waitCallback = null;
        dispatch.waitingOn = [];
        dispatch.resolved = true;
        fn.apply(null, stores);
      } else {
        dispatch.resolved = true;
        this.stores[key].__handleAction__(action);
      }

      dispatchedThisLoop.push(key);

      if (this.currentDispatch[key].resolved) {
        removeFromDispatchQueue.push(key);
      }
    }
  }, this);

  if (!dispatchedThisLoop.length) {
    var storesWithCircularWaits = _keys(this.waitingToDispatch).join(", ");
    throw new Error("Indirect circular wait detected among: " + storesWithCircularWaits);
  }

  _each(removeFromDispatchQueue, function(key) {
    delete this.waitingToDispatch[key];
  }, this);

  if (_size(this.waitingToDispatch)) {
    this.doDispatchLoop(action);
  }
};

Dispatcher.prototype.waitForStores = function(store, stores, fn) {
  if (!this.currentDispatch) {
    throw new Error("Cannot wait unless an action is being dispatched");
  }

  var waitingStoreName = _findKey(this.stores, function(val) {
    return val === store;
  });

  if (stores.indexOf(waitingStoreName) > -1) {
    throw new Error("A store cannot wait on itself");
  }

  var dispatch = this.currentDispatch[waitingStoreName];

  if (dispatch.waitingOn.length) {
    throw new Error(waitingStoreName + " already waiting on stores");
  }

  _each(stores, function(storeName) {
    var storeDispatch = this.currentDispatch[storeName];
    if (!this.stores[storeName]) {
      throw new Error("Cannot wait for non-existant store " + storeName);
    }
    if (storeDispatch.waitingOn.indexOf(waitingStoreName) > -1) {
      throw new Error("Circular wait detected between " + waitingStoreName + " and " + storeName);
    }
  }, this);

  dispatch.resolved = false;
  dispatch.waitingOn = _uniq(dispatch.waitingOn.concat(stores));
  dispatch.waitCallback = fn;
};

module.exports = Dispatcher;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 by Greg Reimer <gregreimer@gmail.com>
 * MIT License. See mit-license.txt for more info.
 */

var chunker = require('./chunker');
var cheerio = require('cheerio');
var util = require('util');
var Readable = require('stream').Readable;
var isTypeXml = require('./is-xml');

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

// TODO: test
function DomReader($, contentType){
  Readable.call(this, {});
  this._contentType = contentType;
  this._$ = $;
  this._i = 0;
  this._keepGoing = true;
}

util.inherits(DomReader, Readable);

DomReader.prototype.stringable = true;

DomReader.prototype.toString = function(){
  var isXml = isTypeXml(this._contentType);
  var doctype = getDoctypeFromCheerio(this._$);
  var isXhtml = isDoctypeXhtml(doctype);
  if (isXml || isXhtml){
    return this._$.xml();
  } else {
    return this._$.html();
  }
};

DomReader.prototype.finalize = function(){
  var body = this.toString();
  this._buffers = chunker.stringToChunks(body, 'utf8');
};

DomReader.prototype.setString = function(str, mimeType){
  var isXml = isTypeXml(contentType);
  this._$ = cheerio.load(str, {xmlMode:isXml});
};

DomReader.prototype._read = function(){
  if (this._i < this._buffers.length){
    if (this._keepGoing){
      this._keepGoing = this.push(this._buffers[this._i++]);
    } else {
      this._keepGoing = true;
    }
  } else {
    this.push(null);
  }
};

DomReader.prototype.size = function(){
  return this._buffers.reduce(function(tally, buffer){
    return tally + buffer.length;
  },0);
};

module.exports = DomReader;

function getDoctypeFromCheerio($){
  var doctype;
  $.root().contents().each(function(){
    var el = this;
    if (el && (el.name||'').toLowerCase() === '!doctype'){
      doctype = '<'+el.data+'>';
    }
  })
  return doctype;
}

function isDoctypeXhtml(doctype){
  return (/xhtml/i).test(doctype);
}
<commit_msg>Stop using DOCTYPE to parse as XML.<commit_after>/*
 * Copyright (c) 2014 by Greg Reimer <gregreimer@gmail.com>
 * MIT License. See mit-license.txt for more info.
 */

var chunker = require('./chunker');
var cheerio = require('cheerio');
var util = require('util');
var Readable = require('stream').Readable;
var isTypeXml = require('./is-xml');

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

// TODO: test
function DomReader($, contentType){
  Readable.call(this, {});
  this._contentType = contentType;
  this._$ = $;
  this._i = 0;
  this._keepGoing = true;
}

util.inherits(DomReader, Readable);

DomReader.prototype.stringable = true;

DomReader.prototype.toString = function(){
  var isXml = isTypeXml(this._contentType);
  return this._$[isXml ? 'xml' : 'html']();
};

DomReader.prototype.finalize = function(){
  var body = this.toString();
  this._buffers = chunker.stringToChunks(body, 'utf8');
};

DomReader.prototype.setString = function(str, mimeType){
  var isXml = isTypeXml(contentType);
  this._$ = cheerio.load(str, {xmlMode:isXml});
};

DomReader.prototype._read = function(){
  if (this._i < this._buffers.length){
    if (this._keepGoing){
      this._keepGoing = this.push(this._buffers[this._i++]);
    } else {
      this._keepGoing = true;
    }
  } else {
    this.push(null);
  }
};

DomReader.prototype.size = function(){
  return this._buffers.reduce(function(tally, buffer){
    return tally + buffer.length;
  },0);
};

module.exports = DomReader;

function getDoctypeFromCheerio($){
  var doctype;
  $.root().contents().each(function(){
    var el = this;
    if (el && (el.name||'').toLowerCase() === '!doctype'){
      doctype = '<'+el.data+'>';
    }
  })
  return doctype;
}

function isDoctypeXhtml(doctype){
  return (/xhtml/i).test(doctype);
}
<|endoftext|>


<commit_before>var records = require('./exceptions.json');

function compareValue(data, ref) {
    return (ref === undefined) || (data === ref);
}

function findSet(shortname) {
    var count = 0;
    function _findSet(name) {
        if (count > 10)
           return undefined;
        var set = records[name];
        count++;
        if (typeof set === "String")
            return _findSet(set);
        return set;
    }
    return _findSet(shortname);
}

var Exceptions = function () {
};

Exceptions.prototype.has = function (shortname, rule, key, extra) {
    var set = findSet(shortname);
    if (set === undefined) return false;
    for (var i = set.length - 1; i >= 0; i--) {
        var exception = set[i];

        return (rule === exception.rule
                && compareValue(extra.type, exception.type));
    }
    return false;
};

exports.Exceptions = Exceptions;
<commit_msg>Added strict<commit_after>'use strict';

var records = require('./exceptions.json');

function compareValue(data, ref) {
    return (ref === undefined) || (data === ref);
}

function findSet(shortname) {
    var count = 0;
    function _findSet(name) {
        if (count > 10)
           return undefined;
        var set = records[name];
        count++;
        if (typeof set === "String")
            return _findSet(set);
        return set;
    }
    return _findSet(shortname);
}

var Exceptions = function () {
};

Exceptions.prototype.has = function (shortname, rule, key, extra) {
    var set = findSet(shortname);
    if (set === undefined) return false;
    for (var i = set.length - 1; i >= 0; i--) {
        var exception = set[i];

        return (rule === exception.rule
                && compareValue(extra.type, exception.type));
    }
    return false;
};

exports.Exceptions = Exceptions;
<|endoftext|>


<commit_before>var bits = require('bit-twiddle')

function fft(dir, nrows, ncols, buffer, x_ptr, y_ptr, scratch_ptr) {
  dir |= 0
  nrows |= 0
  ncols |= 0
  x_ptr |= 0
  y_ptr |= 0
  if(bits.isPow2(ncols)) {
    fftRadix2(dir, nrows, ncols, buffer, x_ptr, y_ptr)
  } else {
    fftBluestein(dir, nrows, ncols, buffer, x_ptr, y_ptr, scratch_ptr)
  }
}
module.exports = fft

function scratchMemory(n) {
  if(bits.isPow2(n)) {
    return 0
  }
  return 2 * n + 4 * bits.nextPow2(2*n + 1)
}
module.exports.scratchMemory = scratchMemory

//Radix 2 FFT Adapted from Paul Bourke's C Implementation
function fftRadix2(dir, nrows, ncols, buffer, x_ptr, y_ptr) {
  dir |= 0
  nrows |= 0
  ncols |= 0
  x_ptr |= 0
  y_ptr |= 0
  var nn,i,i1,j,k,i2,l,l1,l2
  var c1,c2,t,t1,t2,u1,u2,z,row,a,b,c,d,k1,k2,k3

  // Calculate the number of points
  nn = ncols
  m = bits.log2(nn)

  for(row=0; row<nrows; ++row) {
    // Do the bit reversal
    i2 = nn >> 1;
    j = 0;
    for(i=0;i<nn-1;i++) {
      if(i < j) {
        t = buffer[x_ptr+i]
        buffer[x_ptr+i] = buffer[x_ptr+j]
        buffer[x_ptr+j] = t
        t = buffer[y_ptr+i]
        buffer[y_ptr+i] = buffer[y_ptr+j]
        buffer[y_ptr+j] = t
      }
      k = i2
      while(k <= j) {
        j -= k
        k >>= 1
      }
      j += k
    }

    // Compute the FFT
    c1 = -1.0
    c2 = 0.0
    l2 = 1
    for(l=0;l<m;l++) {
      l1 = l2
      l2 <<= 1
      u1 = 1.0
      u2 = 0.0
      for(j=0;j<l1;j++) {
        for(i=j;i<nn;i+=l2) {
          i1 = i + l1
          a = buffer[x_ptr+i1]
          b = buffer[y_ptr+i1]
          c = buffer[x_ptr+i]
          d = buffer[y_ptr+i]
          k1 = u1 * (a + b)
          k2 = a * (u2 - u1)
          k3 = b * (u1 + u2)
          t1 = k1 - k3
          t2 = k1 + k2
          buffer[x_ptr+i1] = c - t1
          buffer[y_ptr+i1] = d - t2
          buffer[x_ptr+i] += t1
          buffer[y_ptr+i] += t2
        }
        k1 = c1 * (u1 + u2)
        k2 = u1 * (c2 - c1)
        k3 = u2 * (c1 + c2)
        u1 = k1 - k3
        u2 = k1 + k2
      }
      c2 = Math.sqrt((1.0 - c1) / 2.0)
      if(dir < 0) {
        c2 = -c2
      }
      c1 = Math.sqrt((1.0 + c1) / 2.0)
    }

    // Scaling for inverse transform
    if(dir < 0) {
      var scale_f = 1.0 / nn
      for(i=0;i<nn;i++) {
        buffer[x_ptr+i] *= scale_f
        buffer[y_ptr+i] *= scale_f
      }
    }

    // Advance pointers
    x_ptr += ncols
    y_ptr += ncols
  }
}

// Use Bluestein algorithm for npot FFTs
// Scratch memory required:  2 * ncols + 4 * bits.nextPow2(2*ncols + 1)
function fftBluestein(dir, nrows, ncols, buffer, x_ptr, y_ptr, scratch_ptr) {
  dir |= 0
  nrows |= 0
  ncols |= 0
  x_ptr |= 0
  y_ptr |= 0
  scratch_ptr |= 0

  // Initialize tables
  var m = bits.nextPow2(2 * ncols + 1)
    , cos_ptr = scratch_ptr
    , sin_ptr = cos_ptr + ncols
    , xs_ptr  = sin_ptr + ncols
    , ys_ptr  = xs_ptr  + m
    , cft_ptr = ys_ptr  + m
    , sft_ptr = cft_ptr + m
    , w = -dir * Math.PI / ncols
    , row, a, b, c, d, k1, k2, k3
    , i
  for(i=0; i<ncols; ++i) {
    a = w * ((i * i) % (ncols * 2))
    c = Math.cos(a)
    d = Math.sin(a)
    buffer[cft_ptr+(m-i)] = buffer[cft_ptr+i] = buffer[cos_ptr+i] = c
    buffer[sft_ptr+(m-i)] = buffer[sft_ptr+i] = buffer[sin_ptr+i] = d
  }
  for(i=ncols; i<=m-ncols; ++i) {
    buffer[cft_ptr+i] = 0.0
  }
  for(i=ncols; i<=m-ncols; ++i) {
    buffer[sft_ptr+i] = 0.0
  }

  fftRadix2(1, 1, m, buffer, cft_ptr, sft_ptr)

  //Compute scale factor
  if(dir < 0) {
    w = 1.0 / ncols
  } else {
    w = 1.0
  }

  //Handle direction
  for(row=0; row<nrows; ++row) {

    // Copy row into scratch memory, multiply weights
    for(i=0; i<ncols; ++i) {
      a = buffer[x_ptr+i]
      b = buffer[y_ptr+i]
      c = buffer[cos_ptr+i]
      d = -buffer[sin_ptr+i]
      k1 = c * (a + b)
      k2 = a * (d - c)
      k3 = b * (c + d)
      buffer[xs_ptr+i] = k1 - k3
      buffer[ys_ptr+i] = k1 + k2
    }
    //Zero out the rest
    for(i=ncols; i<m; ++i) {
      buffer[xs_ptr+i] = 0.0
    }
    for(i=ncols; i<m; ++i) {
      buffer[ys_ptr+i] = 0.0
    }

    // FFT buffer
    fftRadix2(1, 1, m, buffer, xs_ptr, ys_ptr)

    // Apply multiplier
    for(i=0; i<m; ++i) {
      a = buffer[xs_ptr+i]
      b = buffer[ys_ptr+i]
      c = buffer[cft_ptr+i]
      d = buffer[sft_ptr+i]
      k1 = c * (a + b)
      k2 = a * (d - c)
      k3 = b * (c + d)
      buffer[xs_ptr+i] = k1 - k3
      buffer[ys_ptr+i] = k1 + k2
    }

    // Inverse FFT buffer
    fftRadix2(-1, 1, m, buffer, xs_ptr, ys_ptr)

    // Copy result back into x/y
    for(i=0; i<ncols; ++i) {
      a = buffer[xs_ptr+i]
      b = buffer[ys_ptr+i]
      c = buffer[cos_ptr+i]
      d = -buffer[sin_ptr+i]
      k1 = c * (a + b)
      k2 = a * (d - c)
      k3 = b * (c + d)
      buffer[x_ptr+i] = w * (k1 - k3)
      buffer[y_ptr+i] = w * (k1 + k2)
    }

    x_ptr += ncols
    y_ptr += ncols
  }
}
<commit_msg>Missing variable declaration for "m"<commit_after>var bits = require('bit-twiddle')

function fft(dir, nrows, ncols, buffer, x_ptr, y_ptr, scratch_ptr) {
  dir |= 0
  nrows |= 0
  ncols |= 0
  x_ptr |= 0
  y_ptr |= 0
  if(bits.isPow2(ncols)) {
    fftRadix2(dir, nrows, ncols, buffer, x_ptr, y_ptr)
  } else {
    fftBluestein(dir, nrows, ncols, buffer, x_ptr, y_ptr, scratch_ptr)
  }
}
module.exports = fft

function scratchMemory(n) {
  if(bits.isPow2(n)) {
    return 0
  }
  return 2 * n + 4 * bits.nextPow2(2*n + 1)
}
module.exports.scratchMemory = scratchMemory

//Radix 2 FFT Adapted from Paul Bourke's C Implementation
function fftRadix2(dir, nrows, ncols, buffer, x_ptr, y_ptr) {
  dir |= 0
  nrows |= 0
  ncols |= 0
  x_ptr |= 0
  y_ptr |= 0
  var nn,m,i,i1,j,k,i2,l,l1,l2
  var c1,c2,t,t1,t2,u1,u2,z,row,a,b,c,d,k1,k2,k3

  // Calculate the number of points
  nn = ncols
  m = bits.log2(nn)

  for(row=0; row<nrows; ++row) {
    // Do the bit reversal
    i2 = nn >> 1;
    j = 0;
    for(i=0;i<nn-1;i++) {
      if(i < j) {
        t = buffer[x_ptr+i]
        buffer[x_ptr+i] = buffer[x_ptr+j]
        buffer[x_ptr+j] = t
        t = buffer[y_ptr+i]
        buffer[y_ptr+i] = buffer[y_ptr+j]
        buffer[y_ptr+j] = t
      }
      k = i2
      while(k <= j) {
        j -= k
        k >>= 1
      }
      j += k
    }

    // Compute the FFT
    c1 = -1.0
    c2 = 0.0
    l2 = 1
    for(l=0;l<m;l++) {
      l1 = l2
      l2 <<= 1
      u1 = 1.0
      u2 = 0.0
      for(j=0;j<l1;j++) {
        for(i=j;i<nn;i+=l2) {
          i1 = i + l1
          a = buffer[x_ptr+i1]
          b = buffer[y_ptr+i1]
          c = buffer[x_ptr+i]
          d = buffer[y_ptr+i]
          k1 = u1 * (a + b)
          k2 = a * (u2 - u1)
          k3 = b * (u1 + u2)
          t1 = k1 - k3
          t2 = k1 + k2
          buffer[x_ptr+i1] = c - t1
          buffer[y_ptr+i1] = d - t2
          buffer[x_ptr+i] += t1
          buffer[y_ptr+i] += t2
        }
        k1 = c1 * (u1 + u2)
        k2 = u1 * (c2 - c1)
        k3 = u2 * (c1 + c2)
        u1 = k1 - k3
        u2 = k1 + k2
      }
      c2 = Math.sqrt((1.0 - c1) / 2.0)
      if(dir < 0) {
        c2 = -c2
      }
      c1 = Math.sqrt((1.0 + c1) / 2.0)
    }

    // Scaling for inverse transform
    if(dir < 0) {
      var scale_f = 1.0 / nn
      for(i=0;i<nn;i++) {
        buffer[x_ptr+i] *= scale_f
        buffer[y_ptr+i] *= scale_f
      }
    }

    // Advance pointers
    x_ptr += ncols
    y_ptr += ncols
  }
}

// Use Bluestein algorithm for npot FFTs
// Scratch memory required:  2 * ncols + 4 * bits.nextPow2(2*ncols + 1)
function fftBluestein(dir, nrows, ncols, buffer, x_ptr, y_ptr, scratch_ptr) {
  dir |= 0
  nrows |= 0
  ncols |= 0
  x_ptr |= 0
  y_ptr |= 0
  scratch_ptr |= 0

  // Initialize tables
  var m = bits.nextPow2(2 * ncols + 1)
    , cos_ptr = scratch_ptr
    , sin_ptr = cos_ptr + ncols
    , xs_ptr  = sin_ptr + ncols
    , ys_ptr  = xs_ptr  + m
    , cft_ptr = ys_ptr  + m
    , sft_ptr = cft_ptr + m
    , w = -dir * Math.PI / ncols
    , row, a, b, c, d, k1, k2, k3
    , i
  for(i=0; i<ncols; ++i) {
    a = w * ((i * i) % (ncols * 2))
    c = Math.cos(a)
    d = Math.sin(a)
    buffer[cft_ptr+(m-i)] = buffer[cft_ptr+i] = buffer[cos_ptr+i] = c
    buffer[sft_ptr+(m-i)] = buffer[sft_ptr+i] = buffer[sin_ptr+i] = d
  }
  for(i=ncols; i<=m-ncols; ++i) {
    buffer[cft_ptr+i] = 0.0
  }
  for(i=ncols; i<=m-ncols; ++i) {
    buffer[sft_ptr+i] = 0.0
  }

  fftRadix2(1, 1, m, buffer, cft_ptr, sft_ptr)

  //Compute scale factor
  if(dir < 0) {
    w = 1.0 / ncols
  } else {
    w = 1.0
  }

  //Handle direction
  for(row=0; row<nrows; ++row) {

    // Copy row into scratch memory, multiply weights
    for(i=0; i<ncols; ++i) {
      a = buffer[x_ptr+i]
      b = buffer[y_ptr+i]
      c = buffer[cos_ptr+i]
      d = -buffer[sin_ptr+i]
      k1 = c * (a + b)
      k2 = a * (d - c)
      k3 = b * (c + d)
      buffer[xs_ptr+i] = k1 - k3
      buffer[ys_ptr+i] = k1 + k2
    }
    //Zero out the rest
    for(i=ncols; i<m; ++i) {
      buffer[xs_ptr+i] = 0.0
    }
    for(i=ncols; i<m; ++i) {
      buffer[ys_ptr+i] = 0.0
    }

    // FFT buffer
    fftRadix2(1, 1, m, buffer, xs_ptr, ys_ptr)

    // Apply multiplier
    for(i=0; i<m; ++i) {
      a = buffer[xs_ptr+i]
      b = buffer[ys_ptr+i]
      c = buffer[cft_ptr+i]
      d = buffer[sft_ptr+i]
      k1 = c * (a + b)
      k2 = a * (d - c)
      k3 = b * (c + d)
      buffer[xs_ptr+i] = k1 - k3
      buffer[ys_ptr+i] = k1 + k2
    }

    // Inverse FFT buffer
    fftRadix2(-1, 1, m, buffer, xs_ptr, ys_ptr)

    // Copy result back into x/y
    for(i=0; i<ncols; ++i) {
      a = buffer[xs_ptr+i]
      b = buffer[ys_ptr+i]
      c = buffer[cos_ptr+i]
      d = -buffer[sin_ptr+i]
      k1 = c * (a + b)
      k2 = a * (d - c)
      k3 = b * (c + d)
      buffer[x_ptr+i] = w * (k1 - k3)
      buffer[y_ptr+i] = w * (k1 + k2)
    }

    x_ptr += ncols
    y_ptr += ncols
  }
}
<|endoftext|>


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

exports.number = number;
exports.word = word;
exports.character = character;
exports.upperCharacter = upperCharacter;
exports.lowerCharacter = lowerCharacter;
exports.structure = structure;
exports.list = list;
exports.object = object;

function number(minValue, maxValue) {
    minValue = funkit.isDefined(maxValue)? minValue: -maxValue;
    maxValue = maxValue || minValue || Number.MAX_VALUE;

    return funkit.partial(funkit.randint, minValue, maxValue);
}

function word(maxLen) {
    maxLen = maxLen || 100;

    return function() {
        var ret = '';

        for(var i = 0; i < maxLen; i++) ret += character();

        return ret;
    };
}

function character() {
    return String.fromCharCode(funkit.randint(33, 126));
}

function upperCharacter() {
    return String.fromCharCode(funkit.randint(65, 90));
}

function lowerCharacter() {
    return String.fromCharCode(funkit.randint(97, 122));
}

function structure() {
    function recursion(pick) {
        if(funkit.isObject(pick)) {
            pick[word(funkit.randint(1, 10))()] = recursion(_choose());
        }
        if(funkit.isArray(pick)) {
            pick.push(recursion(_choose()));
        }
        return pick;
    }

    function _choose() {
        return funkit.choose(getOpts());
    }

    function getOpts() {
        return [{}, [], character(), number()()];
    }

    return recursion(_choose());
}

function list(maxLen, gen) {
    return function() {
        var ret = [];

        funkit.range(funkit.randint(0, maxLen)).forEach(function() {
            ret.push(gen());
        });

        return ret;
    };
}

function object(maxLen, keyGen, valueGen) {
    return function() {
        var ret = {};

        funkit.range(funkit.randint(0, maxLen)).forEach(function() {
            ret[keyGen()] = valueGen();
        });

        return ret;
    };
}
<commit_msg>Remove redundant whitespace<commit_after>var funkit = require('funkit');

exports.number = number;
exports.word = word;
exports.character = character;
exports.upperCharacter = upperCharacter;
exports.lowerCharacter = lowerCharacter;
exports.structure = structure;
exports.list = list;
exports.object = object;

function number(minValue, maxValue) {
    minValue = funkit.isDefined(maxValue)? minValue: -maxValue;
    maxValue = maxValue || minValue || Number.MAX_VALUE;

    return funkit.partial(funkit.randint, minValue, maxValue);
}

function word(maxLen) {
    maxLen = maxLen || 100;

    return function() {
        var ret = '';

        for(var i = 0; i < maxLen; i++) ret += character();

        return ret;
    };
}

function character() {
    return String.fromCharCode(funkit.randint(33, 126));
}

function upperCharacter() {
    return String.fromCharCode(funkit.randint(65, 90));
}

function lowerCharacter() {
    return String.fromCharCode(funkit.randint(97, 122));
}

function structure() {
    function recursion(pick) {
        if(funkit.isObject(pick)) {
            pick[word(funkit.randint(1, 10))()] = recursion(_choose());
        }
        if(funkit.isArray(pick)) {
            pick.push(recursion(_choose()));
        }
        return pick;
    }

    function _choose() {
        return funkit.choose(getOpts());
    }

    function getOpts() {
        return [{}, [], character(), number()()];
    }

    return recursion(_choose());
}

function list(maxLen, gen) {
    return function() {
        var ret = [];

        funkit.range(funkit.randint(0, maxLen)).forEach(function() {
            ret.push(gen());
        });

        return ret;
    };
}

function object(maxLen, keyGen, valueGen) {
    return function() {
        var ret = {};

        funkit.range(funkit.randint(0, maxLen)).forEach(function() {
            ret[keyGen()] = valueGen();
        });

        return ret;
    };
}
<|endoftext|>


<commit_before>'use strict';

const figures = require('figures');
const table = require('text-table');
const chalk = require('chalk');
const {
	STATE_DOWNLOADING,
	STATE_BUILDING,
	STATE_CLEANING,
	STATE_RUNNING,
	STATE_SUCCESS,
	STATE_ERROR
} = require('./states');

module.exports = state => {
	const items = Object.keys(state).map(version => {
		let message;
		let icon;

		const currentState = state[version];

		if (currentState === STATE_DOWNLOADING) {
			message = chalk.grey('downloading base image');
			icon = chalk.grey(figures.circleDotted);
		}

		if (currentState === STATE_BUILDING) {
			message = chalk.grey('building environment');
			icon = chalk.grey(figures.circleDotted);
		}

		if (currentState === STATE_CLEANING) {
			message = chalk.grey('cleaning up');
			icon = chalk.grey(figures.circleDotted);
		}

		if (currentState === STATE_RUNNING) {
			message = chalk.grey('running');
			icon = chalk.grey(figures.circleDotted);
		}

		if (currentState === STATE_SUCCESS) {
			message = chalk.green('success');
			icon = chalk.green(figures.tick);
		}

		if (currentState === STATE_ERROR) {
			message = chalk.red('error');
			icon = chalk.red(figures.cross);
		}

		return [' ', icon, `${version}:`, message];
	});

	return '\n' + table(items, {align: ['l', 'l', 'r', 'l']});
};
<commit_msg>reindent output for consistency<commit_after>'use strict';

const indentString = require('indent-string');
const figures = require('figures');
const table = require('text-table');
const chalk = require('chalk');
const {
	STATE_DOWNLOADING,
	STATE_BUILDING,
	STATE_CLEANING,
	STATE_RUNNING,
	STATE_SUCCESS,
	STATE_ERROR
} = require('./states');

module.exports = state => {
	const items = Object.keys(state).map(version => {
		let message;
		let icon;

		const currentState = state[version];

		if (currentState === STATE_DOWNLOADING) {
			message = chalk.grey('downloading base image');
			icon = chalk.grey(figures.circleDotted);
		}

		if (currentState === STATE_BUILDING) {
			message = chalk.grey('building environment');
			icon = chalk.grey(figures.circleDotted);
		}

		if (currentState === STATE_CLEANING) {
			message = chalk.grey('cleaning up');
			icon = chalk.grey(figures.circleDotted);
		}

		if (currentState === STATE_RUNNING) {
			message = chalk.grey('running');
			icon = chalk.grey(figures.circleDotted);
		}

		if (currentState === STATE_SUCCESS) {
			message = chalk.green('success');
			icon = chalk.green(figures.tick);
		}

		if (currentState === STATE_ERROR) {
			message = chalk.red('error');
			icon = chalk.red(figures.cross);
		}

		return [icon, ` ${version}: `, message];
	});

	return '\n' + indentString(table(items, {hsep: ''}), 1);
};
<|endoftext|>


<commit_before>/**
 * Handles requests to obtain a grant in the form of a cross domain
 * authorization code.
 *
 * References:
 *  - [Authorization Cross Domain Code 1.0](https://openid.bitbucket.io/draft-acdc-01.html)
 *  - [CIS 2015 Extreme OpenID Connect](https://www.slideshare.net/CloudIDSummit/cis-2015-extreme-open-id-connect-john-bradley)
 *
 * @param {Object} options
 * @param {Function} issue
 * @return {Object} module
 * @api public
 */
module.exports = function(options, issue) {
  if (typeof options == 'function') {
    issue = options;
    options = undefined;
  }
  options = options || {};

  if (!issue) { throw new TypeError('oauth2orize.acdc grant requires an issue callback'); }

  var modes = options.modes || {};
  if (!modes.query) {
    modes.query = require('../modes/query');
  }

  // NOTE: combine with `oauth2orize-pkce` and `oauth2orize-audience`
  function request(req) {
    // TODO: Error if PKCE not present
    // TODO: Error if audience not present.
  }

  function response(txn, res, complete, next) {
    var mode = 'query'
      , respond;
    if (txn.req && txn.req.responseMode) {
      mode = txn.req.responseMode;
    }
    respond = modes[mode];

    if (!respond) {
      // http://lists.openid.net/pipermail/openid-specs-ab/Week-of-Mon-20140317/004680.html
      return next(new AuthorizationError('Unsupported response mode: ' + mode, 'unsupported_response_mode', null, 501));
    }
    if (respond && respond.validate) {
      try {
        respond.validate(txn);
      } catch(ex) {
        return next(ex);
      }
    }

    if (!txn.res.allow) {
      var params = { error: 'access_denied' };
      if (txn.req && txn.req.state) { params.state = txn.req.state; }
      return respond(txn, res, params);
    }

    function issued(err, crossDomainCode) {
      if (err) { return next(err); }
      if (!crossDomainCode) { return next(new AuthorizationError('Request denied by authorization server', 'access_denied')); }

      // NOTE: The draft specification is not explicit about the parameter name
      //       used to convey the cross domain code in the authorization
      //       response, and is lacking non-normative examples.
      //
      //       During development of this module, an extensive search was
      //       conducted to find existing implementations in order to determine
      //       what parameter is used in practice; however, no implementations
      //       were found.  In the absence of explicit guidance, this
      //       implementation chooses to follow convention established by the
      //       normal authorization code response type in OAuth 2.0, and uses
      //       a parameter named `code` to convey the cross domain code.
      var params = { code: crossDomainCode };
      if (txn.req && txn.req.state) { params.state = txn.req.state; }
      complete(function(err) {
        if (err) { return next(err); }
        return respond(txn, res, params);
      });
    }

    var pkce = {
      challenge: txn.req.codeChallenge,
      method: txn.req.codeChallengeMethod
    }

    try {
      var arity = issue.length;
      if (arity == 8) {
        issue(txn.client, txn.user, txn.req.audience, pkce, txn.res, txn.req, txn.locals, issued);
      } else if (arity == 7) {
        issue(txn.client, txn.user, txn.req.audience, pkce, txn.res, txn.req, issued);
      } else if (arity == 6) {
        issue(txn.client, txn.user, txn.req.audience, pkce, txn.res, issued);
      } else { // arity == 5
        issue(txn.client, txn.user, txn.req.audience, pkce, issued);
      }
    } catch (ex) {
      return next(ex);
    }
  }

  /**
   * Return `acdc` grant module.
   */
  var mod = {};
  mod.name = 'acdc';
  mod.request = request;
  mod.response = response;
  return mod;
}
<commit_msg>Add errorHandler to grant.<commit_after>/**
 * Handles requests to obtain a grant in the form of a cross domain
 * authorization code.
 *
 * References:
 *  - [Authorization Cross Domain Code 1.0](https://openid.bitbucket.io/draft-acdc-01.html)
 *  - [CIS 2015 Extreme OpenID Connect](https://www.slideshare.net/CloudIDSummit/cis-2015-extreme-open-id-connect-john-bradley)
 *
 * @param {Object} options
 * @param {Function} issue
 * @return {Object} module
 * @api public
 */
module.exports = function(options, issue) {
  if (typeof options == 'function') {
    issue = options;
    options = undefined;
  }
  options = options || {};

  if (!issue) { throw new TypeError('oauth2orize.acdc grant requires an issue callback'); }

  var modes = options.modes || {};
  if (!modes.query) {
    modes.query = require('../modes/query');
  }

  // NOTE: combine with `oauth2orize-pkce` and `oauth2orize-audience`
  function request(req) {
    // TODO: Error if PKCE not present
    // TODO: Error if audience not present.
  }

  function response(txn, res, complete, next) {
    var mode = 'query'
      , respond;
    if (txn.req && txn.req.responseMode) {
      mode = txn.req.responseMode;
    }
    respond = modes[mode];

    if (!respond) {
      // http://lists.openid.net/pipermail/openid-specs-ab/Week-of-Mon-20140317/004680.html
      return next(new AuthorizationError('Unsupported response mode: ' + mode, 'unsupported_response_mode', null, 501));
    }
    if (respond && respond.validate) {
      try {
        respond.validate(txn);
      } catch(ex) {
        return next(ex);
      }
    }

    if (!txn.res.allow) {
      var params = { error: 'access_denied' };
      if (txn.req && txn.req.state) { params.state = txn.req.state; }
      return respond(txn, res, params);
    }

    function issued(err, crossDomainCode) {
      if (err) { return next(err); }
      if (!crossDomainCode) { return next(new AuthorizationError('Request denied by authorization server', 'access_denied')); }

      // NOTE: The draft specification is not explicit about the parameter name
      //       used to convey the cross domain code in the authorization
      //       response, and is lacking non-normative examples.
      //
      //       During development of this module, an extensive search was
      //       conducted to find existing implementations in order to determine
      //       what parameter is used in practice; however, no implementations
      //       were found.  In the absence of explicit guidance, this
      //       implementation chooses to follow convention established by the
      //       normal authorization code response type in OAuth 2.0, and uses
      //       a parameter named `code` to convey the cross domain code.
      var params = { code: crossDomainCode };
      if (txn.req && txn.req.state) { params.state = txn.req.state; }
      complete(function(err) {
        if (err) { return next(err); }
        return respond(txn, res, params);
      });
    }

    var pkce = {
      challenge: txn.req.codeChallenge,
      method: txn.req.codeChallengeMethod
    }

    try {
      var arity = issue.length;
      if (arity == 8) {
        issue(txn.client, txn.user, txn.req.audience, pkce, txn.res, txn.req, txn.locals, issued);
      } else if (arity == 7) {
        issue(txn.client, txn.user, txn.req.audience, pkce, txn.res, txn.req, issued);
      } else if (arity == 6) {
        issue(txn.client, txn.user, txn.req.audience, pkce, txn.res, issued);
      } else { // arity == 5
        issue(txn.client, txn.user, txn.req.audience, pkce, issued);
      }
    } catch (ex) {
      return next(ex);
    }
  }

  function errorHandler(err, txn, res, next) {
    var mode = 'query'
      , params = {}
      , respond;
    if (txn.req && txn.req.responseMode) {
      mode = txn.req.responseMode;
    }
    respond = modes[mode];

    if (!respond) {
      return next(err);
    }
    if (respond && respond.validate) {
      try {
        respond.validate(txn);
      } catch(ex) {
        return next(err);
      }
    }

    params.error = err.code || 'server_error';
    if (err.message) { params.error_description = err.message; }
    if (err.uri) { params.error_uri = err.uri; }
    if (txn.req && txn.req.state) { params.state = txn.req.state; }
    return respond(txn, res, params);
  }

  /**
   * Return `acdc` grant module.
   */
  var mod = {};
  mod.name = 'acdc';
  mod.request = request;
  mod.response = response;
  return mod;
}
<|endoftext|>