import { readFile } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; const scriptDirectory = path.dirname(fileURLToPath(import.meta.url)); const repoRoot = path.resolve(scriptDirectory, ".."); const openApiPath = path.join(repoRoot, "openapi", "RpgRoller.json"); const appTsPath = path.join(repoRoot, "RpgRoller", "frontend", "app.ts"); const generatedClientPath = path.join(repoRoot, "RpgRoller", "frontend", "generated", "api-client.ts"); const openApi = JSON.parse(await readFile(openApiPath, "utf8")); const generatedClient = await readFile(generatedClientPath, "utf8"); const appSource = await readFile(appTsPath, "utf8"); const errors = []; if (!appSource.includes("from \"./generated/api-client.js\"")) { errors.push("Frontend app.ts must import the generated api-client module."); } for (const [pathKey, pathItem] of Object.entries(openApi.paths ?? {})) { for (const [method, operation] of Object.entries(pathItem ?? {})) { if (operation === null || typeof operation !== "object") { continue; } if (typeof operation.operationId !== "string" || operation.operationId.length === 0) { errors.push(`Missing operationId for ${method.toUpperCase()} ${pathKey}`); continue; } if (!generatedClient.includes(`apiOperations.${operation.operationId}`)) { errors.push(`Generated client is missing operation export for ${operation.operationId}`); } } } if (errors.length > 0) { throw new Error(errors.join("\n")); } console.log("Frontend lint checks passed.");