UNPKG

@kubb/cli

Version:

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

273 lines (269 loc) • 7.72 kB
import { defineCommand, showUsage } from 'citty'; import { colors } from 'consola/utils'; import { isPromise } from '@kubb/core/utils'; import { cosmiconfig } from 'cosmiconfig'; import { createJiti } from 'jiti'; import { LogMapper, createLogger } from '@kubb/core/logger'; import path from 'path'; import * as process from 'process'; import { isInputPath, PromiseManager } from '@kubb/core'; import open from 'open'; // src/commands/generate.ts // src/utils/getPlugins.ts function isJSONPlugins(plugins) { return !!plugins?.some((plugin) => { return Array.isArray(plugin) && typeof plugin?.at(0) === "string"; }); } function isObjectPlugins(plugins) { return plugins instanceof Object && !Array.isArray(plugins); } function getPlugins(plugins) { if (isObjectPlugins(plugins)) { throw new Error("Object plugins are not supported anymore, best to use http://kubb.dev/getting-started/configure#json"); } if (isJSONPlugins(plugins)) { throw new Error("JSON plugins are not supported anymore, best to use http://kubb.dev/getting-started/configure#json"); } return Promise.resolve(plugins); } // src/utils/getConfig.ts async function getConfig(result, args2) { const config = result?.config; let kubbUserConfig = Promise.resolve(config); if (typeof config === "function") { const possiblePromise = config(args2); if (isPromise(possiblePromise)) { kubbUserConfig = possiblePromise; } kubbUserConfig = Promise.resolve(possiblePromise); } let JSONConfig = await kubbUserConfig; if (Array.isArray(JSONConfig)) { const results = []; for (const item of JSONConfig) { const plugins = item.plugins ? await getPlugins(item.plugins) : void 0; results.push({ ...item, plugins }); } return results; } JSONConfig = { ...JSONConfig, plugins: JSONConfig.plugins ? await getPlugins(JSONConfig.plugins) : void 0 }; return JSONConfig; } var tsLoader = async (configFile) => { const jiti = createJiti(import.meta.url, { jsx: { runtime: "automatic", importSource: "@kubb/react" }, sourceMaps: true }); const mod = await jiti.import(configFile, { default: true }); return mod; }; async function getCosmiConfig(moduleName, config) { const searchPlaces = [ "package.json", `.${moduleName}rc`, `.${moduleName}rc.json`, `.${moduleName}rc.yaml`, `.${moduleName}rc.yml`, `.${moduleName}rc.ts`, `.${moduleName}rc.js`, `.${moduleName}rc.mjs`, `.${moduleName}rc.cjs`, `${moduleName}.config.ts`, `${moduleName}.config.js`, `${moduleName}.config.mjs`, `${moduleName}.config.cjs` ]; const explorer = cosmiconfig(moduleName, { cache: false, searchPlaces: [ ...searchPlaces.map((searchPlace) => { return `.config/${searchPlace}`; }), ...searchPlaces.map((searchPlace) => { return `configs/${searchPlace}`; }), ...searchPlaces ], loaders: { ".ts": tsLoader } }); const result = config ? await explorer.load(config) : await explorer.search(); if (result?.isEmpty || !result || !result.config) { throw new Error("Config not defined, create a kubb.config.js or pass through your config with the option --config"); } return result; } async function startWatcher(path2, cb) { const { watch } = await import('chokidar'); const logger = createLogger(); const ignored = "**/{.git,node_modules}/**"; const watcher = watch(path2, { ignorePermissionErrors: true, ignored }); watcher.on("all", (type, file) => { logger?.emit("info", colors.yellow(colors.bold(`Change detected: ${type} ${file}`))); try { cb(path2); } catch (_e) { logger?.emit("warning", colors.red("Watcher failed")); } }); } var args = { config: { type: "string", description: "Path to the Kubb config", alias: "c" }, logLevel: { type: "string", description: "Info, silent or debug", alias: "l", default: "info", valueHint: "silent|info|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 }, ui: { type: "boolean", description: "Open ui", alias: "u", default: false }, help: { type: "boolean", description: "Show help", alias: "h", default: false } }; var command = defineCommand({ meta: { name: "generate", description: "[input] Generate files based on a 'kubb.config.ts' file" }, args, async run(commandContext) { let name = ""; const progressCache = /* @__PURE__ */ new Map(); const { args: args2 } = commandContext; const input = args2._[0]; if (args2.help) { return showUsage(command); } if (args2.debug) { args2.logLevel = "debug"; } const logLevel = LogMapper[args2.logLevel] || 3; const logger = createLogger({ logLevel }); const { generate } = await import('./generate-HUWFJ4IA.js'); logger.emit("start", "Loading config"); const result = await getCosmiConfig("kubb", args2.config); logger.emit("success", `Config loaded(${colors.dim(path.relative(process.cwd(), result.filepath))})`); const config = await getConfig(result, args2); const start = async () => { if (Array.isArray(config)) { const promiseManager = new PromiseManager(); const promises = config.map((c) => () => { name = c.name || ""; progressCache.clear(); return generate({ input, config: c, args: args2, progressCache }); }); await promiseManager.run("seq", promises); return; } progressCache.clear(); await generate({ input, config, progressCache, args: args2 }); return; }; if (args2.ui) { const { startServer } = await import('@kubb/ui'); await startServer( { stop: () => process.exit(1), restart: () => start(), getMeta: () => { const entries = [...progressCache.entries()]; const percentages = entries.reduce( (acc, [key, singleBar]) => { acc[key] = singleBar.getProgress(); return acc; }, {} ); return { name, percentages }; } }, (info) => { const url = `${info.address}:${info.port}`.replace("::", "http://localhost"); logger.consola?.start(`Starting ui on ${url}`); open(url); } ); } if (args2.watch) { if (Array.isArray(config)) { throw new Error("Cannot use watcher with multiple Configs(array)"); } if (isInputPath(config)) { return startWatcher([input || config.input.path], async (paths) => { await start(); logger.emit("start", colors.yellow(colors.bold(`Watching for changes in ${paths.join(" and ")}`))); }); } } await start(); if (globalThis.isDevtoolsEnabled) { const canRestart = await logger.consola?.prompt("Restart(could be used to validate the profiler)?", { type: "confirm", initial: false }); if (canRestart) { await start(); } else { process.exit(1); } } } }); var generate_default = command; export { generate_default as default }; //# sourceMappingURL=generate-65TMSGIL.js.map //# sourceMappingURL=generate-65TMSGIL.js.map