barend-erasmus/web-push-service

View on GitHub
src/main.ts

Summary

Maintainability
A
1 hr
Test Coverage
import { initialize } from './server';
import * as commander from 'commander';
import chalk from 'chalk';
import { InMemoryClientRepository } from './repositories/in-memory-client';
import { InMemorySubscriptionRepository } from './repositories/in-memory-subscription';
import { MongoClientRepository } from './repositories/mongo-client';
import { IClientRepository } from './interfaces/client-repository';
import { ISubscriptionRepository } from './interfaces/subscription-repository';
import { MongoSubscriptionRepository } from './repositories/mongo-subscription';
import { spawnSync } from 'child_process';
import * as fs from 'fs';
import { InstallCLIValidator } from './validators/cli/install';
import { StartCLIValidator } from './validators/cli/start';

commander
  .command('install')
  .option('-h --host <host>', `defaults to 'your-domain.com'`)
  .option('-m --mongo <host>', 'if not provided, file-based storage will be used')
  .option('-p --port <port>', 'port')
  .option('--nginx', 'install NGINX')
  .option('--letsencrypt', `install and configure Let's Encrypt`)
  .action((command: any) => {
    if (!InstallCLIValidator.validate(command)) {
      for (const error of InstallCLIValidator.errors(command)) {
        console.log(`${chalk.red('ERROR:')} ${chalk.white(error)}`);
      }

      return;
    }

    console.log(chalk.blue(`Creating systemd service file...`));
    fs.writeFileSync(
      '/lib/systemd/system/web-push-service.service',
      `[Unit]
    Description=Web Push Service
    
    [Service]
    Type=simple
    ExecStart=/usr/bin/web-push-service start --host ${command.host ? command.host : 'your-domain.com'}${command.mongo ? `--mongo ${command.mongo}` : ''} --port ${command.port}
    
    [Install]
    WantedBy=multi-user.target`,
    );

    console.log(chalk.blue(`Enabling web-push-service`));
    spawnSync('systemctl', ['enable', 'web-push-service']);

    console.log(chalk.blue(`Starting web-push-service...`));
    spawnSync('systemctl', ['start', 'web-push-service']);

    if (command.letsencrypt) {
      console.log(chalk.blue(`Installing letsencrypt...`));
      spawnSync('apt-get', ['install', '-y', 'letsencrypt']);

      console.log(chalk.blue(`Obtaining Certificate letsencrypt...`));
      spawnSync('letsencrypt', [
        'certonly',
        '--standalone',
        '--agree-tos',
        '--email',
        'developersworkspace@gmail.com',
        '-d',
        command.host,
      ]);
    }

    if (command.nginx) {
      console.log(chalk.blue(`Installing nginx...`));
      spawnSync('apt', ['install', '-y', 'nginx']);

      console.log(chalk.blue(`Creating nginx configuration file...`));
      fs.writeFileSync(
        '/etc/nginx/sites-enabled/web-push-service',
        `upstream web-push-service {
      server 127.0.0.1:8080;
  }
  
  server {
      listen 80;
      server_name ${command.host ? command.host : 'your-domain.com'};
  
      server_tokens off;
      gzip on;
      gzip_min_length 1000;
      gunzip on;
      gzip_static on;
  
      location / {
        proxy_pass http://web-push-service;
      }
  }
  
  server {
      listen 443 ssl;
      server_name ${command.host ? command.host : 'your-domain.com'};
  
      server_tokens off;
      gzip on;
      gzip_min_length 1000;
      gunzip on;
      gzip_static on;
  
      proxy_set_header X-Real-IP $remote_addr;

      ${
        command.letsencrypt
          ? `ssl_certificate /etc/letsencrypt/live/${command.host ? command.host : 'your-domain.com'}/fullchain.pem;
      ssl_certificate_key /etc/letsencrypt/live/${command.host ? command.host : 'your-domain.com'}/privkey.pem;
  
      ssl on;
      ssl_session_cache  builtin:1000  shared:SSL:10m;
      ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
      ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
      ssl_prefer_server_ciphers on;`
          : ''
        }
      
  
      location / {
          proxy_pass http://web-push-service;
      }
  }`,
      );

      console.log(chalk.blue(`Configuring firewall...`));
      spawnSync('ufw', ['allow', `'Nginx Full'`]);

      console.log(chalk.blue(`Enabling nginx...`));
      spawnSync('systemctl', ['enable', 'nginx']);

      console.log(chalk.blue(`Starting nginx...`));
      spawnSync('systemctl', ['start', 'nginx']);
    }
  });

commander
  .command('start')
  .option('-h --host <host>', `defaults to 'localhost:8080'`)
  .option('-m --mongo <host>', 'if not provided, file-based storage will be used')
  .option('-p --port <port>', 'port')
  .action((command: any) => {
    if (!StartCLIValidator.validate(command)) {
      for (const error of StartCLIValidator.errors(command)) {
        console.log(`${chalk.red('ERROR:')} ${chalk.white(error)}`);
      }

      return;
    }

    let clientRepository: IClientRepository = null;

    let subscriptionRepository: ISubscriptionRepository = null;

    if (command.mongo) {
      clientRepository = new MongoClientRepository(command.mongo);
      subscriptionRepository = new MongoSubscriptionRepository(command.mongo);
    } else {
      clientRepository = new InMemoryClientRepository('./clients.dat');
      subscriptionRepository = new InMemorySubscriptionRepository('./subscriptions.dat');
    }

    const expressApplication = initialize(
      clientRepository,
      subscriptionRepository,
      command.host ? command.host : 'localhost:8080',
    );

    expressApplication.listen(command.port);

    console.log(chalk.green(`Listening on port ${command.port}`));
  });

commander.parse(process.argv);