Files
Chris Tate 801708a128 react-native and other things (#81)
* react native

* fixes

* pop/push

* fixes

* rename data -> state

* remove . tsbuildinfo

* fixes

* fixes

* user prompt

* fixes

* $id

* combine catalog.ts

* better actions

* repeat

* fix docs

* fixes

* fixes

* fixes

* better stream

* catalog

* fixes

* fixes

* fixes

* dialog

* sonner

* accordion

* catalog on homepage

* fixes

* more catalog

* fixes

* fixes

* refactor

* mv

* 404

* fixes

* nested

* fixes

* fixes

* fixes

* fixes

* mobile playground

* mdx

* fix mdx

* fixes

* streamdown

* fixes

* use haiku

* fixes

* great

* fixes

* fix ...

* fixes

* fixes

* fix build

* fix lint

* fix lint

* fix lint

* fix tests
2026-02-09 01:31:46 -06:00

56 lines
1.5 KiB
TypeScript

import { readFile } from "fs/promises";
import { join } from "path";
import { NextRequest, NextResponse } from "next/server";
import { mdxToCleanMarkdown } from "@/lib/mdx-to-markdown";
export async function GET(req: NextRequest) {
const { searchParams } = new URL(req.url);
const docPath = searchParams.get("path");
if (!docPath) {
return NextResponse.json(
{ error: "Missing ?path= parameter" },
{ status: 400 },
);
}
// Sanitize path: only allow docs paths, no traversal
const normalized = docPath
.replace(/^\//, "")
.replace(/\.\./g, "")
.replace(/[^a-zA-Z0-9/-]/g, "");
if (!normalized.startsWith("docs")) {
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
}
// Map URL path to file path
// /docs -> /app/(main)/docs/page.mdx
// /docs/installation -> /app/(main)/docs/installation/page.mdx
const slug = normalized === "docs" ? "" : normalized.replace(/^docs\/?/, "");
const filePath = slug
? join(
process.cwd(),
"app",
"(main)",
"docs",
...slug.split("/"),
"page.mdx",
)
: join(process.cwd(), "app", "(main)", "docs", "page.mdx");
try {
const raw = await readFile(filePath, "utf-8");
const markdown = mdxToCleanMarkdown(raw);
return new NextResponse(markdown, {
headers: {
"Content-Type": "text/markdown; charset=utf-8",
"Cache-Control": "public, max-age=3600",
},
});
} catch {
return NextResponse.json({ error: "Page not found" }, { status: 404 });
}
}