/* eslint-disable security/detect-object-injection */
'use strict';
/**
* Module dependencies, required for ALL Twyr modules
* @ignore
*/
/**
* Module dependencies, required for this module
* @ignore
*/
const TwyrBaseModule = require('./twyr-base-module').TwyrBaseModule;
const TwyrCompError = require('./twyr-component-error').TwyrComponentError;
/**
* @class TwyrBaseComponent
* @extends {TwyrBaseModule}
* @classdesc The Twyr Web Application Server Base Class for all Components.
*
* @param {TwyrBaseModule} [parent] - The parent module, if any.
* @param {TwyrModuleLoader} [loader] - The loader to be used for managing modules' lifecycle, if any.
*
* @description
* Serves as the "base class" for all other components in the Twyr Web Application Server.
*
*/
class TwyrBaseComponent extends TwyrBaseModule {
// #region Constructor
constructor(parent, loader) {
super(parent, null);
const TwyrCompLoader = require('./twyr-component-loader').TwyrComponentLoader;
const actualLoader = (loader instanceof TwyrCompLoader) ? loader : new TwyrCompLoader(this);
this.$loader = actualLoader;
const inflection = require('inflection');
const Router = require('koa-router');
const parentType = Object.getPrototypeOf(Object.getPrototypeOf(this.$parent)).name;
let inflectedName = inflection.transform(this.name, ['foreign_key', 'dasherize']).replace('-id', '');
if((inflectedName === 'main') && (parentType === 'TwyrBaseFeature')) inflectedName = '';
this.$router = (inflectedName !== '') ? new Router({ 'prefix': `/${inflectedName}` }) : new Router();
}
// #endregion
// #region Lifecycle hooks
/**
* @async
* @function
* @override
* @instance
* @memberof TwyrBaseComponent
* @name _setup
*
* @returns {undefined} Nothing.
*
* @summary Adds the Koa Router routes.
*/
async _setup() {
try {
await super._setup();
await this._addRoutes();
return null;
}
catch(err) {
throw new TwyrCompError(`${this.name}::_setup error`, err);
}
}
/**
* @async
* @function
* @override
* @instance
* @memberof TwyrBaseComponent
* @name _teardown
*
* @returns {undefined} Nothing.
*
* @summary Destroys the Koa Router routes.
*/
async _teardown() {
try {
await this._deleteRoutes();
await super._teardown();
return null;
}
catch(err) {
throw new TwyrCompError(`${this.name}::_teardown error`, err);
}
}
/**
* @async
* @function
* @instance
* @memberof TwyrBaseComponent
* @name _subModuleReconfigure
*
* @param {TwyrBaseModule} subModule - The sub-module that changed configuration.
*
* @returns {undefined} Nothing.
*
* @summary Lets the module know that one of its subModules changed configuration.
*/
async _subModuleReconfigure(subModule) {
await super._subModuleReconfigure(subModule);
await this._deleteRoutes();
await this._addRoutes();
await this.$parent._subModuleReconfigure(this);
return null;
}
// #endregion
// #region Protected methods - need to be overriden by derived classes
/**
* @async
* @function
* @instance
* @memberof TwyrBaseComponent
* @name _addRoutes
*
* @returns {undefined} Nothing.
*
* @summary Adds routes to the Koa Router.
*/
async _addRoutes() {
if(twyrEnv === 'development' || twyrEnv === 'test') console.log(`${this.name}::_addRoutes`);
// Add in the sub-components routes
Object.keys(this.$components || {}).forEach((componentName) => {
const componentRouter = this.$components[componentName].Router;
this.$router.use(componentRouter.routes());
});
return null;
}
/**
* @async
* @function
* @instance
* @memberof TwyrBaseComponent
* @name _deleteRoutes
*
* @returns {undefined} Nothing.
*
* @summary Removes all the routes from the Koa Router.
*/
async _deleteRoutes() {
if(twyrEnv === 'development' || twyrEnv === 'test') console.log(`${this.name}::_deleteRoutes`);
// NOTICE: Undocumented koa-router data structure.
// Be careful upgrading :-)
if(this.$router) this.$router.stack.length = 0;
return null;
}
// #endregion
// #region Properties
/**
* @member {Object} Router
* @override
* @instance
* @memberof TwyrBaseComponent
*
* @readonly
*/
get Router() {
return this.$router;
}
/**
* @override
*/
get dependencies() {
return ['ApiService', 'CacheService', 'ConfigurationService', 'LoggerService', 'WebserverService'].concat(super.dependencies);
}
/**
* @override
*/
get basePath() {
return __dirname;
}
// #endregion
}
exports.TwyrBaseComponent = TwyrBaseComponent;