Backend API RESTful Express.js
Terminétypescriptnodejsexpressmongodbcloudinaryjwtdotenveslint

Backend API RESTful Express.js

Backend prêt pour la production avec architecture MVC modulaire et pipelines d'agrégation MongoDB.

Problème et solution

Construire un socle technique robuste doté d'une gestion centralisée des erreurs et de tests automatisés.

Fonctionnalités

  • Authentification JWT avec renouvellement des refresh tokens
  • Middleware d'autorisation basé sur les rôles
  • Optimisation des requêtes d'agrégation MongoDB
  • Validation stricte des données entrantes
  • Tests d'intégration avec Jest et Supertest

Stack technique

TechnologieVersionObjectifPourquoi ce choix
Node.js—JavaScript runtimeNon-blocking I/O, large ecosystem
Express.js4.19.2HTTP frameworkMinimal, flexible, well-documented
TypeScript5.5.4Type safetyCompile-time error catching, IDE support
MongoDB—Document databaseFlexible schema, JSON-native, horizontal scaling
Mongoose8.5.3MongoDB ODMSchema validation, middleware, query building
JWT (jsonwebtoken)9.0.2Authentication tokensStateless auth, industry standard
bcrypt5.1.1Password hashingAdaptive hashing, salt rounds
Cloudinary2.4.0Image hosting/CDNManaged service, CDN, image transformations
Multer1.4.5-lts.1File upload handlingExpress-integrated, simple API

Architecture

Application Layers

  • Express.js middleware pipeline (CORS, JSON parsing, JWT auth)
  • Domain-based modular structure (users, adminUser, restaurant, orders)
  • Controllers with direct Mongoose access (no service layer abstraction)
  • Global error handler middleware with status code mapping

Infrastructure

  • MongoDB via Mongoose 8.5.3 for document storage
  • Cloudinary v2 for menu item image hosting and CDN
  • Multer for multipart file upload handling
  • JWT (jsonwebtoken) for stateless authentication

Structure du projet

src
adminUser
config
middlewares
orders
restaurant
users
app.ts
server.ts

Points d'API

RMS API (port 3000)

MéthodeRouteObjectif
GET/Health check / welcome
POST/api/users/registerRegister new user
POST/api/users/loginLogin user
POST/api/admin/createAdminCreate admin user
POST/api/admin/adminloginLogin admin
POST/api/restaurant/createRestaurantRegister restaurant owner
POST/api/restaurant/ownerLoginLogin restaurant owner
POST/api/Menuitems/addItemsCreate menu item with image
PUT/api/Menuitems/:itemIdUpdate menu item
GET/api/Menuitems/getAllItemsList all menu items
GET/api/Menuitems/:itemIdGet single menu item
DELETE/api/Menuitems/:itemIdDelete menu item
POST/api/orders/createorderCreate order
POST/api/orders/cancelorder/:orderIdCancel order
GET/api/orders/orderdetails/:orderIdGet order details

Conception de la base de données

users

ColonneTypeNotes
_idPKObjectIdAuto-generated
nameStringRequired
emailStringRequired, unique
passwordStringbcrypt hashed
createdAtDateAuto (timestamps: true)
updatedAtDateAuto (timestamps: true)

User accounts. Email is unique.

admins

ColonneTypeNotes
_idPKObjectIdAuto-generated
nameStringRequired
emailStringRequired, unique
passwordStringbcrypt hashed
userTypeStringenum: ['admin', 'user', 'restOwner']

Admin accounts. Separate collection from users.

restaurants

ColonneTypeNotes
_idPKObjectIdAuto-generated
restaurantEmailStringRequired
restaurantPwdStringbcrypt hashed
restaurantNameStringRequired
restaurantAddressStringRequired
restaurantPhoneNoNumberRequired, unique

Restaurant owner accounts.

menuitems

ColonneTypeNotes
_idPKObjectIdAuto-generated
restaurantIdObjectIdNo ref defined — .populate() won't work
itemNameStringHas typo: require instead of required
itemDescriptionStringHas typo: require instead of required
itemPriceNumberHas typo: require instead of required
itemImageStringCloudinary URL

Menu items per restaurant. restaurantId lacks ref property — schema bug.

orders

ColonneTypeNotes
_idPKObjectIdAuto-generated
customerIdObjectIdref: User
restaurantIdObjectIdref: restaurant
menuIdObjectIdref: MenuItems
orderQuantityNumberNo validation for positive values
orderDateDateDefault: Date.now
orderStatusStringenum: ['in process', 'transit', 'cancelled', 'delivered']
orderBillNumberClient-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.

Décisions de conception clés

Modular Monolith Architecture

Décision : Single Express.js application with domain-based folder structure

Pourquoi : Appropriate for project scale (~15 endpoints, single deployment)

Avantages : Simple deployment, easy debugging, low operational overhead, clear domain ownership

Compromis : Cannot scale domains independently, all modules share process, no service layer for reuse

JWT for Authentication

Décision : Stateless JWT tokens with Authorization: Bearer header

Pourquoi : Standard for REST APIs, no session storage needed

Avantages : Stateless, no server-side session store, scales horizontally

Compromis : No server-side revocation, tokens valid until expiry even if user is deleted

No Service Layer

Décision : Business logic resides directly in controllers

Pourquoi : Simplicity for small project, fewer files to navigate

Avantages : Fast development, fewer abstractions

Compromis : Untestable business logic, code duplication across auth controllers, hard to reuse logic

Cloudinary for Image Storage

Décision : Menu item images uploaded to Cloudinary CDN

Pourquoi : Managed service avoids S3/MinIO setup, provides CDN and image transformations

Avantages : No infrastructure to manage, built-in CDN, free tier available

Compromis : Vendor lock-in, external dependency, cost at scale, latency for non-CDN regions

Client-Supplied Order Bill

Décision : orderBill is sent by the client, not calculated server-side

Pourquoi : Likely intentional simplification for MVP

Avantages : Simpler server logic

Compromis : Critical security vulnerability — clients can manipulate order amounts

No Request Validation Library

Décision : Manual if (!field) validation instead of Zod/Joi

Pourquoi : Simplicity, fewer dependencies

Avantages : No additional dependency, explicit control

Compromis : Inconsistent validation, no type inference from schemas, generic error messages

Tests

None installed•0 tests unitaires

Ce qui est testé

    Couverture manquante

    • No test framework installed (no jest, mocha, vitest)
    • No test files or test directories
    • No unit tests for controllers or middleware
    • No integration tests for API endpoints
    • No authentication flow tests
    • No database operation tests

    Défis clés

    • Développer un middleware performant pour la sécurité et le rate limiting
    • Standardiser les réponses d'erreur sur l'ensemble de l'API

    Apprentissages clés

    • Architecture MVC modulaire avec TypeScript et Node.js
    • Stratégies d'indexation avancées dans MongoDB