@kubb/cli 5.0.0-beta.1 → 5.0.0-beta.100

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 (148) hide show
  1. package/LICENSE +17 -10
  2. package/README.md +171 -51
  3. package/bin/kubb.js +9 -3
  4. package/dist/Telemetry-7z2tIqPm.js +282 -0
  5. package/dist/Telemetry-7z2tIqPm.js.map +1 -0
  6. package/dist/Telemetry-xcWb-UWT.cjs +331 -0
  7. package/dist/Telemetry-xcWb-UWT.cjs.map +1 -0
  8. package/dist/{errors-CjPmyZHy.js → errors-CMvLO2NE.js} +3 -15
  9. package/dist/{errors-CjPmyZHy.js.map → errors-CMvLO2NE.js.map} +1 -1
  10. package/dist/{errors-CLCjoSg0.cjs → errors-DNxBUo3k.cjs} +2 -20
  11. package/dist/{errors-CLCjoSg0.cjs.map → errors-DNxBUo3k.cjs.map} +1 -1
  12. package/dist/generate-dIcWEfOA.cjs +95 -0
  13. package/dist/generate-dIcWEfOA.cjs.map +1 -0
  14. package/dist/generate-nPLBd69v.js +95 -0
  15. package/dist/generate-nPLBd69v.js.map +1 -0
  16. package/dist/index.cjs +33 -252
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.ts +6 -2
  19. package/dist/index.js +34 -253
  20. package/dist/index.js.map +1 -1
  21. package/dist/init-6h3K2syO.cjs +52 -0
  22. package/dist/init-6h3K2syO.cjs.map +1 -0
  23. package/dist/init-CNV6OC7m.js +53 -0
  24. package/dist/init-CNV6OC7m.js.map +1 -0
  25. package/dist/mcp-BzPiZA36.js +21 -0
  26. package/dist/mcp-BzPiZA36.js.map +1 -0
  27. package/dist/mcp-CmxnIZku.cjs +20 -0
  28. package/dist/mcp-CmxnIZku.cjs.map +1 -0
  29. package/dist/package-By3tigpl.js +6 -0
  30. package/dist/package-By3tigpl.js.map +1 -0
  31. package/dist/{package-Cdo6lNjF.cjs → package-CImfPtTH.cjs} +2 -2
  32. package/dist/package-CImfPtTH.cjs.map +1 -0
  33. package/dist/run-BJhB7Qer.js +306 -0
  34. package/dist/run-BJhB7Qer.js.map +1 -0
  35. package/dist/run-BdtVrLKu.cjs +46 -0
  36. package/dist/run-BdtVrLKu.cjs.map +1 -0
  37. package/dist/run-CaOjZRiQ.js +45 -0
  38. package/dist/run-CaOjZRiQ.js.map +1 -0
  39. package/dist/run-D-gAS1Vq.js +1264 -0
  40. package/dist/run-D-gAS1Vq.js.map +1 -0
  41. package/dist/run-DAHp52w3.js +33 -0
  42. package/dist/run-DAHp52w3.js.map +1 -0
  43. package/dist/run-DaVewTtW.cjs +310 -0
  44. package/dist/run-DaVewTtW.cjs.map +1 -0
  45. package/dist/run-HUVxfpGj.cjs +1267 -0
  46. package/dist/run-HUVxfpGj.cjs.map +1 -0
  47. package/dist/run-iidDikJH.cjs +34 -0
  48. package/dist/run-iidDikJH.cjs.map +1 -0
  49. package/dist/tools-CzgGQa64.cjs +175 -0
  50. package/dist/tools-CzgGQa64.cjs.map +1 -0
  51. package/dist/tools-DH1a7ZJH.js +152 -0
  52. package/dist/tools-DH1a7ZJH.js.map +1 -0
  53. package/dist/validate-BUw6PkPp.js +25 -0
  54. package/dist/validate-BUw6PkPp.js.map +1 -0
  55. package/dist/validate-DMfyLIta.cjs +24 -0
  56. package/dist/validate-DMfyLIta.cjs.map +1 -0
  57. package/package.json +24 -30
  58. package/dist/agent-B_pirbeB.cjs +0 -116
  59. package/dist/agent-B_pirbeB.cjs.map +0 -1
  60. package/dist/agent-CUmEyiqY.cjs +0 -58
  61. package/dist/agent-CUmEyiqY.cjs.map +0 -1
  62. package/dist/agent-Ev5hU5hH.js +0 -112
  63. package/dist/agent-Ev5hU5hH.js.map +0 -1
  64. package/dist/agent-v_2S-bnN.js +0 -56
  65. package/dist/agent-v_2S-bnN.js.map +0 -1
  66. package/dist/constants-CnDXa1R6.cjs +0 -148
  67. package/dist/constants-CnDXa1R6.cjs.map +0 -1
  68. package/dist/constants-aL3CP_Wq.js +0 -95
  69. package/dist/constants-aL3CP_Wq.js.map +0 -1
  70. package/dist/define-Bdn8j5VM.cjs +0 -54
  71. package/dist/define-Bdn8j5VM.cjs.map +0 -1
  72. package/dist/define-Ctii4bel.js +0 -43
  73. package/dist/define-Ctii4bel.js.map +0 -1
  74. package/dist/generate-BaJRhbCS.js +0 -66
  75. package/dist/generate-BaJRhbCS.js.map +0 -1
  76. package/dist/generate-CuxArvEk.js +0 -1753
  77. package/dist/generate-CuxArvEk.js.map +0 -1
  78. package/dist/generate-TL8zY_IT.cjs +0 -65
  79. package/dist/generate-TL8zY_IT.cjs.map +0 -1
  80. package/dist/generate-UCP0qpDp.cjs +0 -1756
  81. package/dist/generate-UCP0qpDp.cjs.map +0 -1
  82. package/dist/init-CZ5Xq2Hd.cjs +0 -293
  83. package/dist/init-CZ5Xq2Hd.cjs.map +0 -1
  84. package/dist/init-DRR_YWIq.cjs +0 -25
  85. package/dist/init-DRR_YWIq.cjs.map +0 -1
  86. package/dist/init-DSnRd1RJ.js +0 -25
  87. package/dist/init-DSnRd1RJ.js.map +0 -1
  88. package/dist/init-eNRlotJK.js +0 -289
  89. package/dist/init-eNRlotJK.js.map +0 -1
  90. package/dist/mcp-CLcDV4Jm.cjs +0 -41
  91. package/dist/mcp-CLcDV4Jm.cjs.map +0 -1
  92. package/dist/mcp-D7EIR9fR.js +0 -40
  93. package/dist/mcp-D7EIR9fR.js.map +0 -1
  94. package/dist/mcp-Dakxi9CL.js +0 -16
  95. package/dist/mcp-Dakxi9CL.js.map +0 -1
  96. package/dist/mcp-Dr_RY-hd.cjs +0 -16
  97. package/dist/mcp-Dr_RY-hd.cjs.map +0 -1
  98. package/dist/package-Cdo6lNjF.cjs.map +0 -1
  99. package/dist/package-DPooAj2l.js +0 -6
  100. package/dist/package-DPooAj2l.js.map +0 -1
  101. package/dist/shell-475fQKaX.cjs +0 -62
  102. package/dist/shell-475fQKaX.cjs.map +0 -1
  103. package/dist/shell-DLzN4fRo.js +0 -51
  104. package/dist/shell-DLzN4fRo.js.map +0 -1
  105. package/dist/telemetry-DN95_2pF.cjs +0 -282
  106. package/dist/telemetry-DN95_2pF.cjs.map +0 -1
  107. package/dist/telemetry-LgT_sdPe.js +0 -245
  108. package/dist/telemetry-LgT_sdPe.js.map +0 -1
  109. package/dist/validate-B1o-rY9o.js +0 -25
  110. package/dist/validate-B1o-rY9o.js.map +0 -1
  111. package/dist/validate-CXFY-mHL.cjs +0 -25
  112. package/dist/validate-CXFY-mHL.cjs.map +0 -1
  113. package/dist/validate-kLJoT_hi.js +0 -33
  114. package/dist/validate-kLJoT_hi.js.map +0 -1
  115. package/dist/validate-yKKzqEZ5.cjs +0 -34
  116. package/dist/validate-yKKzqEZ5.cjs.map +0 -1
  117. package/src/commands/agent/start.ts +0 -47
  118. package/src/commands/agent.ts +0 -8
  119. package/src/commands/generate.ts +0 -57
  120. package/src/commands/init.ts +0 -20
  121. package/src/commands/mcp.ts +0 -12
  122. package/src/commands/validate.ts +0 -20
  123. package/src/constants.ts +0 -104
  124. package/src/index.ts +0 -43
  125. package/src/loggers/clackLogger.ts +0 -458
  126. package/src/loggers/fileSystemLogger.ts +0 -138
  127. package/src/loggers/githubActionsLogger.ts +0 -379
  128. package/src/loggers/plainLogger.ts +0 -254
  129. package/src/loggers/types.ts +0 -1
  130. package/src/loggers/utils.ts +0 -106
  131. package/src/runners/agent.ts +0 -149
  132. package/src/runners/generate.ts +0 -333
  133. package/src/runners/init.ts +0 -296
  134. package/src/runners/mcp.ts +0 -45
  135. package/src/runners/validate.ts +0 -39
  136. package/src/types.ts +0 -11
  137. package/src/utils/Writables.ts +0 -17
  138. package/src/utils/executeHooks.ts +0 -45
  139. package/src/utils/flags.ts +0 -9
  140. package/src/utils/getConfig.ts +0 -10
  141. package/src/utils/getCosmiConfig.ts +0 -80
  142. package/src/utils/getSummary.ts +0 -68
  143. package/src/utils/packageManager.ts +0 -23
  144. package/src/utils/runHook.ts +0 -91
  145. package/src/utils/telemetry.ts +0 -273
  146. package/src/utils/watcher.ts +0 -19
  147. /package/dist/{chunk-ByKO4r7w.cjs → rolldown-runtime-Bx3C2hgW.cjs} +0 -0
  148. /package/dist/{chunk--u3MIqq1.js → rolldown-runtime-C0LytTxp.js} +0 -0
@@ -1,458 +0,0 @@
1
- import { relative } from 'node:path'
2
- import process from 'node:process'
3
- import { styleText } from 'node:util'
4
- import * as clack from '@clack/prompts'
5
- import { formatMs, formatMsWithColor, getIntro, toCause } from '@internals/utils'
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'
10
- import { buildProgressLine, formatCommandWithArgs, formatMessage } from './utils.ts'
11
-
12
- /**
13
- * TTY logger with beautiful UI and progress indicators for local development.
14
- */
15
- export const clackLogger = defineLogger({
16
- name: 'clack',
17
- install(context, options) {
18
- const logLevel = options?.logLevel ?? logLevelMap.info
19
- const state = {
20
- totalPlugins: 0,
21
- completedPlugins: 0,
22
- failedPlugins: 0,
23
- totalFiles: 0,
24
- processedFiles: 0,
25
- hrStart: process.hrtime(),
26
- spinner: clack.spinner(),
27
- isSpinning: false,
28
- activeProgress: new Map<string, { interval?: NodeJS.Timeout; progressBar: clack.ProgressResult }>(),
29
- }
30
-
31
- function reset() {
32
- for (const [_key, active] of state.activeProgress) {
33
- if (active.interval) {
34
- clearInterval(active.interval)
35
- }
36
- active.progressBar?.stop()
37
- }
38
-
39
- state.totalPlugins = 0
40
- state.completedPlugins = 0
41
- state.failedPlugins = 0
42
- state.totalFiles = 0
43
- state.processedFiles = 0
44
- state.hrStart = process.hrtime()
45
- state.spinner = clack.spinner()
46
- state.isSpinning = false
47
- state.activeProgress.clear()
48
- }
49
-
50
- function showProgressStep() {
51
- if (logLevel <= logLevelMap.silent) {
52
- return
53
- }
54
-
55
- const line = buildProgressLine(state)
56
- if (line) {
57
- clack.log.step(getMessage(line))
58
- }
59
- }
60
-
61
- function getMessage(message: string): string {
62
- return formatMessage(message, logLevel)
63
- }
64
-
65
- function startSpinner(text?: string) {
66
- state.spinner.start(text)
67
- state.isSpinning = true
68
- }
69
-
70
- function stopSpinner(text?: string) {
71
- state.spinner.stop(text)
72
- state.isSpinning = false
73
- }
74
-
75
- context.on('kubb:info', ({ message, info = '' }) => {
76
- if (logLevel <= logLevelMap.silent) {
77
- return
78
- }
79
-
80
- const text = getMessage([styleText('blue', 'ℹ'), message, styleText('dim', info)].join(' '))
81
-
82
- if (state.isSpinning) {
83
- state.spinner.message(text)
84
- } else {
85
- clack.log.info(text)
86
- }
87
- })
88
-
89
- context.on('kubb:success', ({ message, info = '' }) => {
90
- if (logLevel <= logLevelMap.silent) {
91
- return
92
- }
93
-
94
- const text = getMessage([styleText('blue', '✓'), message, logLevel >= logLevelMap.info ? styleText('dim', info) : undefined].filter(Boolean).join(' '))
95
-
96
- if (state.isSpinning) {
97
- stopSpinner(text)
98
- } else {
99
- clack.log.success(text)
100
- }
101
- })
102
-
103
- context.on('kubb:warn', ({ message, info }) => {
104
- if (logLevel < logLevelMap.warn) {
105
- return
106
- }
107
-
108
- const text = getMessage(
109
- [styleText('yellow', '⚠'), message, logLevel >= logLevelMap.info && info ? styleText('dim', info) : undefined].filter(Boolean).join(' '),
110
- )
111
-
112
- clack.log.warn(text)
113
- })
114
-
115
- context.on('kubb:error', ({ error }) => {
116
- const caused = toCause(error)
117
-
118
- const text = [styleText('red', '✗'), error.message].join(' ')
119
-
120
- if (state.isSpinning) {
121
- stopSpinner(getMessage(text))
122
- } else {
123
- clack.log.error(getMessage(text))
124
- }
125
-
126
- // Show stack trace in debug mode (first 3 frames)
127
- if (logLevel >= logLevelMap.debug && error.stack) {
128
- const frames = error.stack.split('\n').slice(1, 4)
129
- for (const frame of frames) {
130
- clack.log.message(getMessage(styleText('dim', frame.trim())))
131
- }
132
-
133
- if (caused?.stack) {
134
- clack.log.message(styleText('dim', `└─ caused by ${caused.message}`))
135
-
136
- const frames = caused.stack.split('\n').slice(1, 4)
137
- for (const frame of frames) {
138
- clack.log.message(getMessage(` ${styleText('dim', frame.trim())}`))
139
- }
140
- }
141
- }
142
- })
143
-
144
- context.on('kubb:version:new', ({ currentVersion, latestVersion }) => {
145
- if (logLevel <= logLevelMap.silent) {
146
- return
147
- }
148
-
149
- try {
150
- clack.box(
151
- `\`v${currentVersion}\` → \`v${latestVersion}\`
152
- 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
- )
163
- } catch {
164
- console.log(`Update available for Kubb: v${currentVersion} → v${latestVersion}`)
165
- console.log('Run `npm install -g @kubb/cli` to update')
166
- }
167
- })
168
-
169
- context.on('kubb:lifecycle:start', async ({ version }) => {
170
- console.log(`\n${getIntro({ title: 'The ultimate toolkit for working with APIs', description: 'Ready to start', version, areEyesOpen: true })}\n`)
171
-
172
- reset()
173
- })
174
-
175
- context.on('kubb:config:start', () => {
176
- if (logLevel <= logLevelMap.silent) {
177
- return
178
- }
179
-
180
- const text = getMessage('Configuration started')
181
-
182
- clack.intro(text)
183
- startSpinner(getMessage('Configuration loading'))
184
- })
185
-
186
- context.on('kubb:config:end', () => {
187
- if (logLevel <= logLevelMap.silent) {
188
- return
189
- }
190
-
191
- const text = getMessage('Configuration completed')
192
-
193
- clack.outro(text)
194
- })
195
-
196
- context.on('kubb:generation:start', ({ config }) => {
197
- reset()
198
-
199
- // Initialize progress tracking for this generation
200
- state.totalPlugins = config.plugins?.length ?? 0
201
-
202
- const text = getMessage(['Generation started', config.name ? `for ${styleText('dim', config.name)}` : undefined].filter(Boolean).join(' '))
203
-
204
- clack.intro(text)
205
- })
206
-
207
- context.on('kubb:plugin:start', ({ plugin }) => {
208
- if (logLevel <= logLevelMap.silent) {
209
- return
210
- }
211
-
212
- stopSpinner()
213
-
214
- const progressBar = clack.progress({
215
- style: 'block',
216
- max: 100,
217
- size: 30,
218
- })
219
- const text = getMessage(`Generating ${styleText('bold', plugin.name)}`)
220
- progressBar.start(text)
221
-
222
- const interval = setInterval(() => {
223
- progressBar.advance()
224
- }, 100)
225
-
226
- state.activeProgress.set(plugin.name, { progressBar, interval })
227
- })
228
-
229
- context.on('kubb:plugin:end', ({ plugin, duration, success }) => {
230
- stopSpinner()
231
-
232
- const active = state.activeProgress.get(plugin.name)
233
-
234
- if (!active || logLevel === logLevelMap.silent) {
235
- return
236
- }
237
-
238
- clearInterval(active.interval)
239
-
240
- if (success) {
241
- state.completedPlugins++
242
- } else {
243
- state.failedPlugins++
244
- }
245
-
246
- const durationStr = formatMsWithColor(duration)
247
- const text = getMessage(
248
- success
249
- ? `${styleText('bold', plugin.name)} completed in ${durationStr}`
250
- : `${styleText('bold', plugin.name)} failed in ${styleText('red', formatMs(duration))}`,
251
- )
252
-
253
- active.progressBar.stop(text)
254
- state.activeProgress.delete(plugin.name)
255
-
256
- // Show progress step after each plugin
257
- showProgressStep()
258
- })
259
-
260
- context.on('kubb:files:processing:start', ({ files }) => {
261
- if (logLevel <= logLevelMap.silent) {
262
- return
263
- }
264
-
265
- stopSpinner()
266
-
267
- state.totalFiles = files.length
268
- state.processedFiles = 0
269
-
270
- const text = `Writing ${files.length} files`
271
- const progressBar = clack.progress({
272
- style: 'block',
273
- max: files.length,
274
- size: 30,
275
- })
276
-
277
- context.emit('kubb:info', { message: text })
278
- progressBar.start(getMessage(text))
279
- state.activeProgress.set('files', { progressBar })
280
- })
281
-
282
- context.on('kubb:file:processing:update', ({ file, config }) => {
283
- if (logLevel <= logLevelMap.silent) {
284
- return
285
- }
286
-
287
- stopSpinner()
288
-
289
- state.processedFiles++
290
-
291
- const text = `Writing ${relative(config.root, file.path)}`
292
- const active = state.activeProgress.get('files')
293
-
294
- if (!active) {
295
- return
296
- }
297
-
298
- active.progressBar.advance(undefined, text)
299
- })
300
- context.on('kubb:files:processing:end', () => {
301
- if (logLevel <= logLevelMap.silent) {
302
- return
303
- }
304
-
305
- stopSpinner()
306
-
307
- const text = getMessage('Files written successfully')
308
- const active = state.activeProgress.get('files')
309
-
310
- if (!active) {
311
- return
312
- }
313
-
314
- active.progressBar.stop(text)
315
- state.activeProgress.delete('files')
316
-
317
- // Show final progress step after files are written
318
- showProgressStep()
319
- })
320
-
321
- context.on('kubb:generation:end', ({ config }) => {
322
- const text = getMessage(config.name ? `Generation completed for ${styleText('dim', config.name)}` : 'Generation completed')
323
-
324
- clack.outro(text)
325
- })
326
-
327
- context.on('kubb:format:start', () => {
328
- if (logLevel <= logLevelMap.silent) {
329
- return
330
- }
331
-
332
- const text = getMessage('Format started')
333
-
334
- clack.intro(text)
335
- })
336
-
337
- context.on('kubb:format:end', () => {
338
- if (logLevel <= logLevelMap.silent) {
339
- return
340
- }
341
-
342
- const text = getMessage('Format completed')
343
-
344
- clack.outro(text)
345
- })
346
-
347
- context.on('kubb:lint:start', () => {
348
- if (logLevel <= logLevelMap.silent) {
349
- return
350
- }
351
-
352
- const text = getMessage('Lint started')
353
-
354
- clack.intro(text)
355
- })
356
-
357
- context.on('kubb:lint:end', () => {
358
- if (logLevel <= logLevelMap.silent) {
359
- return
360
- }
361
-
362
- const text = getMessage('Lint completed')
363
-
364
- clack.outro(text)
365
- })
366
-
367
- context.on('kubb:hook:start', async ({ id, command, args }) => {
368
- const commandWithArgs = formatCommandWithArgs(command, args)
369
- const text = getMessage(`Hook ${styleText('dim', commandWithArgs)} started`)
370
-
371
- // Skip hook execution if no id is provided (e.g., during benchmarks or tests)
372
- if (!id) {
373
- return
374
- }
375
-
376
- if (logLevel <= logLevelMap.silent) {
377
- await runHook({
378
- id,
379
- command,
380
- args,
381
- commandWithArgs,
382
- context,
383
- sink: {
384
- onStderr: (s) => console.error(s),
385
- onStdout: (s) => console.log(s),
386
- },
387
- })
388
- return
389
- }
390
-
391
- clack.intro(text)
392
-
393
- const logger = clack.taskLog({
394
- title: getMessage(['Executing hook', logLevel >= logLevelMap.info ? styleText('dim', commandWithArgs) : undefined].filter(Boolean).join(' ')),
395
- })
396
-
397
- const writable = new ClackWritable(logger)
398
-
399
- await runHook({
400
- id,
401
- command,
402
- args,
403
- commandWithArgs,
404
- context,
405
- stream: true,
406
- sink: {
407
- onLine: (line) => writable.write(line),
408
- onStderr: (s) => logger.error(s),
409
- onStdout: (s) => logger.message(s),
410
- },
411
- })
412
- })
413
-
414
- context.on('kubb:hook:end', ({ command, args }) => {
415
- if (logLevel <= logLevelMap.silent) {
416
- return
417
- }
418
-
419
- const commandWithArgs = formatCommandWithArgs(command, args)
420
- const text = getMessage(`Hook ${styleText('dim', commandWithArgs)} successfully executed`)
421
-
422
- clack.outro(text)
423
- })
424
-
425
- context.on('kubb:generation:summary', ({ config, pluginTimings, failedPlugins, filesCreated, status, hrStart }) => {
426
- const summary = getSummary({
427
- failedPlugins,
428
- filesCreated,
429
- config,
430
- status,
431
- hrStart,
432
- pluginTimings: logLevel >= logLevelMap.verbose ? pluginTimings : undefined,
433
- })
434
- const title = config.name || ''
435
-
436
- summary.unshift('\n')
437
- summary.push('\n')
438
-
439
- const borderColor = status === 'success' ? 'green' : 'red'
440
- try {
441
- clack.box(summary.join('\n'), getMessage(title), {
442
- width: 'auto',
443
- formatBorder: (s: string) => styleText(borderColor, s),
444
- rounded: true,
445
- withGuide: false,
446
- contentAlign: 'left',
447
- titleAlign: 'center',
448
- })
449
- } catch {
450
- console.log(summary.join('\n'))
451
- }
452
- })
453
-
454
- context.on('kubb:lifecycle:end', () => {
455
- reset()
456
- })
457
- },
458
- })
@@ -1,138 +0,0 @@
1
- import { relative, resolve } from 'node:path'
2
- import process from 'node:process'
3
- import { formatMs, write } from '@internals/utils'
4
- import { defineLogger } from '@kubb/core'
5
-
6
- type CachedEvent = {
7
- date: Date
8
- logs: string[]
9
- fileName?: string
10
- }
11
-
12
- /**
13
- * FileSystem logger that captures debug events and writes them to `.kubb` directory files.
14
- * Note: Logs write on `lifecycle:end` or process exit. Cached logs may be lost if the process crashes before these events.
15
- */
16
- export const fileSystemLogger = defineLogger({
17
- name: 'filesystem',
18
- install(context) {
19
- const state = {
20
- cachedLogs: new Set<CachedEvent>(),
21
- startDate: Date.now(),
22
- }
23
-
24
- function reset() {
25
- state.cachedLogs = new Set<CachedEvent>()
26
- state.startDate = Date.now()
27
- }
28
-
29
- async function writeLogs(name?: string) {
30
- if (state.cachedLogs.size === 0) {
31
- return []
32
- }
33
-
34
- const files: Record<string, string[]> = {}
35
-
36
- for (const log of state.cachedLogs) {
37
- const baseName = log.fileName || `${['kubb', name, state.startDate].filter(Boolean).join('-')}.log`
38
- const pathName = resolve(process.cwd(), '.kubb', baseName)
39
-
40
- if (!files[pathName]) {
41
- files[pathName] = []
42
- }
43
-
44
- if (log.logs.length > 0) {
45
- const timestamp = log.date.toLocaleString()
46
- files[pathName].push(`[${timestamp}]\n${log.logs.join('\n')}`)
47
- }
48
- }
49
-
50
- for (const [fileName, logs] of Object.entries(files)) {
51
- await write(fileName, logs.join('\n\n'))
52
- }
53
-
54
- return Object.keys(files)
55
- }
56
-
57
- context.on('kubb:info', ({ message, info }) => {
58
- state.cachedLogs.add({
59
- date: new Date(),
60
- logs: [`ℹ ${message} ${info}`],
61
- })
62
- })
63
-
64
- context.on('kubb:success', ({ message, info }) => {
65
- state.cachedLogs.add({
66
- date: new Date(),
67
- logs: [`✓ ${message} ${info}`],
68
- })
69
- })
70
-
71
- context.on('kubb:warn', ({ message, info }) => {
72
- state.cachedLogs.add({
73
- date: new Date(),
74
- logs: [`⚠ ${message} ${info}`],
75
- })
76
- })
77
-
78
- context.on('kubb:error', ({ error }) => {
79
- state.cachedLogs.add({
80
- date: new Date(),
81
- logs: [`✗ ${error.message}`, error.stack || 'unknown stack'],
82
- })
83
- })
84
-
85
- context.on('kubb:debug', (message) => {
86
- state.cachedLogs.add({
87
- date: new Date(),
88
- logs: message.logs,
89
- })
90
- })
91
-
92
- context.on('kubb:plugin:start', ({ plugin }) => {
93
- state.cachedLogs.add({
94
- date: new Date(),
95
- logs: [`Generating ${plugin.name}`],
96
- })
97
- })
98
-
99
- context.on('kubb:plugin:end', ({ plugin, duration, success }) => {
100
- const durationStr = formatMs(duration)
101
-
102
- state.cachedLogs.add({
103
- date: new Date(),
104
- logs: [success ? `${plugin.name} completed in ${durationStr}` : `${plugin.name} failed in ${durationStr}`],
105
- })
106
- })
107
-
108
- context.on('kubb:files:processing:start', ({ files }) => {
109
- state.cachedLogs.add({
110
- date: new Date(),
111
- logs: [`Start ${files.length} writing:`, ...files.map((file) => file.path)],
112
- })
113
- })
114
-
115
- context.on('kubb:generation:end', async ({ config }) => {
116
- const writtenFilePaths = await writeLogs(config.name)
117
- if (writtenFilePaths.length > 0) {
118
- const files = writtenFilePaths.map((f) => relative(process.cwd(), f))
119
- await context.emit('kubb:info', { message: 'Debug files written to:', info: files.join(', ') })
120
- }
121
- reset()
122
- })
123
-
124
- // Fallback: Write logs on process exit to handle crashes
125
- const exitHandler = () => {
126
- // Synchronous write on exit - best effort
127
- if (state.cachedLogs.size > 0) {
128
- writeLogs().catch(() => {
129
- // Ignore errors on exit
130
- })
131
- }
132
- }
133
-
134
- process.once('exit', exitHandler)
135
- process.once('SIGINT', exitHandler)
136
- process.once('SIGTERM', exitHandler)
137
- },
138
- })