import { ApiController , ControllerAction } from '../controller' ; import { Request , Response , NextFunction , IDinoProperties , IKeyValuePair } from '../types' ; import { RouteUtility , HttpUtility , DataUtility , FunctionUtility } from '../utility' ; import { DinoModel } from '../entities' ; import { IDinoController } from '../interfaces' ; export class DinoController implements IDinoController { private controller : ApiController ; private controllerAction : ControllerAction ; constructor ( controller , controllerAction ) { this . controller = controller ; this . controllerAction = controllerAction ; } getQueryParams ( ) { let queryParams = this . controllerAction . actionAttributes . actionArguments . map ( x => x . isQueryParam ? x . key : null ) . filter ( x => ! DataUtility . isNull ( x ) ) ; let queryString = { } ; for ( const queryParam of queryParams ) { queryString [ queryParam ] = this . controller . request . query [ queryParam ] ; } return queryString ; } mapSegments ( params , requestUrl ) { return RouteUtility . mapSegmentsAndQueryToActionArguments ( requestUrl , this . controller . request . path , this . getQueryParams ( ) , params ) ; } raiseActionParamsHandlers ( values ) { let attr = this . controllerAction . actionAttributes ; const parseParams = HttpUtility . hasBody ( attr . httpVerb ) ? attr . actionArguments . filter ( x => x . paramIndex !== 0 ) : attr . actionArguments ; for ( const param of parseParams ) { for ( const value of values ) { if ( param . key === value . key ) { value . value = param . handler ( { action : param . action , controller : param . controller , key : param . key , data : param . data , value : value . value } , this . controller . model ) ; } } } } handleHttpBody ( values ) { let attr = this . controllerAction . actionAttributes ; if ( HttpUtility . hasBody ( attr . httpVerb ) ) { let arg = attr . actionArguments . filter ( x => x . paramIndex === 0 ) [ 0 ] ; if ( DataUtility . isUndefined ( arg ) ) { values [ 0 ] = { value : this . controller . request . body } ; } else { values [ 0 ] = { key : arg . key } ; values [ 0 ] . value = arg . handler ( { action : arg . action , controller : arg . controller , key : arg . key , data : arg . data , value : this . controller . request . body } , this . controller . model ) ; } } } attachResultToDino ( sendsResponse , result ) { if ( sendsResponse === false ) { let dino = this . controller . dino ; dino . result = result ; this . controller . next ( ) ; } } patch ( req , res , next ) { this . controller . request = req ; this . controller . response = res ; this . controller . next = next ; this . controller . dino = res . locals . dino ; this . controller . model = new DinoModel ( ) ; this . controller . dino . throw = ( err ) => { this . controller . next ( err ) ; } ; this . controller . dino . proceed = ( result ) => { let dino = this . controller . dino ; dino . result = result ; this . controller . next ( ) ; } ; let dino = this . controller . dino ; dino . returns = this . controllerAction . actionAttributes . returns ; } invokeSetUp ( actionName ) { let ctx = this . controller ; let cta = this . controllerAction ; let values = [ ] ; let params = FunctionUtility . getParamNames ( ctx [ actionName ] ) ; if ( params . length > 0 ) { values = this . mapSegments ( params , cta . actionAttributes . route ) ; this . handleHttpBody ( values ) ; this . raiseActionParamsHandlers ( values ) ; } return values ; } invoke ( actionName ) { let ctx = this . controller ; let values = this . invokeSetUp ( actionName ) ; let result = values . length > 0 ? ctx [ actionName ] . apply ( ctx , values . map ( val => val . value ) ) : ctx [ actionName ] ( ) ; this . attachResultToDino ( this . controllerAction . actionAttributes . sendsResponse , result ) ; } async invokeAsync ( actionName ) { try { let ctx = this . controller ; let values = this . invokeSetUp ( actionName ) ; let result = values . length > 0 ? await ctx [ actionName ] . apply ( ctx , values . map ( val => val . value ) ) : await ctx [ actionName ] ( ) ; this . attachResultToDino ( this . controllerAction . actionAttributes . sendsResponse , result ) ; } catch ( ex ) { this . controller . next ( ex ) ; } } static create ( controller , controllerAction ) { return new DinoController ( controller , controllerAction ) ; } }