import { normalize, extname } from "node:path"; import YAML from "yaml"; import TOML from "smol-toml"; import EMDY from "@endeavorance/emdy"; import type { MuseEntry, UnknownRecord } from "./types"; function parseYAMLEntries(text: string): UnknownRecord[] { const parsedDocs = YAML.parseAllDocuments(text); if (parsedDocs.some((doc) => doc.toJS() === null)) { throw new Error("Encountered NULL resource"); } const errors = parsedDocs.flatMap((doc) => doc.errors); if (errors.length > 0) { throw new Error( `Error parsing YAML resource: ${errors.map((e) => e.message).join(", ")}`, ); } const collection: UnknownRecord[] = parsedDocs.map((doc) => doc.toJS()); return collection; } function parseJSONEntries(text: string): UnknownRecord[] { const parsed = JSON.parse(text); if (Array.isArray(parsed)) { return parsed; } if (typeof parsed === "object") { return [parsed]; } throw new Error("JSON resource must be an object or an array of objects"); } function parseTOMLEntries(text: string): UnknownRecord[] { const parsed = TOML.parse(text); if (Array.isArray(parsed)) { return parsed; } if (typeof parsed === "object") { return [parsed]; } throw new Error("TOML resource must be an object or an array of objects"); } interface ParseMuseFileOptions { contentKey?: string; } export async function parseMuseFile( rawFilePath: string, { contentKey = "content" }: ParseMuseFileOptions = {}, ): Promise { const filePath = normalize(rawFilePath); const file = Bun.file(filePath); const fileType = extname(filePath).slice(1); const rawFileContent = await file.text(); const partial = { _raw: rawFileContent, filePath, meta: {}, }; if (fileType === "md") { const parsed = EMDY.parse(rawFileContent, contentKey); return [ { ...partial, data: parsed, }, ]; } if (fileType === "yaml") { return parseYAMLEntries(rawFileContent).map((data) => ({ ...partial, data, })); } if (fileType === "json") { return parseJSONEntries(rawFileContent).map((data) => ({ ...partial, data, })); } if (fileType === "toml") { return parseTOMLEntries(rawFileContent).map((data) => ({ ...partial, data, })); } throw new Error(`Unsupported file type: ${fileType}`); }