import { KibanaPlatformPlugin } from '@kbn/dev-utils' ; interface AllOptions { id : string ; pluginMap : Map < string , KibanaPlatformPlugin > ; } interface CircularRefsError { from : string ; to : string ; stack : string [ ] ; } export type SearchErrors = CircularRefsError ; interface State { deps : Set < KibanaPlatformPlugin > ; stack : string [ ] ; errors : Map < string , SearchErrors > ; } function traverse ( pluginMap , state , id ) { const plugin = pluginMap . get ( id ) ; if ( plugin === undefined ) { throw new Error ( `Unknown plugin id: ${ id }` ) ; } const prevIndex = state . stack . indexOf ( id ) ; const isVisited = prevIndex > - 1 ; if ( isVisited ) { const from = state . stack [ state . stack . length - 1 ] ; const to = id ; const key = `circular-${ [ from , to ] . sort ( ) . join ( '-' ) }` ; if ( ! state . errors . has ( key ) ) { const error = { from , to , stack : state . stack . slice ( prevIndex ) , } ; state . errors . set ( key , error ) ; } return ; } state . stack . push ( id ) ; new Set ( [ ... plugin . manifest . requiredPlugins , ... plugin . manifest . optionalPlugins , ... plugin . manifest . requiredBundles , ] ) . forEach ( ( depId ) => { state . deps . add ( pluginMap . get ( depId ) ! ) ; traverse ( pluginMap , state , depId ) ; } ) ; state . stack . pop ( ) ; } export function getPluginDeps ( { pluginMap , id } ) { const state = { deps : new Set ( ) , errors : new Map ( ) , stack : [ ] , } ; traverse ( pluginMap , state , id ) ; return state ; }