# All files / src/server index.ts

0% Statements 0/44
0% Branches 0/15
0% Functions 0/6
0% Lines 0/43

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
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100

     import express from 'express';
    import { Request, Response, NextFunction } from 'express';
    import helmet from 'helmet';
    import bodyParser from 'body-parser';
    import { HttpStatusCode, isProduction } from '@cutting/util';
    import { render } from './render';
    import path from 'path';
    import favicon from 'serve-favicon';
    import { Exception } from '../errors/Exception';
    import { contentSecurityPolicy } from 'helmet';
    import noCache from 'nocache';
    import referrerPolicy from 'referrer-policy';

    export const app = express();

    const rootDir = process.cwd();

    const publicDir = path.join(rootDir, isProduction ? 'dist/public' : 'public');

    app.use(express.static(publicDir));

    if (isProduction) {
      app.use(helmet());
      app.use(noCache());
      app.use(referrerPolicy({ policy: 'no-referrer' }));
      app.use(helmet.hidePoweredBy());
      app.use(bodyParser.urlencoded({ extended: false }));
      app.use(bodyParser.json());
      app.use(favicon(path.join(publicDir, 'favicon.ico')));
      app.use(
        contentSecurityPolicy({
          directives: {
            defaultSrc: ["'self'", 'https://covidapi.info/'],
            scriptSrc: [
              "'self'",
              "'unsafe-inline'",
              "'unsafe-eval'",
              'https://www.googletagmanager.com/',
              'https://www.formlets.com',
              'https://www.google-analytics.com',
              'https://www.opendata.nhs.scot/',
            ],
            connectSrc: [
              'https://www.google-analytics.com',
              'www.google-analytics.com',
              'https://www.formlets.com',
              'https://covidapi.info/',
              'https://www.opendata.nhs.scot/',
            ],
            styleSrc: ["'self'", "'unsafe-inline'"],
            imgSrc: ["'self'", 'data:', 'https://www.google-analytics.com'],
            fontSrc: ["'self'", 'data:'],
            objectSrc: ["'self'", 'blob:'],
            frameSrc: ["'self'", 'https://www.formlets.com'],
          },
        }),
      );
    }

    app.get('/download', (req, res) => {
      const CVFile = 'paulcowan-cv.pdf';
      const pdfPath = ['', publicDir, 'assets', CVFile].join('/');

      res.status(HttpStatusCode.Ok).download(pdfPath, CVFile, (err) => {
        if (!err) {
          return;
        }

        console.log(err);
      });
    });

    app.get('/*', async (req, res) => {
      await render({
        req,
        res,
      });
    });

    const errorHandler = (err: Exception, req: Request, res: Response, next: NextFunction): void => {
      if (res.headersSent) {
        return next(err);
      }

      console.error(err);

      res.status(err.status || HttpStatusCode.InternalServerError).send(err.message || 'Internal Error');
    };

    app.use(errorHandler);

    process.on('unhandledRejection', (err) => {
      if (!err) {
        return;
      }

      console.error(err);
      throw err;
    });