Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@kubb/cli

Package Overview
Dependencies
Maintainers
1
Versions
1277
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@kubb/cli - npm Package Compare versions

Comparing version
4.37.7
to
4.37.8
+56
dist/agent-BBrW4jlM.js
import "./chunk--u3MIqq1.js";
import { n as defineCommand } from "./define--M_JMcDC.js";
import { t as version } from "./package-7k6Ul15n.js";
import { a as agentDefaults } from "./constants-CM3dJzjK.js";
//#endregion
//#region src/commands/agent.ts
const command = defineCommand({
name: "agent",
description: "Manage the Kubb Agent server",
subCommands: [defineCommand({
name: "start",
description: "Start the Agent server",
options: {
config: {
type: "string",
description: "Path to the Kubb config",
short: "c"
},
port: {
type: "string",
description: `Port for the server (default: ${agentDefaults.port})`,
short: "p"
},
host: {
type: "string",
description: "Host for the server",
default: agentDefaults.host
},
"allow-write": {
type: "boolean",
description: "Allow writing generated files to the filesystem. When not set, no files are written and the config patch is not persisted.",
default: false
},
"allow-all": {
type: "boolean",
description: "Grant all permissions (implies --allow-write).",
default: false
}
},
async run({ values }) {
const { runAgentStart } = await import("./agent-fcClds-t.js");
await runAgentStart({
port: values.port !== void 0 ? values.port : void 0,
host: values.host,
configPath: values.config,
allowWrite: values["allow-write"],
allowAll: values["allow-all"],
version
});
}
})]
});
//#endregion
export { command };
//# sourceMappingURL=agent-BBrW4jlM.js.map
{"version":3,"file":"agent-BBrW4jlM.js","names":["command","startCommand"],"sources":["../src/commands/agent/start.ts","../src/commands/agent.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../../package.json'\nimport { agentDefaults } from '../../constants.ts'\n\nexport const command = defineCommand({\n name: 'start',\n description: 'Start the Agent server',\n options: {\n config: { type: 'string', description: 'Path to the Kubb config', short: 'c' },\n port: { type: 'string', description: `Port for the server (default: ${agentDefaults.port})`, short: 'p' },\n host: { type: 'string', description: 'Host for the server', default: agentDefaults.host },\n 'allow-write': {\n type: 'boolean',\n description: 'Allow writing generated files to the filesystem. When not set, no files are written and the config patch is not persisted.',\n default: false,\n },\n 'allow-all': { type: 'boolean', description: 'Grant all permissions (implies --allow-write).', default: false },\n },\n async run({ values }) {\n const { runAgentStart } = await import('../../runners/agent.ts')\n\n await runAgentStart({\n port: values.port !== undefined ? values.port : undefined,\n host: values.host,\n configPath: values.config,\n allowWrite: values['allow-write'],\n allowAll: values['allow-all'],\n version,\n })\n },\n})\n","import { defineCommand } from '@internals/utils'\nimport { command as startCommand } from './agent/start.ts'\n\nexport const command = defineCommand({\n name: 'agent',\n description: 'Manage the Kubb Agent server',\n subCommands: [startCommand],\n})\n"],"mappings":";;;;;;ACGA,MAAa,UAAU,cAAc;CACnC,MAAM;CACN,aAAa;CACb,aAAa,CDFQ,cAAc;EACnC,MAAM;EACN,aAAa;EACb,SAAS;GACP,QAAQ;IAAE,MAAM;IAAU,aAAa;IAA2B,OAAO;IAAK;GAC9E,MAAM;IAAE,MAAM;IAAU,aAAa,iCAAiC,cAAc,KAAK;IAAI,OAAO;IAAK;GACzG,MAAM;IAAE,MAAM;IAAU,aAAa;IAAuB,SAAS,cAAc;IAAM;GACzF,eAAe;IACb,MAAM;IACN,aAAa;IACb,SAAS;IACV;GACD,aAAa;IAAE,MAAM;IAAW,aAAa;IAAkD,SAAS;IAAO;GAChH;EACD,MAAM,IAAI,EAAE,UAAU;GACpB,MAAM,EAAE,kBAAkB,MAAM,OAAO;AAEvC,SAAM,cAAc;IAClB,MAAM,OAAO,SAAS,KAAA,IAAY,OAAO,OAAO,KAAA;IAChD,MAAM,OAAO;IACb,YAAY,OAAO;IACnB,YAAY,OAAO;IACnB,UAAU,OAAO;IACjB;IACD,CAAC;;EAEL,CAAC,CCxB2B;CAC5B,CAAC"}
require("./chunk-ByKO4r7w.cjs");
const require_define = require("./define-D6Kfm7-Z.cjs");
const require_package = require("./package-m-LvDtUC.cjs");
const require_constants = require("./constants-BTUap0zs.cjs");
//#region src/commands/agent/start.ts
const command$1 = require_define.defineCommand({
name: "start",
description: "Start the Agent server",
options: {
config: {
type: "string",
description: "Path to the Kubb config",
short: "c"
},
port: {
type: "string",
description: `Port for the server (default: ${require_constants.agentDefaults.port})`,
short: "p"
},
host: {
type: "string",
description: "Host for the server",
default: require_constants.agentDefaults.host
},
"allow-write": {
type: "boolean",
description: "Allow writing generated files to the filesystem. When not set, no files are written and the config patch is not persisted.",
default: false
},
"allow-all": {
type: "boolean",
description: "Grant all permissions (implies --allow-write).",
default: false
}
},
async run({ values }) {
const { runAgentStart } = await Promise.resolve().then(() => require("./agent-bJ5FNFnA.cjs"));
await runAgentStart({
port: values.port !== void 0 ? values.port : void 0,
host: values.host,
configPath: values.config,
allowWrite: values["allow-write"],
allowAll: values["allow-all"],
version: require_package.version
});
}
});
//#endregion
//#region src/commands/agent.ts
const command = require_define.defineCommand({
name: "agent",
description: "Manage the Kubb Agent server",
subCommands: [command$1]
});
//#endregion
exports.command = command;
//# sourceMappingURL=agent-DMy_bQ-M.cjs.map
{"version":3,"file":"agent-DMy_bQ-M.cjs","names":["command","defineCommand","agentDefaults","defineCommand","startCommand"],"sources":["../src/commands/agent/start.ts","../src/commands/agent.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../../package.json'\nimport { agentDefaults } from '../../constants.ts'\n\nexport const command = defineCommand({\n name: 'start',\n description: 'Start the Agent server',\n options: {\n config: { type: 'string', description: 'Path to the Kubb config', short: 'c' },\n port: { type: 'string', description: `Port for the server (default: ${agentDefaults.port})`, short: 'p' },\n host: { type: 'string', description: 'Host for the server', default: agentDefaults.host },\n 'allow-write': {\n type: 'boolean',\n description: 'Allow writing generated files to the filesystem. When not set, no files are written and the config patch is not persisted.',\n default: false,\n },\n 'allow-all': { type: 'boolean', description: 'Grant all permissions (implies --allow-write).', default: false },\n },\n async run({ values }) {\n const { runAgentStart } = await import('../../runners/agent.ts')\n\n await runAgentStart({\n port: values.port !== undefined ? values.port : undefined,\n host: values.host,\n configPath: values.config,\n allowWrite: values['allow-write'],\n allowAll: values['allow-all'],\n version,\n })\n },\n})\n","import { defineCommand } from '@internals/utils'\nimport { command as startCommand } from './agent/start.ts'\n\nexport const command = defineCommand({\n name: 'agent',\n description: 'Manage the Kubb Agent server',\n subCommands: [startCommand],\n})\n"],"mappings":";;;;;AAIA,MAAaA,YAAUC,eAAAA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,SAAS;EACP,QAAQ;GAAE,MAAM;GAAU,aAAa;GAA2B,OAAO;GAAK;EAC9E,MAAM;GAAE,MAAM;GAAU,aAAa,iCAAiCC,kBAAAA,cAAc,KAAK;GAAI,OAAO;GAAK;EACzG,MAAM;GAAE,MAAM;GAAU,aAAa;GAAuB,SAASA,kBAAAA,cAAc;GAAM;EACzF,eAAe;GACb,MAAM;GACN,aAAa;GACb,SAAS;GACV;EACD,aAAa;GAAE,MAAM;GAAW,aAAa;GAAkD,SAAS;GAAO;EAChH;CACD,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,kBAAkB,MAAA,QAAA,SAAA,CAAA,WAAA,QAAM,uBAAA,CAAA;AAEhC,QAAM,cAAc;GAClB,MAAM,OAAO,SAAS,KAAA,IAAY,OAAO,OAAO,KAAA;GAChD,MAAM,OAAO;GACb,YAAY,OAAO;GACnB,YAAY,OAAO;GACnB,UAAU,OAAO;GACjB,SAAA,gBAAA;GACD,CAAC;;CAEL,CAAC;;;AC3BF,MAAa,UAAUC,eAAAA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,aAAa,CAACC,UAAa;CAC5B,CAAC"}
require("./chunk-ByKO4r7w.cjs");
//#region src/commands/generate.ts
const command = require("./define-D6Kfm7-Z.cjs").defineCommand({
name: "generate",
description: "[input] Generate files based on a 'kubb.config.ts' file",
arguments: ["[input]"],
options: {
config: {
type: "string",
description: "Path to the Kubb config",
short: "c"
},
logLevel: {
type: "string",
description: "Info, silent, verbose or debug",
short: "l",
default: "info",
hint: "silent|info|verbose|debug",
enum: [
"silent",
"info",
"verbose",
"debug"
]
},
watch: {
type: "boolean",
description: "Watch mode based on the input file",
short: "w",
default: false
},
debug: {
type: "boolean",
description: "Override logLevel to debug",
short: "d",
default: false
},
verbose: {
type: "boolean",
description: "Override logLevel to verbose",
short: "v",
default: false
},
silent: {
type: "boolean",
description: "Override logLevel to silent",
short: "s",
default: false
}
},
async run({ values, positionals }) {
const logLevel = values.debug ? "debug" : values.verbose ? "verbose" : values.silent ? "silent" : values.logLevel;
const { runGenerateCommand } = await Promise.resolve().then(() => require("./generate-DyK2S7hv.cjs"));
await runGenerateCommand({
input: positionals[0],
configPath: values.config,
logLevel,
watch: values.watch
});
}
});
//#endregion
exports.command = command;
//# sourceMappingURL=generate-CkyN7qeb.cjs.map
{"version":3,"file":"generate-CkyN7qeb.cjs","names":["defineCommand"],"sources":["../src/commands/generate.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\n\nexport const command = defineCommand({\n name: 'generate',\n description: \"[input] Generate files based on a 'kubb.config.ts' file\",\n arguments: ['[input]'],\n options: {\n config: { type: 'string', description: 'Path to the Kubb config', short: 'c' },\n logLevel: {\n type: 'string',\n description: 'Info, silent, verbose or debug',\n short: 'l',\n default: 'info',\n hint: 'silent|info|verbose|debug',\n enum: ['silent', 'info', 'verbose', 'debug'],\n },\n watch: { type: 'boolean', description: 'Watch mode based on the input file', short: 'w', default: false },\n debug: { type: 'boolean', description: 'Override logLevel to debug', short: 'd', default: false },\n verbose: { type: 'boolean', description: 'Override logLevel to verbose', short: 'v', default: false },\n silent: { type: 'boolean', description: 'Override logLevel to silent', short: 's', default: false },\n },\n async run({ values, positionals }) {\n const logLevel = values.debug ? 'debug' : values.verbose ? 'verbose' : values.silent ? 'silent' : values.logLevel\n const { runGenerateCommand } = await import('../runners/generate.ts')\n\n await runGenerateCommand({ input: positionals[0], configPath: values.config, logLevel, watch: values.watch })\n },\n})\n"],"mappings":";;AAEA,MAAa,2CAAUA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,WAAW,CAAC,UAAU;CACtB,SAAS;EACP,QAAQ;GAAE,MAAM;GAAU,aAAa;GAA2B,OAAO;GAAK;EAC9E,UAAU;GACR,MAAM;GACN,aAAa;GACb,OAAO;GACP,SAAS;GACT,MAAM;GACN,MAAM;IAAC;IAAU;IAAQ;IAAW;IAAQ;GAC7C;EACD,OAAO;GAAE,MAAM;GAAW,aAAa;GAAsC,OAAO;GAAK,SAAS;GAAO;EACzG,OAAO;GAAE,MAAM;GAAW,aAAa;GAA8B,OAAO;GAAK,SAAS;GAAO;EACjG,SAAS;GAAE,MAAM;GAAW,aAAa;GAAgC,OAAO;GAAK,SAAS;GAAO;EACrG,QAAQ;GAAE,MAAM;GAAW,aAAa;GAA+B,OAAO;GAAK,SAAS;GAAO;EACpG;CACD,MAAM,IAAI,EAAE,QAAQ,eAAe;EACjC,MAAM,WAAW,OAAO,QAAQ,UAAU,OAAO,UAAU,YAAY,OAAO,SAAS,WAAW,OAAO;EACzG,MAAM,EAAE,uBAAuB,MAAA,QAAA,SAAA,CAAA,WAAA,QAAM,0BAAA,CAAA;AAErC,QAAM,mBAAmB;GAAE,OAAO,YAAY;GAAI,YAAY,OAAO;GAAQ;GAAU,OAAO,OAAO;GAAO,CAAC;;CAEhH,CAAC"}
import "./chunk--u3MIqq1.js";
import { n as defineCommand } from "./define--M_JMcDC.js";
//#region src/commands/generate.ts
const command = defineCommand({
name: "generate",
description: "[input] Generate files based on a 'kubb.config.ts' file",
arguments: ["[input]"],
options: {
config: {
type: "string",
description: "Path to the Kubb config",
short: "c"
},
logLevel: {
type: "string",
description: "Info, silent, verbose or debug",
short: "l",
default: "info",
hint: "silent|info|verbose|debug",
enum: [
"silent",
"info",
"verbose",
"debug"
]
},
watch: {
type: "boolean",
description: "Watch mode based on the input file",
short: "w",
default: false
},
debug: {
type: "boolean",
description: "Override logLevel to debug",
short: "d",
default: false
},
verbose: {
type: "boolean",
description: "Override logLevel to verbose",
short: "v",
default: false
},
silent: {
type: "boolean",
description: "Override logLevel to silent",
short: "s",
default: false
}
},
async run({ values, positionals }) {
const logLevel = values.debug ? "debug" : values.verbose ? "verbose" : values.silent ? "silent" : values.logLevel;
const { runGenerateCommand } = await import("./generate-sIkyxxtw.js");
await runGenerateCommand({
input: positionals[0],
configPath: values.config,
logLevel,
watch: values.watch
});
}
});
//#endregion
export { command };
//# sourceMappingURL=generate-DBo220P3.js.map
{"version":3,"file":"generate-DBo220P3.js","names":[],"sources":["../src/commands/generate.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\n\nexport const command = defineCommand({\n name: 'generate',\n description: \"[input] Generate files based on a 'kubb.config.ts' file\",\n arguments: ['[input]'],\n options: {\n config: { type: 'string', description: 'Path to the Kubb config', short: 'c' },\n logLevel: {\n type: 'string',\n description: 'Info, silent, verbose or debug',\n short: 'l',\n default: 'info',\n hint: 'silent|info|verbose|debug',\n enum: ['silent', 'info', 'verbose', 'debug'],\n },\n watch: { type: 'boolean', description: 'Watch mode based on the input file', short: 'w', default: false },\n debug: { type: 'boolean', description: 'Override logLevel to debug', short: 'd', default: false },\n verbose: { type: 'boolean', description: 'Override logLevel to verbose', short: 'v', default: false },\n silent: { type: 'boolean', description: 'Override logLevel to silent', short: 's', default: false },\n },\n async run({ values, positionals }) {\n const logLevel = values.debug ? 'debug' : values.verbose ? 'verbose' : values.silent ? 'silent' : values.logLevel\n const { runGenerateCommand } = await import('../runners/generate.ts')\n\n await runGenerateCommand({ input: positionals[0], configPath: values.config, logLevel, watch: values.watch })\n },\n})\n"],"mappings":";;;AAEA,MAAa,UAAU,cAAc;CACnC,MAAM;CACN,aAAa;CACb,WAAW,CAAC,UAAU;CACtB,SAAS;EACP,QAAQ;GAAE,MAAM;GAAU,aAAa;GAA2B,OAAO;GAAK;EAC9E,UAAU;GACR,MAAM;GACN,aAAa;GACb,OAAO;GACP,SAAS;GACT,MAAM;GACN,MAAM;IAAC;IAAU;IAAQ;IAAW;IAAQ;GAC7C;EACD,OAAO;GAAE,MAAM;GAAW,aAAa;GAAsC,OAAO;GAAK,SAAS;GAAO;EACzG,OAAO;GAAE,MAAM;GAAW,aAAa;GAA8B,OAAO;GAAK,SAAS;GAAO;EACjG,SAAS;GAAE,MAAM;GAAW,aAAa;GAAgC,OAAO;GAAK,SAAS;GAAO;EACrG,QAAQ;GAAE,MAAM;GAAW,aAAa;GAA+B,OAAO;GAAK,SAAS;GAAO;EACpG;CACD,MAAM,IAAI,EAAE,QAAQ,eAAe;EACjC,MAAM,WAAW,OAAO,QAAQ,UAAU,OAAO,UAAU,YAAY,OAAO,SAAS,WAAW,OAAO;EACzG,MAAM,EAAE,uBAAuB,MAAM,OAAO;AAE5C,QAAM,mBAAmB;GAAE,OAAO,YAAY;GAAI,YAAY,OAAO;GAAQ;GAAU,OAAO,OAAO;GAAO,CAAC;;CAEhH,CAAC"}
const require_chunk = require("./chunk-ByKO4r7w.cjs");
const require_errors = require("./errors-DBW0N9w4.cjs");
const require_telemetry = require("./telemetry-CEm85k_X.cjs");
const require_shell = require("./shell-7HPrTCJ5.cjs");
const require_package = require("./package-m-LvDtUC.cjs");
const require_constants = require("./constants-BTUap0zs.cjs");
let node_util = require("node:util");
let node_events = require("node:events");
let node_crypto = require("node:crypto");
require("node:fs");
let node_fs_promises = require("node:fs/promises");
let node_path = require("node:path");
node_path = require_chunk.__toESM(node_path);
let node_process = require("node:process");
node_process = require_chunk.__toESM(node_process);
let _clack_prompts = require("@clack/prompts");
_clack_prompts = require_chunk.__toESM(_clack_prompts);
let _kubb_core = require("@kubb/core");
let tinyexec = require("tinyexec");
let node_stream = require("node:stream");
let cosmiconfig = require("cosmiconfig");
let jiti = require("jiti");
//#region ../../internals/utils/src/asyncEventEmitter.ts
/**
* A typed EventEmitter that awaits all async listeners before resolving.
* Wraps Node's `EventEmitter` with full TypeScript event-map inference.
*/
var AsyncEventEmitter = class {
/**
* `maxListener` controls the maximum number of listeners per event before Node emits a memory-leak warning.
* @default 10
*/
constructor(maxListener = 10) {
this.#emitter.setMaxListeners(maxListener);
}
#emitter = new node_events.EventEmitter();
/**
* Emits an event and awaits all registered listeners in parallel.
* Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
*/
async emit(eventName, ...eventArgs) {
const listeners = this.#emitter.listeners(eventName);
if (listeners.length === 0) return;
await Promise.all(listeners.map(async (listener) => {
try {
return await listener(...eventArgs);
} catch (err) {
let serializedArgs;
try {
serializedArgs = JSON.stringify(eventArgs);
} catch {
serializedArgs = String(eventArgs);
}
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: require_errors.toError(err) });
}
}));
}
/** Registers a persistent listener for the given event. */
on(eventName, handler) {
this.#emitter.on(eventName, handler);
}
/** Registers a one-shot listener that removes itself after the first invocation. */
onOnce(eventName, handler) {
const wrapper = (...args) => {
this.off(eventName, wrapper);
return handler(...args);
};
this.on(eventName, wrapper);
}
/** Removes a previously registered listener. */
off(eventName, handler) {
this.#emitter.off(eventName, handler);
}
/** Removes all listeners from every event channel. */
removeAll() {
this.#emitter.removeAllListeners();
}
};
//#endregion
//#region ../../internals/utils/src/time.ts
/**
* Calculates elapsed time in milliseconds from a high-resolution start time.
* Rounds to 2 decimal places to provide sub-millisecond precision without noise.
*/
function getElapsedMs(hrStart) {
const [seconds, nanoseconds] = process.hrtime(hrStart);
const ms = seconds * 1e3 + nanoseconds / 1e6;
return Math.round(ms * 100) / 100;
}
/**
* Converts a millisecond duration into a human-readable string.
* Adjusts units (ms, s, m s) based on the magnitude of the duration.
*/
function formatMs(ms) {
if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
return `${Math.round(ms)}ms`;
}
/**
* Convenience helper: formats the elapsed time since `hrStart` in one step.
*/
function formatHrtime(hrStart) {
return formatMs(getElapsedMs(hrStart));
}
//#endregion
//#region ../../internals/utils/src/colors.ts
/**
* Parses a CSS hex color string (`#RGB`) into its RGB channels.
* Falls back to `255` for any channel that cannot be parsed.
*/
function parseHex(color) {
const int = Number.parseInt(color.replace("#", ""), 16);
return Number.isNaN(int) ? {
r: 255,
g: 255,
b: 255
} : {
r: int >> 16 & 255,
g: int >> 8 & 255,
b: int & 255
};
}
/**
* Returns a function that wraps a string in a 24-bit ANSI true-color escape sequence
* for the given hex color.
*/
function hex(color) {
const { r, g, b } = parseHex(color);
return (text) => `\x1b[38;2;${r};${g};${b}m${text}\x1b[0m`;
}
function gradient(colorStops, text) {
const chars = text.split("");
return chars.map((char, i) => {
const t = chars.length <= 1 ? 0 : i / (chars.length - 1);
const seg = Math.min(Math.floor(t * (colorStops.length - 1)), colorStops.length - 2);
const lt = t * (colorStops.length - 1) - seg;
const from = parseHex(colorStops[seg]);
const to = parseHex(colorStops[seg + 1]);
return `\x1b[38;2;${Math.round(from.r + (to.r - from.r) * lt)};${Math.round(from.g + (to.g - from.g) * lt)};${Math.round(from.b + (to.b - from.b) * lt)}m${char}\x1b[0m`;
}).join("");
}
/** ANSI color functions for each part of the Kubb mascot illustration. */
const palette = {
lid: hex("#F55A17"),
woodTop: hex("#F5A217"),
woodMid: hex("#F58517"),
woodBase: hex("#B45309"),
eye: hex("#FFFFFF"),
highlight: hex("#adadc6"),
blush: hex("#FDA4AF")
};
/**
* Generates the Kubb mascot welcome banner.
*/
function getIntro({ title, description, version, areEyesOpen }) {
const kubbVersion = gradient([
"#F58517",
"#F5A217",
"#F55A17"
], `KUBB v${version}`);
const eyeTop = areEyesOpen ? palette.eye("█▀█") : palette.eye("───");
const eyeBottom = areEyesOpen ? palette.eye("▀▀▀") : palette.eye("───");
return `
${palette.lid("▄▄▄▄▄▄▄▄▄▄▄▄▄")}
${palette.woodTop("█ ")}${palette.highlight("▄▄")}${palette.woodTop(" ")}${palette.highlight("▄▄")}${palette.woodTop(" █")} ${kubbVersion}
${palette.woodMid("█ ")}${eyeTop}${palette.woodMid(" ")}${eyeTop}${palette.woodMid(" █")} ${(0, node_util.styleText)("gray", title)}
${palette.woodMid("█ ")}${eyeBottom}${palette.woodMid(" ")}${palette.blush("◡")}${palette.woodMid(" ")}${eyeBottom}${palette.woodMid(" █")} ${(0, node_util.styleText)("yellow", "➜")} ${(0, node_util.styleText)("white", description)}
${palette.woodBase("▀▀▀▀▀▀▀▀▀▀▀▀▀")}
`;
}
/** ANSI color names available for terminal output. */
const randomColors = [
"black",
"red",
"green",
"yellow",
"blue",
"white",
"magenta",
"cyan",
"gray"
];
/**
* Returns the text wrapped in a deterministic ANSI color derived from the text's SHA-256 hash.
*/
function randomCliColor(text) {
if (!text) return "";
return (0, node_util.styleText)(randomColors[(0, node_crypto.createHash)("sha256").update(text).digest().readUInt32BE(0) % randomColors.length] ?? "white", text);
}
/**
* Formats a millisecond duration with an ANSI color based on thresholds:
* green ≤ 500 ms · yellow ≤ 1 000 ms · red > 1 000 ms
*/
function formatMsWithColor(ms) {
const formatted = formatMs(ms);
if (ms <= 500) return (0, node_util.styleText)("green", formatted);
if (ms <= 1e3) return (0, node_util.styleText)("yellow", formatted);
return (0, node_util.styleText)("red", formatted);
}
//#endregion
//#region ../../internals/utils/src/fs.ts
/**
* Writes `data` to `path`, trimming leading/trailing whitespace before saving.
* Skips the write and returns `undefined` when the trimmed content is empty or
* identical to what is already on disk.
* Creates any missing parent directories automatically.
* When `sanity` is `true`, re-reads the file after writing and throws if the
* content does not match.
*/
async function write(path, data, options = {}) {
const trimmed = data.trim();
if (trimmed === "") return void 0;
const resolved = (0, node_path.resolve)(path);
if (typeof Bun !== "undefined") {
const file = Bun.file(resolved);
if ((await file.exists() ? await file.text() : null) === trimmed) return void 0;
await Bun.write(resolved, trimmed);
return trimmed;
}
try {
if (await (0, node_fs_promises.readFile)(resolved, { encoding: "utf-8" }) === trimmed) return void 0;
} catch {}
await (0, node_fs_promises.mkdir)((0, node_path.dirname)(resolved), { recursive: true });
await (0, node_fs_promises.writeFile)(resolved, trimmed, { encoding: "utf-8" });
if (options.sanity) {
const savedData = await (0, node_fs_promises.readFile)(resolved, { encoding: "utf-8" });
if (savedData !== trimmed) throw new Error(`Sanity check failed for ${path}\n\nData[${data.length}]:\n${data}\n\nSaved[${savedData.length}]:\n${savedData}\n`);
return savedData;
}
return trimmed;
}
//#endregion
//#region src/utils/getSummary.ts
function getSummary({ failedPlugins, filesCreated, status, hrStart, config, pluginTimings }) {
const duration = formatHrtime(hrStart);
const pluginsCount = config.plugins?.length ?? 0;
const successCount = pluginsCount - failedPlugins.size;
const meta = {
plugins: status === "success" ? `${(0, node_util.styleText)("green", `${successCount} successful`)}, ${pluginsCount} total` : `${(0, node_util.styleText)("green", `${successCount} successful`)}, ${(0, node_util.styleText)("red", `${failedPlugins.size} failed`)}, ${pluginsCount} total`,
pluginsFailed: status === "failed" ? [...failedPlugins].map(({ plugin }) => randomCliColor(plugin.name)).join(", ") : void 0,
filesCreated,
time: (0, node_util.styleText)("green", duration),
output: node_path.default.isAbsolute(config.root) ? node_path.default.resolve(config.root, config.output.path) : config.root
};
const labels = {
plugins: "Plugins:",
failed: "Failed:",
generated: "Generated:",
pluginTimings: "Plugin Timings:",
output: "Output:"
};
const maxLength = Math.max(0, ...[...Object.values(labels), ...pluginTimings ? Array.from(pluginTimings.keys()) : []].map((s) => s.length));
const summaryLines = [];
summaryLines.push(`${labels.plugins.padEnd(maxLength + 2)} ${meta.plugins}`);
if (meta.pluginsFailed) summaryLines.push(`${labels.failed.padEnd(maxLength + 2)} ${meta.pluginsFailed}`);
summaryLines.push(`${labels.generated.padEnd(maxLength + 2)} ${meta.filesCreated} files in ${meta.time}`);
if (pluginTimings && pluginTimings.size > 0) {
const sortedTimings = Array.from(pluginTimings.entries()).sort((a, b) => b[1] - a[1]);
summaryLines.push(`${labels.pluginTimings}`);
sortedTimings.forEach(([name, time]) => {
const timeStr = time >= 1e3 ? `${(time / 1e3).toFixed(2)}s` : `${Math.round(time)}ms`;
const barLength = Math.min(Math.ceil(time / 100), 10);
const bar = (0, node_util.styleText)("dim", "█".repeat(barLength));
summaryLines.push(`${(0, node_util.styleText)("dim", "•")} ${name.padEnd(maxLength + 1)}${bar} ${timeStr}`);
});
}
summaryLines.push(`${labels.output.padEnd(maxLength + 2)} ${meta.output}`);
return summaryLines;
}
//#endregion
//#region src/utils/runHook.ts
/**
* Execute a hook command, emit debug/hook:end events, and forward output to
* an optional HookOutputSink. All three logger adapters share this function
* so the process-spawning logic lives in exactly one place.
*/
async function runHook({ id, command, args, commandWithArgs, context, stream = false, sink }) {
try {
const proc = (0, tinyexec.x)(command, [...args ?? []], {
nodeOptions: { detached: true },
throwOnError: true
});
if (stream && sink?.onLine) for await (const line of proc) sink.onLine(line);
const result = await proc;
await context.emit("debug", {
date: /* @__PURE__ */ new Date(),
logs: [result.stdout.trimEnd()]
});
await context.emit("hook:end", {
command,
args,
id,
success: true,
error: null
});
} catch (err) {
if (!(err instanceof tinyexec.NonZeroExitError)) {
await context.emit("hook:end", {
command,
args,
id,
success: false,
error: require_errors.toError(err)
});
await context.emit("error", require_errors.toError(err));
return;
}
const stderr = err.output?.stderr ?? "";
const stdout = err.output?.stdout ?? "";
await context.emit("debug", {
date: /* @__PURE__ */ new Date(),
logs: [stdout, stderr].filter(Boolean)
});
if (stderr) sink?.onStderr?.(stderr);
if (stdout) sink?.onStdout?.(stdout);
const errorMessage = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
await context.emit("hook:end", {
command,
args,
id,
success: false,
error: errorMessage
});
await context.emit("error", errorMessage);
}
}
//#endregion
//#region src/utils/Writables.ts
var ClackWritable = class extends node_stream.Writable {
taskLog;
constructor(taskLog, opts) {
super(opts);
this.taskLog = taskLog;
}
_write(chunk, _encoding, callback) {
this.taskLog.message(`${(0, node_util.styleText)("dim", chunk.toString())}`);
callback();
}
};
//#endregion
//#region src/loggers/clackLogger.ts
/**
* Clack adapter for local TTY environments
* Provides a beautiful CLI UI with flat structure inspired by Claude's CLI patterns
*/
const clackLogger = (0, _kubb_core.defineLogger)({
name: "clack",
install(context, options) {
const logLevel = options?.logLevel ?? _kubb_core.logLevel.info;
const state = {
totalPlugins: 0,
completedPlugins: 0,
failedPlugins: 0,
totalFiles: 0,
processedFiles: 0,
hrStart: node_process.default.hrtime(),
spinner: _clack_prompts.spinner(),
isSpinning: false,
activeProgress: /* @__PURE__ */ new Map()
};
function reset() {
for (const [_key, active] of state.activeProgress) {
if (active.interval) clearInterval(active.interval);
active.progressBar?.stop();
}
state.totalPlugins = 0;
state.completedPlugins = 0;
state.failedPlugins = 0;
state.totalFiles = 0;
state.processedFiles = 0;
state.hrStart = node_process.default.hrtime();
state.spinner = _clack_prompts.spinner();
state.isSpinning = false;
state.activeProgress.clear();
}
function showProgressStep() {
if (logLevel <= _kubb_core.logLevel.silent) return;
const line = buildProgressLine(state);
if (line) _clack_prompts.log.step(getMessage(line));
}
function getMessage(message) {
return formatMessage(message, logLevel);
}
function startSpinner(text) {
state.spinner.start(text);
state.isSpinning = true;
}
function stopSpinner(text) {
state.spinner.stop(text);
state.isSpinning = false;
}
context.on("info", (message, info = "") => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
(0, node_util.styleText)("blue", "ℹ"),
message,
(0, node_util.styleText)("dim", info)
].join(" "));
if (state.isSpinning) state.spinner.message(text);
else _clack_prompts.log.info(text);
});
context.on("success", (message, info = "") => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
(0, node_util.styleText)("blue", "✓"),
message,
logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", info) : void 0
].filter(Boolean).join(" "));
if (state.isSpinning) stopSpinner(text);
else _clack_prompts.log.success(text);
});
context.on("warn", (message, info) => {
if (logLevel < _kubb_core.logLevel.warn) return;
const text = getMessage([
(0, node_util.styleText)("yellow", "⚠"),
message,
logLevel >= _kubb_core.logLevel.info && info ? (0, node_util.styleText)("dim", info) : void 0
].filter(Boolean).join(" "));
_clack_prompts.log.warn(text);
});
context.on("error", (error) => {
const caused = require_errors.toCause(error);
const text = [(0, node_util.styleText)("red", "✗"), error.message].join(" ");
if (state.isSpinning) stopSpinner(getMessage(text));
else _clack_prompts.log.error(getMessage(text));
if (logLevel >= _kubb_core.logLevel.debug && error.stack) {
const frames = error.stack.split("\n").slice(1, 4);
for (const frame of frames) _clack_prompts.log.message(getMessage((0, node_util.styleText)("dim", frame.trim())));
if (caused?.stack) {
_clack_prompts.log.message((0, node_util.styleText)("dim", `└─ caused by ${caused.message}`));
const frames = caused.stack.split("\n").slice(1, 4);
for (const frame of frames) _clack_prompts.log.message(getMessage(` ${(0, node_util.styleText)("dim", frame.trim())}`));
}
}
});
context.on("version:new", (version, latestVersion) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
try {
_clack_prompts.box(`\`v${version}\` → \`v${latestVersion}\`
Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
width: "auto",
formatBorder: (s) => (0, node_util.styleText)("yellow", s),
rounded: true,
withGuide: false,
contentAlign: "center",
titleAlign: "center"
});
} catch {
console.log(`Update available for Kubb: v${version} → v${latestVersion}`);
console.log("Run `npm install -g @kubb/cli` to update");
}
});
context.on("lifecycle:start", async (version) => {
console.log(`\n${getIntro({
title: "The ultimate toolkit for working with APIs",
description: "Ready to start",
version,
areEyesOpen: true
})}\n`);
reset();
});
context.on("config:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Configuration started");
_clack_prompts.intro(text);
startSpinner(getMessage("Configuration loading"));
});
context.on("config:end", (_configs) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Configuration completed");
_clack_prompts.outro(text);
});
context.on("generation:start", (config) => {
reset();
state.totalPlugins = config.plugins?.length ?? 0;
const text = getMessage(["Generation started", config.name ? `for ${(0, node_util.styleText)("dim", config.name)}` : void 0].filter(Boolean).join(" "));
_clack_prompts.intro(text);
});
context.on("plugin:start", (plugin) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
stopSpinner();
const progressBar = _clack_prompts.progress({
style: "block",
max: 100,
size: 30
});
const text = getMessage(`Generating ${(0, node_util.styleText)("bold", plugin.name)}`);
progressBar.start(text);
const interval = setInterval(() => {
progressBar.advance();
}, 100);
state.activeProgress.set(plugin.name, {
progressBar,
interval
});
});
context.on("plugin:end", (plugin, { duration, success }) => {
stopSpinner();
const active = state.activeProgress.get(plugin.name);
if (!active || logLevel === _kubb_core.logLevel.silent) return;
clearInterval(active.interval);
if (success) state.completedPlugins++;
else state.failedPlugins++;
const durationStr = formatMsWithColor(duration);
const text = getMessage(success ? `${(0, node_util.styleText)("bold", plugin.name)} completed in ${durationStr}` : `${(0, node_util.styleText)("bold", plugin.name)} failed in ${(0, node_util.styleText)("red", formatMs(duration))}`);
active.progressBar.stop(text);
state.activeProgress.delete(plugin.name);
showProgressStep();
});
context.on("files:processing:start", (files) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
stopSpinner();
state.totalFiles = files.length;
state.processedFiles = 0;
const text = `Writing ${files.length} files`;
const progressBar = _clack_prompts.progress({
style: "block",
max: files.length,
size: 30
});
context.emit("info", text);
progressBar.start(getMessage(text));
state.activeProgress.set("files", { progressBar });
});
context.on("file:processing:update", ({ file, config }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
stopSpinner();
state.processedFiles++;
const text = `Writing ${(0, node_path.relative)(config.root, file.path)}`;
const active = state.activeProgress.get("files");
if (!active) return;
active.progressBar.advance(void 0, text);
});
context.on("files:processing:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
stopSpinner();
const text = getMessage("Files written successfully");
const active = state.activeProgress.get("files");
if (!active) return;
active.progressBar.stop(text);
state.activeProgress.delete("files");
showProgressStep();
});
context.on("generation:end", (config) => {
const text = getMessage(config.name ? `Generation completed for ${(0, node_util.styleText)("dim", config.name)}` : "Generation completed");
_clack_prompts.outro(text);
});
context.on("format:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Format started");
_clack_prompts.intro(text);
});
context.on("format:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Format completed");
_clack_prompts.outro(text);
});
context.on("lint:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Lint started");
_clack_prompts.intro(text);
});
context.on("lint:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Lint completed");
_clack_prompts.outro(text);
});
context.on("hook:start", async ({ id, command, args }) => {
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} started`);
if (!id) return;
if (logLevel <= _kubb_core.logLevel.silent) {
await runHook({
id,
command,
args,
commandWithArgs,
context,
sink: {
onStderr: (s) => console.error(s),
onStdout: (s) => console.log(s)
}
});
return;
}
_clack_prompts.intro(text);
const logger = _clack_prompts.taskLog({ title: getMessage(["Executing hook", logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", commandWithArgs) : void 0].filter(Boolean).join(" ")) });
const writable = new ClackWritable(logger);
await runHook({
id,
command,
args,
commandWithArgs,
context,
stream: true,
sink: {
onLine: (line) => writable.write(line),
onStderr: (s) => logger.error(s),
onStdout: (s) => logger.message(s)
}
});
});
context.on("hook:end", ({ command, args }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage(`Hook ${(0, node_util.styleText)("dim", formatCommandWithArgs(command, args))} successfully executed`);
_clack_prompts.outro(text);
});
context.on("generation:summary", (config, { pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
const summary = getSummary({
failedPlugins,
filesCreated,
config,
status,
hrStart,
pluginTimings: logLevel >= _kubb_core.logLevel.verbose ? pluginTimings : void 0
});
const title = config.name || "";
summary.unshift("\n");
summary.push("\n");
const borderColor = status === "success" ? "green" : "red";
try {
_clack_prompts.box(summary.join("\n"), getMessage(title), {
width: "auto",
formatBorder: (s) => (0, node_util.styleText)(borderColor, s),
rounded: true,
withGuide: false,
contentAlign: "left",
titleAlign: "center"
});
} catch {
console.log(summary.join("\n"));
}
});
context.on("lifecycle:end", () => {
reset();
});
}
});
//#endregion
//#region src/loggers/fileSystemLogger.ts
/**
* FileSystem logger for debug log persistence
* Captures debug and verbose events and writes them to files in .kubb directory
*
* Note: Logs are written on lifecycle:end or process exit. If the process crashes
* before these events, some cached logs may be lost.
*/
const fileSystemLogger = (0, _kubb_core.defineLogger)({
name: "filesystem",
install(context) {
const state = {
cachedLogs: /* @__PURE__ */ new Set(),
startDate: Date.now()
};
function reset() {
state.cachedLogs = /* @__PURE__ */ new Set();
state.startDate = Date.now();
}
async function writeLogs(name) {
if (state.cachedLogs.size === 0) return [];
const files = {};
for (const log of state.cachedLogs) {
const baseName = log.fileName || `${[
"kubb",
name,
state.startDate
].filter(Boolean).join("-")}.log`;
const pathName = (0, node_path.resolve)(node_process.default.cwd(), ".kubb", baseName);
if (!files[pathName]) files[pathName] = [];
if (log.logs.length > 0) {
const timestamp = log.date.toLocaleString();
files[pathName].push(`[${timestamp}]\n${log.logs.join("\n")}`);
}
}
await Promise.all(Object.entries(files).map(([fileName, logs]) => write(fileName, logs.join("\n\n"))));
return Object.keys(files);
}
context.on("info", (message, info) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`ℹ ${message} ${info}`]
});
});
context.on("success", (message, info) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`✓ ${message} ${info}`]
});
});
context.on("warn", (message, info) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`⚠ ${message} ${info}`]
});
});
context.on("error", (error) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`✗ ${error.message}`, error.stack || "unknown stack"]
});
});
context.on("debug", (message) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: message.logs
});
});
context.on("plugin:start", (plugin) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`Generating ${plugin.name}`]
});
});
context.on("plugin:end", (plugin, { duration, success }) => {
const durationStr = formatMs(duration);
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`]
});
});
context.on("files:processing:start", (files) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`Start ${files.length} writing:`, ...files.map((file) => file.path)]
});
});
context.on("generation:end", async (config) => {
const writtenFilePaths = await writeLogs(config.name);
if (writtenFilePaths.length > 0) {
const files = writtenFilePaths.map((f) => (0, node_path.relative)(node_process.default.cwd(), f));
await context.emit("info", "Debug files written to:", files.join(", "));
}
reset();
});
const exitHandler = () => {
if (state.cachedLogs.size > 0) writeLogs().catch(() => {});
};
node_process.default.once("exit", exitHandler);
node_process.default.once("SIGINT", exitHandler);
node_process.default.once("SIGTERM", exitHandler);
}
});
//#endregion
//#region src/loggers/githubActionsLogger.ts
/**
* GitHub Actions adapter for CI environments
* Uses Github group annotations for collapsible sections
*/
const githubActionsLogger = (0, _kubb_core.defineLogger)({
name: "github-actions",
install(context, options) {
const logLevel = options?.logLevel ?? _kubb_core.logLevel.info;
const state = {
totalPlugins: 0,
completedPlugins: 0,
failedPlugins: 0,
totalFiles: 0,
processedFiles: 0,
hrStart: process.hrtime(),
currentConfigs: []
};
function reset() {
state.totalPlugins = 0;
state.completedPlugins = 0;
state.failedPlugins = 0;
state.totalFiles = 0;
state.processedFiles = 0;
state.hrStart = process.hrtime();
state.currentConfigs = [];
}
function showProgressStep() {
if (logLevel <= _kubb_core.logLevel.silent) return;
const line = buildProgressLine(state);
if (line) console.log(getMessage(line));
}
function getMessage(message) {
return formatMessage(message, logLevel);
}
function openGroup(name) {
console.log(`::group::${name}`);
}
function closeGroup(_name) {
console.log("::endgroup::");
}
context.on("info", (message, info = "") => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
(0, node_util.styleText)("blue", "ℹ"),
message,
(0, node_util.styleText)("dim", info)
].join(" "));
console.log(text);
});
context.on("success", (message, info = "") => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
(0, node_util.styleText)("blue", "✓"),
message,
logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", info) : void 0
].filter(Boolean).join(" "));
console.log(text);
});
context.on("warn", (message, info = "") => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
(0, node_util.styleText)("yellow", "⚠"),
message,
logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", info) : void 0
].filter(Boolean).join(" "));
console.warn(`::warning::${text}`);
});
context.on("error", (error) => {
const caused = require_errors.toCause(error);
if (logLevel <= _kubb_core.logLevel.silent) return;
const message = error.message || String(error);
console.error(`::error::${message}`);
if (logLevel >= _kubb_core.logLevel.debug && error.stack) {
const frames = error.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage((0, node_util.styleText)("dim", frame.trim())));
if (caused?.stack) {
console.log((0, node_util.styleText)("dim", `└─ caused by ${caused.message}`));
const frames = caused.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(` ${(0, node_util.styleText)("dim", frame.trim())}`));
}
}
});
context.on("lifecycle:start", (version) => {
console.log((0, node_util.styleText)("yellow", `Kubb ${version} 🧩`));
reset();
});
context.on("config:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Configuration started");
openGroup("Configuration");
console.log(text);
});
context.on("config:end", (configs) => {
state.currentConfigs = configs;
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Configuration completed");
console.log(text);
closeGroup("Configuration");
});
context.on("generation:start", (config) => {
reset();
state.totalPlugins = config.plugins?.length ?? 0;
const text = config.name ? `Generation for ${(0, node_util.styleText)("bold", config.name)}` : "Generation";
if (state.currentConfigs.length > 1) openGroup(text);
if (state.currentConfigs.length === 1) console.log(getMessage(text));
});
context.on("plugin:start", (plugin) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage(`Generating ${(0, node_util.styleText)("bold", plugin.name)}`);
if (state.currentConfigs.length === 1) openGroup(`Plugin: ${plugin.name}`);
console.log(text);
});
context.on("plugin:end", (plugin, { duration, success }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
if (success) state.completedPlugins++;
else state.failedPlugins++;
const durationStr = formatMsWithColor(duration);
const text = getMessage(success ? `${(0, node_util.styleText)("bold", plugin.name)} completed in ${durationStr}` : `${(0, node_util.styleText)("bold", plugin.name)} failed in ${(0, node_util.styleText)("red", formatMs(duration))}`);
console.log(text);
if (state.currentConfigs.length > 1) console.log(" ");
if (state.currentConfigs.length === 1) closeGroup(`Plugin: ${plugin.name}`);
showProgressStep();
});
context.on("files:processing:start", (files) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
state.totalFiles = files.length;
state.processedFiles = 0;
if (state.currentConfigs.length === 1) openGroup("File Generation");
const text = getMessage(`Writing ${files.length} files`);
console.log(text);
});
context.on("files:processing:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Files written successfully");
console.log(text);
if (state.currentConfigs.length === 1) closeGroup("File Generation");
showProgressStep();
});
context.on("file:processing:update", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
state.processedFiles++;
});
context.on("generation:end", (config) => {
const text = getMessage(config.name ? `${(0, node_util.styleText)("blue", "✓")} Generation completed for ${(0, node_util.styleText)("dim", config.name)}` : `${(0, node_util.styleText)("blue", "✓")} Generation completed`);
console.log(text);
});
context.on("format:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Format started");
if (state.currentConfigs.length === 1) openGroup("Formatting");
console.log(text);
});
context.on("format:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Format completed");
console.log(text);
if (state.currentConfigs.length === 1) closeGroup("Formatting");
});
context.on("lint:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Lint started");
if (state.currentConfigs.length === 1) openGroup("Linting");
console.log(text);
});
context.on("lint:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Lint completed");
console.log(text);
if (state.currentConfigs.length === 1) closeGroup("Linting");
});
context.on("hook:start", async ({ id, command, args }) => {
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} started`);
if (logLevel > _kubb_core.logLevel.silent) {
if (state.currentConfigs.length === 1) openGroup(`Hook ${commandWithArgs}`);
console.log(text);
}
if (!id) return;
await runHook({
id,
command,
args,
commandWithArgs,
context,
sink: {
onStdout: logLevel > _kubb_core.logLevel.silent ? (s) => console.log(s) : void 0,
onStderr: logLevel > _kubb_core.logLevel.silent ? (s) => console.error(`::error::${s}`) : void 0
}
});
});
context.on("hook:end", ({ command, args }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} completed`);
console.log(text);
if (state.currentConfigs.length === 1) closeGroup(`Hook ${commandWithArgs}`);
});
context.on("generation:summary", (config, { status, hrStart, failedPlugins }) => {
const pluginsCount = config.plugins?.length ?? 0;
const successCount = pluginsCount - failedPlugins.size;
const duration = formatHrtime(hrStart);
if (state.currentConfigs.length > 1) console.log(" ");
console.log(status === "success" ? `Kubb Summary: ${(0, node_util.styleText)("blue", "✓")} ${`${successCount} successful`}, ${pluginsCount} total, ${(0, node_util.styleText)("green", duration)}` : `Kubb Summary: ${(0, node_util.styleText)("blue", "✓")} ${`${successCount} successful`}, ✗ ${`${failedPlugins.size} failed`}, ${pluginsCount} total, ${(0, node_util.styleText)("green", duration)}`);
if (state.currentConfigs.length > 1) closeGroup(config.name ? `Generation for ${(0, node_util.styleText)("bold", config.name)}` : "Generation");
});
context.on("lifecycle:end", () => {
reset();
});
}
});
//#endregion
//#region src/loggers/plainLogger.ts
/**
* Plain console adapter for non-TTY environments
* Simple console.log output with indentation
*/
const plainLogger = (0, _kubb_core.defineLogger)({
name: "plain",
install(context, options) {
const logLevel = options?.logLevel ?? _kubb_core.logLevel.info;
function getMessage(message) {
return formatMessage(message, logLevel);
}
context.on("info", (message, info) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
"ℹ",
message,
info
].join(" "));
console.log(text);
});
context.on("success", (message, info = "") => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
"✓",
message,
logLevel >= _kubb_core.logLevel.info ? info : void 0
].filter(Boolean).join(" "));
console.log(text);
});
context.on("warn", (message, info) => {
if (logLevel < _kubb_core.logLevel.warn) return;
const text = getMessage([
"⚠",
message,
logLevel >= _kubb_core.logLevel.info ? info : void 0
].filter(Boolean).join(" "));
console.log(text);
});
context.on("error", (error) => {
const caused = require_errors.toCause(error);
const text = getMessage(["✗", error.message].join(" "));
console.log(text);
if (logLevel >= _kubb_core.logLevel.debug && error.stack) {
const frames = error.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(frame.trim()));
if (caused?.stack) {
console.log(`└─ caused by ${caused.message}`);
const frames = caused.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(` ${frame.trim()}`));
}
}
});
context.on("lifecycle:start", () => {
console.log("Kubb CLI 🧩");
});
context.on("config:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Configuration started");
console.log(text);
});
context.on("config:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Configuration completed");
console.log(text);
});
context.on("generation:start", () => {
const text = getMessage("Generation started");
console.log(text);
});
context.on("plugin:start", (plugin) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage(`Generating ${plugin.name}`);
console.log(text);
});
context.on("plugin:end", (plugin, { duration, success }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const durationStr = formatMs(duration);
const text = getMessage(success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`);
console.log(text);
});
context.on("files:processing:start", (files) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage(`Writing ${files.length} files`);
console.log(text);
});
context.on("file:processing:update", ({ file, config }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage(`Writing ${(0, node_path.relative)(config.root, file.path)}`);
console.log(text);
});
context.on("files:processing:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Files written successfully");
console.log(text);
});
context.on("generation:end", (config) => {
const text = getMessage(config.name ? `Generation completed for ${config.name}` : "Generation completed");
console.log(text);
});
context.on("format:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Format started");
console.log(text);
});
context.on("format:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Format completed");
console.log(text);
});
context.on("lint:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Lint started");
console.log(text);
});
context.on("lint:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Lint completed");
console.log(text);
});
context.on("hook:start", async ({ id, command, args }) => {
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${commandWithArgs} started`);
if (logLevel > _kubb_core.logLevel.silent) console.log(text);
if (!id) return;
await runHook({
id,
command,
args,
commandWithArgs,
context,
sink: {
onStdout: logLevel > _kubb_core.logLevel.silent ? (s) => console.log(s) : void 0,
onStderr: logLevel > _kubb_core.logLevel.silent ? (s) => console.error(s) : void 0
}
});
});
context.on("hook:end", ({ command, args }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage(`Hook ${formatCommandWithArgs(command, args)} completed`);
console.log(text);
});
context.on("generation:summary", (config, { pluginTimings, status, hrStart, failedPlugins, filesCreated }) => {
const summary = getSummary({
failedPlugins,
filesCreated,
config,
status,
hrStart,
pluginTimings: logLevel >= _kubb_core.logLevel.verbose ? pluginTimings : void 0
});
console.log(require_constants.SUMMARY_SEPARATOR);
console.log(summary.join("\n"));
console.log(require_constants.SUMMARY_SEPARATOR);
});
}
});
//#endregion
//#region src/loggers/utils.ts
/**
* Optionally prefix a message with a [HH:MM:SS] timestamp when logLevel >= verbose.
* Shared across all logger adapters to avoid duplication.
*/
function formatMessage(message, logLevel) {
if (logLevel >= _kubb_core.logLevel.verbose) return `${(0, node_util.styleText)("dim", `[${(/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
hour12: false,
hour: "2-digit",
minute: "2-digit",
second: "2-digit"
})}]`)} ${message}`;
return message;
}
/**
* Build the progress summary line shared by clack and GitHub Actions loggers.
* Returns null when there is nothing to display.
*/
function buildProgressLine(state) {
const parts = [];
const duration = formatHrtime(state.hrStart);
if (state.totalPlugins > 0) {
const pluginStr = state.failedPlugins > 0 ? `Plugins ${(0, node_util.styleText)("green", state.completedPlugins.toString())}/${state.totalPlugins} ${(0, node_util.styleText)("red", `(${state.failedPlugins} failed)`)}` : `Plugins ${(0, node_util.styleText)("green", state.completedPlugins.toString())}/${state.totalPlugins}`;
parts.push(pluginStr);
}
if (state.totalFiles > 0) parts.push(`Files ${(0, node_util.styleText)("green", state.processedFiles.toString())}/${state.totalFiles}`);
if (parts.length === 0) return null;
parts.push(`${(0, node_util.styleText)("green", duration)} elapsed`);
return parts.join((0, node_util.styleText)("dim", " | "));
}
/**
* Join a command and its optional args into a single display string.
* e.g. ("prettier", ["--write", "."]) → "prettier --write ."
*/
function formatCommandWithArgs(command, args) {
return args?.length ? `${command} ${args.join(" ")}` : command;
}
function detectLogger() {
if (require_telemetry.isGitHubActions()) return "github-actions";
if (require_telemetry.canUseTTY()) return "clack";
return "plain";
}
const logMapper = {
clack: clackLogger,
plain: plainLogger,
"github-actions": githubActionsLogger
};
async function setupLogger(context, { logLevel }) {
const type = detectLogger();
const logger = logMapper[type];
if (!logger) throw new Error(`Unknown adapter type: ${type}`);
const cleanup = await logger.install(context, { logLevel });
if (logLevel >= _kubb_core.logLevel.debug) await fileSystemLogger.install(context, { logLevel });
return cleanup;
}
//#endregion
//#region src/utils/executeHooks.ts
async function executeHooks({ hooks, events }) {
const commands = Array.isArray(hooks.done) ? hooks.done : [hooks.done].filter(Boolean);
for (const command of commands) {
const [cmd, ...args] = require_shell.tokenize(command);
if (!cmd) continue;
const hookId = (0, node_crypto.createHash)("sha256").update(command).digest("hex");
const hookEndPromise = new Promise((resolve, reject) => {
const handler = ({ id, success, error }) => {
if (id !== hookId) return;
events.off("hook:end", handler);
if (!success) {
reject(error ?? /* @__PURE__ */ new Error(`Hook failed: ${command}`));
return;
}
events.emit("success", `${(0, node_util.styleText)("dim", command)} successfully executed`).then(resolve).catch(reject);
};
events.on("hook:end", handler);
});
await events.emit("hook:start", {
id: hookId,
command: cmd,
args
});
await hookEndPromise;
}
}
//#endregion
//#region src/utils/getCosmiConfig.ts
const jiti$1 = (0, jiti.createJiti)(require("url").pathToFileURL(__filename).href, {
jsx: {
runtime: "automatic",
importSource: "@kubb/react-fabric"
},
sourceMaps: true,
interopDefault: true
});
const tsLoader = async (configFile) => {
return await jiti$1.import(configFile, { default: true });
};
async function getCosmiConfig(moduleName, config) {
let result;
const searchPlaces = [
"package.json",
`.${moduleName}rc`,
`.${moduleName}rc.json`,
`.${moduleName}rc.yaml`,
`.${moduleName}rc.yml`,
`.${moduleName}rc.ts`,
`.${moduleName}rc.mts`,
`.${moduleName}rc.cts`,
`.${moduleName}rc.js`,
`.${moduleName}rc.mjs`,
`.${moduleName}rc.cjs`,
`${moduleName}.config.ts`,
`${moduleName}.config.mts`,
`${moduleName}.config.cts`,
`${moduleName}.config.js`,
`${moduleName}.config.mjs`,
`${moduleName}.config.cjs`
];
const explorer = (0, cosmiconfig.cosmiconfig)(moduleName, {
cache: false,
searchPlaces: [
...searchPlaces.map((searchPlace) => {
return `.config/${searchPlace}`;
}),
...searchPlaces.map((searchPlace) => {
return `configs/${searchPlace}`;
}),
...searchPlaces
],
loaders: {
".ts": tsLoader,
".mts": tsLoader,
".cts": tsLoader
}
});
try {
result = config ? await explorer.load(config) : await explorer.search();
} catch (error) {
throw new Error("Config failed loading", { cause: error });
}
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, cb) {
const { watch } = await import("chokidar");
watch(path, {
ignorePermissionErrors: true,
ignored: require_constants.WATCHER_IGNORED_PATHS
}).on("all", async (type, file) => {
console.log((0, node_util.styleText)("yellow", (0, node_util.styleText)("bold", `Change detected: ${type} ${file}`)));
try {
await cb(path);
} catch (_e) {
console.log((0, node_util.styleText)("red", "Watcher failed"));
}
});
}
//#endregion
//#region src/runners/generate.ts
async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, configName, outputPath, logLevel, events, onStart, onEnd }) {
await onStart();
let resolvedTool = toolValue;
if (resolvedTool === "auto") {
const detected = await detect();
if (!detected) await events.emit("warn", noToolMessage);
else {
resolvedTool = detected;
await events.emit("info", `Auto-detected ${toolLabel}: ${(0, node_util.styleText)("dim", resolvedTool)}`);
}
}
if (resolvedTool && resolvedTool !== "auto" && resolvedTool in toolMap) {
const toolConfig = toolMap[resolvedTool];
try {
const hookId = (0, node_crypto.createHash)("sha256").update([configName, resolvedTool].filter(Boolean).join("-")).digest("hex");
const hookEndPromise = new Promise((resolve, reject) => {
const handler = ({ id, success, error }) => {
if (id !== hookId) return;
events.off("hook:end", handler);
if (!success) {
reject(error ?? /* @__PURE__ */ new Error(`${toolConfig.errorMessage}`));
return;
}
events.emit("success", [
`${successPrefix} with ${(0, node_util.styleText)("dim", resolvedTool)}`,
logLevel >= _kubb_core.logLevel.info ? `on ${(0, node_util.styleText)("dim", outputPath)}` : void 0,
"successfully"
].filter(Boolean).join(" ")).then(resolve).catch(reject);
};
events.on("hook:end", handler);
});
await events.emit("hook:start", {
id: hookId,
command: toolConfig.command,
args: toolConfig.args(outputPath)
});
await hookEndPromise;
} catch (caughtError) {
const err = new Error(toolConfig.errorMessage);
err.cause = caughtError;
await events.emit("error", err);
}
}
await onEnd();
}
async function generate({ input, config: userConfig, events, logLevel }) {
const inputPath = input ?? ("path" in userConfig.input ? userConfig.input.path : void 0);
const hrStart = node_process.default.hrtime();
const config = {
...userConfig,
root: userConfig.root || node_process.default.cwd(),
input: inputPath ? {
...userConfig.input,
path: inputPath
} : userConfig.input,
output: {
write: true,
barrelType: "named",
extension: { ".ts": ".ts" },
format: "prettier",
...userConfig.output
}
};
await events.emit("generation:start", config);
await events.emit("info", config.name ? `Setup generation ${(0, node_util.styleText)("bold", config.name)}` : "Setup generation", inputPath);
const { sources, fabric, pluginManager } = await (0, _kubb_core.setup)({
config,
events
});
await events.emit("info", config.name ? `Build generation ${(0, node_util.styleText)("bold", config.name)}` : "Build generation", inputPath);
const { files, failedPlugins, pluginTimings, error } = await (0, _kubb_core.safeBuild)({
config,
events
}, {
pluginManager,
fabric,
events,
sources
});
await events.emit("info", "Load summary");
if (failedPlugins.size > 0 || error) {
const allErrors = [error, ...Array.from(failedPlugins).filter((it) => it.error).map((it) => it.error)].filter(Boolean);
for (const err of allErrors) await events.emit("error", err);
await events.emit("generation:end", config, files, sources);
await events.emit("generation:summary", config, {
failedPlugins,
filesCreated: files.length,
status: "failed",
hrStart,
pluginTimings: logLevel >= _kubb_core.logLevel.verbose ? pluginTimings : void 0
});
await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
command: "generate",
kubbVersion: require_package.version,
plugins: pluginManager.plugins.map((p) => ({
name: p.name,
options: p.options
})),
hrStart,
filesCreated: files.length,
status: "failed"
}));
node_process.default.exit(1);
}
await events.emit("success", "Generation successfully", inputPath);
await events.emit("generation:end", config, files, sources);
const outputPath = node_path.default.resolve(config.root, config.output.path);
if (config.output.format) await runToolPass({
toolValue: config.output.format,
detect: _kubb_core.detectFormatter,
toolMap: _kubb_core.formatters,
toolLabel: "formatter",
successPrefix: "Formatting",
noToolMessage: "No formatter found (biome, prettier, or oxfmt). Skipping formatting.",
configName: config.name,
outputPath,
logLevel,
events,
onStart: () => events.emit("format:start"),
onEnd: () => events.emit("format:end")
});
if (config.output.lint) await runToolPass({
toolValue: config.output.lint,
detect: _kubb_core.detectLinter,
toolMap: _kubb_core.linters,
toolLabel: "linter",
successPrefix: "Linting",
noToolMessage: "No linter found (biome, oxlint, or eslint). Skipping linting.",
configName: config.name,
outputPath,
logLevel,
events,
onStart: () => events.emit("lint:start"),
onEnd: () => events.emit("lint:end")
});
if (config.hooks) {
await events.emit("hooks:start");
await executeHooks({
hooks: config.hooks,
events
});
await events.emit("hooks:end");
}
await events.emit("generation:summary", config, {
failedPlugins,
filesCreated: files.length,
status: "success",
hrStart,
pluginTimings
});
await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
command: "generate",
kubbVersion: require_package.version,
plugins: pluginManager.plugins.map((p) => ({
name: p.name,
options: p.options
})),
hrStart,
filesCreated: files.length,
status: "success"
}));
}
async function runGenerateCommand({ input, configPath, logLevel: logLevelKey, watch }) {
const logLevel = _kubb_core.logLevel[logLevelKey] ?? _kubb_core.logLevel.info;
const events = new AsyncEventEmitter();
const promiseManager = new _kubb_core.PromiseManager();
await setupLogger(events, { logLevel });
await require_telemetry.executeIfOnline(async () => {
try {
const latestVersion = (await (await fetch(require_constants.KUBB_NPM_PACKAGE_URL)).json()).version;
if (latestVersion && require_package.version < latestVersion) await events.emit("version:new", require_package.version, latestVersion);
} catch {}
});
try {
const result = await getCosmiConfig("kubb", configPath);
const configs = await (0, _kubb_core.getConfigs)(result.config, { input });
await events.emit("config:start");
await events.emit("info", "Config loaded", node_path.default.relative(node_process.default.cwd(), result.filepath));
await events.emit("success", "Config loaded successfully", node_path.default.relative(node_process.default.cwd(), result.filepath));
await events.emit("config:end", configs);
await events.emit("lifecycle:start", require_package.version);
const promises = configs.map((config) => {
return async () => {
if ((0, _kubb_core.isInputPath)(config) && watch) {
await startWatcher([input || config.input.path], async (paths) => {
events.removeAll();
await generate({
input,
config,
logLevel,
events
});
_clack_prompts.log.step((0, node_util.styleText)("yellow", `Watching for changes in ${paths.join(" and ")}`));
});
return;
}
await generate({
input,
config,
logLevel,
events
});
};
});
await promiseManager.run("seq", promises);
await events.emit("lifecycle:end");
} catch (error) {
await events.emit("error", require_errors.toError(error));
node_process.default.exit(1);
}
}
//#endregion
exports.runGenerateCommand = runGenerateCommand;
//# sourceMappingURL=generate-DyK2S7hv.cjs.map

Sorry, the diff of this file is too big to display

import "./chunk--u3MIqq1.js";
import { n as toCause, r as toError } from "./errors-6mF_WKxg.js";
import { a as canUseTTY, i as executeIfOnline, o as isGitHubActions, r as sendTelemetry, t as buildTelemetryEvent } from "./telemetry-CHWsjyeK.js";
import { n as tokenize } from "./shell-DqqWsHCD.js";
import { t as version } from "./package-7k6Ul15n.js";
import { i as WATCHER_IGNORED_PATHS, r as SUMMARY_SEPARATOR, t as KUBB_NPM_PACKAGE_URL } from "./constants-CM3dJzjK.js";
import { styleText } from "node:util";
import { EventEmitter } from "node:events";
import { createHash } from "node:crypto";
import "node:fs";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import path, { dirname, relative, resolve } from "node:path";
import process$1 from "node:process";
import * as clack from "@clack/prompts";
import { PromiseManager, defineLogger, detectFormatter, detectLinter, formatters, getConfigs, isInputPath, linters, logLevel, safeBuild, setup } from "@kubb/core";
import { NonZeroExitError, x } from "tinyexec";
import { Writable } from "node:stream";
import { cosmiconfig } from "cosmiconfig";
import { createJiti } from "jiti";
//#region ../../internals/utils/src/asyncEventEmitter.ts
/**
* A typed EventEmitter that awaits all async listeners before resolving.
* Wraps Node's `EventEmitter` with full TypeScript event-map inference.
*/
var AsyncEventEmitter = class {
/**
* `maxListener` controls the maximum number of listeners per event before Node emits a memory-leak warning.
* @default 10
*/
constructor(maxListener = 10) {
this.#emitter.setMaxListeners(maxListener);
}
#emitter = new EventEmitter();
/**
* Emits an event and awaits all registered listeners in parallel.
* Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
*/
async emit(eventName, ...eventArgs) {
const listeners = this.#emitter.listeners(eventName);
if (listeners.length === 0) return;
await Promise.all(listeners.map(async (listener) => {
try {
return await listener(...eventArgs);
} catch (err) {
let serializedArgs;
try {
serializedArgs = JSON.stringify(eventArgs);
} catch {
serializedArgs = String(eventArgs);
}
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
}
}));
}
/** Registers a persistent listener for the given event. */
on(eventName, handler) {
this.#emitter.on(eventName, handler);
}
/** Registers a one-shot listener that removes itself after the first invocation. */
onOnce(eventName, handler) {
const wrapper = (...args) => {
this.off(eventName, wrapper);
return handler(...args);
};
this.on(eventName, wrapper);
}
/** Removes a previously registered listener. */
off(eventName, handler) {
this.#emitter.off(eventName, handler);
}
/** Removes all listeners from every event channel. */
removeAll() {
this.#emitter.removeAllListeners();
}
};
//#endregion
//#region ../../internals/utils/src/time.ts
/**
* Calculates elapsed time in milliseconds from a high-resolution start time.
* Rounds to 2 decimal places to provide sub-millisecond precision without noise.
*/
function getElapsedMs(hrStart) {
const [seconds, nanoseconds] = process.hrtime(hrStart);
const ms = seconds * 1e3 + nanoseconds / 1e6;
return Math.round(ms * 100) / 100;
}
/**
* Converts a millisecond duration into a human-readable string.
* Adjusts units (ms, s, m s) based on the magnitude of the duration.
*/
function formatMs(ms) {
if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
return `${Math.round(ms)}ms`;
}
/**
* Convenience helper: formats the elapsed time since `hrStart` in one step.
*/
function formatHrtime(hrStart) {
return formatMs(getElapsedMs(hrStart));
}
//#endregion
//#region ../../internals/utils/src/colors.ts
/**
* Parses a CSS hex color string (`#RGB`) into its RGB channels.
* Falls back to `255` for any channel that cannot be parsed.
*/
function parseHex(color) {
const int = Number.parseInt(color.replace("#", ""), 16);
return Number.isNaN(int) ? {
r: 255,
g: 255,
b: 255
} : {
r: int >> 16 & 255,
g: int >> 8 & 255,
b: int & 255
};
}
/**
* Returns a function that wraps a string in a 24-bit ANSI true-color escape sequence
* for the given hex color.
*/
function hex(color) {
const { r, g, b } = parseHex(color);
return (text) => `\x1b[38;2;${r};${g};${b}m${text}\x1b[0m`;
}
function gradient(colorStops, text) {
const chars = text.split("");
return chars.map((char, i) => {
const t = chars.length <= 1 ? 0 : i / (chars.length - 1);
const seg = Math.min(Math.floor(t * (colorStops.length - 1)), colorStops.length - 2);
const lt = t * (colorStops.length - 1) - seg;
const from = parseHex(colorStops[seg]);
const to = parseHex(colorStops[seg + 1]);
return `\x1b[38;2;${Math.round(from.r + (to.r - from.r) * lt)};${Math.round(from.g + (to.g - from.g) * lt)};${Math.round(from.b + (to.b - from.b) * lt)}m${char}\x1b[0m`;
}).join("");
}
/** ANSI color functions for each part of the Kubb mascot illustration. */
const palette = {
lid: hex("#F55A17"),
woodTop: hex("#F5A217"),
woodMid: hex("#F58517"),
woodBase: hex("#B45309"),
eye: hex("#FFFFFF"),
highlight: hex("#adadc6"),
blush: hex("#FDA4AF")
};
/**
* Generates the Kubb mascot welcome banner.
*/
function getIntro({ title, description, version, areEyesOpen }) {
const kubbVersion = gradient([
"#F58517",
"#F5A217",
"#F55A17"
], `KUBB v${version}`);
const eyeTop = areEyesOpen ? palette.eye("█▀█") : palette.eye("───");
const eyeBottom = areEyesOpen ? palette.eye("▀▀▀") : palette.eye("───");
return `
${palette.lid("▄▄▄▄▄▄▄▄▄▄▄▄▄")}
${palette.woodTop("█ ")}${palette.highlight("▄▄")}${palette.woodTop(" ")}${palette.highlight("▄▄")}${palette.woodTop(" █")} ${kubbVersion}
${palette.woodMid("█ ")}${eyeTop}${palette.woodMid(" ")}${eyeTop}${palette.woodMid(" █")} ${styleText("gray", title)}
${palette.woodMid("█ ")}${eyeBottom}${palette.woodMid(" ")}${palette.blush("◡")}${palette.woodMid(" ")}${eyeBottom}${palette.woodMid(" █")} ${styleText("yellow", "➜")} ${styleText("white", description)}
${palette.woodBase("▀▀▀▀▀▀▀▀▀▀▀▀▀")}
`;
}
/** ANSI color names available for terminal output. */
const randomColors = [
"black",
"red",
"green",
"yellow",
"blue",
"white",
"magenta",
"cyan",
"gray"
];
/**
* Returns the text wrapped in a deterministic ANSI color derived from the text's SHA-256 hash.
*/
function randomCliColor(text) {
if (!text) return "";
return styleText(randomColors[createHash("sha256").update(text).digest().readUInt32BE(0) % randomColors.length] ?? "white", text);
}
/**
* Formats a millisecond duration with an ANSI color based on thresholds:
* green ≤ 500 ms · yellow ≤ 1 000 ms · red > 1 000 ms
*/
function formatMsWithColor(ms) {
const formatted = formatMs(ms);
if (ms <= 500) return styleText("green", formatted);
if (ms <= 1e3) return styleText("yellow", formatted);
return styleText("red", formatted);
}
//#endregion
//#region ../../internals/utils/src/fs.ts
/**
* Writes `data` to `path`, trimming leading/trailing whitespace before saving.
* Skips the write and returns `undefined` when the trimmed content is empty or
* identical to what is already on disk.
* Creates any missing parent directories automatically.
* When `sanity` is `true`, re-reads the file after writing and throws if the
* content does not match.
*/
async function write(path, data, options = {}) {
const trimmed = data.trim();
if (trimmed === "") return void 0;
const resolved = resolve(path);
if (typeof Bun !== "undefined") {
const file = Bun.file(resolved);
if ((await file.exists() ? await file.text() : null) === trimmed) return void 0;
await Bun.write(resolved, trimmed);
return trimmed;
}
try {
if (await readFile(resolved, { encoding: "utf-8" }) === trimmed) return void 0;
} catch {}
await mkdir(dirname(resolved), { recursive: true });
await writeFile(resolved, trimmed, { encoding: "utf-8" });
if (options.sanity) {
const savedData = await readFile(resolved, { encoding: "utf-8" });
if (savedData !== trimmed) throw new Error(`Sanity check failed for ${path}\n\nData[${data.length}]:\n${data}\n\nSaved[${savedData.length}]:\n${savedData}\n`);
return savedData;
}
return trimmed;
}
//#endregion
//#region src/utils/getSummary.ts
function getSummary({ failedPlugins, filesCreated, status, hrStart, config, pluginTimings }) {
const duration = formatHrtime(hrStart);
const pluginsCount = config.plugins?.length ?? 0;
const successCount = pluginsCount - failedPlugins.size;
const meta = {
plugins: status === "success" ? `${styleText("green", `${successCount} successful`)}, ${pluginsCount} total` : `${styleText("green", `${successCount} successful`)}, ${styleText("red", `${failedPlugins.size} failed`)}, ${pluginsCount} total`,
pluginsFailed: status === "failed" ? [...failedPlugins].map(({ plugin }) => randomCliColor(plugin.name)).join(", ") : void 0,
filesCreated,
time: styleText("green", duration),
output: path.isAbsolute(config.root) ? path.resolve(config.root, config.output.path) : config.root
};
const labels = {
plugins: "Plugins:",
failed: "Failed:",
generated: "Generated:",
pluginTimings: "Plugin Timings:",
output: "Output:"
};
const maxLength = Math.max(0, ...[...Object.values(labels), ...pluginTimings ? Array.from(pluginTimings.keys()) : []].map((s) => s.length));
const summaryLines = [];
summaryLines.push(`${labels.plugins.padEnd(maxLength + 2)} ${meta.plugins}`);
if (meta.pluginsFailed) summaryLines.push(`${labels.failed.padEnd(maxLength + 2)} ${meta.pluginsFailed}`);
summaryLines.push(`${labels.generated.padEnd(maxLength + 2)} ${meta.filesCreated} files in ${meta.time}`);
if (pluginTimings && pluginTimings.size > 0) {
const sortedTimings = Array.from(pluginTimings.entries()).sort((a, b) => b[1] - a[1]);
summaryLines.push(`${labels.pluginTimings}`);
sortedTimings.forEach(([name, time]) => {
const timeStr = time >= 1e3 ? `${(time / 1e3).toFixed(2)}s` : `${Math.round(time)}ms`;
const barLength = Math.min(Math.ceil(time / 100), 10);
const bar = styleText("dim", "█".repeat(barLength));
summaryLines.push(`${styleText("dim", "•")} ${name.padEnd(maxLength + 1)}${bar} ${timeStr}`);
});
}
summaryLines.push(`${labels.output.padEnd(maxLength + 2)} ${meta.output}`);
return summaryLines;
}
//#endregion
//#region src/utils/runHook.ts
/**
* Execute a hook command, emit debug/hook:end events, and forward output to
* an optional HookOutputSink. All three logger adapters share this function
* so the process-spawning logic lives in exactly one place.
*/
async function runHook({ id, command, args, commandWithArgs, context, stream = false, sink }) {
try {
const proc = x(command, [...args ?? []], {
nodeOptions: { detached: true },
throwOnError: true
});
if (stream && sink?.onLine) for await (const line of proc) sink.onLine(line);
const result = await proc;
await context.emit("debug", {
date: /* @__PURE__ */ new Date(),
logs: [result.stdout.trimEnd()]
});
await context.emit("hook:end", {
command,
args,
id,
success: true,
error: null
});
} catch (err) {
if (!(err instanceof NonZeroExitError)) {
await context.emit("hook:end", {
command,
args,
id,
success: false,
error: toError(err)
});
await context.emit("error", toError(err));
return;
}
const stderr = err.output?.stderr ?? "";
const stdout = err.output?.stdout ?? "";
await context.emit("debug", {
date: /* @__PURE__ */ new Date(),
logs: [stdout, stderr].filter(Boolean)
});
if (stderr) sink?.onStderr?.(stderr);
if (stdout) sink?.onStdout?.(stdout);
const errorMessage = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
await context.emit("hook:end", {
command,
args,
id,
success: false,
error: errorMessage
});
await context.emit("error", errorMessage);
}
}
//#endregion
//#region src/utils/Writables.ts
var ClackWritable = class extends Writable {
taskLog;
constructor(taskLog, opts) {
super(opts);
this.taskLog = taskLog;
}
_write(chunk, _encoding, callback) {
this.taskLog.message(`${styleText("dim", chunk.toString())}`);
callback();
}
};
//#endregion
//#region src/loggers/clackLogger.ts
/**
* Clack adapter for local TTY environments
* Provides a beautiful CLI UI with flat structure inspired by Claude's CLI patterns
*/
const clackLogger = defineLogger({
name: "clack",
install(context, options) {
const logLevel$8 = options?.logLevel ?? logLevel.info;
const state = {
totalPlugins: 0,
completedPlugins: 0,
failedPlugins: 0,
totalFiles: 0,
processedFiles: 0,
hrStart: process$1.hrtime(),
spinner: clack.spinner(),
isSpinning: false,
activeProgress: /* @__PURE__ */ new Map()
};
function reset() {
for (const [_key, active] of state.activeProgress) {
if (active.interval) clearInterval(active.interval);
active.progressBar?.stop();
}
state.totalPlugins = 0;
state.completedPlugins = 0;
state.failedPlugins = 0;
state.totalFiles = 0;
state.processedFiles = 0;
state.hrStart = process$1.hrtime();
state.spinner = clack.spinner();
state.isSpinning = false;
state.activeProgress.clear();
}
function showProgressStep() {
if (logLevel$8 <= logLevel.silent) return;
const line = buildProgressLine(state);
if (line) clack.log.step(getMessage(line));
}
function getMessage(message) {
return formatMessage(message, logLevel$8);
}
function startSpinner(text) {
state.spinner.start(text);
state.isSpinning = true;
}
function stopSpinner(text) {
state.spinner.stop(text);
state.isSpinning = false;
}
context.on("info", (message, info = "") => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage([
styleText("blue", "ℹ"),
message,
styleText("dim", info)
].join(" "));
if (state.isSpinning) state.spinner.message(text);
else clack.log.info(text);
});
context.on("success", (message, info = "") => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage([
styleText("blue", "✓"),
message,
logLevel$8 >= logLevel.info ? styleText("dim", info) : void 0
].filter(Boolean).join(" "));
if (state.isSpinning) stopSpinner(text);
else clack.log.success(text);
});
context.on("warn", (message, info) => {
if (logLevel$8 < logLevel.warn) return;
const text = getMessage([
styleText("yellow", "⚠"),
message,
logLevel$8 >= logLevel.info && info ? styleText("dim", info) : void 0
].filter(Boolean).join(" "));
clack.log.warn(text);
});
context.on("error", (error) => {
const caused = toCause(error);
const text = [styleText("red", "✗"), error.message].join(" ");
if (state.isSpinning) stopSpinner(getMessage(text));
else clack.log.error(getMessage(text));
if (logLevel$8 >= logLevel.debug && error.stack) {
const frames = error.stack.split("\n").slice(1, 4);
for (const frame of frames) clack.log.message(getMessage(styleText("dim", frame.trim())));
if (caused?.stack) {
clack.log.message(styleText("dim", `└─ caused by ${caused.message}`));
const frames = caused.stack.split("\n").slice(1, 4);
for (const frame of frames) clack.log.message(getMessage(` ${styleText("dim", frame.trim())}`));
}
}
});
context.on("version:new", (version, latestVersion) => {
if (logLevel$8 <= logLevel.silent) return;
try {
clack.box(`\`v${version}\` → \`v${latestVersion}\`
Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
width: "auto",
formatBorder: (s) => styleText("yellow", s),
rounded: true,
withGuide: false,
contentAlign: "center",
titleAlign: "center"
});
} catch {
console.log(`Update available for Kubb: v${version} → v${latestVersion}`);
console.log("Run `npm install -g @kubb/cli` to update");
}
});
context.on("lifecycle:start", async (version) => {
console.log(`\n${getIntro({
title: "The ultimate toolkit for working with APIs",
description: "Ready to start",
version,
areEyesOpen: true
})}\n`);
reset();
});
context.on("config:start", () => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage("Configuration started");
clack.intro(text);
startSpinner(getMessage("Configuration loading"));
});
context.on("config:end", (_configs) => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage("Configuration completed");
clack.outro(text);
});
context.on("generation:start", (config) => {
reset();
state.totalPlugins = config.plugins?.length ?? 0;
const text = getMessage(["Generation started", config.name ? `for ${styleText("dim", config.name)}` : void 0].filter(Boolean).join(" "));
clack.intro(text);
});
context.on("plugin:start", (plugin) => {
if (logLevel$8 <= logLevel.silent) return;
stopSpinner();
const progressBar = clack.progress({
style: "block",
max: 100,
size: 30
});
const text = getMessage(`Generating ${styleText("bold", plugin.name)}`);
progressBar.start(text);
const interval = setInterval(() => {
progressBar.advance();
}, 100);
state.activeProgress.set(plugin.name, {
progressBar,
interval
});
});
context.on("plugin:end", (plugin, { duration, success }) => {
stopSpinner();
const active = state.activeProgress.get(plugin.name);
if (!active || logLevel$8 === logLevel.silent) return;
clearInterval(active.interval);
if (success) state.completedPlugins++;
else state.failedPlugins++;
const durationStr = formatMsWithColor(duration);
const text = getMessage(success ? `${styleText("bold", plugin.name)} completed in ${durationStr}` : `${styleText("bold", plugin.name)} failed in ${styleText("red", formatMs(duration))}`);
active.progressBar.stop(text);
state.activeProgress.delete(plugin.name);
showProgressStep();
});
context.on("files:processing:start", (files) => {
if (logLevel$8 <= logLevel.silent) return;
stopSpinner();
state.totalFiles = files.length;
state.processedFiles = 0;
const text = `Writing ${files.length} files`;
const progressBar = clack.progress({
style: "block",
max: files.length,
size: 30
});
context.emit("info", text);
progressBar.start(getMessage(text));
state.activeProgress.set("files", { progressBar });
});
context.on("file:processing:update", ({ file, config }) => {
if (logLevel$8 <= logLevel.silent) return;
stopSpinner();
state.processedFiles++;
const text = `Writing ${relative(config.root, file.path)}`;
const active = state.activeProgress.get("files");
if (!active) return;
active.progressBar.advance(void 0, text);
});
context.on("files:processing:end", () => {
if (logLevel$8 <= logLevel.silent) return;
stopSpinner();
const text = getMessage("Files written successfully");
const active = state.activeProgress.get("files");
if (!active) return;
active.progressBar.stop(text);
state.activeProgress.delete("files");
showProgressStep();
});
context.on("generation:end", (config) => {
const text = getMessage(config.name ? `Generation completed for ${styleText("dim", config.name)}` : "Generation completed");
clack.outro(text);
});
context.on("format:start", () => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage("Format started");
clack.intro(text);
});
context.on("format:end", () => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage("Format completed");
clack.outro(text);
});
context.on("lint:start", () => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage("Lint started");
clack.intro(text);
});
context.on("lint:end", () => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage("Lint completed");
clack.outro(text);
});
context.on("hook:start", async ({ id, command, args }) => {
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${styleText("dim", commandWithArgs)} started`);
if (!id) return;
if (logLevel$8 <= logLevel.silent) {
await runHook({
id,
command,
args,
commandWithArgs,
context,
sink: {
onStderr: (s) => console.error(s),
onStdout: (s) => console.log(s)
}
});
return;
}
clack.intro(text);
const logger = clack.taskLog({ title: getMessage(["Executing hook", logLevel$8 >= logLevel.info ? styleText("dim", commandWithArgs) : void 0].filter(Boolean).join(" ")) });
const writable = new ClackWritable(logger);
await runHook({
id,
command,
args,
commandWithArgs,
context,
stream: true,
sink: {
onLine: (line) => writable.write(line),
onStderr: (s) => logger.error(s),
onStdout: (s) => logger.message(s)
}
});
});
context.on("hook:end", ({ command, args }) => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage(`Hook ${styleText("dim", formatCommandWithArgs(command, args))} successfully executed`);
clack.outro(text);
});
context.on("generation:summary", (config, { pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
const summary = getSummary({
failedPlugins,
filesCreated,
config,
status,
hrStart,
pluginTimings: logLevel$8 >= logLevel.verbose ? pluginTimings : void 0
});
const title = config.name || "";
summary.unshift("\n");
summary.push("\n");
const borderColor = status === "success" ? "green" : "red";
try {
clack.box(summary.join("\n"), getMessage(title), {
width: "auto",
formatBorder: (s) => styleText(borderColor, s),
rounded: true,
withGuide: false,
contentAlign: "left",
titleAlign: "center"
});
} catch {
console.log(summary.join("\n"));
}
});
context.on("lifecycle:end", () => {
reset();
});
}
});
//#endregion
//#region src/loggers/fileSystemLogger.ts
/**
* FileSystem logger for debug log persistence
* Captures debug and verbose events and writes them to files in .kubb directory
*
* Note: Logs are written on lifecycle:end or process exit. If the process crashes
* before these events, some cached logs may be lost.
*/
const fileSystemLogger = defineLogger({
name: "filesystem",
install(context) {
const state = {
cachedLogs: /* @__PURE__ */ new Set(),
startDate: Date.now()
};
function reset() {
state.cachedLogs = /* @__PURE__ */ new Set();
state.startDate = Date.now();
}
async function writeLogs(name) {
if (state.cachedLogs.size === 0) return [];
const files = {};
for (const log of state.cachedLogs) {
const baseName = log.fileName || `${[
"kubb",
name,
state.startDate
].filter(Boolean).join("-")}.log`;
const pathName = resolve(process$1.cwd(), ".kubb", baseName);
if (!files[pathName]) files[pathName] = [];
if (log.logs.length > 0) {
const timestamp = log.date.toLocaleString();
files[pathName].push(`[${timestamp}]\n${log.logs.join("\n")}`);
}
}
await Promise.all(Object.entries(files).map(([fileName, logs]) => write(fileName, logs.join("\n\n"))));
return Object.keys(files);
}
context.on("info", (message, info) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`ℹ ${message} ${info}`]
});
});
context.on("success", (message, info) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`✓ ${message} ${info}`]
});
});
context.on("warn", (message, info) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`⚠ ${message} ${info}`]
});
});
context.on("error", (error) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`✗ ${error.message}`, error.stack || "unknown stack"]
});
});
context.on("debug", (message) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: message.logs
});
});
context.on("plugin:start", (plugin) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`Generating ${plugin.name}`]
});
});
context.on("plugin:end", (plugin, { duration, success }) => {
const durationStr = formatMs(duration);
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`]
});
});
context.on("files:processing:start", (files) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`Start ${files.length} writing:`, ...files.map((file) => file.path)]
});
});
context.on("generation:end", async (config) => {
const writtenFilePaths = await writeLogs(config.name);
if (writtenFilePaths.length > 0) {
const files = writtenFilePaths.map((f) => relative(process$1.cwd(), f));
await context.emit("info", "Debug files written to:", files.join(", "));
}
reset();
});
const exitHandler = () => {
if (state.cachedLogs.size > 0) writeLogs().catch(() => {});
};
process$1.once("exit", exitHandler);
process$1.once("SIGINT", exitHandler);
process$1.once("SIGTERM", exitHandler);
}
});
//#endregion
//#region src/loggers/githubActionsLogger.ts
/**
* GitHub Actions adapter for CI environments
* Uses Github group annotations for collapsible sections
*/
const githubActionsLogger = defineLogger({
name: "github-actions",
install(context, options) {
const logLevel$7 = options?.logLevel ?? logLevel.info;
const state = {
totalPlugins: 0,
completedPlugins: 0,
failedPlugins: 0,
totalFiles: 0,
processedFiles: 0,
hrStart: process.hrtime(),
currentConfigs: []
};
function reset() {
state.totalPlugins = 0;
state.completedPlugins = 0;
state.failedPlugins = 0;
state.totalFiles = 0;
state.processedFiles = 0;
state.hrStart = process.hrtime();
state.currentConfigs = [];
}
function showProgressStep() {
if (logLevel$7 <= logLevel.silent) return;
const line = buildProgressLine(state);
if (line) console.log(getMessage(line));
}
function getMessage(message) {
return formatMessage(message, logLevel$7);
}
function openGroup(name) {
console.log(`::group::${name}`);
}
function closeGroup(_name) {
console.log("::endgroup::");
}
context.on("info", (message, info = "") => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage([
styleText("blue", "ℹ"),
message,
styleText("dim", info)
].join(" "));
console.log(text);
});
context.on("success", (message, info = "") => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage([
styleText("blue", "✓"),
message,
logLevel$7 >= logLevel.info ? styleText("dim", info) : void 0
].filter(Boolean).join(" "));
console.log(text);
});
context.on("warn", (message, info = "") => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage([
styleText("yellow", "⚠"),
message,
logLevel$7 >= logLevel.info ? styleText("dim", info) : void 0
].filter(Boolean).join(" "));
console.warn(`::warning::${text}`);
});
context.on("error", (error) => {
const caused = toCause(error);
if (logLevel$7 <= logLevel.silent) return;
const message = error.message || String(error);
console.error(`::error::${message}`);
if (logLevel$7 >= logLevel.debug && error.stack) {
const frames = error.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(styleText("dim", frame.trim())));
if (caused?.stack) {
console.log(styleText("dim", `└─ caused by ${caused.message}`));
const frames = caused.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(` ${styleText("dim", frame.trim())}`));
}
}
});
context.on("lifecycle:start", (version) => {
console.log(styleText("yellow", `Kubb ${version} 🧩`));
reset();
});
context.on("config:start", () => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Configuration started");
openGroup("Configuration");
console.log(text);
});
context.on("config:end", (configs) => {
state.currentConfigs = configs;
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Configuration completed");
console.log(text);
closeGroup("Configuration");
});
context.on("generation:start", (config) => {
reset();
state.totalPlugins = config.plugins?.length ?? 0;
const text = config.name ? `Generation for ${styleText("bold", config.name)}` : "Generation";
if (state.currentConfigs.length > 1) openGroup(text);
if (state.currentConfigs.length === 1) console.log(getMessage(text));
});
context.on("plugin:start", (plugin) => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage(`Generating ${styleText("bold", plugin.name)}`);
if (state.currentConfigs.length === 1) openGroup(`Plugin: ${plugin.name}`);
console.log(text);
});
context.on("plugin:end", (plugin, { duration, success }) => {
if (logLevel$7 <= logLevel.silent) return;
if (success) state.completedPlugins++;
else state.failedPlugins++;
const durationStr = formatMsWithColor(duration);
const text = getMessage(success ? `${styleText("bold", plugin.name)} completed in ${durationStr}` : `${styleText("bold", plugin.name)} failed in ${styleText("red", formatMs(duration))}`);
console.log(text);
if (state.currentConfigs.length > 1) console.log(" ");
if (state.currentConfigs.length === 1) closeGroup(`Plugin: ${plugin.name}`);
showProgressStep();
});
context.on("files:processing:start", (files) => {
if (logLevel$7 <= logLevel.silent) return;
state.totalFiles = files.length;
state.processedFiles = 0;
if (state.currentConfigs.length === 1) openGroup("File Generation");
const text = getMessage(`Writing ${files.length} files`);
console.log(text);
});
context.on("files:processing:end", () => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Files written successfully");
console.log(text);
if (state.currentConfigs.length === 1) closeGroup("File Generation");
showProgressStep();
});
context.on("file:processing:update", () => {
if (logLevel$7 <= logLevel.silent) return;
state.processedFiles++;
});
context.on("generation:end", (config) => {
const text = getMessage(config.name ? `${styleText("blue", "✓")} Generation completed for ${styleText("dim", config.name)}` : `${styleText("blue", "✓")} Generation completed`);
console.log(text);
});
context.on("format:start", () => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Format started");
if (state.currentConfigs.length === 1) openGroup("Formatting");
console.log(text);
});
context.on("format:end", () => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Format completed");
console.log(text);
if (state.currentConfigs.length === 1) closeGroup("Formatting");
});
context.on("lint:start", () => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Lint started");
if (state.currentConfigs.length === 1) openGroup("Linting");
console.log(text);
});
context.on("lint:end", () => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Lint completed");
console.log(text);
if (state.currentConfigs.length === 1) closeGroup("Linting");
});
context.on("hook:start", async ({ id, command, args }) => {
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${styleText("dim", commandWithArgs)} started`);
if (logLevel$7 > logLevel.silent) {
if (state.currentConfigs.length === 1) openGroup(`Hook ${commandWithArgs}`);
console.log(text);
}
if (!id) return;
await runHook({
id,
command,
args,
commandWithArgs,
context,
sink: {
onStdout: logLevel$7 > logLevel.silent ? (s) => console.log(s) : void 0,
onStderr: logLevel$7 > logLevel.silent ? (s) => console.error(`::error::${s}`) : void 0
}
});
});
context.on("hook:end", ({ command, args }) => {
if (logLevel$7 <= logLevel.silent) return;
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${styleText("dim", commandWithArgs)} completed`);
console.log(text);
if (state.currentConfigs.length === 1) closeGroup(`Hook ${commandWithArgs}`);
});
context.on("generation:summary", (config, { status, hrStart, failedPlugins }) => {
const pluginsCount = config.plugins?.length ?? 0;
const successCount = pluginsCount - failedPlugins.size;
const duration = formatHrtime(hrStart);
if (state.currentConfigs.length > 1) console.log(" ");
console.log(status === "success" ? `Kubb Summary: ${styleText("blue", "✓")} ${`${successCount} successful`}, ${pluginsCount} total, ${styleText("green", duration)}` : `Kubb Summary: ${styleText("blue", "✓")} ${`${successCount} successful`}, ✗ ${`${failedPlugins.size} failed`}, ${pluginsCount} total, ${styleText("green", duration)}`);
if (state.currentConfigs.length > 1) closeGroup(config.name ? `Generation for ${styleText("bold", config.name)}` : "Generation");
});
context.on("lifecycle:end", () => {
reset();
});
}
});
//#endregion
//#region src/loggers/plainLogger.ts
/**
* Plain console adapter for non-TTY environments
* Simple console.log output with indentation
*/
const plainLogger = defineLogger({
name: "plain",
install(context, options) {
const logLevel$6 = options?.logLevel ?? logLevel.info;
function getMessage(message) {
return formatMessage(message, logLevel$6);
}
context.on("info", (message, info) => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage([
"ℹ",
message,
info
].join(" "));
console.log(text);
});
context.on("success", (message, info = "") => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage([
"✓",
message,
logLevel$6 >= logLevel.info ? info : void 0
].filter(Boolean).join(" "));
console.log(text);
});
context.on("warn", (message, info) => {
if (logLevel$6 < logLevel.warn) return;
const text = getMessage([
"⚠",
message,
logLevel$6 >= logLevel.info ? info : void 0
].filter(Boolean).join(" "));
console.log(text);
});
context.on("error", (error) => {
const caused = toCause(error);
const text = getMessage(["✗", error.message].join(" "));
console.log(text);
if (logLevel$6 >= logLevel.debug && error.stack) {
const frames = error.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(frame.trim()));
if (caused?.stack) {
console.log(`└─ caused by ${caused.message}`);
const frames = caused.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(` ${frame.trim()}`));
}
}
});
context.on("lifecycle:start", () => {
console.log("Kubb CLI 🧩");
});
context.on("config:start", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Configuration started");
console.log(text);
});
context.on("config:end", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Configuration completed");
console.log(text);
});
context.on("generation:start", () => {
const text = getMessage("Generation started");
console.log(text);
});
context.on("plugin:start", (plugin) => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage(`Generating ${plugin.name}`);
console.log(text);
});
context.on("plugin:end", (plugin, { duration, success }) => {
if (logLevel$6 <= logLevel.silent) return;
const durationStr = formatMs(duration);
const text = getMessage(success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`);
console.log(text);
});
context.on("files:processing:start", (files) => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage(`Writing ${files.length} files`);
console.log(text);
});
context.on("file:processing:update", ({ file, config }) => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage(`Writing ${relative(config.root, file.path)}`);
console.log(text);
});
context.on("files:processing:end", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Files written successfully");
console.log(text);
});
context.on("generation:end", (config) => {
const text = getMessage(config.name ? `Generation completed for ${config.name}` : "Generation completed");
console.log(text);
});
context.on("format:start", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Format started");
console.log(text);
});
context.on("format:end", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Format completed");
console.log(text);
});
context.on("lint:start", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Lint started");
console.log(text);
});
context.on("lint:end", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Lint completed");
console.log(text);
});
context.on("hook:start", async ({ id, command, args }) => {
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${commandWithArgs} started`);
if (logLevel$6 > logLevel.silent) console.log(text);
if (!id) return;
await runHook({
id,
command,
args,
commandWithArgs,
context,
sink: {
onStdout: logLevel$6 > logLevel.silent ? (s) => console.log(s) : void 0,
onStderr: logLevel$6 > logLevel.silent ? (s) => console.error(s) : void 0
}
});
});
context.on("hook:end", ({ command, args }) => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage(`Hook ${formatCommandWithArgs(command, args)} completed`);
console.log(text);
});
context.on("generation:summary", (config, { pluginTimings, status, hrStart, failedPlugins, filesCreated }) => {
const summary = getSummary({
failedPlugins,
filesCreated,
config,
status,
hrStart,
pluginTimings: logLevel$6 >= logLevel.verbose ? pluginTimings : void 0
});
console.log(SUMMARY_SEPARATOR);
console.log(summary.join("\n"));
console.log(SUMMARY_SEPARATOR);
});
}
});
//#endregion
//#region src/loggers/utils.ts
/**
* Optionally prefix a message with a [HH:MM:SS] timestamp when logLevel >= verbose.
* Shared across all logger adapters to avoid duplication.
*/
function formatMessage(message, logLevel$4) {
if (logLevel$4 >= logLevel.verbose) return `${styleText("dim", `[${(/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
hour12: false,
hour: "2-digit",
minute: "2-digit",
second: "2-digit"
})}]`)} ${message}`;
return message;
}
/**
* Build the progress summary line shared by clack and GitHub Actions loggers.
* Returns null when there is nothing to display.
*/
function buildProgressLine(state) {
const parts = [];
const duration = formatHrtime(state.hrStart);
if (state.totalPlugins > 0) {
const pluginStr = state.failedPlugins > 0 ? `Plugins ${styleText("green", state.completedPlugins.toString())}/${state.totalPlugins} ${styleText("red", `(${state.failedPlugins} failed)`)}` : `Plugins ${styleText("green", state.completedPlugins.toString())}/${state.totalPlugins}`;
parts.push(pluginStr);
}
if (state.totalFiles > 0) parts.push(`Files ${styleText("green", state.processedFiles.toString())}/${state.totalFiles}`);
if (parts.length === 0) return null;
parts.push(`${styleText("green", duration)} elapsed`);
return parts.join(styleText("dim", " | "));
}
/**
* Join a command and its optional args into a single display string.
* e.g. ("prettier", ["--write", "."]) → "prettier --write ."
*/
function formatCommandWithArgs(command, args) {
return args?.length ? `${command} ${args.join(" ")}` : command;
}
function detectLogger() {
if (isGitHubActions()) return "github-actions";
if (canUseTTY()) return "clack";
return "plain";
}
const logMapper = {
clack: clackLogger,
plain: plainLogger,
"github-actions": githubActionsLogger
};
async function setupLogger(context, { logLevel: logLevel$5 }) {
const type = detectLogger();
const logger = logMapper[type];
if (!logger) throw new Error(`Unknown adapter type: ${type}`);
const cleanup = await logger.install(context, { logLevel: logLevel$5 });
if (logLevel$5 >= logLevel.debug) await fileSystemLogger.install(context, { logLevel: logLevel$5 });
return cleanup;
}
//#endregion
//#region src/utils/executeHooks.ts
async function executeHooks({ hooks, events }) {
const commands = Array.isArray(hooks.done) ? hooks.done : [hooks.done].filter(Boolean);
for (const command of commands) {
const [cmd, ...args] = tokenize(command);
if (!cmd) continue;
const hookId = createHash("sha256").update(command).digest("hex");
const hookEndPromise = new Promise((resolve, reject) => {
const handler = ({ id, success, error }) => {
if (id !== hookId) return;
events.off("hook:end", handler);
if (!success) {
reject(error ?? /* @__PURE__ */ new Error(`Hook failed: ${command}`));
return;
}
events.emit("success", `${styleText("dim", command)} successfully executed`).then(resolve).catch(reject);
};
events.on("hook:end", handler);
});
await events.emit("hook:start", {
id: hookId,
command: cmd,
args
});
await hookEndPromise;
}
}
//#endregion
//#region src/utils/getCosmiConfig.ts
const jiti = createJiti(import.meta.url, {
jsx: {
runtime: "automatic",
importSource: "@kubb/react-fabric"
},
sourceMaps: true,
interopDefault: true
});
const tsLoader = async (configFile) => {
return await jiti.import(configFile, { default: true });
};
async function getCosmiConfig(moduleName, config) {
let result;
const searchPlaces = [
"package.json",
`.${moduleName}rc`,
`.${moduleName}rc.json`,
`.${moduleName}rc.yaml`,
`.${moduleName}rc.yml`,
`.${moduleName}rc.ts`,
`.${moduleName}rc.mts`,
`.${moduleName}rc.cts`,
`.${moduleName}rc.js`,
`.${moduleName}rc.mjs`,
`.${moduleName}rc.cjs`,
`${moduleName}.config.ts`,
`${moduleName}.config.mts`,
`${moduleName}.config.cts`,
`${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,
".mts": tsLoader,
".cts": tsLoader
}
});
try {
result = config ? await explorer.load(config) : await explorer.search();
} catch (error) {
throw new Error("Config failed loading", { cause: error });
}
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, cb) {
const { watch } = await import("chokidar");
watch(path, {
ignorePermissionErrors: true,
ignored: WATCHER_IGNORED_PATHS
}).on("all", async (type, file) => {
console.log(styleText("yellow", styleText("bold", `Change detected: ${type} ${file}`)));
try {
await cb(path);
} catch (_e) {
console.log(styleText("red", "Watcher failed"));
}
});
}
//#endregion
//#region src/runners/generate.ts
async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, configName, outputPath, logLevel: logLevel$1, events, onStart, onEnd }) {
await onStart();
let resolvedTool = toolValue;
if (resolvedTool === "auto") {
const detected = await detect();
if (!detected) await events.emit("warn", noToolMessage);
else {
resolvedTool = detected;
await events.emit("info", `Auto-detected ${toolLabel}: ${styleText("dim", resolvedTool)}`);
}
}
if (resolvedTool && resolvedTool !== "auto" && resolvedTool in toolMap) {
const toolConfig = toolMap[resolvedTool];
try {
const hookId = createHash("sha256").update([configName, resolvedTool].filter(Boolean).join("-")).digest("hex");
const hookEndPromise = new Promise((resolve, reject) => {
const handler = ({ id, success, error }) => {
if (id !== hookId) return;
events.off("hook:end", handler);
if (!success) {
reject(error ?? /* @__PURE__ */ new Error(`${toolConfig.errorMessage}`));
return;
}
events.emit("success", [
`${successPrefix} with ${styleText("dim", resolvedTool)}`,
logLevel$1 >= logLevel.info ? `on ${styleText("dim", outputPath)}` : void 0,
"successfully"
].filter(Boolean).join(" ")).then(resolve).catch(reject);
};
events.on("hook:end", handler);
});
await events.emit("hook:start", {
id: hookId,
command: toolConfig.command,
args: toolConfig.args(outputPath)
});
await hookEndPromise;
} catch (caughtError) {
const err = new Error(toolConfig.errorMessage);
err.cause = caughtError;
await events.emit("error", err);
}
}
await onEnd();
}
async function generate({ input, config: userConfig, events, logLevel: logLevel$2 }) {
const inputPath = input ?? ("path" in userConfig.input ? userConfig.input.path : void 0);
const hrStart = process$1.hrtime();
const config = {
...userConfig,
root: userConfig.root || process$1.cwd(),
input: inputPath ? {
...userConfig.input,
path: inputPath
} : userConfig.input,
output: {
write: true,
barrelType: "named",
extension: { ".ts": ".ts" },
format: "prettier",
...userConfig.output
}
};
await events.emit("generation:start", config);
await events.emit("info", config.name ? `Setup generation ${styleText("bold", config.name)}` : "Setup generation", inputPath);
const { sources, fabric, pluginManager } = await setup({
config,
events
});
await events.emit("info", config.name ? `Build generation ${styleText("bold", config.name)}` : "Build generation", inputPath);
const { files, failedPlugins, pluginTimings, error } = await safeBuild({
config,
events
}, {
pluginManager,
fabric,
events,
sources
});
await events.emit("info", "Load summary");
if (failedPlugins.size > 0 || error) {
const allErrors = [error, ...Array.from(failedPlugins).filter((it) => it.error).map((it) => it.error)].filter(Boolean);
for (const err of allErrors) await events.emit("error", err);
await events.emit("generation:end", config, files, sources);
await events.emit("generation:summary", config, {
failedPlugins,
filesCreated: files.length,
status: "failed",
hrStart,
pluginTimings: logLevel$2 >= logLevel.verbose ? pluginTimings : void 0
});
await sendTelemetry(buildTelemetryEvent({
command: "generate",
kubbVersion: version,
plugins: pluginManager.plugins.map((p) => ({
name: p.name,
options: p.options
})),
hrStart,
filesCreated: files.length,
status: "failed"
}));
process$1.exit(1);
}
await events.emit("success", "Generation successfully", inputPath);
await events.emit("generation:end", config, files, sources);
const outputPath = path.resolve(config.root, config.output.path);
if (config.output.format) await runToolPass({
toolValue: config.output.format,
detect: detectFormatter,
toolMap: formatters,
toolLabel: "formatter",
successPrefix: "Formatting",
noToolMessage: "No formatter found (biome, prettier, or oxfmt). Skipping formatting.",
configName: config.name,
outputPath,
logLevel: logLevel$2,
events,
onStart: () => events.emit("format:start"),
onEnd: () => events.emit("format:end")
});
if (config.output.lint) await runToolPass({
toolValue: config.output.lint,
detect: detectLinter,
toolMap: linters,
toolLabel: "linter",
successPrefix: "Linting",
noToolMessage: "No linter found (biome, oxlint, or eslint). Skipping linting.",
configName: config.name,
outputPath,
logLevel: logLevel$2,
events,
onStart: () => events.emit("lint:start"),
onEnd: () => events.emit("lint:end")
});
if (config.hooks) {
await events.emit("hooks:start");
await executeHooks({
hooks: config.hooks,
events
});
await events.emit("hooks:end");
}
await events.emit("generation:summary", config, {
failedPlugins,
filesCreated: files.length,
status: "success",
hrStart,
pluginTimings
});
await sendTelemetry(buildTelemetryEvent({
command: "generate",
kubbVersion: version,
plugins: pluginManager.plugins.map((p) => ({
name: p.name,
options: p.options
})),
hrStart,
filesCreated: files.length,
status: "success"
}));
}
async function runGenerateCommand({ input, configPath, logLevel: logLevelKey, watch }) {
const logLevel$3 = logLevel[logLevelKey] ?? logLevel.info;
const events = new AsyncEventEmitter();
const promiseManager = new PromiseManager();
await setupLogger(events, { logLevel: logLevel$3 });
await executeIfOnline(async () => {
try {
const latestVersion = (await (await fetch(KUBB_NPM_PACKAGE_URL)).json()).version;
if (latestVersion && version < latestVersion) await events.emit("version:new", version, latestVersion);
} catch {}
});
try {
const result = await getCosmiConfig("kubb", configPath);
const configs = await getConfigs(result.config, { input });
await events.emit("config:start");
await events.emit("info", "Config loaded", path.relative(process$1.cwd(), result.filepath));
await events.emit("success", "Config loaded successfully", path.relative(process$1.cwd(), result.filepath));
await events.emit("config:end", configs);
await events.emit("lifecycle:start", version);
const promises = configs.map((config) => {
return async () => {
if (isInputPath(config) && watch) {
await startWatcher([input || config.input.path], async (paths) => {
events.removeAll();
await generate({
input,
config,
logLevel: logLevel$3,
events
});
clack.log.step(styleText("yellow", `Watching for changes in ${paths.join(" and ")}`));
});
return;
}
await generate({
input,
config,
logLevel: logLevel$3,
events
});
};
});
await promiseManager.run("seq", promises);
await events.emit("lifecycle:end");
} catch (error) {
await events.emit("error", toError(error));
process$1.exit(1);
}
}
//#endregion
export { runGenerateCommand };
//# sourceMappingURL=generate-sIkyxxtw.js.map

Sorry, the diff of this file is too big to display

import "./chunk--u3MIqq1.js";
import { n as defineCommand } from "./define--M_JMcDC.js";
import { t as version } from "./package-7k6Ul15n.js";
//#region src/commands/init.ts
const command = defineCommand({
name: "init",
description: "Initialize a new Kubb project with interactive setup",
options: { yes: {
type: "boolean",
description: "Skip prompts and use default options",
short: "y",
default: false
} },
async run({ values }) {
const { runInit } = await import("./init-C-InrmSY.js");
await runInit({
yes: values.yes,
version
});
}
});
//#endregion
export { command };
//# sourceMappingURL=init-BkN1O1VV.js.map
{"version":3,"file":"init-BkN1O1VV.js","names":[],"sources":["../src/commands/init.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'init',\n description: 'Initialize a new Kubb project with interactive setup',\n options: {\n yes: { type: 'boolean', description: 'Skip prompts and use default options', short: 'y', default: false },\n },\n async run({ values }) {\n const { runInit } = await import('../runners/init.ts')\n\n await runInit({ yes: values.yes, version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAU,cAAc;CACnC,MAAM;CACN,aAAa;CACb,SAAS,EACP,KAAK;EAAE,MAAM;EAAW,aAAa;EAAwC,OAAO;EAAK,SAAS;EAAO,EAC1G;CACD,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,YAAY,MAAM,OAAO;AAEjC,QAAM,QAAQ;GAAE,KAAK,OAAO;GAAK;GAAS,CAAC;;CAE9C,CAAC"}
require("./chunk-ByKO4r7w.cjs");
const require_define = require("./define-D6Kfm7-Z.cjs");
const require_package = require("./package-m-LvDtUC.cjs");
//#region src/commands/init.ts
const command = require_define.defineCommand({
name: "init",
description: "Initialize a new Kubb project with interactive setup",
options: { yes: {
type: "boolean",
description: "Skip prompts and use default options",
short: "y",
default: false
} },
async run({ values }) {
const { runInit } = await Promise.resolve().then(() => require("./init-hmolV6B4.cjs"));
await runInit({
yes: values.yes,
version: require_package.version
});
}
});
//#endregion
exports.command = command;
//# sourceMappingURL=init-DL8L1JpC.cjs.map
{"version":3,"file":"init-DL8L1JpC.cjs","names":["defineCommand"],"sources":["../src/commands/init.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'init',\n description: 'Initialize a new Kubb project with interactive setup',\n options: {\n yes: { type: 'boolean', description: 'Skip prompts and use default options', short: 'y', default: false },\n },\n async run({ values }) {\n const { runInit } = await import('../runners/init.ts')\n\n await runInit({ yes: values.yes, version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAUA,eAAAA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,SAAS,EACP,KAAK;EAAE,MAAM;EAAW,aAAa;EAAwC,OAAO;EAAK,SAAS;EAAO,EAC1G;CACD,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,YAAY,MAAA,QAAA,SAAA,CAAA,WAAA,QAAM,sBAAA,CAAA;AAE1B,QAAM,QAAQ;GAAE,KAAK,OAAO;GAAK,SAAA,gBAAA;GAAS,CAAC;;CAE9C,CAAC"}
require("./chunk-ByKO4r7w.cjs");
const require_define = require("./define-D6Kfm7-Z.cjs");
const require_package = require("./package-m-LvDtUC.cjs");
//#region src/commands/mcp.ts
const command = require_define.defineCommand({
name: "mcp",
description: "Start the server to enable the MCP client to interact with the LLM.",
async run() {
const { runMcp } = await Promise.resolve().then(() => require("./mcp-X8kKSlov.cjs"));
await runMcp({ version: require_package.version });
}
});
//#endregion
exports.command = command;
//# sourceMappingURL=mcp-BQMtExMD.cjs.map
{"version":3,"file":"mcp-BQMtExMD.cjs","names":["defineCommand"],"sources":["../src/commands/mcp.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'mcp',\n description: 'Start the server to enable the MCP client to interact with the LLM.',\n async run() {\n const { runMcp } = await import('../runners/mcp.ts')\n\n await runMcp({ version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAUA,eAAAA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,MAAM,MAAM;EACV,MAAM,EAAE,WAAW,MAAA,QAAA,SAAA,CAAA,WAAA,QAAM,qBAAA,CAAA;AAEzB,QAAM,OAAO,EAAE,SAAA,gBAAA,SAAS,CAAC;;CAE5B,CAAC"}
import "./chunk--u3MIqq1.js";
import { n as defineCommand } from "./define--M_JMcDC.js";
import { t as version } from "./package-7k6Ul15n.js";
//#region src/commands/mcp.ts
const command = defineCommand({
name: "mcp",
description: "Start the server to enable the MCP client to interact with the LLM.",
async run() {
const { runMcp } = await import("./mcp-Cwbv3dfC.js");
await runMcp({ version });
}
});
//#endregion
export { command };
//# sourceMappingURL=mcp-DaibPZuu.js.map
{"version":3,"file":"mcp-DaibPZuu.js","names":[],"sources":["../src/commands/mcp.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'mcp',\n description: 'Start the server to enable the MCP client to interact with the LLM.',\n async run() {\n const { runMcp } = await import('../runners/mcp.ts')\n\n await runMcp({ version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAU,cAAc;CACnC,MAAM;CACN,aAAa;CACb,MAAM,MAAM;EACV,MAAM,EAAE,WAAW,MAAM,OAAO;AAEhC,QAAM,OAAO,EAAE,SAAS,CAAC;;CAE5B,CAAC"}
//#region package.json
var version = "4.37.8";
//#endregion
export { version as t };
//# sourceMappingURL=package-7k6Ul15n.js.map
{"version":3,"file":"package-7k6Ul15n.js","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
//#region package.json
var version = "4.37.8";
//#endregion
Object.defineProperty(exports, "version", {
enumerable: true,
get: function() {
return version;
}
});
//# sourceMappingURL=package-m-LvDtUC.cjs.map
{"version":3,"file":"package-m-LvDtUC.cjs","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
import "./chunk--u3MIqq1.js";
import { n as defineCommand } from "./define--M_JMcDC.js";
import { t as version } from "./package-7k6Ul15n.js";
//#region src/commands/validate.ts
const command = defineCommand({
name: "validate",
description: "Validate a Swagger/OpenAPI file",
options: { input: {
type: "string",
description: "Path to Swagger/OpenAPI file",
short: "i",
required: true
} },
async run({ values }) {
const { runValidate } = await import("./validate-BGyxLev8.js");
await runValidate({
input: values.input,
version
});
}
});
//#endregion
export { command };
//# sourceMappingURL=validate-BOjhbG3R.js.map
{"version":3,"file":"validate-BOjhbG3R.js","names":[],"sources":["../src/commands/validate.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'validate',\n description: 'Validate a Swagger/OpenAPI file',\n options: {\n input: { type: 'string', description: 'Path to Swagger/OpenAPI file', short: 'i', required: true },\n },\n async run({ values }) {\n const { runValidate } = await import('../runners/validate.ts')\n\n await runValidate({ input: values.input, version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAU,cAAc;CACnC,MAAM;CACN,aAAa;CACb,SAAS,EACP,OAAO;EAAE,MAAM;EAAU,aAAa;EAAgC,OAAO;EAAK,UAAU;EAAM,EACnG;CACD,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,gBAAgB,MAAM,OAAO;AAErC,QAAM,YAAY;GAAE,OAAO,OAAO;GAAO;GAAS,CAAC;;CAEtD,CAAC"}
require("./chunk-ByKO4r7w.cjs");
const require_define = require("./define-D6Kfm7-Z.cjs");
const require_package = require("./package-m-LvDtUC.cjs");
//#region src/commands/validate.ts
const command = require_define.defineCommand({
name: "validate",
description: "Validate a Swagger/OpenAPI file",
options: { input: {
type: "string",
description: "Path to Swagger/OpenAPI file",
short: "i",
required: true
} },
async run({ values }) {
const { runValidate } = await Promise.resolve().then(() => require("./validate-DYVo8-Fj.cjs"));
await runValidate({
input: values.input,
version: require_package.version
});
}
});
//#endregion
exports.command = command;
//# sourceMappingURL=validate-CVlSxr9b.cjs.map
{"version":3,"file":"validate-CVlSxr9b.cjs","names":["defineCommand"],"sources":["../src/commands/validate.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'validate',\n description: 'Validate a Swagger/OpenAPI file',\n options: {\n input: { type: 'string', description: 'Path to Swagger/OpenAPI file', short: 'i', required: true },\n },\n async run({ values }) {\n const { runValidate } = await import('../runners/validate.ts')\n\n await runValidate({ input: values.input, version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAUA,eAAAA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,SAAS,EACP,OAAO;EAAE,MAAM;EAAU,aAAa;EAAgC,OAAO;EAAK,UAAU;EAAM,EACnG;CACD,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,gBAAgB,MAAA,QAAA,SAAA,CAAA,WAAA,QAAM,0BAAA,CAAA;AAE9B,QAAM,YAAY;GAAE,OAAO,OAAO;GAAO,SAAA,gBAAA;GAAS,CAAC;;CAEtD,CAAC"}
+6
-6

@@ -5,3 +5,3 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });

const require_telemetry = require("./telemetry-CEm85k_X.cjs");
const require_package = require("./package-CSJQyhYO.cjs");
const require_package = require("./package-m-LvDtUC.cjs");
let node_util = require("node:util");

@@ -235,7 +235,7 @@ //#region ../../internals/utils/src/cli/schema.ts

const [{ command: generateCommand }, { command: validateCommand }, { command: mcpCommand }, { command: agentCommand }, { command: initCommand }] = await Promise.all([
Promise.resolve().then(() => require("./generate-DQ_S_FW_.cjs")),
Promise.resolve().then(() => require("./validate-BRzEtRj7.cjs")),
Promise.resolve().then(() => require("./mcp-uDMa0yKp.cjs")),
Promise.resolve().then(() => require("./agent-DyNZKnlF.cjs")),
Promise.resolve().then(() => require("./init-CibN8lng.cjs"))
Promise.resolve().then(() => require("./generate-CkyN7qeb.cjs")),
Promise.resolve().then(() => require("./validate-CVlSxr9b.cjs")),
Promise.resolve().then(() => require("./mcp-BQMtExMD.cjs")),
Promise.resolve().then(() => require("./agent-DMy_bQ-M.cjs")),
Promise.resolve().then(() => require("./init-DL8L1JpC.cjs"))
]);

@@ -242,0 +242,0 @@ await cli.run([

import "./chunk--u3MIqq1.js";
import { t as defineCLIAdapter } from "./define--M_JMcDC.js";
import { n as isTelemetryDisabled } from "./telemetry-CHWsjyeK.js";
import { t as version } from "./package-Zc7qipPx.js";
import { t as version } from "./package-7k6Ul15n.js";
import { parseArgs, styleText } from "node:util";

@@ -233,7 +233,7 @@ //#region ../../internals/utils/src/cli/schema.ts

const [{ command: generateCommand }, { command: validateCommand }, { command: mcpCommand }, { command: agentCommand }, { command: initCommand }] = await Promise.all([
import("./generate-Qcw6Ilwk.js"),
import("./validate-IUvDwpX1.js"),
import("./mcp-DwRXOXZV.js"),
import("./agent-B4l6tvKC.js"),
import("./init-DqWUHya_.js")
import("./generate-DBo220P3.js"),
import("./validate-BOjhbG3R.js"),
import("./mcp-DaibPZuu.js"),
import("./agent-BBrW4jlM.js"),
import("./init-BkN1O1VV.js")
]);

@@ -240,0 +240,0 @@ await cli.run([

{
"name": "@kubb/cli",
"version": "4.37.7",
"version": "4.37.8",
"description": "Command-line interface for Kubb, enabling easy generation of TypeScript, React-Query, Zod, and other code from OpenAPI specifications.",

@@ -61,3 +61,3 @@ "keywords": [

"tinyexec": "^1.0.4",
"@kubb/core": "4.37.7"
"@kubb/core": "4.37.8"
},

@@ -67,5 +67,5 @@ "devDependencies": {

"@internals/utils": "0.0.0",
"@kubb/agent": "4.37.7",
"@kubb/mcp": "4.37.7",
"@kubb/oas": "4.37.7"
"@kubb/agent": "4.37.8",
"@kubb/mcp": "4.37.8",
"@kubb/oas": "4.37.8"
},

@@ -72,0 +72,0 @@ "engines": {

import "./chunk--u3MIqq1.js";
import { n as defineCommand } from "./define--M_JMcDC.js";
import { t as version } from "./package-Zc7qipPx.js";
import { a as agentDefaults } from "./constants-CM3dJzjK.js";
//#endregion
//#region src/commands/agent.ts
const command = defineCommand({
name: "agent",
description: "Manage the Kubb Agent server",
subCommands: [defineCommand({
name: "start",
description: "Start the Agent server",
options: {
config: {
type: "string",
description: "Path to the Kubb config",
short: "c"
},
port: {
type: "string",
description: `Port for the server (default: ${agentDefaults.port})`,
short: "p"
},
host: {
type: "string",
description: "Host for the server",
default: agentDefaults.host
},
"allow-write": {
type: "boolean",
description: "Allow writing generated files to the filesystem. When not set, no files are written and the config patch is not persisted.",
default: false
},
"allow-all": {
type: "boolean",
description: "Grant all permissions (implies --allow-write).",
default: false
}
},
async run({ values }) {
const { runAgentStart } = await import("./agent-fcClds-t.js");
await runAgentStart({
port: values.port !== void 0 ? values.port : void 0,
host: values.host,
configPath: values.config,
allowWrite: values["allow-write"],
allowAll: values["allow-all"],
version
});
}
})]
});
//#endregion
export { command };
//# sourceMappingURL=agent-B4l6tvKC.js.map
{"version":3,"file":"agent-B4l6tvKC.js","names":["command","startCommand"],"sources":["../src/commands/agent/start.ts","../src/commands/agent.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../../package.json'\nimport { agentDefaults } from '../../constants.ts'\n\nexport const command = defineCommand({\n name: 'start',\n description: 'Start the Agent server',\n options: {\n config: { type: 'string', description: 'Path to the Kubb config', short: 'c' },\n port: { type: 'string', description: `Port for the server (default: ${agentDefaults.port})`, short: 'p' },\n host: { type: 'string', description: 'Host for the server', default: agentDefaults.host },\n 'allow-write': {\n type: 'boolean',\n description: 'Allow writing generated files to the filesystem. When not set, no files are written and the config patch is not persisted.',\n default: false,\n },\n 'allow-all': { type: 'boolean', description: 'Grant all permissions (implies --allow-write).', default: false },\n },\n async run({ values }) {\n const { runAgentStart } = await import('../../runners/agent.ts')\n\n await runAgentStart({\n port: values.port !== undefined ? values.port : undefined,\n host: values.host,\n configPath: values.config,\n allowWrite: values['allow-write'],\n allowAll: values['allow-all'],\n version,\n })\n },\n})\n","import { defineCommand } from '@internals/utils'\nimport { command as startCommand } from './agent/start.ts'\n\nexport const command = defineCommand({\n name: 'agent',\n description: 'Manage the Kubb Agent server',\n subCommands: [startCommand],\n})\n"],"mappings":";;;;;;ACGA,MAAa,UAAU,cAAc;CACnC,MAAM;CACN,aAAa;CACb,aAAa,CDFQ,cAAc;EACnC,MAAM;EACN,aAAa;EACb,SAAS;GACP,QAAQ;IAAE,MAAM;IAAU,aAAa;IAA2B,OAAO;IAAK;GAC9E,MAAM;IAAE,MAAM;IAAU,aAAa,iCAAiC,cAAc,KAAK;IAAI,OAAO;IAAK;GACzG,MAAM;IAAE,MAAM;IAAU,aAAa;IAAuB,SAAS,cAAc;IAAM;GACzF,eAAe;IACb,MAAM;IACN,aAAa;IACb,SAAS;IACV;GACD,aAAa;IAAE,MAAM;IAAW,aAAa;IAAkD,SAAS;IAAO;GAChH;EACD,MAAM,IAAI,EAAE,UAAU;GACpB,MAAM,EAAE,kBAAkB,MAAM,OAAO;AAEvC,SAAM,cAAc;IAClB,MAAM,OAAO,SAAS,KAAA,IAAY,OAAO,OAAO,KAAA;IAChD,MAAM,OAAO;IACb,YAAY,OAAO;IACnB,YAAY,OAAO;IACnB,UAAU,OAAO;IACjB;IACD,CAAC;;EAEL,CAAC,CCxB2B;CAC5B,CAAC"}
require("./chunk-ByKO4r7w.cjs");
const require_define = require("./define-D6Kfm7-Z.cjs");
const require_package = require("./package-CSJQyhYO.cjs");
const require_constants = require("./constants-BTUap0zs.cjs");
//#region src/commands/agent/start.ts
const command$1 = require_define.defineCommand({
name: "start",
description: "Start the Agent server",
options: {
config: {
type: "string",
description: "Path to the Kubb config",
short: "c"
},
port: {
type: "string",
description: `Port for the server (default: ${require_constants.agentDefaults.port})`,
short: "p"
},
host: {
type: "string",
description: "Host for the server",
default: require_constants.agentDefaults.host
},
"allow-write": {
type: "boolean",
description: "Allow writing generated files to the filesystem. When not set, no files are written and the config patch is not persisted.",
default: false
},
"allow-all": {
type: "boolean",
description: "Grant all permissions (implies --allow-write).",
default: false
}
},
async run({ values }) {
const { runAgentStart } = await Promise.resolve().then(() => require("./agent-bJ5FNFnA.cjs"));
await runAgentStart({
port: values.port !== void 0 ? values.port : void 0,
host: values.host,
configPath: values.config,
allowWrite: values["allow-write"],
allowAll: values["allow-all"],
version: require_package.version
});
}
});
//#endregion
//#region src/commands/agent.ts
const command = require_define.defineCommand({
name: "agent",
description: "Manage the Kubb Agent server",
subCommands: [command$1]
});
//#endregion
exports.command = command;
//# sourceMappingURL=agent-DyNZKnlF.cjs.map
{"version":3,"file":"agent-DyNZKnlF.cjs","names":["command","defineCommand","agentDefaults","defineCommand","startCommand"],"sources":["../src/commands/agent/start.ts","../src/commands/agent.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../../package.json'\nimport { agentDefaults } from '../../constants.ts'\n\nexport const command = defineCommand({\n name: 'start',\n description: 'Start the Agent server',\n options: {\n config: { type: 'string', description: 'Path to the Kubb config', short: 'c' },\n port: { type: 'string', description: `Port for the server (default: ${agentDefaults.port})`, short: 'p' },\n host: { type: 'string', description: 'Host for the server', default: agentDefaults.host },\n 'allow-write': {\n type: 'boolean',\n description: 'Allow writing generated files to the filesystem. When not set, no files are written and the config patch is not persisted.',\n default: false,\n },\n 'allow-all': { type: 'boolean', description: 'Grant all permissions (implies --allow-write).', default: false },\n },\n async run({ values }) {\n const { runAgentStart } = await import('../../runners/agent.ts')\n\n await runAgentStart({\n port: values.port !== undefined ? values.port : undefined,\n host: values.host,\n configPath: values.config,\n allowWrite: values['allow-write'],\n allowAll: values['allow-all'],\n version,\n })\n },\n})\n","import { defineCommand } from '@internals/utils'\nimport { command as startCommand } from './agent/start.ts'\n\nexport const command = defineCommand({\n name: 'agent',\n description: 'Manage the Kubb Agent server',\n subCommands: [startCommand],\n})\n"],"mappings":";;;;;AAIA,MAAaA,YAAUC,eAAAA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,SAAS;EACP,QAAQ;GAAE,MAAM;GAAU,aAAa;GAA2B,OAAO;GAAK;EAC9E,MAAM;GAAE,MAAM;GAAU,aAAa,iCAAiCC,kBAAAA,cAAc,KAAK;GAAI,OAAO;GAAK;EACzG,MAAM;GAAE,MAAM;GAAU,aAAa;GAAuB,SAASA,kBAAAA,cAAc;GAAM;EACzF,eAAe;GACb,MAAM;GACN,aAAa;GACb,SAAS;GACV;EACD,aAAa;GAAE,MAAM;GAAW,aAAa;GAAkD,SAAS;GAAO;EAChH;CACD,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,kBAAkB,MAAA,QAAA,SAAA,CAAA,WAAA,QAAM,uBAAA,CAAA;AAEhC,QAAM,cAAc;GAClB,MAAM,OAAO,SAAS,KAAA,IAAY,OAAO,OAAO,KAAA;GAChD,MAAM,OAAO;GACb,YAAY,OAAO;GACnB,YAAY,OAAO;GACnB,UAAU,OAAO;GACjB,SAAA,gBAAA;GACD,CAAC;;CAEL,CAAC;;;AC3BF,MAAa,UAAUC,eAAAA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,aAAa,CAACC,UAAa;CAC5B,CAAC"}
import "./chunk--u3MIqq1.js";
import { n as toCause, r as toError } from "./errors-6mF_WKxg.js";
import { a as canUseTTY, i as executeIfOnline, o as isGitHubActions, r as sendTelemetry, t as buildTelemetryEvent } from "./telemetry-CHWsjyeK.js";
import { n as tokenize } from "./shell-DqqWsHCD.js";
import { t as version } from "./package-Zc7qipPx.js";
import { i as WATCHER_IGNORED_PATHS, r as SUMMARY_SEPARATOR, t as KUBB_NPM_PACKAGE_URL } from "./constants-CM3dJzjK.js";
import { styleText } from "node:util";
import { EventEmitter } from "node:events";
import { createHash } from "node:crypto";
import "node:fs";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import path, { dirname, relative, resolve } from "node:path";
import process$1 from "node:process";
import * as clack from "@clack/prompts";
import { PromiseManager, defineLogger, detectFormatter, detectLinter, formatters, getConfigs, isInputPath, linters, logLevel, safeBuild, setup } from "@kubb/core";
import { NonZeroExitError, x } from "tinyexec";
import { Writable } from "node:stream";
import { cosmiconfig } from "cosmiconfig";
import { createJiti } from "jiti";
//#region ../../internals/utils/src/asyncEventEmitter.ts
/**
* A typed EventEmitter that awaits all async listeners before resolving.
* Wraps Node's `EventEmitter` with full TypeScript event-map inference.
*/
var AsyncEventEmitter = class {
/**
* `maxListener` controls the maximum number of listeners per event before Node emits a memory-leak warning.
* @default 10
*/
constructor(maxListener = 10) {
this.#emitter.setMaxListeners(maxListener);
}
#emitter = new EventEmitter();
/**
* Emits an event and awaits all registered listeners in parallel.
* Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
*/
async emit(eventName, ...eventArgs) {
const listeners = this.#emitter.listeners(eventName);
if (listeners.length === 0) return;
await Promise.all(listeners.map(async (listener) => {
try {
return await listener(...eventArgs);
} catch (err) {
let serializedArgs;
try {
serializedArgs = JSON.stringify(eventArgs);
} catch {
serializedArgs = String(eventArgs);
}
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
}
}));
}
/** Registers a persistent listener for the given event. */
on(eventName, handler) {
this.#emitter.on(eventName, handler);
}
/** Registers a one-shot listener that removes itself after the first invocation. */
onOnce(eventName, handler) {
const wrapper = (...args) => {
this.off(eventName, wrapper);
return handler(...args);
};
this.on(eventName, wrapper);
}
/** Removes a previously registered listener. */
off(eventName, handler) {
this.#emitter.off(eventName, handler);
}
/** Removes all listeners from every event channel. */
removeAll() {
this.#emitter.removeAllListeners();
}
};
//#endregion
//#region ../../internals/utils/src/time.ts
/**
* Calculates elapsed time in milliseconds from a high-resolution start time.
* Rounds to 2 decimal places to provide sub-millisecond precision without noise.
*/
function getElapsedMs(hrStart) {
const [seconds, nanoseconds] = process.hrtime(hrStart);
const ms = seconds * 1e3 + nanoseconds / 1e6;
return Math.round(ms * 100) / 100;
}
/**
* Converts a millisecond duration into a human-readable string.
* Adjusts units (ms, s, m s) based on the magnitude of the duration.
*/
function formatMs(ms) {
if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
return `${Math.round(ms)}ms`;
}
/**
* Convenience helper: formats the elapsed time since `hrStart` in one step.
*/
function formatHrtime(hrStart) {
return formatMs(getElapsedMs(hrStart));
}
//#endregion
//#region ../../internals/utils/src/colors.ts
/**
* Parses a CSS hex color string (`#RGB`) into its RGB channels.
* Falls back to `255` for any channel that cannot be parsed.
*/
function parseHex(color) {
const int = Number.parseInt(color.replace("#", ""), 16);
return Number.isNaN(int) ? {
r: 255,
g: 255,
b: 255
} : {
r: int >> 16 & 255,
g: int >> 8 & 255,
b: int & 255
};
}
/**
* Returns a function that wraps a string in a 24-bit ANSI true-color escape sequence
* for the given hex color.
*/
function hex(color) {
const { r, g, b } = parseHex(color);
return (text) => `\x1b[38;2;${r};${g};${b}m${text}\x1b[0m`;
}
function gradient(colorStops, text) {
const chars = text.split("");
return chars.map((char, i) => {
const t = chars.length <= 1 ? 0 : i / (chars.length - 1);
const seg = Math.min(Math.floor(t * (colorStops.length - 1)), colorStops.length - 2);
const lt = t * (colorStops.length - 1) - seg;
const from = parseHex(colorStops[seg]);
const to = parseHex(colorStops[seg + 1]);
return `\x1b[38;2;${Math.round(from.r + (to.r - from.r) * lt)};${Math.round(from.g + (to.g - from.g) * lt)};${Math.round(from.b + (to.b - from.b) * lt)}m${char}\x1b[0m`;
}).join("");
}
/** ANSI color functions for each part of the Kubb mascot illustration. */
const palette = {
lid: hex("#F55A17"),
woodTop: hex("#F5A217"),
woodMid: hex("#F58517"),
woodBase: hex("#B45309"),
eye: hex("#FFFFFF"),
highlight: hex("#adadc6"),
blush: hex("#FDA4AF")
};
/**
* Generates the Kubb mascot welcome banner.
*/
function getIntro({ title, description, version, areEyesOpen }) {
const kubbVersion = gradient([
"#F58517",
"#F5A217",
"#F55A17"
], `KUBB v${version}`);
const eyeTop = areEyesOpen ? palette.eye("█▀█") : palette.eye("───");
const eyeBottom = areEyesOpen ? palette.eye("▀▀▀") : palette.eye("───");
return `
${palette.lid("▄▄▄▄▄▄▄▄▄▄▄▄▄")}
${palette.woodTop("█ ")}${palette.highlight("▄▄")}${palette.woodTop(" ")}${palette.highlight("▄▄")}${palette.woodTop(" █")} ${kubbVersion}
${palette.woodMid("█ ")}${eyeTop}${palette.woodMid(" ")}${eyeTop}${palette.woodMid(" █")} ${styleText("gray", title)}
${palette.woodMid("█ ")}${eyeBottom}${palette.woodMid(" ")}${palette.blush("◡")}${palette.woodMid(" ")}${eyeBottom}${palette.woodMid(" █")} ${styleText("yellow", "➜")} ${styleText("white", description)}
${palette.woodBase("▀▀▀▀▀▀▀▀▀▀▀▀▀")}
`;
}
/** ANSI color names available for terminal output. */
const randomColors = [
"black",
"red",
"green",
"yellow",
"blue",
"white",
"magenta",
"cyan",
"gray"
];
/**
* Returns the text wrapped in a deterministic ANSI color derived from the text's SHA-256 hash.
*/
function randomCliColor(text) {
if (!text) return "";
return styleText(randomColors[createHash("sha256").update(text).digest().readUInt32BE(0) % randomColors.length] ?? "white", text);
}
/**
* Formats a millisecond duration with an ANSI color based on thresholds:
* green ≤ 500 ms · yellow ≤ 1 000 ms · red > 1 000 ms
*/
function formatMsWithColor(ms) {
const formatted = formatMs(ms);
if (ms <= 500) return styleText("green", formatted);
if (ms <= 1e3) return styleText("yellow", formatted);
return styleText("red", formatted);
}
//#endregion
//#region ../../internals/utils/src/fs.ts
/**
* Writes `data` to `path`, trimming leading/trailing whitespace before saving.
* Skips the write and returns `undefined` when the trimmed content is empty or
* identical to what is already on disk.
* Creates any missing parent directories automatically.
* When `sanity` is `true`, re-reads the file after writing and throws if the
* content does not match.
*/
async function write(path, data, options = {}) {
const trimmed = data.trim();
if (trimmed === "") return void 0;
const resolved = resolve(path);
if (typeof Bun !== "undefined") {
const file = Bun.file(resolved);
if ((await file.exists() ? await file.text() : null) === trimmed) return void 0;
await Bun.write(resolved, trimmed);
return trimmed;
}
try {
if (await readFile(resolved, { encoding: "utf-8" }) === trimmed) return void 0;
} catch {}
await mkdir(dirname(resolved), { recursive: true });
await writeFile(resolved, trimmed, { encoding: "utf-8" });
if (options.sanity) {
const savedData = await readFile(resolved, { encoding: "utf-8" });
if (savedData !== trimmed) throw new Error(`Sanity check failed for ${path}\n\nData[${data.length}]:\n${data}\n\nSaved[${savedData.length}]:\n${savedData}\n`);
return savedData;
}
return trimmed;
}
//#endregion
//#region src/utils/getSummary.ts
function getSummary({ failedPlugins, filesCreated, status, hrStart, config, pluginTimings }) {
const duration = formatHrtime(hrStart);
const pluginsCount = config.plugins?.length ?? 0;
const successCount = pluginsCount - failedPlugins.size;
const meta = {
plugins: status === "success" ? `${styleText("green", `${successCount} successful`)}, ${pluginsCount} total` : `${styleText("green", `${successCount} successful`)}, ${styleText("red", `${failedPlugins.size} failed`)}, ${pluginsCount} total`,
pluginsFailed: status === "failed" ? [...failedPlugins].map(({ plugin }) => randomCliColor(plugin.name)).join(", ") : void 0,
filesCreated,
time: styleText("green", duration),
output: path.isAbsolute(config.root) ? path.resolve(config.root, config.output.path) : config.root
};
const labels = {
plugins: "Plugins:",
failed: "Failed:",
generated: "Generated:",
pluginTimings: "Plugin Timings:",
output: "Output:"
};
const maxLength = Math.max(0, ...[...Object.values(labels), ...pluginTimings ? Array.from(pluginTimings.keys()) : []].map((s) => s.length));
const summaryLines = [];
summaryLines.push(`${labels.plugins.padEnd(maxLength + 2)} ${meta.plugins}`);
if (meta.pluginsFailed) summaryLines.push(`${labels.failed.padEnd(maxLength + 2)} ${meta.pluginsFailed}`);
summaryLines.push(`${labels.generated.padEnd(maxLength + 2)} ${meta.filesCreated} files in ${meta.time}`);
if (pluginTimings && pluginTimings.size > 0) {
const sortedTimings = Array.from(pluginTimings.entries()).sort((a, b) => b[1] - a[1]);
summaryLines.push(`${labels.pluginTimings}`);
sortedTimings.forEach(([name, time]) => {
const timeStr = time >= 1e3 ? `${(time / 1e3).toFixed(2)}s` : `${Math.round(time)}ms`;
const barLength = Math.min(Math.ceil(time / 100), 10);
const bar = styleText("dim", "█".repeat(barLength));
summaryLines.push(`${styleText("dim", "•")} ${name.padEnd(maxLength + 1)}${bar} ${timeStr}`);
});
}
summaryLines.push(`${labels.output.padEnd(maxLength + 2)} ${meta.output}`);
return summaryLines;
}
//#endregion
//#region src/utils/runHook.ts
/**
* Execute a hook command, emit debug/hook:end events, and forward output to
* an optional HookOutputSink. All three logger adapters share this function
* so the process-spawning logic lives in exactly one place.
*/
async function runHook({ id, command, args, commandWithArgs, context, stream = false, sink }) {
try {
const proc = x(command, [...args ?? []], {
nodeOptions: { detached: true },
throwOnError: true
});
if (stream && sink?.onLine) for await (const line of proc) sink.onLine(line);
const result = await proc;
await context.emit("debug", {
date: /* @__PURE__ */ new Date(),
logs: [result.stdout.trimEnd()]
});
await context.emit("hook:end", {
command,
args,
id,
success: true,
error: null
});
} catch (err) {
if (!(err instanceof NonZeroExitError)) {
await context.emit("hook:end", {
command,
args,
id,
success: false,
error: toError(err)
});
await context.emit("error", toError(err));
return;
}
const stderr = err.output?.stderr ?? "";
const stdout = err.output?.stdout ?? "";
await context.emit("debug", {
date: /* @__PURE__ */ new Date(),
logs: [stdout, stderr].filter(Boolean)
});
if (stderr) sink?.onStderr?.(stderr);
if (stdout) sink?.onStdout?.(stdout);
const errorMessage = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
await context.emit("hook:end", {
command,
args,
id,
success: false,
error: errorMessage
});
await context.emit("error", errorMessage);
}
}
//#endregion
//#region src/utils/Writables.ts
var ClackWritable = class extends Writable {
taskLog;
constructor(taskLog, opts) {
super(opts);
this.taskLog = taskLog;
}
_write(chunk, _encoding, callback) {
this.taskLog.message(`${styleText("dim", chunk.toString())}`);
callback();
}
};
//#endregion
//#region src/loggers/clackLogger.ts
/**
* Clack adapter for local TTY environments
* Provides a beautiful CLI UI with flat structure inspired by Claude's CLI patterns
*/
const clackLogger = defineLogger({
name: "clack",
install(context, options) {
const logLevel$8 = options?.logLevel ?? logLevel.info;
const state = {
totalPlugins: 0,
completedPlugins: 0,
failedPlugins: 0,
totalFiles: 0,
processedFiles: 0,
hrStart: process$1.hrtime(),
spinner: clack.spinner(),
isSpinning: false,
activeProgress: /* @__PURE__ */ new Map()
};
function reset() {
for (const [_key, active] of state.activeProgress) {
if (active.interval) clearInterval(active.interval);
active.progressBar?.stop();
}
state.totalPlugins = 0;
state.completedPlugins = 0;
state.failedPlugins = 0;
state.totalFiles = 0;
state.processedFiles = 0;
state.hrStart = process$1.hrtime();
state.spinner = clack.spinner();
state.isSpinning = false;
state.activeProgress.clear();
}
function showProgressStep() {
if (logLevel$8 <= logLevel.silent) return;
const line = buildProgressLine(state);
if (line) clack.log.step(getMessage(line));
}
function getMessage(message) {
return formatMessage(message, logLevel$8);
}
function startSpinner(text) {
state.spinner.start(text);
state.isSpinning = true;
}
function stopSpinner(text) {
state.spinner.stop(text);
state.isSpinning = false;
}
context.on("info", (message, info = "") => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage([
styleText("blue", "ℹ"),
message,
styleText("dim", info)
].join(" "));
if (state.isSpinning) state.spinner.message(text);
else clack.log.info(text);
});
context.on("success", (message, info = "") => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage([
styleText("blue", "✓"),
message,
logLevel$8 >= logLevel.info ? styleText("dim", info) : void 0
].filter(Boolean).join(" "));
if (state.isSpinning) stopSpinner(text);
else clack.log.success(text);
});
context.on("warn", (message, info) => {
if (logLevel$8 < logLevel.warn) return;
const text = getMessage([
styleText("yellow", "⚠"),
message,
logLevel$8 >= logLevel.info && info ? styleText("dim", info) : void 0
].filter(Boolean).join(" "));
clack.log.warn(text);
});
context.on("error", (error) => {
const caused = toCause(error);
const text = [styleText("red", "✗"), error.message].join(" ");
if (state.isSpinning) stopSpinner(getMessage(text));
else clack.log.error(getMessage(text));
if (logLevel$8 >= logLevel.debug && error.stack) {
const frames = error.stack.split("\n").slice(1, 4);
for (const frame of frames) clack.log.message(getMessage(styleText("dim", frame.trim())));
if (caused?.stack) {
clack.log.message(styleText("dim", `└─ caused by ${caused.message}`));
const frames = caused.stack.split("\n").slice(1, 4);
for (const frame of frames) clack.log.message(getMessage(` ${styleText("dim", frame.trim())}`));
}
}
});
context.on("version:new", (version, latestVersion) => {
if (logLevel$8 <= logLevel.silent) return;
try {
clack.box(`\`v${version}\` → \`v${latestVersion}\`
Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
width: "auto",
formatBorder: (s) => styleText("yellow", s),
rounded: true,
withGuide: false,
contentAlign: "center",
titleAlign: "center"
});
} catch {
console.log(`Update available for Kubb: v${version} → v${latestVersion}`);
console.log("Run `npm install -g @kubb/cli` to update");
}
});
context.on("lifecycle:start", async (version) => {
console.log(`\n${getIntro({
title: "The ultimate toolkit for working with APIs",
description: "Ready to start",
version,
areEyesOpen: true
})}\n`);
reset();
});
context.on("config:start", () => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage("Configuration started");
clack.intro(text);
startSpinner(getMessage("Configuration loading"));
});
context.on("config:end", (_configs) => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage("Configuration completed");
clack.outro(text);
});
context.on("generation:start", (config) => {
reset();
state.totalPlugins = config.plugins?.length ?? 0;
const text = getMessage(["Generation started", config.name ? `for ${styleText("dim", config.name)}` : void 0].filter(Boolean).join(" "));
clack.intro(text);
});
context.on("plugin:start", (plugin) => {
if (logLevel$8 <= logLevel.silent) return;
stopSpinner();
const progressBar = clack.progress({
style: "block",
max: 100,
size: 30
});
const text = getMessage(`Generating ${styleText("bold", plugin.name)}`);
progressBar.start(text);
const interval = setInterval(() => {
progressBar.advance();
}, 100);
state.activeProgress.set(plugin.name, {
progressBar,
interval
});
});
context.on("plugin:end", (plugin, { duration, success }) => {
stopSpinner();
const active = state.activeProgress.get(plugin.name);
if (!active || logLevel$8 === logLevel.silent) return;
clearInterval(active.interval);
if (success) state.completedPlugins++;
else state.failedPlugins++;
const durationStr = formatMsWithColor(duration);
const text = getMessage(success ? `${styleText("bold", plugin.name)} completed in ${durationStr}` : `${styleText("bold", plugin.name)} failed in ${styleText("red", formatMs(duration))}`);
active.progressBar.stop(text);
state.activeProgress.delete(plugin.name);
showProgressStep();
});
context.on("files:processing:start", (files) => {
if (logLevel$8 <= logLevel.silent) return;
stopSpinner();
state.totalFiles = files.length;
state.processedFiles = 0;
const text = `Writing ${files.length} files`;
const progressBar = clack.progress({
style: "block",
max: files.length,
size: 30
});
context.emit("info", text);
progressBar.start(getMessage(text));
state.activeProgress.set("files", { progressBar });
});
context.on("file:processing:update", ({ file, config }) => {
if (logLevel$8 <= logLevel.silent) return;
stopSpinner();
state.processedFiles++;
const text = `Writing ${relative(config.root, file.path)}`;
const active = state.activeProgress.get("files");
if (!active) return;
active.progressBar.advance(void 0, text);
});
context.on("files:processing:end", () => {
if (logLevel$8 <= logLevel.silent) return;
stopSpinner();
const text = getMessage("Files written successfully");
const active = state.activeProgress.get("files");
if (!active) return;
active.progressBar.stop(text);
state.activeProgress.delete("files");
showProgressStep();
});
context.on("generation:end", (config) => {
const text = getMessage(config.name ? `Generation completed for ${styleText("dim", config.name)}` : "Generation completed");
clack.outro(text);
});
context.on("format:start", () => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage("Format started");
clack.intro(text);
});
context.on("format:end", () => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage("Format completed");
clack.outro(text);
});
context.on("lint:start", () => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage("Lint started");
clack.intro(text);
});
context.on("lint:end", () => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage("Lint completed");
clack.outro(text);
});
context.on("hook:start", async ({ id, command, args }) => {
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${styleText("dim", commandWithArgs)} started`);
if (!id) return;
if (logLevel$8 <= logLevel.silent) {
await runHook({
id,
command,
args,
commandWithArgs,
context,
sink: {
onStderr: (s) => console.error(s),
onStdout: (s) => console.log(s)
}
});
return;
}
clack.intro(text);
const logger = clack.taskLog({ title: getMessage(["Executing hook", logLevel$8 >= logLevel.info ? styleText("dim", commandWithArgs) : void 0].filter(Boolean).join(" ")) });
const writable = new ClackWritable(logger);
await runHook({
id,
command,
args,
commandWithArgs,
context,
stream: true,
sink: {
onLine: (line) => writable.write(line),
onStderr: (s) => logger.error(s),
onStdout: (s) => logger.message(s)
}
});
});
context.on("hook:end", ({ command, args }) => {
if (logLevel$8 <= logLevel.silent) return;
const text = getMessage(`Hook ${styleText("dim", formatCommandWithArgs(command, args))} successfully executed`);
clack.outro(text);
});
context.on("generation:summary", (config, { pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
const summary = getSummary({
failedPlugins,
filesCreated,
config,
status,
hrStart,
pluginTimings: logLevel$8 >= logLevel.verbose ? pluginTimings : void 0
});
const title = config.name || "";
summary.unshift("\n");
summary.push("\n");
const borderColor = status === "success" ? "green" : "red";
try {
clack.box(summary.join("\n"), getMessage(title), {
width: "auto",
formatBorder: (s) => styleText(borderColor, s),
rounded: true,
withGuide: false,
contentAlign: "left",
titleAlign: "center"
});
} catch {
console.log(summary.join("\n"));
}
});
context.on("lifecycle:end", () => {
reset();
});
}
});
//#endregion
//#region src/loggers/fileSystemLogger.ts
/**
* FileSystem logger for debug log persistence
* Captures debug and verbose events and writes them to files in .kubb directory
*
* Note: Logs are written on lifecycle:end or process exit. If the process crashes
* before these events, some cached logs may be lost.
*/
const fileSystemLogger = defineLogger({
name: "filesystem",
install(context) {
const state = {
cachedLogs: /* @__PURE__ */ new Set(),
startDate: Date.now()
};
function reset() {
state.cachedLogs = /* @__PURE__ */ new Set();
state.startDate = Date.now();
}
async function writeLogs(name) {
if (state.cachedLogs.size === 0) return [];
const files = {};
for (const log of state.cachedLogs) {
const baseName = log.fileName || `${[
"kubb",
name,
state.startDate
].filter(Boolean).join("-")}.log`;
const pathName = resolve(process$1.cwd(), ".kubb", baseName);
if (!files[pathName]) files[pathName] = [];
if (log.logs.length > 0) {
const timestamp = log.date.toLocaleString();
files[pathName].push(`[${timestamp}]\n${log.logs.join("\n")}`);
}
}
await Promise.all(Object.entries(files).map(([fileName, logs]) => write(fileName, logs.join("\n\n"))));
return Object.keys(files);
}
context.on("info", (message, info) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`ℹ ${message} ${info}`]
});
});
context.on("success", (message, info) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`✓ ${message} ${info}`]
});
});
context.on("warn", (message, info) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`⚠ ${message} ${info}`]
});
});
context.on("error", (error) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`✗ ${error.message}`, error.stack || "unknown stack"]
});
});
context.on("debug", (message) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: message.logs
});
});
context.on("plugin:start", (plugin) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`Generating ${plugin.name}`]
});
});
context.on("plugin:end", (plugin, { duration, success }) => {
const durationStr = formatMs(duration);
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`]
});
});
context.on("files:processing:start", (files) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`Start ${files.length} writing:`, ...files.map((file) => file.path)]
});
});
context.on("generation:end", async (config) => {
const writtenFilePaths = await writeLogs(config.name);
if (writtenFilePaths.length > 0) {
const files = writtenFilePaths.map((f) => relative(process$1.cwd(), f));
await context.emit("info", "Debug files written to:", files.join(", "));
}
reset();
});
const exitHandler = () => {
if (state.cachedLogs.size > 0) writeLogs().catch(() => {});
};
process$1.once("exit", exitHandler);
process$1.once("SIGINT", exitHandler);
process$1.once("SIGTERM", exitHandler);
}
});
//#endregion
//#region src/loggers/githubActionsLogger.ts
/**
* GitHub Actions adapter for CI environments
* Uses Github group annotations for collapsible sections
*/
const githubActionsLogger = defineLogger({
name: "github-actions",
install(context, options) {
const logLevel$7 = options?.logLevel ?? logLevel.info;
const state = {
totalPlugins: 0,
completedPlugins: 0,
failedPlugins: 0,
totalFiles: 0,
processedFiles: 0,
hrStart: process.hrtime(),
currentConfigs: []
};
function reset() {
state.totalPlugins = 0;
state.completedPlugins = 0;
state.failedPlugins = 0;
state.totalFiles = 0;
state.processedFiles = 0;
state.hrStart = process.hrtime();
state.currentConfigs = [];
}
function showProgressStep() {
if (logLevel$7 <= logLevel.silent) return;
const line = buildProgressLine(state);
if (line) console.log(getMessage(line));
}
function getMessage(message) {
return formatMessage(message, logLevel$7);
}
function openGroup(name) {
console.log(`::group::${name}`);
}
function closeGroup(_name) {
console.log("::endgroup::");
}
context.on("info", (message, info = "") => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage([
styleText("blue", "ℹ"),
message,
styleText("dim", info)
].join(" "));
console.log(text);
});
context.on("success", (message, info = "") => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage([
styleText("blue", "✓"),
message,
logLevel$7 >= logLevel.info ? styleText("dim", info) : void 0
].filter(Boolean).join(" "));
console.log(text);
});
context.on("warn", (message, info = "") => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage([
styleText("yellow", "⚠"),
message,
logLevel$7 >= logLevel.info ? styleText("dim", info) : void 0
].filter(Boolean).join(" "));
console.warn(`::warning::${text}`);
});
context.on("error", (error) => {
const caused = toCause(error);
if (logLevel$7 <= logLevel.silent) return;
const message = error.message || String(error);
console.error(`::error::${message}`);
if (logLevel$7 >= logLevel.debug && error.stack) {
const frames = error.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(styleText("dim", frame.trim())));
if (caused?.stack) {
console.log(styleText("dim", `└─ caused by ${caused.message}`));
const frames = caused.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(` ${styleText("dim", frame.trim())}`));
}
}
});
context.on("lifecycle:start", (version) => {
console.log(styleText("yellow", `Kubb ${version} 🧩`));
reset();
});
context.on("config:start", () => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Configuration started");
openGroup("Configuration");
console.log(text);
});
context.on("config:end", (configs) => {
state.currentConfigs = configs;
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Configuration completed");
console.log(text);
closeGroup("Configuration");
});
context.on("generation:start", (config) => {
reset();
state.totalPlugins = config.plugins?.length ?? 0;
const text = config.name ? `Generation for ${styleText("bold", config.name)}` : "Generation";
if (state.currentConfigs.length > 1) openGroup(text);
if (state.currentConfigs.length === 1) console.log(getMessage(text));
});
context.on("plugin:start", (plugin) => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage(`Generating ${styleText("bold", plugin.name)}`);
if (state.currentConfigs.length === 1) openGroup(`Plugin: ${plugin.name}`);
console.log(text);
});
context.on("plugin:end", (plugin, { duration, success }) => {
if (logLevel$7 <= logLevel.silent) return;
if (success) state.completedPlugins++;
else state.failedPlugins++;
const durationStr = formatMsWithColor(duration);
const text = getMessage(success ? `${styleText("bold", plugin.name)} completed in ${durationStr}` : `${styleText("bold", plugin.name)} failed in ${styleText("red", formatMs(duration))}`);
console.log(text);
if (state.currentConfigs.length > 1) console.log(" ");
if (state.currentConfigs.length === 1) closeGroup(`Plugin: ${plugin.name}`);
showProgressStep();
});
context.on("files:processing:start", (files) => {
if (logLevel$7 <= logLevel.silent) return;
state.totalFiles = files.length;
state.processedFiles = 0;
if (state.currentConfigs.length === 1) openGroup("File Generation");
const text = getMessage(`Writing ${files.length} files`);
console.log(text);
});
context.on("files:processing:end", () => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Files written successfully");
console.log(text);
if (state.currentConfigs.length === 1) closeGroup("File Generation");
showProgressStep();
});
context.on("file:processing:update", () => {
if (logLevel$7 <= logLevel.silent) return;
state.processedFiles++;
});
context.on("generation:end", (config) => {
const text = getMessage(config.name ? `${styleText("blue", "✓")} Generation completed for ${styleText("dim", config.name)}` : `${styleText("blue", "✓")} Generation completed`);
console.log(text);
});
context.on("format:start", () => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Format started");
if (state.currentConfigs.length === 1) openGroup("Formatting");
console.log(text);
});
context.on("format:end", () => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Format completed");
console.log(text);
if (state.currentConfigs.length === 1) closeGroup("Formatting");
});
context.on("lint:start", () => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Lint started");
if (state.currentConfigs.length === 1) openGroup("Linting");
console.log(text);
});
context.on("lint:end", () => {
if (logLevel$7 <= logLevel.silent) return;
const text = getMessage("Lint completed");
console.log(text);
if (state.currentConfigs.length === 1) closeGroup("Linting");
});
context.on("hook:start", async ({ id, command, args }) => {
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${styleText("dim", commandWithArgs)} started`);
if (logLevel$7 > logLevel.silent) {
if (state.currentConfigs.length === 1) openGroup(`Hook ${commandWithArgs}`);
console.log(text);
}
if (!id) return;
await runHook({
id,
command,
args,
commandWithArgs,
context,
sink: {
onStdout: logLevel$7 > logLevel.silent ? (s) => console.log(s) : void 0,
onStderr: logLevel$7 > logLevel.silent ? (s) => console.error(`::error::${s}`) : void 0
}
});
});
context.on("hook:end", ({ command, args }) => {
if (logLevel$7 <= logLevel.silent) return;
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${styleText("dim", commandWithArgs)} completed`);
console.log(text);
if (state.currentConfigs.length === 1) closeGroup(`Hook ${commandWithArgs}`);
});
context.on("generation:summary", (config, { status, hrStart, failedPlugins }) => {
const pluginsCount = config.plugins?.length ?? 0;
const successCount = pluginsCount - failedPlugins.size;
const duration = formatHrtime(hrStart);
if (state.currentConfigs.length > 1) console.log(" ");
console.log(status === "success" ? `Kubb Summary: ${styleText("blue", "✓")} ${`${successCount} successful`}, ${pluginsCount} total, ${styleText("green", duration)}` : `Kubb Summary: ${styleText("blue", "✓")} ${`${successCount} successful`}, ✗ ${`${failedPlugins.size} failed`}, ${pluginsCount} total, ${styleText("green", duration)}`);
if (state.currentConfigs.length > 1) closeGroup(config.name ? `Generation for ${styleText("bold", config.name)}` : "Generation");
});
context.on("lifecycle:end", () => {
reset();
});
}
});
//#endregion
//#region src/loggers/plainLogger.ts
/**
* Plain console adapter for non-TTY environments
* Simple console.log output with indentation
*/
const plainLogger = defineLogger({
name: "plain",
install(context, options) {
const logLevel$6 = options?.logLevel ?? logLevel.info;
function getMessage(message) {
return formatMessage(message, logLevel$6);
}
context.on("info", (message, info) => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage([
"ℹ",
message,
info
].join(" "));
console.log(text);
});
context.on("success", (message, info = "") => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage([
"✓",
message,
logLevel$6 >= logLevel.info ? info : void 0
].filter(Boolean).join(" "));
console.log(text);
});
context.on("warn", (message, info) => {
if (logLevel$6 < logLevel.warn) return;
const text = getMessage([
"⚠",
message,
logLevel$6 >= logLevel.info ? info : void 0
].filter(Boolean).join(" "));
console.log(text);
});
context.on("error", (error) => {
const caused = toCause(error);
const text = getMessage(["✗", error.message].join(" "));
console.log(text);
if (logLevel$6 >= logLevel.debug && error.stack) {
const frames = error.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(frame.trim()));
if (caused?.stack) {
console.log(`└─ caused by ${caused.message}`);
const frames = caused.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(` ${frame.trim()}`));
}
}
});
context.on("lifecycle:start", () => {
console.log("Kubb CLI 🧩");
});
context.on("config:start", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Configuration started");
console.log(text);
});
context.on("config:end", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Configuration completed");
console.log(text);
});
context.on("generation:start", () => {
const text = getMessage("Generation started");
console.log(text);
});
context.on("plugin:start", (plugin) => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage(`Generating ${plugin.name}`);
console.log(text);
});
context.on("plugin:end", (plugin, { duration, success }) => {
if (logLevel$6 <= logLevel.silent) return;
const durationStr = formatMs(duration);
const text = getMessage(success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`);
console.log(text);
});
context.on("files:processing:start", (files) => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage(`Writing ${files.length} files`);
console.log(text);
});
context.on("file:processing:update", ({ file, config }) => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage(`Writing ${relative(config.root, file.path)}`);
console.log(text);
});
context.on("files:processing:end", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Files written successfully");
console.log(text);
});
context.on("generation:end", (config) => {
const text = getMessage(config.name ? `Generation completed for ${config.name}` : "Generation completed");
console.log(text);
});
context.on("format:start", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Format started");
console.log(text);
});
context.on("format:end", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Format completed");
console.log(text);
});
context.on("lint:start", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Lint started");
console.log(text);
});
context.on("lint:end", () => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage("Lint completed");
console.log(text);
});
context.on("hook:start", async ({ id, command, args }) => {
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${commandWithArgs} started`);
if (logLevel$6 > logLevel.silent) console.log(text);
if (!id) return;
await runHook({
id,
command,
args,
commandWithArgs,
context,
sink: {
onStdout: logLevel$6 > logLevel.silent ? (s) => console.log(s) : void 0,
onStderr: logLevel$6 > logLevel.silent ? (s) => console.error(s) : void 0
}
});
});
context.on("hook:end", ({ command, args }) => {
if (logLevel$6 <= logLevel.silent) return;
const text = getMessage(`Hook ${formatCommandWithArgs(command, args)} completed`);
console.log(text);
});
context.on("generation:summary", (config, { pluginTimings, status, hrStart, failedPlugins, filesCreated }) => {
const summary = getSummary({
failedPlugins,
filesCreated,
config,
status,
hrStart,
pluginTimings: logLevel$6 >= logLevel.verbose ? pluginTimings : void 0
});
console.log(SUMMARY_SEPARATOR);
console.log(summary.join("\n"));
console.log(SUMMARY_SEPARATOR);
});
}
});
//#endregion
//#region src/loggers/utils.ts
/**
* Optionally prefix a message with a [HH:MM:SS] timestamp when logLevel >= verbose.
* Shared across all logger adapters to avoid duplication.
*/
function formatMessage(message, logLevel$4) {
if (logLevel$4 >= logLevel.verbose) return `${styleText("dim", `[${(/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
hour12: false,
hour: "2-digit",
minute: "2-digit",
second: "2-digit"
})}]`)} ${message}`;
return message;
}
/**
* Build the progress summary line shared by clack and GitHub Actions loggers.
* Returns null when there is nothing to display.
*/
function buildProgressLine(state) {
const parts = [];
const duration = formatHrtime(state.hrStart);
if (state.totalPlugins > 0) {
const pluginStr = state.failedPlugins > 0 ? `Plugins ${styleText("green", state.completedPlugins.toString())}/${state.totalPlugins} ${styleText("red", `(${state.failedPlugins} failed)`)}` : `Plugins ${styleText("green", state.completedPlugins.toString())}/${state.totalPlugins}`;
parts.push(pluginStr);
}
if (state.totalFiles > 0) parts.push(`Files ${styleText("green", state.processedFiles.toString())}/${state.totalFiles}`);
if (parts.length === 0) return null;
parts.push(`${styleText("green", duration)} elapsed`);
return parts.join(styleText("dim", " | "));
}
/**
* Join a command and its optional args into a single display string.
* e.g. ("prettier", ["--write", "."]) → "prettier --write ."
*/
function formatCommandWithArgs(command, args) {
return args?.length ? `${command} ${args.join(" ")}` : command;
}
function detectLogger() {
if (isGitHubActions()) return "github-actions";
if (canUseTTY()) return "clack";
return "plain";
}
const logMapper = {
clack: clackLogger,
plain: plainLogger,
"github-actions": githubActionsLogger
};
async function setupLogger(context, { logLevel: logLevel$5 }) {
const type = detectLogger();
const logger = logMapper[type];
if (!logger) throw new Error(`Unknown adapter type: ${type}`);
const cleanup = await logger.install(context, { logLevel: logLevel$5 });
if (logLevel$5 >= logLevel.debug) await fileSystemLogger.install(context, { logLevel: logLevel$5 });
return cleanup;
}
//#endregion
//#region src/utils/executeHooks.ts
async function executeHooks({ hooks, events }) {
const commands = Array.isArray(hooks.done) ? hooks.done : [hooks.done].filter(Boolean);
for (const command of commands) {
const [cmd, ...args] = tokenize(command);
if (!cmd) continue;
const hookId = createHash("sha256").update(command).digest("hex");
const hookEndPromise = new Promise((resolve, reject) => {
const handler = ({ id, success, error }) => {
if (id !== hookId) return;
events.off("hook:end", handler);
if (!success) {
reject(error ?? /* @__PURE__ */ new Error(`Hook failed: ${command}`));
return;
}
events.emit("success", `${styleText("dim", command)} successfully executed`).then(resolve).catch(reject);
};
events.on("hook:end", handler);
});
await events.emit("hook:start", {
id: hookId,
command: cmd,
args
});
await hookEndPromise;
}
}
//#endregion
//#region src/utils/getCosmiConfig.ts
const jiti = createJiti(import.meta.url, {
jsx: {
runtime: "automatic",
importSource: "@kubb/react-fabric"
},
sourceMaps: true,
interopDefault: true
});
const tsLoader = async (configFile) => {
return await jiti.import(configFile, { default: true });
};
async function getCosmiConfig(moduleName, config) {
let result;
const searchPlaces = [
"package.json",
`.${moduleName}rc`,
`.${moduleName}rc.json`,
`.${moduleName}rc.yaml`,
`.${moduleName}rc.yml`,
`.${moduleName}rc.ts`,
`.${moduleName}rc.mts`,
`.${moduleName}rc.cts`,
`.${moduleName}rc.js`,
`.${moduleName}rc.mjs`,
`.${moduleName}rc.cjs`,
`${moduleName}.config.ts`,
`${moduleName}.config.mts`,
`${moduleName}.config.cts`,
`${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,
".mts": tsLoader,
".cts": tsLoader
}
});
try {
result = config ? await explorer.load(config) : await explorer.search();
} catch (error) {
throw new Error("Config failed loading", { cause: error });
}
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, cb) {
const { watch } = await import("chokidar");
watch(path, {
ignorePermissionErrors: true,
ignored: WATCHER_IGNORED_PATHS
}).on("all", async (type, file) => {
console.log(styleText("yellow", styleText("bold", `Change detected: ${type} ${file}`)));
try {
await cb(path);
} catch (_e) {
console.log(styleText("red", "Watcher failed"));
}
});
}
//#endregion
//#region src/runners/generate.ts
async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, configName, outputPath, logLevel: logLevel$1, events, onStart, onEnd }) {
await onStart();
let resolvedTool = toolValue;
if (resolvedTool === "auto") {
const detected = await detect();
if (!detected) await events.emit("warn", noToolMessage);
else {
resolvedTool = detected;
await events.emit("info", `Auto-detected ${toolLabel}: ${styleText("dim", resolvedTool)}`);
}
}
if (resolvedTool && resolvedTool !== "auto" && resolvedTool in toolMap) {
const toolConfig = toolMap[resolvedTool];
try {
const hookId = createHash("sha256").update([configName, resolvedTool].filter(Boolean).join("-")).digest("hex");
const hookEndPromise = new Promise((resolve, reject) => {
const handler = ({ id, success, error }) => {
if (id !== hookId) return;
events.off("hook:end", handler);
if (!success) {
reject(error ?? /* @__PURE__ */ new Error(`${toolConfig.errorMessage}`));
return;
}
events.emit("success", [
`${successPrefix} with ${styleText("dim", resolvedTool)}`,
logLevel$1 >= logLevel.info ? `on ${styleText("dim", outputPath)}` : void 0,
"successfully"
].filter(Boolean).join(" ")).then(resolve).catch(reject);
};
events.on("hook:end", handler);
});
await events.emit("hook:start", {
id: hookId,
command: toolConfig.command,
args: toolConfig.args(outputPath)
});
await hookEndPromise;
} catch (caughtError) {
const err = new Error(toolConfig.errorMessage);
err.cause = caughtError;
await events.emit("error", err);
}
}
await onEnd();
}
async function generate({ input, config: userConfig, events, logLevel: logLevel$2 }) {
const inputPath = input ?? ("path" in userConfig.input ? userConfig.input.path : void 0);
const hrStart = process$1.hrtime();
const config = {
...userConfig,
root: userConfig.root || process$1.cwd(),
input: inputPath ? {
...userConfig.input,
path: inputPath
} : userConfig.input,
output: {
write: true,
barrelType: "named",
extension: { ".ts": ".ts" },
format: "prettier",
...userConfig.output
}
};
await events.emit("generation:start", config);
await events.emit("info", config.name ? `Setup generation ${styleText("bold", config.name)}` : "Setup generation", inputPath);
const { sources, fabric, pluginManager } = await setup({
config,
events
});
await events.emit("info", config.name ? `Build generation ${styleText("bold", config.name)}` : "Build generation", inputPath);
const { files, failedPlugins, pluginTimings, error } = await safeBuild({
config,
events
}, {
pluginManager,
fabric,
events,
sources
});
await events.emit("info", "Load summary");
if (failedPlugins.size > 0 || error) {
const allErrors = [error, ...Array.from(failedPlugins).filter((it) => it.error).map((it) => it.error)].filter(Boolean);
for (const err of allErrors) await events.emit("error", err);
await events.emit("generation:end", config, files, sources);
await events.emit("generation:summary", config, {
failedPlugins,
filesCreated: files.length,
status: "failed",
hrStart,
pluginTimings: logLevel$2 >= logLevel.verbose ? pluginTimings : void 0
});
await sendTelemetry(buildTelemetryEvent({
command: "generate",
kubbVersion: version,
plugins: pluginManager.plugins.map((p) => ({
name: p.name,
options: p.options
})),
hrStart,
filesCreated: files.length,
status: "failed"
}));
process$1.exit(1);
}
await events.emit("success", "Generation successfully", inputPath);
await events.emit("generation:end", config, files, sources);
const outputPath = path.resolve(config.root, config.output.path);
if (config.output.format) await runToolPass({
toolValue: config.output.format,
detect: detectFormatter,
toolMap: formatters,
toolLabel: "formatter",
successPrefix: "Formatting",
noToolMessage: "No formatter found (biome, prettier, or oxfmt). Skipping formatting.",
configName: config.name,
outputPath,
logLevel: logLevel$2,
events,
onStart: () => events.emit("format:start"),
onEnd: () => events.emit("format:end")
});
if (config.output.lint) await runToolPass({
toolValue: config.output.lint,
detect: detectLinter,
toolMap: linters,
toolLabel: "linter",
successPrefix: "Linting",
noToolMessage: "No linter found (biome, oxlint, or eslint). Skipping linting.",
configName: config.name,
outputPath,
logLevel: logLevel$2,
events,
onStart: () => events.emit("lint:start"),
onEnd: () => events.emit("lint:end")
});
if (config.hooks) {
await events.emit("hooks:start");
await executeHooks({
hooks: config.hooks,
events
});
await events.emit("hooks:end");
}
await events.emit("generation:summary", config, {
failedPlugins,
filesCreated: files.length,
status: "success",
hrStart,
pluginTimings
});
await sendTelemetry(buildTelemetryEvent({
command: "generate",
kubbVersion: version,
plugins: pluginManager.plugins.map((p) => ({
name: p.name,
options: p.options
})),
hrStart,
filesCreated: files.length,
status: "success"
}));
}
async function runGenerateCommand({ input, configPath, logLevel: logLevelKey, watch }) {
const logLevel$3 = logLevel[logLevelKey] ?? logLevel.info;
const events = new AsyncEventEmitter();
const promiseManager = new PromiseManager();
await setupLogger(events, { logLevel: logLevel$3 });
await executeIfOnline(async () => {
try {
const latestVersion = (await (await fetch(KUBB_NPM_PACKAGE_URL)).json()).version;
if (latestVersion && version < latestVersion) await events.emit("version:new", version, latestVersion);
} catch {}
});
try {
const result = await getCosmiConfig("kubb", configPath);
const configs = await getConfigs(result.config, { input });
await events.emit("config:start");
await events.emit("info", "Config loaded", path.relative(process$1.cwd(), result.filepath));
await events.emit("success", "Config loaded successfully", path.relative(process$1.cwd(), result.filepath));
await events.emit("config:end", configs);
await events.emit("lifecycle:start", version);
const promises = configs.map((config) => {
return async () => {
if (isInputPath(config) && watch) {
await startWatcher([input || config.input.path], async (paths) => {
events.removeAll();
await generate({
input,
config,
logLevel: logLevel$3,
events
});
clack.log.step(styleText("yellow", `Watching for changes in ${paths.join(" and ")}`));
});
return;
}
await generate({
input,
config,
logLevel: logLevel$3,
events
});
};
});
await promiseManager.run("seq", promises);
await events.emit("lifecycle:end");
} catch (error) {
await events.emit("error", toError(error));
process$1.exit(1);
}
}
//#endregion
export { runGenerateCommand };
//# sourceMappingURL=generate-B7Ckt_LG.js.map

Sorry, the diff of this file is too big to display

const require_chunk = require("./chunk-ByKO4r7w.cjs");
const require_errors = require("./errors-DBW0N9w4.cjs");
const require_telemetry = require("./telemetry-CEm85k_X.cjs");
const require_shell = require("./shell-7HPrTCJ5.cjs");
const require_package = require("./package-CSJQyhYO.cjs");
const require_constants = require("./constants-BTUap0zs.cjs");
let node_util = require("node:util");
let node_events = require("node:events");
let node_crypto = require("node:crypto");
require("node:fs");
let node_fs_promises = require("node:fs/promises");
let node_path = require("node:path");
node_path = require_chunk.__toESM(node_path);
let node_process = require("node:process");
node_process = require_chunk.__toESM(node_process);
let _clack_prompts = require("@clack/prompts");
_clack_prompts = require_chunk.__toESM(_clack_prompts);
let _kubb_core = require("@kubb/core");
let tinyexec = require("tinyexec");
let node_stream = require("node:stream");
let cosmiconfig = require("cosmiconfig");
let jiti = require("jiti");
//#region ../../internals/utils/src/asyncEventEmitter.ts
/**
* A typed EventEmitter that awaits all async listeners before resolving.
* Wraps Node's `EventEmitter` with full TypeScript event-map inference.
*/
var AsyncEventEmitter = class {
/**
* `maxListener` controls the maximum number of listeners per event before Node emits a memory-leak warning.
* @default 10
*/
constructor(maxListener = 10) {
this.#emitter.setMaxListeners(maxListener);
}
#emitter = new node_events.EventEmitter();
/**
* Emits an event and awaits all registered listeners in parallel.
* Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
*/
async emit(eventName, ...eventArgs) {
const listeners = this.#emitter.listeners(eventName);
if (listeners.length === 0) return;
await Promise.all(listeners.map(async (listener) => {
try {
return await listener(...eventArgs);
} catch (err) {
let serializedArgs;
try {
serializedArgs = JSON.stringify(eventArgs);
} catch {
serializedArgs = String(eventArgs);
}
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: require_errors.toError(err) });
}
}));
}
/** Registers a persistent listener for the given event. */
on(eventName, handler) {
this.#emitter.on(eventName, handler);
}
/** Registers a one-shot listener that removes itself after the first invocation. */
onOnce(eventName, handler) {
const wrapper = (...args) => {
this.off(eventName, wrapper);
return handler(...args);
};
this.on(eventName, wrapper);
}
/** Removes a previously registered listener. */
off(eventName, handler) {
this.#emitter.off(eventName, handler);
}
/** Removes all listeners from every event channel. */
removeAll() {
this.#emitter.removeAllListeners();
}
};
//#endregion
//#region ../../internals/utils/src/time.ts
/**
* Calculates elapsed time in milliseconds from a high-resolution start time.
* Rounds to 2 decimal places to provide sub-millisecond precision without noise.
*/
function getElapsedMs(hrStart) {
const [seconds, nanoseconds] = process.hrtime(hrStart);
const ms = seconds * 1e3 + nanoseconds / 1e6;
return Math.round(ms * 100) / 100;
}
/**
* Converts a millisecond duration into a human-readable string.
* Adjusts units (ms, s, m s) based on the magnitude of the duration.
*/
function formatMs(ms) {
if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
return `${Math.round(ms)}ms`;
}
/**
* Convenience helper: formats the elapsed time since `hrStart` in one step.
*/
function formatHrtime(hrStart) {
return formatMs(getElapsedMs(hrStart));
}
//#endregion
//#region ../../internals/utils/src/colors.ts
/**
* Parses a CSS hex color string (`#RGB`) into its RGB channels.
* Falls back to `255` for any channel that cannot be parsed.
*/
function parseHex(color) {
const int = Number.parseInt(color.replace("#", ""), 16);
return Number.isNaN(int) ? {
r: 255,
g: 255,
b: 255
} : {
r: int >> 16 & 255,
g: int >> 8 & 255,
b: int & 255
};
}
/**
* Returns a function that wraps a string in a 24-bit ANSI true-color escape sequence
* for the given hex color.
*/
function hex(color) {
const { r, g, b } = parseHex(color);
return (text) => `\x1b[38;2;${r};${g};${b}m${text}\x1b[0m`;
}
function gradient(colorStops, text) {
const chars = text.split("");
return chars.map((char, i) => {
const t = chars.length <= 1 ? 0 : i / (chars.length - 1);
const seg = Math.min(Math.floor(t * (colorStops.length - 1)), colorStops.length - 2);
const lt = t * (colorStops.length - 1) - seg;
const from = parseHex(colorStops[seg]);
const to = parseHex(colorStops[seg + 1]);
return `\x1b[38;2;${Math.round(from.r + (to.r - from.r) * lt)};${Math.round(from.g + (to.g - from.g) * lt)};${Math.round(from.b + (to.b - from.b) * lt)}m${char}\x1b[0m`;
}).join("");
}
/** ANSI color functions for each part of the Kubb mascot illustration. */
const palette = {
lid: hex("#F55A17"),
woodTop: hex("#F5A217"),
woodMid: hex("#F58517"),
woodBase: hex("#B45309"),
eye: hex("#FFFFFF"),
highlight: hex("#adadc6"),
blush: hex("#FDA4AF")
};
/**
* Generates the Kubb mascot welcome banner.
*/
function getIntro({ title, description, version, areEyesOpen }) {
const kubbVersion = gradient([
"#F58517",
"#F5A217",
"#F55A17"
], `KUBB v${version}`);
const eyeTop = areEyesOpen ? palette.eye("█▀█") : palette.eye("───");
const eyeBottom = areEyesOpen ? palette.eye("▀▀▀") : palette.eye("───");
return `
${palette.lid("▄▄▄▄▄▄▄▄▄▄▄▄▄")}
${palette.woodTop("█ ")}${palette.highlight("▄▄")}${palette.woodTop(" ")}${palette.highlight("▄▄")}${palette.woodTop(" █")} ${kubbVersion}
${palette.woodMid("█ ")}${eyeTop}${palette.woodMid(" ")}${eyeTop}${palette.woodMid(" █")} ${(0, node_util.styleText)("gray", title)}
${palette.woodMid("█ ")}${eyeBottom}${palette.woodMid(" ")}${palette.blush("◡")}${palette.woodMid(" ")}${eyeBottom}${palette.woodMid(" █")} ${(0, node_util.styleText)("yellow", "➜")} ${(0, node_util.styleText)("white", description)}
${palette.woodBase("▀▀▀▀▀▀▀▀▀▀▀▀▀")}
`;
}
/** ANSI color names available for terminal output. */
const randomColors = [
"black",
"red",
"green",
"yellow",
"blue",
"white",
"magenta",
"cyan",
"gray"
];
/**
* Returns the text wrapped in a deterministic ANSI color derived from the text's SHA-256 hash.
*/
function randomCliColor(text) {
if (!text) return "";
return (0, node_util.styleText)(randomColors[(0, node_crypto.createHash)("sha256").update(text).digest().readUInt32BE(0) % randomColors.length] ?? "white", text);
}
/**
* Formats a millisecond duration with an ANSI color based on thresholds:
* green ≤ 500 ms · yellow ≤ 1 000 ms · red > 1 000 ms
*/
function formatMsWithColor(ms) {
const formatted = formatMs(ms);
if (ms <= 500) return (0, node_util.styleText)("green", formatted);
if (ms <= 1e3) return (0, node_util.styleText)("yellow", formatted);
return (0, node_util.styleText)("red", formatted);
}
//#endregion
//#region ../../internals/utils/src/fs.ts
/**
* Writes `data` to `path`, trimming leading/trailing whitespace before saving.
* Skips the write and returns `undefined` when the trimmed content is empty or
* identical to what is already on disk.
* Creates any missing parent directories automatically.
* When `sanity` is `true`, re-reads the file after writing and throws if the
* content does not match.
*/
async function write(path, data, options = {}) {
const trimmed = data.trim();
if (trimmed === "") return void 0;
const resolved = (0, node_path.resolve)(path);
if (typeof Bun !== "undefined") {
const file = Bun.file(resolved);
if ((await file.exists() ? await file.text() : null) === trimmed) return void 0;
await Bun.write(resolved, trimmed);
return trimmed;
}
try {
if (await (0, node_fs_promises.readFile)(resolved, { encoding: "utf-8" }) === trimmed) return void 0;
} catch {}
await (0, node_fs_promises.mkdir)((0, node_path.dirname)(resolved), { recursive: true });
await (0, node_fs_promises.writeFile)(resolved, trimmed, { encoding: "utf-8" });
if (options.sanity) {
const savedData = await (0, node_fs_promises.readFile)(resolved, { encoding: "utf-8" });
if (savedData !== trimmed) throw new Error(`Sanity check failed for ${path}\n\nData[${data.length}]:\n${data}\n\nSaved[${savedData.length}]:\n${savedData}\n`);
return savedData;
}
return trimmed;
}
//#endregion
//#region src/utils/getSummary.ts
function getSummary({ failedPlugins, filesCreated, status, hrStart, config, pluginTimings }) {
const duration = formatHrtime(hrStart);
const pluginsCount = config.plugins?.length ?? 0;
const successCount = pluginsCount - failedPlugins.size;
const meta = {
plugins: status === "success" ? `${(0, node_util.styleText)("green", `${successCount} successful`)}, ${pluginsCount} total` : `${(0, node_util.styleText)("green", `${successCount} successful`)}, ${(0, node_util.styleText)("red", `${failedPlugins.size} failed`)}, ${pluginsCount} total`,
pluginsFailed: status === "failed" ? [...failedPlugins].map(({ plugin }) => randomCliColor(plugin.name)).join(", ") : void 0,
filesCreated,
time: (0, node_util.styleText)("green", duration),
output: node_path.default.isAbsolute(config.root) ? node_path.default.resolve(config.root, config.output.path) : config.root
};
const labels = {
plugins: "Plugins:",
failed: "Failed:",
generated: "Generated:",
pluginTimings: "Plugin Timings:",
output: "Output:"
};
const maxLength = Math.max(0, ...[...Object.values(labels), ...pluginTimings ? Array.from(pluginTimings.keys()) : []].map((s) => s.length));
const summaryLines = [];
summaryLines.push(`${labels.plugins.padEnd(maxLength + 2)} ${meta.plugins}`);
if (meta.pluginsFailed) summaryLines.push(`${labels.failed.padEnd(maxLength + 2)} ${meta.pluginsFailed}`);
summaryLines.push(`${labels.generated.padEnd(maxLength + 2)} ${meta.filesCreated} files in ${meta.time}`);
if (pluginTimings && pluginTimings.size > 0) {
const sortedTimings = Array.from(pluginTimings.entries()).sort((a, b) => b[1] - a[1]);
summaryLines.push(`${labels.pluginTimings}`);
sortedTimings.forEach(([name, time]) => {
const timeStr = time >= 1e3 ? `${(time / 1e3).toFixed(2)}s` : `${Math.round(time)}ms`;
const barLength = Math.min(Math.ceil(time / 100), 10);
const bar = (0, node_util.styleText)("dim", "█".repeat(barLength));
summaryLines.push(`${(0, node_util.styleText)("dim", "•")} ${name.padEnd(maxLength + 1)}${bar} ${timeStr}`);
});
}
summaryLines.push(`${labels.output.padEnd(maxLength + 2)} ${meta.output}`);
return summaryLines;
}
//#endregion
//#region src/utils/runHook.ts
/**
* Execute a hook command, emit debug/hook:end events, and forward output to
* an optional HookOutputSink. All three logger adapters share this function
* so the process-spawning logic lives in exactly one place.
*/
async function runHook({ id, command, args, commandWithArgs, context, stream = false, sink }) {
try {
const proc = (0, tinyexec.x)(command, [...args ?? []], {
nodeOptions: { detached: true },
throwOnError: true
});
if (stream && sink?.onLine) for await (const line of proc) sink.onLine(line);
const result = await proc;
await context.emit("debug", {
date: /* @__PURE__ */ new Date(),
logs: [result.stdout.trimEnd()]
});
await context.emit("hook:end", {
command,
args,
id,
success: true,
error: null
});
} catch (err) {
if (!(err instanceof tinyexec.NonZeroExitError)) {
await context.emit("hook:end", {
command,
args,
id,
success: false,
error: require_errors.toError(err)
});
await context.emit("error", require_errors.toError(err));
return;
}
const stderr = err.output?.stderr ?? "";
const stdout = err.output?.stdout ?? "";
await context.emit("debug", {
date: /* @__PURE__ */ new Date(),
logs: [stdout, stderr].filter(Boolean)
});
if (stderr) sink?.onStderr?.(stderr);
if (stdout) sink?.onStdout?.(stdout);
const errorMessage = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
await context.emit("hook:end", {
command,
args,
id,
success: false,
error: errorMessage
});
await context.emit("error", errorMessage);
}
}
//#endregion
//#region src/utils/Writables.ts
var ClackWritable = class extends node_stream.Writable {
taskLog;
constructor(taskLog, opts) {
super(opts);
this.taskLog = taskLog;
}
_write(chunk, _encoding, callback) {
this.taskLog.message(`${(0, node_util.styleText)("dim", chunk.toString())}`);
callback();
}
};
//#endregion
//#region src/loggers/clackLogger.ts
/**
* Clack adapter for local TTY environments
* Provides a beautiful CLI UI with flat structure inspired by Claude's CLI patterns
*/
const clackLogger = (0, _kubb_core.defineLogger)({
name: "clack",
install(context, options) {
const logLevel = options?.logLevel ?? _kubb_core.logLevel.info;
const state = {
totalPlugins: 0,
completedPlugins: 0,
failedPlugins: 0,
totalFiles: 0,
processedFiles: 0,
hrStart: node_process.default.hrtime(),
spinner: _clack_prompts.spinner(),
isSpinning: false,
activeProgress: /* @__PURE__ */ new Map()
};
function reset() {
for (const [_key, active] of state.activeProgress) {
if (active.interval) clearInterval(active.interval);
active.progressBar?.stop();
}
state.totalPlugins = 0;
state.completedPlugins = 0;
state.failedPlugins = 0;
state.totalFiles = 0;
state.processedFiles = 0;
state.hrStart = node_process.default.hrtime();
state.spinner = _clack_prompts.spinner();
state.isSpinning = false;
state.activeProgress.clear();
}
function showProgressStep() {
if (logLevel <= _kubb_core.logLevel.silent) return;
const line = buildProgressLine(state);
if (line) _clack_prompts.log.step(getMessage(line));
}
function getMessage(message) {
return formatMessage(message, logLevel);
}
function startSpinner(text) {
state.spinner.start(text);
state.isSpinning = true;
}
function stopSpinner(text) {
state.spinner.stop(text);
state.isSpinning = false;
}
context.on("info", (message, info = "") => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
(0, node_util.styleText)("blue", "ℹ"),
message,
(0, node_util.styleText)("dim", info)
].join(" "));
if (state.isSpinning) state.spinner.message(text);
else _clack_prompts.log.info(text);
});
context.on("success", (message, info = "") => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
(0, node_util.styleText)("blue", "✓"),
message,
logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", info) : void 0
].filter(Boolean).join(" "));
if (state.isSpinning) stopSpinner(text);
else _clack_prompts.log.success(text);
});
context.on("warn", (message, info) => {
if (logLevel < _kubb_core.logLevel.warn) return;
const text = getMessage([
(0, node_util.styleText)("yellow", "⚠"),
message,
logLevel >= _kubb_core.logLevel.info && info ? (0, node_util.styleText)("dim", info) : void 0
].filter(Boolean).join(" "));
_clack_prompts.log.warn(text);
});
context.on("error", (error) => {
const caused = require_errors.toCause(error);
const text = [(0, node_util.styleText)("red", "✗"), error.message].join(" ");
if (state.isSpinning) stopSpinner(getMessage(text));
else _clack_prompts.log.error(getMessage(text));
if (logLevel >= _kubb_core.logLevel.debug && error.stack) {
const frames = error.stack.split("\n").slice(1, 4);
for (const frame of frames) _clack_prompts.log.message(getMessage((0, node_util.styleText)("dim", frame.trim())));
if (caused?.stack) {
_clack_prompts.log.message((0, node_util.styleText)("dim", `└─ caused by ${caused.message}`));
const frames = caused.stack.split("\n").slice(1, 4);
for (const frame of frames) _clack_prompts.log.message(getMessage(` ${(0, node_util.styleText)("dim", frame.trim())}`));
}
}
});
context.on("version:new", (version, latestVersion) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
try {
_clack_prompts.box(`\`v${version}\` → \`v${latestVersion}\`
Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
width: "auto",
formatBorder: (s) => (0, node_util.styleText)("yellow", s),
rounded: true,
withGuide: false,
contentAlign: "center",
titleAlign: "center"
});
} catch {
console.log(`Update available for Kubb: v${version} → v${latestVersion}`);
console.log("Run `npm install -g @kubb/cli` to update");
}
});
context.on("lifecycle:start", async (version) => {
console.log(`\n${getIntro({
title: "The ultimate toolkit for working with APIs",
description: "Ready to start",
version,
areEyesOpen: true
})}\n`);
reset();
});
context.on("config:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Configuration started");
_clack_prompts.intro(text);
startSpinner(getMessage("Configuration loading"));
});
context.on("config:end", (_configs) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Configuration completed");
_clack_prompts.outro(text);
});
context.on("generation:start", (config) => {
reset();
state.totalPlugins = config.plugins?.length ?? 0;
const text = getMessage(["Generation started", config.name ? `for ${(0, node_util.styleText)("dim", config.name)}` : void 0].filter(Boolean).join(" "));
_clack_prompts.intro(text);
});
context.on("plugin:start", (plugin) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
stopSpinner();
const progressBar = _clack_prompts.progress({
style: "block",
max: 100,
size: 30
});
const text = getMessage(`Generating ${(0, node_util.styleText)("bold", plugin.name)}`);
progressBar.start(text);
const interval = setInterval(() => {
progressBar.advance();
}, 100);
state.activeProgress.set(plugin.name, {
progressBar,
interval
});
});
context.on("plugin:end", (plugin, { duration, success }) => {
stopSpinner();
const active = state.activeProgress.get(plugin.name);
if (!active || logLevel === _kubb_core.logLevel.silent) return;
clearInterval(active.interval);
if (success) state.completedPlugins++;
else state.failedPlugins++;
const durationStr = formatMsWithColor(duration);
const text = getMessage(success ? `${(0, node_util.styleText)("bold", plugin.name)} completed in ${durationStr}` : `${(0, node_util.styleText)("bold", plugin.name)} failed in ${(0, node_util.styleText)("red", formatMs(duration))}`);
active.progressBar.stop(text);
state.activeProgress.delete(plugin.name);
showProgressStep();
});
context.on("files:processing:start", (files) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
stopSpinner();
state.totalFiles = files.length;
state.processedFiles = 0;
const text = `Writing ${files.length} files`;
const progressBar = _clack_prompts.progress({
style: "block",
max: files.length,
size: 30
});
context.emit("info", text);
progressBar.start(getMessage(text));
state.activeProgress.set("files", { progressBar });
});
context.on("file:processing:update", ({ file, config }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
stopSpinner();
state.processedFiles++;
const text = `Writing ${(0, node_path.relative)(config.root, file.path)}`;
const active = state.activeProgress.get("files");
if (!active) return;
active.progressBar.advance(void 0, text);
});
context.on("files:processing:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
stopSpinner();
const text = getMessage("Files written successfully");
const active = state.activeProgress.get("files");
if (!active) return;
active.progressBar.stop(text);
state.activeProgress.delete("files");
showProgressStep();
});
context.on("generation:end", (config) => {
const text = getMessage(config.name ? `Generation completed for ${(0, node_util.styleText)("dim", config.name)}` : "Generation completed");
_clack_prompts.outro(text);
});
context.on("format:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Format started");
_clack_prompts.intro(text);
});
context.on("format:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Format completed");
_clack_prompts.outro(text);
});
context.on("lint:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Lint started");
_clack_prompts.intro(text);
});
context.on("lint:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Lint completed");
_clack_prompts.outro(text);
});
context.on("hook:start", async ({ id, command, args }) => {
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} started`);
if (!id) return;
if (logLevel <= _kubb_core.logLevel.silent) {
await runHook({
id,
command,
args,
commandWithArgs,
context,
sink: {
onStderr: (s) => console.error(s),
onStdout: (s) => console.log(s)
}
});
return;
}
_clack_prompts.intro(text);
const logger = _clack_prompts.taskLog({ title: getMessage(["Executing hook", logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", commandWithArgs) : void 0].filter(Boolean).join(" ")) });
const writable = new ClackWritable(logger);
await runHook({
id,
command,
args,
commandWithArgs,
context,
stream: true,
sink: {
onLine: (line) => writable.write(line),
onStderr: (s) => logger.error(s),
onStdout: (s) => logger.message(s)
}
});
});
context.on("hook:end", ({ command, args }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage(`Hook ${(0, node_util.styleText)("dim", formatCommandWithArgs(command, args))} successfully executed`);
_clack_prompts.outro(text);
});
context.on("generation:summary", (config, { pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
const summary = getSummary({
failedPlugins,
filesCreated,
config,
status,
hrStart,
pluginTimings: logLevel >= _kubb_core.logLevel.verbose ? pluginTimings : void 0
});
const title = config.name || "";
summary.unshift("\n");
summary.push("\n");
const borderColor = status === "success" ? "green" : "red";
try {
_clack_prompts.box(summary.join("\n"), getMessage(title), {
width: "auto",
formatBorder: (s) => (0, node_util.styleText)(borderColor, s),
rounded: true,
withGuide: false,
contentAlign: "left",
titleAlign: "center"
});
} catch {
console.log(summary.join("\n"));
}
});
context.on("lifecycle:end", () => {
reset();
});
}
});
//#endregion
//#region src/loggers/fileSystemLogger.ts
/**
* FileSystem logger for debug log persistence
* Captures debug and verbose events and writes them to files in .kubb directory
*
* Note: Logs are written on lifecycle:end or process exit. If the process crashes
* before these events, some cached logs may be lost.
*/
const fileSystemLogger = (0, _kubb_core.defineLogger)({
name: "filesystem",
install(context) {
const state = {
cachedLogs: /* @__PURE__ */ new Set(),
startDate: Date.now()
};
function reset() {
state.cachedLogs = /* @__PURE__ */ new Set();
state.startDate = Date.now();
}
async function writeLogs(name) {
if (state.cachedLogs.size === 0) return [];
const files = {};
for (const log of state.cachedLogs) {
const baseName = log.fileName || `${[
"kubb",
name,
state.startDate
].filter(Boolean).join("-")}.log`;
const pathName = (0, node_path.resolve)(node_process.default.cwd(), ".kubb", baseName);
if (!files[pathName]) files[pathName] = [];
if (log.logs.length > 0) {
const timestamp = log.date.toLocaleString();
files[pathName].push(`[${timestamp}]\n${log.logs.join("\n")}`);
}
}
await Promise.all(Object.entries(files).map(([fileName, logs]) => write(fileName, logs.join("\n\n"))));
return Object.keys(files);
}
context.on("info", (message, info) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`ℹ ${message} ${info}`]
});
});
context.on("success", (message, info) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`✓ ${message} ${info}`]
});
});
context.on("warn", (message, info) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`⚠ ${message} ${info}`]
});
});
context.on("error", (error) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`✗ ${error.message}`, error.stack || "unknown stack"]
});
});
context.on("debug", (message) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: message.logs
});
});
context.on("plugin:start", (plugin) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`Generating ${plugin.name}`]
});
});
context.on("plugin:end", (plugin, { duration, success }) => {
const durationStr = formatMs(duration);
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`]
});
});
context.on("files:processing:start", (files) => {
state.cachedLogs.add({
date: /* @__PURE__ */ new Date(),
logs: [`Start ${files.length} writing:`, ...files.map((file) => file.path)]
});
});
context.on("generation:end", async (config) => {
const writtenFilePaths = await writeLogs(config.name);
if (writtenFilePaths.length > 0) {
const files = writtenFilePaths.map((f) => (0, node_path.relative)(node_process.default.cwd(), f));
await context.emit("info", "Debug files written to:", files.join(", "));
}
reset();
});
const exitHandler = () => {
if (state.cachedLogs.size > 0) writeLogs().catch(() => {});
};
node_process.default.once("exit", exitHandler);
node_process.default.once("SIGINT", exitHandler);
node_process.default.once("SIGTERM", exitHandler);
}
});
//#endregion
//#region src/loggers/githubActionsLogger.ts
/**
* GitHub Actions adapter for CI environments
* Uses Github group annotations for collapsible sections
*/
const githubActionsLogger = (0, _kubb_core.defineLogger)({
name: "github-actions",
install(context, options) {
const logLevel = options?.logLevel ?? _kubb_core.logLevel.info;
const state = {
totalPlugins: 0,
completedPlugins: 0,
failedPlugins: 0,
totalFiles: 0,
processedFiles: 0,
hrStart: process.hrtime(),
currentConfigs: []
};
function reset() {
state.totalPlugins = 0;
state.completedPlugins = 0;
state.failedPlugins = 0;
state.totalFiles = 0;
state.processedFiles = 0;
state.hrStart = process.hrtime();
state.currentConfigs = [];
}
function showProgressStep() {
if (logLevel <= _kubb_core.logLevel.silent) return;
const line = buildProgressLine(state);
if (line) console.log(getMessage(line));
}
function getMessage(message) {
return formatMessage(message, logLevel);
}
function openGroup(name) {
console.log(`::group::${name}`);
}
function closeGroup(_name) {
console.log("::endgroup::");
}
context.on("info", (message, info = "") => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
(0, node_util.styleText)("blue", "ℹ"),
message,
(0, node_util.styleText)("dim", info)
].join(" "));
console.log(text);
});
context.on("success", (message, info = "") => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
(0, node_util.styleText)("blue", "✓"),
message,
logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", info) : void 0
].filter(Boolean).join(" "));
console.log(text);
});
context.on("warn", (message, info = "") => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
(0, node_util.styleText)("yellow", "⚠"),
message,
logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", info) : void 0
].filter(Boolean).join(" "));
console.warn(`::warning::${text}`);
});
context.on("error", (error) => {
const caused = require_errors.toCause(error);
if (logLevel <= _kubb_core.logLevel.silent) return;
const message = error.message || String(error);
console.error(`::error::${message}`);
if (logLevel >= _kubb_core.logLevel.debug && error.stack) {
const frames = error.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage((0, node_util.styleText)("dim", frame.trim())));
if (caused?.stack) {
console.log((0, node_util.styleText)("dim", `└─ caused by ${caused.message}`));
const frames = caused.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(` ${(0, node_util.styleText)("dim", frame.trim())}`));
}
}
});
context.on("lifecycle:start", (version) => {
console.log((0, node_util.styleText)("yellow", `Kubb ${version} 🧩`));
reset();
});
context.on("config:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Configuration started");
openGroup("Configuration");
console.log(text);
});
context.on("config:end", (configs) => {
state.currentConfigs = configs;
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Configuration completed");
console.log(text);
closeGroup("Configuration");
});
context.on("generation:start", (config) => {
reset();
state.totalPlugins = config.plugins?.length ?? 0;
const text = config.name ? `Generation for ${(0, node_util.styleText)("bold", config.name)}` : "Generation";
if (state.currentConfigs.length > 1) openGroup(text);
if (state.currentConfigs.length === 1) console.log(getMessage(text));
});
context.on("plugin:start", (plugin) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage(`Generating ${(0, node_util.styleText)("bold", plugin.name)}`);
if (state.currentConfigs.length === 1) openGroup(`Plugin: ${plugin.name}`);
console.log(text);
});
context.on("plugin:end", (plugin, { duration, success }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
if (success) state.completedPlugins++;
else state.failedPlugins++;
const durationStr = formatMsWithColor(duration);
const text = getMessage(success ? `${(0, node_util.styleText)("bold", plugin.name)} completed in ${durationStr}` : `${(0, node_util.styleText)("bold", plugin.name)} failed in ${(0, node_util.styleText)("red", formatMs(duration))}`);
console.log(text);
if (state.currentConfigs.length > 1) console.log(" ");
if (state.currentConfigs.length === 1) closeGroup(`Plugin: ${plugin.name}`);
showProgressStep();
});
context.on("files:processing:start", (files) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
state.totalFiles = files.length;
state.processedFiles = 0;
if (state.currentConfigs.length === 1) openGroup("File Generation");
const text = getMessage(`Writing ${files.length} files`);
console.log(text);
});
context.on("files:processing:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Files written successfully");
console.log(text);
if (state.currentConfigs.length === 1) closeGroup("File Generation");
showProgressStep();
});
context.on("file:processing:update", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
state.processedFiles++;
});
context.on("generation:end", (config) => {
const text = getMessage(config.name ? `${(0, node_util.styleText)("blue", "✓")} Generation completed for ${(0, node_util.styleText)("dim", config.name)}` : `${(0, node_util.styleText)("blue", "✓")} Generation completed`);
console.log(text);
});
context.on("format:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Format started");
if (state.currentConfigs.length === 1) openGroup("Formatting");
console.log(text);
});
context.on("format:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Format completed");
console.log(text);
if (state.currentConfigs.length === 1) closeGroup("Formatting");
});
context.on("lint:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Lint started");
if (state.currentConfigs.length === 1) openGroup("Linting");
console.log(text);
});
context.on("lint:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Lint completed");
console.log(text);
if (state.currentConfigs.length === 1) closeGroup("Linting");
});
context.on("hook:start", async ({ id, command, args }) => {
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} started`);
if (logLevel > _kubb_core.logLevel.silent) {
if (state.currentConfigs.length === 1) openGroup(`Hook ${commandWithArgs}`);
console.log(text);
}
if (!id) return;
await runHook({
id,
command,
args,
commandWithArgs,
context,
sink: {
onStdout: logLevel > _kubb_core.logLevel.silent ? (s) => console.log(s) : void 0,
onStderr: logLevel > _kubb_core.logLevel.silent ? (s) => console.error(`::error::${s}`) : void 0
}
});
});
context.on("hook:end", ({ command, args }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} completed`);
console.log(text);
if (state.currentConfigs.length === 1) closeGroup(`Hook ${commandWithArgs}`);
});
context.on("generation:summary", (config, { status, hrStart, failedPlugins }) => {
const pluginsCount = config.plugins?.length ?? 0;
const successCount = pluginsCount - failedPlugins.size;
const duration = formatHrtime(hrStart);
if (state.currentConfigs.length > 1) console.log(" ");
console.log(status === "success" ? `Kubb Summary: ${(0, node_util.styleText)("blue", "✓")} ${`${successCount} successful`}, ${pluginsCount} total, ${(0, node_util.styleText)("green", duration)}` : `Kubb Summary: ${(0, node_util.styleText)("blue", "✓")} ${`${successCount} successful`}, ✗ ${`${failedPlugins.size} failed`}, ${pluginsCount} total, ${(0, node_util.styleText)("green", duration)}`);
if (state.currentConfigs.length > 1) closeGroup(config.name ? `Generation for ${(0, node_util.styleText)("bold", config.name)}` : "Generation");
});
context.on("lifecycle:end", () => {
reset();
});
}
});
//#endregion
//#region src/loggers/plainLogger.ts
/**
* Plain console adapter for non-TTY environments
* Simple console.log output with indentation
*/
const plainLogger = (0, _kubb_core.defineLogger)({
name: "plain",
install(context, options) {
const logLevel = options?.logLevel ?? _kubb_core.logLevel.info;
function getMessage(message) {
return formatMessage(message, logLevel);
}
context.on("info", (message, info) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
"ℹ",
message,
info
].join(" "));
console.log(text);
});
context.on("success", (message, info = "") => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage([
"✓",
message,
logLevel >= _kubb_core.logLevel.info ? info : void 0
].filter(Boolean).join(" "));
console.log(text);
});
context.on("warn", (message, info) => {
if (logLevel < _kubb_core.logLevel.warn) return;
const text = getMessage([
"⚠",
message,
logLevel >= _kubb_core.logLevel.info ? info : void 0
].filter(Boolean).join(" "));
console.log(text);
});
context.on("error", (error) => {
const caused = require_errors.toCause(error);
const text = getMessage(["✗", error.message].join(" "));
console.log(text);
if (logLevel >= _kubb_core.logLevel.debug && error.stack) {
const frames = error.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(frame.trim()));
if (caused?.stack) {
console.log(`└─ caused by ${caused.message}`);
const frames = caused.stack.split("\n").slice(1, 4);
for (const frame of frames) console.log(getMessage(` ${frame.trim()}`));
}
}
});
context.on("lifecycle:start", () => {
console.log("Kubb CLI 🧩");
});
context.on("config:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Configuration started");
console.log(text);
});
context.on("config:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Configuration completed");
console.log(text);
});
context.on("generation:start", () => {
const text = getMessage("Generation started");
console.log(text);
});
context.on("plugin:start", (plugin) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage(`Generating ${plugin.name}`);
console.log(text);
});
context.on("plugin:end", (plugin, { duration, success }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const durationStr = formatMs(duration);
const text = getMessage(success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`);
console.log(text);
});
context.on("files:processing:start", (files) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage(`Writing ${files.length} files`);
console.log(text);
});
context.on("file:processing:update", ({ file, config }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage(`Writing ${(0, node_path.relative)(config.root, file.path)}`);
console.log(text);
});
context.on("files:processing:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Files written successfully");
console.log(text);
});
context.on("generation:end", (config) => {
const text = getMessage(config.name ? `Generation completed for ${config.name}` : "Generation completed");
console.log(text);
});
context.on("format:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Format started");
console.log(text);
});
context.on("format:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Format completed");
console.log(text);
});
context.on("lint:start", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Lint started");
console.log(text);
});
context.on("lint:end", () => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage("Lint completed");
console.log(text);
});
context.on("hook:start", async ({ id, command, args }) => {
const commandWithArgs = formatCommandWithArgs(command, args);
const text = getMessage(`Hook ${commandWithArgs} started`);
if (logLevel > _kubb_core.logLevel.silent) console.log(text);
if (!id) return;
await runHook({
id,
command,
args,
commandWithArgs,
context,
sink: {
onStdout: logLevel > _kubb_core.logLevel.silent ? (s) => console.log(s) : void 0,
onStderr: logLevel > _kubb_core.logLevel.silent ? (s) => console.error(s) : void 0
}
});
});
context.on("hook:end", ({ command, args }) => {
if (logLevel <= _kubb_core.logLevel.silent) return;
const text = getMessage(`Hook ${formatCommandWithArgs(command, args)} completed`);
console.log(text);
});
context.on("generation:summary", (config, { pluginTimings, status, hrStart, failedPlugins, filesCreated }) => {
const summary = getSummary({
failedPlugins,
filesCreated,
config,
status,
hrStart,
pluginTimings: logLevel >= _kubb_core.logLevel.verbose ? pluginTimings : void 0
});
console.log(require_constants.SUMMARY_SEPARATOR);
console.log(summary.join("\n"));
console.log(require_constants.SUMMARY_SEPARATOR);
});
}
});
//#endregion
//#region src/loggers/utils.ts
/**
* Optionally prefix a message with a [HH:MM:SS] timestamp when logLevel >= verbose.
* Shared across all logger adapters to avoid duplication.
*/
function formatMessage(message, logLevel) {
if (logLevel >= _kubb_core.logLevel.verbose) return `${(0, node_util.styleText)("dim", `[${(/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
hour12: false,
hour: "2-digit",
minute: "2-digit",
second: "2-digit"
})}]`)} ${message}`;
return message;
}
/**
* Build the progress summary line shared by clack and GitHub Actions loggers.
* Returns null when there is nothing to display.
*/
function buildProgressLine(state) {
const parts = [];
const duration = formatHrtime(state.hrStart);
if (state.totalPlugins > 0) {
const pluginStr = state.failedPlugins > 0 ? `Plugins ${(0, node_util.styleText)("green", state.completedPlugins.toString())}/${state.totalPlugins} ${(0, node_util.styleText)("red", `(${state.failedPlugins} failed)`)}` : `Plugins ${(0, node_util.styleText)("green", state.completedPlugins.toString())}/${state.totalPlugins}`;
parts.push(pluginStr);
}
if (state.totalFiles > 0) parts.push(`Files ${(0, node_util.styleText)("green", state.processedFiles.toString())}/${state.totalFiles}`);
if (parts.length === 0) return null;
parts.push(`${(0, node_util.styleText)("green", duration)} elapsed`);
return parts.join((0, node_util.styleText)("dim", " | "));
}
/**
* Join a command and its optional args into a single display string.
* e.g. ("prettier", ["--write", "."]) → "prettier --write ."
*/
function formatCommandWithArgs(command, args) {
return args?.length ? `${command} ${args.join(" ")}` : command;
}
function detectLogger() {
if (require_telemetry.isGitHubActions()) return "github-actions";
if (require_telemetry.canUseTTY()) return "clack";
return "plain";
}
const logMapper = {
clack: clackLogger,
plain: plainLogger,
"github-actions": githubActionsLogger
};
async function setupLogger(context, { logLevel }) {
const type = detectLogger();
const logger = logMapper[type];
if (!logger) throw new Error(`Unknown adapter type: ${type}`);
const cleanup = await logger.install(context, { logLevel });
if (logLevel >= _kubb_core.logLevel.debug) await fileSystemLogger.install(context, { logLevel });
return cleanup;
}
//#endregion
//#region src/utils/executeHooks.ts
async function executeHooks({ hooks, events }) {
const commands = Array.isArray(hooks.done) ? hooks.done : [hooks.done].filter(Boolean);
for (const command of commands) {
const [cmd, ...args] = require_shell.tokenize(command);
if (!cmd) continue;
const hookId = (0, node_crypto.createHash)("sha256").update(command).digest("hex");
const hookEndPromise = new Promise((resolve, reject) => {
const handler = ({ id, success, error }) => {
if (id !== hookId) return;
events.off("hook:end", handler);
if (!success) {
reject(error ?? /* @__PURE__ */ new Error(`Hook failed: ${command}`));
return;
}
events.emit("success", `${(0, node_util.styleText)("dim", command)} successfully executed`).then(resolve).catch(reject);
};
events.on("hook:end", handler);
});
await events.emit("hook:start", {
id: hookId,
command: cmd,
args
});
await hookEndPromise;
}
}
//#endregion
//#region src/utils/getCosmiConfig.ts
const jiti$1 = (0, jiti.createJiti)(require("url").pathToFileURL(__filename).href, {
jsx: {
runtime: "automatic",
importSource: "@kubb/react-fabric"
},
sourceMaps: true,
interopDefault: true
});
const tsLoader = async (configFile) => {
return await jiti$1.import(configFile, { default: true });
};
async function getCosmiConfig(moduleName, config) {
let result;
const searchPlaces = [
"package.json",
`.${moduleName}rc`,
`.${moduleName}rc.json`,
`.${moduleName}rc.yaml`,
`.${moduleName}rc.yml`,
`.${moduleName}rc.ts`,
`.${moduleName}rc.mts`,
`.${moduleName}rc.cts`,
`.${moduleName}rc.js`,
`.${moduleName}rc.mjs`,
`.${moduleName}rc.cjs`,
`${moduleName}.config.ts`,
`${moduleName}.config.mts`,
`${moduleName}.config.cts`,
`${moduleName}.config.js`,
`${moduleName}.config.mjs`,
`${moduleName}.config.cjs`
];
const explorer = (0, cosmiconfig.cosmiconfig)(moduleName, {
cache: false,
searchPlaces: [
...searchPlaces.map((searchPlace) => {
return `.config/${searchPlace}`;
}),
...searchPlaces.map((searchPlace) => {
return `configs/${searchPlace}`;
}),
...searchPlaces
],
loaders: {
".ts": tsLoader,
".mts": tsLoader,
".cts": tsLoader
}
});
try {
result = config ? await explorer.load(config) : await explorer.search();
} catch (error) {
throw new Error("Config failed loading", { cause: error });
}
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, cb) {
const { watch } = await import("chokidar");
watch(path, {
ignorePermissionErrors: true,
ignored: require_constants.WATCHER_IGNORED_PATHS
}).on("all", async (type, file) => {
console.log((0, node_util.styleText)("yellow", (0, node_util.styleText)("bold", `Change detected: ${type} ${file}`)));
try {
await cb(path);
} catch (_e) {
console.log((0, node_util.styleText)("red", "Watcher failed"));
}
});
}
//#endregion
//#region src/runners/generate.ts
async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, configName, outputPath, logLevel, events, onStart, onEnd }) {
await onStart();
let resolvedTool = toolValue;
if (resolvedTool === "auto") {
const detected = await detect();
if (!detected) await events.emit("warn", noToolMessage);
else {
resolvedTool = detected;
await events.emit("info", `Auto-detected ${toolLabel}: ${(0, node_util.styleText)("dim", resolvedTool)}`);
}
}
if (resolvedTool && resolvedTool !== "auto" && resolvedTool in toolMap) {
const toolConfig = toolMap[resolvedTool];
try {
const hookId = (0, node_crypto.createHash)("sha256").update([configName, resolvedTool].filter(Boolean).join("-")).digest("hex");
const hookEndPromise = new Promise((resolve, reject) => {
const handler = ({ id, success, error }) => {
if (id !== hookId) return;
events.off("hook:end", handler);
if (!success) {
reject(error ?? /* @__PURE__ */ new Error(`${toolConfig.errorMessage}`));
return;
}
events.emit("success", [
`${successPrefix} with ${(0, node_util.styleText)("dim", resolvedTool)}`,
logLevel >= _kubb_core.logLevel.info ? `on ${(0, node_util.styleText)("dim", outputPath)}` : void 0,
"successfully"
].filter(Boolean).join(" ")).then(resolve).catch(reject);
};
events.on("hook:end", handler);
});
await events.emit("hook:start", {
id: hookId,
command: toolConfig.command,
args: toolConfig.args(outputPath)
});
await hookEndPromise;
} catch (caughtError) {
const err = new Error(toolConfig.errorMessage);
err.cause = caughtError;
await events.emit("error", err);
}
}
await onEnd();
}
async function generate({ input, config: userConfig, events, logLevel }) {
const inputPath = input ?? ("path" in userConfig.input ? userConfig.input.path : void 0);
const hrStart = node_process.default.hrtime();
const config = {
...userConfig,
root: userConfig.root || node_process.default.cwd(),
input: inputPath ? {
...userConfig.input,
path: inputPath
} : userConfig.input,
output: {
write: true,
barrelType: "named",
extension: { ".ts": ".ts" },
format: "prettier",
...userConfig.output
}
};
await events.emit("generation:start", config);
await events.emit("info", config.name ? `Setup generation ${(0, node_util.styleText)("bold", config.name)}` : "Setup generation", inputPath);
const { sources, fabric, pluginManager } = await (0, _kubb_core.setup)({
config,
events
});
await events.emit("info", config.name ? `Build generation ${(0, node_util.styleText)("bold", config.name)}` : "Build generation", inputPath);
const { files, failedPlugins, pluginTimings, error } = await (0, _kubb_core.safeBuild)({
config,
events
}, {
pluginManager,
fabric,
events,
sources
});
await events.emit("info", "Load summary");
if (failedPlugins.size > 0 || error) {
const allErrors = [error, ...Array.from(failedPlugins).filter((it) => it.error).map((it) => it.error)].filter(Boolean);
for (const err of allErrors) await events.emit("error", err);
await events.emit("generation:end", config, files, sources);
await events.emit("generation:summary", config, {
failedPlugins,
filesCreated: files.length,
status: "failed",
hrStart,
pluginTimings: logLevel >= _kubb_core.logLevel.verbose ? pluginTimings : void 0
});
await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
command: "generate",
kubbVersion: require_package.version,
plugins: pluginManager.plugins.map((p) => ({
name: p.name,
options: p.options
})),
hrStart,
filesCreated: files.length,
status: "failed"
}));
node_process.default.exit(1);
}
await events.emit("success", "Generation successfully", inputPath);
await events.emit("generation:end", config, files, sources);
const outputPath = node_path.default.resolve(config.root, config.output.path);
if (config.output.format) await runToolPass({
toolValue: config.output.format,
detect: _kubb_core.detectFormatter,
toolMap: _kubb_core.formatters,
toolLabel: "formatter",
successPrefix: "Formatting",
noToolMessage: "No formatter found (biome, prettier, or oxfmt). Skipping formatting.",
configName: config.name,
outputPath,
logLevel,
events,
onStart: () => events.emit("format:start"),
onEnd: () => events.emit("format:end")
});
if (config.output.lint) await runToolPass({
toolValue: config.output.lint,
detect: _kubb_core.detectLinter,
toolMap: _kubb_core.linters,
toolLabel: "linter",
successPrefix: "Linting",
noToolMessage: "No linter found (biome, oxlint, or eslint). Skipping linting.",
configName: config.name,
outputPath,
logLevel,
events,
onStart: () => events.emit("lint:start"),
onEnd: () => events.emit("lint:end")
});
if (config.hooks) {
await events.emit("hooks:start");
await executeHooks({
hooks: config.hooks,
events
});
await events.emit("hooks:end");
}
await events.emit("generation:summary", config, {
failedPlugins,
filesCreated: files.length,
status: "success",
hrStart,
pluginTimings
});
await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
command: "generate",
kubbVersion: require_package.version,
plugins: pluginManager.plugins.map((p) => ({
name: p.name,
options: p.options
})),
hrStart,
filesCreated: files.length,
status: "success"
}));
}
async function runGenerateCommand({ input, configPath, logLevel: logLevelKey, watch }) {
const logLevel = _kubb_core.logLevel[logLevelKey] ?? _kubb_core.logLevel.info;
const events = new AsyncEventEmitter();
const promiseManager = new _kubb_core.PromiseManager();
await setupLogger(events, { logLevel });
await require_telemetry.executeIfOnline(async () => {
try {
const latestVersion = (await (await fetch(require_constants.KUBB_NPM_PACKAGE_URL)).json()).version;
if (latestVersion && require_package.version < latestVersion) await events.emit("version:new", require_package.version, latestVersion);
} catch {}
});
try {
const result = await getCosmiConfig("kubb", configPath);
const configs = await (0, _kubb_core.getConfigs)(result.config, { input });
await events.emit("config:start");
await events.emit("info", "Config loaded", node_path.default.relative(node_process.default.cwd(), result.filepath));
await events.emit("success", "Config loaded successfully", node_path.default.relative(node_process.default.cwd(), result.filepath));
await events.emit("config:end", configs);
await events.emit("lifecycle:start", require_package.version);
const promises = configs.map((config) => {
return async () => {
if ((0, _kubb_core.isInputPath)(config) && watch) {
await startWatcher([input || config.input.path], async (paths) => {
events.removeAll();
await generate({
input,
config,
logLevel,
events
});
_clack_prompts.log.step((0, node_util.styleText)("yellow", `Watching for changes in ${paths.join(" and ")}`));
});
return;
}
await generate({
input,
config,
logLevel,
events
});
};
});
await promiseManager.run("seq", promises);
await events.emit("lifecycle:end");
} catch (error) {
await events.emit("error", require_errors.toError(error));
node_process.default.exit(1);
}
}
//#endregion
exports.runGenerateCommand = runGenerateCommand;
//# sourceMappingURL=generate-C2sBooAl.cjs.map

Sorry, the diff of this file is too big to display

require("./chunk-ByKO4r7w.cjs");
//#region src/commands/generate.ts
const command = require("./define-D6Kfm7-Z.cjs").defineCommand({
name: "generate",
description: "[input] Generate files based on a 'kubb.config.ts' file",
arguments: ["[input]"],
options: {
config: {
type: "string",
description: "Path to the Kubb config",
short: "c"
},
logLevel: {
type: "string",
description: "Info, silent, verbose or debug",
short: "l",
default: "info",
hint: "silent|info|verbose|debug",
enum: [
"silent",
"info",
"verbose",
"debug"
]
},
watch: {
type: "boolean",
description: "Watch mode based on the input file",
short: "w",
default: false
},
debug: {
type: "boolean",
description: "Override logLevel to debug",
short: "d",
default: false
},
verbose: {
type: "boolean",
description: "Override logLevel to verbose",
short: "v",
default: false
},
silent: {
type: "boolean",
description: "Override logLevel to silent",
short: "s",
default: false
}
},
async run({ values, positionals }) {
const logLevel = values.debug ? "debug" : values.verbose ? "verbose" : values.silent ? "silent" : values.logLevel;
const { runGenerateCommand } = await Promise.resolve().then(() => require("./generate-C2sBooAl.cjs"));
await runGenerateCommand({
input: positionals[0],
configPath: values.config,
logLevel,
watch: values.watch
});
}
});
//#endregion
exports.command = command;
//# sourceMappingURL=generate-DQ_S_FW_.cjs.map
{"version":3,"file":"generate-DQ_S_FW_.cjs","names":["defineCommand"],"sources":["../src/commands/generate.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\n\nexport const command = defineCommand({\n name: 'generate',\n description: \"[input] Generate files based on a 'kubb.config.ts' file\",\n arguments: ['[input]'],\n options: {\n config: { type: 'string', description: 'Path to the Kubb config', short: 'c' },\n logLevel: {\n type: 'string',\n description: 'Info, silent, verbose or debug',\n short: 'l',\n default: 'info',\n hint: 'silent|info|verbose|debug',\n enum: ['silent', 'info', 'verbose', 'debug'],\n },\n watch: { type: 'boolean', description: 'Watch mode based on the input file', short: 'w', default: false },\n debug: { type: 'boolean', description: 'Override logLevel to debug', short: 'd', default: false },\n verbose: { type: 'boolean', description: 'Override logLevel to verbose', short: 'v', default: false },\n silent: { type: 'boolean', description: 'Override logLevel to silent', short: 's', default: false },\n },\n async run({ values, positionals }) {\n const logLevel = values.debug ? 'debug' : values.verbose ? 'verbose' : values.silent ? 'silent' : values.logLevel\n const { runGenerateCommand } = await import('../runners/generate.ts')\n\n await runGenerateCommand({ input: positionals[0], configPath: values.config, logLevel, watch: values.watch })\n },\n})\n"],"mappings":";;AAEA,MAAa,2CAAUA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,WAAW,CAAC,UAAU;CACtB,SAAS;EACP,QAAQ;GAAE,MAAM;GAAU,aAAa;GAA2B,OAAO;GAAK;EAC9E,UAAU;GACR,MAAM;GACN,aAAa;GACb,OAAO;GACP,SAAS;GACT,MAAM;GACN,MAAM;IAAC;IAAU;IAAQ;IAAW;IAAQ;GAC7C;EACD,OAAO;GAAE,MAAM;GAAW,aAAa;GAAsC,OAAO;GAAK,SAAS;GAAO;EACzG,OAAO;GAAE,MAAM;GAAW,aAAa;GAA8B,OAAO;GAAK,SAAS;GAAO;EACjG,SAAS;GAAE,MAAM;GAAW,aAAa;GAAgC,OAAO;GAAK,SAAS;GAAO;EACrG,QAAQ;GAAE,MAAM;GAAW,aAAa;GAA+B,OAAO;GAAK,SAAS;GAAO;EACpG;CACD,MAAM,IAAI,EAAE,QAAQ,eAAe;EACjC,MAAM,WAAW,OAAO,QAAQ,UAAU,OAAO,UAAU,YAAY,OAAO,SAAS,WAAW,OAAO;EACzG,MAAM,EAAE,uBAAuB,MAAA,QAAA,SAAA,CAAA,WAAA,QAAM,0BAAA,CAAA;AAErC,QAAM,mBAAmB;GAAE,OAAO,YAAY;GAAI,YAAY,OAAO;GAAQ;GAAU,OAAO,OAAO;GAAO,CAAC;;CAEhH,CAAC"}
import "./chunk--u3MIqq1.js";
import { n as defineCommand } from "./define--M_JMcDC.js";
//#region src/commands/generate.ts
const command = defineCommand({
name: "generate",
description: "[input] Generate files based on a 'kubb.config.ts' file",
arguments: ["[input]"],
options: {
config: {
type: "string",
description: "Path to the Kubb config",
short: "c"
},
logLevel: {
type: "string",
description: "Info, silent, verbose or debug",
short: "l",
default: "info",
hint: "silent|info|verbose|debug",
enum: [
"silent",
"info",
"verbose",
"debug"
]
},
watch: {
type: "boolean",
description: "Watch mode based on the input file",
short: "w",
default: false
},
debug: {
type: "boolean",
description: "Override logLevel to debug",
short: "d",
default: false
},
verbose: {
type: "boolean",
description: "Override logLevel to verbose",
short: "v",
default: false
},
silent: {
type: "boolean",
description: "Override logLevel to silent",
short: "s",
default: false
}
},
async run({ values, positionals }) {
const logLevel = values.debug ? "debug" : values.verbose ? "verbose" : values.silent ? "silent" : values.logLevel;
const { runGenerateCommand } = await import("./generate-B7Ckt_LG.js");
await runGenerateCommand({
input: positionals[0],
configPath: values.config,
logLevel,
watch: values.watch
});
}
});
//#endregion
export { command };
//# sourceMappingURL=generate-Qcw6Ilwk.js.map
{"version":3,"file":"generate-Qcw6Ilwk.js","names":[],"sources":["../src/commands/generate.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\n\nexport const command = defineCommand({\n name: 'generate',\n description: \"[input] Generate files based on a 'kubb.config.ts' file\",\n arguments: ['[input]'],\n options: {\n config: { type: 'string', description: 'Path to the Kubb config', short: 'c' },\n logLevel: {\n type: 'string',\n description: 'Info, silent, verbose or debug',\n short: 'l',\n default: 'info',\n hint: 'silent|info|verbose|debug',\n enum: ['silent', 'info', 'verbose', 'debug'],\n },\n watch: { type: 'boolean', description: 'Watch mode based on the input file', short: 'w', default: false },\n debug: { type: 'boolean', description: 'Override logLevel to debug', short: 'd', default: false },\n verbose: { type: 'boolean', description: 'Override logLevel to verbose', short: 'v', default: false },\n silent: { type: 'boolean', description: 'Override logLevel to silent', short: 's', default: false },\n },\n async run({ values, positionals }) {\n const logLevel = values.debug ? 'debug' : values.verbose ? 'verbose' : values.silent ? 'silent' : values.logLevel\n const { runGenerateCommand } = await import('../runners/generate.ts')\n\n await runGenerateCommand({ input: positionals[0], configPath: values.config, logLevel, watch: values.watch })\n },\n})\n"],"mappings":";;;AAEA,MAAa,UAAU,cAAc;CACnC,MAAM;CACN,aAAa;CACb,WAAW,CAAC,UAAU;CACtB,SAAS;EACP,QAAQ;GAAE,MAAM;GAAU,aAAa;GAA2B,OAAO;GAAK;EAC9E,UAAU;GACR,MAAM;GACN,aAAa;GACb,OAAO;GACP,SAAS;GACT,MAAM;GACN,MAAM;IAAC;IAAU;IAAQ;IAAW;IAAQ;GAC7C;EACD,OAAO;GAAE,MAAM;GAAW,aAAa;GAAsC,OAAO;GAAK,SAAS;GAAO;EACzG,OAAO;GAAE,MAAM;GAAW,aAAa;GAA8B,OAAO;GAAK,SAAS;GAAO;EACjG,SAAS;GAAE,MAAM;GAAW,aAAa;GAAgC,OAAO;GAAK,SAAS;GAAO;EACrG,QAAQ;GAAE,MAAM;GAAW,aAAa;GAA+B,OAAO;GAAK,SAAS;GAAO;EACpG;CACD,MAAM,IAAI,EAAE,QAAQ,eAAe;EACjC,MAAM,WAAW,OAAO,QAAQ,UAAU,OAAO,UAAU,YAAY,OAAO,SAAS,WAAW,OAAO;EACzG,MAAM,EAAE,uBAAuB,MAAM,OAAO;AAE5C,QAAM,mBAAmB;GAAE,OAAO,YAAY;GAAI,YAAY,OAAO;GAAQ;GAAU,OAAO,OAAO;GAAO,CAAC;;CAEhH,CAAC"}
require("./chunk-ByKO4r7w.cjs");
const require_define = require("./define-D6Kfm7-Z.cjs");
const require_package = require("./package-CSJQyhYO.cjs");
//#region src/commands/init.ts
const command = require_define.defineCommand({
name: "init",
description: "Initialize a new Kubb project with interactive setup",
options: { yes: {
type: "boolean",
description: "Skip prompts and use default options",
short: "y",
default: false
} },
async run({ values }) {
const { runInit } = await Promise.resolve().then(() => require("./init-hmolV6B4.cjs"));
await runInit({
yes: values.yes,
version: require_package.version
});
}
});
//#endregion
exports.command = command;
//# sourceMappingURL=init-CibN8lng.cjs.map
{"version":3,"file":"init-CibN8lng.cjs","names":["defineCommand"],"sources":["../src/commands/init.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'init',\n description: 'Initialize a new Kubb project with interactive setup',\n options: {\n yes: { type: 'boolean', description: 'Skip prompts and use default options', short: 'y', default: false },\n },\n async run({ values }) {\n const { runInit } = await import('../runners/init.ts')\n\n await runInit({ yes: values.yes, version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAUA,eAAAA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,SAAS,EACP,KAAK;EAAE,MAAM;EAAW,aAAa;EAAwC,OAAO;EAAK,SAAS;EAAO,EAC1G;CACD,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,YAAY,MAAA,QAAA,SAAA,CAAA,WAAA,QAAM,sBAAA,CAAA;AAE1B,QAAM,QAAQ;GAAE,KAAK,OAAO;GAAK,SAAA,gBAAA;GAAS,CAAC;;CAE9C,CAAC"}
import "./chunk--u3MIqq1.js";
import { n as defineCommand } from "./define--M_JMcDC.js";
import { t as version } from "./package-Zc7qipPx.js";
//#region src/commands/init.ts
const command = defineCommand({
name: "init",
description: "Initialize a new Kubb project with interactive setup",
options: { yes: {
type: "boolean",
description: "Skip prompts and use default options",
short: "y",
default: false
} },
async run({ values }) {
const { runInit } = await import("./init-C-InrmSY.js");
await runInit({
yes: values.yes,
version
});
}
});
//#endregion
export { command };
//# sourceMappingURL=init-DqWUHya_.js.map
{"version":3,"file":"init-DqWUHya_.js","names":[],"sources":["../src/commands/init.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'init',\n description: 'Initialize a new Kubb project with interactive setup',\n options: {\n yes: { type: 'boolean', description: 'Skip prompts and use default options', short: 'y', default: false },\n },\n async run({ values }) {\n const { runInit } = await import('../runners/init.ts')\n\n await runInit({ yes: values.yes, version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAU,cAAc;CACnC,MAAM;CACN,aAAa;CACb,SAAS,EACP,KAAK;EAAE,MAAM;EAAW,aAAa;EAAwC,OAAO;EAAK,SAAS;EAAO,EAC1G;CACD,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,YAAY,MAAM,OAAO;AAEjC,QAAM,QAAQ;GAAE,KAAK,OAAO;GAAK;GAAS,CAAC;;CAE9C,CAAC"}
import "./chunk--u3MIqq1.js";
import { n as defineCommand } from "./define--M_JMcDC.js";
import { t as version } from "./package-Zc7qipPx.js";
//#region src/commands/mcp.ts
const command = defineCommand({
name: "mcp",
description: "Start the server to enable the MCP client to interact with the LLM.",
async run() {
const { runMcp } = await import("./mcp-Cwbv3dfC.js");
await runMcp({ version });
}
});
//#endregion
export { command };
//# sourceMappingURL=mcp-DwRXOXZV.js.map
{"version":3,"file":"mcp-DwRXOXZV.js","names":[],"sources":["../src/commands/mcp.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'mcp',\n description: 'Start the server to enable the MCP client to interact with the LLM.',\n async run() {\n const { runMcp } = await import('../runners/mcp.ts')\n\n await runMcp({ version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAU,cAAc;CACnC,MAAM;CACN,aAAa;CACb,MAAM,MAAM;EACV,MAAM,EAAE,WAAW,MAAM,OAAO;AAEhC,QAAM,OAAO,EAAE,SAAS,CAAC;;CAE5B,CAAC"}
require("./chunk-ByKO4r7w.cjs");
const require_define = require("./define-D6Kfm7-Z.cjs");
const require_package = require("./package-CSJQyhYO.cjs");
//#region src/commands/mcp.ts
const command = require_define.defineCommand({
name: "mcp",
description: "Start the server to enable the MCP client to interact with the LLM.",
async run() {
const { runMcp } = await Promise.resolve().then(() => require("./mcp-X8kKSlov.cjs"));
await runMcp({ version: require_package.version });
}
});
//#endregion
exports.command = command;
//# sourceMappingURL=mcp-uDMa0yKp.cjs.map
{"version":3,"file":"mcp-uDMa0yKp.cjs","names":["defineCommand"],"sources":["../src/commands/mcp.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'mcp',\n description: 'Start the server to enable the MCP client to interact with the LLM.',\n async run() {\n const { runMcp } = await import('../runners/mcp.ts')\n\n await runMcp({ version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAUA,eAAAA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,MAAM,MAAM;EACV,MAAM,EAAE,WAAW,MAAA,QAAA,SAAA,CAAA,WAAA,QAAM,qBAAA,CAAA;AAEzB,QAAM,OAAO,EAAE,SAAA,gBAAA,SAAS,CAAC;;CAE5B,CAAC"}
//#region package.json
var version = "4.37.7";
//#endregion
Object.defineProperty(exports, "version", {
enumerable: true,
get: function() {
return version;
}
});
//# sourceMappingURL=package-CSJQyhYO.cjs.map
{"version":3,"file":"package-CSJQyhYO.cjs","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
//#region package.json
var version = "4.37.7";
//#endregion
export { version as t };
//# sourceMappingURL=package-Zc7qipPx.js.map
{"version":3,"file":"package-Zc7qipPx.js","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
require("./chunk-ByKO4r7w.cjs");
const require_define = require("./define-D6Kfm7-Z.cjs");
const require_package = require("./package-CSJQyhYO.cjs");
//#region src/commands/validate.ts
const command = require_define.defineCommand({
name: "validate",
description: "Validate a Swagger/OpenAPI file",
options: { input: {
type: "string",
description: "Path to Swagger/OpenAPI file",
short: "i",
required: true
} },
async run({ values }) {
const { runValidate } = await Promise.resolve().then(() => require("./validate-DYVo8-Fj.cjs"));
await runValidate({
input: values.input,
version: require_package.version
});
}
});
//#endregion
exports.command = command;
//# sourceMappingURL=validate-BRzEtRj7.cjs.map
{"version":3,"file":"validate-BRzEtRj7.cjs","names":["defineCommand"],"sources":["../src/commands/validate.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'validate',\n description: 'Validate a Swagger/OpenAPI file',\n options: {\n input: { type: 'string', description: 'Path to Swagger/OpenAPI file', short: 'i', required: true },\n },\n async run({ values }) {\n const { runValidate } = await import('../runners/validate.ts')\n\n await runValidate({ input: values.input, version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAUA,eAAAA,cAAc;CACnC,MAAM;CACN,aAAa;CACb,SAAS,EACP,OAAO;EAAE,MAAM;EAAU,aAAa;EAAgC,OAAO;EAAK,UAAU;EAAM,EACnG;CACD,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,gBAAgB,MAAA,QAAA,SAAA,CAAA,WAAA,QAAM,0BAAA,CAAA;AAE9B,QAAM,YAAY;GAAE,OAAO,OAAO;GAAO,SAAA,gBAAA;GAAS,CAAC;;CAEtD,CAAC"}
import "./chunk--u3MIqq1.js";
import { n as defineCommand } from "./define--M_JMcDC.js";
import { t as version } from "./package-Zc7qipPx.js";
//#region src/commands/validate.ts
const command = defineCommand({
name: "validate",
description: "Validate a Swagger/OpenAPI file",
options: { input: {
type: "string",
description: "Path to Swagger/OpenAPI file",
short: "i",
required: true
} },
async run({ values }) {
const { runValidate } = await import("./validate-BGyxLev8.js");
await runValidate({
input: values.input,
version
});
}
});
//#endregion
export { command };
//# sourceMappingURL=validate-IUvDwpX1.js.map
{"version":3,"file":"validate-IUvDwpX1.js","names":[],"sources":["../src/commands/validate.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'validate',\n description: 'Validate a Swagger/OpenAPI file',\n options: {\n input: { type: 'string', description: 'Path to Swagger/OpenAPI file', short: 'i', required: true },\n },\n async run({ values }) {\n const { runValidate } = await import('../runners/validate.ts')\n\n await runValidate({ input: values.input, version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAU,cAAc;CACnC,MAAM;CACN,aAAa;CACb,SAAS,EACP,OAAO;EAAE,MAAM;EAAU,aAAa;EAAgC,OAAO;EAAK,UAAU;EAAM,EACnG;CACD,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,gBAAgB,MAAM,OAAO;AAErC,QAAM,YAAY;GAAE,OAAO,OAAO;GAAO;GAAS,CAAC;;CAEtD,CAAC"}