Skip to main content

Command Palette

Search for a command to run...

Sequelize Folder Structure

Updated
View as Markdown
  1. Introduction
    When building a Node.js application using Sequelize (an ORM for interacting with SQL databases), it's common to organize the code into a structured folder system that reflects the different layers of the application. Here's a common folder structure for Sequelize CRUD (Create, Read, Update, Delete) operations,
    i) /models
    ii) /controllers

    iii) /routes
    iv) /config
    v) /app.js or /server.js

  2. /models
    Contains the Sequelize models, which define the structure of your database tables and the relationships between them.

    Each model file typically represents a database table.

    A common pattern is to have a index.js file in this folder to dynamically load and initialize all models.

     /models
       ├── user.js         # Sequelize model for 'User'
       ├── post.js         # Sequelize model for 'Post'
       └── index.js        # Initializes and exports all models
    
     // user.js (Model Example)
     module.exports = (sequelize, DataTypes) => {
       const User = sequelize.define('User', {
         name: {
           type: DataTypes.STRING,
           allowNull: false
         },
         email: {
           type: DataTypes.STRING,
           allowNull: false,
           unique: true
         }
       });
       return User;
     };
    
     // index.js (Model Initialization)
     const fs = require('fs');
     const path = require('path');
     const Sequelize = require('sequelize');
     const basename = path.basename(__filename);
     const env = process.env.NODE_ENV || 'development';
     const config = require(__dirname + '/../config/config.json')[env];
     const db = {};
    
     const sequelize = new Sequelize(config.database, config.username, config.password, config);
    
     fs.readdirSync(__dirname)
       .filter(file => {
         return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
       })
       .forEach(file => {
         const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
         db[model.name] = model;
       });
    
     Object.keys(db).forEach(modelName => {
       if (db[modelName].associate) {
         db[modelName].associate(db);
       }
     });
    
     db.sequelize = sequelize;
     db.Sequelize = Sequelize;
    
     module.exports = db;
    
  3. /controllers

    Contains logic that responds to incoming requests and interacts with the models. This is where the CRUD operations (Create, Read, Update, Delete) happen.

    Each controller typically maps to a model and defines the methods for handling the operations on the corresponding table (e.g., UserController for the User model).

     /controllers
       ├── userController.js
       └── postController.js
    
     // userController.js (CRUD Example)
     const { User } = require('../models');
    
     // Create a new User
     exports.createUser = async (req, res) => {
       try {
         const user = await User.create(req.body);
         res.status(201).json(user);
       } catch (error) {
         res.status(400).json({ error: error.message });
       }
     };
    
     // Get all Users
     exports.getAllUsers = async (req, res) => {
       try {
         const users = await User.findAll();
         res.status(200).json(users);
       } catch (error) {
         res.status(500).json({ error: error.message });
       }
     };
    
     // Update a User
     exports.updateUser = async (req, res) => {
       try {
         const { id } = req.params;
         const user = await User.findByPk(id);
         if (!user) {
           return res.status(404).json({ error: 'User not found' });
         }
         await user.update(req.body);
         res.status(200).json(user);
       } catch (error) {
         res.status(400).json({ error: error.message });
       }
     };
    
     // Delete a User
     exports.deleteUser = async (req, res) => {
       try {
         const { id } = req.params;
         const user = await User.findByPk(id);
         if (!user) {
           return res.status(404).json({ error: 'User not found' });
         }
         await user.destroy();
         res.status(204).json();
       } catch (error) {
         res.status(500).json({ error: error.message });
       }
     };
    
  4. /routes
    This folder contains the route definitions. Each route typically maps to a controller method for handling a specific HTTP request (GET, POST, PUT, DELETE).

     /routes
       ├── userRoutes.js
       └── postRoutes.js
    
     // userRoutes.js (Route Example)
     const express = require('express');
     const router = express.Router();
     const userController = require('../controllers/userController');
    
     // Routes for User CRUD operations
     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;
    
  5. /config

    This folder contains configuration files, such as database configurations for different environments (development, production, testing).

     /config
       └── config.json
    
     # config.json (Example)
     {
       "development": {
         "username": "root",
         "password": null,
         "database": "database_dev",
         "host": "127.0.0.1",
         "dialect": "mysql"
       },
       "test": {
         "username": "root",
         "password": null,
         "database": "database_test",
         "host": "127.0.0.1",
         "dialect": "mysql"
       },
       "production": {
         "username": "root",
         "password": null,
         "database": "database_prod",
         "host": "127.0.0.1",
         "dialect": "mysql"
       }
     }
    
  6. /app.js or /server.js

    This file initializes the Express server, connects to the database, and loads the routes.

     const express = require('express');
     const app = express();
     const db = require('./models');
     const userRoutes = require('./routes/userRoutes');
    
     app.use(express.json());
     app.use('/api', userRoutes);
    
     db.sequelize.sync().then(() => {
       app.listen(3000, () => {
         console.log('Server is running on port 3000');
       });
     });
    
  7. Complete Folder Structure Example

     /my-sequelize-app
       ├── /models
       ├── /controllers
       ├── /routes
       ├── /config
       ├── /migrations (optional)
       ├── /seeders (optional)
       ├── app.js
       └── package.json
    

    This structure provides a clean separation of concerns, where models handle database interactions, controllers manage business logic, and routes define the API endpoints. This approach keeps the code modular, scalable, and easier to maintain.