This guide outlines the standards that should be followed to ensure consistency across all controllers in the API.
Each controller file should follow this structure:
// 1. Imports
const someService = require('../services/someService');
const asyncHandler = require('../utils/asyncHandler');
const { getPaginatedResponse } = require('../utils/pagination');
const { logRequest } = require('../utils/logger');
// 2. Route Handlers
/**
* Descriptive comment about the endpoint
* HTTP_METHOD /route/path
*/
const handlerFunction = asyncHandler(async (req, res) => {
// Extract parameters
const { param1, param2 } = req.params;
// Log request
logRequest(req, `Descriptive message about the operation: ${param1}`);
// Call service
const result = await someService.someMethod(param1, param2, req.body);
// Send response
res.status(STATUS_CODE).json(result);
});
// 3. Exports
module.exports = {
handlerFunction1,
handlerFunction2,
// ...
};
All route handlers should be wrapped with the asyncHandler
utility:
const handlerFunction = asyncHandler(async (req, res) => {
// Function body
});
The asyncHandler
will catch any errors and pass them to the error-handling middleware, eliminating the need for try/catch blocks in each handler.
Every route handler should log the request using the logRequest
utility:
logRequest(req, `Descriptive message about the operation: ${param}`);
For endpoints that return collections with pagination:
const result = await someService.getItems(params, query);
res.status(200).json(getPaginatedResponse(result, req.query));
Use consistent HTTP status codes across all endpoints:
- 200 OK: For successful GET (single resource), PUT, and PATCH requests
- 201 Created: For successful POST requests that create a new resource
- 204 No Content: For successful DELETE requests
- 400 Bad Request: For client errors (invalid input, etc.)
- 401 Unauthorized: For authentication errors
- 403 Forbidden: For authorization errors
- 404 Not Found: For resources that don't exist
- 409 Conflict: For conflicting operations
- 500 Internal Server Error: For server errors
Extract parameters at the beginning of the handler function:
const { orgId, envId, resourceId } = req.params;
const { filter, sort } = req.query;
const userId = req.user.id; // From auth middleware
Keep the controller thin by delegating business logic to service files:
const result = await someService.someMethod(parameters);
For single resources:
res.status(200).json(resource);
For collections:
res.status(200).json(getPaginatedResponse(result, req.query));
For creation:
res.status(201).json(newResource);
For deletion:
res.status(204).send();