import noop from '@tinkoff/utils/function/noop' ; import type { ChildAppCommandLineRunner , ChildAppRequestConfig , ChildAppLoader , ChildAppPreloadManager , ChildAppStateManager , CHILD_APP_RESOLVE_CONFIG_TOKEN , CHILD_APP_PRELOAD_EXTERNAL_CONFIG_TOKEN , ChildAppFinalConfig , } from '@tramvai/tokens-child-app' ; export class PreloadManager implements ChildAppPreloadManager { private loader : ChildAppLoader ; private runner : ChildAppCommandLineRunner ; private stateManager : ChildAppStateManager ; private preloadExternalConfig : typeof CHILD_APP_PRELOAD_EXTERNAL_CONFIG_TOKEN | null ; private readonly resolveFullConfig : typeof CHILD_APP_RESOLVE_CONFIG_TOKEN ; private shouldRunImmediately = false ; private map = new Map < string , Promise < ChildAppFinalConfig > > ( ) ; private preloadMap = new Map < string , ChildAppFinalConfig > ( ) ; private configHasBeenPreloaded = false ; constructor ( { loader , runner , stateManager , preloadExternalConfig , resolveFullConfig , } ) { this . loader = loader ; this . runner = runner ; this . stateManager = stateManager ; this . preloadExternalConfig = preloadExternalConfig ; this . resolveFullConfig = resolveFullConfig ; } async preload ( request ) { if ( ! this . configHasBeenPreloaded ) { await this . preloadExternalConfig ?. ( ) ; this . configHasBeenPreloaded = true ; } const config = this . resolveFullConfig ( request ) ; const { key } = config ; if ( this . map . has ( key ) ) { await this . map . get ( key ) ; return ; } const promise = this . loader . load ( config ) . then ( ( ) => { if ( this . shouldRunImmediately ) { return this . run ( 'customer' , config ) ; } } ) . catch ( noop ) . then ( ( ) => config ) ; this . map . set ( key , promise ) ; this . preloadMap . set ( config . key , config ) ; if ( this . shouldRunImmediately ) { await promise ; } } isPreloaded ( request ) { const config = this . resolveFullConfig ( request ) ; const { key } = config ; return this . map . has ( key ) ; } async runPreloaded ( ) { this . shouldRunImmediately = true ; const promises = [ ] ; this . map . forEach ( ( childAppPromise ) => { promises . push ( ( async ( ) => { await this . run ( 'customer' , await childAppPromise ) ; } ) ( ) ) ; } ) ; await Promise . all ( promises ) ; } async clearPreloaded ( ) { const promises = [ ] ; this . map . forEach ( ( childAppPromise ) => { promises . push ( ( async ( ) => { await this . run ( 'clear' , await childAppPromise ) ; } ) ( ) ) ; } ) ; await Promise . all ( promises ) ; } getPreloadedList ( ) { return [ ... this . preloadMap . values ( ) ] ; } private async run ( status , config ) { const childApp = this . loader . get ( config ) ; if ( ! childApp ) { return ; } await this . runner . run ( 'server' , status , config ) ; await this . stateManager . registerChildApp ( config ) ; } }