@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
JavaScript
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