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;