openapi-ai-generator 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cache.ts","../src/providers/index.ts","../src/analyzer.ts","../src/config.ts","../src/generator.ts","../src/scanner.ts","../src/index.ts","../src/plugin.ts"],"names":["createHash","existsSync","mkdirSync","join","readFileSync","writeFileSync","generateText","resolve","url","pathToFileURL","dirname","relative","generate"],"mappings":"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","file":"plugin.js","sourcesContent":["import { createHash } from 'crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\n\nexport interface CacheEntry {\n\thash: string;\n\tpathItem: Record<string, unknown>;\n\tcachedAt: string;\n}\n\nexport function computeHash(content: string, provider: string, modelId: string): string {\n\treturn createHash('sha256').update(content).update(provider).update(modelId).digest('hex');\n}\n\nexport class RouteCache {\n\tprivate readonly cacheDir: string;\n\n\tconstructor(cacheDir: string) {\n\t\tthis.cacheDir = cacheDir;\n\t}\n\n\tprivate ensureDir(): void {\n\t\tif (!existsSync(this.cacheDir)) {\n\t\t\tmkdirSync(this.cacheDir, { recursive: true });\n\t\t}\n\t}\n\n\tget(hash: string): Record<string, unknown> | null {\n\t\tconst filePath = join(this.cacheDir, `${hash}.json`);\n\t\tif (!existsSync(filePath)) return null;\n\t\ttry {\n\t\t\tconst entry: CacheEntry = JSON.parse(readFileSync(filePath, 'utf8'));\n\t\t\treturn entry.pathItem;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tset(hash: string, pathItem: Record<string, unknown>): void {\n\t\tthis.ensureDir();\n\t\tconst entry: CacheEntry = {\n\t\t\thash,\n\t\t\tpathItem,\n\t\t\tcachedAt: new Date().toISOString(),\n\t\t};\n\t\tconst filePath = join(this.cacheDir, `${hash}.json`);\n\t\twriteFileSync(filePath, JSON.stringify(entry, null, 2), 'utf8');\n\t}\n}\n","import type { LanguageModel } from \"ai\";\n\nimport type { Provider } from \"../config.js\";\n\nexport function createModel(provider: Provider): LanguageModel {\n switch (provider) {\n case \"azure\":\n return createAzureModel();\n case \"openai\":\n return createOpenAIModel();\n case \"anthropic\":\n return createAnthropicModel();\n default: {\n const _exhaustive: never = provider;\n throw new Error(`Unknown provider: ${_exhaustive}`);\n }\n }\n}\n\nfunction createAzureModel(): LanguageModel {\n const endpoint = requireEnv(\"AZURE_OPENAI_ENDPOINT\");\n const resourceName = endpoint?.match(/https?:\\/\\/([^.]+)/)?.[1];\n const apiKey = requireEnv(\"AZURE_OPENAI_API_KEY\");\n const deployment = requireEnv(\"AZURE_OPENAI_DEPLOYMENT\");\n\n // Dynamic import to avoid loading unused provider SDKs\n const { createAzure } = require(\"@ai-sdk/azure\");\n const azure = createAzure({ resourceName, apiKey });\n return azure(deployment);\n}\n\nfunction createOpenAIModel(): LanguageModel {\n const apiKey = requireEnv(\"OPENAI_API_KEY\");\n const model = process.env.OPENAI_MODEL ?? \"gpt-4o\";\n\n const { createOpenAI } = require(\"@ai-sdk/openai\");\n const openai = createOpenAI({ apiKey });\n return openai(model);\n}\n\nfunction createAnthropicModel(): LanguageModel {\n const apiKey = requireEnv(\"ANTHROPIC_API_KEY\");\n const model = process.env.ANTHROPIC_MODEL ?? \"claude-sonnet-4-6\";\n\n const { createAnthropic } = require(\"@ai-sdk/anthropic\");\n const anthropic = createAnthropic({ apiKey });\n return anthropic(model);\n}\n\nfunction requireEnv(name: string): string {\n const val = process.env[name];\n if (!val) {\n throw new Error(`Required environment variable ${name} is not set.`);\n }\n return val;\n}\n\nexport function getModelId(provider: Provider): string {\n switch (provider) {\n case \"azure\":\n return process.env.AZURE_OPENAI_DEPLOYMENT ?? \"unknown\";\n case \"openai\":\n return process.env.OPENAI_MODEL ?? \"gpt-4o\";\n case \"anthropic\":\n return process.env.ANTHROPIC_MODEL ?? \"claude-sonnet-4-6\";\n }\n}\n","import type { LanguageModel } from \"ai\";\nimport { generateText } from \"ai\";\n\nimport type { JSDocMode, Provider } from \"./config.js\";\nimport type { RouteInfo } from \"./scanner.js\";\n\nimport { computeHash, RouteCache } from \"./cache.js\";\nimport { createModel, getModelId } from \"./providers/index.js\";\n\nexport interface AnalyzeOptions {\n provider: Provider;\n jsdocMode: JSDocMode;\n cache: boolean;\n cacheDir: string;\n}\n\nexport interface AnalyzedRoute {\n urlPath: string;\n pathItem: Record<string, unknown>;\n fromCache: boolean;\n skippedLLM: boolean;\n}\n\nexport async function analyzeRoutes(\n routes: RouteInfo[],\n options: AnalyzeOptions,\n): Promise<AnalyzedRoute[]> {\n const modelId = getModelId(options.provider);\n const cache = options.cache ? new RouteCache(options.cacheDir) : null;\n\n // Lazy-init the model only when we actually need it\n let model: LanguageModel | null = null;\n const getModel = (): LanguageModel => {\n if (!model) model = createModel(options.provider);\n return model;\n };\n\n const results: AnalyzedRoute[] = [];\n\n for (const route of routes) {\n const result = await analyzeRoute(route, options, modelId, cache, getModel);\n results.push(result);\n }\n\n return results;\n}\n\nasync function analyzeRoute(\n route: RouteInfo,\n options: AnalyzeOptions,\n modelId: string,\n cache: RouteCache | null,\n getModel: () => LanguageModel,\n): Promise<AnalyzedRoute> {\n // If @openapi-exact is present or jsdocMode is 'exact', skip LLM\n if (route.hasExactJsdoc && route.exactPathItem) {\n return {\n urlPath: route.urlPath,\n pathItem: route.exactPathItem,\n fromCache: false,\n skippedLLM: true,\n };\n }\n\n if (options.jsdocMode === \"exact\") {\n // In exact mode, if there's a @openapi tag, use it; otherwise still use LLM\n if (route.hasExactJsdoc && route.exactPathItem) {\n return {\n urlPath: route.urlPath,\n pathItem: route.exactPathItem,\n fromCache: false,\n skippedLLM: true,\n };\n }\n }\n\n // Compute cache hash\n const hash = computeHash(route.sourceCode, options.provider, modelId);\n\n // Check cache\n if (cache) {\n const cached = cache.get(hash);\n if (cached) {\n return {\n urlPath: route.urlPath,\n pathItem: cached,\n fromCache: true,\n skippedLLM: true,\n };\n }\n }\n\n // Call LLM\n let pathItem: Record<string, unknown>;\n try {\n pathItem = await callLLM(route, options.jsdocMode, getModel());\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const isContentFilter =\n message.includes(\"content filtering policy\") ||\n message.includes(\"content_filter\") ||\n (err as { status?: number })?.status === 400;\n\n if (isContentFilter) {\n console.warn(\n `Warning: Content filter blocked response for ${route.urlPath}. ` +\n `Skipping route. Use @openapi-exact JSDoc to provide the spec manually.`,\n );\n return {\n urlPath: route.urlPath,\n pathItem: {},\n fromCache: false,\n skippedLLM: false,\n };\n }\n throw err;\n }\n\n // Store in cache\n if (cache) {\n cache.set(hash, pathItem);\n }\n\n return {\n urlPath: route.urlPath,\n pathItem,\n fromCache: false,\n skippedLLM: false,\n };\n}\n\nfunction buildPrompt(route: RouteInfo, jsdocMode: JSDocMode): string {\n const jsDocSection =\n route.jsdocComments.length > 0\n ? `JSDoc COMMENTS (use as ${jsdocMode === \"context\" ? \"additional context\" : \"primary source\"}):\\n${route.jsdocComments.join(\"\\n\\n\")}`\n : \"No JSDoc comments found.\";\n\n return `You are a technical documentation tool that reads existing source code and produces OpenAPI 3.1 documentation data. You do not write or execute code — you only read and describe it.\n\n## Task\n\nRead the Next.js API route source file below and produce a JSON object that documents its HTTP endpoints according to the OpenAPI 3.1 PathItem schema.\n\n## Route metadata\n\n- File: ${route.relativePath}\n- URL path: ${route.urlPath}\n\n## Source file contents\n\n\\`\\`\\`typescript\n${route.sourceCode}\n\\`\\`\\`\n\n${jsDocSection}\n\n## Instructions\n\nFor each exported function named GET, POST, PUT, PATCH, or DELETE, document:\n- operationId: a unique camelCase identifier\n- summary: a short one-line description (max ~4 words, avoid starting with \"Get\", \"Post\", \"Put\", \"Patch\", \"Delete\", these are sometimes inferred from the operationId, and are sometimes in the format of \"Create a ___\", \"Update a ___\", \"Delete a ___\", \"Get a ___\", \"List ___\")\n- description: a fuller explanation of what the endpoint does\n- parameters: path params from URL segments like {id}, and query params from searchParams usage\n- requestBody: schema inferred from request.json() calls and TypeScript types (POST/PUT/PATCH only)\n- responses: per status code, inferred from NextResponse.json() calls and return type annotations\n- tags: inferred from the URL path segments, but typically only one tag should be used. If more than one exists, they show up in multiple categories, and that can be confusing. If there's a question, use the more specific option.\n- security: noted if the code checks for auth tokens, session cookies, or middleware guards\n\n## Output format\n\nReturn a single raw JSON object matching the OpenAPI 3.1 PathItem schema. No explanation, no markdown fences, no extra text — only the JSON object.`;\n}\n\nasync function callLLM(\n route: RouteInfo,\n jsdocMode: JSDocMode,\n model: LanguageModel,\n): Promise<Record<string, unknown>> {\n const prompt = buildPrompt(route, jsdocMode);\n\n const { text } = await generateText({\n model,\n prompt,\n temperature: 0,\n });\n\n return parsePathItem(text, route.urlPath);\n}\n\nfunction parsePathItem(text: string, urlPath: string): Record<string, unknown> {\n // Strip any accidental markdown code fences\n let json = text.trim();\n if (json.startsWith(\"```\")) {\n json = json\n .replace(/^```(?:json)?\\s*/i, \"\")\n .replace(/\\s*```$/, \"\")\n .trim();\n }\n\n try {\n const parsed = JSON.parse(json);\n if (\n typeof parsed !== \"object\" ||\n Array.isArray(parsed) ||\n parsed === null\n ) {\n throw new Error(\"Response is not a JSON object\");\n }\n return parsed;\n } catch (err) {\n console.warn(\n `Warning: Failed to parse LLM response for ${urlPath}. Using empty PathItem.`,\n err,\n );\n return {};\n }\n}\n","import { existsSync } from \"fs\";\nimport { resolve } from \"path\";\nimport { pathToFileURL } from \"url\";\n\nexport type Provider = \"azure\" | \"openai\" | \"anthropic\";\nexport type JSDocMode = \"context\" | \"exact\";\n\nexport interface OpenAPIGenConfig {\n provider: Provider;\n output: {\n specPath: string;\n scalarDocs?: boolean;\n scalarPath?: string;\n };\n openapi: {\n title: string;\n version: string;\n description?: string;\n servers?: Array<{ url: string; description?: string }>;\n security: Array<{ [key: string]: string[] }>;\n components?: {\n securitySchemes?: {\n [key: string]: {\n type: string;\n in: string;\n name: string;\n };\n };\n };\n };\n jsdocMode?: JSDocMode;\n cache?: boolean;\n cacheDir?: string;\n include?: string[];\n exclude?: string[];\n /**\n * Path(s) to .env files to load before running. Defaults to ['.env', '.env.local'].\n * Set to false to disable automatic .env loading.\n */\n envFile?: string | string[] | false;\n}\n\nexport interface ResolvedConfig extends Omit<\n Required<OpenAPIGenConfig>,\n \"envFile\"\n> {\n output: Required<OpenAPIGenConfig[\"output\"]>;\n openapi: Required<OpenAPIGenConfig[\"openapi\"]>;\n envFile: string[] | false;\n}\n\nconst defaults: Omit<ResolvedConfig, \"provider\" | \"output\" | \"openapi\"> = {\n jsdocMode: \"context\",\n cache: true,\n cacheDir: \".openapi-cache\",\n include: [\"src/app/api/**/route.ts\"],\n exclude: [],\n envFile: [\".env\", \".env.local\"],\n};\n\nexport function resolveConfig(config: OpenAPIGenConfig): ResolvedConfig {\n let envFile: string[] | false;\n if (config.envFile === false) {\n envFile = false;\n } else if (typeof config.envFile === \"string\") {\n envFile = [config.envFile];\n } else {\n envFile = config.envFile ?? (defaults.envFile as string[]);\n }\n\n return {\n ...defaults,\n ...config,\n envFile,\n output: {\n scalarDocs: false,\n scalarPath: \"src/app/api/docs/route.ts\",\n ...config.output,\n },\n openapi: {\n description: \"\",\n servers: [],\n components: {},\n ...config.openapi,\n },\n };\n}\n\nexport async function loadConfig(configPath?: string): Promise<ResolvedConfig> {\n const searchPaths = configPath\n ? [configPath]\n : [\n \"openapi-gen.config.ts\",\n \"openapi-gen.config.js\",\n \"openapi-gen.config.mjs\",\n \"openapi-gen.config.cjs\",\n ];\n\n for (const p of searchPaths) {\n const abs = resolve(process.cwd(), p);\n if (existsSync(abs)) {\n const mod = await importConfig(abs);\n const config: OpenAPIGenConfig = mod.default ?? mod;\n return resolveConfig(config);\n }\n }\n\n throw new Error(\n \"No openapi-gen.config.ts found. Create one at your project root.\",\n );\n}\n\nasync function importConfig(\n filePath: string,\n): Promise<{ default?: OpenAPIGenConfig } & OpenAPIGenConfig> {\n // For .ts files, try to use tsx/ts-node if available, else fall back to require\n if (filePath.endsWith(\".ts\")) {\n return importTypeScriptConfig(filePath);\n }\n const url = pathToFileURL(filePath).href;\n return import(url);\n}\n\nasync function importTypeScriptConfig(\n filePath: string,\n): Promise<{ default?: OpenAPIGenConfig } & OpenAPIGenConfig> {\n // Use tsx (bundled as a dependency) to register CJS TypeScript hooks\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n require(\"tsx/cjs\");\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require(filePath);\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'fs';\nimport { dirname, join, resolve } from 'path';\n\nimport type { AnalyzedRoute } from './analyzer.js';\nimport type { ResolvedConfig } from './config.js';\n\nexport interface OpenAPISpec {\n\topenapi: '3.1.0';\n\tinfo: {\n\t\ttitle: string;\n\t\tversion: string;\n\t\tdescription?: string;\n\t};\n\tservers?: Array<{ url: string; description?: string }>;\n\tsecurity?: Array<{ [key: string]: string[] }>;\n\tcomponents?: {\n\t\tsecuritySchemes?: Record<string, unknown>;\n\t\t[key: string]: unknown;\n\t};\n\tpaths: Record<string, unknown>;\n}\n\nexport function assembleSpec(config: ResolvedConfig, routes: AnalyzedRoute[]): OpenAPISpec {\n\tconst paths: Record<string, unknown> = {};\n\n\tfor (const route of routes) {\n\t\tif (Object.keys(route.pathItem).length > 0) {\n\t\t\tpaths[route.urlPath] = route.pathItem;\n\t\t}\n\t}\n\n\tconst spec: OpenAPISpec = {\n\t\topenapi: '3.1.0',\n\t\tinfo: {\n\t\t\ttitle: config.openapi.title,\n\t\t\tversion: config.openapi.version,\n\t\t\t...(config.openapi.description ? { description: config.openapi.description } : {}),\n\t\t},\n\t\tpaths,\n\t};\n\n\tif (config.openapi.servers && config.openapi.servers.length > 0) {\n\t\tspec.servers = config.openapi.servers;\n\t}\n\n\tif (config.openapi.security && config.openapi.security.length > 0) {\n\t\tspec.security = config.openapi.security;\n\t}\n\n\tif (config.openapi.components && Object.keys(config.openapi.components).length > 0) {\n\t\tspec.components = config.openapi.components;\n\t}\n\n\treturn spec;\n}\n\nexport function writeOutputFiles(\n\tconfig: ResolvedConfig,\n\tspec: OpenAPISpec,\n\tcwd: string = process.cwd(),\n): void {\n\twriteSpecFiles(config, spec, cwd);\n\n\tif (config.output.scalarDocs) {\n\t\twriteScalarRoute(config, cwd);\n\t}\n}\n\nfunction writeSpecFiles(config: ResolvedConfig, spec: OpenAPISpec, cwd: string): void {\n\tconst specRoutePath = resolve(cwd, config.output.specPath);\n\tconst specDir = dirname(specRoutePath);\n\n\tensureDir(specDir);\n\n\t// Write spec.json co-located with the route\n\tconst specJsonPath = join(specDir, 'spec.json');\n\twriteFileSync(specJsonPath, JSON.stringify(spec, null, 2), 'utf8');\n\n\t// Write the Next.js route that serves the spec\n\tconst routeContent = `import spec from './spec.json';\n\nexport const dynamic = 'force-static';\n\nexport function GET() {\n return Response.json(spec);\n}\n`;\n\twriteFileSync(specRoutePath, routeContent, 'utf8');\n}\n\nfunction writeScalarRoute(config: ResolvedConfig, cwd: string): void {\n\tconst scalarRoutePath = resolve(cwd, config.output.scalarPath);\n\tensureDir(dirname(scalarRoutePath));\n\n\t// Derive the spec URL from the specPath\n\tconst specUrl = filePathToApiUrl(config.output.specPath);\n\n\tconst routeContent = `export const dynamic = 'force-static';\n\nexport function GET() {\n return new Response(\n \\`<!doctype html>\n<html>\n <head>\n <title>API Docs</title>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <script\n id=\"api-reference\"\n data-url=\"${specUrl}\"\n ></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>\\`,\n { headers: { 'Content-Type': 'text/html' } }\n );\n}\n`;\n\twriteFileSync(scalarRoutePath, routeContent, 'utf8');\n}\n\n/**\n * Convert a file path like src/app/api/openapi.json/route.ts to /api/openapi.json\n */\nfunction filePathToApiUrl(filePath: string): string {\n\tlet path = filePath.replace(/\\\\/g, '/');\n\tpath = path.replace(/^(src\\/)?app\\//, '');\n\tpath = path.replace(/\\/route\\.(ts|tsx|js|jsx)$/, '');\n\tif (!path.startsWith('/')) path = `/${path}`;\n\treturn path;\n}\n\nfunction ensureDir(dir: string): void {\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n}\n","import { readFileSync } from \"fs\";\nimport { relative } from \"path\";\n\nexport interface RouteInfo {\n filePath: string;\n relativePath: string;\n urlPath: string;\n sourceCode: string;\n jsdocComments: string[];\n hasExactJsdoc: boolean;\n exactPathItem?: Record<string, unknown>;\n}\n\nexport async function scanRoutes(\n include: string[],\n exclude: string[],\n cwd: string = process.cwd(),\n): Promise<RouteInfo[]> {\n // Lazy import so that importing this module does not eagerly load fast-glob.\n // This keeps the module lightweight and allows Vitest to mock it cleanly.\n const { default: fg } = await import(\"fast-glob\");\n const files = await fg(include, {\n cwd,\n ignore: exclude,\n absolute: true,\n });\n\n return files.map((filePath) => parseRoute(filePath, cwd));\n}\n\nfunction parseRoute(filePath: string, cwd: string): RouteInfo {\n const relativePath = relative(cwd, filePath);\n const sourceCode = readFileSync(filePath, \"utf8\");\n const urlPath = filePathToUrlPath(relativePath);\n const { jsdocComments, hasExactJsdoc, exactPathItem } =\n extractJsdoc(sourceCode);\n\n return {\n filePath,\n relativePath,\n urlPath,\n sourceCode,\n jsdocComments,\n hasExactJsdoc,\n exactPathItem,\n };\n}\n\n/**\n * Convert a Next.js route file path to an OpenAPI URL path.\n * e.g. src/app/api/users/[id]/route.ts -> /api/users/{id}\n */\nexport function filePathToUrlPath(filePath: string): string {\n // Normalize separators\n let path = filePath.replace(/\\\\/g, \"/\");\n\n // Remove leading src/ or app/ prefixes\n path = path.replace(/^(src\\/)?app\\//, \"\");\n\n // Remove trailing /route.ts or /route.js\n path = path.replace(/\\/route\\.(ts|tsx|js|jsx)$/, \"\");\n\n // Convert Next.js dynamic segments [param] to OpenAPI {param}\n path = path.replace(/\\[([^\\]]+)\\]/g, (_, param) => {\n // Handle catch-all [...param] and optional [[...param]]\n if (param.startsWith(\"...\")) {\n return `{${param.slice(3)}}`;\n }\n return `{${param}}`;\n });\n\n // Ensure leading slash\n if (!path.startsWith(\"/\")) {\n path = `/${path}`;\n }\n\n return path;\n}\n\ninterface JsdocResult {\n jsdocComments: string[];\n hasExactJsdoc: boolean;\n exactPathItem?: Record<string, unknown>;\n}\n\nfunction extractJsdoc(sourceCode: string): JsdocResult {\n // Match all JSDoc comment blocks /** ... */\n const jsdocRegex = /\\/\\*\\*([\\s\\S]*?)\\*\\//g;\n const jsdocComments: string[] = [];\n let hasExactJsdoc = false;\n let exactPathItem: Record<string, unknown> | undefined;\n\n let match: RegExpExecArray | null;\n // biome-ignore lint/suspicious/noAssignInExpressions: required for while loop\n while ((match = jsdocRegex.exec(sourceCode)) !== null) {\n const comment = match[0];\n jsdocComments.push(comment);\n\n // Check for @openapi-exact tag\n if (/@openapi-exact/.test(comment)) {\n hasExactJsdoc = true;\n // Try to extract the JSON from @openapi tag\n const openapiMatch = comment.match(\n /@openapi\\s+([\\s\\S]*?)(?=\\s*\\*\\/|\\s*\\*\\s*@)/,\n );\n if (openapiMatch) {\n try {\n // Clean up JSDoc asterisks from the JSON\n const jsonStr = openapiMatch[1]\n .split(\"\\n\")\n .map((line) => line.replace(/^\\s*\\*\\s?/, \"\"))\n .join(\"\\n\")\n .trim();\n exactPathItem = JSON.parse(jsonStr);\n } catch {\n // If JSON parse fails, fall through to LLM\n hasExactJsdoc = false;\n }\n }\n }\n }\n\n return { jsdocComments, hasExactJsdoc, exactPathItem };\n}\n","export type { JSDocMode, OpenAPIGenConfig, Provider, ResolvedConfig } from './config.js';\n\nexport { analyzeRoutes } from './analyzer.js';\nexport { loadConfig, resolveConfig } from './config.js';\nexport { assembleSpec, writeOutputFiles } from './generator.js';\nexport { filePathToUrlPath, scanRoutes } from './scanner.js';\n\nimport { resolve } from 'node:path';\nimport type { OpenAPIGenConfig } from './config.js';\n\nimport { analyzeRoutes } from './analyzer.js';\nimport { loadConfig } from './config.js';\nimport { assembleSpec, writeOutputFiles } from './generator.js';\nimport { scanRoutes } from './scanner.js';\n\nexport interface GenerateOptions {\n\tconfig?: string;\n\tprovider?: OpenAPIGenConfig['provider'];\n\tcache?: boolean;\n\tcwd?: string;\n}\n\nexport interface GenerateResult {\n\troutesAnalyzed: number;\n\troutesFromCache: number;\n\troutesSkippedLLM: number;\n\tspecPath: string;\n}\n\nexport async function generate(options: GenerateOptions = {}): Promise<GenerateResult> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst config = await loadConfig(options.config);\n\n\t// Allow CLI overrides\n\tif (options.provider) config.provider = options.provider;\n\tif (options.cache === false) config.cache = false;\n\n\t// Load .env files before provider env vars are read\n\tif (config.envFile !== false) {\n\t\tconst { config: dotenvConfig } = await import('dotenv');\n\t\tfor (const file of config.envFile) {\n\t\t\tdotenvConfig({ path: resolve(cwd, file), override: false });\n\t\t}\n\t}\n\n\tconsole.log(`[openapi-ai-generator] Scanning routes...`);\n\tconst routes = await scanRoutes(config.include, config.exclude, cwd);\n\tconsole.log(`[openapi-ai-generator] Found ${routes.length} route(s)`);\n\n\tconsole.log(`[openapi-ai-generator] Analyzing routes with provider: ${config.provider}`);\n\tconst analyzed = await analyzeRoutes(routes, {\n\t\tprovider: config.provider,\n\t\tjsdocMode: config.jsdocMode,\n\t\tcache: config.cache,\n\t\tcacheDir: config.cacheDir,\n\t});\n\n\tconst fromCache = analyzed.filter((r) => r.fromCache).length;\n\tconst skippedLLM = analyzed.filter((r) => r.skippedLLM).length;\n\tconsole.log(\n\t\t`[openapi-ai-generator] ${analyzed.length} routes analyzed (${fromCache} from cache, ${skippedLLM - fromCache} exact JSDoc)`,\n\t);\n\n\tconst spec = assembleSpec(config, analyzed);\n\twriteOutputFiles(config, spec, cwd);\n\n\tconsole.log(`[openapi-ai-generator] Spec written to ${config.output.specPath}`);\n\tif (config.output.scalarDocs) {\n\t\tconsole.log(`[openapi-ai-generator] Scalar docs written to ${config.output.scalarPath}`);\n\t}\n\n\treturn {\n\t\troutesAnalyzed: analyzed.length,\n\t\troutesFromCache: fromCache,\n\t\troutesSkippedLLM: skippedLLM,\n\t\tspecPath: config.output.specPath,\n\t};\n}\n","import type { GenerateOptions } from './index.js';\n\ntype NextConfigLike = {\n\tgenerateBuildId?: unknown;\n};\n\n/**\n * Next.js config plugin that runs openapi-ai-generator before each build.\n * Compatible with both webpack and Turbopack (Next.js 16+).\n *\n * @example\n * // next.config.ts\n * import { withOpenAPIGen } from 'openapi-ai-generator/plugin';\n * export default withOpenAPIGen(nextConfig);\n */\nexport function withOpenAPIGen<T extends NextConfigLike>(\n\tnextConfig: T = {} as T,\n\toptions: GenerateOptions = {},\n): T {\n\tconst existingGenerateBuildId = nextConfig.generateBuildId as\n\t\t| (() => Promise<string | null>)\n\t\t| null\n\t\t| undefined;\n\n\treturn {\n\t\t...nextConfig,\n\t\tasync generateBuildId(): Promise<string | null> {\n\t\t\tconst { generate } = await import('./index.js');\n\t\t\tawait generate(options);\n\t\t\treturn existingGenerateBuildId ? existingGenerateBuildId() : null;\n\t\t},\n\t} as T;\n}\n"]}
1
+ {"version":3,"sources":["../src/cache.ts","../src/providers/index.ts","../src/analyzer.ts","../src/config.ts","../src/generator.ts","../src/scanner.ts","../src/index.ts","../src/plugin.ts"],"names":["createHash","existsSync","mkdirSync","join","readFileSync","writeFileSync","generateText","resolve","url","pathToFileURL","dirname","relative","generate"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAUO,SAAS,WAAA,CAAY,OAAA,EAAiB,QAAA,EAAkB,OAAA,EAAyB;AACvF,EAAA,OAAOA,iBAAA,CAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,MAAA,CAAO,QAAQ,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,OAAO,KAAK,CAAA;AAC1F;AAZA,IAca,UAAA;AAdb,IAAA,UAAA,GAAA,KAAA,CAAA;AAAA,EAAA,cAAA,GAAA;AAcO,IAAM,aAAN,MAAiB;AAAA,MACN,QAAA;AAAA,MAEjB,YAAY,QAAA,EAAkB;AAC7B,QAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAAA,MACjB;AAAA,MAEQ,SAAA,GAAkB;AACzB,QAAA,IAAI,CAACC,aAAA,CAAW,IAAA,CAAK,QAAQ,CAAA,EAAG;AAC/B,UAAAC,YAAA,CAAU,IAAA,CAAK,QAAA,EAAU,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA,QAC7C;AAAA,MACD;AAAA,MAEA,IAAI,IAAA,EAA8C;AACjD,QAAA,MAAM,WAAWC,SAAA,CAAK,IAAA,CAAK,QAAA,EAAU,CAAA,EAAG,IAAI,CAAA,KAAA,CAAO,CAAA;AACnD,QAAA,IAAI,CAACF,aAAA,CAAW,QAAQ,CAAA,EAAG,OAAO,IAAA;AAClC,QAAA,IAAI;AACH,UAAA,MAAM,QAAoB,IAAA,CAAK,KAAA,CAAMG,eAAA,CAAa,QAAA,EAAU,MAAM,CAAC,CAAA;AACnE,UAAA,OAAO,KAAA,CAAM,QAAA;AAAA,QACd,CAAA,CAAA,MAAQ;AACP,UAAA,OAAO,IAAA;AAAA,QACR;AAAA,MACD;AAAA,MAEA,GAAA,CAAI,MAAc,QAAA,EAAyC;AAC1D,QAAA,IAAA,CAAK,SAAA,EAAU;AACf,QAAA,MAAM,KAAA,GAAoB;AAAA,UACzB,IAAA;AAAA,UACA,QAAA;AAAA,UACA,QAAA,EAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,SAClC;AACA,QAAA,MAAM,WAAWD,SAAA,CAAK,IAAA,CAAK,QAAA,EAAU,CAAA,EAAG,IAAI,CAAA,KAAA,CAAO,CAAA;AACnD,QAAAE,gBAAA,CAAc,UAAU,IAAA,CAAK,SAAA,CAAU,OAAO,IAAA,EAAM,CAAC,GAAG,MAAM,CAAA;AAAA,MAC/D;AAAA,KACD;AAAA,EAAA;AAAA,CAAA,CAAA;;;AC5CO,SAAS,YAAY,QAAA,EAAmC;AAC7D,EAAA,QAAQ,QAAA;AAAU,IAChB,KAAK,OAAA;AACH,MAAA,OAAO,gBAAA,EAAiB;AAAA,IAC1B,KAAK,QAAA;AACH,MAAA,OAAO,iBAAA,EAAkB;AAAA,IAC3B,KAAK,WAAA;AACH,MAAA,OAAO,oBAAA,EAAqB;AAAA,IAC9B,SAAS;AACP,MAAA,MAAM,WAAA,GAAqB,QAAA;AAC3B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,WAAW,CAAA,CAAE,CAAA;AAAA,IACpD;AAAA;AAEJ;AAEA,SAAS,gBAAA,GAAkC;AACzC,EAAA,MAAM,QAAA,GAAW,WAAW,uBAAuB,CAAA;AACnD,EAAA,MAAM,YAAA,GAAe,QAAA,EAAU,KAAA,CAAM,oBAAoB,IAAI,CAAC,CAAA;AAC9D,EAAA,MAAM,MAAA,GAAS,WAAW,sBAAsB,CAAA;AAChD,EAAA,MAAM,UAAA,GAAa,WAAW,yBAAyB,CAAA;AAGvD,EAAA,MAAM,EAAE,WAAA,EAAY,GAAI,SAAA,CAAQ,eAAe,CAAA;AAC/C,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,EAAE,YAAA,EAAc,QAAQ,CAAA;AAClD,EAAA,OAAO,MAAM,UAAU,CAAA;AACzB;AAEA,SAAS,iBAAA,GAAmC;AAC1C,EAAA,MAAM,MAAA,GAAS,WAAW,gBAAgB,CAAA;AAC1C,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,YAAA,IAAgB,QAAA;AAE1C,EAAA,MAAM,EAAE,YAAA,EAAa,GAAI,SAAA,CAAQ,gBAAgB,CAAA;AACjD,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,EAAE,MAAA,EAAQ,CAAA;AACtC,EAAA,OAAO,OAAO,KAAK,CAAA;AACrB;AAEA,SAAS,oBAAA,GAAsC;AAC7C,EAAA,MAAM,MAAA,GAAS,WAAW,mBAAmB,CAAA;AAC7C,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,eAAA,IAAmB,mBAAA;AAE7C,EAAA,MAAM,EAAE,eAAA,EAAgB,GAAI,SAAA,CAAQ,mBAAmB,CAAA;AACvD,EAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,EAAE,MAAA,EAAQ,CAAA;AAC5C,EAAA,OAAO,UAAU,KAAK,CAAA;AACxB;AAEA,SAAS,WAAW,IAAA,EAAsB;AACxC,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA;AAC5B,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,IAAI,CAAA,YAAA,CAAc,CAAA;AAAA,EACrE;AACA,EAAA,OAAO,GAAA;AACT;AAEO,SAAS,WAAW,QAAA,EAA4B;AACrD,EAAA,QAAQ,QAAA;AAAU,IAChB,KAAK,OAAA;AACH,MAAA,OAAO,OAAA,CAAQ,IAAI,uBAAA,IAA2B,SAAA;AAAA,IAChD,KAAK,QAAA;AACH,MAAA,OAAO,OAAA,CAAQ,IAAI,YAAA,IAAgB,QAAA;AAAA,IACrC,KAAK,WAAA;AACH,MAAA,OAAO,OAAA,CAAQ,IAAI,eAAA,IAAmB,mBAAA;AAAA;AAE5C;AAlEA,IAAA,cAAA,GAAA,KAAA,CAAA;AAAA,EAAA,wBAAA,GAAA;AAAA,EAAA;AAAA,CAAA,CAAA;ACwBA,eAAsB,aAAA,CACpB,QACA,OAAA,EAC0B;AAC1B,EAAA,MAAM,OAAA,GAAU,UAAA,CAAW,OAAA,CAAQ,QAAQ,CAAA;AAC3C,EAAA,MAAM,QAAQ,OAAA,CAAQ,KAAA,GAAQ,IAAI,UAAA,CAAW,OAAA,CAAQ,QAAQ,CAAA,GAAI,IAAA;AAGjE,EAAA,IAAI,KAAA,GAA8B,IAAA;AAClC,EAAA,MAAM,WAAW,MAAqB;AACpC,IAAA,IAAI,CAAC,KAAA,EAAO,KAAA,GAAQ,WAAA,CAAY,QAAQ,QAAQ,CAAA;AAChD,IAAA,OAAO,KAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,UAA2B,EAAC;AAElC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,SAAS,MAAM,YAAA,CAAa,OAAO,OAAA,EAAS,OAAA,EAAS,OAAO,QAAQ,CAAA;AAC1E,IAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AAAA,EACrB;AAEA,EAAA,OAAO,OAAA;AACT;AAEA,eAAe,YAAA,CACb,KAAA,EACA,OAAA,EACA,OAAA,EACA,OACA,QAAA,EACwB;AAExB,EAAA,IAAI,KAAA,CAAM,aAAA,IAAiB,KAAA,CAAM,aAAA,EAAe;AAC9C,IAAA,OAAO;AAAA,MACL,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,UAAU,KAAA,CAAM,aAAA;AAAA,MAChB,SAAA,EAAW,KAAA;AAAA,MACX,UAAA,EAAY;AAAA,KACd;AAAA,EACF;AAEA,EAAA,IAAI,OAAA,CAAQ,cAAc,OAAA,EAAS;AAEjC,IAAA,IAAI,KAAA,CAAM,aAAA,IAAiB,KAAA,CAAM,aAAA,EAAe;AAC9C,MAAA,OAAO;AAAA,QACL,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,UAAU,KAAA,CAAM,aAAA;AAAA,QAChB,SAAA,EAAW,KAAA;AAAA,QACX,UAAA,EAAY;AAAA,OACd;AAAA,IACF;AAAA,EACF;AAGA,EAAA,MAAM,OAAO,WAAA,CAAY,KAAA,CAAM,UAAA,EAAY,OAAA,CAAQ,UAAU,OAAO,CAAA;AAGpE,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA;AAC7B,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,OAAO;AAAA,QACL,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,QAAA,EAAU,MAAA;AAAA,QACV,SAAA,EAAW,IAAA;AAAA,QACX,UAAA,EAAY;AAAA,OACd;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI;AACF,IAAA,QAAA,GAAW,MAAM,OAAA;AAAA,MACf,KAAA;AAAA,MACA,OAAA,CAAQ,SAAA;AAAA,MACR,QAAA,EAAS;AAAA,MACT,OAAA,CAAQ;AAAA,KACV;AAAA,EACF,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,IAAA,MAAM,eAAA,GACJ,OAAA,CAAQ,QAAA,CAAS,0BAA0B,CAAA,IAC3C,QAAQ,QAAA,CAAS,gBAAgB,CAAA,IAChC,GAAA,EAA6B,MAAA,KAAW,GAAA;AAE3C,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN,CAAA,6CAAA,EAAgD,MAAM,OAAO,CAAA,wEAAA;AAAA,OAE/D;AACA,MAAA,OAAO;AAAA,QACL,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,UAAU,EAAC;AAAA,QACX,SAAA,EAAW,KAAA;AAAA,QACX,UAAA,EAAY;AAAA,OACd;AAAA,IACF;AACA,IAAA,MAAM,GAAA;AAAA,EACR;AAGA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,KAAA,CAAM,GAAA,CAAI,MAAM,QAAQ,CAAA;AAAA,EAC1B;AAEA,EAAA,OAAO;AAAA,IACL,SAAS,KAAA,CAAM,OAAA;AAAA,IACf,QAAA;AAAA,IACA,SAAA,EAAW,KAAA;AAAA,IACX,UAAA,EAAY;AAAA,GACd;AACF;AAEA,SAAS,WAAA,CAAY,OAAkB,SAAA,EAA8B;AACnE,EAAA,MAAM,YAAA,GACJ,MAAM,aAAA,CAAc,MAAA,GAAS,IACzB,CAAA,uBAAA,EAA0B,SAAA,KAAc,SAAA,GAAY,oBAAA,GAAuB,gBAAgB,CAAA;AAAA,EAAO,KAAA,CAAM,aAAA,CAAc,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA,GAClI,0BAAA;AAEN,EAAA,OAAO,CAAA;;AAAA;;AAAA;;AAAA;;AAAA,QAAA,EAQC,MAAM,YAAY;AAAA,YAAA,EACd,MAAM,OAAO;;AAAA;;AAAA;AAAA,EAKzB,MAAM,UAAU;AAAA;;AAAA,EAGhB,YAAY;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA,wJAAA,CAAA;AAiBd;AAEA,eAAe,OAAA,CACb,KAAA,EACA,SAAA,EACA,KAAA,EACA,MAAA,EACkC;AAClC,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,KAAA,EAAO,SAAS,CAAA;AAE3C,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAMC,eAAA,CAAa;AAAA,IAClC,KAAA;AAAA,IACA,MAAA;AAAA,IACA,WAAA,EAAa,CAAA;AAAA,IACb,iBAAiB,MAAA,CAAO,SAAA;AAAA,IACxB,WAAA,EAAa,WAAA,CAAY,OAAA,CAAQ,MAAA,CAAO,SAAS;AAAA,GAClD,CAAA;AAED,EAAA,OAAO,aAAA,CAAc,IAAA,EAAM,KAAA,CAAM,OAAO,CAAA;AAC1C;AAEA,SAAS,aAAA,CAAc,MAAc,OAAA,EAA0C;AAE7E,EAAA,IAAI,IAAA,GAAO,KAAK,IAAA,EAAK;AACrB,EAAA,IAAI,IAAA,CAAK,UAAA,CAAW,KAAK,CAAA,EAAG;AAC1B,IAAA,IAAA,GAAO,IAAA,CACJ,QAAQ,mBAAA,EAAqB,EAAE,EAC/B,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA,CACrB,IAAA,EAAK;AAAA,EACV;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC9B,IAAA,IACE,OAAO,WAAW,QAAA,IAClB,KAAA,CAAM,QAAQ,MAAM,CAAA,IACpB,WAAW,IAAA,EACX;AACA,MAAA,MAAM,IAAI,MAAM,+BAA+B,CAAA;AAAA,IACjD;AACA,IAAA,OAAO,MAAA;AAAA,EACT,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,6CAA6C,OAAO,CAAA,uBAAA,CAAA;AAAA,MACpD;AAAA,KACF;AACA,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAjOA,IAAA,aAAA,GAAA,KAAA,CAAA;AAAA,EAAA,iBAAA,GAAA;AAMA,IAAA,UAAA,EAAA;AACA,IAAA,cAAA,EAAA;AAAA,EAAA;AAAA,CAAA,CAAA;AC6EO,SAAS,cAAc,MAAA,EAA0C;AACtE,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,MAAA,CAAO,YAAY,KAAA,EAAO;AAC5B,IAAA,OAAA,GAAU,KAAA;AAAA,EACZ,CAAA,MAAA,IAAW,OAAO,MAAA,CAAO,OAAA,KAAY,QAAA,EAAU;AAC7C,IAAA,OAAA,GAAU,CAAC,OAAO,OAAO,CAAA;AAAA,EAC3B,CAAA,MAAO;AACL,IAAA,OAAA,GAAU,MAAA,CAAO,WAAY,QAAA,CAAS,OAAA;AAAA,EACxC;AAEA,EAAA,OAAO;AAAA,IACL,GAAG,QAAA;AAAA,IACH,GAAG,MAAA;AAAA,IACH,OAAA;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,GAAG,QAAA,CAAS,MAAA;AAAA,MACZ,GAAG,MAAA,CAAO;AAAA,KACZ;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,UAAA,EAAY,KAAA;AAAA,MACZ,UAAA,EAAY,2BAAA;AAAA,MACZ,cAAc,EAAC;AAAA,MACf,GAAG,MAAA,CAAO;AAAA,KACZ;AAAA,IACA,OAAA,EAAS;AAAA,MACP,WAAA,EAAa,EAAA;AAAA,MACb,SAAS,EAAC;AAAA,MACV,YAAY,EAAC;AAAA,MACb,GAAG,MAAA,CAAO;AAAA;AACZ,GACF;AACF;AAEA,eAAsB,WAAW,UAAA,EAA8C;AAC7E,EAAA,MAAM,WAAA,GAAc,UAAA,GAChB,CAAC,UAAU,CAAA,GACX;AAAA,IACE,uBAAA;AAAA,IACA,uBAAA;AAAA,IACA,wBAAA;AAAA,IACA;AAAA,GACF;AAEJ,EAAA,KAAA,MAAW,KAAK,WAAA,EAAa;AAC3B,IAAA,MAAM,GAAA,GAAMC,YAAA,CAAQ,OAAA,CAAQ,GAAA,IAAO,CAAC,CAAA;AACpC,IAAA,IAAIN,aAAAA,CAAW,GAAG,CAAA,EAAG;AACnB,MAAA,MAAM,GAAA,GAAM,MAAM,YAAA,CAAa,GAAG,CAAA;AAClC,MAAA,MAAM,MAAA,GAA2B,IAAI,OAAA,IAAW,GAAA;AAChD,MAAA,OAAO,cAAc,MAAM,CAAA;AAAA,IAC7B;AAAA,EACF;AAEA,EAAA,MAAM,IAAI,KAAA;AAAA,IACR;AAAA,GACF;AACF;AAEA,eAAe,aACb,QAAA,EAC4D;AAE5D,EAAA,IAAI,QAAA,CAAS,QAAA,CAAS,KAAK,CAAA,EAAG;AAC5B,IAAA,OAAO,uBAAuB,QAAQ,CAAA;AAAA,EACxC;AACA,EAAA,MAAMO,KAAA,GAAMC,iBAAA,CAAc,QAAQ,CAAA,CAAE,IAAA;AACpC,EAAA,OAAO,OAAOD,KAAA,CAAA;AAChB;AAEA,eAAe,uBACb,QAAA,EAC4D;AAG5D,EAAA,SAAA,CAAQ,SAAS,CAAA;AAEjB,EAAA,OAAO,UAAQ,QAAQ,CAAA;AACzB;AAhKA,IAuEM,QAAA;AAvEN,IAAA,WAAA,GAAA,KAAA,CAAA;AAAA,EAAA,eAAA,GAAA;AAuEA,IAAM,QAAA,GAAoE;AAAA,MACxE,SAAA,EAAW,SAAA;AAAA,MACX,KAAA,EAAO,IAAA;AAAA,MACP,QAAA,EAAU,gBAAA;AAAA,MACV,OAAA,EAAS,CAAC,yBAAyB,CAAA;AAAA,MACnC,SAAS,EAAC;AAAA,MACV,OAAA,EAAS,CAAC,MAAA,EAAQ,YAAY,CAAA;AAAA,MAC9B,MAAA,EAAQ;AAAA,QACN,SAAA,EAAW,GAAA;AAAA,QACX,SAAA,EAAW;AAAA;AACb,KACF;AAAA,EAAA;AAAA,CAAA,CAAA;AC5DO,SAAS,YAAA,CACd,QACA,MAAA,EACa;AACb,EAAA,MAAM,QAAiC,EAAC;AAExC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,IAAI,OAAO,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA,CAAE,SAAS,CAAA,EAAG;AAC1C,MAAA,KAAA,CAAM,KAAA,CAAM,OAAO,CAAA,GAAI,KAAA,CAAM,QAAA;AAAA,IAC/B;AAAA,EACF;AAEA,EAAA,MAAM,IAAA,GAAoB;AAAA,IACxB,OAAA,EAAS,OAAA;AAAA,IACT,IAAA,EAAM;AAAA,MACJ,KAAA,EAAO,OAAO,OAAA,CAAQ,KAAA;AAAA,MACtB,OAAA,EAAS,OAAO,OAAA,CAAQ,OAAA;AAAA,MACxB,GAAI,MAAA,CAAO,OAAA,CAAQ,WAAA,GACf,EAAE,aAAa,MAAA,CAAO,OAAA,CAAQ,WAAA,EAAY,GAC1C;AAAC,KACP;AAAA,IACA;AAAA,GACF;AAEA,EAAA,IAAI,OAAO,OAAA,CAAQ,OAAA,IAAW,OAAO,OAAA,CAAQ,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC/D,IAAA,IAAA,CAAK,OAAA,GAAU,OAAO,OAAA,CAAQ,OAAA;AAAA,EAChC;AAEA,EAAA,IAAI,OAAO,OAAA,CAAQ,QAAA,IAAY,OAAO,OAAA,CAAQ,QAAA,CAAS,SAAS,CAAA,EAAG;AACjE,IAAA,IAAA,CAAK,QAAA,GAAW,OAAO,OAAA,CAAQ,QAAA;AAAA,EACjC;AAEA,EAAA,IACE,MAAA,CAAO,OAAA,CAAQ,UAAA,IACf,MAAA,CAAO,IAAA,CAAK,OAAO,OAAA,CAAQ,UAAU,CAAA,CAAE,MAAA,GAAS,CAAA,EAChD;AACA,IAAA,IAAA,CAAK,UAAA,GAAa,OAAO,OAAA,CAAQ,UAAA;AAAA,EACnC;AAEA,EAAA,OAAO,IAAA;AACT;AAEO,SAAS,iBACd,MAAA,EACA,IAAA,EACA,GAAA,GAAc,OAAA,CAAQ,KAAI,EACpB;AACN,EAAA,cAAA,CAAe,MAAA,EAAQ,MAAM,GAAG,CAAA;AAEhC,EAAA,IAAI,MAAA,CAAO,OAAO,UAAA,EAAY;AAC5B,IAAA,gBAAA,CAAiB,QAAQ,GAAG,CAAA;AAAA,EAC9B;AACF;AAEA,SAAS,cAAA,CACP,MAAA,EACA,IAAA,EACA,GAAA,EACM;AACN,EAAA,MAAM,aAAA,GAAgBD,YAAAA,CAAQ,GAAA,EAAK,MAAA,CAAO,OAAO,QAAQ,CAAA;AACzD,EAAA,MAAM,OAAA,GAAUG,aAAQ,aAAa,CAAA;AAErC,EAAA,SAAA,CAAU,OAAO,CAAA;AAGjB,EAAA,MAAM,YAAA,GAAeP,SAAAA,CAAK,OAAA,EAAS,WAAW,CAAA;AAC9C,EAAAE,gBAAAA,CAAc,cAAc,IAAA,CAAK,SAAA,CAAU,MAAM,IAAA,EAAM,CAAC,GAAG,MAAM,CAAA;AAGjE,EAAA,MAAM,YAAA,GAAe,CAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAQrB,EAAAA,gBAAAA,CAAc,aAAA,EAAe,YAAA,EAAc,MAAM,CAAA;AACnD;AAEA,SAAS,gBAAA,CAAiB,QAAwB,GAAA,EAAmB;AACnE,EAAA,MAAM,eAAA,GAAkBE,YAAAA,CAAQ,GAAA,EAAK,MAAA,CAAO,OAAO,UAAU,CAAA;AAC7D,EAAA,SAAA,CAAUG,YAAA,CAAQ,eAAe,CAAC,CAAA;AAGlC,EAAA,MAAM,OAAA,GAAU,gBAAA,CAAiB,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAA;AAEvD,EAAA,MAAM,YAAA,GAAe,CAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAAA,EAcL,OAAO,CAAA;AAAA,MAAA,EACjB,OAAO,MAAA,CAAO,YAAA,IAAgB,OAAO,IAAA,CAAK,MAAA,CAAO,OAAO,YAAY,CAAA,CAAE,SAAS,CAAA,GAAI,CAAA,aAAA,EAAgB,KAAK,SAAA,CAAU,MAAA,CAAO,OAAO,YAAY,CAAC,MAAM,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAS3J,EAAAL,gBAAAA,CAAc,eAAA,EAAiB,YAAA,EAAc,MAAM,CAAA;AACrD;AAKA,SAAS,iBAAiB,QAAA,EAA0B;AAClD,EAAA,IAAI,IAAA,GAAO,QAAA,CAAS,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AACtC,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,gBAAA,EAAkB,EAAE,CAAA;AACxC,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,2BAAA,EAA6B,EAAE,CAAA;AACnD,EAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG,IAAA,GAAO,IAAI,IAAI,CAAA,CAAA;AAC1C,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,UAAU,GAAA,EAAmB;AACpC,EAAA,IAAI,CAACJ,aAAAA,CAAW,GAAG,CAAA,EAAG;AACpB,IAAAC,YAAAA,CAAU,GAAA,EAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA,EACpC;AACF;AAvJA,IAAA,cAAA,GAAA,KAAA,CAAA;AAAA,EAAA,kBAAA,GAAA;AAAA,EAAA;AAAA,CAAA,CAAA;ACaA,eAAsB,WACpB,OAAA,EACA,OAAA,EACA,GAAA,GAAc,OAAA,CAAQ,KAAI,EACJ;AAGtB,EAAA,MAAM,EAAE,OAAA,EAAS,EAAA,EAAG,GAAI,MAAM,OAAO,WAAW,CAAA;AAChD,EAAA,MAAM,KAAA,GAAQ,MAAM,EAAA,CAAG,OAAA,EAAS;AAAA,IAC9B,GAAA;AAAA,IACA,MAAA,EAAQ,OAAA;AAAA,IACR,QAAA,EAAU;AAAA,GACX,CAAA;AAED,EAAA,OAAO,MAAM,GAAA,CAAI,CAAC,aAAa,UAAA,CAAW,QAAA,EAAU,GAAG,CAAC,CAAA;AAC1D;AAEA,SAAS,UAAA,CAAW,UAAkB,GAAA,EAAwB;AAC5D,EAAA,MAAM,YAAA,GAAeS,aAAA,CAAS,GAAA,EAAK,QAAQ,CAAA;AAC3C,EAAA,MAAM,UAAA,GAAaP,eAAAA,CAAa,QAAA,EAAU,MAAM,CAAA;AAChD,EAAA,MAAM,OAAA,GAAU,kBAAkB,YAAY,CAAA;AAC9C,EAAA,MAAM,EAAE,aAAA,EAAe,aAAA,EAAe,aAAA,EAAc,GAClD,aAAa,UAAU,CAAA;AAEzB,EAAA,OAAO;AAAA,IACL,QAAA;AAAA,IACA,YAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,aAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACF;AACF;AAMO,SAAS,kBAAkB,QAAA,EAA0B;AAE1D,EAAA,IAAI,IAAA,GAAO,QAAA,CAAS,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AAGtC,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,gBAAA,EAAkB,EAAE,CAAA;AAGxC,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,2BAAA,EAA6B,EAAE,CAAA;AAGnD,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,eAAA,EAAiB,CAAC,GAAG,KAAA,KAAU;AAEjD,IAAA,IAAI,KAAA,CAAM,UAAA,CAAW,KAAK,CAAA,EAAG;AAC3B,MAAA,OAAO,CAAA,CAAA,EAAI,KAAA,CAAM,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA,CAAA;AAAA,IAC3B;AACA,IAAA,OAAO,IAAI,KAAK,CAAA,CAAA,CAAA;AAAA,EAClB,CAAC,CAAA;AAGD,EAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG;AACzB,IAAA,IAAA,GAAO,IAAI,IAAI,CAAA,CAAA;AAAA,EACjB;AAEA,EAAA,OAAO,IAAA;AACT;AAQA,SAAS,aAAa,UAAA,EAAiC;AAErD,EAAA,MAAM,UAAA,GAAa,uBAAA;AACnB,EAAA,MAAM,gBAA0B,EAAC;AACjC,EAAA,IAAI,aAAA,GAAgB,KAAA;AACpB,EAAA,IAAI,aAAA;AAEJ,EAAA,IAAI,KAAA;AAEJ,EAAA,OAAA,CAAQ,KAAA,GAAQ,UAAA,CAAW,IAAA,CAAK,UAAU,OAAO,IAAA,EAAM;AACrD,IAAA,MAAM,OAAA,GAAU,MAAM,CAAC,CAAA;AACvB,IAAA,aAAA,CAAc,KAAK,OAAO,CAAA;AAG1B,IAAA,IAAI,gBAAA,CAAiB,IAAA,CAAK,OAAO,CAAA,EAAG;AAClC,MAAA,aAAA,GAAgB,IAAA;AAEhB,MAAA,MAAM,eAAe,OAAA,CAAQ,KAAA;AAAA,QAC3B;AAAA,OACF;AACA,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,IAAI;AAEF,UAAA,MAAM,UAAU,YAAA,CAAa,CAAC,EAC3B,KAAA,CAAM,IAAI,EACV,GAAA,CAAI,CAAC,SAAS,IAAA,CAAK,OAAA,CAAQ,aAAa,EAAE,CAAC,EAC3C,IAAA,CAAK,IAAI,EACT,IAAA,EAAK;AACR,UAAA,aAAA,GAAgB,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,QACpC,CAAA,CAAA,MAAQ;AAEN,UAAA,aAAA,GAAgB,KAAA;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,aAAA,EAAe,aAAA,EAAe,aAAA,EAAc;AACvD;AA3HA,IAAA,YAAA,GAAA,KAAA,CAAA;AAAA,EAAA,gBAAA,GAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACAA,IAAA,WAAA,GAAA,EAAA;AAAA,QAAA,CAAA,WAAA,EAAA;AAAA,EAAA,aAAA,EAAA,MAAA,aAAA;AAAA,EAAA,YAAA,EAAA,MAAA,YAAA;AAAA,EAAA,iBAAA,EAAA,MAAA,iBAAA;AAAA,EAAA,QAAA,EAAA,MAAA,QAAA;AAAA,EAAA,UAAA,EAAA,MAAA,UAAA;AAAA,EAAA,aAAA,EAAA,MAAA,aAAA;AAAA,EAAA,UAAA,EAAA,MAAA,UAAA;AAAA,EAAA,gBAAA,EAAA,MAAA;AAAA,CAAA,CAAA;AAoCA,eAAsB,QAAA,CACpB,OAAA,GAA2B,EAAC,EACH;AACzB,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AACvC,EAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,OAAA,CAAQ,MAAM,CAAA;AAG9C,EAAA,IAAI,OAAA,CAAQ,QAAA,EAAU,MAAA,CAAO,QAAA,GAAW,OAAA,CAAQ,QAAA;AAChD,EAAA,IAAI,OAAA,CAAQ,KAAA,KAAU,KAAA,EAAO,MAAA,CAAO,KAAA,GAAQ,KAAA;AAG5C,EAAA,IAAI,MAAA,CAAO,YAAY,KAAA,EAAO;AAC5B,IAAA,MAAM,EAAE,MAAA,EAAQ,YAAA,EAAa,GAAI,MAAM,OAAO,QAAQ,CAAA;AACtD,IAAA,KAAA,MAAW,IAAA,IAAQ,OAAO,OAAA,EAAS;AACjC,MAAA,YAAA,CAAa,EAAE,MAAMG,YAAAA,CAAQ,GAAA,EAAK,IAAI,CAAA,EAAG,QAAA,EAAU,OAAO,CAAA;AAAA,IAC5D;AAAA,EACF;AAEA,EAAA,OAAA,CAAQ,IAAI,CAAA,yCAAA,CAA2C,CAAA;AACvD,EAAA,MAAM,SAAS,MAAM,UAAA,CAAW,OAAO,OAAA,EAAS,MAAA,CAAO,SAAS,GAAG,CAAA;AACnE,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,6BAAA,EAAgC,MAAA,CAAO,MAAM,CAAA,SAAA,CAAW,CAAA;AAEpE,EAAA,OAAA,CAAQ,GAAA;AAAA,IACN,CAAA,uDAAA,EAA0D,OAAO,QAAQ,CAAA;AAAA,GAC3E;AACA,EAAA,MAAM,QAAA,GAAW,MAAM,aAAA,CAAc,MAAA,EAAQ;AAAA,IAC3C,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,WAAW,MAAA,CAAO,SAAA;AAAA,IAClB,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,QAAQ,MAAA,CAAO;AAAA,GAChB,CAAA;AAED,EAAA,MAAM,YAAY,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAA,CAAE,MAAA;AACtD,EAAA,MAAM,aAAa,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,UAAU,CAAA,CAAE,MAAA;AACxD,EAAA,OAAA,CAAQ,GAAA;AAAA,IACN,0BAA0B,QAAA,CAAS,MAAM,qBAAqB,SAAS,CAAA,aAAA,EAAgB,aAAa,SAAS,CAAA,aAAA;AAAA,GAC/G;AAEA,EAAA,MAAM,IAAA,GAAO,YAAA,CAAa,MAAA,EAAQ,QAAQ,CAAA;AAC1C,EAAA,gBAAA,CAAiB,MAAA,EAAQ,MAAM,GAAG,CAAA;AAElC,EAAA,OAAA,CAAQ,GAAA;AAAA,IACN,CAAA,uCAAA,EAA0C,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAA;AAAA,GAClE;AACA,EAAA,IAAI,MAAA,CAAO,OAAO,UAAA,EAAY;AAC5B,IAAA,OAAA,CAAQ,GAAA;AAAA,MACN,CAAA,8CAAA,EAAiD,MAAA,CAAO,MAAA,CAAO,UAAU,CAAA;AAAA,KAC3E;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,gBAAgB,QAAA,CAAS,MAAA;AAAA,IACzB,eAAA,EAAiB,SAAA;AAAA,IACjB,gBAAA,EAAkB,UAAA;AAAA,IAClB,QAAA,EAAU,OAAO,MAAA,CAAO;AAAA,GAC1B;AACF;AA7FA,IAAA,QAAA,GAAA,KAAA,CAAA;AAAA,EAAA,cAAA,GAAA;AAQA,IAAA,aAAA,EAAA;AACA,IAAA,WAAA,EAAA;AACA,IAAA,cAAA,EAAA;AACA,IAAA,YAAA,EAAA;AAMA,IAAA,aAAA,EAAA;AACA,IAAA,WAAA,EAAA;AACA,IAAA,cAAA,EAAA;AACA,IAAA,YAAA,EAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACLO,SAAS,eACd,UAAA,GAAgB,EAAC,EACjB,OAAA,GAA2B,EAAC,EACzB;AACH,EAAA,MAAM,0BAA0B,UAAA,CAAW,eAAA;AAK3C,EAAA,OAAO;AAAA,IACL,GAAG,UAAA;AAAA,IACH,MAAM,eAAA,GAA0C;AAC9C,MAAA,MAAM,EAAE,QAAA,EAAAK,SAAAA,EAAS,GAAI,MAAM,OAAA,CAAA,OAAA,EAAA,CAAA,IAAA,CAAA,OAAA,QAAA,EAAA,EAAA,WAAA,CAAA,CAAA;AAC3B,MAAA,MAAMA,UAAS,OAAO,CAAA;AACtB,MAAA,OAAO,uBAAA,GAA0B,yBAAwB,GAAI,IAAA;AAAA,IAC/D;AAAA,GACF;AACF","file":"plugin.js","sourcesContent":["import { createHash } from 'crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\n\nexport interface CacheEntry {\n\thash: string;\n\tpathItem: Record<string, unknown>;\n\tcachedAt: string;\n}\n\nexport function computeHash(content: string, provider: string, modelId: string): string {\n\treturn createHash('sha256').update(content).update(provider).update(modelId).digest('hex');\n}\n\nexport class RouteCache {\n\tprivate readonly cacheDir: string;\n\n\tconstructor(cacheDir: string) {\n\t\tthis.cacheDir = cacheDir;\n\t}\n\n\tprivate ensureDir(): void {\n\t\tif (!existsSync(this.cacheDir)) {\n\t\t\tmkdirSync(this.cacheDir, { recursive: true });\n\t\t}\n\t}\n\n\tget(hash: string): Record<string, unknown> | null {\n\t\tconst filePath = join(this.cacheDir, `${hash}.json`);\n\t\tif (!existsSync(filePath)) return null;\n\t\ttry {\n\t\t\tconst entry: CacheEntry = JSON.parse(readFileSync(filePath, 'utf8'));\n\t\t\treturn entry.pathItem;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tset(hash: string, pathItem: Record<string, unknown>): void {\n\t\tthis.ensureDir();\n\t\tconst entry: CacheEntry = {\n\t\t\thash,\n\t\t\tpathItem,\n\t\t\tcachedAt: new Date().toISOString(),\n\t\t};\n\t\tconst filePath = join(this.cacheDir, `${hash}.json`);\n\t\twriteFileSync(filePath, JSON.stringify(entry, null, 2), 'utf8');\n\t}\n}\n","import type { LanguageModel } from \"ai\";\n\nimport type { Provider } from \"../config.js\";\n\nexport function createModel(provider: Provider): LanguageModel {\n switch (provider) {\n case \"azure\":\n return createAzureModel();\n case \"openai\":\n return createOpenAIModel();\n case \"anthropic\":\n return createAnthropicModel();\n default: {\n const _exhaustive: never = provider;\n throw new Error(`Unknown provider: ${_exhaustive}`);\n }\n }\n}\n\nfunction createAzureModel(): LanguageModel {\n const endpoint = requireEnv(\"AZURE_OPENAI_ENDPOINT\");\n const resourceName = endpoint?.match(/https?:\\/\\/([^.]+)/)?.[1];\n const apiKey = requireEnv(\"AZURE_OPENAI_API_KEY\");\n const deployment = requireEnv(\"AZURE_OPENAI_DEPLOYMENT\");\n\n // Dynamic import to avoid loading unused provider SDKs\n const { createAzure } = require(\"@ai-sdk/azure\");\n const azure = createAzure({ resourceName, apiKey });\n return azure(deployment);\n}\n\nfunction createOpenAIModel(): LanguageModel {\n const apiKey = requireEnv(\"OPENAI_API_KEY\");\n const model = process.env.OPENAI_MODEL ?? \"gpt-4o\";\n\n const { createOpenAI } = require(\"@ai-sdk/openai\");\n const openai = createOpenAI({ apiKey });\n return openai(model);\n}\n\nfunction createAnthropicModel(): LanguageModel {\n const apiKey = requireEnv(\"ANTHROPIC_API_KEY\");\n const model = process.env.ANTHROPIC_MODEL ?? \"claude-sonnet-4-6\";\n\n const { createAnthropic } = require(\"@ai-sdk/anthropic\");\n const anthropic = createAnthropic({ apiKey });\n return anthropic(model);\n}\n\nfunction requireEnv(name: string): string {\n const val = process.env[name];\n if (!val) {\n throw new Error(`Required environment variable ${name} is not set.`);\n }\n return val;\n}\n\nexport function getModelId(provider: Provider): string {\n switch (provider) {\n case \"azure\":\n return process.env.AZURE_OPENAI_DEPLOYMENT ?? \"unknown\";\n case \"openai\":\n return process.env.OPENAI_MODEL ?? \"gpt-4o\";\n case \"anthropic\":\n return process.env.ANTHROPIC_MODEL ?? \"claude-sonnet-4-6\";\n }\n}\n","import type { LanguageModel } from \"ai\";\nimport { generateText } from \"ai\";\n\nimport type { JSDocMode, Provider, ResolvedLimits } from \"./config.js\";\nimport type { RouteInfo } from \"./scanner.js\";\n\nimport { computeHash, RouteCache } from \"./cache.js\";\nimport { createModel, getModelId } from \"./providers/index.js\";\n\nexport interface AnalyzeOptions {\n provider: Provider;\n jsdocMode: JSDocMode;\n cache: boolean;\n cacheDir: string;\n limits: ResolvedLimits;\n}\n\nexport interface AnalyzedRoute {\n urlPath: string;\n pathItem: Record<string, unknown>;\n fromCache: boolean;\n skippedLLM: boolean;\n}\n\nexport async function analyzeRoutes(\n routes: RouteInfo[],\n options: AnalyzeOptions,\n): Promise<AnalyzedRoute[]> {\n const modelId = getModelId(options.provider);\n const cache = options.cache ? new RouteCache(options.cacheDir) : null;\n\n // Lazy-init the model only when we actually need it\n let model: LanguageModel | null = null;\n const getModel = (): LanguageModel => {\n if (!model) model = createModel(options.provider);\n return model;\n };\n\n const results: AnalyzedRoute[] = [];\n\n for (const route of routes) {\n const result = await analyzeRoute(route, options, modelId, cache, getModel);\n results.push(result);\n }\n\n return results;\n}\n\nasync function analyzeRoute(\n route: RouteInfo,\n options: AnalyzeOptions,\n modelId: string,\n cache: RouteCache | null,\n getModel: () => LanguageModel,\n): Promise<AnalyzedRoute> {\n // If @openapi-exact is present or jsdocMode is 'exact', skip LLM\n if (route.hasExactJsdoc && route.exactPathItem) {\n return {\n urlPath: route.urlPath,\n pathItem: route.exactPathItem,\n fromCache: false,\n skippedLLM: true,\n };\n }\n\n if (options.jsdocMode === \"exact\") {\n // In exact mode, if there's a @openapi tag, use it; otherwise still use LLM\n if (route.hasExactJsdoc && route.exactPathItem) {\n return {\n urlPath: route.urlPath,\n pathItem: route.exactPathItem,\n fromCache: false,\n skippedLLM: true,\n };\n }\n }\n\n // Compute cache hash\n const hash = computeHash(route.sourceCode, options.provider, modelId);\n\n // Check cache\n if (cache) {\n const cached = cache.get(hash);\n if (cached) {\n return {\n urlPath: route.urlPath,\n pathItem: cached,\n fromCache: true,\n skippedLLM: true,\n };\n }\n }\n\n // Call LLM\n let pathItem: Record<string, unknown>;\n try {\n pathItem = await callLLM(\n route,\n options.jsdocMode,\n getModel(),\n options.limits,\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const isContentFilter =\n message.includes(\"content filtering policy\") ||\n message.includes(\"content_filter\") ||\n (err as { status?: number })?.status === 400;\n\n if (isContentFilter) {\n console.warn(\n `Warning: Content filter blocked response for ${route.urlPath}. ` +\n `Skipping route. Use @openapi-exact JSDoc to provide the spec manually.`,\n );\n return {\n urlPath: route.urlPath,\n pathItem: {},\n fromCache: false,\n skippedLLM: false,\n };\n }\n throw err;\n }\n\n // Store in cache\n if (cache) {\n cache.set(hash, pathItem);\n }\n\n return {\n urlPath: route.urlPath,\n pathItem,\n fromCache: false,\n skippedLLM: false,\n };\n}\n\nfunction buildPrompt(route: RouteInfo, jsdocMode: JSDocMode): string {\n const jsDocSection =\n route.jsdocComments.length > 0\n ? `JSDoc COMMENTS (use as ${jsdocMode === \"context\" ? \"additional context\" : \"primary source\"}):\\n${route.jsdocComments.join(\"\\n\\n\")}`\n : \"No JSDoc comments found.\";\n\n return `You are a technical documentation tool that reads existing source code and produces OpenAPI 3.1 documentation data. You do not write or execute code — you only read and describe it.\n\n## Task\n\nRead the Next.js API route source file below and produce a JSON object that documents its HTTP endpoints according to the OpenAPI 3.1 PathItem schema.\n\n## Route metadata\n\n- File: ${route.relativePath}\n- URL path: ${route.urlPath}\n\n## Source file contents\n\n\\`\\`\\`typescript\n${route.sourceCode}\n\\`\\`\\`\n\n${jsDocSection}\n\n## Instructions\n\nFor each exported function named GET, POST, PUT, PATCH, or DELETE, document:\n- operationId: a unique camelCase identifier\n- summary: a short one-line description (max ~4 words, avoid starting with \"Get\", \"Post\", \"Put\", \"Patch\", \"Delete\", these are sometimes inferred from the operationId, and are sometimes in the format of \"Create a ___\", \"Update a ___\", \"Delete a ___\", \"Get a ___\", \"List ___\")\n- description: a fuller explanation of what the endpoint does\n- parameters: path params from URL segments like {id}, and query params from searchParams usage\n- requestBody: schema inferred from request.json() calls and TypeScript types (POST/PUT/PATCH only)\n- responses: per status code, inferred from NextResponse.json() calls and return type annotations\n- tags: inferred from the URL path segments, but typically only one tag should be used. If more than one exists, they show up in multiple categories, and that can be confusing. If there's a question, use the more specific option.\n- security: noted if the code checks for auth tokens, session cookies, or middleware guards\n\n## Output format\n\nReturn a single raw JSON object matching the OpenAPI 3.1 PathItem schema. No explanation, no markdown fences, no extra text — only the JSON object.`;\n}\n\nasync function callLLM(\n route: RouteInfo,\n jsdocMode: JSDocMode,\n model: LanguageModel,\n limits: ResolvedLimits,\n): Promise<Record<string, unknown>> {\n const prompt = buildPrompt(route, jsdocMode);\n\n const { text } = await generateText({\n model,\n prompt,\n temperature: 0,\n maxOutputTokens: limits.maxTokens,\n abortSignal: AbortSignal.timeout(limits.timeoutMs),\n });\n\n return parsePathItem(text, route.urlPath);\n}\n\nfunction parsePathItem(text: string, urlPath: string): Record<string, unknown> {\n // Strip any accidental markdown code fences\n let json = text.trim();\n if (json.startsWith(\"```\")) {\n json = json\n .replace(/^```(?:json)?\\s*/i, \"\")\n .replace(/\\s*```$/, \"\")\n .trim();\n }\n\n try {\n const parsed = JSON.parse(json);\n if (\n typeof parsed !== \"object\" ||\n Array.isArray(parsed) ||\n parsed === null\n ) {\n throw new Error(\"Response is not a JSON object\");\n }\n return parsed;\n } catch (err) {\n console.warn(\n `Warning: Failed to parse LLM response for ${urlPath}. Using empty PathItem.`,\n err,\n );\n return {};\n }\n}\n","import { existsSync } from \"fs\";\nimport { resolve } from \"path\";\nimport { pathToFileURL } from \"url\";\n\nexport type Provider = \"azure\" | \"openai\" | \"anthropic\";\nexport type JSDocMode = \"context\" | \"exact\";\n\nexport interface OpenAPIGenConfig {\n provider: Provider;\n output: {\n specPath: string;\n scalarDocs?: boolean;\n scalarPath?: string;\n scalarConfig?: Record<string, unknown>;\n };\n openapi: {\n title: string;\n version: string;\n description?: string;\n servers?: Array<{ url: string; description?: string }>;\n security: Array<{ [key: string]: string[] }>;\n components?: {\n securitySchemes?: {\n [key: string]: {\n type: string;\n in: string;\n name: string;\n };\n };\n };\n };\n jsdocMode?: JSDocMode;\n cache?: boolean;\n cacheDir?: string;\n include?: string[];\n exclude?: string[];\n /**\n * Path(s) to .env files to load before running. Defaults to ['.env', '.env.local'].\n * Set to false to disable automatic .env loading.\n */\n envFile?: string | string[] | false;\n /**\n * Safeguards for LLM usage per route analysis call.\n */\n limits?: {\n /**\n * Maximum number of output tokens per LLM call. Defaults to 4000.\n */\n maxTokens?: number;\n /**\n * Timeout in milliseconds per LLM call. Defaults to 60000 (60s).\n */\n timeoutMs?: number;\n };\n}\n\nexport interface ResolvedLimits {\n maxTokens: number;\n timeoutMs: number;\n}\n\nexport interface ResolvedConfig extends Omit<\n Required<OpenAPIGenConfig>,\n \"envFile\" | \"limits\"\n> {\n output: Required<OpenAPIGenConfig[\"output\"]>;\n openapi: Required<OpenAPIGenConfig[\"openapi\"]>;\n envFile: string[] | false;\n limits: ResolvedLimits;\n}\n\nconst defaults: Omit<ResolvedConfig, \"provider\" | \"output\" | \"openapi\"> = {\n jsdocMode: \"context\",\n cache: true,\n cacheDir: \".openapi-cache\",\n include: [\"src/app/api/**/route.ts\"],\n exclude: [],\n envFile: [\".env\", \".env.local\"],\n limits: {\n maxTokens: 4000,\n timeoutMs: 60_000,\n },\n};\n\nexport function resolveConfig(config: OpenAPIGenConfig): ResolvedConfig {\n let envFile: string[] | false;\n if (config.envFile === false) {\n envFile = false;\n } else if (typeof config.envFile === \"string\") {\n envFile = [config.envFile];\n } else {\n envFile = config.envFile ?? (defaults.envFile as string[]);\n }\n\n return {\n ...defaults,\n ...config,\n envFile,\n limits: {\n ...defaults.limits,\n ...config.limits,\n },\n output: {\n scalarDocs: false,\n scalarPath: \"src/app/api/docs/route.ts\",\n scalarConfig: {},\n ...config.output,\n },\n openapi: {\n description: \"\",\n servers: [],\n components: {},\n ...config.openapi,\n },\n };\n}\n\nexport async function loadConfig(configPath?: string): Promise<ResolvedConfig> {\n const searchPaths = configPath\n ? [configPath]\n : [\n \"openapi-gen.config.ts\",\n \"openapi-gen.config.js\",\n \"openapi-gen.config.mjs\",\n \"openapi-gen.config.cjs\",\n ];\n\n for (const p of searchPaths) {\n const abs = resolve(process.cwd(), p);\n if (existsSync(abs)) {\n const mod = await importConfig(abs);\n const config: OpenAPIGenConfig = mod.default ?? mod;\n return resolveConfig(config);\n }\n }\n\n throw new Error(\n \"No openapi-gen.config.ts found. Create one at your project root.\",\n );\n}\n\nasync function importConfig(\n filePath: string,\n): Promise<{ default?: OpenAPIGenConfig } & OpenAPIGenConfig> {\n // For .ts files, try to use tsx/ts-node if available, else fall back to require\n if (filePath.endsWith(\".ts\")) {\n return importTypeScriptConfig(filePath);\n }\n const url = pathToFileURL(filePath).href;\n return import(url);\n}\n\nasync function importTypeScriptConfig(\n filePath: string,\n): Promise<{ default?: OpenAPIGenConfig } & OpenAPIGenConfig> {\n // Use tsx (bundled as a dependency) to register CJS TypeScript hooks\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n require(\"tsx/cjs\");\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require(filePath);\n}\n","import { existsSync, mkdirSync, writeFileSync } from \"fs\";\nimport { dirname, join, resolve } from \"path\";\n\nimport type { AnalyzedRoute } from \"./analyzer.js\";\nimport type { ResolvedConfig } from \"./config.js\";\n\nexport interface OpenAPISpec {\n openapi: \"3.1.0\";\n info: {\n title: string;\n version: string;\n description?: string;\n };\n servers?: Array<{ url: string; description?: string }>;\n security?: Array<{ [key: string]: string[] }>;\n components?: {\n securitySchemes?: Record<string, unknown>;\n [key: string]: unknown;\n };\n paths: Record<string, unknown>;\n}\n\nexport function assembleSpec(\n config: ResolvedConfig,\n routes: AnalyzedRoute[],\n): OpenAPISpec {\n const paths: Record<string, unknown> = {};\n\n for (const route of routes) {\n if (Object.keys(route.pathItem).length > 0) {\n paths[route.urlPath] = route.pathItem;\n }\n }\n\n const spec: OpenAPISpec = {\n openapi: \"3.1.0\",\n info: {\n title: config.openapi.title,\n version: config.openapi.version,\n ...(config.openapi.description\n ? { description: config.openapi.description }\n : {}),\n },\n paths,\n };\n\n if (config.openapi.servers && config.openapi.servers.length > 0) {\n spec.servers = config.openapi.servers;\n }\n\n if (config.openapi.security && config.openapi.security.length > 0) {\n spec.security = config.openapi.security;\n }\n\n if (\n config.openapi.components &&\n Object.keys(config.openapi.components).length > 0\n ) {\n spec.components = config.openapi.components;\n }\n\n return spec;\n}\n\nexport function writeOutputFiles(\n config: ResolvedConfig,\n spec: OpenAPISpec,\n cwd: string = process.cwd(),\n): void {\n writeSpecFiles(config, spec, cwd);\n\n if (config.output.scalarDocs) {\n writeScalarRoute(config, cwd);\n }\n}\n\nfunction writeSpecFiles(\n config: ResolvedConfig,\n spec: OpenAPISpec,\n cwd: string,\n): void {\n const specRoutePath = resolve(cwd, config.output.specPath);\n const specDir = dirname(specRoutePath);\n\n ensureDir(specDir);\n\n // Write spec.json co-located with the route\n const specJsonPath = join(specDir, \"spec.json\");\n writeFileSync(specJsonPath, JSON.stringify(spec, null, 2), \"utf8\");\n\n // Write the Next.js route that serves the spec\n const routeContent = `import spec from './spec.json';\n\nexport const dynamic = 'force-static';\n\nexport function GET() {\n return Response.json(spec);\n}\n`;\n writeFileSync(specRoutePath, routeContent, \"utf8\");\n}\n\nfunction writeScalarRoute(config: ResolvedConfig, cwd: string): void {\n const scalarRoutePath = resolve(cwd, config.output.scalarPath);\n ensureDir(dirname(scalarRoutePath));\n\n // Derive the spec URL from the specPath\n const specUrl = filePathToApiUrl(config.output.specPath);\n\n const routeContent = `export const dynamic = 'force-static';\n\nexport function GET() {\n return new Response(\n \\`<!doctype html>\n<html>\n <head>\n <title>API Docs</title>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <script\n id=\"api-reference\"\n data-url=\"${specUrl}\"\n ${config.output.scalarConfig && Object.keys(config.output.scalarConfig).length > 0 ? `data-config=\"${JSON.stringify(config.output.scalarConfig)}\"` : \"\"}\n ></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>\\`,\n { headers: { 'Content-Type': 'text/html' } }\n );\n}\n`;\n writeFileSync(scalarRoutePath, routeContent, \"utf8\");\n}\n\n/**\n * Convert a file path like src/app/api/openapi.json/route.ts to /api/openapi.json\n */\nfunction filePathToApiUrl(filePath: string): string {\n let path = filePath.replace(/\\\\/g, \"/\");\n path = path.replace(/^(src\\/)?app\\//, \"\");\n path = path.replace(/\\/route\\.(ts|tsx|js|jsx)$/, \"\");\n if (!path.startsWith(\"/\")) path = `/${path}`;\n return path;\n}\n\nfunction ensureDir(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n}\n","import { readFileSync } from \"fs\";\nimport { relative } from \"path\";\n\nexport interface RouteInfo {\n filePath: string;\n relativePath: string;\n urlPath: string;\n sourceCode: string;\n jsdocComments: string[];\n hasExactJsdoc: boolean;\n exactPathItem?: Record<string, unknown>;\n}\n\nexport async function scanRoutes(\n include: string[],\n exclude: string[],\n cwd: string = process.cwd(),\n): Promise<RouteInfo[]> {\n // Lazy import so that importing this module does not eagerly load fast-glob.\n // This keeps the module lightweight and allows Vitest to mock it cleanly.\n const { default: fg } = await import(\"fast-glob\");\n const files = await fg(include, {\n cwd,\n ignore: exclude,\n absolute: true,\n });\n\n return files.map((filePath) => parseRoute(filePath, cwd));\n}\n\nfunction parseRoute(filePath: string, cwd: string): RouteInfo {\n const relativePath = relative(cwd, filePath);\n const sourceCode = readFileSync(filePath, \"utf8\");\n const urlPath = filePathToUrlPath(relativePath);\n const { jsdocComments, hasExactJsdoc, exactPathItem } =\n extractJsdoc(sourceCode);\n\n return {\n filePath,\n relativePath,\n urlPath,\n sourceCode,\n jsdocComments,\n hasExactJsdoc,\n exactPathItem,\n };\n}\n\n/**\n * Convert a Next.js route file path to an OpenAPI URL path.\n * e.g. src/app/api/users/[id]/route.ts -> /api/users/{id}\n */\nexport function filePathToUrlPath(filePath: string): string {\n // Normalize separators\n let path = filePath.replace(/\\\\/g, \"/\");\n\n // Remove leading src/ or app/ prefixes\n path = path.replace(/^(src\\/)?app\\//, \"\");\n\n // Remove trailing /route.ts or /route.js\n path = path.replace(/\\/route\\.(ts|tsx|js|jsx)$/, \"\");\n\n // Convert Next.js dynamic segments [param] to OpenAPI {param}\n path = path.replace(/\\[([^\\]]+)\\]/g, (_, param) => {\n // Handle catch-all [...param] and optional [[...param]]\n if (param.startsWith(\"...\")) {\n return `{${param.slice(3)}}`;\n }\n return `{${param}}`;\n });\n\n // Ensure leading slash\n if (!path.startsWith(\"/\")) {\n path = `/${path}`;\n }\n\n return path;\n}\n\ninterface JsdocResult {\n jsdocComments: string[];\n hasExactJsdoc: boolean;\n exactPathItem?: Record<string, unknown>;\n}\n\nfunction extractJsdoc(sourceCode: string): JsdocResult {\n // Match all JSDoc comment blocks /** ... */\n const jsdocRegex = /\\/\\*\\*([\\s\\S]*?)\\*\\//g;\n const jsdocComments: string[] = [];\n let hasExactJsdoc = false;\n let exactPathItem: Record<string, unknown> | undefined;\n\n let match: RegExpExecArray | null;\n // biome-ignore lint/suspicious/noAssignInExpressions: required for while loop\n while ((match = jsdocRegex.exec(sourceCode)) !== null) {\n const comment = match[0];\n jsdocComments.push(comment);\n\n // Check for @openapi-exact tag\n if (/@openapi-exact/.test(comment)) {\n hasExactJsdoc = true;\n // Try to extract the JSON from @openapi tag\n const openapiMatch = comment.match(\n /@openapi\\s+([\\s\\S]*?)(?=\\s*\\*\\/|\\s*\\*\\s*@)/,\n );\n if (openapiMatch) {\n try {\n // Clean up JSDoc asterisks from the JSON\n const jsonStr = openapiMatch[1]\n .split(\"\\n\")\n .map((line) => line.replace(/^\\s*\\*\\s?/, \"\"))\n .join(\"\\n\")\n .trim();\n exactPathItem = JSON.parse(jsonStr);\n } catch {\n // If JSON parse fails, fall through to LLM\n hasExactJsdoc = false;\n }\n }\n }\n }\n\n return { jsdocComments, hasExactJsdoc, exactPathItem };\n}\n","export type {\n JSDocMode,\n OpenAPIGenConfig,\n Provider,\n ResolvedConfig,\n ResolvedLimits,\n} from \"./config.js\";\n\nexport { analyzeRoutes } from \"./analyzer.js\";\nexport { loadConfig, resolveConfig } from \"./config.js\";\nexport { assembleSpec, writeOutputFiles } from \"./generator.js\";\nexport { filePathToUrlPath, scanRoutes } from \"./scanner.js\";\n\nimport { resolve } from \"node:path\";\n\nimport type { OpenAPIGenConfig } from \"./config.js\";\n\nimport { analyzeRoutes } from \"./analyzer.js\";\nimport { loadConfig } from \"./config.js\";\nimport { assembleSpec, writeOutputFiles } from \"./generator.js\";\nimport { scanRoutes } from \"./scanner.js\";\n\nexport interface GenerateOptions {\n config?: string;\n provider?: OpenAPIGenConfig[\"provider\"];\n cache?: boolean;\n cwd?: string;\n}\n\nexport interface GenerateResult {\n routesAnalyzed: number;\n routesFromCache: number;\n routesSkippedLLM: number;\n specPath: string;\n}\n\nexport async function generate(\n options: GenerateOptions = {},\n): Promise<GenerateResult> {\n const cwd = options.cwd ?? process.cwd();\n const config = await loadConfig(options.config);\n\n // Allow CLI overrides\n if (options.provider) config.provider = options.provider;\n if (options.cache === false) config.cache = false;\n\n // Load .env files before provider env vars are read\n if (config.envFile !== false) {\n const { config: dotenvConfig } = await import(\"dotenv\");\n for (const file of config.envFile) {\n dotenvConfig({ path: resolve(cwd, file), override: false });\n }\n }\n\n console.log(`[openapi-ai-generator] Scanning routes...`);\n const routes = await scanRoutes(config.include, config.exclude, cwd);\n console.log(`[openapi-ai-generator] Found ${routes.length} route(s)`);\n\n console.log(\n `[openapi-ai-generator] Analyzing routes with provider: ${config.provider}`,\n );\n const analyzed = await analyzeRoutes(routes, {\n provider: config.provider,\n jsdocMode: config.jsdocMode,\n cache: config.cache,\n cacheDir: config.cacheDir,\n limits: config.limits,\n });\n\n const fromCache = analyzed.filter((r) => r.fromCache).length;\n const skippedLLM = analyzed.filter((r) => r.skippedLLM).length;\n console.log(\n `[openapi-ai-generator] ${analyzed.length} routes analyzed (${fromCache} from cache, ${skippedLLM - fromCache} exact JSDoc)`,\n );\n\n const spec = assembleSpec(config, analyzed);\n writeOutputFiles(config, spec, cwd);\n\n console.log(\n `[openapi-ai-generator] Spec written to ${config.output.specPath}`,\n );\n if (config.output.scalarDocs) {\n console.log(\n `[openapi-ai-generator] Scalar docs written to ${config.output.scalarPath}`,\n );\n }\n\n return {\n routesAnalyzed: analyzed.length,\n routesFromCache: fromCache,\n routesSkippedLLM: skippedLLM,\n specPath: config.output.specPath,\n };\n}\n","import type { GenerateOptions } from \"./index.js\";\n\ntype NextConfigLike = {\n generateBuildId?: unknown;\n};\n\n/**\n * Next.js config plugin that runs openapi-ai-generator before each build.\n * Compatible with both webpack and Turbopack (Next.js 16+).\n *\n * @example\n * // next.config.ts\n * import { withOpenAPIGen } from 'openapi-ai-generator/plugin';\n * export default withOpenAPIGen(nextConfig);\n */\nexport function withOpenAPIGen<T extends NextConfigLike>(\n nextConfig: T = {} as T,\n options: GenerateOptions = {},\n): T {\n const existingGenerateBuildId = nextConfig.generateBuildId as\n | (() => Promise<string | null>)\n | null\n | undefined;\n\n return {\n ...nextConfig,\n async generateBuildId(): Promise<string | null> {\n const { generate } = await import(\"./index.js\");\n await generate(options);\n return existingGenerateBuildId ? existingGenerateBuildId() : null;\n },\n } as T;\n}\n"]}
package/dist/plugin.mjs CHANGED
@@ -166,7 +166,12 @@ async function analyzeRoute(route, options, modelId, cache, getModel) {
166
166
  }
167
167
  let pathItem;
168
168
  try {
169
- pathItem = await callLLM(route, options.jsdocMode, getModel());
169
+ pathItem = await callLLM(
170
+ route,
171
+ options.jsdocMode,
172
+ getModel(),
173
+ options.limits
174
+ );
170
175
  } catch (err) {
171
176
  const message = err instanceof Error ? err.message : String(err);
172
177
  const isContentFilter = message.includes("content filtering policy") || message.includes("content_filter") || err?.status === 400;
@@ -231,12 +236,14 @@ For each exported function named GET, POST, PUT, PATCH, or DELETE, document:
231
236
 
232
237
  Return a single raw JSON object matching the OpenAPI 3.1 PathItem schema. No explanation, no markdown fences, no extra text \u2014 only the JSON object.`;
233
238
  }
234
- async function callLLM(route, jsdocMode, model) {
239
+ async function callLLM(route, jsdocMode, model, limits) {
235
240
  const prompt = buildPrompt(route, jsdocMode);
236
241
  const { text } = await generateText({
237
242
  model,
238
243
  prompt,
239
- temperature: 0
244
+ temperature: 0,
245
+ maxOutputTokens: limits.maxTokens,
246
+ abortSignal: AbortSignal.timeout(limits.timeoutMs)
240
247
  });
241
248
  return parsePathItem(text, route.urlPath);
242
249
  }
@@ -278,9 +285,14 @@ function resolveConfig(config) {
278
285
  ...defaults,
279
286
  ...config,
280
287
  envFile,
288
+ limits: {
289
+ ...defaults.limits,
290
+ ...config.limits
291
+ },
281
292
  output: {
282
293
  scalarDocs: false,
283
294
  scalarPath: "src/app/api/docs/route.ts",
295
+ scalarConfig: {},
284
296
  ...config.output
285
297
  },
286
298
  openapi: {
@@ -330,7 +342,11 @@ var init_config = __esm({
330
342
  cacheDir: ".openapi-cache",
331
343
  include: ["src/app/api/**/route.ts"],
332
344
  exclude: [],
333
- envFile: [".env", ".env.local"]
345
+ envFile: [".env", ".env.local"],
346
+ limits: {
347
+ maxTokens: 4e3,
348
+ timeoutMs: 6e4
349
+ }
334
350
  };
335
351
  }
336
352
  });
@@ -402,6 +418,7 @@ export function GET() {
402
418
  <script
403
419
  id="api-reference"
404
420
  data-url="${specUrl}"
421
+ ${config.output.scalarConfig && Object.keys(config.output.scalarConfig).length > 0 ? `data-config="${JSON.stringify(config.output.scalarConfig)}"` : ""}
405
422
  ></script>
406
423
  <script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
407
424
  </body>
@@ -524,12 +541,15 @@ async function generate(options = {}) {
524
541
  console.log(`[openapi-ai-generator] Scanning routes...`);
525
542
  const routes = await scanRoutes(config.include, config.exclude, cwd);
526
543
  console.log(`[openapi-ai-generator] Found ${routes.length} route(s)`);
527
- console.log(`[openapi-ai-generator] Analyzing routes with provider: ${config.provider}`);
544
+ console.log(
545
+ `[openapi-ai-generator] Analyzing routes with provider: ${config.provider}`
546
+ );
528
547
  const analyzed = await analyzeRoutes(routes, {
529
548
  provider: config.provider,
530
549
  jsdocMode: config.jsdocMode,
531
550
  cache: config.cache,
532
- cacheDir: config.cacheDir
551
+ cacheDir: config.cacheDir,
552
+ limits: config.limits
533
553
  });
534
554
  const fromCache = analyzed.filter((r) => r.fromCache).length;
535
555
  const skippedLLM = analyzed.filter((r) => r.skippedLLM).length;
@@ -538,9 +558,13 @@ async function generate(options = {}) {
538
558
  );
539
559
  const spec = assembleSpec(config, analyzed);
540
560
  writeOutputFiles(config, spec, cwd);
541
- console.log(`[openapi-ai-generator] Spec written to ${config.output.specPath}`);
561
+ console.log(
562
+ `[openapi-ai-generator] Spec written to ${config.output.specPath}`
563
+ );
542
564
  if (config.output.scalarDocs) {
543
- console.log(`[openapi-ai-generator] Scalar docs written to ${config.output.scalarPath}`);
565
+ console.log(
566
+ `[openapi-ai-generator] Scalar docs written to ${config.output.scalarPath}`
567
+ );
544
568
  }
545
569
  return {
546
570
  routesAnalyzed: analyzed.length,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cache.ts","../src/providers/index.ts","../src/analyzer.ts","../src/config.ts","../src/generator.ts","../src/scanner.ts","../src/index.ts","../src/plugin.ts"],"names":["existsSync","resolve","join","writeFileSync","mkdirSync","readFileSync","generate"],"mappings":"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","file":"plugin.mjs","sourcesContent":["import { createHash } from 'crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\n\nexport interface CacheEntry {\n\thash: string;\n\tpathItem: Record<string, unknown>;\n\tcachedAt: string;\n}\n\nexport function computeHash(content: string, provider: string, modelId: string): string {\n\treturn createHash('sha256').update(content).update(provider).update(modelId).digest('hex');\n}\n\nexport class RouteCache {\n\tprivate readonly cacheDir: string;\n\n\tconstructor(cacheDir: string) {\n\t\tthis.cacheDir = cacheDir;\n\t}\n\n\tprivate ensureDir(): void {\n\t\tif (!existsSync(this.cacheDir)) {\n\t\t\tmkdirSync(this.cacheDir, { recursive: true });\n\t\t}\n\t}\n\n\tget(hash: string): Record<string, unknown> | null {\n\t\tconst filePath = join(this.cacheDir, `${hash}.json`);\n\t\tif (!existsSync(filePath)) return null;\n\t\ttry {\n\t\t\tconst entry: CacheEntry = JSON.parse(readFileSync(filePath, 'utf8'));\n\t\t\treturn entry.pathItem;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tset(hash: string, pathItem: Record<string, unknown>): void {\n\t\tthis.ensureDir();\n\t\tconst entry: CacheEntry = {\n\t\t\thash,\n\t\t\tpathItem,\n\t\t\tcachedAt: new Date().toISOString(),\n\t\t};\n\t\tconst filePath = join(this.cacheDir, `${hash}.json`);\n\t\twriteFileSync(filePath, JSON.stringify(entry, null, 2), 'utf8');\n\t}\n}\n","import type { LanguageModel } from \"ai\";\n\nimport type { Provider } from \"../config.js\";\n\nexport function createModel(provider: Provider): LanguageModel {\n switch (provider) {\n case \"azure\":\n return createAzureModel();\n case \"openai\":\n return createOpenAIModel();\n case \"anthropic\":\n return createAnthropicModel();\n default: {\n const _exhaustive: never = provider;\n throw new Error(`Unknown provider: ${_exhaustive}`);\n }\n }\n}\n\nfunction createAzureModel(): LanguageModel {\n const endpoint = requireEnv(\"AZURE_OPENAI_ENDPOINT\");\n const resourceName = endpoint?.match(/https?:\\/\\/([^.]+)/)?.[1];\n const apiKey = requireEnv(\"AZURE_OPENAI_API_KEY\");\n const deployment = requireEnv(\"AZURE_OPENAI_DEPLOYMENT\");\n\n // Dynamic import to avoid loading unused provider SDKs\n const { createAzure } = require(\"@ai-sdk/azure\");\n const azure = createAzure({ resourceName, apiKey });\n return azure(deployment);\n}\n\nfunction createOpenAIModel(): LanguageModel {\n const apiKey = requireEnv(\"OPENAI_API_KEY\");\n const model = process.env.OPENAI_MODEL ?? \"gpt-4o\";\n\n const { createOpenAI } = require(\"@ai-sdk/openai\");\n const openai = createOpenAI({ apiKey });\n return openai(model);\n}\n\nfunction createAnthropicModel(): LanguageModel {\n const apiKey = requireEnv(\"ANTHROPIC_API_KEY\");\n const model = process.env.ANTHROPIC_MODEL ?? \"claude-sonnet-4-6\";\n\n const { createAnthropic } = require(\"@ai-sdk/anthropic\");\n const anthropic = createAnthropic({ apiKey });\n return anthropic(model);\n}\n\nfunction requireEnv(name: string): string {\n const val = process.env[name];\n if (!val) {\n throw new Error(`Required environment variable ${name} is not set.`);\n }\n return val;\n}\n\nexport function getModelId(provider: Provider): string {\n switch (provider) {\n case \"azure\":\n return process.env.AZURE_OPENAI_DEPLOYMENT ?? \"unknown\";\n case \"openai\":\n return process.env.OPENAI_MODEL ?? \"gpt-4o\";\n case \"anthropic\":\n return process.env.ANTHROPIC_MODEL ?? \"claude-sonnet-4-6\";\n }\n}\n","import type { LanguageModel } from \"ai\";\nimport { generateText } from \"ai\";\n\nimport type { JSDocMode, Provider } from \"./config.js\";\nimport type { RouteInfo } from \"./scanner.js\";\n\nimport { computeHash, RouteCache } from \"./cache.js\";\nimport { createModel, getModelId } from \"./providers/index.js\";\n\nexport interface AnalyzeOptions {\n provider: Provider;\n jsdocMode: JSDocMode;\n cache: boolean;\n cacheDir: string;\n}\n\nexport interface AnalyzedRoute {\n urlPath: string;\n pathItem: Record<string, unknown>;\n fromCache: boolean;\n skippedLLM: boolean;\n}\n\nexport async function analyzeRoutes(\n routes: RouteInfo[],\n options: AnalyzeOptions,\n): Promise<AnalyzedRoute[]> {\n const modelId = getModelId(options.provider);\n const cache = options.cache ? new RouteCache(options.cacheDir) : null;\n\n // Lazy-init the model only when we actually need it\n let model: LanguageModel | null = null;\n const getModel = (): LanguageModel => {\n if (!model) model = createModel(options.provider);\n return model;\n };\n\n const results: AnalyzedRoute[] = [];\n\n for (const route of routes) {\n const result = await analyzeRoute(route, options, modelId, cache, getModel);\n results.push(result);\n }\n\n return results;\n}\n\nasync function analyzeRoute(\n route: RouteInfo,\n options: AnalyzeOptions,\n modelId: string,\n cache: RouteCache | null,\n getModel: () => LanguageModel,\n): Promise<AnalyzedRoute> {\n // If @openapi-exact is present or jsdocMode is 'exact', skip LLM\n if (route.hasExactJsdoc && route.exactPathItem) {\n return {\n urlPath: route.urlPath,\n pathItem: route.exactPathItem,\n fromCache: false,\n skippedLLM: true,\n };\n }\n\n if (options.jsdocMode === \"exact\") {\n // In exact mode, if there's a @openapi tag, use it; otherwise still use LLM\n if (route.hasExactJsdoc && route.exactPathItem) {\n return {\n urlPath: route.urlPath,\n pathItem: route.exactPathItem,\n fromCache: false,\n skippedLLM: true,\n };\n }\n }\n\n // Compute cache hash\n const hash = computeHash(route.sourceCode, options.provider, modelId);\n\n // Check cache\n if (cache) {\n const cached = cache.get(hash);\n if (cached) {\n return {\n urlPath: route.urlPath,\n pathItem: cached,\n fromCache: true,\n skippedLLM: true,\n };\n }\n }\n\n // Call LLM\n let pathItem: Record<string, unknown>;\n try {\n pathItem = await callLLM(route, options.jsdocMode, getModel());\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const isContentFilter =\n message.includes(\"content filtering policy\") ||\n message.includes(\"content_filter\") ||\n (err as { status?: number })?.status === 400;\n\n if (isContentFilter) {\n console.warn(\n `Warning: Content filter blocked response for ${route.urlPath}. ` +\n `Skipping route. Use @openapi-exact JSDoc to provide the spec manually.`,\n );\n return {\n urlPath: route.urlPath,\n pathItem: {},\n fromCache: false,\n skippedLLM: false,\n };\n }\n throw err;\n }\n\n // Store in cache\n if (cache) {\n cache.set(hash, pathItem);\n }\n\n return {\n urlPath: route.urlPath,\n pathItem,\n fromCache: false,\n skippedLLM: false,\n };\n}\n\nfunction buildPrompt(route: RouteInfo, jsdocMode: JSDocMode): string {\n const jsDocSection =\n route.jsdocComments.length > 0\n ? `JSDoc COMMENTS (use as ${jsdocMode === \"context\" ? \"additional context\" : \"primary source\"}):\\n${route.jsdocComments.join(\"\\n\\n\")}`\n : \"No JSDoc comments found.\";\n\n return `You are a technical documentation tool that reads existing source code and produces OpenAPI 3.1 documentation data. You do not write or execute code — you only read and describe it.\n\n## Task\n\nRead the Next.js API route source file below and produce a JSON object that documents its HTTP endpoints according to the OpenAPI 3.1 PathItem schema.\n\n## Route metadata\n\n- File: ${route.relativePath}\n- URL path: ${route.urlPath}\n\n## Source file contents\n\n\\`\\`\\`typescript\n${route.sourceCode}\n\\`\\`\\`\n\n${jsDocSection}\n\n## Instructions\n\nFor each exported function named GET, POST, PUT, PATCH, or DELETE, document:\n- operationId: a unique camelCase identifier\n- summary: a short one-line description (max ~4 words, avoid starting with \"Get\", \"Post\", \"Put\", \"Patch\", \"Delete\", these are sometimes inferred from the operationId, and are sometimes in the format of \"Create a ___\", \"Update a ___\", \"Delete a ___\", \"Get a ___\", \"List ___\")\n- description: a fuller explanation of what the endpoint does\n- parameters: path params from URL segments like {id}, and query params from searchParams usage\n- requestBody: schema inferred from request.json() calls and TypeScript types (POST/PUT/PATCH only)\n- responses: per status code, inferred from NextResponse.json() calls and return type annotations\n- tags: inferred from the URL path segments, but typically only one tag should be used. If more than one exists, they show up in multiple categories, and that can be confusing. If there's a question, use the more specific option.\n- security: noted if the code checks for auth tokens, session cookies, or middleware guards\n\n## Output format\n\nReturn a single raw JSON object matching the OpenAPI 3.1 PathItem schema. No explanation, no markdown fences, no extra text — only the JSON object.`;\n}\n\nasync function callLLM(\n route: RouteInfo,\n jsdocMode: JSDocMode,\n model: LanguageModel,\n): Promise<Record<string, unknown>> {\n const prompt = buildPrompt(route, jsdocMode);\n\n const { text } = await generateText({\n model,\n prompt,\n temperature: 0,\n });\n\n return parsePathItem(text, route.urlPath);\n}\n\nfunction parsePathItem(text: string, urlPath: string): Record<string, unknown> {\n // Strip any accidental markdown code fences\n let json = text.trim();\n if (json.startsWith(\"```\")) {\n json = json\n .replace(/^```(?:json)?\\s*/i, \"\")\n .replace(/\\s*```$/, \"\")\n .trim();\n }\n\n try {\n const parsed = JSON.parse(json);\n if (\n typeof parsed !== \"object\" ||\n Array.isArray(parsed) ||\n parsed === null\n ) {\n throw new Error(\"Response is not a JSON object\");\n }\n return parsed;\n } catch (err) {\n console.warn(\n `Warning: Failed to parse LLM response for ${urlPath}. Using empty PathItem.`,\n err,\n );\n return {};\n }\n}\n","import { existsSync } from \"fs\";\nimport { resolve } from \"path\";\nimport { pathToFileURL } from \"url\";\n\nexport type Provider = \"azure\" | \"openai\" | \"anthropic\";\nexport type JSDocMode = \"context\" | \"exact\";\n\nexport interface OpenAPIGenConfig {\n provider: Provider;\n output: {\n specPath: string;\n scalarDocs?: boolean;\n scalarPath?: string;\n };\n openapi: {\n title: string;\n version: string;\n description?: string;\n servers?: Array<{ url: string; description?: string }>;\n security: Array<{ [key: string]: string[] }>;\n components?: {\n securitySchemes?: {\n [key: string]: {\n type: string;\n in: string;\n name: string;\n };\n };\n };\n };\n jsdocMode?: JSDocMode;\n cache?: boolean;\n cacheDir?: string;\n include?: string[];\n exclude?: string[];\n /**\n * Path(s) to .env files to load before running. Defaults to ['.env', '.env.local'].\n * Set to false to disable automatic .env loading.\n */\n envFile?: string | string[] | false;\n}\n\nexport interface ResolvedConfig extends Omit<\n Required<OpenAPIGenConfig>,\n \"envFile\"\n> {\n output: Required<OpenAPIGenConfig[\"output\"]>;\n openapi: Required<OpenAPIGenConfig[\"openapi\"]>;\n envFile: string[] | false;\n}\n\nconst defaults: Omit<ResolvedConfig, \"provider\" | \"output\" | \"openapi\"> = {\n jsdocMode: \"context\",\n cache: true,\n cacheDir: \".openapi-cache\",\n include: [\"src/app/api/**/route.ts\"],\n exclude: [],\n envFile: [\".env\", \".env.local\"],\n};\n\nexport function resolveConfig(config: OpenAPIGenConfig): ResolvedConfig {\n let envFile: string[] | false;\n if (config.envFile === false) {\n envFile = false;\n } else if (typeof config.envFile === \"string\") {\n envFile = [config.envFile];\n } else {\n envFile = config.envFile ?? (defaults.envFile as string[]);\n }\n\n return {\n ...defaults,\n ...config,\n envFile,\n output: {\n scalarDocs: false,\n scalarPath: \"src/app/api/docs/route.ts\",\n ...config.output,\n },\n openapi: {\n description: \"\",\n servers: [],\n components: {},\n ...config.openapi,\n },\n };\n}\n\nexport async function loadConfig(configPath?: string): Promise<ResolvedConfig> {\n const searchPaths = configPath\n ? [configPath]\n : [\n \"openapi-gen.config.ts\",\n \"openapi-gen.config.js\",\n \"openapi-gen.config.mjs\",\n \"openapi-gen.config.cjs\",\n ];\n\n for (const p of searchPaths) {\n const abs = resolve(process.cwd(), p);\n if (existsSync(abs)) {\n const mod = await importConfig(abs);\n const config: OpenAPIGenConfig = mod.default ?? mod;\n return resolveConfig(config);\n }\n }\n\n throw new Error(\n \"No openapi-gen.config.ts found. Create one at your project root.\",\n );\n}\n\nasync function importConfig(\n filePath: string,\n): Promise<{ default?: OpenAPIGenConfig } & OpenAPIGenConfig> {\n // For .ts files, try to use tsx/ts-node if available, else fall back to require\n if (filePath.endsWith(\".ts\")) {\n return importTypeScriptConfig(filePath);\n }\n const url = pathToFileURL(filePath).href;\n return import(url);\n}\n\nasync function importTypeScriptConfig(\n filePath: string,\n): Promise<{ default?: OpenAPIGenConfig } & OpenAPIGenConfig> {\n // Use tsx (bundled as a dependency) to register CJS TypeScript hooks\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n require(\"tsx/cjs\");\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require(filePath);\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'fs';\nimport { dirname, join, resolve } from 'path';\n\nimport type { AnalyzedRoute } from './analyzer.js';\nimport type { ResolvedConfig } from './config.js';\n\nexport interface OpenAPISpec {\n\topenapi: '3.1.0';\n\tinfo: {\n\t\ttitle: string;\n\t\tversion: string;\n\t\tdescription?: string;\n\t};\n\tservers?: Array<{ url: string; description?: string }>;\n\tsecurity?: Array<{ [key: string]: string[] }>;\n\tcomponents?: {\n\t\tsecuritySchemes?: Record<string, unknown>;\n\t\t[key: string]: unknown;\n\t};\n\tpaths: Record<string, unknown>;\n}\n\nexport function assembleSpec(config: ResolvedConfig, routes: AnalyzedRoute[]): OpenAPISpec {\n\tconst paths: Record<string, unknown> = {};\n\n\tfor (const route of routes) {\n\t\tif (Object.keys(route.pathItem).length > 0) {\n\t\t\tpaths[route.urlPath] = route.pathItem;\n\t\t}\n\t}\n\n\tconst spec: OpenAPISpec = {\n\t\topenapi: '3.1.0',\n\t\tinfo: {\n\t\t\ttitle: config.openapi.title,\n\t\t\tversion: config.openapi.version,\n\t\t\t...(config.openapi.description ? { description: config.openapi.description } : {}),\n\t\t},\n\t\tpaths,\n\t};\n\n\tif (config.openapi.servers && config.openapi.servers.length > 0) {\n\t\tspec.servers = config.openapi.servers;\n\t}\n\n\tif (config.openapi.security && config.openapi.security.length > 0) {\n\t\tspec.security = config.openapi.security;\n\t}\n\n\tif (config.openapi.components && Object.keys(config.openapi.components).length > 0) {\n\t\tspec.components = config.openapi.components;\n\t}\n\n\treturn spec;\n}\n\nexport function writeOutputFiles(\n\tconfig: ResolvedConfig,\n\tspec: OpenAPISpec,\n\tcwd: string = process.cwd(),\n): void {\n\twriteSpecFiles(config, spec, cwd);\n\n\tif (config.output.scalarDocs) {\n\t\twriteScalarRoute(config, cwd);\n\t}\n}\n\nfunction writeSpecFiles(config: ResolvedConfig, spec: OpenAPISpec, cwd: string): void {\n\tconst specRoutePath = resolve(cwd, config.output.specPath);\n\tconst specDir = dirname(specRoutePath);\n\n\tensureDir(specDir);\n\n\t// Write spec.json co-located with the route\n\tconst specJsonPath = join(specDir, 'spec.json');\n\twriteFileSync(specJsonPath, JSON.stringify(spec, null, 2), 'utf8');\n\n\t// Write the Next.js route that serves the spec\n\tconst routeContent = `import spec from './spec.json';\n\nexport const dynamic = 'force-static';\n\nexport function GET() {\n return Response.json(spec);\n}\n`;\n\twriteFileSync(specRoutePath, routeContent, 'utf8');\n}\n\nfunction writeScalarRoute(config: ResolvedConfig, cwd: string): void {\n\tconst scalarRoutePath = resolve(cwd, config.output.scalarPath);\n\tensureDir(dirname(scalarRoutePath));\n\n\t// Derive the spec URL from the specPath\n\tconst specUrl = filePathToApiUrl(config.output.specPath);\n\n\tconst routeContent = `export const dynamic = 'force-static';\n\nexport function GET() {\n return new Response(\n \\`<!doctype html>\n<html>\n <head>\n <title>API Docs</title>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <script\n id=\"api-reference\"\n data-url=\"${specUrl}\"\n ></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>\\`,\n { headers: { 'Content-Type': 'text/html' } }\n );\n}\n`;\n\twriteFileSync(scalarRoutePath, routeContent, 'utf8');\n}\n\n/**\n * Convert a file path like src/app/api/openapi.json/route.ts to /api/openapi.json\n */\nfunction filePathToApiUrl(filePath: string): string {\n\tlet path = filePath.replace(/\\\\/g, '/');\n\tpath = path.replace(/^(src\\/)?app\\//, '');\n\tpath = path.replace(/\\/route\\.(ts|tsx|js|jsx)$/, '');\n\tif (!path.startsWith('/')) path = `/${path}`;\n\treturn path;\n}\n\nfunction ensureDir(dir: string): void {\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n}\n","import { readFileSync } from \"fs\";\nimport { relative } from \"path\";\n\nexport interface RouteInfo {\n filePath: string;\n relativePath: string;\n urlPath: string;\n sourceCode: string;\n jsdocComments: string[];\n hasExactJsdoc: boolean;\n exactPathItem?: Record<string, unknown>;\n}\n\nexport async function scanRoutes(\n include: string[],\n exclude: string[],\n cwd: string = process.cwd(),\n): Promise<RouteInfo[]> {\n // Lazy import so that importing this module does not eagerly load fast-glob.\n // This keeps the module lightweight and allows Vitest to mock it cleanly.\n const { default: fg } = await import(\"fast-glob\");\n const files = await fg(include, {\n cwd,\n ignore: exclude,\n absolute: true,\n });\n\n return files.map((filePath) => parseRoute(filePath, cwd));\n}\n\nfunction parseRoute(filePath: string, cwd: string): RouteInfo {\n const relativePath = relative(cwd, filePath);\n const sourceCode = readFileSync(filePath, \"utf8\");\n const urlPath = filePathToUrlPath(relativePath);\n const { jsdocComments, hasExactJsdoc, exactPathItem } =\n extractJsdoc(sourceCode);\n\n return {\n filePath,\n relativePath,\n urlPath,\n sourceCode,\n jsdocComments,\n hasExactJsdoc,\n exactPathItem,\n };\n}\n\n/**\n * Convert a Next.js route file path to an OpenAPI URL path.\n * e.g. src/app/api/users/[id]/route.ts -> /api/users/{id}\n */\nexport function filePathToUrlPath(filePath: string): string {\n // Normalize separators\n let path = filePath.replace(/\\\\/g, \"/\");\n\n // Remove leading src/ or app/ prefixes\n path = path.replace(/^(src\\/)?app\\//, \"\");\n\n // Remove trailing /route.ts or /route.js\n path = path.replace(/\\/route\\.(ts|tsx|js|jsx)$/, \"\");\n\n // Convert Next.js dynamic segments [param] to OpenAPI {param}\n path = path.replace(/\\[([^\\]]+)\\]/g, (_, param) => {\n // Handle catch-all [...param] and optional [[...param]]\n if (param.startsWith(\"...\")) {\n return `{${param.slice(3)}}`;\n }\n return `{${param}}`;\n });\n\n // Ensure leading slash\n if (!path.startsWith(\"/\")) {\n path = `/${path}`;\n }\n\n return path;\n}\n\ninterface JsdocResult {\n jsdocComments: string[];\n hasExactJsdoc: boolean;\n exactPathItem?: Record<string, unknown>;\n}\n\nfunction extractJsdoc(sourceCode: string): JsdocResult {\n // Match all JSDoc comment blocks /** ... */\n const jsdocRegex = /\\/\\*\\*([\\s\\S]*?)\\*\\//g;\n const jsdocComments: string[] = [];\n let hasExactJsdoc = false;\n let exactPathItem: Record<string, unknown> | undefined;\n\n let match: RegExpExecArray | null;\n // biome-ignore lint/suspicious/noAssignInExpressions: required for while loop\n while ((match = jsdocRegex.exec(sourceCode)) !== null) {\n const comment = match[0];\n jsdocComments.push(comment);\n\n // Check for @openapi-exact tag\n if (/@openapi-exact/.test(comment)) {\n hasExactJsdoc = true;\n // Try to extract the JSON from @openapi tag\n const openapiMatch = comment.match(\n /@openapi\\s+([\\s\\S]*?)(?=\\s*\\*\\/|\\s*\\*\\s*@)/,\n );\n if (openapiMatch) {\n try {\n // Clean up JSDoc asterisks from the JSON\n const jsonStr = openapiMatch[1]\n .split(\"\\n\")\n .map((line) => line.replace(/^\\s*\\*\\s?/, \"\"))\n .join(\"\\n\")\n .trim();\n exactPathItem = JSON.parse(jsonStr);\n } catch {\n // If JSON parse fails, fall through to LLM\n hasExactJsdoc = false;\n }\n }\n }\n }\n\n return { jsdocComments, hasExactJsdoc, exactPathItem };\n}\n","export type { JSDocMode, OpenAPIGenConfig, Provider, ResolvedConfig } from './config.js';\n\nexport { analyzeRoutes } from './analyzer.js';\nexport { loadConfig, resolveConfig } from './config.js';\nexport { assembleSpec, writeOutputFiles } from './generator.js';\nexport { filePathToUrlPath, scanRoutes } from './scanner.js';\n\nimport { resolve } from 'node:path';\nimport type { OpenAPIGenConfig } from './config.js';\n\nimport { analyzeRoutes } from './analyzer.js';\nimport { loadConfig } from './config.js';\nimport { assembleSpec, writeOutputFiles } from './generator.js';\nimport { scanRoutes } from './scanner.js';\n\nexport interface GenerateOptions {\n\tconfig?: string;\n\tprovider?: OpenAPIGenConfig['provider'];\n\tcache?: boolean;\n\tcwd?: string;\n}\n\nexport interface GenerateResult {\n\troutesAnalyzed: number;\n\troutesFromCache: number;\n\troutesSkippedLLM: number;\n\tspecPath: string;\n}\n\nexport async function generate(options: GenerateOptions = {}): Promise<GenerateResult> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst config = await loadConfig(options.config);\n\n\t// Allow CLI overrides\n\tif (options.provider) config.provider = options.provider;\n\tif (options.cache === false) config.cache = false;\n\n\t// Load .env files before provider env vars are read\n\tif (config.envFile !== false) {\n\t\tconst { config: dotenvConfig } = await import('dotenv');\n\t\tfor (const file of config.envFile) {\n\t\t\tdotenvConfig({ path: resolve(cwd, file), override: false });\n\t\t}\n\t}\n\n\tconsole.log(`[openapi-ai-generator] Scanning routes...`);\n\tconst routes = await scanRoutes(config.include, config.exclude, cwd);\n\tconsole.log(`[openapi-ai-generator] Found ${routes.length} route(s)`);\n\n\tconsole.log(`[openapi-ai-generator] Analyzing routes with provider: ${config.provider}`);\n\tconst analyzed = await analyzeRoutes(routes, {\n\t\tprovider: config.provider,\n\t\tjsdocMode: config.jsdocMode,\n\t\tcache: config.cache,\n\t\tcacheDir: config.cacheDir,\n\t});\n\n\tconst fromCache = analyzed.filter((r) => r.fromCache).length;\n\tconst skippedLLM = analyzed.filter((r) => r.skippedLLM).length;\n\tconsole.log(\n\t\t`[openapi-ai-generator] ${analyzed.length} routes analyzed (${fromCache} from cache, ${skippedLLM - fromCache} exact JSDoc)`,\n\t);\n\n\tconst spec = assembleSpec(config, analyzed);\n\twriteOutputFiles(config, spec, cwd);\n\n\tconsole.log(`[openapi-ai-generator] Spec written to ${config.output.specPath}`);\n\tif (config.output.scalarDocs) {\n\t\tconsole.log(`[openapi-ai-generator] Scalar docs written to ${config.output.scalarPath}`);\n\t}\n\n\treturn {\n\t\troutesAnalyzed: analyzed.length,\n\t\troutesFromCache: fromCache,\n\t\troutesSkippedLLM: skippedLLM,\n\t\tspecPath: config.output.specPath,\n\t};\n}\n","import type { GenerateOptions } from './index.js';\n\ntype NextConfigLike = {\n\tgenerateBuildId?: unknown;\n};\n\n/**\n * Next.js config plugin that runs openapi-ai-generator before each build.\n * Compatible with both webpack and Turbopack (Next.js 16+).\n *\n * @example\n * // next.config.ts\n * import { withOpenAPIGen } from 'openapi-ai-generator/plugin';\n * export default withOpenAPIGen(nextConfig);\n */\nexport function withOpenAPIGen<T extends NextConfigLike>(\n\tnextConfig: T = {} as T,\n\toptions: GenerateOptions = {},\n): T {\n\tconst existingGenerateBuildId = nextConfig.generateBuildId as\n\t\t| (() => Promise<string | null>)\n\t\t| null\n\t\t| undefined;\n\n\treturn {\n\t\t...nextConfig,\n\t\tasync generateBuildId(): Promise<string | null> {\n\t\t\tconst { generate } = await import('./index.js');\n\t\t\tawait generate(options);\n\t\t\treturn existingGenerateBuildId ? existingGenerateBuildId() : null;\n\t\t},\n\t} as T;\n}\n"]}
1
+ {"version":3,"sources":["../src/cache.ts","../src/providers/index.ts","../src/analyzer.ts","../src/config.ts","../src/generator.ts","../src/scanner.ts","../src/index.ts","../src/plugin.ts"],"names":["existsSync","resolve","join","writeFileSync","mkdirSync","readFileSync","generate"],"mappings":"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","file":"plugin.mjs","sourcesContent":["import { createHash } from 'crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\n\nexport interface CacheEntry {\n\thash: string;\n\tpathItem: Record<string, unknown>;\n\tcachedAt: string;\n}\n\nexport function computeHash(content: string, provider: string, modelId: string): string {\n\treturn createHash('sha256').update(content).update(provider).update(modelId).digest('hex');\n}\n\nexport class RouteCache {\n\tprivate readonly cacheDir: string;\n\n\tconstructor(cacheDir: string) {\n\t\tthis.cacheDir = cacheDir;\n\t}\n\n\tprivate ensureDir(): void {\n\t\tif (!existsSync(this.cacheDir)) {\n\t\t\tmkdirSync(this.cacheDir, { recursive: true });\n\t\t}\n\t}\n\n\tget(hash: string): Record<string, unknown> | null {\n\t\tconst filePath = join(this.cacheDir, `${hash}.json`);\n\t\tif (!existsSync(filePath)) return null;\n\t\ttry {\n\t\t\tconst entry: CacheEntry = JSON.parse(readFileSync(filePath, 'utf8'));\n\t\t\treturn entry.pathItem;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tset(hash: string, pathItem: Record<string, unknown>): void {\n\t\tthis.ensureDir();\n\t\tconst entry: CacheEntry = {\n\t\t\thash,\n\t\t\tpathItem,\n\t\t\tcachedAt: new Date().toISOString(),\n\t\t};\n\t\tconst filePath = join(this.cacheDir, `${hash}.json`);\n\t\twriteFileSync(filePath, JSON.stringify(entry, null, 2), 'utf8');\n\t}\n}\n","import type { LanguageModel } from \"ai\";\n\nimport type { Provider } from \"../config.js\";\n\nexport function createModel(provider: Provider): LanguageModel {\n switch (provider) {\n case \"azure\":\n return createAzureModel();\n case \"openai\":\n return createOpenAIModel();\n case \"anthropic\":\n return createAnthropicModel();\n default: {\n const _exhaustive: never = provider;\n throw new Error(`Unknown provider: ${_exhaustive}`);\n }\n }\n}\n\nfunction createAzureModel(): LanguageModel {\n const endpoint = requireEnv(\"AZURE_OPENAI_ENDPOINT\");\n const resourceName = endpoint?.match(/https?:\\/\\/([^.]+)/)?.[1];\n const apiKey = requireEnv(\"AZURE_OPENAI_API_KEY\");\n const deployment = requireEnv(\"AZURE_OPENAI_DEPLOYMENT\");\n\n // Dynamic import to avoid loading unused provider SDKs\n const { createAzure } = require(\"@ai-sdk/azure\");\n const azure = createAzure({ resourceName, apiKey });\n return azure(deployment);\n}\n\nfunction createOpenAIModel(): LanguageModel {\n const apiKey = requireEnv(\"OPENAI_API_KEY\");\n const model = process.env.OPENAI_MODEL ?? \"gpt-4o\";\n\n const { createOpenAI } = require(\"@ai-sdk/openai\");\n const openai = createOpenAI({ apiKey });\n return openai(model);\n}\n\nfunction createAnthropicModel(): LanguageModel {\n const apiKey = requireEnv(\"ANTHROPIC_API_KEY\");\n const model = process.env.ANTHROPIC_MODEL ?? \"claude-sonnet-4-6\";\n\n const { createAnthropic } = require(\"@ai-sdk/anthropic\");\n const anthropic = createAnthropic({ apiKey });\n return anthropic(model);\n}\n\nfunction requireEnv(name: string): string {\n const val = process.env[name];\n if (!val) {\n throw new Error(`Required environment variable ${name} is not set.`);\n }\n return val;\n}\n\nexport function getModelId(provider: Provider): string {\n switch (provider) {\n case \"azure\":\n return process.env.AZURE_OPENAI_DEPLOYMENT ?? \"unknown\";\n case \"openai\":\n return process.env.OPENAI_MODEL ?? \"gpt-4o\";\n case \"anthropic\":\n return process.env.ANTHROPIC_MODEL ?? \"claude-sonnet-4-6\";\n }\n}\n","import type { LanguageModel } from \"ai\";\nimport { generateText } from \"ai\";\n\nimport type { JSDocMode, Provider, ResolvedLimits } from \"./config.js\";\nimport type { RouteInfo } from \"./scanner.js\";\n\nimport { computeHash, RouteCache } from \"./cache.js\";\nimport { createModel, getModelId } from \"./providers/index.js\";\n\nexport interface AnalyzeOptions {\n provider: Provider;\n jsdocMode: JSDocMode;\n cache: boolean;\n cacheDir: string;\n limits: ResolvedLimits;\n}\n\nexport interface AnalyzedRoute {\n urlPath: string;\n pathItem: Record<string, unknown>;\n fromCache: boolean;\n skippedLLM: boolean;\n}\n\nexport async function analyzeRoutes(\n routes: RouteInfo[],\n options: AnalyzeOptions,\n): Promise<AnalyzedRoute[]> {\n const modelId = getModelId(options.provider);\n const cache = options.cache ? new RouteCache(options.cacheDir) : null;\n\n // Lazy-init the model only when we actually need it\n let model: LanguageModel | null = null;\n const getModel = (): LanguageModel => {\n if (!model) model = createModel(options.provider);\n return model;\n };\n\n const results: AnalyzedRoute[] = [];\n\n for (const route of routes) {\n const result = await analyzeRoute(route, options, modelId, cache, getModel);\n results.push(result);\n }\n\n return results;\n}\n\nasync function analyzeRoute(\n route: RouteInfo,\n options: AnalyzeOptions,\n modelId: string,\n cache: RouteCache | null,\n getModel: () => LanguageModel,\n): Promise<AnalyzedRoute> {\n // If @openapi-exact is present or jsdocMode is 'exact', skip LLM\n if (route.hasExactJsdoc && route.exactPathItem) {\n return {\n urlPath: route.urlPath,\n pathItem: route.exactPathItem,\n fromCache: false,\n skippedLLM: true,\n };\n }\n\n if (options.jsdocMode === \"exact\") {\n // In exact mode, if there's a @openapi tag, use it; otherwise still use LLM\n if (route.hasExactJsdoc && route.exactPathItem) {\n return {\n urlPath: route.urlPath,\n pathItem: route.exactPathItem,\n fromCache: false,\n skippedLLM: true,\n };\n }\n }\n\n // Compute cache hash\n const hash = computeHash(route.sourceCode, options.provider, modelId);\n\n // Check cache\n if (cache) {\n const cached = cache.get(hash);\n if (cached) {\n return {\n urlPath: route.urlPath,\n pathItem: cached,\n fromCache: true,\n skippedLLM: true,\n };\n }\n }\n\n // Call LLM\n let pathItem: Record<string, unknown>;\n try {\n pathItem = await callLLM(\n route,\n options.jsdocMode,\n getModel(),\n options.limits,\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const isContentFilter =\n message.includes(\"content filtering policy\") ||\n message.includes(\"content_filter\") ||\n (err as { status?: number })?.status === 400;\n\n if (isContentFilter) {\n console.warn(\n `Warning: Content filter blocked response for ${route.urlPath}. ` +\n `Skipping route. Use @openapi-exact JSDoc to provide the spec manually.`,\n );\n return {\n urlPath: route.urlPath,\n pathItem: {},\n fromCache: false,\n skippedLLM: false,\n };\n }\n throw err;\n }\n\n // Store in cache\n if (cache) {\n cache.set(hash, pathItem);\n }\n\n return {\n urlPath: route.urlPath,\n pathItem,\n fromCache: false,\n skippedLLM: false,\n };\n}\n\nfunction buildPrompt(route: RouteInfo, jsdocMode: JSDocMode): string {\n const jsDocSection =\n route.jsdocComments.length > 0\n ? `JSDoc COMMENTS (use as ${jsdocMode === \"context\" ? \"additional context\" : \"primary source\"}):\\n${route.jsdocComments.join(\"\\n\\n\")}`\n : \"No JSDoc comments found.\";\n\n return `You are a technical documentation tool that reads existing source code and produces OpenAPI 3.1 documentation data. You do not write or execute code — you only read and describe it.\n\n## Task\n\nRead the Next.js API route source file below and produce a JSON object that documents its HTTP endpoints according to the OpenAPI 3.1 PathItem schema.\n\n## Route metadata\n\n- File: ${route.relativePath}\n- URL path: ${route.urlPath}\n\n## Source file contents\n\n\\`\\`\\`typescript\n${route.sourceCode}\n\\`\\`\\`\n\n${jsDocSection}\n\n## Instructions\n\nFor each exported function named GET, POST, PUT, PATCH, or DELETE, document:\n- operationId: a unique camelCase identifier\n- summary: a short one-line description (max ~4 words, avoid starting with \"Get\", \"Post\", \"Put\", \"Patch\", \"Delete\", these are sometimes inferred from the operationId, and are sometimes in the format of \"Create a ___\", \"Update a ___\", \"Delete a ___\", \"Get a ___\", \"List ___\")\n- description: a fuller explanation of what the endpoint does\n- parameters: path params from URL segments like {id}, and query params from searchParams usage\n- requestBody: schema inferred from request.json() calls and TypeScript types (POST/PUT/PATCH only)\n- responses: per status code, inferred from NextResponse.json() calls and return type annotations\n- tags: inferred from the URL path segments, but typically only one tag should be used. If more than one exists, they show up in multiple categories, and that can be confusing. If there's a question, use the more specific option.\n- security: noted if the code checks for auth tokens, session cookies, or middleware guards\n\n## Output format\n\nReturn a single raw JSON object matching the OpenAPI 3.1 PathItem schema. No explanation, no markdown fences, no extra text — only the JSON object.`;\n}\n\nasync function callLLM(\n route: RouteInfo,\n jsdocMode: JSDocMode,\n model: LanguageModel,\n limits: ResolvedLimits,\n): Promise<Record<string, unknown>> {\n const prompt = buildPrompt(route, jsdocMode);\n\n const { text } = await generateText({\n model,\n prompt,\n temperature: 0,\n maxOutputTokens: limits.maxTokens,\n abortSignal: AbortSignal.timeout(limits.timeoutMs),\n });\n\n return parsePathItem(text, route.urlPath);\n}\n\nfunction parsePathItem(text: string, urlPath: string): Record<string, unknown> {\n // Strip any accidental markdown code fences\n let json = text.trim();\n if (json.startsWith(\"```\")) {\n json = json\n .replace(/^```(?:json)?\\s*/i, \"\")\n .replace(/\\s*```$/, \"\")\n .trim();\n }\n\n try {\n const parsed = JSON.parse(json);\n if (\n typeof parsed !== \"object\" ||\n Array.isArray(parsed) ||\n parsed === null\n ) {\n throw new Error(\"Response is not a JSON object\");\n }\n return parsed;\n } catch (err) {\n console.warn(\n `Warning: Failed to parse LLM response for ${urlPath}. Using empty PathItem.`,\n err,\n );\n return {};\n }\n}\n","import { existsSync } from \"fs\";\nimport { resolve } from \"path\";\nimport { pathToFileURL } from \"url\";\n\nexport type Provider = \"azure\" | \"openai\" | \"anthropic\";\nexport type JSDocMode = \"context\" | \"exact\";\n\nexport interface OpenAPIGenConfig {\n provider: Provider;\n output: {\n specPath: string;\n scalarDocs?: boolean;\n scalarPath?: string;\n scalarConfig?: Record<string, unknown>;\n };\n openapi: {\n title: string;\n version: string;\n description?: string;\n servers?: Array<{ url: string; description?: string }>;\n security: Array<{ [key: string]: string[] }>;\n components?: {\n securitySchemes?: {\n [key: string]: {\n type: string;\n in: string;\n name: string;\n };\n };\n };\n };\n jsdocMode?: JSDocMode;\n cache?: boolean;\n cacheDir?: string;\n include?: string[];\n exclude?: string[];\n /**\n * Path(s) to .env files to load before running. Defaults to ['.env', '.env.local'].\n * Set to false to disable automatic .env loading.\n */\n envFile?: string | string[] | false;\n /**\n * Safeguards for LLM usage per route analysis call.\n */\n limits?: {\n /**\n * Maximum number of output tokens per LLM call. Defaults to 4000.\n */\n maxTokens?: number;\n /**\n * Timeout in milliseconds per LLM call. Defaults to 60000 (60s).\n */\n timeoutMs?: number;\n };\n}\n\nexport interface ResolvedLimits {\n maxTokens: number;\n timeoutMs: number;\n}\n\nexport interface ResolvedConfig extends Omit<\n Required<OpenAPIGenConfig>,\n \"envFile\" | \"limits\"\n> {\n output: Required<OpenAPIGenConfig[\"output\"]>;\n openapi: Required<OpenAPIGenConfig[\"openapi\"]>;\n envFile: string[] | false;\n limits: ResolvedLimits;\n}\n\nconst defaults: Omit<ResolvedConfig, \"provider\" | \"output\" | \"openapi\"> = {\n jsdocMode: \"context\",\n cache: true,\n cacheDir: \".openapi-cache\",\n include: [\"src/app/api/**/route.ts\"],\n exclude: [],\n envFile: [\".env\", \".env.local\"],\n limits: {\n maxTokens: 4000,\n timeoutMs: 60_000,\n },\n};\n\nexport function resolveConfig(config: OpenAPIGenConfig): ResolvedConfig {\n let envFile: string[] | false;\n if (config.envFile === false) {\n envFile = false;\n } else if (typeof config.envFile === \"string\") {\n envFile = [config.envFile];\n } else {\n envFile = config.envFile ?? (defaults.envFile as string[]);\n }\n\n return {\n ...defaults,\n ...config,\n envFile,\n limits: {\n ...defaults.limits,\n ...config.limits,\n },\n output: {\n scalarDocs: false,\n scalarPath: \"src/app/api/docs/route.ts\",\n scalarConfig: {},\n ...config.output,\n },\n openapi: {\n description: \"\",\n servers: [],\n components: {},\n ...config.openapi,\n },\n };\n}\n\nexport async function loadConfig(configPath?: string): Promise<ResolvedConfig> {\n const searchPaths = configPath\n ? [configPath]\n : [\n \"openapi-gen.config.ts\",\n \"openapi-gen.config.js\",\n \"openapi-gen.config.mjs\",\n \"openapi-gen.config.cjs\",\n ];\n\n for (const p of searchPaths) {\n const abs = resolve(process.cwd(), p);\n if (existsSync(abs)) {\n const mod = await importConfig(abs);\n const config: OpenAPIGenConfig = mod.default ?? mod;\n return resolveConfig(config);\n }\n }\n\n throw new Error(\n \"No openapi-gen.config.ts found. Create one at your project root.\",\n );\n}\n\nasync function importConfig(\n filePath: string,\n): Promise<{ default?: OpenAPIGenConfig } & OpenAPIGenConfig> {\n // For .ts files, try to use tsx/ts-node if available, else fall back to require\n if (filePath.endsWith(\".ts\")) {\n return importTypeScriptConfig(filePath);\n }\n const url = pathToFileURL(filePath).href;\n return import(url);\n}\n\nasync function importTypeScriptConfig(\n filePath: string,\n): Promise<{ default?: OpenAPIGenConfig } & OpenAPIGenConfig> {\n // Use tsx (bundled as a dependency) to register CJS TypeScript hooks\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n require(\"tsx/cjs\");\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require(filePath);\n}\n","import { existsSync, mkdirSync, writeFileSync } from \"fs\";\nimport { dirname, join, resolve } from \"path\";\n\nimport type { AnalyzedRoute } from \"./analyzer.js\";\nimport type { ResolvedConfig } from \"./config.js\";\n\nexport interface OpenAPISpec {\n openapi: \"3.1.0\";\n info: {\n title: string;\n version: string;\n description?: string;\n };\n servers?: Array<{ url: string; description?: string }>;\n security?: Array<{ [key: string]: string[] }>;\n components?: {\n securitySchemes?: Record<string, unknown>;\n [key: string]: unknown;\n };\n paths: Record<string, unknown>;\n}\n\nexport function assembleSpec(\n config: ResolvedConfig,\n routes: AnalyzedRoute[],\n): OpenAPISpec {\n const paths: Record<string, unknown> = {};\n\n for (const route of routes) {\n if (Object.keys(route.pathItem).length > 0) {\n paths[route.urlPath] = route.pathItem;\n }\n }\n\n const spec: OpenAPISpec = {\n openapi: \"3.1.0\",\n info: {\n title: config.openapi.title,\n version: config.openapi.version,\n ...(config.openapi.description\n ? { description: config.openapi.description }\n : {}),\n },\n paths,\n };\n\n if (config.openapi.servers && config.openapi.servers.length > 0) {\n spec.servers = config.openapi.servers;\n }\n\n if (config.openapi.security && config.openapi.security.length > 0) {\n spec.security = config.openapi.security;\n }\n\n if (\n config.openapi.components &&\n Object.keys(config.openapi.components).length > 0\n ) {\n spec.components = config.openapi.components;\n }\n\n return spec;\n}\n\nexport function writeOutputFiles(\n config: ResolvedConfig,\n spec: OpenAPISpec,\n cwd: string = process.cwd(),\n): void {\n writeSpecFiles(config, spec, cwd);\n\n if (config.output.scalarDocs) {\n writeScalarRoute(config, cwd);\n }\n}\n\nfunction writeSpecFiles(\n config: ResolvedConfig,\n spec: OpenAPISpec,\n cwd: string,\n): void {\n const specRoutePath = resolve(cwd, config.output.specPath);\n const specDir = dirname(specRoutePath);\n\n ensureDir(specDir);\n\n // Write spec.json co-located with the route\n const specJsonPath = join(specDir, \"spec.json\");\n writeFileSync(specJsonPath, JSON.stringify(spec, null, 2), \"utf8\");\n\n // Write the Next.js route that serves the spec\n const routeContent = `import spec from './spec.json';\n\nexport const dynamic = 'force-static';\n\nexport function GET() {\n return Response.json(spec);\n}\n`;\n writeFileSync(specRoutePath, routeContent, \"utf8\");\n}\n\nfunction writeScalarRoute(config: ResolvedConfig, cwd: string): void {\n const scalarRoutePath = resolve(cwd, config.output.scalarPath);\n ensureDir(dirname(scalarRoutePath));\n\n // Derive the spec URL from the specPath\n const specUrl = filePathToApiUrl(config.output.specPath);\n\n const routeContent = `export const dynamic = 'force-static';\n\nexport function GET() {\n return new Response(\n \\`<!doctype html>\n<html>\n <head>\n <title>API Docs</title>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n </head>\n <body>\n <script\n id=\"api-reference\"\n data-url=\"${specUrl}\"\n ${config.output.scalarConfig && Object.keys(config.output.scalarConfig).length > 0 ? `data-config=\"${JSON.stringify(config.output.scalarConfig)}\"` : \"\"}\n ></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n </body>\n</html>\\`,\n { headers: { 'Content-Type': 'text/html' } }\n );\n}\n`;\n writeFileSync(scalarRoutePath, routeContent, \"utf8\");\n}\n\n/**\n * Convert a file path like src/app/api/openapi.json/route.ts to /api/openapi.json\n */\nfunction filePathToApiUrl(filePath: string): string {\n let path = filePath.replace(/\\\\/g, \"/\");\n path = path.replace(/^(src\\/)?app\\//, \"\");\n path = path.replace(/\\/route\\.(ts|tsx|js|jsx)$/, \"\");\n if (!path.startsWith(\"/\")) path = `/${path}`;\n return path;\n}\n\nfunction ensureDir(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n}\n","import { readFileSync } from \"fs\";\nimport { relative } from \"path\";\n\nexport interface RouteInfo {\n filePath: string;\n relativePath: string;\n urlPath: string;\n sourceCode: string;\n jsdocComments: string[];\n hasExactJsdoc: boolean;\n exactPathItem?: Record<string, unknown>;\n}\n\nexport async function scanRoutes(\n include: string[],\n exclude: string[],\n cwd: string = process.cwd(),\n): Promise<RouteInfo[]> {\n // Lazy import so that importing this module does not eagerly load fast-glob.\n // This keeps the module lightweight and allows Vitest to mock it cleanly.\n const { default: fg } = await import(\"fast-glob\");\n const files = await fg(include, {\n cwd,\n ignore: exclude,\n absolute: true,\n });\n\n return files.map((filePath) => parseRoute(filePath, cwd));\n}\n\nfunction parseRoute(filePath: string, cwd: string): RouteInfo {\n const relativePath = relative(cwd, filePath);\n const sourceCode = readFileSync(filePath, \"utf8\");\n const urlPath = filePathToUrlPath(relativePath);\n const { jsdocComments, hasExactJsdoc, exactPathItem } =\n extractJsdoc(sourceCode);\n\n return {\n filePath,\n relativePath,\n urlPath,\n sourceCode,\n jsdocComments,\n hasExactJsdoc,\n exactPathItem,\n };\n}\n\n/**\n * Convert a Next.js route file path to an OpenAPI URL path.\n * e.g. src/app/api/users/[id]/route.ts -> /api/users/{id}\n */\nexport function filePathToUrlPath(filePath: string): string {\n // Normalize separators\n let path = filePath.replace(/\\\\/g, \"/\");\n\n // Remove leading src/ or app/ prefixes\n path = path.replace(/^(src\\/)?app\\//, \"\");\n\n // Remove trailing /route.ts or /route.js\n path = path.replace(/\\/route\\.(ts|tsx|js|jsx)$/, \"\");\n\n // Convert Next.js dynamic segments [param] to OpenAPI {param}\n path = path.replace(/\\[([^\\]]+)\\]/g, (_, param) => {\n // Handle catch-all [...param] and optional [[...param]]\n if (param.startsWith(\"...\")) {\n return `{${param.slice(3)}}`;\n }\n return `{${param}}`;\n });\n\n // Ensure leading slash\n if (!path.startsWith(\"/\")) {\n path = `/${path}`;\n }\n\n return path;\n}\n\ninterface JsdocResult {\n jsdocComments: string[];\n hasExactJsdoc: boolean;\n exactPathItem?: Record<string, unknown>;\n}\n\nfunction extractJsdoc(sourceCode: string): JsdocResult {\n // Match all JSDoc comment blocks /** ... */\n const jsdocRegex = /\\/\\*\\*([\\s\\S]*?)\\*\\//g;\n const jsdocComments: string[] = [];\n let hasExactJsdoc = false;\n let exactPathItem: Record<string, unknown> | undefined;\n\n let match: RegExpExecArray | null;\n // biome-ignore lint/suspicious/noAssignInExpressions: required for while loop\n while ((match = jsdocRegex.exec(sourceCode)) !== null) {\n const comment = match[0];\n jsdocComments.push(comment);\n\n // Check for @openapi-exact tag\n if (/@openapi-exact/.test(comment)) {\n hasExactJsdoc = true;\n // Try to extract the JSON from @openapi tag\n const openapiMatch = comment.match(\n /@openapi\\s+([\\s\\S]*?)(?=\\s*\\*\\/|\\s*\\*\\s*@)/,\n );\n if (openapiMatch) {\n try {\n // Clean up JSDoc asterisks from the JSON\n const jsonStr = openapiMatch[1]\n .split(\"\\n\")\n .map((line) => line.replace(/^\\s*\\*\\s?/, \"\"))\n .join(\"\\n\")\n .trim();\n exactPathItem = JSON.parse(jsonStr);\n } catch {\n // If JSON parse fails, fall through to LLM\n hasExactJsdoc = false;\n }\n }\n }\n }\n\n return { jsdocComments, hasExactJsdoc, exactPathItem };\n}\n","export type {\n JSDocMode,\n OpenAPIGenConfig,\n Provider,\n ResolvedConfig,\n ResolvedLimits,\n} from \"./config.js\";\n\nexport { analyzeRoutes } from \"./analyzer.js\";\nexport { loadConfig, resolveConfig } from \"./config.js\";\nexport { assembleSpec, writeOutputFiles } from \"./generator.js\";\nexport { filePathToUrlPath, scanRoutes } from \"./scanner.js\";\n\nimport { resolve } from \"node:path\";\n\nimport type { OpenAPIGenConfig } from \"./config.js\";\n\nimport { analyzeRoutes } from \"./analyzer.js\";\nimport { loadConfig } from \"./config.js\";\nimport { assembleSpec, writeOutputFiles } from \"./generator.js\";\nimport { scanRoutes } from \"./scanner.js\";\n\nexport interface GenerateOptions {\n config?: string;\n provider?: OpenAPIGenConfig[\"provider\"];\n cache?: boolean;\n cwd?: string;\n}\n\nexport interface GenerateResult {\n routesAnalyzed: number;\n routesFromCache: number;\n routesSkippedLLM: number;\n specPath: string;\n}\n\nexport async function generate(\n options: GenerateOptions = {},\n): Promise<GenerateResult> {\n const cwd = options.cwd ?? process.cwd();\n const config = await loadConfig(options.config);\n\n // Allow CLI overrides\n if (options.provider) config.provider = options.provider;\n if (options.cache === false) config.cache = false;\n\n // Load .env files before provider env vars are read\n if (config.envFile !== false) {\n const { config: dotenvConfig } = await import(\"dotenv\");\n for (const file of config.envFile) {\n dotenvConfig({ path: resolve(cwd, file), override: false });\n }\n }\n\n console.log(`[openapi-ai-generator] Scanning routes...`);\n const routes = await scanRoutes(config.include, config.exclude, cwd);\n console.log(`[openapi-ai-generator] Found ${routes.length} route(s)`);\n\n console.log(\n `[openapi-ai-generator] Analyzing routes with provider: ${config.provider}`,\n );\n const analyzed = await analyzeRoutes(routes, {\n provider: config.provider,\n jsdocMode: config.jsdocMode,\n cache: config.cache,\n cacheDir: config.cacheDir,\n limits: config.limits,\n });\n\n const fromCache = analyzed.filter((r) => r.fromCache).length;\n const skippedLLM = analyzed.filter((r) => r.skippedLLM).length;\n console.log(\n `[openapi-ai-generator] ${analyzed.length} routes analyzed (${fromCache} from cache, ${skippedLLM - fromCache} exact JSDoc)`,\n );\n\n const spec = assembleSpec(config, analyzed);\n writeOutputFiles(config, spec, cwd);\n\n console.log(\n `[openapi-ai-generator] Spec written to ${config.output.specPath}`,\n );\n if (config.output.scalarDocs) {\n console.log(\n `[openapi-ai-generator] Scalar docs written to ${config.output.scalarPath}`,\n );\n }\n\n return {\n routesAnalyzed: analyzed.length,\n routesFromCache: fromCache,\n routesSkippedLLM: skippedLLM,\n specPath: config.output.specPath,\n };\n}\n","import type { GenerateOptions } from \"./index.js\";\n\ntype NextConfigLike = {\n generateBuildId?: unknown;\n};\n\n/**\n * Next.js config plugin that runs openapi-ai-generator before each build.\n * Compatible with both webpack and Turbopack (Next.js 16+).\n *\n * @example\n * // next.config.ts\n * import { withOpenAPIGen } from 'openapi-ai-generator/plugin';\n * export default withOpenAPIGen(nextConfig);\n */\nexport function withOpenAPIGen<T extends NextConfigLike>(\n nextConfig: T = {} as T,\n options: GenerateOptions = {},\n): T {\n const existingGenerateBuildId = nextConfig.generateBuildId as\n | (() => Promise<string | null>)\n | null\n | undefined;\n\n return {\n ...nextConfig,\n async generateBuildId(): Promise<string | null> {\n const { generate } = await import(\"./index.js\");\n await generate(options);\n return existingGenerateBuildId ? existingGenerateBuildId() : null;\n },\n } as T;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openapi-ai-generator",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Scan Next.js API routes and generate OpenAPI 3.1 specs using LLM analysis",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",