import { config , Constructor , Context , inject , JSONObject } from '@loopback/core' ; import { api , get , HttpErrors , param , RequestContext , Response , RestBindings , } from '@loopback/rest' ; import { ContextGraph } from './context-graph' ; import { ContextExplorerBindings } from './keys' ; import { ContextExplorerConfig } from './types' ; import { renderGraph } from './visualizer' ; export function contextExplorerControllerFactory ( basePath = '/context-explorer' ) { @ api ( { basePath , paths : { } } ) class ContextExplorerController { constructor ( @ config ( { fromBinding : ContextExplorerBindings . COMPONENT } ) private explorerConfig = { path : '/context-explorer' , } , @ inject ( RestBindings . Http . CONTEXT ) private ctx ) { } @ get ( '/inspect' , { 'x-visibility' : 'undocumented' , responses : { } , } ) inspect ( @ param . query . boolean ( 'includeInjections' ) includeInjections = true , @ param . query . boolean ( 'includeParent' ) includeParent = true , @ param . query . boolean ( 'includeGraph' ) includeGraph = true ) { if ( this . explorerConfig . enableInspection === false ) { throw new HttpErrors . NotFound ( ) ; } const result = this . ctx . inspect ( { includeInjections , includeParent } ) ; if ( includeGraph ) { const graph = new ContextGraph ( result ) . render ( ) ; result . graph = graph ; } return result ; } @ get ( '/graph' , { 'x-visibility' : 'undocumented' , responses : { } } ) async graph ( @ param . query . boolean ( 'includeInjections' ) includeInjections = true , @ param . query . boolean ( 'includeParent' ) includeParent = true , @ param . query . string ( 'format' ) format = 'svg' ) { if ( this . explorerConfig . enableSVG === false ) { throw new HttpErrors . NotFound ( ) ; } const result = this . ctx . inspect ( { includeInjections , includeParent } ) ; const graph = new ContextGraph ( result ) . render ( ) ; if ( format === 'dot' ) { this . ctx . response . contentType ( 'text/plain' ) . send ( graph ) ; } else { const svg = await renderGraph ( graph ) ; this . ctx . response . contentType ( 'image/svg+xml' ) . send ( svg ) ; } return this . ctx . response ; } /**
         * Create an array of graphviz dot graphs for d3 animation
         */ @ get ( '/dots' , { 'x-visibility' : 'undocumented' , responses : { } , } ) async dots ( ) { if ( this . explorerConfig . enableD3Animation === false ) { throw new HttpErrors . NotFound ( ) ; } let ctx = this . ctx ; const dots = [ ] ; while ( ctx != null ) { const ctxData = ctx . inspect ( { includeParent : true , includeInjections : true , } ) ; const graph = new ContextGraph ( ctxData ) . render ( ) ; dots . push ( graph ) ; ctx = ctx . parent ; } return dots . reverse ( ) ; } } return ContextExplorerController ; }