- نظرة عامة
- البنية المعمارية
- الطبقات (Layers)
- تدفق البيانات
- المبادئ المعمارية
- التوثيق التفصيلي
- أمثلة عملية
تم إعادة هيكلة المشروع لاتباع أفضل الممارسات في تطوير البرمجيات:
- فصل الاهتمامات (Separation of Concerns)
- قابلية الصيانة (Maintainability)
- قابلية التوسع (Scalability)
- الأمان (Security)
- قابلية الاختبار (Testability)
Frontend: React 18 + TypeScript + Vite
Backend: Node.js + Express.js + TypeScript
Database: PostgreSQL + Drizzle ORM
Security: bcrypt, helmet, cors, rate-limiting
Architecture: Clean Architecture + SOLID Principles
nulip/
├── client/ # Frontend Application
│ ├── public/ # Static Assets
│ ├── src/
│ │ ├── features/ # Feature-Based Structure
│ │ │ ├── auth/
│ │ │ │ ├── components/ # Auth Components
│ │ │ │ ├── hooks/ # Auth Hooks
│ │ │ │ ├── api/ # Auth API Calls
│ │ │ │ └── types.ts # Auth Types
│ │ │ │
│ │ │ ├── inventory/ # Inventory Features
│ │ │ │ ├── fixed/ # Fixed Inventory
│ │ │ │ ├── moving/ # Moving Inventory
│ │ │ │ └── shared/ # Shared Components
│ │ │ │
│ │ │ └── users/ # Users Feature
│ │ │
│ │ ├── shared/ # Shared Code
│ │ │ ├── components/ # Shared Components
│ │ │ │ ├── ui/ # shadcn/ui Components
│ │ │ │ └── layout/ # Layout Components
│ │ │ ├── hooks/ # Shared Hooks
│ │ │ ├── utils/ # Utility Functions
│ │ │ └── lib/ # Third-party Configs
│ │ │
│ │ ├── pages/ # Page Components
│ │ ├── App.tsx # Root Component
│ │ └── main.tsx # Entry Point
│ │
│ └── index.html
│
├── server/ # Backend Application
│ ├── api/ # API Layer
│ │ └── v1/ # API Version 1
│ │ ├── routes/ # Route Definitions
│ │ │ ├── auth.routes.ts
│ │ │ ├── users.routes.ts
│ │ │ └── index.ts # Route Aggregator
│ │ │
│ │ ├── controllers/ # Controllers (Request Handlers)
│ │ │ ├── auth.controller.ts
│ │ │ ├── users.controller.ts
│ │ │ └── inventory.controller.ts
│ │ │
│ │ ├── middleware/ # Custom Middleware
│ │ │ ├── auth.middleware.ts
│ │ │ ├── validation.middleware.ts
│ │ │ └── error.middleware.ts
│ │ │
│ │ └── validators/ # Request Validators
│ │ └── auth.validator.ts
│ │
│ ├── services/ # Business Logic Layer
│ │ ├── auth.service.ts
│ │ ├── users.service.ts
│ │ └── inventory.service.ts
│ │
│ ├── repositories/ # Data Access Layer
│ │ ├── interfaces/ # Repository Interfaces
│ │ └── implementations/ # Repository Implementations
│ │
│ ├── models/ # Domain Models
│ │ └── User.model.ts
│ │
│ ├── utils/ # Utilities
│ │ ├── password.util.ts # Password Hashing
│ │ ├── logger.util.ts # Logging
│ │ └── errors.util.ts # Error Handling
│ │
│ ├── middleware/ # Global Middleware
│ │ ├── security.middleware.ts # Security (Helmet, CORS, Rate Limit)
│ │ └── error.middleware.ts # Global Error Handler
│ │
│ ├── config/ # Configuration
│ │ └── env.config.ts # Environment Config
│ │
│ ├── database/ # Database Layer
│ │ ├── connection.ts # DB Connection
│ │ └── migrations/ # Migrations
│ │
│ ├── scripts/ # Utility Scripts
│ │ └── migrate-passwords.ts # Password Migration
│ │
│ ├── index.ts # Server Entry Point
│ ├── app.ts # Express App Setup
│ └── routes.ts # Legacy Routes (قيد التحديث)
│
├── shared/ # Shared Code
│ ├── types/ # Shared Types
│ ├── schemas/ # Zod Schemas
│ └── constants/ # Shared Constants
│
└── docs/ # Documentation
└── ARCHITECTURE_DOCUMENTATION.md
الموقع: server/api/v1/
المسؤولية: معالجة الطلبات والاستجابات HTTP
المكونات:
// server/api/v1/routes/auth.routes.ts
import { Router } from 'express';
import { AuthController } from '../controllers/auth.controller';
import { authMiddleware } from '../middleware/auth.middleware';
const router = Router();
const controller = new AuthController();
router.post('/login', controller.login.bind(controller));
router.post('/logout', authMiddleware.requireAuth, controller.logout.bind(controller));
router.get('/me', authMiddleware.requireAuth, controller.getMe.bind(controller));
export default router;المسؤوليات:
- توجيه الطلبات إلى الـ Controllers المناسبة
- تطبيق Middleware (Auth, Validation)
- لا يحتوي على منطق عمل
// server/api/v1/controllers/auth.controller.ts
export class AuthController {
constructor(private authService: AuthService) {}
async login(req: Request, res: Response) {
// 1. Validate request
// 2. Call service
// 3. Return response
}
}المسؤوليات:
- استقبال الطلبات
- استدعاء Services
- إرجاع الاستجابات
- معالجة الأخطاء على مستوى HTTP
// server/api/v1/middleware/auth.middleware.ts
export function requireAuth(req, res, next) {
// Verify token
// Add user to request
next();
}المسؤوليات:
- Authentication
- Authorization
- Validation
- Request preprocessing
الموقع: server/services/
المسؤولية: منطق العمل (Business Logic)
المكونات:
// server/services/auth.service.ts
export class AuthService {
constructor(
private userRepository: IUserRepository,
private passwordUtil: PasswordUtil
) {}
async login(username: string, password: string) {
// 1. Find user
// 2. Verify password
// 3. Generate token
// 4. Return user data
}
}المسؤوليات:
- تنفيذ منطق العمل
- تنسيق بين Repositories
- التحقق من القواعد التجارية
- لا يتعامل مباشرة مع HTTP
مثال:
// Business Logic Example
async transferInventory(fromId: string, toId: string, quantity: number) {
// 1. Validate business rules
if (quantity <= 0) throw new ValidationError('Quantity must be positive');
// 2. Check availability
const fromInventory = await this.inventoryRepository.findById(fromId);
if (fromInventory.quantity < quantity) {
throw new BadRequestError('Insufficient inventory');
}
// 3. Execute transfer
await this.inventoryRepository.decrease(fromId, quantity);
await this.inventoryRepository.increase(toId, quantity);
// 4. Log transaction
await this.transactionRepository.create({...});
}الموقع: server/models/
المسؤولية: الكيانات والقواعد الأساسية
المكونات:
// server/models/User.model.ts
export interface User {
id: string;
username: string;
email: string;
password: string; // Hashed
fullName: string;
role: 'admin' | 'supervisor' | 'technician';
isActive: boolean;
createdAt: Date;
updatedAt: Date;
}
export interface UserSafe extends Omit<User, 'password'> {}المسؤوليات:
- تعريف بنية البيانات
- القواعد الأساسية للمجال
- لا يحتوي على منطق عمل معقد
الموقع: server/repositories/ و server/database/
المسؤولية: الوصول للبيانات والخدمات الخارجية
المكونات:
// server/repositories/interfaces/IUserRepository.ts
export interface IUserRepository {
create(data: CreateUserDto): Promise<User>;
findById(id: string): Promise<User | null>;
findByUsername(username: string): Promise<User | null>;
update(id: string, data: UpdateUserDto): Promise<User>;
delete(id: string): Promise<void>;
}// server/repositories/implementations/UserRepository.ts
export class UserRepository implements IUserRepository {
async create(data: CreateUserDto): Promise<User> {
// Database operations using Drizzle ORM
}
}المسؤوليات:
- الوصول إلى قاعدة البيانات
- تنفيذ عمليات CRUD
- عزل قاعدة البيانات عن باقي الطبقات
1. Client Request
↓
POST /api/auth/login
{ username, password }
↓
2. Security Middleware
├── Helmet (Security Headers)
├── CORS (Origin Check)
└── Rate Limiting (5 attempts/15min)
↓
3. Route Handler
auth.routes.ts
↓
4. Controller
AuthController.login()
├── Validate request (Zod)
└── Call Service
↓
5. Service
AuthService.login()
├── Find user (Repository)
├── Verify password (PasswordUtil)
└── Generate token
↓
6. Repository
UserRepository.findByUsername()
└── Database Query (Drizzle ORM)
↓
7. Database
PostgreSQL
↓
8. Response
{ success: true, user, token }
↓
9. Client
1. Client Request
POST /api/users
{ username, email, password, ... }
↓
2. Middleware Stack
├── Security Middleware
├── Auth Middleware (requireAuth)
└── Admin Middleware (requireAdmin)
↓
3. Controller
UsersController.create()
↓
4. Service
UserService.create()
├── Check duplicates
├── Hash password
└── Create user
↓
5. Repository
UserRepository.create()
└── INSERT INTO users
↓
6. Database
PostgreSQL
↓
7. Response
{ success: true, user }
┌─────────────────────────────────────┐
│ Presentation Layer (API/UI) │
│ - Routes, Controllers │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Application Layer (Services) │
│ - Business Logic │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Domain Layer (Models) │
│ - Entities, Value Objects │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Infrastructure Layer (DB/APIs) │
│ - Repositories, External APIs │
└─────────────────────────────────────┘
القواعد:
- الطبقات الداخلية لا تعتمد على الخارجية
- التبعيات تتجه للداخل فقط
- كل طبقة تعتمد فقط على الطبقة التي تحتها
كل class له مسؤولية واحدة:
AuthController: معالجة طلبات Authentication فقطAuthService: منطق Authentication فقطUserRepository: الوصول لبيانات Users فقط
مفتوح للتوسع، مغلق للتعديل:
// يمكن إضافة repository جديد بدون تعديل Service
interface IUserRepository { ... }
class PostgreSQLUserRepository implements IUserRepository { ... }
class MongoDBUserRepository implements IUserRepository { ... }يمكن استبدال الأنواع الفرعية:
// أي implementation لـ IUserRepository يمكن استخدامه
const service = new UserService(new PostgreSQLUserRepository());
// أو
const service = new UserService(new MongoDBUserRepository());واجهات صغيرة ومحددة:
// بدلاً من interface كبير
interface IUserRepository {
// User operations
createUser();
updateUser();
// Inventory operations
createInventory(); // ❌ لا يجب أن يكون هنا
}
// واجهات منفصلة
interface IUserRepository { ... }
interface IInventoryRepository { ... }الاعتماد على التجريدات:
// Service يعتمد على Interface، ليس Implementation
class UserService {
constructor(private userRepo: IUserRepository) {} // ✅
// وليس
constructor(private userRepo: PostgreSQLUserRepository) {} // ❌
}مثال:
// ❌ قبل: تكرار
app.post('/api/users', async (req, res) => {
try {
// validation
// business logic
// database
// response
} catch (error) {
// error handling
}
});
// ✅ بعد: إعادة استخدام
router.post('/users',
validate(createUserSchema),
controller.create.bind(controller)
);الملف: server/utils/password.util.ts
الوظيفة: تشفير والتحقق من كلمات المرور
الاستخدام:
import { passwordUtil } from './utils/password.util';
// Hash password
const hashed = await passwordUtil.hash('plainPassword');
// Compare password
const isValid = await passwordUtil.compare('plainPassword', hashed);
// Check if already hashed
if (passwordUtil.isHashed(password)) {
// Already hashed
}التفاصيل التقنية:
- يستخدم
bcryptمعSALT_ROUNDS = 10 - آمن ضد Rainbow Tables
- مقاوم لـ Timing Attacks
الملف: server/services/auth.service.ts
الوظيفة: منطق Authentication
الطرق:
async login(username: string, password: string): Promise<UserSafe>الخطوات:
- البحث عن المستخدم
- التحقق من حالة الحساب (isActive)
- مقارنة كلمة المرور (bcrypt)
- إذا كانت غير مشفرة، تشفيرها تلقائياً
- إرجاع بيانات المستخدم (بدون كلمة المرور)
الأخطاء:
UnauthorizedError: إذا كان المستخدم غير موجود أو كلمة المرور خاطئة
الملف: server/api/v1/controllers/auth.controller.ts
الوظيفة: معالجة طلبات Authentication
الطرق:
POST /api/auth/login
Body: { username: string, password: string }
Response: { success: true, user: UserSafe, token: string }الخطوات:
- التحقق من البيانات (Zod)
- استدعاء AuthService.login()
- إنشاء session token
- حفظ Session
- إرجاع الاستجابة
الملف: server/middleware/security.middleware.ts
الوظيفة: حماية التطبيق
المكونات:
helmet({
contentSecurityPolicy: { ... },
// يحمي من XSS, Clickjacking, MIME sniffing
})cors({
origin: ['http://localhost:5000'],
credentials: true,
// يسمح فقط للمصادر المصرح بها
})// General: 100 requests / 15 minutes
rateLimit({ windowMs: 15 * 60 * 1000, max: 100 })
// Auth: 5 attempts / 15 minutes
rateLimit({ windowMs: 15 * 60 * 1000, max: 5 })الملف: server/middleware/error.middleware.ts
الوظيفة: معالجة الأخطاء بشكل مركزي
الأنواع:
AppError: Base error classBadRequestError: 400UnauthorizedError: 401ForbiddenError: 403NotFoundError: 404ValidationError: 422InternalServerError: 500
الاستخدام:
// في Service
throw new UnauthorizedError('Invalid credentials');
// في Middleware
app.use(errorHandler); // يعالج جميع الأخطاء// server/repositories/interfaces/IProductRepository.ts
export interface IProductRepository {
findAll(): Promise<Product[]>;
findById(id: string): Promise<Product | null>;
create(data: CreateProductDto): Promise<Product>;
}// server/repositories/implementations/ProductRepository.ts
export class ProductRepository implements IProductRepository {
async findAll(): Promise<Product[]> {
return db.select().from(products);
}
// ...
}// server/services/product.service.ts
export class ProductService {
constructor(private productRepo: IProductRepository) {}
async getAllProducts(): Promise<Product[]> {
return this.productRepo.findAll();
}
}// server/api/v1/controllers/product.controller.ts
export class ProductController {
constructor(private productService: ProductService) {}
async getAll(req: Request, res: Response) {
const products = await this.productService.getAllProducts();
res.json({ success: true, data: products });
}
}// server/api/v1/routes/product.routes.ts
const router = Router();
const service = new ProductService(new ProductRepository());
const controller = new ProductController(service);
router.get('/', controller.getAll.bind(controller));
export default router;// server/app.ts
import { UserRepository } from './repositories/implementations/UserRepository';
import { UserService } from './services/user.service';
import { UsersController } from './api/v1/controllers/users.controller';
// Initialize dependencies
const userRepository = new UserRepository();
const userService = new UserService(userRepository);
const usersController = new UsersController(userService);
// Use in routes
app.post('/api/users', usersController.create.bind(usersController));التشفير: bcrypt with 10 salt rounds
التخزين: Hashed passwords only
التحقق: bcrypt.compare() for timing-safe comparison
Helmet: Security headers
- XSS Protection
- Content Security Policy
- Frame Options
CORS: Origin restrictions
- Whitelist allowed origins
- Credentials support
Rate Limiting: Brute force protection
- Login: 5 attempts / 15 min
- General: 100 requests / 15 min
Tokens: Session-based tokens
- Stored in memory (Map)
- Expiry: 24 hours
- Bearer token format
Middleware: Role-based access
requireAuth: Any authenticated userrequireAdmin: Admin onlyrequireSupervisor: Supervisor or above
❌ routes.ts: 3600+ lines
❌ كل شيء في ملف واحد
❌ كلمات المرور: نص واضح
❌ لا يوجد security middleware
❌ لا يوجد error handling مركزي
❌ صعب الصيانة والتوسع
✅ Routes: منفصلة ومنظمة
✅ Controllers: منطق منفصل
✅ Services: business logic منظم
✅ Repositories: data access معزول
✅ كلمات المرور: مشفرة
✅ Security: middleware stack كامل
✅ Error handling: مركزي
✅ سهولة الصيانة والتوسع
- Files: kebab-case (
auth.controller.ts) - Classes: PascalCase (
AuthController) - Functions: camelCase (
login) - Constants: UPPER_SNAKE_CASE (
SALT_ROUNDS)
- ملف واحد لكل class
- مجلدات منظمة حسب الوظيفة
- imports منظم
- استخدام Custom Error Classes
- Error messages واضحة
- Logging للأخطاء
- استخدام TypeScript في كل مكان
- Interfaces للـ contracts
- Types من Zod schemas
- التوافق مع الكود القديم: الكود القديم لا يزال يعمل
- التحديث التدريجي: يمكن تحديث features واحدة تلو الأخرى
- الاختبار: يجب اختبار كل layer بشكل منفصل
هذا التوثيق يشرح البنية المعمارية بالتفصيل 📚