Building a RESTful micro-service API using NodeJS + TypeScript + ExpressJS + Prisma — Part 1
Let’s start an exciting journey together in building a fully functional RESTful API micro-service from scratch. But before we begin, we must write down the project requirements so that we know what we are trying to build.
User Stories
Here are few simple user stories I could come up with —
- As a user, I shall be able to register myself by creating a new account in the system.
- As a user, I will have to activate my account by using the activation link sent to my email address before using the various api services.
- As a registered and activated user, I shall be able to login into the system using my valid credentials.
- As an authenticated user, I shall be able to add or modify my shopping preferences in my account.
- As a user, I shall be able to reset my password.
- As an authenticated user, I shall be able to see my personal details including my preferences in the system database.
- As an authenticated user, I shall be able to delete my account in the system permanently.
So, these are our 7 lucky requirements. Sweet!
Development Stack
We will use the following pieces of software to build our solution :
1. Node.js
Node.js is an open source back-end JavaScript runtime environment built on Chrome’s v8 engine. Thanks to its simple architecture, building a full fledged web application has never been so easy.
2. Express.JS
We use Express as our web framework of choice because its simple, lightweight and has robust set of features that makes building web APIs super easy.
3. TypsScript
We all know that complex JavaScript code can be hard to maintain due to its lack of debugging support and IDE capabilities. With TypeScript we could bring the type safety to our development workflow and catch most errors at the IDE level before we could even deploy the application. TypeScript is a superset of JavaScript with its open-source compiler and has a rich type system which includes interfaces, enums, hybrid types, generics, union/intersection types, access modifiers and much more. Development experience with TypeScript is a big improvement over JavaScript.
4. Class-Validator / Class-Transformer
We will use these packages to validate user data using data transfer objects or DTOs. There are other cool validation packages like Zod or Joi which you may use but I prefer using class-validator’s decorators which help to keep the validation logic close to our data transfer object properties.
5. Prisma
Prisma is an open-source TypeScript ORM with a rich set of tooling that helps write faster code. Prisma has integration with major database like PostgreSQL, SQL Server, SQLite and even MongoDB. Although I may not consider it as a full blown ORM (Object Relational Mapping) but it surely helps minimize errors in code, thanks to its three basic components — Prisma Client, Prisma Migrate and Prisma Studio. We will go through each of these in the subsequent sections.
6. Database
For database we will use Sqlite in this tutorial. But for production you may want to use PostgreSQL or SQL Server. Make sure you change the DB_URL config in the .env file of the project in such a case.
Did you know that Sqlite is the most used database in the world?
7. Visual Studio Code
Unless you have been living in a cave for the last couple of years, you would know that VS Code is a super cool, multi-platform code editor of choice made by Microsoft and its completely free to use. Although since the last 10 years I have been primarily a Linux and Mac user; no shame in using a good product from Microsoft. What say?
Setup
If you do not have node and npm already installed on your system, I suggest you do it right now and then come back to continue with this tutorial. Follow the official page for installation instructions.
Type the following in the Terminal or Command prompt depending on your operating system. This will create an empty project directory where the real magic will happen.
mkdir node-api-demo && cd node-api-demo
Next we will initialize a node project inside the newly created folder. This command will prompt for a number of details. Press enter to accept the defaults for now.
npm init
If you look closely, you will see a package.json file created inside the folder. It will look something like this. You could modify this file anytime directly from the IDE.
Then we will install TypeScript using the following command.
npm i typescript --save-dev
Make sure you include the save-dev flag because it adds typescript as a development dependency.
Type the following command to initialize a typescript project. It will create a tsconfig.json file inside the project folder. This file contains a lot of typescript compiler options which we will get back to later.
npx typescript --init
The above command may not work for some users and may cause error. In such cases, try the following command instead.
npx -p typescript tsc --init
We shall now install all the dependencies that are required to build our awesome web api micro-service.
npm i express dayjs cors bcrypt config cookie-parser jsonwebtoken lodash nanoid pino pino-pretty class-validator class-transformer reflect-metadata
We will need the following development dependencies as well.
npm i @types/express @types/jsonwebtoken @types/bcrypt @types/body-parser @types/config @types/cookie-parser @types/cors @types/lodash @types/nanoid @types/node @types/pino ts-node --save-dev
If you look at the file package.json now, you should find these dependencies were added to the file automatically. Isn’t that cool? Now we are almost ready to start coding.
So let’s create a source directory and our first typescript file.
mkdir src && touch src/server.ts
It is very cumbersome to restart a service every time you change code. To make this task seamless, we will use another tool called nodemon. It automatically restarts node server when file changes are detected in a specific directory viz. /src. To install nodemon, use the following command.
npm i nodemon
We need to add a nodemon.json file at the same level as package.json and insert the following snippet.
Now, update the package.json file to enable nodemon.
Finally run the node app to check if the project is setup correctly.
npm run dev
Yay! Congratulations, you made it this far. If the server starts without any error, our setup is complete.
Before we go any further, we need to discuss how we should structure our code and decide about the architectural patterns on which we shall build our software.
Architecture
I am sure you have already heard of MVC (model-view-controler) architectural pattern which is used to develop modern day applications. Each architecture component is assigned to handle specific developmental aspect of the app. MVC separates the business logic from the presentation layer. This separation of concerns means the code is more testable and easy to maintain.
I shall also introduce a Service Layer into the mix. A service layer handles the core business logic of the application. It also interacts with the back-end database systems and acts as facade to the Controller layer. This will help to keep the Controller lean and tidy. Some of you may argue that a service layer should be a part of the Model layer itself, but for this demo we shall treat them as separate components.
Project Structure
As the project grows in size, it becomes critical that the code is organized and related files stay together. We will structure our project folder in the following manner.
This is self explanatory and I shall not go in details on which files goes where. But as you may observe, I have grouped the controllers and service classes inside the respective domains like /user, /auth, etc. For larger projects with large number of controllers & services, its advisable to put all controllers in a /controllers folder and all service classes inside a separate /services folder. This will keep the outer package less crowded and more organized.
This brings us to the end of Part 1 of this tutorial where we build an awesome micro-service API using Node.js and Typescript technology. In the next part of this tutorial, we deep dive into the nitty-gritty of creating our first models using Prisma ORM toolkit. See you there.