Let's learn Node.js by building a backend with Nest.js and Sequelize

Duomly - May 27 '20 - - Dev Community

This article was originally published at https://www.blog.duomly.com/node-js-course-with-building-a-fintech-banking-app-lesson-1-start-the-project


In the previous week, I and my friend started to build a project divided for two courses - backend with Golang and frontend with Angular 9. In the meantime, we got the idea to give you an alternative for a Golang course, and show you how to build a similar backend using Node.js.

In this article, we are going to start by setting up the Nest.js project, connecting with the PostgreSQL database and make migrations.

In this course, we will be using Nest.js which is a typescript framework, kind of an Angular for Node.js. It's very comfortable and easy to use, so in my opinion, it's a great choice for beginners.

Besides that, we will use Sequelize for database maintaining and Umzug for migrations. We've selected a PostgreSQL database so it will be great if you could create an empty one to start the project.

I can't wait to get started, but before that, as always I have to mention that we've got a video version for you on our Youtube channel for you.

Let's crush Node.js!

1. What do you need to start Node.js project?

Let's start by clarifying what's important for you to start with us from point 2.

To be able to create a Node.js application you will need Node.js installed. Here you can take a look at the official documentation and download the installer.

The second important thing you need is a PostgreSQL database installed and created for the purpose of this application.

Another thing which would be rather useful then required is the database tool like DBeaver.

If you've got everything ready, let's start a real fun.

2. Installing Nest.js CLI and creating a project

At the beginning let's install Nest.js CLI which will be useful to create a new project. For this use the following command:

$ npm i -g @nestjs/cli

When it's ready, we can create a new project. I called my project lesson-one but feel free to call it how you like.

$ nest new lesson-one

When it's done go into the newly created folder and let's add another needed packages!

3. Add Sequalize and Umzug

For database and migrations, we will use Sequalize and Umzug, so we need to install them now!

So, let's start by installing Sequelize and Sequelize Typescript with the following command:

$ npm install --save sequelize sequelize-typescript
$ npm install pg

After the installation is done, there can be two missing dependencies, which we have to install manually. Let's use the following command to do this:

$ npm install @types/bluebird
$ npm install @types/validator

If you didn't have that problem skip this step and continue with installing Umzug.

 $ npm install umzug

Great, when it's done we can run our backend and start coding. To run Nest.js we use nest start.

4. Create database module

Let's start by creating a new folder in our ./src folder and let's call it modules. When you did it, please inside that folder create another one and call it database.

In the ./src/modules/database let's create two files, database.module.ts and database.provider.ts and let's start from the provider, and let's add the following code there.

import { Sequelize } from 'sequelize-typescript';

export const databaseProvider = [
  {
    provide: 'SEQUELIZE',
    useFactory: async () => {
      const sequelize = new Sequelize({
        dialect: 'postgres',
        host: <YOUR_HOST>,
        port: 5432,
        username: <YOUR_USERNAME>,
        password: <YOUR_PASSWORD>,
        database: <YOUR_DB_NAME>
      });
      sequelize.addModels([]);
      return sequelize;
    }
  }
]

Remember to change the placeholders and set your own database credentials.
When you finished, let's open database.module.ts and add there the code as you see below.

import { Module } from '@nestjs/common';
import { databaseProvider } from './database.provider';

@Module({
  providers: [...databaseProvider],
  exports: [...databaseProvider]
})

export class DatabaseModule { }

Great, the last element in this step is adding a database module to our app.module.ts file, so let's open it and make sure your code looks like this.

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DatabaseModule } from './modules/database/database.module';

@Module({
  imports: [
    DatabaseModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

5. Create migrations

Now, we are going to set up the migration file. Let's go to the root file of the project and create a migrate.ts file. Inside this file, we will connect with the database and set an instance of the umzug.

import { Sequelize } from 'sequelize-typescript';
import Umzug = require('umzug');

const sequelize = new Sequelize({
  dialect: 'postgres',
  host: 'YOUR_HOST',
  port: 5432,
  username: 'YOUR_USERNAME',
  password: 'YOUR_PASSWORD',
  database: 'YOUR_DB_NAME'
});

const umzug = new Umzug({
  storage: 'sequelize',
  storageOptions: { sequelize },
  logging: false,
  migrations: {
    params: [
      sequelize,
      sequelize.constructor,
    ],
    path: './src/migrations',
    pattern: /\.ts$/,
  },
});

const task = (process.argv[2] || '').trim();

switch (task) {
  case 'up':
    umzug.up()
      .then((result) => {
        console.log('Migrations up went successful!', result);
        process.exit(0);
      });
    break;
  case 'down':
    umzug.down()
      .then((result) => {
        console.log('Migrations down went successful!', result);
        process.exit(0);
      });
    break;
  default:
    break;
};

Great, now we will create a folder for migrations in the ./src folder. Inside the new folder, we will create two files for the two tables we would like to create in our database. Let's call them 1.1users.ts and 1.2accounts.ts.

In the first file, we will create up() and down() functions. Let's use the following code in the 1.1users.ts file:

import * as Sequelize from 'sequelize';

const tableName = 'Users';

export async function up(i: any) {
  const queryInterface = i.getQueryInterface() as Sequelize.QueryInterface;
  queryInterface.createTable(tableName, {
    id: {
      type: Sequelize.INTEGER,
      allowNull: false,
      autoIncrement: true,
      unique: true,
      primaryKey: true,
    },
    Username: {
      type: Sequelize.CHAR(200),
      allowNull: false,
    },
    Email: {
      type: Sequelize.CHAR(50),
      allowNull: false,
    },
    Password: {
      type: Sequelize.CHAR(250),
      allowNull: false,
    },
  });
};

export async function down(i: any) {
  const queryInterface = i.getQueryInterface() as Sequelize.QueryInterface;
  queryInterface.dropTable(tableName);
}

And code in the 1.2accounts.ts file will be very similar:

import * as Sequelize from 'sequelize';

const tableName = 'Accounts';

export async function up(i: any) {
  const queryInterface = i.getQueryInterface() as Sequelize.QueryInterface;
  queryInterface.createTable(tableName, {
    id: {
      type: Sequelize.INTEGER,
      allowNull: false,
      autoIncrement: true,
      unique: true,
      primaryKey: true,
    },
    Type: {
      type: Sequelize.CHAR(200),
      allowNull: false,
    },
    Name: {
      type: Sequelize.CHAR(200),
      allowNull: false,
    },
    Balance: {
      type: Sequelize.INTEGER,
      allowNull: true,
    },
    UserId: {
      type: Sequelize.INTEGER,
      references: {
        model: 'Users',
        key: 'id',
      },
    },
  });
};

export async function down(i: any) {
  const queryInterface = i.getQueryInterface() as Sequelize.QueryInterface;
  queryInterface.dropTable(tableName);
}

We are almost there, there is just one step to finish.
Let's open package.json file and let's add a new command:

"scripts": {
    "migrate": "ts-node ./migrate.ts",
...
}

Now we are ready to run the migrations.

6. Running migrations

Running migrations is the last step in this lesson. Let's open the console and run the following code to do migrations:

$ npm run migrate up

After it's finished you can check your database in any database tool like DBeaver and you will see two new tables, connected by UserId.

Now, you can check if migrations down work as well. Undoing the migrations works one by one, so if you did migrations for two tables you need to run migrate down twice to undo both tables.

To undo the migration run the following command:

$ npm run migrate down

When it's done you can check if your tables are undone.

Conclusion

Congratulations, you've just finished the first lesson of our Node.js course, and your project is ready for building an API.

In the next lesson, we will be building a registration feature.

If you didn't manage to get the code correctly you can check it out in our Github repository for this lesson:

https://github.com/Duomly/nodejs-backend-bankapp/tree/Nodejs-Course-Lesson1

I hope you like the new skills you got today and will join us for the next lessons.

If you'd like to build the backend in Golang, check out my friend's course right here:

Golang Course

We are also creating a front-end for this application in Angular 9 which you can check here:

Angular Course

Duomly - Programming Online Courses

Thank you for reading,
Anna from Duomly

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .