import { readdirSync, statSync } from 'fs' import { join, dirname } from 'path' import { fileURLToPath } from 'url' import type { ApiModule } from '../infra/types.js' const __filename = fileURLToPath(import.meta.url) const __dirname = dirname(__filename) const moduleFactoryPattern = /^create\w+Module$/ async function discoverModules(): Promise { const modules: ApiModule[] = [] const entries = readdirSync(__dirname) for (const entry of entries) { const entryPath = join(__dirname, entry) try { const stats = statSync(entryPath) if (!stats.isDirectory()) { continue } const moduleIndexPath = join(entryPath, 'index.ts') let moduleIndexStats: ReturnType try { moduleIndexStats = statSync(moduleIndexPath) } catch { continue } if (!moduleIndexStats.isFile()) { continue } const moduleExports = await import(`./${entry}/index.js`) for (const exportName of Object.keys(moduleExports)) { if (moduleFactoryPattern.test(exportName)) { const factory = moduleExports[exportName] if (typeof factory === 'function') { const module = factory() as ApiModule modules.push(module) } } } } catch (error) { console.warn(`[ModuleLoader] Failed to load module '${entry}':`, error) } } modules.sort((a, b) => { const orderA = a.metadata.order ?? 0 const orderB = b.metadata.order ?? 0 return orderA - orderB }) return modules } export const apiModules: ApiModule[] = await discoverModules() export * from './todo/index.js' export * from './time-tracking/index.js' export * from './recycle-bin/index.js' export * from './pydemos/index.js' export * from './document-parser/index.js' export * from './ai/index.js' export * from './remote/index.js'