mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-07-14 18:15:56 -04:00
feat(server): serve normalized OpenAPI spec at /api/v1/spec.json with shared schema components
Extract spec generation into `openapi-spec.ts` with a `generateOpenApiSpec` function that registers common `$ref` schemas (Title, Person, Episode, Season, etc.) to deduplicate inline definitions across the spec. Add a `/api/v1/spec.json` interceptor that returns the fully normalized document, and point the Scalar docs UI at it instead of the plugin's raw generator output.
Also strip oRPC's impossible `{ not: {} }` void placeholders from request/response bodies via `normalizeOpenApiSpec`, and fix the handler registration so both `/api/v1` and `/api/v1/*` routes are matched.
This commit is contained in:
@@ -1,43 +1,15 @@
|
||||
import { OpenAPIGenerator } from "@orpc/openapi";
|
||||
import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4";
|
||||
import { contract } from "@sofa/api/contract";
|
||||
|
||||
import packageJson from "../apps/server/package.json" with { type: "json" };
|
||||
import {
|
||||
generateOpenApiSpec,
|
||||
openApiTags,
|
||||
} from "../apps/server/src/orpc/openapi-spec";
|
||||
|
||||
const generator = new OpenAPIGenerator({
|
||||
schemaConverters: [new ZodToJsonSchemaConverter()],
|
||||
});
|
||||
|
||||
const spec = await generator.generate(contract, {
|
||||
info: { title: "Sofa API", version: packageJson.version || "1.0.0" },
|
||||
const spec = await generateOpenApiSpec({
|
||||
title: "Sofa API",
|
||||
version: packageJson.version || "1.0.0",
|
||||
servers: [{ url: "https://sofa.example.com/api/v1" }],
|
||||
tags: [
|
||||
{ name: "Titles", description: "Movie and TV show management" },
|
||||
{ name: "Episodes", description: "Episode watch tracking" },
|
||||
{ name: "Seasons", description: "Season watch tracking" },
|
||||
{ name: "People", description: "Cast and crew information" },
|
||||
{ name: "Dashboard", description: "User dashboard data" },
|
||||
{ name: "Explore", description: "Discover trending and popular content" },
|
||||
{ name: "Search", description: "Search for movies and TV shows" },
|
||||
{
|
||||
name: "Discover",
|
||||
description: "Advanced content discovery with filters",
|
||||
},
|
||||
{ name: "System", description: "Server status and configuration" },
|
||||
{ name: "Integrations", description: "Media server integrations" },
|
||||
{ name: "Admin", description: "Server administration" },
|
||||
{ name: "Account", description: "User account management" },
|
||||
],
|
||||
components: {
|
||||
securitySchemes: {
|
||||
session: {
|
||||
type: "apiKey",
|
||||
name: "better-auth.session_token",
|
||||
in: "cookie",
|
||||
description: "Better Auth session cookie",
|
||||
},
|
||||
},
|
||||
},
|
||||
sessionCookieName: "better-auth.session_token",
|
||||
tags: [...openApiTags],
|
||||
});
|
||||
|
||||
// Normalize file upload media types that fumadocs-openapi doesn't support
|
||||
|
||||
Reference in New Issue
Block a user