@kubb/cli 5.0.0-alpha.9 → 5.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +4 -2
  2. package/bin/kubb.js +6 -0
  3. package/dist/{agent-BKphjOIF.cjs → agent-0Nk--lcr.cjs} +5 -5
  4. package/dist/agent-0Nk--lcr.cjs.map +1 -0
  5. package/dist/agent-B_pirbeB.cjs +116 -0
  6. package/dist/agent-B_pirbeB.cjs.map +1 -0
  7. package/dist/{agent-5mmp7QzF.js → agent-DKeVuiUC.js} +5 -5
  8. package/dist/agent-DKeVuiUC.js.map +1 -0
  9. package/dist/agent-Ev5hU5hH.js +112 -0
  10. package/dist/agent-Ev5hU5hH.js.map +1 -0
  11. package/dist/{constants-D0XHAHeZ.cjs → constants-CnDXa1R6.cjs} +30 -60
  12. package/dist/constants-CnDXa1R6.cjs.map +1 -0
  13. package/dist/{constants-DJM9zCXm.js → constants-aL3CP_Wq.js} +23 -59
  14. package/dist/constants-aL3CP_Wq.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-Rly1EXBN.js → generate-B3PZ6Dp-.js} +3 -3
  24. package/dist/generate-B3PZ6Dp-.js.map +1 -0
  25. package/dist/{generate-Cq5RDTBL.cjs → generate-B3jl4ukb.cjs} +559 -265
  26. package/dist/generate-B3jl4ukb.cjs.map +1 -0
  27. package/dist/{generate-DU5zzc54.cjs → generate-DL_7a7Wd.cjs} +3 -3
  28. package/dist/generate-DL_7a7Wd.cjs.map +1 -0
  29. package/dist/{generate-BHNyeQXl.js → generate-Dt_r0ELY.js} +552 -258
  30. package/dist/generate-Dt_r0ELY.js.map +1 -0
  31. package/dist/index.cjs +40 -18
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.js +40 -18
  34. package/dist/index.js.map +1 -1
  35. package/dist/{init-iN7e1XwI.js → init-Bj94Nvt8.js} +4 -4
  36. package/dist/init-Bj94Nvt8.js.map +1 -0
  37. package/dist/{init-BK6inBTR.cjs → init-CZ5Xq2Hd.cjs} +45 -58
  38. package/dist/init-CZ5Xq2Hd.cjs.map +1 -0
  39. package/dist/{init-CN1JFyGX.cjs → init-CyN1oyTF.cjs} +4 -4
  40. package/dist/init-CyN1oyTF.cjs.map +1 -0
  41. package/dist/{init-BQ6zfsnw.js → init-eNRlotJK.js} +41 -54
  42. package/dist/init-eNRlotJK.js.map +1 -0
  43. package/dist/{mcp-eP1S40LZ.js → mcp-BzW703d7.js} +4 -4
  44. package/dist/{mcp-eP1S40LZ.js.map → mcp-BzW703d7.js.map} +1 -1
  45. package/dist/{mcp-CONmm_xT.cjs → mcp-CLcDV4Jm.cjs} +5 -6
  46. package/dist/mcp-CLcDV4Jm.cjs.map +1 -0
  47. package/dist/{mcp-BiGUvbWP.js → mcp-D7EIR9fR.js} +4 -5
  48. package/dist/mcp-D7EIR9fR.js.map +1 -0
  49. package/dist/{mcp-T7Q4nWbT.cjs → mcp-ZY-ONTOp.cjs} +4 -4
  50. package/dist/{mcp-T7Q4nWbT.cjs.map → mcp-ZY-ONTOp.cjs.map} +1 -1
  51. package/dist/{package-BJ6ionm6.cjs → package-D8wlStAg.cjs} +2 -2
  52. package/dist/package-D8wlStAg.cjs.map +1 -0
  53. package/dist/package-Yo-9_m5C.js +6 -0
  54. package/dist/package-Yo-9_m5C.js.map +1 -0
  55. package/dist/{shell-7HPrTCJ5.cjs → shell-475fQKaX.cjs} +8 -3
  56. package/dist/shell-475fQKaX.cjs.map +1 -0
  57. package/dist/{shell-DqqWsHCD.js → shell-DLzN4fRo.js} +8 -3
  58. package/dist/shell-DLzN4fRo.js.map +1 -0
  59. package/dist/{telemetry-DZ7IrLAU.cjs → telemetry-DN95_2pF.cjs} +50 -8
  60. package/dist/telemetry-DN95_2pF.cjs.map +1 -0
  61. package/dist/{telemetry-BF3SMlH6.js → telemetry-LgT_sdPe.js} +48 -6
  62. package/dist/telemetry-LgT_sdPe.js.map +1 -0
  63. package/dist/{validate-DAZdX_0i.js → validate-Dplr99xO.js} +4 -4
  64. package/dist/validate-Dplr99xO.js.map +1 -0
  65. package/dist/{validate-DucFMytl.cjs → validate-_8mBa63G.cjs} +4 -4
  66. package/dist/validate-_8mBa63G.cjs.map +1 -0
  67. package/dist/{validate-BImbbx1t.js → validate-kLJoT_hi.js} +5 -13
  68. package/dist/validate-kLJoT_hi.js.map +1 -0
  69. package/dist/{validate-ujLCYSWU.cjs → validate-yKKzqEZ5.cjs} +6 -14
  70. package/dist/validate-yKKzqEZ5.cjs.map +1 -0
  71. package/package.json +47 -46
  72. package/src/commands/agent/start.ts +20 -4
  73. package/src/commands/generate.ts +35 -6
  74. package/src/commands/init.ts +6 -1
  75. package/src/commands/validate.ts +6 -1
  76. package/src/constants.ts +19 -38
  77. package/src/index.ts +7 -10
  78. package/src/loggers/clackLogger.ts +54 -46
  79. package/src/loggers/fileSystemLogger.ts +15 -16
  80. package/src/loggers/githubActionsLogger.ts +23 -24
  81. package/src/loggers/plainLogger.ts +22 -23
  82. package/src/runners/agent.ts +81 -34
  83. package/src/runners/generate.ts +90 -100
  84. package/src/runners/init.ts +24 -51
  85. package/src/runners/mcp.ts +17 -4
  86. package/src/runners/validate.ts +19 -15
  87. package/src/utils/executeHooks.ts +15 -15
  88. package/src/utils/flags.ts +1 -2
  89. package/src/utils/getConfig.ts +10 -0
  90. package/src/utils/getCosmiConfig.ts +21 -12
  91. package/src/utils/getSummary.ts +1 -1
  92. package/src/utils/runHook.ts +29 -13
  93. package/src/utils/telemetry.ts +16 -3
  94. package/bin/kubb.cjs +0 -18
  95. package/dist/agent-5mmp7QzF.js.map +0 -1
  96. package/dist/agent-BKphjOIF.cjs.map +0 -1
  97. package/dist/agent-BapvKB4r.cjs +0 -92
  98. package/dist/agent-BapvKB4r.cjs.map +0 -1
  99. package/dist/agent-CBrpIMMU.js +0 -88
  100. package/dist/agent-CBrpIMMU.js.map +0 -1
  101. package/dist/constants-D0XHAHeZ.cjs.map +0 -1
  102. package/dist/constants-DJM9zCXm.js.map +0 -1
  103. package/dist/define--M_JMcDC.js +0 -25
  104. package/dist/define--M_JMcDC.js.map +0 -1
  105. package/dist/define-D6Kfm7-Z.cjs +0 -36
  106. package/dist/define-D6Kfm7-Z.cjs.map +0 -1
  107. package/dist/errors-6mF_WKxg.js +0 -27
  108. package/dist/errors-6mF_WKxg.js.map +0 -1
  109. package/dist/errors-DBW0N9w4.cjs.map +0 -1
  110. package/dist/generate-BHNyeQXl.js.map +0 -1
  111. package/dist/generate-Cq5RDTBL.cjs.map +0 -1
  112. package/dist/generate-DU5zzc54.cjs.map +0 -1
  113. package/dist/generate-Rly1EXBN.js.map +0 -1
  114. package/dist/init-BK6inBTR.cjs.map +0 -1
  115. package/dist/init-BQ6zfsnw.js.map +0 -1
  116. package/dist/init-CN1JFyGX.cjs.map +0 -1
  117. package/dist/init-iN7e1XwI.js.map +0 -1
  118. package/dist/jiti-Cd3S0xwr.cjs +0 -16
  119. package/dist/jiti-Cd3S0xwr.cjs.map +0 -1
  120. package/dist/jiti-e08mD2Ph.js +0 -11
  121. package/dist/jiti-e08mD2Ph.js.map +0 -1
  122. package/dist/mcp-BiGUvbWP.js.map +0 -1
  123. package/dist/mcp-CONmm_xT.cjs.map +0 -1
  124. package/dist/package-BJ6ionm6.cjs.map +0 -1
  125. package/dist/package-BKZ0H3Zf.js +0 -6
  126. package/dist/package-BKZ0H3Zf.js.map +0 -1
  127. package/dist/shell-7HPrTCJ5.cjs.map +0 -1
  128. package/dist/shell-DqqWsHCD.js.map +0 -1
  129. package/dist/telemetry-BF3SMlH6.js.map +0 -1
  130. package/dist/telemetry-DZ7IrLAU.cjs.map +0 -1
  131. package/dist/validate-BImbbx1t.js.map +0 -1
  132. package/dist/validate-DAZdX_0i.js.map +0 -1
  133. package/dist/validate-DucFMytl.cjs.map +0 -1
  134. package/dist/validate-ujLCYSWU.cjs.map +0 -1
  135. 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-DZ7IrLAU.cjs");
4
- const require_shell = require("./shell-7HPrTCJ5.cjs");
5
- const require_package = require("./package-BJ6ionm6.cjs");
6
- const require_constants = require("./constants-D0XHAHeZ.cjs");
2
+ const require_errors = require("./errors-CLCjoSg0.cjs");
3
+ const require_telemetry = require("./telemetry-DN95_2pF.cjs");
4
+ const require_shell = require("./shell-475fQKaX.cjs");
5
+ const require_package = require("./package-D8wlStAg.cjs");
6
+ const require_constants = require("./constants-CnDXa1R6.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:",
@@ -270,23 +529,21 @@ function getSummary({ failedPlugins, filesCreated, status, hrStart, config, plug
270
529
  //#endregion
271
530
  //#region src/utils/runHook.ts
272
531
  /**
273
- * Execute a hook command, emit debug/hook:end events, and forward output to
274
- * an optional HookOutputSink. All three logger adapters share this function
275
- * so the process-spawning logic lives in exactly one place.
532
+ * Executes a hook command, emits debug and completion events, and forwards output to an optional sink.
276
533
  */
277
534
  async function runHook({ id, command, args, commandWithArgs, context, stream = false, sink }) {
278
535
  try {
279
536
  const proc = (0, tinyexec.x)(command, [...args ?? []], {
280
- nodeOptions: { detached: true },
537
+ nodeOptions: { detached: process.platform !== "win32" },
281
538
  throwOnError: true
282
539
  });
283
540
  if (stream && sink?.onLine) for await (const line of proc) sink.onLine(line);
284
541
  const result = await proc;
285
- await context.emit("debug", {
542
+ await context.emit("kubb:debug", {
286
543
  date: /* @__PURE__ */ new Date(),
287
544
  logs: [result.stdout.trimEnd()]
288
545
  });
289
- await context.emit("hook:end", {
546
+ await context.emit("kubb:hook:end", {
290
547
  command,
291
548
  args,
292
549
  id,
@@ -295,33 +552,33 @@ async function runHook({ id, command, args, commandWithArgs, context, stream = f
295
552
  });
296
553
  } catch (err) {
297
554
  if (!(err instanceof tinyexec.NonZeroExitError)) {
298
- await context.emit("hook:end", {
555
+ await context.emit("kubb:hook:end", {
299
556
  command,
300
557
  args,
301
558
  id,
302
559
  success: false,
303
560
  error: require_errors.toError(err)
304
561
  });
305
- await context.emit("error", require_errors.toError(err));
562
+ await context.emit("kubb:error", { error: require_errors.toError(err) });
306
563
  return;
307
564
  }
308
565
  const stderr = err.output?.stderr ?? "";
309
566
  const stdout = err.output?.stdout ?? "";
310
- await context.emit("debug", {
567
+ await context.emit("kubb:debug", {
311
568
  date: /* @__PURE__ */ new Date(),
312
569
  logs: [stdout, stderr].filter(Boolean)
313
570
  });
314
571
  if (stderr) sink?.onStderr?.(stderr);
315
572
  if (stdout) sink?.onStdout?.(stdout);
316
573
  const errorMessage = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
317
- await context.emit("hook:end", {
574
+ await context.emit("kubb:hook:end", {
318
575
  command,
319
576
  args,
320
577
  id,
321
578
  success: false,
322
579
  error: errorMessage
323
580
  });
324
- await context.emit("error", errorMessage);
581
+ await context.emit("kubb:error", { error: errorMessage });
325
582
  }
326
583
  }
327
584
  //#endregion
@@ -340,8 +597,7 @@ var ClackWritable = class extends node_stream.Writable {
340
597
  //#endregion
341
598
  //#region src/loggers/clackLogger.ts
342
599
  /**
343
- * Clack adapter for local TTY environments
344
- * Provides a beautiful CLI UI with flat structure inspired by Claude's CLI patterns
600
+ * TTY logger with beautiful UI and progress indicators for local development.
345
601
  */
346
602
  const clackLogger = (0, _kubb_core.defineLogger)({
347
603
  name: "clack",
@@ -389,7 +645,7 @@ const clackLogger = (0, _kubb_core.defineLogger)({
389
645
  state.spinner.stop(text);
390
646
  state.isSpinning = false;
391
647
  }
392
- context.on("info", (message, info = "") => {
648
+ context.on("kubb:info", ({ message, info = "" }) => {
393
649
  if (logLevel <= _kubb_core.logLevel.silent) return;
394
650
  const text = getMessage([
395
651
  (0, node_util.styleText)("blue", "ℹ"),
@@ -399,7 +655,7 @@ const clackLogger = (0, _kubb_core.defineLogger)({
399
655
  if (state.isSpinning) state.spinner.message(text);
400
656
  else _clack_prompts.log.info(text);
401
657
  });
402
- context.on("success", (message, info = "") => {
658
+ context.on("kubb:success", ({ message, info = "" }) => {
403
659
  if (logLevel <= _kubb_core.logLevel.silent) return;
404
660
  const text = getMessage([
405
661
  (0, node_util.styleText)("blue", "✓"),
@@ -409,7 +665,7 @@ const clackLogger = (0, _kubb_core.defineLogger)({
409
665
  if (state.isSpinning) stopSpinner(text);
410
666
  else _clack_prompts.log.success(text);
411
667
  });
412
- context.on("warn", (message, info) => {
668
+ context.on("kubb:warn", ({ message, info }) => {
413
669
  if (logLevel < _kubb_core.logLevel.warn) return;
414
670
  const text = getMessage([
415
671
  (0, node_util.styleText)("yellow", "⚠"),
@@ -418,7 +674,7 @@ const clackLogger = (0, _kubb_core.defineLogger)({
418
674
  ].filter(Boolean).join(" "));
419
675
  _clack_prompts.log.warn(text);
420
676
  });
421
- context.on("error", (error) => {
677
+ context.on("kubb:error", ({ error }) => {
422
678
  const caused = require_errors.toCause(error);
423
679
  const text = [(0, node_util.styleText)("red", "✗"), error.message].join(" ");
424
680
  if (state.isSpinning) stopSpinner(getMessage(text));
@@ -433,19 +689,24 @@ const clackLogger = (0, _kubb_core.defineLogger)({
433
689
  }
434
690
  }
435
691
  });
436
- context.on("version:new", (version, latestVersion) => {
692
+ context.on("kubb:version:new", ({ currentVersion, latestVersion }) => {
437
693
  if (logLevel <= _kubb_core.logLevel.silent) return;
438
- _clack_prompts.box(`\`v${version}\` → \`v${latestVersion}\`
694
+ try {
695
+ _clack_prompts.box(`\`v${currentVersion}\` → \`v${latestVersion}\`
439
696
  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
- });
697
+ width: "auto",
698
+ formatBorder: (s) => (0, node_util.styleText)("yellow", s),
699
+ rounded: true,
700
+ withGuide: false,
701
+ contentAlign: "center",
702
+ titleAlign: "center"
703
+ });
704
+ } catch {
705
+ console.log(`Update available for Kubb: v${currentVersion} → v${latestVersion}`);
706
+ console.log("Run `npm install -g @kubb/cli` to update");
707
+ }
447
708
  });
448
- context.on("lifecycle:start", async (version) => {
709
+ context.on("kubb:lifecycle:start", async ({ version }) => {
449
710
  console.log(`\n${getIntro({
450
711
  title: "The ultimate toolkit for working with APIs",
451
712
  description: "Ready to start",
@@ -454,24 +715,24 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
454
715
  })}\n`);
455
716
  reset();
456
717
  });
457
- context.on("config:start", () => {
718
+ context.on("kubb:config:start", () => {
458
719
  if (logLevel <= _kubb_core.logLevel.silent) return;
459
720
  const text = getMessage("Configuration started");
460
721
  _clack_prompts.intro(text);
461
722
  startSpinner(getMessage("Configuration loading"));
462
723
  });
463
- context.on("config:end", (_configs) => {
724
+ context.on("kubb:config:end", () => {
464
725
  if (logLevel <= _kubb_core.logLevel.silent) return;
465
726
  const text = getMessage("Configuration completed");
466
727
  _clack_prompts.outro(text);
467
728
  });
468
- context.on("generation:start", (config) => {
729
+ context.on("kubb:generation:start", ({ config }) => {
469
730
  reset();
470
731
  state.totalPlugins = config.plugins?.length ?? 0;
471
732
  const text = getMessage(["Generation started", config.name ? `for ${(0, node_util.styleText)("dim", config.name)}` : void 0].filter(Boolean).join(" "));
472
733
  _clack_prompts.intro(text);
473
734
  });
474
- context.on("plugin:start", (plugin) => {
735
+ context.on("kubb:plugin:start", ({ plugin }) => {
475
736
  if (logLevel <= _kubb_core.logLevel.silent) return;
476
737
  stopSpinner();
477
738
  const progressBar = _clack_prompts.progress({
@@ -489,7 +750,7 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
489
750
  interval
490
751
  });
491
752
  });
492
- context.on("plugin:end", (plugin, { duration, success }) => {
753
+ context.on("kubb:plugin:end", ({ plugin, duration, success }) => {
493
754
  stopSpinner();
494
755
  const active = state.activeProgress.get(plugin.name);
495
756
  if (!active || logLevel === _kubb_core.logLevel.silent) return;
@@ -502,7 +763,7 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
502
763
  state.activeProgress.delete(plugin.name);
503
764
  showProgressStep();
504
765
  });
505
- context.on("files:processing:start", (files) => {
766
+ context.on("kubb:files:processing:start", ({ files }) => {
506
767
  if (logLevel <= _kubb_core.logLevel.silent) return;
507
768
  stopSpinner();
508
769
  state.totalFiles = files.length;
@@ -513,11 +774,11 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
513
774
  max: files.length,
514
775
  size: 30
515
776
  });
516
- context.emit("info", text);
777
+ context.emit("kubb:info", { message: text });
517
778
  progressBar.start(getMessage(text));
518
779
  state.activeProgress.set("files", { progressBar });
519
780
  });
520
- context.on("file:processing:update", ({ file, config }) => {
781
+ context.on("kubb:file:processing:update", ({ file, config }) => {
521
782
  if (logLevel <= _kubb_core.logLevel.silent) return;
522
783
  stopSpinner();
523
784
  state.processedFiles++;
@@ -526,7 +787,7 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
526
787
  if (!active) return;
527
788
  active.progressBar.advance(void 0, text);
528
789
  });
529
- context.on("files:processing:end", () => {
790
+ context.on("kubb:files:processing:end", () => {
530
791
  if (logLevel <= _kubb_core.logLevel.silent) return;
531
792
  stopSpinner();
532
793
  const text = getMessage("Files written successfully");
@@ -536,31 +797,31 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
536
797
  state.activeProgress.delete("files");
537
798
  showProgressStep();
538
799
  });
539
- context.on("generation:end", (config) => {
800
+ context.on("kubb:generation:end", ({ config }) => {
540
801
  const text = getMessage(config.name ? `Generation completed for ${(0, node_util.styleText)("dim", config.name)}` : "Generation completed");
541
802
  _clack_prompts.outro(text);
542
803
  });
543
- context.on("format:start", () => {
804
+ context.on("kubb:format:start", () => {
544
805
  if (logLevel <= _kubb_core.logLevel.silent) return;
545
806
  const text = getMessage("Format started");
546
807
  _clack_prompts.intro(text);
547
808
  });
548
- context.on("format:end", () => {
809
+ context.on("kubb:format:end", () => {
549
810
  if (logLevel <= _kubb_core.logLevel.silent) return;
550
811
  const text = getMessage("Format completed");
551
812
  _clack_prompts.outro(text);
552
813
  });
553
- context.on("lint:start", () => {
814
+ context.on("kubb:lint:start", () => {
554
815
  if (logLevel <= _kubb_core.logLevel.silent) return;
555
816
  const text = getMessage("Lint started");
556
817
  _clack_prompts.intro(text);
557
818
  });
558
- context.on("lint:end", () => {
819
+ context.on("kubb:lint:end", () => {
559
820
  if (logLevel <= _kubb_core.logLevel.silent) return;
560
821
  const text = getMessage("Lint completed");
561
822
  _clack_prompts.outro(text);
562
823
  });
563
- context.on("hook:start", async ({ id, command, args }) => {
824
+ context.on("kubb:hook:start", async ({ id, command, args }) => {
564
825
  const commandWithArgs = formatCommandWithArgs(command, args);
565
826
  const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} started`);
566
827
  if (!id) return;
@@ -595,12 +856,12 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
595
856
  }
596
857
  });
597
858
  });
598
- context.on("hook:end", ({ command, args }) => {
859
+ context.on("kubb:hook:end", ({ command, args }) => {
599
860
  if (logLevel <= _kubb_core.logLevel.silent) return;
600
861
  const text = getMessage(`Hook ${(0, node_util.styleText)("dim", formatCommandWithArgs(command, args))} successfully executed`);
601
862
  _clack_prompts.outro(text);
602
863
  });
603
- context.on("generation:summary", (config, { pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
864
+ context.on("kubb:generation:summary", ({ config, pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
604
865
  const summary = getSummary({
605
866
  failedPlugins,
606
867
  filesCreated,
@@ -613,16 +874,20 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
613
874
  summary.unshift("\n");
614
875
  summary.push("\n");
615
876
  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
- });
877
+ try {
878
+ _clack_prompts.box(summary.join("\n"), getMessage(title), {
879
+ width: "auto",
880
+ formatBorder: (s) => (0, node_util.styleText)(borderColor, s),
881
+ rounded: true,
882
+ withGuide: false,
883
+ contentAlign: "left",
884
+ titleAlign: "center"
885
+ });
886
+ } catch {
887
+ console.log(summary.join("\n"));
888
+ }
624
889
  });
625
- context.on("lifecycle:end", () => {
890
+ context.on("kubb:lifecycle:end", () => {
626
891
  reset();
627
892
  });
628
893
  }
@@ -630,11 +895,8 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
630
895
  //#endregion
631
896
  //#region src/loggers/fileSystemLogger.ts
632
897
  /**
633
- * FileSystem logger for debug log persistence
634
- * Captures debug and verbose events and writes them to files in .kubb directory
635
- *
636
- * Note: Logs are written on lifecycle:end or process exit. If the process crashes
637
- * before these events, some cached logs may be lost.
898
+ * FileSystem logger that captures debug events and writes them to `.kubb` directory files.
899
+ * Note: Logs write on `lifecycle:end` or process exit. Cached logs may be lost if the process crashes before these events.
638
900
  */
639
901
  const fileSystemLogger = (0, _kubb_core.defineLogger)({
640
902
  name: "filesystem",
@@ -663,63 +925,66 @@ const fileSystemLogger = (0, _kubb_core.defineLogger)({
663
925
  files[pathName].push(`[${timestamp}]\n${log.logs.join("\n")}`);
664
926
  }
665
927
  }
666
- await Promise.all(Object.entries(files).map(([fileName, logs]) => write(fileName, logs.join("\n\n"))));
928
+ for (const [fileName, logs] of Object.entries(files)) await write(fileName, logs.join("\n\n"));
667
929
  return Object.keys(files);
668
930
  }
669
- context.on("info", (message, info) => {
931
+ context.on("kubb:info", ({ message, info }) => {
670
932
  state.cachedLogs.add({
671
933
  date: /* @__PURE__ */ new Date(),
672
934
  logs: [`ℹ ${message} ${info}`]
673
935
  });
674
936
  });
675
- context.on("success", (message, info) => {
937
+ context.on("kubb:success", ({ message, info }) => {
676
938
  state.cachedLogs.add({
677
939
  date: /* @__PURE__ */ new Date(),
678
940
  logs: [`✓ ${message} ${info}`]
679
941
  });
680
942
  });
681
- context.on("warn", (message, info) => {
943
+ context.on("kubb:warn", ({ message, info }) => {
682
944
  state.cachedLogs.add({
683
945
  date: /* @__PURE__ */ new Date(),
684
946
  logs: [`⚠ ${message} ${info}`]
685
947
  });
686
948
  });
687
- context.on("error", (error) => {
949
+ context.on("kubb:error", ({ error }) => {
688
950
  state.cachedLogs.add({
689
951
  date: /* @__PURE__ */ new Date(),
690
952
  logs: [`✗ ${error.message}`, error.stack || "unknown stack"]
691
953
  });
692
954
  });
693
- context.on("debug", (message) => {
955
+ context.on("kubb:debug", (message) => {
694
956
  state.cachedLogs.add({
695
957
  date: /* @__PURE__ */ new Date(),
696
958
  logs: message.logs
697
959
  });
698
960
  });
699
- context.on("plugin:start", (plugin) => {
961
+ context.on("kubb:plugin:start", ({ plugin }) => {
700
962
  state.cachedLogs.add({
701
963
  date: /* @__PURE__ */ new Date(),
702
964
  logs: [`Generating ${plugin.name}`]
703
965
  });
704
966
  });
705
- context.on("plugin:end", (plugin, { duration, success }) => {
967
+ context.on("kubb:plugin:end", ({ plugin, duration, success }) => {
706
968
  const durationStr = formatMs(duration);
707
969
  state.cachedLogs.add({
708
970
  date: /* @__PURE__ */ new Date(),
709
971
  logs: [success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`]
710
972
  });
711
973
  });
712
- context.on("files:processing:start", (files) => {
974
+ context.on("kubb:files:processing:start", ({ files }) => {
713
975
  state.cachedLogs.add({
714
976
  date: /* @__PURE__ */ new Date(),
715
977
  logs: [`Start ${files.length} writing:`, ...files.map((file) => file.path)]
716
978
  });
717
979
  });
718
- context.on("generation:end", async (config) => {
980
+ context.on("kubb:generation:end", async ({ config }) => {
719
981
  const writtenFilePaths = await writeLogs(config.name);
720
982
  if (writtenFilePaths.length > 0) {
721
983
  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(", "));
984
+ await context.emit("kubb:info", {
985
+ message: "Debug files written to:",
986
+ info: files.join(", ")
987
+ });
723
988
  }
724
989
  reset();
725
990
  });
@@ -734,8 +999,7 @@ const fileSystemLogger = (0, _kubb_core.defineLogger)({
734
999
  //#endregion
735
1000
  //#region src/loggers/githubActionsLogger.ts
736
1001
  /**
737
- * GitHub Actions adapter for CI environments
738
- * Uses Github group annotations for collapsible sections
1002
+ * GitHub Actions logger using group annotations for collapsible sections in CI.
739
1003
  */
740
1004
  const githubActionsLogger = (0, _kubb_core.defineLogger)({
741
1005
  name: "github-actions",
@@ -773,7 +1037,7 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
773
1037
  function closeGroup(_name) {
774
1038
  console.log("::endgroup::");
775
1039
  }
776
- context.on("info", (message, info = "") => {
1040
+ context.on("kubb:info", ({ message, info = "" }) => {
777
1041
  if (logLevel <= _kubb_core.logLevel.silent) return;
778
1042
  const text = getMessage([
779
1043
  (0, node_util.styleText)("blue", "ℹ"),
@@ -782,7 +1046,7 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
782
1046
  ].join(" "));
783
1047
  console.log(text);
784
1048
  });
785
- context.on("success", (message, info = "") => {
1049
+ context.on("kubb:success", ({ message, info = "" }) => {
786
1050
  if (logLevel <= _kubb_core.logLevel.silent) return;
787
1051
  const text = getMessage([
788
1052
  (0, node_util.styleText)("blue", "✓"),
@@ -791,7 +1055,7 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
791
1055
  ].filter(Boolean).join(" "));
792
1056
  console.log(text);
793
1057
  });
794
- context.on("warn", (message, info = "") => {
1058
+ context.on("kubb:warn", ({ message, info = "" }) => {
795
1059
  if (logLevel <= _kubb_core.logLevel.silent) return;
796
1060
  const text = getMessage([
797
1061
  (0, node_util.styleText)("yellow", "⚠"),
@@ -800,7 +1064,7 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
800
1064
  ].filter(Boolean).join(" "));
801
1065
  console.warn(`::warning::${text}`);
802
1066
  });
803
- context.on("error", (error) => {
1067
+ context.on("kubb:error", ({ error }) => {
804
1068
  const caused = require_errors.toCause(error);
805
1069
  if (logLevel <= _kubb_core.logLevel.silent) return;
806
1070
  const message = error.message || String(error);
@@ -815,37 +1079,37 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
815
1079
  }
816
1080
  }
817
1081
  });
818
- context.on("lifecycle:start", (version) => {
1082
+ context.on("kubb:lifecycle:start", ({ version }) => {
819
1083
  console.log((0, node_util.styleText)("yellow", `Kubb ${version} 🧩`));
820
1084
  reset();
821
1085
  });
822
- context.on("config:start", () => {
1086
+ context.on("kubb:config:start", () => {
823
1087
  if (logLevel <= _kubb_core.logLevel.silent) return;
824
1088
  const text = getMessage("Configuration started");
825
1089
  openGroup("Configuration");
826
1090
  console.log(text);
827
1091
  });
828
- context.on("config:end", (configs) => {
1092
+ context.on("kubb:config:end", ({ configs }) => {
829
1093
  state.currentConfigs = configs;
830
1094
  if (logLevel <= _kubb_core.logLevel.silent) return;
831
1095
  const text = getMessage("Configuration completed");
832
1096
  console.log(text);
833
1097
  closeGroup("Configuration");
834
1098
  });
835
- context.on("generation:start", (config) => {
1099
+ context.on("kubb:generation:start", ({ config }) => {
836
1100
  reset();
837
1101
  state.totalPlugins = config.plugins?.length ?? 0;
838
1102
  const text = config.name ? `Generation for ${(0, node_util.styleText)("bold", config.name)}` : "Generation";
839
1103
  if (state.currentConfigs.length > 1) openGroup(text);
840
1104
  if (state.currentConfigs.length === 1) console.log(getMessage(text));
841
1105
  });
842
- context.on("plugin:start", (plugin) => {
1106
+ context.on("kubb:plugin:start", ({ plugin }) => {
843
1107
  if (logLevel <= _kubb_core.logLevel.silent) return;
844
1108
  const text = getMessage(`Generating ${(0, node_util.styleText)("bold", plugin.name)}`);
845
1109
  if (state.currentConfigs.length === 1) openGroup(`Plugin: ${plugin.name}`);
846
1110
  console.log(text);
847
1111
  });
848
- context.on("plugin:end", (plugin, { duration, success }) => {
1112
+ context.on("kubb:plugin:end", ({ plugin, duration, success }) => {
849
1113
  if (logLevel <= _kubb_core.logLevel.silent) return;
850
1114
  if (success) state.completedPlugins++;
851
1115
  else state.failedPlugins++;
@@ -856,7 +1120,7 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
856
1120
  if (state.currentConfigs.length === 1) closeGroup(`Plugin: ${plugin.name}`);
857
1121
  showProgressStep();
858
1122
  });
859
- context.on("files:processing:start", (files) => {
1123
+ context.on("kubb:files:processing:start", ({ files }) => {
860
1124
  if (logLevel <= _kubb_core.logLevel.silent) return;
861
1125
  state.totalFiles = files.length;
862
1126
  state.processedFiles = 0;
@@ -864,46 +1128,46 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
864
1128
  const text = getMessage(`Writing ${files.length} files`);
865
1129
  console.log(text);
866
1130
  });
867
- context.on("files:processing:end", () => {
1131
+ context.on("kubb:files:processing:end", () => {
868
1132
  if (logLevel <= _kubb_core.logLevel.silent) return;
869
1133
  const text = getMessage("Files written successfully");
870
1134
  console.log(text);
871
1135
  if (state.currentConfigs.length === 1) closeGroup("File Generation");
872
1136
  showProgressStep();
873
1137
  });
874
- context.on("file:processing:update", () => {
1138
+ context.on("kubb:file:processing:update", () => {
875
1139
  if (logLevel <= _kubb_core.logLevel.silent) return;
876
1140
  state.processedFiles++;
877
1141
  });
878
- context.on("generation:end", (config) => {
1142
+ context.on("kubb:generation:end", ({ config }) => {
879
1143
  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
1144
  console.log(text);
881
1145
  });
882
- context.on("format:start", () => {
1146
+ context.on("kubb:format:start", () => {
883
1147
  if (logLevel <= _kubb_core.logLevel.silent) return;
884
1148
  const text = getMessage("Format started");
885
1149
  if (state.currentConfigs.length === 1) openGroup("Formatting");
886
1150
  console.log(text);
887
1151
  });
888
- context.on("format:end", () => {
1152
+ context.on("kubb:format:end", () => {
889
1153
  if (logLevel <= _kubb_core.logLevel.silent) return;
890
1154
  const text = getMessage("Format completed");
891
1155
  console.log(text);
892
1156
  if (state.currentConfigs.length === 1) closeGroup("Formatting");
893
1157
  });
894
- context.on("lint:start", () => {
1158
+ context.on("kubb:lint:start", () => {
895
1159
  if (logLevel <= _kubb_core.logLevel.silent) return;
896
1160
  const text = getMessage("Lint started");
897
1161
  if (state.currentConfigs.length === 1) openGroup("Linting");
898
1162
  console.log(text);
899
1163
  });
900
- context.on("lint:end", () => {
1164
+ context.on("kubb:lint:end", () => {
901
1165
  if (logLevel <= _kubb_core.logLevel.silent) return;
902
1166
  const text = getMessage("Lint completed");
903
1167
  console.log(text);
904
1168
  if (state.currentConfigs.length === 1) closeGroup("Linting");
905
1169
  });
906
- context.on("hook:start", async ({ id, command, args }) => {
1170
+ context.on("kubb:hook:start", async ({ id, command, args }) => {
907
1171
  const commandWithArgs = formatCommandWithArgs(command, args);
908
1172
  const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} started`);
909
1173
  if (logLevel > _kubb_core.logLevel.silent) {
@@ -923,14 +1187,14 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
923
1187
  }
924
1188
  });
925
1189
  });
926
- context.on("hook:end", ({ command, args }) => {
1190
+ context.on("kubb:hook:end", ({ command, args }) => {
927
1191
  if (logLevel <= _kubb_core.logLevel.silent) return;
928
1192
  const commandWithArgs = formatCommandWithArgs(command, args);
929
1193
  const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} completed`);
930
1194
  console.log(text);
931
1195
  if (state.currentConfigs.length === 1) closeGroup(`Hook ${commandWithArgs}`);
932
1196
  });
933
- context.on("generation:summary", (config, { status, hrStart, failedPlugins }) => {
1197
+ context.on("kubb:generation:summary", ({ config, status, hrStart, failedPlugins }) => {
934
1198
  const pluginsCount = config.plugins?.length ?? 0;
935
1199
  const successCount = pluginsCount - failedPlugins.size;
936
1200
  const duration = formatHrtime(hrStart);
@@ -938,7 +1202,7 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
938
1202
  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
1203
  if (state.currentConfigs.length > 1) closeGroup(config.name ? `Generation for ${(0, node_util.styleText)("bold", config.name)}` : "Generation");
940
1204
  });
941
- context.on("lifecycle:end", () => {
1205
+ context.on("kubb:lifecycle:end", () => {
942
1206
  reset();
943
1207
  });
944
1208
  }
@@ -946,8 +1210,7 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
946
1210
  //#endregion
947
1211
  //#region src/loggers/plainLogger.ts
948
1212
  /**
949
- * Plain console adapter for non-TTY environments
950
- * Simple console.log output with indentation
1213
+ * Plain console adapter for non-TTY environments with simple `console.log` output.
951
1214
  */
952
1215
  const plainLogger = (0, _kubb_core.defineLogger)({
953
1216
  name: "plain",
@@ -956,7 +1219,7 @@ const plainLogger = (0, _kubb_core.defineLogger)({
956
1219
  function getMessage(message) {
957
1220
  return formatMessage(message, logLevel);
958
1221
  }
959
- context.on("info", (message, info) => {
1222
+ context.on("kubb:info", ({ message, info }) => {
960
1223
  if (logLevel <= _kubb_core.logLevel.silent) return;
961
1224
  const text = getMessage([
962
1225
  "ℹ",
@@ -965,7 +1228,7 @@ const plainLogger = (0, _kubb_core.defineLogger)({
965
1228
  ].join(" "));
966
1229
  console.log(text);
967
1230
  });
968
- context.on("success", (message, info = "") => {
1231
+ context.on("kubb:success", ({ message, info = "" }) => {
969
1232
  if (logLevel <= _kubb_core.logLevel.silent) return;
970
1233
  const text = getMessage([
971
1234
  "✓",
@@ -974,7 +1237,7 @@ const plainLogger = (0, _kubb_core.defineLogger)({
974
1237
  ].filter(Boolean).join(" "));
975
1238
  console.log(text);
976
1239
  });
977
- context.on("warn", (message, info) => {
1240
+ context.on("kubb:warn", ({ message, info }) => {
978
1241
  if (logLevel < _kubb_core.logLevel.warn) return;
979
1242
  const text = getMessage([
980
1243
  "⚠",
@@ -983,7 +1246,7 @@ const plainLogger = (0, _kubb_core.defineLogger)({
983
1246
  ].filter(Boolean).join(" "));
984
1247
  console.log(text);
985
1248
  });
986
- context.on("error", (error) => {
1249
+ context.on("kubb:error", ({ error }) => {
987
1250
  const caused = require_errors.toCause(error);
988
1251
  const text = getMessage(["✗", error.message].join(" "));
989
1252
  console.log(text);
@@ -997,74 +1260,74 @@ const plainLogger = (0, _kubb_core.defineLogger)({
997
1260
  }
998
1261
  }
999
1262
  });
1000
- context.on("lifecycle:start", () => {
1263
+ context.on("kubb:lifecycle:start", () => {
1001
1264
  console.log("Kubb CLI 🧩");
1002
1265
  });
1003
- context.on("config:start", () => {
1266
+ context.on("kubb:config:start", () => {
1004
1267
  if (logLevel <= _kubb_core.logLevel.silent) return;
1005
1268
  const text = getMessage("Configuration started");
1006
1269
  console.log(text);
1007
1270
  });
1008
- context.on("config:end", () => {
1271
+ context.on("kubb:config:end", () => {
1009
1272
  if (logLevel <= _kubb_core.logLevel.silent) return;
1010
1273
  const text = getMessage("Configuration completed");
1011
1274
  console.log(text);
1012
1275
  });
1013
- context.on("generation:start", () => {
1276
+ context.on("kubb:generation:start", () => {
1014
1277
  const text = getMessage("Generation started");
1015
1278
  console.log(text);
1016
1279
  });
1017
- context.on("plugin:start", (plugin) => {
1280
+ context.on("kubb:plugin:start", ({ plugin }) => {
1018
1281
  if (logLevel <= _kubb_core.logLevel.silent) return;
1019
1282
  const text = getMessage(`Generating ${plugin.name}`);
1020
1283
  console.log(text);
1021
1284
  });
1022
- context.on("plugin:end", (plugin, { duration, success }) => {
1285
+ context.on("kubb:plugin:end", ({ plugin, duration, success }) => {
1023
1286
  if (logLevel <= _kubb_core.logLevel.silent) return;
1024
1287
  const durationStr = formatMs(duration);
1025
1288
  const text = getMessage(success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`);
1026
1289
  console.log(text);
1027
1290
  });
1028
- context.on("files:processing:start", (files) => {
1291
+ context.on("kubb:files:processing:start", ({ files }) => {
1029
1292
  if (logLevel <= _kubb_core.logLevel.silent) return;
1030
1293
  const text = getMessage(`Writing ${files.length} files`);
1031
1294
  console.log(text);
1032
1295
  });
1033
- context.on("file:processing:update", ({ file, config }) => {
1296
+ context.on("kubb:file:processing:update", ({ file, config }) => {
1034
1297
  if (logLevel <= _kubb_core.logLevel.silent) return;
1035
1298
  const text = getMessage(`Writing ${(0, node_path.relative)(config.root, file.path)}`);
1036
1299
  console.log(text);
1037
1300
  });
1038
- context.on("files:processing:end", () => {
1301
+ context.on("kubb:files:processing:end", () => {
1039
1302
  if (logLevel <= _kubb_core.logLevel.silent) return;
1040
1303
  const text = getMessage("Files written successfully");
1041
1304
  console.log(text);
1042
1305
  });
1043
- context.on("generation:end", (config) => {
1306
+ context.on("kubb:generation:end", ({ config }) => {
1044
1307
  const text = getMessage(config.name ? `Generation completed for ${config.name}` : "Generation completed");
1045
1308
  console.log(text);
1046
1309
  });
1047
- context.on("format:start", () => {
1310
+ context.on("kubb:format:start", () => {
1048
1311
  if (logLevel <= _kubb_core.logLevel.silent) return;
1049
1312
  const text = getMessage("Format started");
1050
1313
  console.log(text);
1051
1314
  });
1052
- context.on("format:end", () => {
1315
+ context.on("kubb:format:end", () => {
1053
1316
  if (logLevel <= _kubb_core.logLevel.silent) return;
1054
1317
  const text = getMessage("Format completed");
1055
1318
  console.log(text);
1056
1319
  });
1057
- context.on("lint:start", () => {
1320
+ context.on("kubb:lint:start", () => {
1058
1321
  if (logLevel <= _kubb_core.logLevel.silent) return;
1059
1322
  const text = getMessage("Lint started");
1060
1323
  console.log(text);
1061
1324
  });
1062
- context.on("lint:end", () => {
1325
+ context.on("kubb:lint:end", () => {
1063
1326
  if (logLevel <= _kubb_core.logLevel.silent) return;
1064
1327
  const text = getMessage("Lint completed");
1065
1328
  console.log(text);
1066
1329
  });
1067
- context.on("hook:start", async ({ id, command, args }) => {
1330
+ context.on("kubb:hook:start", async ({ id, command, args }) => {
1068
1331
  const commandWithArgs = formatCommandWithArgs(command, args);
1069
1332
  const text = getMessage(`Hook ${commandWithArgs} started`);
1070
1333
  if (logLevel > _kubb_core.logLevel.silent) console.log(text);
@@ -1081,12 +1344,12 @@ const plainLogger = (0, _kubb_core.defineLogger)({
1081
1344
  }
1082
1345
  });
1083
1346
  });
1084
- context.on("hook:end", ({ command, args }) => {
1347
+ context.on("kubb:hook:end", ({ command, args }) => {
1085
1348
  if (logLevel <= _kubb_core.logLevel.silent) return;
1086
1349
  const text = getMessage(`Hook ${formatCommandWithArgs(command, args)} completed`);
1087
1350
  console.log(text);
1088
1351
  });
1089
- context.on("generation:summary", (config, { pluginTimings, status, hrStart, failedPlugins, filesCreated }) => {
1352
+ context.on("kubb:generation:summary", ({ config, pluginTimings, status, hrStart, failedPlugins, filesCreated }) => {
1090
1353
  const summary = getSummary({
1091
1354
  failedPlugins,
1092
1355
  filesCreated,
@@ -1159,25 +1422,25 @@ async function setupLogger(context, { logLevel }) {
1159
1422
  }
1160
1423
  //#endregion
1161
1424
  //#region src/utils/executeHooks.ts
1162
- async function executeHooks({ hooks, events }) {
1163
- const commands = Array.isArray(hooks.done) ? hooks.done : [hooks.done].filter(Boolean);
1425
+ async function executeHooks({ configHooks, hooks }) {
1426
+ const commands = Array.isArray(configHooks.done) ? configHooks.done : [configHooks.done].filter(Boolean);
1164
1427
  for (const command of commands) {
1165
1428
  const [cmd, ...args] = require_shell.tokenize(command);
1166
1429
  if (!cmd) continue;
1167
1430
  const hookId = (0, node_crypto.createHash)("sha256").update(command).digest("hex");
1168
1431
  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}`));
1432
+ const handler = (ctx) => {
1433
+ if (ctx.id !== hookId) return;
1434
+ hooks.off("kubb:hook:end", handler);
1435
+ if (!ctx.success) {
1436
+ reject(ctx.error ?? /* @__PURE__ */ new Error(`Hook failed: ${command}`));
1174
1437
  return;
1175
1438
  }
1176
- events.emit("success", `${(0, node_util.styleText)("dim", command)} successfully executed`).then(resolve).catch(reject);
1439
+ hooks.emit("kubb:success", { message: `${(0, node_util.styleText)("dim", command)} successfully executed` }).then(resolve).catch(reject);
1177
1440
  };
1178
- events.on("hook:end", handler);
1441
+ hooks.on("kubb:hook:end", handler);
1179
1442
  });
1180
- await events.emit("hook:start", {
1443
+ await hooks.emit("kubb:hook:start", {
1181
1444
  id: hookId,
1182
1445
  command: cmd,
1183
1446
  args
@@ -1186,17 +1449,26 @@ async function executeHooks({ hooks, events }) {
1186
1449
  }
1187
1450
  }
1188
1451
  //#endregion
1452
+ //#region src/utils/getConfig.ts
1453
+ async function getConfigs(config, args) {
1454
+ const resolved = await (typeof config === "function" ? config(args) : config);
1455
+ return (Array.isArray(resolved) ? resolved : [resolved]).map((item) => ({
1456
+ ...item,
1457
+ plugins: item.plugins ?? []
1458
+ }));
1459
+ }
1460
+ //#endregion
1189
1461
  //#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
- });
1462
+ const unrunInputOptions = { transform: { jsx: {
1463
+ runtime: "automatic",
1464
+ importSource: "@kubb/renderer-jsx"
1465
+ } } };
1198
1466
  const tsLoader = async (configFile) => {
1199
- return await jiti$1.import(configFile, { default: true });
1467
+ const { module } = await (0, unrun.unrun)({
1468
+ path: configFile,
1469
+ inputOptions: unrunInputOptions
1470
+ });
1471
+ return module;
1200
1472
  };
1201
1473
  async function getCosmiConfig(moduleName, config) {
1202
1474
  let result;
@@ -1207,10 +1479,14 @@ async function getCosmiConfig(moduleName, config) {
1207
1479
  `.${moduleName}rc.yaml`,
1208
1480
  `.${moduleName}rc.yml`,
1209
1481
  `.${moduleName}rc.ts`,
1482
+ `.${moduleName}rc.mts`,
1483
+ `.${moduleName}rc.cts`,
1210
1484
  `.${moduleName}rc.js`,
1211
1485
  `.${moduleName}rc.mjs`,
1212
1486
  `.${moduleName}rc.cjs`,
1213
1487
  `${moduleName}.config.ts`,
1488
+ `${moduleName}.config.mts`,
1489
+ `${moduleName}.config.cts`,
1214
1490
  `${moduleName}.config.js`,
1215
1491
  `${moduleName}.config.mjs`,
1216
1492
  `${moduleName}.config.cjs`
@@ -1226,7 +1502,11 @@ async function getCosmiConfig(moduleName, config) {
1226
1502
  }),
1227
1503
  ...searchPlaces
1228
1504
  ],
1229
- loaders: { ".ts": tsLoader }
1505
+ loaders: {
1506
+ ".ts": tsLoader,
1507
+ ".mts": tsLoader,
1508
+ ".cts": tsLoader
1509
+ }
1230
1510
  });
1231
1511
  try {
1232
1512
  result = config ? await explorer.load(config) : await explorer.search();
@@ -1254,91 +1534,88 @@ async function startWatcher(path, cb) {
1254
1534
  }
1255
1535
  //#endregion
1256
1536
  //#region src/runners/generate.ts
1257
- async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, configName, outputPath, logLevel, events, onStart, onEnd }) {
1537
+ async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, configName, outputPath, logLevel, hooks, onStart, onEnd }) {
1258
1538
  await onStart();
1259
1539
  let resolvedTool = toolValue;
1260
1540
  if (resolvedTool === "auto") {
1261
1541
  const detected = await detect();
1262
- if (!detected) await events.emit("warn", noToolMessage);
1542
+ if (!detected) await hooks.emit("kubb:warn", { message: noToolMessage });
1263
1543
  else {
1264
1544
  resolvedTool = detected;
1265
- await events.emit("info", `Auto-detected ${toolLabel}: ${(0, node_util.styleText)("dim", resolvedTool)}`);
1545
+ await hooks.emit("kubb:info", { message: `Auto-detected ${toolLabel}: ${(0, node_util.styleText)("dim", resolvedTool)}` });
1266
1546
  }
1267
1547
  }
1548
+ let toolError;
1268
1549
  if (resolvedTool && resolvedTool !== "auto" && resolvedTool in toolMap) {
1269
1550
  const toolConfig = toolMap[resolvedTool];
1270
1551
  try {
1271
1552
  const hookId = (0, node_crypto.createHash)("sha256").update([configName, resolvedTool].filter(Boolean).join("-")).digest("hex");
1272
1553
  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}`));
1554
+ const handler = (ctx) => {
1555
+ if (ctx.id !== hookId) return;
1556
+ hooks.off("kubb:hook:end", handler);
1557
+ if (!ctx.success) {
1558
+ reject(ctx.error ?? /* @__PURE__ */ new Error(`${toolConfig.errorMessage}`));
1278
1559
  return;
1279
1560
  }
1280
- events.emit("success", [
1561
+ hooks.emit("kubb:success", { message: [
1281
1562
  `${successPrefix} with ${(0, node_util.styleText)("dim", resolvedTool)}`,
1282
1563
  logLevel >= _kubb_core.logLevel.info ? `on ${(0, node_util.styleText)("dim", outputPath)}` : void 0,
1283
1564
  "successfully"
1284
- ].filter(Boolean).join(" ")).then(resolve).catch(reject);
1565
+ ].filter(Boolean).join(" ") }).then(resolve).catch(reject);
1285
1566
  };
1286
- events.on("hook:end", handler);
1567
+ hooks.on("kubb:hook:end", handler);
1287
1568
  });
1288
- await events.emit("hook:start", {
1569
+ await hooks.emit("kubb:hook:start", {
1289
1570
  id: hookId,
1290
1571
  command: toolConfig.command,
1291
1572
  args: toolConfig.args(outputPath)
1292
1573
  });
1293
1574
  await hookEndPromise;
1294
1575
  } catch (caughtError) {
1295
- const err = new Error(toolConfig.errorMessage);
1296
- err.cause = caughtError;
1297
- await events.emit("error", err);
1576
+ const err = require_errors.toError(caughtError);
1577
+ await hooks.emit("kubb:error", { error: err });
1578
+ toolError = err;
1298
1579
  }
1299
1580
  }
1300
1581
  await onEnd();
1582
+ if (toolError) throw toolError;
1301
1583
  }
1302
- async function generate({ input, config: userConfig, events, logLevel }) {
1303
- const inputPath = input ?? ("path" in userConfig.input ? userConfig.input.path : void 0);
1584
+ async function generate(options) {
1585
+ const { input, hooks, logLevel } = options;
1304
1586
  const hrStart = node_process.default.hrtime();
1587
+ const inputPath = input ?? ("path" in options.config.input ? options.config.input.path : void 0);
1305
1588
  const config = {
1306
- ...userConfig,
1307
- root: userConfig.root || node_process.default.cwd(),
1589
+ ...options.config,
1308
1590
  input: inputPath ? {
1309
- ...userConfig.input,
1591
+ ...options.config.input,
1310
1592
  path: inputPath
1311
- } : userConfig.input,
1312
- output: {
1313
- write: true,
1314
- barrelType: "named",
1315
- extension: { ".ts": ".ts" },
1316
- format: "prettier",
1317
- ...userConfig.output
1318
- }
1593
+ } : options.config.input,
1594
+ ...options.config.output
1319
1595
  };
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
1596
+ const kubb = (0, _kubb_core.createKubb)(config, { hooks });
1597
+ await kubb.setup();
1598
+ await hooks.emit("kubb:generation:start", { config });
1599
+ await hooks.emit("kubb:info", {
1600
+ message: config.name ? `Setup generation ${(0, node_util.styleText)("bold", config.name)}` : "Setup generation",
1601
+ info: inputPath
1325
1602
  });
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
1603
+ await hooks.emit("kubb:info", {
1604
+ message: config.name ? `Build generation ${(0, node_util.styleText)("bold", config.name)}` : "Build generation",
1605
+ info: inputPath
1335
1606
  });
1336
- await events.emit("info", "Load summary");
1607
+ const { files, failedPlugins, pluginTimings, error, driver } = await kubb.safeBuild();
1608
+ await hooks.emit("kubb:info", { message: "Load summary" });
1337
1609
  if (failedPlugins.size > 0 || error) {
1338
1610
  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, {
1611
+ for (const err of allErrors) await hooks.emit("kubb:error", { error: err });
1612
+ await hooks.emit("kubb:generation:end", {
1613
+ config,
1614
+ files,
1615
+ sources: kubb.sources
1616
+ });
1617
+ await hooks.emit("kubb:generation:summary", {
1618
+ config,
1342
1619
  failedPlugins,
1343
1620
  filesCreated: files.length,
1344
1621
  status: "failed",
@@ -1348,7 +1625,7 @@ async function generate({ input, config: userConfig, events, logLevel }) {
1348
1625
  await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
1349
1626
  command: "generate",
1350
1627
  kubbVersion: require_package.version,
1351
- plugins: driver.plugins.map((p) => ({
1628
+ plugins: Array.from(driver.plugins.values(), (p) => ({
1352
1629
  name: p.name,
1353
1630
  options: p.options
1354
1631
  })),
@@ -1358,46 +1635,54 @@ async function generate({ input, config: userConfig, events, logLevel }) {
1358
1635
  }));
1359
1636
  node_process.default.exit(1);
1360
1637
  }
1361
- await events.emit("success", "Generation successfully", inputPath);
1362
- await events.emit("generation:end", config, files, sources);
1638
+ await hooks.emit("kubb:success", {
1639
+ message: "Generation successfully",
1640
+ info: inputPath
1641
+ });
1642
+ await hooks.emit("kubb:generation:end", {
1643
+ config,
1644
+ files,
1645
+ sources: kubb.sources
1646
+ });
1363
1647
  const outputPath = node_path.default.resolve(config.root, config.output.path);
1364
1648
  if (config.output.format) await runToolPass({
1365
1649
  toolValue: config.output.format,
1366
- detect: _kubb_core.detectFormatter,
1367
- toolMap: _kubb_core.formatters,
1650
+ detect: detectFormatter,
1651
+ toolMap: formatters,
1368
1652
  toolLabel: "formatter",
1369
1653
  successPrefix: "Formatting",
1370
- noToolMessage: "No formatter found (biome, prettier, or oxfmt). Skipping formatting.",
1654
+ noToolMessage: "No formatter found (oxfmt, biome, or prettier). Skipping formatting.",
1371
1655
  configName: config.name,
1372
1656
  outputPath,
1373
1657
  logLevel,
1374
- events,
1375
- onStart: () => events.emit("format:start"),
1376
- onEnd: () => events.emit("format:end")
1658
+ hooks,
1659
+ onStart: () => hooks.emit("kubb:format:start"),
1660
+ onEnd: () => hooks.emit("kubb:format:end")
1377
1661
  });
1378
1662
  if (config.output.lint) await runToolPass({
1379
1663
  toolValue: config.output.lint,
1380
- detect: _kubb_core.detectLinter,
1381
- toolMap: _kubb_core.linters,
1664
+ detect: detectLinter,
1665
+ toolMap: linters,
1382
1666
  toolLabel: "linter",
1383
1667
  successPrefix: "Linting",
1384
- noToolMessage: "No linter found (biome, oxlint, or eslint). Skipping linting.",
1668
+ noToolMessage: "No linter found (oxlint, biome, or eslint). Skipping linting.",
1385
1669
  configName: config.name,
1386
1670
  outputPath,
1387
1671
  logLevel,
1388
- events,
1389
- onStart: () => events.emit("lint:start"),
1390
- onEnd: () => events.emit("lint:end")
1672
+ hooks,
1673
+ onStart: () => hooks.emit("kubb:lint:start"),
1674
+ onEnd: () => hooks.emit("kubb:lint:end")
1391
1675
  });
1392
1676
  if (config.hooks) {
1393
- await events.emit("hooks:start");
1677
+ await hooks.emit("kubb:hooks:start");
1394
1678
  await executeHooks({
1395
- hooks: config.hooks,
1396
- events
1679
+ configHooks: config.hooks,
1680
+ hooks
1397
1681
  });
1398
- await events.emit("hooks:end");
1682
+ await hooks.emit("kubb:hooks:end");
1399
1683
  }
1400
- await events.emit("generation:summary", config, {
1684
+ await hooks.emit("kubb:generation:summary", {
1685
+ config,
1401
1686
  failedPlugins,
1402
1687
  filesCreated: files.length,
1403
1688
  status: "success",
@@ -1407,7 +1692,7 @@ async function generate({ input, config: userConfig, events, logLevel }) {
1407
1692
  await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
1408
1693
  command: "generate",
1409
1694
  kubbVersion: require_package.version,
1410
- plugins: driver.plugins.map((p) => ({
1695
+ plugins: Array.from(driver.plugins.values(), (p) => ({
1411
1696
  name: p.name,
1412
1697
  options: p.options
1413
1698
  })),
@@ -1418,29 +1703,38 @@ async function generate({ input, config: userConfig, events, logLevel }) {
1418
1703
  }
1419
1704
  async function runGenerateCommand({ input, configPath, logLevel: logLevelKey, watch }) {
1420
1705
  const logLevel = _kubb_core.logLevel[logLevelKey] ?? _kubb_core.logLevel.info;
1421
- const events = new AsyncEventEmitter();
1422
- await setupLogger(events, { logLevel });
1706
+ const hooks = new AsyncEventEmitter();
1707
+ await setupLogger(hooks, { logLevel });
1423
1708
  await require_telemetry.executeIfOnline(async () => {
1424
1709
  try {
1425
1710
  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);
1711
+ if (latestVersion && require_package.version < latestVersion) await hooks.emit("kubb:version:new", {
1712
+ currentVersion: require_package.version,
1713
+ latestVersion
1714
+ });
1427
1715
  } catch {}
1428
1716
  });
1429
1717
  try {
1430
1718
  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);
1719
+ const configs = await getConfigs(result.config, { input });
1720
+ await hooks.emit("kubb:config:start");
1721
+ await hooks.emit("kubb:info", {
1722
+ message: "Config loaded",
1723
+ info: node_path.default.relative(node_process.default.cwd(), result.filepath)
1724
+ });
1725
+ await hooks.emit("kubb:success", {
1726
+ message: "Config loaded successfully",
1727
+ info: node_path.default.relative(node_process.default.cwd(), result.filepath)
1728
+ });
1729
+ await hooks.emit("kubb:config:end", { configs });
1730
+ await hooks.emit("kubb:lifecycle:start", { version: require_package.version });
1437
1731
  for (const config of configs) if ((0, _kubb_core.isInputPath)(config) && watch) await startWatcher([input || config.input.path], async (paths) => {
1438
- events.removeAll();
1732
+ hooks.removeAll();
1439
1733
  await generate({
1440
1734
  input,
1441
1735
  config,
1442
1736
  logLevel,
1443
- events
1737
+ hooks
1444
1738
  });
1445
1739
  _clack_prompts.log.step((0, node_util.styleText)("yellow", `Watching for changes in ${paths.join(" and ")}`));
1446
1740
  });
@@ -1448,15 +1742,15 @@ async function runGenerateCommand({ input, configPath, logLevel: logLevelKey, wa
1448
1742
  input,
1449
1743
  config,
1450
1744
  logLevel,
1451
- events
1745
+ hooks
1452
1746
  });
1453
- await events.emit("lifecycle:end");
1747
+ await hooks.emit("kubb:lifecycle:end");
1454
1748
  } catch (error) {
1455
- await events.emit("error", require_errors.toError(error));
1749
+ await hooks.emit("kubb:error", { error: require_errors.toError(error) });
1456
1750
  node_process.default.exit(1);
1457
1751
  }
1458
1752
  }
1459
1753
  //#endregion
1460
1754
  exports.runGenerateCommand = runGenerateCommand;
1461
1755
 
1462
- //# sourceMappingURL=generate-Cq5RDTBL.cjs.map
1756
+ //# sourceMappingURL=generate-B3jl4ukb.cjs.map