import fs from "fs"; import path from "path"; import { AppData } from "../data/app-data"; function extensionToFormat(extension) { switch (extension) { case ".ts": return "ts"; case ".js": return "js"; case ".json": return "json"; case ".yaml": case ".yml": return "yaml"; } } /** * Resolve a basename (no extension) to an existing file among supported formats. * Priority: .ts > .js > .json > .yaml > .yml * Errors if multiple matches exist. */ export function resolveDataFile(dir, baseName) { const matches = []; for (const extension of AppData.SupportedDataFileExtensions) { const filePath = path.join(dir, `${baseName}${extension}`); if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) { matches.push({ path: filePath, basename: `${baseName}${extension}`, extension, format: extensionToFormat(extension), }); } } if (matches.length === 0) { return null; } if (matches.length > 1) { const found = matches.map((m) => m.basename).join(", "); throw new Error(`Multiple \`${baseName}\` files found (${found}). Keep only one of: ${AppData.SupportedDataFileExtensions.join(", ")}`); } return matches[0]; } export function supportedDataFileNames(baseName) { return AppData.SupportedDataFileExtensions.map((ext) => `\`${baseName}${ext}\``).join(", "); } export function isSchemaFileName(name) { const base = path.basename(name); if (base === AppData.DbSchemaFileName) { return true; } return AppData.SupportedDataFileExtensions.some((ext) => base === `${AppData.DbSchemaFileName}${ext}`); } /** * Load a data file as a plain object. * - .ts / .js: require() and use default export (or module itself) * - .json: JSON.parse * - .yaml / .yml: Bun.YAML.parse */ export function loadDataFile(resolved) { if (resolved.format === "ts" || resolved.format === "js") { const imported = require(resolved.path); const data = imported && typeof imported === "object" && "default" in imported ? imported.default : imported; if (data == null) { throw new Error(`No default export from \`${resolved.path}\`. Please export a default module.`); } return data; } const text = fs.readFileSync(resolved.path, "utf-8"); if (resolved.format === "json") { return JSON.parse(text); } return Bun.YAML.parse(text); } export function resolveAndLoadDataFile(dir, baseName) { const resolved = resolveDataFile(dir, baseName); if (!resolved) { return null; } return { ...resolved, data: loadDataFile(resolved), }; }