Are you ready to embark on a journey to create a secure and efficient Express REST API? Fasten your seatbelts as we delve into creating a robust API featuring JWT authentication support and the flexibility of using SQLite, MySQL, or PostgreSQL. This guide will help you install, use, and troubleshoot your new API boilerplate.
Table of Contents
Install & Use
Getting started is easy! Follow these steps to set up your Express REST API:
sh
# Clone the repository
git clone https://github.com/aichbauer/express-rest-api-boilerplate.git
# Change into project root
cd express-rest-api-boilerplate
# Install dependencies
yarn
# Choose your database
# For MySQL
yarn add mysql2
# For PostgreSQL
yarn add pg pg-hstore
# Start the API
yarn start
For those who prefer npm:
sh
# Change into project root
cd express-rest-api-boilerplate
# Install dependencies
npm i
# For MySQL
npm i mysql2 -S
# For PostgreSQL
npm i -S pg pg-hstore
# Start the API
npm start
SQLite is supported out of the box as it is the default.
Folder Structure
Here’s a quick breakdown of your project directories:
- api – contains controllers, models, services, etc.
- config – contains routes and database configurations.
- db – solely for the SQLite database, default for NODE_ENV development.
- test – has integration tests using Jest.
Controllers
Controllers handle the incoming requests and returning responses. In this boilerplate, controllers are named in the format ModelnameController.js and employ an object factory pattern.
Create a Controller
Controllers manage CRUD operations. Here’s an analogy to help you understand:
Imagine a restaurant where each type of cuisine corresponds to a different Model. The Chef (Controller) prepares meals (CRUD actions) based on the customer’s orders (requests). If a dish is requested, the Chef gathers ingredients (data) and serves the finished dish (response) accurately, ensuring the customers leave satisfied.
js
const Model = require('../models/Model');
const ModelController = () => {
const create = async (req, res) => {
const value = req.body;
try {
const model = await Model.create({ key: value });
if (!model) return res.status(400).json({ msg: 'Bad Request: Model not found' });
return res.status(200).json(model);
} catch (err) {
console.error(err);
return res.status(500).json({ msg: 'Internal server error' });
}
};
// Similar structure for getAll, get, update, and destroy.
return { create, getAll, get, update, destroy };
};
module.exports = ModelController;
Models
Models represent the data of your application. They’re defined using Sequelize. The structure is similar to the protocol of a sports team:
Each model (player) has strengths (attributes like username, password). The coach (Sequelize) ensures players (models) stick to their positions (definitions) while creating team strategies (queries). Here’s how you define a User model:
js
const Sequelize = require('sequelize');
const bcryptService = require('../services/bcrypt.service');
const sequelize = require('../config/database');
const User = sequelize.define('User', {
username: {
type: Sequelize.STRING,
unique: true,
},
password: {
type: Sequelize.STRING,
},
}, {
hooks: {
beforeCreate: (user) => {
user.password = bcryptService.password(user);
}
}
});
User.prototype.toJSON = function () {
const values = Object.assign({}, this.get());
delete values.password; // omitting sensitive data
return values;
};
module.exports = User;
Policies
Policies act as gatekeepers, ensuring that only authorized users access certain routes. Similar to a security system at an event, they check credentials before entry.
js
module.exports = (req, res, next) => {
if (req.body.userRole === 'admin') {
// some verification logic
return next();
}
return res.status(401).json({ msg: 'Unauthorized' });
};
Services
Services hold snippets of useful code or API calls that complement your API’s functionality. They are like helpers or assistants that aid the main chef (API) in providing a well-rounded meal (response).
js
const commentService = () => {
const getComments = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/comments', {
method: 'GET'
});
return response.json();
} catch (err) {
console.error(err); // handle error
}
};
return { getComments };
};
module.exports = commentService;
Config
The configuration folder contains all server settings, including database connections. Just like setting up a stage for a play, ensure all actors (settings) are in their appropriate places.
Connection and Database
To connect to a database, modify the connection.js
file according to your needs. Don’t forget to set environment variables for production before launching!
Routes
Routes define how your application responds to client requests. They are like the map of a city, guiding users to their desired destinations (resources).
Create Routes
Use routes to structure how your API interacts with clients:
js
const userRoutes = {
POST: '/user': UserController.create,
GET: '/users': UserController.getAll,
GET: '/user:id': UserController.get,
PUT: '/user:id': UserController.update,
DELETE: '/user:id': UserController.destroy,
};
module.exports = userRoutes;
Test
Testing is crucial to ensure that everything works as expected. Tests are like dress rehearsals, identifying discrepancies before the actual show.
Setup
Setup directory holds the _setup.js
for initializing and tearing down your test environment.
npm Scripts
Your boilerplate uses npm scripts as tools to automate tasks. Think of them as your assistants, making sure everything runs smoothly.
Key npm commands:
- npm start – Starts the server with development settings.
- npm test – Runs the defined tests.
- npm run production – Prepares your API for production deployment.
Troubleshooting
If you encounter issues, here are some troubleshooting ideas:
- Check if all dependencies are installed correctly.
- Ensure your database servers (MySQL/PostgreSQL) are running.
- Verify your environment variables are set correctly, especially for production.
- If you have issues with JWT authentication, confirm that you’re sending the correct token in the headers.
For more insights, updates, or to collaborate on AI development projects, stay connected with fxis.ai.
At fxis.ai, we believe that such advancements are crucial for the future of AI, as they enable more comprehensive and effective solutions. Our team is continually exploring new methodologies to push the envelope in artificial intelligence, ensuring that our clients benefit from the latest technological innovations.