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