77 lines
1.8 KiB
TypeScript
77 lines
1.8 KiB
TypeScript
|
|
import { ApiModule, ModuleMetadata } from './types.js'
|
||
|
|
import { ServiceContainer } from './container.js'
|
||
|
|
|
||
|
|
export class ModuleManager {
|
||
|
|
private modules = new Map<string, ApiModule>()
|
||
|
|
private activeModules = new Set<string>()
|
||
|
|
private container: ServiceContainer
|
||
|
|
|
||
|
|
constructor(container: ServiceContainer) {
|
||
|
|
this.container = container
|
||
|
|
}
|
||
|
|
|
||
|
|
async register(module: ApiModule): Promise<void> {
|
||
|
|
const { id, dependencies = [] } = module.metadata
|
||
|
|
|
||
|
|
for (const dep of dependencies) {
|
||
|
|
if (!this.modules.has(dep)) {
|
||
|
|
throw new Error(`Module '${id}' depends on '${dep}' which is not registered`)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
this.modules.set(id, module)
|
||
|
|
|
||
|
|
if (module.lifecycle?.onLoad) {
|
||
|
|
await module.lifecycle.onLoad(this.container)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async activate(id: string): Promise<void> {
|
||
|
|
const module = this.modules.get(id)
|
||
|
|
if (!module) {
|
||
|
|
throw new Error(`Module '${id}' not found`)
|
||
|
|
}
|
||
|
|
|
||
|
|
if (this.activeModules.has(id)) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
const { dependencies = [] } = module.metadata
|
||
|
|
for (const dep of dependencies) {
|
||
|
|
await this.activate(dep)
|
||
|
|
}
|
||
|
|
|
||
|
|
if (module.lifecycle?.onActivate) {
|
||
|
|
await module.lifecycle.onActivate(this.container)
|
||
|
|
}
|
||
|
|
|
||
|
|
this.activeModules.add(id)
|
||
|
|
}
|
||
|
|
|
||
|
|
async deactivate(id: string): Promise<void> {
|
||
|
|
const module = this.modules.get(id)
|
||
|
|
if (!module) return
|
||
|
|
|
||
|
|
if (!this.activeModules.has(id)) return
|
||
|
|
|
||
|
|
if (module.lifecycle?.onDeactivate) {
|
||
|
|
await module.lifecycle.onDeactivate(this.container)
|
||
|
|
}
|
||
|
|
|
||
|
|
this.activeModules.delete(id)
|
||
|
|
}
|
||
|
|
|
||
|
|
getModule(id: string): ApiModule | undefined {
|
||
|
|
return this.modules.get(id)
|
||
|
|
}
|
||
|
|
|
||
|
|
getAllModules(): ApiModule[] {
|
||
|
|
return Array.from(this.modules.values())
|
||
|
|
.sort((a, b) => (a.metadata.order || 0) - (b.metadata.order || 0))
|
||
|
|
}
|
||
|
|
|
||
|
|
getActiveModules(): string[] {
|
||
|
|
return Array.from(this.activeModules)
|
||
|
|
}
|
||
|
|
}
|