@kubb/cli 5.0.0-alpha.5 → 5.0.0-alpha.50

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 (138) hide show
  1. package/README.md +4 -2
  2. package/bin/kubb.js +6 -0
  3. package/dist/agent-Bt-Z24BD.cjs +116 -0
  4. package/dist/agent-Bt-Z24BD.cjs.map +1 -0
  5. package/dist/{agent-SWUT_sgq.js → agent-CHqQt6-j.js} +5 -5
  6. package/dist/agent-CHqQt6-j.js.map +1 -0
  7. package/dist/agent-LgBdb1gx.js +112 -0
  8. package/dist/agent-LgBdb1gx.js.map +1 -0
  9. package/dist/{agent-CEHZSBVT.cjs → agent-l26FqXrz.cjs} +5 -5
  10. package/dist/agent-l26FqXrz.cjs.map +1 -0
  11. package/dist/{constants-BTUap0zs.cjs → constants-B2q7VPbi.cjs} +91 -9
  12. package/dist/constants-B2q7VPbi.cjs.map +1 -0
  13. package/dist/constants-T_2rsi7T.js +137 -0
  14. package/dist/constants-T_2rsi7T.js.map +1 -0
  15. package/dist/define-Bdn8j5VM.cjs +54 -0
  16. package/dist/define-Bdn8j5VM.cjs.map +1 -0
  17. package/dist/define-Ctii4bel.js +43 -0
  18. package/dist/define-Ctii4bel.js.map +1 -0
  19. package/dist/{errors-DBW0N9w4.cjs → errors-CLCjoSg0.cjs} +22 -6
  20. package/dist/errors-CLCjoSg0.cjs.map +1 -0
  21. package/dist/errors-CjPmyZHy.js +43 -0
  22. package/dist/errors-CjPmyZHy.js.map +1 -0
  23. package/dist/{generate-CNkdrX6u.cjs → generate-BSqljMWH.cjs} +3 -3
  24. package/dist/generate-BSqljMWH.cjs.map +1 -0
  25. package/dist/{generate-CtFkZeTU.js → generate-CQPHU8Xt.js} +493 -248
  26. package/dist/generate-CQPHU8Xt.js.map +1 -0
  27. package/dist/{generate-nJaqPdGL.cjs → generate-I-SQLa8R.cjs} +500 -255
  28. package/dist/generate-I-SQLa8R.cjs.map +1 -0
  29. package/dist/{generate-CfoLoEd0.js → generate-TP0il_KX.js} +3 -3
  30. package/dist/generate-TP0il_KX.js.map +1 -0
  31. package/dist/index.cjs +49 -21
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.js +49 -21
  35. package/dist/index.js.map +1 -1
  36. package/dist/{init-D_oERuMn.js → init-13Vizgki.js} +4 -4
  37. package/dist/init-13Vizgki.js.map +1 -0
  38. package/dist/{init-hmolV6B4.cjs → init-AVT-2Uxi.cjs} +31 -21
  39. package/dist/init-AVT-2Uxi.cjs.map +1 -0
  40. package/dist/{init-C-InrmSY.js → init-BecEYFRb.js} +27 -17
  41. package/dist/init-BecEYFRb.js.map +1 -0
  42. package/dist/{init-BAs1d5rK.cjs → init-POdCjZS0.cjs} +4 -4
  43. package/dist/init-POdCjZS0.cjs.map +1 -0
  44. package/dist/{mcp-D2SHEg_d.js → mcp-BDHEbuy3.js} +11 -4
  45. package/dist/mcp-BDHEbuy3.js.map +1 -0
  46. package/dist/{mcp-DEvDB6FY.cjs → mcp-BotRrBI-.cjs} +4 -4
  47. package/dist/{mcp-DEvDB6FY.cjs.map → mcp-BotRrBI-.cjs.map} +1 -1
  48. package/dist/{mcp-ChHFPRzD.cjs → mcp-CqpVw3PO.cjs} +12 -6
  49. package/dist/mcp-CqpVw3PO.cjs.map +1 -0
  50. package/dist/{mcp-jKYiomZT.js → mcp-q4XumdSd.js} +4 -4
  51. package/dist/{mcp-jKYiomZT.js.map → mcp-q4XumdSd.js.map} +1 -1
  52. package/dist/package-BRmZkKt7.js +6 -0
  53. package/dist/package-BRmZkKt7.js.map +1 -0
  54. package/dist/{package-C-fC2Eoy.cjs → package-D86Y6wqb.cjs} +2 -2
  55. package/dist/package-D86Y6wqb.cjs.map +1 -0
  56. package/dist/{shell-7HPrTCJ5.cjs → shell-475fQKaX.cjs} +8 -3
  57. package/dist/shell-475fQKaX.cjs.map +1 -0
  58. package/dist/{shell-DqqWsHCD.js → shell-DLzN4fRo.js} +8 -3
  59. package/dist/shell-DLzN4fRo.js.map +1 -0
  60. package/dist/{telemetry-Cn9X1I5B.cjs → telemetry-B6ZbZOrb.cjs} +50 -8
  61. package/dist/telemetry-B6ZbZOrb.cjs.map +1 -0
  62. package/dist/{telemetry-DxiR7clS.js → telemetry-Dis5nWR_.js} +48 -6
  63. package/dist/telemetry-Dis5nWR_.js.map +1 -0
  64. package/dist/{validate--IXRJEhp.js → validate-AV-0RFuL.js} +4 -4
  65. package/dist/validate-AV-0RFuL.js.map +1 -0
  66. package/dist/{validate-BK3pc8zv.cjs → validate-Cu8Sfj-n.cjs} +4 -4
  67. package/dist/validate-Cu8Sfj-n.cjs.map +1 -0
  68. package/dist/{validate-Bbrn3Q-A.cjs → validate-D-8_wAFV.cjs} +6 -14
  69. package/dist/validate-D-8_wAFV.cjs.map +1 -0
  70. package/dist/{validate-l8vLmwKA.js → validate-GfErHsnI.js} +5 -13
  71. package/dist/validate-GfErHsnI.js.map +1 -0
  72. package/package.json +47 -46
  73. package/src/commands/agent/start.ts +20 -4
  74. package/src/commands/generate.ts +35 -6
  75. package/src/commands/init.ts +6 -1
  76. package/src/commands/validate.ts +6 -1
  77. package/src/constants.ts +65 -11
  78. package/src/index.ts +10 -12
  79. package/src/loggers/clackLogger.ts +54 -46
  80. package/src/loggers/fileSystemLogger.ts +13 -11
  81. package/src/loggers/githubActionsLogger.ts +22 -22
  82. package/src/loggers/plainLogger.ts +21 -21
  83. package/src/runners/agent.ts +81 -34
  84. package/src/runners/generate.ts +90 -109
  85. package/src/runners/init.ts +9 -9
  86. package/src/runners/mcp.ts +19 -3
  87. package/src/runners/validate.ts +19 -15
  88. package/src/types.ts +11 -0
  89. package/src/utils/executeHooks.ts +11 -11
  90. package/src/utils/flags.ts +10 -0
  91. package/src/utils/getConfig.ts +10 -0
  92. package/src/utils/getCosmiConfig.ts +9 -3
  93. package/src/utils/getSummary.ts +1 -1
  94. package/src/utils/runHook.ts +27 -9
  95. package/src/utils/telemetry.ts +16 -3
  96. package/bin/kubb.cjs +0 -18
  97. package/dist/agent-C6o_6GSJ.cjs +0 -92
  98. package/dist/agent-C6o_6GSJ.cjs.map +0 -1
  99. package/dist/agent-CEHZSBVT.cjs.map +0 -1
  100. package/dist/agent-L50VNhXv.js +0 -88
  101. package/dist/agent-L50VNhXv.js.map +0 -1
  102. package/dist/agent-SWUT_sgq.js.map +0 -1
  103. package/dist/constants-BTUap0zs.cjs.map +0 -1
  104. package/dist/constants-CM3dJzjK.js +0 -67
  105. package/dist/constants-CM3dJzjK.js.map +0 -1
  106. package/dist/define--M_JMcDC.js +0 -25
  107. package/dist/define--M_JMcDC.js.map +0 -1
  108. package/dist/define-D6Kfm7-Z.cjs +0 -36
  109. package/dist/define-D6Kfm7-Z.cjs.map +0 -1
  110. package/dist/errors-6mF_WKxg.js +0 -27
  111. package/dist/errors-6mF_WKxg.js.map +0 -1
  112. package/dist/errors-DBW0N9w4.cjs.map +0 -1
  113. package/dist/generate-CNkdrX6u.cjs.map +0 -1
  114. package/dist/generate-CfoLoEd0.js.map +0 -1
  115. package/dist/generate-CtFkZeTU.js.map +0 -1
  116. package/dist/generate-nJaqPdGL.cjs.map +0 -1
  117. package/dist/init-BAs1d5rK.cjs.map +0 -1
  118. package/dist/init-C-InrmSY.js.map +0 -1
  119. package/dist/init-D_oERuMn.js.map +0 -1
  120. package/dist/init-hmolV6B4.cjs.map +0 -1
  121. package/dist/jiti-Cd3S0xwr.cjs +0 -16
  122. package/dist/jiti-Cd3S0xwr.cjs.map +0 -1
  123. package/dist/jiti-e08mD2Ph.js +0 -11
  124. package/dist/jiti-e08mD2Ph.js.map +0 -1
  125. package/dist/mcp-ChHFPRzD.cjs.map +0 -1
  126. package/dist/mcp-D2SHEg_d.js.map +0 -1
  127. package/dist/package-C-fC2Eoy.cjs.map +0 -1
  128. package/dist/package-DxH_MEG4.js +0 -6
  129. package/dist/package-DxH_MEG4.js.map +0 -1
  130. package/dist/shell-7HPrTCJ5.cjs.map +0 -1
  131. package/dist/shell-DqqWsHCD.js.map +0 -1
  132. package/dist/telemetry-Cn9X1I5B.cjs.map +0 -1
  133. package/dist/telemetry-DxiR7clS.js.map +0 -1
  134. package/dist/validate--IXRJEhp.js.map +0 -1
  135. package/dist/validate-BK3pc8zv.cjs.map +0 -1
  136. package/dist/validate-Bbrn3Q-A.cjs.map +0 -1
  137. package/dist/validate-l8vLmwKA.js.map +0 -1
  138. package/src/utils/getIntro.ts +0 -1
@@ -1,30 +1,38 @@
1
1
  import "./chunk--u3MIqq1.js";
2
- import { n as toCause, r as toError } from "./errors-6mF_WKxg.js";
3
- import { a as canUseTTY, i as executeIfOnline, o as isGitHubActions, r as sendTelemetry, t as buildTelemetryEvent } from "./telemetry-DxiR7clS.js";
4
- import { n as tokenize } from "./shell-DqqWsHCD.js";
5
- import { t as version } from "./package-DxH_MEG4.js";
6
- import { i as WATCHER_IGNORED_PATHS, r as SUMMARY_SEPARATOR, t as KUBB_NPM_PACKAGE_URL } from "./constants-CM3dJzjK.js";
2
+ import { n as toCause, r as toError } from "./errors-CjPmyZHy.js";
3
+ import { a as canUseTTY, i as executeIfOnline, o as isGitHubActions, r as sendTelemetry, t as buildTelemetryEvent } from "./telemetry-Dis5nWR_.js";
4
+ import { n as tokenize } from "./shell-DLzN4fRo.js";
5
+ import { t as version } from "./package-BRmZkKt7.js";
6
+ import { a as SUMMARY_SEPARATOR, n as KUBB_NPM_PACKAGE_URL, o as WATCHER_IGNORED_PATHS } from "./constants-T_2rsi7T.js";
7
7
  import { styleText } from "node:util";
8
8
  import { EventEmitter } from "node:events";
9
9
  import { createHash } from "node:crypto";
10
- import "node:fs";
10
+ import { spawn } from "node:child_process";
11
+ import { readdirSync } from "node:fs";
11
12
  import { mkdir, readFile, writeFile } from "node:fs/promises";
12
13
  import path, { dirname, relative, resolve } from "node:path";
13
14
  import process$1 from "node:process";
14
15
  import * as clack from "@clack/prompts";
15
- import { PromiseManager, defineLogger, detectFormatter, detectLinter, formatters, getConfigs, isInputPath, linters, logLevel, safeBuild, setup } from "@kubb/core";
16
+ import { createKubb, defineLogger, isInputPath, logLevel } from "@kubb/core";
16
17
  import { NonZeroExitError, x } from "tinyexec";
17
18
  import { Writable } from "node:stream";
18
19
  import { cosmiconfig } from "cosmiconfig";
19
20
  import { createJiti } from "jiti";
20
21
  //#region ../../internals/utils/src/asyncEventEmitter.ts
21
22
  /**
22
- * A typed EventEmitter that awaits all async listeners before resolving.
23
+ * Typed `EventEmitter` that awaits all async listeners before resolving.
23
24
  * Wraps Node's `EventEmitter` with full TypeScript event-map inference.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * const emitter = new AsyncEventEmitter<{ build: [name: string] }>()
29
+ * emitter.on('build', async (name) => { console.log(name) })
30
+ * await emitter.emit('build', 'petstore') // all listeners awaited
31
+ * ```
24
32
  */
25
33
  var AsyncEventEmitter = class {
26
34
  /**
27
- * `maxListener` controls the maximum number of listeners per event before Node emits a memory-leak warning.
35
+ * Maximum number of listeners per event before Node emits a memory-leak warning.
28
36
  * @default 10
29
37
  */
30
38
  constructor(maxListener = 10) {
@@ -32,31 +40,48 @@ var AsyncEventEmitter = class {
32
40
  }
33
41
  #emitter = new EventEmitter();
34
42
  /**
35
- * Emits an event and awaits all registered listeners in parallel.
43
+ * Emits `eventName` and awaits all registered listeners sequentially.
36
44
  * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * await emitter.emit('build', 'petstore')
49
+ * ```
37
50
  */
38
51
  async emit(eventName, ...eventArgs) {
39
52
  const listeners = this.#emitter.listeners(eventName);
40
53
  if (listeners.length === 0) return;
41
- await Promise.all(listeners.map(async (listener) => {
54
+ for (const listener of listeners) try {
55
+ await listener(...eventArgs);
56
+ } catch (err) {
57
+ let serializedArgs;
42
58
  try {
43
- return await listener(...eventArgs);
44
- } catch (err) {
45
- let serializedArgs;
46
- try {
47
- serializedArgs = JSON.stringify(eventArgs);
48
- } catch {
49
- serializedArgs = String(eventArgs);
50
- }
51
- throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
59
+ serializedArgs = JSON.stringify(eventArgs);
60
+ } catch {
61
+ serializedArgs = String(eventArgs);
52
62
  }
53
- }));
63
+ throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
64
+ }
54
65
  }
55
- /** Registers a persistent listener for the given event. */
66
+ /**
67
+ * Registers a persistent listener for `eventName`.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * emitter.on('build', async (name) => { console.log(name) })
72
+ * ```
73
+ */
56
74
  on(eventName, handler) {
57
75
  this.#emitter.on(eventName, handler);
58
76
  }
59
- /** Registers a one-shot listener that removes itself after the first invocation. */
77
+ /**
78
+ * Registers a one-shot listener that removes itself after the first invocation.
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * emitter.onOnce('build', async (name) => { console.log(name) })
83
+ * ```
84
+ */
60
85
  onOnce(eventName, handler) {
61
86
  const wrapper = (...args) => {
62
87
  this.off(eventName, wrapper);
@@ -64,11 +89,37 @@ var AsyncEventEmitter = class {
64
89
  };
65
90
  this.on(eventName, wrapper);
66
91
  }
67
- /** Removes a previously registered listener. */
92
+ /**
93
+ * Removes a previously registered listener.
94
+ *
95
+ * @example
96
+ * ```ts
97
+ * emitter.off('build', handler)
98
+ * ```
99
+ */
68
100
  off(eventName, handler) {
69
101
  this.#emitter.off(eventName, handler);
70
102
  }
71
- /** Removes all listeners from every event channel. */
103
+ /**
104
+ * Returns the number of listeners registered for `eventName`.
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * emitter.on('build', handler)
109
+ * emitter.listenerCount('build') // 1
110
+ * ```
111
+ */
112
+ listenerCount(eventName) {
113
+ return this.#emitter.listenerCount(eventName);
114
+ }
115
+ /**
116
+ * Removes all listeners from every event channel.
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * emitter.removeAll()
121
+ * ```
122
+ */
72
123
  removeAll() {
73
124
  this.#emitter.removeAllListeners();
74
125
  }
@@ -76,8 +127,15 @@ var AsyncEventEmitter = class {
76
127
  //#endregion
77
128
  //#region ../../internals/utils/src/time.ts
78
129
  /**
79
- * Calculates elapsed time in milliseconds from a high-resolution start time.
80
- * Rounds to 2 decimal places to provide sub-millisecond precision without noise.
130
+ * Calculates elapsed time in milliseconds from a high-resolution `process.hrtime` start time.
131
+ * Rounds to 2 decimal places for sub-millisecond precision without noise.
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * const start = process.hrtime()
136
+ * doWork()
137
+ * getElapsedMs(start) // 42.35
138
+ * ```
81
139
  */
82
140
  function getElapsedMs(hrStart) {
83
141
  const [seconds, nanoseconds] = process.hrtime(hrStart);
@@ -85,8 +143,14 @@ function getElapsedMs(hrStart) {
85
143
  return Math.round(ms * 100) / 100;
86
144
  }
87
145
  /**
88
- * Converts a millisecond duration into a human-readable string.
89
- * Adjusts units (ms, s, m s) based on the magnitude of the duration.
146
+ * Converts a millisecond duration into a human-readable string (`ms`, `s`, or `m s`).
147
+ *
148
+ * @example
149
+ * ```ts
150
+ * formatMs(250) // '250ms'
151
+ * formatMs(1500) // '1.50s'
152
+ * formatMs(90000) // '1m 30.0s'
153
+ * ```
90
154
  */
91
155
  function formatMs(ms) {
92
156
  if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
@@ -94,7 +158,14 @@ function formatMs(ms) {
94
158
  return `${Math.round(ms)}ms`;
95
159
  }
96
160
  /**
97
- * Convenience helper: formats the elapsed time since `hrStart` in one step.
161
+ * Formats the elapsed time since `hrStart` as a human-readable string.
162
+ *
163
+ * @example
164
+ * ```ts
165
+ * const start = process.hrtime()
166
+ * doWork()
167
+ * formatHrtime(start) // '1.50s'
168
+ * ```
98
169
  */
99
170
  function formatHrtime(hrStart) {
100
171
  return formatMs(getElapsedMs(hrStart));
@@ -136,7 +207,9 @@ function gradient(colorStops, text) {
136
207
  return `\x1b[38;2;${Math.round(from.r + (to.r - from.r) * lt)};${Math.round(from.g + (to.g - from.g) * lt)};${Math.round(from.b + (to.b - from.b) * lt)}m${char}\x1b[0m`;
137
208
  }).join("");
138
209
  }
139
- /** ANSI color functions for each part of the Kubb mascot illustration. */
210
+ /**
211
+ * ANSI color functions for each part of the Kubb mascot illustration.
212
+ */
140
213
  const palette = {
141
214
  lid: hex("#F55A17"),
142
215
  woodTop: hex("#F5A217"),
@@ -147,7 +220,12 @@ const palette = {
147
220
  blush: hex("#FDA4AF")
148
221
  };
149
222
  /**
150
- * Generates the Kubb mascot welcome banner.
223
+ * Generates the Kubb mascot welcome banner as an ANSI-colored string.
224
+ *
225
+ * @example
226
+ * ```ts
227
+ * console.log(getIntro({ title: 'kubb.config.ts', description: 'generating…', version: '5.0.0', areEyesOpen: true }))
228
+ * ```
151
229
  */
152
230
  function getIntro({ title, description, version, areEyesOpen }) {
153
231
  const kubbVersion = gradient([
@@ -165,7 +243,13 @@ function getIntro({ title, description, version, areEyesOpen }) {
165
243
  ${palette.woodBase("▀▀▀▀▀▀▀▀▀▀▀▀▀")}
166
244
  `;
167
245
  }
168
- /** ANSI color names available for terminal output. */
246
+ /** ANSI color names available for deterministic terminal coloring.
247
+ *
248
+ * @example
249
+ * ```ts
250
+ * const color = randomColors[2] // 'green'
251
+ * ```
252
+ */
169
253
  const randomColors = [
170
254
  "black",
171
255
  "red",
@@ -178,15 +262,27 @@ const randomColors = [
178
262
  "gray"
179
263
  ];
180
264
  /**
181
- * Returns the text wrapped in a deterministic ANSI color derived from the text's SHA-256 hash.
265
+ * Wraps `text` in a deterministic ANSI color derived from the text's SHA-256 hash.
266
+ *
267
+ * @example
268
+ * ```ts
269
+ * randomCliColor('petstore') // '\x1b[33m' + 'petstore' + '\x1b[39m' (always the same color for 'petstore')
270
+ * ```
182
271
  */
183
272
  function randomCliColor(text) {
184
273
  if (!text) return "";
185
274
  return styleText(randomColors[createHash("sha256").update(text).digest().readUInt32BE(0) % randomColors.length] ?? "white", text);
186
275
  }
187
276
  /**
188
- * Formats a millisecond duration with an ANSI color based on thresholds:
189
- * green 500 ms · yellow 1 000 ms · red > 1 000 ms
277
+ * Formats a millisecond duration with a threshold-based ANSI color.
278
+ * `≤ 500 ms` → green · `≤ 1 000 ms` → yellow · `> 1 000 ms` → red.
279
+ *
280
+ * @example
281
+ * ```ts
282
+ * formatMsWithColor(200) // '\x1b[32m200ms\x1b[39m'
283
+ * formatMsWithColor(800) // '\x1b[33m800ms\x1b[39m'
284
+ * formatMsWithColor(1500) // '\x1b[31m1.50s\x1b[39m'
285
+ * ```
190
286
  */
191
287
  function formatMsWithColor(ms) {
192
288
  const formatted = formatMs(ms);
@@ -195,27 +291,96 @@ function formatMsWithColor(ms) {
195
291
  return styleText("red", formatted);
196
292
  }
197
293
  //#endregion
294
+ //#region ../../internals/utils/src/formatters.ts
295
+ /**
296
+ * CLI command descriptors for each supported code formatter.
297
+ *
298
+ * Each entry contains the executable `command`, an `args` factory that maps an
299
+ * output path to the correct argument list, and an `errorMessage` shown when
300
+ * the formatter is not found.
301
+ */
302
+ const formatters = {
303
+ prettier: {
304
+ command: "prettier",
305
+ args: (outputPath) => [
306
+ "--ignore-unknown",
307
+ "--write",
308
+ outputPath
309
+ ],
310
+ errorMessage: "Prettier not found"
311
+ },
312
+ biome: {
313
+ command: "biome",
314
+ args: (outputPath) => [
315
+ "format",
316
+ "--write",
317
+ outputPath
318
+ ],
319
+ errorMessage: "Biome not found"
320
+ },
321
+ oxfmt: {
322
+ command: "oxfmt",
323
+ args: (outputPath) => [outputPath],
324
+ errorMessage: "Oxfmt not found"
325
+ }
326
+ };
327
+ async function isFormatterAvailable(formatter) {
328
+ return new Promise((resolve) => {
329
+ const child = spawn(formatter, ["--version"], { stdio: "ignore" });
330
+ child.on("close", (code) => resolve(code === 0));
331
+ child.on("error", () => resolve(false));
332
+ });
333
+ }
334
+ /**
335
+ * Detects the first available code formatter on the current system.
336
+ *
337
+ * - Checks in preference order: `oxfmt`, `biome`, `prettier`.
338
+ * - Returns `null` when none are found.
339
+ *
340
+ * @example
341
+ * ```ts
342
+ * const formatter = await detectFormatter()
343
+ * if (formatter) {
344
+ * console.log(`Using ${formatter} for formatting`)
345
+ * }
346
+ * ```
347
+ */
348
+ async function detectFormatter() {
349
+ const formatterNames = new Set([
350
+ "oxfmt",
351
+ "biome",
352
+ "prettier"
353
+ ]);
354
+ for (const formatter of formatterNames) if (await isFormatterAvailable(formatter)) return formatter;
355
+ return null;
356
+ }
357
+ //#endregion
198
358
  //#region ../../internals/utils/src/fs.ts
199
359
  /**
200
360
  * Writes `data` to `path`, trimming leading/trailing whitespace before saving.
201
- * Skips the write and returns `undefined` when the trimmed content is empty or
202
- * identical to what is already on disk.
361
+ * Skips the write when the trimmed content is empty or identical to what is already on disk.
203
362
  * Creates any missing parent directories automatically.
204
- * When `sanity` is `true`, re-reads the file after writing and throws if the
205
- * content does not match.
363
+ * When `sanity` is `true`, re-reads the file after writing and throws if the content does not match.
364
+ *
365
+ * @example
366
+ * ```ts
367
+ * await write('./src/Pet.ts', source) // writes and returns trimmed content
368
+ * await write('./src/Pet.ts', source) // null — file unchanged
369
+ * await write('./src/Pet.ts', ' ') // null — empty content skipped
370
+ * ```
206
371
  */
207
372
  async function write(path, data, options = {}) {
208
373
  const trimmed = data.trim();
209
- if (trimmed === "") return void 0;
374
+ if (trimmed === "") return null;
210
375
  const resolved = resolve(path);
211
376
  if (typeof Bun !== "undefined") {
212
377
  const file = Bun.file(resolved);
213
- if ((await file.exists() ? await file.text() : null) === trimmed) return void 0;
378
+ if ((await file.exists() ? await file.text() : null) === trimmed) return null;
214
379
  await Bun.write(resolved, trimmed);
215
380
  return trimmed;
216
381
  }
217
382
  try {
218
- if (await readFile(resolved, { encoding: "utf-8" }) === trimmed) return void 0;
383
+ if (await readFile(resolved, { encoding: "utf-8" }) === trimmed) return null;
219
384
  } catch {}
220
385
  await mkdir(dirname(resolved), { recursive: true });
221
386
  await writeFile(resolved, trimmed, { encoding: "utf-8" });
@@ -227,6 +392,83 @@ async function write(path, data, options = {}) {
227
392
  return trimmed;
228
393
  }
229
394
  //#endregion
395
+ //#region ../../internals/utils/src/linters.ts
396
+ /**
397
+ * Collects all files under `dir` recursively using Node's built-in fs APIs.
398
+ *
399
+ * Passing explicit file paths to oxlint (instead of a directory) bypasses
400
+ * oxlint's `.gitignore`-aware directory traversal, which would otherwise skip
401
+ * files that are listed in `.gitignore` (e.g. generated output directories).
402
+ */
403
+ function findLintableFiles(dir) {
404
+ try {
405
+ return readdirSync(dir, {
406
+ withFileTypes: true,
407
+ recursive: true
408
+ }).filter((d) => d.isFile()).map((d) => `${d.parentPath}/${d.name}`);
409
+ } catch {
410
+ return [];
411
+ }
412
+ }
413
+ /**
414
+ * CLI command descriptors for each supported linter.
415
+ *
416
+ * Each entry contains the executable `command`, an `args` factory that maps an
417
+ * output path to the correct argument list, and an `errorMessage` shown when
418
+ * the linter is not found.
419
+ */
420
+ const linters = {
421
+ eslint: {
422
+ command: "eslint",
423
+ args: (outputPath) => [outputPath, "--fix"],
424
+ errorMessage: "Eslint not found"
425
+ },
426
+ biome: {
427
+ command: "biome",
428
+ args: (outputPath) => [
429
+ "lint",
430
+ "--fix",
431
+ outputPath
432
+ ],
433
+ errorMessage: "Biome not found"
434
+ },
435
+ oxlint: {
436
+ command: "oxlint",
437
+ args: (outputPath) => ["--fix", ...findLintableFiles(outputPath)],
438
+ errorMessage: "Oxlint not found"
439
+ }
440
+ };
441
+ async function isLinterAvailable(linter) {
442
+ return new Promise((resolve) => {
443
+ const child = spawn(linter, ["--version"], { stdio: "ignore" });
444
+ child.on("close", (code) => resolve(code === 0));
445
+ child.on("error", () => resolve(false));
446
+ });
447
+ }
448
+ /**
449
+ * Detects the first available linter on the current system.
450
+ *
451
+ * - Checks in preference order: `oxlint`, `biome`, `eslint`.
452
+ * - Returns `null` when none are found.
453
+ *
454
+ * @example
455
+ * ```ts
456
+ * const linter = await detectLinter()
457
+ * if (linter) {
458
+ * console.log(`Using ${linter} for linting`)
459
+ * }
460
+ * ```
461
+ */
462
+ async function detectLinter() {
463
+ const linterNames = new Set([
464
+ "oxlint",
465
+ "biome",
466
+ "eslint"
467
+ ]);
468
+ for (const linter of linterNames) if (await isLinterAvailable(linter)) return linter;
469
+ return null;
470
+ }
471
+ //#endregion
230
472
  //#region src/utils/getSummary.ts
231
473
  function getSummary({ failedPlugins, filesCreated, status, hrStart, config, pluginTimings }) {
232
474
  const duration = formatHrtime(hrStart);
@@ -237,7 +479,7 @@ function getSummary({ failedPlugins, filesCreated, status, hrStart, config, plug
237
479
  pluginsFailed: status === "failed" ? [...failedPlugins].map(({ plugin }) => randomCliColor(plugin.name)).join(", ") : void 0,
238
480
  filesCreated,
239
481
  time: styleText("green", duration),
240
- output: path.isAbsolute(config.root) ? path.resolve(config.root, config.output.path) : config.root
482
+ output: path.resolve(config.root, config.output.path)
241
483
  };
242
484
  const labels = {
243
485
  plugins: "Plugins:",
@@ -279,11 +521,11 @@ async function runHook({ id, command, args, commandWithArgs, context, stream = f
279
521
  });
280
522
  if (stream && sink?.onLine) for await (const line of proc) sink.onLine(line);
281
523
  const result = await proc;
282
- await context.emit("debug", {
524
+ await context.emit("kubb:debug", {
283
525
  date: /* @__PURE__ */ new Date(),
284
526
  logs: [result.stdout.trimEnd()]
285
527
  });
286
- await context.emit("hook:end", {
528
+ await context.emit("kubb:hook:end", {
287
529
  command,
288
530
  args,
289
531
  id,
@@ -292,33 +534,33 @@ async function runHook({ id, command, args, commandWithArgs, context, stream = f
292
534
  });
293
535
  } catch (err) {
294
536
  if (!(err instanceof NonZeroExitError)) {
295
- await context.emit("hook:end", {
537
+ await context.emit("kubb:hook:end", {
296
538
  command,
297
539
  args,
298
540
  id,
299
541
  success: false,
300
542
  error: toError(err)
301
543
  });
302
- await context.emit("error", toError(err));
544
+ await context.emit("kubb:error", toError(err));
303
545
  return;
304
546
  }
305
547
  const stderr = err.output?.stderr ?? "";
306
548
  const stdout = err.output?.stdout ?? "";
307
- await context.emit("debug", {
549
+ await context.emit("kubb:debug", {
308
550
  date: /* @__PURE__ */ new Date(),
309
551
  logs: [stdout, stderr].filter(Boolean)
310
552
  });
311
553
  if (stderr) sink?.onStderr?.(stderr);
312
554
  if (stdout) sink?.onStdout?.(stdout);
313
555
  const errorMessage = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
314
- await context.emit("hook:end", {
556
+ await context.emit("kubb:hook:end", {
315
557
  command,
316
558
  args,
317
559
  id,
318
560
  success: false,
319
561
  error: errorMessage
320
562
  });
321
- await context.emit("error", errorMessage);
563
+ await context.emit("kubb:error", errorMessage);
322
564
  }
323
565
  }
324
566
  //#endregion
@@ -386,7 +628,7 @@ const clackLogger = defineLogger({
386
628
  state.spinner.stop(text);
387
629
  state.isSpinning = false;
388
630
  }
389
- context.on("info", (message, info = "") => {
631
+ context.on("kubb:info", (message, info = "") => {
390
632
  if (logLevel$8 <= logLevel.silent) return;
391
633
  const text = getMessage([
392
634
  styleText("blue", "ℹ"),
@@ -396,7 +638,7 @@ const clackLogger = defineLogger({
396
638
  if (state.isSpinning) state.spinner.message(text);
397
639
  else clack.log.info(text);
398
640
  });
399
- context.on("success", (message, info = "") => {
641
+ context.on("kubb:success", (message, info = "") => {
400
642
  if (logLevel$8 <= logLevel.silent) return;
401
643
  const text = getMessage([
402
644
  styleText("blue", "✓"),
@@ -406,7 +648,7 @@ const clackLogger = defineLogger({
406
648
  if (state.isSpinning) stopSpinner(text);
407
649
  else clack.log.success(text);
408
650
  });
409
- context.on("warn", (message, info) => {
651
+ context.on("kubb:warn", (message, info) => {
410
652
  if (logLevel$8 < logLevel.warn) return;
411
653
  const text = getMessage([
412
654
  styleText("yellow", "⚠"),
@@ -415,7 +657,7 @@ const clackLogger = defineLogger({
415
657
  ].filter(Boolean).join(" "));
416
658
  clack.log.warn(text);
417
659
  });
418
- context.on("error", (error) => {
660
+ context.on("kubb:error", (error) => {
419
661
  const caused = toCause(error);
420
662
  const text = [styleText("red", "✗"), error.message].join(" ");
421
663
  if (state.isSpinning) stopSpinner(getMessage(text));
@@ -430,19 +672,24 @@ const clackLogger = defineLogger({
430
672
  }
431
673
  }
432
674
  });
433
- context.on("version:new", (version, latestVersion) => {
675
+ context.on("kubb:version:new", (version, latestVersion) => {
434
676
  if (logLevel$8 <= logLevel.silent) return;
435
- clack.box(`\`v${version}\` → \`v${latestVersion}\`
677
+ try {
678
+ clack.box(`\`v${version}\` → \`v${latestVersion}\`
436
679
  Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
437
- width: "auto",
438
- formatBorder: (s) => styleText("yellow", s),
439
- rounded: true,
440
- withGuide: false,
441
- contentAlign: "center",
442
- titleAlign: "center"
443
- });
680
+ width: "auto",
681
+ formatBorder: (s) => styleText("yellow", s),
682
+ rounded: true,
683
+ withGuide: false,
684
+ contentAlign: "center",
685
+ titleAlign: "center"
686
+ });
687
+ } catch {
688
+ console.log(`Update available for Kubb: v${version} → v${latestVersion}`);
689
+ console.log("Run `npm install -g @kubb/cli` to update");
690
+ }
444
691
  });
445
- context.on("lifecycle:start", async (version) => {
692
+ context.on("kubb:lifecycle:start", async (version) => {
446
693
  console.log(`\n${getIntro({
447
694
  title: "The ultimate toolkit for working with APIs",
448
695
  description: "Ready to start",
@@ -451,24 +698,24 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
451
698
  })}\n`);
452
699
  reset();
453
700
  });
454
- context.on("config:start", () => {
701
+ context.on("kubb:config:start", () => {
455
702
  if (logLevel$8 <= logLevel.silent) return;
456
703
  const text = getMessage("Configuration started");
457
704
  clack.intro(text);
458
705
  startSpinner(getMessage("Configuration loading"));
459
706
  });
460
- context.on("config:end", (_configs) => {
707
+ context.on("kubb:config:end", (_configs) => {
461
708
  if (logLevel$8 <= logLevel.silent) return;
462
709
  const text = getMessage("Configuration completed");
463
710
  clack.outro(text);
464
711
  });
465
- context.on("generation:start", (config) => {
712
+ context.on("kubb:generation:start", (config) => {
466
713
  reset();
467
714
  state.totalPlugins = config.plugins?.length ?? 0;
468
715
  const text = getMessage(["Generation started", config.name ? `for ${styleText("dim", config.name)}` : void 0].filter(Boolean).join(" "));
469
716
  clack.intro(text);
470
717
  });
471
- context.on("plugin:start", (plugin) => {
718
+ context.on("kubb:plugin:start", (plugin) => {
472
719
  if (logLevel$8 <= logLevel.silent) return;
473
720
  stopSpinner();
474
721
  const progressBar = clack.progress({
@@ -486,7 +733,7 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
486
733
  interval
487
734
  });
488
735
  });
489
- context.on("plugin:end", (plugin, { duration, success }) => {
736
+ context.on("kubb:plugin:end", (plugin, { duration, success }) => {
490
737
  stopSpinner();
491
738
  const active = state.activeProgress.get(plugin.name);
492
739
  if (!active || logLevel$8 === logLevel.silent) return;
@@ -499,7 +746,7 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
499
746
  state.activeProgress.delete(plugin.name);
500
747
  showProgressStep();
501
748
  });
502
- context.on("files:processing:start", (files) => {
749
+ context.on("kubb:files:processing:start", (files) => {
503
750
  if (logLevel$8 <= logLevel.silent) return;
504
751
  stopSpinner();
505
752
  state.totalFiles = files.length;
@@ -510,11 +757,11 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
510
757
  max: files.length,
511
758
  size: 30
512
759
  });
513
- context.emit("info", text);
760
+ context.emit("kubb:info", text);
514
761
  progressBar.start(getMessage(text));
515
762
  state.activeProgress.set("files", { progressBar });
516
763
  });
517
- context.on("file:processing:update", ({ file, config }) => {
764
+ context.on("kubb:file:processing:update", ({ file, config }) => {
518
765
  if (logLevel$8 <= logLevel.silent) return;
519
766
  stopSpinner();
520
767
  state.processedFiles++;
@@ -523,7 +770,7 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
523
770
  if (!active) return;
524
771
  active.progressBar.advance(void 0, text);
525
772
  });
526
- context.on("files:processing:end", () => {
773
+ context.on("kubb:files:processing:end", () => {
527
774
  if (logLevel$8 <= logLevel.silent) return;
528
775
  stopSpinner();
529
776
  const text = getMessage("Files written successfully");
@@ -533,31 +780,31 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
533
780
  state.activeProgress.delete("files");
534
781
  showProgressStep();
535
782
  });
536
- context.on("generation:end", (config) => {
783
+ context.on("kubb:generation:end", (config) => {
537
784
  const text = getMessage(config.name ? `Generation completed for ${styleText("dim", config.name)}` : "Generation completed");
538
785
  clack.outro(text);
539
786
  });
540
- context.on("format:start", () => {
787
+ context.on("kubb:format:start", () => {
541
788
  if (logLevel$8 <= logLevel.silent) return;
542
789
  const text = getMessage("Format started");
543
790
  clack.intro(text);
544
791
  });
545
- context.on("format:end", () => {
792
+ context.on("kubb:format:end", () => {
546
793
  if (logLevel$8 <= logLevel.silent) return;
547
794
  const text = getMessage("Format completed");
548
795
  clack.outro(text);
549
796
  });
550
- context.on("lint:start", () => {
797
+ context.on("kubb:lint:start", () => {
551
798
  if (logLevel$8 <= logLevel.silent) return;
552
799
  const text = getMessage("Lint started");
553
800
  clack.intro(text);
554
801
  });
555
- context.on("lint:end", () => {
802
+ context.on("kubb:lint:end", () => {
556
803
  if (logLevel$8 <= logLevel.silent) return;
557
804
  const text = getMessage("Lint completed");
558
805
  clack.outro(text);
559
806
  });
560
- context.on("hook:start", async ({ id, command, args }) => {
807
+ context.on("kubb:hook:start", async ({ id, command, args }) => {
561
808
  const commandWithArgs = formatCommandWithArgs(command, args);
562
809
  const text = getMessage(`Hook ${styleText("dim", commandWithArgs)} started`);
563
810
  if (!id) return;
@@ -592,12 +839,12 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
592
839
  }
593
840
  });
594
841
  });
595
- context.on("hook:end", ({ command, args }) => {
842
+ context.on("kubb:hook:end", ({ command, args }) => {
596
843
  if (logLevel$8 <= logLevel.silent) return;
597
844
  const text = getMessage(`Hook ${styleText("dim", formatCommandWithArgs(command, args))} successfully executed`);
598
845
  clack.outro(text);
599
846
  });
600
- context.on("generation:summary", (config, { pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
847
+ context.on("kubb:generation:summary", (config, { pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
601
848
  const summary = getSummary({
602
849
  failedPlugins,
603
850
  filesCreated,
@@ -610,16 +857,20 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
610
857
  summary.unshift("\n");
611
858
  summary.push("\n");
612
859
  const borderColor = status === "success" ? "green" : "red";
613
- clack.box(summary.join("\n"), getMessage(title), {
614
- width: "auto",
615
- formatBorder: (s) => styleText(borderColor, s),
616
- rounded: true,
617
- withGuide: false,
618
- contentAlign: "left",
619
- titleAlign: "center"
620
- });
860
+ try {
861
+ clack.box(summary.join("\n"), getMessage(title), {
862
+ width: "auto",
863
+ formatBorder: (s) => styleText(borderColor, s),
864
+ rounded: true,
865
+ withGuide: false,
866
+ contentAlign: "left",
867
+ titleAlign: "center"
868
+ });
869
+ } catch {
870
+ console.log(summary.join("\n"));
871
+ }
621
872
  });
622
- context.on("lifecycle:end", () => {
873
+ context.on("kubb:lifecycle:end", () => {
623
874
  reset();
624
875
  });
625
876
  }
@@ -660,63 +911,63 @@ const fileSystemLogger = defineLogger({
660
911
  files[pathName].push(`[${timestamp}]\n${log.logs.join("\n")}`);
661
912
  }
662
913
  }
663
- await Promise.all(Object.entries(files).map(([fileName, logs]) => write(fileName, logs.join("\n\n"))));
914
+ for (const [fileName, logs] of Object.entries(files)) await write(fileName, logs.join("\n\n"));
664
915
  return Object.keys(files);
665
916
  }
666
- context.on("info", (message, info) => {
917
+ context.on("kubb:info", (message, info) => {
667
918
  state.cachedLogs.add({
668
919
  date: /* @__PURE__ */ new Date(),
669
920
  logs: [`ℹ ${message} ${info}`]
670
921
  });
671
922
  });
672
- context.on("success", (message, info) => {
923
+ context.on("kubb:success", (message, info) => {
673
924
  state.cachedLogs.add({
674
925
  date: /* @__PURE__ */ new Date(),
675
926
  logs: [`✓ ${message} ${info}`]
676
927
  });
677
928
  });
678
- context.on("warn", (message, info) => {
929
+ context.on("kubb:warn", (message, info) => {
679
930
  state.cachedLogs.add({
680
931
  date: /* @__PURE__ */ new Date(),
681
932
  logs: [`⚠ ${message} ${info}`]
682
933
  });
683
934
  });
684
- context.on("error", (error) => {
935
+ context.on("kubb:error", (error) => {
685
936
  state.cachedLogs.add({
686
937
  date: /* @__PURE__ */ new Date(),
687
938
  logs: [`✗ ${error.message}`, error.stack || "unknown stack"]
688
939
  });
689
940
  });
690
- context.on("debug", (message) => {
941
+ context.on("kubb:debug", (message) => {
691
942
  state.cachedLogs.add({
692
943
  date: /* @__PURE__ */ new Date(),
693
944
  logs: message.logs
694
945
  });
695
946
  });
696
- context.on("plugin:start", (plugin) => {
947
+ context.on("kubb:plugin:start", (plugin) => {
697
948
  state.cachedLogs.add({
698
949
  date: /* @__PURE__ */ new Date(),
699
950
  logs: [`Generating ${plugin.name}`]
700
951
  });
701
952
  });
702
- context.on("plugin:end", (plugin, { duration, success }) => {
953
+ context.on("kubb:plugin:end", (plugin, { duration, success }) => {
703
954
  const durationStr = formatMs(duration);
704
955
  state.cachedLogs.add({
705
956
  date: /* @__PURE__ */ new Date(),
706
957
  logs: [success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`]
707
958
  });
708
959
  });
709
- context.on("files:processing:start", (files) => {
960
+ context.on("kubb:files:processing:start", (files) => {
710
961
  state.cachedLogs.add({
711
962
  date: /* @__PURE__ */ new Date(),
712
963
  logs: [`Start ${files.length} writing:`, ...files.map((file) => file.path)]
713
964
  });
714
965
  });
715
- context.on("generation:end", async (config) => {
966
+ context.on("kubb:generation:end", async (config) => {
716
967
  const writtenFilePaths = await writeLogs(config.name);
717
968
  if (writtenFilePaths.length > 0) {
718
969
  const files = writtenFilePaths.map((f) => relative(process$1.cwd(), f));
719
- await context.emit("info", "Debug files written to:", files.join(", "));
970
+ await context.emit("kubb:info", "Debug files written to:", files.join(", "));
720
971
  }
721
972
  reset();
722
973
  });
@@ -770,7 +1021,7 @@ const githubActionsLogger = defineLogger({
770
1021
  function closeGroup(_name) {
771
1022
  console.log("::endgroup::");
772
1023
  }
773
- context.on("info", (message, info = "") => {
1024
+ context.on("kubb:info", (message, info = "") => {
774
1025
  if (logLevel$7 <= logLevel.silent) return;
775
1026
  const text = getMessage([
776
1027
  styleText("blue", "ℹ"),
@@ -779,7 +1030,7 @@ const githubActionsLogger = defineLogger({
779
1030
  ].join(" "));
780
1031
  console.log(text);
781
1032
  });
782
- context.on("success", (message, info = "") => {
1033
+ context.on("kubb:success", (message, info = "") => {
783
1034
  if (logLevel$7 <= logLevel.silent) return;
784
1035
  const text = getMessage([
785
1036
  styleText("blue", "✓"),
@@ -788,7 +1039,7 @@ const githubActionsLogger = defineLogger({
788
1039
  ].filter(Boolean).join(" "));
789
1040
  console.log(text);
790
1041
  });
791
- context.on("warn", (message, info = "") => {
1042
+ context.on("kubb:warn", (message, info = "") => {
792
1043
  if (logLevel$7 <= logLevel.silent) return;
793
1044
  const text = getMessage([
794
1045
  styleText("yellow", "⚠"),
@@ -797,7 +1048,7 @@ const githubActionsLogger = defineLogger({
797
1048
  ].filter(Boolean).join(" "));
798
1049
  console.warn(`::warning::${text}`);
799
1050
  });
800
- context.on("error", (error) => {
1051
+ context.on("kubb:error", (error) => {
801
1052
  const caused = toCause(error);
802
1053
  if (logLevel$7 <= logLevel.silent) return;
803
1054
  const message = error.message || String(error);
@@ -812,37 +1063,37 @@ const githubActionsLogger = defineLogger({
812
1063
  }
813
1064
  }
814
1065
  });
815
- context.on("lifecycle:start", (version) => {
1066
+ context.on("kubb:lifecycle:start", (version) => {
816
1067
  console.log(styleText("yellow", `Kubb ${version} 🧩`));
817
1068
  reset();
818
1069
  });
819
- context.on("config:start", () => {
1070
+ context.on("kubb:config:start", () => {
820
1071
  if (logLevel$7 <= logLevel.silent) return;
821
1072
  const text = getMessage("Configuration started");
822
1073
  openGroup("Configuration");
823
1074
  console.log(text);
824
1075
  });
825
- context.on("config:end", (configs) => {
1076
+ context.on("kubb:config:end", (configs) => {
826
1077
  state.currentConfigs = configs;
827
1078
  if (logLevel$7 <= logLevel.silent) return;
828
1079
  const text = getMessage("Configuration completed");
829
1080
  console.log(text);
830
1081
  closeGroup("Configuration");
831
1082
  });
832
- context.on("generation:start", (config) => {
1083
+ context.on("kubb:generation:start", (config) => {
833
1084
  reset();
834
1085
  state.totalPlugins = config.plugins?.length ?? 0;
835
1086
  const text = config.name ? `Generation for ${styleText("bold", config.name)}` : "Generation";
836
1087
  if (state.currentConfigs.length > 1) openGroup(text);
837
1088
  if (state.currentConfigs.length === 1) console.log(getMessage(text));
838
1089
  });
839
- context.on("plugin:start", (plugin) => {
1090
+ context.on("kubb:plugin:start", (plugin) => {
840
1091
  if (logLevel$7 <= logLevel.silent) return;
841
1092
  const text = getMessage(`Generating ${styleText("bold", plugin.name)}`);
842
1093
  if (state.currentConfigs.length === 1) openGroup(`Plugin: ${plugin.name}`);
843
1094
  console.log(text);
844
1095
  });
845
- context.on("plugin:end", (plugin, { duration, success }) => {
1096
+ context.on("kubb:plugin:end", (plugin, { duration, success }) => {
846
1097
  if (logLevel$7 <= logLevel.silent) return;
847
1098
  if (success) state.completedPlugins++;
848
1099
  else state.failedPlugins++;
@@ -853,7 +1104,7 @@ const githubActionsLogger = defineLogger({
853
1104
  if (state.currentConfigs.length === 1) closeGroup(`Plugin: ${plugin.name}`);
854
1105
  showProgressStep();
855
1106
  });
856
- context.on("files:processing:start", (files) => {
1107
+ context.on("kubb:files:processing:start", (files) => {
857
1108
  if (logLevel$7 <= logLevel.silent) return;
858
1109
  state.totalFiles = files.length;
859
1110
  state.processedFiles = 0;
@@ -861,46 +1112,46 @@ const githubActionsLogger = defineLogger({
861
1112
  const text = getMessage(`Writing ${files.length} files`);
862
1113
  console.log(text);
863
1114
  });
864
- context.on("files:processing:end", () => {
1115
+ context.on("kubb:files:processing:end", () => {
865
1116
  if (logLevel$7 <= logLevel.silent) return;
866
1117
  const text = getMessage("Files written successfully");
867
1118
  console.log(text);
868
1119
  if (state.currentConfigs.length === 1) closeGroup("File Generation");
869
1120
  showProgressStep();
870
1121
  });
871
- context.on("file:processing:update", () => {
1122
+ context.on("kubb:file:processing:update", () => {
872
1123
  if (logLevel$7 <= logLevel.silent) return;
873
1124
  state.processedFiles++;
874
1125
  });
875
- context.on("generation:end", (config) => {
1126
+ context.on("kubb:generation:end", (config) => {
876
1127
  const text = getMessage(config.name ? `${styleText("blue", "✓")} Generation completed for ${styleText("dim", config.name)}` : `${styleText("blue", "✓")} Generation completed`);
877
1128
  console.log(text);
878
1129
  });
879
- context.on("format:start", () => {
1130
+ context.on("kubb:format:start", () => {
880
1131
  if (logLevel$7 <= logLevel.silent) return;
881
1132
  const text = getMessage("Format started");
882
1133
  if (state.currentConfigs.length === 1) openGroup("Formatting");
883
1134
  console.log(text);
884
1135
  });
885
- context.on("format:end", () => {
1136
+ context.on("kubb:format:end", () => {
886
1137
  if (logLevel$7 <= logLevel.silent) return;
887
1138
  const text = getMessage("Format completed");
888
1139
  console.log(text);
889
1140
  if (state.currentConfigs.length === 1) closeGroup("Formatting");
890
1141
  });
891
- context.on("lint:start", () => {
1142
+ context.on("kubb:lint:start", () => {
892
1143
  if (logLevel$7 <= logLevel.silent) return;
893
1144
  const text = getMessage("Lint started");
894
1145
  if (state.currentConfigs.length === 1) openGroup("Linting");
895
1146
  console.log(text);
896
1147
  });
897
- context.on("lint:end", () => {
1148
+ context.on("kubb:lint:end", () => {
898
1149
  if (logLevel$7 <= logLevel.silent) return;
899
1150
  const text = getMessage("Lint completed");
900
1151
  console.log(text);
901
1152
  if (state.currentConfigs.length === 1) closeGroup("Linting");
902
1153
  });
903
- context.on("hook:start", async ({ id, command, args }) => {
1154
+ context.on("kubb:hook:start", async ({ id, command, args }) => {
904
1155
  const commandWithArgs = formatCommandWithArgs(command, args);
905
1156
  const text = getMessage(`Hook ${styleText("dim", commandWithArgs)} started`);
906
1157
  if (logLevel$7 > logLevel.silent) {
@@ -920,14 +1171,14 @@ const githubActionsLogger = defineLogger({
920
1171
  }
921
1172
  });
922
1173
  });
923
- context.on("hook:end", ({ command, args }) => {
1174
+ context.on("kubb:hook:end", ({ command, args }) => {
924
1175
  if (logLevel$7 <= logLevel.silent) return;
925
1176
  const commandWithArgs = formatCommandWithArgs(command, args);
926
1177
  const text = getMessage(`Hook ${styleText("dim", commandWithArgs)} completed`);
927
1178
  console.log(text);
928
1179
  if (state.currentConfigs.length === 1) closeGroup(`Hook ${commandWithArgs}`);
929
1180
  });
930
- context.on("generation:summary", (config, { status, hrStart, failedPlugins }) => {
1181
+ context.on("kubb:generation:summary", (config, { status, hrStart, failedPlugins }) => {
931
1182
  const pluginsCount = config.plugins?.length ?? 0;
932
1183
  const successCount = pluginsCount - failedPlugins.size;
933
1184
  const duration = formatHrtime(hrStart);
@@ -935,7 +1186,7 @@ const githubActionsLogger = defineLogger({
935
1186
  console.log(status === "success" ? `Kubb Summary: ${styleText("blue", "✓")} ${`${successCount} successful`}, ${pluginsCount} total, ${styleText("green", duration)}` : `Kubb Summary: ${styleText("blue", "✓")} ${`${successCount} successful`}, ✗ ${`${failedPlugins.size} failed`}, ${pluginsCount} total, ${styleText("green", duration)}`);
936
1187
  if (state.currentConfigs.length > 1) closeGroup(config.name ? `Generation for ${styleText("bold", config.name)}` : "Generation");
937
1188
  });
938
- context.on("lifecycle:end", () => {
1189
+ context.on("kubb:lifecycle:end", () => {
939
1190
  reset();
940
1191
  });
941
1192
  }
@@ -953,7 +1204,7 @@ const plainLogger = defineLogger({
953
1204
  function getMessage(message) {
954
1205
  return formatMessage(message, logLevel$6);
955
1206
  }
956
- context.on("info", (message, info) => {
1207
+ context.on("kubb:info", (message, info) => {
957
1208
  if (logLevel$6 <= logLevel.silent) return;
958
1209
  const text = getMessage([
959
1210
  "ℹ",
@@ -962,7 +1213,7 @@ const plainLogger = defineLogger({
962
1213
  ].join(" "));
963
1214
  console.log(text);
964
1215
  });
965
- context.on("success", (message, info = "") => {
1216
+ context.on("kubb:success", (message, info = "") => {
966
1217
  if (logLevel$6 <= logLevel.silent) return;
967
1218
  const text = getMessage([
968
1219
  "✓",
@@ -971,7 +1222,7 @@ const plainLogger = defineLogger({
971
1222
  ].filter(Boolean).join(" "));
972
1223
  console.log(text);
973
1224
  });
974
- context.on("warn", (message, info) => {
1225
+ context.on("kubb:warn", (message, info) => {
975
1226
  if (logLevel$6 < logLevel.warn) return;
976
1227
  const text = getMessage([
977
1228
  "⚠",
@@ -980,7 +1231,7 @@ const plainLogger = defineLogger({
980
1231
  ].filter(Boolean).join(" "));
981
1232
  console.log(text);
982
1233
  });
983
- context.on("error", (error) => {
1234
+ context.on("kubb:error", (error) => {
984
1235
  const caused = toCause(error);
985
1236
  const text = getMessage(["✗", error.message].join(" "));
986
1237
  console.log(text);
@@ -994,74 +1245,74 @@ const plainLogger = defineLogger({
994
1245
  }
995
1246
  }
996
1247
  });
997
- context.on("lifecycle:start", () => {
1248
+ context.on("kubb:lifecycle:start", () => {
998
1249
  console.log("Kubb CLI 🧩");
999
1250
  });
1000
- context.on("config:start", () => {
1251
+ context.on("kubb:config:start", () => {
1001
1252
  if (logLevel$6 <= logLevel.silent) return;
1002
1253
  const text = getMessage("Configuration started");
1003
1254
  console.log(text);
1004
1255
  });
1005
- context.on("config:end", () => {
1256
+ context.on("kubb:config:end", () => {
1006
1257
  if (logLevel$6 <= logLevel.silent) return;
1007
1258
  const text = getMessage("Configuration completed");
1008
1259
  console.log(text);
1009
1260
  });
1010
- context.on("generation:start", () => {
1261
+ context.on("kubb:generation:start", () => {
1011
1262
  const text = getMessage("Generation started");
1012
1263
  console.log(text);
1013
1264
  });
1014
- context.on("plugin:start", (plugin) => {
1265
+ context.on("kubb:plugin:start", (plugin) => {
1015
1266
  if (logLevel$6 <= logLevel.silent) return;
1016
1267
  const text = getMessage(`Generating ${plugin.name}`);
1017
1268
  console.log(text);
1018
1269
  });
1019
- context.on("plugin:end", (plugin, { duration, success }) => {
1270
+ context.on("kubb:plugin:end", (plugin, { duration, success }) => {
1020
1271
  if (logLevel$6 <= logLevel.silent) return;
1021
1272
  const durationStr = formatMs(duration);
1022
1273
  const text = getMessage(success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`);
1023
1274
  console.log(text);
1024
1275
  });
1025
- context.on("files:processing:start", (files) => {
1276
+ context.on("kubb:files:processing:start", (files) => {
1026
1277
  if (logLevel$6 <= logLevel.silent) return;
1027
1278
  const text = getMessage(`Writing ${files.length} files`);
1028
1279
  console.log(text);
1029
1280
  });
1030
- context.on("file:processing:update", ({ file, config }) => {
1281
+ context.on("kubb:file:processing:update", ({ file, config }) => {
1031
1282
  if (logLevel$6 <= logLevel.silent) return;
1032
1283
  const text = getMessage(`Writing ${relative(config.root, file.path)}`);
1033
1284
  console.log(text);
1034
1285
  });
1035
- context.on("files:processing:end", () => {
1286
+ context.on("kubb:files:processing:end", () => {
1036
1287
  if (logLevel$6 <= logLevel.silent) return;
1037
1288
  const text = getMessage("Files written successfully");
1038
1289
  console.log(text);
1039
1290
  });
1040
- context.on("generation:end", (config) => {
1291
+ context.on("kubb:generation:end", (config) => {
1041
1292
  const text = getMessage(config.name ? `Generation completed for ${config.name}` : "Generation completed");
1042
1293
  console.log(text);
1043
1294
  });
1044
- context.on("format:start", () => {
1295
+ context.on("kubb:format:start", () => {
1045
1296
  if (logLevel$6 <= logLevel.silent) return;
1046
1297
  const text = getMessage("Format started");
1047
1298
  console.log(text);
1048
1299
  });
1049
- context.on("format:end", () => {
1300
+ context.on("kubb:format:end", () => {
1050
1301
  if (logLevel$6 <= logLevel.silent) return;
1051
1302
  const text = getMessage("Format completed");
1052
1303
  console.log(text);
1053
1304
  });
1054
- context.on("lint:start", () => {
1305
+ context.on("kubb:lint:start", () => {
1055
1306
  if (logLevel$6 <= logLevel.silent) return;
1056
1307
  const text = getMessage("Lint started");
1057
1308
  console.log(text);
1058
1309
  });
1059
- context.on("lint:end", () => {
1310
+ context.on("kubb:lint:end", () => {
1060
1311
  if (logLevel$6 <= logLevel.silent) return;
1061
1312
  const text = getMessage("Lint completed");
1062
1313
  console.log(text);
1063
1314
  });
1064
- context.on("hook:start", async ({ id, command, args }) => {
1315
+ context.on("kubb:hook:start", async ({ id, command, args }) => {
1065
1316
  const commandWithArgs = formatCommandWithArgs(command, args);
1066
1317
  const text = getMessage(`Hook ${commandWithArgs} started`);
1067
1318
  if (logLevel$6 > logLevel.silent) console.log(text);
@@ -1078,12 +1329,12 @@ const plainLogger = defineLogger({
1078
1329
  }
1079
1330
  });
1080
1331
  });
1081
- context.on("hook:end", ({ command, args }) => {
1332
+ context.on("kubb:hook:end", ({ command, args }) => {
1082
1333
  if (logLevel$6 <= logLevel.silent) return;
1083
1334
  const text = getMessage(`Hook ${formatCommandWithArgs(command, args)} completed`);
1084
1335
  console.log(text);
1085
1336
  });
1086
- context.on("generation:summary", (config, { pluginTimings, status, hrStart, failedPlugins, filesCreated }) => {
1337
+ context.on("kubb:generation:summary", (config, { pluginTimings, status, hrStart, failedPlugins, filesCreated }) => {
1087
1338
  const summary = getSummary({
1088
1339
  failedPlugins,
1089
1340
  filesCreated,
@@ -1156,8 +1407,8 @@ async function setupLogger(context, { logLevel: logLevel$5 }) {
1156
1407
  }
1157
1408
  //#endregion
1158
1409
  //#region src/utils/executeHooks.ts
1159
- async function executeHooks({ hooks, events }) {
1160
- const commands = Array.isArray(hooks.done) ? hooks.done : [hooks.done].filter(Boolean);
1410
+ async function executeHooks({ configHooks, hooks }) {
1411
+ const commands = Array.isArray(configHooks.done) ? configHooks.done : [configHooks.done].filter(Boolean);
1161
1412
  for (const command of commands) {
1162
1413
  const [cmd, ...args] = tokenize(command);
1163
1414
  if (!cmd) continue;
@@ -1165,16 +1416,16 @@ async function executeHooks({ hooks, events }) {
1165
1416
  const hookEndPromise = new Promise((resolve, reject) => {
1166
1417
  const handler = ({ id, success, error }) => {
1167
1418
  if (id !== hookId) return;
1168
- events.off("hook:end", handler);
1419
+ hooks.off("kubb:hook:end", handler);
1169
1420
  if (!success) {
1170
1421
  reject(error ?? /* @__PURE__ */ new Error(`Hook failed: ${command}`));
1171
1422
  return;
1172
1423
  }
1173
- events.emit("success", `${styleText("dim", command)} successfully executed`).then(resolve).catch(reject);
1424
+ hooks.emit("kubb:success", `${styleText("dim", command)} successfully executed`).then(resolve).catch(reject);
1174
1425
  };
1175
- events.on("hook:end", handler);
1426
+ hooks.on("kubb:hook:end", handler);
1176
1427
  });
1177
- await events.emit("hook:start", {
1428
+ await hooks.emit("kubb:hook:start", {
1178
1429
  id: hookId,
1179
1430
  command: cmd,
1180
1431
  args
@@ -1183,11 +1434,20 @@ async function executeHooks({ hooks, events }) {
1183
1434
  }
1184
1435
  }
1185
1436
  //#endregion
1437
+ //#region src/utils/getConfig.ts
1438
+ async function getConfigs(config, args) {
1439
+ const resolved = await (typeof config === "function" ? config(args) : config);
1440
+ return (Array.isArray(resolved) ? resolved : [resolved]).map((item) => ({
1441
+ ...item,
1442
+ plugins: item.plugins ?? []
1443
+ }));
1444
+ }
1445
+ //#endregion
1186
1446
  //#region src/utils/getCosmiConfig.ts
1187
1447
  const jiti = createJiti(import.meta.url, {
1188
1448
  jsx: {
1189
1449
  runtime: "automatic",
1190
- importSource: "@kubb/react-fabric"
1450
+ importSource: "@kubb/renderer-jsx"
1191
1451
  },
1192
1452
  sourceMaps: true,
1193
1453
  interopDefault: true
@@ -1204,10 +1464,14 @@ async function getCosmiConfig(moduleName, config) {
1204
1464
  `.${moduleName}rc.yaml`,
1205
1465
  `.${moduleName}rc.yml`,
1206
1466
  `.${moduleName}rc.ts`,
1467
+ `.${moduleName}rc.mts`,
1468
+ `.${moduleName}rc.cts`,
1207
1469
  `.${moduleName}rc.js`,
1208
1470
  `.${moduleName}rc.mjs`,
1209
1471
  `.${moduleName}rc.cjs`,
1210
1472
  `${moduleName}.config.ts`,
1473
+ `${moduleName}.config.mts`,
1474
+ `${moduleName}.config.cts`,
1211
1475
  `${moduleName}.config.js`,
1212
1476
  `${moduleName}.config.mjs`,
1213
1477
  `${moduleName}.config.cjs`
@@ -1223,7 +1487,11 @@ async function getCosmiConfig(moduleName, config) {
1223
1487
  }),
1224
1488
  ...searchPlaces
1225
1489
  ],
1226
- loaders: { ".ts": tsLoader }
1490
+ loaders: {
1491
+ ".ts": tsLoader,
1492
+ ".mts": tsLoader,
1493
+ ".cts": tsLoader
1494
+ }
1227
1495
  });
1228
1496
  try {
1229
1497
  result = config ? await explorer.load(config) : await explorer.search();
@@ -1251,17 +1519,18 @@ async function startWatcher(path, cb) {
1251
1519
  }
1252
1520
  //#endregion
1253
1521
  //#region src/runners/generate.ts
1254
- async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, configName, outputPath, logLevel: logLevel$1, events, onStart, onEnd }) {
1522
+ async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, configName, outputPath, logLevel: logLevel$1, hooks, onStart, onEnd }) {
1255
1523
  await onStart();
1256
1524
  let resolvedTool = toolValue;
1257
1525
  if (resolvedTool === "auto") {
1258
1526
  const detected = await detect();
1259
- if (!detected) await events.emit("warn", noToolMessage);
1527
+ if (!detected) await hooks.emit("kubb:warn", noToolMessage);
1260
1528
  else {
1261
1529
  resolvedTool = detected;
1262
- await events.emit("info", `Auto-detected ${toolLabel}: ${styleText("dim", resolvedTool)}`);
1530
+ await hooks.emit("kubb:info", `Auto-detected ${toolLabel}: ${styleText("dim", resolvedTool)}`);
1263
1531
  }
1264
1532
  }
1533
+ let toolError;
1265
1534
  if (resolvedTool && resolvedTool !== "auto" && resolvedTool in toolMap) {
1266
1535
  const toolConfig = toolMap[resolvedTool];
1267
1536
  try {
@@ -1269,73 +1538,58 @@ async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefi
1269
1538
  const hookEndPromise = new Promise((resolve, reject) => {
1270
1539
  const handler = ({ id, success, error }) => {
1271
1540
  if (id !== hookId) return;
1272
- events.off("hook:end", handler);
1541
+ hooks.off("kubb:hook:end", handler);
1273
1542
  if (!success) {
1274
1543
  reject(error ?? /* @__PURE__ */ new Error(`${toolConfig.errorMessage}`));
1275
1544
  return;
1276
1545
  }
1277
- events.emit("success", [
1546
+ hooks.emit("kubb:success", [
1278
1547
  `${successPrefix} with ${styleText("dim", resolvedTool)}`,
1279
1548
  logLevel$1 >= logLevel.info ? `on ${styleText("dim", outputPath)}` : void 0,
1280
1549
  "successfully"
1281
1550
  ].filter(Boolean).join(" ")).then(resolve).catch(reject);
1282
1551
  };
1283
- events.on("hook:end", handler);
1552
+ hooks.on("kubb:hook:end", handler);
1284
1553
  });
1285
- await events.emit("hook:start", {
1554
+ await hooks.emit("kubb:hook:start", {
1286
1555
  id: hookId,
1287
1556
  command: toolConfig.command,
1288
1557
  args: toolConfig.args(outputPath)
1289
1558
  });
1290
1559
  await hookEndPromise;
1291
1560
  } catch (caughtError) {
1292
- const err = new Error(toolConfig.errorMessage);
1293
- err.cause = caughtError;
1294
- await events.emit("error", err);
1561
+ const err = toError(caughtError);
1562
+ await hooks.emit("kubb:error", err);
1563
+ toolError = err;
1295
1564
  }
1296
1565
  }
1297
1566
  await onEnd();
1567
+ if (toolError) throw toolError;
1298
1568
  }
1299
- async function generate({ input, config: userConfig, events, logLevel: logLevel$2 }) {
1300
- const inputPath = input ?? ("path" in userConfig.input ? userConfig.input.path : void 0);
1569
+ async function generate(options) {
1570
+ const { input, hooks, logLevel: logLevel$2 } = options;
1301
1571
  const hrStart = process$1.hrtime();
1572
+ const inputPath = input ?? ("path" in options.config.input ? options.config.input.path : void 0);
1302
1573
  const config = {
1303
- ...userConfig,
1304
- root: userConfig.root || process$1.cwd(),
1574
+ ...options.config,
1305
1575
  input: inputPath ? {
1306
- ...userConfig.input,
1576
+ ...options.config.input,
1307
1577
  path: inputPath
1308
- } : userConfig.input,
1309
- output: {
1310
- write: true,
1311
- barrelType: "named",
1312
- extension: { ".ts": ".ts" },
1313
- format: "prettier",
1314
- ...userConfig.output
1315
- }
1578
+ } : options.config.input,
1579
+ ...options.config.output
1316
1580
  };
1317
- await events.emit("generation:start", config);
1318
- await events.emit("info", config.name ? `Setup generation ${styleText("bold", config.name)}` : "Setup generation", inputPath);
1319
- const { sources, fabric, pluginManager } = await setup({
1320
- config,
1321
- events
1322
- });
1323
- await events.emit("info", config.name ? `Build generation ${styleText("bold", config.name)}` : "Build generation", inputPath);
1324
- const { files, failedPlugins, pluginTimings, error } = await safeBuild({
1325
- config,
1326
- events
1327
- }, {
1328
- pluginManager,
1329
- fabric,
1330
- events,
1331
- sources
1332
- });
1333
- await events.emit("info", "Load summary");
1581
+ const kubb = createKubb(config, { hooks });
1582
+ await kubb.setup();
1583
+ await hooks.emit("kubb:generation:start", config);
1584
+ await hooks.emit("kubb:info", config.name ? `Setup generation ${styleText("bold", config.name)}` : "Setup generation", inputPath);
1585
+ await hooks.emit("kubb:info", config.name ? `Build generation ${styleText("bold", config.name)}` : "Build generation", inputPath);
1586
+ const { files, failedPlugins, pluginTimings, error, driver } = await kubb.safeBuild();
1587
+ await hooks.emit("kubb:info", "Load summary");
1334
1588
  if (failedPlugins.size > 0 || error) {
1335
1589
  const allErrors = [error, ...Array.from(failedPlugins).filter((it) => it.error).map((it) => it.error)].filter(Boolean);
1336
- for (const err of allErrors) await events.emit("error", err);
1337
- await events.emit("generation:end", config, files, sources);
1338
- await events.emit("generation:summary", config, {
1590
+ for (const err of allErrors) await hooks.emit("kubb:error", err);
1591
+ await hooks.emit("kubb:generation:end", config, files, kubb.sources);
1592
+ await hooks.emit("kubb:generation:summary", config, {
1339
1593
  failedPlugins,
1340
1594
  filesCreated: files.length,
1341
1595
  status: "failed",
@@ -1345,7 +1599,7 @@ async function generate({ input, config: userConfig, events, logLevel: logLevel$
1345
1599
  await sendTelemetry(buildTelemetryEvent({
1346
1600
  command: "generate",
1347
1601
  kubbVersion: version,
1348
- plugins: pluginManager.plugins.map((p) => ({
1602
+ plugins: Array.from(driver.plugins.values(), (p) => ({
1349
1603
  name: p.name,
1350
1604
  options: p.options
1351
1605
  })),
@@ -1355,8 +1609,8 @@ async function generate({ input, config: userConfig, events, logLevel: logLevel$
1355
1609
  }));
1356
1610
  process$1.exit(1);
1357
1611
  }
1358
- await events.emit("success", "Generation successfully", inputPath);
1359
- await events.emit("generation:end", config, files, sources);
1612
+ await hooks.emit("kubb:success", "Generation successfully", inputPath);
1613
+ await hooks.emit("kubb:generation:end", config, files, kubb.sources);
1360
1614
  const outputPath = path.resolve(config.root, config.output.path);
1361
1615
  if (config.output.format) await runToolPass({
1362
1616
  toolValue: config.output.format,
@@ -1364,13 +1618,13 @@ async function generate({ input, config: userConfig, events, logLevel: logLevel$
1364
1618
  toolMap: formatters,
1365
1619
  toolLabel: "formatter",
1366
1620
  successPrefix: "Formatting",
1367
- noToolMessage: "No formatter found (biome, prettier, or oxfmt). Skipping formatting.",
1621
+ noToolMessage: "No formatter found (oxfmt, biome, or prettier). Skipping formatting.",
1368
1622
  configName: config.name,
1369
1623
  outputPath,
1370
1624
  logLevel: logLevel$2,
1371
- events,
1372
- onStart: () => events.emit("format:start"),
1373
- onEnd: () => events.emit("format:end")
1625
+ hooks,
1626
+ onStart: () => hooks.emit("kubb:format:start"),
1627
+ onEnd: () => hooks.emit("kubb:format:end")
1374
1628
  });
1375
1629
  if (config.output.lint) await runToolPass({
1376
1630
  toolValue: config.output.lint,
@@ -1378,23 +1632,23 @@ async function generate({ input, config: userConfig, events, logLevel: logLevel$
1378
1632
  toolMap: linters,
1379
1633
  toolLabel: "linter",
1380
1634
  successPrefix: "Linting",
1381
- noToolMessage: "No linter found (biome, oxlint, or eslint). Skipping linting.",
1635
+ noToolMessage: "No linter found (oxlint, biome, or eslint). Skipping linting.",
1382
1636
  configName: config.name,
1383
1637
  outputPath,
1384
1638
  logLevel: logLevel$2,
1385
- events,
1386
- onStart: () => events.emit("lint:start"),
1387
- onEnd: () => events.emit("lint:end")
1639
+ hooks,
1640
+ onStart: () => hooks.emit("kubb:lint:start"),
1641
+ onEnd: () => hooks.emit("kubb:lint:end")
1388
1642
  });
1389
1643
  if (config.hooks) {
1390
- await events.emit("hooks:start");
1644
+ await hooks.emit("kubb:hooks:start");
1391
1645
  await executeHooks({
1392
- hooks: config.hooks,
1393
- events
1646
+ configHooks: config.hooks,
1647
+ hooks
1394
1648
  });
1395
- await events.emit("hooks:end");
1649
+ await hooks.emit("kubb:hooks:end");
1396
1650
  }
1397
- await events.emit("generation:summary", config, {
1651
+ await hooks.emit("kubb:generation:summary", config, {
1398
1652
  failedPlugins,
1399
1653
  filesCreated: files.length,
1400
1654
  status: "success",
@@ -1404,7 +1658,7 @@ async function generate({ input, config: userConfig, events, logLevel: logLevel$
1404
1658
  await sendTelemetry(buildTelemetryEvent({
1405
1659
  command: "generate",
1406
1660
  kubbVersion: version,
1407
- plugins: pluginManager.plugins.map((p) => ({
1661
+ plugins: Array.from(driver.plugins.values(), (p) => ({
1408
1662
  name: p.name,
1409
1663
  options: p.options
1410
1664
  })),
@@ -1415,54 +1669,45 @@ async function generate({ input, config: userConfig, events, logLevel: logLevel$
1415
1669
  }
1416
1670
  async function runGenerateCommand({ input, configPath, logLevel: logLevelKey, watch }) {
1417
1671
  const logLevel$3 = logLevel[logLevelKey] ?? logLevel.info;
1418
- const events = new AsyncEventEmitter();
1419
- const promiseManager = new PromiseManager();
1420
- await setupLogger(events, { logLevel: logLevel$3 });
1672
+ const hooks = new AsyncEventEmitter();
1673
+ await setupLogger(hooks, { logLevel: logLevel$3 });
1421
1674
  await executeIfOnline(async () => {
1422
1675
  try {
1423
1676
  const latestVersion = (await (await fetch(KUBB_NPM_PACKAGE_URL)).json()).version;
1424
- if (latestVersion && version < latestVersion) await events.emit("version:new", version, latestVersion);
1677
+ if (latestVersion && version < latestVersion) await hooks.emit("kubb:version:new", version, latestVersion);
1425
1678
  } catch {}
1426
1679
  });
1427
1680
  try {
1428
1681
  const result = await getCosmiConfig("kubb", configPath);
1429
1682
  const configs = await getConfigs(result.config, { input });
1430
- await events.emit("config:start");
1431
- await events.emit("info", "Config loaded", path.relative(process$1.cwd(), result.filepath));
1432
- await events.emit("success", "Config loaded successfully", path.relative(process$1.cwd(), result.filepath));
1433
- await events.emit("config:end", configs);
1434
- await events.emit("lifecycle:start", version);
1435
- const promises = configs.map((config) => {
1436
- return async () => {
1437
- if (isInputPath(config) && watch) {
1438
- await startWatcher([input || config.input.path], async (paths) => {
1439
- events.removeAll();
1440
- await generate({
1441
- input,
1442
- config,
1443
- logLevel: logLevel$3,
1444
- events
1445
- });
1446
- clack.log.step(styleText("yellow", `Watching for changes in ${paths.join(" and ")}`));
1447
- });
1448
- return;
1449
- }
1450
- await generate({
1451
- input,
1452
- config,
1453
- logLevel: logLevel$3,
1454
- events
1455
- });
1456
- };
1683
+ await hooks.emit("kubb:config:start");
1684
+ await hooks.emit("kubb:info", "Config loaded", path.relative(process$1.cwd(), result.filepath));
1685
+ await hooks.emit("kubb:success", "Config loaded successfully", path.relative(process$1.cwd(), result.filepath));
1686
+ await hooks.emit("kubb:config:end", configs);
1687
+ await hooks.emit("kubb:lifecycle:start", version);
1688
+ for (const config of configs) if (isInputPath(config) && watch) await startWatcher([input || config.input.path], async (paths) => {
1689
+ hooks.removeAll();
1690
+ await generate({
1691
+ input,
1692
+ config,
1693
+ logLevel: logLevel$3,
1694
+ hooks
1695
+ });
1696
+ clack.log.step(styleText("yellow", `Watching for changes in ${paths.join(" and ")}`));
1697
+ });
1698
+ else await generate({
1699
+ input,
1700
+ config,
1701
+ logLevel: logLevel$3,
1702
+ hooks
1457
1703
  });
1458
- await promiseManager.run("seq", promises);
1459
- await events.emit("lifecycle:end");
1704
+ await hooks.emit("kubb:lifecycle:end");
1460
1705
  } catch (error) {
1461
- await events.emit("error", toError(error));
1706
+ await hooks.emit("kubb:error", toError(error));
1462
1707
  process$1.exit(1);
1463
1708
  }
1464
1709
  }
1465
1710
  //#endregion
1466
1711
  export { runGenerateCommand };
1467
1712
 
1468
- //# sourceMappingURL=generate-CtFkZeTU.js.map
1713
+ //# sourceMappingURL=generate-CQPHU8Xt.js.map