ExpressJs

⌘K
  1. Home
  2. Docs
  3. ExpressJs
  4. Typeorm
  5. Configuration

Configuration

1. Project Setup

1.1 Install Node.js

Make sure Node.js is installed on your machine. You can check this by running:

node -v
npm -v

If Node.js is not installed, download and install it from here.

1.2 Create a New Project Directory

Create a new directory for your project:

mkdir typeorm-express-tutorial
cd typeorm-express-tutorial

1.3 Initialize a Node.js Project

Initialize a new Node.js project by running:

npm init -y

This will generate a package.json file in your project directory.

2. Install Required Libraries

2.1 Install Express and TypeORM

Install Express, TypeORM, MySQL driver, and other required libraries:

npm install express typeorm mysql2 dotenv reflect-metadata

2.2 Install Development Dependencies

Install the necessary development tools:

npm install --save-dev nodemon

3. Project Structure

Set up your project structure as follows:

typeorm-express-tutorial/

├── src/
│   ├── entities/
│   │   └── Category.js
│   ├── migrations/
│   ├── routes/
│   │   └── categoryRoutes.js
│   ├── controllers/
│   │   └── categoryController.js
│   ├── data-source.js
│   ├── app.js
│   └── index.js
├── .env
├── package.json
└── nodemon.json

4. Create Entity

4.1 Define the Category Entity

In the src/entities/ directory, create a file named Category.js:

const { EntitySchema } = require('typeorm');

module.exports = new EntitySchema({
    name: 'Category',
    tableName: 'categories',
    columns: {
        id: {
            type: 'int',
            primary: true,
            generated: true,
        },
        name: {
            type: 'varchar',
            nullable: false,
        },
        createdAt: {
            type: 'timestamp',
            createDate: true,
        },
        updatedAt: {
            type: 'timestamp',
            updateDate: true,
        },
    },
});

5. Configure Database Connection

5.1 Create data-source.js

In the src/ directory, create a file named data-source.js to configure the database connection:

require('reflect-metadata');
require('dotenv').config();
const { DataSource } = require('typeorm');
const path = require('path');

// Import entities
const Category = require('./entities/Category');

const dbConfig = {
    type: 'mysql',
    host: process.env.DB_HOST || 'localhost',
    port: parseInt(process.env.DB_PORT, 10) || 3306,
    username: process.env.DB_USERNAME || 'root',
    password: process.env.DB_PASSWORD || '',
    database: process.env.DB_DATABASE || 'mydatabase',
    synchronize: false,
    logging: process.env.DB_LOGGING === 'true',
    entities: [Category],
    migrations: [path.join(__dirname, 'migrations/**/*.js')],
    cli: {
        migrationsDir: 'src/migrations',
    },
};

const AppDataSource = new DataSource(dbConfig);

AppDataSource.initialize()
    .then(() => {
        console.log('Data Source has been initialized!');
    })
    .catch((err) => {
        console.error('Error during Data Source initialization:', err);
    });

module.exports = AppDataSource;

7. Create Express App

7.1 Create app.js

In the src/ directory, create a file named app.js to set up the Express application:

const express = require('express');
const categoryRoutes = require('./routes/categoryRoutes');

const app = express();

app.use(express.json());

// Use routes
app.use('/categories', categoryRoutes);

module.exports = app;

8. Create Routes and Controllers

8.1 Create categoryRoutes.js

In the src/routes/ directory, create a file named categoryRoutes.js:

const express = require('express');
const categoryController = require('../controllers/categoryController');

const router = express.Router();

router.get('/', categoryController.getAllCategories);
router.post('/', categoryController.createCategory);

module.exports = router;

8.2 Create categoryController.js

In the src/controllers/ directory, create a file named categoryController.js:

const AppDataSource = require('../data-source');
const Category = require('../entities/Category');

const getAllCategories = async (req, res) => {
    const categoryRepository = AppDataSource.getRepository(Category.options.name);
    const categories = await categoryRepository.find();
    res.json(categories);
};

const createCategory = async (req, res) => {
    const categoryRepository = AppDataSource.getRepository(Category.options.name);
    const newCategory = categoryRepository.create(req.body);
    const result = await categoryRepository.save(newCategory);
    res.status(201).json(result);
};

module.exports = {
    getAllCategories,
    createCategory,
};

9. Main Entry Point

9.1 Create index.js

In the src/ directory, create index.js to start the server:

const app = require('./app');

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

10. Run the Project

10.1 Update package.json Scripts

Update the scripts section in package.json:

"scripts": {
  "start": "node src/index.js",
  "dev": "nodemon src/index.js",
  "migration:generate": "typeorm migration:generate -n",
  "migration:run": "typeorm migration:run",
  "migration:revert": "typeorm migration:revert"
}

10.2 Create nodemon.json

In the root directory, create nodemon.json to automatically restart the server during development:

{
  "watch": ["src"],
  "ext": "js",
  "exec": "node src/index.js"
}

11. Generate and Run Migrations

11.1 Generate a Migration

To generate a migration based on your entity:

npm run migration:generate -- -n CreateCategoryTable

11.2 Run Migrations

To apply the generated migration:

npm run migration:run

12. Document API with Swagger

12.1 Install Swagger Libraries

Install Swagger libraries:

npm install swagger-jsdoc swagger-ui-express

12.2 Set Up Swagger in app.js

Add Swagger setup to app.js:

const swaggerJsDoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');

const swaggerOptions = {
    swaggerDefinition: {
        openapi: '3.0.0',
        info: {
            title: 'Category API',
            version: '1.0.0',
            description: 'API documentation for Category management',
        },
    },
    apis: ['./src/routes/*.js'],
};

const swaggerDocs = swaggerJsDoc(swaggerOptions);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));

if index.js or app.js in src folder then like below

const express = require('express');
const swaggerJsDoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');
const categoryRoutes = require('./routes/categoryRoutes');

const app = express();

app.use(express.json());

// Swagger setup
const swaggerOptions = {
    swaggerDefinition: {
        openapi: '3.0.0',
        info: {
            title: 'Category API',
            version: '1.0.0',
            description: 'API documentation for Category management',
        },

        components: {
            schemas: {
                Category: {
                    type: 'object',
                    properties: {
                        id: {
                            type: 'integer',
                            description: 'Category ID',
                            example: 1,
                        },
                        name: {
                            type: 'string',
                            description: 'Category name',
                            example: 'Electronics',
                        },
                        createdAt: {
                            type: 'string',
                            format: 'date-time',
                            description: 'Timestamp when the category was created',
                            example: '2024-08-25T13:00:00.000Z',
                        },
                        updatedAt: {
                            type: 'string',
                            format: 'date-time',
                            description: 'Timestamp when the category was last updated',
                            example: '2024-08-25T13:00:00.000Z',
                        },
                    },
                },
            },
        },
    
    },
    apis: [path.join(__dirname, './routes/*.js')], // Corrected path to routes
};

const swaggerDocs = swaggerJsDoc(swaggerOptions);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));

// Use routes
app.use('/categories', categoryRoutes);

module.exports = app;

Category Routes

In the src/routes/categoryRoutes.js file, we will define the routes for the Category entity and add Swagger documentation annotations

const express = require('express');
const categoryController = require('../controllers/categoryController');

const router = express.Router();

/**
 * @swagger
 * tags:
 *   name: Categories
 *   description: API for managing categories
 */

/**
 * @swagger
 * /categories:
 *   get:
 *     summary: Get all categories
 *     tags: [Categories]
 *     responses:
 *       200:
 *         description: List of categories
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items:
 *                 $ref: '#/components/schemas/Category'
 */
router.get('/', categoryController.getAllCategories);

/**
 * @swagger
 * /categories:
 *   post:
 *     summary: Create a new category
 *     tags: [Categories]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/Category'
 *     responses:
 *       201:
 *         description: The category was successfully created
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Category'
 */
router.post('/', categoryController.createCategory);

module.exports = router;

Category Controller

In the src/controllers/categoryController.js file, we will define the logic for handling the routes.

const AppDataSource = require('../data-source');
const Category = require('../entities/Category');

const getAllCategories = async (req, res) => {
    try {
        const categoryRepository = AppDataSource.getRepository(Category.options.name);
        const categories = await categoryRepository.find();
        res.json(categories);
    } catch (error) {
        res.status(500).json({ error: 'An error occurred while fetching categories' });
    }
};

const createCategory = async (req, res) => {
    try {
        const categoryRepository = AppDataSource.getRepository(Category.options.name);
        const newCategory = categoryRepository.create(req.body);
        const result = await categoryRepository.save(newCategory);
        res.status(201).json(result);
    } catch (error) {
        res.status(500).json({ error: 'An error occurred while creating the category' });
    }
};

module.exports = {
    getAllCategories,
    createCategory,
};

13. Run the Application

Finally, start the development server:

npm run dev

Create a Swagger Configuration Module

Create a new file named swaggerConfig.js (or any name you prefer) in your src directory. This file will contain the Swagger setup code.

const swaggerJsDoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');
const path = require('path');

const swaggerOptions = {
    swaggerDefinition: {
        openapi: '3.0.0',
        info: {
            title: 'API Documentation',
            version: '1.0.0',
            description: 'API documentation for Category, SubCategory, and Product management',
        },
        components: {
            schemas: {
                Category: {
                    type: 'object',
                    properties: {
                        id: { type: 'integer', description: 'Category ID', example: 1 },
                        name: { type: 'string', description: 'Category name', example: 'Electronics' },
                        createdAt: { type: 'string', format: 'date-time', description: 'Creation timestamp', example: '2024-08-25T13:00:00.000Z' },
                        updatedAt: { type: 'string', format: 'date-time', description: 'Update timestamp', example: '2024-08-25T13:00:00.000Z' },
                    },
                },
                SubCategory: {
                    type: 'object',
                    properties: {
                        id: { type: 'integer', description: 'SubCategory ID', example: 1 },
                        name: { type: 'string', description: 'SubCategory name', example: 'Smartphones' },
                        createdAt: { type: 'string', format: 'date-time', description: 'Creation timestamp', example: '2024-08-25T13:00:00.000Z' },
                        updatedAt: { type: 'string', format: 'date-time', description: 'Update timestamp', example: '2024-08-25T13:00:00.000Z' },
                        category: { $ref: '#/components/schemas/Category' },
                    },
                },
                Product: {
                    type: 'object',
                    properties: {
                        id: { type: 'integer', description: 'Product ID', example: 1 },
                        name: { type: 'string', description: 'Product name', example: 'Smartphone XYZ' },
                        price: { type: 'number', format: 'float', description: 'Product price', example: 299.99 },
                        createdAt: { type: 'string', format: 'date-time', description: 'Creation timestamp', example: '2024-08-25T13:00:00.000Z' },
                        updatedAt: { type: 'string', format: 'date-time', description: 'Update timestamp', example: '2024-08-25T13:00:00.000Z' },
                        category: { $ref: '#/components/schemas/Category' },
                        subCategory: { $ref: '#/components/schemas/SubCategory' },
                    },
                },
            },
        },
    },
    apis: [path.join(__dirname, './routes/*.js')], // Adjust path as needed
};

const swaggerDocs = swaggerJsDoc(swaggerOptions);

const setupSwagger = (app) => {
    app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));
};

module.exports = setupSwagger;

How can we help?