@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
@@ -1,102 +0,0 @@
1
- import net from 'node:net'
2
- import path from 'node:path'
3
- import * as process from 'node:process'
4
- import { fileURLToPath } from 'node:url'
5
- import { styleText } from 'node:util'
6
- import * as clack from '@clack/prompts'
7
- import { spawnAsync } from '@internals/utils'
8
- import { agentDefaults } from '../constants.ts'
9
- import { buildTelemetryEvent, sendTelemetry } from '../utils/telemetry.ts'
10
-
11
- type AgentStartOptions = {
12
- port: string | undefined
13
- host: string
14
- configPath: string | undefined
15
- allowWrite: boolean
16
- allowAll: boolean
17
- version: string
18
- }
19
-
20
- function isPortAvailable(port: number, host: string): Promise<boolean> {
21
- return new Promise((resolve) => {
22
- const server = net.createServer()
23
- server.once('error', () => resolve(false))
24
- server.once('listening', () => {
25
- server.close()
26
- resolve(true)
27
- })
28
- server.listen(port, host)
29
- })
30
- }
31
-
32
- export async function runAgentStart({ port, host, configPath, allowWrite, allowAll, version }: AgentStartOptions): Promise<void> {
33
- const hrStart = process.hrtime()
34
-
35
- try {
36
- // Load .env file into process.env using Node.js built-in (v20.12.0+)
37
- try {
38
- process.loadEnvFile()
39
- } catch {
40
- // .env file may not exist; ignore
41
- }
42
-
43
- // Resolve the @kubb/agent package path
44
- const agentPkgUrl = import.meta.resolve('@kubb/agent/package.json')
45
- const agentPkgPath = fileURLToPath(agentPkgUrl)
46
- const agentDir = path.dirname(agentPkgPath)
47
- const serverPath = path.join(agentDir, agentDefaults.serverEntryPath)
48
-
49
- // CLI params take priority over process.env; process.env fills in what the CLI didn't specify;
50
- // agentDefaults are the last resort. Build env as: defaults ← process.env ← CLI.
51
- const PORT = port !== undefined ? port : (process.env.PORT ?? agentDefaults.port)
52
- const HOST = host !== agentDefaults.host ? host : (process.env.HOST ?? agentDefaults.host)
53
- const KUBB_AGENT_ROOT = process.env.KUBB_AGENT_ROOT ?? process.cwd()
54
- const KUBB_AGENT_CONFIG = path.resolve(process.cwd(), configPath || process.env.KUBB_AGENT_CONFIG || agentDefaults.configFile)
55
- const KUBB_AGENT_ALLOW_WRITE = allowAll || allowWrite ? 'true' : (process.env.KUBB_AGENT_ALLOW_WRITE ?? 'false')
56
- const KUBB_AGENT_ALLOW_ALL = allowAll ? 'true' : (process.env.KUBB_AGENT_ALLOW_ALL ?? 'false')
57
- const KUBB_AGENT_TOKEN = process.env.KUBB_AGENT_TOKEN
58
- const KUBB_AGENT_RETRY_TIMEOUT = process.env.KUBB_AGENT_RETRY_TIMEOUT ?? agentDefaults.retryTimeout
59
- const KUBB_STUDIO_URL = process.env.KUBB_STUDIO_URL ?? agentDefaults.studioUrl
60
-
61
- const env = {
62
- ...process.env,
63
- PORT,
64
- HOST,
65
- KUBB_AGENT_ROOT,
66
- KUBB_AGENT_CONFIG,
67
- KUBB_AGENT_ALLOW_WRITE,
68
- KUBB_AGENT_ALLOW_ALL,
69
- KUBB_AGENT_TOKEN,
70
- KUBB_AGENT_RETRY_TIMEOUT,
71
- KUBB_STUDIO_URL,
72
- }
73
-
74
- clack.log.step(styleText('cyan', 'Starting agent server...'))
75
- clack.log.info(styleText('dim', `Config: ${KUBB_AGENT_CONFIG}`))
76
- clack.log.info(styleText('dim', `Host: ${HOST}`))
77
- clack.log.info(styleText('dim', `Port: ${PORT}`))
78
- if (!KUBB_AGENT_ALLOW_WRITE && !KUBB_AGENT_ALLOW_ALL) {
79
- clack.log.warn(styleText('yellow', 'Filesystem writes disabled. Use --allow-write or --allow-all to enable.'))
80
- }
81
-
82
- if (!(await isPortAvailable(Number(PORT), HOST))) {
83
- clack.log.error(styleText('red', `Port ${PORT} is already in use. Stop the existing process or choose a different port with --port.`))
84
- process.exit(1)
85
- }
86
-
87
- console.log(env)
88
-
89
- // Spawns the server as a detached background process so the CLI can exit independently.
90
- await spawnAsync('node', [serverPath], {
91
- env,
92
- cwd: process.cwd(),
93
- })
94
-
95
- await sendTelemetry(buildTelemetryEvent({ command: 'agent', kubbVersion: version, hrStart, status: 'success' }))
96
- } catch (error) {
97
- await sendTelemetry(buildTelemetryEvent({ command: 'agent', kubbVersion: version, hrStart, status: 'failed' }))
98
- clack.log.error(styleText('red', 'Failed to start agent server'))
99
- console.error(error)
100
- process.exit(1)
101
- }
102
- }
@@ -1,343 +0,0 @@
1
- import { createHash } from 'node:crypto'
2
- import path from 'node:path'
3
- import process from 'node:process'
4
- import { styleText } from 'node:util'
5
- import * as clack from '@clack/prompts'
6
- import type { AsyncEventEmitter } from '@internals/utils'
7
- import { AsyncEventEmitter as AsyncEventEmitterClass, executeIfOnline, toError } from '@internals/utils'
8
- import {
9
- type CLIOptions,
10
- type Config,
11
- detectFormatter,
12
- detectLinter,
13
- formatters,
14
- getConfigs,
15
- isInputPath,
16
- type KubbEvents,
17
- linters,
18
- logLevel as logLevelMap,
19
- safeBuild,
20
- setup,
21
- } from '@kubb/core'
22
- import { version } from '../../package.json'
23
- import { KUBB_NPM_PACKAGE_URL } from '../constants.ts'
24
- import { setupLogger } from '../loggers/utils.ts'
25
- import { executeHooks } from '../utils/executeHooks.ts'
26
- import { getCosmiConfig } from '../utils/getCosmiConfig.ts'
27
- import { buildTelemetryEvent, sendTelemetry } from '../utils/telemetry.ts'
28
- import { startWatcher } from '../utils/watcher.ts'
29
-
30
- type GenerateProps = {
31
- input?: string
32
- config: Config
33
- events: AsyncEventEmitter<KubbEvents>
34
- logLevel: number
35
- }
36
-
37
- type ToolMap = typeof formatters | typeof linters
38
-
39
- type RunToolPassOptions = {
40
- toolValue: string
41
- detect: () => Promise<string | undefined>
42
- toolMap: ToolMap
43
- /** Short noun used in "Auto-detected <toolLabel>:" message, e.g. "formatter" or "linter". */
44
- toolLabel: string
45
- /** Verb prefix for the success message, e.g. "Formatting" or "Linting". */
46
- successPrefix: string
47
- noToolMessage: string
48
- configName: string | undefined
49
- outputPath: string
50
- logLevel: number
51
- events: AsyncEventEmitter<KubbEvents>
52
- onStart: () => Promise<void>
53
- onEnd: () => Promise<void>
54
- }
55
-
56
- async function runToolPass({
57
- toolValue,
58
- detect,
59
- toolMap,
60
- toolLabel,
61
- successPrefix,
62
- noToolMessage,
63
- configName,
64
- outputPath,
65
- logLevel,
66
- events,
67
- onStart,
68
- onEnd,
69
- }: RunToolPassOptions) {
70
- await onStart()
71
-
72
- let resolvedTool = toolValue
73
- if (resolvedTool === 'auto') {
74
- const detected = await detect()
75
- if (!detected) {
76
- await events.emit('warn', noToolMessage)
77
- } else {
78
- resolvedTool = detected
79
- await events.emit('info', `Auto-detected ${toolLabel}: ${styleText('dim', resolvedTool)}`)
80
- }
81
- }
82
-
83
- if (resolvedTool && resolvedTool !== 'auto' && resolvedTool in toolMap) {
84
- const toolConfig = toolMap[resolvedTool as keyof ToolMap]
85
-
86
- try {
87
- const hookId = createHash('sha256').update([configName, resolvedTool].filter(Boolean).join('-')).digest('hex')
88
-
89
- // Wire up the hook:end listener BEFORE emitting hook:start to avoid the race condition
90
- // where hook:end fires synchronously inside emit('hook:start') before the listener is registered.
91
- const hookEndPromise = new Promise<void>((resolve, reject) => {
92
- const handler = ({ id, success, error }: { id?: string; command: string; args?: readonly string[]; success: boolean; error: Error | null }) => {
93
- if (id !== hookId) return
94
- events.off('hook:end', handler)
95
- if (!success) {
96
- reject(error ?? new Error(`${toolConfig.errorMessage}`))
97
- return
98
- }
99
- events
100
- .emit(
101
- 'success',
102
- [
103
- `${successPrefix} with ${styleText('dim', resolvedTool)}`,
104
- logLevel >= logLevelMap.info ? `on ${styleText('dim', outputPath)}` : undefined,
105
- 'successfully',
106
- ]
107
- .filter(Boolean)
108
- .join(' '),
109
- )
110
- .then(resolve)
111
- .catch(reject)
112
- }
113
- events.on('hook:end', handler)
114
- })
115
-
116
- await events.emit('hook:start', {
117
- id: hookId,
118
- command: toolConfig.command,
119
- args: toolConfig.args(outputPath),
120
- })
121
-
122
- await hookEndPromise
123
- } catch (caughtError) {
124
- const err = new Error(toolConfig.errorMessage)
125
- err.cause = caughtError
126
- await events.emit('error', err)
127
- }
128
- }
129
-
130
- await onEnd()
131
- }
132
-
133
- async function generate({ input, config: userConfig, events, logLevel }: GenerateProps): Promise<void> {
134
- const inputPath = input ?? ('path' in userConfig.input ? userConfig.input.path : undefined)
135
- const hrStart = process.hrtime()
136
-
137
- const config: Config = {
138
- ...userConfig,
139
- root: userConfig.root || process.cwd(),
140
- input: inputPath
141
- ? {
142
- ...userConfig.input,
143
- path: inputPath,
144
- }
145
- : userConfig.input,
146
- output: {
147
- write: true,
148
- barrelType: 'named',
149
- extension: {
150
- '.ts': '.ts',
151
- },
152
- format: 'prettier',
153
- ...userConfig.output,
154
- },
155
- }
156
-
157
- await events.emit('generation:start', config)
158
-
159
- await events.emit('info', config.name ? `Setup generation ${styleText('bold', config.name)}` : 'Setup generation', inputPath)
160
-
161
- const { sources, fabric, driver } = await setup({
162
- config,
163
- events,
164
- })
165
-
166
- await events.emit('info', config.name ? `Build generation ${styleText('bold', config.name)}` : 'Build generation', inputPath)
167
-
168
- const { files, failedPlugins, pluginTimings, error } = await safeBuild(
169
- {
170
- config,
171
- events,
172
- },
173
- { driver, fabric, events, sources },
174
- )
175
-
176
- await events.emit('info', 'Load summary')
177
-
178
- // Handle build failures (either from failed plugins or general errors)
179
-
180
- const hasFailures = failedPlugins.size > 0 || error
181
- if (hasFailures) {
182
- // Collect all errors from failed plugins and general error
183
- const allErrors: Error[] = [
184
- error,
185
- ...Array.from(failedPlugins)
186
- .filter((it) => it.error)
187
- .map((it) => it.error),
188
- ].filter(Boolean)
189
-
190
- for (const err of allErrors) {
191
- await events.emit('error', err)
192
- }
193
-
194
- await events.emit('generation:end', config, files, sources)
195
-
196
- await events.emit('generation:summary', config, {
197
- failedPlugins,
198
- filesCreated: files.length,
199
- status: 'failed',
200
- hrStart,
201
- pluginTimings: logLevel >= logLevelMap.verbose ? pluginTimings : undefined,
202
- })
203
-
204
- await sendTelemetry(
205
- buildTelemetryEvent({
206
- command: 'generate',
207
- kubbVersion: version,
208
- plugins: driver.plugins.map((p) => ({ name: p.name, options: p.options as Record<string, unknown> })),
209
- hrStart,
210
- filesCreated: files.length,
211
- status: 'failed',
212
- }),
213
- )
214
-
215
- process.exit(1)
216
- }
217
-
218
- await events.emit('success', 'Generation successfully', inputPath)
219
- await events.emit('generation:end', config, files, sources)
220
-
221
- const outputPath = path.resolve(config.root, config.output.path)
222
-
223
- if (config.output.format) {
224
- await runToolPass({
225
- toolValue: config.output.format,
226
- detect: detectFormatter,
227
- toolMap: formatters,
228
- toolLabel: 'formatter',
229
- successPrefix: 'Formatting',
230
- noToolMessage: 'No formatter found (biome, prettier, or oxfmt). Skipping formatting.',
231
- configName: config.name,
232
- outputPath,
233
- logLevel,
234
- events,
235
- onStart: () => events.emit('format:start'),
236
- onEnd: () => events.emit('format:end'),
237
- })
238
- }
239
-
240
- if (config.output.lint) {
241
- await runToolPass({
242
- toolValue: config.output.lint,
243
- detect: detectLinter,
244
- toolMap: linters,
245
- toolLabel: 'linter',
246
- successPrefix: 'Linting',
247
- noToolMessage: 'No linter found (biome, oxlint, or eslint). Skipping linting.',
248
- configName: config.name,
249
- outputPath,
250
- logLevel,
251
- events,
252
- onStart: () => events.emit('lint:start'),
253
- onEnd: () => events.emit('lint:end'),
254
- })
255
- }
256
-
257
- if (config.hooks) {
258
- await events.emit('hooks:start')
259
- await executeHooks({ hooks: config.hooks, events })
260
-
261
- await events.emit('hooks:end')
262
- }
263
-
264
- // Only reached when there are no failures (process.exit(1) is called above otherwise)
265
- await events.emit('generation:summary', config, {
266
- failedPlugins,
267
- filesCreated: files.length,
268
- status: 'success',
269
- hrStart,
270
- pluginTimings,
271
- })
272
-
273
- const telemetryEvent = buildTelemetryEvent({
274
- command: 'generate',
275
- kubbVersion: version,
276
- plugins: driver.plugins.map((p) => ({ name: p.name, options: p.options as Record<string, unknown> })),
277
- hrStart,
278
- filesCreated: files.length,
279
- status: 'success',
280
- })
281
-
282
- await sendTelemetry(telemetryEvent)
283
- }
284
-
285
- type GenerateCommandOptions = {
286
- input?: string
287
- configPath?: string
288
- logLevel: string
289
- watch: boolean
290
- }
291
-
292
- export async function runGenerateCommand({ input, configPath, logLevel: logLevelKey, watch }: GenerateCommandOptions): Promise<void> {
293
- const logLevel = logLevelMap[logLevelKey as keyof typeof logLevelMap] ?? logLevelMap.info
294
- const events = new AsyncEventEmitterClass<KubbEvents>()
295
-
296
- await setupLogger(events, { logLevel })
297
-
298
- await executeIfOnline(async () => {
299
- try {
300
- const res = await fetch(KUBB_NPM_PACKAGE_URL)
301
- const data = (await res.json()) as { version: string }
302
- const latestVersion = data.version
303
-
304
- if (latestVersion && version < latestVersion) {
305
- await events.emit('version:new', version, latestVersion)
306
- }
307
- } catch {
308
- // Ignore network errors for version check
309
- }
310
- })
311
-
312
- try {
313
- const result = await getCosmiConfig('kubb', configPath)
314
- const configs = await getConfigs(result.config, { input } as CLIOptions)
315
-
316
- await events.emit('config:start')
317
- await events.emit('info', 'Config loaded', path.relative(process.cwd(), result.filepath))
318
- await events.emit('success', 'Config loaded successfully', path.relative(process.cwd(), result.filepath))
319
- await events.emit('config:end', configs)
320
-
321
- await events.emit('lifecycle:start', version)
322
-
323
- for (const config of configs) {
324
- if (isInputPath(config) && watch) {
325
- await startWatcher([input || config.input.path], async (paths) => {
326
- // remove to avoid duplicate listeners after each change
327
- events.removeAll()
328
-
329
- await generate({ input, config, logLevel, events })
330
-
331
- clack.log.step(styleText('yellow', `Watching for changes in ${paths.join(' and ')}`))
332
- })
333
- } else {
334
- await generate({ input, config, logLevel, events })
335
- }
336
- }
337
-
338
- await events.emit('lifecycle:end')
339
- } catch (error) {
340
- await events.emit('error', toError(error))
341
- process.exit(1)
342
- }
343
- }