ksmithut/skyway

View on GitHub
swagger2/routes/routes.js

Summary

Maintainability
A
2 hrs
Test Coverage
'use strict'

const R = require('ramda')
const debug = require('debug')('skyway')
const Router = require('express').Router
const compose = require('compose-middleware').compose
const normalizeDocs = require('./normalize-docs')
// Middleware Modules
const security = require('./security')
const parse = require('./parse')
const validateHead = require('./validate-head')
const validateBody = require('./validate-body')
const handler = require('./handler')

const hasRunValidation = Symbol('hasRunValidation')

const middlewareModules = {
  security,
  parse,
  validateHead,
  validateBody,
  handler
}

module.exports = getDocs => {
  const waitForDocs = getDocs.then(normalizeDocs)

  waitForDocs.catch(err => {
    debug('Invalid Schema', err)
  })

  return options => {
    const router = new Router()

    router.use((req, res, next) => {
      waitForDocs.then(() => next()).catch(next)
    })

    waitForDocs
      .then(docs => {
        const getModuleContext = R.propOr(R.always(options), 'context')
        const initContext = getContext => getContext(options, docs)
        const contexts = R.map(
          R.pipe(getModuleContext, initContext),
          middlewareModules
        )
        const createOperationMiddleware = R.pipe(
          R.flatten,
          R.reject(R.isNil),
          compose
        )

        R.forEach(operation => {
          const path = operation.expressPath
          const middleware = createOperationMiddleware([
            middlewareModules.security.middleware(operation, contexts.security),
            middlewareModules.validateHead.middleware(
              operation,
              contexts.validateHead
            ),
            middlewareModules.parse.middleware(operation, contexts.parse),
            middlewareModules.validateBody.middleware(
              operation,
              contexts.validateBody
            ),
            middlewareModules.handler.middleware(operation, contexts.handler)
            // TODO response serialization
            // TODO response validation
          ])
          router[operation.method](path, (req, res, next) => {
            if (req[hasRunValidation]) return next()
            req[hasRunValidation] = true
            middleware(req, res, next)
          })
        }, docs.operations)
      })
      .catch(
        /* istanbul ignore next */ err => {
          debug('Error initializing route middleware', err)
        }
      )

    return router
  }
}