How to Set Up a Node.js Express App with Sequelize and AWS MySQL RDS + Source Code
Two Ways to Get Started:
1️⃣ Follow the step-by-step guide in the tutorial above.
2️⃣ Download the source code and practice at your own pace.
🚀 An exciting journey awaits—let’s begin!
Introduction
In this post, we will:
- Define Sequelize models for User and Post tables.
- Set up the routes, controllers, and services to handle CRUD operations.
- Maintain a clean and scalable code structure by separating concerns into different folders.
Let’s dive in and organize our code to make it more maintainable!
Step 1: Define Sequelize Models (Tables)
Sequelize models represent the structure of the database tables. Let’s start by defining the models for User and Post.
1.1. Create the User Model
In the models folder, create a file named User.js:
// src/models/User.js
const { DataTypes } = require('sequelize');
const sequelize = require('../db');
const User = sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
username: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
});
module.exports = User;
This model defines the User table with id, username, and email fields.
1.2. Create the Post Model
Next, create a Post.js file in the models folder:
// src/models/Post.js
const { DataTypes } = require('sequelize');
const sequelize = require('../db');
const User = require('./User'); // Reference to User model
const Post = sequelize.define('Post', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
content: {
type: DataTypes.TEXT,
allowNull: false,
},
});
// Define relationship: One User has many Posts
Post.belongsTo(User, { foreignKey: 'userId' });
module.exports = Post;
This defines the Post model with title, content, and a relationship to the User model.
Step 2: Create Routes, Controllers, and Services
To maintain clean and scalable code, we will separate the application logic into routes, controllers, and services.
2.1. Folder Structure
Let’s organize the folders as follows:
/src
/controllers
userController.js
postController.js
/routes
userRoutes.js
postRoutes.js
/services
userService.js
postService.js
/models
User.js
Post.js
app.js
2.2. Create Services for Business Logic
The service layer will handle the actual business logic, such as interacting with the database.
userService.js
Create the services/userService.js file:
// services/userService.js
const User = require('../models/User');
const createUser = async (username, email) => {
const user = await User.create({ username, email });
return user;
};
const getAllUsers = async () => {
const users = await User.findAll();
return users;
};
const getUserById = async (id) => {
const user = await User.findByPk(id);
return user;
};
const updateUser = async (id, username, email) => {
const user = await User.findByPk(id);
if (user) {
user.username = username;
user.email = email;
await user.save();
return user;
}
return null;
};
const deleteUser = async (id) => {
const user = await User.findByPk(id);
if (user) {
await user.destroy();
return true;
}
return false;
};
module.exports = {
createUser,
getAllUsers,
getUserById,
updateUser,
deleteUser,
};
postService.js
Create the services/postService.js file:
javascript
Copy
// services/postService.js
const Post = require('../models/Post');
const createPost = async (title, content, userId) => {
const post = await Post.create({ title, content, userId });
return post;
};
const getAllPosts = async () => {
const posts = await Post.findAll();
return posts;
};
const getPostById = async (id) => {
const post = await Post.findByPk(id);
return post;
};
const updatePost = async (id, title, content) => {
const post = await Post.findByPk(id);
if (post) {
post.title = title;
post.content = content;
await post.save();
return post;
}
return null;
};
const deletePost = async (id) => {
const post = await Post.findByPk(id);
if (post) {
await post.destroy();
return true;
}
return false;
};
module.exports = {
createPost,
getAllPosts,
getPostById,
updatePost,
deletePost,
};
2.3. Create Controllers for Handling Requests
The controller layer will handle HTTP requests and interact with the services.
userController.js
Create the controllers/userController.js file:
javascript
Copy
// controllers/userController.js
const userService = require('../services/userService');
const createUser = async (req, res) => {
const { username, email } = req.body;
try {
const user = await userService.createUser(username, email);
res.status(201).json(user);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const getAllUsers = async (req, res) => {
try {
const users = await userService.getAllUsers();
res.status(200).json(users);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const updateUser = async (req, res) => {
const { id } = req.params;
const { username, email } = req.body;
try {
const user = await userService.updateUser(id, username, email);
if (user) {
res.status(200).json(user);
} else {
res.status(404).json({ message: 'User not found' });
}
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const deleteUser = async (req, res) => {
const { id } = req.params;
try {
const success = await userService.deleteUser(id);
if (success) {
res.status(200).json({ message: 'User deleted' });
} else {
res.status(404).json({ message: 'User not found' });
}
} catch (error) {
res.status(500).json({ message: error.message });
}
};
module.exports = {
createUser,
getAllUsers,
updateUser,
deleteUser,
};
postController.js
Create the controllers/postController.js file:
// controllers/postController.js
const postService = require('../services/postService');
const createPost = async (req, res) => {
const { title, content, userId } = req.body;
try {
const post = await postService.createPost(title, content, userId);
res.status(201).json(post);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const getAllPosts = async (req, res) => {
try {
const posts = await postService.getAllPosts();
res.status(200).json(posts);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const updatePost = async (req, res) => {
const { id } = req.params;
const { title, content } = req.body;
try {
const post = await postService.updatePost(id, title, content);
if (post) {
res.status(200).json(post);
} else {
res.status(404).json({ message: 'Post not found' });
}
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const deletePost = async (req, res) => {
const { id } = req.params;
try {
const success = await postService.deletePost(id);
if (success) {
res.status(200).json({ message: 'Post deleted' });
} else {
res.status(404).json({ message: 'Post not found' });
}
} catch (error) {
res.status(500).json({ message: error.message });
}
};
module.exports = {
createPost,
getAllPosts,
updatePost,
deletePost,
};
2.4. Create Routes for the API
Now, let's define the routes to connect the controllers to our app.
userRoutes.js
Create the routes/userRoutes.js file:
// routes/userRoutes.js
const express = require('express');
const userController = require('../controllers/userController');
const router = express.Router();
router.post('/users', userController.createUser);
router.get('/users', userController.getAllUsers);
router.put('/users/:id', userController.updateUser);
router.delete('/users/:id', userController.deleteUser);
module.exports = router;
postRoutes.js
Create the routes/postRoutes.js file:
javascript
Copy
// routes/postRoutes.js
const express = require('express');
const postController = require('../controllers/postController');
const router = express.Router();
router.post('/posts', postController.createPost);
router.get('/posts', postController.getAllPosts);
router.put('/posts/:id', postController.updatePost);
router.delete('/posts/:id', postController.deletePost);
module.exports = router;
Step 3: Set Up Express Application and Routes
Finally, let’s bring everything together in the app.js file:
// app.js
const express = require('express');
const sequelize = require('./db');
const userRoutes = require('./routes/userRoutes');
const postRoutes = require('./routes/postRoutes');
const app = express();
const port = 3000;
app.use(express.json());
app.use(userRoutes);
app.use(postRoutes);
sequelize.authenticate().then(() => {
console.log('Database connected successfully!');
}).catch((error) => {
console.error('Unable to connect to the database:', error);
});
sequelize.sync({ force: true }).then(() => {
console.log('Database synced');
});
app.listen(port, () => {
console.log(`App running at http://localhost:${port}`);
});
Step 4: Test Your CRUD Endpoints
Now that we’ve defined the models and set up CRUD operations, let’s test everything using Postman or cURL:
- POST /users: Create a new user.
- GET /users: Get all users.
- PUT /users/🆔 Update a user by id.
- DELETE /users/🆔 Delete a user by id.
- POST /posts: Create a new post.
- GET /posts: Get all posts.
DOWNLOAD SOURCE CODE 'crud' BRANCH
Conclusion
In this post, we’ve:
- Defined Sequelize models for User and Post.
- Created routes, controllers, and services to handle CRUD operations.
- Structured the code into separate folders for routes, controllers, and services to maintain a clean and scalable architecture.
In the next post, we’ll explore authentication, authorization, and deployment.
Top comments (0)