UNPKG

@kubb/cli

Version:

Command-line interface for Kubb, enabling easy generation of TypeScript, React-Query, Zod, and other code from OpenAPI specifications.

158 lines (134 loc) 4.17 kB
import path from 'node:path' import * as process from 'node:process' import { styleText } from 'node:util' import * as clack from '@clack/prompts' import { type CLIOptions, isInputPath, type KubbEvents, LogLevel, PromiseManager } from '@kubb/core' import { AsyncEventEmitter, executeIfOnline, getConfigs } from '@kubb/core/utils' import type { ArgsDef, ParsedArgs } from 'citty' import { defineCommand, showUsage } from 'citty' import { version } from '../../package.json' import { setupLogger } from '../loggers/utils.ts' import { generate } from '../runners/generate.ts' import { getCosmiConfig } from '../utils/getCosmiConfig.ts' import { startWatcher } from '../utils/watcher.ts' const args = { config: { type: 'string', description: 'Path to the Kubb config', alias: 'c', }, logLevel: { type: 'string', description: 'Info, silent, verbose or debug', alias: 'l', default: 'info', valueHint: 'silent|info|verbose|debug', }, watch: { type: 'boolean', description: 'Watch mode based on the input file', alias: 'w', default: false, }, debug: { type: 'boolean', description: 'Override logLevel to debug', alias: 'd', default: false, }, verbose: { type: 'boolean', description: 'Override logLevel to verbose', alias: 'v', default: false, }, silent: { type: 'boolean', description: 'Override logLevel to silent', alias: 's', default: false, }, help: { type: 'boolean', description: 'Show help', alias: 'h', default: false, }, } as const satisfies ArgsDef export type Args = ParsedArgs<typeof args> const command = defineCommand({ meta: { name: 'generate', description: "[input] Generate files based on a 'kubb.config.ts' file", }, args, async run(commandContext) { const { args } = commandContext const input = args._[0] const events = new AsyncEventEmitter<KubbEvents>() const promiseManager = new PromiseManager() if (args.help) { return showUsage(command) } if (args.debug) { args.logLevel = 'debug' } if (args.verbose) { args.logLevel = 'verbose' } if (args.silent) { args.logLevel = 'silent' } const logLevel = LogLevel[args.logLevel as keyof typeof LogLevel] || 3 await setupLogger(events, { logLevel }) await executeIfOnline(async () => { try { const res = await fetch('https://registry.npmjs.org/@kubb/cli/latest') const data = (await res.json()) as { version: string } const latestVersion = data.version if (latestVersion && version < latestVersion) { await events.emit('version:new', version, latestVersion) } } catch { // Ignore network errors for version check } }) try { const result = await getCosmiConfig('kubb', args.config) const configs = await getConfigs(result.config, args as CLIOptions) await events.emit('config:start') await events.emit('info', 'Config loaded', path.relative(process.cwd(), result.filepath)) await events.emit('success', 'Config loaded successfully', path.relative(process.cwd(), result.filepath)) await events.emit('config:end', configs) await events.emit('lifecycle:start', version) const promises = configs.map((config) => { return async () => { if (isInputPath(config) && args.watch) { await startWatcher([input || config.input.path], async (paths) => { await generate({ input, config, logLevel, events, }) clack.log.step(styleText('yellow', `Watching for changes in ${paths.join(' and ')}`)) }) return } await generate({ input, config, logLevel, events, }) } }) await promiseManager.run('seq', promises) await events.emit('lifecycle:end') } catch (error) { await events.emit('error', error as Error) process.exit(1) } }, }) export default command