import * as fs from 'fs' import * as path from 'path' import { pathToFileURL } from 'url' import Logger, { LoggerType } from '#application/logger' import Storage from '#application/storage' import { Command } from '#application/types' export class CommandRegistry { private readonly commands: Map = new Map() private readonly logger = Logger.type(LoggerType.COMMAND) public getCommand(name: string): Command | undefined { return this.commands.get(name) } public async loadCommands(): Promise { const directory = Storage.getAppPath('commands') this.logger.info(`Loading commands from: ${directory}`) try { const files = await fs.promises.readdir(directory, { withFileTypes: true }) await Promise.all(files.filter((file) => this.isValidCommandFile(file)).map((file) => this.loadCommandFile(file))) } catch (error) { this.logger.error(`Failed to read commands directory: ${error instanceof Error ? error.message : String(error)}`) } } private isValidCommandFile(file: fs.Dirent): boolean { return file.isFile() && (file.name.endsWith('.ts') || file.name.endsWith('.js')) } private async loadCommandFile(file: fs.Dirent): Promise { try { const filePath = Storage.getAppPath('commands', file.name) const commandName = path.basename(file.name, path.extname(file.name)) const module = await import(pathToFileURL(filePath).href) if (typeof module.default !== 'function') { this.logger.warn(`Unrecognized export in ${file.name}`) return } this.registerCommand(commandName, module.default) } catch (error) { this.logger.error(`Error loading command ${file.name}: ${error instanceof Error ? error.message : String(error)}`) } } private registerCommand(name: string, CommandClass: Command): void { if (this.commands.has(name)) { this.logger.warn(`Command '${name}' is already registered. Overwriting...`) } this.commands.set(name, CommandClass) this.logger.info(`Registered command: ${name}`) } }