@kubb/cli 5.0.0-alpha.7 → 5.0.0-alpha.71

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