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