@kubb/cli 5.0.0-beta.2 → 5.0.0-beta.21

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 (151) hide show
  1. package/README.md +177 -26
  2. package/dist/agent-B1y251-b.cjs +70 -0
  3. package/dist/agent-B1y251-b.cjs.map +1 -0
  4. package/dist/agent-jGZu4zRF.js +68 -0
  5. package/dist/agent-jGZu4zRF.js.map +1 -0
  6. package/dist/{chunk--u3MIqq1.js → chunk-BvFE5Tac.js} +1 -0
  7. package/dist/constants-B2JTeRBb.js +42 -0
  8. package/dist/constants-B2JTeRBb.js.map +1 -0
  9. package/dist/constants-BINTA5VZ.cjs +77 -0
  10. package/dist/constants-BINTA5VZ.cjs.map +1 -0
  11. package/dist/constants-BYGmiFs0.cjs +139 -0
  12. package/dist/constants-BYGmiFs0.cjs.map +1 -0
  13. package/dist/constants-DSJ-Xrbv.js +116 -0
  14. package/dist/constants-DSJ-Xrbv.js.map +1 -0
  15. package/dist/define-Bdn8j5VM.cjs.map +1 -1
  16. package/dist/{define-Ctii4bel.js → define-m_fp-Aqm.js} +2 -2
  17. package/dist/{define-Ctii4bel.js.map → define-m_fp-Aqm.js.map} +1 -1
  18. package/dist/{errors-CjPmyZHy.js → errors-CINO1EIv.js} +2 -2
  19. package/dist/{errors-CjPmyZHy.js.map → errors-CINO1EIv.js.map} +1 -1
  20. package/dist/errors-CLCjoSg0.cjs.map +1 -1
  21. package/dist/{generate-DL_7a7Wd.cjs → generate-CszBbEx_.cjs} +10 -4
  22. package/dist/generate-CszBbEx_.cjs.map +1 -0
  23. package/dist/{generate-B3PZ6Dp-.js → generate-Dqk3rinP.js} +12 -6
  24. package/dist/generate-Dqk3rinP.js.map +1 -0
  25. package/dist/index.cjs +20 -11
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +22 -13
  29. package/dist/index.js.map +1 -1
  30. package/dist/init-BSfLyes_.js +53 -0
  31. package/dist/init-BSfLyes_.js.map +1 -0
  32. package/dist/init-JrYOUBes.cjs +53 -0
  33. package/dist/init-JrYOUBes.cjs.map +1 -0
  34. package/dist/mcp-BiLUSMgD.js +39 -0
  35. package/dist/mcp-BiLUSMgD.js.map +1 -0
  36. package/dist/mcp-DY_TKMoS.cjs +39 -0
  37. package/dist/mcp-DY_TKMoS.cjs.map +1 -0
  38. package/dist/package-C_LGzz8A.js +6 -0
  39. package/dist/package-C_LGzz8A.js.map +1 -0
  40. package/dist/{package-D8wlStAg.cjs → package-CyNXMTr8.cjs} +2 -2
  41. package/dist/package-CyNXMTr8.cjs.map +1 -0
  42. package/dist/run-B11-UaUs.cjs +33 -0
  43. package/dist/run-B11-UaUs.cjs.map +1 -0
  44. package/dist/{init-eNRlotJK.js → run-BNqMQygv.js} +107 -149
  45. package/dist/run-BNqMQygv.js.map +1 -0
  46. package/dist/{init-CZ5Xq2Hd.cjs → run-BnGfi7Cp.cjs} +105 -147
  47. package/dist/run-BnGfi7Cp.cjs.map +1 -0
  48. package/dist/{generate-Dt_r0ELY.js → run-BryUpjjc.js} +484 -410
  49. package/dist/run-BryUpjjc.js.map +1 -0
  50. package/dist/{agent-Ev5hU5hH.js → run-BzpYYOQs.js} +53 -44
  51. package/dist/run-BzpYYOQs.js.map +1 -0
  52. package/dist/run-CCZ24VKk.js +51 -0
  53. package/dist/run-CCZ24VKk.js.map +1 -0
  54. package/dist/run-CQbj3ley.cjs +52 -0
  55. package/dist/run-CQbj3ley.cjs.map +1 -0
  56. package/dist/{generate-B3jl4ukb.cjs → run-CmiuJkLG.cjs} +481 -407
  57. package/dist/run-CmiuJkLG.cjs.map +1 -0
  58. package/dist/{agent-B_pirbeB.cjs → run-DwdAwnLG.cjs} +51 -42
  59. package/dist/run-DwdAwnLG.cjs.map +1 -0
  60. package/dist/run-PSA9X7ci.js +32 -0
  61. package/dist/run-PSA9X7ci.js.map +1 -0
  62. package/dist/shell-475fQKaX.cjs.map +1 -1
  63. package/dist/{shell-DLzN4fRo.js → shell-CN6DNqeC.js} +2 -2
  64. package/dist/{shell-DLzN4fRo.js.map → shell-CN6DNqeC.js.map} +1 -1
  65. package/dist/{telemetry-DN95_2pF.cjs → telemetry-B2iWkY5e.cjs} +5 -7
  66. package/dist/telemetry-B2iWkY5e.cjs.map +1 -0
  67. package/dist/{telemetry-LgT_sdPe.js → telemetry-BkektVz6.js} +6 -8
  68. package/dist/telemetry-BkektVz6.js.map +1 -0
  69. package/dist/validate-8VIogDlj.cjs +26 -0
  70. package/dist/validate-8VIogDlj.cjs.map +1 -0
  71. package/dist/validate-KufVWuQ1.js +26 -0
  72. package/dist/validate-KufVWuQ1.js.map +1 -0
  73. package/package.json +23 -15
  74. package/src/commands/agent/start.ts +10 -7
  75. package/src/commands/agent.ts +3 -1
  76. package/src/commands/generate.ts +5 -3
  77. package/src/commands/init.ts +34 -3
  78. package/src/commands/mcp.ts +28 -4
  79. package/src/commands/validate.ts +6 -4
  80. package/src/constants.ts +2 -58
  81. package/src/index.ts +5 -3
  82. package/src/loggers/clackLogger.ts +72 -81
  83. package/src/loggers/fileSystemLogger.ts +26 -13
  84. package/src/loggers/githubActionsLogger.ts +74 -28
  85. package/src/loggers/plainLogger.ts +55 -30
  86. package/src/loggers/types.ts +6 -0
  87. package/src/loggers/utils.ts +158 -9
  88. package/src/runners/agent/run.ts +113 -0
  89. package/src/runners/agent/utils.ts +98 -0
  90. package/src/runners/generate/run.ts +316 -0
  91. package/src/runners/generate/utils.ts +216 -0
  92. package/src/runners/init/run.ts +212 -0
  93. package/src/{utils/packageManager.ts → runners/init/utils.ts} +10 -0
  94. package/src/runners/mcp/run.ts +37 -0
  95. package/src/runners/validate/run.ts +63 -0
  96. package/src/{utils/telemetry.ts → telemetry.ts} +12 -5
  97. package/dist/agent-0Nk--lcr.cjs +0 -58
  98. package/dist/agent-0Nk--lcr.cjs.map +0 -1
  99. package/dist/agent-B_pirbeB.cjs.map +0 -1
  100. package/dist/agent-DKeVuiUC.js +0 -56
  101. package/dist/agent-DKeVuiUC.js.map +0 -1
  102. package/dist/agent-Ev5hU5hH.js.map +0 -1
  103. package/dist/constants-CnDXa1R6.cjs +0 -148
  104. package/dist/constants-CnDXa1R6.cjs.map +0 -1
  105. package/dist/constants-aL3CP_Wq.js +0 -95
  106. package/dist/constants-aL3CP_Wq.js.map +0 -1
  107. package/dist/generate-B3PZ6Dp-.js.map +0 -1
  108. package/dist/generate-B3jl4ukb.cjs.map +0 -1
  109. package/dist/generate-DL_7a7Wd.cjs.map +0 -1
  110. package/dist/generate-Dt_r0ELY.js.map +0 -1
  111. package/dist/init-Bj94Nvt8.js +0 -25
  112. package/dist/init-Bj94Nvt8.js.map +0 -1
  113. package/dist/init-CZ5Xq2Hd.cjs.map +0 -1
  114. package/dist/init-CyN1oyTF.cjs +0 -25
  115. package/dist/init-CyN1oyTF.cjs.map +0 -1
  116. package/dist/init-eNRlotJK.js.map +0 -1
  117. package/dist/mcp-BzW703d7.js +0 -16
  118. package/dist/mcp-BzW703d7.js.map +0 -1
  119. package/dist/mcp-CLcDV4Jm.cjs +0 -41
  120. package/dist/mcp-CLcDV4Jm.cjs.map +0 -1
  121. package/dist/mcp-D7EIR9fR.js +0 -40
  122. package/dist/mcp-D7EIR9fR.js.map +0 -1
  123. package/dist/mcp-ZY-ONTOp.cjs +0 -16
  124. package/dist/mcp-ZY-ONTOp.cjs.map +0 -1
  125. package/dist/package-D8wlStAg.cjs.map +0 -1
  126. package/dist/package-Yo-9_m5C.js +0 -6
  127. package/dist/package-Yo-9_m5C.js.map +0 -1
  128. package/dist/telemetry-DN95_2pF.cjs.map +0 -1
  129. package/dist/telemetry-LgT_sdPe.js.map +0 -1
  130. package/dist/validate-Dplr99xO.js +0 -25
  131. package/dist/validate-Dplr99xO.js.map +0 -1
  132. package/dist/validate-_8mBa63G.cjs +0 -25
  133. package/dist/validate-_8mBa63G.cjs.map +0 -1
  134. package/dist/validate-kLJoT_hi.js +0 -33
  135. package/dist/validate-kLJoT_hi.js.map +0 -1
  136. package/dist/validate-yKKzqEZ5.cjs +0 -34
  137. package/dist/validate-yKKzqEZ5.cjs.map +0 -1
  138. package/src/runners/agent.ts +0 -149
  139. package/src/runners/generate.ts +0 -333
  140. package/src/runners/init.ts +0 -296
  141. package/src/runners/mcp.ts +0 -45
  142. package/src/runners/validate.ts +0 -39
  143. package/src/types.ts +0 -11
  144. package/src/utils/Writables.ts +0 -17
  145. package/src/utils/executeHooks.ts +0 -45
  146. package/src/utils/flags.ts +0 -9
  147. package/src/utils/getConfig.ts +0 -10
  148. package/src/utils/getCosmiConfig.ts +0 -80
  149. package/src/utils/getSummary.ts +0 -68
  150. package/src/utils/runHook.ts +0 -91
  151. package/src/utils/watcher.ts +0 -19
@@ -1,9 +1,9 @@
1
1
  const require_chunk = require("./chunk-ByKO4r7w.cjs");
2
2
  const require_errors = require("./errors-CLCjoSg0.cjs");
3
- const require_telemetry = require("./telemetry-DN95_2pF.cjs");
3
+ const require_telemetry = require("./telemetry-B2iWkY5e.cjs");
4
4
  const require_shell = require("./shell-475fQKaX.cjs");
5
- const require_package = require("./package-D8wlStAg.cjs");
6
- const require_constants = require("./constants-CnDXa1R6.cjs");
5
+ const require_package = require("./package-CyNXMTr8.cjs");
6
+ const require_constants = require("./constants-BINTA5VZ.cjs");
7
7
  let node_util = require("node:util");
8
8
  let node_events = require("node:events");
9
9
  let node_crypto = require("node:crypto");
@@ -17,10 +17,9 @@ node_process = require_chunk.__toESM(node_process, 1);
17
17
  let _clack_prompts = require("@clack/prompts");
18
18
  _clack_prompts = require_chunk.__toESM(_clack_prompts, 1);
19
19
  let _kubb_core = require("@kubb/core");
20
- let tinyexec = require("tinyexec");
21
- let node_stream = require("node:stream");
22
20
  let cosmiconfig = require("cosmiconfig");
23
- let unrun = require("unrun");
21
+ let jiti = require("jiti");
22
+ let tinyexec = require("tinyexec");
24
23
  //#region ../../internals/utils/src/asyncEventEmitter.ts
25
24
  /**
26
25
  * Typed `EventEmitter` that awaits all async listeners before resolving.
@@ -51,9 +50,12 @@ var AsyncEventEmitter = class {
51
50
  * await emitter.emit('build', 'petstore')
52
51
  * ```
53
52
  */
54
- async emit(eventName, ...eventArgs) {
53
+ emit(eventName, ...eventArgs) {
55
54
  const listeners = this.#emitter.listeners(eventName);
56
55
  if (listeners.length === 0) return;
56
+ return this.#emitAll(eventName, listeners, eventArgs);
57
+ }
58
+ async #emitAll(eventName, listeners, eventArgs) {
57
59
  for (const listener of listeners) try {
58
60
  await listener(...eventArgs);
59
61
  } catch (err) {
@@ -489,112 +491,6 @@ async function detectLinter() {
489
491
  return null;
490
492
  }
491
493
  //#endregion
492
- //#region src/utils/getSummary.ts
493
- function getSummary({ failedPlugins, filesCreated, status, hrStart, config, pluginTimings }) {
494
- const duration = formatHrtime(hrStart);
495
- const pluginsCount = config.plugins?.length ?? 0;
496
- const successCount = pluginsCount - failedPlugins.size;
497
- const meta = {
498
- 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`,
499
- pluginsFailed: status === "failed" ? [...failedPlugins].map(({ plugin }) => randomCliColor(plugin.name)).join(", ") : void 0,
500
- filesCreated,
501
- time: (0, node_util.styleText)("green", duration),
502
- output: node_path.default.resolve(config.root, config.output.path)
503
- };
504
- const labels = {
505
- plugins: "Plugins:",
506
- failed: "Failed:",
507
- generated: "Generated:",
508
- pluginTimings: "Plugin Timings:",
509
- output: "Output:"
510
- };
511
- const maxLength = Math.max(0, ...[...Object.values(labels), ...pluginTimings ? Array.from(pluginTimings.keys()) : []].map((s) => s.length));
512
- const summaryLines = [];
513
- summaryLines.push(`${labels.plugins.padEnd(maxLength + 2)} ${meta.plugins}`);
514
- if (meta.pluginsFailed) summaryLines.push(`${labels.failed.padEnd(maxLength + 2)} ${meta.pluginsFailed}`);
515
- summaryLines.push(`${labels.generated.padEnd(maxLength + 2)} ${meta.filesCreated} files in ${meta.time}`);
516
- if (pluginTimings && pluginTimings.size > 0) {
517
- const sortedTimings = Array.from(pluginTimings.entries()).sort((a, b) => b[1] - a[1]);
518
- summaryLines.push(`${labels.pluginTimings}`);
519
- sortedTimings.forEach(([name, time]) => {
520
- const timeStr = time >= 1e3 ? `${(time / 1e3).toFixed(2)}s` : `${Math.round(time)}ms`;
521
- const barLength = Math.min(Math.ceil(time / 100), 10);
522
- const bar = (0, node_util.styleText)("dim", "█".repeat(barLength));
523
- summaryLines.push(`${(0, node_util.styleText)("dim", "•")} ${name.padEnd(maxLength + 1)}${bar} ${timeStr}`);
524
- });
525
- }
526
- summaryLines.push(`${labels.output.padEnd(maxLength + 2)} ${meta.output}`);
527
- return summaryLines;
528
- }
529
- //#endregion
530
- //#region src/utils/runHook.ts
531
- /**
532
- * Executes a hook command, emits debug and completion events, and forwards output to an optional sink.
533
- */
534
- async function runHook({ id, command, args, commandWithArgs, context, stream = false, sink }) {
535
- try {
536
- const proc = (0, tinyexec.x)(command, [...args ?? []], {
537
- nodeOptions: { detached: process.platform !== "win32" },
538
- throwOnError: true
539
- });
540
- if (stream && sink?.onLine) for await (const line of proc) sink.onLine(line);
541
- const result = await proc;
542
- await context.emit("kubb:debug", {
543
- date: /* @__PURE__ */ new Date(),
544
- logs: [result.stdout.trimEnd()]
545
- });
546
- await context.emit("kubb:hook:end", {
547
- command,
548
- args,
549
- id,
550
- success: true,
551
- error: null
552
- });
553
- } catch (err) {
554
- if (!(err instanceof tinyexec.NonZeroExitError)) {
555
- await context.emit("kubb:hook:end", {
556
- command,
557
- args,
558
- id,
559
- success: false,
560
- error: require_errors.toError(err)
561
- });
562
- await context.emit("kubb:error", { error: require_errors.toError(err) });
563
- return;
564
- }
565
- const stderr = err.output?.stderr ?? "";
566
- const stdout = err.output?.stdout ?? "";
567
- await context.emit("kubb:debug", {
568
- date: /* @__PURE__ */ new Date(),
569
- logs: [stdout, stderr].filter(Boolean)
570
- });
571
- if (stderr) sink?.onStderr?.(stderr);
572
- if (stdout) sink?.onStdout?.(stdout);
573
- const errorMessage = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
574
- await context.emit("kubb:hook:end", {
575
- command,
576
- args,
577
- id,
578
- success: false,
579
- error: errorMessage
580
- });
581
- await context.emit("kubb:error", { error: errorMessage });
582
- }
583
- }
584
- //#endregion
585
- //#region src/utils/Writables.ts
586
- var ClackWritable = class extends node_stream.Writable {
587
- taskLog;
588
- constructor(taskLog, opts) {
589
- super(opts);
590
- this.taskLog = taskLog;
591
- }
592
- _write(chunk, _encoding, callback) {
593
- this.taskLog.message(`${(0, node_util.styleText)("dim", chunk.toString())}`);
594
- callback();
595
- }
596
- };
597
- //#endregion
598
494
  //#region src/loggers/clackLogger.ts
599
495
  /**
600
496
  * TTY logger with beautiful UI and progress indicators for local development.
@@ -612,7 +508,8 @@ const clackLogger = (0, _kubb_core.defineLogger)({
612
508
  hrStart: node_process.default.hrtime(),
613
509
  spinner: _clack_prompts.spinner(),
614
510
  isSpinning: false,
615
- activeProgress: /* @__PURE__ */ new Map()
511
+ activeProgress: /* @__PURE__ */ new Map(),
512
+ activeHookLogs: /* @__PURE__ */ new Map()
616
513
  };
617
514
  function reset() {
618
515
  for (const [_key, active] of state.activeProgress) {
@@ -628,6 +525,7 @@ const clackLogger = (0, _kubb_core.defineLogger)({
628
525
  state.spinner = _clack_prompts.spinner();
629
526
  state.isSpinning = false;
630
527
  state.activeProgress.clear();
528
+ state.activeHookLogs.clear();
631
529
  }
632
530
  function showProgressStep() {
633
531
  if (logLevel <= _kubb_core.logLevel.silent) return;
@@ -642,6 +540,7 @@ const clackLogger = (0, _kubb_core.defineLogger)({
642
540
  state.isSpinning = true;
643
541
  }
644
542
  function stopSpinner(text) {
543
+ if (!state.isSpinning) return;
645
544
  state.spinner.stop(text);
646
545
  state.isSpinning = false;
647
546
  }
@@ -652,8 +551,11 @@ const clackLogger = (0, _kubb_core.defineLogger)({
652
551
  message,
653
552
  (0, node_util.styleText)("dim", info)
654
553
  ].join(" "));
655
- if (state.isSpinning) state.spinner.message(text);
656
- else _clack_prompts.log.info(text);
554
+ if (state.isSpinning) {
555
+ state.spinner.message(text);
556
+ return;
557
+ }
558
+ _clack_prompts.log.info(text);
657
559
  });
658
560
  context.on("kubb:success", ({ message, info = "" }) => {
659
561
  if (logLevel <= _kubb_core.logLevel.silent) return;
@@ -662,8 +564,11 @@ const clackLogger = (0, _kubb_core.defineLogger)({
662
564
  message,
663
565
  logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", info) : void 0
664
566
  ].filter(Boolean).join(" "));
665
- if (state.isSpinning) stopSpinner(text);
666
- else _clack_prompts.log.success(text);
567
+ if (state.isSpinning) {
568
+ stopSpinner(text);
569
+ return;
570
+ }
571
+ _clack_prompts.log.success(text);
667
572
  });
668
573
  context.on("kubb:warn", ({ message, info }) => {
669
574
  if (logLevel < _kubb_core.logLevel.warn) return;
@@ -677,8 +582,11 @@ const clackLogger = (0, _kubb_core.defineLogger)({
677
582
  context.on("kubb:error", ({ error }) => {
678
583
  const caused = require_errors.toCause(error);
679
584
  const text = [(0, node_util.styleText)("red", "✗"), error.message].join(" ");
680
- if (state.isSpinning) stopSpinner(getMessage(text));
681
- else _clack_prompts.log.error(getMessage(text));
585
+ if (state.isSpinning) {
586
+ stopSpinner(getMessage(text));
587
+ return;
588
+ }
589
+ _clack_prompts.log.error(getMessage(text));
682
590
  if (logLevel >= _kubb_core.logLevel.debug && error.stack) {
683
591
  const frames = error.stack.split("\n").slice(1, 4);
684
592
  for (const frame of frames) _clack_prompts.log.message(getMessage((0, node_util.styleText)("dim", frame.trim())));
@@ -729,6 +637,7 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
729
637
  context.on("kubb:generation:start", ({ config }) => {
730
638
  reset();
731
639
  state.totalPlugins = config.plugins?.length ?? 0;
640
+ if (logLevel <= _kubb_core.logLevel.silent) return;
732
641
  const text = getMessage(["Generation started", config.name ? `for ${(0, node_util.styleText)("dim", config.name)}` : void 0].filter(Boolean).join(" "));
733
642
  _clack_prompts.intro(text);
734
643
  });
@@ -778,14 +687,14 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
778
687
  progressBar.start(getMessage(text));
779
688
  state.activeProgress.set("files", { progressBar });
780
689
  });
781
- context.on("kubb:file:processing:update", ({ file, config }) => {
690
+ context.on("kubb:files:processing:update", ({ files }) => {
782
691
  if (logLevel <= _kubb_core.logLevel.silent) return;
783
692
  stopSpinner();
784
- state.processedFiles++;
785
- const text = `Writing ${(0, node_path.relative)(config.root, file.path)}`;
786
693
  const active = state.activeProgress.get("files");
787
- if (!active) return;
788
- active.progressBar.advance(void 0, text);
694
+ for (const { file, config } of files) {
695
+ state.processedFiles++;
696
+ if (active) active.progressBar.advance(void 0, `Writing ${(0, node_path.relative)(config.root, file.path)}`);
697
+ }
789
698
  });
790
699
  context.on("kubb:files:processing:end", () => {
791
700
  if (logLevel <= _kubb_core.logLevel.silent) return;
@@ -798,68 +707,44 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
798
707
  showProgressStep();
799
708
  });
800
709
  context.on("kubb:generation:end", ({ config }) => {
710
+ stopSpinner();
801
711
  const text = getMessage(config.name ? `Generation completed for ${(0, node_util.styleText)("dim", config.name)}` : "Generation completed");
802
712
  _clack_prompts.outro(text);
803
713
  });
804
714
  context.on("kubb:format:start", () => {
805
715
  if (logLevel <= _kubb_core.logLevel.silent) return;
806
- const text = getMessage("Format started");
807
- _clack_prompts.intro(text);
808
- });
809
- context.on("kubb:format:end", () => {
810
- if (logLevel <= _kubb_core.logLevel.silent) return;
811
- const text = getMessage("Format completed");
812
- _clack_prompts.outro(text);
716
+ _clack_prompts.log.step(getMessage("Formatting"));
813
717
  });
814
718
  context.on("kubb:lint:start", () => {
815
719
  if (logLevel <= _kubb_core.logLevel.silent) return;
816
- const text = getMessage("Lint started");
817
- _clack_prompts.intro(text);
720
+ _clack_prompts.log.step(getMessage("Linting"));
818
721
  });
819
- context.on("kubb:lint:end", () => {
722
+ context.on("kubb:hooks:start", () => {
820
723
  if (logLevel <= _kubb_core.logLevel.silent) return;
821
- const text = getMessage("Lint completed");
822
- _clack_prompts.outro(text);
724
+ _clack_prompts.log.step(getMessage("Running hooks"));
823
725
  });
824
- context.on("kubb:hook:start", async ({ id, command, args }) => {
825
- const commandWithArgs = formatCommandWithArgs(command, args);
826
- const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} started`);
827
- if (!id) return;
828
- if (logLevel <= _kubb_core.logLevel.silent) {
829
- await runHook({
830
- id,
831
- command,
832
- args,
833
- commandWithArgs,
834
- context,
835
- sink: {
836
- onStderr: (s) => console.error(s),
837
- onStdout: (s) => console.log(s)
838
- }
839
- });
840
- return;
841
- }
842
- _clack_prompts.intro(text);
843
- 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(" ")) });
844
- const writable = new ClackWritable(logger);
845
- await runHook({
846
- id,
847
- command,
848
- args,
849
- commandWithArgs,
850
- context,
851
- stream: true,
852
- sink: {
853
- onLine: (line) => writable.write(line),
854
- onStderr: (s) => logger.error(s),
855
- onStdout: (s) => logger.message(s)
856
- }
726
+ context.on("kubb:hook:start", ({ id, command, args }) => {
727
+ if (logLevel <= _kubb_core.logLevel.silent || !id) return;
728
+ stopSpinner();
729
+ const title = getMessage(`Running ${(0, node_util.styleText)("dim", formatCommandWithArgs(command, args))}`);
730
+ const taskLog = _clack_prompts.taskLog({ title });
731
+ state.activeHookLogs.set(id, {
732
+ taskLog,
733
+ hrStart: node_process.default.hrtime()
857
734
  });
858
735
  });
859
- context.on("kubb:hook:end", ({ command, args }) => {
860
- if (logLevel <= _kubb_core.logLevel.silent) return;
861
- const text = getMessage(`Hook ${(0, node_util.styleText)("dim", formatCommandWithArgs(command, args))} successfully executed`);
862
- _clack_prompts.outro(text);
736
+ context.on("kubb:hook:end", ({ id, command, args, success, error }) => {
737
+ if (logLevel <= _kubb_core.logLevel.silent || !id) return;
738
+ const active = state.activeHookLogs.get(id);
739
+ if (!active) return;
740
+ state.activeHookLogs.delete(id);
741
+ const commandWithArgs = formatCommandWithArgs(command, args);
742
+ const duration = formatMsWithColor(getElapsedMs(active.hrStart));
743
+ if (success) active.taskLog.success(getMessage(`${(0, node_util.styleText)("dim", commandWithArgs)} completed in ${duration}`));
744
+ else {
745
+ const reason = error?.message ? ` (${error.message})` : "";
746
+ active.taskLog.error(getMessage(`${(0, node_util.styleText)("dim", commandWithArgs)} failed${reason}`), { showLog: true });
747
+ }
863
748
  });
864
749
  context.on("kubb:generation:summary", ({ config, pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
865
750
  const summary = getSummary({
@@ -890,13 +775,29 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
890
775
  context.on("kubb:lifecycle:end", () => {
891
776
  reset();
892
777
  });
778
+ return (_commandWithArgs, hookId) => {
779
+ if (logLevel <= _kubb_core.logLevel.silent) return {
780
+ onStdout: (s) => console.log(s),
781
+ onStderr: (s) => console.error(s)
782
+ };
783
+ const active = state.activeHookLogs.get(hookId);
784
+ if (!active) return null;
785
+ const { taskLog } = active;
786
+ return {
787
+ stream: true,
788
+ onLine: (line) => taskLog.message((0, node_util.styleText)("dim", line)),
789
+ onStdout: (s) => taskLog.message(s),
790
+ onStderr: (s) => taskLog.message((0, node_util.styleText)("red", s))
791
+ };
792
+ };
893
793
  }
894
794
  });
895
795
  //#endregion
896
796
  //#region src/loggers/fileSystemLogger.ts
897
797
  /**
898
798
  * FileSystem logger that captures debug events and writes them to `.kubb` directory files.
899
- * Note: Logs write on `lifecycle:end` or process exit. Cached logs may be lost if the process crashes before these events.
799
+ *
800
+ * @note Logs are written on `kubb:lifecycle:end` or process exit. Cached logs may be lost if the process crashes before either event.
900
801
  */
901
802
  const fileSystemLogger = (0, _kubb_core.defineLogger)({
902
803
  name: "filesystem",
@@ -921,29 +822,31 @@ const fileSystemLogger = (0, _kubb_core.defineLogger)({
921
822
  const pathName = (0, node_path.resolve)(node_process.default.cwd(), ".kubb", baseName);
922
823
  if (!files[pathName]) files[pathName] = [];
923
824
  if (log.logs.length > 0) {
924
- const timestamp = log.date.toLocaleString();
925
- files[pathName].push(`[${timestamp}]\n${log.logs.join("\n")}`);
825
+ const prefix = `[${log.date.toLocaleString()}] `;
826
+ const indent = " ".repeat(prefix.length);
827
+ const [first, ...rest] = log.logs;
828
+ files[pathName].push([prefix + first, ...rest.map((line) => indent + line)].join("\n"));
926
829
  }
927
830
  }
928
- for (const [fileName, logs] of Object.entries(files)) await write(fileName, logs.join("\n\n"));
831
+ for (const [fileName, logs] of Object.entries(files)) await write(fileName, logs.join("\n"));
929
832
  return Object.keys(files);
930
833
  }
931
834
  context.on("kubb:info", ({ message, info }) => {
932
835
  state.cachedLogs.add({
933
836
  date: /* @__PURE__ */ new Date(),
934
- logs: [`ℹ ${message} ${info}`]
837
+ logs: [`ℹ ${[message, info].filter(Boolean).join(" ")}`]
935
838
  });
936
839
  });
937
840
  context.on("kubb:success", ({ message, info }) => {
938
841
  state.cachedLogs.add({
939
842
  date: /* @__PURE__ */ new Date(),
940
- logs: [`✓ ${message} ${info}`]
843
+ logs: [`✓ ${[message, info].filter(Boolean).join(" ")}`]
941
844
  });
942
845
  });
943
846
  context.on("kubb:warn", ({ message, info }) => {
944
847
  state.cachedLogs.add({
945
848
  date: /* @__PURE__ */ new Date(),
946
- logs: [`⚠ ${message} ${info}`]
849
+ logs: [`⚠ ${[message, info].filter(Boolean).join(" ")}`]
947
850
  });
948
851
  });
949
852
  context.on("kubb:error", ({ error }) => {
@@ -952,29 +855,30 @@ const fileSystemLogger = (0, _kubb_core.defineLogger)({
952
855
  logs: [`✗ ${error.message}`, error.stack || "unknown stack"]
953
856
  });
954
857
  });
955
- context.on("kubb:debug", (message) => {
858
+ context.on("kubb:debug", ({ date, fileName, logs }) => {
956
859
  state.cachedLogs.add({
957
- date: /* @__PURE__ */ new Date(),
958
- logs: message.logs
860
+ date,
861
+ fileName,
862
+ logs
959
863
  });
960
864
  });
961
865
  context.on("kubb:plugin:start", ({ plugin }) => {
962
866
  state.cachedLogs.add({
963
867
  date: /* @__PURE__ */ new Date(),
964
- logs: [`Generating ${plugin.name}`]
868
+ logs: [`► Generating ${plugin.name}`]
965
869
  });
966
870
  });
967
871
  context.on("kubb:plugin:end", ({ plugin, duration, success }) => {
968
872
  const durationStr = formatMs(duration);
969
873
  state.cachedLogs.add({
970
874
  date: /* @__PURE__ */ new Date(),
971
- logs: [success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`]
875
+ logs: [success ? `✓ ${plugin.name} completed in ${durationStr}` : `✗ ${plugin.name} failed in ${durationStr}`]
972
876
  });
973
877
  });
974
878
  context.on("kubb:files:processing:start", ({ files }) => {
975
879
  state.cachedLogs.add({
976
880
  date: /* @__PURE__ */ new Date(),
977
- logs: [`Start ${files.length} writing:`, ...files.map((file) => file.path)]
881
+ logs: [`► Writing ${files.length} files`, ...files.map((file) => ` ${file.path}`)]
978
882
  });
979
883
  });
980
884
  context.on("kubb:generation:end", async ({ config }) => {
@@ -1011,17 +915,21 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
1011
915
  failedPlugins: 0,
1012
916
  totalFiles: 0,
1013
917
  processedFiles: 0,
1014
- hrStart: process.hrtime(),
1015
- currentConfigs: []
918
+ hrStart: node_process.default.hrtime(),
919
+ currentConfigs: [],
920
+ hookStarts: /* @__PURE__ */ new Map(),
921
+ openGroupDepth: 0
1016
922
  };
1017
923
  function reset() {
924
+ closeAllGroups();
1018
925
  state.totalPlugins = 0;
1019
926
  state.completedPlugins = 0;
1020
927
  state.failedPlugins = 0;
1021
928
  state.totalFiles = 0;
1022
929
  state.processedFiles = 0;
1023
- state.hrStart = process.hrtime();
930
+ state.hrStart = node_process.default.hrtime();
1024
931
  state.currentConfigs = [];
932
+ state.hookStarts.clear();
1025
933
  }
1026
934
  function showProgressStep() {
1027
935
  if (logLevel <= _kubb_core.logLevel.silent) return;
@@ -1033,9 +941,17 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
1033
941
  }
1034
942
  function openGroup(name) {
1035
943
  console.log(`::group::${name}`);
944
+ state.openGroupDepth++;
1036
945
  }
1037
946
  function closeGroup(_name) {
1038
947
  console.log("::endgroup::");
948
+ if (state.openGroupDepth > 0) state.openGroupDepth--;
949
+ }
950
+ function closeAllGroups() {
951
+ while (state.openGroupDepth > 0) {
952
+ console.log("::endgroup::");
953
+ state.openGroupDepth--;
954
+ }
1039
955
  }
1040
956
  context.on("kubb:info", ({ message, info = "" }) => {
1041
957
  if (logLevel <= _kubb_core.logLevel.silent) return;
@@ -1066,6 +982,7 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
1066
982
  });
1067
983
  context.on("kubb:error", ({ error }) => {
1068
984
  const caused = require_errors.toCause(error);
985
+ closeAllGroups();
1069
986
  if (logLevel <= _kubb_core.logLevel.silent) return;
1070
987
  const message = error.message || String(error);
1071
988
  console.error(`::error::${message}`);
@@ -1083,6 +1000,9 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
1083
1000
  console.log((0, node_util.styleText)("yellow", `Kubb ${version} 🧩`));
1084
1001
  reset();
1085
1002
  });
1003
+ context.on("kubb:version:new", ({ currentVersion, latestVersion }) => {
1004
+ console.log(`::notice::Update available for Kubb: v${currentVersion} → v${latestVersion}. Run \`npm install -g @kubb/cli\` to update.`);
1005
+ });
1086
1006
  context.on("kubb:config:start", () => {
1087
1007
  if (logLevel <= _kubb_core.logLevel.silent) return;
1088
1008
  const text = getMessage("Configuration started");
@@ -1135,9 +1055,9 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
1135
1055
  if (state.currentConfigs.length === 1) closeGroup("File Generation");
1136
1056
  showProgressStep();
1137
1057
  });
1138
- context.on("kubb:file:processing:update", () => {
1058
+ context.on("kubb:files:processing:update", ({ files }) => {
1139
1059
  if (logLevel <= _kubb_core.logLevel.silent) return;
1140
- state.processedFiles++;
1060
+ state.processedFiles += files.length;
1141
1061
  });
1142
1062
  context.on("kubb:generation:end", ({ config }) => {
1143
1063
  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`);
@@ -1167,31 +1087,35 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
1167
1087
  console.log(text);
1168
1088
  if (state.currentConfigs.length === 1) closeGroup("Linting");
1169
1089
  });
1170
- context.on("kubb:hook:start", async ({ id, command, args }) => {
1090
+ context.on("kubb:hooks:start", () => {
1091
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1092
+ if (state.currentConfigs.length === 1) openGroup("Hooks");
1093
+ console.log(getMessage("Hooks started"));
1094
+ });
1095
+ context.on("kubb:hooks:end", () => {
1096
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1097
+ console.log(getMessage("Hooks completed"));
1098
+ if (state.currentConfigs.length === 1) closeGroup("Hooks");
1099
+ });
1100
+ context.on("kubb:hook:start", ({ id, command, args }) => {
1101
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1102
+ if (id) state.hookStarts.set(id, node_process.default.hrtime());
1171
1103
  const commandWithArgs = formatCommandWithArgs(command, args);
1172
1104
  const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} started`);
1173
- if (logLevel > _kubb_core.logLevel.silent) {
1174
- if (state.currentConfigs.length === 1) openGroup(`Hook ${commandWithArgs}`);
1175
- console.log(text);
1176
- }
1177
- if (!id) return;
1178
- await runHook({
1179
- id,
1180
- command,
1181
- args,
1182
- commandWithArgs,
1183
- context,
1184
- sink: {
1185
- onStdout: logLevel > _kubb_core.logLevel.silent ? (s) => console.log(s) : void 0,
1186
- onStderr: logLevel > _kubb_core.logLevel.silent ? (s) => console.error(`::error::${s}`) : void 0
1187
- }
1188
- });
1105
+ if (state.currentConfigs.length === 1) openGroup(`Hook ${commandWithArgs}`);
1106
+ console.log(text);
1189
1107
  });
1190
- context.on("kubb:hook:end", ({ command, args }) => {
1108
+ context.on("kubb:hook:end", ({ id, command, args, success, error }) => {
1191
1109
  if (logLevel <= _kubb_core.logLevel.silent) return;
1110
+ const hrStart = id ? state.hookStarts.get(id) : void 0;
1111
+ if (id) state.hookStarts.delete(id);
1112
+ const durationStr = hrStart ? ` in ${formatMsWithColor(getElapsedMs(hrStart))}` : "";
1192
1113
  const commandWithArgs = formatCommandWithArgs(command, args);
1193
- const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} completed`);
1194
- console.log(text);
1114
+ if (success) console.log(getMessage(`${(0, node_util.styleText)("green", "✓")} Hook ${(0, node_util.styleText)("dim", commandWithArgs)} completed${durationStr}`));
1115
+ else {
1116
+ const reason = error?.message ? ` (${error.message})` : "";
1117
+ console.log(`::error::Hook ${commandWithArgs} failed${durationStr}${reason}`);
1118
+ }
1195
1119
  if (state.currentConfigs.length === 1) closeGroup(`Hook ${commandWithArgs}`);
1196
1120
  });
1197
1121
  context.on("kubb:generation:summary", ({ config, status, hrStart, failedPlugins }) => {
@@ -1205,6 +1129,10 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
1205
1129
  context.on("kubb:lifecycle:end", () => {
1206
1130
  reset();
1207
1131
  });
1132
+ return (_commandWithArgs, _hookId) => ({
1133
+ onStdout: logLevel > _kubb_core.logLevel.silent ? (s) => console.log(s) : void 0,
1134
+ onStderr: logLevel > _kubb_core.logLevel.silent ? (s) => console.error(`::error::${s}`) : void 0
1135
+ });
1208
1136
  }
1209
1137
  });
1210
1138
  //#endregion
@@ -1216,6 +1144,7 @@ const plainLogger = (0, _kubb_core.defineLogger)({
1216
1144
  name: "plain",
1217
1145
  install(context, options) {
1218
1146
  const logLevel = options?.logLevel ?? _kubb_core.logLevel.info;
1147
+ const hookStarts = /* @__PURE__ */ new Map();
1219
1148
  function getMessage(message) {
1220
1149
  return formatMessage(message, logLevel);
1221
1150
  }
@@ -1260,8 +1189,12 @@ const plainLogger = (0, _kubb_core.defineLogger)({
1260
1189
  }
1261
1190
  }
1262
1191
  });
1263
- context.on("kubb:lifecycle:start", () => {
1264
- console.log("Kubb CLI 🧩");
1192
+ context.on("kubb:lifecycle:start", ({ version }) => {
1193
+ console.log(`Kubb CLI v${version}`);
1194
+ });
1195
+ context.on("kubb:version:new", ({ currentVersion, latestVersion }) => {
1196
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1197
+ console.log(getMessage(`Update available: v${currentVersion} → v${latestVersion}. Run \`npm install -g @kubb/cli\` to update.`));
1265
1198
  });
1266
1199
  context.on("kubb:config:start", () => {
1267
1200
  if (logLevel <= _kubb_core.logLevel.silent) return;
@@ -1293,10 +1226,9 @@ const plainLogger = (0, _kubb_core.defineLogger)({
1293
1226
  const text = getMessage(`Writing ${files.length} files`);
1294
1227
  console.log(text);
1295
1228
  });
1296
- context.on("kubb:file:processing:update", ({ file, config }) => {
1229
+ context.on("kubb:files:processing:update", ({ files }) => {
1297
1230
  if (logLevel <= _kubb_core.logLevel.silent) return;
1298
- const text = getMessage(`Writing ${(0, node_path.relative)(config.root, file.path)}`);
1299
- console.log(text);
1231
+ for (const { file, config } of files) console.log(getMessage(`Writing ${(0, node_path.relative)(config.root, file.path)}`));
1300
1232
  });
1301
1233
  context.on("kubb:files:processing:end", () => {
1302
1234
  if (logLevel <= _kubb_core.logLevel.silent) return;
@@ -1327,27 +1259,31 @@ const plainLogger = (0, _kubb_core.defineLogger)({
1327
1259
  const text = getMessage("Lint completed");
1328
1260
  console.log(text);
1329
1261
  });
1330
- context.on("kubb:hook:start", async ({ id, command, args }) => {
1262
+ context.on("kubb:hooks:start", () => {
1263
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1264
+ console.log(getMessage("Hooks started"));
1265
+ });
1266
+ context.on("kubb:hooks:end", () => {
1267
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1268
+ console.log(getMessage("Hooks completed"));
1269
+ });
1270
+ context.on("kubb:hook:start", ({ id, command, args }) => {
1271
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1272
+ if (id) hookStarts.set(id, node_process.default.hrtime());
1331
1273
  const commandWithArgs = formatCommandWithArgs(command, args);
1332
- const text = getMessage(`Hook ${commandWithArgs} started`);
1333
- if (logLevel > _kubb_core.logLevel.silent) console.log(text);
1334
- if (!id) return;
1335
- await runHook({
1336
- id,
1337
- command,
1338
- args,
1339
- commandWithArgs,
1340
- context,
1341
- sink: {
1342
- onStdout: logLevel > _kubb_core.logLevel.silent ? (s) => console.log(s) : void 0,
1343
- onStderr: logLevel > _kubb_core.logLevel.silent ? (s) => console.error(s) : void 0
1344
- }
1345
- });
1274
+ console.log(getMessage(`Hook ${commandWithArgs} started`));
1346
1275
  });
1347
- context.on("kubb:hook:end", ({ command, args }) => {
1276
+ context.on("kubb:hook:end", ({ id, command, args, success, error }) => {
1348
1277
  if (logLevel <= _kubb_core.logLevel.silent) return;
1349
- const text = getMessage(`Hook ${formatCommandWithArgs(command, args)} completed`);
1350
- console.log(text);
1278
+ const hrStart = id ? hookStarts.get(id) : void 0;
1279
+ if (id) hookStarts.delete(id);
1280
+ const durationStr = hrStart ? ` in ${formatMs(getElapsedMs(hrStart))}` : "";
1281
+ const commandWithArgs = formatCommandWithArgs(command, args);
1282
+ if (success) console.log(getMessage(`✓ Hook ${commandWithArgs} completed${durationStr}`));
1283
+ else {
1284
+ const reason = error?.message ? ` (${error.message})` : "";
1285
+ console.log(getMessage(`✗ Hook ${commandWithArgs} failed${durationStr}${reason}`));
1286
+ }
1351
1287
  });
1352
1288
  context.on("kubb:generation:summary", ({ config, pluginTimings, status, hrStart, failedPlugins, filesCreated }) => {
1353
1289
  const summary = getSummary({
@@ -1362,6 +1298,10 @@ const plainLogger = (0, _kubb_core.defineLogger)({
1362
1298
  console.log(summary.join("\n"));
1363
1299
  console.log(require_constants.SUMMARY_SEPARATOR);
1364
1300
  });
1301
+ return (_commandWithArgs, _hookId) => ({
1302
+ onStdout: logLevel > _kubb_core.logLevel.silent ? (s) => console.log(s) : void 0,
1303
+ onStderr: logLevel > _kubb_core.logLevel.silent ? (s) => console.error(s) : void 0
1304
+ });
1365
1305
  }
1366
1306
  });
1367
1307
  //#endregion
@@ -1416,125 +1356,241 @@ async function setupLogger(context, { logLevel }) {
1416
1356
  const type = detectLogger();
1417
1357
  const logger = logMapper[type];
1418
1358
  if (!logger) throw new Error(`Unknown adapter type: ${type}`);
1419
- const cleanup = await logger.install(context, { logLevel });
1359
+ const makeSink = await logger.install(context, { logLevel });
1420
1360
  if (logLevel >= _kubb_core.logLevel.debug) await fileSystemLogger.install(context, { logLevel });
1421
- return cleanup;
1361
+ return typeof makeSink === "function" ? makeSink : null;
1422
1362
  }
1423
- //#endregion
1424
- //#region src/utils/executeHooks.ts
1425
- async function executeHooks({ configHooks, hooks }) {
1426
- const commands = Array.isArray(configHooks.done) ? configHooks.done : [configHooks.done].filter(Boolean);
1427
- for (const command of commands) {
1428
- const [cmd, ...args] = require_shell.tokenize(command);
1429
- if (!cmd) continue;
1430
- const hookId = (0, node_crypto.createHash)("sha256").update(command).digest("hex");
1431
- const hookEndPromise = new Promise((resolve, reject) => {
1432
- const handler = (ctx) => {
1433
- if (ctx.id !== hookId) return;
1434
- hooks.off("kubb:hook:end", handler);
1435
- if (!ctx.success) {
1436
- reject(ctx.error ?? /* @__PURE__ */ new Error(`Hook failed: ${command}`));
1437
- return;
1438
- }
1439
- hooks.emit("kubb:success", { message: `${(0, node_util.styleText)("dim", command)} successfully executed` }).then(resolve).catch(reject);
1440
- };
1441
- hooks.on("kubb:hook:end", handler);
1442
- });
1443
- await hooks.emit("kubb:hook:start", {
1444
- id: hookId,
1445
- command: cmd,
1446
- args
1363
+ /**
1364
+ * Builds the generation summary lines rendered in the end-of-run box.
1365
+ * Returns an array of styled strings, one per summary row.
1366
+ */
1367
+ function getSummary({ failedPlugins, filesCreated, status, hrStart, config, pluginTimings }) {
1368
+ const duration = formatHrtime(hrStart);
1369
+ const pluginsCount = config.plugins?.length ?? 0;
1370
+ const successCount = pluginsCount - failedPlugins.size;
1371
+ const meta = {
1372
+ 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`,
1373
+ pluginsFailed: status === "failed" ? [...failedPlugins].map(({ plugin }) => randomCliColor(plugin.name)).join(", ") : void 0,
1374
+ filesCreated,
1375
+ time: (0, node_util.styleText)("green", duration),
1376
+ output: node_path.default.resolve(config.root, config.output.path)
1377
+ };
1378
+ const labels = {
1379
+ plugins: "Plugins:",
1380
+ failed: "Failed:",
1381
+ generated: "Generated:",
1382
+ pluginTimings: "Plugin Timings:",
1383
+ output: "Output:"
1384
+ };
1385
+ const maxLength = Math.max(0, ...[...Object.values(labels), ...pluginTimings ? Array.from(pluginTimings.keys()) : []].map((s) => s.length));
1386
+ const summaryLines = [];
1387
+ summaryLines.push(`${labels.plugins.padEnd(maxLength + 2)} ${meta.plugins}`);
1388
+ if (meta.pluginsFailed) summaryLines.push(`${labels.failed.padEnd(maxLength + 2)} ${meta.pluginsFailed}`);
1389
+ summaryLines.push(`${labels.generated.padEnd(maxLength + 2)} ${meta.filesCreated} files in ${meta.time}`);
1390
+ if (pluginTimings && pluginTimings.size > 0) {
1391
+ const sortedTimings = Array.from(pluginTimings.entries()).sort((a, b) => b[1] - a[1]);
1392
+ summaryLines.push(`${labels.pluginTimings}`);
1393
+ sortedTimings.forEach(([name, time]) => {
1394
+ const timeStr = time >= 1e3 ? `${(time / 1e3).toFixed(2)}s` : `${Math.round(time)}ms`;
1395
+ const barLength = Math.min(Math.ceil(time / 100), 10);
1396
+ const bar = (0, node_util.styleText)("dim", "█".repeat(barLength));
1397
+ summaryLines.push(`${(0, node_util.styleText)("dim", "•")} ${name.padEnd(maxLength + 1)}${bar} ${timeStr}`);
1447
1398
  });
1448
- await hookEndPromise;
1449
1399
  }
1400
+ summaryLines.push(`${labels.output.padEnd(maxLength + 2)} ${meta.output}`);
1401
+ return summaryLines;
1450
1402
  }
1451
1403
  //#endregion
1452
- //#region src/utils/getConfig.ts
1453
- async function getConfigs(config, args) {
1454
- const resolved = await (typeof config === "function" ? config(args) : config);
1455
- return (Array.isArray(resolved) ? resolved : [resolved]).map((item) => ({
1456
- ...item,
1457
- plugins: item.plugins ?? []
1458
- }));
1459
- }
1460
- //#endregion
1461
- //#region src/utils/getCosmiConfig.ts
1462
- const unrunInputOptions = { transform: { jsx: {
1463
- runtime: "automatic",
1464
- importSource: "@kubb/renderer-jsx"
1465
- } } };
1466
- const tsLoader = async (configFile) => {
1467
- const { module } = await (0, unrun.unrun)({
1468
- path: configFile,
1469
- inputOptions: unrunInputOptions
1470
- });
1471
- return module;
1472
- };
1473
- async function getCosmiConfig(moduleName, config) {
1474
- let result;
1475
- const searchPlaces = [
1476
- "package.json",
1477
- `.${moduleName}rc`,
1478
- `.${moduleName}rc.json`,
1479
- `.${moduleName}rc.yaml`,
1480
- `.${moduleName}rc.yml`,
1481
- `.${moduleName}rc.ts`,
1482
- `.${moduleName}rc.mts`,
1483
- `.${moduleName}rc.cts`,
1484
- `.${moduleName}rc.js`,
1485
- `.${moduleName}rc.mjs`,
1486
- `.${moduleName}rc.cjs`,
1487
- `${moduleName}.config.ts`,
1488
- `${moduleName}.config.mts`,
1489
- `${moduleName}.config.cts`,
1490
- `${moduleName}.config.js`,
1491
- `${moduleName}.config.mjs`,
1492
- `${moduleName}.config.cjs`
1493
- ];
1494
- const explorer = (0, cosmiconfig.cosmiconfig)(moduleName, {
1404
+ //#region src/runners/generate/utils.ts
1405
+ const jiti$1 = (0, jiti.createJiti)(require("url").pathToFileURL(__filename).href, {
1406
+ jsx: {
1407
+ runtime: "automatic",
1408
+ importSource: "@kubb/renderer-jsx"
1409
+ },
1410
+ moduleCache: false
1411
+ });
1412
+ const tsLoader = (configFile) => jiti$1.import(configFile, { default: true });
1413
+ const MODULE_NAME = "kubb";
1414
+ const BASE_SEARCH_PLACES = [
1415
+ "package.json",
1416
+ `.${MODULE_NAME}rc`,
1417
+ `.${MODULE_NAME}rc.json`,
1418
+ `.${MODULE_NAME}rc.yaml`,
1419
+ `.${MODULE_NAME}rc.yml`,
1420
+ `.${MODULE_NAME}rc.ts`,
1421
+ `.${MODULE_NAME}rc.mts`,
1422
+ `.${MODULE_NAME}rc.cts`,
1423
+ `.${MODULE_NAME}rc.js`,
1424
+ `.${MODULE_NAME}rc.mjs`,
1425
+ `.${MODULE_NAME}rc.cjs`,
1426
+ `${MODULE_NAME}.config.ts`,
1427
+ `${MODULE_NAME}.config.mts`,
1428
+ `${MODULE_NAME}.config.cts`,
1429
+ `${MODULE_NAME}.config.js`,
1430
+ `${MODULE_NAME}.config.mjs`,
1431
+ `${MODULE_NAME}.config.cjs`
1432
+ ];
1433
+ const SEARCH_PLACES = [
1434
+ "",
1435
+ ".config/",
1436
+ "configs/"
1437
+ ].flatMap((prefix) => BASE_SEARCH_PLACES.map((p) => `${prefix}${p}`));
1438
+ async function getCosmiConfig(configFile) {
1439
+ const explorer = (0, cosmiconfig.cosmiconfig)(MODULE_NAME, {
1495
1440
  cache: false,
1496
- searchPlaces: [
1497
- ...searchPlaces.map((searchPlace) => {
1498
- return `.config/${searchPlace}`;
1499
- }),
1500
- ...searchPlaces.map((searchPlace) => {
1501
- return `configs/${searchPlace}`;
1502
- }),
1503
- ...searchPlaces
1504
- ],
1441
+ searchPlaces: SEARCH_PLACES,
1505
1442
  loaders: {
1506
1443
  ".ts": tsLoader,
1507
1444
  ".mts": tsLoader,
1508
1445
  ".cts": tsLoader
1509
1446
  }
1510
1447
  });
1448
+ let result;
1511
1449
  try {
1512
- result = config ? await explorer.load(config) : await explorer.search();
1450
+ result = configFile ? await explorer.load(configFile) : await explorer.search();
1513
1451
  } catch (error) {
1514
1452
  throw new Error("Config failed loading", { cause: error });
1515
1453
  }
1516
- 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");
1454
+ if (!result?.config || result.isEmpty) throw new Error("Config not defined, create a kubb.config.js or pass through your config with the option --config");
1517
1455
  return result;
1518
1456
  }
1519
- //#endregion
1520
- //#region src/utils/watcher.ts
1521
- async function startWatcher(path, cb) {
1457
+ /**
1458
+ * Discovers the Kubb config via cosmiconfig and resolves it into a normalized array of configs.
1459
+ * Every config in the result is guaranteed to have a `plugins` array.
1460
+ */
1461
+ async function getConfigs({ configPath, input }) {
1462
+ const result = await getCosmiConfig(configPath);
1463
+ const resolved = await (typeof result.config === "function" ? result.config({ input }) : result.config);
1464
+ const userConfigs = Array.isArray(resolved) ? resolved : [resolved];
1465
+ return {
1466
+ configPath: result.filepath,
1467
+ configs: userConfigs.map((item) => ({
1468
+ ...item,
1469
+ plugins: item.plugins ?? []
1470
+ }))
1471
+ };
1472
+ }
1473
+ /**
1474
+ * Runs the `done` hooks defined in a Kubb config in sequence.
1475
+ */
1476
+ async function executeHooks({ configHooks, hooks, makeSink }) {
1477
+ const commands = Array.isArray(configHooks.done) ? configHooks.done : [configHooks.done].filter(Boolean);
1478
+ for (const command of commands) {
1479
+ const [cmd, ...args] = require_shell.tokenize(command);
1480
+ if (!cmd) continue;
1481
+ const hookId = (0, node_crypto.createHash)("sha256").update(command).digest("hex");
1482
+ const commandWithArgs = [cmd, ...args].join(" ");
1483
+ await hooks.emit("kubb:hook:start", {
1484
+ id: hookId,
1485
+ command: cmd,
1486
+ args
1487
+ });
1488
+ const { stream = false, onLine, onStdout, onStderr } = makeSink?.(commandWithArgs, hookId) ?? {};
1489
+ await runHook({
1490
+ id: hookId,
1491
+ command: cmd,
1492
+ args,
1493
+ commandWithArgs,
1494
+ context: hooks,
1495
+ stream,
1496
+ sink: {
1497
+ onLine,
1498
+ onStdout,
1499
+ onStderr
1500
+ }
1501
+ });
1502
+ }
1503
+ }
1504
+ async function runHook({ id, command, args, commandWithArgs, context, stream = false, sink }) {
1505
+ const emitEnd = (success, error) => context.emit("kubb:hook:end", {
1506
+ command,
1507
+ args,
1508
+ id,
1509
+ success,
1510
+ error
1511
+ });
1512
+ try {
1513
+ const proc = (0, tinyexec.x)(command, [...args ?? []], {
1514
+ nodeOptions: { detached: process.platform !== "win32" },
1515
+ throwOnError: true
1516
+ });
1517
+ if (stream && sink?.onLine) for await (const line of proc) sink.onLine(line);
1518
+ const result = await proc;
1519
+ await context.emit("kubb:debug", {
1520
+ date: /* @__PURE__ */ new Date(),
1521
+ logs: [result.stdout.trimEnd()]
1522
+ });
1523
+ await context.emit("kubb:success", { message: `${(0, node_util.styleText)("dim", commandWithArgs)} successfully executed` });
1524
+ await emitEnd(true, null);
1525
+ } catch (err) {
1526
+ if (!(err instanceof tinyexec.NonZeroExitError)) {
1527
+ const error = require_errors.toError(err);
1528
+ await emitEnd(false, error);
1529
+ await context.emit("kubb:error", { error });
1530
+ return;
1531
+ }
1532
+ const stderr = err.output?.stderr ?? "";
1533
+ const stdout = err.output?.stdout ?? "";
1534
+ await context.emit("kubb:debug", {
1535
+ date: /* @__PURE__ */ new Date(),
1536
+ logs: [stdout, stderr].filter(Boolean)
1537
+ });
1538
+ if (stderr) sink?.onStderr?.(stderr);
1539
+ if (stdout) sink?.onStdout?.(stdout);
1540
+ const error = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
1541
+ await emitEnd(false, error);
1542
+ await context.emit("kubb:error", { error });
1543
+ }
1544
+ }
1545
+ /**
1546
+ * Starts a file watcher on the given paths and calls `cb` on any change.
1547
+ * Ignores `.git` and `node_modules` directories.
1548
+ */
1549
+ async function startWatcher(path, cb, log = {
1550
+ info: console.log,
1551
+ error: console.log
1552
+ }) {
1522
1553
  const { watch } = await import("chokidar");
1523
- watch(path, {
1554
+ const watcher = watch(path, {
1524
1555
  ignorePermissionErrors: true,
1525
1556
  ignored: require_constants.WATCHER_IGNORED_PATHS
1526
- }).on("all", async (type, file) => {
1527
- console.log((0, node_util.styleText)("yellow", (0, node_util.styleText)("bold", `Change detected: ${type} ${file}`)));
1557
+ });
1558
+ process.once("SIGINT", () => {
1559
+ watcher.close();
1560
+ });
1561
+ process.once("SIGTERM", () => {
1562
+ watcher.close();
1563
+ });
1564
+ watcher.on("all", async (type, file) => {
1565
+ log.info((0, node_util.styleText)("yellow", (0, node_util.styleText)("bold", `Change detected: ${type} ${file}`)));
1528
1566
  try {
1529
1567
  await cb(path);
1530
1568
  } catch (_e) {
1531
- console.log((0, node_util.styleText)("red", "Watcher failed"));
1569
+ log.error((0, node_util.styleText)("red", "Watcher failed"));
1532
1570
  }
1533
1571
  });
1534
1572
  }
1535
1573
  //#endregion
1536
- //#region src/runners/generate.ts
1537
- async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, configName, outputPath, logLevel, hooks, onStart, onEnd }) {
1574
+ //#region src/runners/generate/run.ts
1575
+ /**
1576
+ * Registers a one-shot `kubb:hook:end` listener for `hookId` BEFORE the caller emits `kubb:hook:start`,
1577
+ * avoiding the race where a synchronous emitter fires end before the listener is attached.
1578
+ */
1579
+ function waitForHookEnd(hooks, hookId, onSuccess, fallbackErrorMessage) {
1580
+ return new Promise((resolve, reject) => {
1581
+ const handler = (ctx) => {
1582
+ if (ctx.id !== hookId) return;
1583
+ hooks.off("kubb:hook:end", handler);
1584
+ if (!ctx.success) {
1585
+ reject(ctx.error ?? new Error(fallbackErrorMessage));
1586
+ return;
1587
+ }
1588
+ Promise.resolve(onSuccess()).then(resolve).catch(reject);
1589
+ };
1590
+ hooks.on("kubb:hook:end", handler);
1591
+ });
1592
+ }
1593
+ async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, configName, outputPath, logLevel, hooks, makeSink, onStart, onEnd }) {
1538
1594
  await onStart();
1539
1595
  let resolvedTool = toolValue;
1540
1596
  if (resolvedTool === "auto") {
@@ -1548,29 +1604,35 @@ async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefi
1548
1604
  let toolError;
1549
1605
  if (resolvedTool && resolvedTool !== "auto" && resolvedTool in toolMap) {
1550
1606
  const toolConfig = toolMap[resolvedTool];
1607
+ const hookId = (0, node_crypto.createHash)("sha256").update([configName, resolvedTool].filter(Boolean).join("-")).digest("hex");
1608
+ const successMessage = [
1609
+ `${successPrefix} with ${(0, node_util.styleText)("dim", resolvedTool)}`,
1610
+ logLevel >= _kubb_core.logLevel.info ? `on ${(0, node_util.styleText)("dim", outputPath)}` : void 0,
1611
+ "successfully"
1612
+ ].filter(Boolean).join(" ");
1551
1613
  try {
1552
- const hookId = (0, node_crypto.createHash)("sha256").update([configName, resolvedTool].filter(Boolean).join("-")).digest("hex");
1553
- const hookEndPromise = new Promise((resolve, reject) => {
1554
- const handler = (ctx) => {
1555
- if (ctx.id !== hookId) return;
1556
- hooks.off("kubb:hook:end", handler);
1557
- if (!ctx.success) {
1558
- reject(ctx.error ?? /* @__PURE__ */ new Error(`${toolConfig.errorMessage}`));
1559
- return;
1560
- }
1561
- hooks.emit("kubb:success", { message: [
1562
- `${successPrefix} with ${(0, node_util.styleText)("dim", resolvedTool)}`,
1563
- logLevel >= _kubb_core.logLevel.info ? `on ${(0, node_util.styleText)("dim", outputPath)}` : void 0,
1564
- "successfully"
1565
- ].filter(Boolean).join(" ") }).then(resolve).catch(reject);
1566
- };
1567
- hooks.on("kubb:hook:end", handler);
1568
- });
1614
+ const hookArgs = toolConfig.args(outputPath);
1615
+ const commandWithArgs = [toolConfig.command, ...hookArgs].join(" ");
1616
+ const hookEndPromise = waitForHookEnd(hooks, hookId, () => hooks.emit("kubb:success", { message: successMessage }), toolConfig.errorMessage);
1569
1617
  await hooks.emit("kubb:hook:start", {
1570
1618
  id: hookId,
1571
1619
  command: toolConfig.command,
1572
- args: toolConfig.args(outputPath)
1620
+ args: hookArgs
1573
1621
  });
1622
+ const { stream = false, onLine, onStdout, onStderr } = makeSink?.(commandWithArgs, hookId) ?? {};
1623
+ runHook({
1624
+ id: hookId,
1625
+ command: toolConfig.command,
1626
+ args: hookArgs,
1627
+ commandWithArgs,
1628
+ context: hooks,
1629
+ stream,
1630
+ sink: {
1631
+ onLine,
1632
+ onStdout,
1633
+ onStderr
1634
+ }
1635
+ }).catch(() => {});
1574
1636
  await hookEndPromise;
1575
1637
  } catch (caughtError) {
1576
1638
  const err = require_errors.toError(caughtError);
@@ -1582,9 +1644,9 @@ async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefi
1582
1644
  if (toolError) throw toolError;
1583
1645
  }
1584
1646
  async function generate(options) {
1585
- const { input, hooks, logLevel } = options;
1647
+ const { input, hooks, logLevel, makeSink } = options;
1586
1648
  const hrStart = node_process.default.hrtime();
1587
- const inputPath = input ?? ("path" in options.config.input ? options.config.input.path : void 0);
1649
+ const inputPath = input ?? (options.config.input && "path" in options.config.input ? options.config.input.path : void 0);
1588
1650
  const config = {
1589
1651
  ...options.config,
1590
1652
  input: inputPath ? {
@@ -1594,25 +1656,36 @@ async function generate(options) {
1594
1656
  ...options.config.output
1595
1657
  };
1596
1658
  const kubb = (0, _kubb_core.createKubb)(config, { hooks });
1597
- await kubb.setup();
1598
1659
  await hooks.emit("kubb:generation:start", { config });
1599
1660
  await hooks.emit("kubb:info", {
1600
1661
  message: config.name ? `Setup generation ${(0, node_util.styleText)("bold", config.name)}` : "Setup generation",
1601
1662
  info: inputPath
1602
1663
  });
1664
+ await kubb.setup();
1603
1665
  await hooks.emit("kubb:info", {
1604
1666
  message: config.name ? `Build generation ${(0, node_util.styleText)("bold", config.name)}` : "Build generation",
1605
1667
  info: inputPath
1606
1668
  });
1607
1669
  const { files, failedPlugins, pluginTimings, error, driver } = await kubb.safeBuild();
1608
1670
  await hooks.emit("kubb:info", { message: "Load summary" });
1671
+ const telemetryPlugins = Array.from(driver.plugins.values(), (p) => ({
1672
+ name: p.name,
1673
+ options: p.options
1674
+ }));
1675
+ const reportTelemetry = (status) => require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
1676
+ command: "generate",
1677
+ kubbVersion: require_package.version,
1678
+ plugins: telemetryPlugins,
1679
+ hrStart,
1680
+ filesCreated: files.length,
1681
+ status
1682
+ }));
1609
1683
  if (failedPlugins.size > 0 || error) {
1610
- const allErrors = [error, ...Array.from(failedPlugins).filter((it) => it.error).map((it) => it.error)].filter(Boolean);
1684
+ const allErrors = [error, ...Array.from(failedPlugins, (it) => it.error)].filter(Boolean);
1611
1685
  for (const err of allErrors) await hooks.emit("kubb:error", { error: err });
1612
1686
  await hooks.emit("kubb:generation:end", {
1613
1687
  config,
1614
- files,
1615
- sources: kubb.sources
1688
+ storage: kubb.storage
1616
1689
  });
1617
1690
  await hooks.emit("kubb:generation:summary", {
1618
1691
  config,
@@ -1622,62 +1695,51 @@ async function generate(options) {
1622
1695
  hrStart,
1623
1696
  pluginTimings: logLevel >= _kubb_core.logLevel.verbose ? pluginTimings : void 0
1624
1697
  });
1625
- await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
1626
- command: "generate",
1627
- kubbVersion: require_package.version,
1628
- plugins: Array.from(driver.plugins.values(), (p) => ({
1629
- name: p.name,
1630
- options: p.options
1631
- })),
1632
- hrStart,
1633
- filesCreated: files.length,
1634
- status: "failed"
1635
- }));
1636
- node_process.default.exit(1);
1698
+ await reportTelemetry("failed");
1699
+ return false;
1637
1700
  }
1638
1701
  await hooks.emit("kubb:success", {
1639
- message: "Generation successfully",
1702
+ message: "Generation succeeded",
1640
1703
  info: inputPath
1641
1704
  });
1642
1705
  await hooks.emit("kubb:generation:end", {
1643
1706
  config,
1644
- files,
1645
- sources: kubb.sources
1707
+ storage: kubb.storage
1646
1708
  });
1647
1709
  const outputPath = node_path.default.resolve(config.root, config.output.path);
1648
- if (config.output.format) await runToolPass({
1710
+ const toolPasses = [config.output.format && {
1649
1711
  toolValue: config.output.format,
1650
1712
  detect: detectFormatter,
1651
1713
  toolMap: formatters,
1652
1714
  toolLabel: "formatter",
1653
1715
  successPrefix: "Formatting",
1654
1716
  noToolMessage: "No formatter found (oxfmt, biome, or prettier). Skipping formatting.",
1655
- configName: config.name,
1656
- outputPath,
1657
- logLevel,
1658
- hooks,
1659
1717
  onStart: () => hooks.emit("kubb:format:start"),
1660
1718
  onEnd: () => hooks.emit("kubb:format:end")
1661
- });
1662
- if (config.output.lint) await runToolPass({
1719
+ }, config.output.lint && {
1663
1720
  toolValue: config.output.lint,
1664
1721
  detect: detectLinter,
1665
1722
  toolMap: linters,
1666
1723
  toolLabel: "linter",
1667
1724
  successPrefix: "Linting",
1668
1725
  noToolMessage: "No linter found (oxlint, biome, or eslint). Skipping linting.",
1726
+ onStart: () => hooks.emit("kubb:lint:start"),
1727
+ onEnd: () => hooks.emit("kubb:lint:end")
1728
+ }].filter(Boolean);
1729
+ for (const pass of toolPasses) await runToolPass({
1730
+ ...pass,
1669
1731
  configName: config.name,
1670
1732
  outputPath,
1671
1733
  logLevel,
1672
1734
  hooks,
1673
- onStart: () => hooks.emit("kubb:lint:start"),
1674
- onEnd: () => hooks.emit("kubb:lint:end")
1735
+ makeSink
1675
1736
  });
1676
1737
  if (config.hooks) {
1677
1738
  await hooks.emit("kubb:hooks:start");
1678
1739
  await executeHooks({
1679
1740
  configHooks: config.hooks,
1680
- hooks
1741
+ hooks,
1742
+ makeSink
1681
1743
  });
1682
1744
  await hooks.emit("kubb:hooks:end");
1683
1745
  }
@@ -1689,68 +1751,80 @@ async function generate(options) {
1689
1751
  hrStart,
1690
1752
  pluginTimings
1691
1753
  });
1692
- await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
1693
- command: "generate",
1694
- kubbVersion: require_package.version,
1695
- plugins: Array.from(driver.plugins.values(), (p) => ({
1696
- name: p.name,
1697
- options: p.options
1698
- })),
1699
- hrStart,
1700
- filesCreated: files.length,
1701
- status: "success"
1702
- }));
1754
+ await reportTelemetry("success");
1755
+ return true;
1703
1756
  }
1704
- async function runGenerateCommand({ input, configPath, logLevel: logLevelKey, watch }) {
1705
- const logLevel = _kubb_core.logLevel[logLevelKey] ?? _kubb_core.logLevel.info;
1706
- const hooks = new AsyncEventEmitter();
1707
- await setupLogger(hooks, { logLevel });
1757
+ async function checkForUpdate(hooks) {
1708
1758
  await require_telemetry.executeIfOnline(async () => {
1709
1759
  try {
1710
- const latestVersion = (await (await fetch(require_constants.KUBB_NPM_PACKAGE_URL)).json()).version;
1711
- if (latestVersion && require_package.version < latestVersion) await hooks.emit("kubb:version:new", {
1760
+ const data = await (await fetch(require_constants.KUBB_NPM_PACKAGE_URL)).json();
1761
+ if (data.version && require_package.version < data.version) await hooks.emit("kubb:version:new", {
1712
1762
  currentVersion: require_package.version,
1713
- latestVersion
1763
+ latestVersion: data.version
1714
1764
  });
1715
1765
  } catch {}
1716
1766
  });
1767
+ }
1768
+ /**
1769
+ * Runs the full Kubb generation lifecycle for the given CLI options.
1770
+ * Sets up the logger, checks for a newer version, loads configs, and calls `generate` for each config entry.
1771
+ */
1772
+ async function run({ input, configPath, logLevel: logLevelKey, watch }) {
1773
+ const logLevel = _kubb_core.logLevel[logLevelKey] ?? _kubb_core.logLevel.info;
1774
+ const hooks = new AsyncEventEmitter();
1775
+ const makeSink = await setupLogger(hooks, { logLevel });
1776
+ await hooks.emit("kubb:lifecycle:start", { version: require_package.version });
1777
+ await checkForUpdate(hooks);
1717
1778
  try {
1718
- const result = await getCosmiConfig("kubb", configPath);
1719
- const configs = await getConfigs(result.config, { input });
1720
1779
  await hooks.emit("kubb:config:start");
1780
+ const { configs, configPath: resolvedConfigPath } = await getConfigs({
1781
+ configPath,
1782
+ input
1783
+ });
1784
+ const relativeConfigPath = node_path.default.relative(node_process.default.cwd(), resolvedConfigPath);
1721
1785
  await hooks.emit("kubb:info", {
1722
1786
  message: "Config loaded",
1723
- info: node_path.default.relative(node_process.default.cwd(), result.filepath)
1787
+ info: relativeConfigPath
1724
1788
  });
1725
1789
  await hooks.emit("kubb:success", {
1726
1790
  message: "Config loaded successfully",
1727
- info: node_path.default.relative(node_process.default.cwd(), result.filepath)
1791
+ info: relativeConfigPath
1728
1792
  });
1729
1793
  await hooks.emit("kubb:config:end", { configs });
1730
- await hooks.emit("kubb:lifecycle:start", { version: require_package.version });
1794
+ let anyFailed = false;
1731
1795
  for (const config of configs) if ((0, _kubb_core.isInputPath)(config) && watch) await startWatcher([input || config.input.path], async (paths) => {
1732
- hooks.removeAll();
1733
1796
  await generate({
1734
1797
  input,
1735
1798
  config,
1736
1799
  logLevel,
1737
- hooks
1800
+ hooks,
1801
+ makeSink
1738
1802
  });
1739
1803
  _clack_prompts.log.step((0, node_util.styleText)("yellow", `Watching for changes in ${paths.join(" and ")}`));
1804
+ }, {
1805
+ info: (msg) => _clack_prompts.log.info(msg),
1806
+ error: (msg) => _clack_prompts.log.error(msg)
1740
1807
  });
1741
- else await generate({
1742
- input,
1743
- config,
1744
- logLevel,
1745
- hooks
1746
- });
1808
+ else try {
1809
+ if (!await generate({
1810
+ input,
1811
+ config,
1812
+ logLevel,
1813
+ hooks,
1814
+ makeSink
1815
+ })) anyFailed = true;
1816
+ } catch (configError) {
1817
+ await hooks.emit("kubb:error", { error: require_errors.toError(configError) });
1818
+ anyFailed = true;
1819
+ }
1747
1820
  await hooks.emit("kubb:lifecycle:end");
1821
+ if (anyFailed) node_process.default.exit(1);
1748
1822
  } catch (error) {
1749
1823
  await hooks.emit("kubb:error", { error: require_errors.toError(error) });
1750
1824
  node_process.default.exit(1);
1751
1825
  }
1752
1826
  }
1753
1827
  //#endregion
1754
- exports.runGenerateCommand = runGenerateCommand;
1828
+ exports.run = run;
1755
1829
 
1756
- //# sourceMappingURL=generate-B3jl4ukb.cjs.map
1830
+ //# sourceMappingURL=run-CmiuJkLG.cjs.map