මෙම project එකේ අරමුණ වන්නේ, පසුගිය modules වලින් අප ඉගෙන ගත් සියලුම දේ (Express, MongoDB, Mongoose, JWT Authentication, Error Handling, Validation) ප්රායෝගිකව යොදාගෙන, සම්පූර්ණ backend API එකක් මුල සිට ගොඩනැගීමයි.
අප නිර්මාණය කරන Notes API එකේ ප්රධාන features:
හොඳ project එකකදී code එක ක්රමවත්ව සංවිධානය කිරීම ඉතා වැදගත් වේ. අපි පහත folder structure එක භාවිතා කරමු:
/notes-api |-- /config | |-- db.js # Database connection logic |-- /middleware | |-- auth.js # JWT authentication middleware | |-- errorHandler.js # Custom error handler |-- /models | |-- Note.js # Note Mongoose model | |-- User.js # User Mongoose model |-- /routes | |-- auth.js # Authentication routes (register, login) | |-- notes.js # CRUD routes for notes |-- .env # Environment variables (DB URI, JWT Secret) |-- .gitignore # Git ignore file |-- package.json |-- server.js # Main server entry point
Terminal එකේ පහත commands run කරන්න:
mkdir notes-api
cd notes-api
npm init -y
npm install express mongoose bcryptjs jsonwebtoken dotenv joi
npm install --save-dev nodemon
ඔබේ package.json
file එකේ, "scripts" කොටසට "start": "node server.js"
සහ "dev": "nodemon server.js"
ලෙස එකතු කරගන්න.
ඉහත පෙන්වා ඇති පරිදි config
, middleware
, models
, සහ routes
folders සාදාගන්න.
Project එකේ root එකේ .env
නමින් file එකක් සාදා, ඔබේ MongoDB connection string එක සහ JWT secret key එක ඇතුළත් කරන්න.
.env
file එක:
MONGO_URI=mongodb://localhost:27017/notesApiProject
JWT_SECRET=thisisareallylongandsecuresecretkey
PORT=5000
⚠️ වැදගත්: .gitignore
file එකක් සාදා, එහි node_modules
සහ .env
යන දෙකම ඇතුළත් කරන්න. .env
file එකේ ඇති රහස්ය තොරතුරු කිසිවිටෙකත් Git repository එකකට commit නොකළ යුතුය.
config/db.js
)
const mongoose = require('mongoose');
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGO_URI);
console.log('MongoDB Connected...');
} catch (err) {
console.error(err.message);
process.exit(1); // Exit process with failure
}
};
module.exports = connectDB;
models/User.js
& models/Note.js
)User model එක අපි 7 වන module එකේදී සාදන ලදී. Note model එකට, එය කුමන user ට අයිතිද යන්න track කිරීමට `user` field එකක් එකතු කරමු.
models/Note.js
file එක:
const mongoose = require('mongoose');
const NoteSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User', // 'User' model එකට සම්බන්ධ කිරීම
required: true,
},
title: {
type: String,
required: true,
trim: true,
},
content: {
type: String,
required: true,
},
createdAt: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model('Note', NoteSchema);
Module 7 සහ 8 හි නිර්මාණය කළ middleware/auth.js
සහ middleware/errorHandler.js
files ඒ ආකාරයෙන්ම භාවිතා කළ හැක.
routes/auth.js
file එක:
Module 7 හි JWT සහ bcrypt සමඟ නිර්මාණය කළ registration සහ login routes මෙහි ඇතුළත් කරන්න.
routes/notes.js
file එක:
මෙය අපේ project එකේ ප්රධානතම කොටසයි. මෙහිදී අපි note එකක් create, read, update, සහ delete කිරීමේදී, `auth` middleware එක යොදාගෙන, login වූ user ට පමණක් එම ක්රියාවන් කිරීමට ඉඩ ලබා දෙනවා.
const express = require('express');
const router = express.Router();
const auth = require('../middleware/auth');
const Note = require('../models/Note');
const Joi = require('joi');
// Note validation schema
const noteSchema = Joi.object({
title: Joi.string().min(3).required(),
content: Joi.string().min(5).required(),
});
// @route POST api/notes
// @desc Create a new note
// @access Private
router.post('/', auth, async (req, res, next) => {
try {
await noteSchema.validateAsync(req.body);
const { title, content } = req.body;
const newNote = new Note({
user: req.user.id,
title,
content,
});
const note = await newNote.save();
res.status(201).json(note);
} catch (error) {
if (error.isJoi) return res.status(400).json({ message: error.details[0].message });
next(error);
}
});
// @route GET api/notes
// @desc Get all notes for a user
// @access Private
router.get('/', auth, async (req, res, next) => {
try {
const notes = await Note.find({ user: req.user.id }).sort({ createdAt: -1 });
res.json(notes);
} catch (err) {
next(err);
}
});
// @route PUT api/notes/:id
// @desc Update a note
// @access Private
router.put('/:id', auth, async (req, res, next) => {
try {
await noteSchema.validateAsync(req.body);
let note = await Note.findById(req.params.id);
if (!note) return res.status(404).json({ message: 'Note not found' });
// User තමන්ගේම note එකක් update කරනවාදැයි පරීක්ෂා කිරීම
if (note.user.toString() !== req.user.id) {
return res.status(401).json({ message: 'Not authorized' });
}
note = await Note.findByIdAndUpdate(req.params.id, { $set: req.body }, { new: true });
res.json(note);
} catch (error) {
if (error.isJoi) return res.status(400).json({ message: error.details[0].message });
next(error);
}
});
// @route DELETE api/notes/:id
// @desc Delete a note
// @access Private
router.delete('/:id', auth, async (req, res, next) => {
try {
let note = await Note.findById(req.params.id);
if (!note) return res.status(404).json({ message: 'Note not found' });
if (note.user.toString() !== req.user.id) {
return res.status(401).json({ message: 'Not authorized' });
}
await Note.findByIdAndDelete(req.params.id);
res.json({ message: 'Note removed' });
} catch (err) {
next(err);
}
});
module.exports = router;
server.js
)අවසාන වශයෙන්, අපි මේ සියලු කොටස් එකට සම්බන්ධ කර server එක run කරමු.
const express = require('express');
const dotenv = require('dotenv');
const connectDB = require('./config/db');
const errorHandler = require('./middleware/errorHandler');
// Load env vars
dotenv.config();
// Connect to database
connectDB();
const app = express();
// Body Parser Middleware
app.use(express.json());
// Mount routers
app.use('/api/auth', require('./routes/auth'));
app.use('/api/notes', require('./routes/notes'));
// Error Handler Middleware (must be last)
app.use(errorHandler);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Postman වැනි API client එකක් භාවිතා කර, ඔබේ endpoints test කරන්න.