import { pathToFileURL } from 'url'; import * as path from 'path'; import * as fs from 'fs'; import { InvalidMiddlewareException, InvalidRouteException } from '../exceptions'; import { Route, HttpHandler, Middleware } from '../http'; import Registry from './Registry'; class DynamicRegistry extends Registry { private readonly routesDir?: string; private readonly middlewaresDir?: string; public constructor(routesDir?: string, middlewaresDir?: string) { super(); this.routesDir = routesDir; this.middlewaresDir = middlewaresDir; } protected async registerRoutes(): Promise { if(this.routesDir == null) return this; const routesDir: string = this.routesDir; const files = fs.readdirSync(routesDir, { recursive: true, encoding: 'utf8' }); for(const file of files) { if(/\.js$/.test(file)) { const fileUrl = pathToFileURL(path.join(routesDir, file)).toString(); const RouteClass = await import(fileUrl).then(mod => mod.default?.default ?? mod.default ?? mod); if(RouteClass.prototype instanceof Route) { this.registerHttpHandler(new RouteClass(this.getServer())); } else throw new InvalidRouteException(fileUrl); } } return this; } protected async registerMiddlewares(): Promise { if(this.middlewaresDir == null) return this; const middlewaresDir: string = this.middlewaresDir; const files = fs.readdirSync(middlewaresDir, { recursive: true, encoding: 'utf8' }); for(const file of files) { if(/\.js$/.test(file)) { const fileUrl = pathToFileURL(path.join(middlewaresDir, file)).toString(); const MiddlewareClass = await import(fileUrl).then(mod => mod.default?.default ?? mod.default ?? mod); if(MiddlewareClass.prototype instanceof Middleware) { this.registerHttpHandler(new MiddlewareClass(this.getServer())); } else throw new InvalidMiddlewareException(fileUrl); } } return this; } } export default DynamicRegistry;