Backend

Routes

Route file conventions and middleware composition.

Routes wire HTTP paths to controller functions and compose middleware. Each resource has its own route file.

Pattern

Route files export a factory function that returns an Express Router:

// src/routes/auth.route.ts
import { Router } from 'express'
import { useAuthController } from '../controllers/auth.controller'
import { useRevokedTokenRepo } from '../repositories/revoked-token.repo'
import { authenticate } from '@codisolutions23/node-utils'
import { resolveOptionalTenant } from '../middleware/tenant.middleware'
import { accessTokenSecret } from '../config'

export default function useAuthRoute() {
  const router = Router()
  const { existsByJti } = useRevokedTokenRepo()
  const { login, refreshToken, logout, getCurrentUser } = useAuthController()

  // Shared middleware instances for this router
  const authMiddleware = authenticate(accessTokenSecret, existsByJti)

  router.post('/login',    resolveOptionalTenant, login)
  router.post('/refresh',  refreshToken)
  router.get('/user',      authMiddleware, getCurrentUser)
  router.delete('/logout', authMiddleware, logout)

  return router
}

Route Index

All routes are mounted in src/routes/index.ts under /api/:

// src/routes/index.ts
import { Router } from 'express'
import useAuthRoute          from './auth.route'
import useBookingRoute       from './booking.route'
import useOrganizationRoute  from './organization.route'
import useUserRoute          from './user.route'
import useServiceRoute       from './service.route'
// ...

const router = Router()

router.use('/auth',          useAuthRoute())
router.use('/bookings',      useBookingRoute())
router.use('/organizations', useOrganizationRoute())
router.use('/users',         useUserRoute())
router.use('/services',      useServiceRoute())

export default router

Mounted in src/app.ts:

app.use('/api', routes)

Middleware Composition

Middleware is composed per route — not globally applied unless it truly applies to all routes:

// Apply auth on specific routes
router.get('/',    authMiddleware, getBookings)
router.post('/',   authMiddleware, createBooking)

// Mix auth levels on the same resource
router.get('/public-stats', getPublicStats)          // no auth
router.get('/private',      authMiddleware, getPrivate)  // auth required
router.delete('/:id',       adminMiddleware, deleteItem) // admin only

REST Conventions

OperationMethodPath
ListGET/bookings
Get oneGET/bookings/:id
CreatePOST/bookings
Full replacePUT/bookings/:id
Partial updatePATCH/bookings/:id
Delete (soft)DELETE/bookings/:id
Sub-resource actionPATCH/bookings/:id/cancel
Nested resourcePOST/bookings/:id/payment