UNPKG

@kubb/plugin-oas

Version:
155 lines (133 loc) 4.22 kB
import { FileManager, type Group, createPlugin } from '@kubb/core' import { parseFromConfig } from './utils/parseFromConfig.ts' import path from 'node:path' import type { Config } from '@kubb/core' import type { Logger } from '@kubb/core/logger' import { camelCase } from '@kubb/core/transformers' import type { Oas } from '@kubb/oas' import { OperationGenerator } from './OperationGenerator.ts' import { SchemaGenerator } from './SchemaGenerator.ts' import { jsonGenerator } from './generators' import type { PluginOas } from './types.ts' export const pluginOasName = 'plugin-oas' satisfies PluginOas['name'] export const pluginOas = createPlugin<PluginOas>((options) => { const { output = { path: 'schemas', }, group, validate = true, generators = [jsonGenerator], serverIndex, contentType, oasClass, } = options const getOas = async ({ config, logger }: { config: Config; logger: Logger }): Promise<Oas> => { try { // 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) if (validate) { await oas.valdiate() } return oas } catch (e) { const error = e as Error logger.emit('warning', error?.message) return parseFromConfig(config, oasClass) } } return { name: pluginOasName, options: { output, ...options, }, context() { const { config, logger } = this return { getOas() { return getOas({ config, logger }) }, async getBaseURL() { const oasInstance = await this.getOas() if (serverIndex) { return oasInstance.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 ?? FileManager.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 buildStart() { if (!output) { return } const oas = await getOas({ config: this.config, logger: this.logger, }) await oas.dereference() const schemaGenerator = new SchemaGenerator( { unknownType: 'unknown', dateType: 'date', transformers: {}, ...this.plugin.options, }, { 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.addFile(...schemaFiles) const operationGenerator = new OperationGenerator(this.plugin.options, { oas, pluginManager: this.pluginManager, plugin: this.plugin, contentType, exclude: undefined, include: undefined, override: undefined, mode: 'split', }) const operationFiles = await operationGenerator.build(...generators) await this.addFile(...operationFiles) }, } })