import { Adaptor , AdaptorConfig } from "./adaptor/mod.ts" ; import { EndpointConfig , GenericEndpoint , EndpointWithConfigure } from "./endpoint/mod.ts" ; import { Constructor , Util } from "../util/mod.ts" ; import { MiddleWareWithConfigure , Middleware , MiddlewareConfig } from "./middleware/mod.ts" ; import { GenericEndpointInput } from "./endpoint/endpoint_input.ts" ; import { Client } from "../client.ts" ; import { Router } from "./router.ts" ; import ObservableMap from "../util/observable_map.ts" ; import instantiate = WebAssembly . instantiate ; import { HttpAdaptor } from "../adaptor/http_adaptor/adaptor.ts" ; import { Injector } from "./injector/injector.ts" ; export class EnlaceServer { #isStarted : boolean = false ; public get isStarted ( ) : boolean { return this . #isStarted ; } public start ( ) { this . #isStarted = true ; for ( const [ adaptor , configure ] of this . adaptorsToConfigure ) { adaptor . attachOnServer ( this , configure ) ; } } /**
     * A map table store the relationship between adaptors and thier own configure.
     */ public readonly adaptorsToConfigure : ObservableMap < Adaptor , AdaptorConfig > = new ObservableMap ( ) ; /**
     * Router instance contained in the EnlaceServer.
     */ public readonly router : Router = new Router ( this ) ; /**
     * A list value indicates all the adaptors in the EnlaceServer.
     */ protected get adaptors ( ) : Adaptor [ ] { return [ ... this . adaptorsToConfigure . keys ( ) ] ; } param adaptor param configure public addAdaptorWithConfigure ( adaptor , configure ) { Injector . shard . register ( adaptor ) ; const instance = Injector . shard . resolve ( adaptor ) ; if ( this . #isStarted ) { instance . attachOnServer ( this , configure ) ; } instance . didReceiveContent = ( content , client ) => { this . receiveContent ( instance , content , client ) . then ( ) ; } ; this . adaptorsToConfigure . set ( instance , configure ) ; return instance ; } param adaptor param input param client protected async receiveContent ( adaptor , input , client ) { const path = input . path ; const middleWaresWithConfigure = this . getMiddlewaresWithPathAndAdaptor ( path , adaptor ) ; const endpointWithConfigure = this . getEndpointWithPathAndAdaptor ( path , adaptor ) ; this . executeMiddleWaresWithInput ( middleWaresWithConfigure . map ( mw => mw . middleWare ) , input ) ; if ( endpointWithConfigure ) { const result = await this . executeEndpointWithConfigure ( endpointWithConfigure , path , input ) ; if ( result ) { adaptor . sendToClient ( client , result ) ; } else { } } else { } } param path param adaptor protected getMiddlewaresWithPathAndAdaptor ( path , adaptor ) { return [ ... this . router . matchMiddleWareWithPath ( path ) , ... adaptor . router . matchMiddleWareWithPath ( path ) , ] ; } param path param adaptor protected getEndpointWithPathAndAdaptor ( path , adaptor ) { let endpointWithConfigure ; const endpointWithConfigureInRoot = this . router . matchEndpointWithPath ( path ) ; if ( endpointWithConfigureInRoot && endpointWithConfigureInRoot . configure . selectAdaptor ( adaptor ) ) { endpointWithConfigure = endpointWithConfigureInRoot ; } else { const endpointWithConfigureInAdaptor = adaptor . router . matchEndpointWithPath ( path ) ; endpointWithConfigure = endpointWithConfigureInAdaptor ; } return endpointWithConfigure ; } param endpointWithConfigure param path param input returns protected async executeEndpointWithConfigure ( endpointWithConfigure , path , input ) { const pathParameters = Util . parsePath ( path , endpointWithConfigure . configure . expectedPath ) ; input . pathParameters = pathParameters ; let result = endpointWithConfigure . endpoint . receive ( input ) ; if ( result instanceof Promise ) { result = await result ; } return result ; } param middleware param input protected executeMiddleWaresWithInput ( middleware , input ) { if ( middleware . length > 0 ) { const first = middleware [ 0 ] ; first ( input , ( ) => { this . executeMiddleWaresWithInput ( middleware . splice ( 1 ) , input ) ; } ) ; } } }