OpenVeo Core server

API Docs for: 7.0.0
Show:

File: app/server/loaders/routeLoader.js

'use strict';

/**
 * @module core-loaders
 */

/**
 * Provides functions to load routes from core and plugins
 * configuration.
 *
 * @class routeLoader
 * @static
 */

var path = require('path');
var util = require('util');
var openVeoApi = require('@openveo/api');

var controllers = {};

/**
 * Gets the list of routes from a route configuration object with,
 * for each one, the method, the path and the action to call.
 *
 * @example
 *     var routeLoader = process.require('app/server/loaders/routeLoader.js');
 *     var routes = {
 *       'get /test' : 'app/server/controllers/TestController.getTestAction',
 *       'post /test' : 'app/server/controllers/TestController.postTestAction'
 *     };
 *
 *     console.log(routeLoader.decodeRoutes('/', routes));
 *     // [
 *     //   {
 *     //     method: 'get',
 *     //     path: '/test',
 *     //     action: Function
 *     //   },
 *     //   {
 *     //     method: 'post',
 *     //     path: 'test',
 *     //     action: Function
 *     //   }
 *     // ]
 *
 * @method decodeRoutes
 * @static
 * @param {String} pluginPath The root path of the plugin associated to the routes
 * @param {Object} routes An object of routes
 * @return {Array} The decoded list of routes
 * @throws {TypeError} If one of the route controllers is not a Controller
 */
module.exports.decodeRoutes = function(pluginPath, routes) {
  var decodedRoutes = [];

  if (routes) {

    for (var match in routes) {

      // e.g. get /test
      // Extract HTTP method and path
      var matchChunks = /^(get|post|delete|put)? ?(\/?.*)$/.exec(match.toLowerCase());

      var actions = [];

      // If the action associated to the path is an array
      // keep it this way
      if (util.isArray(routes[match]))
        actions = routes[match];

      // If not an array, make it an array
      else
        actions.push(routes[match]);

      actions.forEach(function(action) {

        // e.g. app/server/controllers/TestController.getTestAction
        var actionChunks = action.split('.');

        // Got a path and an action for this route
        if (matchChunks && matchChunks[2] && actionChunks.length === 2) {

          try {

            // Try to register the controller
            var controllerFilePath = path.join(pluginPath, actionChunks[0] + '.js');
            var controllerInstance;

            // Create an instance of the controller only once per controller
            if (controllers[controllerFilePath])
              controllerInstance = controllers[controllerFilePath];
            else {
              var Controller = require(controllerFilePath);

              if (!(Controller.prototype instanceof openVeoApi.controllers.Controller))
                throw new TypeError(controllerFilePath + ' is not a Controller');

              controllerInstance = new Controller();
              controllers[controllerFilePath] = controllerInstance;
            }

            // Got a method to call on the controller
            if (controllerInstance[actionChunks[1]]) {

              // Store the new route
              decodedRoutes.push({
                method: (matchChunks[1] && matchChunks[1].toLowerCase()) || 'all',
                path: matchChunks[2],
                action: controllerInstance[actionChunks[1]].bind(controllerInstance)
              });

            } else {
              process.logger.warn('Action for route ' + match + ' is not valid', {
                action: 'decodeRoutes'
              });
            }

          } catch (e) {
            process.logger.warn('Error while loading route ' + match, {
              action: 'decodeRoutes',
              error: e.message,
              stack: e.stack
            });
          }

        }

      });


    }

  }

  return decodedRoutes;
};

/**
 * Applies a list of routes to a router.
 *
 * @example
 *     var router = express.Router();
 *     var routeLoader = process.require('app/server/loaders/routeLoader.js');
 *     var routes = [
 *       {
 *         method: 'get',
 *         path: '/logout',
 *         action: [Function]
 *       }
 *     ];
 *     routeLoader.applyRoutes(routes, router);
 *
 * @method applyRoutes
 * @static
 * @param {Array} routes The list of routes to apply
 * @param {Object} router An express router to attach the routes to
 */
module.exports.applyRoutes = function(routes, router) {
  if (routes && routes.length && router) {
    routes.forEach(function(route) {
      process.logger.debug('Route loaded', {
        route: route.method + ' ' + route.path
      });

      // Deactivate cache on all requests made on this router
      if (route.method === 'get')
        router[route.method](route.path, openVeoApi.middlewares.disableCacheMiddleware);

      router[route.method](route.path, route.action);
    });
  }
};