Будівництво динамічного API для управління формами з Node.js і MongoDB: Мій шлях та уроки, які я отримав

Сьогодні я розпочав подорож з кодування для створення динамічного API управління формами. Мета полягала в тому, щоб створити систему, де форми можна призначати до певних категорій (наприклад, Куб, Квадрат і Циліндр) і керувати ними через операції CRUD. Цей процес навчив мене цінним урокам щодо розробки API, ініціалізації бази даних і організації коду для масштабованості.

У цій статті я поділюсь тим, що я досяг, з якими викликами стикнувся і чітким планом для тих, хто хоче створити подібний проект.

Що я дізнався сьогодні

1. Структурування проекту на Node.js для розробки API

Добре структурований проект є основою ефективної розробки. Ось структура директорій, яку я використав для цього проекту:

project/  
│  
├── models/  
│ ├── shapeModel.js # Схема для форми  
│ ├── categoryShapeModel.js # Схема для категорії  
│  
├── controllers/  
│ ├── shapeController.js # Логіка для управління формами  
│  
├── routes/  
│ ├── shapeRoutes.js # Маршрути для кінцевих точок, пов'язаних з формами  
│  
├── config/  
│ ├── db.js # Логіка підключення до MongoDB  
│  
├── seedCategories.js # Скрипт для одноразової вставки категорій  
├── app.js # Основна точка входу  
├── .env # Змінні середовища  
└── package.json # Залежності

2. Створення схем MongoDB

Я навчився, як визначати схеми для форм і категорій. Ці схеми забезпечують узгодженість у базі даних, дозволяючи створювати потужні взаємозв'язки, наприклад, прив'язуючи форми до категорій.

Схема категорії

const mongoose = require("mongoose");  

const categorySchema = mongoose.Schema(  
 {  
 name: {  
 type: String,  
 required: true,  
 unique: true,  
 enum: ["Cube", "Square", "Cylinder"],   
 },  
 },  
 { timestamps: true }  
);  

module.exports = mongoose.model("Category", categorySchema);

Схема форми

const mongoose = require("mongoose");  

const shapeSchema = mongoose.Schema(  
 {  
 category: {  
 type: mongoose.Schema.Types.ObjectId,  
 ref: "Category",   
 required: true,  
 },  
 color: { type: String, required: true },  
 size: { type: Number, required: true },  
 position: {  
 x: { type: Number, required: true },  
 y: { type: Number, required: true },  
 z: { type: Number, required: true },  
 },  
 rotation: {  
 x: { type: Number, required: true },  
 y: { type: Number, required: true },  
 z: { type: Number, required: true },  
 },  
 },  
 { timestamps: true }  
);  

module.exports = mongoose.model("Shape", shapeSchema);

3. Ініціалізація бази даних

Я розв'язав задачу ініціалізації попередньо визначених категорій (“Cube,” “Square,” “Cylinder”) у базі даних. Замість того, щоб додавати ці записи вручну, я створив скрипт ініціалізації, який запускається один раз і автоматично вставляє дані.

Скрипт ініціалізації

const mongoose = require("mongoose");  
const Category = require("./models/categoryShapeModel");  
const dotenv = require("dotenv");  

dotenv.config();  

const connectDB = async () => {  
 await mongoose.connect(process.env.MONGO_URI, {  
 useNewUrlParser: true,  
 useUnifiedTopology: true,  
 });  
 console.log("MongoDB connected");  
};  

const seedCategories = async () => {  
 const categories = ["Cube", "Square", "Cylinder"];  
 for (const name of categories) {  
 const exists = await Category.findOne({ name });  
 if (!exists) {  
 await Category.create({ name });  
 console.log(`Inserted category: ${name}`);  
 } else {  
 console.log(`Category ${name} already exists`);  
 }  
 }  
 process.exit();  
};  

(async () => {  
 await connectDB();  
 await seedCategories();  
})();

4. Створення RESTful кінцевих точок

Я створив CRUD (Create, Read, Update, Delete) кінцеві точки для управління формами.
Кожна кінцева точка включає обробку помилок, щоб забезпечити надійність функціональності.

Кінцеві точки

  • GET /api/shapes/:categoryId - Отримати всі форми для конкретної категорії.
  • POST /api/shapes/:categoryId - Додати нову форму до категорії.
  • PUT /api/shapes/:id - Оновити деталі форми.
  • DELETE /api/shapes/:id - Видалити форму.

Приклад: Контролер для додавання форми

const addShape = async (req, res) => {  
 const { color, size, position, rotation } = req.body;  

 try {  
 const category = await Category.findById(req.params.categoryId);  

 if (!category) {  
 return res.status(404).json({ message: "Категорію не знайдено" });  
 }  

 const shape = new Shape({  
 category: category._id,  
 color,  
 size,  
 position,  
 rotation,  
 });  

 const savedShape = await shape.save();  
 res.status(201).json(savedShape);  
 } catch (error) {  
 res.status(500).json({ message: "Помилка при додаванні форми", error });  
 }  
};

5. Підключення до MongoDB

Щоб підключити моє API до MongoDB, я створив багаторазову утиліту підключення:

const mongoose = require("mongoose");  

const connectDB = async () => {  
 try {  
 await mongoose.connect(process.env.MONGO_URI, {  
 useNewUrlParser: true,  
 useUnifiedTopology: true,  
 });  
 console.log("MongoDB успішно підключено");  
 } catch (error) {  
 console.error("Помилка підключення до MongoDB", error);  
 process.exit(1);  
 }  
};  

module.exports = connectDB;

План на наступні кроки

Ось що я планую робити далі:

  1. Реалізація аутентифікації
  • Додати ролі користувачів (Admin, User) для контролю доступу.
  • Захистити кінцеві точки API за допомогою JWT.

2. Створення фронтенду

  • Використати React для створення інтерфейсу для керування формами та категоріями.
  • Дозволити користувачам динамічно візуалізувати форми.

3. Логування помилок і моніторинг

  • Інтегрувати інструменти, такі як Winston або Morgan, для детального відстеження помилок.

4. Документація API

  • Використати Swagger або Postman для документування всіх кінцевих точок для зручного тестування.

Перекладено з: Building a Dynamic Shape Management API with Node.js and MongoDB: My Journey and Lessons Learned

Leave a Reply

Your email address will not be published. Required fields are marked *