Abyss Monitor
  • Abyss Monitor
  • Setup
    • Core
    • Logger
    • Stats Performance
    • Store
    • Middleware
    • Alerts
  • Tutorials
    • Create an API
    • Distributed Cron Task
  • About
    • Links
Powered by GitBook
On this page
  1. Tutorials

Create an API

Create an fast and easy to use API using AbyssMonitor features

PreviousAlertsNextDistributed Cron Task

Last updated 8 months ago

provide tools to setup an easy API with NodeJS and TypeScript. Tools are designed to works with Express.

Setup

Create your first Middleware

import { Request, Response, NextFunction } from 'express';
import * as contentType from 'content-type';
import { IMonitorLocals, Logger, Middleware } from '@abyss-project/monitor';

export const ALLOWED_REQUEST_TYPES = [
  'application/json',
  'multipart/form-data',
  'application/x-www-form-urlencoded',
];

@Middleware()
export default class MyMiddleware {
  private static readonly logger = new Logger({});

  public async run(
    req: Request,
    res: Response<unknown, IMonitorLocals>,
    next: NextFunction,
  ): Promise<void> {
    if (req.headers['content-type']) {
      const contentT = contentType.parse({ headers: req.headers });

      if (!ALLOWED_REQUEST_TYPES.includes(contentT.type)) {
        // Throw an error because invalid request type
      }
    }

    next();
  }
}

Create your first Controller

import { Request, Response } from 'express';
import { Controller, Get, IMonitorLocals, Logger, Middlewares } from '@abyss-project/monitor';
import MyMiddleware from './../middlewares/my-middleware.middleware.ts'
@Controller({ prefixPath: '/' })
@Middlewares([MyMiddleware])
export default class MyController {
  private static readonly logger = new Logger({});

  @Get({
    path: '/hello-world',
  })
  @Middlewares([])
  async helloWorld(
    req: Request<Record<string, never>, string, void>,
    res: Response<string, IMonitorLocals>,
  ): Promise<void> {
    res.send(`Hello world !`);
  }
}

Create the Express Application

import {
  IMonitorLocals,
  contextMiddleware,
  controllerLoader,
  loggerEndpointMiddleware,
  loggerSetupMiddleware,
  Logger,
} from '@abyss-project/monitor';
import express, { Response, Request, NextFunction, Router } from 'express';
import { json, urlencoded } from 'body-parser';
import cors from 'cors';
import cookieParser from 'cookie-parser';
import helmet from 'helmet';
import compression from 'compression';
import swaggerUi from 'swagger-ui-express';
import MyController from './controllers/my-controller.controller.ts';
import MyMiddleware from './middlewares/my-middleware.middleware.ts';
require('express-async-errors');

const PREFIX = '/api';
const PORT = 5000;

const apiLogger = new Logger({
  shouldDisableRemoteLogging: process.env.NODE_ENV === 'DEVELOPMENT',
});

const init = async (): Promise<express.Application> => {
  const app = express();
  // Adding the ContextMiddleware
  app.use(contextMiddleware);

  // Disabling the PoweredBy Express header
  app.disable('x-powered-by');

  // Enabling CORS and set kind of request my API will accept because
  // I want to make this API public
  app.use(cors());
  app.use((req: Request, res: Response<unknown, ILocals>, next: NextFunction) => {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader(
      'Access-Control-Allow-Headers',
      'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization',
    );
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
    res.setHeader('Access-Control-Expose-Headers', 'Content-disposition, filename');
    next();
  });

  app.use(urlencoded({ extended: true }));
  app.use(json());
  app.use(cookieParser());
  app.use(helmet());
  app.use(compression());

  // Setting logger middleware
  app.use(loggerSetupMiddleware);
  app.use((req, res: Response<unknown, IMonitorLocals>, next) =>
    loggerEndpointMiddleware(apiLogger, req, res, next),
  );

  // Setting up the swagger
  const {
    swagger: { tags, paths },
  } = await controllerLoader(app, {
    prefix: PREFIX,
    router: Router,
    middlewares: [MyMiddleware],
    controllers: [MyController],
  });

  app.use(
    (error: Error, _req: Request, _res: Response<unknown, IMonitorLocals>, _next: NextFunction) => {
      // Do what you want with the error
      apiLogger.error(error);
    },
  );

  app
    .listen(PORT, () => {
      apiLogger.info(`API started on port ${PORT}`);
    })
    .on('error', (error) => {
      apiLogger.error(`API failed to start. Error: ${error}`);
    });

  const defaultSwagger = {
    openapi: '3.0.3',
    info: {
      title: 'My First API',
      description: '',
      version: '1.0',
      termsOfService: 'http://swagger.io/terms/',
      contact: {
        email: 'apiteam@swagger.io',
      },
      license: {
        name: 'Apache 2.0',
      },
      url: 'http://www.apache.org/licenses/LICENSE-2.0.html',
    },
    produces: ['application/json'],
    host: `http://localhost:${PORT}`,
    basePath: PREFIX,
    tags,
    paths,
  };

  app.use(
    '/swagger',
    (req: Request, res: Response<unknown, IMonitorLocals>, next: NextFunction) => {
      // Disabling the log on swagger endpoint to not spam with useless logs
      res.locals.shouldNotPublishLog = true;
      next();
    },
    swaggerUi.serve,
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    swaggerUi.setup(defaultSwagger),
  );

  return app;
};

await init();
AbyssMonitor