@kubb/cli 4.32.3 → 4.33.0
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/dist/agent-CJ69TqoO.js +87 -0
- package/dist/agent-CJ69TqoO.js.map +1 -0
- package/dist/agent-CduUX7Ye.cjs +91 -0
- package/dist/agent-CduUX7Ye.cjs.map +1 -0
- package/dist/agent-D0A3RQho.js +57 -0
- package/dist/agent-D0A3RQho.js.map +1 -0
- package/dist/agent-DrnwQBZf.cjs +60 -0
- package/dist/agent-DrnwQBZf.cjs.map +1 -0
- package/dist/constants-CEKRremI.js +79 -0
- package/dist/constants-CEKRremI.js.map +1 -0
- package/dist/constants-CnPOlsJq.cjs +126 -0
- package/dist/constants-CnPOlsJq.cjs.map +1 -0
- package/dist/errors-BUjJsNoe.cjs +44 -0
- package/dist/errors-BUjJsNoe.cjs.map +1 -0
- package/dist/errors-bSLTEh4e.js +27 -0
- package/dist/errors-bSLTEh4e.js.map +1 -0
- package/dist/{generate-DFdkL6Kp.cjs → generate-ByMgAV76.cjs} +423 -577
- package/dist/generate-ByMgAV76.cjs.map +1 -0
- package/dist/generate-CiUPO5ds.cjs +65 -0
- package/dist/generate-CiUPO5ds.cjs.map +1 -0
- package/dist/generate-DIIxtkWT.js +66 -0
- package/dist/generate-DIIxtkWT.js.map +1 -0
- package/dist/{generate-zZuxBP8z.js → generate-HP5ySfjV.js} +422 -577
- package/dist/generate-HP5ySfjV.js.map +1 -0
- package/dist/index.cjs +226 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +226 -35
- package/dist/index.js.map +1 -1
- package/dist/init-Cd1hCb7q.cjs +296 -0
- package/dist/init-Cd1hCb7q.cjs.map +1 -0
- package/dist/init-DLNrkDF4.js +25 -0
- package/dist/init-DLNrkDF4.js.map +1 -0
- package/dist/init-Df_aXezV.cjs +24 -0
- package/dist/init-Df_aXezV.cjs.map +1 -0
- package/dist/init-DyKK2fTp.js +291 -0
- package/dist/init-DyKK2fTp.js.map +1 -0
- package/dist/jiti-BdskUHhD.cjs +16 -0
- package/dist/jiti-BdskUHhD.cjs.map +1 -0
- package/dist/jiti-Cl7t20dO.js +11 -0
- package/dist/jiti-Cl7t20dO.js.map +1 -0
- package/dist/mcp-B73FC8dF.cjs +42 -0
- package/dist/mcp-B73FC8dF.cjs.map +1 -0
- package/dist/mcp-Bd9LITaI.js +16 -0
- package/dist/mcp-Bd9LITaI.js.map +1 -0
- package/dist/mcp-Cf-1dsB-.js +41 -0
- package/dist/mcp-Cf-1dsB-.js.map +1 -0
- package/dist/mcp-Clg-Qnkr.cjs +15 -0
- package/dist/mcp-Clg-Qnkr.cjs.map +1 -0
- package/dist/package-681jTtCk.js +6 -0
- package/dist/package-681jTtCk.js.map +1 -0
- package/dist/{package-C2pulzfz.cjs → package-aKgzEJtp.cjs} +2 -2
- package/dist/package-aKgzEJtp.cjs.map +1 -0
- package/dist/{telemetry-DYWvlxqs.js → telemetry-C4gOKX2x.js} +31 -10
- package/dist/telemetry-C4gOKX2x.js.map +1 -0
- package/dist/{telemetry-BDSSqUiG.cjs → telemetry-T5IA2dWA.cjs} +40 -7
- package/dist/telemetry-T5IA2dWA.cjs.map +1 -0
- package/dist/types-CLtz0jem.js +25 -0
- package/dist/types-CLtz0jem.js.map +1 -0
- package/dist/types-Ck2lzFON.cjs +36 -0
- package/dist/types-Ck2lzFON.cjs.map +1 -0
- package/dist/validate-Chjg23AE.js +41 -0
- package/dist/validate-Chjg23AE.js.map +1 -0
- package/dist/validate-Cr26q5xX.js +25 -0
- package/dist/validate-Cr26q5xX.js.map +1 -0
- package/dist/validate-DURmg-2Q.cjs +24 -0
- package/dist/validate-DURmg-2Q.cjs.map +1 -0
- package/dist/validate-Dqi9T_c4.cjs +42 -0
- package/dist/validate-Dqi9T_c4.cjs.map +1 -0
- package/package.json +5 -6
- package/src/cli/adapters/nodeAdapter.ts +159 -0
- package/src/cli/help.ts +36 -0
- package/src/cli/index.ts +16 -0
- package/src/cli/parse.ts +18 -0
- package/src/cli/schema.ts +38 -0
- package/src/cli/types.ts +95 -0
- package/src/commands/agent/start.ts +27 -136
- package/src/commands/agent.ts +6 -25
- package/src/commands/generate.ts +26 -158
- package/src/commands/init.ts +9 -360
- package/src/commands/mcp.ts +7 -52
- package/src/commands/validate.ts +9 -60
- package/src/constants.ts +77 -0
- package/src/index.ts +36 -42
- package/src/loggers/clackLogger.ts +42 -140
- package/src/loggers/fileSystemLogger.ts +1 -12
- package/src/loggers/githubActionsLogger.ts +36 -101
- package/src/loggers/plainLogger.ts +23 -70
- package/src/loggers/utils.ts +66 -2
- package/src/runners/agent.ts +100 -0
- package/src/runners/generate.ts +208 -100
- package/src/runners/init.ts +322 -0
- package/src/runners/mcp.ts +32 -0
- package/src/runners/validate.ts +35 -0
- package/src/utils/Writables.ts +2 -2
- package/src/utils/envDetection.ts +34 -0
- package/src/utils/errors.ts +23 -0
- package/src/utils/executeHooks.ts +18 -6
- package/src/utils/getCosmiConfig.ts +10 -11
- package/src/utils/getIntro.ts +17 -18
- package/src/utils/getSummary.ts +11 -15
- package/src/utils/jiti.ts +9 -0
- package/src/utils/packageManager.ts +3 -3
- package/src/utils/randomColor.ts +3 -12
- package/src/utils/runHook.ts +75 -0
- package/src/utils/spawnAsync.ts +47 -0
- package/src/utils/telemetry.ts +8 -25
- package/src/utils/watcher.ts +2 -4
- package/dist/agent-BuijLPSZ.cjs +0 -20
- package/dist/agent-BuijLPSZ.cjs.map +0 -1
- package/dist/agent-Dswt_kxP.js +0 -20
- package/dist/agent-Dswt_kxP.js.map +0 -1
- package/dist/generate-DFdkL6Kp.cjs.map +0 -1
- package/dist/generate-zZuxBP8z.js.map +0 -1
- package/dist/init-CNLk2fNd.js +0 -304
- package/dist/init-CNLk2fNd.js.map +0 -1
- package/dist/init-CSP6FGaW.cjs +0 -308
- package/dist/init-CSP6FGaW.cjs.map +0 -1
- package/dist/mcp-44Od-yig.cjs +0 -57
- package/dist/mcp-44Od-yig.cjs.map +0 -1
- package/dist/mcp-CgaHrkDs.js +0 -57
- package/dist/mcp-CgaHrkDs.js.map +0 -1
- package/dist/package--eaEMq2R.js +0 -6
- package/dist/package--eaEMq2R.js.map +0 -1
- package/dist/package-C2pulzfz.cjs.map +0 -1
- package/dist/start-CB8afXV6.cjs +0 -134
- package/dist/start-CB8afXV6.cjs.map +0 -1
- package/dist/start-DHPjtHJj.js +0 -131
- package/dist/start-DHPjtHJj.js.map +0 -1
- package/dist/telemetry-BDSSqUiG.cjs.map +0 -1
- package/dist/telemetry-DYWvlxqs.js.map +0 -1
- package/dist/validate-C7s0cFnp.cjs +0 -66
- package/dist/validate-C7s0cFnp.cjs.map +0 -1
- package/dist/validate-_7cmvjg_.js +0 -66
- package/dist/validate-_7cmvjg_.js.map +0 -1
- package/src/loggers/envDetection.ts +0 -28
- package/src/loggers/index.ts +0 -5
package/src/commands/init.ts
CHANGED
|
@@ -1,366 +1,15 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
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 { detectPackageManager, type PackageManagerInfo } from '@kubb/core'
|
|
7
|
-
import { defineCommand } from 'citty'
|
|
8
1
|
import { version } from '../../package.json'
|
|
9
|
-
import {
|
|
2
|
+
import { defineCommand } from '../cli/index.ts'
|
|
10
3
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
importName: string
|
|
17
|
-
category: 'core' | 'typescript' | 'query' | 'validation' | 'testing' | 'mocking' | 'docs'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const plugins: PluginOption[] = [
|
|
21
|
-
{
|
|
22
|
-
value: 'plugin-oas',
|
|
23
|
-
label: 'OpenAPI Parser',
|
|
24
|
-
hint: 'Required',
|
|
25
|
-
packageName: '@kubb/plugin-oas',
|
|
26
|
-
importName: 'pluginOas',
|
|
27
|
-
category: 'core',
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
value: 'plugin-ts',
|
|
31
|
-
label: 'TypeScript',
|
|
32
|
-
hint: 'Recommended',
|
|
33
|
-
packageName: '@kubb/plugin-ts',
|
|
34
|
-
importName: 'pluginTs',
|
|
35
|
-
category: 'typescript',
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
value: 'plugin-client',
|
|
39
|
-
label: 'Client (Fetch/Axios)',
|
|
40
|
-
packageName: '@kubb/plugin-client',
|
|
41
|
-
importName: 'pluginClient',
|
|
42
|
-
category: 'typescript',
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
value: 'plugin-react-query',
|
|
46
|
-
label: 'React Query / TanStack Query',
|
|
47
|
-
packageName: '@kubb/plugin-react-query',
|
|
48
|
-
importName: 'pluginReactQuery',
|
|
49
|
-
category: 'query',
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
value: 'plugin-solid-query',
|
|
53
|
-
label: 'Solid Query',
|
|
54
|
-
packageName: '@kubb/plugin-solid-query',
|
|
55
|
-
importName: 'pluginSolidQuery',
|
|
56
|
-
category: 'query',
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
value: 'plugin-svelte-query',
|
|
60
|
-
label: 'Svelte Query',
|
|
61
|
-
packageName: '@kubb/plugin-svelte-query',
|
|
62
|
-
importName: 'pluginSvelteQuery',
|
|
63
|
-
category: 'query',
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
value: 'plugin-vue-query',
|
|
67
|
-
label: 'Vue Query',
|
|
68
|
-
packageName: '@kubb/plugin-vue-query',
|
|
69
|
-
importName: 'pluginVueQuery',
|
|
70
|
-
category: 'query',
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
value: 'plugin-swr',
|
|
74
|
-
label: 'SWR',
|
|
75
|
-
packageName: '@kubb/plugin-swr',
|
|
76
|
-
importName: 'pluginSwr',
|
|
77
|
-
category: 'query',
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
value: 'plugin-zod',
|
|
81
|
-
label: 'Zod Schemas',
|
|
82
|
-
packageName: '@kubb/plugin-zod',
|
|
83
|
-
importName: 'pluginZod',
|
|
84
|
-
category: 'validation',
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
value: 'plugin-faker',
|
|
88
|
-
label: 'Faker.js Mocks',
|
|
89
|
-
packageName: '@kubb/plugin-faker',
|
|
90
|
-
importName: 'pluginFaker',
|
|
91
|
-
category: 'mocking',
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
value: 'plugin-msw',
|
|
95
|
-
label: 'MSW Handlers',
|
|
96
|
-
packageName: '@kubb/plugin-msw',
|
|
97
|
-
importName: 'pluginMsw',
|
|
98
|
-
category: 'mocking',
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
value: 'plugin-cypress',
|
|
102
|
-
label: 'Cypress Tests',
|
|
103
|
-
packageName: '@kubb/plugin-cypress',
|
|
104
|
-
importName: 'pluginCypress',
|
|
105
|
-
category: 'testing',
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
value: 'plugin-redoc',
|
|
109
|
-
label: 'ReDoc Documentation',
|
|
110
|
-
packageName: '@kubb/plugin-redoc',
|
|
111
|
-
importName: 'pluginRedoc',
|
|
112
|
-
category: 'docs',
|
|
4
|
+
export const command = defineCommand({
|
|
5
|
+
name: 'init',
|
|
6
|
+
description: 'Initialize a new Kubb project with interactive setup',
|
|
7
|
+
options: {
|
|
8
|
+
yes: { type: 'boolean', description: 'Skip prompts and use default options', short: 'y', default: false },
|
|
113
9
|
},
|
|
114
|
-
|
|
10
|
+
async run({ values }) {
|
|
11
|
+
const { runInit } = await import('../runners/init.ts')
|
|
115
12
|
|
|
116
|
-
|
|
117
|
-
const imports = selectedPlugins.map((plugin) => `import { ${plugin.importName} } from '${plugin.packageName}'`).join('\n')
|
|
118
|
-
|
|
119
|
-
const pluginConfigs = selectedPlugins
|
|
120
|
-
.map((plugin) => {
|
|
121
|
-
if (plugin.value === 'plugin-oas') {
|
|
122
|
-
return ' pluginOas(),'
|
|
123
|
-
}
|
|
124
|
-
if (plugin.value === 'plugin-ts') {
|
|
125
|
-
return ` pluginTs({\n output: {\n path: 'models',\n },\n }),`
|
|
126
|
-
}
|
|
127
|
-
if (plugin.value === 'plugin-client') {
|
|
128
|
-
return ` pluginClient({\n output: {\n path: 'clients',\n },\n }),`
|
|
129
|
-
}
|
|
130
|
-
if (plugin.value === 'plugin-react-query') {
|
|
131
|
-
return ` pluginReactQuery({\n output: {\n path: 'hooks',\n },\n }),`
|
|
132
|
-
}
|
|
133
|
-
if (plugin.value === 'plugin-zod') {
|
|
134
|
-
return ` pluginZod({\n output: {\n path: 'zod',\n },\n }),`
|
|
135
|
-
}
|
|
136
|
-
if (plugin.value === 'plugin-faker') {
|
|
137
|
-
return ` pluginFaker({\n output: {\n path: 'mocks',\n },\n }),`
|
|
138
|
-
}
|
|
139
|
-
if (plugin.value === 'plugin-msw') {
|
|
140
|
-
return ` pluginMsw({\n output: {\n path: 'msw',\n },\n }),`
|
|
141
|
-
}
|
|
142
|
-
if (plugin.value === 'plugin-swr') {
|
|
143
|
-
return ` pluginSwr({\n output: {\n path: 'hooks',\n },\n }),`
|
|
144
|
-
}
|
|
145
|
-
// Default config for other plugins
|
|
146
|
-
return ` ${plugin.importName}(),`
|
|
147
|
-
})
|
|
148
|
-
.join('\n')
|
|
149
|
-
|
|
150
|
-
return `import { defineConfig } from '@kubb/core'
|
|
151
|
-
${imports}
|
|
152
|
-
|
|
153
|
-
export default defineConfig({
|
|
154
|
-
root: '.',
|
|
155
|
-
input: {
|
|
156
|
-
path: '${inputPath}',
|
|
157
|
-
},
|
|
158
|
-
output: {
|
|
159
|
-
path: '${outputPath}',
|
|
160
|
-
clean: true,
|
|
13
|
+
await runInit({ yes: values.yes, version })
|
|
161
14
|
},
|
|
162
|
-
plugins: [
|
|
163
|
-
${pluginConfigs}
|
|
164
|
-
],
|
|
165
15
|
})
|
|
166
|
-
`
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const DEFAULT_INPUT_PATH = './openapi.yaml'
|
|
170
|
-
const DEFAULT_OUTPUT_PATH = './src/gen'
|
|
171
|
-
const DEFAULT_PLUGINS = ['plugin-oas', 'plugin-ts']
|
|
172
|
-
|
|
173
|
-
const command = defineCommand({
|
|
174
|
-
meta: {
|
|
175
|
-
name: 'init',
|
|
176
|
-
description: 'Initialize a new Kubb project with interactive setup',
|
|
177
|
-
},
|
|
178
|
-
args: {
|
|
179
|
-
yes: {
|
|
180
|
-
type: 'boolean',
|
|
181
|
-
alias: 'y',
|
|
182
|
-
description: 'Skip prompts and use default options',
|
|
183
|
-
default: false,
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
async run({ args }) {
|
|
187
|
-
const cwd = process.cwd()
|
|
188
|
-
const yes = args.yes
|
|
189
|
-
|
|
190
|
-
clack.intro(styleText('bgCyan', styleText('black', ' Kubb Init ')))
|
|
191
|
-
|
|
192
|
-
try {
|
|
193
|
-
// Check/create package.json
|
|
194
|
-
let packageManager: PackageManagerInfo
|
|
195
|
-
if (!hasPackageJson(cwd)) {
|
|
196
|
-
if (!yes) {
|
|
197
|
-
const shouldInit = await clack.confirm({
|
|
198
|
-
message: 'No package.json found. Would you like to create one?',
|
|
199
|
-
initialValue: true,
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
if (clack.isCancel(shouldInit) || !shouldInit) {
|
|
203
|
-
clack.cancel('Operation cancelled.')
|
|
204
|
-
process.exit(0)
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Detect package manager before initializing
|
|
209
|
-
packageManager = detectPackageManager(cwd)
|
|
210
|
-
|
|
211
|
-
const spinner = clack.spinner()
|
|
212
|
-
spinner.start(`Initializing package.json with ${packageManager.name}`)
|
|
213
|
-
|
|
214
|
-
await initPackageJson(cwd, packageManager)
|
|
215
|
-
|
|
216
|
-
spinner.stop(`Created package.json with ${packageManager.name}`)
|
|
217
|
-
} else {
|
|
218
|
-
packageManager = detectPackageManager(cwd)
|
|
219
|
-
clack.log.info(`Detected package manager: ${styleText('cyan', packageManager.name)}`)
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Prompt for OpenAPI spec path
|
|
223
|
-
let inputPath: string
|
|
224
|
-
if (yes) {
|
|
225
|
-
inputPath = DEFAULT_INPUT_PATH
|
|
226
|
-
clack.log.info(`Using input path: ${styleText('cyan', inputPath)}`)
|
|
227
|
-
} else {
|
|
228
|
-
const inputPathResult = await clack.text({
|
|
229
|
-
message: 'Where is your OpenAPI specification located?',
|
|
230
|
-
placeholder: DEFAULT_INPUT_PATH,
|
|
231
|
-
defaultValue: DEFAULT_INPUT_PATH,
|
|
232
|
-
validate: (value) => {
|
|
233
|
-
if (!value) return 'Input path is required'
|
|
234
|
-
},
|
|
235
|
-
})
|
|
236
|
-
|
|
237
|
-
if (clack.isCancel(inputPathResult)) {
|
|
238
|
-
clack.cancel('Operation cancelled.')
|
|
239
|
-
process.exit(0)
|
|
240
|
-
}
|
|
241
|
-
inputPath = inputPathResult as string
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Prompt for output directory
|
|
245
|
-
let outputPath: string
|
|
246
|
-
if (yes) {
|
|
247
|
-
outputPath = DEFAULT_OUTPUT_PATH
|
|
248
|
-
clack.log.info(`Using output path: ${styleText('cyan', outputPath)}`)
|
|
249
|
-
} else {
|
|
250
|
-
const outputPathResult = await clack.text({
|
|
251
|
-
message: 'Where should the generated files be output?',
|
|
252
|
-
placeholder: DEFAULT_OUTPUT_PATH,
|
|
253
|
-
defaultValue: DEFAULT_OUTPUT_PATH,
|
|
254
|
-
validate: (value) => {
|
|
255
|
-
if (!value) return 'Output path is required'
|
|
256
|
-
},
|
|
257
|
-
})
|
|
258
|
-
|
|
259
|
-
if (clack.isCancel(outputPathResult)) {
|
|
260
|
-
clack.cancel('Operation cancelled.')
|
|
261
|
-
process.exit(0)
|
|
262
|
-
}
|
|
263
|
-
outputPath = outputPathResult as string
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Plugin selection
|
|
267
|
-
let selectedPlugins: PluginOption[]
|
|
268
|
-
if (yes) {
|
|
269
|
-
selectedPlugins = plugins.filter((plugin) => DEFAULT_PLUGINS.includes(plugin.value))
|
|
270
|
-
clack.log.info(`Using plugins: ${styleText('cyan', selectedPlugins.map((p) => p.label).join(', '))}`)
|
|
271
|
-
} else {
|
|
272
|
-
const selectedPluginValues = await clack.multiselect({
|
|
273
|
-
message: 'Select plugins to use:',
|
|
274
|
-
options: plugins.map((plugin) => ({
|
|
275
|
-
value: plugin.value,
|
|
276
|
-
label: plugin.label,
|
|
277
|
-
hint: plugin.hint,
|
|
278
|
-
})),
|
|
279
|
-
initialValues: DEFAULT_PLUGINS,
|
|
280
|
-
required: true,
|
|
281
|
-
})
|
|
282
|
-
|
|
283
|
-
if (clack.isCancel(selectedPluginValues)) {
|
|
284
|
-
clack.cancel('Operation cancelled.')
|
|
285
|
-
process.exit(0)
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
selectedPlugins = plugins.filter((plugin) => (selectedPluginValues as string[]).includes(plugin.value))
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Ensure plugin-oas is always included
|
|
292
|
-
if (!selectedPlugins.find((p) => p.value === 'plugin-oas')) {
|
|
293
|
-
selectedPlugins.unshift(plugins.find((p) => p.value === 'plugin-oas')!)
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// Install packages
|
|
297
|
-
const packagesToInstall = ['@kubb/core', '@kubb/cli', '@kubb/agent', ...selectedPlugins.map((p) => p.packageName)]
|
|
298
|
-
|
|
299
|
-
const spinner = clack.spinner()
|
|
300
|
-
spinner.start(`Installing ${packagesToInstall.length} packages with ${packageManager.name}`)
|
|
301
|
-
|
|
302
|
-
try {
|
|
303
|
-
await installPackages(packagesToInstall, packageManager, cwd)
|
|
304
|
-
spinner.stop(`Installed ${packagesToInstall.length} packages`)
|
|
305
|
-
} catch (error) {
|
|
306
|
-
spinner.stop('Installation failed')
|
|
307
|
-
throw error
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Generate config file
|
|
311
|
-
const configSpinner = clack.spinner()
|
|
312
|
-
configSpinner.start('Creating kubb.config.ts')
|
|
313
|
-
|
|
314
|
-
const configContent = generateConfigFile(selectedPlugins, inputPath, outputPath)
|
|
315
|
-
const configPath = path.join(cwd, 'kubb.config.ts')
|
|
316
|
-
|
|
317
|
-
// Check if config already exists
|
|
318
|
-
if (fs.existsSync(configPath)) {
|
|
319
|
-
configSpinner.stop('kubb.config.ts already exists')
|
|
320
|
-
|
|
321
|
-
if (!yes) {
|
|
322
|
-
const shouldOverwrite = await clack.confirm({
|
|
323
|
-
message: 'kubb.config.ts already exists. Overwrite?',
|
|
324
|
-
initialValue: false,
|
|
325
|
-
})
|
|
326
|
-
|
|
327
|
-
if (clack.isCancel(shouldOverwrite) || !shouldOverwrite) {
|
|
328
|
-
clack.cancel('Keeping existing configuration. Packages have been installed.')
|
|
329
|
-
process.exit(0)
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
configSpinner.start('Overwriting kubb.config.ts')
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
fs.writeFileSync(configPath, configContent, 'utf-8')
|
|
337
|
-
|
|
338
|
-
configSpinner.stop('Created kubb.config.ts')
|
|
339
|
-
|
|
340
|
-
// Success message
|
|
341
|
-
clack.outro(
|
|
342
|
-
styleText('green', '✓ All set!') +
|
|
343
|
-
'\n\n' +
|
|
344
|
-
styleText('dim', 'Next steps:') +
|
|
345
|
-
'\n' +
|
|
346
|
-
styleText('cyan', ` 1. Make sure your OpenAPI spec is at: ${inputPath}`) +
|
|
347
|
-
'\n' +
|
|
348
|
-
styleText('cyan', ' 2. Generate code with: npx kubb generate') +
|
|
349
|
-
'\n' +
|
|
350
|
-
styleText('cyan', ' Or start a stream server with: npx kubb start') +
|
|
351
|
-
'\n' +
|
|
352
|
-
styleText('cyan', ` 3. Find generated files in: ${outputPath}`) +
|
|
353
|
-
'\n\n' +
|
|
354
|
-
styleText('dim', `Using ${packageManager.name} • Kubb v${version}`),
|
|
355
|
-
)
|
|
356
|
-
} catch (error) {
|
|
357
|
-
clack.log.error(styleText('red', 'An error occurred during initialization'))
|
|
358
|
-
if (error instanceof Error) {
|
|
359
|
-
clack.log.error(error.message)
|
|
360
|
-
}
|
|
361
|
-
process.exit(1)
|
|
362
|
-
}
|
|
363
|
-
},
|
|
364
|
-
})
|
|
365
|
-
|
|
366
|
-
export default command
|
package/src/commands/mcp.ts
CHANGED
|
@@ -1,57 +1,12 @@
|
|
|
1
|
-
import process from 'node:process'
|
|
2
|
-
import { styleText } from 'node:util'
|
|
3
|
-
import type { ArgsDef } from 'citty'
|
|
4
|
-
import { defineCommand, showUsage } from 'citty'
|
|
5
|
-
import { createJiti } from 'jiti'
|
|
6
1
|
import { version } from '../../package.json'
|
|
7
|
-
import {
|
|
2
|
+
import { defineCommand } from '../cli/index.ts'
|
|
8
3
|
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
help: {
|
|
15
|
-
type: 'boolean',
|
|
16
|
-
description: 'Show help',
|
|
17
|
-
alias: 'h',
|
|
18
|
-
default: false,
|
|
19
|
-
},
|
|
20
|
-
} as const satisfies ArgsDef
|
|
21
|
-
|
|
22
|
-
const command = defineCommand({
|
|
23
|
-
meta: {
|
|
24
|
-
name: 'mcp',
|
|
25
|
-
description: 'Start the server to enable the MCP client to interact with the LLM.',
|
|
26
|
-
},
|
|
27
|
-
args,
|
|
28
|
-
async run(commandContext) {
|
|
29
|
-
const { args } = commandContext
|
|
30
|
-
|
|
31
|
-
if (args.help) {
|
|
32
|
-
return showUsage(command)
|
|
33
|
-
}
|
|
4
|
+
export const command = defineCommand({
|
|
5
|
+
name: 'mcp',
|
|
6
|
+
description: 'Start the server to enable the MCP client to interact with the LLM.',
|
|
7
|
+
async run() {
|
|
8
|
+
const { runMcp } = await import('../runners/mcp.ts')
|
|
34
9
|
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
mod = await jiti.import('@kubb/mcp', { default: true })
|
|
38
|
-
} catch (_e) {
|
|
39
|
-
console.error(`Import of '@kubb/mcp' is required to start the MCP server`)
|
|
40
|
-
process.exit(1)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const { run } = mod
|
|
44
|
-
const hrStart = process.hrtime()
|
|
45
|
-
try {
|
|
46
|
-
console.log('⏳ Starting MCP server...')
|
|
47
|
-
console.warn(styleText('yellow', 'This feature is still under development — use with caution'))
|
|
48
|
-
run()
|
|
49
|
-
await sendTelemetry(buildTelemetryEvent({ command: 'mcp', kubbVersion: version, hrStart, status: 'success' }))
|
|
50
|
-
} catch (error) {
|
|
51
|
-
await sendTelemetry(buildTelemetryEvent({ command: 'mcp', kubbVersion: version, hrStart, status: 'failed' }))
|
|
52
|
-
console.error((error as Error)?.message)
|
|
53
|
-
}
|
|
10
|
+
await runMcp({ version })
|
|
54
11
|
},
|
|
55
12
|
})
|
|
56
|
-
|
|
57
|
-
export default command
|
package/src/commands/validate.ts
CHANGED
|
@@ -1,66 +1,15 @@
|
|
|
1
|
-
import process from 'node:process'
|
|
2
|
-
import type { ArgsDef } from 'citty'
|
|
3
|
-
import { defineCommand, showUsage } from 'citty'
|
|
4
|
-
import { createJiti } from 'jiti'
|
|
5
1
|
import { version } from '../../package.json'
|
|
6
|
-
import {
|
|
2
|
+
import { defineCommand } from '../cli/index.ts'
|
|
7
3
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
input: {
|
|
14
|
-
type: 'string',
|
|
15
|
-
description: 'Path to Swagger/OpenAPI file',
|
|
16
|
-
alias: 'i',
|
|
17
|
-
},
|
|
18
|
-
help: {
|
|
19
|
-
type: 'boolean',
|
|
20
|
-
description: 'Show help',
|
|
21
|
-
alias: 'h',
|
|
22
|
-
default: false,
|
|
4
|
+
export const command = defineCommand({
|
|
5
|
+
name: 'validate',
|
|
6
|
+
description: 'Validate a Swagger/OpenAPI file',
|
|
7
|
+
options: {
|
|
8
|
+
input: { type: 'string', description: 'Path to Swagger/OpenAPI file', short: 'i', required: true },
|
|
23
9
|
},
|
|
24
|
-
|
|
10
|
+
async run({ values }) {
|
|
11
|
+
const { runValidate } = await import('../runners/validate.ts')
|
|
25
12
|
|
|
26
|
-
|
|
27
|
-
meta: {
|
|
28
|
-
name: 'validate',
|
|
29
|
-
description: 'Validate a Swagger/OpenAPI file',
|
|
30
|
-
},
|
|
31
|
-
args,
|
|
32
|
-
async run(commandContext) {
|
|
33
|
-
const { args } = commandContext
|
|
34
|
-
|
|
35
|
-
if (args.help) {
|
|
36
|
-
return showUsage(command)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (args.input) {
|
|
40
|
-
let mod: any
|
|
41
|
-
try {
|
|
42
|
-
mod = await jiti.import('@kubb/oas', { default: true })
|
|
43
|
-
} catch (_e) {
|
|
44
|
-
console.error(`Import of '@kubb/oas' is required to do validation`)
|
|
45
|
-
process.exit(1)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const { parse } = mod
|
|
49
|
-
const hrStart = process.hrtime()
|
|
50
|
-
try {
|
|
51
|
-
const oas = await parse(args.input)
|
|
52
|
-
await oas.validate()
|
|
53
|
-
|
|
54
|
-
await sendTelemetry(buildTelemetryEvent({ command: 'validate', kubbVersion: version, hrStart, status: 'success' }))
|
|
55
|
-
console.log('✅ Validation success')
|
|
56
|
-
} catch (error) {
|
|
57
|
-
await sendTelemetry(buildTelemetryEvent({ command: 'validate', kubbVersion: version, hrStart, status: 'failed' }))
|
|
58
|
-
console.error('❌ Validation failed')
|
|
59
|
-
console.log((error as Error)?.message)
|
|
60
|
-
process.exit(1)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
13
|
+
await runValidate({ input: values.input, version })
|
|
63
14
|
},
|
|
64
15
|
})
|
|
65
|
-
|
|
66
|
-
export default command
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/** NPM registry endpoint used to check for @kubb/cli updates. */
|
|
2
|
+
export const KUBB_NPM_PACKAGE_URL = 'https://registry.npmjs.org/@kubb/cli/latest' as const
|
|
3
|
+
|
|
4
|
+
/** OpenTelemetry ingestion endpoint for anonymous usage telemetry. */
|
|
5
|
+
export const OTLP_ENDPOINT = 'https://otlp.kubb.dev' as const
|
|
6
|
+
|
|
7
|
+
/** Horizontal rule rendered above/below the plain-logger generation summary. */
|
|
8
|
+
export const SUMMARY_SEPARATOR = '─'.repeat(27)
|
|
9
|
+
|
|
10
|
+
/** Maximum number of █ characters in a plugin timing bar. */
|
|
11
|
+
export const SUMMARY_MAX_BAR_LENGTH = 10 as const
|
|
12
|
+
|
|
13
|
+
/** Divides elapsed milliseconds into bar-length units (1 block per 100 ms). */
|
|
14
|
+
export const SUMMARY_TIME_SCALE_DIVISOR = 100 as const
|
|
15
|
+
|
|
16
|
+
/** Glob pattern for paths the file watcher ignores. */
|
|
17
|
+
export const WATCHER_IGNORED_PATHS = '**/{.git,node_modules}/**' as const
|
|
18
|
+
|
|
19
|
+
/** Default runtime values for the `agent start` command. */
|
|
20
|
+
export const agentDefaults = {
|
|
21
|
+
port: '3000',
|
|
22
|
+
host: 'localhost',
|
|
23
|
+
configFile: 'kubb.config.ts',
|
|
24
|
+
retryTimeout: '30000',
|
|
25
|
+
studioUrl: 'https://studio.kubb.dev',
|
|
26
|
+
/** Relative path from the @kubb/agent package root to the server entry. */
|
|
27
|
+
serverEntryPath: '.output/server/index.mjs',
|
|
28
|
+
} as const
|
|
29
|
+
|
|
30
|
+
/** Default values used during interactive `init` scaffolding. */
|
|
31
|
+
export const initDefaults = {
|
|
32
|
+
inputPath: './openapi.yaml',
|
|
33
|
+
outputPath: './src/gen',
|
|
34
|
+
plugins: ['plugin-oas', 'plugin-ts'],
|
|
35
|
+
} as const
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Maps each plugin value to the default config snippet inserted by `init`.
|
|
39
|
+
* The `satisfies` constraint ensures all values remain plain strings while
|
|
40
|
+
* `as const` keeps the object deeply immutable.
|
|
41
|
+
*/
|
|
42
|
+
export const pluginDefaultConfigs = {
|
|
43
|
+
'plugin-oas': 'pluginOas()',
|
|
44
|
+
'plugin-ts': `pluginTs({
|
|
45
|
+
output: { path: 'models' },
|
|
46
|
+
})`,
|
|
47
|
+
'plugin-client': `pluginClient({
|
|
48
|
+
output: { path: 'clients' },
|
|
49
|
+
})`,
|
|
50
|
+
'plugin-react-query': `pluginReactQuery({
|
|
51
|
+
output: { path: 'hooks' },
|
|
52
|
+
})`,
|
|
53
|
+
'plugin-solid-query': `pluginSolidQuery({
|
|
54
|
+
output: { path: 'hooks' },
|
|
55
|
+
})`,
|
|
56
|
+
'plugin-svelte-query': `pluginSvelteQuery({
|
|
57
|
+
output: { path: 'hooks' },
|
|
58
|
+
})`,
|
|
59
|
+
'plugin-vue-query': `pluginVueQuery({
|
|
60
|
+
output: { path: 'hooks' },
|
|
61
|
+
})`,
|
|
62
|
+
'plugin-swr': `pluginSwr({
|
|
63
|
+
output: { path: 'hooks' },
|
|
64
|
+
})`,
|
|
65
|
+
'plugin-zod': `pluginZod({
|
|
66
|
+
output: { path: 'zod' },
|
|
67
|
+
})`,
|
|
68
|
+
'plugin-faker': `pluginFaker({
|
|
69
|
+
output: { path: 'mocks' },
|
|
70
|
+
})`,
|
|
71
|
+
'plugin-msw': `pluginMsw({
|
|
72
|
+
output: { path: 'msw' },
|
|
73
|
+
})`,
|
|
74
|
+
} as const satisfies Record<string, string>
|
|
75
|
+
|
|
76
|
+
/** Color palette used by randomCliColor() for deterministic plugin name coloring. */
|
|
77
|
+
export const randomColors = ['black', 'red', 'green', 'yellow', 'blue', 'white', 'magenta', 'cyan', 'gray', 'blue'] as const
|
package/src/index.ts
CHANGED
|
@@ -1,51 +1,45 @@
|
|
|
1
1
|
import { styleText } from 'node:util'
|
|
2
|
-
import { defineCommand, runCommand, runMain } from 'citty'
|
|
3
2
|
import { version } from '../package.json'
|
|
3
|
+
import { createCLI } from './cli/index.ts'
|
|
4
4
|
import { isTelemetryDisabled } from './utils/telemetry.ts'
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
meta: {
|
|
8
|
-
name: 'kubb',
|
|
9
|
-
version,
|
|
10
|
-
description: 'Kubb generation',
|
|
11
|
-
},
|
|
12
|
-
args: {
|
|
13
|
-
version: {
|
|
14
|
-
type: 'boolean',
|
|
15
|
-
alias: 'v',
|
|
16
|
-
description: 'Show version number',
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
async setup({ rawArgs, args }) {
|
|
20
|
-
if (args.version) {
|
|
21
|
-
console.log(version)
|
|
22
|
-
process.exit(0)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (!isTelemetryDisabled()) {
|
|
26
|
-
console.log(
|
|
27
|
-
`${styleText('yellow', 'Notice:')} Kubb collects anonymous telemetry data to help improve the tool. No personal data or file contents are collected. \nTo disable, set ${styleText('cyan', 'KUBB_DISABLE_TELEMETRY=1')}.\n`,
|
|
28
|
-
)
|
|
29
|
-
}
|
|
6
|
+
const cli = createCLI()
|
|
30
7
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
8
|
+
function shouldShowTelemetryNotice(argv: string[]): boolean {
|
|
9
|
+
if (isTelemetryDisabled()) {
|
|
10
|
+
return false
|
|
11
|
+
}
|
|
12
|
+
// Skip when the user is just asking for help or version info
|
|
13
|
+
const quietFlags = new Set(['--help', '-h', '--version', '-v'])
|
|
14
|
+
if (argv.some((arg) => quietFlags.has(arg))) {
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
17
|
+
// Skip in non-interactive / scripting contexts
|
|
18
|
+
if (!process.stdout.isTTY) {
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
21
|
+
return true
|
|
22
|
+
}
|
|
34
23
|
|
|
35
|
-
|
|
24
|
+
export async function run(argv: string[] = process.argv): Promise<void> {
|
|
25
|
+
if (shouldShowTelemetryNotice(argv)) {
|
|
26
|
+
console.log(
|
|
27
|
+
`${styleText('yellow', 'Notice:')} Kubb collects anonymous telemetry data to help improve the tool. No personal data or file contents are collected. \nTo disable, set ${styleText('cyan', 'KUBB_DISABLE_TELEMETRY=1')}.\n`,
|
|
28
|
+
)
|
|
29
|
+
}
|
|
36
30
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
init: () => import('./commands/init.ts').then((r) => r.default),
|
|
46
|
-
},
|
|
47
|
-
})
|
|
31
|
+
const [{ command: generateCommand }, { command: validateCommand }, { command: mcpCommand }, { command: agentCommand }, { command: initCommand }] =
|
|
32
|
+
await Promise.all([
|
|
33
|
+
import('./commands/generate.ts'),
|
|
34
|
+
import('./commands/validate.ts'),
|
|
35
|
+
import('./commands/mcp.ts'),
|
|
36
|
+
import('./commands/agent.ts'),
|
|
37
|
+
import('./commands/init.ts'),
|
|
38
|
+
])
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
await cli.run([generateCommand, validateCommand, mcpCommand, agentCommand, initCommand], argv, {
|
|
41
|
+
programName: 'kubb',
|
|
42
|
+
defaultCommandName: 'generate',
|
|
43
|
+
version,
|
|
44
|
+
})
|
|
51
45
|
}
|