Files
website/apps/docs/scripts/fix-openapi.mjs
Mauricio Siu aa524f56e5 fix: enhance OpenAPI schema handling in fix-openapi script
- Added logic to unwrap nested OpenAPI specifications from migrated APIs, improving compatibility with various API structures.
- Updated the condition for writing the fixed schema to include unwrapped status, ensuring all necessary changes are saved.
2026-02-24 01:03:44 -06:00

109 lines
3.2 KiB
JavaScript

import { readFileSync, writeFileSync } from "fs";
import { join } from "path";
const openapiPath = join(process.cwd(), "public", "openapi.json");
console.log("Fixing OpenAPI schema...");
try {
let openapi = JSON.parse(readFileSync(openapiPath, "utf8"));
let unwrapped = false;
// If the spec is nested (e.g. result.data.json from a migrated/source API), use the inner spec
if (openapi.result?.data?.json && typeof openapi.result.data.json === "object") {
openapi = openapi.result.data.json;
unwrapped = true;
console.log("✓ Unwrapped nested OpenAPI spec (result.data.json)");
}
let fixed = 0;
let securityFixed = false;
// Remove Authorization security scheme and add x-api-key
if (!openapi.components) {
openapi.components = {};
}
if (!openapi.components.securitySchemes) {
openapi.components.securitySchemes = {};
}
// Remove old Authorization scheme
if (openapi.components.securitySchemes["Authorization"]) {
delete openapi.components.securitySchemes["Authorization"];
securityFixed = true;
}
// Add x-api-key scheme
openapi.components.securitySchemes["x-api-key"] = {
type: "apiKey",
in: "header",
name: "x-api-key",
description: "API key authentication. Use YOUR-GENERATED-API-KEY",
"x-default": "your-key",
};
securityFixed = true;
// Replace global security from Authorization to x-api-key
if (openapi.security) {
openapi.security = openapi.security.filter((sec) => !sec["Authorization"]);
} else {
openapi.security = [];
}
const hasApiKeySecurity = openapi.security.some((sec) => sec["x-api-key"]);
if (!hasApiKeySecurity) {
openapi.security.push({ "x-api-key": [] });
securityFixed = true;
}
// Replace Authorization with x-api-key in all operation security
for (const [path, pathItem] of Object.entries(openapi.paths || {})) {
for (const [method, operation] of Object.entries(pathItem)) {
if (operation && operation.security) {
// Replace Authorization with x-api-key
operation.security = operation.security.map((sec) => {
if (sec["Authorization"] !== undefined) {
securityFixed = true;
return { "x-api-key": [] };
}
return sec;
});
}
}
}
// Fix empty response schemas
for (const [path, pathItem] of Object.entries(openapi.paths || {})) {
for (const [method, operation] of Object.entries(pathItem)) {
if (operation.responses) {
for (const [status, response] of Object.entries(operation.responses)) {
if (response.content && response.content["application/json"]) {
const content = response.content["application/json"];
// Check if schema is completely empty or missing
if (Object.keys(content).length === 0 || !content.schema) {
response.content["application/json"] = {
schema: {
type: "object",
description: "Successful response",
},
};
fixed++;
}
}
}
}
}
}
if (unwrapped || fixed > 0 || securityFixed) {
writeFileSync(openapiPath, JSON.stringify(openapi, null, 2));
if (fixed > 0) console.log(`✓ Fixed ${fixed} empty response schemas`);
if (securityFixed) console.log("✓ Added x-api-key security scheme");
} else {
console.log("✓ No fixes needed");
}
} catch (error) {
console.error("Error fixing OpenAPI schema:", error.message);
process.exit(1);
}