Files
sofa/scripts/generate-openapi-spec.ts
T
jake 4ce285f721 feat(docs): use parameterized OpenAPI server URL
Replace the static `https://sofa.example.com/api/v1` server entry with a variable-based URL (`{protocol}://{host}:{port}/api/v1`) so the spec works against any instance out of the box. Also move the output path from `docs/openapi.json` to `docs/public/openapi.json` so the file is served as a static asset by the docs site.
2026-03-15 14:40:33 -04:00

76 lines
2.0 KiB
TypeScript

import packageJson from "../apps/server/package.json" with { type: "json" };
import {
generateOpenApiSpec,
openApiTags,
} from "../apps/server/src/orpc/openapi-spec";
const spec = await generateOpenApiSpec({
title: "Sofa API",
version: packageJson.version || "1.0.0",
servers: [
{
url: "{protocol}://{host}:{port}/api/v1",
variables: {
protocol: {
default: "http",
enum: ["http", "https"],
},
host: {
default: "localhost",
},
port: {
default: "3000",
},
},
},
],
sessionCookieName: "better-auth.session_token",
tags: [...openApiTags],
});
// Normalize file upload media types that fumadocs-openapi doesn't support
// (e.g. image/jpeg, image/png, */*) to multipart/form-data
const supportedMediaTypes = new Set([
"application/json",
"multipart/form-data",
"application/x-www-form-urlencoded",
"application/octet-stream",
"text/plain",
]);
for (const pathItem of Object.values(spec.paths ?? {})) {
if (!pathItem) continue;
const httpMethods = [
"get",
"put",
"post",
"delete",
"options",
"head",
"patch",
"trace",
] as const;
for (const key of httpMethods) {
const method = pathItem[key];
if (!method?.requestBody || !("content" in method.requestBody)) continue;
const content = method.requestBody.content;
const unsupported = Object.keys(content).filter(
(type) => !supportedMediaTypes.has(type),
);
if (unsupported.length > 0) {
// Replace unsupported types with a single multipart/form-data entry
for (const type of unsupported) delete content[type];
content["multipart/form-data"] = {
schema: {
type: "object",
properties: { file: { type: "string", format: "binary" } },
required: ["file"],
},
};
}
}
}
await Bun.write("docs/public/openapi.json", JSON.stringify(spec, null, 2));
console.log("OpenAPI spec written to docs/openapi.json");