JK
>CARGANDO // CARGANDO
INICIALIZANDO VISTA
Backend API REST listo para producción con arquitectura modular MVC, pipelines de agregación en MongoDB y autenticación segura.
Crear una base modular sólida con manejo centralizado de errores, cabeceras de seguridad y pruebas automatizadas fiables.
| Tecnología | Versión | Propósito | Por qué se eligió |
|---|---|---|---|
| Node.js | — | JavaScript runtime | Non-blocking I/O, large ecosystem |
| Express.js | 4.19.2 | HTTP framework | Minimal, flexible, well-documented |
| TypeScript | 5.5.4 | Type safety | Compile-time error catching, IDE support |
| MongoDB | — | Document database | Flexible schema, JSON-native, horizontal scaling |
| Mongoose | 8.5.3 | MongoDB ODM | Schema validation, middleware, query building |
| JWT (jsonwebtoken) | 9.0.2 | Authentication tokens | Stateless auth, industry standard |
| bcrypt | 5.1.1 | Password hashing | Adaptive hashing, salt rounds |
| Cloudinary | 2.4.0 | Image hosting/CDN | Managed service, CDN, image transformations |
| Multer | 1.4.5-lts.1 | File upload handling | Express-integrated, simple API |
| Método | Ruta | Propósito |
|---|---|---|
| GET | / | Health check / welcome |
| POST | /api/users/register | Register new user |
| POST | /api/users/login | Login user |
| POST | /api/admin/createAdmin | Create admin user |
| POST | /api/admin/adminlogin | Login admin |
| POST | /api/restaurant/createRestaurant | Register restaurant owner |
| POST | /api/restaurant/ownerLogin | Login restaurant owner |
| POST | /api/Menuitems/addItems | Create menu item with image |
| PUT | /api/Menuitems/:itemId | Update menu item |
| GET | /api/Menuitems/getAllItems | List all menu items |
| GET | /api/Menuitems/:itemId | Get single menu item |
| DELETE | /api/Menuitems/:itemId | Delete menu item |
| POST | /api/orders/createorder | Create order |
| POST | /api/orders/cancelorder/:orderId | Cancel order |
| GET | /api/orders/orderdetails/:orderId | Get order details |
| Columna | Tipo | Notas |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| name | String | Required |
| String | Required, unique | |
| password | String | bcrypt hashed |
| createdAt | Date | Auto (timestamps: true) |
| updatedAt | Date | Auto (timestamps: true) |
User accounts. Email is unique.
| Columna | Tipo | Notas |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| name | String | Required |
| String | Required, unique | |
| password | String | bcrypt hashed |
| userType | String | enum: ['admin', 'user', 'restOwner'] |
Admin accounts. Separate collection from users.
| Columna | Tipo | Notas |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| restaurantEmail | String | Required |
| restaurantPwd | String | bcrypt hashed |
| restaurantName | String | Required |
| restaurantAddress | String | Required |
| restaurantPhoneNo | Number | Required, unique |
Restaurant owner accounts.
| Columna | Tipo | Notas |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| restaurantId | ObjectId | No ref defined — .populate() won't work |
| itemName | String | Has typo: require instead of required |
| itemDescription | String | Has typo: require instead of required |
| itemPrice | Number | Has typo: require instead of required |
| itemImage | String | Cloudinary URL |
Menu items per restaurant. restaurantId lacks ref property — schema bug.
| Columna | Tipo | Notas |
|---|---|---|
| _idPK | ObjectId | Auto-generated |
| customerId | ObjectId | ref: User |
| restaurantId | ObjectId | ref: restaurant |
| menuId | ObjectId | ref: MenuItems |
| orderQuantity | Number | No validation for positive values |
| orderDate | Date | Default: Date.now |
| orderStatus | String | enum: ['in process', 'transit', 'cancelled', 'delivered'] |
| orderBill | Number | Client-supplied — security concern |
Orders are client-supplied bill amounts — no server-side price calculation.
One-to-Many: Users→Orders, Restaurants→MenuItems, Restaurants→Orders, MenuItems→Orders. All via ObjectId references. No many-to-many relationships. menuitems.restaurantId lacks ref property.
Decisión: Single Express.js application with domain-based folder structure
Motivo: Appropriate for project scale (~15 endpoints, single deployment)
Beneficios: Simple deployment, easy debugging, low operational overhead, clear domain ownership
Compensaciones: Cannot scale domains independently, all modules share process, no service layer for reuse
Decisión: Stateless JWT tokens with Authorization: Bearer header
Motivo: Standard for REST APIs, no session storage needed
Beneficios: Stateless, no server-side session store, scales horizontally
Compensaciones: No server-side revocation, tokens valid until expiry even if user is deleted
Decisión: Business logic resides directly in controllers
Motivo: Simplicity for small project, fewer files to navigate
Beneficios: Fast development, fewer abstractions
Compensaciones: Untestable business logic, code duplication across auth controllers, hard to reuse logic
Decisión: Menu item images uploaded to Cloudinary CDN
Motivo: Managed service avoids S3/MinIO setup, provides CDN and image transformations
Beneficios: No infrastructure to manage, built-in CDN, free tier available
Compensaciones: Vendor lock-in, external dependency, cost at scale, latency for non-CDN regions
Decisión: orderBill is sent by the client, not calculated server-side
Motivo: Likely intentional simplification for MVP
Beneficios: Simpler server logic
Compensaciones: Critical security vulnerability — clients can manipulate order amounts
Decisión: Manual if (!field) validation instead of Zod/Joi
Motivo: Simplicity, fewer dependencies
Beneficios: No additional dependency, explicit control
Compensaciones: Inconsistent validation, no type inference from schemas, generic error messages