This commit is contained in:
Endeavorance 2025-02-24 14:03:04 -05:00
parent 45580288e1
commit 8b276cc226
5 changed files with 145 additions and 119 deletions

View file

@ -3,12 +3,71 @@ import {
AnyResourceSchema,
ResourceMap,
} from "@proscenium/playbill";
import YAML from "yaml";
import YAML, { YAMLParseError } from "yaml";
import { extractFrontmatter, extractMarkdown } from "./markdown";
type FileFormat = "yaml" | "markdown";
export class ResourceFileError extends Error {}
export class NullResourceError extends Error {}
export class ResourceFileError extends Error { }
export class NullResourceError extends Error { }
function determineFileFormat(filePath: string): FileFormat {
return filePath.split(".").pop() === "md" ? "markdown" : "yaml";
}
function loadYamlResourceFile(filePath: string, text: string): AnyResource[] {
const parsedDocs = YAML.parseAllDocuments(text);
if (parsedDocs.some((doc) => doc.toJS() === null)) {
throw new NullResourceError(`Null resource defined in ${filePath}`);
}
const errors = parsedDocs.flatMap((doc) => doc.errors);
if (errors.length > 0) {
throw new ResourceFileError(`Error parsing ${filePath}: ${errors}`);
}
const collection: AnyResource[] = [];
for (const doc of parsedDocs) {
if (doc.errors.length > 0) {
throw new ResourceFileError(`Error parsing ${filePath}: ${doc.errors}`);
}
const raw = doc.toJS();
const parsed = AnyResourceSchema.parse(raw);
const type = parsed.$define;
const schemaToUse = ResourceMap[type];
const validated = schemaToUse.parse(parsed);
collection.push(validated);
}
return collection;
}
function loadMarkdownResourceFile(
filePath: string,
text: string,
): AnyResource[] {
try {
const frontmatter = extractFrontmatter(text);
const markdown = extractMarkdown(text);
const together = {
...frontmatter,
description: markdown,
};
const parsed = AnyResourceSchema.parse(together);
return [parsed];
} catch (e) {
if (e instanceof YAMLParseError) {
throw new ResourceFileError(`Error parsing frontmatter in ${filePath}`);
}
throw e;
}
}
/**
* Load and process all documents in a yaml file at the given path
@ -22,49 +81,13 @@ export async function loadResourceFile(
filePath: string,
): Promise<AnyResource[]> {
const file = Bun.file(filePath);
const format: FileFormat =
filePath.split(".").pop() === "md" ? "markdown" : "yaml";
const text = await file.text();
const format = determineFileFormat(filePath);
if (format === "yaml") {
const parsedDocs = YAML.parseAllDocuments(text);
if (parsedDocs.some((doc) => doc.toJS() === null)) {
throw new NullResourceError(`Null resource defined in ${filePath}`);
}
const errors = parsedDocs.flatMap((doc) => doc.errors);
if (errors.length > 0) {
throw new ResourceFileError(`Error parsing ${filePath}: ${errors}`);
}
const collection: AnyResource[] = [];
for (const doc of parsedDocs) {
if (doc.errors.length > 0) {
throw new ResourceFileError(`Error parsing ${filePath}: ${doc.errors}`);
}
const raw = doc.toJS();
const parsed = AnyResourceSchema.parse(raw);
const type = parsed.$define;
const schemaToUse = ResourceMap[type];
const validated = schemaToUse.parse(parsed);
collection.push(validated);
}
return collection;
switch (format) {
case "yaml":
return loadYamlResourceFile(filePath, text);
case "markdown":
return loadMarkdownResourceFile(filePath, text);
}
const frontmatter = extractFrontmatter(text);
const markdown = extractMarkdown(text);
const together = {
...frontmatter,
description: markdown,
};
const parsed = AnyResourceSchema.parse(together);
return [parsed];
}