@kubb/cli 5.4.1 → 5.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/{background-BDZa6MJS.js → background-C64cE-Ua.js} +2 -2
  2. package/dist/{background-BDZa6MJS.js.map → background-C64cE-Ua.js.map} +1 -1
  3. package/dist/background-CqXG88yo.js +2 -0
  4. package/dist/{background-CNHhnQ5M.cjs → background-DTWZnKnJ.cjs} +2 -2
  5. package/dist/{background-CNHhnQ5M.cjs.map → background-DTWZnKnJ.cjs.map} +1 -1
  6. package/dist/{connect-CIVmP_6l.js → connect-9Oc4cfYT.js} +2 -2
  7. package/dist/{connect-CIVmP_6l.js.map → connect-9Oc4cfYT.js.map} +1 -1
  8. package/dist/{connect-DLbFBfoV.cjs → connect-aB9I7Wqg.cjs} +2 -2
  9. package/dist/{connect-DLbFBfoV.cjs.map → connect-aB9I7Wqg.cjs.map} +1 -1
  10. package/dist/{generate-BY_PbRPu.js → generate-BOMX7IVh.js} +2 -2
  11. package/dist/{generate-BY_PbRPu.js.map → generate-BOMX7IVh.js.map} +1 -1
  12. package/dist/{generate-BWwjYxN5.cjs → generate-CTBkaj_g.cjs} +2 -2
  13. package/dist/{generate-BWwjYxN5.cjs.map → generate-CTBkaj_g.cjs.map} +1 -1
  14. package/dist/index.cjs +7 -7
  15. package/dist/index.js +7 -7
  16. package/dist/{init-Dpa1wuah.js → init-CLoakc-0.js} +3 -3
  17. package/dist/{init-Dpa1wuah.js.map → init-CLoakc-0.js.map} +1 -1
  18. package/dist/{init-yb2ZIQwp.cjs → init-DBHdf5aF.cjs} +3 -3
  19. package/dist/{init-yb2ZIQwp.cjs.map → init-DBHdf5aF.cjs.map} +1 -1
  20. package/dist/{login-Di6_DU_V.js → login-DSlP3N0Y.js} +2 -2
  21. package/dist/{login-Di6_DU_V.js.map → login-DSlP3N0Y.js.map} +1 -1
  22. package/dist/{login-LVIZdclC.cjs → login-d2Qe4fhd.cjs} +2 -2
  23. package/dist/{login-LVIZdclC.cjs.map → login-d2Qe4fhd.cjs.map} +1 -1
  24. package/dist/{logout-BOhSROh8.js → logout-C4B9lPtr.js} +3 -3
  25. package/dist/{logout-BOhSROh8.js.map → logout-C4B9lPtr.js.map} +1 -1
  26. package/dist/{logout-B8L-Jb8P.cjs → logout-D3GiSg15.cjs} +3 -3
  27. package/dist/{logout-B8L-Jb8P.cjs.map → logout-D3GiSg15.cjs.map} +1 -1
  28. package/dist/{output-D-9bGS7y.cjs → output-9qUFmWFq.cjs} +2 -2
  29. package/dist/{output-D-9bGS7y.cjs.map → output-9qUFmWFq.cjs.map} +1 -1
  30. package/dist/{output-C5h3LBgQ.js → output-Dkoh9Ig6.js} +32 -32
  31. package/dist/{output-C5h3LBgQ.js.map → output-Dkoh9Ig6.js.map} +1 -1
  32. package/dist/package-9W_72uNT.js +6 -0
  33. package/dist/package-9W_72uNT.js.map +1 -0
  34. package/dist/{package-DjS7Xk-S.cjs → package-C0HirQFL.cjs} +2 -2
  35. package/dist/package-C0HirQFL.cjs.map +1 -0
  36. package/dist/{run-BNQt-kUj.cjs → run-BFn3tpiE.cjs} +2 -2
  37. package/dist/{run-BNQt-kUj.cjs.map → run-BFn3tpiE.cjs.map} +1 -1
  38. package/dist/{run-G2lUygYI.js → run-BH26mNIp.js} +2 -2
  39. package/dist/{run-G2lUygYI.js.map → run-BH26mNIp.js.map} +1 -1
  40. package/dist/{run-Bidc3n3b.cjs → run-BhRWMu9D.cjs} +2 -2
  41. package/dist/{run-Bidc3n3b.cjs.map → run-BhRWMu9D.cjs.map} +1 -1
  42. package/dist/{run-_hE0GAWu.cjs → run-Blvb9Xpo.cjs} +8 -10
  43. package/dist/run-Blvb9Xpo.cjs.map +1 -0
  44. package/dist/{run-BsP5syy1.js → run-BtgXGBEQ.js} +8 -10
  45. package/dist/run-BtgXGBEQ.js.map +1 -0
  46. package/dist/{run-BaqE5cze.js → run-DH4iFBCV.js} +2 -2
  47. package/dist/{run-BaqE5cze.js.map → run-DH4iFBCV.js.map} +1 -1
  48. package/dist/{run-GGJ4QLsg.cjs → run-DZIUhVsF.cjs} +2 -2
  49. package/dist/{run-GGJ4QLsg.cjs.map → run-DZIUhVsF.cjs.map} +1 -1
  50. package/dist/{run-Drf9rg9j.js → run-DeQhQ9nw.js} +2 -2
  51. package/dist/{run-Drf9rg9j.js.map → run-DeQhQ9nw.js.map} +1 -1
  52. package/dist/{run-0k75--OI.cjs → run-_9aC9inz.cjs} +4 -4
  53. package/dist/{run-0k75--OI.cjs.map → run-_9aC9inz.cjs.map} +1 -1
  54. package/dist/{run-DQNoMoHW.js → run-rjPx8C8b.js} +4 -4
  55. package/dist/{run-DQNoMoHW.js.map → run-rjPx8C8b.js.map} +1 -1
  56. package/dist/{snapshot-DndnZx5y.cjs → snapshot-BOJa_d8W.cjs} +4 -4
  57. package/dist/{snapshot-DndnZx5y.cjs.map → snapshot-BOJa_d8W.cjs.map} +1 -1
  58. package/dist/{snapshot-ZY24CtRk.js → snapshot-QwAF-jtn.js} +4 -4
  59. package/dist/{snapshot-ZY24CtRk.js.map → snapshot-QwAF-jtn.js.map} +1 -1
  60. package/dist/{start-BlwmWZDb.js → start-BJlQdJA_.js} +3 -3
  61. package/dist/{start-BlwmWZDb.js.map → start-BJlQdJA_.js.map} +1 -1
  62. package/dist/{start-Bu5xpzix.cjs → start-CNwAkbvJ.cjs} +3 -3
  63. package/dist/{start-Bu5xpzix.cjs.map → start-CNwAkbvJ.cjs.map} +1 -1
  64. package/dist/{status-L4I8buia.cjs → status-DGqYtJjk.cjs} +3 -3
  65. package/dist/{status-L4I8buia.cjs.map → status-DGqYtJjk.cjs.map} +1 -1
  66. package/dist/{status-5UqQP9WB.js → status-Djgd7LoZ.js} +3 -3
  67. package/dist/{status-5UqQP9WB.js.map → status-Djgd7LoZ.js.map} +1 -1
  68. package/dist/{stop-BQkjAPNH.cjs → stop-CFRhvsL_.cjs} +2 -2
  69. package/dist/{stop-BQkjAPNH.cjs.map → stop-CFRhvsL_.cjs.map} +1 -1
  70. package/dist/{stop-mqUTbxMO.js → stop-CKaFhKLQ.js} +2 -2
  71. package/dist/{stop-mqUTbxMO.js.map → stop-CKaFhKLQ.js.map} +1 -1
  72. package/dist/{studio-BBnIuXst.js → studio-BHVkTqrV.js} +9 -9
  73. package/dist/{studio-BBnIuXst.js.map → studio-BHVkTqrV.js.map} +1 -1
  74. package/dist/{studio-BFy085ae.cjs → studio-C42UMY7Y.cjs} +9 -9
  75. package/dist/{studio-BFy085ae.cjs.map → studio-C42UMY7Y.cjs.map} +1 -1
  76. package/dist/studioWorker.js +2 -2
  77. package/dist/{utils-BWksgOYQ.js → utils-BYY3_cyq.js} +266 -266
  78. package/dist/utils-BYY3_cyq.js.map +1 -0
  79. package/dist/{utils-DqUNntyL.cjs → utils-Dcw3l4Wz.cjs} +9 -3
  80. package/dist/utils-Dcw3l4Wz.cjs.map +1 -0
  81. package/package.json +8 -8
  82. package/dist/background-CS7jIBAY.js +0 -2
  83. package/dist/package-DjS7Xk-S.cjs.map +0 -1
  84. package/dist/package-IY922xjh.js +0 -6
  85. package/dist/package-IY922xjh.js.map +0 -1
  86. package/dist/run-BsP5syy1.js.map +0 -1
  87. package/dist/run-_hE0GAWu.cjs.map +0 -1
  88. package/dist/utils-BWksgOYQ.js.map +0 -1
  89. package/dist/utils-DqUNntyL.cjs.map +0 -1
@@ -2,7 +2,7 @@ import "./rolldown-runtime-CRm0XQPb.js";
2
2
  import { t as toError } from "./errors-BQJzaUwP.js";
3
3
  import { t as getAgentName } from "./agent-w0Hlq4mG.js";
4
4
  import { c as URL_WATCHER_TIMEOUT_MS, l as WATCHER_IGNORED_PATHS, s as URL_WATCHER_INTERVAL_MS } from "./Telemetry-cHHOzBW8.js";
5
- import { f as formatMsWithColor, h as getElapsedMs, m as formatMs, p as canUseTTY } from "./output-C5h3LBgQ.js";
5
+ import { f as canUseTTY, h as getElapsedMs, m as formatMs, p as formatMsWithColor } from "./output-Dkoh9Ig6.js";
6
6
  import { styleText } from "node:util";
7
7
  import { randomUUID } from "node:crypto";
8
8
  import process from "node:process";
@@ -13,7 +13,7 @@ import { createJiti } from "jiti";
13
13
  import { Diagnostics, createCliReporter, logLevel } from "@kubb/core";
14
14
  import { NonZeroExitError, x } from "tinyexec";
15
15
  import { loadConfig } from "unconfig";
16
- import { isGreater, isValid, truncate } from "verkit";
16
+ import { isGreaterThan, isValid, truncate } from "verkit";
17
17
  //#region ../../internals/utils/src/tools.ts
18
18
  /**
19
19
  * CLI command descriptors for each supported code formatter.
@@ -149,6 +149,258 @@ function createModuleLoader() {
149
149
  return options?.default ? jiti.import(filePath, { default: true }) : jiti.import(filePath);
150
150
  } };
151
151
  }
152
+ /**
153
+ * TTY logger for local development, with animated steps and progress bars.
154
+ */
155
+ const clackLogger = {
156
+ name: "clack",
157
+ install: createLogger({
158
+ group: (title) => clack.intro(title),
159
+ groupEnd: (text) => clack.outro(text),
160
+ step: (text) => clack.log.step(text, { spacing: 0 }),
161
+ info: (text) => clack.log.info(text),
162
+ success: (text) => clack.log.success(text),
163
+ warn: (text) => clack.log.warn(text),
164
+ error: (text) => clack.log.error(text),
165
+ block: (lines) => clack.log.message(lines, { spacing: 0 }),
166
+ raw: (lines) => console.log(styleText("dim", lines.join("\n"))),
167
+ diagnostic: (lines) => clack.log.message(lines, {
168
+ symbol: "",
169
+ secondarySymbol: ""
170
+ }),
171
+ update: (lines, title) => clack.box(lines.join("\n"), title, {
172
+ width: "auto",
173
+ formatBorder: (border) => styleText("yellow", border),
174
+ rounded: true,
175
+ withGuide: false,
176
+ contentAlign: "center",
177
+ titleAlign: "center"
178
+ }),
179
+ spinner() {
180
+ const spinner = clack.spinner();
181
+ return {
182
+ start: (text) => spinner.start(text),
183
+ message: (text) => spinner.message(text),
184
+ clear: () => spinner.clear(),
185
+ stop: (text) => spinner.stop(text),
186
+ error: (text) => spinner.error(text)
187
+ };
188
+ },
189
+ progress(max) {
190
+ const bar = clack.progress({
191
+ style: "block",
192
+ max,
193
+ size: 30
194
+ });
195
+ return {
196
+ start: (text) => bar.start(text),
197
+ advance: (text) => bar.advance(1, text),
198
+ stop: (text) => bar.stop(text)
199
+ };
200
+ }
201
+ })
202
+ };
203
+ //#endregion
204
+ //#region src/loggers/utils.ts
205
+ /**
206
+ * Display path for a config's input: the string form, or its `path` field when the input is an
207
+ * object. Loggers show it alongside `Generation started`.
208
+ */
209
+ function getInputPath(config) {
210
+ const { input } = config;
211
+ if (typeof input === "string") return input;
212
+ return typeof input?.path === "string" ? input.path : void 0;
213
+ }
214
+ /**
215
+ * Counts a noun, so a message never reads `1 files`.
216
+ *
217
+ * @example
218
+ * `pluralize(1, 'config')` returns `'1 config'`
219
+ */
220
+ function pluralize(count, noun) {
221
+ return `${count} ${count === 1 ? noun : `${noun}s`}`;
222
+ }
223
+ /**
224
+ * Optionally prefix a message with a [HH:MM:SS] timestamp when logLevel >= verbose.
225
+ * Shared across all logger adapters to avoid duplication.
226
+ */
227
+ function formatMessage(message, logLevel$2) {
228
+ if (logLevel$2 >= logLevel.verbose) {
229
+ const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
230
+ hour12: false,
231
+ hour: "2-digit",
232
+ minute: "2-digit",
233
+ second: "2-digit"
234
+ });
235
+ return `${styleText("dim", `[${timestamp}]`)} ${message}`;
236
+ }
237
+ return message;
238
+ }
239
+ /**
240
+ * Renders the versions from a `studio:connected` event as one parenthetical. The runtime is listed
241
+ * only when it differs from the host, and Studio's only when it sent one.
242
+ */
243
+ function formatVersions({ studio, kubb, agent }) {
244
+ return [
245
+ `v${agent}`,
246
+ kubb !== agent ? `runtime v${kubb}` : void 0,
247
+ studio ? `Studio v${studio}` : void 0
248
+ ].filter(Boolean).join(", ");
249
+ }
250
+ /**
251
+ * Extracts the `.cause` of an `Error` as an `Error`, or `undefined` when absent or not an `Error`.
252
+ */
253
+ function toCause(error) {
254
+ return error.cause instanceof Error ? error.cause : void 0;
255
+ }
256
+ /**
257
+ * First stack frames for verbose error output, including an optional `cause` chain.
258
+ */
259
+ function formatErrorFrames(error) {
260
+ if (!error.stack) return null;
261
+ const frames = error.stack.split("\n").slice(1, 4).map((frame) => frame.trim());
262
+ const caused = toCause(error);
263
+ if (!caused?.stack) return { frames };
264
+ return {
265
+ frames,
266
+ cause: {
267
+ header: `└─ caused by ${caused.message}`,
268
+ frames: caused.stack.split("\n").slice(1, 4).map((frame) => frame.trim())
269
+ }
270
+ };
271
+ }
272
+ /**
273
+ * Build the progress summary line shown by the clack logger.
274
+ * Returns null when there is nothing to display.
275
+ */
276
+ function buildProgressLine(state) {
277
+ const parts = [];
278
+ const duration = formatMs(getElapsedMs(state.hrStart));
279
+ if (state.totalPlugins > 0) {
280
+ 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}`;
281
+ parts.push(pluginStr);
282
+ }
283
+ if (state.totalFiles > 0) parts.push(`Files ${styleText("green", state.processedFiles.toString())}/${state.totalFiles}`);
284
+ if (parts.length === 0) return null;
285
+ parts.push(`${styleText("green", duration)} elapsed`);
286
+ return parts.join(styleText("dim", " | "));
287
+ }
288
+ /**
289
+ * Creates the per-run progress counters used by the clack logger.
290
+ */
291
+ function createProgressCounters() {
292
+ return {
293
+ totalPlugins: 0,
294
+ completedPlugins: 0,
295
+ failedPlugins: 0,
296
+ totalFiles: 0,
297
+ processedFiles: 0,
298
+ hrStart: process.hrtime()
299
+ };
300
+ }
301
+ /**
302
+ * Resets the progress counters in place at the start/end of a generation run.
303
+ */
304
+ function resetProgressCounters(state) {
305
+ state.totalPlugins = 0;
306
+ state.completedPlugins = 0;
307
+ state.failedPlugins = 0;
308
+ state.totalFiles = 0;
309
+ state.processedFiles = 0;
310
+ state.hrStart = process.hrtime();
311
+ }
312
+ /**
313
+ * Records a finished plugin against the progress counters.
314
+ */
315
+ function recordPluginResult(state, success) {
316
+ if (success) state.completedPlugins++;
317
+ else state.failedPlugins++;
318
+ }
319
+ /**
320
+ * Join a command and its optional args into a single display string.
321
+ *
322
+ * @example With args
323
+ * `formatCommandWithArgs('prettier', ['--write', '.'])` returns `'prettier --write .'`
324
+ */
325
+ function formatCommandWithArgs(command, args) {
326
+ return args?.length ? `${command} ${args.join(" ")}` : command;
327
+ }
328
+ /**
329
+ * Bridges a {@link Reporter} onto the run's hook emitter: calls `report` with each config's
330
+ * {@link GenerationResult} on `kubb:generation:end`. The reporter never touches the emitter.
331
+ */
332
+ function installReporter(context, reporter, ctx) {
333
+ const pluginFiles = reporter.needsPluginFiles ? /* @__PURE__ */ new Map() : void 0;
334
+ if (pluginFiles) context.hook("kubb:plugin:end", ({ config, plugin, files }) => {
335
+ const filesByPlugin = pluginFiles.get(config) ?? /* @__PURE__ */ new Map();
336
+ const seen = new Set([...filesByPlugin.values()].flatMap((paths) => [...paths]));
337
+ const added = files.filter((file) => !seen.has(file.path)).map((file) => file.path);
338
+ if (added.length) filesByPlugin.set(plugin.name, /* @__PURE__ */ new Set([...filesByPlugin.get(plugin.name) ?? [], ...added]));
339
+ pluginFiles.set(config, filesByPlugin);
340
+ });
341
+ context.hook("kubb:generation:end", async ({ config, diagnostics = [], filesCreated = 0, status = "success", hrStart = process.hrtime() }) => {
342
+ const files = pluginFiles?.get(config);
343
+ const grouped = files && [...files].map(([plugin, paths]) => ({
344
+ plugin,
345
+ files: [...paths]
346
+ }));
347
+ await reporter.report({
348
+ config,
349
+ diagnostics,
350
+ filesCreated,
351
+ status,
352
+ hrStart,
353
+ pluginFiles: grouped
354
+ }, ctx);
355
+ pluginFiles?.delete(config);
356
+ });
357
+ if (reporter.drain) context.hook("kubb:lifecycle:end", () => reporter.drain?.(ctx));
358
+ }
359
+ /**
360
+ * Installs the live logger (the TUI view) and the given reporters (the output). The reporters are
361
+ * already selected by the caller (the CLI maps `--reporter` to names via `selectReporters`). This
362
+ * only wires them. Loggers receive hook subprocess output through `kubb:hook:line` and the
363
+ * `stdout`/`stderr` on `kubb:hook:end`, so nothing is returned here.
364
+ *
365
+ * Loggers and reporters are independent, except for `cli`: it both installs the live logger view
366
+ * here and registers a reporter that renders the per-config summary through that logger, so the
367
+ * summary lands inside the group the logger opened. The `json` reporter owns stdout, so the whole
368
+ * `cli` reporter (live logger and summary) is skipped whenever `json` is among the reporters, even
369
+ * if `cli` is also listed.
370
+ */
371
+ async function setupReporters(context, { logLevel, reporters, logger: forcedLogger }) {
372
+ let cliHandle;
373
+ const hasJson = reporters.some((reporter) => reporter.name === "json");
374
+ const ctx = { logLevel };
375
+ for (const reporter of reporters) {
376
+ if (reporter.name !== "cli") {
377
+ installReporter(context, reporter, ctx);
378
+ continue;
379
+ }
380
+ if (hasJson) continue;
381
+ const handle = await (forcedLogger ?? (canUseTTY() && !getAgentName() ? clackLogger : plainLogger)).install(context, { logLevel }) ?? void 0;
382
+ cliHandle = handle;
383
+ installReporter(context, createCliReporter({ render: handle?.renderSummary }), ctx);
384
+ }
385
+ return cliHandle;
386
+ }
387
+ /**
388
+ * Picks the reporters whose `name` matches one of `names`, in the order the names are given.
389
+ * The config carries every available reporter, and the host selects which to activate by name
390
+ * (the CLI maps `--reporter` to this). Duplicate names and names without a matching reporter are
391
+ * skipped.
392
+ */
393
+ function selectReporters(reporters, names) {
394
+ const seen = /* @__PURE__ */ new Set();
395
+ const selected = [];
396
+ for (const name of names) {
397
+ if (seen.has(name)) continue;
398
+ seen.add(name);
399
+ const reporter = reporters.find((candidate) => candidate.name === name);
400
+ if (reporter) selected.push(reporter);
401
+ }
402
+ return selected;
403
+ }
152
404
  //#endregion
153
405
  //#region src/loggers/createLogger.ts
154
406
  /**
@@ -194,8 +446,8 @@ function trimBlankEdges(lines) {
194
446
  */
195
447
  function createLogger(writer) {
196
448
  return function install(context, options) {
197
- const logLevel$2 = options?.logLevel ?? logLevel.info;
198
- const silent = logLevel$2 <= logLevel.silent;
449
+ const logLevel$1 = options?.logLevel ?? logLevel.info;
450
+ const silent = logLevel$1 <= logLevel.silent;
199
451
  const state = {
200
452
  ...createProgressCounters(),
201
453
  spinner: null,
@@ -209,7 +461,7 @@ function createLogger(writer) {
209
461
  groupOpen: false
210
462
  };
211
463
  function text(message) {
212
- return formatMessage(message, logLevel$2);
464
+ return formatMessage(message, logLevel$1);
213
465
  }
214
466
  function startSpinner(message) {
215
467
  if (silent) return;
@@ -299,7 +551,7 @@ function createLogger(writer) {
299
551
  const line = text([
300
552
  styleText("green", "✓"),
301
553
  message,
302
- logLevel$2 >= logLevel.info && info ? styleText("dim", info) : void 0
554
+ logLevel$1 >= logLevel.info && info ? styleText("dim", info) : void 0
303
555
  ].filter(Boolean).join(" "));
304
556
  if (state.spinner) {
305
557
  state.spinner.message(line);
@@ -308,11 +560,11 @@ function createLogger(writer) {
308
560
  writer.success(line);
309
561
  });
310
562
  context.hook("kubb:warn", ({ message, info }) => {
311
- if (logLevel$2 < logLevel.warn) return;
563
+ if (logLevel$1 < logLevel.warn) return;
312
564
  writer.warn(text([
313
565
  styleText("yellow", "⚠"),
314
566
  message,
315
- logLevel$2 >= logLevel.info && info ? styleText("dim", info) : void 0
567
+ logLevel$1 >= logLevel.info && info ? styleText("dim", info) : void 0
316
568
  ].filter(Boolean).join(" ")));
317
569
  });
318
570
  context.hook("kubb:error", ({ error }) => {
@@ -320,7 +572,7 @@ function createLogger(writer) {
320
572
  const line = [styleText("red", "✗"), error.message].join(" ");
321
573
  if (state.spinner) stopSpinner(line, "failed");
322
574
  else writer.error(text(line));
323
- const frames = logLevel$2 >= logLevel.verbose ? formatErrorFrames(error) : null;
575
+ const frames = logLevel$1 >= logLevel.verbose ? formatErrorFrames(error) : null;
324
576
  if (!frames) return;
325
577
  writer.block(frames.frames.map((frame) => text(styleText("dim", frame))));
326
578
  if (frames.cause) writer.block([styleText("dim", frames.cause.header), ...frames.cause.frames.map((frame) => text(` ${styleText("dim", frame)}`))]);
@@ -353,7 +605,7 @@ function createLogger(writer) {
353
605
  startSpinner("✓ Ready to receive jobs");
354
606
  });
355
607
  context.hook("studio:disconnected", ({ reason }) => {
356
- if (logLevel$2 < logLevel.warn) return;
608
+ if (logLevel$1 < logLevel.warn) return;
357
609
  stopSpinner();
358
610
  writer.warn(text(`⚠ Kubb Studio ended the session (${reason})`));
359
611
  });
@@ -373,7 +625,7 @@ function createLogger(writer) {
373
625
  writer.info(text(styleText("dim", `Retrying connection to Kubb Studio in ${formatMs(delayMs)}`)));
374
626
  });
375
627
  context.hook("studio:warn", ({ message, permission }) => {
376
- if (logLevel$2 < logLevel.warn) return;
628
+ if (logLevel$1 < logLevel.warn) return;
377
629
  const remedy = permission ? `; pass --${permission.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`)} to allow it` : "";
378
630
  writer.warn(text(`⚠ ${message}${remedy}`));
379
631
  });
@@ -498,57 +750,6 @@ function createLogger(writer) {
498
750
  } };
499
751
  };
500
752
  }
501
- /**
502
- * TTY logger for local development, with animated steps and progress bars.
503
- */
504
- const clackLogger = {
505
- name: "clack",
506
- install: createLogger({
507
- group: (title) => clack.intro(title),
508
- groupEnd: (text) => clack.outro(text),
509
- step: (text) => clack.log.step(text, { spacing: 0 }),
510
- info: (text) => clack.log.info(text),
511
- success: (text) => clack.log.success(text),
512
- warn: (text) => clack.log.warn(text),
513
- error: (text) => clack.log.error(text),
514
- block: (lines) => clack.log.message(lines, { spacing: 0 }),
515
- raw: (lines) => console.log(styleText("dim", lines.join("\n"))),
516
- diagnostic: (lines) => clack.log.message(lines, {
517
- symbol: "",
518
- secondarySymbol: ""
519
- }),
520
- update: (lines, title) => clack.box(lines.join("\n"), title, {
521
- width: "auto",
522
- formatBorder: (border) => styleText("yellow", border),
523
- rounded: true,
524
- withGuide: false,
525
- contentAlign: "center",
526
- titleAlign: "center"
527
- }),
528
- spinner() {
529
- const spinner = clack.spinner();
530
- return {
531
- start: (text) => spinner.start(text),
532
- message: (text) => spinner.message(text),
533
- clear: () => spinner.clear(),
534
- stop: (text) => spinner.stop(text),
535
- error: (text) => spinner.error(text)
536
- };
537
- },
538
- progress(max) {
539
- const bar = clack.progress({
540
- style: "block",
541
- max,
542
- size: 30
543
- });
544
- return {
545
- start: (text) => bar.start(text),
546
- advance: (text) => bar.advance(1, text),
547
- stop: (text) => bar.stop(text)
548
- };
549
- }
550
- })
551
- };
552
753
  //#endregion
553
754
  //#region src/loggers/plainLogger.ts
554
755
  /**
@@ -601,207 +802,6 @@ function createPlainLogger(write) {
601
802
  */
602
803
  const plainLogger = createPlainLogger((line) => console.log(line));
603
804
  //#endregion
604
- //#region src/loggers/utils.ts
605
- /**
606
- * Display path for a config's input: the string form, or its `path` field when the input is an
607
- * object. Loggers show it alongside `Generation started`.
608
- */
609
- function getInputPath(config) {
610
- const { input } = config;
611
- if (typeof input === "string") return input;
612
- return typeof input?.path === "string" ? input.path : void 0;
613
- }
614
- /**
615
- * Counts a noun, so a message never reads `1 files`.
616
- *
617
- * @example
618
- * `pluralize(1, 'config')` returns `'1 config'`
619
- */
620
- function pluralize(count, noun) {
621
- return `${count} ${count === 1 ? noun : `${noun}s`}`;
622
- }
623
- /**
624
- * Optionally prefix a message with a [HH:MM:SS] timestamp when logLevel >= verbose.
625
- * Shared across all logger adapters to avoid duplication.
626
- */
627
- function formatMessage(message, logLevel$1) {
628
- if (logLevel$1 >= logLevel.verbose) {
629
- const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
630
- hour12: false,
631
- hour: "2-digit",
632
- minute: "2-digit",
633
- second: "2-digit"
634
- });
635
- return `${styleText("dim", `[${timestamp}]`)} ${message}`;
636
- }
637
- return message;
638
- }
639
- /**
640
- * Renders the versions from a `studio:connected` event as one parenthetical. The runtime is listed
641
- * only when it differs from the host, and Studio's only when it sent one.
642
- */
643
- function formatVersions({ studio, kubb, agent }) {
644
- return [
645
- `v${agent}`,
646
- kubb !== agent ? `runtime v${kubb}` : void 0,
647
- studio ? `Studio v${studio}` : void 0
648
- ].filter(Boolean).join(", ");
649
- }
650
- /**
651
- * Extracts the `.cause` of an `Error` as an `Error`, or `undefined` when absent or not an `Error`.
652
- */
653
- function toCause(error) {
654
- return error.cause instanceof Error ? error.cause : void 0;
655
- }
656
- /**
657
- * First stack frames for verbose error output, including an optional `cause` chain.
658
- */
659
- function formatErrorFrames(error) {
660
- if (!error.stack) return null;
661
- const frames = error.stack.split("\n").slice(1, 4).map((frame) => frame.trim());
662
- const caused = toCause(error);
663
- if (!caused?.stack) return { frames };
664
- return {
665
- frames,
666
- cause: {
667
- header: `└─ caused by ${caused.message}`,
668
- frames: caused.stack.split("\n").slice(1, 4).map((frame) => frame.trim())
669
- }
670
- };
671
- }
672
- /**
673
- * Build the progress summary line shown by the clack logger.
674
- * Returns null when there is nothing to display.
675
- */
676
- function buildProgressLine(state) {
677
- const parts = [];
678
- const duration = formatMs(getElapsedMs(state.hrStart));
679
- if (state.totalPlugins > 0) {
680
- 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}`;
681
- parts.push(pluginStr);
682
- }
683
- if (state.totalFiles > 0) parts.push(`Files ${styleText("green", state.processedFiles.toString())}/${state.totalFiles}`);
684
- if (parts.length === 0) return null;
685
- parts.push(`${styleText("green", duration)} elapsed`);
686
- return parts.join(styleText("dim", " | "));
687
- }
688
- /**
689
- * Creates the per-run progress counters used by the clack logger.
690
- */
691
- function createProgressCounters() {
692
- return {
693
- totalPlugins: 0,
694
- completedPlugins: 0,
695
- failedPlugins: 0,
696
- totalFiles: 0,
697
- processedFiles: 0,
698
- hrStart: process.hrtime()
699
- };
700
- }
701
- /**
702
- * Resets the progress counters in place at the start/end of a generation run.
703
- */
704
- function resetProgressCounters(state) {
705
- state.totalPlugins = 0;
706
- state.completedPlugins = 0;
707
- state.failedPlugins = 0;
708
- state.totalFiles = 0;
709
- state.processedFiles = 0;
710
- state.hrStart = process.hrtime();
711
- }
712
- /**
713
- * Records a finished plugin against the progress counters.
714
- */
715
- function recordPluginResult(state, success) {
716
- if (success) state.completedPlugins++;
717
- else state.failedPlugins++;
718
- }
719
- /**
720
- * Join a command and its optional args into a single display string.
721
- *
722
- * @example With args
723
- * `formatCommandWithArgs('prettier', ['--write', '.'])` returns `'prettier --write .'`
724
- */
725
- function formatCommandWithArgs(command, args) {
726
- return args?.length ? `${command} ${args.join(" ")}` : command;
727
- }
728
- /**
729
- * Bridges a {@link Reporter} onto the run's hook emitter: calls `report` with each config's
730
- * {@link GenerationResult} on `kubb:generation:end`. The reporter never touches the emitter.
731
- */
732
- function installReporter(context, reporter, ctx) {
733
- const pluginFiles = reporter.needsPluginFiles ? /* @__PURE__ */ new Map() : void 0;
734
- if (pluginFiles) context.hook("kubb:plugin:end", ({ config, plugin, files }) => {
735
- const filesByPlugin = pluginFiles.get(config) ?? /* @__PURE__ */ new Map();
736
- const seen = new Set([...filesByPlugin.values()].flatMap((paths) => [...paths]));
737
- const added = files.filter((file) => !seen.has(file.path)).map((file) => file.path);
738
- if (added.length) filesByPlugin.set(plugin.name, /* @__PURE__ */ new Set([...filesByPlugin.get(plugin.name) ?? [], ...added]));
739
- pluginFiles.set(config, filesByPlugin);
740
- });
741
- context.hook("kubb:generation:end", async ({ config, diagnostics = [], filesCreated = 0, status = "success", hrStart = process.hrtime() }) => {
742
- const files = pluginFiles?.get(config);
743
- const grouped = files && [...files].map(([plugin, paths]) => ({
744
- plugin,
745
- files: [...paths]
746
- }));
747
- await reporter.report({
748
- config,
749
- diagnostics,
750
- filesCreated,
751
- status,
752
- hrStart,
753
- pluginFiles: grouped
754
- }, ctx);
755
- pluginFiles?.delete(config);
756
- });
757
- if (reporter.drain) context.hook("kubb:lifecycle:end", () => reporter.drain?.(ctx));
758
- }
759
- /**
760
- * Installs the live logger (the TUI view) and the given reporters (the output). The reporters are
761
- * already selected by the caller (the CLI maps `--reporter` to names via `selectReporters`). This
762
- * only wires them. Loggers receive hook subprocess output through `kubb:hook:line` and the
763
- * `stdout`/`stderr` on `kubb:hook:end`, so nothing is returned here.
764
- *
765
- * Loggers and reporters are independent, except for `cli`: it both installs the live logger view
766
- * here and registers a reporter that renders the per-config summary through that logger, so the
767
- * summary lands inside the group the logger opened. The `json` reporter owns stdout, so the whole
768
- * `cli` reporter (live logger and summary) is skipped whenever `json` is among the reporters, even
769
- * if `cli` is also listed.
770
- */
771
- async function setupReporters(context, { logLevel, reporters, logger: forcedLogger }) {
772
- let cliHandle;
773
- const hasJson = reporters.some((reporter) => reporter.name === "json");
774
- const ctx = { logLevel };
775
- for (const reporter of reporters) {
776
- if (reporter.name !== "cli") {
777
- installReporter(context, reporter, ctx);
778
- continue;
779
- }
780
- if (hasJson) continue;
781
- const handle = await (forcedLogger ?? (canUseTTY() && !getAgentName() ? clackLogger : plainLogger)).install(context, { logLevel }) ?? void 0;
782
- cliHandle = handle;
783
- installReporter(context, createCliReporter({ render: handle?.renderSummary }), ctx);
784
- }
785
- return cliHandle;
786
- }
787
- /**
788
- * Picks the reporters whose `name` matches one of `names`, in the order the names are given.
789
- * The config carries every available reporter, and the host selects which to activate by name
790
- * (the CLI maps `--reporter` to this). Duplicate names and names without a matching reporter are
791
- * skipped.
792
- */
793
- function selectReporters(reporters, names) {
794
- const seen = /* @__PURE__ */ new Set();
795
- const selected = [];
796
- for (const name of names) {
797
- if (seen.has(name)) continue;
798
- seen.add(name);
799
- const reporter = reporters.find((candidate) => candidate.name === name);
800
- if (reporter) selected.push(reporter);
801
- }
802
- return selected;
803
- }
804
- //#endregion
805
805
  //#region src/runners/generate/utils.ts
806
806
  const loader = createModuleLoader();
807
807
  const tsLoader = (configFile) => loader.load(configFile, { default: true });
@@ -876,7 +876,7 @@ async function getConfigs({ configPath, input, watch, logLevel }) {
876
876
  */
877
877
  function isNewerVersion(current, latest) {
878
878
  if (!isValid(current) || !isValid(latest)) return false;
879
- return isGreater(truncate(latest, "patch"), truncate(current, "patch"));
879
+ return isGreaterThan(truncate(latest, "patch"), truncate(current, "patch"));
880
880
  }
881
881
  /**
882
882
  * Runs the `output.postGenerate` commands of a Kubb config in sequence and returns each command's
@@ -1104,6 +1104,6 @@ function startUrlWatcher(url, cb, options = {}) {
1104
1104
  return stop;
1105
1105
  }
1106
1106
  //#endregion
1107
- export { runPostGenerate as a, pluralize as c, createPlainLogger as d, FORMATTER_PREFERENCE as f, linters as g, formatters as h, runHook as i, selectReporters as l, detectTool as m, getConfigs as n, startUrlWatcher as o, LINTER_PREFERENCE as p, isNewerVersion as r, startWatcher as s, fetchUrlBody as t, setupReporters as u };
1107
+ export { linters as _, runPostGenerate as a, createPlainLogger as c, selectReporters as d, setupReporters as f, formatters as g, detectTool as h, runHook as i, plainLogger as l, LINTER_PREFERENCE as m, getConfigs as n, startUrlWatcher as o, FORMATTER_PREFERENCE as p, isNewerVersion as r, startWatcher as s, fetchUrlBody as t, pluralize as u };
1108
1108
 
1109
- //# sourceMappingURL=utils-BWksgOYQ.js.map
1109
+ //# sourceMappingURL=utils-BYY3_cyq.js.map