UNPKG

next-openapi-gen

Version:

Automatically generate OpenAPI 3.0 documentation from Next.js projects, with support for TypeScript types and Zod schemas.

74 lines (73 loc) 2.72 kB
import path from "path"; import fs from "fs"; import { RouteProcessor } from "./route-processor.js"; import { cleanSpec } from "./utils.js"; export class OpenApiGenerator { config; template; routeProcessor; constructor() { const templatePath = path.resolve("./next.openapi.json"); this.template = JSON.parse(fs.readFileSync(templatePath, "utf-8")); this.config = this.getConfig(); this.routeProcessor = new RouteProcessor(this.config); } getConfig() { // @ts-ignore const { apiDir, schemaDir, docsUrl, ui, outputFile, includeOpenApiRoutes, schemaType = "typescript" } = this.template; return { apiDir, schemaDir, docsUrl, ui, outputFile, includeOpenApiRoutes, schemaType, }; } generate() { const { apiDir } = this.config; // Check if app router structure exists let appRouterApiDir = ""; if (fs.existsSync(path.join(path.dirname(apiDir), "app", "api"))) { appRouterApiDir = path.join(path.dirname(apiDir), "app", "api"); console.log(`Found app router API directory at ${appRouterApiDir}`); } // Scan pages router routes this.routeProcessor.scanApiRoutes(apiDir); // If app router directory exists, scan it as well if (appRouterApiDir) { this.routeProcessor.scanApiRoutes(appRouterApiDir); } this.template.paths = this.routeProcessor.getSwaggerPaths(); // Add server URL for examples if not already defined if (!this.template.servers || this.template.servers.length === 0) { this.template.servers = [ { url: this.template.basePath || "", description: "API server", }, ]; } // Ensure there's a components section if not already defined if (!this.template.components) { this.template.components = {}; } // Add schemas section if not already defined if (!this.template.components.schemas) { this.template.components.schemas = {}; } // Get defined schemas from the processor const definedSchemas = this.routeProcessor .getSchemaProcessor() .getDefinedSchemas(); if (definedSchemas && Object.keys(definedSchemas).length > 0) { this.template.components.schemas = { ...this.template.components.schemas, ...definedSchemas, }; } const openapiSpec = cleanSpec(this.template); return openapiSpec; } }