@kubb/cli 5.0.0-beta.54 → 5.0.0-beta.56
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 +0 -1
- package/dist/{Telemetry-DC5WVMB9.cjs → Telemetry-BuDSora3.cjs} +83 -112
- package/dist/Telemetry-BuDSora3.cjs.map +1 -0
- package/dist/{Telemetry-BZH4YIxq.js → Telemetry-C66uYyC2.js} +82 -111
- package/dist/Telemetry-C66uYyC2.js.map +1 -0
- package/dist/define-C4AB3POr.cjs.map +1 -1
- package/dist/define-C63T4jp6.js.map +1 -1
- package/dist/{generate-CSu0xUcm.js → generate-DZlEPvGX.js} +3 -9
- package/dist/generate-DZlEPvGX.js.map +1 -0
- package/dist/{generate-BRt2AlAO.cjs → generate-wadnaW25.cjs} +3 -9
- package/dist/generate-wadnaW25.cjs.map +1 -0
- package/dist/index.cjs +8 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +8 -22
- package/dist/index.js.map +1 -1
- package/dist/{init-YMqAAWFE.cjs → init-B8In4PV3.cjs} +3 -3
- package/dist/{init-YMqAAWFE.cjs.map → init-B8In4PV3.cjs.map} +1 -1
- package/dist/{init-CnVtpZfe.js → init-DAyMW8Tb.js} +3 -3
- package/dist/{init-CnVtpZfe.js.map → init-DAyMW8Tb.js.map} +1 -1
- package/dist/{mcp-CnP9ZVBz.js → mcp-BpenB6vE.js} +3 -3
- package/dist/{mcp-CnP9ZVBz.js.map → mcp-BpenB6vE.js.map} +1 -1
- package/dist/{mcp-B2wwhU2v.cjs → mcp-nVpSgCz-.cjs} +3 -3
- package/dist/{mcp-B2wwhU2v.cjs.map → mcp-nVpSgCz-.cjs.map} +1 -1
- package/dist/package-BSMI4dNK.js +6 -0
- package/dist/package-BSMI4dNK.js.map +1 -0
- package/dist/{package-C8wmoP1B.cjs → package-CsEMNf0Q.cjs} +2 -2
- package/dist/package-CsEMNf0Q.cjs.map +1 -0
- package/dist/{run-C-omuksC.js → run-BG7Giryi.js} +36 -99
- package/dist/run-BG7Giryi.js.map +1 -0
- package/dist/{run-DMWGLJUx.cjs → run-Bj64iPU_.cjs} +2 -2
- package/dist/{run-DMWGLJUx.cjs.map → run-Bj64iPU_.cjs.map} +1 -1
- package/dist/{run-Cou32en2.js → run-CSYH_DiQ.js} +83 -165
- package/dist/run-CSYH_DiQ.js.map +1 -0
- package/dist/{run-C7cr0qhi.js → run-CUkZ6gnP.js} +2 -2
- package/dist/{run-C7cr0qhi.js.map → run-CUkZ6gnP.js.map} +1 -1
- package/dist/{run-DGMgkbD3.cjs → run-DCXY-eRK.cjs} +2 -2
- package/dist/{run-DGMgkbD3.cjs.map → run-DCXY-eRK.cjs.map} +1 -1
- package/dist/{run-4WGNek3a.cjs → run-DWqZHzYL.cjs} +86 -168
- package/dist/run-DWqZHzYL.cjs.map +1 -0
- package/dist/{run-BtjzfTz3.cjs → run-DpKny2hT.cjs} +30 -93
- package/dist/run-DpKny2hT.cjs.map +1 -0
- package/dist/{run-DLVIbuN0.js → run-OWQyNzZx.js} +2 -2
- package/dist/{run-DLVIbuN0.js.map → run-OWQyNzZx.js.map} +1 -1
- package/dist/tools-BU99bhi8.js +152 -0
- package/dist/tools-BU99bhi8.js.map +1 -0
- package/dist/tools-_Xp8-_zy.cjs +175 -0
- package/dist/tools-_Xp8-_zy.cjs.map +1 -0
- package/dist/{validate-Bqf5fxQp.cjs → validate-CJZ7XveW.cjs} +3 -3
- package/dist/{validate-Bqf5fxQp.cjs.map → validate-CJZ7XveW.cjs.map} +1 -1
- package/dist/{validate-BlNh3LLm.js → validate-DPgK_e7n.js} +3 -3
- package/dist/{validate-BlNh3LLm.js.map → validate-DPgK_e7n.js.map} +1 -1
- package/package.json +5 -5
- package/src/Telemetry.ts +20 -22
- package/src/commands/generate.ts +0 -6
- package/src/constants.ts +1 -1
- package/src/index.ts +4 -21
- package/src/runners/generate/run.ts +12 -16
- package/src/runners/generate/utils.ts +18 -19
- package/src/runners/init/utils.ts +9 -3
- package/dist/Telemetry-BZH4YIxq.js.map +0 -1
- package/dist/Telemetry-DC5WVMB9.cjs.map +0 -1
- package/dist/generate-BRt2AlAO.cjs.map +0 -1
- package/dist/generate-CSu0xUcm.js.map +0 -1
- package/dist/package-C8wmoP1B.cjs.map +0 -1
- package/dist/package-CNNBB6JV.js +0 -6
- package/dist/package-CNNBB6JV.js.map +0 -1
- package/dist/run-4WGNek3a.cjs.map +0 -1
- package/dist/run-BtjzfTz3.cjs.map +0 -1
- package/dist/run-C-omuksC.js.map +0 -1
- package/dist/run-Cou32en2.js.map +0 -1
- package/dist/shell-DsgkfUSW.js +0 -51
- package/dist/shell-DsgkfUSW.js.map +0 -1
- package/dist/shell-Lh-vLWwH.cjs +0 -62
- package/dist/shell-Lh-vLWwH.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools-BU99bhi8.js","names":[],"sources":["../../../internals/utils/src/tools.ts"],"sourcesContent":["import { spawn } from 'node:child_process'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\n/**\n * CLI command descriptors for each supported code formatter.\n *\n * Each entry contains the executable `command`, an `args` factory that maps an\n * output path to the correct argument list, and an `errorMessage` shown when\n * the formatter is not found.\n */\nexport const formatters = {\n prettier: {\n command: 'prettier',\n args: (outputPath: string) => ['--ignore-unknown', '--write', outputPath],\n errorMessage: 'Prettier not found',\n },\n biome: {\n command: 'biome',\n args: (outputPath: string) => ['format', '--write', outputPath],\n errorMessage: 'Biome not found',\n },\n oxfmt: {\n command: 'oxfmt',\n args: (outputPath: string) => [outputPath],\n errorMessage: 'Oxfmt not found',\n },\n} as const\n\n/**\n * CLI command descriptors for each supported linter.\n *\n * Each entry contains the executable `command`, an `args` factory that maps an\n * output path to the correct argument list, and an `errorMessage` shown when\n * the linter is not found.\n */\nexport const linters = {\n eslint: {\n command: 'eslint',\n args: (outputPath: string) => [outputPath, '--fix'],\n errorMessage: 'Eslint not found',\n },\n biome: {\n command: 'biome',\n args: (outputPath: string) => ['lint', '--fix', outputPath],\n errorMessage: 'Biome not found',\n },\n oxlint: {\n command: 'oxlint',\n // --no-ignore so oxlint lints the folder even when it's gitignored (generated output dirs usually are).\n args: (outputPath: string) => ['--fix', '--no-ignore', outputPath],\n errorMessage: 'Oxlint not found',\n },\n} as const\n\n/**\n * Resolves to `true` when running `tool --version` exits with code 0.\n */\nasync function isToolAvailable(tool: string): Promise<boolean> {\n return new Promise((resolve) => {\n const child = spawn(tool, ['--version'], { stdio: 'ignore' })\n child.on('close', (code) => resolve(code === 0))\n child.on('error', () => resolve(false))\n })\n}\n\n/**\n * Returns the first installed tool from `candidates`, checked in order, or `null` when none are found.\n *\n * Availability is probed by running `<tool> --version` and checking for a zero exit code.\n *\n * @example\n * ```ts\n * const formatter = await detectTool(['oxfmt', 'biome', 'prettier'] as const)\n * const linter = await detectTool(['oxlint', 'biome', 'eslint'] as const)\n * ```\n */\nexport async function detectTool<TName extends string>(candidates: ReadonlyArray<TName>): Promise<TName | null> {\n for (const tool of candidates) {\n if (await isToolAvailable(tool)) {\n return tool\n }\n }\n\n return null\n}\n\n/**\n * Supported package manager identifiers.\n *\n * @example\n * ```ts\n * const pm: PackageManagerName = 'pnpm'\n * ```\n */\nexport type PackageManagerName = 'npm' | 'pnpm' | 'yarn' | 'bun'\n\n/**\n * Metadata describing a package manager's lock file and install command.\n */\nexport interface PackageManagerInfo {\n /**\n * Identifier used in CLI commands, e.g. `pnpm`, `yarn`.\n */\n name: PackageManagerName\n /**\n * Lock file name that uniquely identifies this package manager in a project root.\n */\n lockFile: string\n /**\n * Subcommands passed to the package manager binary to install a dev dependency.\n */\n installCommand: ReadonlyArray<string>\n}\n\n/**\n * Metadata for each supported package manager, keyed by its short name.\n *\n * @example\n * ```ts\n * packageManagers.pnpm.installCommand // ['add', '-D']\n * packageManagers.npm.lockFile // 'package-lock.json'\n * ```\n */\nconst packageManagers: Record<PackageManagerName, PackageManagerInfo> = {\n pnpm: {\n name: 'pnpm',\n lockFile: 'pnpm-lock.yaml',\n installCommand: ['add', '-D'],\n },\n yarn: {\n name: 'yarn',\n lockFile: 'yarn.lock',\n installCommand: ['add', '-D'],\n },\n bun: {\n name: 'bun',\n lockFile: 'bun.lockb',\n installCommand: ['add', '-d'],\n },\n npm: {\n name: 'npm',\n lockFile: 'package-lock.json',\n installCommand: ['install', '--save-dev'],\n },\n}\n\n/**\n * Minimal shape of `package.json` fields read during detection.\n */\ntype PackageJson = {\n /**\n * The `packageManager` field from `package.json` (e.g. `\"pnpm@9.0.0\"`).\n */\n packageManager?: string\n}\n\n/**\n * Detects the active package manager for the given directory.\n * Resolution order: `packageManager` field in `package.json`, then presence of a lock file.\n * Falls back to `npm` when no signal is found.\n *\n * @example\n * ```ts\n * detectPackageManager('/my/project') // { name: 'pnpm', lockFile: 'pnpm-lock.yaml', ... }\n * detectPackageManager() // falls back to npm when no lock file is found\n * ```\n */\nexport function detectPackageManager(cwd: string = process.cwd()): PackageManagerInfo {\n const packageJsonPath = join(cwd, 'package.json')\n if (existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as PackageJson\n const pmField = packageJson.packageManager\n if (typeof pmField === 'string') {\n const name = pmField.split('@')[0]\n if (name && name in packageManagers) {\n return packageManagers[name as PackageManagerName]\n }\n }\n } catch {\n // Continue to lock file detection\n }\n }\n\n for (const pm of Object.values(packageManagers)) {\n if (existsSync(join(cwd, pm.lockFile))) {\n return pm\n }\n }\n\n return packageManagers.npm\n}\n"],"mappings":";;;;;;;;;;;;AAWA,MAAa,aAAa;CACxB,UAAU;EACR,SAAS;EACT,OAAO,eAAuB;GAAC;GAAoB;GAAW;EAAU;EACxE,cAAc;CAChB;CACA,OAAO;EACL,SAAS;EACT,OAAO,eAAuB;GAAC;GAAU;GAAW;EAAU;EAC9D,cAAc;CAChB;CACA,OAAO;EACL,SAAS;EACT,OAAO,eAAuB,CAAC,UAAU;EACzC,cAAc;CAChB;AACF;;;;;;;;AASA,MAAa,UAAU;CACrB,QAAQ;EACN,SAAS;EACT,OAAO,eAAuB,CAAC,YAAY,OAAO;EAClD,cAAc;CAChB;CACA,OAAO;EACL,SAAS;EACT,OAAO,eAAuB;GAAC;GAAQ;GAAS;EAAU;EAC1D,cAAc;CAChB;CACA,QAAQ;EACN,SAAS;EAET,OAAO,eAAuB;GAAC;GAAS;GAAe;EAAU;EACjE,cAAc;CAChB;AACF;;;;AAKA,eAAe,gBAAgB,MAAgC;CAC7D,OAAO,IAAI,SAAS,YAAY;EAC9B,MAAM,QAAQ,MAAM,MAAM,CAAC,WAAW,GAAG,EAAE,OAAO,SAAS,CAAC;EAC5D,MAAM,GAAG,UAAU,SAAS,QAAQ,SAAS,CAAC,CAAC;EAC/C,MAAM,GAAG,eAAe,QAAQ,KAAK,CAAC;CACxC,CAAC;AACH;;;;;;;;;;;;AAaA,eAAsB,WAAiC,YAAyD;CAC9G,KAAK,MAAM,QAAQ,YACjB,IAAI,MAAM,gBAAgB,IAAI,GAC5B,OAAO;CAIX,OAAO;AACT;;;;;;;;;;AAuCA,MAAM,kBAAkE;CACtE,MAAM;EACJ,MAAM;EACN,UAAU;EACV,gBAAgB,CAAC,OAAO,IAAI;CAC9B;CACA,MAAM;EACJ,MAAM;EACN,UAAU;EACV,gBAAgB,CAAC,OAAO,IAAI;CAC9B;CACA,KAAK;EACH,MAAM;EACN,UAAU;EACV,gBAAgB,CAAC,OAAO,IAAI;CAC9B;CACA,KAAK;EACH,MAAM;EACN,UAAU;EACV,gBAAgB,CAAC,WAAW,YAAY;CAC1C;AACF;;;;;;;;;;;;AAuBA,SAAgB,qBAAqB,MAAc,QAAQ,IAAI,GAAuB;CACpF,MAAM,kBAAkB,KAAK,KAAK,cAAc;CAChD,IAAI,WAAW,eAAe,GAC5B,IAAI;EAEF,MAAM,UADc,KAAK,MAAM,aAAa,iBAAiB,OAAO,CAC1C,CAAC,CAAC;EAC5B,IAAI,OAAO,YAAY,UAAU;GAC/B,MAAM,OAAO,QAAQ,MAAM,GAAG,CAAC,CAAC;GAChC,IAAI,QAAQ,QAAQ,iBAClB,OAAO,gBAAgB;EAE3B;CACF,QAAQ,CAER;CAGF,KAAK,MAAM,MAAM,OAAO,OAAO,eAAe,GAC5C,IAAI,WAAW,KAAK,KAAK,GAAG,QAAQ,CAAC,GACnC,OAAO;CAIX,OAAO,gBAAgB;AACzB"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
require("./chunk-Bx3C2hgW.cjs");
|
|
2
|
+
let node_child_process = require("node:child_process");
|
|
3
|
+
let node_fs = require("node:fs");
|
|
4
|
+
let node_path = require("node:path");
|
|
5
|
+
//#region ../../internals/utils/src/tools.ts
|
|
6
|
+
/**
|
|
7
|
+
* CLI command descriptors for each supported code formatter.
|
|
8
|
+
*
|
|
9
|
+
* Each entry contains the executable `command`, an `args` factory that maps an
|
|
10
|
+
* output path to the correct argument list, and an `errorMessage` shown when
|
|
11
|
+
* the formatter is not found.
|
|
12
|
+
*/
|
|
13
|
+
const formatters = {
|
|
14
|
+
prettier: {
|
|
15
|
+
command: "prettier",
|
|
16
|
+
args: (outputPath) => [
|
|
17
|
+
"--ignore-unknown",
|
|
18
|
+
"--write",
|
|
19
|
+
outputPath
|
|
20
|
+
],
|
|
21
|
+
errorMessage: "Prettier not found"
|
|
22
|
+
},
|
|
23
|
+
biome: {
|
|
24
|
+
command: "biome",
|
|
25
|
+
args: (outputPath) => [
|
|
26
|
+
"format",
|
|
27
|
+
"--write",
|
|
28
|
+
outputPath
|
|
29
|
+
],
|
|
30
|
+
errorMessage: "Biome not found"
|
|
31
|
+
},
|
|
32
|
+
oxfmt: {
|
|
33
|
+
command: "oxfmt",
|
|
34
|
+
args: (outputPath) => [outputPath],
|
|
35
|
+
errorMessage: "Oxfmt not found"
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* CLI command descriptors for each supported linter.
|
|
40
|
+
*
|
|
41
|
+
* Each entry contains the executable `command`, an `args` factory that maps an
|
|
42
|
+
* output path to the correct argument list, and an `errorMessage` shown when
|
|
43
|
+
* the linter is not found.
|
|
44
|
+
*/
|
|
45
|
+
const linters = {
|
|
46
|
+
eslint: {
|
|
47
|
+
command: "eslint",
|
|
48
|
+
args: (outputPath) => [outputPath, "--fix"],
|
|
49
|
+
errorMessage: "Eslint not found"
|
|
50
|
+
},
|
|
51
|
+
biome: {
|
|
52
|
+
command: "biome",
|
|
53
|
+
args: (outputPath) => [
|
|
54
|
+
"lint",
|
|
55
|
+
"--fix",
|
|
56
|
+
outputPath
|
|
57
|
+
],
|
|
58
|
+
errorMessage: "Biome not found"
|
|
59
|
+
},
|
|
60
|
+
oxlint: {
|
|
61
|
+
command: "oxlint",
|
|
62
|
+
args: (outputPath) => [
|
|
63
|
+
"--fix",
|
|
64
|
+
"--no-ignore",
|
|
65
|
+
outputPath
|
|
66
|
+
],
|
|
67
|
+
errorMessage: "Oxlint not found"
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Resolves to `true` when running `tool --version` exits with code 0.
|
|
72
|
+
*/
|
|
73
|
+
async function isToolAvailable(tool) {
|
|
74
|
+
return new Promise((resolve) => {
|
|
75
|
+
const child = (0, node_child_process.spawn)(tool, ["--version"], { stdio: "ignore" });
|
|
76
|
+
child.on("close", (code) => resolve(code === 0));
|
|
77
|
+
child.on("error", () => resolve(false));
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Returns the first installed tool from `candidates`, checked in order, or `null` when none are found.
|
|
82
|
+
*
|
|
83
|
+
* Availability is probed by running `<tool> --version` and checking for a zero exit code.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* const formatter = await detectTool(['oxfmt', 'biome', 'prettier'] as const)
|
|
88
|
+
* const linter = await detectTool(['oxlint', 'biome', 'eslint'] as const)
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
async function detectTool(candidates) {
|
|
92
|
+
for (const tool of candidates) if (await isToolAvailable(tool)) return tool;
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Metadata for each supported package manager, keyed by its short name.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* packageManagers.pnpm.installCommand // ['add', '-D']
|
|
101
|
+
* packageManagers.npm.lockFile // 'package-lock.json'
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
const packageManagers = {
|
|
105
|
+
pnpm: {
|
|
106
|
+
name: "pnpm",
|
|
107
|
+
lockFile: "pnpm-lock.yaml",
|
|
108
|
+
installCommand: ["add", "-D"]
|
|
109
|
+
},
|
|
110
|
+
yarn: {
|
|
111
|
+
name: "yarn",
|
|
112
|
+
lockFile: "yarn.lock",
|
|
113
|
+
installCommand: ["add", "-D"]
|
|
114
|
+
},
|
|
115
|
+
bun: {
|
|
116
|
+
name: "bun",
|
|
117
|
+
lockFile: "bun.lockb",
|
|
118
|
+
installCommand: ["add", "-d"]
|
|
119
|
+
},
|
|
120
|
+
npm: {
|
|
121
|
+
name: "npm",
|
|
122
|
+
lockFile: "package-lock.json",
|
|
123
|
+
installCommand: ["install", "--save-dev"]
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Detects the active package manager for the given directory.
|
|
128
|
+
* Resolution order: `packageManager` field in `package.json`, then presence of a lock file.
|
|
129
|
+
* Falls back to `npm` when no signal is found.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* detectPackageManager('/my/project') // { name: 'pnpm', lockFile: 'pnpm-lock.yaml', ... }
|
|
134
|
+
* detectPackageManager() // falls back to npm when no lock file is found
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
function detectPackageManager(cwd = process.cwd()) {
|
|
138
|
+
const packageJsonPath = (0, node_path.join)(cwd, "package.json");
|
|
139
|
+
if ((0, node_fs.existsSync)(packageJsonPath)) try {
|
|
140
|
+
const pmField = JSON.parse((0, node_fs.readFileSync)(packageJsonPath, "utf-8")).packageManager;
|
|
141
|
+
if (typeof pmField === "string") {
|
|
142
|
+
const name = pmField.split("@")[0];
|
|
143
|
+
if (name && name in packageManagers) return packageManagers[name];
|
|
144
|
+
}
|
|
145
|
+
} catch {}
|
|
146
|
+
for (const pm of Object.values(packageManagers)) if ((0, node_fs.existsSync)((0, node_path.join)(cwd, pm.lockFile))) return pm;
|
|
147
|
+
return packageManagers.npm;
|
|
148
|
+
}
|
|
149
|
+
//#endregion
|
|
150
|
+
Object.defineProperty(exports, "detectPackageManager", {
|
|
151
|
+
enumerable: true,
|
|
152
|
+
get: function() {
|
|
153
|
+
return detectPackageManager;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
Object.defineProperty(exports, "detectTool", {
|
|
157
|
+
enumerable: true,
|
|
158
|
+
get: function() {
|
|
159
|
+
return detectTool;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
Object.defineProperty(exports, "formatters", {
|
|
163
|
+
enumerable: true,
|
|
164
|
+
get: function() {
|
|
165
|
+
return formatters;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
Object.defineProperty(exports, "linters", {
|
|
169
|
+
enumerable: true,
|
|
170
|
+
get: function() {
|
|
171
|
+
return linters;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
//# sourceMappingURL=tools-_Xp8-_zy.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools-_Xp8-_zy.cjs","names":[],"sources":["../../../internals/utils/src/tools.ts"],"sourcesContent":["import { spawn } from 'node:child_process'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\n/**\n * CLI command descriptors for each supported code formatter.\n *\n * Each entry contains the executable `command`, an `args` factory that maps an\n * output path to the correct argument list, and an `errorMessage` shown when\n * the formatter is not found.\n */\nexport const formatters = {\n prettier: {\n command: 'prettier',\n args: (outputPath: string) => ['--ignore-unknown', '--write', outputPath],\n errorMessage: 'Prettier not found',\n },\n biome: {\n command: 'biome',\n args: (outputPath: string) => ['format', '--write', outputPath],\n errorMessage: 'Biome not found',\n },\n oxfmt: {\n command: 'oxfmt',\n args: (outputPath: string) => [outputPath],\n errorMessage: 'Oxfmt not found',\n },\n} as const\n\n/**\n * CLI command descriptors for each supported linter.\n *\n * Each entry contains the executable `command`, an `args` factory that maps an\n * output path to the correct argument list, and an `errorMessage` shown when\n * the linter is not found.\n */\nexport const linters = {\n eslint: {\n command: 'eslint',\n args: (outputPath: string) => [outputPath, '--fix'],\n errorMessage: 'Eslint not found',\n },\n biome: {\n command: 'biome',\n args: (outputPath: string) => ['lint', '--fix', outputPath],\n errorMessage: 'Biome not found',\n },\n oxlint: {\n command: 'oxlint',\n // --no-ignore so oxlint lints the folder even when it's gitignored (generated output dirs usually are).\n args: (outputPath: string) => ['--fix', '--no-ignore', outputPath],\n errorMessage: 'Oxlint not found',\n },\n} as const\n\n/**\n * Resolves to `true` when running `tool --version` exits with code 0.\n */\nasync function isToolAvailable(tool: string): Promise<boolean> {\n return new Promise((resolve) => {\n const child = spawn(tool, ['--version'], { stdio: 'ignore' })\n child.on('close', (code) => resolve(code === 0))\n child.on('error', () => resolve(false))\n })\n}\n\n/**\n * Returns the first installed tool from `candidates`, checked in order, or `null` when none are found.\n *\n * Availability is probed by running `<tool> --version` and checking for a zero exit code.\n *\n * @example\n * ```ts\n * const formatter = await detectTool(['oxfmt', 'biome', 'prettier'] as const)\n * const linter = await detectTool(['oxlint', 'biome', 'eslint'] as const)\n * ```\n */\nexport async function detectTool<TName extends string>(candidates: ReadonlyArray<TName>): Promise<TName | null> {\n for (const tool of candidates) {\n if (await isToolAvailable(tool)) {\n return tool\n }\n }\n\n return null\n}\n\n/**\n * Supported package manager identifiers.\n *\n * @example\n * ```ts\n * const pm: PackageManagerName = 'pnpm'\n * ```\n */\nexport type PackageManagerName = 'npm' | 'pnpm' | 'yarn' | 'bun'\n\n/**\n * Metadata describing a package manager's lock file and install command.\n */\nexport interface PackageManagerInfo {\n /**\n * Identifier used in CLI commands, e.g. `pnpm`, `yarn`.\n */\n name: PackageManagerName\n /**\n * Lock file name that uniquely identifies this package manager in a project root.\n */\n lockFile: string\n /**\n * Subcommands passed to the package manager binary to install a dev dependency.\n */\n installCommand: ReadonlyArray<string>\n}\n\n/**\n * Metadata for each supported package manager, keyed by its short name.\n *\n * @example\n * ```ts\n * packageManagers.pnpm.installCommand // ['add', '-D']\n * packageManagers.npm.lockFile // 'package-lock.json'\n * ```\n */\nconst packageManagers: Record<PackageManagerName, PackageManagerInfo> = {\n pnpm: {\n name: 'pnpm',\n lockFile: 'pnpm-lock.yaml',\n installCommand: ['add', '-D'],\n },\n yarn: {\n name: 'yarn',\n lockFile: 'yarn.lock',\n installCommand: ['add', '-D'],\n },\n bun: {\n name: 'bun',\n lockFile: 'bun.lockb',\n installCommand: ['add', '-d'],\n },\n npm: {\n name: 'npm',\n lockFile: 'package-lock.json',\n installCommand: ['install', '--save-dev'],\n },\n}\n\n/**\n * Minimal shape of `package.json` fields read during detection.\n */\ntype PackageJson = {\n /**\n * The `packageManager` field from `package.json` (e.g. `\"pnpm@9.0.0\"`).\n */\n packageManager?: string\n}\n\n/**\n * Detects the active package manager for the given directory.\n * Resolution order: `packageManager` field in `package.json`, then presence of a lock file.\n * Falls back to `npm` when no signal is found.\n *\n * @example\n * ```ts\n * detectPackageManager('/my/project') // { name: 'pnpm', lockFile: 'pnpm-lock.yaml', ... }\n * detectPackageManager() // falls back to npm when no lock file is found\n * ```\n */\nexport function detectPackageManager(cwd: string = process.cwd()): PackageManagerInfo {\n const packageJsonPath = join(cwd, 'package.json')\n if (existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as PackageJson\n const pmField = packageJson.packageManager\n if (typeof pmField === 'string') {\n const name = pmField.split('@')[0]\n if (name && name in packageManagers) {\n return packageManagers[name as PackageManagerName]\n }\n }\n } catch {\n // Continue to lock file detection\n }\n }\n\n for (const pm of Object.values(packageManagers)) {\n if (existsSync(join(cwd, pm.lockFile))) {\n return pm\n }\n }\n\n return packageManagers.npm\n}\n"],"mappings":";;;;;;;;;;;;AAWA,MAAa,aAAa;CACxB,UAAU;EACR,SAAS;EACT,OAAO,eAAuB;GAAC;GAAoB;GAAW;EAAU;EACxE,cAAc;CAChB;CACA,OAAO;EACL,SAAS;EACT,OAAO,eAAuB;GAAC;GAAU;GAAW;EAAU;EAC9D,cAAc;CAChB;CACA,OAAO;EACL,SAAS;EACT,OAAO,eAAuB,CAAC,UAAU;EACzC,cAAc;CAChB;AACF;;;;;;;;AASA,MAAa,UAAU;CACrB,QAAQ;EACN,SAAS;EACT,OAAO,eAAuB,CAAC,YAAY,OAAO;EAClD,cAAc;CAChB;CACA,OAAO;EACL,SAAS;EACT,OAAO,eAAuB;GAAC;GAAQ;GAAS;EAAU;EAC1D,cAAc;CAChB;CACA,QAAQ;EACN,SAAS;EAET,OAAO,eAAuB;GAAC;GAAS;GAAe;EAAU;EACjE,cAAc;CAChB;AACF;;;;AAKA,eAAe,gBAAgB,MAAgC;CAC7D,OAAO,IAAI,SAAS,YAAY;EAC9B,MAAM,SAAA,GAAA,mBAAA,MAAA,CAAc,MAAM,CAAC,WAAW,GAAG,EAAE,OAAO,SAAS,CAAC;EAC5D,MAAM,GAAG,UAAU,SAAS,QAAQ,SAAS,CAAC,CAAC;EAC/C,MAAM,GAAG,eAAe,QAAQ,KAAK,CAAC;CACxC,CAAC;AACH;;;;;;;;;;;;AAaA,eAAsB,WAAiC,YAAyD;CAC9G,KAAK,MAAM,QAAQ,YACjB,IAAI,MAAM,gBAAgB,IAAI,GAC5B,OAAO;CAIX,OAAO;AACT;;;;;;;;;;AAuCA,MAAM,kBAAkE;CACtE,MAAM;EACJ,MAAM;EACN,UAAU;EACV,gBAAgB,CAAC,OAAO,IAAI;CAC9B;CACA,MAAM;EACJ,MAAM;EACN,UAAU;EACV,gBAAgB,CAAC,OAAO,IAAI;CAC9B;CACA,KAAK;EACH,MAAM;EACN,UAAU;EACV,gBAAgB,CAAC,OAAO,IAAI;CAC9B;CACA,KAAK;EACH,MAAM;EACN,UAAU;EACV,gBAAgB,CAAC,WAAW,YAAY;CAC1C;AACF;;;;;;;;;;;;AAuBA,SAAgB,qBAAqB,MAAc,QAAQ,IAAI,GAAuB;CACpF,MAAM,mBAAA,GAAA,UAAA,KAAA,CAAuB,KAAK,cAAc;CAChD,KAAA,GAAA,QAAA,WAAA,CAAe,eAAe,GAC5B,IAAI;EAEF,MAAM,UADc,KAAK,OAAA,GAAA,QAAA,aAAA,CAAmB,iBAAiB,OAAO,CAC1C,CAAC,CAAC;EAC5B,IAAI,OAAO,YAAY,UAAU;GAC/B,MAAM,OAAO,QAAQ,MAAM,GAAG,CAAC,CAAC;GAChC,IAAI,QAAQ,QAAQ,iBAClB,OAAO,gBAAgB;EAE3B;CACF,QAAQ,CAER;CAGF,KAAK,MAAM,MAAM,OAAO,OAAO,eAAe,GAC5C,KAAA,GAAA,QAAA,WAAA,EAAA,GAAA,UAAA,KAAA,CAAoB,KAAK,GAAG,QAAQ,CAAC,GACnC,OAAO;CAIX,OAAO,gBAAgB;AACzB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require("./chunk-Bx3C2hgW.cjs");
|
|
2
2
|
const require_define = require("./define-C4AB3POr.cjs");
|
|
3
|
-
const require_package = require("./package-
|
|
3
|
+
const require_package = require("./package-CsEMNf0Q.cjs");
|
|
4
4
|
//#region src/commands/validate.ts
|
|
5
5
|
const command = require_define.defineCommand({
|
|
6
6
|
name: "validate",
|
|
@@ -13,7 +13,7 @@ const command = require_define.defineCommand({
|
|
|
13
13
|
required: true
|
|
14
14
|
} },
|
|
15
15
|
async run({ values }) {
|
|
16
|
-
const { run } = await Promise.resolve().then(() => require("./run-
|
|
16
|
+
const { run } = await Promise.resolve().then(() => require("./run-Bj64iPU_.cjs"));
|
|
17
17
|
await run({
|
|
18
18
|
input: values.input,
|
|
19
19
|
version: require_package.version
|
|
@@ -23,4 +23,4 @@ const command = require_define.defineCommand({
|
|
|
23
23
|
//#endregion
|
|
24
24
|
exports.command = command;
|
|
25
25
|
|
|
26
|
-
//# sourceMappingURL=validate-
|
|
26
|
+
//# sourceMappingURL=validate-CJZ7XveW.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-
|
|
1
|
+
{"version":3,"file":"validate-CJZ7XveW.cjs","names":["defineCommand"],"sources":["../src/commands/validate.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'validate',\n description:\n 'Parse and validate an OpenAPI/Swagger file for structural correctness. Reports schema errors, missing required fields, and malformed references. Use this before running generate to catch spec issues early.',\n examples: ['kubb validate --input ./openapi.yaml', 'kubb validate --input https://petstore3.swagger.io/api/v3/openapi.json'],\n options: {\n input: {\n type: 'string',\n description: 'Path or URL to the OpenAPI/Swagger file to validate',\n short: 'i',\n required: true,\n },\n },\n async run({ values }) {\n const { run } = await import('../runners/validate/run.ts')\n\n await run({ input: values.input, version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAUA,eAAAA,cAAc;CACnC,MAAM;CACN,aACE;CACF,UAAU,CAAC,wCAAwC,wEAAwE;CAC3H,SAAS,EACP,OAAO;EACL,MAAM;EACN,aAAa;EACb,OAAO;EACP,UAAU;CACZ,EACF;CACA,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,QAAQ,MAAA,QAAA,QAAA,CAAA,CAAA,WAAA,QAAM,oBAAA,CAAA;EAEtB,MAAM,IAAI;GAAE,OAAO,OAAO;GAAO,SAAA,gBAAA;EAAQ,CAAC;CAC5C;AACF,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./chunk-C0LytTxp.js";
|
|
2
2
|
import { n as defineCommand } from "./define-C63T4jp6.js";
|
|
3
|
-
import { t as version } from "./package-
|
|
3
|
+
import { t as version } from "./package-BSMI4dNK.js";
|
|
4
4
|
//#region src/commands/validate.ts
|
|
5
5
|
const command = defineCommand({
|
|
6
6
|
name: "validate",
|
|
@@ -13,7 +13,7 @@ const command = defineCommand({
|
|
|
13
13
|
required: true
|
|
14
14
|
} },
|
|
15
15
|
async run({ values }) {
|
|
16
|
-
const { run } = await import("./run-
|
|
16
|
+
const { run } = await import("./run-CUkZ6gnP.js");
|
|
17
17
|
await run({
|
|
18
18
|
input: values.input,
|
|
19
19
|
version
|
|
@@ -23,4 +23,4 @@ const command = defineCommand({
|
|
|
23
23
|
//#endregion
|
|
24
24
|
export { command };
|
|
25
25
|
|
|
26
|
-
//# sourceMappingURL=validate-
|
|
26
|
+
//# sourceMappingURL=validate-DPgK_e7n.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-
|
|
1
|
+
{"version":3,"file":"validate-DPgK_e7n.js","names":[],"sources":["../src/commands/validate.ts"],"sourcesContent":["import { defineCommand } from '@internals/utils'\nimport { version } from '../../package.json'\n\nexport const command = defineCommand({\n name: 'validate',\n description:\n 'Parse and validate an OpenAPI/Swagger file for structural correctness. Reports schema errors, missing required fields, and malformed references. Use this before running generate to catch spec issues early.',\n examples: ['kubb validate --input ./openapi.yaml', 'kubb validate --input https://petstore3.swagger.io/api/v3/openapi.json'],\n options: {\n input: {\n type: 'string',\n description: 'Path or URL to the OpenAPI/Swagger file to validate',\n short: 'i',\n required: true,\n },\n },\n async run({ values }) {\n const { run } = await import('../runners/validate/run.ts')\n\n await run({ input: values.input, version })\n },\n})\n"],"mappings":";;;;AAGA,MAAa,UAAU,cAAc;CACnC,MAAM;CACN,aACE;CACF,UAAU,CAAC,wCAAwC,wEAAwE;CAC3H,SAAS,EACP,OAAO;EACL,MAAM;EACN,aAAa;EACb,OAAO;EACP,UAAU;CACZ,EACF;CACA,MAAM,IAAI,EAAE,UAAU;EACpB,MAAM,EAAE,QAAQ,MAAM,OAAO;EAE7B,MAAM,IAAI;GAAE,OAAO,OAAO;GAAO;EAAQ,CAAC;CAC5C;AACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/cli",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.56",
|
|
4
4
|
"description": "Official CLI for Kubb. Run kubb generate, kubb init, kubb validate, and kubb mcp to manage the full code generation lifecycle from OpenAPI/Swagger specs.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -52,16 +52,16 @@
|
|
|
52
52
|
"cosmiconfig": "^9.0.2",
|
|
53
53
|
"jiti": "^2.7.0",
|
|
54
54
|
"tinyexec": "~1.1.2",
|
|
55
|
-
"@kubb/core": "5.0.0-beta.
|
|
55
|
+
"@kubb/core": "5.0.0-beta.56"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@internals/shared": "0.0.0",
|
|
59
59
|
"@internals/utils": "0.0.0",
|
|
60
|
-
"@kubb/adapter-oas": "5.0.0-beta.
|
|
60
|
+
"@kubb/adapter-oas": "5.0.0-beta.56"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"@kubb/adapter-oas": "5.0.0-beta.
|
|
64
|
-
"@kubb/mcp": "5.0.0-beta.
|
|
63
|
+
"@kubb/adapter-oas": "5.0.0-beta.56",
|
|
64
|
+
"@kubb/mcp": "5.0.0-beta.56"
|
|
65
65
|
},
|
|
66
66
|
"peerDependenciesMeta": {
|
|
67
67
|
"@kubb/adapter-oas": {
|
package/src/Telemetry.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomBytes } from 'node:crypto'
|
|
2
2
|
import os from 'node:os'
|
|
3
3
|
import process from 'node:process'
|
|
4
|
-
import {
|
|
4
|
+
import { isCIEnvironment, runtime } from '@internals/utils'
|
|
5
5
|
import { OTLP_ENDPOINT } from './constants.ts'
|
|
6
6
|
|
|
7
7
|
// OpenTelemetry OTLP JSON types
|
|
@@ -117,7 +117,7 @@ export type TelemetryEvent = {
|
|
|
117
117
|
/**
|
|
118
118
|
* Name of the JavaScript runtime that executed the run, `'bun'`, `'deno'`, or `'node'`.
|
|
119
119
|
*/
|
|
120
|
-
runtime:
|
|
120
|
+
runtime: string
|
|
121
121
|
/**
|
|
122
122
|
* Major version of the active runtime, e.g. `'1'` under Bun or `'22'` under Node.
|
|
123
123
|
*/
|
|
@@ -139,7 +139,7 @@ export class Telemetry {
|
|
|
139
139
|
/**
|
|
140
140
|
* Returns `true` when telemetry is disabled via `DO_NOT_TRACK` or `KUBB_DISABLE_TELEMETRY`.
|
|
141
141
|
*/
|
|
142
|
-
static isDisabled(): boolean {
|
|
142
|
+
static get isDisabled(): boolean {
|
|
143
143
|
return (
|
|
144
144
|
process.env['DO_NOT_TRACK'] === '1' ||
|
|
145
145
|
process.env['DO_NOT_TRACK'] === 'true' ||
|
|
@@ -166,8 +166,8 @@ export class Telemetry {
|
|
|
166
166
|
command: options.command,
|
|
167
167
|
kubbVersion: options.kubbVersion,
|
|
168
168
|
nodeVersion: process.versions.node.split('.')[0] as string,
|
|
169
|
-
runtime:
|
|
170
|
-
runtimeVersion:
|
|
169
|
+
runtime: runtime.name,
|
|
170
|
+
runtimeVersion: runtime.version.split('.')[0] as string,
|
|
171
171
|
platform: os.platform(),
|
|
172
172
|
ci: isCIEnvironment(),
|
|
173
173
|
plugins: options.plugins ?? [],
|
|
@@ -266,25 +266,23 @@ export class Telemetry {
|
|
|
266
266
|
* `KUBB_DISABLE_TELEMETRY`, and fails silently so telemetry never interrupts a run.
|
|
267
267
|
*/
|
|
268
268
|
static async send(event: TelemetryEvent): Promise<void> {
|
|
269
|
-
if (Telemetry.isDisabled
|
|
269
|
+
if (Telemetry.isDisabled) {
|
|
270
270
|
return
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
})
|
|
273
|
+
try {
|
|
274
|
+
await fetch(`${OTLP_ENDPOINT}/v1/traces`, {
|
|
275
|
+
method: 'POST',
|
|
276
|
+
headers: {
|
|
277
|
+
'Content-Type': 'application/json',
|
|
278
|
+
'Kubb-Telemetry-Version': '1',
|
|
279
|
+
'Kubb-Telemetry-Source': 'kubb-core',
|
|
280
|
+
},
|
|
281
|
+
body: JSON.stringify(Telemetry.buildOtlpPayload(event)),
|
|
282
|
+
signal: AbortSignal.timeout(5_000),
|
|
283
|
+
})
|
|
284
|
+
} catch (_e) {
|
|
285
|
+
// Fail silently, telemetry must never break the run
|
|
286
|
+
}
|
|
289
287
|
}
|
|
290
288
|
}
|
package/src/commands/generate.ts
CHANGED
|
@@ -45,11 +45,6 @@ export const command = defineCommand({
|
|
|
45
45
|
hint: 'cli|json|file',
|
|
46
46
|
enum: ['cli', 'json', 'file'],
|
|
47
47
|
},
|
|
48
|
-
'no-cache': {
|
|
49
|
-
type: 'boolean',
|
|
50
|
-
description: 'Disable the incremental build cache and force a full regeneration',
|
|
51
|
-
default: false,
|
|
52
|
-
},
|
|
53
48
|
},
|
|
54
49
|
async run({ values, positionals }) {
|
|
55
50
|
const logLevel = values.verbose ? 'verbose' : values.silent ? 'silent' : values.logLevel
|
|
@@ -65,7 +60,6 @@ export const command = defineCommand({
|
|
|
65
60
|
logLevel,
|
|
66
61
|
watch: values.watch,
|
|
67
62
|
reporters,
|
|
68
|
-
noCache: values['no-cache'],
|
|
69
63
|
})
|
|
70
64
|
},
|
|
71
65
|
})
|
package/src/constants.ts
CHANGED
|
@@ -16,4 +16,4 @@ export const WATCHER_IGNORED_PATHS = '**/{.git,node_modules}/**' as const
|
|
|
16
16
|
/**
|
|
17
17
|
* Flags that short-circuit execution (help/version), no telemetry notice is shown.
|
|
18
18
|
*/
|
|
19
|
-
export const QUIET_FLAGS = new Set(['--help', '-h', '--version', '-v']
|
|
19
|
+
export const QUIET_FLAGS = new Set<string>(['--help', '-h', '--version', '-v'])
|
package/src/index.ts
CHANGED
|
@@ -1,31 +1,14 @@
|
|
|
1
1
|
import { styleText } from 'node:util'
|
|
2
|
-
import { createCLI
|
|
2
|
+
import { createCLI } from '@internals/utils'
|
|
3
3
|
import { Telemetry } from './Telemetry.ts'
|
|
4
4
|
import { version } from '../package.json'
|
|
5
5
|
import { QUIET_FLAGS } from './constants.ts'
|
|
6
6
|
|
|
7
7
|
const cli = createCLI()
|
|
8
|
-
|
|
9
|
-
function shouldShowTelemetryNotice(argv: Array<string>): boolean {
|
|
10
|
-
if (Telemetry.isDisabled()) {
|
|
11
|
-
return false
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// Skip when the user is just asking for help or version info
|
|
15
|
-
if (argv.some((arg) => isFlag(QUIET_FLAGS, arg))) {
|
|
16
|
-
return false
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Skip in non-interactive / scripting contexts
|
|
20
|
-
if (!process.stdout.isTTY) {
|
|
21
|
-
return false
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return true
|
|
25
|
-
}
|
|
26
|
-
|
|
27
8
|
export async function run(argv: Array<string> = process.argv): Promise<void> {
|
|
28
|
-
|
|
9
|
+
const isQuietFlag = argv.some((arg) => QUIET_FLAGS.has(arg))
|
|
10
|
+
|
|
11
|
+
if (!Telemetry.isDisabled && !isQuietFlag) {
|
|
29
12
|
console.log(
|
|
30
13
|
`${styleText('yellow', 'Notice:')} Kubb collects anonymous telemetry data to help improve the tool. No personal data or file contents are collected. \nTo disable, set ${styleText('cyan', 'KUBB_DISABLE_TELEMETRY=1')}.\n`,
|
|
31
14
|
)
|
|
@@ -5,7 +5,7 @@ import process from 'node:process'
|
|
|
5
5
|
import { styleText } from 'node:util'
|
|
6
6
|
import * as clack from '@clack/prompts'
|
|
7
7
|
import type { AsyncEventEmitter } from '@internals/utils'
|
|
8
|
-
import { AsyncEventEmitter as AsyncEventEmitterClass,
|
|
8
|
+
import { AsyncEventEmitter as AsyncEventEmitterClass, detectTool, formatters, linters, toError } from '@internals/utils'
|
|
9
9
|
import {
|
|
10
10
|
type CLIOptions,
|
|
11
11
|
cliReporter,
|
|
@@ -208,7 +208,7 @@ async function generate(options: GenerateProps): Promise<boolean> {
|
|
|
208
208
|
config.output.format && {
|
|
209
209
|
code: Diagnostics.code.formatFailed,
|
|
210
210
|
toolValue: config.output.format,
|
|
211
|
-
detect:
|
|
211
|
+
detect: () => detectTool(['oxfmt', 'biome', 'prettier'] as const),
|
|
212
212
|
toolMap: formatters,
|
|
213
213
|
toolLabel: 'formatter',
|
|
214
214
|
successPrefix: 'Formatting',
|
|
@@ -219,7 +219,7 @@ async function generate(options: GenerateProps): Promise<boolean> {
|
|
|
219
219
|
config.output.lint && {
|
|
220
220
|
code: Diagnostics.code.lintFailed,
|
|
221
221
|
toolValue: config.output.lint,
|
|
222
|
-
detect:
|
|
222
|
+
detect: () => detectTool(['oxlint', 'biome', 'eslint'] as const),
|
|
223
223
|
toolMap: linters,
|
|
224
224
|
toolLabel: 'linter',
|
|
225
225
|
successPrefix: 'Linting',
|
|
@@ -302,21 +302,18 @@ type GenerateCommandOptions = {
|
|
|
302
302
|
logLevel: string
|
|
303
303
|
watch: boolean
|
|
304
304
|
reporters?: Array<ReporterName>
|
|
305
|
-
noCache?: boolean
|
|
306
305
|
}
|
|
307
306
|
|
|
308
307
|
async function checkForUpdate(hooks: AsyncEventEmitter<KubbHooks>): Promise<void> {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
await Diagnostics.emit(hooks, Diagnostics.update({ currentVersion: version, latestVersion: data.version }))
|
|
315
|
-
}
|
|
316
|
-
} catch {
|
|
317
|
-
// Ignore network errors
|
|
308
|
+
try {
|
|
309
|
+
const res = await fetch(KUBB_NPM_PACKAGE_URL)
|
|
310
|
+
const data = (await res.json()) as { version: string }
|
|
311
|
+
if (data.version && version < data.version) {
|
|
312
|
+
await Diagnostics.emit(hooks, Diagnostics.update({ currentVersion: version, latestVersion: data.version }))
|
|
318
313
|
}
|
|
319
|
-
}
|
|
314
|
+
} catch {
|
|
315
|
+
// Ignore network errors
|
|
316
|
+
}
|
|
320
317
|
}
|
|
321
318
|
|
|
322
319
|
/**
|
|
@@ -324,7 +321,7 @@ async function checkForUpdate(hooks: AsyncEventEmitter<KubbHooks>): Promise<void
|
|
|
324
321
|
* Loads configs, sets up the selected reporters (CLI `--reporter` overrides `config.reporters`),
|
|
325
322
|
* checks for a newer version, and calls `generate` for each config entry.
|
|
326
323
|
*/
|
|
327
|
-
export async function run({ input, configPath, logLevel: logLevelKey, watch, reporters: cliReporters
|
|
324
|
+
export async function run({ input, configPath, logLevel: logLevelKey, watch, reporters: cliReporters }: GenerateCommandOptions): Promise<void> {
|
|
328
325
|
const logLevel = logLevelMap[logLevelKey as keyof typeof logLevelMap] ?? logLevelMap.info
|
|
329
326
|
const hooks = new AsyncEventEmitterClass<KubbHooks>()
|
|
330
327
|
|
|
@@ -338,7 +335,6 @@ export async function run({ input, configPath, logLevel: logLevelKey, watch, rep
|
|
|
338
335
|
input,
|
|
339
336
|
watch,
|
|
340
337
|
logLevel: logLevelKey as CLIOptions['logLevel'],
|
|
341
|
-
noCache,
|
|
342
338
|
})
|
|
343
339
|
configs = loaded.configs
|
|
344
340
|
resolvedConfigPath = loaded.configPath
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { hash } from 'node:crypto'
|
|
2
2
|
import { styleText } from 'node:util'
|
|
3
|
+
import { createModuleLoader } from '@internals/shared'
|
|
3
4
|
import type { AsyncEventEmitter } from '@internals/utils'
|
|
4
|
-
import { toError
|
|
5
|
+
import { toError } from '@internals/utils'
|
|
5
6
|
import type { CLIOptions, Config, KubbHooks, PossibleConfig } from '@kubb/core'
|
|
6
7
|
import { cosmiconfig } from 'cosmiconfig'
|
|
7
|
-
import { createJiti } from 'jiti'
|
|
8
8
|
import { NonZeroExitError, x } from 'tinyexec'
|
|
9
9
|
import { WATCHER_IGNORED_PATHS } from '../../constants.ts'
|
|
10
10
|
|
|
@@ -14,12 +14,9 @@ type CosmiconfigResult = {
|
|
|
14
14
|
config: PossibleConfig<CLIOptions>
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const
|
|
18
|
-
jsx: { runtime: 'automatic', importSource: '@kubb/renderer-jsx' },
|
|
19
|
-
moduleCache: false,
|
|
20
|
-
})
|
|
17
|
+
const loader = createModuleLoader()
|
|
21
18
|
|
|
22
|
-
const tsLoader = (configFile: string) =>
|
|
19
|
+
const tsLoader = (configFile: string) => loader.load(configFile, { default: true })
|
|
23
20
|
|
|
24
21
|
const MODULE_NAME = 'kubb'
|
|
25
22
|
|
|
@@ -83,10 +80,6 @@ type GetConfigsOptions = {
|
|
|
83
80
|
* Log level forwarded to the user's `defineConfig` function.
|
|
84
81
|
*/
|
|
85
82
|
logLevel?: CLIOptions['logLevel']
|
|
86
|
-
/**
|
|
87
|
-
* When set, turns off the incremental build cache for this run, forcing a full regeneration.
|
|
88
|
-
*/
|
|
89
|
-
noCache?: boolean
|
|
90
83
|
}
|
|
91
84
|
|
|
92
85
|
type GetConfigsResult = {
|
|
@@ -104,20 +97,15 @@ type GetConfigsResult = {
|
|
|
104
97
|
* Discovers the Kubb config via cosmiconfig and resolves it into a normalized array of configs.
|
|
105
98
|
* Every config in the result is guaranteed to have a `plugins` array.
|
|
106
99
|
*/
|
|
107
|
-
export async function getConfigs({ configPath, input, watch, logLevel
|
|
100
|
+
export async function getConfigs({ configPath, input, watch, logLevel }: GetConfigsOptions): Promise<GetConfigsResult> {
|
|
108
101
|
const result = await getCosmiConfig(configPath)
|
|
109
|
-
const cli: CLIOptions = { config: configPath, input, watch, logLevel
|
|
102
|
+
const cli: CLIOptions = { config: configPath, input, watch, logLevel }
|
|
110
103
|
const resolved = await (typeof result.config === 'function' ? result.config(cli) : result.config)
|
|
111
104
|
const userConfigs = Array.isArray(resolved) ? resolved : [resolved]
|
|
112
105
|
|
|
113
106
|
return {
|
|
114
107
|
configPath: result.filepath,
|
|
115
|
-
configs: userConfigs.map((item) => {
|
|
116
|
-
const config = { ...item, plugins: item.plugins ?? [] } as Config
|
|
117
|
-
// `--no-cache` overrides whatever cache the config resolved to (fsCache by default), so the
|
|
118
|
-
// run regenerates everything instead of restoring a snapshot.
|
|
119
|
-
return noCache ? { ...config, cache: undefined } : config
|
|
120
|
-
}),
|
|
108
|
+
configs: userConfigs.map((item) => ({ ...item, plugins: item.plugins ?? [] }) as Config),
|
|
121
109
|
}
|
|
122
110
|
}
|
|
123
111
|
|
|
@@ -126,6 +114,17 @@ type ExecuteHooksOptions = {
|
|
|
126
114
|
hooks: AsyncEventEmitter<KubbHooks>
|
|
127
115
|
}
|
|
128
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Tokenizes a shell command string, respecting single and double quotes.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* tokenize('git commit -m "initial commit"')
|
|
122
|
+
* // → ['git', 'commit', '-m', 'initial commit']
|
|
123
|
+
*/
|
|
124
|
+
function tokenize(command: string): Array<string> {
|
|
125
|
+
return (command.match(/[^\s"']+|"([^"]*)"|'([^']*)'/g) ?? []).map((token) => token.replace(/^["']|["']$/g, ''))
|
|
126
|
+
}
|
|
127
|
+
|
|
129
128
|
/**
|
|
130
129
|
* Runs the `done` hooks defined in a Kubb config in sequence.
|
|
131
130
|
*/
|
|
@@ -2,7 +2,7 @@ import fs from 'node:fs'
|
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import process from 'node:process'
|
|
4
4
|
import type { PackageManagerInfo, PackageManagerName } from '@internals/utils'
|
|
5
|
-
import {
|
|
5
|
+
import { x } from 'tinyexec'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Returns `true` when a `package.json` exists at `cwd`.
|
|
@@ -22,12 +22,18 @@ export async function initPackageJson(cwd: string, packageManager: PackageManage
|
|
|
22
22
|
bun: ['init', '-y'],
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
await
|
|
25
|
+
await x(packageManager.name, commands[packageManager.name], {
|
|
26
|
+
nodeOptions: { cwd, stdio: 'inherit' },
|
|
27
|
+
throwOnError: true,
|
|
28
|
+
})
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
/**
|
|
29
32
|
* Installs the given packages at `cwd` using the detected package manager.
|
|
30
33
|
*/
|
|
31
34
|
export async function installPackages(packages: Array<string>, packageManager: PackageManagerInfo, cwd: string = process.cwd()): Promise<void> {
|
|
32
|
-
await
|
|
35
|
+
await x(packageManager.name, [...packageManager.installCommand, ...packages], {
|
|
36
|
+
nodeOptions: { cwd, stdio: 'inherit' },
|
|
37
|
+
throwOnError: true,
|
|
38
|
+
})
|
|
33
39
|
}
|