@kubb/cli 5.11.3 → 5.11.5
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-DHf64JZ0.js → Telemetry-BlAR8vxu.js} +3 -31
- package/dist/Telemetry-BlAR8vxu.js.map +1 -0
- package/dist/{Telemetry-DyPhPm0f.cjs → Telemetry-CF1YNdR-.cjs} +2 -42
- package/dist/Telemetry-CF1YNdR-.cjs.map +1 -0
- package/dist/{background-qThnqeWn.cjs → background-CaZZul1n.cjs} +5 -4
- package/dist/background-CaZZul1n.cjs.map +1 -0
- package/dist/{background-Doe7_Wwo.js → background-DKyMPeHm.js} +7 -5
- package/dist/background-DKyMPeHm.js.map +1 -0
- package/dist/{background-5cHVRJLj.js → background-DUHqYiuQ.js} +1 -1
- package/dist/config-Bh00Hwpw.js +132 -0
- package/dist/config-Bh00Hwpw.js.map +1 -0
- package/dist/config-D63Gum4F.cjs +169 -0
- package/dist/config-D63Gum4F.cjs.map +1 -0
- package/dist/config-iVdOcpro.js +1 -0
- package/dist/credentials-CZK6zPLv.js.map +1 -1
- package/dist/credentials-DDaKqtJn.cjs.map +1 -1
- package/dist/errors-Cl69p_vI.cjs +43 -0
- package/dist/errors-Cl69p_vI.cjs.map +1 -0
- package/dist/errors-DmC83ALX.js +32 -0
- package/dist/errors-DmC83ALX.js.map +1 -0
- package/dist/index.cjs +874 -309
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +864 -299
- package/dist/index.js.map +1 -1
- package/dist/registry-CfYNeyOc.cjs +272 -0
- package/dist/registry-CfYNeyOc.cjs.map +1 -0
- package/dist/registry-D688-8EH.js +200 -0
- package/dist/registry-D688-8EH.js.map +1 -0
- package/dist/reporters-BHyW4d5Q.js +817 -0
- package/dist/reporters-BHyW4d5Q.js.map +1 -0
- package/dist/reporters-DrQJfnU2.cjs +829 -0
- package/dist/reporters-DrQJfnU2.cjs.map +1 -0
- package/dist/run-B4SKmzAG.js +1 -0
- package/dist/{run-_I3J6qxb.cjs → run-BldagXO-.cjs} +4 -3
- package/dist/{run-_I3J6qxb.cjs.map → run-BldagXO-.cjs.map} +1 -1
- package/dist/{run-CPDiH3Hm.js → run-C1FHgzNR.js} +3 -2
- package/dist/{run-CPDiH3Hm.js.map → run-C1FHgzNR.js.map} +1 -1
- package/dist/run-CYHpe0V_.cjs +227 -0
- package/dist/run-CYHpe0V_.cjs.map +1 -0
- package/dist/run-CaJbZO-f.cjs +94 -0
- package/dist/run-CaJbZO-f.cjs.map +1 -0
- package/dist/run-Cj-HJxYW.js +93 -0
- package/dist/run-Cj-HJxYW.js.map +1 -0
- package/dist/{run-D3JYO5Ha.cjs → run-DkBJkKor.cjs} +172 -76
- package/dist/run-DkBJkKor.cjs.map +1 -0
- package/dist/run-S3xKq4bj.js +224 -0
- package/dist/run-S3xKq4bj.js.map +1 -0
- package/dist/{run-DfCOkPNm.js → run-vBNko5TH.js} +166 -70
- package/dist/run-vBNko5TH.js.map +1 -0
- package/dist/{snapshot-DpaFwPrR.cjs → snapshot-CsIJRKEL.cjs} +51 -64
- package/dist/snapshot-CsIJRKEL.cjs.map +1 -0
- package/dist/{snapshot-C2znYElk.js → snapshot-Cvo94y5d.js} +49 -62
- package/dist/snapshot-Cvo94y5d.js.map +1 -0
- package/dist/status-C-NPN63r.cjs +78 -0
- package/dist/status-C-NPN63r.cjs.map +1 -0
- package/dist/status-DTsZxa5Y.js +77 -0
- package/dist/status-DTsZxa5Y.js.map +1 -0
- package/dist/studioWorker.js +2 -2
- package/dist/summary-C22oNZu_.cjs +46 -0
- package/dist/summary-C22oNZu_.cjs.map +1 -0
- package/dist/summary-F11HQput.js +41 -0
- package/dist/summary-F11HQput.js.map +1 -0
- package/dist/text-28DwO_5A.cjs +341 -0
- package/dist/text-28DwO_5A.cjs.map +1 -0
- package/dist/text-BThr2r0T.js +239 -0
- package/dist/text-BThr2r0T.js.map +1 -0
- package/dist/utils-BLXM2UkN.cjs +727 -0
- package/dist/utils-BLXM2UkN.cjs.map +1 -0
- package/dist/utils-Cv3YUnSi.js +612 -0
- package/dist/utils-Cv3YUnSi.js.map +1 -0
- package/package.json +7 -7
- package/dist/Telemetry-DHf64JZ0.js.map +0 -1
- package/dist/Telemetry-DyPhPm0f.cjs.map +0 -1
- package/dist/background-Doe7_Wwo.js.map +0 -1
- package/dist/background-qThnqeWn.cjs.map +0 -1
- package/dist/config-DJgo6i9_.cjs +0 -113
- package/dist/config-DJgo6i9_.cjs.map +0 -1
- package/dist/config-PG9NSJHL.js +0 -95
- package/dist/config-PG9NSJHL.js.map +0 -1
- package/dist/output-B4fjaKge.cjs +0 -1076
- package/dist/output-B4fjaKge.cjs.map +0 -1
- package/dist/output-B9XbFYXT.js +0 -937
- package/dist/output-B9XbFYXT.js.map +0 -1
- package/dist/registry-CUs-pcSk.js +0 -115
- package/dist/registry-CUs-pcSk.js.map +0 -1
- package/dist/registry-t78Mn8DF.cjs +0 -157
- package/dist/registry-t78Mn8DF.cjs.map +0 -1
- package/dist/run-BtNq-0P2.js +0 -39
- package/dist/run-BtNq-0P2.js.map +0 -1
- package/dist/run-CPhZVSrZ.js +0 -343
- package/dist/run-CPhZVSrZ.js.map +0 -1
- package/dist/run-D3JYO5Ha.cjs.map +0 -1
- package/dist/run-DfCOkPNm.js.map +0 -1
- package/dist/run-DvdBqT9o.cjs +0 -345
- package/dist/run-DvdBqT9o.cjs.map +0 -1
- package/dist/run-EyyX3vvP.js +0 -1
- package/dist/run-pM4T492F.cjs +0 -40
- package/dist/run-pM4T492F.cjs.map +0 -1
- package/dist/snapshot-C2znYElk.js.map +0 -1
- package/dist/snapshot-DpaFwPrR.cjs.map +0 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import "./rolldown-runtime-CRm0XQPb.js";
|
|
2
|
+
import { n as toError } from "./errors-DmC83ALX.js";
|
|
3
|
+
import { n as trackRun } from "./Telemetry-BlAR8vxu.js";
|
|
4
|
+
import { t as pluralize } from "./text-BThr2r0T.js";
|
|
5
|
+
import { n as findConfigFile, t as getConfigs } from "./config-Bh00Hwpw.js";
|
|
6
|
+
import { t as logCommandSummary } from "./summary-F11HQput.js";
|
|
7
|
+
import { styleText } from "node:util";
|
|
8
|
+
import process from "node:process";
|
|
9
|
+
import { resolve } from "node:path";
|
|
10
|
+
//#region src/runners/validate/run.ts
|
|
11
|
+
/**
|
|
12
|
+
* Validates `input` with the configured adapters, falling back to OpenAPI when no config exists.
|
|
13
|
+
* Exits the process with code 1 on validation failure or missing dependency.
|
|
14
|
+
*/
|
|
15
|
+
async function run({ input, configPath }) {
|
|
16
|
+
const hrStart = process.hrtime();
|
|
17
|
+
const report = trackRun({
|
|
18
|
+
command: "validate",
|
|
19
|
+
hrStart
|
|
20
|
+
});
|
|
21
|
+
let adapterName;
|
|
22
|
+
try {
|
|
23
|
+
const configFile = configPath ?? findConfigFile();
|
|
24
|
+
const loaded = configFile ? await getConfigs({
|
|
25
|
+
configPath: configFile,
|
|
26
|
+
input
|
|
27
|
+
}).catch((error) => {
|
|
28
|
+
if (configPath) throw error;
|
|
29
|
+
}) : void 0;
|
|
30
|
+
const fallback = async () => {
|
|
31
|
+
adapterName = "@kubb/adapter-oas";
|
|
32
|
+
const { adapterOas } = await import("@kubb/adapter-oas");
|
|
33
|
+
return [{
|
|
34
|
+
adapter: adapterOas(),
|
|
35
|
+
input
|
|
36
|
+
}];
|
|
37
|
+
};
|
|
38
|
+
const unique = new Map((loaded?.configs ?? []).map((config) => {
|
|
39
|
+
const resolved = URL.canParse(input) ? input : resolve(config.root || process.cwd(), input);
|
|
40
|
+
return [`${config.adapter?.name}\0${resolved}`, {
|
|
41
|
+
adapter: config.adapter,
|
|
42
|
+
input: resolved
|
|
43
|
+
}];
|
|
44
|
+
}));
|
|
45
|
+
const targets = loaded ? [...unique.values()] : await fallback();
|
|
46
|
+
if (!targets.length) throw new Error("The Kubb config contains no configurations to validate.");
|
|
47
|
+
for (const target of targets) {
|
|
48
|
+
adapterName = target.adapter?.name;
|
|
49
|
+
if (!target.adapter) throw new Error("No adapter is configured. Set adapter in your Kubb config to validate this specification.");
|
|
50
|
+
await target.adapter.validate(target.input, { throwOnError: true });
|
|
51
|
+
}
|
|
52
|
+
const specifications = new Set(targets.map((target) => target.input)).size;
|
|
53
|
+
const adapterNames = [...new Set(targets.flatMap((target) => target.adapter?.name ?? []))];
|
|
54
|
+
await report({ status: "success" });
|
|
55
|
+
logCommandSummary({
|
|
56
|
+
title: "Validation passed",
|
|
57
|
+
status: "success",
|
|
58
|
+
hrStart,
|
|
59
|
+
lines: [
|
|
60
|
+
` ${styleText("bold", `${pluralize(specifications, "specification")} validated`)}`,
|
|
61
|
+
` ${styleText("dim", "Input")} ${styleText("cyan", input)}`,
|
|
62
|
+
` ${styleText("dim", adapterNames.length === 1 ? "Adapter" : "Adapters")} ${adapterNames.join(", ")}`
|
|
63
|
+
]
|
|
64
|
+
});
|
|
65
|
+
} catch (error) {
|
|
66
|
+
await report({ status: "failed" });
|
|
67
|
+
const message = toError(error).message;
|
|
68
|
+
const missingAdapter = adapterName === "@kubb/adapter-oas" && /(?:Cannot find|Cannot resolve|not found)[\s\S]*@kubb\/adapter-oas/.test(message);
|
|
69
|
+
logCommandSummary({
|
|
70
|
+
title: missingAdapter ? "Could not validate" : "Validation failed",
|
|
71
|
+
status: "failed",
|
|
72
|
+
hrStart,
|
|
73
|
+
lines: [
|
|
74
|
+
` ${styleText("dim", "Input")} ${styleText("cyan", input)}`,
|
|
75
|
+
` ${styleText("dim", "Adapter")} ${adapterName ?? "not configured"}${missingAdapter ? " · not installed" : ""}`,
|
|
76
|
+
"",
|
|
77
|
+
styleText("bold", missingAdapter ? "Required package" : "Validation error"),
|
|
78
|
+
` ${styleText("red", message)}`,
|
|
79
|
+
...missingAdapter ? [
|
|
80
|
+
"",
|
|
81
|
+
"Install it with:",
|
|
82
|
+
styleText("cyan", " npm install @kubb/adapter-oas"),
|
|
83
|
+
styleText("cyan", " pnpm add @kubb/adapter-oas")
|
|
84
|
+
] : []
|
|
85
|
+
]
|
|
86
|
+
});
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
export { run };
|
|
92
|
+
|
|
93
|
+
//# sourceMappingURL=run-Cj-HJxYW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-Cj-HJxYW.js","names":[],"sources":["../src/runners/validate/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { resolve } from 'node:path'\nimport { styleText } from 'node:util'\nimport { findConfigFile } from '@internals/shared'\nimport { toError } from '@internals/utils'\nimport type { Config } from '@kubb/core'\nimport { trackRun } from '../../Telemetry.ts'\nimport { getConfigs } from '../../config.ts'\nimport { pluralize } from '../../ui/text.ts'\nimport { logCommandSummary } from '../../ui/summary.ts'\n\ntype ValidateOptions = {\n /**\n * Path or URL to the specification to validate.\n */\n input: string\n configPath?: string\n}\n\n/**\n * Validates `input` with the configured adapters, falling back to OpenAPI when no config exists.\n * Exits the process with code 1 on validation failure or missing dependency.\n */\nexport async function run({ input, configPath }: ValidateOptions): Promise<void> {\n const hrStart = process.hrtime()\n const report = trackRun({ command: 'validate', hrStart })\n let adapterName: string | undefined\n\n try {\n const configFile = configPath ?? findConfigFile()\n // A config found by search that does not load must not block validating a file; an explicit `--config` still fails.\n const loaded = configFile\n ? await getConfigs({ configPath: configFile, input }).catch((error) => {\n if (configPath) throw error\n })\n : undefined\n const fallback = async () => {\n adapterName = '@kubb/adapter-oas'\n const { adapterOas } = await import('@kubb/adapter-oas')\n return [{ adapter: adapterOas(), input }]\n }\n // An array config often repeats one adapter, so each adapter and input pair is validated once.\n const unique = new Map(\n (loaded?.configs ?? []).map((config) => {\n const resolved = URL.canParse(input) ? input : resolve(config.root || process.cwd(), input)\n return [`${config.adapter?.name}\\0${resolved}`, { adapter: config.adapter, input: resolved }] as const\n }),\n )\n const targets: Array<{ adapter: Config['adapter']; input: string }> = loaded ? [...unique.values()] : await fallback()\n if (!targets.length) throw new Error('The Kubb config contains no configurations to validate.')\n for (const target of targets) {\n adapterName = target.adapter?.name\n if (!target.adapter) throw new Error('No adapter is configured. Set adapter in your Kubb config to validate this specification.')\n await target.adapter.validate(target.input, { throwOnError: true })\n }\n const specifications = new Set(targets.map((target) => target.input)).size\n const adapterNames = [...new Set(targets.flatMap((target) => target.adapter?.name ?? []))]\n await report({ status: 'success' })\n\n logCommandSummary({\n title: 'Validation passed',\n status: 'success',\n hrStart,\n lines: [\n ` ${styleText('bold', `${pluralize(specifications, 'specification')} validated`)}`,\n ` ${styleText('dim', 'Input')} ${styleText('cyan', input)}`,\n ` ${styleText('dim', adapterNames.length === 1 ? 'Adapter' : 'Adapters')} ${adapterNames.join(', ')}`,\n ],\n })\n } catch (error) {\n await report({ status: 'failed' })\n const message = toError(error).message\n const missingAdapter = adapterName === '@kubb/adapter-oas' && /(?:Cannot find|Cannot resolve|not found)[\\s\\S]*@kubb\\/adapter-oas/.test(message)\n logCommandSummary({\n title: missingAdapter ? 'Could not validate' : 'Validation failed',\n status: 'failed',\n hrStart,\n lines: [\n ` ${styleText('dim', 'Input')} ${styleText('cyan', input)}`,\n ` ${styleText('dim', 'Adapter')} ${adapterName ?? 'not configured'}${missingAdapter ? ' · not installed' : ''}`,\n '',\n styleText('bold', missingAdapter ? 'Required package' : 'Validation error'),\n ` ${styleText('red', message)}`,\n ...(missingAdapter\n ? ['', 'Install it with:', styleText('cyan', ' npm install @kubb/adapter-oas'), styleText('cyan', ' pnpm add @kubb/adapter-oas')]\n : []),\n ],\n })\n\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAuBA,eAAsB,IAAI,EAAE,OAAO,cAA8C;CAC/E,MAAM,UAAU,QAAQ,OAAO;CAC/B,MAAM,SAAS,SAAS;EAAE,SAAS;EAAY;CAAQ,CAAC;CACxD,IAAI;CAEJ,IAAI;EACF,MAAM,aAAa,cAAc,eAAe;EAEhD,MAAM,SAAS,aACX,MAAM,WAAW;GAAE,YAAY;GAAY;EAAM,CAAC,CAAC,CAAC,OAAO,UAAU;GACnE,IAAI,YAAY,MAAM;EACxB,CAAC,IACD,KAAA;EACJ,MAAM,WAAW,YAAY;GAC3B,cAAc;GACd,MAAM,EAAE,eAAe,MAAM,OAAO;GACpC,OAAO,CAAC;IAAE,SAAS,WAAW;IAAG;GAAM,CAAC;EAC1C;EAEA,MAAM,SAAS,IAAI,KAChB,QAAQ,WAAW,CAAC,EAAA,CAAG,KAAK,WAAW;GACtC,MAAM,WAAW,IAAI,SAAS,KAAK,IAAI,QAAQ,QAAQ,OAAO,QAAQ,QAAQ,IAAI,GAAG,KAAK;GAC1F,OAAO,CAAC,GAAG,OAAO,SAAS,KAAK,IAAI,YAAY;IAAE,SAAS,OAAO;IAAS,OAAO;GAAS,CAAC;EAC9F,CAAC,CACH;EACA,MAAM,UAAgE,SAAS,CAAC,GAAG,OAAO,OAAO,CAAC,IAAI,MAAM,SAAS;EACrH,IAAI,CAAC,QAAQ,QAAQ,MAAM,IAAI,MAAM,yDAAyD;EAC9F,KAAK,MAAM,UAAU,SAAS;GAC5B,cAAc,OAAO,SAAS;GAC9B,IAAI,CAAC,OAAO,SAAS,MAAM,IAAI,MAAM,2FAA2F;GAChI,MAAM,OAAO,QAAQ,SAAS,OAAO,OAAO,EAAE,cAAc,KAAK,CAAC;EACpE;EACA,MAAM,iBAAiB,IAAI,IAAI,QAAQ,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC,CAAC;EACtE,MAAM,eAAe,CAAC,GAAG,IAAI,IAAI,QAAQ,SAAS,WAAW,OAAO,SAAS,QAAQ,CAAC,CAAC,CAAC,CAAC;EACzF,MAAM,OAAO,EAAE,QAAQ,UAAU,CAAC;EAElC,kBAAkB;GAChB,OAAO;GACP,QAAQ;GACR;GACA,OAAO;IACL,KAAK,UAAU,QAAQ,GAAG,UAAU,gBAAgB,eAAe,EAAE,WAAW;IAChF,KAAK,UAAU,OAAO,OAAO,EAAE,MAAM,UAAU,QAAQ,KAAK;IAC5D,KAAK,UAAU,OAAO,aAAa,WAAW,IAAI,YAAY,UAAU,EAAE,IAAI,aAAa,KAAK,IAAI;GACtG;EACF,CAAC;CACH,SAAS,OAAO;EACd,MAAM,OAAO,EAAE,QAAQ,SAAS,CAAC;EACjC,MAAM,UAAU,QAAQ,KAAK,CAAC,CAAC;EAC/B,MAAM,iBAAiB,gBAAgB,uBAAuB,oEAAoE,KAAK,OAAO;EAC9I,kBAAkB;GAChB,OAAO,iBAAiB,uBAAuB;GAC/C,QAAQ;GACR;GACA,OAAO;IACL,KAAK,UAAU,OAAO,OAAO,EAAE,MAAM,UAAU,QAAQ,KAAK;IAC5D,KAAK,UAAU,OAAO,SAAS,EAAE,IAAI,eAAe,mBAAmB,iBAAiB,qBAAqB;IAC7G;IACA,UAAU,QAAQ,iBAAiB,qBAAqB,kBAAkB;IAC1E,KAAK,UAAU,OAAO,OAAO;IAC7B,GAAI,iBACA;KAAC;KAAI;KAAoB,UAAU,QAAQ,iCAAiC;KAAG,UAAU,QAAQ,8BAA8B;IAAC,IAChI,CAAC;GACP;EACF,CAAC;EAED,QAAQ,KAAK,CAAC;CAChB;AACF"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const require_rolldown_runtime = require("./rolldown-runtime-CPE0t6oh.cjs");
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
2
|
+
const require_errors = require("./errors-Cl69p_vI.cjs");
|
|
3
|
+
const require_Telemetry = require("./Telemetry-CF1YNdR-.cjs");
|
|
4
|
+
const require_utils = require("./utils-BLXM2UkN.cjs");
|
|
5
|
+
const require_text = require("./text-28DwO_5A.cjs");
|
|
6
|
+
const require_config = require("./config-D63Gum4F.cjs");
|
|
7
|
+
const require_reporters = require("./reporters-DrQJfnU2.cjs");
|
|
5
8
|
const require_credentials = require("./credentials-DDaKqtJn.cjs");
|
|
6
9
|
let node_util = require("node:util");
|
|
7
10
|
let node_os = require("node:os");
|
|
@@ -10,11 +13,42 @@ node_process = require_rolldown_runtime.__toESM(node_process, 1);
|
|
|
10
13
|
let tinyexec = require("tinyexec");
|
|
11
14
|
let node_path = require("node:path");
|
|
12
15
|
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
13
|
-
let _kubb_core = require("@kubb/core");
|
|
14
16
|
let _clack_prompts = require("@clack/prompts");
|
|
15
17
|
_clack_prompts = require_rolldown_runtime.__toESM(_clack_prompts, 1);
|
|
18
|
+
let _kubb_core = require("@kubb/core");
|
|
16
19
|
let _kubb_studio = require("@kubb/studio");
|
|
17
20
|
let _kubb_studio_protocol = require("@kubb/studio/protocol");
|
|
21
|
+
//#region ../../internals/utils/src/copyToClipboard.ts
|
|
22
|
+
const COMMANDS = {
|
|
23
|
+
darwin: ["pbcopy"],
|
|
24
|
+
win32: ["clip.exe"],
|
|
25
|
+
linux: [
|
|
26
|
+
"xclip",
|
|
27
|
+
"-selection",
|
|
28
|
+
"clipboard"
|
|
29
|
+
]
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Copies text to the system clipboard with the platform's own tool. Resolves `false` in CI, on a
|
|
33
|
+
* platform without a known tool, or when the tool is missing or fails.
|
|
34
|
+
*/
|
|
35
|
+
async function copyToClipboard(text) {
|
|
36
|
+
const command = node_process.default.platform === "linux" && node_process.default.env.WAYLAND_DISPLAY ? ["wl-copy"] : COMMANDS[node_process.default.platform];
|
|
37
|
+
if (!command || require_Telemetry.isCIEnvironment()) return false;
|
|
38
|
+
const [name, ...args] = command;
|
|
39
|
+
const run = (0, tinyexec.x)(name, args, {
|
|
40
|
+
timeout: 2e3,
|
|
41
|
+
nodeOptions: { stdio: [
|
|
42
|
+
"pipe",
|
|
43
|
+
"ignore",
|
|
44
|
+
"ignore"
|
|
45
|
+
] }
|
|
46
|
+
});
|
|
47
|
+
run.process?.stdin?.once("error", () => {});
|
|
48
|
+
run.process?.stdin?.end(text);
|
|
49
|
+
return run.then(({ exitCode }) => exitCode === 0, () => false);
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
18
52
|
//#region ../../internals/utils/src/openInBrowser.ts
|
|
19
53
|
const ignore = () => {};
|
|
20
54
|
/**
|
|
@@ -43,8 +77,10 @@ function openInBrowser(target) {
|
|
|
43
77
|
* server log, or a `Referer` header.
|
|
44
78
|
*/
|
|
45
79
|
async function login({ studioUrl, autoOpen }, { signal, previousCredentials } = {}) {
|
|
46
|
-
const spinner =
|
|
80
|
+
const spinner = require_utils.createSpinner();
|
|
81
|
+
let retryUntil = 0;
|
|
47
82
|
let waiting = false;
|
|
83
|
+
let countdown;
|
|
48
84
|
try {
|
|
49
85
|
const { token, agent } = await (0, _kubb_studio.pairAgent)({
|
|
50
86
|
studioUrl,
|
|
@@ -54,99 +90,123 @@ async function login({ studioUrl, autoOpen }, { signal, previousCredentials } =
|
|
|
54
90
|
machineId: await require_credentials.getMachineId(),
|
|
55
91
|
signal,
|
|
56
92
|
onCode: (session) => {
|
|
57
|
-
|
|
93
|
+
require_text.logStep([
|
|
94
|
+
"Pair this machine",
|
|
95
|
+
`${(0, node_util.styleText)("dim", "Open")} ${(0, node_util.styleText)("cyan", session.verification_uri)}`,
|
|
96
|
+
`${(0, node_util.styleText)("dim", "Code")} ${(0, node_util.styleText)("bold", session.user_code)}`
|
|
97
|
+
].join("\n"));
|
|
58
98
|
if (autoOpen) openInBrowser(session.verification_uri_complete);
|
|
59
|
-
|
|
99
|
+
const deadline = Date.now() + (session.expires_in > 0 ? session.expires_in : 600) * 1e3;
|
|
100
|
+
let copied = false;
|
|
101
|
+
const waitingText = () => `Waiting for approval ${(0, node_util.styleText)("dim", `expires in ${formatCountdown(deadline - Date.now())}${copied ? " · code copied" : ""} · ctrl+c to cancel`)}`;
|
|
102
|
+
clearInterval(countdown);
|
|
103
|
+
spinner.start(waitingText());
|
|
60
104
|
waiting = true;
|
|
105
|
+
if (require_text.isRichOutput()) countdown = setInterval(() => Date.now() > retryUntil && spinner.message(waitingText()), 1e3);
|
|
106
|
+
copyToClipboard(session.user_code).then((done) => {
|
|
107
|
+
copied = done;
|
|
108
|
+
});
|
|
61
109
|
},
|
|
62
|
-
onRetry: (error) =>
|
|
110
|
+
onRetry: (error) => {
|
|
111
|
+
retryUntil = Date.now() + 5e3;
|
|
112
|
+
spinner.message(`Could not reach Kubb Studio, retrying: ${error.message}`);
|
|
113
|
+
}
|
|
63
114
|
});
|
|
64
|
-
|
|
115
|
+
clearInterval(countdown);
|
|
116
|
+
spinner.stop(`Paired as ${agent.name}${agent.organizationSlug ? ` · org ${agent.organizationSlug}` : ""}`);
|
|
65
117
|
const keepsIdentity = previousCredentials?.studioUrl === studioUrl && previousCredentials.agentId === agent.id;
|
|
66
118
|
const credentials = {
|
|
67
119
|
studioUrl,
|
|
68
120
|
token,
|
|
69
121
|
agentId: agent.id,
|
|
70
122
|
agentSlug: agent.slug,
|
|
123
|
+
...agent.organizationSlug ? { organizationSlug: agent.organizationSlug } : {},
|
|
71
124
|
...keepsIdentity && previousCredentials?.projects ? { projects: previousCredentials.projects } : {}
|
|
72
125
|
};
|
|
73
126
|
await require_credentials.writeCredentials(credentials);
|
|
74
127
|
console.log(`Credentials stored in ${require_credentials.getCredentialsPath()}`);
|
|
75
128
|
return credentials;
|
|
76
129
|
} catch (error) {
|
|
130
|
+
clearInterval(countdown);
|
|
77
131
|
if (waiting) spinner.stop(error instanceof _kubb_studio.PairingCanceledError ? "Pairing canceled" : "Pairing failed");
|
|
78
132
|
throw error;
|
|
79
133
|
}
|
|
80
134
|
}
|
|
135
|
+
/** Time left on a pairing code as `m:ss`, never below `0:00`. */
|
|
136
|
+
function formatCountdown(ms) {
|
|
137
|
+
const seconds = Math.max(0, Math.ceil(ms / 1e3));
|
|
138
|
+
return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, "0")}`;
|
|
139
|
+
}
|
|
81
140
|
/**
|
|
82
|
-
* What each permission is asked as, in the order the
|
|
141
|
+
* What each permission is asked as, in the order the list shows them.
|
|
83
142
|
*/
|
|
84
143
|
const PERMISSIONS = [
|
|
85
144
|
{
|
|
86
145
|
key: _kubb_studio_protocol.AgentPermission.READ,
|
|
87
|
-
label: "read
|
|
88
|
-
|
|
146
|
+
label: "read source",
|
|
147
|
+
title: () => "Read generated files",
|
|
148
|
+
hint: "show code in the browser"
|
|
89
149
|
},
|
|
90
150
|
{
|
|
91
151
|
key: _kubb_studio_protocol.AgentPermission.READ_AST,
|
|
92
|
-
label: "read
|
|
93
|
-
|
|
152
|
+
label: "read spec",
|
|
153
|
+
title: () => "Read the parsed spec",
|
|
154
|
+
hint: "browse schemas and operations"
|
|
94
155
|
},
|
|
95
156
|
{
|
|
96
157
|
key: _kubb_studio_protocol.AgentPermission.WRITE,
|
|
97
|
-
label: "write
|
|
98
|
-
|
|
158
|
+
label: "write files",
|
|
159
|
+
title: () => "Write files to disk",
|
|
160
|
+
hint: "generate from the browser"
|
|
99
161
|
},
|
|
100
162
|
{
|
|
101
163
|
key: _kubb_studio_protocol.AgentPermission.CONFIG_EDIT,
|
|
102
|
-
label: "edit
|
|
103
|
-
|
|
164
|
+
label: "edit config",
|
|
165
|
+
title: (configPath) => `Change ${configPath}`,
|
|
166
|
+
hint: "edit plugin options"
|
|
104
167
|
},
|
|
105
168
|
{
|
|
106
169
|
key: _kubb_studio_protocol.AgentPermission.EXEC,
|
|
107
|
-
label: "run
|
|
108
|
-
|
|
170
|
+
label: "run tools",
|
|
171
|
+
title: () => "Run the formatter, linter, and postGenerate",
|
|
172
|
+
hint: "after each generation"
|
|
109
173
|
}
|
|
110
174
|
];
|
|
111
175
|
/**
|
|
112
|
-
*
|
|
113
|
-
*
|
|
176
|
+
* Two permissions per row, each marked granted or not, with the flags that grant the missing ones
|
|
177
|
+
* after the last row. For `kubb studio status`.
|
|
114
178
|
*/
|
|
115
179
|
function formatPermissionRows(granted) {
|
|
116
|
-
|
|
180
|
+
const width = Math.max(...PERMISSIONS.map(({ label }) => label.length));
|
|
181
|
+
const cells = PERMISSIONS.map(({ key, label }) => `${granted[key] ? (0, node_util.styleText)("green", "✓") : (0, node_util.styleText)("red", "✖")} ${label.padEnd(width)}`);
|
|
182
|
+
const rows = Array.from({ length: Math.ceil(cells.length / 2) }, (_, index) => cells.slice(index * 2, index * 2 + 2).join(" "));
|
|
183
|
+
const flags = PERMISSIONS.filter(({ key }) => !granted[key]).map(({ key }) => require_text.toPermissionFlag(key)).join(" ");
|
|
184
|
+
return flags ? [...rows.slice(0, -1), `${rows.at(-1)} ${(0, node_util.styleText)("dim", flags)}`] : rows;
|
|
117
185
|
}
|
|
118
186
|
/**
|
|
119
187
|
* Resolves Studio permissions for the current project.
|
|
120
|
-
* Flags win, saved answers are reused, and
|
|
188
|
+
* Flags win, saved answers are reused, and the rest are asked in one list whose answers are stored
|
|
189
|
+
* in `~/.kubb/credentials.json`.
|
|
121
190
|
*/
|
|
122
|
-
async function resolvePermissions(options, credentials, configPath =
|
|
191
|
+
async function resolvePermissions(options, credentials, configPath = require_config.KUBB_CONFIG_FILENAME) {
|
|
123
192
|
const project = node_process.default.cwd();
|
|
124
193
|
const remembered = credentials.projects?.[project];
|
|
125
|
-
const granted = {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
allowWrite: false,
|
|
129
|
-
allowConfigEdit: false,
|
|
130
|
-
allowExec: false
|
|
131
|
-
};
|
|
132
|
-
const answers = {};
|
|
194
|
+
const granted = Object.fromEntries(PERMISSIONS.map(({ key }) => [key, options.permission[key] || remembered?.[key] === true]));
|
|
195
|
+
const pending = PERMISSIONS.filter(({ key }) => !options.permission[key] && typeof remembered?.[key] !== "boolean");
|
|
196
|
+
if (!pending.length || require_Telemetry.isCIEnvironment() || !require_text.canUseTTY()) return granted;
|
|
133
197
|
_clack_prompts.updateSettings({ withGuide: true });
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}) === true;
|
|
147
|
-
answers[key] = granted[key];
|
|
148
|
-
}
|
|
149
|
-
if (Object.keys(answers).length) await require_credentials.writeCredentials({
|
|
198
|
+
const selected = await _clack_prompts.multiselect({
|
|
199
|
+
message: "What may Kubb Studio do in this project?",
|
|
200
|
+
options: pending.map(({ key, title, hint }) => ({
|
|
201
|
+
value: key,
|
|
202
|
+
label: title(configPath),
|
|
203
|
+
hint
|
|
204
|
+
})),
|
|
205
|
+
required: false
|
|
206
|
+
});
|
|
207
|
+
if (_clack_prompts.isCancel(selected)) return granted;
|
|
208
|
+
const answers = Object.fromEntries(pending.map(({ key }) => [key, selected.includes(key)]));
|
|
209
|
+
await require_credentials.writeCredentials({
|
|
150
210
|
...credentials,
|
|
151
211
|
projects: {
|
|
152
212
|
...credentials.projects,
|
|
@@ -156,7 +216,10 @@ async function resolvePermissions(options, credentials, configPath = require_out
|
|
|
156
216
|
}
|
|
157
217
|
}
|
|
158
218
|
});
|
|
159
|
-
return
|
|
219
|
+
return {
|
|
220
|
+
...granted,
|
|
221
|
+
...answers
|
|
222
|
+
};
|
|
160
223
|
}
|
|
161
224
|
/**
|
|
162
225
|
* Loads the project's Kubb config the same way `kubb generate` does.
|
|
@@ -178,14 +241,6 @@ async function loadConfigs(options) {
|
|
|
178
241
|
config
|
|
179
242
|
};
|
|
180
243
|
}
|
|
181
|
-
/**
|
|
182
|
-
* Explains a rejected token to the operator. Builds the error and nothing else, so each caller
|
|
183
|
-
* decides what happens to the credentials.
|
|
184
|
-
*/
|
|
185
|
-
function explainRejectedToken(error, reason) {
|
|
186
|
-
if (reason === "reauthExhausted") return /* @__PURE__ */ new Error(`${error.message} Studio rejected the newly approved token too. Run \`kubb studio login\` and try again.`);
|
|
187
|
-
return /* @__PURE__ */ new Error(`${error.message} Run \`kubb studio login\` to pair again.`);
|
|
188
|
-
}
|
|
189
244
|
/** Validates the project and resolves pairing and permissions before starting its worker. */
|
|
190
245
|
async function prepareConnection(options, signal) {
|
|
191
246
|
const { configPath } = await loadConfigs(options);
|
|
@@ -215,9 +270,10 @@ async function connect(options, context = {}) {
|
|
|
215
270
|
events.once("SIGINT", stop);
|
|
216
271
|
events.once("SIGTERM", stop);
|
|
217
272
|
}
|
|
273
|
+
let unwatch;
|
|
218
274
|
try {
|
|
219
275
|
if (!context.prepared) {
|
|
220
|
-
const { getWorkerStatus } = await Promise.resolve().then(() => require("./background-
|
|
276
|
+
const { getWorkerStatus } = await Promise.resolve().then(() => require("./background-CaZZul1n.cjs"));
|
|
221
277
|
if ((await getWorkerStatus()).running) throw new _kubb_core.Diagnostics.Error({
|
|
222
278
|
code: _kubb_core.Diagnostics.code.unknown,
|
|
223
279
|
severity: "error",
|
|
@@ -230,18 +286,27 @@ async function connect(options, context = {}) {
|
|
|
230
286
|
let hinted = false;
|
|
231
287
|
let pairedAgain = false;
|
|
232
288
|
const hooks = new _kubb_core.Hookable();
|
|
233
|
-
|
|
289
|
+
require_reporters.setupReporters(hooks, {
|
|
234
290
|
logLevel: _kubb_core.logLevel[options.logLevel ?? "info"],
|
|
235
291
|
reporters: [_kubb_core.cliReporter],
|
|
236
|
-
...context.onState ? {
|
|
292
|
+
...context.onState ? { writer: require_text.plainWriter } : {}
|
|
237
293
|
});
|
|
294
|
+
const listens = !context.onState && node_process.default.stdin.isTTY === true && require_text.canUseTTY();
|
|
295
|
+
let background = false;
|
|
238
296
|
hooks.hook("studio:connected", async () => {
|
|
239
297
|
pairedAgain = false;
|
|
240
298
|
await context.onState?.("connected");
|
|
299
|
+
if (listens && !unwatch) unwatch = watchKeys({
|
|
300
|
+
onBackground: () => {
|
|
301
|
+
background = true;
|
|
302
|
+
stop();
|
|
303
|
+
},
|
|
304
|
+
onStop: stop
|
|
305
|
+
});
|
|
241
306
|
if (hinted || context.onState || options.logLevel === "silent") return;
|
|
242
307
|
hinted = true;
|
|
243
|
-
|
|
244
|
-
|
|
308
|
+
require_text.logBlock([`${(0, node_util.styleText)("dim", "Project")} ${node_path.default.basename(node_process.default.cwd())} ${(0, node_util.styleText)("dim", PERMISSIONS.filter(({ key }) => permissions[key]).map(({ label }) => label).join(" · ") || "no permissions")}`, (0, node_util.styleText)("dim", listens ? "Press b to keep running in the background, Ctrl+C to disconnect" : "Press Ctrl+C to disconnect")]);
|
|
309
|
+
require_text.logTip();
|
|
245
310
|
});
|
|
246
311
|
hooks.hook("studio:reconnecting", () => context.onState?.("reconnecting"));
|
|
247
312
|
for (;;) try {
|
|
@@ -261,8 +326,10 @@ async function connect(options, context = {}) {
|
|
|
261
326
|
if (!(error instanceof _kubb_studio.InvalidAgentTokenError)) throw error;
|
|
262
327
|
await context.onState?.("authentication required");
|
|
263
328
|
await require_credentials.clearCredentials();
|
|
264
|
-
if (pairedAgain) throw
|
|
265
|
-
if (context.onState || require_Telemetry.isCIEnvironment() || !
|
|
329
|
+
if (pairedAgain) throw new Error(`${error.message} Studio rejected the newly approved token too. Run \`kubb studio login\` and try again.`);
|
|
330
|
+
if (context.onState || require_Telemetry.isCIEnvironment() || !require_text.canUseTTY()) throw new Error(`${error.message} Run \`kubb studio login\` to pair again.`);
|
|
331
|
+
unwatch?.();
|
|
332
|
+
unwatch = void 0;
|
|
266
333
|
console.log((0, node_util.styleText)("yellow", `${error.message} Pairing again...`));
|
|
267
334
|
credentials = await login(options, {
|
|
268
335
|
signal,
|
|
@@ -271,15 +338,50 @@ async function connect(options, context = {}) {
|
|
|
271
338
|
pairedAgain = true;
|
|
272
339
|
permissions = await resolvePermissions(options, credentials, configPath);
|
|
273
340
|
}
|
|
274
|
-
|
|
341
|
+
await hooks.callHook("kubb:lifecycle:end");
|
|
342
|
+
unwatch?.();
|
|
343
|
+
if (background) {
|
|
344
|
+
const { startWorker } = await Promise.resolve().then(() => require("./background-CaZZul1n.cjs"));
|
|
345
|
+
await startWorker(options);
|
|
346
|
+
if (options.logLevel !== "silent") require_text.logOutro("Running in the background · kubb studio stop");
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
if (!context.onState && signal.aborted && options.logLevel !== "silent") require_text.logOutro("Disconnected");
|
|
275
350
|
} catch (error) {
|
|
276
351
|
if (!(error instanceof _kubb_studio.PairingCanceledError)) throw error;
|
|
277
352
|
} finally {
|
|
353
|
+
unwatch?.();
|
|
278
354
|
events.off("SIGINT", stop);
|
|
279
355
|
events.off("SIGTERM", stop);
|
|
280
356
|
}
|
|
281
357
|
}
|
|
282
358
|
/**
|
|
359
|
+
* Listens for single keys on a TTY stdin. Raw mode turns Ctrl+C into a key instead of SIGINT, so it
|
|
360
|
+
* is handled here too. Returns the function that restores the terminal, safe to call twice.
|
|
361
|
+
*/
|
|
362
|
+
function watchKeys({ onBackground, onStop }) {
|
|
363
|
+
const stdin = node_process.default.stdin;
|
|
364
|
+
const onData = (data) => {
|
|
365
|
+
const key = data.toString();
|
|
366
|
+
if (key === "b" || key === "B") onBackground();
|
|
367
|
+
if (key === "") onStop();
|
|
368
|
+
};
|
|
369
|
+
const cancelAlias = _clack_prompts.settings.aliases.get("");
|
|
370
|
+
_clack_prompts.settings.aliases.delete("");
|
|
371
|
+
stdin.setRawMode(true);
|
|
372
|
+
stdin.on("data", onData);
|
|
373
|
+
stdin.resume();
|
|
374
|
+
let restored = false;
|
|
375
|
+
return () => {
|
|
376
|
+
if (restored) return;
|
|
377
|
+
restored = true;
|
|
378
|
+
if (cancelAlias) _clack_prompts.settings.aliases.set("", cancelAlias);
|
|
379
|
+
stdin.off("data", onData);
|
|
380
|
+
stdin.setRawMode(false);
|
|
381
|
+
stdin.pause();
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
283
385
|
* Runs a Studio command from its parsed flags: builds the {@link StudioOptions}, prints the intro,
|
|
284
386
|
* and reports the run to telemetry. A failure is printed and sets the exit code instead of throwing.
|
|
285
387
|
*/
|
|
@@ -288,13 +390,7 @@ async function runStudio(values, action, { block = false, json = false } = {}) {
|
|
|
288
390
|
version: require_Telemetry.version,
|
|
289
391
|
configPath: values.config,
|
|
290
392
|
studioUrl: values.url ?? _kubb_studio.defaultStudioUrl,
|
|
291
|
-
permission:
|
|
292
|
-
allowRead: values.allowRead ?? false,
|
|
293
|
-
allowReadAst: values.allowReadAst ?? false,
|
|
294
|
-
allowWrite: values.allowWrite ?? false,
|
|
295
|
-
allowConfigEdit: values.allowConfigEdit ?? false,
|
|
296
|
-
allowExec: values.allowExec ?? false
|
|
297
|
-
},
|
|
393
|
+
permission: Object.fromEntries(Object.values(_kubb_studio_protocol.AgentPermission).map((key) => [key, values[key] ?? false])),
|
|
298
394
|
autoOpen: values.open ?? true,
|
|
299
395
|
logLevel: values.logLevel
|
|
300
396
|
};
|
|
@@ -303,7 +399,7 @@ async function runStudio(values, action, { block = false, json = false } = {}) {
|
|
|
303
399
|
hrStart: node_process.default.hrtime()
|
|
304
400
|
});
|
|
305
401
|
try {
|
|
306
|
-
if (options.logLevel !== "silent" && !json)
|
|
402
|
+
if (options.logLevel !== "silent" && !json) require_text.logIntro({
|
|
307
403
|
warning: (0, node_util.styleText)("yellow", "This feature is still under development, use with caution"),
|
|
308
404
|
block
|
|
309
405
|
});
|
|
@@ -311,7 +407,7 @@ async function runStudio(values, action, { block = false, json = false } = {}) {
|
|
|
311
407
|
await report({ status: "success" });
|
|
312
408
|
} catch (error) {
|
|
313
409
|
await report({ status: "failed" });
|
|
314
|
-
console.error(
|
|
410
|
+
console.error(require_errors.toError(error).message);
|
|
315
411
|
node_process.default.exitCode = 1;
|
|
316
412
|
}
|
|
317
413
|
}
|
|
@@ -323,4 +419,4 @@ exports.login = login;
|
|
|
323
419
|
exports.prepareConnection = prepareConnection;
|
|
324
420
|
exports.runStudio = runStudio;
|
|
325
421
|
|
|
326
|
-
//# sourceMappingURL=run-
|
|
422
|
+
//# sourceMappingURL=run-DkBJkKor.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-DkBJkKor.cjs","names":["process","isCIEnvironment","x","isCIEnvironment","process","createSpinner","pairAgent","path","process","hostname","getMachineId","styleText","isRichOutput","writeCredentials","getCredentialsPath","PairingCanceledError","AgentPermission","toPermissionFlag","KUBB_CONFIG_FILENAME","isCIEnvironment","canUseTTY","prompts","getConfigs","Diagnostics","readCredentials","Hookable","logLevelMap","cliReporter","plainWriter","connectAgent","InvalidAgentTokenError","clearCredentials","defaultStudioUrl","trackRun","toError"],"sources":["../../../internals/utils/src/copyToClipboard.ts","../../../internals/utils/src/openInBrowser.ts","../src/runners/studio/run.ts"],"sourcesContent":["import process from 'node:process'\nimport { x } from 'tinyexec'\nimport { isCIEnvironment } from './isCIEnvironment.ts'\n\nconst COMMANDS: Partial<Record<NodeJS.Platform, [string, ...Array<string>]>> = {\n darwin: ['pbcopy'],\n win32: ['clip.exe'],\n linux: ['xclip', '-selection', 'clipboard'],\n}\n\n/**\n * Copies text to the system clipboard with the platform's own tool. Resolves `false` in CI, on a\n * platform without a known tool, or when the tool is missing or fails.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n // Wayland sessions have no X selection for xclip to serve, so they use `wl-copy`.\n const command = process.platform === 'linux' && process.env.WAYLAND_DISPLAY ? (['wl-copy'] as const) : COMMANDS[process.platform]\n if (!command || isCIEnvironment()) return false\n\n const [name, ...args] = command\n // stdout and stderr are ignored: xclip and wl-copy stay alive to serve the selection and would hold open pipes until the timeout.\n const run = x(name, args, { timeout: 2_000, nodeOptions: { stdio: ['pipe', 'ignore', 'ignore'] } })\n // A missing tool closes stdin before the write lands; the rejection below reports it.\n run.process?.stdin?.once('error', () => {})\n run.process?.stdin?.end(text)\n\n return run.then(\n ({ exitCode }) => exitCode === 0,\n () => false,\n )\n}\n","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 { hostname } from 'node:os'\nimport { toPermissionFlag } from '../../ui/text.ts'\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 { copyToClipboard, isCIEnvironment, openInBrowser, toError } from '@internals/utils'\nimport type { CLIOptions, Config } from '@kubb/core'\nimport { cliReporter, Diagnostics, Hookable, type KubbHooks, logLevel as logLevelMap } from '@kubb/core'\nimport { connectAgent, defaultStudioUrl, InvalidAgentTokenError, pairAgent, PairingCanceledError } from '@kubb/studio'\nimport { AgentPermission } from '@kubb/studio/protocol'\nimport { trackRun } from '../../Telemetry.ts'\nimport { plainWriter } from '../../loggers/plainWriter.ts'\nimport setupReporters from '../../loggers/reporters.ts'\nimport { logIntro, logOutro, logTip } from '../../ui/intro.ts'\nimport { logBlock, logStep } from '../../ui/log.ts'\nimport { createSpinner } from '../../ui/spinner.ts'\nimport { canUseTTY, isRichOutput } 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\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<AgentPermission, 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\n/** The flags a `kubb studio` subcommand parsed; each one is optional since a subcommand declares only the flags it uses. */\nexport type StudioValues = {\n config?: string\n url?: string\n allowRead?: boolean\n allowReadAst?: boolean\n allowWrite?: boolean\n allowConfigEdit?: boolean\n allowExec?: boolean\n open?: boolean\n logLevel?: CLIOptions['logLevel']\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 // A retry notice stays on screen a while before the countdown takes the line back.\n let retryUntil = 0\n // The spinner only starts once a code is shown.\n let waiting = false\n let countdown: NodeJS.Timeout | undefined\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 logStep(\n [\n 'Pair this machine',\n `${styleText('dim', 'Open')} ${styleText('cyan', session.verification_uri)}`,\n `${styleText('dim', 'Code')} ${styleText('bold', session.user_code)}`,\n ].join('\\n'),\n )\n\n if (autoOpen) {\n openInBrowser(session.verification_uri_complete)\n }\n\n // Same fallback as the poll in `@kubb/studio`, so the countdown ends when polling does.\n const deadline = Date.now() + (session.expires_in > 0 ? session.expires_in : 600) * 1000\n let copied = false\n const waitingText = () =>\n `Waiting for approval ${styleText('dim', `expires in ${formatCountdown(deadline - Date.now())}${copied ? ' · code copied' : ''} · ctrl+c to cancel`)}`\n clearInterval(countdown)\n spinner.start(waitingText())\n waiting = true\n // Plain output prints every message, so only an animated spinner ticks.\n if (isRichOutput()) countdown = setInterval(() => Date.now() > retryUntil && spinner.message(waitingText()), 1000)\n // Not awaited: the code shows at once, and the spinner picks up the copy when it lands.\n void copyToClipboard(session.user_code).then((done) => {\n copied = done\n })\n },\n onRetry: (error) => {\n retryUntil = Date.now() + 5000\n spinner.message(`Could not reach Kubb Studio, retrying: ${error.message}`)\n },\n })\n clearInterval(countdown)\n spinner.stop(`Paired as ${agent.name}${agent.organizationSlug ? ` · org ${agent.organizationSlug}` : ''}`)\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 ...(agent.organizationSlug ? { organizationSlug: agent.organizationSlug } : {}),\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 clearInterval(countdown)\n if (waiting) {\n spinner.stop(error instanceof PairingCanceledError ? 'Pairing canceled' : 'Pairing failed')\n }\n throw error\n }\n}\n\n/** Time left on a pairing code as `m:ss`, never below `0:00`. */\nexport function formatCountdown(ms: number): string {\n const seconds = Math.max(0, Math.ceil(ms / 1000))\n\n return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, '0')}`\n}\n\n/**\n * What each permission is asked as, in the order the list shows them.\n */\nconst PERMISSIONS: ReadonlyArray<{\n key: AgentPermission\n /**\n * Short label for status output and the connect summary.\n */\n label: string\n title: (configPath: string) => string\n hint: string\n}> = [\n { key: AgentPermission.READ, label: 'read source', title: () => 'Read generated files', hint: 'show code in the browser' },\n { key: AgentPermission.READ_AST, label: 'read spec', title: () => 'Read the parsed spec', hint: 'browse schemas and operations' },\n { key: AgentPermission.WRITE, label: 'write files', title: () => 'Write files to disk', hint: 'generate from the browser' },\n { key: AgentPermission.CONFIG_EDIT, label: 'edit config', title: (configPath) => `Change ${configPath}`, hint: 'edit plugin options' },\n { key: AgentPermission.EXEC, label: 'run tools', title: () => 'Run the formatter, linter, and postGenerate', hint: 'after each generation' },\n]\n\n/**\n * Two permissions per row, each marked granted or not, with the flags that grant the missing ones\n * after the last row. For `kubb studio status`.\n */\nexport function formatPermissionRows(granted: Partial<Record<AgentPermission, boolean>>): Array<string> {\n const width = Math.max(...PERMISSIONS.map(({ label }) => label.length))\n const cells = PERMISSIONS.map(({ key, label }) => `${granted[key] ? styleText('green', '✓') : styleText('red', '✖')} ${label.padEnd(width)}`)\n const rows = Array.from({ length: Math.ceil(cells.length / 2) }, (_, index) => cells.slice(index * 2, index * 2 + 2).join(' '))\n const flags = PERMISSIONS.filter(({ key }) => !granted[key])\n .map(({ key }) => toPermissionFlag(key))\n .join(' ')\n\n return flags ? [...rows.slice(0, -1), `${rows.at(-1)} ${styleText('dim', flags)}`] : rows\n}\n\n/**\n * Resolves Studio permissions for the current project.\n * Flags win, saved answers are reused, and the rest are asked in one list whose answers are stored\n * in `~/.kubb/credentials.json`.\n */\nexport async function resolvePermissions(\n options: StudioOptions,\n credentials: Credentials,\n configPath: string = KUBB_CONFIG_FILENAME,\n): Promise<Record<AgentPermission, boolean>> {\n const project = process.cwd()\n const remembered = credentials.projects?.[project]\n const granted = Object.fromEntries(PERMISSIONS.map(({ key }) => [key, options.permission[key] || remembered?.[key] === true])) as Record<\n AgentPermission,\n boolean\n >\n const pending = PERMISSIONS.filter(({ key }) => !options.permission[key] && typeof remembered?.[key] !== 'boolean')\n\n if (!pending.length || isCIEnvironment() || !canUseTTY()) return granted\n\n prompts.updateSettings({ withGuide: true })\n const selected = await prompts.multiselect({\n message: 'What may Kubb Studio do in this project?',\n options: pending.map(({ key, title, hint }) => ({ value: key, label: title(configPath), hint })),\n required: false,\n })\n // A canceled list grants nothing and saves nothing, so the next run asks again.\n if (prompts.isCancel(selected)) return granted\n\n const answers = Object.fromEntries(pending.map(({ key }) => [key, selected.includes(key)]))\n await writeCredentials({\n ...credentials,\n projects: { ...credentials.projects, [project]: { ...remembered, ...answers } },\n })\n\n return { ...granted, ...answers }\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 Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'Config not defined, create a kubb.config.ts or pass it with --config',\n })\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\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 stored = await readCredentials()\n const credentials = await (async () => {\n if (stored?.studioUrl === options.studioUrl) return stored\n if (isCIEnvironment()) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: `Not paired with ${options.studioUrl}. In CI, run \\`kubb studio snapshot\\` instead, or run \\`kubb studio login\\` on a machine with a browser.`,\n })\n }\n return login(options, { signal })\n })()\n const permissions = await resolvePermissions(options, credentials, configPath)\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 let unwatch: (() => void) | undefined\n try {\n if (!context.prepared) {\n const { getWorkerStatus } = await import('./background.ts')\n const worker = await getWorkerStatus()\n if (worker.running)\n throw new Diagnostics.Error({\n code: Diagnostics.code.unknown,\n severity: 'error',\n message: 'This project is running in the background. Run `kubb studio stop` first.',\n })\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 ? { writer: plainWriter } : {}),\n })\n // `b` hands the session to the background worker; only a foreground run in a terminal listens.\n const listens = !context.onState && process.stdin.isTTY === true && canUseTTY()\n let background = false\n hooks.hook('studio:connected', async () => {\n pairedAgain = false\n await context.onState?.('connected')\n if (listens && !unwatch) {\n unwatch = watchKeys({\n onBackground: () => {\n background = true\n stop()\n },\n onStop: stop,\n })\n }\n if (hinted || context.onState || options.logLevel === 'silent') return\n hinted = true\n logBlock([\n `${styleText('dim', 'Project')} ${path.basename(process.cwd())} ${styleText(\n 'dim',\n PERMISSIONS.filter(({ key }) => permissions[key])\n .map(({ label }) => label)\n .join(' · ') || 'no permissions',\n )}`,\n styleText('dim', listens ? 'Press b to keep running in the background, Ctrl+C to disconnect' : 'Press Ctrl+C to disconnect'),\n ])\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 await clearCredentials()\n if (pairedAgain) throw new Error(`${error.message} Studio rejected the newly approved token too. Run \\`kubb studio login\\` and try again.`)\n if (context.onState || isCIEnvironment() || !canUseTTY()) throw new Error(`${error.message} Run \\`kubb studio login\\` to pair again.`)\n\n // The pairing prompts need stdin back.\n unwatch?.()\n unwatch = undefined\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 // Stops the \"Ready for jobs\" spinner, which would otherwise keep drawing under the closing line.\n await hooks.callHook('kubb:lifecycle:end')\n unwatch?.()\n if (background) {\n const { startWorker } = await import('./background.ts')\n await startWorker(options)\n if (options.logLevel !== 'silent') logOutro('Running in the background · kubb studio stop')\n return\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 unwatch?.()\n events.off('SIGINT', stop)\n events.off('SIGTERM', stop)\n }\n}\n\n/**\n * Listens for single keys on a TTY stdin. Raw mode turns Ctrl+C into a key instead of SIGINT, so it\n * is handled here too. Returns the function that restores the terminal, safe to call twice.\n */\nexport function watchKeys({ onBackground, onStop }: { onBackground: () => void; onStop: () => void }): () => void {\n const stdin = process.stdin\n const onData = (data: Buffer) => {\n const key = data.toString()\n if (key === 'b' || key === 'B') onBackground()\n if (key === '\\u0003') onStop()\n }\n // A clack spinner reads stdin too and exits the process on Ctrl+C, before the session can close\n // its socket, so its Ctrl+C alias is lifted while these keys are read.\n const cancelAlias = prompts.settings.aliases.get('\\u0003')\n prompts.settings.aliases.delete('\\u0003')\n stdin.setRawMode(true)\n stdin.on('data', onData)\n stdin.resume()\n let restored = false\n\n return () => {\n if (restored) return\n restored = true\n if (cancelAlias) prompts.settings.aliases.set('\\u0003', cancelAlias)\n stdin.off('data', onData)\n stdin.setRawMode(false)\n stdin.pause()\n }\n}\n\n/**\n * Runs a Studio command from its parsed flags: builds the {@link StudioOptions}, prints the intro,\n * and reports the run to telemetry. A failure is printed and sets the exit code instead of throwing.\n */\nexport async function runStudio(\n values: StudioValues,\n action: (options: StudioOptions) => Promise<unknown>,\n { block = false, json = false }: { block?: boolean; json?: boolean } = {},\n): Promise<void> {\n const options: StudioOptions = {\n version,\n configPath: values.config,\n studioUrl: values.url ?? defaultStudioUrl,\n permission: Object.fromEntries(Object.values(AgentPermission).map((key) => [key, values[key] ?? false])) as Record<AgentPermission, boolean>,\n autoOpen: values.open ?? true,\n logLevel: values.logLevel,\n }\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(options)\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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"}
|