@kubb/cli 5.11.4 → 5.11.6
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-Be1nltUh.cjs → Telemetry-Be3hIy6_.cjs} +2 -42
- package/dist/Telemetry-Be3hIy6_.cjs.map +1 -0
- package/dist/{Telemetry-CwaVQsvD.js → Telemetry-CfJAUDnh.js} +3 -31
- package/dist/Telemetry-CfJAUDnh.js.map +1 -0
- package/dist/{background-CQPyCSn0.js → background-BBpH2jmk.js} +7 -5
- package/dist/background-BBpH2jmk.js.map +1 -0
- package/dist/{background-mKdZ5HRx.cjs → background-BW-e9FCX.cjs} +5 -4
- package/dist/background-BW-e9FCX.cjs.map +1 -0
- package/dist/{background-aTbwrgui.js → background-DS2zOde-.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 +872 -307
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +863 -298
- package/dist/index.js.map +1 -1
- package/dist/registry-BlKLO4ft.cjs +272 -0
- package/dist/registry-BlKLO4ft.cjs.map +1 -0
- package/dist/registry-CgQYxUju.js +200 -0
- package/dist/registry-CgQYxUju.js.map +1 -0
- package/dist/reporters-Dl8lrJZG.js +817 -0
- package/dist/reporters-Dl8lrJZG.js.map +1 -0
- package/dist/reporters-TkCgd4dS.cjs +829 -0
- package/dist/reporters-TkCgd4dS.cjs.map +1 -0
- package/dist/{run-YHth5Afz.js → run-BJn0RSW2.js} +170 -76
- package/dist/run-BJn0RSW2.js.map +1 -0
- package/dist/{run-BWRmQxtE.cjs → run-BszyZwY3.cjs} +176 -82
- package/dist/run-BszyZwY3.cjs.map +1 -0
- package/dist/{run-Bczs5vbI.cjs → run-BtVKUjdK.cjs} +4 -3
- package/dist/{run-Bczs5vbI.cjs.map → run-BtVKUjdK.cjs.map} +1 -1
- package/dist/run-CFf0yxyY.cjs +94 -0
- package/dist/run-CFf0yxyY.cjs.map +1 -0
- package/dist/run-D_dD7xHp.js +93 -0
- package/dist/run-D_dD7xHp.js.map +1 -0
- package/dist/run-DsJJCzQD.js +1 -0
- package/dist/{run-B6VxJ_VM.js → run-KuzAqsjg.js} +3 -2
- package/dist/{run-B6VxJ_VM.js.map → run-KuzAqsjg.js.map} +1 -1
- package/dist/run-TrjCNL8e.cjs +227 -0
- package/dist/run-TrjCNL8e.cjs.map +1 -0
- package/dist/run-wkN1irUo.js +224 -0
- package/dist/run-wkN1irUo.js.map +1 -0
- package/dist/{snapshot-Cilp10vE.js → snapshot-CdGwHH15.js} +49 -62
- package/dist/snapshot-CdGwHH15.js.map +1 -0
- package/dist/{snapshot-D_rXnnMH.cjs → snapshot-u4L8mh4Y.cjs} +51 -64
- package/dist/snapshot-u4L8mh4Y.cjs.map +1 -0
- package/dist/status-DHPeR3bq.js +77 -0
- package/dist/status-DHPeR3bq.js.map +1 -0
- package/dist/status-dpSvxxtN.cjs +78 -0
- package/dist/status-dpSvxxtN.cjs.map +1 -0
- package/dist/studioWorker.js +2 -2
- package/dist/summary-6-rotl2L.cjs +46 -0
- package/dist/summary-6-rotl2L.cjs.map +1 -0
- package/dist/summary-DkSLti6f.js +41 -0
- package/dist/summary-DkSLti6f.js.map +1 -0
- package/dist/text-CMP4M19Z.js +239 -0
- package/dist/text-CMP4M19Z.js.map +1 -0
- package/dist/text-CknhKMvM.cjs +341 -0
- package/dist/text-CknhKMvM.cjs.map +1 -0
- package/dist/utils-CnjEJIdZ.js +612 -0
- package/dist/utils-CnjEJIdZ.js.map +1 -0
- package/dist/utils-DpKrXR2t.cjs +727 -0
- package/dist/utils-DpKrXR2t.cjs.map +1 -0
- package/package.json +7 -7
- package/dist/Telemetry-Be1nltUh.cjs.map +0 -1
- package/dist/Telemetry-CwaVQsvD.js.map +0 -1
- package/dist/background-CQPyCSn0.js.map +0 -1
- package/dist/background-mKdZ5HRx.cjs.map +0 -1
- package/dist/config-B56ZuVhi.js +0 -95
- package/dist/config-B56ZuVhi.js.map +0 -1
- package/dist/config-Cs4N79Fm.cjs +0 -113
- package/dist/config-Cs4N79Fm.cjs.map +0 -1
- package/dist/output-HgzJqkSF.cjs +0 -1076
- package/dist/output-HgzJqkSF.cjs.map +0 -1
- package/dist/output-PhkPtNP7.js +0 -937
- package/dist/output-PhkPtNP7.js.map +0 -1
- package/dist/registry-DYUhC7rH.js +0 -115
- package/dist/registry-DYUhC7rH.js.map +0 -1
- package/dist/registry-tk-v78fd.cjs +0 -157
- package/dist/registry-tk-v78fd.cjs.map +0 -1
- package/dist/run-AfjIBtiL.js +0 -39
- package/dist/run-AfjIBtiL.js.map +0 -1
- package/dist/run-BWRmQxtE.cjs.map +0 -1
- package/dist/run-B_Gr9TJ4.cjs +0 -345
- package/dist/run-B_Gr9TJ4.cjs.map +0 -1
- package/dist/run-CwrI0wRy.js +0 -1
- package/dist/run-DDoJGjWT.cjs +0 -40
- package/dist/run-DDoJGjWT.cjs.map +0 -1
- package/dist/run-SYKj8-Q5.js +0 -343
- package/dist/run-SYKj8-Q5.js.map +0 -1
- package/dist/run-YHth5Afz.js.map +0 -1
- package/dist/snapshot-Cilp10vE.js.map +0 -1
- package/dist/snapshot-D_rXnnMH.cjs.map +0 -1
package/dist/output-PhkPtNP7.js
DELETED
|
@@ -1,937 +0,0 @@
|
|
|
1
|
-
import "./rolldown-runtime-CRm0XQPb.js";
|
|
2
|
-
import { a as getElapsedMs, i as formatMs, s as isCIEnvironment } from "./Telemetry-CwaVQsvD.js";
|
|
3
|
-
import { stripVTControlCharacters, styleText } from "node:util";
|
|
4
|
-
import process$1 from "node:process";
|
|
5
|
-
import { readFile } from "node:fs/promises";
|
|
6
|
-
import { dirname, join, relative, resolve } from "node:path";
|
|
7
|
-
import { existsSync } from "node:fs";
|
|
8
|
-
import { getAgentProfile } from "gunshi/agent";
|
|
9
|
-
import { Diagnostics, logLevel } from "@kubb/core";
|
|
10
|
-
import * as clack from "@clack/prompts";
|
|
11
|
-
import { createJiti } from "jiti";
|
|
12
|
-
import { setTimeout } from "node:timers/promises";
|
|
13
|
-
//#region ../../internals/shared/src/constants.ts
|
|
14
|
-
const KUBB_CONFIG_FILENAME = "kubb.config.ts";
|
|
15
|
-
/** File extensions a Kubb config file may use. */
|
|
16
|
-
const CONFIG_EXTENSIONS = [
|
|
17
|
-
".ts",
|
|
18
|
-
".mts",
|
|
19
|
-
".cts",
|
|
20
|
-
".js",
|
|
21
|
-
".mjs",
|
|
22
|
-
".cjs"
|
|
23
|
-
];
|
|
24
|
-
const KUBB_PACKAGE_NAME = "kubb";
|
|
25
|
-
const initDefaults = {
|
|
26
|
-
inputPath: "./openapi.yaml",
|
|
27
|
-
outputPath: "./src/gen",
|
|
28
|
-
plugins: ["plugin-ts"]
|
|
29
|
-
};
|
|
30
|
-
//#endregion
|
|
31
|
-
//#region ../../internals/shared/src/loader.ts
|
|
32
|
-
/**
|
|
33
|
-
* jiti options for loading Kubb config modules: the automatic JSX runtime pointed at
|
|
34
|
-
* `@kubb/renderer-jsx`, and `moduleCache` off so a re-load re-evaluates the file.
|
|
35
|
-
*/
|
|
36
|
-
const JITI_OPTIONS = {
|
|
37
|
-
jsx: {
|
|
38
|
-
runtime: "automatic",
|
|
39
|
-
importSource: "@kubb/renderer-jsx"
|
|
40
|
-
},
|
|
41
|
-
moduleCache: false
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* Plain JavaScript files. jiti hands these to Node's native `import()`, whose module cache never
|
|
45
|
-
* lets go of a file, so `moduleCache: false` alone would keep returning the first version of it.
|
|
46
|
-
*/
|
|
47
|
-
const JAVASCRIPT_EXTENSION = /\.[cm]?jsx?$/;
|
|
48
|
-
const jiti = createJiti(import.meta.url, JITI_OPTIONS);
|
|
49
|
-
/**
|
|
50
|
-
* Loads a Kubb TypeScript or JavaScript config module via jiti.
|
|
51
|
-
*
|
|
52
|
-
* jiti transpiles TypeScript and the `@kubb/renderer-jsx` JSX runtime on the fly. Every load
|
|
53
|
-
* re-evaluates the file, so a config edited on disk is picked up by the next load.
|
|
54
|
-
*
|
|
55
|
-
* @example
|
|
56
|
-
* ```ts
|
|
57
|
-
* const config = await loadModule('/abs/kubb.config.ts', { default: true })
|
|
58
|
-
* ```
|
|
59
|
-
*/
|
|
60
|
-
async function loadModule(filePath, options) {
|
|
61
|
-
if (!JAVASCRIPT_EXTENSION.test(filePath)) return options?.default ? jiti.import(filePath, { default: true }) : jiti.import(filePath);
|
|
62
|
-
const mod = await jiti.evalModule(await readFile(filePath, "utf8"), {
|
|
63
|
-
filename: filePath,
|
|
64
|
-
async: true,
|
|
65
|
-
forceTranspile: true
|
|
66
|
-
});
|
|
67
|
-
return options?.default ? mod?.default ?? mod : mod;
|
|
68
|
-
}
|
|
69
|
-
//#endregion
|
|
70
|
-
//#region ../../internals/shared/src/config.ts
|
|
71
|
-
const SEARCH_FILES = [
|
|
72
|
-
"",
|
|
73
|
-
".config/",
|
|
74
|
-
"configs/"
|
|
75
|
-
].flatMap((prefix) => [`${prefix}.kubbrc`, `${prefix}kubb.config`]);
|
|
76
|
-
/**
|
|
77
|
-
* The first Kubb config file in `cwd` or the nearest parent folder that has one: `.kubbrc` before
|
|
78
|
-
* `kubb.config`, the folder itself before its `.config/` and `configs/`, and {@link CONFIG_EXTENSIONS} in order.
|
|
79
|
-
*/
|
|
80
|
-
function findConfigFile(cwd = process$1.cwd()) {
|
|
81
|
-
for (let dir = resolve(cwd);; dir = dirname(dir)) {
|
|
82
|
-
const found = SEARCH_FILES.flatMap((file) => CONFIG_EXTENSIONS.map((extension) => join(dir, `${file}${extension}`))).find((file) => existsSync(file));
|
|
83
|
-
if (found || dirname(dir) === dir) return found;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Loads a Kubb config module, calls it with `cli` when it exports a function, and returns its
|
|
88
|
-
* configs as a list, so a single config and a `defineConfig([...])` array read the same.
|
|
89
|
-
*/
|
|
90
|
-
async function loadConfigFile(file, cli) {
|
|
91
|
-
const loaded = await loadModule(file, { default: true });
|
|
92
|
-
const resolved = await (typeof loaded === "function" ? loaded(cli) : loaded);
|
|
93
|
-
return Array.isArray(resolved) ? resolved : [resolved];
|
|
94
|
-
}
|
|
95
|
-
//#endregion
|
|
96
|
-
//#region src/utils/env.ts
|
|
97
|
-
/**
|
|
98
|
-
* Returns `true` when the process has an interactive TTY with a valid terminal
|
|
99
|
-
* width and is not running in CI.
|
|
100
|
-
*
|
|
101
|
-
* Some IDE-embedded terminals report `isTTY = true` but set `columns` to `0`,
|
|
102
|
-
* which breaks clack's box-drawing helpers (they call `String.prototype.repeat`
|
|
103
|
-
* with a negative count and throw a `RangeError`). A positive column count is
|
|
104
|
-
* required before the TTY counts as usable.
|
|
105
|
-
*
|
|
106
|
-
* @example
|
|
107
|
-
* ```ts
|
|
108
|
-
* if (canUseTTY()) {
|
|
109
|
-
* renderProgressBar()
|
|
110
|
-
* }
|
|
111
|
-
* ```
|
|
112
|
-
*/
|
|
113
|
-
function canUseTTY() {
|
|
114
|
-
return process.stdout.isTTY && (process.stdout.columns ?? 0) > 0 && !isCIEnvironment();
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Returns `true` when output can carry spinners and clack's gutter: an interactive TTY that no AI
|
|
118
|
-
* coding agent is reading. Cursor-movement escapes are hard for an agent to parse even over a
|
|
119
|
-
* pseudo-TTY, so it gets the plain writer.
|
|
120
|
-
*/
|
|
121
|
-
function isRichOutput() {
|
|
122
|
-
return canUseTTY() && !getAgentProfile().isAgent;
|
|
123
|
-
}
|
|
124
|
-
//#endregion
|
|
125
|
-
//#region src/loggers/banner.ts
|
|
126
|
-
/**
|
|
127
|
-
* xterm-256 color for each pixel letter of the mascot. Fixed codes rather than named colors, so a
|
|
128
|
-
* terminal theme cannot repaint it.
|
|
129
|
-
*/
|
|
130
|
-
const colors = {
|
|
131
|
-
/** Hoodie. */
|
|
132
|
-
O: 208,
|
|
133
|
-
/** Shadow where the hood meets the face. */
|
|
134
|
-
R: 166,
|
|
135
|
-
/** Face. */
|
|
136
|
-
F: 223,
|
|
137
|
-
/** Eyes. */
|
|
138
|
-
K: 16,
|
|
139
|
-
/** Blush. */
|
|
140
|
-
B: 217,
|
|
141
|
-
/** Mouth. */
|
|
142
|
-
M: 131
|
|
143
|
-
};
|
|
144
|
-
/**
|
|
145
|
-
* The two pixel rows of the face around the eyes, for each expression.
|
|
146
|
-
*/
|
|
147
|
-
const eyes = {
|
|
148
|
-
open: ["FFFFFFFFFF", "FFKFFFFKFF"],
|
|
149
|
-
left: ["FFFFFFFFFF", "FKFFFFKFFF"],
|
|
150
|
-
right: ["FFFFFFFFFF", "FFFKFFFFKF"],
|
|
151
|
-
blink: ["FFFFFFFFFF", "FKKFFFFKKF"],
|
|
152
|
-
happy: ["FFKFFFFKFF", "FKFKFFKFKF"]
|
|
153
|
-
};
|
|
154
|
-
/**
|
|
155
|
-
* The frames the mascot plays when the CLI starts, each with how long it stays on screen. It ends on
|
|
156
|
-
* open eyes, which stay.
|
|
157
|
-
*/
|
|
158
|
-
const wakeUp = [
|
|
159
|
-
["blink", 100],
|
|
160
|
-
["open", 180],
|
|
161
|
-
["left", 140],
|
|
162
|
-
["right", 140],
|
|
163
|
-
["open", 80],
|
|
164
|
-
["happy", 220],
|
|
165
|
-
["open", 0]
|
|
166
|
-
];
|
|
167
|
-
/**
|
|
168
|
-
* The kid in the orange hoodie from the Kubb logo, one letter per pixel and `.` for none. Each
|
|
169
|
-
* 2 × 2 block becomes one terminal cell, so a block holds at most two colors.
|
|
170
|
-
*/
|
|
171
|
-
function pixels(expression) {
|
|
172
|
-
const [top, bottom] = eyes[expression];
|
|
173
|
-
return [
|
|
174
|
-
"....OOOOOOOOOO....",
|
|
175
|
-
"..OORRRRRRRRRROO..",
|
|
176
|
-
`..OO${top}OO..`,
|
|
177
|
-
`OOFF${bottom}FFOO`,
|
|
178
|
-
"OOFFBBFFMMFFBBFFOO",
|
|
179
|
-
"..OOOOFFFFFFOOOO.."
|
|
180
|
-
];
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Quadrant glyphs indexed by which quarters are filled: top left 1, top right 2, bottom left 4,
|
|
184
|
-
* bottom right 8.
|
|
185
|
-
*/
|
|
186
|
-
const quadrants = " ▘▝▀▖▌▞▛▗▚▐▜▄▙▟█";
|
|
187
|
-
/**
|
|
188
|
-
* Draws each 2 × 2 block of pixels as one quadrant glyph. The glyph's filled quarters take the first
|
|
189
|
-
* color in the block and the rest take the other.
|
|
190
|
-
*/
|
|
191
|
-
function drawHead(expression) {
|
|
192
|
-
const rows = pixels(expression);
|
|
193
|
-
const lines = [];
|
|
194
|
-
for (let y = 0; y < rows.length; y += 2) {
|
|
195
|
-
let line = "";
|
|
196
|
-
for (let x = 0; x < rows[y].length; x += 2) {
|
|
197
|
-
const block = [
|
|
198
|
-
rows[y][x],
|
|
199
|
-
rows[y][x + 1],
|
|
200
|
-
rows[y + 1][x],
|
|
201
|
-
rows[y + 1][x + 1]
|
|
202
|
-
];
|
|
203
|
-
const fg = block.find((pixel) => pixel in colors);
|
|
204
|
-
if (!fg) {
|
|
205
|
-
line += " ";
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
const bg = colors[block.find((pixel) => pixel !== fg) ?? "."];
|
|
209
|
-
const mask = block.reduce((bits, pixel, index) => pixel === fg ? bits | 1 << index : bits, 0);
|
|
210
|
-
line += `\x1b[38;5;${colors[fg]}${bg === void 0 ? "" : `;48;5;${bg}`}m${quadrants[mask]}\x1b[0m`;
|
|
211
|
-
}
|
|
212
|
-
lines.push(line);
|
|
213
|
-
}
|
|
214
|
-
return lines;
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Generates the Kubb mascot welcome banner as an ANSI-colored string: the head with the version,
|
|
218
|
-
* title, and description beside it.
|
|
219
|
-
*
|
|
220
|
-
* @example
|
|
221
|
-
* ```ts
|
|
222
|
-
* console.log(getIntro({ title: 'kubb.config.ts', description: 'generating…', version: '5.0.0', expression: 'open' }))
|
|
223
|
-
* ```
|
|
224
|
-
*/
|
|
225
|
-
function getIntro({ title, description, version, expression }) {
|
|
226
|
-
const text = [
|
|
227
|
-
styleText(["bold", "yellow"], `KUBB v${version}`),
|
|
228
|
-
styleText("gray", title),
|
|
229
|
-
`${styleText("yellow", "➜")} ${styleText("white", description)}`
|
|
230
|
-
];
|
|
231
|
-
return drawHead(expression).map((line, index) => ` ${line} ${text[index]}`).join("\n");
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Formats a millisecond duration with a threshold-based ANSI color.
|
|
235
|
-
* `≤ 500 ms` → green · `≤ 1 000 ms` → yellow · `> 1 000 ms` → red.
|
|
236
|
-
*
|
|
237
|
-
* @example
|
|
238
|
-
* ```ts
|
|
239
|
-
* formatMsWithColor(200) // '\x1b[32m200ms\x1b[39m'
|
|
240
|
-
* formatMsWithColor(800) // '\x1b[33m800ms\x1b[39m'
|
|
241
|
-
* formatMsWithColor(1500) // '\x1b[31m1.50s\x1b[39m'
|
|
242
|
-
* ```
|
|
243
|
-
*/
|
|
244
|
-
function formatMsWithColor(ms) {
|
|
245
|
-
const formatted = formatMs(ms);
|
|
246
|
-
if (ms <= 500) return styleText("green", formatted);
|
|
247
|
-
if (ms <= 1e3) return styleText("yellow", formatted);
|
|
248
|
-
return styleText("red", formatted);
|
|
249
|
-
}
|
|
250
|
-
//#endregion
|
|
251
|
-
//#region src/loggers/createLogger.ts
|
|
252
|
-
/** Display path for a config's input: the string form, or its `path` field when the input is an object. */
|
|
253
|
-
function getInputPath(config) {
|
|
254
|
-
const { input } = config;
|
|
255
|
-
if (typeof input === "string") return input;
|
|
256
|
-
return typeof input?.path === "string" ? input.path : void 0;
|
|
257
|
-
}
|
|
258
|
-
/** Counts a noun, so a message never reads `1 files`. */
|
|
259
|
-
function pluralize(count, noun) {
|
|
260
|
-
return `${count} ${count === 1 ? noun : `${noun}s`}`;
|
|
261
|
-
}
|
|
262
|
-
/** Prefixes a `[HH:MM:SS]` timestamp at verbose and above. */
|
|
263
|
-
function formatMessage(message, logLevel$1) {
|
|
264
|
-
if (logLevel$1 >= logLevel.verbose) {
|
|
265
|
-
const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
|
|
266
|
-
hour12: false,
|
|
267
|
-
hour: "2-digit",
|
|
268
|
-
minute: "2-digit",
|
|
269
|
-
second: "2-digit"
|
|
270
|
-
});
|
|
271
|
-
return `${styleText("dim", `[${timestamp}]`)} ${message}`;
|
|
272
|
-
}
|
|
273
|
-
return message;
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Renders a `studio:connected` event's versions: the runtime only when it differs from the host.
|
|
277
|
-
*/
|
|
278
|
-
function formatVersions({ studio, kubb, agent }) {
|
|
279
|
-
return [
|
|
280
|
-
`v${agent}`,
|
|
281
|
-
kubb !== agent ? `runtime v${kubb}` : void 0,
|
|
282
|
-
`Studio v${studio}`
|
|
283
|
-
].filter(Boolean).join(", ");
|
|
284
|
-
}
|
|
285
|
-
/** The progress summary line the clack logger shows, `null` when there is nothing to display. */
|
|
286
|
-
function buildProgressLine(state) {
|
|
287
|
-
const parts = [];
|
|
288
|
-
const duration = formatMs(getElapsedMs(state.hrStart));
|
|
289
|
-
if (state.totalPlugins > 0) {
|
|
290
|
-
const pluginStr = state.failedPlugins > 0 ? `Plugins ${styleText("green", state.completedPlugins.toString())}/${state.totalPlugins} ${styleText("red", `(${state.failedPlugins} failed)`)}` : `Plugins ${styleText("green", state.completedPlugins.toString())}/${state.totalPlugins}`;
|
|
291
|
-
parts.push(pluginStr);
|
|
292
|
-
}
|
|
293
|
-
if (state.totalFiles > 0) parts.push(`Files ${styleText("green", state.processedFiles.toString())}/${state.totalFiles}`);
|
|
294
|
-
if (parts.length === 0) return null;
|
|
295
|
-
parts.push(`${styleText("green", duration)} elapsed`);
|
|
296
|
-
return parts.join(styleText("dim", " | "));
|
|
297
|
-
}
|
|
298
|
-
function createProgressCounters() {
|
|
299
|
-
return {
|
|
300
|
-
totalPlugins: 0,
|
|
301
|
-
completedPlugins: 0,
|
|
302
|
-
failedPlugins: 0,
|
|
303
|
-
totalFiles: 0,
|
|
304
|
-
processedFiles: 0,
|
|
305
|
-
hrStart: process$1.hrtime()
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* The three output phases, in the order the generate runner runs them.
|
|
310
|
-
*/
|
|
311
|
-
const PHASES = {
|
|
312
|
-
format: {
|
|
313
|
-
running: "Formatting",
|
|
314
|
-
success: "Formatted",
|
|
315
|
-
failure: "Formatting failed"
|
|
316
|
-
},
|
|
317
|
-
lint: {
|
|
318
|
-
running: "Linting",
|
|
319
|
-
success: "Linted",
|
|
320
|
-
failure: "Linting failed"
|
|
321
|
-
},
|
|
322
|
-
hooks: {
|
|
323
|
-
running: "Running post-generate hooks",
|
|
324
|
-
success: "Post-generate hooks completed",
|
|
325
|
-
failure: "Post-generate hooks failed",
|
|
326
|
-
showHookResults: true
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
/**
|
|
330
|
-
* Drops the blank lines a subprocess leaves at either end of its output, so its block does not open
|
|
331
|
-
* or close on an empty row.
|
|
332
|
-
*/
|
|
333
|
-
function trimBlankEdges(lines) {
|
|
334
|
-
const start = lines.findIndex((line) => line.trim());
|
|
335
|
-
if (start === -1) return [];
|
|
336
|
-
return lines.slice(start, lines.findLastIndex((line) => line.trim()) + 1);
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* Wires a {@link LoggerWriter} onto the run's hooks. This owns what a run says and in what order:
|
|
340
|
-
* one group per config, a step over the plugin work, a progress bar for the writes, one step per
|
|
341
|
-
* output phase, then the summary and the group's closing result. The writer only decides how each
|
|
342
|
-
* line looks, so every logger reports the same run the same way.
|
|
343
|
-
*
|
|
344
|
-
* @example
|
|
345
|
-
* ```ts
|
|
346
|
-
* export const plainLogger = createLogger(writer, { audience: 'agent' })
|
|
347
|
-
* ```
|
|
348
|
-
*/
|
|
349
|
-
function createLogger(writer, { audience }) {
|
|
350
|
-
return function install(context, { logLevel: logLevel$2 }) {
|
|
351
|
-
const silent = logLevel$2 <= logLevel.silent;
|
|
352
|
-
const human = audience === "human";
|
|
353
|
-
const formatOptions = {
|
|
354
|
-
audience,
|
|
355
|
-
verbose: logLevel$2 >= logLevel.verbose,
|
|
356
|
-
width: Math.min(process$1.stdout.columns || 80, 100) - 2
|
|
357
|
-
};
|
|
358
|
-
const state = {
|
|
359
|
-
...createProgressCounters(),
|
|
360
|
-
spinner: null,
|
|
361
|
-
progress: null,
|
|
362
|
-
hooks: /* @__PURE__ */ new Map(),
|
|
363
|
-
/**
|
|
364
|
-
* Plugin results held back while the generation step owns the line.
|
|
365
|
-
*/
|
|
366
|
-
pluginLines: [],
|
|
367
|
-
phase: null,
|
|
368
|
-
groupOpen: false,
|
|
369
|
-
/**
|
|
370
|
-
* Whether this run keeps its files in memory, as a `kubb studio` run without `--allow-write` does.
|
|
371
|
-
*/
|
|
372
|
-
inMemory: false,
|
|
373
|
-
/**
|
|
374
|
-
* Problems held back so the human view can print them grouped by plugin once the build ends.
|
|
375
|
-
*/
|
|
376
|
-
problems: [],
|
|
377
|
-
/**
|
|
378
|
-
* The finished config's diagnostics and file count, for the closing summary.
|
|
379
|
-
*/
|
|
380
|
-
outcome: null
|
|
381
|
-
};
|
|
382
|
-
function text(message) {
|
|
383
|
-
return formatMessage(message, logLevel$2);
|
|
384
|
-
}
|
|
385
|
-
function startSpinner(message) {
|
|
386
|
-
if (silent) return;
|
|
387
|
-
state.spinner = writer.spinner();
|
|
388
|
-
state.spinner.start(text(message));
|
|
389
|
-
}
|
|
390
|
-
function stopSpinner(message, status = "success") {
|
|
391
|
-
const spinner = state.spinner;
|
|
392
|
-
if (!spinner) return;
|
|
393
|
-
state.spinner = null;
|
|
394
|
-
if (message === void 0) {
|
|
395
|
-
spinner.clear();
|
|
396
|
-
return;
|
|
397
|
-
}
|
|
398
|
-
if (status === "failed") {
|
|
399
|
-
spinner.error(text(message));
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
spinner.stop(text(message));
|
|
403
|
-
}
|
|
404
|
-
function stopProgress(message) {
|
|
405
|
-
const progress = state.progress;
|
|
406
|
-
if (!progress) return;
|
|
407
|
-
state.progress = null;
|
|
408
|
-
progress.stop(message === void 0 ? "" : text(message));
|
|
409
|
-
}
|
|
410
|
-
function startPhase({ running, success, failure, showHookResults = false }) {
|
|
411
|
-
state.phase = {
|
|
412
|
-
successLabel: success,
|
|
413
|
-
failureLabel: failure,
|
|
414
|
-
showHookResults,
|
|
415
|
-
failed: false,
|
|
416
|
-
hrStart: process$1.hrtime(),
|
|
417
|
-
lines: [],
|
|
418
|
-
output: []
|
|
419
|
-
};
|
|
420
|
-
startSpinner(running);
|
|
421
|
-
}
|
|
422
|
-
function endPhase() {
|
|
423
|
-
const phase = state.phase;
|
|
424
|
-
state.phase = null;
|
|
425
|
-
if (!phase || silent) return;
|
|
426
|
-
const duration = formatMsWithColor(getElapsedMs(phase.hrStart));
|
|
427
|
-
stopSpinner(phase.failed ? `${phase.failureLabel} after ${duration}` : `${phase.successLabel} in ${duration}`, phase.failed ? "failed" : "success");
|
|
428
|
-
if (phase.lines.length) writer.block(phase.lines);
|
|
429
|
-
writeOutput(phase.output);
|
|
430
|
-
}
|
|
431
|
-
function writeOutput(lines) {
|
|
432
|
-
const output = trimBlankEdges(lines);
|
|
433
|
-
if (output.length) writer.raw(output);
|
|
434
|
-
}
|
|
435
|
-
/** `✖ Failed 1 error · 1 warning in plugin-ts` once the build ended, or `✗ Generation failed` for a run that stopped early. */
|
|
436
|
-
function failedTitle() {
|
|
437
|
-
const diagnostics = state.outcome?.diagnostics ?? [];
|
|
438
|
-
const counts = formatCounts(diagnostics);
|
|
439
|
-
if (!human || !counts) return "✗ Generation failed";
|
|
440
|
-
const plugins = Diagnostics.failedPlugins(diagnostics);
|
|
441
|
-
return `✖ Failed ${counts}${plugins.length ? ` in ${plugins.join(", ")}` : ""}`;
|
|
442
|
-
}
|
|
443
|
-
function closeGroup(status) {
|
|
444
|
-
if (!state.groupOpen) return;
|
|
445
|
-
state.groupOpen = false;
|
|
446
|
-
stopSpinner();
|
|
447
|
-
stopProgress();
|
|
448
|
-
writer.groupEnd(status === "failed" ? styleText("red", failedTitle()) : styleText("green", "✓ Generation succeeded"));
|
|
449
|
-
}
|
|
450
|
-
function reset() {
|
|
451
|
-
stopSpinner();
|
|
452
|
-
stopProgress();
|
|
453
|
-
Object.assign(state, createProgressCounters());
|
|
454
|
-
state.hooks.clear();
|
|
455
|
-
state.pluginLines = [];
|
|
456
|
-
state.phase = null;
|
|
457
|
-
state.groupOpen = false;
|
|
458
|
-
state.problems = [];
|
|
459
|
-
state.outcome = null;
|
|
460
|
-
}
|
|
461
|
-
/**
|
|
462
|
-
* Prints problems grouped under their plugin's name, each with the code aligned at the right.
|
|
463
|
-
*/
|
|
464
|
-
function writeProblems(problems) {
|
|
465
|
-
if (!problems.length) return;
|
|
466
|
-
if (!human) {
|
|
467
|
-
for (const problem of problems) writer.diagnostic(Diagnostics.format(problem, formatOptions));
|
|
468
|
-
return;
|
|
469
|
-
}
|
|
470
|
-
const lines = [...Map.groupBy(problems, (problem) => problem.plugin ?? "")].flatMap(([plugin, group]) => [...plugin ? [` ${styleText("bold", plugin)}`, ""] : [], ...group.flatMap((problem) => [...Diagnostics.format(problem, formatOptions).map((line) => ` ${line}`), ""])]);
|
|
471
|
-
writer.diagnostic(lines.slice(0, -1));
|
|
472
|
-
}
|
|
473
|
-
/** The run's verdict: `1 error · 1 warning` for a human, `1 error, 1 warning` for an agent. */
|
|
474
|
-
function formatCounts(diagnostics) {
|
|
475
|
-
const { errors, warnings } = Diagnostics.count(diagnostics);
|
|
476
|
-
return [errors && pluralize(errors, "error"), warnings && pluralize(warnings, "warning")].filter(Boolean).join(human ? " · " : ", ");
|
|
477
|
-
}
|
|
478
|
-
function formatLine(symbol, message, info) {
|
|
479
|
-
return text([
|
|
480
|
-
symbol,
|
|
481
|
-
message,
|
|
482
|
-
info && styleText("dim", info)
|
|
483
|
-
].filter(Boolean).join(" "));
|
|
484
|
-
}
|
|
485
|
-
context.hook("kubb:warn", ({ message, info }) => {
|
|
486
|
-
if (logLevel$2 < logLevel.warn) return;
|
|
487
|
-
writer.warn(formatLine(styleText("yellow", "⚠"), message, logLevel$2 >= logLevel.info ? info : void 0));
|
|
488
|
-
});
|
|
489
|
-
context.hook("kubb:error", ({ error }) => {
|
|
490
|
-
if (state.phase) state.phase.failed = true;
|
|
491
|
-
const message = error.name === "Error" || Diagnostics.isError(error) ? error.message : `${error.name}: ${error.message}`;
|
|
492
|
-
const help = Diagnostics.isError(error) ? error.diagnostic.help : void 0;
|
|
493
|
-
const [headline = "", ...details] = Diagnostics.format({
|
|
494
|
-
code: Diagnostics.code.unknown,
|
|
495
|
-
severity: "error",
|
|
496
|
-
message,
|
|
497
|
-
help,
|
|
498
|
-
cause: error
|
|
499
|
-
}, formatOptions);
|
|
500
|
-
if (!human) {
|
|
501
|
-
stopSpinner();
|
|
502
|
-
stopProgress();
|
|
503
|
-
writer.diagnostic([headline, ...details]);
|
|
504
|
-
return;
|
|
505
|
-
}
|
|
506
|
-
if (state.spinner) stopSpinner(message, "failed");
|
|
507
|
-
else writer.error(text(message));
|
|
508
|
-
if (details.length) writer.block(details.map(text));
|
|
509
|
-
});
|
|
510
|
-
context.hook("kubb:diagnostic", ({ diagnostic }) => {
|
|
511
|
-
if (silent && diagnostic.severity !== "error") return;
|
|
512
|
-
stopSpinner();
|
|
513
|
-
stopProgress();
|
|
514
|
-
if (Diagnostics.isUpdate(diagnostic)) {
|
|
515
|
-
writer.update([`\`v${diagnostic.currentVersion}\` → \`v${diagnostic.latestVersion}\``, "Run `npm install -g @kubb/cli` to update"], "Update available for `Kubb`");
|
|
516
|
-
return;
|
|
517
|
-
}
|
|
518
|
-
if (human && state.groupOpen) {
|
|
519
|
-
state.problems.push(diagnostic);
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
writeProblems([diagnostic]);
|
|
523
|
-
});
|
|
524
|
-
context.hook("studio:disconnected", ({ code, reason }) => {
|
|
525
|
-
if (logLevel$2 < logLevel.warn) return;
|
|
526
|
-
stopSpinner();
|
|
527
|
-
if (code === 4002) {
|
|
528
|
-
writer.warn(text("⚠ Another process connected to Kubb Studio as this agent, so this one stopped"));
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
writer.warn(text(`⚠ Kubb Studio ended the session (${reason || `code ${code}`})`));
|
|
532
|
-
});
|
|
533
|
-
context.hook("studio:warn", ({ message, permission }) => {
|
|
534
|
-
if (logLevel$2 < logLevel.warn) return;
|
|
535
|
-
const remedy = permission ? `; pass --${permission.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`)} to allow it` : "";
|
|
536
|
-
writer.warn(text(`⚠ ${message}${remedy}`));
|
|
537
|
-
});
|
|
538
|
-
context.hook("studio:error", ({ error }) => {
|
|
539
|
-
if (state.spinner) {
|
|
540
|
-
stopSpinner(error.message, "failed");
|
|
541
|
-
return;
|
|
542
|
-
}
|
|
543
|
-
writer.error(text(error.message));
|
|
544
|
-
});
|
|
545
|
-
context.hook("kubb:lifecycle:start", () => {
|
|
546
|
-
reset();
|
|
547
|
-
});
|
|
548
|
-
context.hook("kubb:generation:start", ({ config }) => {
|
|
549
|
-
closeGroup("failed");
|
|
550
|
-
reset();
|
|
551
|
-
state.totalPlugins = config.plugins?.length ?? 0;
|
|
552
|
-
state.inMemory = config.storage?.name === "memory";
|
|
553
|
-
if (silent) return;
|
|
554
|
-
const inputPath = getInputPath(config);
|
|
555
|
-
writer.group(text([styleText("bold", config.name ?? "kubb"), inputPath ? styleText("dim", inputPath) : void 0].filter(Boolean).join(" ")));
|
|
556
|
-
state.groupOpen = true;
|
|
557
|
-
startSpinner("Generating");
|
|
558
|
-
});
|
|
559
|
-
context.hook("kubb:format:start", () => startPhase(PHASES.format));
|
|
560
|
-
context.hook("kubb:format:end", endPhase);
|
|
561
|
-
context.hook("kubb:lint:start", () => startPhase(PHASES.lint));
|
|
562
|
-
context.hook("kubb:lint:end", endPhase);
|
|
563
|
-
context.hook("kubb:hooks:start", () => startPhase(PHASES.hooks));
|
|
564
|
-
context.hook("kubb:hooks:end", endPhase);
|
|
565
|
-
context.hook("kubb:hook:end", (ctx) => {
|
|
566
|
-
const { id, command, name, args, success, error } = ctx;
|
|
567
|
-
if (!id) return;
|
|
568
|
-
if (!success && state.phase) state.phase.failed = true;
|
|
569
|
-
if (silent) {
|
|
570
|
-
if (!ctx.success) {
|
|
571
|
-
if (ctx.stdout) console.log(ctx.stdout);
|
|
572
|
-
if (ctx.stderr) console.error(ctx.stderr);
|
|
573
|
-
}
|
|
574
|
-
return;
|
|
575
|
-
}
|
|
576
|
-
const active = state.hooks.get(id);
|
|
577
|
-
if (!active) return;
|
|
578
|
-
state.hooks.delete(id);
|
|
579
|
-
const label = styleText("dim", name ?? (args?.length ? `${command} ${args.join(" ")}` : command));
|
|
580
|
-
const reason = error?.message ? ` (${error.message})` : "";
|
|
581
|
-
const result = success ? `${styleText("green", "✓")} ${label} in ${formatMsWithColor(getElapsedMs(active.hrStart))}` : `${styleText("red", "✗")} ${label} failed${reason}`;
|
|
582
|
-
const phase = state.phase;
|
|
583
|
-
if (phase) {
|
|
584
|
-
if (phase.showHookResults || !success) phase.lines.push(result);
|
|
585
|
-
phase.output.push(...active.lines);
|
|
586
|
-
return;
|
|
587
|
-
}
|
|
588
|
-
stopSpinner();
|
|
589
|
-
writer.step(text(result));
|
|
590
|
-
writeOutput(active.lines);
|
|
591
|
-
});
|
|
592
|
-
context.hook("kubb:generation:end", ({ diagnostics = [], filesCreated = 0, hrStart = process$1.hrtime() }) => {
|
|
593
|
-
stopSpinner();
|
|
594
|
-
stopProgress();
|
|
595
|
-
state.outcome = {
|
|
596
|
-
diagnostics,
|
|
597
|
-
filesCreated,
|
|
598
|
-
hrStart
|
|
599
|
-
};
|
|
600
|
-
writeProblems(state.problems.splice(0));
|
|
601
|
-
});
|
|
602
|
-
context.hook("kubb:lifecycle:end", () => {
|
|
603
|
-
writeProblems(state.problems.splice(0));
|
|
604
|
-
closeGroup("failed");
|
|
605
|
-
reset();
|
|
606
|
-
});
|
|
607
|
-
if (!silent) {
|
|
608
|
-
context.hook("kubb:info", ({ message, info }) => {
|
|
609
|
-
const line = formatLine(styleText("blue", "ℹ"), message, info);
|
|
610
|
-
if (state.phase) {
|
|
611
|
-
state.phase.lines.push(line);
|
|
612
|
-
return;
|
|
613
|
-
}
|
|
614
|
-
if (state.spinner) {
|
|
615
|
-
state.spinner.message(line);
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
618
|
-
writer.info(line);
|
|
619
|
-
});
|
|
620
|
-
context.hook("kubb:success", ({ message, info }) => {
|
|
621
|
-
const line = formatLine(styleText("green", "✓"), message, logLevel$2 >= logLevel.info ? info : void 0);
|
|
622
|
-
if (state.spinner) {
|
|
623
|
-
state.spinner.message(line);
|
|
624
|
-
return;
|
|
625
|
-
}
|
|
626
|
-
writer.success(line);
|
|
627
|
-
});
|
|
628
|
-
context.hook("studio:connected", ({ url, versions }) => {
|
|
629
|
-
stopSpinner();
|
|
630
|
-
writer.success(text(`✓ Connected to ${styleText("cyan", url)} ${styleText("dim", `(${formatVersions(versions)})`)}`));
|
|
631
|
-
startSpinner("✓ Ready to receive jobs");
|
|
632
|
-
});
|
|
633
|
-
context.hook("studio:command", ({ command, info }) => {
|
|
634
|
-
stopSpinner();
|
|
635
|
-
writer.success(text(`✓ Finished ${command} ${styleText("dim", `(${info})`)}`));
|
|
636
|
-
startSpinner("✓ Ready to receive jobs");
|
|
637
|
-
});
|
|
638
|
-
context.hook("studio:reconnecting", ({ delayMs }) => {
|
|
639
|
-
stopSpinner();
|
|
640
|
-
writer.info(text(styleText("dim", `Retrying connection to Kubb Studio in ${formatMs(delayMs)}`)));
|
|
641
|
-
});
|
|
642
|
-
context.hook("kubb:plugin:start", ({ plugin }) => {
|
|
643
|
-
state.spinner?.message(text(`Generating ${styleText("dim", plugin.name)}`));
|
|
644
|
-
});
|
|
645
|
-
context.hook("kubb:plugin:end", ({ plugin, duration, success }) => {
|
|
646
|
-
if (success) state.completedPlugins++;
|
|
647
|
-
if (!success) state.failedPlugins++;
|
|
648
|
-
state.pluginLines.push(text(`${plugin.name} ${success ? "completed" : "failed"} in ${formatMsWithColor(duration)}`));
|
|
649
|
-
});
|
|
650
|
-
context.hook("kubb:plugins:end", () => {
|
|
651
|
-
const failed = state.failedPlugins > 0;
|
|
652
|
-
stopSpinner(buildProgressLine(state) ?? void 0, failed ? "failed" : "success");
|
|
653
|
-
if (state.pluginLines.length) {
|
|
654
|
-
writer.block(state.pluginLines);
|
|
655
|
-
state.pluginLines = [];
|
|
656
|
-
}
|
|
657
|
-
});
|
|
658
|
-
context.hook("kubb:files:processing:start", ({ files }) => {
|
|
659
|
-
stopSpinner();
|
|
660
|
-
state.totalFiles = files.length;
|
|
661
|
-
state.processedFiles = 0;
|
|
662
|
-
state.progress = writer.progress(files.length);
|
|
663
|
-
state.progress.start(text(`${state.inMemory ? "Generating" : "Writing"} ${pluralize(files.length, "file")}`));
|
|
664
|
-
});
|
|
665
|
-
context.hook("kubb:files:processing:update", ({ files }) => {
|
|
666
|
-
for (const { file, config } of files) {
|
|
667
|
-
state.processedFiles++;
|
|
668
|
-
state.progress?.advance(`${state.inMemory ? "Generating" : "Writing"} ${relative(config.root, file.path)}`);
|
|
669
|
-
}
|
|
670
|
-
});
|
|
671
|
-
context.hook("kubb:files:processing:end", () => {
|
|
672
|
-
stopProgress(state.inMemory ? `Generated ${pluralize(state.processedFiles, "file")} in memory` : `Wrote ${pluralize(state.processedFiles, "file")}`);
|
|
673
|
-
});
|
|
674
|
-
context.hook("kubb:hook:start", ({ id }) => {
|
|
675
|
-
if (!id) return;
|
|
676
|
-
state.hooks.set(id, {
|
|
677
|
-
hrStart: process$1.hrtime(),
|
|
678
|
-
lines: []
|
|
679
|
-
});
|
|
680
|
-
});
|
|
681
|
-
context.hook("kubb:hook:line", ({ id, line }) => {
|
|
682
|
-
const active = state.hooks.get(id);
|
|
683
|
-
if (!active) return;
|
|
684
|
-
if (state.phase) {
|
|
685
|
-
active.lines.push(line);
|
|
686
|
-
return;
|
|
687
|
-
}
|
|
688
|
-
writer.raw([line]);
|
|
689
|
-
});
|
|
690
|
-
}
|
|
691
|
-
return { renderSummary(lines, { status }) {
|
|
692
|
-
if (silent || !state.groupOpen) return;
|
|
693
|
-
if (human) {
|
|
694
|
-
closeGroup(status);
|
|
695
|
-
writer.diagnostic([...lines]);
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
stopSpinner();
|
|
699
|
-
stopProgress();
|
|
700
|
-
state.groupOpen = false;
|
|
701
|
-
const { diagnostics = [], filesCreated = 0, hrStart = process$1.hrtime() } = state.outcome ?? {};
|
|
702
|
-
if (status === "failed") {
|
|
703
|
-
const plugins = Diagnostics.failedPlugins(diagnostics);
|
|
704
|
-
writer.diagnostic([`Kubb failed: ${formatCounts(diagnostics) || "an error"}${plugins.length ? ` (${plugins.join(", ")})` : ""}. Exit code 1.`, "Rerun with --reporter json for machine-readable diagnostics."]);
|
|
705
|
-
return;
|
|
706
|
-
}
|
|
707
|
-
const warnings = formatCounts(diagnostics);
|
|
708
|
-
writer.diagnostic([`Kubb succeeded: ${pluralize(filesCreated, "file")} generated in ${formatMs(getElapsedMs(hrStart))}${warnings ? `, ${warnings}` : ""}.`]);
|
|
709
|
-
} };
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
//#endregion
|
|
713
|
-
//#region src/loggers/clackLogger.ts
|
|
714
|
-
/**
|
|
715
|
-
* Draws with clack: a gutter bar per group, animated steps, and a progress bar for the writes.
|
|
716
|
-
*/
|
|
717
|
-
const clackWriter = {
|
|
718
|
-
group: (title) => clack.intro(title),
|
|
719
|
-
groupEnd: (text) => clack.outro(text),
|
|
720
|
-
step: (text) => clack.log.step(text, { spacing: 0 }),
|
|
721
|
-
info: (text) => clack.log.info(text),
|
|
722
|
-
success: (text) => clack.log.success(text),
|
|
723
|
-
warn: (text) => clack.log.warn(text),
|
|
724
|
-
error: (text) => clack.log.error(text),
|
|
725
|
-
block: (lines) => clack.log.message(lines, { spacing: 0 }),
|
|
726
|
-
raw: (lines) => console.log(styleText("dim", lines.join("\n"))),
|
|
727
|
-
diagnostic: (lines) => clack.log.message(lines, {
|
|
728
|
-
symbol: "",
|
|
729
|
-
secondarySymbol: ""
|
|
730
|
-
}),
|
|
731
|
-
update: (lines, title) => clack.box(lines.join("\n"), title, {
|
|
732
|
-
width: "auto",
|
|
733
|
-
formatBorder: (border) => styleText("yellow", border),
|
|
734
|
-
rounded: true,
|
|
735
|
-
withGuide: false,
|
|
736
|
-
contentAlign: "center",
|
|
737
|
-
titleAlign: "center"
|
|
738
|
-
}),
|
|
739
|
-
spinner: () => clack.spinner(),
|
|
740
|
-
progress(max) {
|
|
741
|
-
const bar = clack.progress({
|
|
742
|
-
style: "block",
|
|
743
|
-
max,
|
|
744
|
-
size: 30
|
|
745
|
-
});
|
|
746
|
-
return {
|
|
747
|
-
start: (text) => bar.start(text),
|
|
748
|
-
advance: (text) => bar.advance(1, text),
|
|
749
|
-
stop: (text) => bar.stop(text)
|
|
750
|
-
};
|
|
751
|
-
}
|
|
752
|
-
};
|
|
753
|
-
/**
|
|
754
|
-
* TTY logger for local development, with animated steps and progress bars.
|
|
755
|
-
*/
|
|
756
|
-
const clackLogger = createLogger(clackWriter, { audience: "human" });
|
|
757
|
-
//#endregion
|
|
758
|
-
//#region src/loggers/plainLogger.ts
|
|
759
|
-
/**
|
|
760
|
-
* Prefixes that stand in for the symbols clack draws, so plain output reads the same way.
|
|
761
|
-
*/
|
|
762
|
-
const SYMBOLS = {
|
|
763
|
-
info: "ℹ",
|
|
764
|
-
warn: "⚠",
|
|
765
|
-
error: "✗",
|
|
766
|
-
step: "◇"
|
|
767
|
-
};
|
|
768
|
-
/** Draws with one `write` call per line. Nothing animates, so a step prints at start and end. */
|
|
769
|
-
function createWriter(write) {
|
|
770
|
-
return {
|
|
771
|
-
group: write,
|
|
772
|
-
groupEnd: write,
|
|
773
|
-
step: (text) => write(`${SYMBOLS.step} ${text}`),
|
|
774
|
-
info: write,
|
|
775
|
-
success: write,
|
|
776
|
-
warn: write,
|
|
777
|
-
error: (text) => write(`${SYMBOLS.error} ${text}`),
|
|
778
|
-
block: (lines) => write(lines.join("\n")),
|
|
779
|
-
raw: (lines) => write(lines.join("\n")),
|
|
780
|
-
diagnostic: (lines) => write(lines.join("\n")),
|
|
781
|
-
update: (lines, title) => write([title, ...lines].join("\n")),
|
|
782
|
-
spinner: () => ({
|
|
783
|
-
start: write,
|
|
784
|
-
message: write,
|
|
785
|
-
clear: () => {},
|
|
786
|
-
stop: (text) => text && write(text),
|
|
787
|
-
error: (text) => write(`${SYMBOLS.error} ${text}`)
|
|
788
|
-
}),
|
|
789
|
-
progress: () => ({
|
|
790
|
-
start: write,
|
|
791
|
-
advance: write,
|
|
792
|
-
stop: (text) => text && write(text)
|
|
793
|
-
})
|
|
794
|
-
};
|
|
795
|
-
}
|
|
796
|
-
/** The plain logger writing through `write`, e.g. `console.error` so stdout carries only JSON. */
|
|
797
|
-
function createPlainLogger(write) {
|
|
798
|
-
return createLogger(createWriter(write), { audience: "agent" });
|
|
799
|
-
}
|
|
800
|
-
/** Draws on the console, for non-TTY environments and for an AI coding agent reading the output. */
|
|
801
|
-
const plainWriter = createWriter((line) => console.log(line));
|
|
802
|
-
/**
|
|
803
|
-
* Console adapter for non-TTY environments, and for an AI coding agent reading the output. Reports
|
|
804
|
-
* the same run in the same order as `clackLogger`, without the animation.
|
|
805
|
-
*/
|
|
806
|
-
const plainLogger = createLogger(plainWriter, { audience: "agent" });
|
|
807
|
-
//#endregion
|
|
808
|
-
//#region src/loggers/output.ts
|
|
809
|
-
const SPONSOR_TIPS = [
|
|
810
|
-
"Your sponsorship keeps Kubb codegen, plugins, and docs maintained",
|
|
811
|
-
"Sponsor faster generators and better Kubb Studio workflows",
|
|
812
|
-
"Help keep Kubb free for TypeScript teams building APIs",
|
|
813
|
-
"Support React Query, Zod, Faker, and MSW integrations",
|
|
814
|
-
"Back open-source tools that turn OpenAPI into TypeScript",
|
|
815
|
-
"Sponsor fixes, releases, and new plugins for your API workflow",
|
|
816
|
-
"Help Kubb stay independent and focused on developer tools"
|
|
817
|
-
];
|
|
818
|
-
const SPONSOR_LINKS = [
|
|
819
|
-
"https://github.com/sponsors/stijnvanhulle",
|
|
820
|
-
"https://opencollective.com/kubb",
|
|
821
|
-
"https://kubb.dev/sponsors"
|
|
822
|
-
];
|
|
823
|
-
/** The writer the loggers draw with on this terminal, so a command's own lines look like its run. */
|
|
824
|
-
function writer() {
|
|
825
|
-
return isRichOutput() ? clackWriter : plainWriter;
|
|
826
|
-
}
|
|
827
|
-
function nextTip() {
|
|
828
|
-
return `${SPONSOR_TIPS[Math.floor(Math.random() * SPONSOR_TIPS.length)]}: ${SPONSOR_LINKS[Math.floor(Math.random() * SPONSOR_LINKS.length)]}`;
|
|
829
|
-
}
|
|
830
|
-
function formatTip(tip) {
|
|
831
|
-
return styleText("magenta", " Tip ") + styleText("yellow", tip);
|
|
832
|
-
}
|
|
833
|
-
/**
|
|
834
|
-
* Prints one random tip outside every group. Rich terminals get the styled variant;
|
|
835
|
-
* plain/CI output gets a stable text-only line so the tip is still visible as final output.
|
|
836
|
-
*/
|
|
837
|
-
function logTip() {
|
|
838
|
-
const tip = nextTip();
|
|
839
|
-
if (!isRichOutput()) {
|
|
840
|
-
console.log(`Tip: ${tip}`);
|
|
841
|
-
return;
|
|
842
|
-
}
|
|
843
|
-
console.log(`${styleText("magenta", "✦")}${formatTip(tip)}`);
|
|
844
|
-
}
|
|
845
|
-
function write(level, message) {
|
|
846
|
-
if (isRichOutput()) {
|
|
847
|
-
clack.log[level](message);
|
|
848
|
-
return;
|
|
849
|
-
}
|
|
850
|
-
console.log(`${SYMBOLS[level]} ${message}`);
|
|
851
|
-
}
|
|
852
|
-
/**
|
|
853
|
-
* Opens a command's output with its title.
|
|
854
|
-
*/
|
|
855
|
-
function logIntro({ title, warning, block = true }) {
|
|
856
|
-
if (block && isRichOutput()) {
|
|
857
|
-
if (title) clack.intro(title);
|
|
858
|
-
if (warning) clack.log.warn(warning);
|
|
859
|
-
return;
|
|
860
|
-
}
|
|
861
|
-
if (title) console.log(title);
|
|
862
|
-
if (warning) console.warn(warning);
|
|
863
|
-
if (title || warning) console.log();
|
|
864
|
-
}
|
|
865
|
-
/**
|
|
866
|
-
* Closes the block {@link logIntro} opened. The closing gutter is not a written line, so plain
|
|
867
|
-
* output prints the text on its own.
|
|
868
|
-
*/
|
|
869
|
-
function logOutro(text) {
|
|
870
|
-
writer().groupEnd(text);
|
|
871
|
-
}
|
|
872
|
-
/**
|
|
873
|
-
* Prints one empty line between two groups, without clack's gutter bar, since the bar belongs to a
|
|
874
|
-
* group and a spacer sits outside every one.
|
|
875
|
-
*/
|
|
876
|
-
function logSpacer() {
|
|
877
|
-
console.log("");
|
|
878
|
-
}
|
|
879
|
-
/**
|
|
880
|
-
* Opens the command with the Kubb mascot and version, or a single version line where the terminal
|
|
881
|
-
* cannot draw it. The mascot first plays its wake-up frames in place, which takes under a second.
|
|
882
|
-
*/
|
|
883
|
-
async function logBanner(version) {
|
|
884
|
-
const intro = (expression) => getIntro({
|
|
885
|
-
title: "Turn your API spec into type-safe code",
|
|
886
|
-
description: "Ready to start",
|
|
887
|
-
version,
|
|
888
|
-
expression
|
|
889
|
-
});
|
|
890
|
-
const fits = () => stripVTControlCharacters(intro("open")).split("\n").every((line) => line.length <= process.stdout.columns);
|
|
891
|
-
if (!isRichOutput() || !process.stdout.hasColors(256) || !fits()) {
|
|
892
|
-
console.log(`Kubb CLI v${version}`);
|
|
893
|
-
return;
|
|
894
|
-
}
|
|
895
|
-
console.log("");
|
|
896
|
-
for (const [index, [expression, ms]] of wakeUp.entries()) {
|
|
897
|
-
const frame = intro(expression);
|
|
898
|
-
if (index > 0) process.stdout.moveCursor(0, -frame.split("\n").length);
|
|
899
|
-
console.log(frame);
|
|
900
|
-
await setTimeout(ms);
|
|
901
|
-
}
|
|
902
|
-
console.log("");
|
|
903
|
-
}
|
|
904
|
-
/** Prints lines as one block, without a symbol in front of them. Not the writer's block, which drops clack's spacing around it. */
|
|
905
|
-
function logBlock(lines) {
|
|
906
|
-
if (isRichOutput()) {
|
|
907
|
-
clack.log.message(lines);
|
|
908
|
-
return;
|
|
909
|
-
}
|
|
910
|
-
console.log([lines].flat().join("\n"));
|
|
911
|
-
}
|
|
912
|
-
function logInfo(message) {
|
|
913
|
-
write("info", message);
|
|
914
|
-
}
|
|
915
|
-
function logWarn(message) {
|
|
916
|
-
write("warn", message);
|
|
917
|
-
}
|
|
918
|
-
function logError(message) {
|
|
919
|
-
write("error", message);
|
|
920
|
-
}
|
|
921
|
-
/**
|
|
922
|
-
* Reports a step the command is taking, rather than something it found.
|
|
923
|
-
*/
|
|
924
|
-
function logStep(message) {
|
|
925
|
-
write("step", message);
|
|
926
|
-
}
|
|
927
|
-
/**
|
|
928
|
-
* A progress spinner, or a writer that prints each message it is given when the terminal cannot
|
|
929
|
-
* animate one. Callers drive both the same way, including the failure state.
|
|
930
|
-
*/
|
|
931
|
-
function createSpinner() {
|
|
932
|
-
return writer().spinner();
|
|
933
|
-
}
|
|
934
|
-
//#endregion
|
|
935
|
-
export { initDefaults as C, KUBB_PACKAGE_NAME as S, isRichOutput as _, logInfo as a, CONFIG_EXTENSIONS as b, logSpacer as c, logWarn as d, createPlainLogger as f, canUseTTY as g, pluralize as h, logError as i, logStep as l, clackLogger as m, logBanner as n, logIntro as o, plainLogger as p, logBlock as r, logOutro as s, createSpinner as t, logTip as u, findConfigFile as v, KUBB_CONFIG_FILENAME as x, loadConfigFile as y };
|
|
936
|
-
|
|
937
|
-
//# sourceMappingURL=output-PhkPtNP7.js.map
|