1
0
Fork 0
nodejs-backend-template/server/api/Controller.js

94 lines
3.0 KiB
JavaScript

const ApplicationError = require('../utils/application-error');
const validMethod = {
get: 'get',
post: 'post',
delete: 'delete',
patch: 'patch',
put: 'put'
};
/**
* A class that represents a controller for processing HTTP routes.
*/
class Controller {
/**
* Creates a new instance of the Controller class.
*
* @param {Object} options Options for the controller.
* @param {string} options.method HTTP method (for example, 'get', 'post', 'delete', 'patch', 'put').
* @param {string} options.path The route path (URL).
* @param {function} options.handler The request handler that will be called when the route is accessed.
* @param {Joi.Schema} options.validationSchema Validation scheme for validating input data.
* @param {function[]} options.middlewares Middleware to be called before the handler.
*/
constructor({ method, path, handler, validationSchema, middlewares }) {
if (!validMethod[method] || !path || !handler) {
console.error(`Controller misconfiguration. Method: ${method}, path: ${path}, handler exists: ${!!handler}`);
process.exit(-1);
}
this.method = method;
this.path = path;
this.handler = handler;
this.validationSchema = validationSchema;
this.middlewares = middlewares;
}
/**
* Validates input data according to the validation scheme.
*
* @param {Express.Request} req The Express request object.
* @param {Express.Response} res The Express response object.
* @throws {ApplicationError.JsonValidation} If the data does not match the validation scheme.
*/
async validate(req, res) {
if (!this.validationSchema) {
return;
}
const objectToValidate = this.method === 'get' ? req.query : req.body;
try {
const value = await this.validationSchema.validateAsync(objectToValidate, {stripUnknown: true});
if (this.method === 'get') {
req.query = value;
} else {
req.body = value;
}
} catch (e) {
const message = e.details.map(i => i.message).join(',');
throw ApplicationError.JsonValidation(message);
}
}
/**
* Performs HTTP request processing.
*
* @param {Express.Request} req The Express request object.
* @param {Express.Response} res The Express response object.
* @param {function} next Function for further processing of the request.
*/
async run(req, res, next) {
try {
const handlerResult = await this.handler(req, res, next);
if (!res.headersSent) {
return res.status(200).json({ success: true, statusCode: 200, data: handlerResult });
}
} catch (e) {
next(e);
}
}
/**
* Registers the controller with the Express router.
* @param {Express.Router} router The Express router in which the controller will be registered.
*/
register(router) {
const self = this;
const handle = async function (req, res, next) {
return await self.run(req, res, next);
};
this.middlewares.forEach(middleware => {
router[this.method](this.path, middleware) ;
});
router[this.method](this.path, handle);
}
}
module.exports = Controller;