import { Application , BindingAddress , BindingKey , Constructor , Context , ContextView , filterByTag , Getter , inject , invokeMethod , } from '@loopback/core' ; /**
 * A strongly-typed binding key for current date
 */ const CURRENT_DATE = BindingKey . create < Date > ( 'currentDate' ) ; /**
 * A strongly-typed binding key for current user
 */ const CURRENT_USER = BindingKey . create < string > ( 'currentUser' ) ; /**
 * A strongly-typed binding key for current language
 */ const CURRENT_LANGUAGE = BindingKey . create < string > ( 'currentLanguage' ) ; /**
 * A strongly-typed binding key for `GreetingService`
 */ const GREETING_SERVICE = BindingKey . create < GreetingService > ( 'services.GreetingService' ) ; /**
 * A factory function to return the current date
 */ const getCurrentDate = ( ) => new Date ( ) ; interface Greeter { language : string ; greet ( name ) : string ; } class ChineseGreeter implements Greeter { language = 'zh' ; greet ( name ) { return `你好，${ name }！` ; } } class EnglishGreeter implements Greeter { language = 'en' ; greet ( name ) { return `Hello, ${ name }!` ; } } /**
 * A class with dependency injection
 */ class GreetingService { constructor ( @ inject . view ( filterByTag ( 'greeter' ) ) private greetersView ) { } @ inject . getter ( CURRENT_DATE ) private now : Getter < Date > ; async greet ( @ inject ( CURRENT_LANGUAGE ) language , @ inject ( CURRENT_USER ) userName ) { const date = await this . now ( ) ; const greeters = await this . greetersView . values ( ) ; for ( const greeter of greeters ) { if ( greeter . language === language ) { const msg = greeter . greet ( userName ) ; return `[${ date . toISOString ( ) }] (${ language }) ${ msg }` ; } } return `[${ date . toISOString ( ) }] Hello, ${ userName }!` ; } } export async function main ( ) { const app = new GreetingApplication ( ) ; app . addGreeter ( 'greeters.EnglishGreeter' , EnglishGreeter ) ; await app . greetInEnglish ( ) ; app . addGreeter ( 'greeters.ChineseGreeter' , ChineseGreeter ) ; await app . greetInChineseThenEnglish ( ) ; return app . greetings ; } export class GreetingApplication extends Application { readonly greetings : string [ ] = [ ] ; private static requestCounter = 0 ; constructor ( ) { super ( ) ; this . bind ( GREETING_SERVICE ) . toClass ( GreetingService ) ; this . bind ( CURRENT_DATE ) . toDynamicValue ( getCurrentDate ) ; } addGreeter ( key , cls ) { this . bind ( key ) . toClass ( cls ) . tag ( 'greeter' ) ; } async greetInEnglish ( ) { const { greetingService , requestCtx } = await this . createRequest ( 'John' , 'zh' ) ; let greeting = await greetingService . greet ( 'en' , 'Jane' ) ; this . greetings . push ( greeting ) ; greeting = await invokeMethod ( greetingService , 'greet' , requestCtx ) ; this . greetings . push ( greeting ) ; requestCtx . close ( ) ; } async greetInChineseThenEnglish ( ) { const { greetingService , requestCtx } = await this . createRequest ( 'John' , 'zh' ) ; let greeting = await invokeMethod ( greetingService , 'greet' , requestCtx ) ; this . greetings . push ( greeting ) ; requestCtx . bind ( CURRENT_LANGUAGE ) . to ( 'en' ) ; requestCtx . bind ( CURRENT_USER ) . to ( 'Jane' ) ; greeting = await invokeMethod ( greetingService , 'greet' , requestCtx ) ; this . greetings . push ( greeting ) ; requestCtx . close ( ) ; } private async createRequest ( user , language ) { const requestCtx = new Context ( this , `request-${ GreetingApplication . requestCounter ++ }` ) ; requestCtx . bind ( CURRENT_USER ) . to ( user ) ; requestCtx . bind ( CURRENT_LANGUAGE ) . to ( language ) ; const greetingService = await requestCtx . get ( GREETING_SERVICE ) ; return { greetingService , requestCtx } ; } } if ( require . main === module ) { main ( ) . then ( greetings => greetings . forEach ( g => console . log ( g ) ) ) . catch ( err => { console . error ( err ) ; process . exit ( 1 ) ; } ) ; }