js/services/middlewares/middlewares_svc_provider.js
// NPM IMPORTS
import assert from 'assert'
import {format} from 'util'
// COMMON IMPORTS
import T from 'devapt-core-common/dist/js/utils/types'
import ServiceProvider from 'devapt-core-common/dist/js/services/service_provider'
import ServiceResponse from 'devapt-core-common/dist/js/services/service_response'
import RenderingBuilder from 'devapt-core-common/dist/js/rendering/rendering_builder'
// SERVICES IMPORTS
import ExecutableRouteMiddleware from './executable_route_middleware'
/**
* Contextual constant for this file logs.
* @private
*/
const context = 'server/services/middlewares/middlewares_svc_provider'
/**
* Middlewares service provider class.
*
* @author Luc BORIES
* @license Apache-2.0
*/
export default class MiddlewaresSvcProvider extends ServiceProvider
{
/**
* Create a middleware service provider.
*
* @param {string} arg_provider_name - consumer name.
* @param {Service} arg_service_instance - service instance.
* @param {string} arg_context - logging context label.
*
* @returns {nothing}
*/
constructor(arg_provider_name, arg_service_instance, arg_context)
{
super(arg_provider_name, arg_service_instance, arg_context ? arg_context : context)
/**
* Class test flag.
* @type {boolean}
*/
this.is_middleware_svc_provider = true
/**
* Service executable instance.
* @type {Executable}
*/
this.exec = new ExecutableRouteMiddleware()
this.exec.service = this.service
}
/**
* Get provider operations names.
* @abstract
*
* @returns {array}
*/
get_operations_names()
{
return ['devapt-mw-list', 'devapt-mw-get']
}
/**
* Produce service datas on request.
*
* @param {ServiceRequest} arg_request - service request instance.
*
* @returns {Promise} - promise of ServiceResponse instance.
*/
produce(arg_request)
{
this.enter_group('produce')
if ( ! T.isObject(arg_request) || ! arg_request.is_service_request)
{
this.leave_group('produce:error:bad request object.')
return Promise.resolve({error:'bad request object'})
}
const response = new ServiceResponse(arg_request)
const operation = arg_request.get_operation()
const operands = arg_request.get_operands()
const credentials = arg_request.get_credentials()
// CHECK OPERANDS
if ( ! T.isNotEmptyArray(operands) )
{
return Promise.resolve(undefined)
}
// DEBUG
const debug_msg = format('produce:service[%s] operation[%s] operands count[%d]', response.get_service(), operation, operands.length)
// console.log(context + debug_msg)
this.debug(debug_msg)
// GET TARGET ROUTE
const opd_1 = operands.length > 0 ? operands[0] : undefined
const opd_1_route = T.isObject(opd_1) ? opd_1.route : opd_1
let target_route = opd_1_route && T.isNotEmptyString(opd_1_route) ? opd_1_route : undefined
if ( ! target_route)
{
this.fill_error(response, operands, 'bad middleware route string')
return Promise.resolve(response)
}
target_route = target_route.endsWith('/') ? target_route.slice(0, target_route.length - 1) : target_route
// GET ROUTES
const routes = this.get_setting_js('routes', [])
// console.log(debug_msg + ':target_route=', target_route)
switch(operation) {
case 'get': {
let renderer_result_json = undefined
// SEARCH ROUTE
let route_mw_file = undefined
let route_page_view = undefined
let route_page_menubar = undefined
// TODO REPLACE FOREACH TO END LOOP ON FOUND
routes.forEach(
(route_cfg)=>{
const loop_route = route_cfg.route.endsWith('/') ? route_cfg.route.slice(0, target_route.length - 1) : route_cfg.route
if (loop_route == target_route)
{
route_mw_file = route_cfg.mw_file
route_page_view = route_cfg.page_view
route_page_menubar = route_cfg.page_menubar
console.log(context + ':process:target_route found')
}
}
)
try {
// PROCESS MIDDLEWARE FILE
if ( T.isString(route_mw_file) )
{
console.log(context + ':process:route_mw_file found', route_mw_file)
renderer_result_json = this.process_mw_file(route_mw_file, credentials)
response.set_results( [renderer_result_json] )
this.leave_group( format('produce:middleware file:service[%s] operation[%s]', response.get_service(), operation) )
return Promise.resolve(response)
}
// VIEW RENDERING MIDDLEWARE
if ( T.isString(route_page_view) )
{
console.log(context + ':process:route_page_view found', route_page_view)
renderer_result_json = this.process_mw_view(route_page_view, route_page_menubar, credentials)
response.set_results( [renderer_result_json] )
this.leave_group( format('produce:view rendering:service[%s] operation[%s]', response.get_service(), operation) )
return Promise.resolve(response)
}
// BAD ROUTE CONFIG
this.fill_error(response, operands, 'route not found for target', target_route)
return Promise.resolve(response)
}
catch(e)
{
this.fill_error(response, operands, 'exception for target', target_route, e)
return Promise.resolve(response)
}
}
}
this.fill_error(response, operands, 'bad operation', target_route)
return Promise.resolve(response)
}
/**
* Process a middleware file.
*
* @param {string} arg_mw_file - middleware file.
* @param {Credentials} arg_credentials - request credentials.
*
* @returns {object} - JSON rendering result.
*/
process_mw_file(arg_mw_file, arg_credentials)
{
this.enter_group('process_mw_file:' + arg_mw_file)
assert( T.isString(arg_mw_file), context + ':process_mw_file:bad file string')
let mw_cfg = undefined
// CHECK PATH
const path_file_name = this.get_runtime().context.get_absolute_path(arg_mw_file)
assert(T.isString(path_file_name), context + ':bad middleware file path string')
// LOAD MIDDLEWARE FILE
try {
this.info('Loading middleware file')
mw_cfg = require(path_file_name).service_cfg
// console.log(mw_cfg, 'mw_cfg')
}
catch(e)
{
console.log(context + ':process_mw_file:middleware loading error:' + e)
this.error('process_mw_file:middleware file not found or not valid')
this.leave_group('ExecutableRouteMiddleware.exec_http')
return undefined
}
// PROCESSING MIDDLEWARE
try {
this.info('Processing middleware view')
const view = mw_cfg.view
const menubar = mw_cfg.menubar
const renderer_result_json = this.process_mw_view(view, menubar, arg_credentials)
this.info('Loading middleware after')
return renderer_result_json
}
catch(e)
{
console.log(context + ':process_mw_file:middleware processing error:' + e)
this.error('process_mw_file:middleware processing error', e)
this.leave_group('ExecutableRouteMiddleware.exec_http')
return undefined
}
}
/**
* Process a middleware view.
*
* @param {string|Component} arg_view_name - middleware view name.
* @param {string} arg_menubar_name - middleware menubar name.
* @param {Credentials} arg_credentials - request credentials.
*
* @returns {object} - JSON rendering result.
*/
process_mw_view(arg_view_name, arg_menubar_name, arg_credentials)
{
const view_name = T.isString(arg_view_name) ? arg_view_name : ( ( T.isObject(arg_view_name) && arg_view_name.is_component) ? arg_view_name.get_name() : 'undefined')
const menubar_name = T.isString(arg_menubar_name) ? arg_menubar_name : ( ( T.isObject(arg_menubar_name) && arg_menubar_name.is_component) ? arg_menubar_name.get_name() : 'undefined')
console.log(context + ':process_mw_view:view,menubar:', view_name, menubar_name)
assert( T.isString(arg_view_name) || ( T.isObject(arg_view_name) && arg_view_name.is_component), context + ':process_mw_view:bad view string or object')
// GET ASSETS CONFIG
const assets = this.service.get_assets_services_names('any')
// CREATE RENDERING RESULT AND BUILDER
const arg_application = undefined
const renderer = new RenderingBuilder(this.runtime, assets.style, assets.script, assets.image, assets.html, arg_application)
// RENDER TREE
const renderer_result_json = renderer.render_json_content(arg_view_name, arg_menubar_name, arg_credentials)
return renderer_result_json
}
/**
* Populate a response with error message.
*
* @param {ServiceResponse} arg_response - response instance.
* @param {array} arg_operands - request operands.
* @param {string} arg_error - error text.
* @param {string} arg_target_route - target route (optional).
* @param {Error} arg_exception - exception (optional).
*
* @returns {nothing}
*/
fill_error(arg_response, arg_operands, arg_error, arg_target_route, arg_exception)
{
const op = arg_response.get_operation()
const svc = arg_response.get_service()
const error_msg = format('produce:error=[%s] with svc=[%s] operation=[%s] target route=[%s] exception=[%s].', arg_error, svc, op, arg_target_route, arg_exception)
arg_response.set_has_error(true)
arg_response.set_error(error_msg)
arg_response.set_results(arg_operands)
this.leave_group(error_msg)
}
}