singularity-forge/web/app/api/experimental/route.ts
2026-05-05 14:46:18 +02:00

123 lines
4.1 KiB
TypeScript

import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { homedir } from "node:os";
import { dirname, join } from "node:path";
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
export const runtime = "nodejs";
export const dynamic = "force-dynamic";
const NO_STORE = { "Cache-Control": "no-store" } as const;
// ─── Helpers (same pattern as remote-questions/route.ts) ─────────────────────
function getPreferencesPath(): string {
return join(homedir(), ".sf", "PREFERENCES.md");
}
function parseFrontmatter(content: string): {
data: Record<string, unknown>;
body: string;
} {
const startMarker = content.startsWith("---\r\n") ? "---\r\n" : "---\n";
if (!content.startsWith(startMarker)) return { data: {}, body: content };
const searchStart = startMarker.length;
const endIdx = content.indexOf("\n---", searchStart);
if (endIdx === -1) return { data: {}, body: content };
const block = content.slice(searchStart, endIdx);
const afterFrontmatter = content.slice(endIdx + 4);
try {
const parsed = parseYaml(block.replace(/\r/g, ""));
const data =
typeof parsed === "object" && parsed !== null
? (parsed as Record<string, unknown>)
: {};
return { data, body: afterFrontmatter };
} catch {
return { data: {}, body: content };
}
}
function writeFrontmatter(data: Record<string, unknown>, body: string): string {
const yamlStr = stringifyYaml(data, { lineWidth: 0 }).trimEnd();
return `---\n${yamlStr}\n---${body}`;
}
function readPrefs(): { data: Record<string, unknown>; body: string } {
const path = getPreferencesPath();
if (!existsSync(path)) return { data: {}, body: "\n" };
const content = readFileSync(path, "utf-8");
return parseFrontmatter(content);
}
function writePrefs(data: Record<string, unknown>, body: string): void {
const path = getPreferencesPath();
const dir = dirname(path);
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
writeFileSync(path, writeFrontmatter(data, body), "utf-8");
}
// ─── GET — read current experimental flags ───────────────────────────────────
export async function GET(): Promise<Response> {
try {
const { data } = readPrefs();
const exp =
typeof data.experimental === "object" && data.experimental !== null
? (data.experimental as Record<string, unknown>)
: {};
return Response.json({ rtk: exp.rtk === true }, { headers: NO_STORE });
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
return Response.json(
{ error: message },
{ status: 500, headers: NO_STORE },
);
}
}
// ─── PATCH — toggle an experimental flag ────────────────────────────────────
//
// Body: { flag: "rtk", enabled: boolean }
export async function PATCH(request: Request): Promise<Response> {
try {
const body = (await request.json()) as Record<string, unknown>;
const { flag, enabled } = body;
const KNOWN_FLAGS = new Set(["rtk"]);
if (typeof flag !== "string" || !KNOWN_FLAGS.has(flag)) {
return Response.json(
{
error: `Unknown experimental flag "${flag}". Known flags: ${[...KNOWN_FLAGS].join(", ")}`,
},
{ status: 400, headers: NO_STORE },
);
}
if (typeof enabled !== "boolean") {
return Response.json(
{ error: "enabled must be a boolean" },
{ status: 400, headers: NO_STORE },
);
}
const { data, body: mdBody } = readPrefs();
// Merge into experimental block
const existing =
typeof data.experimental === "object" && data.experimental !== null
? { ...(data.experimental as Record<string, unknown>) }
: {};
existing[flag] = enabled;
data.experimental = existing;
writePrefs(data, mdBody);
return Response.json({ [flag]: enabled }, { headers: NO_STORE });
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
return Response.json(
{ error: `Failed to update experimental flag: ${message}` },
{ status: 500, headers: NO_STORE },
);
}
}