dalisoft/nanoexpress

View on GitHub
src/middlewares/http.js

Summary

Maintainability
B
6 hrs
Test Coverage
import { http } from '../handler';
import {
  prepareValidation,
  prepareRouteFunctions,
  prepareSwaggerDocs,
  logger
} from '../helpers';

export default (path = '/*', fns, config, ajv, method, app) => {
  if (typeof path === 'function') {
    if (Array.isArray(fns)) {
      fns.unshift(path);
    } else if (!fns) {
      fns = path;
    }
    path = '/*';
  }

  const {
    route,
    prepared,
    empty,
    schema,
    allAsync,
    asyncToSync,
    error
  } = prepareRouteFunctions(fns, app);

  const validationMap = prepareValidation(ajv, schema && schema.schema, config);

  if (config.swagger) {
    prepareSwaggerDocs(config.swagger, path, method, schema);

    if (!app.swaggerApplied) {
      app.get('/docs/swagger.json', { isRaw: true }, (req, res) => {
        res.writeHeader('Content-Type', 'application/json');
        res.end(JSON.stringify(config.swagger, null, 4));
      });
      app.swaggerApplied = true;
    }
  }

  if (error) {
    return config._notFoundHandler
      ? config._notFoundHandler
      : (req, res) =>
          res.end(
            '{"middleware_type":"sync","error":"The route handler not found"}'
          );
  }

  if (route === undefined) {
    logger.error('Route - route function was not defined', {
      route,
      path,
      method
    });
    return;
  }

  const handler = empty
    ? route
    : async (req, res, config) => {
        let middlewareChainingTransferPreviousResult;
        for (const fn of prepared) {
          if (fn.simple || !fn.async) {
            fn(req, res, config, middlewareChainingTransferPreviousResult);

            if (error && !middlewareChainingTransferPreviousResult) {
              if (error && !res.aborted) {
                if (config._errorHandler) {
                  return config._errorHandler(error, req, res);
                }
                return res.end(
                  `{"middleware_type":"${fn.type}",error":"${error.message}"}`
                );
              }
              return;
            }
          } else {
            const middleware = await fn(
              req,
              res,
              config,
              middlewareChainingTransferPreviousResult
            ).catch((error) => ({
              error
            }));

            if (middleware === res) {
              return res;
            } else if (middleware && middleware.error) {
              if (!res.aborted) {
                if (config._errorHandler) {
                  return config._errorHandler(middleware.error, req, res);
                }
                return res.end(
                  `{"middleware_type":"${fn.type}",error":"${middleware.error.message}"}`
                );
              }
              return;
            }

            middlewareChainingTransferPreviousResult = middleware;
          }
        }

        if (method === 'options') {
          return res;
        }

        if (!route.async || route.simple) {
          route(req, res, config, middlewareChainingTransferPreviousResult);
          return res;
        }

        return route(
          req,
          res,
          config,
          middlewareChainingTransferPreviousResult
        );
      };

  handler.async = empty ? route.async : allAsync;
  handler.simple = route.simple;
  handler.asyncToSync = asyncToSync;

  return http(path, handler, config, schema, ajv, method, validationMap, app);
};