@kubb/cli 5.8.4 → 5.9.1
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/README.md +9 -3
- package/bin/kubb.js +1 -1
- package/dist/{Telemetry-DKccmt8g.cjs → Telemetry-BSuUeat7.cjs} +26 -66
- package/dist/Telemetry-BSuUeat7.cjs.map +1 -0
- package/dist/{Telemetry-Ci7sRy6A.js → Telemetry-DxSvCR-R.js} +26 -66
- package/dist/Telemetry-DxSvCR-R.js.map +1 -0
- package/dist/{background-B7VAPM7b.cjs → background-Bztbu76P.cjs} +2 -2
- package/dist/{background-B7VAPM7b.cjs.map → background-Bztbu76P.cjs.map} +1 -1
- package/dist/background-C5ADaF5O.js +1 -0
- package/dist/{background-CnSPyAn7.js → background-DErMBYPd.js} +2 -2
- package/dist/{background-CnSPyAn7.js.map → background-DErMBYPd.js.map} +1 -1
- package/dist/{commands-Cgmj9PsM.js → commands-BATSnmRI.js} +3 -3
- package/dist/{commands-Cgmj9PsM.js.map → commands-BATSnmRI.js.map} +1 -1
- package/dist/{commands-CLUcjHHU.cjs → commands-wWv2IyJV.cjs} +3 -3
- package/dist/{commands-CLUcjHHU.cjs.map → commands-wWv2IyJV.cjs.map} +1 -1
- package/dist/{config-DAdYwK_D.js → config-B6UIKcl1.js} +13 -16
- package/dist/config-B6UIKcl1.js.map +1 -0
- package/dist/{config-CRBZcWwg.cjs → config-Bo9ro7vg.cjs} +13 -16
- package/dist/config-Bo9ro7vg.cjs.map +1 -0
- package/dist/constants-Cii4HX64.js +12 -0
- package/dist/constants-Cii4HX64.js.map +1 -0
- package/dist/constants-Df449N47.cjs +29 -0
- package/dist/constants-Df449N47.cjs.map +1 -0
- package/dist/index.cjs +20 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +20 -28
- package/dist/index.js.map +1 -1
- package/dist/{output-CWupdozw.cjs → output-BnK0scpX.cjs} +10 -15
- package/dist/output-BnK0scpX.cjs.map +1 -0
- package/dist/{output-B9Yw7vL0.js → output-qFt4vV7K.js} +10 -15
- package/dist/output-qFt4vV7K.js.map +1 -0
- package/dist/{reporters-C5HAypFq.cjs → reporters-B4rZOlo8.cjs} +2 -2
- package/dist/{reporters-C5HAypFq.cjs.map → reporters-B4rZOlo8.cjs.map} +1 -1
- package/dist/{reporters-CNZQUlXY.js → reporters-H21Jvrff.js} +2 -2
- package/dist/{reporters-CNZQUlXY.js.map → reporters-H21Jvrff.js.map} +1 -1
- package/dist/{run-VAkf24Cw.cjs → run-89YfZJuo.cjs} +3 -3
- package/dist/{run-VAkf24Cw.cjs.map → run-89YfZJuo.cjs.map} +1 -1
- package/dist/run-8HrdMihy.js +1 -0
- package/dist/{run-CMkKa1rU.cjs → run-BN1-GpZI.cjs} +10 -22
- package/dist/run-BN1-GpZI.cjs.map +1 -0
- package/dist/{run-CQKXIa2D.cjs → run-BOmuzVe1.cjs} +2 -2
- package/dist/{run-CQKXIa2D.cjs.map → run-BOmuzVe1.cjs.map} +1 -1
- package/dist/{run-Ey756UCd.js → run-BYff_byB.js} +2 -2
- package/dist/{run-Ey756UCd.js.map → run-BYff_byB.js.map} +1 -1
- package/dist/{run-99Go42ib.js → run-CFK9DYis.js} +2 -2
- package/dist/{run-99Go42ib.js.map → run-CFK9DYis.js.map} +1 -1
- package/dist/{run-USNnlQcA.js → run-CJHsZZB8.js} +41 -49
- package/dist/run-CJHsZZB8.js.map +1 -0
- package/dist/{run-yb2R1vt0.js → run-Ca_OX3WZ.js} +6 -7
- package/dist/run-Ca_OX3WZ.js.map +1 -0
- package/dist/{run-C5P5_H0R.cjs → run-Ct6kzKpg.cjs} +6 -6
- package/dist/run-Ct6kzKpg.cjs.map +1 -0
- package/dist/{run-BnCdDjXH.cjs → run-DAjjmDdw.cjs} +7 -7
- package/dist/{run-BnCdDjXH.cjs.map → run-DAjjmDdw.cjs.map} +1 -1
- package/dist/{run-E11sqsk0.cjs → run-DL2wLwBZ.cjs} +41 -49
- package/dist/run-DL2wLwBZ.cjs.map +1 -0
- package/dist/{run-DRR30f0e.js → run-Dej-hm91.js} +3 -3
- package/dist/{run-DRR30f0e.js.map → run-Dej-hm91.js.map} +1 -1
- package/dist/{run-9oIapU5y.js → run-DlQDj_SV.js} +7 -7
- package/dist/{run-9oIapU5y.js.map → run-DlQDj_SV.js.map} +1 -1
- package/dist/{run-ClLBHOpl.cjs → run-Dm7nOUUF.cjs} +3 -5
- package/dist/run-Dm7nOUUF.cjs.map +1 -0
- package/dist/{run-CnBJroZW.cjs → run-DpAMfkm5.cjs} +2 -2
- package/dist/{run-CnBJroZW.cjs.map → run-DpAMfkm5.cjs.map} +1 -1
- package/dist/{run-IkpyXtut.js → run-DssKB_1f.js} +3 -5
- package/dist/run-DssKB_1f.js.map +1 -0
- package/dist/{run-BSQJrncc.js → run-N37yeEmo.js} +10 -22
- package/dist/run-N37yeEmo.js.map +1 -0
- package/dist/{snapshot-CXplfGXC.cjs → snapshot-B27W-HME.cjs} +5 -5
- package/dist/{snapshot-CXplfGXC.cjs.map → snapshot-B27W-HME.cjs.map} +1 -1
- package/dist/{snapshot-2q9d9Dqg.js → snapshot-Ctv0_Xwv.js} +5 -5
- package/dist/{snapshot-2q9d9Dqg.js.map → snapshot-Ctv0_Xwv.js.map} +1 -1
- package/dist/studioWorker.js +2 -2
- package/dist/{utils-Dhx5PMpD.js → utils-BHW8kA8P.js} +11 -8
- package/dist/utils-BHW8kA8P.js.map +1 -0
- package/dist/{utils-ZcCFqERz.cjs → utils-BzQ46pgd.cjs} +16 -13
- package/dist/utils-BzQ46pgd.cjs.map +1 -0
- package/package.json +7 -7
- package/dist/Telemetry-Ci7sRy6A.js.map +0 -1
- package/dist/Telemetry-DKccmt8g.cjs.map +0 -1
- package/dist/background-CATamspG.js +0 -1
- package/dist/config-CRBZcWwg.cjs.map +0 -1
- package/dist/config-DAdYwK_D.js.map +0 -1
- package/dist/constants-CdxpgX3_.cjs +0 -115
- package/dist/constants-CdxpgX3_.cjs.map +0 -1
- package/dist/constants-DHRspBTo.js +0 -92
- package/dist/constants-DHRspBTo.js.map +0 -1
- package/dist/output-B9Yw7vL0.js.map +0 -1
- package/dist/output-CWupdozw.cjs.map +0 -1
- package/dist/run-BSQJrncc.js.map +0 -1
- package/dist/run-C5P5_H0R.cjs.map +0 -1
- package/dist/run-CMkKa1rU.cjs.map +0 -1
- package/dist/run-ClLBHOpl.cjs.map +0 -1
- package/dist/run-E11sqsk0.cjs.map +0 -1
- package/dist/run-IkpyXtut.js.map +0 -1
- package/dist/run-USNnlQcA.js.map +0 -1
- package/dist/run-yb2R1vt0.js.map +0 -1
- package/dist/utils-Dhx5PMpD.js.map +0 -1
- package/dist/utils-ZcCFqERz.cjs.map +0 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
const require_agent = require("./agent-DElUuYuy.cjs");
|
|
2
|
-
const require_constants = require("./constants-
|
|
3
|
-
const require_output = require("./output-
|
|
4
|
-
const
|
|
2
|
+
const require_constants = require("./constants-Df449N47.cjs");
|
|
3
|
+
const require_output = require("./output-BnK0scpX.cjs");
|
|
4
|
+
const require_registry = require("./registry-DER9aRyg.cjs");
|
|
5
|
+
const require_utils = require("./utils-BzQ46pgd.cjs");
|
|
6
|
+
const require_run = require("./run-Ct6kzKpg.cjs");
|
|
5
7
|
let node_util = require("node:util");
|
|
6
8
|
let node_process = require("node:process");
|
|
7
9
|
node_process = require_agent.__toESM(node_process, 1);
|
|
@@ -12,19 +14,8 @@ _clack_prompts = require_agent.__toESM(_clack_prompts, 1);
|
|
|
12
14
|
let node_fs = require("node:fs");
|
|
13
15
|
node_fs = require_agent.__toESM(node_fs, 1);
|
|
14
16
|
//#region ../../internals/shared/src/init.ts
|
|
15
|
-
/**
|
|
16
|
-
* Resolves a comma-separated plugin flag (e.g. `--plugins plugin-ts,plugin-zod`) into the
|
|
17
|
-
* matching known plugin options. Unrecognized names are dropped, and a missing flag yields
|
|
18
|
-
* an empty list.
|
|
19
|
-
*/
|
|
20
|
-
function resolvePlugins(pluginsFlag) {
|
|
21
|
-
if (!pluginsFlag) return [];
|
|
22
|
-
const requested = pluginsFlag.split(",").map((value) => value.trim()).filter(Boolean);
|
|
23
|
-
return require_constants.availablePlugins.filter((plugin) => requested.includes(plugin.value));
|
|
24
|
-
}
|
|
25
17
|
function generateConfigFile({ selectedPlugins, inputPath, outputPath }) {
|
|
26
|
-
return `import { defineConfig } from 'kubb/config'
|
|
27
|
-
${selectedPlugins.map((plugin) => `import { ${plugin.importName} } from '${plugin.packageName}'`).join("\n")}
|
|
18
|
+
return `${[`import { defineConfig } from 'kubb/config'`, ...selectedPlugins.map((plugin) => `import { ${plugin.importName} } from '${plugin.packageName}'`)].join("\n")}
|
|
28
19
|
|
|
29
20
|
export default defineConfig({
|
|
30
21
|
input: '${inputPath}',
|
|
@@ -38,18 +29,6 @@ ${selectedPlugins.map((plugin) => ` ${plugin.importName}(),`).join("\n")}
|
|
|
38
29
|
})
|
|
39
30
|
`;
|
|
40
31
|
}
|
|
41
|
-
/**
|
|
42
|
-
* Turns package names into install specifiers for the wizard.
|
|
43
|
-
*
|
|
44
|
-
* `kubb` is pinned to the exact version of the running CLI, since both ship from the same release
|
|
45
|
-
* and resolving `kubb@beta` separately can land on a different version than the CLI doing the
|
|
46
|
-
* scaffolding. Plugins release from their own repo on their own cadence, so they follow the
|
|
47
|
-
* release channel of the CLI through its dist-tag.
|
|
48
|
-
*/
|
|
49
|
-
function resolveInstallVersions({ packages, version }) {
|
|
50
|
-
const tag = version.match(/-([a-z]+)/)?.[1] ?? "latest";
|
|
51
|
-
return packages.map((name) => name === "kubb" ? `${name}@${version}` : `${name}@${tag}`);
|
|
52
|
-
}
|
|
53
32
|
//#endregion
|
|
54
33
|
//#region src/runners/init/run.ts
|
|
55
34
|
function cancelAndExit(message = "Operation canceled.") {
|
|
@@ -82,7 +61,9 @@ async function run({ yes, version, input: inputFlag, output: outputFlag, plugins
|
|
|
82
61
|
return result;
|
|
83
62
|
}
|
|
84
63
|
try {
|
|
85
|
-
|
|
64
|
+
const plugins = (await require_registry.fetchRegistryIndex({ registry: require_registry.registryUrl() })).filter((entry) => entry.kind === "plugin" && !require_registry.incompatibility(entry.manifest));
|
|
65
|
+
const byId = new Map(plugins.map((entry) => [entry.id, entry]));
|
|
66
|
+
if (!node_fs.default.existsSync(node_path.default.join(cwd, "package.json"))) {
|
|
86
67
|
if (!yes) {
|
|
87
68
|
const shouldInit = await _clack_prompts.confirm({
|
|
88
69
|
message: "No package.json found. Would you like to create one?",
|
|
@@ -97,7 +78,7 @@ async function run({ yes, version, input: inputFlag, output: outputFlag, plugins
|
|
|
97
78
|
spinner.stop(`Created package.json with ${packageManager.name}`);
|
|
98
79
|
}
|
|
99
80
|
const packageManager = require_utils.detectPackageManager(cwd);
|
|
100
|
-
|
|
81
|
+
require_output.logInfo(`Detected package manager: ${(0, node_util.styleText)("cyan", packageManager.name)}`);
|
|
101
82
|
const inputPath = await resolveOrPrompt(inputFlag, require_constants.initDefaults.inputPath, "Using input path", () => _clack_prompts.text({
|
|
102
83
|
message: "Where is your OpenAPI specification located?",
|
|
103
84
|
placeholder: require_constants.initDefaults.inputPath,
|
|
@@ -114,17 +95,16 @@ async function run({ yes, version, input: inputFlag, output: outputFlag, plugins
|
|
|
114
95
|
if (!value) return "Output path is required";
|
|
115
96
|
}
|
|
116
97
|
}));
|
|
117
|
-
const defaultPlugins = require_constants.
|
|
118
|
-
const pluginLabel = (
|
|
98
|
+
const defaultPlugins = require_constants.initDefaults.plugins.flatMap((slug) => byId.get(require_registry.toRegistryId(slug)) ?? []);
|
|
99
|
+
const pluginLabel = (entries) => (0, node_util.styleText)("cyan", entries.map((entry) => entry.manifest.displayName).join(", "));
|
|
119
100
|
const selectedPlugins = await (async () => {
|
|
120
101
|
if (pluginsFlag) {
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return plugins;
|
|
102
|
+
const ids = pluginsFlag.split(",").map((id) => id.trim()).filter(Boolean);
|
|
103
|
+
const unknown = ids.filter((id) => !byId.has(require_registry.toRegistryId(id)));
|
|
104
|
+
if (unknown.length) throw new Error(`Not in the Kubb registry: ${unknown.join(", ")}. Browse the plugins at https://kubb.dev/extensions.`);
|
|
105
|
+
const entries = ids.map((id) => byId.get(require_registry.toRegistryId(id)));
|
|
106
|
+
require_output.logInfo(`Using plugins: ${pluginLabel(entries)}`);
|
|
107
|
+
return entries;
|
|
128
108
|
}
|
|
129
109
|
if (yes) {
|
|
130
110
|
require_output.logInfo(`Using plugins: ${pluginLabel(defaultPlugins)}`);
|
|
@@ -132,21 +112,23 @@ async function run({ yes, version, input: inputFlag, output: outputFlag, plugins
|
|
|
132
112
|
}
|
|
133
113
|
const values = await _clack_prompts.multiselect({
|
|
134
114
|
message: "Select plugins to use:",
|
|
135
|
-
options:
|
|
136
|
-
value,
|
|
137
|
-
label,
|
|
138
|
-
hint
|
|
115
|
+
options: plugins.map(({ id, manifest }) => ({
|
|
116
|
+
value: id,
|
|
117
|
+
label: manifest.displayName,
|
|
118
|
+
hint: manifest.category
|
|
139
119
|
})),
|
|
140
|
-
initialValues:
|
|
120
|
+
initialValues: defaultPlugins.map((entry) => entry.id),
|
|
141
121
|
required: true
|
|
142
122
|
});
|
|
143
123
|
if (_clack_prompts.isCancel(values)) cancelAndExit();
|
|
144
|
-
return
|
|
124
|
+
return plugins.filter((entry) => values.includes(entry.id));
|
|
145
125
|
})();
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
126
|
+
const missing = require_utils.missingPluginDependencies({
|
|
127
|
+
selected: selectedPlugins.map((entry) => entry.manifest.name),
|
|
128
|
+
manifests: selectedPlugins.map((entry) => entry.manifest)
|
|
149
129
|
});
|
|
130
|
+
if (missing.length) throw new Error(`${missing.join("\n")}\nAdd the missing plugins and run kubb init again.`);
|
|
131
|
+
const packagesToInstall = [`${require_constants.KUBB_PACKAGE_NAME}@${version}`, ...selectedPlugins.map((entry) => require_registry.installSpec(entry.artifact))];
|
|
150
132
|
const spinner = require_output.createSpinner();
|
|
151
133
|
spinner.start(`Installing ${packagesToInstall.length} packages with ${packageManager.name}`);
|
|
152
134
|
try {
|
|
@@ -159,7 +141,7 @@ async function run({ yes, version, input: inputFlag, output: outputFlag, plugins
|
|
|
159
141
|
const configSpinner = require_output.createSpinner();
|
|
160
142
|
configSpinner.start(`Creating ${require_constants.KUBB_CONFIG_FILENAME}`);
|
|
161
143
|
const configContent = generateConfigFile({
|
|
162
|
-
selectedPlugins,
|
|
144
|
+
selectedPlugins: [],
|
|
163
145
|
inputPath,
|
|
164
146
|
outputPath
|
|
165
147
|
});
|
|
@@ -176,6 +158,16 @@ async function run({ yes, version, input: inputFlag, output: outputFlag, plugins
|
|
|
176
158
|
configSpinner.start(`Overwriting ${require_constants.KUBB_CONFIG_FILENAME}`);
|
|
177
159
|
}
|
|
178
160
|
await dryRun.run(() => node_fs.default.promises.writeFile(configPath, configContent, "utf-8"), { message: `write ${require_constants.KUBB_CONFIG_FILENAME}` });
|
|
161
|
+
for (const entry of selectedPlugins) {
|
|
162
|
+
const reason = await dryRun.run(() => require_run.addToConfig({
|
|
163
|
+
detail: entry,
|
|
164
|
+
configFile: configPath
|
|
165
|
+
}), {
|
|
166
|
+
message: `add ${entry.manifest.export}() to ${require_constants.KUBB_CONFIG_FILENAME}`,
|
|
167
|
+
resolve: () => void 0
|
|
168
|
+
});
|
|
169
|
+
if (reason) throw new Error(`Could not add ${entry.manifest.export}() to ${require_constants.KUBB_CONFIG_FILENAME}: ${reason}`);
|
|
170
|
+
}
|
|
179
171
|
configSpinner.stop(`Created ${require_constants.KUBB_CONFIG_FILENAME}`);
|
|
180
172
|
require_output.logOutro((0, node_util.styleText)("green", "✓ All set!") + "\n\n" + (0, node_util.styleText)("dim", "Next steps:") + "\n" + (0, node_util.styleText)("cyan", ` 1. Make sure your OpenAPI spec is at: ${inputPath}`) + "\n" + (0, node_util.styleText)("cyan", " 2. Generate code with: npx kubb generate") + "\n" + (0, node_util.styleText)("cyan", ` 3. Find generated files in: ${outputPath}`) + "\n\n" + (0, node_util.styleText)("dim", `Using ${packageManager.name} • Kubb v${version}`));
|
|
181
173
|
} catch (error) {
|
|
@@ -187,4 +179,4 @@ async function run({ yes, version, input: inputFlag, output: outputFlag, plugins
|
|
|
187
179
|
//#endregion
|
|
188
180
|
exports.run = run;
|
|
189
181
|
|
|
190
|
-
//# sourceMappingURL=run-
|
|
182
|
+
//# sourceMappingURL=run-DL2wLwBZ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-DL2wLwBZ.cjs","names":["process","styleText","clack","fetchRegistryIndex","registryUrl","incompatibility","fs","path","detectPackageManager","createSpinner","initPackageJson","initDefaults","toRegistryId","missingPluginDependencies","KUBB_PACKAGE_NAME","installSpec","installPackages","KUBB_CONFIG_FILENAME","addToConfig"],"sources":["../../../internals/shared/src/init.ts","../src/runners/init/run.ts"],"sourcesContent":["import { availablePlugins, type PluginOption } from './constants.ts'\n\n/**\n * Resolves a comma-separated plugin flag (e.g. `--plugins plugin-ts,plugin-zod`) into the\n * matching known plugin options. Unrecognized names are dropped, and a missing flag yields\n * an empty list.\n */\nexport function resolvePlugins(pluginsFlag: string | undefined): Array<PluginOption> {\n if (!pluginsFlag) {\n return []\n }\n const requested = pluginsFlag\n .split(',')\n .map((value) => value.trim())\n .filter(Boolean)\n return availablePlugins.filter((plugin) => requested.includes(plugin.value))\n}\n\nexport function generateConfigFile({\n selectedPlugins,\n inputPath,\n outputPath,\n}: {\n selectedPlugins: Array<PluginOption>\n inputPath: string\n outputPath: string\n}): string {\n const imports = [\n `import { defineConfig } from 'kubb/config'`,\n ...selectedPlugins.map((plugin) => `import { ${plugin.importName} } from '${plugin.packageName}'`),\n ].join('\\n')\n\n const pluginConfigs = selectedPlugins.map((plugin) => ` ${plugin.importName}(),`).join('\\n')\n\n return `${imports}\n\nexport default defineConfig({\n input: '${inputPath}',\n output: {\n path: '${outputPath}',\n clean: true,\n },\n plugins: [\n${pluginConfigs}\n ],\n})\n`\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport * as clack from '@clack/prompts'\nimport type { DryRunExtension } from '@gunshi/plugin-dryrun'\nimport { generateConfigFile, initDefaults, KUBB_CONFIG_FILENAME, KUBB_PACKAGE_NAME } from '@internals/shared'\nimport type { RegistryEntry } from '@kubb/core'\nimport { createSpinner, logError, logInfo, logIntro, logOutro } from '../../loggers/output.ts'\nimport { addToConfig } from '../add/run.ts'\nimport { fetchRegistryIndex, incompatibility, installSpec, registryUrl, toRegistryId } from '../../utils/registry.ts'\nimport { detectPackageManager, initPackageJson, installPackages, missingPluginDependencies } from './utils.ts'\n\nfunction cancelAndExit(message = 'Operation canceled.'): never {\n clack.cancel(message)\n process.exit(0)\n}\n\ntype InitOptions = {\n /**\n * When `true`, skips all interactive prompts and uses default values.\n */\n yes: boolean\n /**\n * Current `@kubb/cli` version string, shown in the closing outro.\n */\n version: string\n /**\n * Input path flag value from `--input`. When provided, skips the input prompt.\n */\n input?: string\n /**\n * Output directory flag value from `--output`. When provided, skips the output prompt.\n */\n output?: string\n /**\n * Comma-separated plugin list from `--plugins`, e.g. `'plugin-ts,plugin-zod'`. When provided, skips the plugin selection prompt.\n */\n plugins?: string\n /**\n * Dry-run extension from `@gunshi/plugin-dryrun`. When enabled, package installation and the\n * config file write are skipped.\n */\n dryRun: DryRunExtension\n}\n\n/**\n * Runs the interactive Kubb scaffolding wizard.\n * Detects the package manager, prompts for input/output paths and plugins, installs packages, and writes `kubb.config.ts`.\n * Pass `yes: true` to skip all prompts and use defaults.\n */\nexport async function run({ yes, version, input: inputFlag, output: outputFlag, plugins: pluginsFlag, dryRun }: InitOptions): Promise<void> {\n const cwd = process.cwd()\n\n logIntro({ title: styleText('bgCyan', styleText('black', ' Kubb Init ')) })\n\n /**\n * Returns `flag` when provided, the `defaultValue` when `yes` is set,\n * or calls `prompt()` for interactive input. Exits on cancellation.\n */\n async function resolveOrPrompt<T>(flag: T | undefined, defaultValue: T, logLabel: string, prompt: () => Promise<NoInfer<T> | symbol>): Promise<T> {\n if (flag !== undefined) {\n logInfo(`${logLabel}: ${styleText('cyan', String(flag))}`)\n return flag\n }\n if (yes) {\n logInfo(`${logLabel}: ${styleText('cyan', String(defaultValue))}`)\n return defaultValue\n }\n const result = await prompt()\n if (clack.isCancel(result)) cancelAndExit()\n return result as T\n }\n\n try {\n // The plugins come from the Kubb registry, like `kubb add`, so read it before changing anything\n const plugins = (await fetchRegistryIndex({ registry: registryUrl() })).filter((entry) => entry.kind === 'plugin' && !incompatibility(entry.manifest))\n const byId = new Map(plugins.map((entry) => [entry.id, entry]))\n\n // Check/create package.json, detect package manager once after the block\n if (!fs.existsSync(path.join(cwd, 'package.json'))) {\n if (!yes) {\n const shouldInit = await clack.confirm({\n message: 'No package.json found. Would you like to create one?',\n initialValue: true,\n })\n\n if (clack.isCancel(shouldInit) || !shouldInit) {\n cancelAndExit()\n }\n }\n\n const packageManager = detectPackageManager(cwd)\n const spinner = createSpinner()\n spinner.start(`Initializing package.json with ${packageManager.name}`)\n await initPackageJson(cwd, packageManager)\n spinner.stop(`Created package.json with ${packageManager.name}`)\n }\n\n const packageManager = detectPackageManager(cwd)\n logInfo(`Detected package manager: ${styleText('cyan', packageManager.name)}`)\n\n // Prompt for OpenAPI spec path\n const inputPath = await resolveOrPrompt(inputFlag, initDefaults.inputPath, 'Using input path', () =>\n clack.text({\n message: 'Where is your OpenAPI specification located?',\n placeholder: initDefaults.inputPath,\n defaultValue: initDefaults.inputPath,\n validate: (value) => {\n if (!value) return 'Input path is required'\n },\n }),\n )\n\n // Prompt for output directory\n const outputPath = await resolveOrPrompt(outputFlag, initDefaults.outputPath, 'Using output path', () =>\n clack.text({\n message: 'Where should the generated files be output?',\n placeholder: initDefaults.outputPath,\n defaultValue: initDefaults.outputPath,\n validate: (value) => {\n if (!value) return 'Output path is required'\n },\n }),\n )\n\n // Plugin selection\n const defaultPlugins = initDefaults.plugins.flatMap((slug) => byId.get(toRegistryId(slug)) ?? [])\n const pluginLabel = (entries: Array<RegistryEntry>) => styleText('cyan', entries.map((entry) => entry.manifest.displayName).join(', '))\n\n const selectedPlugins: Array<RegistryEntry> = await (async () => {\n if (pluginsFlag) {\n const ids = pluginsFlag\n .split(',')\n .map((id) => id.trim())\n .filter(Boolean)\n const unknown = ids.filter((id) => !byId.has(toRegistryId(id)))\n if (unknown.length) throw new Error(`Not in the Kubb registry: ${unknown.join(', ')}. Browse the plugins at https://kubb.dev/extensions.`)\n const entries = ids.map((id) => byId.get(toRegistryId(id))!)\n logInfo(`Using plugins: ${pluginLabel(entries)}`)\n return entries\n }\n if (yes) {\n logInfo(`Using plugins: ${pluginLabel(defaultPlugins)}`)\n return defaultPlugins\n }\n const values = await clack.multiselect({\n message: 'Select plugins to use:',\n options: plugins.map(({ id, manifest }) => ({ value: id, label: manifest.displayName, hint: manifest.category })),\n initialValues: defaultPlugins.map((entry) => entry.id),\n required: true,\n })\n if (clack.isCancel(values)) cancelAndExit()\n return plugins.filter((entry) => (values as Array<string>).includes(entry.id))\n })()\n\n // Check the selection against the plugins' manifests before installing anything\n const missing = missingPluginDependencies({\n selected: selectedPlugins.map((entry) => entry.manifest.name),\n manifests: selectedPlugins.map((entry) => entry.manifest),\n })\n if (missing.length) {\n throw new Error(`${missing.join('\\n')}\\nAdd the missing plugins and run kubb init again.`)\n }\n\n // Install `kubb` at the running CLI's version and each plugin at the version the registry pins\n const packagesToInstall = [`${KUBB_PACKAGE_NAME}@${version}`, ...selectedPlugins.map((entry) => installSpec(entry.artifact))]\n\n const spinner = createSpinner()\n spinner.start(`Installing ${packagesToInstall.length} packages with ${packageManager.name}`)\n\n try {\n await dryRun.run(() => installPackages(packagesToInstall, packageManager, cwd), {\n message: `install ${packagesToInstall.length} packages with ${packageManager.name}`,\n })\n spinner.stop(`Installed ${packagesToInstall.length} packages`)\n } catch (error) {\n spinner.stop('Installation failed')\n throw error\n }\n\n // Generate config file\n const configSpinner = createSpinner()\n configSpinner.start(`Creating ${KUBB_CONFIG_FILENAME}`)\n\n const configContent = generateConfigFile({ selectedPlugins: [], inputPath, outputPath })\n const configPath = path.join(cwd, KUBB_CONFIG_FILENAME)\n\n if (fs.existsSync(configPath)) {\n configSpinner.stop(`${KUBB_CONFIG_FILENAME} already exists`)\n\n if (!yes) {\n const shouldOverwrite = await clack.confirm({\n message: `${KUBB_CONFIG_FILENAME} already exists. Overwrite?`,\n initialValue: false,\n })\n\n if (clack.isCancel(shouldOverwrite) || !shouldOverwrite) {\n cancelAndExit('Keeping existing configuration. Packages have been installed.')\n }\n }\n\n configSpinner.start(`Overwriting ${KUBB_CONFIG_FILENAME}`)\n }\n\n await dryRun.run(() => fs.promises.writeFile(configPath, configContent, 'utf-8'), { message: `write ${KUBB_CONFIG_FILENAME}` })\n\n // Add each plugin the way `kubb add` does\n for (const entry of selectedPlugins) {\n const reason = await dryRun.run(() => addToConfig({ detail: entry, configFile: configPath }), {\n message: `add ${entry.manifest.export}() to ${KUBB_CONFIG_FILENAME}`,\n resolve: () => undefined,\n })\n if (reason) throw new Error(`Could not add ${entry.manifest.export}() to ${KUBB_CONFIG_FILENAME}: ${reason}`)\n }\n\n configSpinner.stop(`Created ${KUBB_CONFIG_FILENAME}`)\n\n logOutro(\n styleText('green', '✓ All set!') +\n '\\n\\n' +\n styleText('dim', 'Next steps:') +\n '\\n' +\n styleText('cyan', ` 1. Make sure your OpenAPI spec is at: ${inputPath}`) +\n '\\n' +\n styleText('cyan', ' 2. Generate code with: npx kubb generate') +\n '\\n' +\n styleText('cyan', ` 3. Find generated files in: ${outputPath}`) +\n '\\n\\n' +\n styleText('dim', `Using ${packageManager.name} • Kubb v${version}`),\n )\n } catch (error) {\n logError(styleText('red', 'An error occurred during initialization'))\n if (error instanceof Error) {\n logError(error.message)\n }\n process.exit(1)\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "./rolldown-runtime-CRm0XQPb.js";
|
|
2
2
|
import { t as getErrorMessage } from "./errors-DmC83ALX.js";
|
|
3
|
-
import { a as logInfo, d as logWarn, i as logError, l as logStep, o as logIntro, r as logBlock, s as logOutro } from "./output-
|
|
3
|
+
import { a as logInfo, d as logWarn, i as logError, l as logStep, o as logIntro, r as logBlock, s as logOutro } from "./output-qFt4vV7K.js";
|
|
4
4
|
import { a as isOutdated, i as installSpec, n as fetchRegistryIndex, o as registryUrl, r as incompatibility, s as toRegistryId } from "./registry-B7BvdrGE.js";
|
|
5
|
-
import {
|
|
5
|
+
import { r as installPackages, t as detectPackageManager } from "./utils-BHW8kA8P.js";
|
|
6
6
|
import { styleText } from "node:util";
|
|
7
7
|
import process from "node:process";
|
|
8
8
|
import { readInstalledPackages } from "@kubb/core";
|
|
@@ -62,4 +62,4 @@ async function run({ ids, check, yes }) {
|
|
|
62
62
|
//#endregion
|
|
63
63
|
export { run };
|
|
64
64
|
|
|
65
|
-
//# sourceMappingURL=run-
|
|
65
|
+
//# sourceMappingURL=run-Dej-hm91.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-
|
|
1
|
+
{"version":3,"file":"run-Dej-hm91.js","names":[],"sources":["../src/runners/update/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport * as clack from '@clack/prompts'\nimport { getErrorMessage } from '@internals/utils'\nimport { readInstalledPackages } from '@kubb/core'\nimport { logBlock, logError, logInfo, logIntro, logOutro, logStep, logWarn } from '../../loggers/output.ts'\nimport { fetchRegistryIndex, incompatibility, installSpec, isOutdated, registryUrl, toRegistryId } from '../../utils/registry.ts'\nimport { detectPackageManager, installPackages } from '../init/utils.ts'\n\nexport type UpdateOptions = {\n /**\n * Registry ids to update. Empty updates every installed extension the registry lists.\n */\n ids: Array<string>\n check: boolean\n yes: boolean\n}\n\n/**\n * Moves installed extensions to the version the registry pins. Lists the proposals, asks, then\n * installs them. With `check`, only lists them.\n */\nexport async function run({ ids, check, yes }: UpdateOptions): Promise<void> {\n const cwd = process.cwd()\n logIntro({ title: styleText('bgCyan', styleText('black', ' Kubb Update ')) })\n\n try {\n const wanted = new Set(ids.map(toRegistryId))\n const [entries, installed] = await Promise.all([fetchRegistryIndex({ registry: registryUrl() }), readInstalledPackages({ root: cwd })])\n const versions = new Map(installed.map((item) => [item.package, item.version]))\n\n const tracked = entries.filter((entry) => versions.has(entry.artifact.package) && (!wanted.size || wanted.has(entry.id)))\n for (const id of wanted) {\n if (!tracked.some((entry) => entry.id === id)) logWarn(`${id} is not installed, or not in the registry.`)\n }\n\n const proposals = tracked.filter((entry) => {\n if (!isOutdated({ installed: versions.get(entry.artifact.package), latest: entry.artifact.version })) return false\n const problem = incompatibility(entry.manifest)\n if (problem) logWarn(`Skipped ${entry.id}: ${problem}`)\n return !problem\n })\n\n if (!proposals.length) {\n logOutro(ids.length ? `No updates for ${ids.join(', ')}.` : 'Every installed extension is up to date.')\n return\n }\n\n const plural = proposals.length === 1 ? '' : 's'\n logBlock(\n proposals.map(({ artifact }) => `${artifact.package} ${versions.get(artifact.package) ?? 'not installed'} -> ${styleText('green', artifact.version)}`),\n )\n\n if (check) {\n logOutro(`${proposals.length} update${plural} available. Run \\`kubb update\\` to install.`)\n return\n }\n\n const confirmed = yes || (await clack.confirm({ message: `Install ${proposals.length} update${plural}?`, initialValue: true }))\n if (clack.isCancel(confirmed) || !confirmed) {\n clack.cancel('Operation canceled.')\n return\n }\n\n const packageManager = detectPackageManager(cwd)\n const specs = proposals.map(({ artifact }) => installSpec(artifact))\n logStep(`Installing ${specs.join(', ')} with ${packageManager.name}`)\n await installPackages(specs, packageManager, cwd)\n\n logInfo(`Updated ${specs.length} extension${plural}`)\n logOutro(styleText('green', 'Done'))\n } catch (error) {\n logError(getErrorMessage(error))\n process.exitCode = 1\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAsBA,eAAsB,IAAI,EAAE,KAAK,OAAO,OAAqC;CAC3E,MAAM,MAAM,QAAQ,IAAI;CACxB,SAAS,EAAE,OAAO,UAAU,UAAU,UAAU,SAAS,eAAe,CAAC,EAAE,CAAC;CAE5E,IAAI;EACF,MAAM,SAAS,IAAI,IAAI,IAAI,IAAI,YAAY,CAAC;EAC5C,MAAM,CAAC,SAAS,aAAa,MAAM,QAAQ,IAAI,CAAC,mBAAmB,EAAE,UAAU,YAAY,EAAE,CAAC,GAAG,sBAAsB,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC;EACtI,MAAM,WAAW,IAAI,IAAI,UAAU,KAAK,SAAS,CAAC,KAAK,SAAS,KAAK,OAAO,CAAC,CAAC;EAE9E,MAAM,UAAU,QAAQ,QAAQ,UAAU,SAAS,IAAI,MAAM,SAAS,OAAO,MAAM,CAAC,OAAO,QAAQ,OAAO,IAAI,MAAM,EAAE,EAAE;EACxH,KAAK,MAAM,MAAM,QACf,IAAI,CAAC,QAAQ,MAAM,UAAU,MAAM,OAAO,EAAE,GAAG,QAAQ,GAAG,GAAG,2CAA2C;EAG1G,MAAM,YAAY,QAAQ,QAAQ,UAAU;GAC1C,IAAI,CAAC,WAAW;IAAE,WAAW,SAAS,IAAI,MAAM,SAAS,OAAO;IAAG,QAAQ,MAAM,SAAS;GAAQ,CAAC,GAAG,OAAO;GAC7G,MAAM,UAAU,gBAAgB,MAAM,QAAQ;GAC9C,IAAI,SAAS,QAAQ,WAAW,MAAM,GAAG,IAAI,SAAS;GACtD,OAAO,CAAC;EACV,CAAC;EAED,IAAI,CAAC,UAAU,QAAQ;GACrB,SAAS,IAAI,SAAS,kBAAkB,IAAI,KAAK,IAAI,EAAE,KAAK,0CAA0C;GACtG;EACF;EAEA,MAAM,SAAS,UAAU,WAAW,IAAI,KAAK;EAC7C,SACE,UAAU,KAAK,EAAE,eAAe,GAAG,SAAS,QAAQ,IAAI,SAAS,IAAI,SAAS,OAAO,KAAK,gBAAgB,MAAM,UAAU,SAAS,SAAS,OAAO,GAAG,CACxJ;EAEA,IAAI,OAAO;GACT,SAAS,GAAG,UAAU,OAAO,SAAS,OAAO,4CAA4C;GACzF;EACF;EAEA,MAAM,YAAY,OAAQ,MAAM,MAAM,QAAQ;GAAE,SAAS,WAAW,UAAU,OAAO,SAAS,OAAO;GAAI,cAAc;EAAK,CAAC;EAC7H,IAAI,MAAM,SAAS,SAAS,KAAK,CAAC,WAAW;GAC3C,MAAM,OAAO,qBAAqB;GAClC;EACF;EAEA,MAAM,iBAAiB,qBAAqB,GAAG;EAC/C,MAAM,QAAQ,UAAU,KAAK,EAAE,eAAe,YAAY,QAAQ,CAAC;EACnE,QAAQ,cAAc,MAAM,KAAK,IAAI,EAAE,QAAQ,eAAe,MAAM;EACpE,MAAM,gBAAgB,OAAO,gBAAgB,GAAG;EAEhD,QAAQ,WAAW,MAAM,OAAO,YAAY,QAAQ;EACpD,SAAS,UAAU,SAAS,MAAM,CAAC;CACrC,SAAS,OAAO;EACd,SAAS,gBAAgB,KAAK,CAAC;EAC/B,QAAQ,WAAW;CACrB;AACF"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import "./rolldown-runtime-CRm0XQPb.js";
|
|
2
2
|
import { n as toError } from "./errors-DmC83ALX.js";
|
|
3
3
|
import { i as isCIEnvironment } from "./agent-BPIqnEl2.js";
|
|
4
|
-
import { n as trackRun, r as version } from "./Telemetry-
|
|
5
|
-
import { t as KUBB_CONFIG_FILENAME } from "./constants-
|
|
6
|
-
import { n as getConfigs } from "./config-
|
|
7
|
-
import { g as plainLogger, o as logIntro, p as canUseTTY, r as logBlock, s as logOutro, t as createSpinner, u as logTip } from "./output-
|
|
8
|
-
import { n as setupReporters } from "./reporters-
|
|
4
|
+
import { n as trackRun, r as version } from "./Telemetry-DxSvCR-R.js";
|
|
5
|
+
import { t as KUBB_CONFIG_FILENAME } from "./constants-Cii4HX64.js";
|
|
6
|
+
import { n as getConfigs } from "./config-B6UIKcl1.js";
|
|
7
|
+
import { g as plainLogger, o as logIntro, p as canUseTTY, r as logBlock, s as logOutro, t as createSpinner, u as logTip } from "./output-qFt4vV7K.js";
|
|
8
|
+
import { n as setupReporters } from "./reporters-H21Jvrff.js";
|
|
9
9
|
import { styleText } from "node:util";
|
|
10
10
|
import { hash, randomBytes } from "node:crypto";
|
|
11
11
|
import { hostname } from "node:os";
|
|
@@ -280,7 +280,7 @@ async function connect(options, context = {}) {
|
|
|
280
280
|
}
|
|
281
281
|
try {
|
|
282
282
|
if (!context.prepared) {
|
|
283
|
-
const { getWorkerStatus } = await import("./background-
|
|
283
|
+
const { getWorkerStatus } = await import("./background-C5ADaF5O.js");
|
|
284
284
|
if ((await getWorkerStatus()).running) throw new Error("This project is running in the background. Run `kubb studio stop` first.");
|
|
285
285
|
}
|
|
286
286
|
const prepared = context.prepared ?? await prepareConnection(options, signal);
|
|
@@ -363,4 +363,4 @@ async function run({ options, action, block = false, json = false }) {
|
|
|
363
363
|
//#endregion
|
|
364
364
|
export { login as a, clearCredentials as c, loadConfigs as i, getProjectKubbHome as l, createStudioOptions as n, prepareConnection as o, formatPermissionRows as r, run as s, connect as t, readCredentials as u };
|
|
365
365
|
|
|
366
|
-
//# sourceMappingURL=run-
|
|
366
|
+
//# sourceMappingURL=run-DlQDj_SV.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-9oIapU5y.js","names":["logLevelMap"],"sources":["../../../internals/utils/src/openInBrowser.ts","../src/runners/studio/credentials.ts","../src/runners/studio/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { x } from 'tinyexec'\nimport { isCIEnvironment } from './isCIEnvironment.ts'\n\nconst ignore = () => {}\n\n/**\n * Opens a URL or local file in the default browser, unless running in CI.\n */\nexport function openInBrowser(target: string): void {\n if (isCIEnvironment()) return\n\n if (process.platform === 'win32') {\n x('cmd', ['/c', 'start', '', target]).then(ignore, ignore)\n return\n }\n x(process.platform === 'darwin' ? 'open' : 'xdg-open', [target]).then(ignore, ignore)\n}\n","import { hash, randomBytes } from 'node:crypto'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { kubbStorage, resolveKubbDir } from '@kubb/core'\n\nconst projectBase = (project = process.cwd()) => path.join('projects', hash('sha256', project))\n\n/**\n * Root for the credential and machine identity of the current project, inside `KUBB_HOME`.\n *\n * Studio agents are project connections, so two projects on one machine must not share the same\n * persisted token or machine secret.\n */\nexport function getProjectKubbHome(project = process.cwd()): string {\n return resolveKubbDir(projectBase(project))\n}\n\nconst projectStorage = () => kubbStorage({ base: projectBase() })\n\nconst CREDENTIALS_FILENAME = 'credentials.json'\n\n/**\n * Absolute path of the stored credential, so callers can name it in output without rebuilding it.\n */\nexport function getCredentialsPath(): string {\n return path.join(getProjectKubbHome(), CREDENTIALS_FILENAME)\n}\n\nexport type Credentials = {\n /**\n * The Studio instance this machine paired with. A different `--url` means re-pairing.\n */\n studioUrl: string\n /**\n * Bearer token for this machine. Never logged, never printed.\n */\n token: string\n agentId: string\n agentSlug: string\n /**\n * Permissions the user has already granted, keyed by absolute project path, so the CLI asks\n * once per project instead of on every run.\n */\n projects?: Record<string, { allowRead?: boolean; allowWrite?: boolean; allowConfigEdit?: boolean; allowExec?: boolean }>\n}\n\n/**\n * Reads the stored credential, or null when this machine has not paired yet or the file is\n * unreadable or corrupt. A bad file is treated as \"not paired\" so `kubb studio login` can\n * overwrite it rather than the CLI dying on it.\n */\nexport async function readCredentials(): Promise<Credentials | null> {\n const stored = await projectStorage()\n .getItem<Credentials>(CREDENTIALS_FILENAME)\n .catch(() => null)\n\n return typeof stored?.token === 'string' && stored.token !== '' ? stored : null\n}\n\n/**\n * Writes the credential into the project folder, which only its owner can open.\n */\nexport async function writeCredentials(credentials: Credentials): Promise<void> {\n await projectStorage().setItem(CREDENTIALS_FILENAME, credentials)\n}\n\n/**\n * Forgets the stored credential. Succeeds when there was nothing to forget.\n */\nexport async function clearCredentials(): Promise<void> {\n await projectStorage().removeItem(CREDENTIALS_FILENAME)\n}\n\n/**\n * Reads this project's machine secret, creating it on first use. Pairing sends its hash, so pairing\n * the same project again rotates one agent's token instead of creating a second agent. It lives\n * apart from the credential, which {@link clearCredentials} deletes.\n */\nexport async function getMachineId(): Promise<string> {\n const storage = projectStorage()\n const stored = await storage.getItem('machine-secret').catch(() => null)\n if (typeof stored === 'string' && stored.trim()) return stored.trim()\n\n const secret = randomBytes(32).toString('hex')\n await storage.setItem('machine-secret', secret)\n\n return secret\n}\n","import { hostname } from 'node:os'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport * as prompts from '@clack/prompts'\nimport { KUBB_CONFIG_FILENAME } from '@internals/shared'\nimport { isCIEnvironment, openInBrowser, toError } from '@internals/utils'\nimport type { CLIOptions, Config } from '@kubb/core'\nimport { cliReporter, Hookable, type KubbHooks, logLevel as logLevelMap } from '@kubb/core'\nimport { connectAgent, defaultStudioUrl, InvalidAgentTokenError, pairAgent, PairingCanceledError } from '@kubb/studio'\nimport { trackRun } from '../../Telemetry.ts'\nimport { plainLogger } from '../../loggers/plainLogger.ts'\nimport setupReporters from '../../loggers/reporters.ts'\nimport { createSpinner, logBlock, logIntro, logOutro, logTip } from '../../loggers/output.ts'\nimport { canUseTTY } from '../../utils/env.ts'\nimport { getConfigs } from '../../config.ts'\nimport { clearCredentials, type Credentials, getCredentialsPath, getMachineId, readCredentials, writeCredentials } from './credentials.ts'\nimport { version } from '../../../package.json'\n\ntype Permission = 'allowRead' | 'allowWrite' | 'allowConfigEdit' | 'allowExec'\n\nexport type StudioOptions = {\n /**\n * Current `@kubb/cli` version, reported to Studio and used for the telemetry payload.\n */\n version: string\n configPath?: string\n /**\n * Base URL of the Studio instance, for a self-hosted deployment. Resolved before it reaches here,\n * since stored credentials are bound to it.\n */\n studioUrl: string\n /**\n * What Studio may do in this project. Each flag grants outright; the rest are asked once per\n * project through {@link resolvePermissions}.\n */\n permission: Record<Permission, boolean>\n /**\n * Whether to open the approval page in a browser during pairing.\n */\n autoOpen: boolean\n logLevel?: CLIOptions['logLevel']\n}\n\nexport type SnapshotOptions = Pick<StudioOptions, 'configPath' | 'studioUrl' | 'logLevel'> & {\n /**\n * Organization CI API key. Falls back to `KUBB_TOKEN`.\n */\n token?: string\n /**\n * Stable identity for the CI agent. Falls back to CI auto-detection.\n */\n id?: string\n /** Identity of another CI agent to also compare with. Falls back to CI auto-detection. */\n baseId?: string\n /**\n * Package name for the generated tarball. Falls back to the nearest package.json.\n */\n name?: string\n /**\n * Package version for the generated tarball. Falls back to the nearest package.json.\n */\n packageVersion?: string\n /**\n * Print the result as one JSON object instead of a summary.\n */\n json?: boolean\n}\n\ntype StudioValues = {\n config?: string\n url?: string\n allowRead: boolean\n allowWrite: boolean\n allowConfigEdit: boolean\n allowExec: boolean\n open?: boolean\n logLevel?: CLIOptions['logLevel']\n}\n\nexport function createStudioOptions(values: StudioValues): StudioOptions {\n return {\n version,\n configPath: values.config,\n studioUrl: values.url ?? defaultStudioUrl,\n permission: {\n allowRead: values.allowRead,\n allowWrite: values.allowWrite,\n allowConfigEdit: values.allowConfigEdit,\n allowExec: values.allowExec,\n },\n autoOpen: values.open ?? true,\n logLevel: values.logLevel,\n }\n}\n\ntype LoginOptions = {\n /**\n * Aborting this cancels an in-flight pairing request or poll and rejects with\n * {@link PairingCanceledError}. Wired to `kubb studio`'s shutdown signal, so Ctrl+C during\n * pairing cancels it instead of leaving the poll running.\n */\n signal?: AbortSignal\n /**\n * Credentials from before this login. When the fresh pairing resolves to the same agent on the\n * same Studio, its saved project permissions carry forward instead of being asked again.\n * Left out for an explicitly requested `kubb studio login`, which always starts clean.\n */\n previousCredentials?: Credentials | null\n}\n\n/**\n * Pairs this machine with Studio and stores the resulting token.\n *\n * The CLI holds a code and the browser approves it, rather than the user copying a token out of\n * the UI. The token comes back over the CLI's own HTTPS POST, so it never lands in a URL, a\n * server log, or a `Referer` header.\n */\nexport async function login({ studioUrl, autoOpen }: StudioOptions, { signal, previousCredentials }: LoginOptions = {}): Promise<Credentials> {\n const spinner = createSpinner()\n // The spinner only starts once a code is shown.\n let waiting = false\n\n try {\n const { token, agent } = await pairAgent({\n studioUrl,\n type: 'cli',\n name: path.basename(process.cwd()),\n hostname: hostname(),\n machineId: await getMachineId(),\n signal,\n onCode: (session) => {\n console.log(`\\nOpen ${styleText('cyan', session.verification_uri)} and approve the code ${styleText('bold', session.user_code)}`)\n\n if (autoOpen) {\n openInBrowser(session.verification_uri_complete)\n }\n\n spinner.start('Waiting for approval')\n waiting = true\n },\n onRetry: (error) => spinner.message(`Could not reach Kubb Studio, retrying: ${error.message}`),\n })\n spinner.stop(`Paired as ${agent.name}`)\n\n const keepsIdentity = previousCredentials?.studioUrl === studioUrl && previousCredentials.agentId === agent.id\n const credentials: Credentials = {\n studioUrl,\n token,\n agentId: agent.id,\n agentSlug: agent.slug,\n ...(keepsIdentity && previousCredentials?.projects ? { projects: previousCredentials.projects } : {}),\n }\n await writeCredentials(credentials)\n\n console.log(`Credentials stored in ${getCredentialsPath()}`)\n\n return credentials\n } catch (error) {\n if (waiting) {\n spinner.stop(error instanceof PairingCanceledError ? 'Pairing canceled' : 'Pairing failed')\n }\n throw error\n }\n}\n\n/**\n * What each permission is asked as, in the order the questions appear.\n */\nconst PERMISSIONS: ReadonlyArray<{\n key: Permission\n /**\n * Short label for status output and the connect summary.\n */\n label: string\n question: (project: string, configPath: string) => string\n}> = [\n {\n key: 'allowRead',\n label: 'read generated files',\n question: () => 'Let Kubb Studio read the files a generation produced?',\n },\n { key: 'allowWrite', label: 'write generated files', question: (project) => `Let Kubb Studio write generated files into ${project}?` },\n {\n key: 'allowConfigEdit',\n label: 'edit kubb.config.ts',\n question: (_project, configPath) => `Let Kubb Studio change plugin options in ${configPath}?`,\n },\n {\n key: 'allowExec',\n label: 'run formatter, linter, postGenerate',\n question: () => 'Let Kubb Studio run the formatter, the linter, and output.postGenerate?',\n },\n]\n\n/**\n * One row per permission, for the connect banner and `kubb studio status`. A list rather than a\n * joined line: four labels this long read as one run-on sentence side by side.\n */\nexport function formatPermissionRows(granted: Record<Permission, boolean>): Array<string> {\n return PERMISSIONS.map(({ key, label }) => `${granted[key] ? styleText('green', '✔') : styleText('red', '✘')} ${label}`)\n}\n\n/**\n * Resolves Studio permissions for the current project.\n * Flags win, saved answers are reused, and new answers are stored unless `persist` is false.\n */\nexport async function resolvePermissions(\n options: StudioOptions,\n credentials: Credentials,\n configPath: string = KUBB_CONFIG_FILENAME,\n /**\n * Stores new answers in `~/.kubb/credentials.json`.\n * Pass `false` for `KUBB_AGENT_TOKEN` sessions so a temporary token is not written back to disk.\n */\n persist = true,\n): Promise<Record<Permission, boolean>> {\n const project = process.cwd()\n const remembered = credentials.projects?.[project]\n const granted: Record<Permission, boolean> = { allowRead: false, allowWrite: false, allowConfigEdit: false, allowExec: false }\n const answers: Partial<Record<Permission, boolean>> = {}\n prompts.updateSettings({ withGuide: true })\n\n for (const { key, question } of PERMISSIONS) {\n if (options.permission[key] || typeof remembered?.[key] === 'boolean') {\n granted[key] = options.permission[key] || remembered?.[key] === true\n continue\n }\n\n if (isCIEnvironment() || !canUseTTY()) {\n granted[key] = false\n continue\n }\n\n granted[key] = (await prompts.confirm({ message: question(project, configPath), initialValue: false })) === true\n answers[key] = granted[key]\n }\n if (persist && Object.keys(answers).length) {\n await writeCredentials({\n ...credentials,\n projects: { ...credentials.projects, [project]: { ...remembered, ...answers } },\n })\n }\n\n return granted\n}\n\n/**\n * Loads the project's Kubb config the same way `kubb generate` does.\n * Returns the first config.\n */\nexport async function loadConfigs(options: Pick<StudioOptions, 'configPath' | 'logLevel'>): Promise<{ configPath: string; config: Config }> {\n const { configPath, configs } = await getConfigs({ configPath: options.configPath, logLevel: options.logLevel })\n const [config] = configs\n\n if (!config) {\n throw new Error('Config not defined, create a kubb.config.ts or pass it with --config')\n }\n\n // `getConfigs` resolves this to an absolute path. Relativized here, once, so the permission\n // prompt and the path Studio receives over the wire both show the project-relative form instead\n // of leaking the local filesystem layout.\n return { configPath: path.relative(process.cwd(), configPath) || configPath, config }\n}\n\n/**\n * Why a rejected token could not be recovered automatically: it came from `KUBB_AGENT_TOKEN`, no\n * browser is available to re-pair with, or the token this run already re-paired for was rejected\n * again.\n */\ntype RejectedTokenReason = 'envToken' | 'nonInteractive' | 'reauthExhausted'\n\n/**\n * Explains a rejected token to the operator. Builds the error and nothing else, so each caller\n * decides what happens to the credentials.\n */\nfunction explainRejectedToken(error: InvalidAgentTokenError, reason: RejectedTokenReason): Error {\n if (reason === 'envToken') {\n return new Error(`${error.message} Pair again and update KUBB_AGENT_TOKEN.`)\n }\n\n if (reason === 'reauthExhausted') {\n return new Error(`${error.message} Studio rejected the newly approved token too. Run \\`kubb studio login\\` and try again.`)\n }\n\n return new Error(`${error.message} Run \\`kubb studio login\\` to pair again.`)\n}\n\nexport type PreparedConnection = {\n configPath: string\n credentials: Credentials\n permissions: StudioOptions['permission']\n}\n\n/** Validates the project and resolves pairing and permissions before starting its worker. */\nexport async function prepareConnection(options: StudioOptions, signal?: AbortSignal): Promise<PreparedConnection> {\n const { configPath } = await loadConfigs(options)\n const envToken = process.env.KUBB_AGENT_TOKEN\n const stored = envToken ? null : await readCredentials()\n const credentials = await (async () => {\n if (envToken) return { studioUrl: options.studioUrl, token: envToken, agentId: '', agentSlug: '' }\n if (stored?.studioUrl === options.studioUrl) return stored\n if (isCIEnvironment()) {\n throw new Error(`Not paired with ${options.studioUrl}. Set KUBB_AGENT_TOKEN, or run \\`kubb studio login\\` on a machine with a browser.`)\n }\n return login(options, { signal })\n })()\n const permissions = await resolvePermissions(options, credentials, configPath, !envToken)\n return { configPath, credentials, permissions }\n}\n\nexport type WorkerState = 'starting' | 'connected' | 'reconnecting' | 'authentication required' | 'stopped'\n\n/** Runs the same project connection in the foreground or in a background worker. */\nexport async function connect(\n options: StudioOptions,\n context: {\n prepared?: PreparedConnection\n signal?: AbortSignal\n onState?: (state: WorkerState) => void | Promise<void>\n } = {},\n): Promise<void> {\n const shutdown = new AbortController()\n const signal = context.signal ?? shutdown.signal\n const stop = () => shutdown.abort()\n const events = process as unknown as NodeJS.EventEmitter\n if (!context.signal) {\n events.once('SIGINT', stop)\n events.once('SIGTERM', stop)\n }\n try {\n if (!context.prepared) {\n const { getWorkerStatus } = await import('./background.ts')\n const worker = await getWorkerStatus()\n if (worker.running) throw new Error('This project is running in the background. Run `kubb studio stop` first.')\n }\n const prepared = context.prepared ?? (await prepareConnection(options, signal))\n let { credentials, permissions } = prepared\n const { configPath } = prepared\n let hinted = false\n // Set by a fresh pairing until it connects, so a token rejected right after approval fails the run instead of looping.\n let pairedAgain = false\n\n // The background worker writes to a log file, so it gets the plain logger rather than the\n // animated one. The logger also covers the `studio:*` events and each generation run.\n const hooks = new Hookable<KubbHooks>()\n setupReporters(hooks, {\n logLevel: logLevelMap[options.logLevel ?? 'info'],\n reporters: [cliReporter],\n ...(context.onState ? { logger: plainLogger } : {}),\n })\n hooks.hook('studio:connected', async () => {\n pairedAgain = false\n await context.onState?.('connected')\n if (hinted || context.onState || options.logLevel === 'silent') return\n hinted = true\n logBlock(styleText('dim', 'Press Ctrl+C to disconnect'))\n logTip()\n })\n hooks.hook('studio:reconnecting', () => context.onState?.('reconnecting'))\n\n for (;;) {\n try {\n await connectAgent({\n token: credentials.token,\n studioUrl: options.studioUrl,\n configPath,\n version: options.version,\n root: process.cwd(),\n permissions,\n loadConfig: async () => (await loadConfigs(options)).config,\n hooks,\n signal,\n })\n break\n } catch (error) {\n if (!(error instanceof InvalidAgentTokenError)) throw error\n await context.onState?.('authentication required')\n if (process.env.KUBB_AGENT_TOKEN) throw explainRejectedToken(error, 'envToken')\n await clearCredentials()\n if (pairedAgain) throw explainRejectedToken(error, 'reauthExhausted')\n if (context.onState || isCIEnvironment() || !canUseTTY()) throw explainRejectedToken(error, 'nonInteractive')\n\n console.log(styleText('yellow', `${error.message} Pairing again...`))\n credentials = await login(options, { signal, previousCredentials: credentials })\n pairedAgain = true\n permissions = await resolvePermissions(options, credentials, configPath)\n }\n }\n if (!context.onState && signal.aborted && options.logLevel !== 'silent') logOutro('Disconnected')\n } catch (error) {\n if (!(error instanceof PairingCanceledError)) throw error\n } finally {\n events.off('SIGINT', stop)\n events.off('SIGTERM', stop)\n }\n}\n\n/**\n * Runs a Studio command with shared setup and telemetry reporting.\n */\nexport async function run({\n options,\n action,\n block = false,\n json = false,\n}: {\n options: Pick<StudioOptions, 'logLevel'>\n action: () => Promise<unknown>\n block?: boolean\n json?: boolean\n}): Promise<void> {\n const report = trackRun({ command: 'studio', hrStart: process.hrtime() })\n\n try {\n if (options.logLevel !== 'silent' && !json) {\n logIntro({\n warning: styleText('yellow', 'This feature is still under development, use with caution'),\n block,\n })\n }\n\n await action()\n\n await report({ status: 'success' })\n } catch (error) {\n await report({ status: 'failed' })\n console.error(toError(error).message)\n process.exitCode = 1\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run-DlQDj_SV.js","names":["logLevelMap"],"sources":["../../../internals/utils/src/openInBrowser.ts","../src/runners/studio/credentials.ts","../src/runners/studio/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { x } from 'tinyexec'\nimport { isCIEnvironment } from './isCIEnvironment.ts'\n\nconst ignore = () => {}\n\n/**\n * Opens a URL or local file in the default browser, unless running in CI.\n */\nexport function openInBrowser(target: string): void {\n if (isCIEnvironment()) return\n\n if (process.platform === 'win32') {\n x('cmd', ['/c', 'start', '', target]).then(ignore, ignore)\n return\n }\n x(process.platform === 'darwin' ? 'open' : 'xdg-open', [target]).then(ignore, ignore)\n}\n","import { hash, randomBytes } from 'node:crypto'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { kubbStorage, resolveKubbDir } from '@kubb/core'\n\nconst projectBase = (project = process.cwd()) => path.join('projects', hash('sha256', project))\n\n/**\n * Root for the credential and machine identity of the current project, inside `KUBB_HOME`.\n *\n * Studio agents are project connections, so two projects on one machine must not share the same\n * persisted token or machine secret.\n */\nexport function getProjectKubbHome(project = process.cwd()): string {\n return resolveKubbDir(projectBase(project))\n}\n\nconst projectStorage = () => kubbStorage({ base: projectBase() })\n\nconst CREDENTIALS_FILENAME = 'credentials.json'\n\n/**\n * Absolute path of the stored credential, so callers can name it in output without rebuilding it.\n */\nexport function getCredentialsPath(): string {\n return path.join(getProjectKubbHome(), CREDENTIALS_FILENAME)\n}\n\nexport type Credentials = {\n /**\n * The Studio instance this machine paired with. A different `--url` means re-pairing.\n */\n studioUrl: string\n /**\n * Bearer token for this machine. Never logged, never printed.\n */\n token: string\n agentId: string\n agentSlug: string\n /**\n * Permissions the user has already granted, keyed by absolute project path, so the CLI asks\n * once per project instead of on every run.\n */\n projects?: Record<string, { allowRead?: boolean; allowWrite?: boolean; allowConfigEdit?: boolean; allowExec?: boolean }>\n}\n\n/**\n * Reads the stored credential, or null when this machine has not paired yet or the file is\n * unreadable or corrupt. A bad file is treated as \"not paired\" so `kubb studio login` can\n * overwrite it rather than the CLI dying on it.\n */\nexport async function readCredentials(): Promise<Credentials | null> {\n const stored = await projectStorage()\n .getItem<Credentials>(CREDENTIALS_FILENAME)\n .catch(() => null)\n\n return typeof stored?.token === 'string' && stored.token !== '' ? stored : null\n}\n\n/**\n * Writes the credential into the project folder, which only its owner can open.\n */\nexport async function writeCredentials(credentials: Credentials): Promise<void> {\n await projectStorage().setItem(CREDENTIALS_FILENAME, credentials)\n}\n\n/**\n * Forgets the stored credential. Succeeds when there was nothing to forget.\n */\nexport async function clearCredentials(): Promise<void> {\n await projectStorage().removeItem(CREDENTIALS_FILENAME)\n}\n\n/**\n * Reads this project's machine secret, creating it on first use. Pairing sends its hash, so pairing\n * the same project again rotates one agent's token instead of creating a second agent. It lives\n * apart from the credential, which {@link clearCredentials} deletes.\n */\nexport async function getMachineId(): Promise<string> {\n const storage = projectStorage()\n const stored = await storage.getItem('machine-secret').catch(() => null)\n if (typeof stored === 'string' && stored.trim()) return stored.trim()\n\n const secret = randomBytes(32).toString('hex')\n await storage.setItem('machine-secret', secret)\n\n return secret\n}\n","import { hostname } from 'node:os'\nimport path from 'node:path'\nimport process from 'node:process'\nimport { styleText } from 'node:util'\nimport * as prompts from '@clack/prompts'\nimport { KUBB_CONFIG_FILENAME } from '@internals/shared'\nimport { isCIEnvironment, openInBrowser, toError } from '@internals/utils'\nimport type { CLIOptions, Config } from '@kubb/core'\nimport { cliReporter, Hookable, type KubbHooks, logLevel as logLevelMap } from '@kubb/core'\nimport { connectAgent, defaultStudioUrl, InvalidAgentTokenError, pairAgent, PairingCanceledError } from '@kubb/studio'\nimport { trackRun } from '../../Telemetry.ts'\nimport { plainLogger } from '../../loggers/plainLogger.ts'\nimport setupReporters from '../../loggers/reporters.ts'\nimport { createSpinner, logBlock, logIntro, logOutro, logTip } from '../../loggers/output.ts'\nimport { canUseTTY } from '../../utils/env.ts'\nimport { getConfigs } from '../../config.ts'\nimport { clearCredentials, type Credentials, getCredentialsPath, getMachineId, readCredentials, writeCredentials } from './credentials.ts'\nimport { version } from '../../../package.json'\n\ntype Permission = 'allowRead' | 'allowWrite' | 'allowConfigEdit' | 'allowExec'\n\nexport type StudioOptions = {\n /**\n * Current `@kubb/cli` version, reported to Studio and used for the telemetry payload.\n */\n version: string\n configPath?: string\n /**\n * Base URL of the Studio instance, for a self-hosted deployment. Resolved before it reaches here,\n * since stored credentials are bound to it.\n */\n studioUrl: string\n /**\n * What Studio may do in this project. Each flag grants outright; the rest are asked once per\n * project through {@link resolvePermissions}.\n */\n permission: Record<Permission, boolean>\n /**\n * Whether to open the approval page in a browser during pairing.\n */\n autoOpen: boolean\n logLevel?: CLIOptions['logLevel']\n}\n\nexport type SnapshotOptions = Pick<StudioOptions, 'configPath' | 'studioUrl' | 'logLevel'> & {\n /**\n * Organization CI API key. Falls back to `KUBB_TOKEN`.\n */\n token?: string\n /**\n * Stable identity for the CI agent. Falls back to CI auto-detection.\n */\n id?: string\n /** Identity of another CI agent to also compare with. Falls back to CI auto-detection. */\n baseId?: string\n /**\n * Package name for the generated tarball. Falls back to the nearest package.json.\n */\n name?: string\n /**\n * Package version for the generated tarball. Falls back to the nearest package.json.\n */\n packageVersion?: string\n /**\n * Print the result as one JSON object instead of a summary.\n */\n json?: boolean\n}\n\ntype StudioValues = {\n config?: string\n url?: string\n allowRead: boolean\n allowWrite: boolean\n allowConfigEdit: boolean\n allowExec: boolean\n open?: boolean\n logLevel?: CLIOptions['logLevel']\n}\n\nexport function createStudioOptions(values: StudioValues): StudioOptions {\n return {\n version,\n configPath: values.config,\n studioUrl: values.url ?? defaultStudioUrl,\n permission: {\n allowRead: values.allowRead,\n allowWrite: values.allowWrite,\n allowConfigEdit: values.allowConfigEdit,\n allowExec: values.allowExec,\n },\n autoOpen: values.open ?? true,\n logLevel: values.logLevel,\n }\n}\n\ntype LoginOptions = {\n /**\n * Aborting this cancels an in-flight pairing request or poll and rejects with\n * {@link PairingCanceledError}. Wired to `kubb studio`'s shutdown signal, so Ctrl+C during\n * pairing cancels it instead of leaving the poll running.\n */\n signal?: AbortSignal\n /**\n * Credentials from before this login. When the fresh pairing resolves to the same agent on the\n * same Studio, its saved project permissions carry forward instead of being asked again.\n * Left out for an explicitly requested `kubb studio login`, which always starts clean.\n */\n previousCredentials?: Credentials | null\n}\n\n/**\n * Pairs this machine with Studio and stores the resulting token.\n *\n * The CLI holds a code and the browser approves it, rather than the user copying a token out of\n * the UI. The token comes back over the CLI's own HTTPS POST, so it never lands in a URL, a\n * server log, or a `Referer` header.\n */\nexport async function login({ studioUrl, autoOpen }: StudioOptions, { signal, previousCredentials }: LoginOptions = {}): Promise<Credentials> {\n const spinner = createSpinner()\n // The spinner only starts once a code is shown.\n let waiting = false\n\n try {\n const { token, agent } = await pairAgent({\n studioUrl,\n type: 'cli',\n name: path.basename(process.cwd()),\n hostname: hostname(),\n machineId: await getMachineId(),\n signal,\n onCode: (session) => {\n console.log(`\\nOpen ${styleText('cyan', session.verification_uri)} and approve the code ${styleText('bold', session.user_code)}`)\n\n if (autoOpen) {\n openInBrowser(session.verification_uri_complete)\n }\n\n spinner.start('Waiting for approval')\n waiting = true\n },\n onRetry: (error) => spinner.message(`Could not reach Kubb Studio, retrying: ${error.message}`),\n })\n spinner.stop(`Paired as ${agent.name}`)\n\n const keepsIdentity = previousCredentials?.studioUrl === studioUrl && previousCredentials.agentId === agent.id\n const credentials: Credentials = {\n studioUrl,\n token,\n agentId: agent.id,\n agentSlug: agent.slug,\n ...(keepsIdentity && previousCredentials?.projects ? { projects: previousCredentials.projects } : {}),\n }\n await writeCredentials(credentials)\n\n console.log(`Credentials stored in ${getCredentialsPath()}`)\n\n return credentials\n } catch (error) {\n if (waiting) {\n spinner.stop(error instanceof PairingCanceledError ? 'Pairing canceled' : 'Pairing failed')\n }\n throw error\n }\n}\n\n/**\n * What each permission is asked as, in the order the questions appear.\n */\nconst PERMISSIONS: ReadonlyArray<{\n key: Permission\n /**\n * Short label for status output and the connect summary.\n */\n label: string\n question: (project: string, configPath: string) => string\n}> = [\n {\n key: 'allowRead',\n label: 'read generated files',\n question: () => 'Let Kubb Studio read the files a generation produced?',\n },\n { key: 'allowWrite', label: 'write generated files', question: (project) => `Let Kubb Studio write generated files into ${project}?` },\n {\n key: 'allowConfigEdit',\n label: 'edit kubb.config.ts',\n question: (_project, configPath) => `Let Kubb Studio change plugin options in ${configPath}?`,\n },\n {\n key: 'allowExec',\n label: 'run formatter, linter, postGenerate',\n question: () => 'Let Kubb Studio run the formatter, the linter, and output.postGenerate?',\n },\n]\n\n/**\n * One row per permission, for the connect banner and `kubb studio status`. A list rather than a\n * joined line: four labels this long read as one run-on sentence side by side.\n */\nexport function formatPermissionRows(granted: Record<Permission, boolean>): Array<string> {\n return PERMISSIONS.map(({ key, label }) => `${granted[key] ? styleText('green', '✔') : styleText('red', '✘')} ${label}`)\n}\n\n/**\n * Resolves Studio permissions for the current project.\n * Flags win, saved answers are reused, and new answers are stored unless `persist` is false.\n */\nexport async function resolvePermissions(\n options: StudioOptions,\n credentials: Credentials,\n configPath: string = KUBB_CONFIG_FILENAME,\n /**\n * Stores new answers in `~/.kubb/credentials.json`.\n * Pass `false` for `KUBB_AGENT_TOKEN` sessions so a temporary token is not written back to disk.\n */\n persist = true,\n): Promise<Record<Permission, boolean>> {\n const project = process.cwd()\n const remembered = credentials.projects?.[project]\n const granted: Record<Permission, boolean> = { allowRead: false, allowWrite: false, allowConfigEdit: false, allowExec: false }\n const answers: Partial<Record<Permission, boolean>> = {}\n prompts.updateSettings({ withGuide: true })\n\n for (const { key, question } of PERMISSIONS) {\n if (options.permission[key] || typeof remembered?.[key] === 'boolean') {\n granted[key] = options.permission[key] || remembered?.[key] === true\n continue\n }\n\n if (isCIEnvironment() || !canUseTTY()) {\n granted[key] = false\n continue\n }\n\n granted[key] = (await prompts.confirm({ message: question(project, configPath), initialValue: false })) === true\n answers[key] = granted[key]\n }\n if (persist && Object.keys(answers).length) {\n await writeCredentials({\n ...credentials,\n projects: { ...credentials.projects, [project]: { ...remembered, ...answers } },\n })\n }\n\n return granted\n}\n\n/**\n * Loads the project's Kubb config the same way `kubb generate` does.\n * Returns the first config.\n */\nexport async function loadConfigs(options: Pick<StudioOptions, 'configPath' | 'logLevel'>): Promise<{ configPath: string; config: Config }> {\n const { configPath, configs } = await getConfigs({ configPath: options.configPath, logLevel: options.logLevel })\n const [config] = configs\n\n if (!config) {\n throw new Error('Config not defined, create a kubb.config.ts or pass it with --config')\n }\n\n // `getConfigs` resolves this to an absolute path. Relativized here, once, so the permission\n // prompt and the path Studio receives over the wire both show the project-relative form instead\n // of leaking the local filesystem layout.\n return { configPath: path.relative(process.cwd(), configPath) || configPath, config }\n}\n\n/**\n * Why a rejected token could not be recovered automatically: it came from `KUBB_AGENT_TOKEN`, no\n * browser is available to re-pair with, or the token this run already re-paired for was rejected\n * again.\n */\ntype RejectedTokenReason = 'envToken' | 'nonInteractive' | 'reauthExhausted'\n\n/**\n * Explains a rejected token to the operator. Builds the error and nothing else, so each caller\n * decides what happens to the credentials.\n */\nfunction explainRejectedToken(error: InvalidAgentTokenError, reason: RejectedTokenReason): Error {\n if (reason === 'envToken') {\n return new Error(`${error.message} Pair again and update KUBB_AGENT_TOKEN.`)\n }\n\n if (reason === 'reauthExhausted') {\n return new Error(`${error.message} Studio rejected the newly approved token too. Run \\`kubb studio login\\` and try again.`)\n }\n\n return new Error(`${error.message} Run \\`kubb studio login\\` to pair again.`)\n}\n\nexport type PreparedConnection = {\n configPath: string\n credentials: Credentials\n permissions: StudioOptions['permission']\n}\n\n/** Validates the project and resolves pairing and permissions before starting its worker. */\nexport async function prepareConnection(options: StudioOptions, signal?: AbortSignal): Promise<PreparedConnection> {\n const { configPath } = await loadConfigs(options)\n const envToken = process.env.KUBB_AGENT_TOKEN\n const stored = envToken ? null : await readCredentials()\n const credentials = await (async () => {\n if (envToken) return { studioUrl: options.studioUrl, token: envToken, agentId: '', agentSlug: '' }\n if (stored?.studioUrl === options.studioUrl) return stored\n if (isCIEnvironment()) {\n throw new Error(`Not paired with ${options.studioUrl}. Set KUBB_AGENT_TOKEN, or run \\`kubb studio login\\` on a machine with a browser.`)\n }\n return login(options, { signal })\n })()\n const permissions = await resolvePermissions(options, credentials, configPath, !envToken)\n return { configPath, credentials, permissions }\n}\n\nexport type WorkerState = 'starting' | 'connected' | 'reconnecting' | 'authentication required' | 'stopped'\n\n/** Runs the same project connection in the foreground or in a background worker. */\nexport async function connect(\n options: StudioOptions,\n context: {\n prepared?: PreparedConnection\n signal?: AbortSignal\n onState?: (state: WorkerState) => void | Promise<void>\n } = {},\n): Promise<void> {\n const shutdown = new AbortController()\n const signal = context.signal ?? shutdown.signal\n const stop = () => shutdown.abort()\n const events = process as unknown as NodeJS.EventEmitter\n if (!context.signal) {\n events.once('SIGINT', stop)\n events.once('SIGTERM', stop)\n }\n try {\n if (!context.prepared) {\n const { getWorkerStatus } = await import('./background.ts')\n const worker = await getWorkerStatus()\n if (worker.running) throw new Error('This project is running in the background. Run `kubb studio stop` first.')\n }\n const prepared = context.prepared ?? (await prepareConnection(options, signal))\n let { credentials, permissions } = prepared\n const { configPath } = prepared\n let hinted = false\n // Set by a fresh pairing until it connects, so a token rejected right after approval fails the run instead of looping.\n let pairedAgain = false\n\n // The background worker writes to a log file, so it gets the plain logger rather than the\n // animated one. The logger also covers the `studio:*` events and each generation run.\n const hooks = new Hookable<KubbHooks>()\n setupReporters(hooks, {\n logLevel: logLevelMap[options.logLevel ?? 'info'],\n reporters: [cliReporter],\n ...(context.onState ? { logger: plainLogger } : {}),\n })\n hooks.hook('studio:connected', async () => {\n pairedAgain = false\n await context.onState?.('connected')\n if (hinted || context.onState || options.logLevel === 'silent') return\n hinted = true\n logBlock(styleText('dim', 'Press Ctrl+C to disconnect'))\n logTip()\n })\n hooks.hook('studio:reconnecting', () => context.onState?.('reconnecting'))\n\n for (;;) {\n try {\n await connectAgent({\n token: credentials.token,\n studioUrl: options.studioUrl,\n configPath,\n version: options.version,\n root: process.cwd(),\n permissions,\n loadConfig: async () => (await loadConfigs(options)).config,\n hooks,\n signal,\n })\n break\n } catch (error) {\n if (!(error instanceof InvalidAgentTokenError)) throw error\n await context.onState?.('authentication required')\n if (process.env.KUBB_AGENT_TOKEN) throw explainRejectedToken(error, 'envToken')\n await clearCredentials()\n if (pairedAgain) throw explainRejectedToken(error, 'reauthExhausted')\n if (context.onState || isCIEnvironment() || !canUseTTY()) throw explainRejectedToken(error, 'nonInteractive')\n\n console.log(styleText('yellow', `${error.message} Pairing again...`))\n credentials = await login(options, { signal, previousCredentials: credentials })\n pairedAgain = true\n permissions = await resolvePermissions(options, credentials, configPath)\n }\n }\n if (!context.onState && signal.aborted && options.logLevel !== 'silent') logOutro('Disconnected')\n } catch (error) {\n if (!(error instanceof PairingCanceledError)) throw error\n } finally {\n events.off('SIGINT', stop)\n events.off('SIGTERM', stop)\n }\n}\n\n/**\n * Runs a Studio command with shared setup and telemetry reporting.\n */\nexport async function run({\n options,\n action,\n block = false,\n json = false,\n}: {\n options: Pick<StudioOptions, 'logLevel'>\n action: () => Promise<unknown>\n block?: boolean\n json?: boolean\n}): Promise<void> {\n const report = trackRun({ command: 'studio', hrStart: process.hrtime() })\n\n try {\n if (options.logLevel !== 'silent' && !json) {\n logIntro({\n warning: styleText('yellow', 'This feature is still under development, use with caution'),\n block,\n })\n }\n\n await action()\n\n await report({ status: 'success' })\n } catch (error) {\n await report({ status: 'failed' })\n console.error(toError(error).message)\n process.exitCode = 1\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const require_agent = require("./agent-DElUuYuy.cjs");
|
|
2
2
|
const require_errors = require("./errors-BdA8M78q.cjs");
|
|
3
|
-
const require_Telemetry = require("./Telemetry-
|
|
3
|
+
const require_Telemetry = require("./Telemetry-BSuUeat7.cjs");
|
|
4
4
|
let node_util = require("node:util");
|
|
5
5
|
let node_process = require("node:process");
|
|
6
6
|
node_process = require_agent.__toESM(node_process, 1);
|
|
@@ -16,9 +16,7 @@ async function run({ input }) {
|
|
|
16
16
|
});
|
|
17
17
|
try {
|
|
18
18
|
const { adapterOas } = await import("@kubb/adapter-oas");
|
|
19
|
-
|
|
20
|
-
if (!adapter.validate) throw new Error("The loaded adapter does not support validation.");
|
|
21
|
-
await adapter.validate(input, { throwOnError: true });
|
|
19
|
+
await adapterOas().validate(input, { throwOnError: true });
|
|
22
20
|
await report({ status: "success" });
|
|
23
21
|
console.log("✅ Validation success");
|
|
24
22
|
} catch (error) {
|
|
@@ -40,4 +38,4 @@ async function run({ input }) {
|
|
|
40
38
|
//#endregion
|
|
41
39
|
exports.run = run;
|
|
42
40
|
|
|
43
|
-
//# sourceMappingURL=run-
|
|
41
|
+
//# sourceMappingURL=run-Dm7nOUUF.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-Dm7nOUUF.cjs","names":["trackRun","process","styleText","toError"],"sources":["../src/runners/validate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport { trackRun } from '../../Telemetry.ts'\n\ntype ValidateOptions = {\n /**\n * Path or URL to the OpenAPI/Swagger file to validate.\n */\n input: string\n}\n\n/**\n * Validates an OpenAPI/Swagger file at `input` using `@kubb/adapter-oas`.\n * Exits the process with code 1 on validation failure or missing dependency.\n */\nexport async function run({ input }: ValidateOptions): Promise<void> {\n const report = trackRun({ command: 'validate', hrStart: process.hrtime() })\n\n try {\n const { adapterOas } = await import('@kubb/adapter-oas')\n\n await adapterOas().validate(input, { throwOnError: true })\n await report({ status: 'success' })\n\n console.log('✅ Validation success')\n } catch (error) {\n await report({ status: 'failed' })\n if (error instanceof Error && /@kubb\\/adapter-oas/.test(error.message)) {\n console.error(styleText('red', 'The @kubb/adapter-oas package is not installed.'))\n console.error('')\n console.error('Install it with:')\n console.error(styleText('cyan', ' npm install @kubb/adapter-oas'))\n console.error(styleText('cyan', ' # or'))\n console.error(styleText('cyan', ' pnpm install @kubb/adapter-oas'))\n console.error('')\n }\n console.error('❌ Validation failed')\n console.error(toError(error).message)\n\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;;;;;;AAgBA,eAAsB,IAAI,EAAE,SAAyC;CACnE,MAAM,SAASA,kBAAAA,SAAS;EAAE,SAAS;EAAY,SAASC,aAAAA,QAAQ,OAAO;CAAE,CAAC;CAE1E,IAAI;EACF,MAAM,EAAE,eAAe,MAAM,OAAO;EAEpC,MAAM,WAAW,CAAC,CAAC,SAAS,OAAO,EAAE,cAAc,KAAK,CAAC;EACzD,MAAM,OAAO,EAAE,QAAQ,UAAU,CAAC;EAElC,QAAQ,IAAI,sBAAsB;CACpC,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,IAAI,iBAAiB,SAAS,qBAAqB,KAAK,MAAM,OAAO,GAAG;GACtE,QAAQ,OAAA,GAAMC,UAAAA,UAAAA,CAAU,OAAO,iDAAiD,CAAC;GACjF,QAAQ,MAAM,EAAE;GAChB,QAAQ,MAAM,kBAAkB;GAChC,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,iCAAiC,CAAC;GAClE,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,QAAQ,CAAC;GACzC,QAAQ,OAAA,GAAMA,UAAAA,UAAAA,CAAU,QAAQ,kCAAkC,CAAC;GACnE,QAAQ,MAAM,EAAE;EAClB;EACA,QAAQ,MAAM,qBAAqB;EACnC,QAAQ,MAAMC,eAAAA,QAAQ,KAAK,CAAC,CAAC,OAAO;EAEpC,aAAA,QAAQ,KAAK,CAAC;CAChB;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const require_agent = require("./agent-DElUuYuy.cjs");
|
|
2
2
|
const require_errors = require("./errors-BdA8M78q.cjs");
|
|
3
|
-
const require_output = require("./output-
|
|
3
|
+
const require_output = require("./output-BnK0scpX.cjs");
|
|
4
4
|
const require_registry = require("./registry-DER9aRyg.cjs");
|
|
5
5
|
let node_util = require("node:util");
|
|
6
6
|
let node_process = require("node:process");
|
|
@@ -69,4 +69,4 @@ async function run() {
|
|
|
69
69
|
//#endregion
|
|
70
70
|
exports.run = run;
|
|
71
71
|
|
|
72
|
-
//# sourceMappingURL=run-
|
|
72
|
+
//# sourceMappingURL=run-DpAMfkm5.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-
|
|
1
|
+
{"version":3,"file":"run-DpAMfkm5.cjs","names":["readInstalledPackages","fetchRegistryIndex","getErrorMessage","isOutdated","process","registryUrl","styleText"],"sources":["../src/runners/list/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { getErrorMessage } from '@internals/utils'\nimport { readInstalledPackages, type RegistryEntry } from '@kubb/core'\nimport { logBlock, logError, logOutro, logWarn } from '../../loggers/output.ts'\nimport { fetchRegistryIndex, isOutdated, registryUrl } from '../../utils/registry.ts'\n\nexport type ListRow = {\n id?: string\n package: string\n installed?: string\n registry?: string\n update: boolean\n}\n\n/**\n * The installed packages that ship a `kubb-extension.json` or have a registry entry, with the\n * version the registry pins.\n */\nexport async function listExtensions({ cwd, registry }: { cwd: string; registry: string }): Promise<Array<ListRow>> {\n const [installed, entries] = await Promise.all([\n readInstalledPackages({ root: cwd }),\n fetchRegistryIndex({ registry }).catch((error: unknown): Array<RegistryEntry> => {\n logWarn(`Showing installed extensions only: ${getErrorMessage(error)}`)\n return []\n }),\n ])\n const byPackage = new Map(entries.map((entry) => [entry.artifact.package, entry]))\n\n return installed.flatMap(({ package: name, version, manifest }): Array<ListRow> => {\n const entry = byPackage.get(name)\n if (!entry && !manifest) return []\n const latest = entry?.artifact.version\n return [{ id: entry?.id, package: name, installed: version, registry: latest, update: !!latest && isOutdated({ installed: version, latest }) }]\n })\n}\n\n/** Prints the installed extensions as a table. */\nexport async function run(): Promise<void> {\n try {\n const rows = await listExtensions({ cwd: process.cwd(), registry: registryUrl() })\n if (!rows.length) {\n logOutro('No installed extensions found.')\n return\n }\n\n const header = ['ID', 'PACKAGE', 'INSTALLED', 'REGISTRY', 'UPDATE']\n const cells = rows.map((row) => [row.id ?? '-', row.package, row.installed ?? '-', row.registry ?? '-', row.update ? 'yes' : 'no'])\n const widths = header.map((title, index) => Math.max(title.length, ...cells.map((cell) => cell[index]!.length)))\n const line = (cell: Array<string>) =>\n cell\n .map((value, index) => value.padEnd(widths[index]!))\n .join(' ')\n .trimEnd()\n\n logBlock([styleText('dim', line(header)), ...cells.map(line)])\n } catch (error) {\n logError(getErrorMessage(error))\n process.exitCode = 1\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAmBA,eAAsB,eAAe,EAAE,KAAK,YAAwE;CAClH,MAAM,CAAC,WAAW,WAAW,MAAM,QAAQ,IAAI,EAAA,GAC7CA,WAAAA,sBAAAA,CAAsB,EAAE,MAAM,IAAI,CAAC,GACnCC,iBAAAA,mBAAmB,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,UAAyC;EAC/E,eAAA,QAAQ,sCAAsCC,eAAAA,gBAAgB,KAAK,GAAG;EACtE,OAAO,CAAC;CACV,CAAC,CACH,CAAC;CACD,MAAM,YAAY,IAAI,IAAI,QAAQ,KAAK,UAAU,CAAC,MAAM,SAAS,SAAS,KAAK,CAAC,CAAC;CAEjF,OAAO,UAAU,SAAS,EAAE,SAAS,MAAM,SAAS,eAA+B;EACjF,MAAM,QAAQ,UAAU,IAAI,IAAI;EAChC,IAAI,CAAC,SAAS,CAAC,UAAU,OAAO,CAAC;EACjC,MAAM,SAAS,OAAO,SAAS;EAC/B,OAAO,CAAC;GAAE,IAAI,OAAO;GAAI,SAAS;GAAM,WAAW;GAAS,UAAU;GAAQ,QAAQ,CAAC,CAAC,UAAUC,iBAAAA,WAAW;IAAE,WAAW;IAAS;GAAO,CAAC;EAAE,CAAC;CAChJ,CAAC;AACH;;AAGA,eAAsB,MAAqB;CACzC,IAAI;EACF,MAAM,OAAO,MAAM,eAAe;GAAE,KAAKC,aAAAA,QAAQ,IAAI;GAAG,UAAUC,iBAAAA,YAAY;EAAE,CAAC;EACjF,IAAI,CAAC,KAAK,QAAQ;GAChB,eAAA,SAAS,gCAAgC;GACzC;EACF;EAEA,MAAM,SAAS;GAAC;GAAM;GAAW;GAAa;GAAY;EAAQ;EAClE,MAAM,QAAQ,KAAK,KAAK,QAAQ;GAAC,IAAI,MAAM;GAAK,IAAI;GAAS,IAAI,aAAa;GAAK,IAAI,YAAY;GAAK,IAAI,SAAS,QAAQ;EAAI,CAAC;EAClI,MAAM,SAAS,OAAO,KAAK,OAAO,UAAU,KAAK,IAAI,MAAM,QAAQ,GAAG,MAAM,KAAK,SAAS,KAAK,MAAM,CAAE,MAAM,CAAC,CAAC;EAC/G,MAAM,QAAQ,SACZ,KACG,KAAK,OAAO,UAAU,MAAM,OAAO,OAAO,MAAO,CAAC,CAAC,CACnD,KAAK,IAAI,CAAC,CACV,QAAQ;EAEb,eAAA,SAAS,EAAA,GAACC,UAAAA,UAAAA,CAAU,OAAO,KAAK,MAAM,CAAC,GAAG,GAAG,MAAM,IAAI,IAAI,CAAC,CAAC;CAC/D,SAAS,OAAO;EACd,eAAA,SAASJ,eAAAA,gBAAgB,KAAK,CAAC;EAC/B,aAAA,QAAA,WAAmB;CACrB;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./rolldown-runtime-CRm0XQPb.js";
|
|
2
2
|
import { n as toError } from "./errors-DmC83ALX.js";
|
|
3
|
-
import { n as trackRun } from "./Telemetry-
|
|
3
|
+
import { n as trackRun } from "./Telemetry-DxSvCR-R.js";
|
|
4
4
|
import { styleText } from "node:util";
|
|
5
5
|
import process from "node:process";
|
|
6
6
|
//#region src/runners/validate/run.ts
|
|
@@ -15,9 +15,7 @@ async function run({ input }) {
|
|
|
15
15
|
});
|
|
16
16
|
try {
|
|
17
17
|
const { adapterOas } = await import("@kubb/adapter-oas");
|
|
18
|
-
|
|
19
|
-
if (!adapter.validate) throw new Error("The loaded adapter does not support validation.");
|
|
20
|
-
await adapter.validate(input, { throwOnError: true });
|
|
18
|
+
await adapterOas().validate(input, { throwOnError: true });
|
|
21
19
|
await report({ status: "success" });
|
|
22
20
|
console.log("✅ Validation success");
|
|
23
21
|
} catch (error) {
|
|
@@ -39,4 +37,4 @@ async function run({ input }) {
|
|
|
39
37
|
//#endregion
|
|
40
38
|
export { run };
|
|
41
39
|
|
|
42
|
-
//# sourceMappingURL=run-
|
|
40
|
+
//# sourceMappingURL=run-DssKB_1f.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-DssKB_1f.js","names":[],"sources":["../src/runners/validate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { styleText } from 'node:util'\nimport { toError } from '@internals/utils'\nimport { trackRun } from '../../Telemetry.ts'\n\ntype ValidateOptions = {\n /**\n * Path or URL to the OpenAPI/Swagger file to validate.\n */\n input: string\n}\n\n/**\n * Validates an OpenAPI/Swagger file at `input` using `@kubb/adapter-oas`.\n * Exits the process with code 1 on validation failure or missing dependency.\n */\nexport async function run({ input }: ValidateOptions): Promise<void> {\n const report = trackRun({ command: 'validate', hrStart: process.hrtime() })\n\n try {\n const { adapterOas } = await import('@kubb/adapter-oas')\n\n await adapterOas().validate(input, { throwOnError: true })\n await report({ status: 'success' })\n\n console.log('✅ Validation success')\n } catch (error) {\n await report({ status: 'failed' })\n if (error instanceof Error && /@kubb\\/adapter-oas/.test(error.message)) {\n console.error(styleText('red', 'The @kubb/adapter-oas package is not installed.'))\n console.error('')\n console.error('Install it with:')\n console.error(styleText('cyan', ' npm install @kubb/adapter-oas'))\n console.error(styleText('cyan', ' # or'))\n console.error(styleText('cyan', ' pnpm install @kubb/adapter-oas'))\n console.error('')\n }\n console.error('❌ Validation failed')\n console.error(toError(error).message)\n\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;;;;;AAgBA,eAAsB,IAAI,EAAE,SAAyC;CACnE,MAAM,SAAS,SAAS;EAAE,SAAS;EAAY,SAAS,QAAQ,OAAO;CAAE,CAAC;CAE1E,IAAI;EACF,MAAM,EAAE,eAAe,MAAM,OAAO;EAEpC,MAAM,WAAW,CAAC,CAAC,SAAS,OAAO,EAAE,cAAc,KAAK,CAAC;EACzD,MAAM,OAAO,EAAE,QAAQ,UAAU,CAAC;EAElC,QAAQ,IAAI,sBAAsB;CACpC,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,IAAI,iBAAiB,SAAS,qBAAqB,KAAK,MAAM,OAAO,GAAG;GACtE,QAAQ,MAAM,UAAU,OAAO,iDAAiD,CAAC;GACjF,QAAQ,MAAM,EAAE;GAChB,QAAQ,MAAM,kBAAkB;GAChC,QAAQ,MAAM,UAAU,QAAQ,iCAAiC,CAAC;GAClE,QAAQ,MAAM,UAAU,QAAQ,QAAQ,CAAC;GACzC,QAAQ,MAAM,UAAU,QAAQ,kCAAkC,CAAC;GACnE,QAAQ,MAAM,EAAE;EAClB;EACA,QAAQ,MAAM,qBAAqB;EACnC,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC,OAAO;EAEpC,QAAQ,KAAK,CAAC;CAChB;AACF"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import "./rolldown-runtime-CRm0XQPb.js";
|
|
2
2
|
import { n as toError } from "./errors-DmC83ALX.js";
|
|
3
|
-
import { n as trackRun, r as version } from "./Telemetry-
|
|
4
|
-
import { n as getConfigs } from "./config-
|
|
5
|
-
import { _ as pluralize, a as logInfo, c as logSpacer, i as logError, l as logStep, n as logBanner, o as logIntro, s as logOutro, t as createSpinner, u as logTip } from "./output-
|
|
6
|
-
import { n as setupReporters, t as selectReporters } from "./reporters-
|
|
3
|
+
import { n as trackRun, r as version } from "./Telemetry-DxSvCR-R.js";
|
|
4
|
+
import { n as getConfigs } from "./config-B6UIKcl1.js";
|
|
5
|
+
import { _ as pluralize, a as logInfo, c as logSpacer, i as logError, l as logStep, n as logBanner, o as logIntro, s as logOutro, t as createSpinner, u as logTip } from "./output-qFt4vV7K.js";
|
|
6
|
+
import { n as setupReporters, t as selectReporters } from "./reporters-H21Jvrff.js";
|
|
7
|
+
import { a as isOutdated } from "./registry-B7BvdrGE.js";
|
|
7
8
|
import { styleText } from "node:util";
|
|
8
9
|
import process from "node:process";
|
|
9
10
|
import path from "node:path";
|
|
10
11
|
import { Diagnostics, Hookable, cliReporter, createKubb, fileReporter, getInputKind, htmlReporter, jsonReporter, logLevel, memoryStorage } from "@kubb/core";
|
|
11
|
-
import { isGreaterThan, isValid, truncate } from "verkit";
|
|
12
12
|
//#region src/runners/generate/utils.ts
|
|
13
13
|
/** Glob pattern for paths the file watcher ignores. */
|
|
14
14
|
const WATCHER_IGNORED_PATHS = "**/{.git,node_modules}/**";
|
|
@@ -22,21 +22,6 @@ const URL_WATCHER_INTERVAL_MS = 2e3;
|
|
|
22
22
|
/** Upper bound in milliseconds for one URL watcher request, headers and body read, so a hung server never stalls polling. */
|
|
23
23
|
const URL_WATCHER_TIMEOUT_MS = 1e4;
|
|
24
24
|
/**
|
|
25
|
-
* Returns `true` when `latest` is a newer semver version than `current`. Compares each numeric
|
|
26
|
-
* part, so `5.10.0` beats `5.9.0` where a plain string comparison would not. Prerelease
|
|
27
|
-
* suffixes are ignored, and a malformed version never reports an update.
|
|
28
|
-
*
|
|
29
|
-
* @example Double-digit minor
|
|
30
|
-
* `isNewerVersion('5.9.0', '5.10.0') // true`
|
|
31
|
-
*
|
|
32
|
-
* @example String comparison would get this wrong the other way
|
|
33
|
-
* `isNewerVersion('5.10.0', '5.9.0') // false`
|
|
34
|
-
*/
|
|
35
|
-
function isNewerVersion(current, latest) {
|
|
36
|
-
if (!isValid(current) || !isValid(latest)) return false;
|
|
37
|
-
return isGreaterThan(truncate(latest, "patch"), truncate(current, "patch"));
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
25
|
* Wraps `run` so invocations never overlap: a trigger that lands while a run is in flight
|
|
41
26
|
* marks it dirty and runs once more after it finishes, no matter how many triggers arrived.
|
|
42
27
|
* Useful for event-driven reruns (a file watcher, a queue drain) where bursts should
|
|
@@ -228,7 +213,10 @@ async function generate(options) {
|
|
|
228
213
|
async function checkForUpdate(hooks) {
|
|
229
214
|
try {
|
|
230
215
|
const data = await (await fetch(KUBB_NPM_PACKAGE_URL, { signal: AbortSignal.timeout(UPDATE_CHECK_TIMEOUT_MS) })).json();
|
|
231
|
-
if (data.version &&
|
|
216
|
+
if (data.version && isOutdated({
|
|
217
|
+
installed: version,
|
|
218
|
+
latest: data.version
|
|
219
|
+
})) await Diagnostics.emit(hooks, Diagnostics.update({
|
|
232
220
|
currentVersion: version,
|
|
233
221
|
latestVersion: data.version
|
|
234
222
|
}));
|
|
@@ -348,4 +336,4 @@ async function run({ input, configPath, logLevel: logLevelKey, watch, reporters:
|
|
|
348
336
|
//#endregion
|
|
349
337
|
export { run };
|
|
350
338
|
|
|
351
|
-
//# sourceMappingURL=run-
|
|
339
|
+
//# sourceMappingURL=run-N37yeEmo.js.map
|