setup common express/connect routes including 404, 500 and errorHandler.

NOTE: this should be called after your middlewares and routes.

@param {*} app express application instance
@param {*} config
@return {*} app
333406
function configureRoutes(app, config) {
    config = config || {};

    // TODO: add declarative routes
    // 'GET /foo bar/baz:qux' --> get('/foo', require('bar/baz')['qux'])
    // ...

    if (config.resources) {
        Object.keys(config.resources).forEach(function (urlPrefix) {
            DEBUG && debug('configure resource route: ', urlPrefix, '--->', config.resources[urlPrefix]);
            require('./resource').configureResource(app, urlPrefix, require(config.resources[urlPrefix]));
        });
    }

    if (config.statics) {
        Object.keys(config.statics).forEach(function (urlPrefix) {
            var dir = path.resolve(process.cwd(), config.statics[urlPrefix]);
            DEBUG && debug('configure http static route: ', urlPrefix, '--->', dir);
            app.use(urlPrefix, require('serve-static')(dir));
        });
    }

    if (config.root) {
        var root = path.resolve(process.cwd(), config.root);
        DEBUG && debug('configure http static root:', root);
        app.use(require('serve-static')(root));

        var favicon = path.join(root, 'favicon.ico');
        DEBUG && debug('configure http favicon route:', favicon);
        app.use(require('serve-favicon')(favicon));
    }

    DEBUG && debug('configure error routes', config.errors);
    if (config.errors) {
        var config404 = config.errors['404'];
        if (config404) {
            app.use(require('./error404')(config404));
        }
        var config500 = config.errors['500'];
        if (config500) {
            app.use(require('./error500')(config500));
        }
    }

    // NOTE: this should be end-of-middleware chain
    app.use(require('errorhandler')({dumpException: true, showStack: true}));

    return app;
}
412078
function createServer (options, callback) {
  typeforce({
    keeper: 'Object',
    port: 'Number',
    readonly: '?Boolean'
  }, options)

  var keeper = options.keeper
  var port = options.port
  var app = express()
  if (options.readonly) {
    app.set('readonly', true)
  }

  // var mapping

  app.set('keeper', keeper)
  app.use(function (req, res, next) {
    var requestDomain = domain.create()
    requestDomain.add(req)
    requestDomain.add(res)
    requestDomain.on('error', function (err) {
      debug('Uncaught error, processing in domain error handler: ' + err.message)
      errorHandler(err, req, res)
    })

    res.on('close', requestDomain.dispose.bind(requestDomain))
    requestDomain.run(next)
  })

  app.use(function (req, res, next) {
    if (req.hostname !== 'localhost' && req.hostname !== '127.0.0.1') {
      throw utils.httpError(400, 'Only local requests permitted')
    }

    next()
  })

  /**
   * Routes
   */
  router(app)

  /**
   * Error Handling
   */
  app.use(errorHandler)

  // client.externalIp(function(err, ip) {
  //   console.log('External ip', ip)
  //   keeper.externalIp(ip)
  // })

  // var ttl = 144000

  process.on('exit', cleanup)
  process.on('SIGINT', cleanup)
  process.on('SIGTERM', cleanup)
  process.on('uncaughtException', function (err) {
    console.log('Uncaught exception, caught in process catch-all: ' + err.message)
    console.log(err.stack)
  })

  // if (require.main === global.module) {
  // run directly, not as sub-app

  // var mappingIntervalId = setInterval(createPortMapping, ttl)
  // var pubPort = port
  var privPort = port
  var serverIsUp
  // var portPromise = createPortMapping()
  // portPromise.done(checkReady)

  var server = app.listen(privPort, function () {
    serverIsUp = true
    checkReady()
  })

  function checkReady () {
    if (serverIsUp
      // && portPromise.inspect().state === 'fulfilled'
      && callback) {
      callback(null, server)
    }
  }

  function errorHandler (err, req, res, next) {
    if (res.finished) return

    var code = err.code || 500
    var msg = 'code' in err ? err.message : 'There was an error with your request. Please contact support@tradle.io'

    // log('Error:' + err.message)
    res.status(code).json({
      code: code,
      message: msg
    }, null, 2)
  }

  // function createPortMapping () {
  //   return ports.mapPort({
  //       public: pubPort,
  //       private: privPort,
  //       hijack: true
  //     })
  //     .then(function () {
  //       mapping = {
  //         public: pubPort,
  //         private: privPort
  //       }
  //     })
  //     .catch(function (err) {
  //       console.error('Failed to create port mapping, but continuing', err)
  //       clearInterval(mappingIntervalId)
  //     // process.exit()
  //     })
  // }

  function cleanup () {
    if (!server) return

    debug('CLEANUP')
    if (server) {
      try {
        server.close()
      } catch (err) {}
      server = null
    }

    // if (mapping) {
    //   clearInterval(mappingIntervalId)
    //   ports.unmapPort(mapping['public'])
    //   mapping = null
    // }

    setTimeout(process.exit.bind(process), 1000)
  }

  return server
}
32620
function auth(app, config) {
  /* Ensure authorizer */
  if (!type.is(config.authorizer, Function)) {
    throw new Error("Authorizer must be a [Function]!");
  }

  /* Check debug type */
  if (type.is(config.debug, Function)) {
    debug = config.debug;
  } else if (config.debug) {
    debug = console.log;
  }

  app.use(function (req, res, next) {
    /* Set the session authorized property */
    req.session.authorized = config.authorizer(req);

    next();
  });

  /* Set authorization rules for each path */
  config.routes.forEach(function (route) {
    if (!type.is(route.path, Array) && !type.is(route.path, String)) {
      throw new Error("The route's path must be a [String] or an [Array] of [String]s!");
    }

    debug(route.method + " " + route.path + " --> " + route.allows);

    /* Callback for each method */
    function callback(req, res, next) {
      authorize(route, req, res, next);
    }

    /* The base router */
    var router = app.route(route.path);

    /* If method is an array */
    if (type.is(route.method, Array)) {
      return route.method.forEach(function (method) {
        router[method.toLowerCase()](callback);
      });
    }

    /* If method is a string */
    if (type.is(route.method, String)) {
      return router[route.method.toLowerCase()](callback);
    }

    /* If no method is specified default to ALL */
    router(callback);
  });
}
1105280
function makeServeMiddleware(/* config */) {
  return function handle(req, resp, next) {
    if (/^\/.*\.css$/.test(req.url)) {
      resp.end("");
    }
    else {
      next();
    }
  };
}
1311055
function initErrorHandler (config) {
    // add error handler
    config.express.use(function(error, req, res, next) {
        // error must be object with stack
        if (typeof error !== 'object' || typeof error.stack !== 'string') {
            error = new Error(error)
        }
        // whether or not response will be JSON
        var json = req.query.json === '1' || req.query.json === 'true' || (req.xhr && req.query.json !== '0' && req.query.json !== 'false') ? true : false
        // set clean stack
        if (defined(stackUtils)) {
            error.stack = stackUtils.clean(error.stack)
        }
        // if error contains cookies then set cookies with response
        if (error.cookies) {
            // set cookies
            _.each(error.cookies, (value, name) => {
                setCookie(name, res, value)
            })
        }
        // get http code from error code
        var code = error.code
        // if code is not between 300 and 500 then set to 500
        if (!(code >= 300 && code <= 500)) {
            code = error.code = 500
        }
        // json response is expected
        if (json) {
            // code is for redirect
            if (code === 301 || code === 302) {
                res.json({
                    code: code,
                    redirect: true,
                    url: error.url,
                })
            }
            // if error is 409 conflict data should be current instance
            else if (code === 409) {
                // set http status code
                res.status(code)
                // send current instance data
                res.json(error.data)
            }
            // code is other error
            else {
                // get message
                var message = error.message || 'Unknown error'
                // build response
                var resData = {
                    error: message,
                    code: code,
                    data: error.data,
                }
                // add stack if in dev
                if (!isProd) {
                    resData.stack = error.stack.split('\n')
                    // remove last element from stack which is empty
                    resData.stack.pop()
                }
                // set http status code
                res.status(code)
                // send current instance data
                res.json(resData)
            }
        }
        // html response is expected
        else {
            // code is for redirect
            if (code === 301 || code === 302) {
                res.redirect(code, error.url)
            }
            // code is error
            else {
                // set http status code
                res.status(code)
                // create pretty printed json data
                if (error.data) {
                    error.prettyData = JSON.stringify(error.data, null, 4)
                }
                // build data for error template
                var data = {
                    error: error,
                    production: isProd,
                    session: req.session,
                }
                // add assets to template data
                _.merge(data, config.assets)
                // render error page
                res.render('error', data)
            }
        }
    })
}
1028194
async function connect (mongoose, connectionName, connectionOpts) {
  const isDefault = connectionName === 'default'

  // Normalize and destructure connection options
  if (typeof connectionOpts === 'string') {
    connectionOpts = { uri: connectionOpts }
  }
  let { uri, options, forceReconnect } = connectionOpts

  // Apply default options
  // https://mongoosejs.com/docs/connections.html#options
  options = {
    useNewUrlParser: true,
    useCreateIndex: true,
    ...options
  }

  // Manualy create connection
  let conn
  if (isDefault) {
    conn = mongoose.connection
  } else {
    conn = new mongoose.Connection(mongoose)
    mongoose.connections.push(conn)
  }

  // $logger helper
  conn.$logger = isDefault
    ? consola
    : consola.withTag(connectionName)

  // Log connection events
  logConnectionEvents(conn)

  // $connect helper
  conn.$connect = () => {
    return new Promise((resolve, reject) => {
      conn.openUri(uri, options, (error) => {
        if (error) {
          reject(error)
        } else {
          resolve(conn)
        }
      })
    })
  }

  // Make accessable via mongoose.$connectionName
  mongoose['$' + connectionName] = conn

  // Setup force reconnect
  if (forceReconnect) {
    const timeout = forceReconnect === true ? 1000 : forceReconnect
    conn.on('error', () => {
      conn.close()
    })
    conn.on('disconnected', () => {
      setTimeout(() => { conn.$connect() }, timeout)
    })
  }

  // Connect
  await conn.$connect()
  await conn.$initialConnection
}
504754
function route() {
        configure()

        middlewares()

        for (let route of config.routes) {
            if (route.type === 'view')
                server[route.method](route.src, (req, res) => {
                    res.render(`${app.root}/views/${route.dest}.twig`, {})
                })

            if (route.type === 'controller') {
                let [path, method] = route.dest.split('::')

                let controller = function () {
                    if (!app.controllers)
                        return require(`${app.root}/controllers/${path.replace('.', '/')}`)(app)

                    if (path.split('.').length > 1)
                        return app.controllers[path.split('.')[0]][path.split('.')[1]]
                    else
                        return app.controllers[path]
                }()

                let func = wrapper(controller[method])
                if (!func)
                    app.drivers.logger.error('blockbase-express - wrapper', `Undefined function ${controller}${method}`)

                if (route.method === 'post' || route.method === 'put')
                    server[route.method](route.src, upload.any(), func)
                else
                    server[route.method](route.src, func)
            }
        }

        errors()
    }
122181
function initApp (config) {
    // init each module in the order loaded
    _.each(config.moduleNames, moduleName => {
        var module = config.modules[moduleName]
        // load modules and controllers for module, setup routes
        initModule(config, module)
        // merge module routes to global routes
        _.merge(config.routes, module.routes)
    })
    // initialize merged routes from all modules
    var router = initRoutes(config, config.routes)
    // bind router to app base
    config.express.use('/', router)
}
884006
function Router(req, res, next) {
        const server = this;
        const state = {
            method: req.method.toUpperCase(),
            params: {},
            routes: routes.concat(),
            routeUnhandled: true,
            server: server,
        };
        run(state, req, res, err => {
            req.params = {};
            if (state.routeUnhandled) req.log('unhandled', 'Router had no matching paths');
            next(err);
        });
    }
649683
function request (app) {
  app = app || blueprint.app.server.express;
  return supertest (app);
}
733045
function createServer() {
  function app(req, res, next){ app.handle(req, res, function(){
    res.end("", 'utf8');
  }); }
  merge(app, proto);
  merge(app, EventEmitter.prototype);
  app.route = '/';
  app.stack = [];
  return app;
}
764298
function createApplication() {
  var app = connect();
  utils.merge(app, proto);
  app.request = { __proto__: req };
  app.response = { __proto__: res };
  app.init();
  return app;
}
480834
function(err){
			if(!err){
				var address = app[serverNS].address();

				if(config.port){
					app.info('Server online at %s:%s', address.address, address.port);
				}else if(config.file){
					app.info('Server online via %s', config.file);
				}else{
					app.info('Server online!');
				}
			}
			app.emit('app.register', 'express');
			return callback(err);
		}
206315
function start(app) {
    /**
     * Create HTTP server.
     */

    const config = require('./config')();
    port = normalizePort(config.get('port'));
    server = http.createServer(app);

    /**
     * Listen on provided port, on all network interfaces.
     */

    app.set('port', port);
    server.listen(port);
    server.on('error', onError);
    server.on('listening', onListening);

    return server;
}
455615
function connectApp(token) {
  const CONNECTION = new Connection();

  return new Promise((resolve, reject) => {
    CONNECTION.connect(token)
      .then(() => resolve(new ConnectionHandler(CONNECTION)))
      .catch((error) => reject(error));
  });
}
713496
function(app) {
  app.loadConfigBaseApp(Constants.RESERVED.SERVERS, path.join(app.get(Constants.RESERVED.SERVICE_PATH), Constants.FILEPATH.SERVER));
  let servers = app.get(Constants.RESERVED.SERVERS);
  let serverMap = {}, slist, i, l, server;
  for (let serverType in servers) {
    slist = servers[serverType];
    for (i = 0, l = slist.length; i < l; i++) {
      server = slist[i];
      server.serverType = serverType;
      if(server[Constants.RESERVED.CLUSTER_COUNT]) {
        utils.loadCluster(app, server, serverMap);
        continue;
      }
      serverMap[server.id] = server;
      if (server.wsPort) {
        logger.warn('wsPort is deprecated, use clientPort in frontend server instead, server: %j', server);
      }
    }
  }
  app.set(Constants.KEYWORDS.SERVER_MAP, serverMap);
}
765452
function GhostServer(rootApp) {
    this.rootApp = rootApp;
    this.httpServer = null;
    this.connections = {};
    this.connectionId = 0;

    // Expose config module for use externally.
    this.config = config;
}