const App = require('../modules/App')
// eslint-disable-next-line n/no-deprecated-api
const nativeApp = process.binding('ub_app')
/**
* JavaScript mixins registration
*
* @protected
*/
module.exports = {
initializeMixins,
registerMixinModule
}
/**
* Interface for mixin modules
*
* @interface MixinModule
*/
/**
* Called for each entity which have specified mixin. Task ot this function is to register methods / events for entity
* what implements mixin functionality
*
* @function
* @name MixinModule#initEntity
* @param {UBEntity} entity Entity for initialization
* @param {UBEntityMixin} mixinCfg Mixin configuration from entity metafile
*/
/**
* Called once for mixin just after domain is loaded but before App.emit('domainIsLoaded') event emitted
*
* @function
* @name MixinModule#initDomain
*/
/**
* Array of registered mixins in order they are registered
*
* @private
* @type {Array<string>}
*/
const _orderedMixinNames = []
/**
* A map of registered mixins. Keys are mixin name
*
* @private
* @type {Object<string, MixinModule>}
*/
const _mixinModulesMap = {}
/**
* A way to add additional mixins into domain
*
* @param {string} mixinName A name used as "mixins" section key inside entity *.meta file
* @param {MixinModule} mixinModule A module what implements a {MixinModule} interface
*/
function registerMixinModule (mixinName, mixinModule) {
if (_mixinModulesMap[mixinName]) {
throw new Error(`Mixin module for ${mixinName} is already registered`)
}
_orderedMixinNames.push(mixinName)
_mixinModulesMap[mixinName] = mixinModule
}
/**
* Go through all the domain entities and call initialization for all its mixins.
* Called by `UB.start()`
*
* @protected
*/
function initializeMixins () {
// initialize domain level mixin handlers
_orderedMixinNames.forEach(mixinName => {
const mixinModule = _mixinModulesMap[mixinName]
if (typeof mixinModule.initDomain === 'function') {
mixinModule.initDomain()
}
})
for (const eName in App.domainInfo.entities) {
const e = App.domainInfo.entities[eName]
const enabledEntityMixins = Object.keys(e.mixins).filter(mn => e.mixins[mn].enabled !== false)
// apply mixins in order they are registered
_orderedMixinNames.forEach(mn => {
if ((enabledEntityMixins.indexOf(mn) !== -1) &&
(_mixinModulesMap[mn].initEntity)) {
// console.debug(`Init mixin '${mn}' for ${e.name}' ...`)
_mixinModulesMap[mn].initEntity(e, e.mixins[mn]) // initialize mixin for entity
}
})
// verify all entity mixins are registered
enabledEntityMixins.forEach(mn => {
if (!_mixinModulesMap[mn]) {
console.warn(`Mixin ${mn} configured for entity ${e.name} but not implemented in domain`)
}
})
}
}
// Add native mixin names to _modulesMap to prevents possible naming conflicts between native and JS mixins
;(function () {
if (typeof nativeApp._getRegisteredMixinNames !== 'function') {
throw new Error('This version of @unitybase/ub package require UB server to be at last 5.19.0')
}
const mixinNames = nativeApp._getRegisteredMixinNames() || {}
for (const mixinName of mixinNames) {
_mixinModulesMap[mixinName] = {}
}
})()