CRUD API dengan Node.js, Express, dan MySQL
CRUD API dengan Node.js, Express, dan MySQL
1. Struktur Project
crud-app/
├── src/
│ ├── config/
│ │ └── database.js
│ ├── controllers/
│ │ └── productController.js
│ ├── models/
│ │ └── productModel.js
│ ├── routes/
│ │ └── productRoutes.js
│ └── app.js
├── .env
└── package.json
2. Instalasi Dependencies
mkdir crud-app
cd crud-app
npm init -y
# Install dependencies
npm install express mysql2 dotenv cors
npm install --save-dev nodemon
3. Database Setup
CREATE DATABASE crud_db;
USE crud_db;
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
stock INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
4. Konfigurasi Environment
# .env
PORT=3000
DB_HOST=127.0.0.1
DB_USER=root
DB_PASSWORD=yourpassword
DB_NAME=crud_db
5. Database Configuration
// src/config/database.js
const mysql = require('mysql2');
require('dotenv').config();
const pool = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
});
module.exports = pool.promise();
6. Product Model
// src/models/productModel.js
const db = require('../config/database');
class Product {
static async findAll() {
try {
const [rows] = await db.query('SELECT * FROM products');
return rows;
} catch (error) {
throw error;
}
}
static async findById(id) {
try {
const [rows] = await db.query('SELECT * FROM products WHERE id = ?', [id]);
return rows[0];
} catch (error) {
throw error;
}
}
static async create(data) {
try {
const [result] = await db.query(
'INSERT INTO products (name, price, stock) VALUES (?, ?, ?)',
[data.name, data.price, data.stock]
);
return result.insertId;
} catch (error) {
throw error;
}
}
static async update(id, data) {
try {
const [result] = await db.query(
'UPDATE products SET name = ?, price = ?, stock = ? WHERE id = ?',
[data.name, data.price, data.stock, id]
);
return result.affectedRows > 0;
} catch (error) {
throw error;
}
}
static async delete(id) {
try {
const [result] = await db.query('DELETE FROM products WHERE id = ?', [id]);
return result.affectedRows > 0;
} catch (error) {
throw error;
}
}
}
module.exports = Product;
7. Product Controller
// src/controllers/productController.js
const Product = require('../models/productModel');
class ProductController {
// Get all products
static async getProducts(req, res) {
try {
const products = await Product.findAll();
res.json({
status: 'success',
data: products
});
} catch (error) {
res.status(500).json({
status: 'error',
message: error.message
});
}
}
// Get single product
static async getProduct(req, res) {
try {
const product = await Product.findById(req.params.id);
if (!product) {
return res.status(404).json({
status: 'error',
message: 'Product not found'
});
}
res.json({
status: 'success',
data: product
});
} catch (error) {
res.status(500).json({
status: 'error',
message: error.message
});
}
}
// Create product
static async createProduct(req, res) {
try {
const { name, price, stock } = req.body;
// Validasi input
if (!name || !price || !stock) {
return res.status(400).json({
status: 'error',
message: 'Please provide name, price and stock'
});
}
const productId = await Product.create({ name, price, stock });
res.status(201).json({
status: 'success',
message: 'Product created successfully',
data: { id: productId }
});
} catch (error) {
res.status(500).json({
status: 'error',
message: error.message
});
}
}
// Update product
static async updateProduct(req, res) {
try {
const { name, price, stock } = req.body;
const updated = await Product.update(req.params.id, { name, price, stock });
if (!updated) {
return res.status(404).json({
status: 'error',
message: 'Product not found'
});
}
res.json({
status: 'success',
message: 'Product updated successfully'
});
} catch (error) {
res.status(500).json({
status: 'error',
message: error.message
});
}
}
// Delete product
static async deleteProduct(req, res) {
try {
const deleted = await Product.delete(req.params.id);
if (!deleted) {
return res.status(404).json({
status: 'error',
message: 'Product not found'
});
}
res.json({
status: 'success',
message: 'Product deleted successfully'
});
} catch (error) {
res.status(500).json({
status: 'error',
message: error.message
});
}
}
}
module.exports = ProductController;
8. Product Routes
// src/routes/productRoutes.js
const express = require('express');
const router = express.Router();
const ProductController = require('../controllers/productController');
// Routes
router.get('/products', ProductController.getProducts);
router.get('/products/:id', ProductController.getProduct);
router.post('/products', ProductController.createProduct);
router.put('/products/:id', ProductController.updateProduct);
router.delete('/products/:id', ProductController.deleteProduct);
module.exports = router;
9. Express App Setup
// src/app.js
const express = require('express');
const cors = require('cors');
require('dotenv').config();
const productRoutes = require('./routes/productRoutes');
const app = express();
// Middleware
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Routes
app.use('/api', productRoutes);
// Error handling
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({
status: 'error',
message: 'Something broke!'
});
});
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
10. Package.json Scripts
tambahkan berikut di package.json
{
"scripts": {
"start": "node src/app.js",
"dev": "nodemon src/app.js"
}
}
hasil akhirnya
{
"name": "crud_app",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node src/app.js",
"dev": "nodemon src/app.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.4.7",
"express": "^4.21.1",
"mysql2": "^3.11.5"
},
"devDependencies": {
"nodemon": "^3.1.7"
}
}
cara running nya
npm run dev
11. Testing API dengan Postman
GET All Products
GET http://localhost:3000/api/products
GET Single Product
GET http://localhost:3000/api/products/1
Create Product
POST http://localhost:3000/api/products
Content-Type: application/json
{
"name": "Product 1",
"price": 99.99,
"stock": 100
}
Update Product
PUT http://localhost:3000/api/products/1
Content-Type: application/json
{
"name": "Updated Product",
"price": 149.99,
"stock": 75
}
Delete Product
DELETE http://localhost:3000/api/products/1
Last updated