UNPKG

@kubb/cli

Version:

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

215 lines (209 loc) • 6.24 kB
import { defineCommand, showUsage } from "citty"; import path from "node:path"; import * as process$1 from "node:process"; import { PromiseManager, isInputPath } from "@kubb/core"; import { LogMapper, createLogger } from "@kubb/core/logger"; import pc from "picocolors"; import { isPromise } from "@kubb/core/utils"; import { cosmiconfig } from "cosmiconfig"; import { createJiti } from "jiti"; //#region 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); } //#endregion //#region src/utils/getConfig.ts /** * Converting UserConfig to Config without a change in the object beside the JSON convert. */ async function getConfig(result, args) { const config = result?.config; let kubbUserConfig = Promise.resolve(config); if (typeof config === "function") { const possiblePromise = config(args); 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; } //#endregion //#region src/utils/getCosmiConfig.ts const tsLoader = async (configFile) => { return await createJiti(import.meta.url, { jsx: { runtime: "automatic", importSource: "@kubb/react" }, sourceMaps: true }).import(configFile, { default: true }); }; 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; } //#endregion //#region src/utils/watcher.ts async function startWatcher(path$1, cb) { const { watch } = await import("chokidar"); const logger = createLogger(); watch(path$1, { ignorePermissionErrors: true, ignored: "**/{.git,node_modules}/**" }).on("all", (type, file) => { logger?.emit("info", pc.yellow(pc.bold(`Change detected: ${type} ${file}`))); try { cb(path$1); } catch (_e) { logger?.emit("warning", pc.red("Watcher failed")); } }); } //#endregion //#region src/commands/generate.ts const command = defineCommand({ meta: { name: "generate", description: "[input] Generate files based on a 'kubb.config.ts' file" }, 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 }, help: { type: "boolean", description: "Show help", alias: "h", default: false } }, async run(commandContext) { const progressCache = /* @__PURE__ */ new Map(); const { args } = commandContext; const input = args._[0]; if (args.help) return showUsage(command); if (args.debug) args.logLevel = "debug"; const logLevel = LogMapper[args.logLevel] || 3; const logger = createLogger({ logLevel }); const { generate } = await import("./generate-vHDmA5Mm.js"); logger.emit("start", "Loading config"); const result = await getCosmiConfig("kubb", args.config); logger.emit("success", `Config loaded(${pc.dim(path.relative(process$1.cwd(), result.filepath))})`); const config = await getConfig(result, args); const start = async () => { if (Array.isArray(config)) { const promiseManager = new PromiseManager(); const promises = config.map((c) => () => { progressCache.clear(); return generate({ input, config: c, args, progressCache }); }); await promiseManager.run("seq", promises); return; } progressCache.clear(); await generate({ input, config, progressCache, args }); }; if (args.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", pc.yellow(pc.bold(`Watching for changes in ${paths.join(" and ")}`))); }); } await start(); if (globalThis.isDevtoolsEnabled) if (await logger.consola?.prompt("Restart(could be used to validate the profiler)?", { type: "confirm", initial: false })) await start(); else process$1.exit(1); } }); var generate_default = command; //#endregion export { generate_default as default }; //# sourceMappingURL=generate-BqNABk2X.js.map