Reference Source

js/topology/registry/loaders/load_config.js

// NPM IMPORTS
import assert from 'assert'
import path from 'path'

// COMMON IMPORTS
import T from '../../../utils/types'
import LoggerConsole from '../../../loggers/logger_console_standalone'

// SERVER IMPORTS
import load_nodes from './load_nodes'
import load_tenants from './load_tenants'
import load_plugins from './load_plugins'
import load_security from './load_security'
import load_deployments from './load_deployments'


const context = 'common/topology/registry/loaders/load_config'



/**
 * Load the 'config' key of the final state
 * Pure function: (Plain Object) => (new Plain Object)
 */
function load_config(arg_state, arg_initial_config, arg_base_dir, arg_world_dir, arg_trace)
{
	const logs = new LoggerConsole(arg_trace)
	let should_toggle_trace = false
	
	logs.info(context, 'loading config')
	
	
	arg_world_dir = arg_world_dir ? arg_world_dir : (arg_base_dir ? path.join(arg_base_dir, 'resources') : undefined)

	
	// LOAD JSON
	try {
		// GET CONFIG JSON
		if (! arg_initial_config)
		{
			arg_initial_config = require('./default_config_app').default_config
		}
		
		let config = arg_initial_config
		config.resources = config.resources || {}
		
		// LOAD OTHERS FILES
		if (T.isString(config.nodes))
		{
			const file_path_name = path.join(arg_world_dir, config.nodes)
			config.nodes = require(file_path_name).nodes
		}
		if (T.isString(config.tenants))
		{
			const file_path_name = path.join(arg_world_dir, config.tenants)
			config.tenants = require(file_path_name).tenants
		}
		if (T.isString(config.plugins))
		{
			const file_path_name = path.join(arg_world_dir, config.plugins)
			config.plugins = require(file_path_name).plugins
		}
		if (T.isString(config.deployments))
		{
			const file_path_name = path.join(arg_world_dir, config.deployments)
			config.deployments = require(file_path_name).deployments
		}
		if (T.isString(config.security))
		{
			const file_path_name = path.join(arg_world_dir, config.security)
			config.security = require(file_path_name).security
		}
		if (T.isString(config.loggers))
		{
			const file_path_name = path.join(arg_world_dir, config.loggers)
			config.loggers = require(file_path_name).loggers
		}
		if (T.isString(config.traces))
		{
			const file_path_name = path.join(arg_world_dir, config.traces)
			config.traces = require(file_path_name).traces
		}
		
        
		// CHECK CONFIG PARTS
		assert(T.isObject(config), 'load_config should be a plain object')
		assert(T.isObject(config.nodes), 'load_config:nodes should be a plain object')
		assert(T.isObject(config.tenants), 'load_config:tenants should be a plain object')
		assert(T.isObject(config.plugins), 'load_config:plugins should be a plain object')
		assert(T.isObject(config.deployments), 'load_config:deployments should be a plain object')
		assert(T.isObject(config.security), 'load_config:security should be a plain object')
		assert(T.isObject(config.loggers), 'load_config:loggers should be a plain object')
		assert(T.isObject(config.traces), 'load_config:traces should be a plain object')
		
		config.traces.loading = T.isBoolean(config.traces.loading) ? config.traces.loading : false
		if (arg_trace != config.traces.loading)
		{
			should_toggle_trace = true
			logs.toggle_trace()
		}

		// LOAD CONFIG PARTS
		logs.info(context, 'loading config parts')
		arg_state.config = {}
		
		arg_state.config.resources = {}
		arg_state.config.resources.by_name = {} // Resource plain object definitions
		arg_state.config.resources.by_file = {} // Resource names (map name:name)
		arg_state.config.resources.by_package = {} // Resource names (map name:name)
		arg_state.config.resources.by_type = {}
		arg_state.config.resources.by_type.commands = {} // Resource names (map name:name)
		arg_state.config.resources.by_type.services = {} // Resource names (map name:name)
		arg_state.config.resources.by_type.views = {} // Resource names (map name:name)
		arg_state.config.resources.by_type.models = {} // Resource names (map name:name)
		arg_state.config.resources.by_type.menubars = {} // Resource names (map name:name)
		arg_state.config.resources.by_type.menus = {} // Resource names (map name:name)
		arg_state.config.resources.by_type.datasources = {} // Resource names (map name:name)
		arg_state.config.resources.by_type.loggers = {} // Resource names (map name:name)
		arg_state.config.resources.by_type.templates = {} // Resource names (map name:name)
		
		arg_state.config.nodes = load_nodes(logs, config.nodes, arg_world_dir)
		if (arg_state.config.nodes && ! arg_state.config.nodes.error)
		{
			arg_state.config.tenants = load_tenants(logs, config.tenants, config.plugins, arg_world_dir)

			if (arg_state.config.tenants && ! arg_state.config.tenants.error)
			{
				arg_state.config.plugins = load_plugins(logs, config.plugins, arg_world_dir)

				if (arg_state.config.plugins && ! arg_state.config.plugins.error)
				{
					arg_state.config.deployments  = load_deployments(logs, config.deployments, arg_world_dir)
					arg_state.config.security     = load_security(logs, config.security, arg_world_dir)
					arg_state.config.loggers      = config.loggers
					arg_state.config.traces       = config.traces
				}
			}
		}
		arg_state.config.nodes       = arg_state.config.nodes       ? arg_state.config.nodes : {}
		arg_state.config.tenants     = arg_state.config.tenants     ? arg_state.config.tenants : {}
		arg_state.config.plugins     = arg_state.config.plugins     ? arg_state.config.plugins : {}
		arg_state.config.deployments = arg_state.config.deployments ? arg_state.config.deployments : {}
		arg_state.config.security    = arg_state.config.security    ? arg_state.config.security : {}
		arg_state.config.loggers     = arg_state.config.loggers     ? arg_state.config.loggers : {}
		arg_state.config.traces      = arg_state.config.traces      ? arg_state.config.traces : {}
		
		// POPULATE STORE RESOURCES
		const has_error = arg_state.config.nodes.error || arg_state.config.tenants.error || arg_state.config.plugins.error || arg_state.config.security.error 
		if ( ! has_error)
		{
			logs.info(context, 'populate store resources, loop on tenants packages')
			Object.keys(arg_state.config.tenants).forEach(
				(tenant_name)=>{
					const tenant_cfg = arg_state.config.tenants[tenant_name]
					Object.keys(tenant_cfg.packages).forEach(
						(package_name) => {
							if (package_name === 'error' || package_name === 'error_msg' || package_name === 'files')
							{
								return
							}
							
							logs.info(context, 'loading config for package ' + package_name)
							
							let package_obj = tenant_cfg.packages[package_name]
							arg_state.config.resources.by_package[package_name] = {}
							
							// REGISTER RESOURCE BY NAME
							logs.info(context, 'storing resources by name for package ' + package_name)
							Object.keys(package_obj.resources_by_name).forEach(
								(resource_name) => {
									// logs.debug(context, 'loading config for package ' + package_name + ' for register resource by name for ' + resource_name)
									
									let resource_obj = package_obj.resources_by_name[resource_name]
									arg_state.config.resources.by_name[resource_name] = resource_obj
									arg_state.config.resources.by_package[package_name][resource_name] = resource_name
								}
							)
							
							// REGISTER RESOURCE BY FILE
							logs.info(context, 'storing resources by file for package ' + package_name)
							Object.keys(package_obj.resources_by_file).forEach(
								(file_name) => {
									// logs.info(context, 'loading config for package ' + package_name + ' for register resource by file:' + file_name)
									arg_state.config.resources.by_file[file_name] = {}
									Object.keys(package_obj.resources_by_file[file_name]).forEach(
										(resource_name) => {
											// logs.info(context, 'loading config for package ' + package_name + ' for register resource by file:' + file_name + ' for ' + resource_name)
											arg_state.config.resources.by_file[file_name][resource_name] = resource_name
										}
									)
								}
							)
							
							// REGISTER RESOURCE BY TYPE
							logs.info(context, 'storing resources by type for package ' + package_name)
							Object.keys(package_obj.resources_by_type).forEach(
								(type_name) => {
									// logs.info(context, 'loading config for package ' + package_name + ' for register resource by type:' + type_name)
									Object.keys(package_obj.resources_by_type[type_name]).forEach(
										(resource_name) => {
											// logs.debug(context, 'loading config for package ' + package_name + ' for register resource by type for ' + resource_name)
											arg_state.config.resources.by_type[type_name][resource_name] = resource_name
										}
									)
								}
							)
							
							logs.info(context, 'storing resources end for package ' + package_name)
						}
					)
				}
			)
		}

		
		// PROCESS ERROR
		logs.info(context, 'processing errors')
		const add_sub_error = (arg_type, arg_error) => {
			if (! arg_state.config.error)
			{
				arg_state.config.error = { context:context, exception:'has sub errors', error_msg:'see sub errors' }
			}
			if (! arg_state.config.suberrors)
			{
				arg_state.config.error.suberrors = []
			}
			const msg = arg_error.error_msg ? arg_error.error_msg : arg_error.exception
			arg_state.config.error.suberrors.push( {type:arg_type, context:arg_error.context, error_msg:msg} )
			
		}
		
		if (arg_state.config.nodes.error)
		{
			add_sub_error('nodes', arg_state.config.nodes.error)
		}
		if (arg_state.config.tenants.error)
		{
			add_sub_error('tenants', arg_state.config.tenants.error)
		}
		if (arg_state.config.plugins.error)
		{
			add_sub_error('plugins', arg_state.config.plugins.error)
		}
		if (arg_state.config.deployments.error)
		{
			add_sub_error('deployments', arg_state.config.deployments.error)
		}
		if (arg_state.config.security.error)
		{
			add_sub_error('security', arg_state.config.security.error)
		}
	}
	catch(e)
	{
		arg_state.config = { error: { context:context, exception:e, error_msg:e.toString() } }
		// console.error(e, context)
	}
	
    // console.log( Object.keys(arg_state.config.resources.by_name), 'resources' )
	
	if (should_toggle_trace)
	{
		logs.toggle_trace()
	}
	
	logs.info(context, 'loading config is finished, returns state')
	return arg_state
}

export default load_config