UNPKG

@kubb/plugin-oas

Version:

OpenAPI Specification (OAS) plugin for Kubb, providing core functionality for parsing and processing OpenAPI/Swagger schemas for code generation.

163 lines (141 loc) 4.26 kB
import path from 'node:path' import { type Config, definePlugin, type Group, getMode } from '@kubb/core' import { camelCase } from '@kubb/core/transformers' import type { Oas } from '@kubb/oas' import { parseFromConfig } from '@kubb/oas' import { jsonGenerator } from './generators' import { OperationGenerator } from './OperationGenerator.ts' import { SchemaGenerator } from './SchemaGenerator.ts' import type { PluginOas } from './types.ts' export const pluginOasName = 'plugin-oas' satisfies PluginOas['name'] export const pluginOas = definePlugin<PluginOas>((options) => { const { output = { path: 'schemas', }, group, validate = true, generators = [jsonGenerator], serverIndex, contentType, oasClass, discriminator = 'strict', } = options const getOas = async ({ config }: { config: Config }): Promise<Oas> => { // needs to be in a different variable or the catch here will not work(return of a promise instead) const oas = await parseFromConfig(config, oasClass) oas.setOptions({ contentType, discriminator, }) try { if (validate) { await oas.valdiate() } } catch (e) { const error = e as Error console.warn(error?.message) } return oas } return { name: pluginOasName, options: { output, validate, discriminator, ...options, }, inject() { const config = this.config let oas: Oas return { async getOas() { if (!oas) { oas = await getOas({ config }) } return oas }, async getBaseURL() { const oas = await getOas({ config }) if (serverIndex) { return oas.api.servers?.at(serverIndex)?.url } return undefined }, } }, resolvePath(baseName, pathMode, options) { const root = path.resolve(this.config.root, this.config.output.path) const mode = pathMode ?? getMode(path.resolve(root, output.path)) if (mode === 'single') { /** * when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend * Other plugins then need to call addOrAppend instead of just add from the fileManager class */ return path.resolve(root, output.path) } if (group && (options?.group?.path || options?.group?.tag)) { const groupName: Group['name'] = group?.name ? group.name : (ctx) => { if (group?.type === 'path') { return `${ctx.group.split('/')[1]}` } return `${camelCase(ctx.group)}Controller` } return path.resolve( root, output.path, groupName({ group: group.type === 'path' ? options.group.path! : options.group.tag!, }), baseName, ) } return path.resolve(root, output.path, baseName) }, async install() { if (!output) { return } const oas = await this.getOas() await oas.dereference() const schemaGenerator = new SchemaGenerator( { unknownType: 'unknown', emptySchemaType: 'unknown', dateType: 'date', transformers: {}, ...this.plugin.options, }, { fabric: this.fabric, oas, pluginManager: this.pluginManager, plugin: this.plugin, contentType, include: undefined, override: undefined, mode: 'split', output: output.path, }, ) const schemaFiles = await schemaGenerator.build(...generators) await this.upsertFile(...schemaFiles) const operationGenerator = new OperationGenerator(this.plugin.options, { fabric: this.fabric, oas, pluginManager: this.pluginManager, plugin: this.plugin, contentType, exclude: undefined, include: undefined, override: undefined, mode: 'split', }) const operationFiles = await operationGenerator.build(...generators) await this.upsertFile(...operationFiles) }, } })