You are reading the docs for CalmAPI 1.x (legacy), which is no longer developed. Run npx calmapi@next doctor in your 1.x project to check it against published advisories, then see Migrating from 1.x or the CalmAPI 2 docs.

Routing & Configuration

Configure custom paths, nested routes, and module settings.


Automatic Routing#

CalmAPI automatically creates routes for your modules!

Module name: product
Auto-generated route: /api/products (pluralized)


Custom Route Paths#

Override the automatic route using settings.js:

JavaScript
// product.settings.js
module.exports = {
    moduleRoute: 'shop-items'
};

Result: Your API is now at /api/shop-items instead of /api/products


Route File Structure#

JavaScript
// product.route.js
const express = require('express');
const router = express.Router();
const ProductController = require('./product.controller');
const AuthController = require('../auth/auth.controller');

// Public routes
router.get('/', ProductController.getAll);
router.get('/:id', ProductController.get);

// Protected routes (require authentication)
router.use(AuthController.checkLogin);

router.post('/', ProductController.insert);
router.put('/:id', ProductController.update);
router.delete('/:id', ProductController.delete);

module.exports = router;

Common Route Patterns#

Standard CRUD Routes#

JavaScript
router.get('/', Controller.getAll);           // GET all
router.get('/:id', Controller.get);           // GET one
router.post('/', Controller.insert);          // CREATE
router.put('/:id', Controller.update);        // UPDATE
router.delete('/:id', Controller.delete);     // DELETE

Custom Routes#

JavaScript
// Must come BEFORE /:id routes
router.get('/featured', ProductController.getFeatured);
router.get('/search', ProductController.search);
router.get('/low-stock', ProductController.getLowStock);

// Then standard routes
router.get('/:id', ProductController.get);

Nested Routes#

JavaScript
// Get reviews for a product
router.get('/:id/reviews', ProductController.getReviews);

// Add review to a product
router.post('/:id/reviews', ReviewController.insert);

// Get product images
router.get('/:id/images', ProductController.getImages);

Authentication & Middleware#

Protect All Routes#

JavaScript
// All routes require authentication
router.use(AuthController.checkLogin);

router.get('/', ProductController.getAll);
router.post('/', ProductController.insert);
// ... all routes are protected

Mix Public and Protected#

JavaScript
// Public routes
router.get('/', ProductController.getAll);
router.get('/:id', ProductController.get);

// From here on, require authentication
router.use(AuthController.checkLogin);

// Protected routes
router.post('/', ProductController.insert);
router.put('/:id', ProductController.update);
router.delete('/:id', ProductController.delete);

Optional Authentication#

JavaScript
// Check if user is logged in, but don't require it
router.use(AuthController.optionalCheckLogin);

router.get('/', ProductController.getAll);  
// Will have req.user if logged in, undefined if not

Complete Routing Example#

JavaScript
const express = require('express');
const router = express.Router();
const ProductController = require('./product.controller');
const AuthController = require('../auth/auth.controller');

// Public routes - anyone can access
router.get('/', ProductController.getAll);
router.get('/featured', ProductController.getFeatured);
router.get('/search', ProductController.search);
router.get('/category/:categoryId', ProductController.getByCategory);
router.get('/:id', ProductController.get);

// Admin-only routes
router.use(AuthController.checkLogin);
router.use(AuthController.checkAdmin);

router.post('/', ProductController.insert);
router.put('/:id', ProductController.update);
router.delete('/:id', ProductController.delete);
router.post('/:id/feature', ProductController.toggleFeatured);

module.exports = router;

Settings File#

The *.settings.js file configures your module:

JavaScript
// product.settings.js
module.exports = {
    // Custom route path
    moduleRoute: 'products',
    
    // Can add other module-specific settings here
    cacheTimeout: 300,
    maxPageSize: 100
};

Nested Modules#

Create sub-modules with nested routes:

src/modules/
├── shop/
│   ├── product/
│   │   ├── product.controller.js
│   │   ├── product.route.js
│   │   └── ...
│   └── category/
│       ├── category.controller.js
│       ├── category.route.js
│       └── ...

Result:

  • /api/shop/products
  • /api/shop/categories

Tips & Best Practices#

1. Order Matters!#

JavaScript
// Good ✅
router.get('/featured', ProductController.getFeatured);
router.get('/:id', ProductController.get);

// Bad ❌
router.get('/:id', ProductController.get);
router.get('/featured', ProductController.getFeatured);  
// 'featured' will be treated as an ID!

2. Use Descriptive Route Names#

JavaScript
// Good
moduleRoute: 'blog-posts'
moduleRoute: 'user-profiles'

// Avoid
moduleRoute: 'bp'
moduleRoute: 'data'
JavaScript
// Product routes
router.get('/', ...);
router.get('/:id', ...);

// Product reviews (nested)
router.get('/:id/reviews', ...);
router.post('/:id/reviews', ...);

// Product images (nested)
router.get('/:id/images', ...);