neet/refined-itsukara-link

View on GitHub
packages/@neet/vschedule-api/src/infra/app.ts

Summary

Maintainability
A
1 hr
Test Coverage
/* eslint-disable react-hooks/rules-of-hooks */
import './setup';

import apiSpec from '@neet/vschedule-api-spec';
import express, { Application } from 'express';
import * as OpenApiValidator from 'express-openapi-validator';
import expressWinston from 'express-winston';
import { inject, injectable } from 'inversify';
import { useExpressServer } from 'routing-controllers';
import swaggerUi from 'swagger-ui-express';
import winston from 'winston';

import {
  AuthController,
  ChannelController,
  MediaAttachmentController,
  OrganizationsController,
  PerformersController,
  StreamsController,
  YoutubeWebsubController,
} from '../adapters';
import { IConfig, ILogger } from '../app';
import { TYPES } from '../types';
import {
  appErrorHandler,
  domainErrorHandler,
  openapiErrorHandler,
  routingControllerErrorHandler,
} from './middlewares';
import { Passport } from './passport';
import { YoutubeWebsubParser } from './services';
import { createSession } from './session';

@injectable()
export class App {
  constructor(
    @inject(TYPES.Config)
    private readonly _config: IConfig,

    @inject(TYPES.Logger)
    private readonly _logger: ILogger,

    @inject(Passport)
    private readonly _passport: Passport,

    @inject(YoutubeWebsubParser)
    private readonly _youtubeWebsubParser: YoutubeWebsubParser,
  ) {}

  public configure(): Application {
    const app = express();
    const winstonInstance = this._logger as winston.Logger;

    // parser
    app.use(express.json());
    app.use(express.urlencoded({ extended: true }));
    app.use(expressWinston.logger({ winstonInstance }));
    app.use(this._youtubeWebsubParser.handler);

    // session
    app.use(createSession(this._config.session));
    app.use(this._passport.configure());

    // OpenAPI Documentation
    app.use('/docs', swaggerUi.serve, swaggerUi.setup(apiSpec));

    // OpenAPI
    app.use(
      '/rest',
      OpenApiValidator.middleware({
        apiSpec: require.resolve('@neet/vschedule-api-spec'),
        validateApiSpec: true,
        validateRequests: true,
        validateResponses: false,
      }),
    );

    // Controllers
    useExpressServer(app, {
      cors: true,
      validation: false,
      classTransformer: false,
      defaultErrorHandler: false,
      controllers: [
        AuthController,
        ChannelController,
        MediaAttachmentController,
        OrganizationsController,
        PerformersController,
        StreamsController,
        YoutubeWebsubController,
      ],
      authorizationChecker: (action) => {
        return action.request.isAuthenticated();
      },
      currentUserChecker: (action) => {
        return action.request.user;
      },
    });

    // Default Error handlers
    app.use(domainErrorHandler);
    app.use(appErrorHandler);
    app.use(openapiErrorHandler);
    app.use(routingControllerErrorHandler);
    app.use(expressWinston.errorLogger({ winstonInstance }));

    return app;
  }
}