@kubb/cli 4.32.4 → 4.33.1

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 (133) hide show
  1. package/dist/agent-Bd1QdPVV.cjs +91 -0
  2. package/dist/agent-Bd1QdPVV.cjs.map +1 -0
  3. package/dist/agent-D83d9Pud.cjs +60 -0
  4. package/dist/agent-D83d9Pud.cjs.map +1 -0
  5. package/dist/agent-DgKQXSmR.js +57 -0
  6. package/dist/agent-DgKQXSmR.js.map +1 -0
  7. package/dist/agent-u_Ehwz6r.js +87 -0
  8. package/dist/agent-u_Ehwz6r.js.map +1 -0
  9. package/dist/constants-BTUap0zs.cjs +108 -0
  10. package/dist/constants-BTUap0zs.cjs.map +1 -0
  11. package/dist/constants-CM3dJzjK.js +67 -0
  12. package/dist/constants-CM3dJzjK.js.map +1 -0
  13. package/dist/define--M_JMcDC.js +25 -0
  14. package/dist/define--M_JMcDC.js.map +1 -0
  15. package/dist/define-D6Kfm7-Z.cjs +36 -0
  16. package/dist/define-D6Kfm7-Z.cjs.map +1 -0
  17. package/dist/errors-6mF_WKxg.js +27 -0
  18. package/dist/errors-6mF_WKxg.js.map +1 -0
  19. package/dist/errors-DBW0N9w4.cjs +44 -0
  20. package/dist/errors-DBW0N9w4.cjs.map +1 -0
  21. package/dist/generate-Bn8n4w1O.cjs +65 -0
  22. package/dist/generate-Bn8n4w1O.cjs.map +1 -0
  23. package/dist/{generate-CpWtSc45.js → generate-CAsV9wSx.js} +656 -689
  24. package/dist/generate-CAsV9wSx.js.map +1 -0
  25. package/dist/generate-D-59YK0L.js +66 -0
  26. package/dist/generate-D-59YK0L.js.map +1 -0
  27. package/dist/{generate-COj0aMS6.cjs → generate-JC65igQh.cjs} +662 -694
  28. package/dist/generate-JC65igQh.cjs.map +1 -0
  29. package/dist/index.cjs +226 -35
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.ts +1 -1
  32. package/dist/index.js +226 -35
  33. package/dist/index.js.map +1 -1
  34. package/dist/init-C-InrmSY.js +302 -0
  35. package/dist/init-C-InrmSY.js.map +1 -0
  36. package/dist/init-CXP8OfMe.js +25 -0
  37. package/dist/init-CXP8OfMe.js.map +1 -0
  38. package/dist/init-CbeE-L-0.cjs +25 -0
  39. package/dist/init-CbeE-L-0.cjs.map +1 -0
  40. package/dist/init-hmolV6B4.cjs +306 -0
  41. package/dist/init-hmolV6B4.cjs.map +1 -0
  42. package/dist/jiti-Cd3S0xwr.cjs +16 -0
  43. package/dist/jiti-Cd3S0xwr.cjs.map +1 -0
  44. package/dist/jiti-e08mD2Ph.js +11 -0
  45. package/dist/jiti-e08mD2Ph.js.map +1 -0
  46. package/dist/mcp-BDxg2oJm.cjs +16 -0
  47. package/dist/mcp-BDxg2oJm.cjs.map +1 -0
  48. package/dist/mcp-ChHFPRzD.cjs +42 -0
  49. package/dist/mcp-ChHFPRzD.cjs.map +1 -0
  50. package/dist/mcp-D2SHEg_d.js +41 -0
  51. package/dist/mcp-D2SHEg_d.js.map +1 -0
  52. package/dist/mcp-MSoE4vNA.js +16 -0
  53. package/dist/mcp-MSoE4vNA.js.map +1 -0
  54. package/dist/{package-aNQWvWbS.cjs → package-CUVyeIbt.cjs} +2 -2
  55. package/dist/package-CUVyeIbt.cjs.map +1 -0
  56. package/dist/package-Cbd8OC6q.js +6 -0
  57. package/dist/package-Cbd8OC6q.js.map +1 -0
  58. package/dist/shell-7HPrTCJ5.cjs +57 -0
  59. package/dist/shell-7HPrTCJ5.cjs.map +1 -0
  60. package/dist/shell-DqqWsHCD.js +46 -0
  61. package/dist/shell-DqqWsHCD.js.map +1 -0
  62. package/dist/{telemetry-BDSSqUiG.cjs → telemetry-Cn9X1I5B.cjs} +79 -9
  63. package/dist/telemetry-Cn9X1I5B.cjs.map +1 -0
  64. package/dist/{telemetry-DYWvlxqs.js → telemetry-DxiR7clS.js} +63 -11
  65. package/dist/telemetry-DxiR7clS.js.map +1 -0
  66. package/dist/validate-BG8A3aQS.cjs +25 -0
  67. package/dist/validate-BG8A3aQS.cjs.map +1 -0
  68. package/dist/validate-BZ1UFkwA.js +25 -0
  69. package/dist/validate-BZ1UFkwA.js.map +1 -0
  70. package/dist/validate-Bbrn3Q-A.cjs +42 -0
  71. package/dist/validate-Bbrn3Q-A.cjs.map +1 -0
  72. package/dist/validate-l8vLmwKA.js +41 -0
  73. package/dist/validate-l8vLmwKA.js.map +1 -0
  74. package/package.json +6 -6
  75. package/src/commands/agent/start.ts +27 -136
  76. package/src/commands/agent.ts +6 -25
  77. package/src/commands/generate.ts +26 -158
  78. package/src/commands/init.ts +9 -360
  79. package/src/commands/mcp.ts +7 -52
  80. package/src/commands/validate.ts +9 -60
  81. package/src/constants.ts +76 -0
  82. package/src/index.ts +36 -42
  83. package/src/loggers/clackLogger.ts +65 -165
  84. package/src/loggers/fileSystemLogger.ts +2 -14
  85. package/src/loggers/githubActionsLogger.ts +58 -125
  86. package/src/loggers/plainLogger.ts +44 -92
  87. package/src/loggers/utils.ts +67 -4
  88. package/src/runners/agent.ts +100 -0
  89. package/src/runners/generate.ts +223 -102
  90. package/src/runners/init.ts +323 -0
  91. package/src/runners/mcp.ts +32 -0
  92. package/src/runners/validate.ts +35 -0
  93. package/src/utils/Writables.ts +2 -2
  94. package/src/utils/executeHooks.ts +20 -8
  95. package/src/utils/getCosmiConfig.ts +10 -11
  96. package/src/utils/getIntro.ts +1 -81
  97. package/src/utils/getSummary.ts +12 -17
  98. package/src/utils/jiti.ts +9 -0
  99. package/src/utils/packageManager.ts +4 -4
  100. package/src/utils/runHook.ts +75 -0
  101. package/src/utils/telemetry.ts +8 -26
  102. package/src/utils/watcher.ts +2 -4
  103. package/dist/agent-6COck3B9.cjs +0 -20
  104. package/dist/agent-6COck3B9.cjs.map +0 -1
  105. package/dist/agent-DMm6c5Vg.js +0 -20
  106. package/dist/agent-DMm6c5Vg.js.map +0 -1
  107. package/dist/generate-COj0aMS6.cjs.map +0 -1
  108. package/dist/generate-CpWtSc45.js.map +0 -1
  109. package/dist/init-Bdn3_qir.js +0 -304
  110. package/dist/init-Bdn3_qir.js.map +0 -1
  111. package/dist/init-CFW2kWY8.cjs +0 -308
  112. package/dist/init-CFW2kWY8.cjs.map +0 -1
  113. package/dist/mcp-DkwtARfo.cjs +0 -57
  114. package/dist/mcp-DkwtARfo.cjs.map +0 -1
  115. package/dist/mcp-DrH93Vq4.js +0 -57
  116. package/dist/mcp-DrH93Vq4.js.map +0 -1
  117. package/dist/package-BnJbGmLm.js +0 -6
  118. package/dist/package-BnJbGmLm.js.map +0 -1
  119. package/dist/package-aNQWvWbS.cjs.map +0 -1
  120. package/dist/start-CqTUu14n.js +0 -131
  121. package/dist/start-CqTUu14n.js.map +0 -1
  122. package/dist/start-D-rsIJGo.cjs +0 -134
  123. package/dist/start-D-rsIJGo.cjs.map +0 -1
  124. package/dist/telemetry-BDSSqUiG.cjs.map +0 -1
  125. package/dist/telemetry-DYWvlxqs.js.map +0 -1
  126. package/dist/validate-BlV8L8gC.js +0 -66
  127. package/dist/validate-BlV8L8gC.js.map +0 -1
  128. package/dist/validate-COhZUXF8.cjs +0 -66
  129. package/dist/validate-COhZUXF8.cjs.map +0 -1
  130. package/src/loggers/envDetection.ts +0 -28
  131. package/src/loggers/index.ts +0 -5
  132. package/src/utils/formatMsWithColor.ts +0 -22
  133. package/src/utils/randomColor.ts +0 -23
@@ -1,78 +1,146 @@
1
1
  const require_chunk = require("./chunk-ByKO4r7w.cjs");
2
- const require_package = require("./package-aNQWvWbS.cjs");
3
- const require_telemetry = require("./telemetry-BDSSqUiG.cjs");
2
+ const require_errors = require("./errors-DBW0N9w4.cjs");
3
+ const require_telemetry = require("./telemetry-Cn9X1I5B.cjs");
4
+ const require_shell = require("./shell-7HPrTCJ5.cjs");
5
+ const require_package = require("./package-CUVyeIbt.cjs");
6
+ const require_constants = require("./constants-BTUap0zs.cjs");
4
7
  let node_util = require("node:util");
5
- let citty = require("citty");
8
+ let node_events = require("node:events");
6
9
  let node_crypto = require("node:crypto");
7
- let node_process = require("node:process");
8
- node_process = require_chunk.__toESM(node_process);
9
- let _kubb_core_utils = require("@kubb/core/utils");
10
+ require("node:fs");
11
+ let node_fs_promises = require("node:fs/promises");
10
12
  let node_path = require("node:path");
11
13
  node_path = require_chunk.__toESM(node_path);
14
+ let node_process = require("node:process");
15
+ node_process = require_chunk.__toESM(node_process);
12
16
  let _clack_prompts = require("@clack/prompts");
13
17
  _clack_prompts = require_chunk.__toESM(_clack_prompts);
14
18
  let _kubb_core = require("@kubb/core");
15
19
  let tinyexec = require("tinyexec");
16
20
  let node_stream = require("node:stream");
17
- let _kubb_core_fs = require("@kubb/core/fs");
18
21
  let cosmiconfig = require("cosmiconfig");
19
22
  let jiti = require("jiti");
20
- //#region src/utils/formatMsWithColor.ts
23
+ //#region ../../internals/utils/src/asyncEventEmitter.ts
21
24
  /**
22
- * Formats milliseconds with color based on duration thresholds:
23
- * - Green: <= 500ms
24
- * - Yellow: > 500ms and <= 1000ms
25
- * - Red: > 1000ms
25
+ * A typed EventEmitter that awaits all async listeners before resolving.
26
+ * Wraps Node's `EventEmitter` with full TypeScript event-map inference.
26
27
  */
27
- function formatMsWithColor(ms) {
28
- const formatted = (0, _kubb_core_utils.formatMs)(ms);
29
- if (ms <= 500) return (0, node_util.styleText)("green", formatted);
30
- if (ms <= 1e3) return (0, node_util.styleText)("yellow", formatted);
31
- return (0, node_util.styleText)("red", formatted);
32
- }
28
+ var AsyncEventEmitter = class {
29
+ /**
30
+ * `maxListener` controls the maximum number of listeners per event before Node emits a memory-leak warning.
31
+ * @default 10
32
+ */
33
+ constructor(maxListener = 10) {
34
+ this.#emitter.setMaxListeners(maxListener);
35
+ }
36
+ #emitter = new node_events.EventEmitter();
37
+ /**
38
+ * Emits an event and awaits all registered listeners in parallel.
39
+ * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
40
+ */
41
+ async emit(eventName, ...eventArgs) {
42
+ const listeners = this.#emitter.listeners(eventName);
43
+ if (listeners.length === 0) return;
44
+ await Promise.all(listeners.map(async (listener) => {
45
+ 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) });
55
+ }
56
+ }));
57
+ }
58
+ /** Registers a persistent listener for the given event. */
59
+ on(eventName, handler) {
60
+ this.#emitter.on(eventName, handler);
61
+ }
62
+ /** Registers a one-shot listener that removes itself after the first invocation. */
63
+ onOnce(eventName, handler) {
64
+ const wrapper = (...args) => {
65
+ this.off(eventName, wrapper);
66
+ return handler(...args);
67
+ };
68
+ this.on(eventName, wrapper);
69
+ }
70
+ /** Removes a previously registered listener. */
71
+ off(eventName, handler) {
72
+ this.#emitter.off(eventName, handler);
73
+ }
74
+ /** Removes all listeners from every event channel. */
75
+ removeAll() {
76
+ this.#emitter.removeAllListeners();
77
+ }
78
+ };
33
79
  //#endregion
34
- //#region src/utils/getIntro.ts
80
+ //#region ../../internals/utils/src/time.ts
35
81
  /**
36
- * ANSI True Color (24-bit) utilities for terminal output
37
- * Supports hex color codes without external dependencies like chalk
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.
38
84
  */
85
+ function getElapsedMs(hrStart) {
86
+ const [seconds, nanoseconds] = process.hrtime(hrStart);
87
+ const ms = seconds * 1e3 + nanoseconds / 1e6;
88
+ return Math.round(ms * 100) / 100;
89
+ }
39
90
  /**
40
- * Convert hex color to ANSI 24-bit true color escape sequence
41
- * @param color - Hex color code (with or without #), e.g., '#FF5500' or 'FF5500'
42
- * @returns Function that wraps text with the color
91
+ * Converts a millisecond duration into a human-readable string.
92
+ * Adjusts units (ms, s, m s) based on the magnitude of the duration.
43
93
  */
44
- function hex(color) {
45
- const cleanHex = color.replace("#", "");
46
- const r = Number.parseInt(cleanHex.slice(0, 2), 16);
47
- const g = Number.parseInt(cleanHex.slice(2, 4), 16);
48
- const b = Number.parseInt(cleanHex.slice(4, 6), 16);
49
- const safeR = Number.isNaN(r) ? 255 : r;
50
- const safeG = Number.isNaN(g) ? 255 : g;
51
- const safeB = Number.isNaN(b) ? 255 : b;
52
- return (text) => `\x1b[38;2;${safeR};${safeG};${safeB}m${text}\x1b[0m`;
94
+ function formatMs(ms) {
95
+ if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
96
+ if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
97
+ return `${Math.round(ms)}ms`;
53
98
  }
54
- function hexToRgb(color) {
55
- const c = color.replace("#", "");
56
- return {
57
- r: Number.parseInt(c.slice(0, 2), 16),
58
- g: Number.parseInt(c.slice(2, 4), 16),
59
- b: Number.parseInt(c.slice(4, 6), 16)
60
- };
99
+ /**
100
+ * Convenience helper: formats the elapsed time since `hrStart` in one step.
101
+ */
102
+ function formatHrtime(hrStart) {
103
+ return formatMs(getElapsedMs(hrStart));
61
104
  }
62
- function gradient(colors) {
63
- return (text) => {
64
- const chars = [...text];
65
- return chars.map((char, i) => {
66
- const t = chars.length <= 1 ? 0 : i / (chars.length - 1);
67
- const seg = Math.min(Math.floor(t * (colors.length - 1)), colors.length - 2);
68
- const lt = t * (colors.length - 1) - seg;
69
- const from = hexToRgb(colors[seg]);
70
- const to = hexToRgb(colors[seg + 1]);
71
- 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`;
72
- }).join("");
105
+ //#endregion
106
+ //#region ../../internals/utils/src/colors.ts
107
+ /**
108
+ * Parses a CSS hex color string (`#RGB`) into its RGB channels.
109
+ * Falls back to `255` for any channel that cannot be parsed.
110
+ */
111
+ function parseHex(color) {
112
+ const int = Number.parseInt(color.replace("#", ""), 16);
113
+ return Number.isNaN(int) ? {
114
+ r: 255,
115
+ g: 255,
116
+ b: 255
117
+ } : {
118
+ r: int >> 16 & 255,
119
+ g: int >> 8 & 255,
120
+ b: int & 255
73
121
  };
74
122
  }
75
- const colors = {
123
+ /**
124
+ * Returns a function that wraps a string in a 24-bit ANSI true-color escape sequence
125
+ * for the given hex color.
126
+ */
127
+ function hex(color) {
128
+ const { r, g, b } = parseHex(color);
129
+ return (text) => `\x1b[38;2;${r};${g};${b}m${text}\x1b[0m`;
130
+ }
131
+ function gradient(colorStops, text) {
132
+ const chars = text.split("");
133
+ return chars.map((char, i) => {
134
+ const t = chars.length <= 1 ? 0 : i / (chars.length - 1);
135
+ const seg = Math.min(Math.floor(t * (colorStops.length - 1)), colorStops.length - 2);
136
+ const lt = t * (colorStops.length - 1) - seg;
137
+ const from = parseHex(colorStops[seg]);
138
+ const to = parseHex(colorStops[seg + 1]);
139
+ 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
+ }).join("");
141
+ }
142
+ /** ANSI color functions for each part of the Kubb mascot illustration. */
143
+ const palette = {
76
144
  lid: hex("#F55A17"),
77
145
  woodTop: hex("#F5A217"),
78
146
  woodMid: hex("#F58517"),
@@ -82,57 +150,94 @@ const colors = {
82
150
  blush: hex("#FDA4AF")
83
151
  };
84
152
  /**
85
- * Generates the Kubb mascot face welcome message
86
- * @param version - The version string to display
87
- * @returns Formatted mascot face string
153
+ * Generates the Kubb mascot welcome banner.
88
154
  */
89
155
  function getIntro({ title, description, version, areEyesOpen }) {
90
156
  const kubbVersion = gradient([
91
157
  "#F58517",
92
158
  "#F5A217",
93
159
  "#F55A17"
94
- ])(`KUBB v${version}`);
95
- const eyeTop = areEyesOpen ? colors.eye("█▀█") : colors.eye("───");
96
- const eyeBottom = areEyesOpen ? colors.eye("▀▀▀") : colors.eye("───");
160
+ ], `KUBB v${version}`);
161
+ const eyeTop = areEyesOpen ? palette.eye("█▀█") : palette.eye("───");
162
+ const eyeBottom = areEyesOpen ? palette.eye("▀▀▀") : palette.eye("───");
97
163
  return `
98
- ${colors.lid("▄▄▄▄▄▄▄▄▄▄▄▄▄")}
99
- ${colors.woodTop("█ ")}${colors.highlight("▄▄")}${colors.woodTop(" ")}${colors.highlight("▄▄")}${colors.woodTop(" █")} ${kubbVersion}
100
- ${colors.woodMid("█ ")}${eyeTop}${colors.woodMid(" ")}${eyeTop}${colors.woodMid(" █")} ${(0, node_util.styleText)("gray", title)}
101
- ${colors.woodMid("█ ")}${eyeBottom}${colors.woodMid(" ")}${colors.blush("◡")}${colors.woodMid(" ")}${eyeBottom}${colors.woodMid(" █")} ${(0, node_util.styleText)("yellow", "➜")} ${(0, node_util.styleText)("white", description)}
102
- ${colors.woodBase("▀▀▀▀▀▀▀▀▀▀▀▀▀")}
164
+ ${palette.lid("▄▄▄▄▄▄▄▄▄▄▄▄▄")}
165
+ ${palette.woodTop("█ ")}${palette.highlight("▄▄")}${palette.woodTop(" ")}${palette.highlight("▄▄")}${palette.woodTop(" █")} ${kubbVersion}
166
+ ${palette.woodMid("█ ")}${eyeTop}${palette.woodMid(" ")}${eyeTop}${palette.woodMid(" █")} ${(0, node_util.styleText)("gray", title)}
167
+ ${palette.woodMid("█ ")}${eyeBottom}${palette.woodMid(" ")}${palette.blush("◡")}${palette.woodMid(" ")}${eyeBottom}${palette.woodMid(" █")} ${(0, node_util.styleText)("yellow", "➜")} ${(0, node_util.styleText)("white", description)}
168
+ ${palette.woodBase("▀▀▀▀▀▀▀▀▀▀▀▀▀")}
103
169
  `;
104
170
  }
105
- //#endregion
106
- //#region src/utils/randomColor.ts
107
- function randomColor(text) {
108
- if (!text) return "white";
109
- const defaultColors = [
110
- "black",
111
- "red",
112
- "green",
113
- "yellow",
114
- "blue",
115
- "red",
116
- "green",
117
- "magenta",
118
- "cyan",
119
- "gray"
120
- ];
121
- return defaultColors[(0, node_crypto.createHash)("sha256").update(text).digest().readUInt32BE(0) % defaultColors.length] ?? "white";
122
- }
171
+ /** ANSI color names available for terminal output. */
172
+ const randomColors = [
173
+ "black",
174
+ "red",
175
+ "green",
176
+ "yellow",
177
+ "blue",
178
+ "white",
179
+ "magenta",
180
+ "cyan",
181
+ "gray"
182
+ ];
183
+ /**
184
+ * Returns the text wrapped in a deterministic ANSI color derived from the text's SHA-256 hash.
185
+ */
123
186
  function randomCliColor(text) {
124
187
  if (!text) return "";
125
- return (0, node_util.styleText)(randomColor(text), text);
188
+ return (0, node_util.styleText)(randomColors[(0, node_crypto.createHash)("sha256").update(text).digest().readUInt32BE(0) % randomColors.length] ?? "white", text);
189
+ }
190
+ /**
191
+ * Formats a millisecond duration with an ANSI color based on thresholds:
192
+ * green ≤ 500 ms · yellow ≤ 1 000 ms · red > 1 000 ms
193
+ */
194
+ function formatMsWithColor(ms) {
195
+ const formatted = formatMs(ms);
196
+ if (ms <= 500) return (0, node_util.styleText)("green", formatted);
197
+ if (ms <= 1e3) return (0, node_util.styleText)("yellow", formatted);
198
+ return (0, node_util.styleText)("red", formatted);
199
+ }
200
+ //#endregion
201
+ //#region ../../internals/utils/src/fs.ts
202
+ /**
203
+ * 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.
206
+ * 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 — useful for catching write failures on unreliable file systems.
209
+ */
210
+ async function write(path, data, options = {}) {
211
+ const trimmed = data.trim();
212
+ if (trimmed === "") return void 0;
213
+ const resolved = (0, node_path.resolve)(path);
214
+ if (typeof Bun !== "undefined") {
215
+ const file = Bun.file(resolved);
216
+ if ((await file.exists() ? await file.text() : null) === trimmed) return void 0;
217
+ await Bun.write(resolved, trimmed);
218
+ return trimmed;
219
+ }
220
+ try {
221
+ if (await (0, node_fs_promises.readFile)(resolved, { encoding: "utf-8" }) === trimmed) return void 0;
222
+ } catch {}
223
+ await (0, node_fs_promises.mkdir)((0, node_path.dirname)(resolved), { recursive: true });
224
+ await (0, node_fs_promises.writeFile)(resolved, trimmed, { encoding: "utf-8" });
225
+ if (options.sanity) {
226
+ const savedData = await (0, node_fs_promises.readFile)(resolved, { encoding: "utf-8" });
227
+ if (savedData !== trimmed) throw new Error(`Sanity check failed for ${path}\n\nData[${data.length}]:\n${data}\n\nSaved[${savedData.length}]:\n${savedData}\n`);
228
+ return savedData;
229
+ }
230
+ return trimmed;
126
231
  }
127
232
  //#endregion
128
233
  //#region src/utils/getSummary.ts
129
234
  function getSummary({ failedPlugins, filesCreated, status, hrStart, config, pluginTimings }) {
130
- const duration = (0, _kubb_core_utils.formatHrtime)(hrStart);
131
- const pluginsCount = config.plugins?.length || 0;
235
+ const duration = formatHrtime(hrStart);
236
+ const pluginsCount = config.plugins?.length ?? 0;
132
237
  const successCount = pluginsCount - failedPlugins.size;
133
238
  const meta = {
134
239
  plugins: status === "success" ? `${(0, node_util.styleText)("green", `${successCount} successful`)}, ${pluginsCount} total` : `${(0, node_util.styleText)("green", `${successCount} successful`)}, ${(0, node_util.styleText)("red", `${failedPlugins.size} failed`)}, ${pluginsCount} total`,
135
- pluginsFailed: status === "failed" ? [...failedPlugins]?.map(({ plugin }) => randomCliColor(plugin.name))?.join(", ") : void 0,
240
+ pluginsFailed: status === "failed" ? [...failedPlugins].map(({ plugin }) => randomCliColor(plugin.name)).join(", ") : void 0,
136
241
  filesCreated,
137
242
  time: (0, node_util.styleText)("green", duration),
138
243
  output: node_path.default.isAbsolute(config.root) ? node_path.default.resolve(config.root, config.output.path) : config.root
@@ -150,23 +255,76 @@ function getSummary({ failedPlugins, filesCreated, status, hrStart, config, plug
150
255
  if (meta.pluginsFailed) summaryLines.push(`${labels.failed.padEnd(maxLength + 2)} ${meta.pluginsFailed}`);
151
256
  summaryLines.push(`${labels.generated.padEnd(maxLength + 2)} ${meta.filesCreated} files in ${meta.time}`);
152
257
  if (pluginTimings && pluginTimings.size > 0) {
153
- const TIME_SCALE_DIVISOR = 100;
154
- const MAX_BAR_LENGTH = 10;
155
258
  const sortedTimings = Array.from(pluginTimings.entries()).sort((a, b) => b[1] - a[1]);
156
- if (sortedTimings.length > 0) {
157
- summaryLines.push(`${labels.pluginTimings}`);
158
- sortedTimings.forEach(([name, time]) => {
159
- const timeStr = time >= 1e3 ? `${(time / 1e3).toFixed(2)}s` : `${Math.round(time)}ms`;
160
- const barLength = Math.min(Math.ceil(time / TIME_SCALE_DIVISOR), MAX_BAR_LENGTH);
161
- const bar = (0, node_util.styleText)("dim", "".repeat(barLength));
162
- summaryLines.push(`${(0, node_util.styleText)("dim", "•")} ${name.padEnd(maxLength + 1)}${bar} ${timeStr}`);
163
- });
164
- }
259
+ summaryLines.push(`${labels.pluginTimings}`);
260
+ sortedTimings.forEach(([name, time]) => {
261
+ const timeStr = time >= 1e3 ? `${(time / 1e3).toFixed(2)}s` : `${Math.round(time)}ms`;
262
+ const barLength = Math.min(Math.ceil(time / 100), 10);
263
+ const bar = (0, node_util.styleText)("dim", "█".repeat(barLength));
264
+ summaryLines.push(`${(0, node_util.styleText)("dim", "")} ${name.padEnd(maxLength + 1)}${bar} ${timeStr}`);
265
+ });
165
266
  }
166
267
  summaryLines.push(`${labels.output.padEnd(maxLength + 2)} ${meta.output}`);
167
268
  return summaryLines;
168
269
  }
169
270
  //#endregion
271
+ //#region src/utils/runHook.ts
272
+ /**
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.
276
+ */
277
+ async function runHook({ id, command, args, commandWithArgs, context, stream = false, sink }) {
278
+ try {
279
+ const proc = (0, tinyexec.x)(command, [...args ?? []], {
280
+ nodeOptions: { detached: true },
281
+ throwOnError: true
282
+ });
283
+ if (stream && sink?.onLine) for await (const line of proc) sink.onLine(line);
284
+ const result = await proc;
285
+ await context.emit("debug", {
286
+ date: /* @__PURE__ */ new Date(),
287
+ logs: [result.stdout.trimEnd()]
288
+ });
289
+ await context.emit("hook:end", {
290
+ command,
291
+ args,
292
+ id,
293
+ success: true,
294
+ error: null
295
+ });
296
+ } catch (err) {
297
+ if (!(err instanceof tinyexec.NonZeroExitError)) {
298
+ await context.emit("hook:end", {
299
+ command,
300
+ args,
301
+ id,
302
+ success: false,
303
+ error: require_errors.toError(err)
304
+ });
305
+ await context.emit("error", require_errors.toError(err));
306
+ return;
307
+ }
308
+ const stderr = err.output?.stderr ?? "";
309
+ const stdout = err.output?.stdout ?? "";
310
+ await context.emit("debug", {
311
+ date: /* @__PURE__ */ new Date(),
312
+ logs: [stdout, stderr].filter(Boolean)
313
+ });
314
+ if (stderr) sink?.onStderr?.(stderr);
315
+ if (stdout) sink?.onStdout?.(stdout);
316
+ const errorMessage = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
317
+ await context.emit("hook:end", {
318
+ command,
319
+ args,
320
+ id,
321
+ success: false,
322
+ error: errorMessage
323
+ });
324
+ await context.emit("error", errorMessage);
325
+ }
326
+ }
327
+ //#endregion
170
328
  //#region src/utils/Writables.ts
171
329
  var ClackWritable = class extends node_stream.Writable {
172
330
  taskLog;
@@ -175,7 +333,7 @@ var ClackWritable = class extends node_stream.Writable {
175
333
  this.taskLog = taskLog;
176
334
  }
177
335
  _write(chunk, _encoding, callback) {
178
- this.taskLog.message(`${(0, node_util.styleText)("dim", chunk?.toString())}`);
336
+ this.taskLog.message(`${(0, node_util.styleText)("dim", chunk.toString())}`);
179
337
  callback();
180
338
  }
181
339
  };
@@ -188,7 +346,7 @@ var ClackWritable = class extends node_stream.Writable {
188
346
  const clackLogger = (0, _kubb_core.defineLogger)({
189
347
  name: "clack",
190
348
  install(context, options) {
191
- const logLevel = options?.logLevel || _kubb_core.LogLevel.info;
349
+ const logLevel = options?.logLevel ?? _kubb_core.logLevel.info;
192
350
  const state = {
193
351
  totalPlugins: 0,
194
352
  completedPlugins: 0,
@@ -216,27 +374,12 @@ const clackLogger = (0, _kubb_core.defineLogger)({
216
374
  state.activeProgress.clear();
217
375
  }
218
376
  function showProgressStep() {
219
- if (logLevel <= _kubb_core.LogLevel.silent) return;
220
- const parts = [];
221
- const duration = (0, _kubb_core_utils.formatHrtime)(state.hrStart);
222
- if (state.totalPlugins > 0) {
223
- const pluginStr = state.failedPlugins > 0 ? `Plugins ${(0, node_util.styleText)("green", state.completedPlugins.toString())}/${state.totalPlugins} ${(0, node_util.styleText)("red", `(${state.failedPlugins} failed)`)}` : `Plugins ${(0, node_util.styleText)("green", state.completedPlugins.toString())}/${state.totalPlugins}`;
224
- parts.push(pluginStr);
225
- }
226
- if (state.totalFiles > 0) parts.push(`Files ${(0, node_util.styleText)("green", state.processedFiles.toString())}/${state.totalFiles}`);
227
- if (parts.length > 0) {
228
- parts.push(`${(0, node_util.styleText)("green", duration)} elapsed`);
229
- _clack_prompts.log.step(getMessage(parts.join((0, node_util.styleText)("dim", " | "))));
230
- }
377
+ if (logLevel <= _kubb_core.logLevel.silent) return;
378
+ const line = buildProgressLine(state);
379
+ if (line) _clack_prompts.log.step(getMessage(line));
231
380
  }
232
381
  function getMessage(message) {
233
- if (logLevel >= _kubb_core.LogLevel.verbose) return [(0, node_util.styleText)("dim", `[${(/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
234
- hour12: false,
235
- hour: "2-digit",
236
- minute: "2-digit",
237
- second: "2-digit"
238
- })}]`), message].join(" ");
239
- return message;
382
+ return formatMessage(message, logLevel);
240
383
  }
241
384
  function startSpinner(text) {
242
385
  state.spinner.start(text);
@@ -247,7 +390,7 @@ const clackLogger = (0, _kubb_core.defineLogger)({
247
390
  state.isSpinning = false;
248
391
  }
249
392
  context.on("info", (message, info = "") => {
250
- if (logLevel <= _kubb_core.LogLevel.silent) return;
393
+ if (logLevel <= _kubb_core.logLevel.silent) return;
251
394
  const text = getMessage([
252
395
  (0, node_util.styleText)("blue", "ℹ"),
253
396
  message,
@@ -257,30 +400,30 @@ const clackLogger = (0, _kubb_core.defineLogger)({
257
400
  else _clack_prompts.log.info(text);
258
401
  });
259
402
  context.on("success", (message, info = "") => {
260
- if (logLevel <= _kubb_core.LogLevel.silent) return;
403
+ if (logLevel <= _kubb_core.logLevel.silent) return;
261
404
  const text = getMessage([
262
405
  (0, node_util.styleText)("blue", "✓"),
263
406
  message,
264
- logLevel >= _kubb_core.LogLevel.info ? (0, node_util.styleText)("dim", info) : void 0
407
+ logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", info) : void 0
265
408
  ].filter(Boolean).join(" "));
266
409
  if (state.isSpinning) stopSpinner(text);
267
410
  else _clack_prompts.log.success(text);
268
411
  });
269
412
  context.on("warn", (message, info) => {
270
- if (logLevel < _kubb_core.LogLevel.warn) return;
413
+ if (logLevel < _kubb_core.logLevel.warn) return;
271
414
  const text = getMessage([
272
415
  (0, node_util.styleText)("yellow", "⚠"),
273
416
  message,
274
- logLevel >= _kubb_core.LogLevel.info && info ? (0, node_util.styleText)("dim", info) : void 0
417
+ logLevel >= _kubb_core.logLevel.info && info ? (0, node_util.styleText)("dim", info) : void 0
275
418
  ].filter(Boolean).join(" "));
276
419
  _clack_prompts.log.warn(text);
277
420
  });
278
421
  context.on("error", (error) => {
279
- const caused = error.cause;
422
+ const caused = require_errors.toCause(error);
280
423
  const text = [(0, node_util.styleText)("red", "✗"), error.message].join(" ");
281
424
  if (state.isSpinning) stopSpinner(getMessage(text));
282
425
  else _clack_prompts.log.error(getMessage(text));
283
- if (logLevel >= _kubb_core.LogLevel.debug && error.stack) {
426
+ if (logLevel >= _kubb_core.logLevel.debug && error.stack) {
284
427
  const frames = error.stack.split("\n").slice(1, 4);
285
428
  for (const frame of frames) _clack_prompts.log.message(getMessage((0, node_util.styleText)("dim", frame.trim())));
286
429
  if (caused?.stack) {
@@ -291,7 +434,7 @@ const clackLogger = (0, _kubb_core.defineLogger)({
291
434
  }
292
435
  });
293
436
  context.on("version:new", (version, latestVersion) => {
294
- if (logLevel <= _kubb_core.LogLevel.silent) return;
437
+ if (logLevel <= _kubb_core.logLevel.silent) return;
295
438
  _clack_prompts.box(`\`v${version}\` → \`v${latestVersion}\`
296
439
  Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
297
440
  width: "auto",
@@ -312,24 +455,24 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
312
455
  reset();
313
456
  });
314
457
  context.on("config:start", () => {
315
- if (logLevel <= _kubb_core.LogLevel.silent) return;
458
+ if (logLevel <= _kubb_core.logLevel.silent) return;
316
459
  const text = getMessage("Configuration started");
317
460
  _clack_prompts.intro(text);
318
461
  startSpinner(getMessage("Configuration loading"));
319
462
  });
320
463
  context.on("config:end", (_configs) => {
321
- if (logLevel <= _kubb_core.LogLevel.silent) return;
464
+ if (logLevel <= _kubb_core.logLevel.silent) return;
322
465
  const text = getMessage("Configuration completed");
323
466
  _clack_prompts.outro(text);
324
467
  });
325
468
  context.on("generation:start", (config) => {
326
- state.totalPlugins = config.plugins?.length || 0;
469
+ reset();
470
+ state.totalPlugins = config.plugins?.length ?? 0;
327
471
  const text = getMessage(["Generation started", config.name ? `for ${(0, node_util.styleText)("dim", config.name)}` : void 0].filter(Boolean).join(" "));
328
472
  _clack_prompts.intro(text);
329
- reset();
330
473
  });
331
474
  context.on("plugin:start", (plugin) => {
332
- if (logLevel <= _kubb_core.LogLevel.silent) return;
475
+ if (logLevel <= _kubb_core.logLevel.silent) return;
333
476
  stopSpinner();
334
477
  const progressBar = _clack_prompts.progress({
335
478
  style: "block",
@@ -349,18 +492,18 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
349
492
  context.on("plugin:end", (plugin, { duration, success }) => {
350
493
  stopSpinner();
351
494
  const active = state.activeProgress.get(plugin.name);
352
- if (!active || logLevel === _kubb_core.LogLevel.silent) return;
495
+ if (!active || logLevel === _kubb_core.logLevel.silent) return;
353
496
  clearInterval(active.interval);
354
497
  if (success) state.completedPlugins++;
355
498
  else state.failedPlugins++;
356
499
  const durationStr = formatMsWithColor(duration);
357
- const text = getMessage(success ? `${(0, node_util.styleText)("bold", plugin.name)} completed in ${durationStr}` : `${(0, node_util.styleText)("bold", plugin.name)} failed in ${(0, node_util.styleText)("red", (0, _kubb_core_utils.formatMs)(duration))}`);
500
+ const text = getMessage(success ? `${(0, node_util.styleText)("bold", plugin.name)} completed in ${durationStr}` : `${(0, node_util.styleText)("bold", plugin.name)} failed in ${(0, node_util.styleText)("red", formatMs(duration))}`);
358
501
  active.progressBar.stop(text);
359
502
  state.activeProgress.delete(plugin.name);
360
503
  showProgressStep();
361
504
  });
362
505
  context.on("files:processing:start", (files) => {
363
- if (logLevel <= _kubb_core.LogLevel.silent) return;
506
+ if (logLevel <= _kubb_core.logLevel.silent) return;
364
507
  stopSpinner();
365
508
  state.totalFiles = files.length;
366
509
  state.processedFiles = 0;
@@ -375,7 +518,7 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
375
518
  state.activeProgress.set("files", { progressBar });
376
519
  });
377
520
  context.on("file:processing:update", ({ file, config }) => {
378
- if (logLevel <= _kubb_core.LogLevel.silent) return;
521
+ if (logLevel <= _kubb_core.logLevel.silent) return;
379
522
  stopSpinner();
380
523
  state.processedFiles++;
381
524
  const text = `Writing ${(0, node_path.relative)(config.root, file.path)}`;
@@ -384,7 +527,7 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
384
527
  active.progressBar.advance(void 0, text);
385
528
  });
386
529
  context.on("files:processing:end", () => {
387
- if (logLevel <= _kubb_core.LogLevel.silent) return;
530
+ if (logLevel <= _kubb_core.logLevel.silent) return;
388
531
  stopSpinner();
389
532
  const text = getMessage("Files written successfully");
390
533
  const active = state.activeProgress.get("files");
@@ -398,113 +541,63 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
398
541
  _clack_prompts.outro(text);
399
542
  });
400
543
  context.on("format:start", () => {
401
- if (logLevel <= _kubb_core.LogLevel.silent) return;
544
+ if (logLevel <= _kubb_core.logLevel.silent) return;
402
545
  const text = getMessage("Format started");
403
546
  _clack_prompts.intro(text);
404
547
  });
405
548
  context.on("format:end", () => {
406
- if (logLevel <= _kubb_core.LogLevel.silent) return;
549
+ if (logLevel <= _kubb_core.logLevel.silent) return;
407
550
  const text = getMessage("Format completed");
408
551
  _clack_prompts.outro(text);
409
552
  });
410
553
  context.on("lint:start", () => {
411
- if (logLevel <= _kubb_core.LogLevel.silent) return;
554
+ if (logLevel <= _kubb_core.logLevel.silent) return;
412
555
  const text = getMessage("Lint started");
413
556
  _clack_prompts.intro(text);
414
557
  });
415
558
  context.on("lint:end", () => {
416
- if (logLevel <= _kubb_core.LogLevel.silent) return;
559
+ if (logLevel <= _kubb_core.logLevel.silent) return;
417
560
  const text = getMessage("Lint completed");
418
561
  _clack_prompts.outro(text);
419
562
  });
420
563
  context.on("hook:start", async ({ id, command, args }) => {
421
- const commandWithArgs = args?.length ? `${command} ${args.join(" ")}` : command;
564
+ const commandWithArgs = formatCommandWithArgs(command, args);
422
565
  const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} started`);
423
566
  if (!id) return;
424
- if (logLevel <= _kubb_core.LogLevel.silent) {
425
- try {
426
- const result = await (0, tinyexec.x)(command, [...args ?? []], {
427
- nodeOptions: { detached: true },
428
- throwOnError: true
429
- });
430
- await context.emit("debug", {
431
- date: /* @__PURE__ */ new Date(),
432
- logs: [result.stdout.trimEnd()]
433
- });
434
- await context.emit("hook:end", {
435
- command,
436
- args,
437
- id,
438
- success: true,
439
- error: null
440
- });
441
- } catch (err) {
442
- const error = err;
443
- const stderr = error.output?.stderr ?? "";
444
- const stdout = error.output?.stdout ?? "";
445
- await context.emit("debug", {
446
- date: /* @__PURE__ */ new Date(),
447
- logs: [stdout, stderr].filter(Boolean)
448
- });
449
- if (stderr) console.error(stderr);
450
- if (stdout) console.log(stdout);
451
- const errorMessage = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
452
- await context.emit("hook:end", {
453
- command,
454
- args,
455
- id,
456
- success: false,
457
- error: errorMessage
458
- });
459
- await context.emit("error", errorMessage);
460
- }
461
- return;
462
- }
463
- _clack_prompts.intro(text);
464
- const logger = _clack_prompts.taskLog({ title: getMessage(["Executing hook", logLevel >= _kubb_core.LogLevel.info ? (0, node_util.styleText)("dim", commandWithArgs) : void 0].filter(Boolean).join(" ")) });
465
- const writable = new ClackWritable(logger);
466
- try {
467
- const proc = (0, tinyexec.x)(command, [...args ?? []], {
468
- nodeOptions: { detached: true },
469
- throwOnError: true
470
- });
471
- for await (const line of proc) writable.write(line);
472
- const result = await proc;
473
- await context.emit("debug", {
474
- date: /* @__PURE__ */ new Date(),
475
- logs: [result.stdout.trimEnd()]
476
- });
477
- await context.emit("hook:end", {
478
- command,
479
- args,
567
+ if (logLevel <= _kubb_core.logLevel.silent) {
568
+ await runHook({
480
569
  id,
481
- success: true,
482
- error: null
483
- });
484
- } catch (err) {
485
- const error = err;
486
- const stderr = error.output?.stderr ?? "";
487
- const stdout = error.output?.stdout ?? "";
488
- await context.emit("debug", {
489
- date: /* @__PURE__ */ new Date(),
490
- logs: [stdout, stderr].filter(Boolean)
491
- });
492
- if (stderr) logger.error(stderr);
493
- if (stdout) logger.message(stdout);
494
- const errorMessage = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
495
- await context.emit("hook:end", {
496
570
  command,
497
571
  args,
498
- id,
499
- success: false,
500
- error: errorMessage
572
+ commandWithArgs,
573
+ context,
574
+ sink: {
575
+ onStderr: (s) => console.error(s),
576
+ onStdout: (s) => console.log(s)
577
+ }
501
578
  });
502
- await context.emit("error", errorMessage);
579
+ return;
503
580
  }
581
+ _clack_prompts.intro(text);
582
+ const logger = _clack_prompts.taskLog({ title: getMessage(["Executing hook", logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", commandWithArgs) : void 0].filter(Boolean).join(" ")) });
583
+ const writable = new ClackWritable(logger);
584
+ await runHook({
585
+ id,
586
+ command,
587
+ args,
588
+ commandWithArgs,
589
+ context,
590
+ stream: true,
591
+ sink: {
592
+ onLine: (line) => writable.write(line),
593
+ onStderr: (s) => logger.error(s),
594
+ onStdout: (s) => logger.message(s)
595
+ }
596
+ });
504
597
  });
505
598
  context.on("hook:end", ({ command, args }) => {
506
- if (logLevel <= _kubb_core.LogLevel.silent) return;
507
- const text = getMessage(`Hook ${(0, node_util.styleText)("dim", args?.length ? `${command} ${args.join(" ")}` : command)} successfully executed`);
599
+ if (logLevel <= _kubb_core.logLevel.silent) return;
600
+ const text = getMessage(`Hook ${(0, node_util.styleText)("dim", formatCommandWithArgs(command, args))} successfully executed`);
508
601
  _clack_prompts.outro(text);
509
602
  });
510
603
  context.on("generation:summary", (config, { pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
@@ -514,25 +607,15 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
514
607
  config,
515
608
  status,
516
609
  hrStart,
517
- pluginTimings: logLevel >= _kubb_core.LogLevel.verbose ? pluginTimings : void 0
610
+ pluginTimings: logLevel >= _kubb_core.logLevel.verbose ? pluginTimings : void 0
518
611
  });
519
612
  const title = config.name || "";
520
613
  summary.unshift("\n");
521
614
  summary.push("\n");
522
- if (status === "success") {
523
- _clack_prompts.box(summary.join("\n"), getMessage(title), {
524
- width: "auto",
525
- formatBorder: (s) => (0, node_util.styleText)("green", s),
526
- rounded: true,
527
- withGuide: false,
528
- contentAlign: "left",
529
- titleAlign: "center"
530
- });
531
- return;
532
- }
615
+ const borderColor = status === "success" ? "green" : "red";
533
616
  _clack_prompts.box(summary.join("\n"), getMessage(title), {
534
617
  width: "auto",
535
- formatBorder: (s) => (0, node_util.styleText)("red", s),
618
+ formatBorder: (s) => (0, node_util.styleText)(borderColor, s),
536
619
  rounded: true,
537
620
  withGuide: false,
538
621
  contentAlign: "left",
@@ -545,26 +628,6 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
545
628
  }
546
629
  });
547
630
  //#endregion
548
- //#region src/loggers/envDetection.ts
549
- /**
550
- * Check if running in GitHub Actions environment
551
- */
552
- function isGitHubActions() {
553
- return !!process.env.GITHUB_ACTIONS;
554
- }
555
- /**
556
- * Check if running in any CI environment
557
- */
558
- function isCIEnvironment() {
559
- return !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI || process.env.CIRCLECI || process.env.TRAVIS || process.env.JENKINS_URL || process.env.BUILDKITE);
560
- }
561
- /**
562
- * Check if TTY is available for interactive output
563
- */
564
- function canUseTTY() {
565
- return !!process.stdout.isTTY && !isCIEnvironment();
566
- }
567
- //#endregion
568
631
  //#region src/loggers/fileSystemLogger.ts
569
632
  /**
570
633
  * FileSystem logger for debug log persistence
@@ -593,7 +656,7 @@ const fileSystemLogger = (0, _kubb_core.defineLogger)({
593
656
  name,
594
657
  state.startDate
595
658
  ].filter(Boolean).join("-")}.log`;
596
- const pathName = (0, node_path.resolve)(process.cwd(), ".kubb", baseName);
659
+ const pathName = (0, node_path.resolve)(node_process.default.cwd(), ".kubb", baseName);
597
660
  if (!files[pathName]) files[pathName] = [];
598
661
  if (log.logs.length > 0) {
599
662
  const timestamp = log.date.toLocaleString();
@@ -601,82 +664,73 @@ const fileSystemLogger = (0, _kubb_core.defineLogger)({
601
664
  }
602
665
  }
603
666
  await Promise.all(Object.entries(files).map(async ([fileName, logs]) => {
604
- return (0, _kubb_core_fs.write)(fileName, logs.join("\n\n"));
667
+ return write(fileName, logs.join("\n\n"));
605
668
  }));
606
669
  return Object.keys(files);
607
670
  }
608
671
  context.on("info", (message, info) => {
609
672
  state.cachedLogs.add({
610
673
  date: /* @__PURE__ */ new Date(),
611
- logs: [`ℹ ${message} ${info}`],
612
- fileName: void 0
674
+ logs: [`ℹ ${message} ${info}`]
613
675
  });
614
676
  });
615
677
  context.on("success", (message, info) => {
616
678
  state.cachedLogs.add({
617
679
  date: /* @__PURE__ */ new Date(),
618
- logs: [`✓ ${message} ${info}`],
619
- fileName: void 0
680
+ logs: [`✓ ${message} ${info}`]
620
681
  });
621
682
  });
622
683
  context.on("warn", (message, info) => {
623
684
  state.cachedLogs.add({
624
685
  date: /* @__PURE__ */ new Date(),
625
- logs: [`⚠ ${message} ${info}`],
626
- fileName: void 0
686
+ logs: [`⚠ ${message} ${info}`]
627
687
  });
628
688
  });
629
689
  context.on("error", (error) => {
630
690
  state.cachedLogs.add({
631
691
  date: /* @__PURE__ */ new Date(),
632
- logs: [`✗ ${error.message}`, error.stack || "unknown stack"],
633
- fileName: void 0
692
+ logs: [`✗ ${error.message}`, error.stack || "unknown stack"]
634
693
  });
635
694
  });
636
695
  context.on("debug", (message) => {
637
696
  state.cachedLogs.add({
638
697
  date: /* @__PURE__ */ new Date(),
639
- logs: message.logs,
640
- fileName: void 0
698
+ logs: message.logs
641
699
  });
642
700
  });
643
701
  context.on("plugin:start", (plugin) => {
644
702
  state.cachedLogs.add({
645
703
  date: /* @__PURE__ */ new Date(),
646
- logs: [`Generating ${plugin.name}`],
647
- fileName: void 0
704
+ logs: [`Generating ${plugin.name}`]
648
705
  });
649
706
  });
650
707
  context.on("plugin:end", (plugin, { duration, success }) => {
651
- const durationStr = (0, _kubb_core_utils.formatMs)(duration);
708
+ const durationStr = formatMs(duration);
652
709
  state.cachedLogs.add({
653
710
  date: /* @__PURE__ */ new Date(),
654
- logs: [success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`],
655
- fileName: void 0
711
+ logs: [success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`]
656
712
  });
657
713
  });
658
714
  context.on("files:processing:start", (files) => {
659
715
  state.cachedLogs.add({
660
716
  date: /* @__PURE__ */ new Date(),
661
- logs: [`Start ${files.length} writing:`, ...files.map((file) => file.path)],
662
- fileName: void 0
717
+ logs: [`Start ${files.length} writing:`, ...files.map((file) => file.path)]
663
718
  });
664
719
  });
665
720
  context.on("generation:end", async (config) => {
666
721
  const writtenFilePaths = await writeLogs(config.name);
667
722
  if (writtenFilePaths.length > 0) {
668
- const files = writtenFilePaths.map((f) => (0, node_path.relative)(process.cwd(), f));
723
+ const files = writtenFilePaths.map((f) => (0, node_path.relative)(node_process.default.cwd(), f));
669
724
  await context.emit("info", "Debug files written to:", files.join(", "));
670
725
  }
671
726
  reset();
672
727
  });
673
- context.on("lifecycle:end", async () => {});
674
728
  const exitHandler = () => {
675
729
  if (state.cachedLogs.size > 0) writeLogs().catch(() => {});
676
730
  };
677
- process.once("exit", exitHandler);
678
- process.once("SIGINT", exitHandler);
679
- process.once("SIGTERM", exitHandler);
731
+ node_process.default.once("exit", exitHandler);
732
+ node_process.default.once("SIGINT", exitHandler);
733
+ node_process.default.once("SIGTERM", exitHandler);
680
734
  }
681
735
  });
682
736
  //#endregion
@@ -688,7 +742,7 @@ const fileSystemLogger = (0, _kubb_core.defineLogger)({
688
742
  const githubActionsLogger = (0, _kubb_core.defineLogger)({
689
743
  name: "github-actions",
690
744
  install(context, options) {
691
- const logLevel = options?.logLevel || _kubb_core.LogLevel.info;
745
+ const logLevel = options?.logLevel ?? _kubb_core.logLevel.info;
692
746
  const state = {
693
747
  totalPlugins: 0,
694
748
  completedPlugins: 0,
@@ -705,29 +759,15 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
705
759
  state.totalFiles = 0;
706
760
  state.processedFiles = 0;
707
761
  state.hrStart = process.hrtime();
762
+ state.currentConfigs = [];
708
763
  }
709
764
  function showProgressStep() {
710
- if (logLevel <= _kubb_core.LogLevel.silent) return;
711
- const parts = [];
712
- const duration = (0, _kubb_core_utils.formatHrtime)(state.hrStart);
713
- if (state.totalPlugins > 0) {
714
- const pluginStr = state.failedPlugins > 0 ? `Plugins ${(0, node_util.styleText)("green", state.completedPlugins.toString())}/${state.totalPlugins} ${(0, node_util.styleText)("red", `(${state.failedPlugins} failed)`)}` : `Plugins ${(0, node_util.styleText)("green", state.completedPlugins.toString())}/${state.totalPlugins}`;
715
- parts.push(pluginStr);
716
- }
717
- if (state.totalFiles > 0) parts.push(`Files ${(0, node_util.styleText)("green", state.processedFiles.toString())}/${state.totalFiles}`);
718
- if (parts.length > 0) {
719
- parts.push(`${(0, node_util.styleText)("green", duration)} elapsed`);
720
- console.log(getMessage(parts.join((0, node_util.styleText)("dim", " | "))));
721
- }
765
+ if (logLevel <= _kubb_core.logLevel.silent) return;
766
+ const line = buildProgressLine(state);
767
+ if (line) console.log(getMessage(line));
722
768
  }
723
769
  function getMessage(message) {
724
- if (logLevel >= _kubb_core.LogLevel.verbose) return [(0, node_util.styleText)("dim", `[${(/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
725
- hour12: false,
726
- hour: "2-digit",
727
- minute: "2-digit",
728
- second: "2-digit"
729
- })}]`), message].join(" ");
730
- return message;
770
+ return formatMessage(message, logLevel);
731
771
  }
732
772
  function openGroup(name) {
733
773
  console.log(`::group::${name}`);
@@ -736,7 +776,7 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
736
776
  console.log("::endgroup::");
737
777
  }
738
778
  context.on("info", (message, info = "") => {
739
- if (logLevel <= _kubb_core.LogLevel.silent) return;
779
+ if (logLevel <= _kubb_core.logLevel.silent) return;
740
780
  const text = getMessage([
741
781
  (0, node_util.styleText)("blue", "ℹ"),
742
782
  message,
@@ -745,29 +785,29 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
745
785
  console.log(text);
746
786
  });
747
787
  context.on("success", (message, info = "") => {
748
- if (logLevel <= _kubb_core.LogLevel.silent) return;
788
+ if (logLevel <= _kubb_core.logLevel.silent) return;
749
789
  const text = getMessage([
750
790
  (0, node_util.styleText)("blue", "✓"),
751
791
  message,
752
- logLevel >= _kubb_core.LogLevel.info ? (0, node_util.styleText)("dim", info) : void 0
792
+ logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", info) : void 0
753
793
  ].filter(Boolean).join(" "));
754
794
  console.log(text);
755
795
  });
756
796
  context.on("warn", (message, info = "") => {
757
- if (logLevel <= _kubb_core.LogLevel.silent) return;
797
+ if (logLevel <= _kubb_core.logLevel.silent) return;
758
798
  const text = getMessage([
759
799
  (0, node_util.styleText)("yellow", "⚠"),
760
800
  message,
761
- logLevel >= _kubb_core.LogLevel.info ? (0, node_util.styleText)("dim", info) : void 0
801
+ logLevel >= _kubb_core.logLevel.info ? (0, node_util.styleText)("dim", info) : void 0
762
802
  ].filter(Boolean).join(" "));
763
803
  console.warn(`::warning::${text}`);
764
804
  });
765
805
  context.on("error", (error) => {
766
- const caused = error.cause;
767
- if (logLevel <= _kubb_core.LogLevel.silent) return;
806
+ const caused = require_errors.toCause(error);
807
+ if (logLevel <= _kubb_core.logLevel.silent) return;
768
808
  const message = error.message || String(error);
769
809
  console.error(`::error::${message}`);
770
- if (logLevel >= _kubb_core.LogLevel.debug && error.stack) {
810
+ if (logLevel >= _kubb_core.logLevel.debug && error.stack) {
771
811
  const frames = error.stack.split("\n").slice(1, 4);
772
812
  for (const frame of frames) console.log(getMessage((0, node_util.styleText)("dim", frame.trim())));
773
813
  if (caused?.stack) {
@@ -782,44 +822,44 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
782
822
  reset();
783
823
  });
784
824
  context.on("config:start", () => {
785
- if (logLevel <= _kubb_core.LogLevel.silent) return;
825
+ if (logLevel <= _kubb_core.logLevel.silent) return;
786
826
  const text = getMessage("Configuration started");
787
827
  openGroup("Configuration");
788
828
  console.log(text);
789
829
  });
790
830
  context.on("config:end", (configs) => {
791
831
  state.currentConfigs = configs;
792
- if (logLevel <= _kubb_core.LogLevel.silent) return;
832
+ if (logLevel <= _kubb_core.logLevel.silent) return;
793
833
  const text = getMessage("Configuration completed");
794
834
  console.log(text);
795
835
  closeGroup("Configuration");
796
836
  });
797
837
  context.on("generation:start", (config) => {
798
- state.totalPlugins = config.plugins?.length || 0;
838
+ reset();
839
+ state.totalPlugins = config.plugins?.length ?? 0;
799
840
  const text = config.name ? `Generation for ${(0, node_util.styleText)("bold", config.name)}` : "Generation";
800
841
  if (state.currentConfigs.length > 1) openGroup(text);
801
842
  if (state.currentConfigs.length === 1) console.log(getMessage(text));
802
- reset();
803
843
  });
804
844
  context.on("plugin:start", (plugin) => {
805
- if (logLevel <= _kubb_core.LogLevel.silent) return;
845
+ if (logLevel <= _kubb_core.logLevel.silent) return;
806
846
  const text = getMessage(`Generating ${(0, node_util.styleText)("bold", plugin.name)}`);
807
847
  if (state.currentConfigs.length === 1) openGroup(`Plugin: ${plugin.name}`);
808
848
  console.log(text);
809
849
  });
810
850
  context.on("plugin:end", (plugin, { duration, success }) => {
811
- if (logLevel <= _kubb_core.LogLevel.silent) return;
851
+ if (logLevel <= _kubb_core.logLevel.silent) return;
812
852
  if (success) state.completedPlugins++;
813
853
  else state.failedPlugins++;
814
854
  const durationStr = formatMsWithColor(duration);
815
- const text = getMessage(success ? `${(0, node_util.styleText)("bold", plugin.name)} completed in ${durationStr}` : `${(0, node_util.styleText)("bold", plugin.name)} failed in ${(0, node_util.styleText)("red", (0, _kubb_core_utils.formatMs)(duration))}`);
855
+ const text = getMessage(success ? `${(0, node_util.styleText)("bold", plugin.name)} completed in ${durationStr}` : `${(0, node_util.styleText)("bold", plugin.name)} failed in ${(0, node_util.styleText)("red", formatMs(duration))}`);
816
856
  console.log(text);
817
857
  if (state.currentConfigs.length > 1) console.log(" ");
818
858
  if (state.currentConfigs.length === 1) closeGroup(`Plugin: ${plugin.name}`);
819
859
  showProgressStep();
820
860
  });
821
861
  context.on("files:processing:start", (files) => {
822
- if (logLevel <= _kubb_core.LogLevel.silent) return;
862
+ if (logLevel <= _kubb_core.logLevel.silent) return;
823
863
  state.totalFiles = files.length;
824
864
  state.processedFiles = 0;
825
865
  if (state.currentConfigs.length === 1) openGroup("File Generation");
@@ -827,108 +867,82 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
827
867
  console.log(text);
828
868
  });
829
869
  context.on("files:processing:end", () => {
830
- if (logLevel <= _kubb_core.LogLevel.silent) return;
870
+ if (logLevel <= _kubb_core.logLevel.silent) return;
831
871
  const text = getMessage("Files written successfully");
832
872
  console.log(text);
833
873
  if (state.currentConfigs.length === 1) closeGroup("File Generation");
874
+ showProgressStep();
834
875
  });
835
876
  context.on("file:processing:update", () => {
836
- if (logLevel <= _kubb_core.LogLevel.silent) return;
877
+ if (logLevel <= _kubb_core.logLevel.silent) return;
837
878
  state.processedFiles++;
838
879
  });
839
- context.on("files:processing:end", () => {
840
- if (logLevel <= _kubb_core.LogLevel.silent) return;
841
- showProgressStep();
842
- });
843
880
  context.on("generation:end", (config) => {
844
881
  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`);
845
882
  console.log(text);
846
883
  });
847
884
  context.on("format:start", () => {
848
- if (logLevel <= _kubb_core.LogLevel.silent) return;
885
+ if (logLevel <= _kubb_core.logLevel.silent) return;
849
886
  const text = getMessage("Format started");
850
887
  if (state.currentConfigs.length === 1) openGroup("Formatting");
851
888
  console.log(text);
852
889
  });
853
890
  context.on("format:end", () => {
854
- if (logLevel <= _kubb_core.LogLevel.silent) return;
891
+ if (logLevel <= _kubb_core.logLevel.silent) return;
855
892
  const text = getMessage("Format completed");
856
893
  console.log(text);
857
894
  if (state.currentConfigs.length === 1) closeGroup("Formatting");
858
895
  });
859
896
  context.on("lint:start", () => {
860
- if (logLevel <= _kubb_core.LogLevel.silent) return;
897
+ if (logLevel <= _kubb_core.logLevel.silent) return;
861
898
  const text = getMessage("Lint started");
862
899
  if (state.currentConfigs.length === 1) openGroup("Linting");
863
900
  console.log(text);
864
901
  });
865
902
  context.on("lint:end", () => {
866
- if (logLevel <= _kubb_core.LogLevel.silent) return;
903
+ if (logLevel <= _kubb_core.logLevel.silent) return;
867
904
  const text = getMessage("Lint completed");
868
905
  console.log(text);
869
906
  if (state.currentConfigs.length === 1) closeGroup("Linting");
870
907
  });
871
908
  context.on("hook:start", async ({ id, command, args }) => {
872
- const commandWithArgs = args?.length ? `${command} ${args.join(" ")}` : command;
909
+ const commandWithArgs = formatCommandWithArgs(command, args);
873
910
  const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} started`);
874
- if (logLevel > _kubb_core.LogLevel.silent) {
911
+ if (logLevel > _kubb_core.logLevel.silent) {
875
912
  if (state.currentConfigs.length === 1) openGroup(`Hook ${commandWithArgs}`);
876
913
  console.log(text);
877
914
  }
878
915
  if (!id) return;
879
- try {
880
- const result = await (0, tinyexec.x)(command, [...args ?? []], {
881
- nodeOptions: { detached: true },
882
- throwOnError: true
883
- });
884
- await context.emit("debug", {
885
- date: /* @__PURE__ */ new Date(),
886
- logs: [result.stdout.trimEnd()]
887
- });
888
- if (logLevel > _kubb_core.LogLevel.silent) console.log(result.stdout.trimEnd());
889
- await context.emit("hook:end", {
890
- command,
891
- args,
892
- id,
893
- success: true,
894
- error: null
895
- });
896
- } catch (err) {
897
- const error = err;
898
- const stderr = error.output?.stderr ?? "";
899
- const stdout = error.output?.stdout ?? "";
900
- await context.emit("debug", {
901
- date: /* @__PURE__ */ new Date(),
902
- logs: [stdout, stderr].filter(Boolean)
903
- });
904
- if (stderr) console.error(`::error::${stderr}`);
905
- if (stdout) console.log(stdout);
906
- const errorMessage = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
907
- await context.emit("hook:end", {
908
- command,
909
- args,
910
- id,
911
- success: false,
912
- error: errorMessage
913
- });
914
- await context.emit("error", errorMessage);
915
- }
916
+ await runHook({
917
+ id,
918
+ command,
919
+ args,
920
+ commandWithArgs,
921
+ context,
922
+ sink: {
923
+ onStdout: logLevel > _kubb_core.logLevel.silent ? (s) => console.log(s) : void 0,
924
+ onStderr: logLevel > _kubb_core.logLevel.silent ? (s) => console.error(`::error::${s}`) : void 0
925
+ }
926
+ });
916
927
  });
917
928
  context.on("hook:end", ({ command, args }) => {
918
- if (logLevel <= _kubb_core.LogLevel.silent) return;
919
- const commandWithArgs = args?.length ? `${command} ${args.join(" ")}` : command;
929
+ if (logLevel <= _kubb_core.logLevel.silent) return;
930
+ const commandWithArgs = formatCommandWithArgs(command, args);
920
931
  const text = getMessage(`Hook ${(0, node_util.styleText)("dim", commandWithArgs)} completed`);
921
932
  console.log(text);
922
933
  if (state.currentConfigs.length === 1) closeGroup(`Hook ${commandWithArgs}`);
923
934
  });
924
935
  context.on("generation:summary", (config, { status, hrStart, failedPlugins }) => {
925
- const pluginsCount = config.plugins?.length || 0;
936
+ const pluginsCount = config.plugins?.length ?? 0;
926
937
  const successCount = pluginsCount - failedPlugins.size;
927
- const duration = (0, _kubb_core_utils.formatHrtime)(hrStart);
938
+ const duration = formatHrtime(hrStart);
928
939
  if (state.currentConfigs.length > 1) console.log(" ");
929
940
  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)}`);
930
941
  if (state.currentConfigs.length > 1) closeGroup(config.name ? `Generation for ${(0, node_util.styleText)("bold", config.name)}` : "Generation");
931
942
  });
943
+ context.on("lifecycle:end", () => {
944
+ reset();
945
+ });
932
946
  }
933
947
  });
934
948
  //#endregion
@@ -940,18 +954,12 @@ const githubActionsLogger = (0, _kubb_core.defineLogger)({
940
954
  const plainLogger = (0, _kubb_core.defineLogger)({
941
955
  name: "plain",
942
956
  install(context, options) {
943
- const logLevel = options?.logLevel || 3;
957
+ const logLevel = options?.logLevel ?? _kubb_core.logLevel.info;
944
958
  function getMessage(message) {
945
- if (logLevel >= _kubb_core.LogLevel.verbose) return [`[${(/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
946
- hour12: false,
947
- hour: "2-digit",
948
- minute: "2-digit",
949
- second: "2-digit"
950
- })}]`, message].join(" ");
951
- return message;
959
+ return formatMessage(message, logLevel);
952
960
  }
953
961
  context.on("info", (message, info) => {
954
- if (logLevel <= _kubb_core.LogLevel.silent) return;
962
+ if (logLevel <= _kubb_core.logLevel.silent) return;
955
963
  const text = getMessage([
956
964
  "ℹ",
957
965
  message,
@@ -960,28 +968,28 @@ const plainLogger = (0, _kubb_core.defineLogger)({
960
968
  console.log(text);
961
969
  });
962
970
  context.on("success", (message, info = "") => {
963
- if (logLevel <= _kubb_core.LogLevel.silent) return;
971
+ if (logLevel <= _kubb_core.logLevel.silent) return;
964
972
  const text = getMessage([
965
973
  "✓",
966
974
  message,
967
- logLevel >= _kubb_core.LogLevel.info ? info : void 0
975
+ logLevel >= _kubb_core.logLevel.info ? info : void 0
968
976
  ].filter(Boolean).join(" "));
969
977
  console.log(text);
970
978
  });
971
979
  context.on("warn", (message, info) => {
972
- if (logLevel < _kubb_core.LogLevel.warn) return;
980
+ if (logLevel < _kubb_core.logLevel.warn) return;
973
981
  const text = getMessage([
974
982
  "⚠",
975
983
  message,
976
- logLevel >= _kubb_core.LogLevel.info ? info : void 0
984
+ logLevel >= _kubb_core.logLevel.info ? info : void 0
977
985
  ].filter(Boolean).join(" "));
978
986
  console.log(text);
979
987
  });
980
988
  context.on("error", (error) => {
981
- const caused = error.cause;
989
+ const caused = require_errors.toCause(error);
982
990
  const text = getMessage(["✗", error.message].join(" "));
983
991
  console.log(text);
984
- if (logLevel >= _kubb_core.LogLevel.debug && error.stack) {
992
+ if (logLevel >= _kubb_core.logLevel.debug && error.stack) {
985
993
  const frames = error.stack.split("\n").slice(1, 4);
986
994
  for (const frame of frames) console.log(getMessage(frame.trim()));
987
995
  if (caused?.stack) {
@@ -995,42 +1003,42 @@ const plainLogger = (0, _kubb_core.defineLogger)({
995
1003
  console.log("Kubb CLI 🧩");
996
1004
  });
997
1005
  context.on("config:start", () => {
998
- if (logLevel <= _kubb_core.LogLevel.silent) return;
1006
+ if (logLevel <= _kubb_core.logLevel.silent) return;
999
1007
  const text = getMessage("Configuration started");
1000
1008
  console.log(text);
1001
1009
  });
1002
1010
  context.on("config:end", () => {
1003
- if (logLevel <= _kubb_core.LogLevel.silent) return;
1011
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1004
1012
  const text = getMessage("Configuration completed");
1005
1013
  console.log(text);
1006
1014
  });
1007
1015
  context.on("generation:start", () => {
1008
- const text = getMessage("Configuration started");
1016
+ const text = getMessage("Generation started");
1009
1017
  console.log(text);
1010
1018
  });
1011
1019
  context.on("plugin:start", (plugin) => {
1012
- if (logLevel <= _kubb_core.LogLevel.silent) return;
1020
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1013
1021
  const text = getMessage(`Generating ${plugin.name}`);
1014
1022
  console.log(text);
1015
1023
  });
1016
1024
  context.on("plugin:end", (plugin, { duration, success }) => {
1017
- if (logLevel <= _kubb_core.LogLevel.silent) return;
1018
- const durationStr = (0, _kubb_core_utils.formatMs)(duration);
1025
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1026
+ const durationStr = formatMs(duration);
1019
1027
  const text = getMessage(success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`);
1020
1028
  console.log(text);
1021
1029
  });
1022
1030
  context.on("files:processing:start", (files) => {
1023
- if (logLevel <= _kubb_core.LogLevel.silent) return;
1031
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1024
1032
  const text = getMessage(`Writing ${files.length} files`);
1025
1033
  console.log(text);
1026
1034
  });
1027
1035
  context.on("file:processing:update", ({ file, config }) => {
1028
- if (logLevel <= _kubb_core.LogLevel.silent) return;
1036
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1029
1037
  const text = getMessage(`Writing ${(0, node_path.relative)(config.root, file.path)}`);
1030
1038
  console.log(text);
1031
1039
  });
1032
1040
  context.on("files:processing:end", () => {
1033
- if (logLevel <= _kubb_core.LogLevel.silent) return;
1041
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1034
1042
  const text = getMessage("Files written successfully");
1035
1043
  console.log(text);
1036
1044
  });
@@ -1039,71 +1047,45 @@ const plainLogger = (0, _kubb_core.defineLogger)({
1039
1047
  console.log(text);
1040
1048
  });
1041
1049
  context.on("format:start", () => {
1042
- if (logLevel <= _kubb_core.LogLevel.silent) return;
1050
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1043
1051
  const text = getMessage("Format started");
1044
1052
  console.log(text);
1045
1053
  });
1046
1054
  context.on("format:end", () => {
1047
- if (logLevel <= _kubb_core.LogLevel.silent) return;
1055
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1048
1056
  const text = getMessage("Format completed");
1049
1057
  console.log(text);
1050
1058
  });
1051
1059
  context.on("lint:start", () => {
1052
- if (logLevel <= _kubb_core.LogLevel.silent) return;
1060
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1053
1061
  const text = getMessage("Lint started");
1054
1062
  console.log(text);
1055
1063
  });
1056
1064
  context.on("lint:end", () => {
1057
- if (logLevel <= _kubb_core.LogLevel.silent) return;
1065
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1058
1066
  const text = getMessage("Lint completed");
1059
1067
  console.log(text);
1060
1068
  });
1061
1069
  context.on("hook:start", async ({ id, command, args }) => {
1062
- const commandWithArgs = args?.length ? `${command} ${args.join(" ")}` : command;
1070
+ const commandWithArgs = formatCommandWithArgs(command, args);
1063
1071
  const text = getMessage(`Hook ${commandWithArgs} started`);
1064
- if (logLevel > _kubb_core.LogLevel.silent) console.log(text);
1072
+ if (logLevel > _kubb_core.logLevel.silent) console.log(text);
1065
1073
  if (!id) return;
1066
- try {
1067
- const result = await (0, tinyexec.x)(command, [...args ?? []], {
1068
- nodeOptions: { detached: true },
1069
- throwOnError: true
1070
- });
1071
- await context.emit("debug", {
1072
- date: /* @__PURE__ */ new Date(),
1073
- logs: [result.stdout.trimEnd()]
1074
- });
1075
- if (logLevel > _kubb_core.LogLevel.silent) console.log(result.stdout.trimEnd());
1076
- await context.emit("hook:end", {
1077
- command,
1078
- args,
1079
- id,
1080
- success: true,
1081
- error: null
1082
- });
1083
- } catch (err) {
1084
- const error = err;
1085
- const stderr = error.output?.stderr ?? "";
1086
- const stdout = error.output?.stdout ?? "";
1087
- await context.emit("debug", {
1088
- date: /* @__PURE__ */ new Date(),
1089
- logs: [stdout, stderr].filter(Boolean)
1090
- });
1091
- if (stderr) console.error(stderr);
1092
- if (stdout) console.log(stdout);
1093
- const errorMessage = /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`);
1094
- await context.emit("hook:end", {
1095
- command,
1096
- args,
1097
- id,
1098
- success: false,
1099
- error: errorMessage
1100
- });
1101
- await context.emit("error", errorMessage);
1102
- }
1074
+ await runHook({
1075
+ id,
1076
+ command,
1077
+ args,
1078
+ commandWithArgs,
1079
+ context,
1080
+ sink: {
1081
+ onStdout: logLevel > _kubb_core.logLevel.silent ? (s) => console.log(s) : void 0,
1082
+ onStderr: logLevel > _kubb_core.logLevel.silent ? (s) => console.error(s) : void 0
1083
+ }
1084
+ });
1103
1085
  });
1104
1086
  context.on("hook:end", ({ command, args }) => {
1105
- if (logLevel <= _kubb_core.LogLevel.silent) return;
1106
- const text = getMessage(`Hook ${args?.length ? `${command} ${args.join(" ")}` : command} completed`);
1087
+ if (logLevel <= _kubb_core.logLevel.silent) return;
1088
+ const text = getMessage(`Hook ${formatCommandWithArgs(command, args)} completed`);
1107
1089
  console.log(text);
1108
1090
  });
1109
1091
  context.on("generation:summary", (config, { pluginTimings, status, hrStart, failedPlugins, filesCreated }) => {
@@ -1113,19 +1095,55 @@ const plainLogger = (0, _kubb_core.defineLogger)({
1113
1095
  config,
1114
1096
  status,
1115
1097
  hrStart,
1116
- pluginTimings: logLevel >= _kubb_core.LogLevel.verbose ? pluginTimings : void 0
1098
+ pluginTimings: logLevel >= _kubb_core.logLevel.verbose ? pluginTimings : void 0
1117
1099
  });
1118
- console.log("---------------------------");
1100
+ console.log(require_constants.SUMMARY_SEPARATOR);
1119
1101
  console.log(summary.join("\n"));
1120
- console.log("---------------------------");
1102
+ console.log(require_constants.SUMMARY_SEPARATOR);
1121
1103
  });
1122
1104
  }
1123
1105
  });
1124
1106
  //#endregion
1125
1107
  //#region src/loggers/utils.ts
1108
+ /**
1109
+ * Optionally prefix a message with a [HH:MM:SS] timestamp when logLevel >= verbose.
1110
+ * Shared across all logger adapters to avoid duplication.
1111
+ */
1112
+ function formatMessage(message, logLevel) {
1113
+ if (logLevel >= _kubb_core.logLevel.verbose) return `${(0, node_util.styleText)("dim", `[${(/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
1114
+ hour12: false,
1115
+ hour: "2-digit",
1116
+ minute: "2-digit",
1117
+ second: "2-digit"
1118
+ })}]`)} ${message}`;
1119
+ return message;
1120
+ }
1121
+ /**
1122
+ * Build the progress summary line shared by clack and GitHub Actions loggers.
1123
+ * Returns null when there is nothing to display.
1124
+ */
1125
+ function buildProgressLine(state) {
1126
+ const parts = [];
1127
+ const duration = formatHrtime(state.hrStart);
1128
+ if (state.totalPlugins > 0) {
1129
+ const pluginStr = state.failedPlugins > 0 ? `Plugins ${(0, node_util.styleText)("green", state.completedPlugins.toString())}/${state.totalPlugins} ${(0, node_util.styleText)("red", `(${state.failedPlugins} failed)`)}` : `Plugins ${(0, node_util.styleText)("green", state.completedPlugins.toString())}/${state.totalPlugins}`;
1130
+ parts.push(pluginStr);
1131
+ }
1132
+ if (state.totalFiles > 0) parts.push(`Files ${(0, node_util.styleText)("green", state.processedFiles.toString())}/${state.totalFiles}`);
1133
+ if (parts.length === 0) return null;
1134
+ parts.push(`${(0, node_util.styleText)("green", duration)} elapsed`);
1135
+ return parts.join((0, node_util.styleText)("dim", " | "));
1136
+ }
1137
+ /**
1138
+ * Join a command and its optional args into a single display string.
1139
+ * e.g. ("prettier", ["--write", "."]) → "prettier --write ."
1140
+ */
1141
+ function formatCommandWithArgs(command, args) {
1142
+ return args?.length ? `${command} ${args.join(" ")}` : command;
1143
+ }
1126
1144
  function detectLogger() {
1127
- if (isGitHubActions()) return "github-actions";
1128
- if (canUseTTY()) return "clack";
1145
+ if (require_telemetry.isGitHubActions()) return "github-actions";
1146
+ if (require_telemetry.canUseTTY()) return "clack";
1129
1147
  return "plain";
1130
1148
  }
1131
1149
  const logMapper = {
@@ -1138,7 +1156,7 @@ async function setupLogger(context, { logLevel }) {
1138
1156
  const logger = logMapper[type];
1139
1157
  if (!logger) throw new Error(`Unknown adapter type: ${type}`);
1140
1158
  const cleanup = await logger.install(context, { logLevel });
1141
- if (logLevel >= _kubb_core.LogLevel.debug) await fileSystemLogger.install(context, { logLevel });
1159
+ if (logLevel >= _kubb_core.logLevel.debug) await fileSystemLogger.install(context, { logLevel });
1142
1160
  return cleanup;
1143
1161
  }
1144
1162
  //#endregion
@@ -1146,22 +1164,143 @@ async function setupLogger(context, { logLevel }) {
1146
1164
  async function executeHooks({ hooks, events }) {
1147
1165
  const commands = Array.isArray(hooks.done) ? hooks.done : [hooks.done].filter(Boolean);
1148
1166
  for (const command of commands) {
1149
- const [cmd, ...args] = (0, _kubb_core_utils.tokenize)(command);
1167
+ const [cmd, ...args] = require_shell.tokenize(command);
1150
1168
  if (!cmd) continue;
1151
1169
  const hookId = (0, node_crypto.createHash)("sha256").update(command).digest("hex");
1170
+ const hookEndPromise = new Promise((resolve, reject) => {
1171
+ const handler = ({ id, success, error }) => {
1172
+ if (id !== hookId) return;
1173
+ events.off("hook:end", handler);
1174
+ if (!success) {
1175
+ reject(error ?? /* @__PURE__ */ new Error(`Hook failed: ${command}`));
1176
+ return;
1177
+ }
1178
+ events.emit("success", `${(0, node_util.styleText)("dim", command)} successfully executed`).then(resolve).catch(reject);
1179
+ };
1180
+ events.on("hook:end", handler);
1181
+ });
1152
1182
  await events.emit("hook:start", {
1153
1183
  id: hookId,
1154
1184
  command: cmd,
1155
1185
  args
1156
1186
  });
1157
- await events.onOnce("hook:end", async ({ success, error }) => {
1158
- if (!success) throw error;
1159
- await events.emit("success", `${(0, node_util.styleText)("dim", command)} successfully executed`);
1160
- });
1187
+ await hookEndPromise;
1161
1188
  }
1162
1189
  }
1163
1190
  //#endregion
1191
+ //#region src/utils/getCosmiConfig.ts
1192
+ const jiti$1 = (0, jiti.createJiti)(require("url").pathToFileURL(__filename).href, {
1193
+ jsx: {
1194
+ runtime: "automatic",
1195
+ importSource: "@kubb/react-fabric"
1196
+ },
1197
+ sourceMaps: true,
1198
+ interopDefault: true
1199
+ });
1200
+ const tsLoader = async (configFile) => {
1201
+ return await jiti$1.import(configFile, { default: true });
1202
+ };
1203
+ async function getCosmiConfig(moduleName, config) {
1204
+ let result;
1205
+ const searchPlaces = [
1206
+ "package.json",
1207
+ `.${moduleName}rc`,
1208
+ `.${moduleName}rc.json`,
1209
+ `.${moduleName}rc.yaml`,
1210
+ `.${moduleName}rc.yml`,
1211
+ `.${moduleName}rc.ts`,
1212
+ `.${moduleName}rc.js`,
1213
+ `.${moduleName}rc.mjs`,
1214
+ `.${moduleName}rc.cjs`,
1215
+ `${moduleName}.config.ts`,
1216
+ `${moduleName}.config.js`,
1217
+ `${moduleName}.config.mjs`,
1218
+ `${moduleName}.config.cjs`
1219
+ ];
1220
+ const explorer = (0, cosmiconfig.cosmiconfig)(moduleName, {
1221
+ cache: false,
1222
+ searchPlaces: [
1223
+ ...searchPlaces.map((searchPlace) => {
1224
+ return `.config/${searchPlace}`;
1225
+ }),
1226
+ ...searchPlaces.map((searchPlace) => {
1227
+ return `configs/${searchPlace}`;
1228
+ }),
1229
+ ...searchPlaces
1230
+ ],
1231
+ loaders: { ".ts": tsLoader }
1232
+ });
1233
+ try {
1234
+ result = config ? await explorer.load(config) : await explorer.search();
1235
+ } catch (error) {
1236
+ throw new Error("Config failed loading", { cause: error });
1237
+ }
1238
+ if (result?.isEmpty || !result || !result.config) throw new Error("Config not defined, create a kubb.config.js or pass through your config with the option --config");
1239
+ return result;
1240
+ }
1241
+ //#endregion
1242
+ //#region src/utils/watcher.ts
1243
+ async function startWatcher(path, cb) {
1244
+ const { watch } = await import("chokidar");
1245
+ watch(path, {
1246
+ ignorePermissionErrors: true,
1247
+ ignored: require_constants.WATCHER_IGNORED_PATHS
1248
+ }).on("all", async (type, file) => {
1249
+ console.log((0, node_util.styleText)("yellow", (0, node_util.styleText)("bold", `Change detected: ${type} ${file}`)));
1250
+ try {
1251
+ await cb(path);
1252
+ } catch (_e) {
1253
+ console.log((0, node_util.styleText)("red", "Watcher failed"));
1254
+ }
1255
+ });
1256
+ }
1257
+ //#endregion
1164
1258
  //#region src/runners/generate.ts
1259
+ async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, configName, outputPath, logLevel, events, onStart, onEnd }) {
1260
+ await onStart();
1261
+ let resolvedTool = toolValue;
1262
+ if (resolvedTool === "auto") {
1263
+ const detected = await detect();
1264
+ if (!detected) await events.emit("warn", noToolMessage);
1265
+ else {
1266
+ resolvedTool = detected;
1267
+ await events.emit("info", `Auto-detected ${toolLabel}: ${(0, node_util.styleText)("dim", resolvedTool)}`);
1268
+ }
1269
+ }
1270
+ if (resolvedTool && resolvedTool !== "auto" && resolvedTool in toolMap) {
1271
+ const toolConfig = toolMap[resolvedTool];
1272
+ try {
1273
+ const hookId = (0, node_crypto.createHash)("sha256").update([configName, resolvedTool].filter(Boolean).join("-")).digest("hex");
1274
+ const hookEndPromise = new Promise((resolve, reject) => {
1275
+ const handler = ({ id, success, error }) => {
1276
+ if (id !== hookId) return;
1277
+ events.off("hook:end", handler);
1278
+ if (!success) {
1279
+ reject(error ?? /* @__PURE__ */ new Error(`${toolConfig.errorMessage}`));
1280
+ return;
1281
+ }
1282
+ events.emit("success", [
1283
+ `${successPrefix} with ${(0, node_util.styleText)("dim", resolvedTool)}`,
1284
+ logLevel >= _kubb_core.logLevel.info ? `on ${(0, node_util.styleText)("dim", outputPath)}` : void 0,
1285
+ "successfully"
1286
+ ].filter(Boolean).join(" ")).then(resolve).catch(reject);
1287
+ };
1288
+ events.on("hook:end", handler);
1289
+ });
1290
+ await events.emit("hook:start", {
1291
+ id: hookId,
1292
+ command: toolConfig.command,
1293
+ args: toolConfig.args(outputPath)
1294
+ });
1295
+ await hookEndPromise;
1296
+ } catch (caughtError) {
1297
+ const err = new Error(toolConfig.errorMessage);
1298
+ err.cause = caughtError;
1299
+ await events.emit("error", err);
1300
+ }
1301
+ }
1302
+ await onEnd();
1303
+ }
1165
1304
  async function generate({ input, config: userConfig, events, logLevel }) {
1166
1305
  const inputPath = input ?? ("path" in userConfig.input ? userConfig.input.path : void 0);
1167
1306
  const hrStart = node_process.default.hrtime();
@@ -1198,16 +1337,15 @@ async function generate({ input, config: userConfig, events, logLevel }) {
1198
1337
  });
1199
1338
  await events.emit("info", "Load summary");
1200
1339
  if (failedPlugins.size > 0 || error) {
1201
- [error, ...Array.from(failedPlugins).filter((it) => it.error).map((it) => it.error)].filter(Boolean).forEach((err) => {
1202
- events.emit("error", err);
1203
- });
1340
+ const allErrors = [error, ...Array.from(failedPlugins).filter((it) => it.error).map((it) => it.error)].filter(Boolean);
1341
+ for (const err of allErrors) await events.emit("error", err);
1204
1342
  await events.emit("generation:end", config, files, sources);
1205
1343
  await events.emit("generation:summary", config, {
1206
1344
  failedPlugins,
1207
1345
  filesCreated: files.length,
1208
1346
  status: "failed",
1209
1347
  hrStart,
1210
- pluginTimings: logLevel >= _kubb_core.LogLevel.verbose ? pluginTimings : void 0
1348
+ pluginTimings: logLevel >= _kubb_core.logLevel.verbose ? pluginTimings : void 0
1211
1349
  });
1212
1350
  await require_telemetry.sendTelemetry(require_telemetry.buildTelemetryEvent({
1213
1351
  command: "generate",
@@ -1224,80 +1362,35 @@ async function generate({ input, config: userConfig, events, logLevel }) {
1224
1362
  }
1225
1363
  await events.emit("success", "Generation successfully", inputPath);
1226
1364
  await events.emit("generation:end", config, files, sources);
1227
- if (config.output.format) {
1228
- await events.emit("format:start");
1229
- let formatter = config.output.format;
1230
- if (formatter === "auto") {
1231
- const detectedFormatter = await (0, _kubb_core_utils.detectFormatter)();
1232
- if (!detectedFormatter) await events.emit("warn", "No formatter found (biome, prettier, or oxfmt). Skipping formatting.");
1233
- else {
1234
- formatter = detectedFormatter;
1235
- await events.emit("info", `Auto-detected formatter: ${(0, node_util.styleText)("dim", formatter)}`);
1236
- }
1237
- }
1238
- if (formatter && formatter !== "auto" && formatter in _kubb_core_utils.formatters) {
1239
- const formatterConfig = _kubb_core_utils.formatters[formatter];
1240
- const outputPath = node_path.default.resolve(config.root, config.output.path);
1241
- try {
1242
- const hookId = (0, node_crypto.createHash)("sha256").update([config.name, formatter].filter(Boolean).join("-")).digest("hex");
1243
- await events.emit("hook:start", {
1244
- id: hookId,
1245
- command: formatterConfig.command,
1246
- args: formatterConfig.args(outputPath)
1247
- });
1248
- await events.onOnce("hook:end", async ({ success, error }) => {
1249
- if (!success) throw error;
1250
- await events.emit("success", [
1251
- `Formatting with ${(0, node_util.styleText)("dim", formatter)}`,
1252
- logLevel >= _kubb_core.LogLevel.info ? `on ${(0, node_util.styleText)("dim", outputPath)}` : void 0,
1253
- "successfully"
1254
- ].filter(Boolean).join(" "));
1255
- });
1256
- } catch (caughtError) {
1257
- const error = new Error(formatterConfig.errorMessage);
1258
- error.cause = caughtError;
1259
- await events.emit("error", error);
1260
- }
1261
- }
1262
- await events.emit("format:end");
1263
- }
1264
- if (config.output.lint) {
1265
- await events.emit("lint:start");
1266
- let linter = config.output.lint;
1267
- if (linter === "auto") {
1268
- const detectedLinter = await (0, _kubb_core_utils.detectLinter)();
1269
- if (!detectedLinter) await events.emit("warn", "No linter found (biome, oxlint, or eslint). Skipping linting.");
1270
- else {
1271
- linter = detectedLinter;
1272
- await events.emit("info", `Auto-detected linter: ${(0, node_util.styleText)("dim", linter)}`);
1273
- }
1274
- }
1275
- if (linter && linter !== "auto" && linter in _kubb_core_utils.linters) {
1276
- const linterConfig = _kubb_core_utils.linters[linter];
1277
- const outputPath = node_path.default.resolve(config.root, config.output.path);
1278
- try {
1279
- const hookId = (0, node_crypto.createHash)("sha256").update([config.name, linter].filter(Boolean).join("-")).digest("hex");
1280
- await events.emit("hook:start", {
1281
- id: hookId,
1282
- command: linterConfig.command,
1283
- args: linterConfig.args(outputPath)
1284
- });
1285
- await events.onOnce("hook:end", async ({ success, error }) => {
1286
- if (!success) throw error;
1287
- await events.emit("success", [
1288
- `Linting with ${(0, node_util.styleText)("dim", linter)}`,
1289
- logLevel >= _kubb_core.LogLevel.info ? `on ${(0, node_util.styleText)("dim", outputPath)}` : void 0,
1290
- "successfully"
1291
- ].filter(Boolean).join(" "));
1292
- });
1293
- } catch (caughtError) {
1294
- const error = new Error(linterConfig.errorMessage);
1295
- error.cause = caughtError;
1296
- await events.emit("error", error);
1297
- }
1298
- }
1299
- await events.emit("lint:end");
1300
- }
1365
+ const outputPath = node_path.default.resolve(config.root, config.output.path);
1366
+ if (config.output.format) await runToolPass({
1367
+ toolValue: config.output.format,
1368
+ detect: _kubb_core.detectFormatter,
1369
+ toolMap: _kubb_core.formatters,
1370
+ toolLabel: "formatter",
1371
+ successPrefix: "Formatting",
1372
+ noToolMessage: "No formatter found (biome, prettier, or oxfmt). Skipping formatting.",
1373
+ configName: config.name,
1374
+ outputPath,
1375
+ logLevel,
1376
+ events,
1377
+ onStart: () => events.emit("format:start"),
1378
+ onEnd: () => events.emit("format:end")
1379
+ });
1380
+ if (config.output.lint) await runToolPass({
1381
+ toolValue: config.output.lint,
1382
+ detect: _kubb_core.detectLinter,
1383
+ toolMap: _kubb_core.linters,
1384
+ toolLabel: "linter",
1385
+ successPrefix: "Linting",
1386
+ noToolMessage: "No linter found (biome, oxlint, or eslint). Skipping linting.",
1387
+ configName: config.name,
1388
+ outputPath,
1389
+ logLevel,
1390
+ events,
1391
+ onStart: () => events.emit("lint:start"),
1392
+ onEnd: () => events.emit("lint:end")
1393
+ });
1301
1394
  if (config.hooks) {
1302
1395
  await events.emit("hooks:start");
1303
1396
  await executeHooks({
@@ -1306,11 +1399,10 @@ async function generate({ input, config: userConfig, events, logLevel }) {
1306
1399
  });
1307
1400
  await events.emit("hooks:end");
1308
1401
  }
1309
- const generationStatus = failedPlugins.size > 0 || error ? "failed" : "success";
1310
1402
  await events.emit("generation:summary", config, {
1311
1403
  failedPlugins,
1312
1404
  filesCreated: files.length,
1313
- status: generationStatus,
1405
+ status: "success",
1314
1406
  hrStart,
1315
1407
  pluginTimings
1316
1408
  });
@@ -1323,183 +1415,59 @@ async function generate({ input, config: userConfig, events, logLevel }) {
1323
1415
  })),
1324
1416
  hrStart,
1325
1417
  filesCreated: files.length,
1326
- status: generationStatus
1418
+ status: "success"
1327
1419
  }));
1328
1420
  }
1329
- //#endregion
1330
- //#region src/utils/getCosmiConfig.ts
1331
- const tsLoader = async (configFile) => {
1332
- return await (0, jiti.createJiti)(require("url").pathToFileURL(__filename).href, {
1333
- jsx: {
1334
- runtime: "automatic",
1335
- importSource: "@kubb/react-fabric"
1336
- },
1337
- sourceMaps: true,
1338
- interopDefault: true
1339
- }).import(configFile, { default: true });
1340
- };
1341
- async function getCosmiConfig(moduleName, config) {
1342
- let result;
1343
- const searchPlaces = [
1344
- "package.json",
1345
- `.${moduleName}rc`,
1346
- `.${moduleName}rc.json`,
1347
- `.${moduleName}rc.yaml`,
1348
- `.${moduleName}rc.yml`,
1349
- `.${moduleName}rc.ts`,
1350
- `.${moduleName}rc.js`,
1351
- `.${moduleName}rc.mjs`,
1352
- `.${moduleName}rc.cjs`,
1353
- `${moduleName}.config.ts`,
1354
- `${moduleName}.config.js`,
1355
- `${moduleName}.config.mjs`,
1356
- `${moduleName}.config.cjs`
1357
- ];
1358
- const explorer = (0, cosmiconfig.cosmiconfig)(moduleName, {
1359
- cache: false,
1360
- searchPlaces: [
1361
- ...searchPlaces.map((searchPlace) => {
1362
- return `.config/${searchPlace}`;
1363
- }),
1364
- ...searchPlaces.map((searchPlace) => {
1365
- return `configs/${searchPlace}`;
1366
- }),
1367
- ...searchPlaces
1368
- ],
1369
- loaders: { ".ts": tsLoader }
1370
- });
1371
- try {
1372
- result = config ? await explorer.load(config) : await explorer.search();
1373
- } catch (error) {
1374
- throw new Error("Config failed loading", { cause: error });
1375
- }
1376
- if (result?.isEmpty || !result || !result.config) throw new Error("Config not defined, create a kubb.config.js or pass through your config with the option --config");
1377
- return result;
1378
- }
1379
- //#endregion
1380
- //#region src/utils/watcher.ts
1381
- async function startWatcher(path, cb) {
1382
- const { watch } = await import("chokidar");
1383
- watch(path, {
1384
- ignorePermissionErrors: true,
1385
- ignored: "**/{.git,node_modules}/**"
1386
- }).on("all", async (type, file) => {
1387
- console.log((0, node_util.styleText)("yellow", (0, node_util.styleText)("bold", `Change detected: ${type} ${file}`)));
1421
+ async function runGenerateCommand({ input, configPath, logLevel: logLevelKey, watch }) {
1422
+ const logLevel = _kubb_core.logLevel[logLevelKey] ?? _kubb_core.logLevel.info;
1423
+ const events = new AsyncEventEmitter();
1424
+ const promiseManager = new _kubb_core.PromiseManager();
1425
+ await setupLogger(events, { logLevel });
1426
+ await require_telemetry.executeIfOnline(async () => {
1388
1427
  try {
1389
- await cb(path);
1390
- } catch (_e) {
1391
- console.log((0, node_util.styleText)("red", "Watcher failed"));
1392
- }
1428
+ const latestVersion = (await (await fetch(require_constants.KUBB_NPM_PACKAGE_URL)).json()).version;
1429
+ if (latestVersion && require_package.version < latestVersion) await events.emit("version:new", require_package.version, latestVersion);
1430
+ } catch {}
1393
1431
  });
1394
- }
1395
- //#endregion
1396
- //#region src/commands/generate.ts
1397
- const command = (0, citty.defineCommand)({
1398
- meta: {
1399
- name: "generate",
1400
- description: "[input] Generate files based on a 'kubb.config.ts' file"
1401
- },
1402
- args: {
1403
- config: {
1404
- type: "string",
1405
- description: "Path to the Kubb config",
1406
- alias: "c"
1407
- },
1408
- logLevel: {
1409
- type: "string",
1410
- description: "Info, silent, verbose or debug",
1411
- alias: "l",
1412
- default: "info",
1413
- valueHint: "silent|info|verbose|debug"
1414
- },
1415
- watch: {
1416
- type: "boolean",
1417
- description: "Watch mode based on the input file",
1418
- alias: "w",
1419
- default: false
1420
- },
1421
- debug: {
1422
- type: "boolean",
1423
- description: "Override logLevel to debug",
1424
- alias: "d",
1425
- default: false
1426
- },
1427
- verbose: {
1428
- type: "boolean",
1429
- description: "Override logLevel to verbose",
1430
- alias: "v",
1431
- default: false
1432
- },
1433
- silent: {
1434
- type: "boolean",
1435
- description: "Override logLevel to silent",
1436
- alias: "s",
1437
- default: false
1438
- },
1439
- help: {
1440
- type: "boolean",
1441
- description: "Show help",
1442
- alias: "h",
1443
- default: false
1444
- }
1445
- },
1446
- async run(commandContext) {
1447
- const { args } = commandContext;
1448
- const input = args._[0];
1449
- const events = new _kubb_core_utils.AsyncEventEmitter();
1450
- const promiseManager = new _kubb_core.PromiseManager();
1451
- if (args.help) return (0, citty.showUsage)(command);
1452
- if (args.debug) args.logLevel = "debug";
1453
- if (args.verbose) args.logLevel = "verbose";
1454
- if (args.silent) args.logLevel = "silent";
1455
- const logLevel = _kubb_core.LogLevel[args.logLevel] || 3;
1456
- await setupLogger(events, { logLevel });
1457
- await (0, _kubb_core_utils.executeIfOnline)(async () => {
1458
- try {
1459
- const latestVersion = (await (await fetch("https://registry.npmjs.org/@kubb/cli/latest")).json()).version;
1460
- if (latestVersion && require_package.version < latestVersion) await events.emit("version:new", require_package.version, latestVersion);
1461
- } catch {}
1462
- });
1463
- try {
1464
- const result = await getCosmiConfig("kubb", args.config);
1465
- const configs = await (0, _kubb_core_utils.getConfigs)(result.config, args);
1466
- await events.emit("config:start");
1467
- await events.emit("info", "Config loaded", node_path.default.relative(node_process.cwd(), result.filepath));
1468
- await events.emit("success", "Config loaded successfully", node_path.default.relative(node_process.cwd(), result.filepath));
1469
- await events.emit("config:end", configs);
1470
- await events.emit("lifecycle:start", require_package.version);
1471
- const promises = configs.map((config) => {
1472
- return async () => {
1473
- if ((0, _kubb_core.isInputPath)(config) && args.watch) {
1474
- await startWatcher([input || config.input.path], async (paths) => {
1475
- events.removeAll();
1476
- await generate({
1477
- input,
1478
- config,
1479
- logLevel,
1480
- events
1481
- });
1482
- _clack_prompts.log.step((0, node_util.styleText)("yellow", `Watching for changes in ${paths.join(" and ")}`));
1432
+ try {
1433
+ const result = await getCosmiConfig("kubb", configPath);
1434
+ const configs = await (0, _kubb_core.getConfigs)(result.config, { input });
1435
+ await events.emit("config:start");
1436
+ await events.emit("info", "Config loaded", node_path.default.relative(node_process.default.cwd(), result.filepath));
1437
+ await events.emit("success", "Config loaded successfully", node_path.default.relative(node_process.default.cwd(), result.filepath));
1438
+ await events.emit("config:end", configs);
1439
+ await events.emit("lifecycle:start", require_package.version);
1440
+ const promises = configs.map((config) => {
1441
+ return async () => {
1442
+ if ((0, _kubb_core.isInputPath)(config) && watch) {
1443
+ await startWatcher([input || config.input.path], async (paths) => {
1444
+ events.removeAll();
1445
+ await generate({
1446
+ input,
1447
+ config,
1448
+ logLevel,
1449
+ events
1483
1450
  });
1484
- return;
1485
- }
1486
- await generate({
1487
- input,
1488
- config,
1489
- logLevel,
1490
- events
1451
+ _clack_prompts.log.step((0, node_util.styleText)("yellow", `Watching for changes in ${paths.join(" and ")}`));
1491
1452
  });
1492
- };
1493
- });
1494
- await promiseManager.run("seq", promises);
1495
- await events.emit("lifecycle:end");
1496
- } catch (error) {
1497
- await events.emit("error", error);
1498
- node_process.exit(1);
1499
- }
1453
+ return;
1454
+ }
1455
+ await generate({
1456
+ input,
1457
+ config,
1458
+ logLevel,
1459
+ events
1460
+ });
1461
+ };
1462
+ });
1463
+ await promiseManager.run("seq", promises);
1464
+ await events.emit("lifecycle:end");
1465
+ } catch (error) {
1466
+ await events.emit("error", require_errors.toError(error));
1467
+ node_process.default.exit(1);
1500
1468
  }
1501
- });
1469
+ }
1502
1470
  //#endregion
1503
- exports.default = command;
1471
+ exports.runGenerateCommand = runGenerateCommand;
1504
1472
 
1505
- //# sourceMappingURL=generate-COj0aMS6.cjs.map
1473
+ //# sourceMappingURL=generate-JC65igQh.cjs.map