Categories
Docker and Kubernetes Full Stack Development Typescript

NestJS Template for APIs

Bootstrap your secure API development with a standard GitHub NestJS template

GitHub has the concept of template repositories. This allows us to invest the time in creating a skeleton project only once and then to create GitHub repositories out of this template. In this brief post I’m sharing a GitHub template for NestJS API Backend applications.

As the rush to total digitisation compels us to write ever more APIs, it’s useful to have a template that provides the key features each of our API backends needs.

I therefore decided to invest the time and created such template, available on GitHub.

This NestJS template offers the following boilerplate capabilities:

  • A Configuration Service ready to go. This allows us to create a .env file for environment variables and have such properties available anywhere in the app.
  • A JWT service based on Passport and Auth0
  • A Permissions Guard which protects APIs with the roles contained in the JWT token passed within the request
  • A Shared Service for common functionality
  • A pagination skeleton, to handle paginated data
  • A boilerplate controller, with one open and one secure endpoint
  • A boilerplate service that the controller can invoke
  • Typeorm dependencies
  • A boilerplate Docker configuration

For details on how to build and run the application and create a Docker image if you want, please refer to the GitHub documentation.

The API security configuration is centred around Auth0, an Identity As A Service product.

If you want to know more about how to configure a NestJS API Backend with Auth0, please refer to these articles:

Setting up Auth0 for your full-stack Angular SPA

Feedback Pal Nest JS API Backend

Hope you’ll find this useful.

Categories
Full Stack Development Javascript Typescript Uncategorized Web

Using dotenv in Typescript

Typescript is awesome, I think that as we start using it, this becomes apparent. It provides type safety and to build full stack applications with an object-oriented mindset. However Typescript is a superset of Javascript and its support for typing doesn’t come for free. It has its own compiler in order to understand its syntax. Ultimately Typescript code is compiled into Javascript.

If you’re building production applications, you’ll be familiar with the need to keep your secrets outside the source code and provide them as runtime configuration and if you are a full-stack Javascript developer chances are that you have used Node.js as backend server.

Every application has the basic need to externalise some configuration properties, and historically the npm package to achieve this has been dotenv. This package loads .env files and fills the process.env object which can then be used to access environment variables in your application.

Working with third-party libraries in Typescript is not as straight-forward as one might think. It a typical Node.js setup, to use dotenv one would use something like this (after installing dotenv with npm i dotenv):

require('dotenv').config();

From now all environment variables in .env are accessible through process.env.YOUR_EV

With Typescript this doesn’t work because require is a Node.js syntax, not a Typescript syntax.

The goal is to use dotenv (and generally any TP Javascript modules) in a Typescript application: how do we achieve that?

The usual way to use third-party libraries in Typescript is to use types. There’s an open source project which makes available most types for existing Javascript libraries to Typescript applications. It’s called DefinitelyTyped. Thanks to this project, it’s possible to use existing Javascript libraries in Typescript projects by using the following syntax:

npm i --save-dev @types/<module>

This guarantees that Typescript will access the module types as if they were Typescript types. For dotenv I’ve found that this doesn’t work and indeed @types/dotenv is deprecated. After considerable time spent on the internet looking at possible solutions, none of which worked, I’ve found a way to achieve this with Webpack.

Webpack to the rescue

Webpack is a bundler that can be used in combination with plugins to provide compile and bundling options for your application. It’s the de-facto standard for packaging JS/Typescript/CSS files into production-ready applications. In a nutshell, one provides a webpack configuration file, instructs the tool what to compile and the target environment and Webpack creates bundles which can then be used on the frontend as well as backend. Thanks to Webpack is also possible not only to optimise the bundles for production, by creating minified versions, thus improving the overall performance of your application but also to create code that works in older browsers, eg IE9.

Let’s say that you have a .env file in the root of your project with the following environment variable, an API key to use Google Geolocation APIs:

API_KEY='<your-secret-key-here>'

You’d like to use this environment variable in your Typescript application as follows:

// ./src/app.ts
const form = document.querySelector('form')!;
const addressInput = document.getElementById('address')! as HTMLInputElement;
console.log(process.env);

const apiKey = process.env.API_KEY;
if (!apiKey) {
  throw new Error('No API Key');
}

function searchAddressHandler(event: Event) {
  event.preventDefault();
  const enteredAddress = addressInput.value;
  console.log(enteredAddress);

  // send to Google's API!
}
form.addEventListener('submit', searchAddressHandler);

First you’ll need to install the webpack and dotenv-webpack npm modules. You can do this by running the following command:

npm i --save-dev dotenv-webpack ts-loader typescript webpack webpack-cli webpack-dev-server

Then, you can setup your Webpack config (webpack.config.js) as follows:

const path = require('path');
const Dotenv = require('dotenv-webpack');

module.exports = {
  mode: 'development',
  entry: './src/app.ts',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: 'dist',
  },
  devtool: 'inline-source-map',
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node-modules/,
      },
    ],
  },
  resolve: {
    extensions: ['.ts', '.js'],
  },
  plugins: [new Dotenv()],
};

Here you will notice the Dotenv declaration as well as the plugins entry.

Et voila’. You can now use process.env.YOUR_EV in your code, without the need to install dotenv or any complex configuration for Node.js or type compatibility.

Happy coding folks!