@kubb/cli 5.0.0-beta.6 → 5.0.0-beta.61
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.
- package/LICENSE +17 -10
- package/README.md +170 -51
- package/dist/Telemetry-CVdyJarO.js +283 -0
- package/dist/Telemetry-CVdyJarO.js.map +1 -0
- package/dist/Telemetry-DrppRqqW.cjs +320 -0
- package/dist/Telemetry-DrppRqqW.cjs.map +1 -0
- package/dist/{define-Bdn8j5VM.cjs → define-C4AB3POr.cjs} +2 -2
- package/dist/{define-Bdn8j5VM.cjs.map → define-C4AB3POr.cjs.map} +1 -1
- package/dist/{define-Ctii4bel.js → define-C63T4jp6.js} +2 -2
- package/dist/{define-Ctii4bel.js.map → define-C63T4jp6.js.map} +1 -1
- package/dist/{errors-CjPmyZHy.js → errors-BsemQCMn.js} +2 -2
- package/dist/{errors-CjPmyZHy.js.map → errors-BsemQCMn.js.map} +1 -1
- package/dist/{errors-CLCjoSg0.cjs → errors-DykI11xo.cjs} +2 -2
- package/dist/{errors-CLCjoSg0.cjs.map → errors-DykI11xo.cjs.map} +1 -1
- package/dist/{generate-BB2Q7I9s.cjs → generate-CJuBlTeJ.cjs} +22 -17
- package/dist/generate-CJuBlTeJ.cjs.map +1 -0
- package/dist/{generate-BmulGxIM.js → generate-DAePC4G2.js} +22 -17
- package/dist/generate-DAePC4G2.js.map +1 -0
- package/dist/index.cjs +10 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -27
- package/dist/index.js.map +1 -1
- package/dist/{init-BTp9if7K.js → init-C8m7Z_W8.js} +6 -6
- package/dist/{init-BTp9if7K.js.map → init-C8m7Z_W8.js.map} +1 -1
- package/dist/{init-Dpg8e1HN.cjs → init-T1DC44PT.cjs} +6 -6
- package/dist/{init-Dpg8e1HN.cjs.map → init-T1DC44PT.cjs.map} +1 -1
- package/dist/{mcp-wpl6sYYR.cjs → mcp-B60MeTmD.cjs} +6 -6
- package/dist/{mcp-wpl6sYYR.cjs.map → mcp-B60MeTmD.cjs.map} +1 -1
- package/dist/{mcp-C9RoU-Dg.js → mcp-lEYflz1a.js} +6 -6
- package/dist/{mcp-C9RoU-Dg.js.map → mcp-lEYflz1a.js.map} +1 -1
- package/dist/package-BynuV_3t.js +6 -0
- package/dist/package-BynuV_3t.js.map +1 -0
- package/dist/{package-iheSdfas.cjs → package-QUV6JOtx.cjs} +2 -2
- package/dist/package-QUV6JOtx.cjs.map +1 -0
- package/dist/run-9ZhHuNZQ.cjs +33 -0
- package/dist/run-9ZhHuNZQ.cjs.map +1 -0
- package/dist/run-BG7Giryi.js +296 -0
- package/dist/run-BG7Giryi.js.map +1 -0
- package/dist/{validate-BU4fPTMc.cjs → run-BQO_tPlc.cjs} +25 -20
- package/dist/run-BQO_tPlc.cjs.map +1 -0
- package/dist/run-C-5oRB_f.cjs +1380 -0
- package/dist/run-C-5oRB_f.cjs.map +1 -0
- package/dist/run-CYnDu3ch.js +51 -0
- package/dist/run-CYnDu3ch.js.map +1 -0
- package/dist/run-Da0AZlgo.js +1377 -0
- package/dist/run-Da0AZlgo.js.map +1 -0
- package/dist/run-DpKny2hT.cjs +300 -0
- package/dist/run-DpKny2hT.cjs.map +1 -0
- package/dist/run-h8NTawHO.js +32 -0
- package/dist/run-h8NTawHO.js.map +1 -0
- package/dist/tools-BU99bhi8.js +152 -0
- package/dist/tools-BU99bhi8.js.map +1 -0
- package/dist/tools-_Xp8-_zy.cjs +175 -0
- package/dist/tools-_Xp8-_zy.cjs.map +1 -0
- package/dist/{validate-BfJoCxrC.js → validate-BhDi3x5e.js} +6 -6
- package/dist/{validate-BfJoCxrC.js.map → validate-BhDi3x5e.js.map} +1 -1
- package/dist/{validate-DIDBROB2.cjs → validate-CUEvWAyG.cjs} +6 -6
- package/dist/{validate-DIDBROB2.cjs.map → validate-CUEvWAyG.cjs.map} +1 -1
- package/package.json +12 -27
- package/src/Telemetry.ts +297 -0
- package/src/commands/generate.ts +18 -12
- package/src/commands/init.ts +2 -2
- package/src/commands/mcp.ts +2 -2
- package/src/commands/validate.ts +2 -2
- package/src/constants.ts +2 -35
- package/src/index.ts +5 -21
- package/src/loggers/clackLogger.ts +136 -202
- package/src/loggers/defineLogger.ts +59 -0
- package/src/loggers/plainLogger.ts +48 -103
- package/src/loggers/types.ts +6 -1
- package/src/loggers/utils.ts +167 -24
- package/src/runners/generate/run.ts +399 -0
- package/src/runners/generate/utils.ts +229 -0
- package/src/runners/{init.ts → init/run.ts} +81 -78
- package/src/runners/init/utils.ts +39 -0
- package/src/runners/mcp/run.ts +37 -0
- package/src/runners/{validate.ts → validate/run.ts} +25 -20
- package/dist/agent-BJEvbSiP.js +0 -68
- package/dist/agent-BJEvbSiP.js.map +0 -1
- package/dist/agent-CXNO6dgj.cjs +0 -70
- package/dist/agent-CXNO6dgj.cjs.map +0 -1
- package/dist/agent-D9CKYh4K.cjs +0 -122
- package/dist/agent-D9CKYh4K.cjs.map +0 -1
- package/dist/agent-VXKxLCho.js +0 -118
- package/dist/agent-VXKxLCho.js.map +0 -1
- package/dist/constants-BPJBMT_6.js +0 -45
- package/dist/constants-BPJBMT_6.js.map +0 -1
- package/dist/constants-BYGmiFs0.cjs +0 -139
- package/dist/constants-BYGmiFs0.cjs.map +0 -1
- package/dist/constants-DSJ-Xrbv.js +0 -116
- package/dist/constants-DSJ-Xrbv.js.map +0 -1
- package/dist/constants-Rcaqzyd-.cjs +0 -80
- package/dist/constants-Rcaqzyd-.cjs.map +0 -1
- package/dist/generate-BB2Q7I9s.cjs.map +0 -1
- package/dist/generate-B_p5dl68.cjs +0 -1755
- package/dist/generate-B_p5dl68.cjs.map +0 -1
- package/dist/generate-BmulGxIM.js.map +0 -1
- package/dist/generate-DAsdUw3z.js +0 -1752
- package/dist/generate-DAsdUw3z.js.map +0 -1
- package/dist/init-CJ80lKSP.cjs +0 -239
- package/dist/init-CJ80lKSP.cjs.map +0 -1
- package/dist/init-DCqcEq86.js +0 -235
- package/dist/init-DCqcEq86.js.map +0 -1
- package/dist/mcp-D1llTaRM.cjs +0 -50
- package/dist/mcp-D1llTaRM.cjs.map +0 -1
- package/dist/mcp-DNUw8nqb.js +0 -49
- package/dist/mcp-DNUw8nqb.js.map +0 -1
- package/dist/package-iheSdfas.cjs.map +0 -1
- package/dist/package-vLafMWCe.js +0 -6
- package/dist/package-vLafMWCe.js.map +0 -1
- package/dist/shell-475fQKaX.cjs +0 -62
- package/dist/shell-475fQKaX.cjs.map +0 -1
- package/dist/shell-DLzN4fRo.js +0 -51
- package/dist/shell-DLzN4fRo.js.map +0 -1
- package/dist/telemetry-BLX0NzRk.cjs +0 -282
- package/dist/telemetry-BLX0NzRk.cjs.map +0 -1
- package/dist/telemetry-juq4QBf7.js +0 -245
- package/dist/telemetry-juq4QBf7.js.map +0 -1
- package/dist/validate-BU4fPTMc.cjs.map +0 -1
- package/dist/validate-k9s_hFah.js +0 -46
- package/dist/validate-k9s_hFah.js.map +0 -1
- package/src/commands/agent/start.ts +0 -50
- package/src/commands/agent.ts +0 -10
- package/src/loggers/fileSystemLogger.ts +0 -138
- package/src/loggers/githubActionsLogger.ts +0 -379
- package/src/runners/agent.ts +0 -155
- package/src/runners/generate.ts +0 -333
- package/src/runners/mcp.ts +0 -56
- package/src/types.ts +0 -11
- package/src/utils/Writables.ts +0 -17
- package/src/utils/executeHooks.ts +0 -45
- package/src/utils/flags.ts +0 -9
- package/src/utils/getConfig.ts +0 -10
- package/src/utils/getCosmiConfig.ts +0 -75
- package/src/utils/getSummary.ts +0 -68
- package/src/utils/packageManager.ts +0 -23
- package/src/utils/runHook.ts +0 -91
- package/src/utils/telemetry.ts +0 -273
- package/src/utils/watcher.ts +0 -19
- /package/dist/{chunk-ByKO4r7w.cjs → chunk-Bx3C2hgW.cjs} +0 -0
- /package/dist/{chunk--u3MIqq1.js → chunk-C0LytTxp.js} +0 -0
|
@@ -2,49 +2,52 @@ import { relative } from 'node:path'
|
|
|
2
2
|
import process from 'node:process'
|
|
3
3
|
import { styleText } from 'node:util'
|
|
4
4
|
import * as clack from '@clack/prompts'
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { ClackWritable } from '../utils/Writables.ts'
|
|
10
|
-
import { buildProgressLine, formatCommandWithArgs, formatMessage } from './utils.ts'
|
|
5
|
+
import { formatMsWithColor, getElapsedMs, getIntro, toCause } from '@internals/utils'
|
|
6
|
+
import { Diagnostics, type KubbHooks, logLevel as logLevelMap } from '@kubb/core'
|
|
7
|
+
import { defineLogger } from './defineLogger.ts'
|
|
8
|
+
import { buildProgressLine, createProgressCounters, formatCommandWithArgs, formatMessage, recordPluginResult, resetProgressCounters } from './utils.ts'
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
|
-
* TTY logger with
|
|
11
|
+
* TTY logger for local development, with spinners and progress bars.
|
|
14
12
|
*/
|
|
15
13
|
export const clackLogger = defineLogger({
|
|
16
14
|
name: 'clack',
|
|
17
15
|
install(context, options) {
|
|
18
16
|
const logLevel = options?.logLevel ?? logLevelMap.info
|
|
19
17
|
const state = {
|
|
20
|
-
|
|
21
|
-
completedPlugins: 0,
|
|
22
|
-
failedPlugins: 0,
|
|
23
|
-
totalFiles: 0,
|
|
24
|
-
processedFiles: 0,
|
|
25
|
-
hrStart: process.hrtime(),
|
|
18
|
+
...createProgressCounters(),
|
|
26
19
|
spinner: clack.spinner(),
|
|
27
20
|
isSpinning: false,
|
|
21
|
+
runningPlugins: new Set<string>(),
|
|
28
22
|
activeProgress: new Map<string, { interval?: NodeJS.Timeout; progressBar: clack.ProgressResult }>(),
|
|
23
|
+
activeHookLogs: new Map<string, { taskLog: ReturnType<typeof clack.taskLog>; hrStart: [number, number] }>(),
|
|
29
24
|
}
|
|
30
25
|
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
// Clear every active progress bar's interval, stop it, and drop the map.
|
|
27
|
+
function stopActiveProgress() {
|
|
28
|
+
for (const [, active] of state.activeProgress) {
|
|
33
29
|
if (active.interval) {
|
|
34
30
|
clearInterval(active.interval)
|
|
35
31
|
}
|
|
36
32
|
active.progressBar?.stop()
|
|
37
33
|
}
|
|
34
|
+
state.activeProgress.clear()
|
|
35
|
+
}
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
state
|
|
43
|
-
state.processedFiles = 0
|
|
44
|
-
state.hrStart = process.hrtime()
|
|
37
|
+
function reset() {
|
|
38
|
+
stopActiveProgress()
|
|
39
|
+
|
|
40
|
+
resetProgressCounters(state)
|
|
45
41
|
state.spinner = clack.spinner()
|
|
46
42
|
state.isSpinning = false
|
|
47
|
-
state.
|
|
43
|
+
state.runningPlugins.clear()
|
|
44
|
+
state.activeHookLogs.clear()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Label for the shared plugin bar, listing the plugins currently generating.
|
|
48
|
+
function pluginProgressText(): string {
|
|
49
|
+
const running = [...state.runningPlugins].map((name) => styleText('bold', name))
|
|
50
|
+
return getMessage(running.length > 0 ? `Generating ${running.join(', ')}` : 'Generating plugins')
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
function showProgressStep() {
|
|
@@ -62,12 +65,20 @@ export const clackLogger = defineLogger({
|
|
|
62
65
|
return formatMessage(message, logLevel)
|
|
63
66
|
}
|
|
64
67
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
// Registers a handler that prints a fixed step message, skipped at silent level.
|
|
69
|
+
function onStep<E extends keyof KubbHooks>(event: E, message: string): void {
|
|
70
|
+
context.on(event, () => {
|
|
71
|
+
if (logLevel <= logLevelMap.silent) {
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
clack.log.step(getMessage(message))
|
|
75
|
+
})
|
|
68
76
|
}
|
|
69
77
|
|
|
70
78
|
function stopSpinner(text?: string) {
|
|
79
|
+
if (!state.isSpinning) {
|
|
80
|
+
return
|
|
81
|
+
}
|
|
71
82
|
state.spinner.stop(text)
|
|
72
83
|
state.isSpinning = false
|
|
73
84
|
}
|
|
@@ -77,13 +88,13 @@ export const clackLogger = defineLogger({
|
|
|
77
88
|
return
|
|
78
89
|
}
|
|
79
90
|
|
|
80
|
-
const text = getMessage([styleText('blue', 'ℹ'), message, styleText('dim', info)].join(' '))
|
|
91
|
+
const text = getMessage([styleText('blue', 'ℹ'), message, info ? styleText('dim', info) : undefined].filter(Boolean).join(' '))
|
|
81
92
|
|
|
82
93
|
if (state.isSpinning) {
|
|
83
94
|
state.spinner.message(text)
|
|
84
|
-
|
|
85
|
-
clack.log.info(text)
|
|
95
|
+
return
|
|
86
96
|
}
|
|
97
|
+
clack.log.info(text)
|
|
87
98
|
})
|
|
88
99
|
|
|
89
100
|
context.on('kubb:success', ({ message, info = '' }) => {
|
|
@@ -95,9 +106,9 @@ export const clackLogger = defineLogger({
|
|
|
95
106
|
|
|
96
107
|
if (state.isSpinning) {
|
|
97
108
|
stopSpinner(text)
|
|
98
|
-
|
|
99
|
-
clack.log.success(text)
|
|
109
|
+
return
|
|
100
110
|
}
|
|
111
|
+
clack.log.success(text)
|
|
101
112
|
})
|
|
102
113
|
|
|
103
114
|
context.on('kubb:warn', ({ message, info }) => {
|
|
@@ -119,12 +130,12 @@ export const clackLogger = defineLogger({
|
|
|
119
130
|
|
|
120
131
|
if (state.isSpinning) {
|
|
121
132
|
stopSpinner(getMessage(text))
|
|
122
|
-
|
|
123
|
-
clack.log.error(getMessage(text))
|
|
133
|
+
return
|
|
124
134
|
}
|
|
135
|
+
clack.log.error(getMessage(text))
|
|
125
136
|
|
|
126
|
-
// Show stack trace in
|
|
127
|
-
if (logLevel >= logLevelMap.
|
|
137
|
+
// Show stack trace in verbose mode (first 3 frames)
|
|
138
|
+
if (logLevel >= logLevelMap.verbose && error.stack) {
|
|
128
139
|
const frames = error.stack.split('\n').slice(1, 4)
|
|
129
140
|
for (const frame of frames) {
|
|
130
141
|
clack.log.message(getMessage(styleText('dim', frame.trim())))
|
|
@@ -141,14 +152,21 @@ export const clackLogger = defineLogger({
|
|
|
141
152
|
}
|
|
142
153
|
})
|
|
143
154
|
|
|
144
|
-
context.on('kubb:
|
|
145
|
-
|
|
155
|
+
context.on('kubb:diagnostic', ({ diagnostic }) => {
|
|
156
|
+
// Silent still surfaces errors so failures stay visible. It drops warnings and info.
|
|
157
|
+
if (logLevel <= logLevelMap.silent && diagnostic.severity !== 'error') {
|
|
146
158
|
return
|
|
147
159
|
}
|
|
148
160
|
|
|
149
|
-
|
|
161
|
+
stopSpinner()
|
|
162
|
+
|
|
163
|
+
// Stop any lingering progress UI so the multi-line block renders cleanly.
|
|
164
|
+
stopActiveProgress()
|
|
165
|
+
|
|
166
|
+
// The version-update notice keeps its own framed box instead of the diagnostic gutter.
|
|
167
|
+
if (Diagnostics.isUpdate(diagnostic)) {
|
|
150
168
|
clack.box(
|
|
151
|
-
`\`v${currentVersion}\` → \`v${latestVersion}\`
|
|
169
|
+
`\`v${diagnostic.currentVersion}\` → \`v${diagnostic.latestVersion}\`
|
|
152
170
|
Run \`npm install -g @kubb/cli\` to update`,
|
|
153
171
|
'Update available for `Kubb`',
|
|
154
172
|
{
|
|
@@ -160,37 +178,21 @@ Run \`npm install -g @kubb/cli\` to update`,
|
|
|
160
178
|
titleAlign: 'center',
|
|
161
179
|
},
|
|
162
180
|
)
|
|
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
181
|
|
|
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
182
|
return
|
|
178
183
|
}
|
|
179
184
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
clack.
|
|
183
|
-
|
|
185
|
+
// Hand the severity glyph to clack as the gutter `symbol`, then let it draw the
|
|
186
|
+
// bar on each detail line via the default `secondarySymbol`. The headline and
|
|
187
|
+
// details carry their own colors, so clack only owns the gutter.
|
|
188
|
+
const { symbol, headline, details } = Diagnostics.format(diagnostic)
|
|
189
|
+
clack.log.message([headline, ...details], { symbol })
|
|
184
190
|
})
|
|
185
191
|
|
|
186
|
-
context.on('kubb:
|
|
187
|
-
|
|
188
|
-
return
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const text = getMessage('Configuration completed')
|
|
192
|
+
context.on('kubb:lifecycle:start', async ({ version }) => {
|
|
193
|
+
console.log(`\n${getIntro({ title: 'The meta framework for code generation', description: 'Ready to start', version, areEyesOpen: true })}\n`)
|
|
192
194
|
|
|
193
|
-
|
|
195
|
+
reset()
|
|
194
196
|
})
|
|
195
197
|
|
|
196
198
|
context.on('kubb:generation:start', ({ config }) => {
|
|
@@ -199,11 +201,17 @@ Run \`npm install -g @kubb/cli\` to update`,
|
|
|
199
201
|
// Initialize progress tracking for this generation
|
|
200
202
|
state.totalPlugins = config.plugins?.length ?? 0
|
|
201
203
|
|
|
204
|
+
if (logLevel <= logLevelMap.silent) {
|
|
205
|
+
return
|
|
206
|
+
}
|
|
207
|
+
|
|
202
208
|
const text = getMessage(['Generation started', config.name ? `for ${styleText('dim', config.name)}` : undefined].filter(Boolean).join(' '))
|
|
203
209
|
|
|
204
210
|
clack.intro(text)
|
|
205
211
|
})
|
|
206
212
|
|
|
213
|
+
// Plugins run concurrently, so they share a single progress bar. A bar per plugin
|
|
214
|
+
// would make clack render them side by side and pile up keypress listeners.
|
|
207
215
|
context.on('kubb:plugin:start', ({ plugin }) => {
|
|
208
216
|
if (logLevel <= logLevelMap.silent) {
|
|
209
217
|
return
|
|
@@ -211,50 +219,44 @@ Run \`npm install -g @kubb/cli\` to update`,
|
|
|
211
219
|
|
|
212
220
|
stopSpinner()
|
|
213
221
|
|
|
222
|
+
state.runningPlugins.add(plugin.name)
|
|
223
|
+
|
|
224
|
+
const active = state.activeProgress.get('plugins')
|
|
225
|
+
if (active) {
|
|
226
|
+
active.progressBar.advance(0, pluginProgressText())
|
|
227
|
+
return
|
|
228
|
+
}
|
|
229
|
+
|
|
214
230
|
const progressBar = clack.progress({
|
|
215
231
|
style: 'block',
|
|
216
|
-
max:
|
|
232
|
+
max: Math.max(state.totalPlugins, 1),
|
|
217
233
|
size: 30,
|
|
218
234
|
})
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
progressBar.advance()
|
|
224
|
-
}, 100)
|
|
225
|
-
|
|
226
|
-
state.activeProgress.set(plugin.name, { progressBar, interval })
|
|
235
|
+
progressBar.start(pluginProgressText())
|
|
236
|
+
// Catch up to plugins already finished before this bar opened.
|
|
237
|
+
progressBar.advance(state.completedPlugins + state.failedPlugins, pluginProgressText())
|
|
238
|
+
state.activeProgress.set('plugins', { progressBar })
|
|
227
239
|
})
|
|
228
240
|
|
|
229
|
-
context.on('kubb:plugin:end', ({ plugin,
|
|
241
|
+
context.on('kubb:plugin:end', ({ plugin, success }) => {
|
|
230
242
|
stopSpinner()
|
|
231
243
|
|
|
232
|
-
const active = state.activeProgress.get(
|
|
244
|
+
const active = state.activeProgress.get('plugins')
|
|
233
245
|
|
|
234
246
|
if (!active || logLevel === logLevelMap.silent) {
|
|
235
247
|
return
|
|
236
248
|
}
|
|
237
249
|
|
|
238
|
-
|
|
250
|
+
state.runningPlugins.delete(plugin.name)
|
|
251
|
+
recordPluginResult(state, success)
|
|
252
|
+
active.progressBar.advance(1, pluginProgressText())
|
|
239
253
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
state.
|
|
254
|
+
// Close the bar once nothing is generating, then print the progress step.
|
|
255
|
+
if (state.runningPlugins.size === 0) {
|
|
256
|
+
active.progressBar.stop(getMessage('Plugins generated'))
|
|
257
|
+
state.activeProgress.delete('plugins')
|
|
258
|
+
showProgressStep()
|
|
244
259
|
}
|
|
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
260
|
})
|
|
259
261
|
|
|
260
262
|
context.on('kubb:files:processing:start', ({ files }) => {
|
|
@@ -279,23 +281,20 @@ Run \`npm install -g @kubb/cli\` to update`,
|
|
|
279
281
|
state.activeProgress.set('files', { progressBar })
|
|
280
282
|
})
|
|
281
283
|
|
|
282
|
-
context.on('kubb:
|
|
284
|
+
context.on('kubb:files:processing:update', ({ files }) => {
|
|
283
285
|
if (logLevel <= logLevelMap.silent) {
|
|
284
286
|
return
|
|
285
287
|
}
|
|
286
288
|
|
|
287
289
|
stopSpinner()
|
|
288
290
|
|
|
289
|
-
state.processedFiles++
|
|
290
|
-
|
|
291
|
-
const text = `Writing ${relative(config.root, file.path)}`
|
|
292
291
|
const active = state.activeProgress.get('files')
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
292
|
+
for (const { file, config } of files) {
|
|
293
|
+
state.processedFiles++
|
|
294
|
+
if (active) {
|
|
295
|
+
active.progressBar.advance(undefined, `Writing ${relative(config.root, file.path)}`)
|
|
296
|
+
}
|
|
296
297
|
}
|
|
297
|
-
|
|
298
|
-
active.progressBar.advance(undefined, text)
|
|
299
298
|
})
|
|
300
299
|
context.on('kubb:files:processing:end', () => {
|
|
301
300
|
if (logLevel <= logLevelMap.silent) {
|
|
@@ -319,135 +318,70 @@ Run \`npm install -g @kubb/cli\` to update`,
|
|
|
319
318
|
})
|
|
320
319
|
|
|
321
320
|
context.on('kubb:generation:end', ({ config }) => {
|
|
321
|
+
stopSpinner()
|
|
322
|
+
|
|
322
323
|
const text = getMessage(config.name ? `Generation completed for ${styleText('dim', config.name)}` : 'Generation completed')
|
|
323
324
|
|
|
324
325
|
clack.outro(text)
|
|
325
326
|
})
|
|
326
327
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
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
|
-
})
|
|
328
|
+
onStep('kubb:format:start', 'Formatting')
|
|
329
|
+
onStep('kubb:lint:start', 'Linting')
|
|
330
|
+
onStep('kubb:hooks:start', 'Running hooks')
|
|
346
331
|
|
|
347
|
-
context.on('kubb:
|
|
348
|
-
if (logLevel <= logLevelMap.silent) {
|
|
332
|
+
context.on('kubb:hook:start', ({ id, command, args }) => {
|
|
333
|
+
if (logLevel <= logLevelMap.silent || !id) {
|
|
349
334
|
return
|
|
350
335
|
}
|
|
351
336
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
clack.intro(text)
|
|
355
|
-
})
|
|
356
|
-
|
|
357
|
-
context.on('kubb:lint:end', () => {
|
|
358
|
-
if (logLevel <= logLevelMap.silent) {
|
|
359
|
-
return
|
|
360
|
-
}
|
|
337
|
+
stopSpinner()
|
|
361
338
|
|
|
362
|
-
const
|
|
339
|
+
const commandWithArgs = formatCommandWithArgs(command, args)
|
|
340
|
+
const title = getMessage(`Running ${styleText('dim', commandWithArgs)}`)
|
|
341
|
+
const taskLog = clack.taskLog({ title })
|
|
363
342
|
|
|
364
|
-
|
|
343
|
+
state.activeHookLogs.set(id, { taskLog, hrStart: process.hrtime() })
|
|
365
344
|
})
|
|
366
345
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
346
|
+
// Registered only when not silent, so its presence is what tells the runner to stream
|
|
347
|
+
// (`kubb:hook:line` listenerCount). At silent level the listener is absent, so no streaming happens.
|
|
348
|
+
if (logLevel > logLevelMap.silent) {
|
|
349
|
+
context.on('kubb:hook:line', ({ id, line }) => {
|
|
350
|
+
const active = state.activeHookLogs.get(id)
|
|
351
|
+
active?.taskLog.message(styleText('dim', line))
|
|
352
|
+
})
|
|
353
|
+
}
|
|
370
354
|
|
|
371
|
-
|
|
355
|
+
context.on('kubb:hook:end', ({ id, command, args, success, error, stdout, stderr }) => {
|
|
372
356
|
if (!id) {
|
|
373
357
|
return
|
|
374
358
|
}
|
|
375
359
|
|
|
376
360
|
if (logLevel <= logLevelMap.silent) {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
context,
|
|
383
|
-
sink: {
|
|
384
|
-
onStderr: (s) => console.error(s),
|
|
385
|
-
onStdout: (s) => console.log(s),
|
|
386
|
-
},
|
|
387
|
-
})
|
|
361
|
+
// Even when silent, surface a failed hook's captured output.
|
|
362
|
+
if (!success) {
|
|
363
|
+
if (stdout) console.log(stdout)
|
|
364
|
+
if (stderr) console.error(stderr)
|
|
365
|
+
}
|
|
388
366
|
return
|
|
389
367
|
}
|
|
390
368
|
|
|
391
|
-
|
|
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) {
|
|
369
|
+
const active = state.activeHookLogs.get(id)
|
|
370
|
+
if (!active) {
|
|
416
371
|
return
|
|
417
372
|
}
|
|
373
|
+
state.activeHookLogs.delete(id)
|
|
418
374
|
|
|
419
375
|
const commandWithArgs = formatCommandWithArgs(command, args)
|
|
420
|
-
const
|
|
421
|
-
|
|
422
|
-
clack.outro(text)
|
|
423
|
-
})
|
|
376
|
+
const duration = formatMsWithColor(getElapsedMs(active.hrStart))
|
|
424
377
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
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'))
|
|
378
|
+
if (success) {
|
|
379
|
+
active.taskLog.success(getMessage(`${styleText('dim', commandWithArgs)} completed in ${duration}`))
|
|
380
|
+
} else {
|
|
381
|
+
// The hook's output already reached the taskLog live via `kubb:hook:line`, so `showLog`
|
|
382
|
+
// replays it here. `kubb:hook:end` carries no captured output on the streaming path.
|
|
383
|
+
const reason = error?.message ? ` (${error.message})` : ''
|
|
384
|
+
active.taskLog.error(getMessage(`${styleText('dim', commandWithArgs)} failed${reason}`), { showLog: true })
|
|
451
385
|
}
|
|
452
386
|
})
|
|
453
387
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { AsyncEventEmitter } from '@internals/utils'
|
|
2
|
+
import type { KubbHooks } from '@kubb/core'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Options accepted by a logger's `install` callback.
|
|
6
|
+
*/
|
|
7
|
+
export type LoggerOptions = {
|
|
8
|
+
/**
|
|
9
|
+
* Output verbosity. Use the `logLevel` constants exported from `@kubb/core`
|
|
10
|
+
* (`silent`, `error`, `warn`, `info`, `verbose`, `debug`).
|
|
11
|
+
*/
|
|
12
|
+
logLevel: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Event emitter handed to `Logger.install`. Use `.on('kubb:info', ...)` and
|
|
17
|
+
* friends to subscribe to build events.
|
|
18
|
+
*/
|
|
19
|
+
export type LoggerContext = AsyncEventEmitter<KubbHooks>
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Logger contract. A logger receives the build's event emitter and subscribes
|
|
23
|
+
* to whichever lifecycle events it wants to forward to its destination
|
|
24
|
+
* (console, file, remote service).
|
|
25
|
+
*/
|
|
26
|
+
export type Logger<TOptions extends LoggerOptions = LoggerOptions> = {
|
|
27
|
+
/**
|
|
28
|
+
* Display name used in diagnostics.
|
|
29
|
+
*/
|
|
30
|
+
name: string
|
|
31
|
+
/**
|
|
32
|
+
* Called once per build with the shared event emitter. Subscribe to the
|
|
33
|
+
* lifecycle events the logger wants to forward to its destination.
|
|
34
|
+
*/
|
|
35
|
+
install: (context: LoggerContext, options?: TOptions) => void | Promise<void>
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type UserLogger<TOptions extends LoggerOptions = LoggerOptions> = Logger<TOptions>
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Defines a typed logger. The `install` method subscribes to lifecycle events
|
|
42
|
+
* on the shared emitter and forwards them to the logger's destination.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { defineLogger } from '@kubb/cli'
|
|
47
|
+
*
|
|
48
|
+
* export const myLogger = defineLogger({
|
|
49
|
+
* name: 'my-logger',
|
|
50
|
+
* install(context) {
|
|
51
|
+
* context.on('kubb:info', ({ message }) => console.log('ℹ', message))
|
|
52
|
+
* context.on('kubb:error', ({ error }) => console.error('✗', error.message))
|
|
53
|
+
* },
|
|
54
|
+
* })
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export function defineLogger<Options extends LoggerOptions = LoggerOptions>(logger: UserLogger<Options>): Logger<Options> {
|
|
58
|
+
return logger
|
|
59
|
+
}
|