js/topology/define/topology_define_plugin.js
// NPM IMPORTS
import assert from 'assert'
import fs from 'fs'
// COMMON IMPORTS
import T from '../../utils/types'
import TopologyDefineItem from './topology_define_item'
let context = 'common/topology/define/topology_define_plugin'
/**
* TopologyDefinePlugin class: describe a Plugin topology item.
*
* @author Luc BORIES
* @license Apache-2.0
*
* @example
* SETTINGS FORMAT:
* "plugins":
* "pluginA":
* "type":"...", // rendering, services
* "file":"..."
* "pluginB":
* "type":"...",
* "package":"..."
*
*/
export default class TopologyDefinePlugin extends TopologyDefineItem
{
/**
* Create a TopologyDefinePlugin instance.
*
* @param {string} arg_name - instance name.
* @param {object} arg_settings - instance settings map.
* @param {string} arg_log_context - trace context string.
*
* @returns {nothing}
*/
constructor(arg_name, arg_settings, arg_log_context)
{
const log_context = arg_log_context ? arg_log_context : context
super(arg_name, arg_settings, 'TopologyDefinePlugin', log_context)
this.is_topology_define_plugin = true
this.topology_type = 'plugins'
this.topology_plugin_type = this.get_setting('type', undefined)
this.topology_plugin_file = this.get_setting('file', undefined)
this.topology_plugin_package = this.get_setting('package', undefined)
this.info('Plugin is created')
}
/**
* Load rendering plugins.
*
* @returns {Class} - Plugin class.
*/
load_plugin_class()
{
const self = this
self.enter_group('load_plugin_class')
this.debug('plugin=%s', this.get_name())
let plugin_class = undefined
// RENDERING PLUGIN IS LOADED FROM A NPM PACKAGE
if ( T.isString(this.topology_plugin_package) && this.topology_plugin_package != 'default' )
{
// TODO : loading packages without full path?
let file_path = undefined
const pkg = this.topology_plugin_package
file_path = self.get_runtime().context.get_absolute_path('./node_modules/', pkg)
let file_path_stats = file_path ? fs.statSync(file_path) : undefined
if ( ! file_path_stats || ! file_path_stats.isDirectory())
{
this.debug('plugin=%s not found in [%s]', this.get_name(), './node_modules/')
file_path = self.get_runtime().context.get_absolute_path('../node_modules/', pkg)
file_path_stats = file_path ? fs.statSync(file_path) : undefined
if ( ! file_path_stats || ! file_path_stats.isDirectory())
{
this.debug('plugin=%s not found in [%s]', this.get_name(), '../node_modules/')
file_path = self.get_runtime().context.get_absolute_path('../../node_modules/', pkg)
file_path_stats = file_path ? fs.statSync(file_path) : undefined
if ( ! file_path_stats || ! file_path_stats.isDirectory())
{
this.debug('plugin=%s not found in [%s]', this.get_name(), '../../node_modules/')
file_path = self.get_runtime().context.get_absolute_path('../../../node_modules/', pkg)
file_path_stats = file_path ? fs.statSync(file_path) : undefined
if ( ! file_path_stats || ! file_path_stats.isDirectory())
{
this.debug('plugin=%s not found in [%s]', this.get_name(), '../../../node_modules/')
file_path = undefined
}
}
}
}
if (file_path)
{
// console.log(context + ':load_plugin_class:package=%s for plugin=%s at=%s', pkg, this.get_name(), file_path)
this.debug('plugin=%s found for path [%s]', this.get_name(), file_path)
plugin_class = require(file_path)
}
else
{
file_path = undefined
console.error(context + ':load_plugin_class:not found package=%s for plugin=%s at=%s', pkg, this.get_name())
}
}
// LOAD A PLUGIN FROM A PATH
else if ( T.isString(this.topology_plugin_file) )
{
const file_path = self.get_runtime().context.get_absolute_path(this.topology_plugin_file)
// console.log(context + ':load_plugin_class:file_path=%s for plugin=%s', file_path, this.get_name())
plugin_class = require(file_path)
}
if (plugin_class && plugin_class.default)
{
plugin_class = plugin_class.default
}
self.leave_group('load_plugin_class')
return plugin_class
}
/**
* Create plugins.
*
* @param {RuntimeBase} - arg_runtime - Runtime instance.
* @param {Class} - arg_plugin_class - Plugin class.
* @param {PluginsManager} - arg_plugins_manager - PluginsManager instance.
*
* @returns {Promise}
*/
create_plugin(arg_runtime, arg_plugin_class, arg_plugins_manager)
{
// REGISTER PLUGIN CLASS
if (arg_plugin_class)
{
try
{
const plugin = new arg_plugin_class(arg_runtime, arg_plugins_manager)
arg_plugins_manager.load_at_first(plugin)
plugin.$plugin_class = arg_plugin_class
this.topology_plugin_instance = plugin
// console.log(context + ':create_plugin:plugin=%s is loaded', this.get_name())
return plugin
}
catch(e) {
console.error(context + ':create_plugin:plugin=%s error during load [%s]', this.get_name(), e.toString())
}
}
return undefined
}
/**
* Load rendering plugins.
*
* @param {RuntimeBase} - arg_runtime - Runtime instance.
*
* @returns {Promise} - Promise of Plugin instance.
*/
load_rendering_plugin(arg_runtime)
{
const self = this
self.enter_group('load_rendering_plugin')
assert( T.isObject(arg_runtime) && arg_runtime.is_base_runtime, context + ':load_rendering_plugin:bad runtime instance' )
const plugins_mgr = arg_runtime.get_plugins_factory().get_rendering_manager()
assert( T.isObject(plugins_mgr) && plugins_mgr.is_plugins_manager, context + ':load_rendering_plugin:bad plugin manager object')
const plugin_class = this.load_plugin_class()
const plugin = this.create_plugin(arg_runtime, plugin_class, plugins_mgr)
if (plugin && plugin.is_rendering_plugin)
{
plugin.find_rendering_function = (type)=>{
if ( T.isFunction(plugin.$plugin_class.find_rendering_function) )
{
// console.log('plugin.$plugin_class.find_rendering_function FOUND')
return plugin.$plugin_class.find_rendering_function(type)
}
// console.log('plugin.$plugin_class.find_rendering_function NOT FOUND')
return undefined
}
self.leave_group('load_rendering_plugin')
return Promise.resolve(plugin)
}
self.leave_group('load_rendering_plugin:not found')
return Promise.resolve(undefined)
}
/**
* Load services plugins.
*
* @param {RuntimeBase} - arg_runtime - Runtime instance.
*
* @returns {Promise} - Promise of Plugin instance.
*/
load_services_plugin(arg_runtime)
{
const self = this
self.enter_group('load_services_plugin')
assert( T.isObject(arg_runtime) && arg_runtime.is_base_runtime, context + ':load_services_plugin:bad runtime instance' )
const plugins_mgr = arg_runtime.get_plugins_factory().get_services_manager()
assert( T.isObject(plugins_mgr) && plugins_mgr.is_plugins_manager, context + ':load_services_plugin:bad plugin manager object')
const plugin_class = this.load_plugin_class()
const plugin = this.create_plugin(arg_runtime, plugin_class, plugins_mgr)
plugins_mgr.register_plugin(plugin)
self.leave_group('load_services_plugin')
return Promise.resolve(plugin)
}
/**
* Find a rendering function.
*
* @param {string} arg_type - rendering item type.
*
* @returns {Function} - rendering function.
*/
find_rendering_function(arg_type)
{
if ( this.topology_plugin_type != 'rendering')
{
console.warn(context + ':find_rendering_function:not a rendering plugin:' + this.get_name())
return undefined
}
if ( ! T.isObject(this.topology_plugin_instance) || ! this.topology_plugin_instance.is_rendering_plugin )
{
console.warn(context + ':find_rendering_function:no rendering plugin instance:' + this.get_name())
return undefined
}
if ( ! T.isFunction(this.topology_plugin_instance.find_rendering_function) )
{
console.warn(context + ':find_rendering_function:no rendering plugin function:' + this.get_name())
return undefined
}
const fn = this.topology_plugin_instance.find_rendering_function(arg_type)
// console.log(fn, context + ':find_rendering_function:rendering function for ' + this.get_name())
return fn
}
}