import { NodeCG } from "nodecg-types/types/server" ; import { ObjectMap , Service , ServiceDependency , ServiceInstance } from "./service" ; import { emptySuccess , error , Result } from "./utils/result" ; import { EventEmitter } from "events" ; import { ServiceProvider } from "./serviceProvider" ; /**
 * Manages bundles and their dependencies on nodecg-io services.
 */ export class BundleManager extends EventEmitter { private readonly bundles : ObjectMap < ServiceDependency < unknown > [ ] > = { } ; constructor ( private readonly nodecg ) { super ( ) ; } return { ObjectMap < ServiceDependency < unknown > [ ] > } getBundleDependencies ( ) { return this . bundles ; } param bundleName param service param clientUpdate return a  ServiceProvider that allows the bundle to access the service client, if a service instance is set
     * and there were no errors in the client creation.
      registerServiceDependency < C > ( bundleName , service ) { const serviceDependencies = this . bundles [ bundleName ] ?? [ ] ; if ( serviceDependencies . find ( ( sd ) => sd . serviceType === service . serviceType ) ) { this . nodecg . log . info ( `Bundle "${ bundleName }" has registered a dependency to the service "${ service . serviceType }" more than once!` ) ; return ; } const provider = new ServiceProvider < C > ( ) ; serviceDependencies . push ( { serviceType : service . serviceType , serviceInstance : undefined , provider } ) ; this . bundles [ bundleName ] = serviceDependencies ; this . emit ( "change" ) ; this . nodecg . log . info ( `Bundle "${ bundleName }" has registered a dependency on the service "${ service . serviceType }"` ) ; return provider ; } /**
     * Assigns a service instance to the service dependency of a bundle and gives the bundle access to the current
     * service client. Future client updates will be handled through  BundleManager . handleInstanceUpdate .
     *  param bundleName param instanceName param instance setServiceDependency ( bundleName , instanceName , instance ) { const bundle = this . bundles [ bundleName ] ; if ( bundle === undefined ) { return error ( `Bundle "${ bundleName }" couldn't be found.` ) ; } const svcDependency = bundle . find ( ( svcDep ) => svcDep . serviceType === instance . serviceType ) ; if ( svcDependency === undefined ) { return error ( `Bundle "${ bundleName } doesn't depend on the "${ instance . serviceType }" service.` ) ; } const oldInstance = svcDependency . serviceInstance ; svcDependency . serviceInstance = instanceName ; svcDependency . provider . updateClient ( instance . client ) ; this . emit ( "change" ) ; this . emit ( "reregisterInstance" , oldInstance ) ; return emptySuccess ( ) ; } param bundleName param serviceType return unsetServiceDependency ( bundleName , serviceType ) { const bundle = this . bundles [ bundleName ] ; const svcDependency = bundle ?. find ( ( svcDep ) => svcDep . serviceType === serviceType ) ; if ( svcDependency !== undefined ) { const oldInstance = svcDependency . serviceInstance ; svcDependency . serviceInstance = undefined ; svcDependency . provider . updateClient ( undefined ) ; this . emit ( "change" ) ; this . emit ( "reregisterInstance" , oldInstance ) ; return true ; } return false ; } param serviceInstance param instName handleInstanceUpdate ( serviceInstance , instName ) { Object . entries ( this . bundles ) . forEach ( ( [ _bundleName , svcDependencies ] ) => { svcDependencies . forEach ( ( dep ) => { if ( dep . serviceInstance === instName ) { dep . provider . updateClient ( serviceInstance . client ) ; } } ) ; } ) ; } }