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

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 (173) hide show
  1. package/README.md +180 -27
  2. package/bin/kubb.js +6 -0
  3. package/dist/agent-Bx2yllmS.js +68 -0
  4. package/dist/agent-Bx2yllmS.js.map +1 -0
  5. package/dist/agent-CeLwj5im.cjs +70 -0
  6. package/dist/agent-CeLwj5im.cjs.map +1 -0
  7. package/dist/{chunk--u3MIqq1.js → chunk-BvFE5Tac.js} +1 -0
  8. package/dist/constants-B2JTeRBb.js +42 -0
  9. package/dist/constants-B2JTeRBb.js.map +1 -0
  10. package/dist/constants-BINTA5VZ.cjs +77 -0
  11. package/dist/constants-BINTA5VZ.cjs.map +1 -0
  12. package/dist/constants-BYGmiFs0.cjs +139 -0
  13. package/dist/constants-BYGmiFs0.cjs.map +1 -0
  14. package/dist/constants-DSJ-Xrbv.js +116 -0
  15. package/dist/constants-DSJ-Xrbv.js.map +1 -0
  16. package/dist/define-Bdn8j5VM.cjs +54 -0
  17. package/dist/define-Bdn8j5VM.cjs.map +1 -0
  18. package/dist/define-m_fp-Aqm.js +43 -0
  19. package/dist/define-m_fp-Aqm.js.map +1 -0
  20. package/dist/errors-CINO1EIv.js +43 -0
  21. package/dist/errors-CINO1EIv.js.map +1 -0
  22. package/dist/{errors-DBW0N9w4.cjs → errors-CLCjoSg0.cjs} +22 -6
  23. package/dist/errors-CLCjoSg0.cjs.map +1 -0
  24. package/dist/{generate-Rly1EXBN.js → generate-BLvcvoIj.js} +12 -6
  25. package/dist/generate-BLvcvoIj.js.map +1 -0
  26. package/dist/{generate-DU5zzc54.cjs → generate-drLxTAnz.cjs} +11 -5
  27. package/dist/generate-drLxTAnz.cjs.map +1 -0
  28. package/dist/index.cjs +52 -21
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.js +53 -22
  32. package/dist/index.js.map +1 -1
  33. package/dist/init-CGu7JZEF.js +53 -0
  34. package/dist/init-CGu7JZEF.js.map +1 -0
  35. package/dist/init-CyCjvIEF.cjs +53 -0
  36. package/dist/init-CyCjvIEF.cjs.map +1 -0
  37. package/dist/mcp-Cq2sylQC.js +39 -0
  38. package/dist/mcp-Cq2sylQC.js.map +1 -0
  39. package/dist/mcp-DSF5gpI-.cjs +39 -0
  40. package/dist/mcp-DSF5gpI-.cjs.map +1 -0
  41. package/dist/{package-BJ6ionm6.cjs → package-DZ-6zAIO.cjs} +2 -2
  42. package/dist/package-DZ-6zAIO.cjs.map +1 -0
  43. package/dist/package-OLYIpjqw.js +6 -0
  44. package/dist/package-OLYIpjqw.js.map +1 -0
  45. package/dist/{generate-BHNyeQXl.js → run-Bfbr3RaM.js} +781 -502
  46. package/dist/run-Bfbr3RaM.js.map +1 -0
  47. package/dist/run-BzpYYOQs.js +121 -0
  48. package/dist/run-BzpYYOQs.js.map +1 -0
  49. package/dist/run-CCZ24VKk.js +51 -0
  50. package/dist/run-CCZ24VKk.js.map +1 -0
  51. package/dist/run-CF97BWVa.js +244 -0
  52. package/dist/run-CF97BWVa.js.map +1 -0
  53. package/dist/run-CQbj3ley.cjs +52 -0
  54. package/dist/run-CQbj3ley.cjs.map +1 -0
  55. package/dist/{generate-Cq5RDTBL.cjs → run-CVlrIZoW.cjs} +786 -507
  56. package/dist/run-CVlrIZoW.cjs.map +1 -0
  57. package/dist/run-D0hmRpHy.js +49 -0
  58. package/dist/run-D0hmRpHy.js.map +1 -0
  59. package/dist/run-DwdAwnLG.cjs +125 -0
  60. package/dist/run-DwdAwnLG.cjs.map +1 -0
  61. package/dist/run-Lr0Ctnu0.cjs +50 -0
  62. package/dist/run-Lr0Ctnu0.cjs.map +1 -0
  63. package/dist/run-YsoCk5we.cjs +248 -0
  64. package/dist/run-YsoCk5we.cjs.map +1 -0
  65. package/dist/{shell-7HPrTCJ5.cjs → shell-475fQKaX.cjs} +8 -3
  66. package/dist/shell-475fQKaX.cjs.map +1 -0
  67. package/dist/{shell-DqqWsHCD.js → shell-CN6DNqeC.js} +9 -4
  68. package/dist/shell-CN6DNqeC.js.map +1 -0
  69. package/dist/{telemetry-DZ7IrLAU.cjs → telemetry-B2iWkY5e.cjs} +53 -13
  70. package/dist/telemetry-B2iWkY5e.cjs.map +1 -0
  71. package/dist/{telemetry-BF3SMlH6.js → telemetry-BkektVz6.js} +52 -12
  72. package/dist/telemetry-BkektVz6.js.map +1 -0
  73. package/dist/validate-CAUqLaGt.js +26 -0
  74. package/dist/validate-CAUqLaGt.js.map +1 -0
  75. package/dist/validate-J6AEd5zK.cjs +26 -0
  76. package/dist/validate-J6AEd5zK.cjs.map +1 -0
  77. package/package.json +57 -48
  78. package/src/commands/agent/start.ts +27 -8
  79. package/src/commands/agent.ts +3 -1
  80. package/src/commands/generate.ts +39 -8
  81. package/src/commands/init.ts +40 -4
  82. package/src/commands/mcp.ts +28 -4
  83. package/src/commands/validate.ts +11 -4
  84. package/src/constants.ts +5 -80
  85. package/src/index.ts +12 -13
  86. package/src/loggers/clackLogger.ts +98 -88
  87. package/src/loggers/fileSystemLogger.ts +37 -25
  88. package/src/loggers/githubActionsLogger.ts +35 -48
  89. package/src/loggers/plainLogger.ts +33 -45
  90. package/src/loggers/types.ts +6 -0
  91. package/src/loggers/utils.ts +155 -9
  92. package/src/runners/agent/run.ts +113 -0
  93. package/src/runners/agent/utils.ts +98 -0
  94. package/src/runners/generate/run.ts +276 -0
  95. package/src/runners/generate/utils.ts +209 -0
  96. package/src/runners/init/run.ts +211 -0
  97. package/src/{utils/packageManager.ts → runners/init/utils.ts} +10 -0
  98. package/src/runners/mcp/run.ts +55 -0
  99. package/src/runners/validate/run.ts +63 -0
  100. package/src/{utils/telemetry.ts → telemetry.ts} +28 -8
  101. package/bin/kubb.cjs +0 -18
  102. package/dist/agent-5mmp7QzF.js +0 -56
  103. package/dist/agent-5mmp7QzF.js.map +0 -1
  104. package/dist/agent-BKphjOIF.cjs +0 -58
  105. package/dist/agent-BKphjOIF.cjs.map +0 -1
  106. package/dist/agent-BapvKB4r.cjs +0 -92
  107. package/dist/agent-BapvKB4r.cjs.map +0 -1
  108. package/dist/agent-CBrpIMMU.js +0 -88
  109. package/dist/agent-CBrpIMMU.js.map +0 -1
  110. package/dist/constants-D0XHAHeZ.cjs +0 -178
  111. package/dist/constants-D0XHAHeZ.cjs.map +0 -1
  112. package/dist/constants-DJM9zCXm.js +0 -131
  113. package/dist/constants-DJM9zCXm.js.map +0 -1
  114. package/dist/define--M_JMcDC.js +0 -25
  115. package/dist/define--M_JMcDC.js.map +0 -1
  116. package/dist/define-D6Kfm7-Z.cjs +0 -36
  117. package/dist/define-D6Kfm7-Z.cjs.map +0 -1
  118. package/dist/errors-6mF_WKxg.js +0 -27
  119. package/dist/errors-6mF_WKxg.js.map +0 -1
  120. package/dist/errors-DBW0N9w4.cjs.map +0 -1
  121. package/dist/generate-BHNyeQXl.js.map +0 -1
  122. package/dist/generate-Cq5RDTBL.cjs.map +0 -1
  123. package/dist/generate-DU5zzc54.cjs.map +0 -1
  124. package/dist/generate-Rly1EXBN.js.map +0 -1
  125. package/dist/init-BK6inBTR.cjs +0 -306
  126. package/dist/init-BK6inBTR.cjs.map +0 -1
  127. package/dist/init-BQ6zfsnw.js +0 -302
  128. package/dist/init-BQ6zfsnw.js.map +0 -1
  129. package/dist/init-CN1JFyGX.cjs +0 -25
  130. package/dist/init-CN1JFyGX.cjs.map +0 -1
  131. package/dist/init-iN7e1XwI.js +0 -25
  132. package/dist/init-iN7e1XwI.js.map +0 -1
  133. package/dist/jiti-Cd3S0xwr.cjs +0 -16
  134. package/dist/jiti-Cd3S0xwr.cjs.map +0 -1
  135. package/dist/jiti-e08mD2Ph.js +0 -11
  136. package/dist/jiti-e08mD2Ph.js.map +0 -1
  137. package/dist/mcp-BiGUvbWP.js +0 -41
  138. package/dist/mcp-BiGUvbWP.js.map +0 -1
  139. package/dist/mcp-CONmm_xT.cjs +0 -42
  140. package/dist/mcp-CONmm_xT.cjs.map +0 -1
  141. package/dist/mcp-T7Q4nWbT.cjs +0 -16
  142. package/dist/mcp-T7Q4nWbT.cjs.map +0 -1
  143. package/dist/mcp-eP1S40LZ.js +0 -16
  144. package/dist/mcp-eP1S40LZ.js.map +0 -1
  145. package/dist/package-BJ6ionm6.cjs.map +0 -1
  146. package/dist/package-BKZ0H3Zf.js +0 -6
  147. package/dist/package-BKZ0H3Zf.js.map +0 -1
  148. package/dist/shell-7HPrTCJ5.cjs.map +0 -1
  149. package/dist/shell-DqqWsHCD.js.map +0 -1
  150. package/dist/telemetry-BF3SMlH6.js.map +0 -1
  151. package/dist/telemetry-DZ7IrLAU.cjs.map +0 -1
  152. package/dist/validate-BImbbx1t.js +0 -41
  153. package/dist/validate-BImbbx1t.js.map +0 -1
  154. package/dist/validate-DAZdX_0i.js +0 -25
  155. package/dist/validate-DAZdX_0i.js.map +0 -1
  156. package/dist/validate-DucFMytl.cjs +0 -25
  157. package/dist/validate-DucFMytl.cjs.map +0 -1
  158. package/dist/validate-ujLCYSWU.cjs +0 -42
  159. package/dist/validate-ujLCYSWU.cjs.map +0 -1
  160. package/src/runners/agent.ts +0 -102
  161. package/src/runners/generate.ts +0 -343
  162. package/src/runners/init.ts +0 -323
  163. package/src/runners/mcp.ts +0 -32
  164. package/src/runners/validate.ts +0 -35
  165. package/src/types.ts +0 -11
  166. package/src/utils/Writables.ts +0 -17
  167. package/src/utils/executeHooks.ts +0 -45
  168. package/src/utils/flags.ts +0 -10
  169. package/src/utils/getCosmiConfig.ts +0 -71
  170. package/src/utils/getSummary.ts +0 -68
  171. package/src/utils/jiti.ts +0 -9
  172. package/src/utils/runHook.ts +0 -75
  173. package/src/utils/watcher.ts +0 -19
@@ -4,14 +4,30 @@ import { styleText } from 'node:util'
4
4
  import * as clack from '@clack/prompts'
5
5
  import { formatMs, formatMsWithColor, getIntro, toCause } from '@internals/utils'
6
6
  import { defineLogger, logLevel as logLevelMap } from '@kubb/core'
7
- import { getSummary } from '../utils/getSummary.ts'
8
- import { runHook } from '../utils/runHook.ts'
9
- import { ClackWritable } from '../utils/Writables.ts'
7
+ import { getSummary } from './utils.ts'
10
8
  import { buildProgressLine, formatCommandWithArgs, formatMessage } from './utils.ts'
9
+ import { Writable } from 'node:stream'
10
+ import type { WritableOptions } from 'node:stream'
11
11
 
12
12
  /**
13
- * Clack adapter for local TTY environments
14
- * Provides a beautiful CLI UI with flat structure inspired by Claude's CLI patterns
13
+ * Node.js `Writable` stream that forwards each chunk to a clack `taskLog` message.
14
+ * Used to pipe hook subprocess output into the clack task log UI.
15
+ */
16
+ class ClackWritable extends Writable {
17
+ taskLog: ReturnType<typeof clack.taskLog>
18
+ constructor(taskLog: ReturnType<typeof clack.taskLog>, opts?: WritableOptions) {
19
+ super(opts)
20
+
21
+ this.taskLog = taskLog
22
+ }
23
+ _write(chunk: Buffer, _encoding: BufferEncoding, callback: (error?: Error | null) => void): void {
24
+ this.taskLog.message(`${styleText('dim', chunk.toString())}`)
25
+ callback()
26
+ }
27
+ }
28
+
29
+ /**
30
+ * TTY logger with beautiful UI and progress indicators for local development.
15
31
  */
16
32
  export const clackLogger = defineLogger({
17
33
  name: 'clack',
@@ -73,7 +89,7 @@ export const clackLogger = defineLogger({
73
89
  state.isSpinning = false
74
90
  }
75
91
 
76
- context.on('info', (message, info = '') => {
92
+ context.on('kubb:info', ({ message, info = '' }) => {
77
93
  if (logLevel <= logLevelMap.silent) {
78
94
  return
79
95
  }
@@ -87,7 +103,7 @@ export const clackLogger = defineLogger({
87
103
  }
88
104
  })
89
105
 
90
- context.on('success', (message, info = '') => {
106
+ context.on('kubb:success', ({ message, info = '' }) => {
91
107
  if (logLevel <= logLevelMap.silent) {
92
108
  return
93
109
  }
@@ -101,7 +117,7 @@ export const clackLogger = defineLogger({
101
117
  }
102
118
  })
103
119
 
104
- context.on('warn', (message, info) => {
120
+ context.on('kubb:warn', ({ message, info }) => {
105
121
  if (logLevel < logLevelMap.warn) {
106
122
  return
107
123
  }
@@ -113,7 +129,7 @@ export const clackLogger = defineLogger({
113
129
  clack.log.warn(text)
114
130
  })
115
131
 
116
- context.on('error', (error) => {
132
+ context.on('kubb:error', ({ error }) => {
117
133
  const caused = toCause(error)
118
134
 
119
135
  const text = [styleText('red', '✗'), error.message].join(' ')
@@ -142,33 +158,38 @@ export const clackLogger = defineLogger({
142
158
  }
143
159
  })
144
160
 
145
- context.on('version:new', (version, latestVersion) => {
161
+ context.on('kubb:version:new', ({ currentVersion, latestVersion }) => {
146
162
  if (logLevel <= logLevelMap.silent) {
147
163
  return
148
164
  }
149
165
 
150
- clack.box(
151
- `\`v${version}\` → \`v${latestVersion}\`
166
+ try {
167
+ clack.box(
168
+ `\`v${currentVersion}\` → \`v${latestVersion}\`
152
169
  Run \`npm install -g @kubb/cli\` to update`,
153
- 'Update available for `Kubb`',
154
- {
155
- width: 'auto',
156
- formatBorder: (s: string) => styleText('yellow', s),
157
- rounded: true,
158
- withGuide: false,
159
- contentAlign: 'center',
160
- titleAlign: 'center',
161
- },
162
- )
170
+ 'Update available for `Kubb`',
171
+ {
172
+ width: 'auto',
173
+ formatBorder: (s: string) => styleText('yellow', s),
174
+ rounded: true,
175
+ withGuide: false,
176
+ contentAlign: 'center',
177
+ titleAlign: 'center',
178
+ },
179
+ )
180
+ } catch {
181
+ console.log(`Update available for Kubb: v${currentVersion} → v${latestVersion}`)
182
+ console.log('Run `npm install -g @kubb/cli` to update')
183
+ }
163
184
  })
164
185
 
165
- context.on('lifecycle:start', async (version) => {
186
+ context.on('kubb:lifecycle:start', async ({ version }) => {
166
187
  console.log(`\n${getIntro({ title: 'The ultimate toolkit for working with APIs', description: 'Ready to start', version, areEyesOpen: true })}\n`)
167
188
 
168
189
  reset()
169
190
  })
170
191
 
171
- context.on('config:start', () => {
192
+ context.on('kubb:config:start', () => {
172
193
  if (logLevel <= logLevelMap.silent) {
173
194
  return
174
195
  }
@@ -179,7 +200,7 @@ Run \`npm install -g @kubb/cli\` to update`,
179
200
  startSpinner(getMessage('Configuration loading'))
180
201
  })
181
202
 
182
- context.on('config:end', (_configs) => {
203
+ context.on('kubb:config:end', () => {
183
204
  if (logLevel <= logLevelMap.silent) {
184
205
  return
185
206
  }
@@ -189,7 +210,7 @@ Run \`npm install -g @kubb/cli\` to update`,
189
210
  clack.outro(text)
190
211
  })
191
212
 
192
- context.on('generation:start', (config) => {
213
+ context.on('kubb:generation:start', ({ config }) => {
193
214
  reset()
194
215
 
195
216
  // Initialize progress tracking for this generation
@@ -200,7 +221,7 @@ Run \`npm install -g @kubb/cli\` to update`,
200
221
  clack.intro(text)
201
222
  })
202
223
 
203
- context.on('plugin:start', (plugin) => {
224
+ context.on('kubb:plugin:start', ({ plugin }) => {
204
225
  if (logLevel <= logLevelMap.silent) {
205
226
  return
206
227
  }
@@ -222,7 +243,7 @@ Run \`npm install -g @kubb/cli\` to update`,
222
243
  state.activeProgress.set(plugin.name, { progressBar, interval })
223
244
  })
224
245
 
225
- context.on('plugin:end', (plugin, { duration, success }) => {
246
+ context.on('kubb:plugin:end', ({ plugin, duration, success }) => {
226
247
  stopSpinner()
227
248
 
228
249
  const active = state.activeProgress.get(plugin.name)
@@ -253,7 +274,7 @@ Run \`npm install -g @kubb/cli\` to update`,
253
274
  showProgressStep()
254
275
  })
255
276
 
256
- context.on('files:processing:start', (files) => {
277
+ context.on('kubb:files:processing:start', ({ files }) => {
257
278
  if (logLevel <= logLevelMap.silent) {
258
279
  return
259
280
  }
@@ -270,12 +291,12 @@ Run \`npm install -g @kubb/cli\` to update`,
270
291
  size: 30,
271
292
  })
272
293
 
273
- context.emit('info', text)
294
+ context.emit('kubb:info', { message: text })
274
295
  progressBar.start(getMessage(text))
275
296
  state.activeProgress.set('files', { progressBar })
276
297
  })
277
298
 
278
- context.on('file:processing:update', ({ file, config }) => {
299
+ context.on('kubb:file:processing:update', ({ file, config }) => {
279
300
  if (logLevel <= logLevelMap.silent) {
280
301
  return
281
302
  }
@@ -293,7 +314,7 @@ Run \`npm install -g @kubb/cli\` to update`,
293
314
 
294
315
  active.progressBar.advance(undefined, text)
295
316
  })
296
- context.on('files:processing:end', () => {
317
+ context.on('kubb:files:processing:end', () => {
297
318
  if (logLevel <= logLevelMap.silent) {
298
319
  return
299
320
  }
@@ -314,13 +335,13 @@ Run \`npm install -g @kubb/cli\` to update`,
314
335
  showProgressStep()
315
336
  })
316
337
 
317
- context.on('generation:end', (config) => {
338
+ context.on('kubb:generation:end', ({ config }) => {
318
339
  const text = getMessage(config.name ? `Generation completed for ${styleText('dim', config.name)}` : 'Generation completed')
319
340
 
320
341
  clack.outro(text)
321
342
  })
322
343
 
323
- context.on('format:start', () => {
344
+ context.on('kubb:format:start', () => {
324
345
  if (logLevel <= logLevelMap.silent) {
325
346
  return
326
347
  }
@@ -330,7 +351,7 @@ Run \`npm install -g @kubb/cli\` to update`,
330
351
  clack.intro(text)
331
352
  })
332
353
 
333
- context.on('format:end', () => {
354
+ context.on('kubb:format:end', () => {
334
355
  if (logLevel <= logLevelMap.silent) {
335
356
  return
336
357
  }
@@ -340,7 +361,7 @@ Run \`npm install -g @kubb/cli\` to update`,
340
361
  clack.outro(text)
341
362
  })
342
363
 
343
- context.on('lint:start', () => {
364
+ context.on('kubb:lint:start', () => {
344
365
  if (logLevel <= logLevelMap.silent) {
345
366
  return
346
367
  }
@@ -350,7 +371,7 @@ Run \`npm install -g @kubb/cli\` to update`,
350
371
  clack.intro(text)
351
372
  })
352
373
 
353
- context.on('lint:end', () => {
374
+ context.on('kubb:lint:end', () => {
354
375
  if (logLevel <= logLevelMap.silent) {
355
376
  return
356
377
  }
@@ -360,54 +381,18 @@ Run \`npm install -g @kubb/cli\` to update`,
360
381
  clack.outro(text)
361
382
  })
362
383
 
363
- context.on('hook:start', async ({ id, command, args }) => {
364
- const commandWithArgs = formatCommandWithArgs(command, args)
365
- const text = getMessage(`Hook ${styleText('dim', commandWithArgs)} started`)
366
-
367
- // Skip hook execution if no id is provided (e.g., during benchmarks or tests)
368
- if (!id) {
369
- return
370
- }
371
-
384
+ context.on('kubb:hook:start', ({ command, args }) => {
372
385
  if (logLevel <= logLevelMap.silent) {
373
- await runHook({
374
- id,
375
- command,
376
- args,
377
- commandWithArgs,
378
- context,
379
- sink: {
380
- onStderr: (s) => console.error(s),
381
- onStdout: (s) => console.log(s),
382
- },
383
- })
384
386
  return
385
387
  }
386
388
 
387
- clack.intro(text)
388
-
389
- const logger = clack.taskLog({
390
- title: getMessage(['Executing hook', logLevel >= logLevelMap.info ? styleText('dim', commandWithArgs) : undefined].filter(Boolean).join(' ')),
391
- })
392
-
393
- const writable = new ClackWritable(logger)
389
+ const commandWithArgs = formatCommandWithArgs(command, args)
390
+ const text = getMessage(`Hook ${styleText('dim', commandWithArgs)} started`)
394
391
 
395
- await runHook({
396
- id,
397
- command,
398
- args,
399
- commandWithArgs,
400
- context,
401
- stream: true,
402
- sink: {
403
- onLine: (line) => writable.write(line),
404
- onStderr: (s) => logger.error(s),
405
- onStdout: (s) => logger.message(s),
406
- },
407
- })
392
+ clack.intro(text)
408
393
  })
409
394
 
410
- context.on('hook:end', ({ command, args }) => {
395
+ context.on('kubb:hook:end', ({ command, args }) => {
411
396
  if (logLevel <= logLevelMap.silent) {
412
397
  return
413
398
  }
@@ -418,7 +403,7 @@ Run \`npm install -g @kubb/cli\` to update`,
418
403
  clack.outro(text)
419
404
  })
420
405
 
421
- context.on('generation:summary', (config, { pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
406
+ context.on('kubb:generation:summary', ({ config, pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
422
407
  const summary = getSummary({
423
408
  failedPlugins,
424
409
  filesCreated,
@@ -433,18 +418,43 @@ Run \`npm install -g @kubb/cli\` to update`,
433
418
  summary.push('\n')
434
419
 
435
420
  const borderColor = status === 'success' ? 'green' : 'red'
436
- clack.box(summary.join('\n'), getMessage(title), {
437
- width: 'auto',
438
- formatBorder: (s: string) => styleText(borderColor, s),
439
- rounded: true,
440
- withGuide: false,
441
- contentAlign: 'left',
442
- titleAlign: 'center',
443
- })
421
+ try {
422
+ clack.box(summary.join('\n'), getMessage(title), {
423
+ width: 'auto',
424
+ formatBorder: (s: string) => styleText(borderColor, s),
425
+ rounded: true,
426
+ withGuide: false,
427
+ contentAlign: 'left',
428
+ titleAlign: 'center',
429
+ })
430
+ } catch {
431
+ console.log(summary.join('\n'))
432
+ }
444
433
  })
445
434
 
446
- context.on('lifecycle:end', () => {
435
+ context.on('kubb:lifecycle:end', () => {
447
436
  reset()
448
437
  })
438
+
439
+ return (commandWithArgs: string) => {
440
+ if (logLevel <= logLevelMap.silent) {
441
+ return {
442
+ onStdout: (s: string) => console.log(s),
443
+ onStderr: (s: string) => console.error(s),
444
+ }
445
+ }
446
+
447
+ const logger = clack.taskLog({
448
+ title: getMessage(['Executing hook', logLevel >= logLevelMap.info ? styleText('dim', commandWithArgs) : undefined].filter(Boolean).join(' ')),
449
+ })
450
+ const writable = new ClackWritable(logger)
451
+
452
+ return {
453
+ stream: true,
454
+ onLine: (line: string) => writable.write(line),
455
+ onStdout: (s: string) => logger.message(s),
456
+ onStderr: (s: string) => logger.error(s),
457
+ }
458
+ }
449
459
  },
450
460
  })
@@ -4,17 +4,24 @@ import { formatMs, write } from '@internals/utils'
4
4
  import { defineLogger } from '@kubb/core'
5
5
 
6
6
  type CachedEvent = {
7
+ /**
8
+ * Timestamp when this event was captured, used to derive the log filename.
9
+ */
7
10
  date: Date
11
+ /**
12
+ * Accumulated log lines for this event.
13
+ */
8
14
  logs: string[]
15
+ /**
16
+ * Optional override for the output filename inside `.kubb/`. When omitted, the filename is derived from `date`.
17
+ */
9
18
  fileName?: string
10
19
  }
11
20
 
12
21
  /**
13
- * FileSystem logger for debug log persistence
14
- * Captures debug and verbose events and writes them to files in .kubb directory
22
+ * FileSystem logger that captures debug events and writes them to `.kubb` directory files.
15
23
  *
16
- * Note: Logs are written on lifecycle:end or process exit. If the process crashes
17
- * before these events, some cached logs may be lost.
24
+ * @note Logs are written on `kubb:lifecycle:end` or process exit. Cached logs may be lost if the process crashes before either event.
18
25
  */
19
26
  export const fileSystemLogger = defineLogger({
20
27
  name: 'filesystem',
@@ -45,79 +52,84 @@ export const fileSystemLogger = defineLogger({
45
52
  }
46
53
 
47
54
  if (log.logs.length > 0) {
48
- const timestamp = log.date.toLocaleString()
49
- files[pathName].push(`[${timestamp}]\n${log.logs.join('\n')}`)
55
+ const prefix = `[${log.date.toLocaleString()}] `
56
+ const indent = ' '.repeat(prefix.length)
57
+ const [first, ...rest] = log.logs
58
+ files[pathName].push([prefix + first, ...rest.map((line) => indent + line)].join('\n'))
50
59
  }
51
60
  }
52
61
 
53
- await Promise.all(Object.entries(files).map(([fileName, logs]) => write(fileName, logs.join('\n\n'))))
62
+ for (const [fileName, logs] of Object.entries(files)) {
63
+ await write(fileName, logs.join('\n'))
64
+ }
54
65
 
55
66
  return Object.keys(files)
56
67
  }
57
68
 
58
- context.on('info', (message, info) => {
69
+ context.on('kubb:info', ({ message, info }) => {
59
70
  state.cachedLogs.add({
60
71
  date: new Date(),
61
- logs: [`ℹ ${message} ${info}`],
72
+ logs: [`ℹ ${[message, info].filter(Boolean).join(' ')}`],
62
73
  })
63
74
  })
64
75
 
65
- context.on('success', (message, info) => {
76
+ context.on('kubb:success', ({ message, info }) => {
66
77
  state.cachedLogs.add({
67
78
  date: new Date(),
68
- logs: [`✓ ${message} ${info}`],
79
+ logs: [`✓ ${[message, info].filter(Boolean).join(' ')}`],
69
80
  })
70
81
  })
71
82
 
72
- context.on('warn', (message, info) => {
83
+ context.on('kubb:warn', ({ message, info }) => {
73
84
  state.cachedLogs.add({
74
85
  date: new Date(),
75
- logs: [`⚠ ${message} ${info}`],
86
+ logs: [`⚠ ${[message, info].filter(Boolean).join(' ')}`],
76
87
  })
77
88
  })
78
89
 
79
- context.on('error', (error) => {
90
+ context.on('kubb:error', ({ error }) => {
80
91
  state.cachedLogs.add({
81
92
  date: new Date(),
82
93
  logs: [`✗ ${error.message}`, error.stack || 'unknown stack'],
83
94
  })
84
95
  })
85
96
 
86
- context.on('debug', (message) => {
97
+ context.on('kubb:debug', ({ date, fileName, logs }) => {
87
98
  state.cachedLogs.add({
88
- date: new Date(),
89
- logs: message.logs,
99
+ date,
100
+ fileName,
101
+ logs,
90
102
  })
91
103
  })
92
104
 
93
- context.on('plugin:start', (plugin) => {
105
+ context.on('kubb:plugin:start', ({ plugin }) => {
94
106
  state.cachedLogs.add({
95
107
  date: new Date(),
96
- logs: [`Generating ${plugin.name}`],
108
+ logs: [`► Generating ${plugin.name}`],
97
109
  })
98
110
  })
99
111
 
100
- context.on('plugin:end', (plugin, { duration, success }) => {
112
+ context.on('kubb:plugin:end', ({ plugin, duration, success }) => {
101
113
  const durationStr = formatMs(duration)
102
114
 
103
115
  state.cachedLogs.add({
104
116
  date: new Date(),
105
- logs: [success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`],
117
+ logs: [success ? `✓ ${plugin.name} completed in ${durationStr}` : `✗ ${plugin.name} failed in ${durationStr}`],
106
118
  })
107
119
  })
108
120
 
109
- context.on('files:processing:start', (files) => {
121
+ context.on('kubb:files:processing:start', ({ files }) => {
110
122
  state.cachedLogs.add({
111
123
  date: new Date(),
112
- logs: [`Start ${files.length} writing:`, ...files.map((file) => file.path)],
124
+ logs: [`► Writing ${files.length} files`, ...files.map((file) => ` ${file.path}`)],
113
125
  })
114
126
  })
115
127
 
116
- context.on('generation:end', async (config) => {
128
+ context.on('kubb:generation:end', async ({ config }) => {
117
129
  const writtenFilePaths = await writeLogs(config.name)
118
130
  if (writtenFilePaths.length > 0) {
119
131
  const files = writtenFilePaths.map((f) => relative(process.cwd(), f))
120
- await context.emit('info', 'Debug files written to:', files.join(', '))
132
+ await context.emit('kubb:info', { message: 'Debug files written to:', info: files.join(', ') })
121
133
  }
122
134
  reset()
123
135
  })