import { readdir, readFile } from 'node:fs/promises' import { existsSync } from 'node:fs' import { join, extname, resolve } from 'node:path' import type { Resource } from './types.js' import { pathToFileURL } from 'node:url' /** * Load all resource definitions from collections/, questions/, dashboards/ subdirs. * Supports .ts/.js files that default-export a Resource, and .sql/.mongodb + .meta.json pairs. */ export async function loadResources(baseDir: string = '.'): Promise { const resources: Resource[] = [] const root = resolve(baseDir) const subdirs = ['collections', 'questions', 'dashboards', 'snippets'] for (const subdir of subdirs) { const dir = join(root, subdir) if (!existsSync(dir)) continue const files = await readdir(dir) for (const file of files) { const ext = extname(file) if (ext === '.ts' || ext === '.js') { const filePath = join(dir, file) const mod = await import(pathToFileURL(filePath).href) const resource = mod.default as Resource if (resource && resource.kind) { resources.push(resource) } } else if (ext === '.sql' || ext === '.mongodb') { const baseName = file.replace(/\.(sql|mongodb)$/, '') const metaPath = join(dir, `${baseName}.meta.json`) if (existsSync(metaPath)) { const content = await readFile(join(dir, file), 'utf-8') const meta = JSON.parse(await readFile(metaPath, 'utf-8')) if (subdir === 'snippets') { resources.push({ kind: 'snippet', content, ...meta, }) } else { resources.push({ kind: 'question', type: 'native', query: content, ...meta, }) } } } } } return resources }