All files / apps/public-api/src main.ts

0% Statements 0/82
0% Branches 0/1
0% Functions 0/1
0% Lines 0/82

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83                                                                                                                                                                     
import '@amalia/kernel/config/server';

import { HttpException } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import bodyParser from 'body-parser';
import bodyParserXml from 'body-parser-xml';
import express from 'express';
import helmet from 'helmet';
import { isNil } from 'lodash-es';
import { initializeTransactionalContext, StorageDriver } from 'typeorm-transactional';

import { toError } from '@amalia/ext/typescript';
import { Logger as JSONLogger } from '@amalia/kernel/logger/server';

import { PublicApiRootModule } from './app/app.module';
import { PublicApiService } from './app/public-api-module/PublicApi.service';
import { configuration } from './configuration';

export async function bootstrap() {
  initializeTransactionalContext({ storageDriver: StorageDriver.AUTO });
  // We can't use the integrated server of nest, or it'll start all the controllers, and we don't need them.
  // To reduce start time, we use createApplicationContext which only registers the modules and services.
  // Then we use express to listen to HTTP requests.
  const app = await NestFactory.createApplicationContext(PublicApiRootModule, {
    bufferLogs: true,
  });

  const logger = app.get(JSONLogger);
  app.useLogger(logger);

  const expressServer = express();
  expressServer.use(helmet());

  expressServer.use(bodyParser.json());

  // We add an XML body parser to parse all incoming HTTP requests with the MIME type `**/xml*`
  // (Used here to process Salesforce incoming messages which use SOAP Xml payload).
  bodyParserXml(bodyParser);
  expressServer.use(bodyParser.xml());

  const publicApiService = app.get(PublicApiService);

  expressServer.get('/v1/custom-reports/:customReportId', async (req, res) => {
    const limit = isNil(req.query['limit']) ? 100 : +req.query['limit'];

    if (limit > 500) {
      res.status(400).json({ message: 'Limit is too big. Max is 500.' });
      return;
    }

    try {
      const data = await publicApiService.getData(
        req.headers['x-api-key'] as string,
        req.params.customReportId,
        +(req.query['page'] || 0),
        limit,
      );
      res.json(data);
    } catch (e) {
      if (e instanceof HttpException) {
        res.status(e.getStatus()).send(e.getResponse());
        return;
      }
      const error = toError(e);
      logger.error({ message: error.message, error });
      res.sendStatus(500);
    }
  });

  expressServer.listen(configuration.apps.publicApi.port, () => {
    logger.log(`App started on port ${configuration.apps.publicApi.port}`);
  });

  return expressServer;
}

bootstrap().catch((error) => {
  // Loggers may not be ready yet.
  // eslint-disable-next-line no-console
  console.error('Error at application startup', error);
  process.exit(1);
});