mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-12 02:02:13 +03:00
81 lines
2.4 KiB
TypeScript
81 lines
2.4 KiB
TypeScript
/**
|
|
* API: OpenAPI Spec
|
|
* GET — returns the parsed openapi.yaml as structured JSON catalog
|
|
*/
|
|
|
|
import { NextResponse } from "next/server";
|
|
import fs from "fs";
|
|
import path from "path";
|
|
import yaml from "js-yaml";
|
|
|
|
let cachedSpec: { data: any; mtime: number } | null = null;
|
|
|
|
export async function GET() {
|
|
try {
|
|
// Try multiple locations for the spec file
|
|
const candidates = [
|
|
path.join(process.cwd(), "docs", "openapi.yaml"),
|
|
path.join(process.cwd(), "app", "docs", "openapi.yaml"),
|
|
];
|
|
|
|
let specPath = "";
|
|
for (const p of candidates) {
|
|
if (fs.existsSync(p)) { specPath = p; break; }
|
|
}
|
|
|
|
if (!specPath) {
|
|
return NextResponse.json({ error: "openapi.yaml not found" }, { status: 404 });
|
|
}
|
|
|
|
const stat = fs.statSync(specPath);
|
|
const mtime = stat.mtimeMs;
|
|
|
|
// Use cache if file hasn't changed
|
|
if (cachedSpec && cachedSpec.mtime === mtime) {
|
|
return NextResponse.json(cachedSpec.data);
|
|
}
|
|
|
|
const content = fs.readFileSync(specPath, "utf-8");
|
|
const raw: any = yaml.load(content);
|
|
|
|
// Build a structured catalog
|
|
const catalog: any = {
|
|
info: raw.info || {},
|
|
servers: raw.servers || [],
|
|
tags: Array.isArray(raw.tags) ? raw.tags : [],
|
|
endpoints: [] as any[],
|
|
schemas: Object.keys(raw.components?.schemas || {}),
|
|
};
|
|
|
|
// Parse paths into flat endpoint list
|
|
const paths = raw.paths || {};
|
|
for (const [pathStr, methods] of Object.entries(paths as Record<string, any>)) {
|
|
if (!methods || typeof methods !== "object") continue;
|
|
for (const [method, spec] of Object.entries(methods as Record<string, any>)) {
|
|
if (["get", "post", "put", "patch", "delete"].includes(method) && spec) {
|
|
catalog.endpoints.push({
|
|
method: method.toUpperCase(),
|
|
path: pathStr,
|
|
tags: Array.isArray(spec.tags) ? spec.tags : [],
|
|
summary: spec.summary || "",
|
|
description: spec.description || "",
|
|
security: spec.security ? true : false,
|
|
parameters: spec.parameters || [],
|
|
requestBody: spec.requestBody ? true : false,
|
|
responses: Object.keys(spec.responses || {}),
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
cachedSpec = { data: catalog, mtime };
|
|
|
|
return NextResponse.json(catalog);
|
|
} catch (error: any) {
|
|
return NextResponse.json(
|
|
{ error: error.message || "Failed to parse OpenAPI spec" },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|