@kubb/cli 5.9.2 → 5.9.4
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/Telemetry-ByFeVTz5.cjs +314 -0
- package/dist/Telemetry-ByFeVTz5.cjs.map +1 -0
- package/dist/Telemetry-E_BBHmnT.js +259 -0
- package/dist/Telemetry-E_BBHmnT.js.map +1 -0
- package/dist/background-CZ2nVKwB.js +1 -0
- package/dist/{background-Bh4FDWa3.cjs → background-DdUVvDwi.cjs} +7 -6
- package/dist/{background-Bh4FDWa3.cjs.map → background-DdUVvDwi.cjs.map} +1 -1
- package/dist/{background-B0YbkZ0s.js → background-H30JH70B.js} +3 -2
- package/dist/{background-B0YbkZ0s.js.map → background-H30JH70B.js.map} +1 -1
- package/dist/{reporters-B4rZOlo8.cjs → config-Ck2JHe5r.cjs} +36 -4
- package/dist/config-Ck2JHe5r.cjs.map +1 -0
- package/dist/{reporters-H21Jvrff.js → config-DxePdyxe.js} +29 -3
- package/dist/config-DxePdyxe.js.map +1 -0
- package/dist/credentials-C8tjAhTo.js +1 -0
- package/dist/credentials-CZK6zPLv.js +62 -0
- package/dist/credentials-CZK6zPLv.js.map +1 -0
- package/dist/credentials-DDaKqtJn.cjs +113 -0
- package/dist/credentials-DDaKqtJn.cjs.map +1 -0
- package/dist/index.cjs +702 -207
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +697 -206
- package/dist/index.js.map +1 -1
- package/dist/{output-BnK0scpX.cjs → output-Cd3Kmvo0.cjs} +141 -66
- package/dist/output-Cd3Kmvo0.cjs.map +1 -0
- package/dist/{output-qFt4vV7K.js → output-DS5hyqwL.js} +173 -129
- package/dist/output-DS5hyqwL.js.map +1 -0
- package/dist/{registry-B7BvdrGE.js → registry-CSXUuuCy.js} +2 -2
- package/dist/{registry-B7BvdrGE.js.map → registry-CSXUuuCy.js.map} +1 -1
- package/dist/{registry-DER9aRyg.cjs → registry-CrvQxnxy.cjs} +6 -6
- package/dist/{registry-DER9aRyg.cjs.map → registry-CrvQxnxy.cjs.map} +1 -1
- package/dist/rolldown-runtime-CPE0t6oh.cjs +53 -0
- package/dist/{run-BcMMYk7G.js → run-BPD5Vaon.js} +5 -7
- package/dist/{run-BcMMYk7G.js.map → run-BPD5Vaon.js.map} +1 -1
- package/dist/{run-e8gMz1M_.cjs → run-C0Tfrddq.cjs} +5 -6
- package/dist/{run-e8gMz1M_.cjs.map → run-C0Tfrddq.cjs.map} +1 -1
- package/dist/{run-fg0ycsS_.cjs → run-CbN00IHp.cjs} +16 -18
- package/dist/{run-fg0ycsS_.cjs.map → run-CbN00IHp.cjs.map} +1 -1
- package/dist/{run-KLPSFEv-.js → run-CecrPSop.js} +2 -3
- package/dist/{run-KLPSFEv-.js.map → run-CecrPSop.js.map} +1 -1
- package/dist/{run-BCswmM8Q.js → run-Ck04_W4q.js} +2 -3
- package/dist/{run-BCswmM8Q.js.map → run-Ck04_W4q.js.map} +1 -1
- package/dist/{run-BQQhNg8I.js → run-DcP1czVQ.js} +25 -84
- package/dist/run-DcP1czVQ.js.map +1 -0
- package/dist/{run-D8EJ2hKI.cjs → run-Dyc52IzX.cjs} +5 -6
- package/dist/{run-D8EJ2hKI.cjs.map → run-Dyc52IzX.cjs.map} +1 -1
- package/dist/{run-C8dyBAPb.cjs → run-QqLDhthl.cjs} +46 -158
- package/dist/run-QqLDhthl.cjs.map +1 -0
- package/dist/run-WkXSXG2V.js +1 -0
- package/dist/{snapshot-B45A4RfA.cjs → snapshot-NGLcfG6E.cjs} +17 -26
- package/dist/snapshot-NGLcfG6E.cjs.map +1 -0
- package/dist/{snapshot-C0WaZZiF.js → snapshot-iEjgROga.js} +15 -24
- package/dist/snapshot-iEjgROga.js.map +1 -0
- package/dist/studioWorker.js +2 -2
- package/package.json +7 -8
- package/dist/Telemetry-B_C4MVJd.cjs +0 -231
- package/dist/Telemetry-B_C4MVJd.cjs.map +0 -1
- package/dist/Telemetry-DER8LIO5.js +0 -207
- package/dist/Telemetry-DER8LIO5.js.map +0 -1
- package/dist/agent-BPIqnEl2.js +0 -59
- package/dist/agent-BPIqnEl2.js.map +0 -1
- package/dist/agent-DElUuYuy.cjs +0 -120
- package/dist/agent-DElUuYuy.cjs.map +0 -1
- package/dist/background-DSKoOwcG.js +0 -1
- package/dist/commands-BegVe5Mt.js +0 -81
- package/dist/commands-BegVe5Mt.js.map +0 -1
- package/dist/commands-hXDwA0zn.cjs +0 -87
- package/dist/commands-hXDwA0zn.cjs.map +0 -1
- package/dist/config-B6UIKcl1.js +0 -117
- package/dist/config-B6UIKcl1.js.map +0 -1
- package/dist/config-Bo9ro7vg.cjs +0 -129
- package/dist/config-Bo9ro7vg.cjs.map +0 -1
- package/dist/constants-Cii4HX64.js +0 -12
- package/dist/constants-Cii4HX64.js.map +0 -1
- package/dist/constants-Df449N47.cjs +0 -29
- package/dist/constants-Df449N47.cjs.map +0 -1
- package/dist/errors-BdA8M78q.cjs +0 -43
- package/dist/errors-BdA8M78q.cjs.map +0 -1
- package/dist/errors-DmC83ALX.js +0 -32
- package/dist/errors-DmC83ALX.js.map +0 -1
- package/dist/output-BnK0scpX.cjs.map +0 -1
- package/dist/output-qFt4vV7K.js.map +0 -1
- package/dist/reporters-B4rZOlo8.cjs.map +0 -1
- package/dist/reporters-H21Jvrff.js.map +0 -1
- package/dist/run-89YfZJuo.cjs +0 -67
- package/dist/run-89YfZJuo.cjs.map +0 -1
- package/dist/run-8HrdMihy.js +0 -1
- package/dist/run-BQQhNg8I.js.map +0 -1
- package/dist/run-BYff_byB.js +0 -71
- package/dist/run-BYff_byB.js.map +0 -1
- package/dist/run-C8dyBAPb.cjs.map +0 -1
- package/dist/run-CJHsZZB8.js +0 -178
- package/dist/run-CJHsZZB8.js.map +0 -1
- package/dist/run-Ca_OX3WZ.js +0 -105
- package/dist/run-Ca_OX3WZ.js.map +0 -1
- package/dist/run-Ct6kzKpg.cjs +0 -109
- package/dist/run-Ct6kzKpg.cjs.map +0 -1
- package/dist/run-DL2wLwBZ.cjs +0 -182
- package/dist/run-DL2wLwBZ.cjs.map +0 -1
- package/dist/run-Dej-hm91.js +0 -65
- package/dist/run-Dej-hm91.js.map +0 -1
- package/dist/run-DpAMfkm5.cjs +0 -72
- package/dist/run-DpAMfkm5.cjs.map +0 -1
- package/dist/snapshot-B45A4RfA.cjs.map +0 -1
- package/dist/snapshot-C0WaZZiF.js.map +0 -1
- package/dist/utils-BHW8kA8P.js +0 -83
- package/dist/utils-BHW8kA8P.js.map +0 -1
- package/dist/utils-BzQ46pgd.cjs +0 -109
- package/dist/utils-BzQ46pgd.cjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import "./rolldown-runtime-CRm0XQPb.js";
|
|
2
|
-
import { r as version, t as isDisabled } from "./Telemetry-
|
|
1
|
+
import { t as __name } from "./rolldown-runtime-CRm0XQPb.js";
|
|
2
|
+
import { c as getErrorMessage, r as version, t as isDisabled } from "./Telemetry-E_BBHmnT.js";
|
|
3
|
+
import { S as initDefaults, a as logInfo, b as KUBB_CONFIG_FILENAME, d as logWarn, i as logError, l as logStep, o as logIntro, r as logBlock, s as logOutro, t as createSpinner, v as findConfigFile, x as KUBB_PACKAGE_NAME } from "./output-DS5hyqwL.js";
|
|
4
|
+
import { a as isOutdated, i as installSpec, n as fetchRegistryIndex, o as registryUrl, r as incompatibility, s as toRegistryId, t as fetchRegistryDetail } from "./registry-CSXUuuCy.js";
|
|
3
5
|
import { styleText } from "node:util";
|
|
4
6
|
import dryrun, { pluginId as dryRunId } from "@gunshi/plugin-dryrun";
|
|
5
7
|
import { cli, define, defineWithTypes } from "gunshi";
|
|
8
|
+
import process$1 from "node:process";
|
|
9
|
+
import { x } from "tinyexec";
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import * as clack from "@clack/prompts";
|
|
12
|
+
import fs from "node:fs";
|
|
13
|
+
import { readInstalledPackages } from "@kubb/core";
|
|
6
14
|
//#region src/commands/shared.ts
|
|
7
15
|
const configArg = { config: {
|
|
8
16
|
type: "string",
|
|
@@ -64,43 +72,6 @@ const studioPermissionArgs = {
|
|
|
64
72
|
}
|
|
65
73
|
};
|
|
66
74
|
//#endregion
|
|
67
|
-
//#region src/commands/add.ts
|
|
68
|
-
const command$13 = define({
|
|
69
|
-
name: "add",
|
|
70
|
-
description: "Install a plugin, adapter, or parser from the Kubb registry at its reviewed version. A plugin is added to kubb.config.ts, an adapter or parser prints the code to add. Reads KUBB_REGISTRY to use another registry.",
|
|
71
|
-
examples: [
|
|
72
|
-
"kubb add plugin-zod",
|
|
73
|
-
"kubb add kubb-labs/plugin-react-query",
|
|
74
|
-
"kubb add acme/plugin-x --yes",
|
|
75
|
-
"kubb add plugin-zod --no-install"
|
|
76
|
-
].join("\n"),
|
|
77
|
-
toKebab: true,
|
|
78
|
-
args: {
|
|
79
|
-
id: {
|
|
80
|
-
type: "positional",
|
|
81
|
-
description: "Registry id: owner/slug, or a slug for an official extension",
|
|
82
|
-
required: true
|
|
83
|
-
},
|
|
84
|
-
...configArg,
|
|
85
|
-
...yesArg,
|
|
86
|
-
install: {
|
|
87
|
-
type: "boolean",
|
|
88
|
-
description: "Install the package. Pass --no-install to only edit the config",
|
|
89
|
-
negatable: true,
|
|
90
|
-
default: true
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
async run({ values }) {
|
|
94
|
-
const { run } = await import("./run-8HrdMihy.js");
|
|
95
|
-
await run({
|
|
96
|
-
id: values.id,
|
|
97
|
-
configPath: values.config,
|
|
98
|
-
yes: values.yes,
|
|
99
|
-
install: values.install
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
//#endregion
|
|
104
75
|
//#region src/commands/generate.ts
|
|
105
76
|
const REPORTER_NAMES = [
|
|
106
77
|
"cli",
|
|
@@ -124,7 +95,7 @@ function resolveLogLevel({ verbose, silent, logLevel }) {
|
|
|
124
95
|
if (silent) return "silent";
|
|
125
96
|
return logLevel;
|
|
126
97
|
}
|
|
127
|
-
const command$
|
|
98
|
+
const command$13 = defineWithTypes()({
|
|
128
99
|
name: "generate",
|
|
129
100
|
description: "Generate TypeScript types, API clients, React Query hooks, Zod schemas, and more from an OpenAPI specification. Reads kubb.config.ts by default. Pass an OpenAPI file path as the first argument to override the input without editing the config.",
|
|
130
101
|
examples: [
|
|
@@ -174,7 +145,7 @@ const command$12 = defineWithTypes()({
|
|
|
174
145
|
async run(ctx) {
|
|
175
146
|
const { values } = ctx;
|
|
176
147
|
const logLevel = resolveLogLevel(values);
|
|
177
|
-
const { run } = await import("./run-
|
|
148
|
+
const { run } = await import("./run-BPD5Vaon.js");
|
|
178
149
|
await run({
|
|
179
150
|
input: values.input,
|
|
180
151
|
configPath: values.config,
|
|
@@ -186,71 +157,9 @@ const command$12 = defineWithTypes()({
|
|
|
186
157
|
}
|
|
187
158
|
});
|
|
188
159
|
//#endregion
|
|
189
|
-
//#region src/commands/init.ts
|
|
190
|
-
const command$11 = defineWithTypes()({
|
|
191
|
-
name: "init",
|
|
192
|
-
description: "Scaffold a kubb.config.ts and install plugins for code generation from an OpenAPI spec. Run without flags for interactive setup, or pass --input, --output, and --plugins to skip the prompts.",
|
|
193
|
-
examples: [
|
|
194
|
-
"kubb init",
|
|
195
|
-
"kubb init --yes",
|
|
196
|
-
"kubb init --input ./openapi.yaml --output ./src/gen --plugins plugin-ts,plugin-zod",
|
|
197
|
-
"kubb init --plugins plugin-ts,plugin-axios,plugin-react-query",
|
|
198
|
-
"kubb init --yes --dry-run"
|
|
199
|
-
].join("\n"),
|
|
200
|
-
toKebab: true,
|
|
201
|
-
args: {
|
|
202
|
-
yes: {
|
|
203
|
-
type: "boolean",
|
|
204
|
-
description: "Skip prompts and use default options",
|
|
205
|
-
short: "y",
|
|
206
|
-
default: false
|
|
207
|
-
},
|
|
208
|
-
input: {
|
|
209
|
-
type: "string",
|
|
210
|
-
description: "Path to the OpenAPI specification",
|
|
211
|
-
short: "i",
|
|
212
|
-
metavar: "path"
|
|
213
|
-
},
|
|
214
|
-
output: {
|
|
215
|
-
type: "string",
|
|
216
|
-
description: "Output directory for generated files",
|
|
217
|
-
short: "o",
|
|
218
|
-
metavar: "path"
|
|
219
|
-
},
|
|
220
|
-
plugins: {
|
|
221
|
-
type: "string",
|
|
222
|
-
description: "Comma-separated Kubb registry ids of the plugins to add, the same ids `kubb add` takes (plugin-ts, plugin-zod, acme/plugin-x)",
|
|
223
|
-
metavar: "plugin-ts,plugin-zod,..."
|
|
224
|
-
}
|
|
225
|
-
},
|
|
226
|
-
async run(ctx) {
|
|
227
|
-
const { values } = ctx;
|
|
228
|
-
const { run } = await import("./run-CJHsZZB8.js");
|
|
229
|
-
await run({
|
|
230
|
-
yes: values.yes,
|
|
231
|
-
version,
|
|
232
|
-
input: values.input,
|
|
233
|
-
output: values.output,
|
|
234
|
-
plugins: values.plugins,
|
|
235
|
-
dryRun: ctx.extensions[dryRunId]
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
//#endregion
|
|
240
|
-
//#region src/commands/list.ts
|
|
241
|
-
const command$10 = define({
|
|
242
|
-
name: "list",
|
|
243
|
-
description: "List the installed Kubb extensions: their registry id, package, installed version, the version the Kubb registry pins, and whether an update exists.",
|
|
244
|
-
examples: "kubb list",
|
|
245
|
-
async run() {
|
|
246
|
-
const { run } = await import("./run-BYff_byB.js");
|
|
247
|
-
await run();
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
//#endregion
|
|
251
160
|
//#region src/commands/mcp.ts
|
|
252
161
|
/** The runner is imported when the command runs, so listing `kubb --help` never loads `@kubb/mcp`. */
|
|
253
|
-
const command$
|
|
162
|
+
const command$12 = define({
|
|
254
163
|
name: "mcp",
|
|
255
164
|
description: "Start a Model Context Protocol (MCP) server that exposes Kubb code generation as tools for AI assistants. Once running, configure your AI client (Claude, Cursor, Windsurf, etc.) to connect to it — the assistant can then call kubb generate directly without leaving the chat.",
|
|
256
165
|
examples: [
|
|
@@ -260,13 +169,29 @@ const command$9 = define({
|
|
|
260
169
|
].join("\n"),
|
|
261
170
|
rendering: { header: null },
|
|
262
171
|
async run() {
|
|
263
|
-
const { run } = await import("./run-
|
|
172
|
+
const { run } = await import("./run-CecrPSop.js");
|
|
264
173
|
await run();
|
|
265
174
|
}
|
|
266
175
|
});
|
|
267
176
|
//#endregion
|
|
177
|
+
//#region src/commands/studio/studioCommand.ts
|
|
178
|
+
/**
|
|
179
|
+
* Defines a `kubb studio` subcommand. The runner, and with it `@kubb/studio`, loads only when the
|
|
180
|
+
* command runs, so `kubb --help` never does.
|
|
181
|
+
*/
|
|
182
|
+
function studioCommand({ action, block, ...definition }) {
|
|
183
|
+
return define({
|
|
184
|
+
...definition,
|
|
185
|
+
toKebab: true,
|
|
186
|
+
async run({ values }) {
|
|
187
|
+
const { runStudio } = await import("./run-WkXSXG2V.js");
|
|
188
|
+
await runStudio(values, action, { block });
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
//#endregion
|
|
268
193
|
//#region src/commands/studio/connect.ts
|
|
269
|
-
const command$
|
|
194
|
+
const command$11 = studioCommand({
|
|
270
195
|
name: "connect",
|
|
271
196
|
description: "Connect this project to Kubb Studio and generate from the browser.",
|
|
272
197
|
examples: [
|
|
@@ -275,7 +200,6 @@ const command$8 = define({
|
|
|
275
200
|
"kubb studio connect --allow-write --allow-exec",
|
|
276
201
|
"kubb studio connect --url http://localhost:3000"
|
|
277
202
|
].join("\n"),
|
|
278
|
-
toKebab: true,
|
|
279
203
|
args: {
|
|
280
204
|
...configArg,
|
|
281
205
|
...studioConnectionArgs,
|
|
@@ -288,45 +212,42 @@ const command$8 = define({
|
|
|
288
212
|
},
|
|
289
213
|
...logLevelArg
|
|
290
214
|
},
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
await
|
|
215
|
+
block: true,
|
|
216
|
+
async action(options) {
|
|
217
|
+
const { connect } = await import("./run-WkXSXG2V.js");
|
|
218
|
+
await connect(options);
|
|
294
219
|
}
|
|
295
220
|
});
|
|
296
221
|
//#endregion
|
|
297
222
|
//#region src/commands/studio/login.ts
|
|
298
|
-
const command$
|
|
223
|
+
const command$10 = studioCommand({
|
|
299
224
|
name: "login",
|
|
300
225
|
description: "Pair this machine with Kubb Studio without connecting.",
|
|
301
226
|
examples: ["kubb studio login", "kubb studio login --url http://localhost:3000"].join("\n"),
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
await loginRunner(ctx);
|
|
227
|
+
args: command$11.args,
|
|
228
|
+
async action(options) {
|
|
229
|
+
const { login } = await import("./run-WkXSXG2V.js");
|
|
230
|
+
await login(options);
|
|
307
231
|
}
|
|
308
232
|
});
|
|
309
233
|
//#endregion
|
|
310
234
|
//#region src/commands/studio/logout.ts
|
|
311
|
-
const command$
|
|
235
|
+
const command$9 = studioCommand({
|
|
312
236
|
name: "logout",
|
|
313
237
|
description: "Forget the stored Kubb Studio token.",
|
|
314
|
-
examples:
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
async run(ctx) {
|
|
323
|
-
const { logoutRunner } = await import("./commands-BegVe5Mt.js");
|
|
324
|
-
await logoutRunner(ctx);
|
|
238
|
+
examples: "kubb studio logout",
|
|
239
|
+
args: {},
|
|
240
|
+
async action() {
|
|
241
|
+
const { stopWorker } = await import("./background-CZ2nVKwB.js");
|
|
242
|
+
const { clearCredentials } = await import("./credentials-C8tjAhTo.js");
|
|
243
|
+
await stopWorker();
|
|
244
|
+
await clearCredentials();
|
|
245
|
+
console.log("Signed out of Kubb Studio.");
|
|
325
246
|
}
|
|
326
247
|
});
|
|
327
248
|
//#endregion
|
|
328
249
|
//#region src/commands/studio/snapshot.ts
|
|
329
|
-
const command$
|
|
250
|
+
const command$8 = define({
|
|
330
251
|
name: "snapshot",
|
|
331
252
|
description: "Generate and publish a Kubb Studio snapshot from CI.",
|
|
332
253
|
examples: ["kubb studio snapshot", "kubb studio snapshot --json"].join("\n"),
|
|
@@ -360,51 +281,69 @@ const command$5 = define({
|
|
|
360
281
|
...logLevelArg
|
|
361
282
|
},
|
|
362
283
|
async run(ctx) {
|
|
363
|
-
const { runner } = await import("./snapshot-
|
|
284
|
+
const { runner } = await import("./snapshot-iEjgROga.js");
|
|
364
285
|
await runner(ctx);
|
|
365
286
|
}
|
|
366
287
|
});
|
|
367
288
|
//#endregion
|
|
368
289
|
//#region src/commands/studio/background.ts
|
|
369
|
-
const command$
|
|
290
|
+
const command$7 = studioCommand({
|
|
370
291
|
name: "start",
|
|
371
292
|
description: "Keep this project connected to Kubb Studio in the background.",
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
await startRunner(ctx);
|
|
293
|
+
args: command$11.args,
|
|
294
|
+
async action(options) {
|
|
295
|
+
const { startWorker } = await import("./background-CZ2nVKwB.js");
|
|
296
|
+
await startWorker(options);
|
|
377
297
|
}
|
|
378
298
|
});
|
|
379
299
|
const stopCommand = define({
|
|
380
300
|
name: "stop",
|
|
381
301
|
description: "Stop this project's background connection and keep its pairing.",
|
|
382
302
|
async run() {
|
|
383
|
-
const {
|
|
384
|
-
await
|
|
303
|
+
const { stopWorker } = await import("./background-CZ2nVKwB.js");
|
|
304
|
+
await stopWorker();
|
|
305
|
+
console.log("Background connection stopped.");
|
|
385
306
|
}
|
|
386
307
|
});
|
|
387
308
|
//#endregion
|
|
388
309
|
//#region src/commands/studio/status.ts
|
|
389
|
-
const command$
|
|
310
|
+
const command$6 = studioCommand({
|
|
390
311
|
name: "status",
|
|
391
312
|
description: "Show the project worker, Kubb Studio pairing, and saved permissions.",
|
|
392
|
-
examples:
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
const
|
|
402
|
-
|
|
313
|
+
examples: "kubb studio status",
|
|
314
|
+
args: { url: studioConnectionArgs.url },
|
|
315
|
+
async action(options) {
|
|
316
|
+
const { getWorkerLogPath, getWorkerStatus } = await import("./background-CZ2nVKwB.js");
|
|
317
|
+
const { readCredentials } = await import("./credentials-C8tjAhTo.js");
|
|
318
|
+
const { formatPermissionRows } = await import("./run-WkXSXG2V.js");
|
|
319
|
+
const worker = await getWorkerStatus();
|
|
320
|
+
console.log(`Background connection: ${worker.state}${worker.running ? ` (PID ${worker.pid})` : ""}`);
|
|
321
|
+
console.log(`Logs: ${getWorkerLogPath()}`);
|
|
322
|
+
const credentials = await readCredentials();
|
|
323
|
+
if (!credentials) {
|
|
324
|
+
console.log("Not paired. Run `kubb studio login`.");
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
console.log(`Paired with ${credentials.studioUrl} as ${styleText("cyan", credentials.agentSlug || credentials.agentId)}`);
|
|
328
|
+
if (credentials.studioUrl !== options.studioUrl) console.log(styleText("yellow", `Connecting to ${options.studioUrl} needs pairing again.`));
|
|
329
|
+
const remembered = credentials.projects?.[process$1.cwd()];
|
|
330
|
+
if (!remembered) {
|
|
331
|
+
console.log(styleText("dim", "No saved permissions for this project. Run `kubb studio` to connect and choose."));
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
console.log(styleText("dim", "Saved permissions"));
|
|
335
|
+
for (const row of formatPermissionRows({
|
|
336
|
+
allowRead: remembered.allowRead === true,
|
|
337
|
+
allowWrite: remembered.allowWrite === true,
|
|
338
|
+
allowConfigEdit: remembered.allowConfigEdit === true,
|
|
339
|
+
allowExec: remembered.allowExec === true
|
|
340
|
+
})) console.log(row);
|
|
403
341
|
}
|
|
404
342
|
});
|
|
405
343
|
//#endregion
|
|
406
344
|
//#region src/commands/studio/index.ts
|
|
407
|
-
const command$
|
|
345
|
+
const command$5 = define({
|
|
346
|
+
...command$11,
|
|
408
347
|
name: "studio",
|
|
409
348
|
description: "Connect this project to Kubb Studio, or manage its pairing and snapshots.",
|
|
410
349
|
examples: [
|
|
@@ -415,20 +354,14 @@ const command$2 = define({
|
|
|
415
354
|
"kubb studio logout",
|
|
416
355
|
"kubb studio snapshot"
|
|
417
356
|
].join("\n"),
|
|
418
|
-
toKebab: true,
|
|
419
|
-
args: command$8.args,
|
|
420
|
-
async run(ctx) {
|
|
421
|
-
const { connectRunner } = await import("./commands-BegVe5Mt.js");
|
|
422
|
-
await connectRunner(ctx);
|
|
423
|
-
},
|
|
424
357
|
subCommands: {
|
|
425
|
-
start: command$
|
|
358
|
+
start: command$7,
|
|
426
359
|
stop: stopCommand,
|
|
427
|
-
connect: command$
|
|
428
|
-
login: command$
|
|
429
|
-
logout: command$
|
|
430
|
-
status: command$
|
|
431
|
-
snapshot: command$
|
|
360
|
+
connect: command$11,
|
|
361
|
+
login: command$10,
|
|
362
|
+
logout: command$9,
|
|
363
|
+
status: command$6,
|
|
364
|
+
snapshot: command$8
|
|
432
365
|
}
|
|
433
366
|
});
|
|
434
367
|
/**
|
|
@@ -445,41 +378,9 @@ function routeStudioFlags(args) {
|
|
|
445
378
|
];
|
|
446
379
|
}
|
|
447
380
|
//#endregion
|
|
448
|
-
//#region src/commands/update.ts
|
|
449
|
-
const command$1 = define({
|
|
450
|
-
name: "update",
|
|
451
|
-
description: "Update installed extensions to the version the Kubb registry pins. Pass ids to update only those, or --check to list the updates without installing.",
|
|
452
|
-
examples: [
|
|
453
|
-
"kubb update",
|
|
454
|
-
"kubb update --check",
|
|
455
|
-
"kubb update plugin-zod plugin-ts --yes"
|
|
456
|
-
].join("\n"),
|
|
457
|
-
args: {
|
|
458
|
-
ids: {
|
|
459
|
-
type: "positional",
|
|
460
|
-
description: "Registry ids to update, all installed extensions when omitted",
|
|
461
|
-
multiple: true
|
|
462
|
-
},
|
|
463
|
-
check: {
|
|
464
|
-
type: "boolean",
|
|
465
|
-
description: "List the available updates without installing them",
|
|
466
|
-
default: false
|
|
467
|
-
},
|
|
468
|
-
...yesArg
|
|
469
|
-
},
|
|
470
|
-
async run({ values }) {
|
|
471
|
-
const { run } = await import("./run-Dej-hm91.js");
|
|
472
|
-
await run({
|
|
473
|
-
ids: values.ids ?? [],
|
|
474
|
-
check: values.check,
|
|
475
|
-
yes: values.yes
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
});
|
|
479
|
-
//#endregion
|
|
480
381
|
//#region src/commands/validate.ts
|
|
481
382
|
/** The runner is imported when the command runs, so listing `kubb --help` never loads `@kubb/adapter-oas`. */
|
|
482
|
-
const command = define({
|
|
383
|
+
const command$4 = define({
|
|
483
384
|
name: "validate",
|
|
484
385
|
description: "Parse and validate an OpenAPI/Swagger file for structural correctness. Reports schema errors, missing required fields, and malformed references. Use this before running generate to catch spec issues early.",
|
|
485
386
|
examples: ["kubb validate ./openapi.yaml", "kubb validate https://petstore3.swagger.io/api/v3/openapi.json"].join("\n"),
|
|
@@ -489,7 +390,7 @@ const command = define({
|
|
|
489
390
|
required: true
|
|
490
391
|
} },
|
|
491
392
|
async run({ values }) {
|
|
492
|
-
const { run } = await import("./run-
|
|
393
|
+
const { run } = await import("./run-Ck04_W4q.js");
|
|
493
394
|
await run({ input: values.input });
|
|
494
395
|
}
|
|
495
396
|
});
|
|
@@ -524,6 +425,596 @@ function resolveDeprecatedFlags(args) {
|
|
|
524
425
|
});
|
|
525
426
|
}
|
|
526
427
|
//#endregion
|
|
428
|
+
//#region ../../internals/shared/src/init.ts
|
|
429
|
+
/** The `kubb.config.ts` `kubb init` writes before `kubb add` puts each plugin in. */
|
|
430
|
+
function generateConfigFile({ inputPath, outputPath }) {
|
|
431
|
+
return `import { defineConfig } from 'kubb/config'
|
|
432
|
+
|
|
433
|
+
export default defineConfig({
|
|
434
|
+
input: '${inputPath}',
|
|
435
|
+
output: {
|
|
436
|
+
path: '${outputPath}',
|
|
437
|
+
clean: true,
|
|
438
|
+
},
|
|
439
|
+
plugins: [],
|
|
440
|
+
})
|
|
441
|
+
`;
|
|
442
|
+
}
|
|
443
|
+
//#endregion
|
|
444
|
+
//#region src/runners/init/utils.ts
|
|
445
|
+
/** Metadata for each supported package manager, keyed by its short name. */
|
|
446
|
+
const packageManagers = {
|
|
447
|
+
pnpm: {
|
|
448
|
+
name: "pnpm",
|
|
449
|
+
lockFiles: ["pnpm-lock.yaml"],
|
|
450
|
+
initCommand: ["init"],
|
|
451
|
+
installCommand: ["add", "-D"]
|
|
452
|
+
},
|
|
453
|
+
yarn: {
|
|
454
|
+
name: "yarn",
|
|
455
|
+
lockFiles: ["yarn.lock"],
|
|
456
|
+
initCommand: ["init", "-y"],
|
|
457
|
+
installCommand: ["add", "-D"]
|
|
458
|
+
},
|
|
459
|
+
bun: {
|
|
460
|
+
name: "bun",
|
|
461
|
+
lockFiles: ["bun.lock", "bun.lockb"],
|
|
462
|
+
initCommand: ["init", "-y"],
|
|
463
|
+
installCommand: ["add", "-d"]
|
|
464
|
+
},
|
|
465
|
+
npm: {
|
|
466
|
+
name: "npm",
|
|
467
|
+
lockFiles: ["package-lock.json"],
|
|
468
|
+
initCommand: ["init", "-y"],
|
|
469
|
+
installCommand: ["install", "--save-dev"]
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
/** Detects the package manager for `cwd`: the `packageManager` field in `package.json`, then a lock file, then `npm`. */
|
|
473
|
+
function detectPackageManager(cwd = process$1.cwd()) {
|
|
474
|
+
const packageJsonPath = path.join(cwd, "package.json");
|
|
475
|
+
if (fs.existsSync(packageJsonPath)) try {
|
|
476
|
+
const pmField = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8")).packageManager;
|
|
477
|
+
if (typeof pmField === "string") {
|
|
478
|
+
const name = pmField.split("@")[0];
|
|
479
|
+
if (name && name in packageManagers) return packageManagers[name];
|
|
480
|
+
}
|
|
481
|
+
} catch {}
|
|
482
|
+
for (const pm of Object.values(packageManagers)) if (pm.lockFiles.some((lockFile) => fs.existsSync(path.join(cwd, lockFile)))) return pm;
|
|
483
|
+
return packageManagers.npm;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Initializes a new `package.json` at `cwd` using the detected package manager.
|
|
487
|
+
*/
|
|
488
|
+
async function initPackageJson(cwd, packageManager) {
|
|
489
|
+
await x(packageManager.name, [...packageManager.initCommand], {
|
|
490
|
+
nodeOptions: {
|
|
491
|
+
cwd,
|
|
492
|
+
stdio: "inherit"
|
|
493
|
+
},
|
|
494
|
+
throwOnError: true
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Installs the given packages at `cwd` using the detected package manager.
|
|
499
|
+
*/
|
|
500
|
+
async function installPackages(packages, packageManager, cwd = process$1.cwd()) {
|
|
501
|
+
await x(packageManager.name, [...packageManager.installCommand, ...packages], {
|
|
502
|
+
nodeOptions: {
|
|
503
|
+
cwd,
|
|
504
|
+
stdio: "inherit"
|
|
505
|
+
},
|
|
506
|
+
throwOnError: true
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* What the installed manifests of the `selected` plugins say is missing from the selection: a
|
|
511
|
+
* `dependencies` entry, or a `client` plugin next to a `consumer`. Empty when nothing is missing.
|
|
512
|
+
* `optionalDependencies` are skipped, since `kubb init` writes the default options.
|
|
513
|
+
*/
|
|
514
|
+
function missingPluginDependencies({ selected, manifests }) {
|
|
515
|
+
const hasClient = manifests.some((manifest) => manifest.role === "client");
|
|
516
|
+
return manifests.flatMap((manifest) => [...(manifest.dependencies ?? []).filter((name) => !selected.includes(name)).map((name) => `${manifest.name} needs ${name}.`), ...manifest.role === "consumer" && !hasClient ? [`${manifest.name} needs a client plugin, such as plugin-axios or plugin-fetch.`] : []]);
|
|
517
|
+
}
|
|
518
|
+
//#endregion
|
|
519
|
+
//#region src/runners/add/run.ts
|
|
520
|
+
/** The import and the `defineConfig` property to merge into `kubb.config.ts` by hand. */
|
|
521
|
+
function toSnippet({ artifact, manifest }) {
|
|
522
|
+
const call = `${manifest.export}()`;
|
|
523
|
+
const property = {
|
|
524
|
+
plugin: `plugins: [..., ${call}],`,
|
|
525
|
+
adapter: `adapter: ${call},`,
|
|
526
|
+
parser: `parsers: [..., ${call}],`
|
|
527
|
+
};
|
|
528
|
+
return [
|
|
529
|
+
`import { ${manifest.export} } from '${artifact.package}'`,
|
|
530
|
+
"",
|
|
531
|
+
property[manifest.kind]
|
|
532
|
+
].join("\n");
|
|
533
|
+
}
|
|
534
|
+
/** Adds the plugin call and its import to the config file. Returns why it could not, or `undefined`. */
|
|
535
|
+
async function addToConfig({ detail, configFile }) {
|
|
536
|
+
const { artifact, manifest } = detail;
|
|
537
|
+
try {
|
|
538
|
+
const { writeConfigEdits } = await import("@kubb/studio");
|
|
539
|
+
const { outcomes } = await writeConfigEdits({
|
|
540
|
+
filePath: configFile,
|
|
541
|
+
edits: [{
|
|
542
|
+
operation: "add-plugin",
|
|
543
|
+
plugin: artifact.package
|
|
544
|
+
}],
|
|
545
|
+
extensions: /* @__PURE__ */ new Map([[artifact.package, {
|
|
546
|
+
package: artifact.package,
|
|
547
|
+
version: artifact.version,
|
|
548
|
+
manifest
|
|
549
|
+
}]])
|
|
550
|
+
});
|
|
551
|
+
return outcomes[0]?.applied ? void 0 : outcomes[0]?.reason ?? "the config file was not changed";
|
|
552
|
+
} catch (error) {
|
|
553
|
+
return getErrorMessage(error);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
async function selectExtension(registry) {
|
|
557
|
+
const options = (await fetchRegistryIndex({ registry })).toSorted((a, b) => a.id.localeCompare(b.id)).map((entry) => ({
|
|
558
|
+
value: entry.id,
|
|
559
|
+
label: entry.manifest.displayName,
|
|
560
|
+
hint: `${entry.id} · ${entry.kind} ${entry.artifact.version} · ${entry.manifest.description}`
|
|
561
|
+
}));
|
|
562
|
+
if (!options.length) throw new Error(`The registry at ${registry} lists no extensions.`);
|
|
563
|
+
const id = await clack.autocomplete({
|
|
564
|
+
message: "Select an extension to add:",
|
|
565
|
+
options,
|
|
566
|
+
filter: (search, option) => `${option.label} ${option.hint}`.toLowerCase().includes(search.toLowerCase())
|
|
567
|
+
});
|
|
568
|
+
return clack.isCancel(id) ? void 0 : id;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Installs an extension from the Kubb registry at its reviewed version and, for a plugin, adds it to
|
|
572
|
+
* `kubb.config.ts`. Without an id, asks which one. Refuses when the running Kubb or Node.js version
|
|
573
|
+
* is outside its compatibility.
|
|
574
|
+
*/
|
|
575
|
+
async function run$4({ id: input, configPath, yes, install }) {
|
|
576
|
+
const cwd = process$1.cwd();
|
|
577
|
+
logIntro({ title: styleText("bgCyan", styleText("black", " Kubb Add ")) });
|
|
578
|
+
try {
|
|
579
|
+
const registry = registryUrl();
|
|
580
|
+
if (!input && yes) throw new Error("Pass a registry id, such as plugin-zod, when using --yes.");
|
|
581
|
+
const id = input ? toRegistryId(input) : await selectExtension(registry);
|
|
582
|
+
if (!id) {
|
|
583
|
+
clack.cancel("Operation canceled.");
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
const detail = await fetchRegistryDetail({
|
|
587
|
+
id,
|
|
588
|
+
registry
|
|
589
|
+
});
|
|
590
|
+
const { artifact, manifest } = detail;
|
|
591
|
+
const problem = incompatibility(manifest);
|
|
592
|
+
if (problem) throw new Error(problem);
|
|
593
|
+
const spec = installSpec(artifact);
|
|
594
|
+
const configFile = manifest.kind === "plugin" ? configPath ? path.resolve(configPath) : findConfigFile(cwd) : void 0;
|
|
595
|
+
if (manifest.kind === "plugin" && !configFile) throw new Error("No kubb.config.ts found. Run `kubb init` first, or pass --config.");
|
|
596
|
+
logInfo(`${styleText("cyan", manifest.displayName)} (${manifest.kind}): ${manifest.description}`);
|
|
597
|
+
logBlock([install ? `Install ${styleText("cyan", spec)} as a dev dependency` : `Skip installing ${spec}`, configFile ? `Add ${styleText("cyan", `${manifest.export}()`)} to ${path.relative(cwd, configFile) || configFile}` : `Print the ${manifest.kind} snippet to add`]);
|
|
598
|
+
const confirmed = yes || await clack.confirm({
|
|
599
|
+
message: "Continue?",
|
|
600
|
+
initialValue: true
|
|
601
|
+
});
|
|
602
|
+
if (clack.isCancel(confirmed) || !confirmed) {
|
|
603
|
+
clack.cancel("Operation canceled.");
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
if (install) {
|
|
607
|
+
const packageManager = detectPackageManager(cwd);
|
|
608
|
+
logStep(`Installing ${spec} with ${packageManager.name}`);
|
|
609
|
+
await installPackages([spec], packageManager, cwd);
|
|
610
|
+
}
|
|
611
|
+
const reason = configFile ? await addToConfig({
|
|
612
|
+
detail,
|
|
613
|
+
configFile
|
|
614
|
+
}) : `add the ${manifest.kind} to your config`;
|
|
615
|
+
if (!reason) {
|
|
616
|
+
logOutro(styleText("green", install ? `Added ${spec}` : `Added ${manifest.export}() to the config. Install ${spec} to use it.`));
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
if (configFile) logWarn(`Could not edit ${configFile}: ${reason}`);
|
|
620
|
+
logBlock([
|
|
621
|
+
"Add the import to your Kubb config and merge the property into its defineConfig call:",
|
|
622
|
+
"",
|
|
623
|
+
toSnippet(detail)
|
|
624
|
+
]);
|
|
625
|
+
logOutro(styleText("green", install ? `Installed ${spec}. Add it with the snippet above.` : `Install ${spec} and add the snippet above.`));
|
|
626
|
+
} catch (error) {
|
|
627
|
+
logError(getErrorMessage(error));
|
|
628
|
+
process$1.exitCode = 1;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
__name(run$4, "run");
|
|
632
|
+
const command$3 = define({
|
|
633
|
+
name: "add",
|
|
634
|
+
description: "Install a plugin, adapter, or parser from the Kubb registry at its reviewed version. Without an id, pick one from the registry. A plugin is added to kubb.config.ts, an adapter or parser prints the code to add. Reads KUBB_REGISTRY to use another registry.",
|
|
635
|
+
examples: [
|
|
636
|
+
"kubb add",
|
|
637
|
+
"kubb add plugin-zod",
|
|
638
|
+
"kubb add kubb-labs/plugin-react-query",
|
|
639
|
+
"kubb add acme/plugin-x --yes",
|
|
640
|
+
"kubb add plugin-zod --no-install"
|
|
641
|
+
].join("\n"),
|
|
642
|
+
toKebab: true,
|
|
643
|
+
args: {
|
|
644
|
+
id: {
|
|
645
|
+
type: "positional",
|
|
646
|
+
description: "Registry id: owner/slug, or a slug for an official extension. Asked for when omitted",
|
|
647
|
+
required: false
|
|
648
|
+
},
|
|
649
|
+
...configArg,
|
|
650
|
+
...yesArg,
|
|
651
|
+
install: {
|
|
652
|
+
type: "boolean",
|
|
653
|
+
description: "Install the package. Pass --no-install to only edit the config",
|
|
654
|
+
negatable: true,
|
|
655
|
+
default: true
|
|
656
|
+
}
|
|
657
|
+
},
|
|
658
|
+
run: ({ values }) => run$4({
|
|
659
|
+
id: values.id,
|
|
660
|
+
configPath: values.config,
|
|
661
|
+
yes: values.yes,
|
|
662
|
+
install: values.install
|
|
663
|
+
})
|
|
664
|
+
});
|
|
665
|
+
//#endregion
|
|
666
|
+
//#region src/runners/init/run.ts
|
|
667
|
+
function cancelAndExit(message = "Operation canceled.") {
|
|
668
|
+
clack.cancel(message);
|
|
669
|
+
process$1.exit(0);
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Runs the interactive Kubb scaffolding wizard.
|
|
673
|
+
* Detects the package manager, prompts for input/output paths and plugins, installs packages, and writes `kubb.config.ts`.
|
|
674
|
+
* Pass `yes: true` to skip all prompts and use defaults.
|
|
675
|
+
*/
|
|
676
|
+
async function run$3({ yes, input: inputFlag, output: outputFlag, plugins: pluginsFlag, dryRun }) {
|
|
677
|
+
const cwd = process$1.cwd();
|
|
678
|
+
logIntro({ title: styleText("bgCyan", styleText("black", " Kubb Init ")) });
|
|
679
|
+
/**
|
|
680
|
+
* Returns `flag` when provided, the `defaultValue` when `yes` is set,
|
|
681
|
+
* or calls `prompt()` for interactive input. Exits on cancellation.
|
|
682
|
+
*/
|
|
683
|
+
async function resolveOrPrompt(flag, defaultValue, logLabel, prompt) {
|
|
684
|
+
if (flag !== void 0) {
|
|
685
|
+
logInfo(`${logLabel}: ${styleText("cyan", String(flag))}`);
|
|
686
|
+
return flag;
|
|
687
|
+
}
|
|
688
|
+
if (yes) {
|
|
689
|
+
logInfo(`${logLabel}: ${styleText("cyan", String(defaultValue))}`);
|
|
690
|
+
return defaultValue;
|
|
691
|
+
}
|
|
692
|
+
const result = await prompt();
|
|
693
|
+
if (clack.isCancel(result)) cancelAndExit();
|
|
694
|
+
return result;
|
|
695
|
+
}
|
|
696
|
+
try {
|
|
697
|
+
const plugins = (await fetchRegistryIndex({ registry: registryUrl() })).filter((entry) => entry.kind === "plugin" && !incompatibility(entry.manifest));
|
|
698
|
+
const byId = new Map(plugins.map((entry) => [entry.id, entry]));
|
|
699
|
+
if (!fs.existsSync(path.join(cwd, "package.json"))) {
|
|
700
|
+
if (!yes) {
|
|
701
|
+
const shouldInit = await clack.confirm({
|
|
702
|
+
message: "No package.json found. Would you like to create one?",
|
|
703
|
+
initialValue: true
|
|
704
|
+
});
|
|
705
|
+
if (clack.isCancel(shouldInit) || !shouldInit) cancelAndExit();
|
|
706
|
+
}
|
|
707
|
+
const packageManager = detectPackageManager(cwd);
|
|
708
|
+
const spinner = createSpinner();
|
|
709
|
+
spinner.start(`Initializing package.json with ${packageManager.name}`);
|
|
710
|
+
await initPackageJson(cwd, packageManager);
|
|
711
|
+
spinner.stop(`Created package.json with ${packageManager.name}`);
|
|
712
|
+
}
|
|
713
|
+
const packageManager = detectPackageManager(cwd);
|
|
714
|
+
logInfo(`Detected package manager: ${styleText("cyan", packageManager.name)}`);
|
|
715
|
+
const inputPath = await resolveOrPrompt(inputFlag, initDefaults.inputPath, "Using input path", () => clack.text({
|
|
716
|
+
message: "Where is your OpenAPI specification located?",
|
|
717
|
+
placeholder: initDefaults.inputPath,
|
|
718
|
+
defaultValue: initDefaults.inputPath,
|
|
719
|
+
validate: (value) => {
|
|
720
|
+
if (!value) return "Input path is required";
|
|
721
|
+
}
|
|
722
|
+
}));
|
|
723
|
+
const outputPath = await resolveOrPrompt(outputFlag, initDefaults.outputPath, "Using output path", () => clack.text({
|
|
724
|
+
message: "Where should the generated files be output?",
|
|
725
|
+
placeholder: initDefaults.outputPath,
|
|
726
|
+
defaultValue: initDefaults.outputPath,
|
|
727
|
+
validate: (value) => {
|
|
728
|
+
if (!value) return "Output path is required";
|
|
729
|
+
}
|
|
730
|
+
}));
|
|
731
|
+
const defaultPlugins = initDefaults.plugins.flatMap((slug) => byId.get(toRegistryId(slug)) ?? []);
|
|
732
|
+
const pluginLabel = (entries) => styleText("cyan", entries.map((entry) => entry.manifest.displayName).join(", "));
|
|
733
|
+
const selectedPlugins = await (async () => {
|
|
734
|
+
if (pluginsFlag) {
|
|
735
|
+
const ids = pluginsFlag.split(",").map((id) => id.trim()).filter(Boolean);
|
|
736
|
+
const unknown = ids.filter((id) => !byId.has(toRegistryId(id)));
|
|
737
|
+
if (unknown.length) throw new Error(`Not in the Kubb registry: ${unknown.join(", ")}. Browse the plugins at https://kubb.dev/extensions.`);
|
|
738
|
+
const entries = ids.map((id) => byId.get(toRegistryId(id)));
|
|
739
|
+
logInfo(`Using plugins: ${pluginLabel(entries)}`);
|
|
740
|
+
return entries;
|
|
741
|
+
}
|
|
742
|
+
if (yes) {
|
|
743
|
+
logInfo(`Using plugins: ${pluginLabel(defaultPlugins)}`);
|
|
744
|
+
return defaultPlugins;
|
|
745
|
+
}
|
|
746
|
+
const values = await clack.multiselect({
|
|
747
|
+
message: "Select plugins to use:",
|
|
748
|
+
options: plugins.map(({ id, manifest }) => ({
|
|
749
|
+
value: id,
|
|
750
|
+
label: manifest.displayName,
|
|
751
|
+
hint: manifest.category
|
|
752
|
+
})),
|
|
753
|
+
initialValues: defaultPlugins.map((entry) => entry.id),
|
|
754
|
+
required: true
|
|
755
|
+
});
|
|
756
|
+
if (clack.isCancel(values)) cancelAndExit();
|
|
757
|
+
return plugins.filter((entry) => values.includes(entry.id));
|
|
758
|
+
})();
|
|
759
|
+
const missing = missingPluginDependencies({
|
|
760
|
+
selected: selectedPlugins.map((entry) => entry.manifest.name),
|
|
761
|
+
manifests: selectedPlugins.map((entry) => entry.manifest)
|
|
762
|
+
});
|
|
763
|
+
if (missing.length) throw new Error(`${missing.join("\n")}\nAdd the missing plugins and run kubb init again.`);
|
|
764
|
+
const packagesToInstall = [`${KUBB_PACKAGE_NAME}@${version}`, ...selectedPlugins.map((entry) => installSpec(entry.artifact))];
|
|
765
|
+
const spinner = createSpinner();
|
|
766
|
+
spinner.start(`Installing ${packagesToInstall.length} packages with ${packageManager.name}`);
|
|
767
|
+
try {
|
|
768
|
+
await dryRun.run(() => installPackages(packagesToInstall, packageManager, cwd), { message: `install ${packagesToInstall.length} packages with ${packageManager.name}` });
|
|
769
|
+
spinner.stop(`Installed ${packagesToInstall.length} packages`);
|
|
770
|
+
} catch (error) {
|
|
771
|
+
spinner.stop("Installation failed");
|
|
772
|
+
throw error;
|
|
773
|
+
}
|
|
774
|
+
const configSpinner = createSpinner();
|
|
775
|
+
configSpinner.start(`Creating ${KUBB_CONFIG_FILENAME}`);
|
|
776
|
+
const configContent = generateConfigFile({
|
|
777
|
+
inputPath,
|
|
778
|
+
outputPath
|
|
779
|
+
});
|
|
780
|
+
const configPath = path.join(cwd, KUBB_CONFIG_FILENAME);
|
|
781
|
+
if (fs.existsSync(configPath)) {
|
|
782
|
+
configSpinner.stop(`${KUBB_CONFIG_FILENAME} already exists`);
|
|
783
|
+
if (!yes) {
|
|
784
|
+
const shouldOverwrite = await clack.confirm({
|
|
785
|
+
message: `${KUBB_CONFIG_FILENAME} already exists. Overwrite?`,
|
|
786
|
+
initialValue: false
|
|
787
|
+
});
|
|
788
|
+
if (clack.isCancel(shouldOverwrite) || !shouldOverwrite) cancelAndExit("Keeping existing configuration. Packages have been installed.");
|
|
789
|
+
}
|
|
790
|
+
configSpinner.start(`Overwriting ${KUBB_CONFIG_FILENAME}`);
|
|
791
|
+
}
|
|
792
|
+
await dryRun.run(() => fs.promises.writeFile(configPath, configContent, "utf-8"), { message: `write ${KUBB_CONFIG_FILENAME}` });
|
|
793
|
+
for (const entry of selectedPlugins) {
|
|
794
|
+
const reason = await dryRun.run(() => addToConfig({
|
|
795
|
+
detail: entry,
|
|
796
|
+
configFile: configPath
|
|
797
|
+
}), {
|
|
798
|
+
message: `add ${entry.manifest.export}() to ${KUBB_CONFIG_FILENAME}`,
|
|
799
|
+
resolve: () => void 0
|
|
800
|
+
});
|
|
801
|
+
if (reason) throw new Error(`Could not add ${entry.manifest.export}() to ${KUBB_CONFIG_FILENAME}: ${reason}`);
|
|
802
|
+
}
|
|
803
|
+
configSpinner.stop(`Created ${KUBB_CONFIG_FILENAME}`);
|
|
804
|
+
logOutro(styleText("green", "✓ All set!") + "\n\n" + styleText("dim", "Next steps:") + "\n" + styleText("cyan", ` 1. Make sure your OpenAPI spec is at: ${inputPath}`) + "\n" + styleText("cyan", " 2. Generate code with: npx kubb generate") + "\n" + styleText("cyan", ` 3. Find generated files in: ${outputPath}`) + "\n\n" + styleText("dim", `Using ${packageManager.name} • Kubb v${version}`));
|
|
805
|
+
} catch (error) {
|
|
806
|
+
logError(styleText("red", "An error occurred during initialization"));
|
|
807
|
+
if (error instanceof Error) logError(error.message);
|
|
808
|
+
process$1.exit(1);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
__name(run$3, "run");
|
|
812
|
+
const command$2 = defineWithTypes()({
|
|
813
|
+
name: "init",
|
|
814
|
+
description: "Scaffold a kubb.config.ts and install plugins for code generation from an OpenAPI spec. Run without flags for interactive setup, or pass --input, --output, and --plugins to skip the prompts.",
|
|
815
|
+
examples: [
|
|
816
|
+
"kubb init",
|
|
817
|
+
"kubb init --yes",
|
|
818
|
+
"kubb init --input ./openapi.yaml --output ./src/gen --plugins plugin-ts,plugin-zod",
|
|
819
|
+
"kubb init --plugins plugin-ts,plugin-axios,plugin-react-query",
|
|
820
|
+
"kubb init --yes --dry-run"
|
|
821
|
+
].join("\n"),
|
|
822
|
+
toKebab: true,
|
|
823
|
+
args: {
|
|
824
|
+
yes: {
|
|
825
|
+
type: "boolean",
|
|
826
|
+
description: "Skip prompts and use default options",
|
|
827
|
+
short: "y",
|
|
828
|
+
default: false
|
|
829
|
+
},
|
|
830
|
+
input: {
|
|
831
|
+
type: "string",
|
|
832
|
+
description: "Path to the OpenAPI specification",
|
|
833
|
+
short: "i",
|
|
834
|
+
metavar: "path"
|
|
835
|
+
},
|
|
836
|
+
output: {
|
|
837
|
+
type: "string",
|
|
838
|
+
description: "Output directory for generated files",
|
|
839
|
+
short: "o",
|
|
840
|
+
metavar: "path"
|
|
841
|
+
},
|
|
842
|
+
plugins: {
|
|
843
|
+
type: "string",
|
|
844
|
+
description: "Comma-separated Kubb registry ids of the plugins to add, the same ids `kubb add` takes (plugin-ts, plugin-zod, acme/plugin-x)",
|
|
845
|
+
metavar: "plugin-ts,plugin-zod,..."
|
|
846
|
+
}
|
|
847
|
+
},
|
|
848
|
+
run: ({ values, extensions }) => run$3({
|
|
849
|
+
yes: values.yes,
|
|
850
|
+
input: values.input,
|
|
851
|
+
output: values.output,
|
|
852
|
+
plugins: values.plugins,
|
|
853
|
+
dryRun: extensions[dryRunId]
|
|
854
|
+
})
|
|
855
|
+
});
|
|
856
|
+
//#endregion
|
|
857
|
+
//#region src/runners/list/run.ts
|
|
858
|
+
/**
|
|
859
|
+
* The installed packages that ship a `kubb-extension.json` or have a registry entry, with the
|
|
860
|
+
* version the registry pins.
|
|
861
|
+
*/
|
|
862
|
+
async function listExtensions({ cwd, registry }) {
|
|
863
|
+
const [installed, entries] = await Promise.all([readInstalledPackages({ root: cwd }), fetchRegistryIndex({ registry }).catch((error) => {
|
|
864
|
+
logWarn(`Showing installed extensions only: ${getErrorMessage(error)}`);
|
|
865
|
+
return [];
|
|
866
|
+
})]);
|
|
867
|
+
const byPackage = new Map(entries.map((entry) => [entry.artifact.package, entry]));
|
|
868
|
+
return installed.flatMap(({ package: name, version, manifest }) => {
|
|
869
|
+
const entry = byPackage.get(name);
|
|
870
|
+
if (!entry && !manifest) return [];
|
|
871
|
+
const latest = entry?.artifact.version;
|
|
872
|
+
return [{
|
|
873
|
+
id: entry?.id,
|
|
874
|
+
package: name,
|
|
875
|
+
installed: version,
|
|
876
|
+
registry: latest,
|
|
877
|
+
update: !!latest && isOutdated({
|
|
878
|
+
installed: version,
|
|
879
|
+
latest
|
|
880
|
+
})
|
|
881
|
+
}];
|
|
882
|
+
});
|
|
883
|
+
}
|
|
884
|
+
/** Prints the installed extensions as a table. */
|
|
885
|
+
async function run$2() {
|
|
886
|
+
try {
|
|
887
|
+
const rows = await listExtensions({
|
|
888
|
+
cwd: process$1.cwd(),
|
|
889
|
+
registry: registryUrl()
|
|
890
|
+
});
|
|
891
|
+
if (!rows.length) {
|
|
892
|
+
logOutro("No installed extensions found.");
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
const header = [
|
|
896
|
+
"ID",
|
|
897
|
+
"PACKAGE",
|
|
898
|
+
"INSTALLED",
|
|
899
|
+
"REGISTRY",
|
|
900
|
+
"UPDATE"
|
|
901
|
+
];
|
|
902
|
+
const cells = rows.map((row) => [
|
|
903
|
+
row.id ?? "-",
|
|
904
|
+
row.package,
|
|
905
|
+
row.installed ?? "-",
|
|
906
|
+
row.registry ?? "-",
|
|
907
|
+
row.update ? "yes" : "no"
|
|
908
|
+
]);
|
|
909
|
+
const widths = header.map((title, index) => Math.max(title.length, ...cells.map((cell) => cell[index].length)));
|
|
910
|
+
const line = (cell) => cell.map((value, index) => value.padEnd(widths[index])).join(" ").trimEnd();
|
|
911
|
+
logBlock([styleText("dim", line(header)), ...cells.map(line)]);
|
|
912
|
+
} catch (error) {
|
|
913
|
+
logError(getErrorMessage(error));
|
|
914
|
+
process$1.exitCode = 1;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
__name(run$2, "run");
|
|
918
|
+
const command$1 = define({
|
|
919
|
+
name: "list",
|
|
920
|
+
description: "List the installed Kubb extensions: their registry id, package, installed version, the version the Kubb registry pins, and whether an update exists.",
|
|
921
|
+
examples: "kubb list",
|
|
922
|
+
run: () => run$2()
|
|
923
|
+
});
|
|
924
|
+
//#endregion
|
|
925
|
+
//#region src/runners/update/run.ts
|
|
926
|
+
/**
|
|
927
|
+
* Moves installed extensions to the version the registry pins. Lists the proposals, asks, then
|
|
928
|
+
* installs them. With `check`, only lists them.
|
|
929
|
+
*/
|
|
930
|
+
async function run$1({ ids, check, yes }) {
|
|
931
|
+
const cwd = process$1.cwd();
|
|
932
|
+
logIntro({ title: styleText("bgCyan", styleText("black", " Kubb Update ")) });
|
|
933
|
+
try {
|
|
934
|
+
const wanted = new Set(ids.map(toRegistryId));
|
|
935
|
+
const [entries, installed] = await Promise.all([fetchRegistryIndex({ registry: registryUrl() }), readInstalledPackages({ root: cwd })]);
|
|
936
|
+
const versions = new Map(installed.map((item) => [item.package, item.version]));
|
|
937
|
+
const tracked = entries.filter((entry) => versions.has(entry.artifact.package) && (!wanted.size || wanted.has(entry.id)));
|
|
938
|
+
for (const id of wanted) if (!tracked.some((entry) => entry.id === id)) logWarn(`${id} is not installed, or not in the registry.`);
|
|
939
|
+
const proposals = tracked.filter((entry) => {
|
|
940
|
+
if (!isOutdated({
|
|
941
|
+
installed: versions.get(entry.artifact.package),
|
|
942
|
+
latest: entry.artifact.version
|
|
943
|
+
})) return false;
|
|
944
|
+
const problem = incompatibility(entry.manifest);
|
|
945
|
+
if (problem) logWarn(`Skipped ${entry.id}: ${problem}`);
|
|
946
|
+
return !problem;
|
|
947
|
+
});
|
|
948
|
+
if (!proposals.length) {
|
|
949
|
+
logOutro(ids.length ? `No updates for ${ids.join(", ")}.` : "Every installed extension is up to date.");
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
const change = ({ kind, artifact }) => `${kind} ${versions.get(artifact.package) ?? "not installed"} -> ${styleText("green", artifact.version)}`;
|
|
953
|
+
logBlock(proposals.map((entry) => `${entry.artifact.package} ${change(entry)}`));
|
|
954
|
+
if (check) {
|
|
955
|
+
const plural = proposals.length === 1 ? "" : "s";
|
|
956
|
+
logOutro(`${proposals.length} update${plural} available. Run \`kubb update\` to install.`);
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
let selected = proposals;
|
|
960
|
+
if (!yes) {
|
|
961
|
+
const chosen = await clack.multiselect({
|
|
962
|
+
message: "Select the updates to install:",
|
|
963
|
+
options: proposals.map((entry) => ({
|
|
964
|
+
value: entry.id,
|
|
965
|
+
label: entry.artifact.package,
|
|
966
|
+
hint: change(entry)
|
|
967
|
+
})),
|
|
968
|
+
initialValues: proposals.map((entry) => entry.id),
|
|
969
|
+
required: true
|
|
970
|
+
});
|
|
971
|
+
if (clack.isCancel(chosen)) {
|
|
972
|
+
clack.cancel("Operation canceled.");
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
selected = proposals.filter((entry) => chosen.includes(entry.id));
|
|
976
|
+
}
|
|
977
|
+
const plural = selected.length === 1 ? "" : "s";
|
|
978
|
+
const packageManager = detectPackageManager(cwd);
|
|
979
|
+
const specs = selected.map(({ artifact }) => installSpec(artifact));
|
|
980
|
+
logStep(`Installing ${specs.join(", ")} with ${packageManager.name}`);
|
|
981
|
+
await installPackages(specs, packageManager, cwd);
|
|
982
|
+
logInfo(`Updated ${specs.length} extension${plural}`);
|
|
983
|
+
logOutro(styleText("green", "Done"));
|
|
984
|
+
} catch (error) {
|
|
985
|
+
logError(getErrorMessage(error));
|
|
986
|
+
process$1.exitCode = 1;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
__name(run$1, "run");
|
|
990
|
+
const command = define({
|
|
991
|
+
name: "update",
|
|
992
|
+
description: "Update installed extensions to the version the Kubb registry pins. Pass ids to update only those, or --check to list the updates without installing.",
|
|
993
|
+
examples: [
|
|
994
|
+
"kubb update",
|
|
995
|
+
"kubb update --check",
|
|
996
|
+
"kubb update plugin-zod plugin-ts --yes"
|
|
997
|
+
].join("\n"),
|
|
998
|
+
args: {
|
|
999
|
+
ids: {
|
|
1000
|
+
type: "positional",
|
|
1001
|
+
description: "Registry ids to update, all installed extensions when omitted",
|
|
1002
|
+
multiple: true
|
|
1003
|
+
},
|
|
1004
|
+
check: {
|
|
1005
|
+
type: "boolean",
|
|
1006
|
+
description: "List the available updates without installing them",
|
|
1007
|
+
default: false
|
|
1008
|
+
},
|
|
1009
|
+
...yesArg
|
|
1010
|
+
},
|
|
1011
|
+
run: ({ values }) => run$1({
|
|
1012
|
+
ids: values.ids ?? [],
|
|
1013
|
+
check: values.check,
|
|
1014
|
+
yes: values.yes
|
|
1015
|
+
})
|
|
1016
|
+
});
|
|
1017
|
+
//#endregion
|
|
527
1018
|
//#region src/index.ts
|
|
528
1019
|
/** Flags that short-circuit execution (help and version). The telemetry notice is suppressed for these. */
|
|
529
1020
|
const QUIET_FLAGS = /* @__PURE__ */ new Set([
|
|
@@ -541,19 +1032,19 @@ async function run(argv = process.argv.slice(2)) {
|
|
|
541
1032
|
const args = routeStudioFlags(resolveDeprecatedFlags(argv));
|
|
542
1033
|
const isQuietFlag = args.some((arg) => QUIET_FLAGS.has(arg));
|
|
543
1034
|
if (!isDisabled() && !isQuietFlag) console.error(`${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`);
|
|
544
|
-
await cli(args, command$
|
|
1035
|
+
await cli(args, command$13, {
|
|
545
1036
|
name: "kubb",
|
|
546
1037
|
version,
|
|
547
1038
|
description: "Generate code from an OpenAPI specification, manage Kubb extensions, or connect the project to Kubb Studio.",
|
|
548
1039
|
subCommands: {
|
|
549
|
-
generate: command$
|
|
550
|
-
init: command$
|
|
551
|
-
validate: command,
|
|
552
|
-
mcp: command$
|
|
553
|
-
studio: command$
|
|
554
|
-
add: command$
|
|
555
|
-
update: command
|
|
556
|
-
list: command$
|
|
1040
|
+
generate: command$13,
|
|
1041
|
+
init: command$2,
|
|
1042
|
+
validate: command$4,
|
|
1043
|
+
mcp: command$12,
|
|
1044
|
+
studio: command$5,
|
|
1045
|
+
add: command$3,
|
|
1046
|
+
update: command,
|
|
1047
|
+
list: command$1
|
|
557
1048
|
},
|
|
558
1049
|
fallbackToEntry: true,
|
|
559
1050
|
strict: true,
|