feat: complete search REST route, restore disk sync, and extraFields support across API/MCP

This commit is contained in:
asepharyana
2026-08-21 11:03:04 +07:00
parent 989ee9c464
commit a67a8c6469
11 changed files with 319 additions and 34 deletions
+2 -3
View File
@@ -60,11 +60,10 @@ export function parseFile(absPath: string, relPath: string): ParsedFile {
// Extract any non-standard frontmatter keys as dynamic extra fields.
// These are stored in DB as JSONB + rendered as dynamic badges in the UI.
const extraFields: Record<string, string> = {};
const extraFields: Record<string, unknown> = {};
for (const [k, v] of Object.entries(data)) {
if (!STANDARD_FRONTMATTER_KEYS.has(k) && v !== undefined && v !== null) {
// Serialize non-string values (numbers, booleans) to string
extraFields[k] = typeof v === "string" ? v : JSON.stringify(v);
extraFields[k] = v;
}
}
+53
View File
@@ -79,3 +79,56 @@ test("parseFile: body excludes frontmatter delimiter", () => {
expect(body).not.toContain("---");
expect(body).toContain("# Real body");
});
test("parseFile: extracts dynamic extra fields", () => {
const { meta } = writeDoc(
"writeups/ctf/chal.md",
[
"---",
'title: CTF Challenge',
'event: DEF CON 2024',
'points: 100',
'solved: true',
"---",
"# Solved",
].join("\n"),
);
expect(meta.extraFields?.event).toBe("DEF CON 2024");
expect(meta.extraFields?.points).toBe(100);
expect(meta.extraFields?.solved).toBe(true);
});
test("stringifyFile: writes file that round-trips via parseFile", async () => {
const { stringifyFile } = await import("../src/index");
const p = join(tmp, "docs/roundtrip.md");
const meta = {
id: "docs/roundtrip",
slug: "docs/roundtrip",
title: "Roundtrip Test",
type: "documentation" as const,
section: "docs" as const,
status: "published" as const,
author: "tester",
tags: ["a", "b"],
path: "docs/roundtrip.md",
createdAt: "2026-08-21T00:00:00.000Z",
updatedAt: "2026-08-21T00:00:00.000Z",
extraFields: {
event: "DEF CON",
difficulty: "medium",
points: 500,
},
};
const body = "# Content\n\nParagraph content.";
stringifyFile(p, "docs/roundtrip.md", meta, body);
const parsed = parseFile(p, "docs/roundtrip.md");
expect(parsed.meta.title).toBe("Roundtrip Test");
expect(parsed.meta.author).toBe("tester");
expect(parsed.meta.tags).toEqual(["a", "b"]);
expect(parsed.meta.extraFields?.event).toBe("DEF CON");
expect(parsed.meta.extraFields?.difficulty).toBe("medium");
expect(parsed.meta.extraFields?.points).toBe(500);
expect(parsed.body.trim()).toBe(body);
});