Architecture Overview
JifiJs follows a clean, modular MVC (Model-View-Controller) architecture with additional layers for separation of concerns.
Architecture Layers
┌─────────────────────────────────────┐
│ Client Application │
└──────────────┬──────────────────────┘
│ HTTP Requests
┌──────────────▼──────────────────────┐
│ Routes + Middleware │
│ (Authentication, Validation, │
│ Rate Limiting, Logging) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Controllers │
│ (Request handling, Response │
│ formatting) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Services │
│ (Business logic, Database │
│ operations, Caching) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Models (Mongoose) │
│ (Database schemas, │
│ Validation) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ MongoDB Database │
└─────────────────────────────────────┘
Cache Layer (Redis)
┌─────────────────────────────────────┐
│ Caching Service │
│ - Authentication cache │
│ - Query result cache │
│ - Rate limiting │
└─────────────────────────────────────┘
Queue System (Bull)
┌─────────────────────────────────────┐
│ Background Jobs │
│ - Email sending │
│ - Data processing │
└─────────────────────────────────────┘
Directory Structure
express-backend-ts/
├── bin/ # CLI tools and scripts
│ ├── cli # Main CLI entry point
│ ├── script/ # Generation scripts
│ └── templates.js # Code templates
├── configs/ # Configuration files
│ ├── app.config.ts # App-wide configuration
│ ├── database.config.ts # MongoDB configuration
│ ├── redis.config.ts # Redis configuration
│ └── response.config.ts # Response formatting
├── docs/ # API documentation
│ ├── swagger.ts # Swagger configuration
│ └── routes/ # Route documentation
├── routes/ # Route definitions
│ ├── routes.ts # Main route registry
│ ├── admin/ # Admin routes
│ ├── app/ # Application routes
│ └── auth.route.ts # Authentication routes
├── src/ # Source code
│ ├── controllers/ # Request handlers
│ │ ├── admin/
│ │ ├── app/
│ │ └── auth.controller.ts
│ ├── models/ # Database models
│ │ ├── auth/
│ │ └── log.model.ts
│ ├── services/ # Business logic
│ │ ├── admin/
│ │ ├── app/
│ │ └── auth/
│ └── types/ # TypeScript interfaces
│ ├── service.types.ts
│ └── auth.types.ts
├── utils/ # Utilities and helpers
│ ├── bases/ # Base classes
│ │ ├── base.controller.ts
│ │ ├── base.service.ts
│ │ └── mail.service.ts
│ ├── helpers/ # Helper functions
│ │ ├── cache.helper.ts
│ │ └── logger.helper.ts
│ ├── interceptors/ # Request/response interceptors
│ ├── middlewares/ # Express middlewares
│ │ ├── app.middleware.ts
│ │ └── auth/
│ ├── seeders/ # Database seeders
│ └── validations/ # Joi validation schemas
├── templates/ # Email templates
│ └── auth/
├── main.ts # Application entry point
├── package.json
└── tsconfig.json
Request Flow
1. HTTP Request Arrives
GET /product/123
Headers:
x-api-key: xxx
Authorization: Bearer yyy
2. Middleware Stack
// Route definition in routes.ts
{
path: '/product',
middlewares: [
Middleware.xApiKey, // Validate API key
Middleware.rateLimit, // Check rate limits
Middleware.isLogin, // Authenticate user
]
}
Execution order:
- API Key Validation - Checks
x-api-keyheader - Rate Limiting - Prevents abuse (Redis-based)
- Authentication - Validates JWT token (cache-first)
- Request Logging - Logs request details
3. Controller Layer
// routes/app/product.route.ts
import ProductController from '../../src/controllers/app/product.controller';
const productController = new ProductController();
router.get('/:id', productController.show);
Controller responsibilities:
- Extract request parameters
- Call appropriate service method
- Format response
- Handle errors
4. Service Layer
// src/services/app/product.service.ts
class ProductService extends BaseService<IProduct> {
async findById(id: string) {
// Check cache first
const cached = await this.cacheGet(`product:${id}`);
if (cached) return { error: false, data: cached };
// Query database
const result = await this.model.findById(id);
// Cache result
await this.cacheSet(`product:${id}`, result, 3600);
return { error: false, data: result };
}
}
Service responsibilities:
- Business logic implementation
- Database operations
- Caching
- Data transformation
- Transaction management
5. Model Layer
// src/models/product.model.ts
const productSchema = {
name: { type: String, required: true },
price: { type: Number, required: true },
stock: { type: Number, default: 0 },
};
const Product: Model<IProduct> = BaseSchema<IProduct>(
'products',
productSchema
);
Model responsibilities:
- Schema definition
- Validation rules
- Indexes
- Virtual properties
- Static methods
6. Response
{
"status_code": 200,
"status": "SUCCESS",
"message": "Product retrieved successfully",
"data": {
"_id": "65abc123...",
"name": "Laptop",
"price": 999.99,
"stock": 10
}
}