evcc-io/scripts/state-schema/openapi.ts
andig c3f3384bfc
API: generate /api/state documentation from UI types (#32431)
Co-authored-by: Michael Geers <michael@geers.tv>
2026-08-03 11:06:37 +00:00

38 lines
1.4 KiB
TypeScript

import { readFileSync, writeFileSync } from "node:fs";
import { parse, stringify } from "yaml";
import { bundle, createConfig } from "@redocly/openapi-core";
import type { StateSchemas } from "./schemas";
const OPENAPI_PATH = "server/openapi.yaml";
const STATE_PATH = "server/openapi.state.yaml";
const MCP_JSON_PATH = "server/mcp/openapi.json";
const HEADER = `# GENERATED FILE - DO NOT EDIT (source: assets/js/types/evcc.ts, update: make openapi)
`;
export function writeStateSchemas(schemas: StateSchemas): void {
const root = parse(readFileSync(OPENAPI_PATH, "utf8"));
const handWritten = new Set(Object.keys(root.components?.schemas ?? {}));
for (const name of Object.keys(schemas.defs)) {
if (handWritten.has(name)) {
throw new Error(`generated schema "${name}" collides with hand-written component`);
}
}
const doc =
HEADER +
stringify(
{ components: { schemas: schemas.defs } },
{ lineWidth: 0, aliasDuplicateObjects: false }
);
writeFileSync(STATE_PATH, doc);
}
// inline the multi-file spec into the single json embedded by the MCP server
export async function bundleMcpJson(): Promise<void> {
const { bundle: result } = await bundle({ ref: OPENAPI_PATH, config: await createConfig({}) });
const doc = result.parsed as { servers?: unknown };
delete doc.servers; // mcp server sets its own url
writeFileSync(MCP_JSON_PATH, JSON.stringify(doc, null, 2) + "\n");
}