@kubb/cli 5.0.0-beta.38 → 5.0.0-beta.39
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/{agent-CfZ_Uqde.js → agent-CLspGfSn.js} +4 -4
- package/dist/{agent-CfZ_Uqde.js.map → agent-CLspGfSn.js.map} +1 -1
- package/dist/{agent-Bl8JwjMa.cjs → agent-RdNQgRXD.cjs} +4 -4
- package/dist/{agent-Bl8JwjMa.cjs.map → agent-RdNQgRXD.cjs.map} +1 -1
- package/dist/{constants-CYxk4aNm.js → constants-84a47qA-.js} +2 -6
- package/dist/constants-84a47qA-.js.map +1 -0
- package/dist/{constants-CAKUpLcQ.cjs → constants-BtmponZ3.cjs} +1 -11
- package/dist/constants-BtmponZ3.cjs.map +1 -0
- package/dist/{generate-Bgds6Zx3.cjs → generate-DK1pLJMi.cjs} +2 -2
- package/dist/{generate-Bgds6Zx3.cjs.map → generate-DK1pLJMi.cjs.map} +1 -1
- package/dist/{generate-CfxFqNeb.js → generate-Db0pJmbG.js} +2 -2
- package/dist/{generate-CfxFqNeb.js.map → generate-Db0pJmbG.js.map} +1 -1
- package/dist/index.cjs +9 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +9 -9
- package/dist/index.js.map +1 -1
- package/dist/{init-TIec3Dym.js → init-DKMwmbmx.js} +2 -2
- package/dist/{init-TIec3Dym.js.map → init-DKMwmbmx.js.map} +1 -1
- package/dist/{init-C5wnuzeK.cjs → init-D_MQBDVz.cjs} +2 -2
- package/dist/{init-C5wnuzeK.cjs.map → init-D_MQBDVz.cjs.map} +1 -1
- package/dist/{mcp-Damue5Mq.js → mcp-DqNyN0cN.js} +3 -3
- package/dist/{mcp-Damue5Mq.js.map → mcp-DqNyN0cN.js.map} +1 -1
- package/dist/{mcp-Cr753GW1.cjs → mcp-DvEeDWlW.cjs} +3 -3
- package/dist/{mcp-Cr753GW1.cjs.map → mcp-DvEeDWlW.cjs.map} +1 -1
- package/dist/package-C8u_WvqI.js +6 -0
- package/dist/package-C8u_WvqI.js.map +1 -0
- package/dist/{package-guApEHiW.cjs → package-CusjBrSS.cjs} +2 -2
- package/dist/package-CusjBrSS.cjs.map +1 -0
- package/dist/{run-DJxYClJV.js → run-BQ3Qj0xB.js} +4 -4
- package/dist/run-BQ3Qj0xB.js.map +1 -0
- package/dist/{run-BvXxelGR.js → run-BQzoaxjR.js} +3 -3
- package/dist/run-BQzoaxjR.js.map +1 -0
- package/dist/{run-C752fag9.js → run-BabEDDqN.js} +128 -369
- package/dist/run-BabEDDqN.js.map +1 -0
- package/dist/{run-BFEK9md9.js → run-CGf0KEts.js} +3 -3
- package/dist/run-CGf0KEts.js.map +1 -0
- package/dist/{run-BFZtWpcW.cjs → run-CJUmJcbC.cjs} +128 -369
- package/dist/run-CJUmJcbC.cjs.map +1 -0
- package/dist/{run-Bz9IFMWg.cjs → run-CkTpemme.cjs} +3 -3
- package/dist/run-CkTpemme.cjs.map +1 -0
- package/dist/{run-BQZyg7If.cjs → run-Cl4SrSob.cjs} +3 -3
- package/dist/run-Cl4SrSob.cjs.map +1 -0
- package/dist/{run-BFv6avA_.cjs → run-D-s2LdlW.cjs} +5 -5
- package/dist/run-D-s2LdlW.cjs.map +1 -0
- package/dist/{validate-DMzjP-hd.cjs → validate-CkW_AKZp.cjs} +3 -3
- package/dist/{validate-DMzjP-hd.cjs.map → validate-CkW_AKZp.cjs.map} +1 -1
- package/dist/{validate-CYTKdezO.js → validate-jRewvR0c.js} +3 -3
- package/dist/{validate-CYTKdezO.js.map → validate-jRewvR0c.js.map} +1 -1
- package/package.json +7 -7
- package/src/constants.ts +0 -15
- package/src/index.ts +2 -2
- package/src/loggers/clackLogger.ts +4 -6
- package/src/loggers/githubActionsLogger.ts +3 -3
- package/src/loggers/plainLogger.ts +2 -3
- package/src/loggers/utils.ts +27 -32
- package/src/runners/agent/run.ts +2 -2
- package/src/runners/generate/run.ts +21 -17
- package/src/runners/mcp/run.ts +2 -2
- package/src/runners/validate/run.ts +2 -2
- package/dist/constants-CAKUpLcQ.cjs.map +0 -1
- package/dist/constants-CYxk4aNm.js.map +0 -1
- package/dist/package-Cnt1K03J.js +0 -6
- package/dist/package-Cnt1K03J.js.map +0 -1
- package/dist/package-guApEHiW.cjs.map +0 -1
- package/dist/run-BFEK9md9.js.map +0 -1
- package/dist/run-BFZtWpcW.cjs.map +0 -1
- package/dist/run-BFv6avA_.cjs.map +0 -1
- package/dist/run-BQZyg7If.cjs.map +0 -1
- package/dist/run-BvXxelGR.js.map +0 -1
- package/dist/run-Bz9IFMWg.cjs.map +0 -1
- package/dist/run-C752fag9.js.map +0 -1
- package/dist/run-DJxYClJV.js.map +0 -1
- package/dist/telemetry-B80oJfxR.cjs +0 -280
- package/dist/telemetry-B80oJfxR.cjs.map +0 -1
- package/dist/telemetry-ueaMzs_c.js +0 -243
- package/dist/telemetry-ueaMzs_c.js.map +0 -1
- package/src/loggers/diagnostics.ts +0 -77
- package/src/reporters/cliReporter.ts +0 -89
- package/src/reporters/fileReporter.ts +0 -103
- package/src/reporters/jsonReporter.ts +0 -20
- package/src/reporters/report.ts +0 -84
- package/src/telemetry.ts +0 -280
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import "./chunk-CRm0XQPb.js";
|
|
2
2
|
import { n as toCause, r as toError } from "./errors-CoxrNXaA.js";
|
|
3
|
-
import { a as canUseTTY, i as executeIfOnline, o as isGitHubActions, r as sendTelemetry, t as buildTelemetryEvent } from "./telemetry-ueaMzs_c.js";
|
|
4
3
|
import { n as tokenize } from "./shell-BrqyJdB7.js";
|
|
5
|
-
import { t as version } from "./package-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
4
|
+
import { t as version } from "./package-C8u_WvqI.js";
|
|
5
|
+
import { r as WATCHER_IGNORED_PATHS, t as KUBB_NPM_PACKAGE_URL } from "./constants-84a47qA-.js";
|
|
6
|
+
import { styleText } from "node:util";
|
|
8
7
|
import { EventEmitter } from "node:events";
|
|
9
8
|
import { createHash } from "node:crypto";
|
|
10
9
|
import { spawn } from "node:child_process";
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import
|
|
10
|
+
import { existsSync } from "node:fs";
|
|
11
|
+
import path, { relative } from "node:path";
|
|
12
|
+
import { promises } from "node:dns";
|
|
13
|
+
import { Diagnostics, Telemetry, cliReporter, createKubb, defineLogger, logLevel, selectReporters } from "@kubb/core";
|
|
14
14
|
import process$1 from "node:process";
|
|
15
15
|
import * as clack from "@clack/prompts";
|
|
16
|
-
import { Diagnostics, createKubb, createReporter, defineLogger, diagnosticCode, isInputPath, isPerformanceDiagnostic, isProblemDiagnostic, isUpdateDiagnostic, logLevel, narrowDiagnostic } from "@kubb/core";
|
|
17
16
|
import { cosmiconfig } from "cosmiconfig";
|
|
18
17
|
import { createJiti } from "jiti";
|
|
19
18
|
import { NonZeroExitError, x } from "tinyexec";
|
|
@@ -285,32 +284,6 @@ function getIntro({ title, description, version, areEyesOpen }) {
|
|
|
285
284
|
`;
|
|
286
285
|
}
|
|
287
286
|
/**
|
|
288
|
-
* ANSI color names used by {@link randomCliColor} for deterministic terminal coloring.
|
|
289
|
-
*/
|
|
290
|
-
const randomColors = [
|
|
291
|
-
"black",
|
|
292
|
-
"red",
|
|
293
|
-
"green",
|
|
294
|
-
"yellow",
|
|
295
|
-
"blue",
|
|
296
|
-
"white",
|
|
297
|
-
"magenta",
|
|
298
|
-
"cyan",
|
|
299
|
-
"gray"
|
|
300
|
-
];
|
|
301
|
-
/**
|
|
302
|
-
* Wraps `text` in a deterministic ANSI color derived from the text's SHA-256 hash.
|
|
303
|
-
*
|
|
304
|
-
* @example
|
|
305
|
-
* ```ts
|
|
306
|
-
* randomCliColor('petstore') // '\x1b[33m' + 'petstore' + '\x1b[39m' (always the same color for 'petstore')
|
|
307
|
-
* ```
|
|
308
|
-
*/
|
|
309
|
-
function randomCliColor(text) {
|
|
310
|
-
if (!text) return "";
|
|
311
|
-
return styleText(randomColors[createHash("sha256").update(text).digest().readUInt32BE(0) % randomColors.length] ?? "white", text);
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
287
|
* Formats a millisecond duration with a threshold-based ANSI color.
|
|
315
288
|
* `≤ 500 ms` → green · `≤ 1 000 ms` → yellow · `> 1 000 ms` → red.
|
|
316
289
|
*
|
|
@@ -328,6 +301,55 @@ function formatMsWithColor(ms) {
|
|
|
328
301
|
return styleText("red", formatted);
|
|
329
302
|
}
|
|
330
303
|
//#endregion
|
|
304
|
+
//#region ../../internals/utils/src/env.ts
|
|
305
|
+
/**
|
|
306
|
+
* Returns `true` when running inside a GitHub Actions workflow.
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```ts
|
|
310
|
+
* if (isGitHubActions()) {
|
|
311
|
+
* core.setOutput('result', 'ok')
|
|
312
|
+
* }
|
|
313
|
+
* ```
|
|
314
|
+
*/
|
|
315
|
+
function isGitHubActions() {
|
|
316
|
+
return !!process.env.GITHUB_ACTIONS;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Returns `true` when the process is running in a CI environment.
|
|
320
|
+
* Covers GitHub Actions, GitLab CI, CircleCI, Travis CI, Jenkins, Bitbucket,
|
|
321
|
+
* TeamCity, Buildkite, and Azure Pipelines.
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* ```ts
|
|
325
|
+
* if (isCIEnvironment()) {
|
|
326
|
+
* logger.level = 'error'
|
|
327
|
+
* }
|
|
328
|
+
* ```
|
|
329
|
+
*/
|
|
330
|
+
function isCIEnvironment() {
|
|
331
|
+
return !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI || process.env.BITBUCKET_BUILD_NUMBER || process.env.JENKINS_URL || process.env.CIRCLECI || process.env.TRAVIS || process.env.TEAMCITY_VERSION || process.env.BUILDKITE || process.env.TF_BUILD);
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Returns `true` when the process has an interactive TTY with a valid terminal
|
|
335
|
+
* width and is not running in CI.
|
|
336
|
+
*
|
|
337
|
+
* Some IDE-embedded terminals report `isTTY = true` but set `columns` to `0`,
|
|
338
|
+
* which breaks clack's box-drawing helpers (they call `String.prototype.repeat`
|
|
339
|
+
* with a negative count and throw a `RangeError`). We therefore require a
|
|
340
|
+
* positive column count before declaring the TTY usable.
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* ```ts
|
|
344
|
+
* if (canUseTTY()) {
|
|
345
|
+
* renderProgressBar()
|
|
346
|
+
* }
|
|
347
|
+
* ```
|
|
348
|
+
*/
|
|
349
|
+
function canUseTTY() {
|
|
350
|
+
return !!process.stdout.isTTY && (process.stdout.columns ?? 0) > 0 && !isCIEnvironment();
|
|
351
|
+
}
|
|
352
|
+
//#endregion
|
|
331
353
|
//#region ../../internals/utils/src/formatters.ts
|
|
332
354
|
/**
|
|
333
355
|
* CLI command descriptors for each supported code formatter.
|
|
@@ -392,62 +414,8 @@ async function detectFormatter() {
|
|
|
392
414
|
return null;
|
|
393
415
|
}
|
|
394
416
|
//#endregion
|
|
395
|
-
//#region ../../internals/utils/src/fs.ts
|
|
396
|
-
/**
|
|
397
|
-
* Writes `data` to `path`, trimming leading/trailing whitespace before saving.
|
|
398
|
-
* Skips the write when the trimmed content is empty or identical to what is already on disk.
|
|
399
|
-
* Creates any missing parent directories automatically.
|
|
400
|
-
* When `sanity` is `true`, re-reads the file after writing and throws if the content does not match.
|
|
401
|
-
*
|
|
402
|
-
* @example
|
|
403
|
-
* ```ts
|
|
404
|
-
* await write('./src/Pet.ts', source) // writes and returns trimmed content
|
|
405
|
-
* await write('./src/Pet.ts', source) // null — file unchanged
|
|
406
|
-
* await write('./src/Pet.ts', ' ') // null — empty content skipped
|
|
407
|
-
* ```
|
|
408
|
-
*/
|
|
409
|
-
async function write(path, data, options = {}) {
|
|
410
|
-
const trimmed = data.trim();
|
|
411
|
-
if (trimmed === "") return null;
|
|
412
|
-
const resolved = resolve(path);
|
|
413
|
-
if (typeof Bun !== "undefined") {
|
|
414
|
-
const file = Bun.file(resolved);
|
|
415
|
-
if ((await file.exists() ? await file.text() : null) === trimmed) return null;
|
|
416
|
-
await Bun.write(resolved, trimmed);
|
|
417
|
-
return trimmed;
|
|
418
|
-
}
|
|
419
|
-
try {
|
|
420
|
-
if (await readFile(resolved, { encoding: "utf-8" }) === trimmed) return null;
|
|
421
|
-
} catch {}
|
|
422
|
-
await mkdir(dirname(resolved), { recursive: true });
|
|
423
|
-
await writeFile(resolved, trimmed, { encoding: "utf-8" });
|
|
424
|
-
if (options.sanity) {
|
|
425
|
-
const savedData = await readFile(resolved, { encoding: "utf-8" });
|
|
426
|
-
if (savedData !== trimmed) throw new Error(`Sanity check failed for ${path}\n\nData[${data.length}]:\n${data}\n\nSaved[${savedData.length}]:\n${savedData}\n`);
|
|
427
|
-
return savedData;
|
|
428
|
-
}
|
|
429
|
-
return trimmed;
|
|
430
|
-
}
|
|
431
|
-
//#endregion
|
|
432
417
|
//#region ../../internals/utils/src/linters.ts
|
|
433
418
|
/**
|
|
434
|
-
* Collects all files under `dir` recursively using Node's built-in fs APIs.
|
|
435
|
-
*
|
|
436
|
-
* Passing explicit file paths to oxlint (instead of a directory) bypasses
|
|
437
|
-
* oxlint's `.gitignore`-aware directory traversal, which would otherwise skip
|
|
438
|
-
* files that are listed in `.gitignore` (e.g. generated output directories).
|
|
439
|
-
*/
|
|
440
|
-
function findLintableFiles(dir) {
|
|
441
|
-
try {
|
|
442
|
-
return readdirSync(dir, {
|
|
443
|
-
withFileTypes: true,
|
|
444
|
-
recursive: true
|
|
445
|
-
}).filter((d) => d.isFile()).map((d) => `${d.parentPath}/${d.name}`);
|
|
446
|
-
} catch {
|
|
447
|
-
return [];
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
/**
|
|
451
419
|
* CLI command descriptors for each supported linter.
|
|
452
420
|
*
|
|
453
421
|
* Each entry contains the executable `command`, an `args` factory that maps an
|
|
@@ -471,7 +439,11 @@ const linters = {
|
|
|
471
439
|
},
|
|
472
440
|
oxlint: {
|
|
473
441
|
command: "oxlint",
|
|
474
|
-
args: (outputPath) => [
|
|
442
|
+
args: (outputPath) => [
|
|
443
|
+
"--fix",
|
|
444
|
+
"--no-ignore",
|
|
445
|
+
outputPath
|
|
446
|
+
],
|
|
475
447
|
errorMessage: "Oxlint not found"
|
|
476
448
|
}
|
|
477
449
|
};
|
|
@@ -506,266 +478,50 @@ async function detectLinter() {
|
|
|
506
478
|
return null;
|
|
507
479
|
}
|
|
508
480
|
//#endregion
|
|
509
|
-
//#region src/
|
|
510
|
-
/**
|
|
511
|
-
* Builds the normalized {@link Report} for one config from its {@link GenerationResult}. Splits the
|
|
512
|
-
* diagnostics into problems and per-plugin timings (slowest first) and derives the plugin and issue
|
|
513
|
-
* counts, so every reporter renders the same data.
|
|
514
|
-
*/
|
|
515
|
-
function buildReport(result) {
|
|
516
|
-
const { config, diagnostics, filesCreated, status, hrStart } = result;
|
|
517
|
-
const failed = Diagnostics.failedPlugins(diagnostics);
|
|
518
|
-
const total = config.plugins?.length ?? 0;
|
|
519
|
-
const counts = Diagnostics.count(diagnostics);
|
|
520
|
-
const problems = diagnostics.filter(isProblemDiagnostic);
|
|
521
|
-
const timings = diagnostics.filter(isPerformanceDiagnostic).sort((a, b) => b.duration - a.duration).map((diagnostic) => ({
|
|
522
|
-
plugin: diagnostic.plugin,
|
|
523
|
-
durationMs: diagnostic.duration
|
|
524
|
-
}));
|
|
525
|
-
return {
|
|
526
|
-
name: config.name ?? "",
|
|
527
|
-
status,
|
|
528
|
-
plugins: {
|
|
529
|
-
passed: total - failed.length,
|
|
530
|
-
failed,
|
|
531
|
-
total
|
|
532
|
-
},
|
|
533
|
-
counts,
|
|
534
|
-
filesCreated,
|
|
535
|
-
durationMs: getElapsedMs(hrStart),
|
|
536
|
-
output: resolve(config.root, config.output.path),
|
|
537
|
-
timings,
|
|
538
|
-
diagnostics: problems.map((diagnostic) => Diagnostics.serialize(diagnostic))
|
|
539
|
-
};
|
|
540
|
-
}
|
|
541
|
-
//#endregion
|
|
542
|
-
//#region src/reporters/cliReporter.ts
|
|
543
|
-
/**
|
|
544
|
-
* Builds the vitest/jest-style summary for one {@link Report}: right-aligned dim labels with
|
|
545
|
-
* `N passed (total)` counts, and a per-plugin `Timings` section when `showTimings`.
|
|
546
|
-
*/
|
|
547
|
-
function buildSummaryLines(report, { showTimings }) {
|
|
548
|
-
const { status, plugins, counts, filesCreated, durationMs, output, timings } = report;
|
|
549
|
-
const rows = [];
|
|
550
|
-
rows.push(["Plugins", status === "success" ? `${styleText("green", `${plugins.passed} passed`)} (${plugins.total})` : `${styleText("green", `${plugins.passed} passed`)} | ${styleText("red", `${plugins.failed.length} failed`)} (${plugins.total})`]);
|
|
551
|
-
if (status === "failed" && plugins.failed.length > 0) rows.push(["Failed", plugins.failed.map((name) => randomCliColor(name)).join(", ")]);
|
|
552
|
-
if (counts.errors > 0 || counts.warnings > 0) {
|
|
553
|
-
const issues = [counts.errors > 0 ? styleText("red", `${counts.errors} ${counts.errors === 1 ? "error" : "errors"}`) : void 0, counts.warnings > 0 ? styleText("yellow", `${counts.warnings} ${counts.warnings === 1 ? "warning" : "warnings"}`) : void 0].filter(Boolean).join(" | ");
|
|
554
|
-
rows.push(["Issues", issues]);
|
|
555
|
-
}
|
|
556
|
-
rows.push(["Files", `${styleText("green", String(filesCreated))} generated`]);
|
|
557
|
-
rows.push(["Duration", styleText("green", formatMs(durationMs))]);
|
|
558
|
-
rows.push(["Output", output]);
|
|
559
|
-
const labelWidth = Math.max(...rows.map(([label]) => label.length), timings.length > 0 ? 7 : 0);
|
|
560
|
-
const lines = rows.map(([label, value]) => `${styleText("dim", label.padStart(labelWidth))} ${value}`);
|
|
561
|
-
if (showTimings && timings.length > 0) {
|
|
562
|
-
const nameWidth = Math.max(0, ...timings.map((timing) => timing.plugin.length));
|
|
563
|
-
const indent = " ".repeat(labelWidth + 2);
|
|
564
|
-
lines.push(styleText("dim", "Timings".padStart(labelWidth)));
|
|
565
|
-
for (const timing of timings) {
|
|
566
|
-
const timeStr = formatMs(timing.durationMs);
|
|
567
|
-
const barLength = Math.min(Math.ceil(timing.durationMs / 100), 10);
|
|
568
|
-
const bar = styleText("dim", "█".repeat(barLength));
|
|
569
|
-
lines.push(`${indent}${styleText("dim", "•")} ${timing.plugin.padEnd(nameWidth)} ${bar} ${timeStr}`);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
return lines;
|
|
573
|
-
}
|
|
481
|
+
//#region ../../internals/utils/src/network.ts
|
|
574
482
|
/**
|
|
575
|
-
*
|
|
576
|
-
* dependency): a blank line, the config name colored by status, then the summary rows.
|
|
483
|
+
* Well-known stable domains used as DNS probes to check internet connectivity.
|
|
577
484
|
*/
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
/**
|
|
584
|
-
* The default `cli` reporter. Renders the {@link Report} for each config as it finishes, independent
|
|
585
|
-
* of the live logger view. Suppressed at `silent`; the `verbose` level adds the per-plugin timings.
|
|
586
|
-
*/
|
|
587
|
-
const cliReporter = createReporter({
|
|
588
|
-
name: "cli",
|
|
589
|
-
report(result, { logLevel: logLevel$7 }) {
|
|
590
|
-
if (logLevel$7 <= logLevel.silent) return;
|
|
591
|
-
const report = buildReport(result);
|
|
592
|
-
renderSummary(buildSummaryLines(report, { showTimings: logLevel$7 >= logLevel.verbose }), {
|
|
593
|
-
title: report.name,
|
|
594
|
-
status: report.status
|
|
595
|
-
});
|
|
596
|
-
}
|
|
597
|
-
});
|
|
598
|
-
//#endregion
|
|
599
|
-
//#region src/loggers/diagnostics.ts
|
|
600
|
-
/**
|
|
601
|
-
* Glyph and accent color per severity, matching the miette/oxlint convention
|
|
602
|
-
* (`×` error, `⚠` warning, `ℹ` advice).
|
|
603
|
-
*/
|
|
604
|
-
const severityStyle = {
|
|
605
|
-
error: {
|
|
606
|
-
glyph: "×",
|
|
607
|
-
color: "red"
|
|
608
|
-
},
|
|
609
|
-
warning: {
|
|
610
|
-
glyph: "⚠",
|
|
611
|
-
color: "yellow"
|
|
612
|
-
},
|
|
613
|
-
info: {
|
|
614
|
-
glyph: "ℹ",
|
|
615
|
-
color: "blue"
|
|
616
|
-
}
|
|
617
|
-
};
|
|
618
|
-
/**
|
|
619
|
-
* The colored, bold severity glyph (`×`, `⚠`, `ℹ`) on its own. Pass it as clack's
|
|
620
|
-
* `symbol` so clack owns the gutter and adds the bar to the continuation lines,
|
|
621
|
-
* instead of baking the glyph into the message text.
|
|
622
|
-
*/
|
|
623
|
-
function diagnosticSymbol(severity) {
|
|
624
|
-
const { glyph, color } = severityStyle[severity];
|
|
625
|
-
return styleText(color, styleText("bold", glyph));
|
|
626
|
-
}
|
|
627
|
-
/**
|
|
628
|
-
* The `plugin(CODE): message` headline, without the leading severity glyph.
|
|
629
|
-
*/
|
|
630
|
-
function diagnosticHeadline(diagnostic) {
|
|
631
|
-
const { code, severity, message } = diagnostic;
|
|
632
|
-
const plugin = isProblemDiagnostic(diagnostic) ? diagnostic.plugin : void 0;
|
|
633
|
-
const { color } = severityStyle[severity];
|
|
634
|
-
return `${styleText(color, styleText("bold", plugin ? `${plugin}(${code})` : code))}: ${message}`;
|
|
635
|
-
}
|
|
636
|
-
/**
|
|
637
|
-
* The detail lines below the headline: optional `at <pointer>`, `help:`, and
|
|
638
|
-
* `docs:`. OpenAPI has no line/column, so the location is the JSON pointer the
|
|
639
|
-
* adapter built. Each line keeps a two-space indent so it sits under the headline.
|
|
640
|
-
*/
|
|
641
|
-
function diagnosticDetails(diagnostic) {
|
|
642
|
-
const { code } = diagnostic;
|
|
643
|
-
const problem = isProblemDiagnostic(diagnostic) ? diagnostic : void 0;
|
|
644
|
-
const location = problem?.location;
|
|
645
|
-
const help = problem?.help;
|
|
646
|
-
const lines = [];
|
|
647
|
-
if (location && "pointer" in location) lines.push(` ${styleText("dim", "at")} ${styleText("cyan", location.pointer)}`);
|
|
648
|
-
if (help) lines.push(` ${styleText("cyan", "help:")} ${help}`);
|
|
649
|
-
if (code !== diagnosticCode.unknown) lines.push(` ${styleText("dim", "docs:")} ${styleText("cyan", Diagnostics.docsUrl(code))}`);
|
|
650
|
-
return lines;
|
|
651
|
-
}
|
|
485
|
+
const TEST_DOMAINS = [
|
|
486
|
+
"dns.google.com",
|
|
487
|
+
"cloudflare.com",
|
|
488
|
+
"one.one.one.one"
|
|
489
|
+
];
|
|
652
490
|
/**
|
|
653
|
-
*
|
|
654
|
-
*
|
|
655
|
-
* Use this where clack's gutter is not available (plain, file output); clack
|
|
656
|
-
* loggers pass {@link diagnosticSymbol}, {@link diagnosticHeadline}, and
|
|
657
|
-
* {@link diagnosticDetails} to `clack.log.message` instead.
|
|
491
|
+
* Returns `true` when the system has internet connectivity.
|
|
492
|
+
* Probes DNS resolution against well-known stable domains.
|
|
658
493
|
*
|
|
659
494
|
* @example
|
|
660
495
|
* ```ts
|
|
661
|
-
*
|
|
496
|
+
* if (await isOnline()) {
|
|
497
|
+
* await fetchLatestVersion()
|
|
498
|
+
* }
|
|
662
499
|
* ```
|
|
663
500
|
*/
|
|
664
|
-
function
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
* Builds the `## Summary` section: the same counts the cli and json reporters expose, as a list of
|
|
671
|
-
* `label value` rows with the labels padded to a common width.
|
|
672
|
-
*/
|
|
673
|
-
function buildSummarySection(report) {
|
|
674
|
-
const { status, plugins, counts, filesCreated, durationMs, output } = report;
|
|
675
|
-
const rows = [["Status", status], ["Plugins", status === "success" ? `${plugins.passed} passed (${plugins.total})` : `${plugins.passed} passed | ${plugins.failed.length} failed (${plugins.total})`]];
|
|
676
|
-
if (plugins.failed.length > 0) rows.push(["Failed", plugins.failed.join(", ")]);
|
|
677
|
-
rows.push(["Issues", `${counts.errors} errors | ${counts.warnings} warnings | ${counts.infos} infos`]);
|
|
678
|
-
rows.push(["Files", `${filesCreated} generated`]);
|
|
679
|
-
rows.push(["Duration", formatMs(durationMs)]);
|
|
680
|
-
rows.push(["Output", output]);
|
|
681
|
-
const labelWidth = Math.max(...rows.map(([label]) => label.length));
|
|
682
|
-
return [
|
|
683
|
-
"## Summary",
|
|
684
|
-
"",
|
|
685
|
-
...rows.map(([label, value]) => ` ${label.padEnd(labelWidth)} ${value}`)
|
|
686
|
-
];
|
|
687
|
-
}
|
|
688
|
-
/**
|
|
689
|
-
* Builds the `## Problems` section: each problem rendered in the miette block format, blocks
|
|
690
|
-
* separated by a blank line. Returns an empty array when there are no problems, so the caller
|
|
691
|
-
* can drop the heading.
|
|
692
|
-
*/
|
|
693
|
-
function buildProblemSection(diagnostics) {
|
|
694
|
-
const problems = diagnostics.filter(isProblemDiagnostic);
|
|
695
|
-
if (problems.length === 0) return [];
|
|
696
|
-
return [
|
|
697
|
-
"## Problems",
|
|
698
|
-
"",
|
|
699
|
-
problems.map((diagnostic) => formatDiagnostic(diagnostic).join("\n")).join("\n\n")
|
|
700
|
-
];
|
|
701
|
-
}
|
|
702
|
-
/**
|
|
703
|
-
* Builds the `## Timings` section from a {@link Report}: one `plugin duration` row per record,
|
|
704
|
-
* slowest first with the plugin names left-aligned and the durations right-aligned. Returns an
|
|
705
|
-
* empty array when there are no timings.
|
|
706
|
-
*/
|
|
707
|
-
function buildTimingSection(report) {
|
|
708
|
-
const { timings } = report;
|
|
709
|
-
if (timings.length === 0) return [];
|
|
710
|
-
const nameWidth = Math.max(...timings.map((timing) => timing.plugin.length));
|
|
711
|
-
const durations = timings.map((timing) => formatMs(timing.durationMs));
|
|
712
|
-
const durationWidth = Math.max(...durations.map((duration) => duration.length));
|
|
713
|
-
return [
|
|
714
|
-
"## Timings",
|
|
715
|
-
"",
|
|
716
|
-
...timings.map((timing, index) => ` ${timing.plugin.padEnd(nameWidth)} ${durations[index].padStart(durationWidth)}`)
|
|
717
|
-
];
|
|
501
|
+
async function isOnline() {
|
|
502
|
+
for (const domain of TEST_DOMAINS) try {
|
|
503
|
+
await promises.resolve(domain);
|
|
504
|
+
return true;
|
|
505
|
+
} catch {}
|
|
506
|
+
return false;
|
|
718
507
|
}
|
|
719
508
|
/**
|
|
720
|
-
*
|
|
721
|
-
* plain-text document: a `# <name> — <timestamp>` header, a `## Summary` with the same counts the
|
|
722
|
-
* cli and json reporters expose, a `## Problems` section in the miette block format, and a
|
|
723
|
-
* `## Timings` section. Selected with `--reporter file` (or `reporters: ['file']`), replacing the
|
|
724
|
-
* old `--debug` flag.
|
|
509
|
+
* Executes `fn` only when the system is online. Returns `null` when offline or on error.
|
|
725
510
|
*
|
|
726
|
-
* @
|
|
727
|
-
*
|
|
728
|
-
*
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
name: "file",
|
|
732
|
-
async report(result) {
|
|
733
|
-
const { diagnostics, config } = result;
|
|
734
|
-
if (diagnostics.length === 0) return;
|
|
735
|
-
const report = buildReport(result);
|
|
736
|
-
const content = stripVTControlCharacters([config.name ? `# ${config.name} — ${(/* @__PURE__ */ new Date()).toISOString()}` : `# ${(/* @__PURE__ */ new Date()).toISOString()}`, ...[
|
|
737
|
-
buildSummarySection(report),
|
|
738
|
-
buildProblemSection(diagnostics),
|
|
739
|
-
buildTimingSection(report)
|
|
740
|
-
].filter((section) => section.length > 0).map((section) => section.join("\n"))].join("\n\n"));
|
|
741
|
-
const baseName = `${[
|
|
742
|
-
"kubb",
|
|
743
|
-
config.name,
|
|
744
|
-
Date.now()
|
|
745
|
-
].filter(Boolean).join("-")}.log`;
|
|
746
|
-
const pathName = resolve(process$1.cwd(), ".kubb", baseName);
|
|
747
|
-
await write(pathName, `${content}\n`);
|
|
748
|
-
console.error(`Debug log written to ${relative(process$1.cwd(), pathName)}`);
|
|
749
|
-
}
|
|
750
|
-
});
|
|
751
|
-
//#endregion
|
|
752
|
-
//#region src/reporters/jsonReporter.ts
|
|
753
|
-
/**
|
|
754
|
-
* The `json` reporter. `report` returns one config's {@link Report}, which {@link createReporter}
|
|
755
|
-
* buffers, and `flush` writes them as a single pretty-printed JSON array on `kubb:lifecycle:end`.
|
|
756
|
-
* Buffering keeps a multi-config run one valid JSON document on stdout instead of concatenated
|
|
757
|
-
* objects that would break `jq .`. The terminal reporter is suppressed while `json` is active so
|
|
758
|
-
* stdout stays valid JSON.
|
|
511
|
+
* @example
|
|
512
|
+
* ```ts
|
|
513
|
+
* const version = await executeIfOnline(() => fetchLatestVersion('kubb'))
|
|
514
|
+
* // null when offline
|
|
515
|
+
* ```
|
|
759
516
|
*/
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
return
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
process$1.stdout.write(`${JSON.stringify(reports, null, 2)}\n`);
|
|
517
|
+
async function executeIfOnline(fn) {
|
|
518
|
+
if (!await isOnline()) return null;
|
|
519
|
+
try {
|
|
520
|
+
return await fn();
|
|
521
|
+
} catch {
|
|
522
|
+
return null;
|
|
767
523
|
}
|
|
768
|
-
}
|
|
524
|
+
}
|
|
769
525
|
//#endregion
|
|
770
526
|
//#region src/loggers/clackLogger.ts
|
|
771
527
|
/**
|
|
@@ -882,7 +638,7 @@ const clackLogger = defineLogger({
|
|
|
882
638
|
if (logLevel$6 <= logLevel.silent && diagnostic.severity !== "error") return;
|
|
883
639
|
stopSpinner();
|
|
884
640
|
stopActiveProgress();
|
|
885
|
-
if (
|
|
641
|
+
if (Diagnostics.isUpdate(diagnostic)) {
|
|
886
642
|
clack.box(`\`v${diagnostic.currentVersion}\` → \`v${diagnostic.latestVersion}\`
|
|
887
643
|
Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
|
|
888
644
|
width: "auto",
|
|
@@ -894,7 +650,8 @@ Run \`npm install -g @kubb/cli\` to update`, "Update available for `Kubb`", {
|
|
|
894
650
|
});
|
|
895
651
|
return;
|
|
896
652
|
}
|
|
897
|
-
|
|
653
|
+
const { symbol, headline, details } = Diagnostics.format(diagnostic);
|
|
654
|
+
clack.log.message([headline, ...details], { symbol });
|
|
898
655
|
});
|
|
899
656
|
context.on("kubb:lifecycle:start", async ({ version }) => {
|
|
900
657
|
console.log(`\n${getIntro({
|
|
@@ -1141,7 +898,7 @@ const githubActionsLogger = defineLogger({
|
|
|
1141
898
|
context.on("kubb:diagnostic", ({ diagnostic }) => {
|
|
1142
899
|
closeAllGroups();
|
|
1143
900
|
if (logLevel$5 <= logLevel.silent && diagnostic.severity !== "error") return;
|
|
1144
|
-
if (!
|
|
901
|
+
if (!Diagnostics.isProblem(diagnostic)) {
|
|
1145
902
|
console.log(`::notice::${diagnostic.message}`);
|
|
1146
903
|
return;
|
|
1147
904
|
}
|
|
@@ -1149,7 +906,7 @@ const githubActionsLogger = defineLogger({
|
|
|
1149
906
|
if (diagnostic.location && "pointer" in diagnostic.location) parts.push(`(at ${diagnostic.location.pointer})`);
|
|
1150
907
|
if (diagnostic.plugin) parts.push(`[plugin: ${diagnostic.plugin}]`);
|
|
1151
908
|
if (diagnostic.help) parts.push(`help: ${diagnostic.help}`);
|
|
1152
|
-
if (diagnostic.code !==
|
|
909
|
+
if (diagnostic.code !== Diagnostics.code.unknown) parts.push(`docs: ${Diagnostics.docsUrl(diagnostic.code)}`);
|
|
1153
910
|
console.error(`::error::${parts.join(" ")}`);
|
|
1154
911
|
});
|
|
1155
912
|
context.on("kubb:lifecycle:start", ({ version }) => {
|
|
@@ -1313,7 +1070,7 @@ const plainLogger = defineLogger({
|
|
|
1313
1070
|
});
|
|
1314
1071
|
context.on("kubb:diagnostic", ({ diagnostic }) => {
|
|
1315
1072
|
if (logLevel$4 <= logLevel.silent && diagnostic.severity !== "error") return;
|
|
1316
|
-
console.log(getMessage(
|
|
1073
|
+
console.log(getMessage(Diagnostics.formatLines(diagnostic).join("\n")));
|
|
1317
1074
|
});
|
|
1318
1075
|
context.on("kubb:lifecycle:start", ({ version }) => {
|
|
1319
1076
|
console.log(`Kubb CLI v${version}`);
|
|
@@ -1495,31 +1252,32 @@ function installReporter(context, reporter, ctx) {
|
|
|
1495
1252
|
hrStart
|
|
1496
1253
|
}, ctx);
|
|
1497
1254
|
});
|
|
1498
|
-
if (reporter.
|
|
1255
|
+
if (reporter.drain) context.on("kubb:lifecycle:end", () => reporter.drain?.(ctx));
|
|
1499
1256
|
}
|
|
1500
1257
|
/**
|
|
1501
|
-
* Installs the live logger (the TUI view) and the
|
|
1502
|
-
* terminal logger's hook sink when one was installed.
|
|
1503
|
-
*
|
|
1258
|
+
* Installs the live logger (the TUI view) and the given reporters (the output), returning the
|
|
1259
|
+
* terminal logger's hook sink when one was installed. The reporters are already selected by the
|
|
1260
|
+
* caller (the CLI maps `--reporter` to names via `selectReporters`); this only wires them.
|
|
1504
1261
|
*
|
|
1505
|
-
*
|
|
1506
|
-
* `json`
|
|
1262
|
+
* Loggers and reporters are independent: the `cli` reporter also activates the env logger summary.
|
|
1263
|
+
* The `json` reporter owns stdout, so the live logger and the `cli` summary are suppressed whenever
|
|
1264
|
+
* `json` is among the reporters, even if `cli` is also listed.
|
|
1507
1265
|
*/
|
|
1508
1266
|
async function setupReporters(context, { logLevel, reporters }) {
|
|
1509
|
-
const
|
|
1510
|
-
const hasJson = unique.has("json");
|
|
1267
|
+
const hasJson = reporters.some((reporter) => reporter.name === "json");
|
|
1511
1268
|
const ctx = { logLevel };
|
|
1512
1269
|
let makeSink = null;
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1270
|
+
for (const reporter of reporters) {
|
|
1271
|
+
if (reporter.name === "cli") {
|
|
1272
|
+
if (hasJson) continue;
|
|
1273
|
+
const type = detectLogger();
|
|
1274
|
+
const logger = logMapper[type];
|
|
1275
|
+
if (!logger) throw new Error(`Unknown adapter type: ${type}`);
|
|
1276
|
+
const sink = await logger.install(context, { logLevel });
|
|
1277
|
+
makeSink = typeof sink === "function" ? sink : null;
|
|
1278
|
+
}
|
|
1279
|
+
installReporter(context, reporter, ctx);
|
|
1520
1280
|
}
|
|
1521
|
-
if (hasJson) installReporter(context, jsonReporter, ctx);
|
|
1522
|
-
if (unique.has("file")) installReporter(context, fileReporter, ctx);
|
|
1523
1281
|
return makeSink;
|
|
1524
1282
|
}
|
|
1525
1283
|
//#endregion
|
|
@@ -1718,7 +1476,7 @@ async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefi
|
|
|
1718
1476
|
}
|
|
1719
1477
|
}
|
|
1720
1478
|
let toolError;
|
|
1721
|
-
if (resolvedTool && resolvedTool !== "auto" && resolvedTool in toolMap) {
|
|
1479
|
+
if (resolvedTool && resolvedTool !== "auto" && resolvedTool in toolMap && existsSync(outputPath)) {
|
|
1722
1480
|
const toolConfig = toolMap[resolvedTool];
|
|
1723
1481
|
const hookId = createHash("sha256").update([configName, resolvedTool].filter(Boolean).join("-")).digest("hex");
|
|
1724
1482
|
const successMessage = [
|
|
@@ -1786,7 +1544,7 @@ async function generate(options) {
|
|
|
1786
1544
|
name: p.name,
|
|
1787
1545
|
options: p.options
|
|
1788
1546
|
}));
|
|
1789
|
-
const reportTelemetry = (status) =>
|
|
1547
|
+
const reportTelemetry = (status) => Telemetry.send(Telemetry.build({
|
|
1790
1548
|
command: "generate",
|
|
1791
1549
|
kubbVersion: version,
|
|
1792
1550
|
plugins: telemetryPlugins,
|
|
@@ -1795,8 +1553,8 @@ async function generate(options) {
|
|
|
1795
1553
|
status
|
|
1796
1554
|
}));
|
|
1797
1555
|
for (const diagnostic of diagnostics) {
|
|
1798
|
-
if (!
|
|
1799
|
-
const unknown =
|
|
1556
|
+
if (!Diagnostics.isProblem(diagnostic)) continue;
|
|
1557
|
+
const unknown = Diagnostics.narrow(diagnostic, Diagnostics.code.unknown);
|
|
1800
1558
|
if (unknown) await hooks.emit("kubb:error", { error: unknown.cause ?? new Error(unknown.message) });
|
|
1801
1559
|
else await Diagnostics.emit(hooks, diagnostic);
|
|
1802
1560
|
}
|
|
@@ -1815,7 +1573,7 @@ async function generate(options) {
|
|
|
1815
1573
|
const outputPath = path.resolve(config.root, config.output.path);
|
|
1816
1574
|
const outputDiagnostics = [];
|
|
1817
1575
|
const toolPasses = [config.output.format && {
|
|
1818
|
-
code:
|
|
1576
|
+
code: Diagnostics.code.formatFailed,
|
|
1819
1577
|
toolValue: config.output.format,
|
|
1820
1578
|
detect: detectFormatter,
|
|
1821
1579
|
toolMap: formatters,
|
|
@@ -1825,7 +1583,7 @@ async function generate(options) {
|
|
|
1825
1583
|
onStart: () => hooks.emit("kubb:format:start"),
|
|
1826
1584
|
onEnd: () => hooks.emit("kubb:format:end")
|
|
1827
1585
|
}, config.output.lint && {
|
|
1828
|
-
code:
|
|
1586
|
+
code: Diagnostics.code.lintFailed,
|
|
1829
1587
|
toolValue: config.output.lint,
|
|
1830
1588
|
detect: detectLinter,
|
|
1831
1589
|
toolMap: linters,
|
|
@@ -1866,7 +1624,7 @@ async function generate(options) {
|
|
|
1866
1624
|
hooks.off("kubb:hook:end", onHookEnd);
|
|
1867
1625
|
}
|
|
1868
1626
|
for (const error of hookFailures) {
|
|
1869
|
-
const diagnostic = outputDiagnostic(
|
|
1627
|
+
const diagnostic = outputDiagnostic(Diagnostics.code.hookFailed, "Post-generate hook", error);
|
|
1870
1628
|
outputDiagnostics.push(diagnostic);
|
|
1871
1629
|
await Diagnostics.emit(hooks, diagnostic);
|
|
1872
1630
|
}
|
|
@@ -1936,14 +1694,15 @@ async function run({ input, configPath, logLevel: logLevelKey, watch, reporters:
|
|
|
1936
1694
|
} catch (error) {
|
|
1937
1695
|
await setupReporters(hooks, {
|
|
1938
1696
|
logLevel: logLevel$2,
|
|
1939
|
-
reporters: [
|
|
1697
|
+
reporters: [cliReporter]
|
|
1940
1698
|
});
|
|
1941
1699
|
await hooks.emit("kubb:error", { error: toError(error) });
|
|
1942
1700
|
process$1.exit(1);
|
|
1943
1701
|
}
|
|
1702
|
+
const requestedNames = cliReporters?.length ? cliReporters : ["cli"];
|
|
1944
1703
|
const makeSink = await setupReporters(hooks, {
|
|
1945
1704
|
logLevel: logLevel$2,
|
|
1946
|
-
reporters:
|
|
1705
|
+
reporters: selectReporters(configs[0]?.reporters ?? [], requestedNames)
|
|
1947
1706
|
});
|
|
1948
1707
|
await hooks.emit("kubb:lifecycle:start", { version });
|
|
1949
1708
|
await checkForUpdate(hooks);
|
|
@@ -1960,7 +1719,7 @@ async function run({ input, configPath, logLevel: logLevelKey, watch, reporters:
|
|
|
1960
1719
|
});
|
|
1961
1720
|
await hooks.emit("kubb:config:end", { configs });
|
|
1962
1721
|
let anyFailed = false;
|
|
1963
|
-
for (const config of configs) if (
|
|
1722
|
+
for (const config of configs) if (config.input && "path" in config.input && watch) await startWatcher([input || config.input.path], async (paths) => {
|
|
1964
1723
|
await generate({
|
|
1965
1724
|
input,
|
|
1966
1725
|
config,
|
|
@@ -1995,4 +1754,4 @@ async function run({ input, configPath, logLevel: logLevelKey, watch, reporters:
|
|
|
1995
1754
|
//#endregion
|
|
1996
1755
|
export { run };
|
|
1997
1756
|
|
|
1998
|
-
//# sourceMappingURL=run-
|
|
1757
|
+
//# sourceMappingURL=run-BabEDDqN.js.map
|