@bage/core-express

Core express for node js library

Usage no npm install needed!

<script type="module">
  import bageCoreExpress from 'https://cdn.skypack.dev/@bage/core-express';
</script>

README

core express based node js library

Core library to built an express based service in node js.

Built With


Libraries


  • Exposed Libraries
  - auth
  - Server
  - Router (express.Router)
  - utils
  - connectSequelizeDb
  - validate
  - errors

Descriptions

auth

Authentication library using jwt. consists of :

  • verifyToken : to verify access token using JWT-RS256 encryptions
  • authenticateRequest : to authenticate any incoming requests with token and schema
  • sign : to sign in any data with the private token
  • hash : hash any text using sha256 hashing
  • decode : to decode any token given using jwt-decode

Server

Main express server class to be instantiated

  • verifyToken : to verify access token using JWT-RS256 encryptions
  • authenticateRequest : to authenticate any incoming requests with token and schema
  • sign : to sign in any data with the private token
  • hash : hash any text using sha256 hashing
  • decode : to decode any token given using jwt-decode

Router

Authentication library using jwt. consists of :

  • verifyToken : to verify access token using JWT-RS256 encryptions
  • authenticateRequest : to authenticate any incoming requests with token and schema
  • sign : to sign in any data with the private token
  • hash : hash any text using sha256 hashing
  • decode : to decode any token given using jwt-decode

utils

Authentication library using jwt. consists of :

  • verifyToken : to verify access token using JWT-RS256 encryptions
  • authenticateRequest : to authenticate any incoming requests with token and schema
  • sign : to sign in any data with the private token
  • hash : hash any text using sha256 hashing
  • decode : to decode any token given using jwt-decode

connectSequelizeDb

Authentication library using jwt. consists of :

  • verifyToken : to verify access token using JWT-RS256 encryptions
  • authenticateRequest : to authenticate any incoming requests with token and schema
  • sign : to sign in any data with the private token
  • hash : hash any text using sha256 hashing
  • decode : to decode any token given using jwt-decode

validate

Authentication library using jwt. consists of :

  • verifyToken : to verify access token using JWT-RS256 encryptions
  • authenticateRequest : to authenticate any incoming requests with token and schema
  • sign : to sign in any data with the private token
  • hash : hash any text using sha256 hashing
  • decode : to decode any token given using jwt-decode

errors

Authentication library using jwt. consists of :

  • verifyToken : to verify access token using JWT-RS256 encryptions
  • authenticateRequest : to authenticate any incoming requests with token and schema
  • sign : to sign in any data with the private token
  • hash : hash any text using sha256 hashing
  • decode : to decode any token given using jwt-decode

Getting Started


Prerequisites

  • Node.js v^8.10.0
  • npm v^6.4.1

Installing

  • clone repository : npm install @bage/core-express
  • instantiate
  • modify .env configurations into api used values
  • Run npm install : npm install

Running service

npm run start

Orchestrating Server

  const Producer = require('sqs-producer');
  const Sequelize = require('sequelize');

  const { Server, connectSequelizeDb } = require('../core');
  const config = require('../config');
  const { CityDb, CustomerDb, SQSApi } = require('./repositories');
  const { City, Hello } = require('./services');
  const routes = require('./routes');

  /**
  * Initiating DB connections and instantiate DB classes (CityDb, CustomerDb)
  * @param {object} app - express server object
  */
  const initDB = (app) => {
    const { logger }  = app.locals;
    const dbConfig = config.resources.db;
    app.locals.Sequelize = Sequelize;
    const crowdSysDb = connectSequelizeDb(Sequelize, dbConfig, logger);

    const opts = {
      logger, crowdSysDb, Sequelize
    };

    app.locals.cityDb = new CityDb(opts);
    app.locals.customerDb = new CustomerDb(opts);
  };

  /**
  * Initiating other api connections and instantiate API access classes (SQSApi)
  * @param {object} app - express server object
  */
  const initApi = (app) => {
    const { url, region, accessKey, secretKey } = config.resources.sqs;
    const producer = Producer.create({
      queueUrl: url,
      region: region,
      accessKeyId: accessKey,
      secretAccessKey: secretKey
    });

    const { logger } = app.locals;

    const opts = {
      logger,
      producer
    };

    app.locals.sqsApi = new SQSApi(opts);
  };

  /**
  * Initiating api service classes (City, Hello)
  * @param {object} app - express server object
  */
  const initServices = (app) => {
    const {
      logger,
      sqsApi,
      cityDb,
      customerDb
    } = app.locals;
    
    app.locals.city = new City({
      logger, sqsApi, cityDb
    });
    app.locals.hello = new Hello({
      logger, sqsApi, customerDb
    });
  };

  /**
  * collect all initiations in an array
  */
  const inits = [
    initDB,
    initApi,
    initServices
  ];

  /**
  * Instantiating core server class
  * assign config, inits, routes
  * config is get from importing from config folder
  * router is get from importing the router folder
  * other parameter that can be set is an array of middlewares
  */
  const server = new Server({
    config,
    inits,
    routes
  });

  /**
  * Run server
  */
  server.listen();

  /**
  * create function to gracefully stop the service
  */
  const stopServer = (signal) => {
    return server.stop(signal);
  };

  /**
  * assign process signals to gracefully stop the service 
  */
  process.on('SIGINT', stopServer);
  process.on('SIGTERM', stopServer);

  /**
  * exporting the server to be used in the lambda.js functions
  */
  module.exports = server;

What happens behind the scene in Server.js

  class Server {
    constructor(opts) {
      Object.assign(this, opts);
      
      /**
      * instantiating express.js and assign to this.app
      * */  
      this.app = express();
      
      /**
      * assign config sent from server orchestration to app.locals.config
      * so it can be accessed from any requests (to access just call req.app.locals.config)
      */
      this.app.locals.config = this.config;

      /**
      * create logger using bunyan.createLogger
      * assign to app.locals.logger to be used from any requests (to access just call req.app.locals.logger)
      */
      this.logger = createLogger(this.config.logger);
      this.app.locals.logger = this.logger;

      /**
      * assign bodyParser to the express server
      * so it can read any body payload that sent through requests
      */
      this.app.use(bodyParser.json());
      this.app.use(bodyParser.urlencoded({ extended: true, limit: '25mb' }));

      /**
      * log every incoming requests
      */
      this.app.use(logRequest);
      

      /**
      * assign any middlewares given to the server
      */
      if (this.middlewares && this.middlewares && this.middlewares.length) {
        this.middlewares.forEach(middleware => this.app.use(middleware));
      }

      /**
      * assign swagger documents and set /docs to be the path for accessing swagger
      */
      if (swaggerDocs) {
        this.app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));
      }

      /**
      * assign any routes given to the server
      */
      if (this.routes && this.routes.length) {
        this.routes.forEach(route => this.app.use(route));
      }

      /**
      * assign errorHandler to catch and send any custom error assigns in the code
      */
      this.app.use(errorHandler);

      /**
      * log any response sent to the clients or any other services
      */
      this.app.use(logResponse);
    }

    async listen() {
      /**
      * assign any initializations given to the server
      */
      if (this.inits && this.inits.length) {
        try {
          await this.inits.reduce((p, init) => p.then(() => init(this.app)), Promise.resolve());
        } catch (error) {
          this.logger.error({ error }, 'failed on initializations process');
          throw error;
        }
      }

      /**
      * run server by listening to the port given in the config files
      */
      return new Promise((resolve) => {
        this.server = this.app.listen(this.config.port, () => {
          this.logger.info(`${this.config.name} is listening to ${this.config.host}:${this.config.port}`);
          return resolve();
        });
      });
    }

    async stop(signal) {
      /**
      * log server as shutdown process and then close the server
      */
      this.logger.info({ event: 'shutdown', signal });
      this.server.close();
    }
  }

other usage can be seen in the representatives folder and files available in current project

Versioning


v.1.0.0

initial works

Authors


  • muslimi