@kubb/cli
Version:
Command-line interface for Kubb, enabling easy generation of TypeScript, React-Query, Zod, and other code from OpenAPI specifications.
209 lines (203 loc) • 7.24 kB
JavaScript
import * as process3 from 'process';
import process3__default from 'process';
import { setup, safeBuild } from '@kubb/core';
import { LogMapper, createLogger, randomCliColour } from '@kubb/core/logger';
import { SingleBar, Presets } from 'cli-progress';
import { colors } from 'consola/utils';
import { execa } from 'execa';
import { parseArgsStringToArgv } from 'string-argv';
import { Writable } from 'stream';
import path from 'path';
// src/runners/generate.ts
var ConsolaWritable = class extends Writable {
consola;
command;
constructor(consola, command, opts) {
super(opts);
this.command = command;
this.consola = consola;
}
_write(chunk, _encoding, callback) {
process3.stdout.write(`${colors.dim(chunk?.toString())}`);
callback();
}
};
async function executeHooks({ hooks, logger }) {
const commands = Array.isArray(hooks.done) ? hooks.done : [hooks.done].filter(Boolean);
for (const command of commands) {
const consolaWritable = new ConsolaWritable(logger.consola, command);
const [cmd, ..._args] = [...parseArgsStringToArgv(command)];
if (!cmd) {
continue;
}
logger?.emit("start", `Executing hook ${logger.logLevel !== LogMapper.silent ? colors.dim(command) : ""}`);
await execa(cmd, _args, {
detached: true,
stdout: logger?.logLevel === LogMapper.silent ? void 0 : ["pipe", consolaWritable],
stripFinalNewline: true
});
logger?.emit("success", `Executed hook ${logger.logLevel !== LogMapper.silent ? colors.dim(command) : ""}`);
}
logger?.emit("success", "Executed hooks");
}
// src/utils/getErrorCauses.ts
function getErrorCauses(errors) {
return errors.reduce((prev, error) => {
const causedError = error?.cause;
if (causedError) {
prev = [...prev, ...getErrorCauses([causedError])];
return prev;
}
prev = [...prev, error];
return prev;
}, []).filter(Boolean);
}
// src/utils/parseHrtimeToSeconds.ts
function parseHrtimeToSeconds(hrtime) {
const seconds = (hrtime[0] + hrtime[1] / 1e9).toFixed(3);
return seconds;
}
// src/utils/getSummary.ts
function getSummary({ pluginManager, filesCreated, status, hrStart, config }) {
const logs = /* @__PURE__ */ new Set();
const elapsedSeconds = parseHrtimeToSeconds(process.hrtime(hrStart));
const buildStartPlugins = pluginManager.executed.filter((item) => item.hookName === "buildStart" && item.plugin.name !== "core").map((item) => item.plugin.name);
const buildEndPlugins = pluginManager.executed.filter((item) => item.hookName === "buildEnd" && item.plugin.name !== "core").map((item) => item.plugin.name);
const failedPlugins = config.plugins?.filter((plugin) => !buildEndPlugins.includes(plugin.name))?.map((plugin) => plugin.name);
const pluginsCount = config.plugins?.length || 0;
const meta = {
plugins: status === "success" ? `${colors.green(`${buildStartPlugins.length} successful`)}, ${pluginsCount} total` : `${colors.red(`${failedPlugins?.length ?? 1} failed`)}, ${pluginsCount} total`,
pluginsFailed: status === "failed" ? failedPlugins?.map((name) => randomCliColour(name))?.join(", ") : void 0,
filesCreated,
time: `${colors.yellow(`${elapsedSeconds}s`)}`,
output: path.isAbsolute(config.root) ? path.resolve(config.root, config.output.path) : config.root
};
logs.add(
[
[`${colors.bold("Plugins:")} ${meta.plugins}`, true],
[`${colors.dim("Failed:")} ${meta.pluginsFailed || "none"}`, !!meta.pluginsFailed],
[`${colors.bold("Generated:")} ${meta.filesCreated} files in ${meta.time}`, true],
[`${colors.bold("Output:")} ${meta.output}`, true]
].map((item) => {
if (item.at(1)) {
return item.at(0);
}
return void 0;
}).filter(Boolean).join("\n")
);
return [...logs];
}
// src/runners/generate.ts
async function generate({ input, config, progressCache, args }) {
const hrStart = process3__default.hrtime();
const logLevel = LogMapper[args.logLevel] || 3;
const logger = createLogger({
logLevel,
name: config.name
});
const { root = process3__default.cwd(), ...userConfig } = config;
const inputPath = input ?? ("path" in userConfig.input ? userConfig.input.path : void 0);
if (logger.logLevel !== LogMapper.debug) {
logger.on("progress_start", ({ id, size, message = "" }) => {
logger.consola?.pauseLogs();
const payload = { id, message };
const progressBar = new SingleBar(
{
format: "{percentage}% {bar} {value}/{total} | {message}",
barsize: 30,
clearOnComplete: true,
emptyOnZero: true
},
Presets.shades_grey
);
if (!progressCache.has(id)) {
progressCache.set(id, progressBar);
progressBar.start(size, 1, payload);
}
});
logger.on("progress_stop", ({ id }) => {
progressCache.get(id)?.stop();
logger.consola?.resumeLogs();
});
logger.on("progressed", ({ id, message = "" }) => {
const payload = { id, message };
progressCache.get(id)?.increment(1, payload);
});
}
const definedConfig = {
root,
...userConfig,
input: inputPath ? {
...userConfig.input,
path: inputPath
} : userConfig.input,
output: {
write: true,
barrelType: "named",
extension: {
".ts": ".ts"
},
...userConfig.output
}
};
const pluginManager = await setup({
config: definedConfig,
logger
});
logger.emit("start", `Building ${logger.logLevel !== LogMapper.silent ? colors.dim(inputPath) : ""}`);
const { files, error } = await safeBuild({
config: definedConfig,
pluginManager,
logger
});
if (logger.logLevel === LogMapper.debug) {
logger.consola?.start("Writing logs");
const logFiles = await logger.writeLogs();
logger.consola?.success(`Written logs:
${logFiles.join("\n")}`);
}
const summary = getSummary({
filesCreated: files.length,
pluginManager,
config: definedConfig,
status: error ? "failed" : "success",
hrStart
});
if (error && logger.consola) {
logger.consola?.resumeLogs();
logger.consola.error(`Build failed ${logger.logLevel !== LogMapper.silent ? colors.dim(inputPath) : ""}`);
logger.consola.box({
title: `${config.name || ""}`,
message: summary.join(""),
style: {
padding: 2,
borderColor: "red",
borderStyle: "rounded"
}
});
const errors = getErrorCauses([error]);
if (logger.consola && errors.length && logger.logLevel === LogMapper.debug) {
errors.forEach((err) => {
logger.consola?.error(err);
});
}
logger.consola?.error(error);
process3__default.exit(1);
}
if (config.hooks) {
await executeHooks({ hooks: config.hooks, logger });
}
logger.consola?.log(`\u26A1Build completed ${logger.logLevel !== LogMapper.silent ? colors.dim(inputPath) : ""}`);
logger.consola?.box({
title: `${config.name || ""}`,
message: summary.join(""),
style: {
padding: 2,
borderColor: "green",
borderStyle: "rounded"
}
});
}
export { generate };
//# sourceMappingURL=generate-HUWFJ4IA.js.map
//# sourceMappingURL=generate-HUWFJ4IA.js.map