react-doctor 0.9.12-dev.a2b460d → 0.9.12-dev.e183c35
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 +28 -1
- package/bin/react-doctor.js +1 -9
- package/dist/active-run-trace-dlIZeEvb.js +18 -0
- package/dist/active-scan-abort-registry-DwG6tSPy.js +28 -0
- package/dist/{build-section-divider-Vz879zXD.js → build-section-divider-D2kON1gx.js} +10 -25
- package/dist/{ci-BVYrYekU.js → ci-BDF4MCw4.js} +13 -12
- package/dist/cli.js +82 -31
- package/dist/{design-D-TYN_tr.js → design-5z-_ATHh.js} +4 -4
- package/dist/{devtools-DPRVRu3S.js → devtools-BiC-AP3B.js} +4 -4
- package/dist/{exit-gracefully-Cjv5kC_l.js → exit-gracefully-D-9LC4_A.js} +15 -9
- package/dist/get-east-asian-width-Cglw13G7.js +444 -0
- package/dist/{report-error-1l7v6_dE.js → handle-error-CiH-zHAJ.js} +6 -61
- package/dist/index.d.ts +53 -42
- package/dist/index.js +54808 -54552
- package/dist/{inspect-kkvDHKDE.js → inspect-UlnsYEF7.js} +22 -20
- package/dist/{install-ZeYvD9Rw.js → install-D3ZEk4sy.js} +9 -8
- package/dist/{install-doctor-script-D58Hr1dM.js → install-doctor-script-B7P7AJly.js} +6 -441
- package/dist/{install-github-workflow-DkMicv8E.js → install-github-workflow-CfSmkFY0.js} +6 -6
- package/dist/{install-react-doctor-CjgE52al.js → install-react-doctor-B2nUFSke.js} +47 -45
- package/dist/{run-scan-app-Ciq22jzp.js → jsx-runtime-COe_zui7.js} +281 -2759
- package/dist/{print-branded-header-D4QYSu-h.js → print-branded-header-DWWSXUyB.js} +4 -4
- package/dist/project-analysis-worker.d.ts +1 -0
- package/dist/project-analysis-worker.js +51900 -0
- package/dist/prompt-runtime-scan-url-B2VI0Xh9.js +240 -0
- package/dist/{read-object-file-OFRlvCAL.js → read-object-file-BmbCMY0Q.js} +4 -4
- package/dist/{record-metric-CMe2d1Xv.js → record-metric-BMWbP8MZ.js} +2726 -5663
- package/dist/report-error-6PgTfB1z.js +64 -0
- package/dist/{report-workflow-result-EagkH_v9.js → report-workflow-result-BGcNuwxL.js} +5 -5
- package/dist/{resolve-scope-CMNrOdDf.js → resolve-scope-Bq-uMX-y.js} +6 -6
- package/dist/{rules-CzR1qUru.js → rules-Cw83jL1c.js} +6 -6
- package/dist/run-scan-app-CR-bq134.js +2508 -0
- package/dist/runtime-scan/browser-probe.iife.js +855 -0
- package/dist/runtime-scan-C0Sq0Vsq.js +770 -0
- package/dist/sanitize-runtime-url-B2iNA5hC.js +76 -0
- package/dist/{scan-D4m5r4Rs.js → scan-BfuDcKtg.js} +10 -22
- package/dist/semver-DFtnEmN-.js +3219 -0
- package/dist/{should-fail-scan-gate-lMTlhEhE.js → should-fail-scan-gate-CGmZKFSQ.js} +153 -184
- package/dist/{should-skip-prompts-mXKZBNCz.js → should-skip-prompts-K3hVW95X.js} +4 -4
- package/dist/should-use-tui-Clt-_eNL.js +25 -0
- package/dist/skills/improve-threejs/SKILL.md +102 -0
- package/dist/skills/performance/SKILL.md +113 -0
- package/dist/skills/react-doctor/SKILL.md +6 -0
- package/dist/{unref-stdin-Cxhw67r6.js → telemetry-runtime-Cix2Ie97.js} +7 -31
- package/dist/unref-stdin-BKT_s38a.js +12 -0
- package/dist/{version-CnvVY2VD.js → version-D3IeIvrP.js} +4 -4
- package/dist/{why-BktDEhhH.js → why-vS83AKil.js} +4 -4
- package/dist/with-run-span-DuqJWpuS.js +110 -0
- package/package.json +7 -9
- package/dist/chunk-q7NCDQ7-.js +0 -28
- package/dist/lsp.js +0 -81145
|
@@ -1,24 +1,17 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { n as registerActiveTuiRenderer, t as exitGracefully } from "./exit-gracefully-
|
|
6
|
-
import {
|
|
7
|
-
import { i as isReactDoctorWorkflowInstalled } from "./install-github-workflow-DkMicv8E.js";
|
|
8
|
-
import { r as resolveScope, s as resolveBlockingLevel, t as finalizeScope, u as toForwardSlashes } from "./resolve-scope-CMNrOdDf.js";
|
|
9
|
-
import { A as resolveMergeBaseRef, B as buildEmptyReportMessage, C as copyToClipboard, D as deduplicateProjectScans, E as collectProjectSourceFileCounts, F as printDiagnosticsDump, G as formatLearnMoreLine, H as buildRulePriorityMap, I as formatDiagnosticSite, L as hasIncompleteScoreAnalysis, M as pluralize, N as formatElapsedTime, O as createInvocationInspect, P as printFooter, R as filterDiagnosticsByCategories, S as CLI_AGENT_BINARIES, T as buildHandoffPayload, U as buildSortedRuleGroups, V as hasLintHardFailure, W as formatFixRecipeLine, _ as resolveCliInspectOptions, a as projectManifestChanged, b as setUpGitHubActions, c as selectProjects, d as resolveProjectChangedLineRanges, f as resolveProjectDiffIncludePaths, g as resolveWorkspaceDeadCodeOwner, h as retryMissingProjectScores, l as buildCodeFrame, n as formatSkippedProjectsMessage, o as partitionProjectScanOutcomes, p as resolveProjectSourceFilePaths, r as validateIncludeUntrackedScope, s as discoverWorkspacePackages, t as shouldFailScanGate, u as resolveProjectScan, v as filterScansForSurface, w as launchCliAgent, x as detectLaunchableAgents, y as countUniqueScannedFiles, z as buildNoScoreMessage } from "./should-fail-scan-gate-lMTlhEhE.js";
|
|
10
|
-
import { a as recordGate, f as ONBOARDING_EVENT, n as openUrl, r as isGatePending } from "./report-workflow-result-EagkH_v9.js";
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="d7867bb3-5dd2-5798-b5dc-3fb046c80d68")}catch(e){}}();
|
|
3
|
+
import { i as __toESM, r as __require, t as __commonJSMin } from "./chunk-ChKA3wi6.js";
|
|
4
|
+
import { T as METRIC, t as recordCount } from "./record-metric-BMWbP8MZ.js";
|
|
5
|
+
import { n as registerActiveTuiRenderer, t as exitGracefully } from "./exit-gracefully-D-9LC4_A.js";
|
|
6
|
+
import { a as chalk, i as stripAnsi, n as isFullWidth$1, r as isWide$1 } from "./get-east-asian-width-Cglw13G7.js";
|
|
11
7
|
import { EventEmitter } from "node:events";
|
|
12
8
|
import { execFileSync } from "node:child_process";
|
|
13
|
-
import path from "node:path";
|
|
14
9
|
import * as fs$1 from "node:fs";
|
|
15
10
|
import fs from "node:fs";
|
|
16
11
|
import process$1, { cwd, env } from "node:process";
|
|
17
12
|
import os from "node:os";
|
|
18
13
|
import { PassThrough, Stream } from "node:stream";
|
|
19
|
-
import { performance as performance$1 } from "node:perf_hooks";
|
|
20
14
|
import tty from "node:tty";
|
|
21
|
-
import { getSkillAgentConfig } from "agent-install";
|
|
22
15
|
import Yoga from "yoga-layout";
|
|
23
16
|
//#region ../../node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react.production.js
|
|
24
17
|
/**
|
|
@@ -20447,7 +20440,7 @@ if (process$1.env["DEV"] === "true") {
|
|
|
20447
20440
|
import.meta.resolve("react-devtools-core");
|
|
20448
20441
|
isDevtoolsInstalled = true;
|
|
20449
20442
|
} catch {}
|
|
20450
|
-
if (isDevtoolsInstalled) await import("./devtools-
|
|
20443
|
+
if (isDevtoolsInstalled) await import("./devtools-BiC-AP3B.js");
|
|
20451
20444
|
}
|
|
20452
20445
|
const diff = (before, after) => {
|
|
20453
20446
|
if (before === after) return;
|
|
@@ -20951,24 +20944,24 @@ const BEL = "\x07";
|
|
|
20951
20944
|
const ESC = "\x1B";
|
|
20952
20945
|
const BACKSLASH = "\\";
|
|
20953
20946
|
const CSI = "[";
|
|
20954
|
-
const OSC
|
|
20947
|
+
const OSC = "]";
|
|
20955
20948
|
const C1_ST = "";
|
|
20956
20949
|
const CC_BEL = BEL.charCodeAt(0);
|
|
20957
20950
|
const CC_ESC = ESC.charCodeAt(0);
|
|
20958
20951
|
const CC_BACKSLASH = BACKSLASH.charCodeAt(0);
|
|
20959
20952
|
const CC_CSI = CSI.charCodeAt(0);
|
|
20960
|
-
const CC_OSC = OSC
|
|
20953
|
+
const CC_OSC = OSC.charCodeAt(0);
|
|
20961
20954
|
const CC_C1_ST = C1_ST.charCodeAt(0);
|
|
20962
20955
|
"0".charCodeAt(0);
|
|
20963
20956
|
"9".charCodeAt(0);
|
|
20964
20957
|
";".charCodeAt(0);
|
|
20965
20958
|
"m".charCodeAt(0);
|
|
20966
20959
|
const ESCAPES = new Set([CC_ESC, 155]);
|
|
20967
|
-
const linkCodePrefix = `${ESC}${OSC
|
|
20960
|
+
const linkCodePrefix = `${ESC}${OSC}8;`;
|
|
20968
20961
|
const linkCodePrefixCharCodes = linkCodePrefix.split("").map((char) => char.charCodeAt(0));
|
|
20969
|
-
const linkEndCode = `${ESC}${OSC
|
|
20970
|
-
const linkEndCodeST = `${ESC}${OSC
|
|
20971
|
-
const linkEndCodeC1ST = `${ESC}${OSC
|
|
20962
|
+
const linkEndCode = `${ESC}${OSC}8;;${BEL}`;
|
|
20963
|
+
const linkEndCodeST = `${ESC}${OSC}8;;${ESC}${BACKSLASH}`;
|
|
20964
|
+
const linkEndCodeC1ST = `${ESC}${OSC}8;;${C1_ST}`;
|
|
20972
20965
|
//#endregion
|
|
20973
20966
|
//#region ../../node_modules/.pnpm/@alcalzone+ansi-tokenize@0.3.0/node_modules/@alcalzone/ansi-tokenize/build/ansiCodes.js
|
|
20974
20967
|
const endCodesSet = /* @__PURE__ */ new Set();
|
|
@@ -23962,2102 +23955,6 @@ A React hook that returns the stdout stream where Ink renders your app.
|
|
|
23962
23955
|
*/
|
|
23963
23956
|
const useStdout = () => (0, import_react.useContext)(StdoutContext);
|
|
23964
23957
|
//#endregion
|
|
23965
|
-
//#region src/cli/utils/get-top-error-rule-keys.ts
|
|
23966
|
-
const getTopErrorRuleKeys = (diagnostics, limit, rulePriority) => new Set(buildSortedRuleGroups(diagnostics.filter((diagnostic) => diagnostic.severity === "error"), rulePriority).slice(0, limit).map(([ruleKey]) => ruleKey));
|
|
23967
|
-
//#endregion
|
|
23968
|
-
//#region src/cli/utils/compute-score-projection.ts
|
|
23969
|
-
const computeProjectedScore = async (topErrorSource, rescoreSource, currentScore) => {
|
|
23970
|
-
const topErrorRuleKeys = getTopErrorRuleKeys(topErrorSource, 3, buildRulePriorityMap([currentScore]));
|
|
23971
|
-
if (topErrorRuleKeys.size === 0) return null;
|
|
23972
|
-
const potentialScore = await calculateScore(rescoreSource.filter((diagnostic) => !topErrorRuleKeys.has(`${diagnostic.plugin}/${diagnostic.rule}`)));
|
|
23973
|
-
if (!potentialScore || potentialScore.score <= currentScore.score) return null;
|
|
23974
|
-
return potentialScore.score;
|
|
23975
|
-
};
|
|
23976
|
-
//#endregion
|
|
23977
|
-
//#region src/cli/utils/is-share-opted-out.ts
|
|
23978
|
-
const isShareOptedOut = (scans, flagNoScore) => Boolean(flagNoScore) || scans.some((scan) => Boolean(scan.config?.noScore) || scan.config?.share === false);
|
|
23979
|
-
//#endregion
|
|
23980
|
-
//#region src/cli/utils/resolve-project-tui-scan-scope.ts
|
|
23981
|
-
const resolveProjectTuiScanScope = (input) => {
|
|
23982
|
-
if (input.plan.scope === "full") return {};
|
|
23983
|
-
if (input.plan.diffInfo === null) return null;
|
|
23984
|
-
const changedSourceFiles = resolveProjectDiffIncludePaths(input.rootDirectory, input.projectDirectory, input.plan.diffInfo);
|
|
23985
|
-
const baselineBaseFiles = input.plan.baselineDiffPlan === null ? null : resolveProjectSourceFilePaths(input.rootDirectory, input.projectDirectory, input.plan.baselineDiffPlan.baseFiles);
|
|
23986
|
-
const baselineHeadFiles = input.plan.baselineDiffPlan === null ? null : resolveProjectSourceFilePaths(input.rootDirectory, input.projectDirectory, input.plan.baselineDiffPlan.headFiles);
|
|
23987
|
-
const supplyChainManifestChanged = input.supplyChainEnabled && projectManifestChanged(input.rootDirectory, input.projectDirectory, input.plan.diffInfo);
|
|
23988
|
-
const hasBaselineOnlyFiles = (baselineBaseFiles?.length ?? 0) > 0;
|
|
23989
|
-
if (!supplyChainManifestChanged && changedSourceFiles.length === 0 && !hasBaselineOnlyFiles) return null;
|
|
23990
|
-
const includePaths = [...changedSourceFiles];
|
|
23991
|
-
if (includePaths.length === 0 && hasBaselineOnlyFiles) includePaths.push(...baselineBaseFiles ?? []);
|
|
23992
|
-
if (supplyChainManifestChanged) includePaths.push("package.json");
|
|
23993
|
-
return {
|
|
23994
|
-
includePaths,
|
|
23995
|
-
baseline: input.plan.baselineRef !== null && baselineBaseFiles !== null && baselineHeadFiles !== null ? {
|
|
23996
|
-
ref: input.plan.baselineRef,
|
|
23997
|
-
baseFiles: baselineBaseFiles,
|
|
23998
|
-
headFiles: baselineHeadFiles
|
|
23999
|
-
} : void 0,
|
|
24000
|
-
changedLineRanges: input.plan.scope === "lines" && input.plan.changedLineRanges !== null ? resolveProjectChangedLineRanges(input.rootDirectory, input.projectDirectory, input.plan.changedLineRanges) : void 0,
|
|
24001
|
-
supplyChainManifestChanged
|
|
24002
|
-
};
|
|
24003
|
-
};
|
|
24004
|
-
//#endregion
|
|
24005
|
-
//#region src/cli/utils/resolve-tui-scan-scope.ts
|
|
24006
|
-
const resolveTuiScanScope = async (input) => {
|
|
24007
|
-
const requestedScope = resolveScope(input.flags, input.userConfig);
|
|
24008
|
-
const includeUntracked = input.flags.includeUntracked ?? false;
|
|
24009
|
-
validateIncludeUntrackedScope(includeUntracked, requestedScope.scope);
|
|
24010
|
-
const diffInfo = requestedScope.scope !== void 0 && requestedScope.scope !== "full" ? await getDiffInfo(input.directory, requestedScope.base, includeUntracked) : null;
|
|
24011
|
-
const scope = await finalizeScope({
|
|
24012
|
-
requested: requestedScope,
|
|
24013
|
-
diffInfo,
|
|
24014
|
-
skipPrompts: true,
|
|
24015
|
-
isQuiet: false
|
|
24016
|
-
});
|
|
24017
|
-
let comparisonBaseRef = null;
|
|
24018
|
-
if (scope !== "full" && diffInfo !== null && !diffInfo.isCurrentChanges) if (diffInfo.baseSha !== void 0) comparisonBaseRef = await resolveMergeBaseRef(input.directory, diffInfo.baseSha);
|
|
24019
|
-
else if (diffInfo.diffBaseRef !== void 0) comparisonBaseRef = diffInfo.diffBaseRef;
|
|
24020
|
-
else comparisonBaseRef = await resolveMergeBaseRef(input.directory, diffInfo.baseBranch);
|
|
24021
|
-
const baselineRef = scope === "changed" ? comparisonBaseRef : null;
|
|
24022
|
-
const baselineDiffPlan = baselineRef === null ? null : await getBaselineDiffPlan(input.directory, baselineRef);
|
|
24023
|
-
const linesBaseRef = diffInfo?.isCurrentChanges ? "HEAD" : comparisonBaseRef;
|
|
24024
|
-
const changedLineRanges = scope === "lines" && diffInfo !== null && (diffInfo.isCurrentChanges || linesBaseRef !== null) ? await getChangedLineRanges({
|
|
24025
|
-
directory: input.directory,
|
|
24026
|
-
baseRef: linesBaseRef ?? void 0,
|
|
24027
|
-
files: [...diffInfo.changedFiles],
|
|
24028
|
-
includeUntracked
|
|
24029
|
-
}) : null;
|
|
24030
|
-
if (scope === "lines" && changedLineRanges === null) {
|
|
24031
|
-
cliLogger.warn("Could not determine changed lines (no base ref or git diff failed); reporting all issues in changed files.");
|
|
24032
|
-
cliLogger.break();
|
|
24033
|
-
}
|
|
24034
|
-
return {
|
|
24035
|
-
baselineDiffPlan,
|
|
24036
|
-
baselineIntended: scope === "changed" && diffInfo !== null && !diffInfo.isCurrentChanges,
|
|
24037
|
-
baselineRef,
|
|
24038
|
-
changedLineRanges,
|
|
24039
|
-
diffInfo,
|
|
24040
|
-
scope
|
|
24041
|
-
};
|
|
24042
|
-
};
|
|
24043
|
-
//#endregion
|
|
24044
|
-
//#region src/cli/utils/select-report-diagnostics.ts
|
|
24045
|
-
const selectReportDiagnostics = (input) => {
|
|
24046
|
-
const surfaceDiagnostics = filterScansForSurface([input.scan], input.surface ?? "cli");
|
|
24047
|
-
return {
|
|
24048
|
-
diagnostics: filterDiagnosticsByCategories(surfaceDiagnostics, new Set(input.categoryFilters)),
|
|
24049
|
-
demotedDiagnosticCount: input.scan.result.diagnostics.length - surfaceDiagnostics.length
|
|
24050
|
-
};
|
|
24051
|
-
};
|
|
24052
|
-
//#endregion
|
|
24053
|
-
//#region src/cli/utils/clamp-number.ts
|
|
24054
|
-
const clampNumber = (value, minimum, maximum) => Math.max(minimum, Math.min(maximum, value));
|
|
24055
|
-
//#endregion
|
|
24056
|
-
//#region src/cli/utils/is-printable-input.ts
|
|
24057
|
-
const isPrintableInput = (input) => input.length > 0 && [...input].every((character) => character.charCodeAt(0) >= 32);
|
|
24058
|
-
//#endregion
|
|
24059
|
-
//#region src/cli/utils/resolve-visible-start.ts
|
|
24060
|
-
const resolveVisibleStart = ({ itemCount, offset, selectedIndex, viewportHeight }) => {
|
|
24061
|
-
if (viewportHeight <= 0) return 0;
|
|
24062
|
-
const boundedOffset = clampNumber(offset, 0, Math.max(0, itemCount - viewportHeight));
|
|
24063
|
-
if (selectedIndex < boundedOffset) return selectedIndex;
|
|
24064
|
-
if (selectedIndex >= boundedOffset + viewportHeight) return Math.max(0, selectedIndex - viewportHeight + 1);
|
|
24065
|
-
return boundedOffset;
|
|
24066
|
-
};
|
|
24067
|
-
//#endregion
|
|
24068
|
-
//#region src/cli/utils/terminal-symbols.ts
|
|
24069
|
-
const supportsUnicodeSymbols = process.platform !== "win32" ? process.env.TERM !== "linux" : Boolean(process.env.WT_SESSION) || Boolean(process.env.TERMINUS_SUBLIME) || process.env.ConEmuTask === "{cmd::Cmder}" || process.env.TERM_PROGRAM === "Terminus-Sublime" || process.env.TERM_PROGRAM === "vscode" || process.env.TERM === "xterm-256color" || process.env.TERM === "alacritty" || process.env.TERM === "rxvt-unicode" || process.env.TERM === "rxvt-unicode-256color" || process.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
24070
|
-
const terminalSymbols = {
|
|
24071
|
-
pointer: supportsUnicodeSymbols ? "❯" : ">",
|
|
24072
|
-
pointerSmall: "›",
|
|
24073
|
-
radioOn: supportsUnicodeSymbols ? "◉" : "(*)",
|
|
24074
|
-
radioOff: supportsUnicodeSymbols ? "◯" : "( )"
|
|
24075
|
-
};
|
|
24076
|
-
//#endregion
|
|
24077
|
-
//#region src/cli/ink/hooks/use-exit-on-ctrl-c.ts
|
|
24078
|
-
const SHOW_CURSOR = "\x1B[?25h";
|
|
24079
|
-
const useExitOnCtrlC = (onCancel) => {
|
|
24080
|
-
useInput((input, key) => {
|
|
24081
|
-
if (key.ctrl && input === "c") {
|
|
24082
|
-
onCancel?.();
|
|
24083
|
-
recordCount(METRIC.tuiCancelled, 1, { resourceFooter: true });
|
|
24084
|
-
process.stdin.setRawMode?.(false);
|
|
24085
|
-
process.stdout.write(SHOW_CURSOR);
|
|
24086
|
-
exitGracefully();
|
|
24087
|
-
}
|
|
24088
|
-
});
|
|
24089
|
-
};
|
|
24090
|
-
//#endregion
|
|
24091
|
-
//#region src/cli/ink/hooks/use-stdout-dimensions.ts
|
|
24092
|
-
const readDimensions = (stdout) => ({
|
|
24093
|
-
columns: stdout?.columns ?? 80,
|
|
24094
|
-
rows: stdout?.rows ?? 24
|
|
24095
|
-
});
|
|
24096
|
-
const useStdoutDimensions = () => {
|
|
24097
|
-
const { stdout } = useStdout();
|
|
24098
|
-
const [dimensions, setDimensions] = (0, import_react.useState)(() => readDimensions(stdout));
|
|
24099
|
-
(0, import_react.useEffect)(() => {
|
|
24100
|
-
if (!stdout) return;
|
|
24101
|
-
const onResize = () => setDimensions(readDimensions(stdout));
|
|
24102
|
-
stdout.on("resize", onResize);
|
|
24103
|
-
return () => {
|
|
24104
|
-
stdout.off("resize", onResize);
|
|
24105
|
-
};
|
|
24106
|
-
}, [stdout]);
|
|
24107
|
-
return dimensions;
|
|
24108
|
-
};
|
|
24109
|
-
//#endregion
|
|
24110
|
-
//#region src/cli/ink/lib/fuzzy-match.ts
|
|
24111
|
-
const fuzzyMatch = (query, target) => {
|
|
24112
|
-
if (query.length === 0) return {
|
|
24113
|
-
score: 0,
|
|
24114
|
-
matchedIndices: []
|
|
24115
|
-
};
|
|
24116
|
-
const lowerQuery = query.toLowerCase();
|
|
24117
|
-
const lowerTarget = target.toLowerCase();
|
|
24118
|
-
const matchedIndices = [];
|
|
24119
|
-
let score = 0;
|
|
24120
|
-
let queryIndex = 0;
|
|
24121
|
-
let previousMatchIndex = Number.NEGATIVE_INFINITY;
|
|
24122
|
-
for (let targetIndex = 0; targetIndex < lowerTarget.length && queryIndex < lowerQuery.length; targetIndex++) {
|
|
24123
|
-
if (lowerTarget[targetIndex] !== lowerQuery[queryIndex]) continue;
|
|
24124
|
-
matchedIndices.push(targetIndex);
|
|
24125
|
-
if (targetIndex === previousMatchIndex + 1) score += 5;
|
|
24126
|
-
const previousCharacter = target[targetIndex - 1];
|
|
24127
|
-
if (targetIndex === 0 || previousCharacter === "-" || previousCharacter === "_" || previousCharacter === "/" || previousCharacter === " ") score += 10;
|
|
24128
|
-
previousMatchIndex = targetIndex;
|
|
24129
|
-
queryIndex++;
|
|
24130
|
-
}
|
|
24131
|
-
if (queryIndex < lowerQuery.length) return null;
|
|
24132
|
-
score -= matchedIndices[0] * 1;
|
|
24133
|
-
return {
|
|
24134
|
-
score,
|
|
24135
|
-
matchedIndices
|
|
24136
|
-
};
|
|
24137
|
-
};
|
|
24138
|
-
//#endregion
|
|
24139
|
-
//#region ../../node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react-jsx-runtime.production.js
|
|
24140
|
-
/**
|
|
24141
|
-
* @license React
|
|
24142
|
-
* react-jsx-runtime.production.js
|
|
24143
|
-
*
|
|
24144
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
24145
|
-
*
|
|
24146
|
-
* This source code is licensed under the MIT license found in the
|
|
24147
|
-
* LICENSE file in the root directory of this source tree.
|
|
24148
|
-
*/
|
|
24149
|
-
var require_react_jsx_runtime_production = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
24150
|
-
var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment");
|
|
24151
|
-
function jsxProd(type, config, maybeKey) {
|
|
24152
|
-
var key = null;
|
|
24153
|
-
void 0 !== maybeKey && (key = "" + maybeKey);
|
|
24154
|
-
void 0 !== config.key && (key = "" + config.key);
|
|
24155
|
-
if ("key" in config) {
|
|
24156
|
-
maybeKey = {};
|
|
24157
|
-
for (var propName in config) "key" !== propName && (maybeKey[propName] = config[propName]);
|
|
24158
|
-
} else maybeKey = config;
|
|
24159
|
-
config = maybeKey.ref;
|
|
24160
|
-
return {
|
|
24161
|
-
$$typeof: REACT_ELEMENT_TYPE,
|
|
24162
|
-
type,
|
|
24163
|
-
key,
|
|
24164
|
-
ref: void 0 !== config ? config : null,
|
|
24165
|
-
props: maybeKey
|
|
24166
|
-
};
|
|
24167
|
-
}
|
|
24168
|
-
exports.Fragment = REACT_FRAGMENT_TYPE;
|
|
24169
|
-
exports.jsx = jsxProd;
|
|
24170
|
-
exports.jsxs = jsxProd;
|
|
24171
|
-
}));
|
|
24172
|
-
//#endregion
|
|
24173
|
-
//#region ../../node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react-jsx-runtime.development.js
|
|
24174
|
-
/**
|
|
24175
|
-
* @license React
|
|
24176
|
-
* react-jsx-runtime.development.js
|
|
24177
|
-
*
|
|
24178
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
24179
|
-
*
|
|
24180
|
-
* This source code is licensed under the MIT license found in the
|
|
24181
|
-
* LICENSE file in the root directory of this source tree.
|
|
24182
|
-
*/
|
|
24183
|
-
var require_react_jsx_runtime_development = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
24184
|
-
"production" !== process.env.NODE_ENV && (function() {
|
|
24185
|
-
function getComponentNameFromType(type) {
|
|
24186
|
-
if (null == type) return null;
|
|
24187
|
-
if ("function" === typeof type) return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
|
|
24188
|
-
if ("string" === typeof type) return type;
|
|
24189
|
-
switch (type) {
|
|
24190
|
-
case REACT_FRAGMENT_TYPE: return "Fragment";
|
|
24191
|
-
case REACT_PROFILER_TYPE: return "Profiler";
|
|
24192
|
-
case REACT_STRICT_MODE_TYPE: return "StrictMode";
|
|
24193
|
-
case REACT_SUSPENSE_TYPE: return "Suspense";
|
|
24194
|
-
case REACT_SUSPENSE_LIST_TYPE: return "SuspenseList";
|
|
24195
|
-
case REACT_ACTIVITY_TYPE: return "Activity";
|
|
24196
|
-
}
|
|
24197
|
-
if ("object" === typeof type) switch ("number" === typeof type.tag && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), type.$$typeof) {
|
|
24198
|
-
case REACT_PORTAL_TYPE: return "Portal";
|
|
24199
|
-
case REACT_CONTEXT_TYPE: return type.displayName || "Context";
|
|
24200
|
-
case REACT_CONSUMER_TYPE: return (type._context.displayName || "Context") + ".Consumer";
|
|
24201
|
-
case REACT_FORWARD_REF_TYPE:
|
|
24202
|
-
var innerType = type.render;
|
|
24203
|
-
type = type.displayName;
|
|
24204
|
-
type || (type = innerType.displayName || innerType.name || "", type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef");
|
|
24205
|
-
return type;
|
|
24206
|
-
case REACT_MEMO_TYPE: return innerType = type.displayName || null, null !== innerType ? innerType : getComponentNameFromType(type.type) || "Memo";
|
|
24207
|
-
case REACT_LAZY_TYPE:
|
|
24208
|
-
innerType = type._payload;
|
|
24209
|
-
type = type._init;
|
|
24210
|
-
try {
|
|
24211
|
-
return getComponentNameFromType(type(innerType));
|
|
24212
|
-
} catch (x) {}
|
|
24213
|
-
}
|
|
24214
|
-
return null;
|
|
24215
|
-
}
|
|
24216
|
-
function testStringCoercion(value) {
|
|
24217
|
-
return "" + value;
|
|
24218
|
-
}
|
|
24219
|
-
function checkKeyStringCoercion(value) {
|
|
24220
|
-
try {
|
|
24221
|
-
testStringCoercion(value);
|
|
24222
|
-
var JSCompiler_inline_result = !1;
|
|
24223
|
-
} catch (e) {
|
|
24224
|
-
JSCompiler_inline_result = !0;
|
|
24225
|
-
}
|
|
24226
|
-
if (JSCompiler_inline_result) {
|
|
24227
|
-
JSCompiler_inline_result = console;
|
|
24228
|
-
var JSCompiler_temp_const = JSCompiler_inline_result.error;
|
|
24229
|
-
var JSCompiler_inline_result$jscomp$0 = "function" === typeof Symbol && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
|
|
24230
|
-
JSCompiler_temp_const.call(JSCompiler_inline_result, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", JSCompiler_inline_result$jscomp$0);
|
|
24231
|
-
return testStringCoercion(value);
|
|
24232
|
-
}
|
|
24233
|
-
}
|
|
24234
|
-
function getTaskName(type) {
|
|
24235
|
-
if (type === REACT_FRAGMENT_TYPE) return "<>";
|
|
24236
|
-
if ("object" === typeof type && null !== type && type.$$typeof === REACT_LAZY_TYPE) return "<...>";
|
|
24237
|
-
try {
|
|
24238
|
-
var name = getComponentNameFromType(type);
|
|
24239
|
-
return name ? "<" + name + ">" : "<...>";
|
|
24240
|
-
} catch (x) {
|
|
24241
|
-
return "<...>";
|
|
24242
|
-
}
|
|
24243
|
-
}
|
|
24244
|
-
function getOwner() {
|
|
24245
|
-
var dispatcher = ReactSharedInternals.A;
|
|
24246
|
-
return null === dispatcher ? null : dispatcher.getOwner();
|
|
24247
|
-
}
|
|
24248
|
-
function UnknownOwner() {
|
|
24249
|
-
return Error("react-stack-top-frame");
|
|
24250
|
-
}
|
|
24251
|
-
function hasValidKey(config) {
|
|
24252
|
-
if (hasOwnProperty.call(config, "key")) {
|
|
24253
|
-
var getter = Object.getOwnPropertyDescriptor(config, "key").get;
|
|
24254
|
-
if (getter && getter.isReactWarning) return !1;
|
|
24255
|
-
}
|
|
24256
|
-
return void 0 !== config.key;
|
|
24257
|
-
}
|
|
24258
|
-
function defineKeyPropWarningGetter(props, displayName) {
|
|
24259
|
-
function warnAboutAccessingKey() {
|
|
24260
|
-
specialPropKeyWarningShown || (specialPropKeyWarningShown = !0, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", displayName));
|
|
24261
|
-
}
|
|
24262
|
-
warnAboutAccessingKey.isReactWarning = !0;
|
|
24263
|
-
Object.defineProperty(props, "key", {
|
|
24264
|
-
get: warnAboutAccessingKey,
|
|
24265
|
-
configurable: !0
|
|
24266
|
-
});
|
|
24267
|
-
}
|
|
24268
|
-
function elementRefGetterWithDeprecationWarning() {
|
|
24269
|
-
var componentName = getComponentNameFromType(this.type);
|
|
24270
|
-
didWarnAboutElementRef[componentName] || (didWarnAboutElementRef[componentName] = !0, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."));
|
|
24271
|
-
componentName = this.props.ref;
|
|
24272
|
-
return void 0 !== componentName ? componentName : null;
|
|
24273
|
-
}
|
|
24274
|
-
function ReactElement(type, key, props, owner, debugStack, debugTask) {
|
|
24275
|
-
var refProp = props.ref;
|
|
24276
|
-
type = {
|
|
24277
|
-
$$typeof: REACT_ELEMENT_TYPE,
|
|
24278
|
-
type,
|
|
24279
|
-
key,
|
|
24280
|
-
props,
|
|
24281
|
-
_owner: owner
|
|
24282
|
-
};
|
|
24283
|
-
null !== (void 0 !== refProp ? refProp : null) ? Object.defineProperty(type, "ref", {
|
|
24284
|
-
enumerable: !1,
|
|
24285
|
-
get: elementRefGetterWithDeprecationWarning
|
|
24286
|
-
}) : Object.defineProperty(type, "ref", {
|
|
24287
|
-
enumerable: !1,
|
|
24288
|
-
value: null
|
|
24289
|
-
});
|
|
24290
|
-
type._store = {};
|
|
24291
|
-
Object.defineProperty(type._store, "validated", {
|
|
24292
|
-
configurable: !1,
|
|
24293
|
-
enumerable: !1,
|
|
24294
|
-
writable: !0,
|
|
24295
|
-
value: 0
|
|
24296
|
-
});
|
|
24297
|
-
Object.defineProperty(type, "_debugInfo", {
|
|
24298
|
-
configurable: !1,
|
|
24299
|
-
enumerable: !1,
|
|
24300
|
-
writable: !0,
|
|
24301
|
-
value: null
|
|
24302
|
-
});
|
|
24303
|
-
Object.defineProperty(type, "_debugStack", {
|
|
24304
|
-
configurable: !1,
|
|
24305
|
-
enumerable: !1,
|
|
24306
|
-
writable: !0,
|
|
24307
|
-
value: debugStack
|
|
24308
|
-
});
|
|
24309
|
-
Object.defineProperty(type, "_debugTask", {
|
|
24310
|
-
configurable: !1,
|
|
24311
|
-
enumerable: !1,
|
|
24312
|
-
writable: !0,
|
|
24313
|
-
value: debugTask
|
|
24314
|
-
});
|
|
24315
|
-
Object.freeze && (Object.freeze(type.props), Object.freeze(type));
|
|
24316
|
-
return type;
|
|
24317
|
-
}
|
|
24318
|
-
function jsxDEVImpl(type, config, maybeKey, isStaticChildren, debugStack, debugTask) {
|
|
24319
|
-
var children = config.children;
|
|
24320
|
-
if (void 0 !== children) if (isStaticChildren) if (isArrayImpl(children)) {
|
|
24321
|
-
for (isStaticChildren = 0; isStaticChildren < children.length; isStaticChildren++) validateChildKeys(children[isStaticChildren]);
|
|
24322
|
-
Object.freeze && Object.freeze(children);
|
|
24323
|
-
} else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
|
|
24324
|
-
else validateChildKeys(children);
|
|
24325
|
-
if (hasOwnProperty.call(config, "key")) {
|
|
24326
|
-
children = getComponentNameFromType(type);
|
|
24327
|
-
var keys = Object.keys(config).filter(function(k) {
|
|
24328
|
-
return "key" !== k;
|
|
24329
|
-
});
|
|
24330
|
-
isStaticChildren = 0 < keys.length ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" : "{key: someKey}";
|
|
24331
|
-
didWarnAboutKeySpread[children + isStaticChildren] || (keys = 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}", console.error("A props object containing a \"key\" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />", isStaticChildren, children, keys, children), didWarnAboutKeySpread[children + isStaticChildren] = !0);
|
|
24332
|
-
}
|
|
24333
|
-
children = null;
|
|
24334
|
-
void 0 !== maybeKey && (checkKeyStringCoercion(maybeKey), children = "" + maybeKey);
|
|
24335
|
-
hasValidKey(config) && (checkKeyStringCoercion(config.key), children = "" + config.key);
|
|
24336
|
-
if ("key" in config) {
|
|
24337
|
-
maybeKey = {};
|
|
24338
|
-
for (var propName in config) "key" !== propName && (maybeKey[propName] = config[propName]);
|
|
24339
|
-
} else maybeKey = config;
|
|
24340
|
-
children && defineKeyPropWarningGetter(maybeKey, "function" === typeof type ? type.displayName || type.name || "Unknown" : type);
|
|
24341
|
-
return ReactElement(type, children, maybeKey, getOwner(), debugStack, debugTask);
|
|
24342
|
-
}
|
|
24343
|
-
function validateChildKeys(node) {
|
|
24344
|
-
isValidElement(node) ? node._store && (node._store.validated = 1) : "object" === typeof node && null !== node && node.$$typeof === REACT_LAZY_TYPE && ("fulfilled" === node._payload.status ? isValidElement(node._payload.value) && node._payload.value._store && (node._payload.value._store.validated = 1) : node._store && (node._store.validated = 1));
|
|
24345
|
-
}
|
|
24346
|
-
function isValidElement(object) {
|
|
24347
|
-
return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
|
|
24348
|
-
}
|
|
24349
|
-
var React = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
|
|
24350
|
-
return null;
|
|
24351
|
-
};
|
|
24352
|
-
React = { react_stack_bottom_frame: function(callStackForError) {
|
|
24353
|
-
return callStackForError();
|
|
24354
|
-
} };
|
|
24355
|
-
var specialPropKeyWarningShown;
|
|
24356
|
-
var didWarnAboutElementRef = {};
|
|
24357
|
-
var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(React, UnknownOwner)();
|
|
24358
|
-
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
|
|
24359
|
-
var didWarnAboutKeySpread = {};
|
|
24360
|
-
exports.Fragment = REACT_FRAGMENT_TYPE;
|
|
24361
|
-
exports.jsx = function(type, config, maybeKey) {
|
|
24362
|
-
var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
|
|
24363
|
-
return jsxDEVImpl(type, config, maybeKey, !1, trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack, trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
|
|
24364
|
-
};
|
|
24365
|
-
exports.jsxs = function(type, config, maybeKey) {
|
|
24366
|
-
var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
|
|
24367
|
-
return jsxDEVImpl(type, config, maybeKey, !0, trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack, trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
|
|
24368
|
-
};
|
|
24369
|
-
})();
|
|
24370
|
-
}));
|
|
24371
|
-
//#endregion
|
|
24372
|
-
//#region src/cli/ink/components/project-select.tsx
|
|
24373
|
-
var import_jsx_runtime = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
24374
|
-
if (process.env.NODE_ENV === "production") module.exports = require_react_jsx_runtime_production();
|
|
24375
|
-
else module.exports = require_react_jsx_runtime_development();
|
|
24376
|
-
})))();
|
|
24377
|
-
const MatchedName = ({ name, matchedIndices, isSelected }) => {
|
|
24378
|
-
if (matchedIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24379
|
-
bold: isSelected,
|
|
24380
|
-
wrap: "truncate-end",
|
|
24381
|
-
children: name
|
|
24382
|
-
});
|
|
24383
|
-
const matchedIndexSet = new Set(matchedIndices);
|
|
24384
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24385
|
-
bold: isSelected,
|
|
24386
|
-
wrap: "truncate-end",
|
|
24387
|
-
children: [...name].map((character, index) => matchedIndexSet.has(index) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24388
|
-
color: "yellow",
|
|
24389
|
-
children: character
|
|
24390
|
-
}, index) : character)
|
|
24391
|
-
});
|
|
24392
|
-
};
|
|
24393
|
-
const ProjectSelect = ({ packages, rootDirectory, onSubmit }) => {
|
|
24394
|
-
const { rows: terminalRows } = useStdoutDimensions();
|
|
24395
|
-
useExitOnCtrlC();
|
|
24396
|
-
const [selectionMode, setSelectionMode] = (0, import_react.useState)("list");
|
|
24397
|
-
const [searchQuery, setSearchQuery] = (0, import_react.useState)("");
|
|
24398
|
-
const [selectedIndex, setSelectedIndex] = (0, import_react.useState)(0);
|
|
24399
|
-
const [scrollOffset, setScrollOffset] = (0, import_react.useState)(0);
|
|
24400
|
-
const [checkedDirectories, setCheckedDirectories] = (0, import_react.useState)(() => /* @__PURE__ */ new Set());
|
|
24401
|
-
const didRecordProjectPathContext = (0, import_react.useRef)(false);
|
|
24402
|
-
const matchedPackages = (0, import_react.useMemo)(() => {
|
|
24403
|
-
const scoredPackages = packages.flatMap((workspacePackage) => {
|
|
24404
|
-
const result = fuzzyMatch(searchQuery, workspacePackage.name);
|
|
24405
|
-
return result ? [{
|
|
24406
|
-
workspacePackage,
|
|
24407
|
-
result
|
|
24408
|
-
}] : [];
|
|
24409
|
-
});
|
|
24410
|
-
if (searchQuery.length > 0) scoredPackages.sort((leftPackage, rightPackage) => rightPackage.result.score - leftPackage.result.score);
|
|
24411
|
-
return scoredPackages.map(({ workspacePackage, result }) => ({
|
|
24412
|
-
workspacePackage,
|
|
24413
|
-
matchedIndices: result.matchedIndices,
|
|
24414
|
-
relativeDirectory: path.relative(rootDirectory, workspacePackage.directory) || "."
|
|
24415
|
-
}));
|
|
24416
|
-
}, [
|
|
24417
|
-
packages,
|
|
24418
|
-
rootDirectory,
|
|
24419
|
-
searchQuery
|
|
24420
|
-
]);
|
|
24421
|
-
const hasProjectPathContext = matchedPackages.some(({ relativeDirectory, workspacePackage }) => relativeDirectory !== workspacePackage.name);
|
|
24422
|
-
(0, import_react.useEffect)(() => {
|
|
24423
|
-
if (!hasProjectPathContext || didRecordProjectPathContext.current) return;
|
|
24424
|
-
didRecordProjectPathContext.current = true;
|
|
24425
|
-
recordCount(METRIC.tuiProjectPathContextShown);
|
|
24426
|
-
}, [hasProjectPathContext]);
|
|
24427
|
-
const isSearching = selectionMode === "search";
|
|
24428
|
-
const hasFilterLine = isSearching || searchQuery.length > 0;
|
|
24429
|
-
const listHeight = Math.max(1, Math.min(Math.max(matchedPackages.length, 1), terminalRows - 3 - (hasFilterLine ? 1 : 0)));
|
|
24430
|
-
const selectedPackageIndex = matchedPackages.length === 0 ? 0 : clampNumber(selectedIndex, 0, matchedPackages.length - 1);
|
|
24431
|
-
const selectedWorkspacePackage = matchedPackages[selectedPackageIndex]?.workspacePackage;
|
|
24432
|
-
const updateFilter = (nextSearchQuery) => {
|
|
24433
|
-
setSearchQuery(nextSearchQuery);
|
|
24434
|
-
setSelectedIndex(0);
|
|
24435
|
-
setScrollOffset(0);
|
|
24436
|
-
};
|
|
24437
|
-
const moveSelection = (indexDelta) => {
|
|
24438
|
-
if (matchedPackages.length === 0) return;
|
|
24439
|
-
const nextSelectedIndex = clampNumber(selectedPackageIndex + indexDelta, 0, matchedPackages.length - 1);
|
|
24440
|
-
setSelectedIndex(nextSelectedIndex);
|
|
24441
|
-
setScrollOffset((currentOffset) => {
|
|
24442
|
-
if (nextSelectedIndex < currentOffset) return nextSelectedIndex;
|
|
24443
|
-
if (nextSelectedIndex >= currentOffset + listHeight) return nextSelectedIndex - listHeight + 1;
|
|
24444
|
-
return currentOffset;
|
|
24445
|
-
});
|
|
24446
|
-
};
|
|
24447
|
-
const toggleCheckedDirectory = (directory) => {
|
|
24448
|
-
setCheckedDirectories((currentCheckedDirectories) => {
|
|
24449
|
-
const updatedCheckedDirectories = new Set(currentCheckedDirectories);
|
|
24450
|
-
if (updatedCheckedDirectories.has(directory)) updatedCheckedDirectories.delete(directory);
|
|
24451
|
-
else updatedCheckedDirectories.add(directory);
|
|
24452
|
-
return updatedCheckedDirectories;
|
|
24453
|
-
});
|
|
24454
|
-
};
|
|
24455
|
-
const submitDirectories = (directories) => {
|
|
24456
|
-
onSubmit([...directories]);
|
|
24457
|
-
};
|
|
24458
|
-
const submitSelection = () => {
|
|
24459
|
-
if (checkedDirectories.size > 0) {
|
|
24460
|
-
const selectedDirectories = [];
|
|
24461
|
-
for (const workspacePackage of packages) if (checkedDirectories.has(workspacePackage.directory)) selectedDirectories.push(workspacePackage.directory);
|
|
24462
|
-
return submitDirectories(selectedDirectories);
|
|
24463
|
-
}
|
|
24464
|
-
if (selectedWorkspacePackage) submitDirectories([selectedWorkspacePackage.directory]);
|
|
24465
|
-
};
|
|
24466
|
-
useInput((input, key) => {
|
|
24467
|
-
if (isSearching) {
|
|
24468
|
-
if (key.return) return setSelectionMode("list");
|
|
24469
|
-
if (key.escape) {
|
|
24470
|
-
updateFilter("");
|
|
24471
|
-
return setSelectionMode("list");
|
|
24472
|
-
}
|
|
24473
|
-
if (key.downArrow || key.ctrl && input === "n") return moveSelection(1);
|
|
24474
|
-
if (key.upArrow || key.ctrl && input === "p") return moveSelection(-1);
|
|
24475
|
-
if (key.backspace || key.delete) return updateFilter(searchQuery.slice(0, -1));
|
|
24476
|
-
if (isPrintableInput(input) && !key.ctrl && !key.meta) updateFilter(searchQuery + input);
|
|
24477
|
-
return;
|
|
24478
|
-
}
|
|
24479
|
-
if (input === "/") return setSelectionMode("search");
|
|
24480
|
-
if (input === " ") {
|
|
24481
|
-
if (selectedWorkspacePackage) toggleCheckedDirectory(selectedWorkspacePackage.directory);
|
|
24482
|
-
return;
|
|
24483
|
-
}
|
|
24484
|
-
if (input === "a") {
|
|
24485
|
-
if (matchedPackages.length === 0) return;
|
|
24486
|
-
setCheckedDirectories((currentCheckedDirectories) => {
|
|
24487
|
-
const updatedCheckedDirectories = new Set(currentCheckedDirectories);
|
|
24488
|
-
const shouldClearMatches = matchedPackages.every((matchedPackage) => currentCheckedDirectories.has(matchedPackage.workspacePackage.directory));
|
|
24489
|
-
for (const matchedPackage of matchedPackages) if (shouldClearMatches) updatedCheckedDirectories.delete(matchedPackage.workspacePackage.directory);
|
|
24490
|
-
else updatedCheckedDirectories.add(matchedPackage.workspacePackage.directory);
|
|
24491
|
-
return updatedCheckedDirectories;
|
|
24492
|
-
});
|
|
24493
|
-
return;
|
|
24494
|
-
}
|
|
24495
|
-
if (input === "q") return submitDirectories([]);
|
|
24496
|
-
if (key.escape) {
|
|
24497
|
-
if (searchQuery.length > 0) return updateFilter("");
|
|
24498
|
-
if (checkedDirectories.size > 0) return setCheckedDirectories(/* @__PURE__ */ new Set());
|
|
24499
|
-
return submitDirectories([]);
|
|
24500
|
-
}
|
|
24501
|
-
if (key.return) return submitSelection();
|
|
24502
|
-
if (key.downArrow || input === "j") return moveSelection(1);
|
|
24503
|
-
if (key.upArrow || input === "k") return moveSelection(-1);
|
|
24504
|
-
if (key.pageDown) return moveSelection(listHeight);
|
|
24505
|
-
if (key.pageUp) return moveSelection(-listHeight);
|
|
24506
|
-
});
|
|
24507
|
-
const visibleStart = resolveVisibleStart({
|
|
24508
|
-
itemCount: matchedPackages.length,
|
|
24509
|
-
offset: scrollOffset,
|
|
24510
|
-
selectedIndex: selectedPackageIndex,
|
|
24511
|
-
viewportHeight: listHeight
|
|
24512
|
-
});
|
|
24513
|
-
const visibleMatches = matchedPackages.slice(visibleStart, visibleStart + listHeight);
|
|
24514
|
-
const longestNameLength = Math.max(0, ...packages.map((workspacePackage) => workspacePackage.name.length));
|
|
24515
|
-
let filterLine = null;
|
|
24516
|
-
if (isSearching) filterLine = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
24517
|
-
wrap: "truncate-end",
|
|
24518
|
-
children: [
|
|
24519
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24520
|
-
color: "cyan",
|
|
24521
|
-
children: "/ "
|
|
24522
|
-
}),
|
|
24523
|
-
searchQuery.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: searchQuery }) : null,
|
|
24524
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24525
|
-
inverse: true,
|
|
24526
|
-
children: " "
|
|
24527
|
-
})
|
|
24528
|
-
]
|
|
24529
|
-
});
|
|
24530
|
-
else if (searchQuery.length > 0) filterLine = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24531
|
-
dimColor: true,
|
|
24532
|
-
wrap: "truncate-end",
|
|
24533
|
-
children: `filter: ${searchQuery}`
|
|
24534
|
-
});
|
|
24535
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
24536
|
-
flexDirection: "column",
|
|
24537
|
-
children: [
|
|
24538
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
24539
|
-
wrap: "truncate-end",
|
|
24540
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24541
|
-
bold: true,
|
|
24542
|
-
children: "Select projects to scan"
|
|
24543
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
24544
|
-
dimColor: true,
|
|
24545
|
-
children: [
|
|
24546
|
-
" ",
|
|
24547
|
-
checkedDirectories.size,
|
|
24548
|
-
"/",
|
|
24549
|
-
packages.length
|
|
24550
|
-
]
|
|
24551
|
-
})]
|
|
24552
|
-
}),
|
|
24553
|
-
filterLine,
|
|
24554
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
24555
|
-
flexDirection: "column",
|
|
24556
|
-
height: listHeight,
|
|
24557
|
-
children: matchedPackages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24558
|
-
dimColor: true,
|
|
24559
|
-
children: "No matching projects"
|
|
24560
|
-
}) : visibleMatches.map((matchedPackage, visiblePackageIndex) => {
|
|
24561
|
-
const isSelected = visibleStart + visiblePackageIndex === selectedPackageIndex;
|
|
24562
|
-
const isChecked = checkedDirectories.has(matchedPackage.workspacePackage.directory);
|
|
24563
|
-
const shouldShowRelativeDirectory = matchedPackage.relativeDirectory !== matchedPackage.workspacePackage.name;
|
|
24564
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
24565
|
-
wrap: "truncate-end",
|
|
24566
|
-
children: [
|
|
24567
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24568
|
-
color: isSelected ? "cyan" : void 0,
|
|
24569
|
-
children: isSelected ? `${terminalSymbols.pointer} ` : " "
|
|
24570
|
-
}),
|
|
24571
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24572
|
-
color: isChecked ? "green" : void 0,
|
|
24573
|
-
children: isChecked ? `${terminalSymbols.radioOn} ` : `${terminalSymbols.radioOff} `
|
|
24574
|
-
}),
|
|
24575
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MatchedName, {
|
|
24576
|
-
name: matchedPackage.workspacePackage.name,
|
|
24577
|
-
matchedIndices: matchedPackage.matchedIndices,
|
|
24578
|
-
isSelected
|
|
24579
|
-
}),
|
|
24580
|
-
shouldShowRelativeDirectory ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
24581
|
-
dimColor: true,
|
|
24582
|
-
children: [" ".repeat(longestNameLength - matchedPackage.workspacePackage.name.length + 2), matchedPackage.relativeDirectory]
|
|
24583
|
-
}) : null
|
|
24584
|
-
]
|
|
24585
|
-
}, matchedPackage.workspacePackage.directory);
|
|
24586
|
-
})
|
|
24587
|
-
}),
|
|
24588
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
24589
|
-
marginTop: 1,
|
|
24590
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24591
|
-
dimColor: true,
|
|
24592
|
-
wrap: "truncate-end",
|
|
24593
|
-
children: isSearching ? "type to filter · enter confirm · esc clear" : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
24594
|
-
"space select · a all · / search · ",
|
|
24595
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24596
|
-
color: "cyan",
|
|
24597
|
-
children: "enter"
|
|
24598
|
-
}),
|
|
24599
|
-
" to submit · q cancel"
|
|
24600
|
-
] })
|
|
24601
|
-
})
|
|
24602
|
-
})
|
|
24603
|
-
]
|
|
24604
|
-
});
|
|
24605
|
-
};
|
|
24606
|
-
//#endregion
|
|
24607
|
-
//#region src/cli/utils/onboarding-pacing.ts
|
|
24608
|
-
const FORCE_ONBOARDING_ENV_VAR = "REACT_DOCTOR_FORCE_ONBOARDING";
|
|
24609
|
-
const FALSY_FLAG_VALUES = new Set([
|
|
24610
|
-
"",
|
|
24611
|
-
"0",
|
|
24612
|
-
"false"
|
|
24613
|
-
]);
|
|
24614
|
-
const isOnboardingForced = (environment = process.env) => {
|
|
24615
|
-
const value = environment[FORCE_ONBOARDING_ENV_VAR];
|
|
24616
|
-
return value !== void 0 && !FALSY_FLAG_VALUES.has(value.toLowerCase());
|
|
24617
|
-
};
|
|
24618
|
-
const shouldRecordOnboarding = (input) => input.paceOnboardingSections && !input.forceOnboarding && !input.verbose && !input.isNonInteractiveEnvironment;
|
|
24619
|
-
const canAnimateOnboarding = (stream = process.stdout) => {
|
|
24620
|
-
if (!(stream.isTTY === true && (stream.columns ?? 0) > 0 && process.env.TERM !== "dumb")) return false;
|
|
24621
|
-
if (isOnboardingForced()) return true;
|
|
24622
|
-
return !isGitHookEnvironment() && !isCiEnvironment();
|
|
24623
|
-
};
|
|
24624
|
-
//#endregion
|
|
24625
|
-
//#region src/cli/utils/onboarding-state.ts
|
|
24626
|
-
const ONBOARDING_GATE = {
|
|
24627
|
-
id: ONBOARDING_EVENT,
|
|
24628
|
-
scope: "global"
|
|
24629
|
-
};
|
|
24630
|
-
const markOnboardingComplete = (options = {}) => {
|
|
24631
|
-
if (isGatePending(ONBOARDING_GATE, {}, options)) recordGate(ONBOARDING_GATE, {}, options);
|
|
24632
|
-
};
|
|
24633
|
-
//#endregion
|
|
24634
|
-
//#region src/cli/ink/hooks/use-report-reveal.ts
|
|
24635
|
-
const useReportReveal = ({ issueCount, onRevealComplete }) => {
|
|
24636
|
-
const { stdout } = useStdout();
|
|
24637
|
-
const shouldAnimate = issueCount > 0 && canAnimateOnboarding(stdout ?? void 0);
|
|
24638
|
-
const streamStepCount = Math.min(12, Math.max(issueCount, 8));
|
|
24639
|
-
const [streamStep, setStreamStep] = (0, import_react.useState)(0);
|
|
24640
|
-
const [didRevealActions, setDidRevealActions] = (0, import_react.useState)(false);
|
|
24641
|
-
const didNotifyRevealComplete = (0, import_react.useRef)(false);
|
|
24642
|
-
const isStreaming = shouldAnimate && streamStep < streamStepCount;
|
|
24643
|
-
const didReachActions = shouldAnimate ? didRevealActions : stdout?.isTTY === true;
|
|
24644
|
-
(0, import_react.useEffect)(() => {
|
|
24645
|
-
if (!shouldAnimate) return;
|
|
24646
|
-
let nextStreamStep = 0;
|
|
24647
|
-
const intervalId = setInterval(() => {
|
|
24648
|
-
nextStreamStep = Math.min(streamStepCount, nextStreamStep + 1);
|
|
24649
|
-
setStreamStep(nextStreamStep);
|
|
24650
|
-
if (nextStreamStep === streamStepCount) clearInterval(intervalId);
|
|
24651
|
-
}, 125);
|
|
24652
|
-
return () => clearInterval(intervalId);
|
|
24653
|
-
}, [shouldAnimate, streamStepCount]);
|
|
24654
|
-
(0, import_react.useEffect)(() => {
|
|
24655
|
-
if (!shouldAnimate || isStreaming) return;
|
|
24656
|
-
const timeoutId = setTimeout(() => setDidRevealActions(true), 850);
|
|
24657
|
-
return () => clearTimeout(timeoutId);
|
|
24658
|
-
}, [isStreaming, shouldAnimate]);
|
|
24659
|
-
(0, import_react.useEffect)(() => {
|
|
24660
|
-
if (!didReachActions || didNotifyRevealComplete.current) return;
|
|
24661
|
-
didNotifyRevealComplete.current = true;
|
|
24662
|
-
onRevealComplete?.();
|
|
24663
|
-
}, [didReachActions, onRevealComplete]);
|
|
24664
|
-
if (!shouldAnimate) return {
|
|
24665
|
-
phase: "actions",
|
|
24666
|
-
streamSelectedIndex: 0
|
|
24667
|
-
};
|
|
24668
|
-
if (isStreaming) return {
|
|
24669
|
-
phase: "streaming",
|
|
24670
|
-
streamSelectedIndex: streamStep % issueCount
|
|
24671
|
-
};
|
|
24672
|
-
return {
|
|
24673
|
-
phase: didRevealActions ? "actions" : "score",
|
|
24674
|
-
streamSelectedIndex: 0
|
|
24675
|
-
};
|
|
24676
|
-
};
|
|
24677
|
-
//#endregion
|
|
24678
|
-
//#region src/cli/ink/lib/diagnostic-list-entries.ts
|
|
24679
|
-
const CATEGORY_RANK = new Map(DIAGNOSTIC_CATEGORY_BUCKETS.map((category, index) => [category, index]));
|
|
24680
|
-
const buildDiagnosticListEntries = (rows) => {
|
|
24681
|
-
const rowsByCategory = /* @__PURE__ */ new Map();
|
|
24682
|
-
for (const [rowIndex, row] of rows.entries()) {
|
|
24683
|
-
const categoryRows = rowsByCategory.get(row.category) ?? [];
|
|
24684
|
-
categoryRows.push({
|
|
24685
|
-
row,
|
|
24686
|
-
rowIndex
|
|
24687
|
-
});
|
|
24688
|
-
rowsByCategory.set(row.category, categoryRows);
|
|
24689
|
-
}
|
|
24690
|
-
const orderedCategories = [...rowsByCategory.keys()].sort((categoryA, categoryB) => {
|
|
24691
|
-
const rankDelta = (CATEGORY_RANK.get(categoryA) ?? Number.MAX_SAFE_INTEGER) - (CATEGORY_RANK.get(categoryB) ?? Number.MAX_SAFE_INTEGER);
|
|
24692
|
-
return rankDelta !== 0 ? rankDelta : categoryA.localeCompare(categoryB);
|
|
24693
|
-
});
|
|
24694
|
-
const entries = [];
|
|
24695
|
-
for (const category of orderedCategories) {
|
|
24696
|
-
const categoryRows = rowsByCategory.get(category) ?? [];
|
|
24697
|
-
entries.push({
|
|
24698
|
-
kind: "header",
|
|
24699
|
-
category
|
|
24700
|
-
});
|
|
24701
|
-
for (const indexedRow of categoryRows) entries.push({
|
|
24702
|
-
kind: "item",
|
|
24703
|
-
...indexedRow
|
|
24704
|
-
});
|
|
24705
|
-
}
|
|
24706
|
-
return entries;
|
|
24707
|
-
};
|
|
24708
|
-
//#endregion
|
|
24709
|
-
//#region src/cli/ink/lib/diagnostic-rows.ts
|
|
24710
|
-
const buildDiagnosticRows = (diagnostics, scores) => {
|
|
24711
|
-
return buildSortedRuleGroups(diagnostics, buildRulePriorityMap(scores)).map(([ruleKey, ruleDiagnostics]) => {
|
|
24712
|
-
const representative = ruleDiagnostics.find((diagnostic) => diagnostic.line > 0) ?? ruleDiagnostics[0];
|
|
24713
|
-
return {
|
|
24714
|
-
ruleKey,
|
|
24715
|
-
diagnostics: ruleDiagnostics,
|
|
24716
|
-
severity: representative.severity === "error" ? "error" : "warning",
|
|
24717
|
-
category: representative.category,
|
|
24718
|
-
title: representative.title ?? ruleKey,
|
|
24719
|
-
location: formatDiagnosticSite(representative),
|
|
24720
|
-
siteCount: ruleDiagnostics.length,
|
|
24721
|
-
representative,
|
|
24722
|
-
ruleGuideUrl: hasPublishedFixRecipe(representative) ? buildRuleDocsUrl(representative.plugin, representative.rule) : null
|
|
24723
|
-
};
|
|
24724
|
-
});
|
|
24725
|
-
};
|
|
24726
|
-
//#endregion
|
|
24727
|
-
//#region src/cli/ink/lib/resolve-report-layout.ts
|
|
24728
|
-
const STACKED_FIXED_ROWS = 9;
|
|
24729
|
-
const resolveReportLayout = ({ columns, diagnosticEntryCount, terminalRows }) => {
|
|
24730
|
-
const width = Math.max(1, columns - 2);
|
|
24731
|
-
const reportRows = Math.max(0, terminalRows - 1);
|
|
24732
|
-
const isWide = columns >= 120 && terminalRows >= 22;
|
|
24733
|
-
const isCompact = !isWide && terminalRows <= TUI_REPORT_COMPACT_MAX_ROWS;
|
|
24734
|
-
const showsViewerScoreHeader = !isCompact || reportRows >= 8;
|
|
24735
|
-
const detailHeight = Math.max(0, isWide ? reportRows - 3 : Math.min(15, reportRows - STACKED_FIXED_ROWS - 3));
|
|
24736
|
-
const availableListHeight = isWide ? Math.max(3, detailHeight - 4 - 1) : Math.max(3, reportRows - STACKED_FIXED_ROWS - detailHeight);
|
|
24737
|
-
const isStackedReportCapped = !isCompact && !isWide && availableListHeight > 16;
|
|
24738
|
-
let listHeight = availableListHeight;
|
|
24739
|
-
if (isCompact) {
|
|
24740
|
-
const viewerScoreHeaderRows = showsViewerScoreHeader ? 4 : 0;
|
|
24741
|
-
listHeight = Math.min(diagnosticEntryCount, Math.max(3, reportRows - 1 - viewerScoreHeaderRows));
|
|
24742
|
-
} else if (!isWide) listHeight = Math.min(diagnosticEntryCount, 16, availableListHeight);
|
|
24743
|
-
const detailColumnWidth = Math.max(20, Math.floor(width * TUI_REPORT_DETAIL_WIDTH_FRACTION));
|
|
24744
|
-
const listColumnWidth = Math.max(20, width - detailColumnWidth - 3);
|
|
24745
|
-
let layout = "stacked";
|
|
24746
|
-
if (isCompact) layout = "compact";
|
|
24747
|
-
else if (isWide) layout = "split";
|
|
24748
|
-
return {
|
|
24749
|
-
detailColumnWidth,
|
|
24750
|
-
detailHeight,
|
|
24751
|
-
isStackedReportCapped,
|
|
24752
|
-
layout,
|
|
24753
|
-
listColumnWidth,
|
|
24754
|
-
listHeight,
|
|
24755
|
-
showsViewerScoreHeader,
|
|
24756
|
-
width
|
|
24757
|
-
};
|
|
24758
|
-
};
|
|
24759
|
-
//#endregion
|
|
24760
|
-
//#region src/cli/ink/components/action-menu.tsx
|
|
24761
|
-
const ActionMenu = ({ actions, selectedIndex: controlledSelectedIndex, onSelectionChange, onEscape, onQuit }) => {
|
|
24762
|
-
const [internalSelectedIndex, setInternalSelectedIndex] = (0, import_react.useState)(0);
|
|
24763
|
-
const selectedIndex = controlledSelectedIndex ?? internalSelectedIndex;
|
|
24764
|
-
const changeSelection = onSelectionChange ?? setInternalSelectedIndex;
|
|
24765
|
-
useInput((input, key) => {
|
|
24766
|
-
if (input === "q") return onQuit();
|
|
24767
|
-
if (key.escape) return onEscape();
|
|
24768
|
-
if (actions.length === 0) return;
|
|
24769
|
-
if (key.upArrow || input === "k") return changeSelection(Math.max(0, selectedIndex - 1));
|
|
24770
|
-
if (key.downArrow || input === "j") return changeSelection(Math.min(actions.length - 1, selectedIndex + 1));
|
|
24771
|
-
if (key.return) actions[selectedIndex]?.onSelect();
|
|
24772
|
-
});
|
|
24773
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
24774
|
-
flexDirection: "column",
|
|
24775
|
-
marginTop: 1,
|
|
24776
|
-
children: actions.map((action, index) => {
|
|
24777
|
-
const isSelected = index === selectedIndex;
|
|
24778
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
24779
|
-
flexDirection: "column",
|
|
24780
|
-
marginBottom: index < actions.length - 1 ? 1 : void 0,
|
|
24781
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
24782
|
-
color: isSelected ? "cyan" : void 0,
|
|
24783
|
-
bold: isSelected,
|
|
24784
|
-
children: [
|
|
24785
|
-
isSelected ? terminalSymbols.pointer : terminalSymbols.pointerSmall,
|
|
24786
|
-
" ",
|
|
24787
|
-
action.label
|
|
24788
|
-
]
|
|
24789
|
-
}), isSelected ? action.description : null]
|
|
24790
|
-
}, action.id);
|
|
24791
|
-
})
|
|
24792
|
-
});
|
|
24793
|
-
};
|
|
24794
|
-
//#endregion
|
|
24795
|
-
//#region src/cli/ink/components/agent-handoff.tsx
|
|
24796
|
-
const AgentHandoff = ({ agents, onSelect, onCopyPrompt, onBack, onQuit }) => {
|
|
24797
|
-
const actions = [...agents.map((agentId) => ({
|
|
24798
|
-
id: agentId,
|
|
24799
|
-
label: getSkillAgentConfig(agentId).displayName,
|
|
24800
|
-
onSelect: () => onSelect(agentId)
|
|
24801
|
-
})), {
|
|
24802
|
-
id: "copy-prompt",
|
|
24803
|
-
label: "Copy prompt",
|
|
24804
|
-
description: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24805
|
-
dimColor: true,
|
|
24806
|
-
children: "Paste into any agent or edit it first"
|
|
24807
|
-
}),
|
|
24808
|
-
onSelect: onCopyPrompt
|
|
24809
|
-
}];
|
|
24810
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
24811
|
-
flexDirection: "column",
|
|
24812
|
-
children: [
|
|
24813
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
24814
|
-
paddingLeft: 2,
|
|
24815
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24816
|
-
bold: true,
|
|
24817
|
-
children: "Choose how to continue"
|
|
24818
|
-
})
|
|
24819
|
-
}),
|
|
24820
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ActionMenu, {
|
|
24821
|
-
actions,
|
|
24822
|
-
onEscape: onBack,
|
|
24823
|
-
onQuit
|
|
24824
|
-
}),
|
|
24825
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
24826
|
-
marginTop: 1,
|
|
24827
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24828
|
-
dimColor: true,
|
|
24829
|
-
children: "↑/↓ move · enter select · esc back · q quit"
|
|
24830
|
-
})
|
|
24831
|
-
})
|
|
24832
|
-
]
|
|
24833
|
-
});
|
|
24834
|
-
};
|
|
24835
|
-
//#endregion
|
|
24836
|
-
//#region src/cli/utils/format-hyperlink.ts
|
|
24837
|
-
const OSC = "\x1B]";
|
|
24838
|
-
const ST = "\x1B\\";
|
|
24839
|
-
/**
|
|
24840
|
-
* Wraps `text` in an OSC 8 hyperlink pointing at `uri`. The visible characters
|
|
24841
|
-
* are exactly `text`; the link is carried in escape sequences a capable
|
|
24842
|
-
* terminal turns into a click target.
|
|
24843
|
-
*/
|
|
24844
|
-
const formatHyperlink = (text, uri) => `${OSC}8;;${uri}${ST}${text}${OSC}8;;${ST}`;
|
|
24845
|
-
//#endregion
|
|
24846
|
-
//#region src/cli/utils/supports-hyperlinks.ts
|
|
24847
|
-
const HYPERLINK_CAPABLE_TERM_PROGRAMS = new Set([
|
|
24848
|
-
"iTerm.app",
|
|
24849
|
-
"WezTerm",
|
|
24850
|
-
"vscode",
|
|
24851
|
-
"Hyper",
|
|
24852
|
-
"ghostty",
|
|
24853
|
-
"Tabby",
|
|
24854
|
-
"rio"
|
|
24855
|
-
]);
|
|
24856
|
-
const parseVteVersion = (raw) => {
|
|
24857
|
-
const parsed = Number.parseInt(raw ?? "", 10);
|
|
24858
|
-
return Number.isNaN(parsed) ? 0 : parsed;
|
|
24859
|
-
};
|
|
24860
|
-
/**
|
|
24861
|
-
* Whether `stream` is a terminal that renders OSC 8 hyperlinks. Auto-detected
|
|
24862
|
-
* from terminal-identity env vars; the de-facto `FORCE_HYPERLINK` env var
|
|
24863
|
-
* overrides detection (`FORCE_HYPERLINK=0`/`false` forces off, any other value
|
|
24864
|
-
* forces on), mirroring how the ecosystem's terminal libraries gate the same
|
|
24865
|
-
* feature. Off for non-TTYs, `TERM=dumb`, and CI (whose log viewers render the
|
|
24866
|
-
* raw escape rather than a link). Unknown terminals default to off.
|
|
24867
|
-
*/
|
|
24868
|
-
const supportsHyperlinks = (stream = process.stdout, env = process.env) => {
|
|
24869
|
-
const forced = env.FORCE_HYPERLINK;
|
|
24870
|
-
if (forced !== void 0 && forced !== "") return forced !== "0" && forced.toLowerCase() !== "false";
|
|
24871
|
-
if (stream.isTTY !== true) return false;
|
|
24872
|
-
if (env.TERM === "dumb") return false;
|
|
24873
|
-
if (isCiEnvironment(env)) return false;
|
|
24874
|
-
if (env.WT_SESSION) return true;
|
|
24875
|
-
if (env.KITTY_WINDOW_ID || env.TERM === "xterm-kitty") return true;
|
|
24876
|
-
if (parseVteVersion(env.VTE_VERSION) >= 5e3) return true;
|
|
24877
|
-
return Boolean(env.TERM_PROGRAM && HYPERLINK_CAPABLE_TERM_PROGRAMS.has(env.TERM_PROGRAM));
|
|
24878
|
-
};
|
|
24879
|
-
//#endregion
|
|
24880
|
-
//#region src/cli/ink/components/tui-link.tsx
|
|
24881
|
-
const TuiLink = ({ children, url }) => {
|
|
24882
|
-
const shouldFormatHyperlink = supportsHyperlinks();
|
|
24883
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Transform, {
|
|
24884
|
-
transform: (text) => shouldFormatHyperlink ? formatHyperlink(text, url) : text,
|
|
24885
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children })
|
|
24886
|
-
});
|
|
24887
|
-
};
|
|
24888
|
-
//#endregion
|
|
24889
|
-
//#region src/cli/ink/components/ci-justification.tsx
|
|
24890
|
-
const CiJustification = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
24891
|
-
flexDirection: "column",
|
|
24892
|
-
paddingLeft: 2,
|
|
24893
|
-
children: [
|
|
24894
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24895
|
-
dimColor: true,
|
|
24896
|
-
children: "Scan every pull request to prevent new React issues while you fix the backlog."
|
|
24897
|
-
}),
|
|
24898
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
24899
|
-
dimColor: true,
|
|
24900
|
-
children: [
|
|
24901
|
-
"Used by teams at ",
|
|
24902
|
-
CI_TRUST_COMPANIES,
|
|
24903
|
-
"."
|
|
24904
|
-
]
|
|
24905
|
-
}),
|
|
24906
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TuiLink, {
|
|
24907
|
-
url: GITHUB_ACTIONS_SETUP_URL,
|
|
24908
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24909
|
-
color: "cyan",
|
|
24910
|
-
children: GITHUB_ACTIONS_SETUP_URL
|
|
24911
|
-
})
|
|
24912
|
-
})
|
|
24913
|
-
]
|
|
24914
|
-
});
|
|
24915
|
-
//#endregion
|
|
24916
|
-
//#region src/cli/ink/components/ci-setup.tsx
|
|
24917
|
-
const CiSetup = ({ feedback, onConfirm, onLearnMore, onBack, onQuit }) => {
|
|
24918
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
24919
|
-
flexDirection: "column",
|
|
24920
|
-
children: [
|
|
24921
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
24922
|
-
bold: true,
|
|
24923
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24924
|
-
color: "cyan",
|
|
24925
|
-
children: "?"
|
|
24926
|
-
}), " Add React Doctor to GitHub Actions?"]
|
|
24927
|
-
}),
|
|
24928
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CiJustification, {}),
|
|
24929
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ActionMenu, {
|
|
24930
|
-
actions: [{
|
|
24931
|
-
id: "confirm",
|
|
24932
|
-
label: "Yes, add the workflow",
|
|
24933
|
-
onSelect: onConfirm
|
|
24934
|
-
}, {
|
|
24935
|
-
id: "learn-more",
|
|
24936
|
-
label: "Open the GitHub Actions guide",
|
|
24937
|
-
onSelect: onLearnMore
|
|
24938
|
-
}],
|
|
24939
|
-
onEscape: onBack,
|
|
24940
|
-
onQuit
|
|
24941
|
-
}),
|
|
24942
|
-
feedback ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24943
|
-
color: feedback.didSucceed ? "green" : "yellow",
|
|
24944
|
-
children: feedback.didSucceed ? feedback.message : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TuiLink, {
|
|
24945
|
-
url: GITHUB_ACTIONS_SETUP_URL,
|
|
24946
|
-
children: feedback.message
|
|
24947
|
-
})
|
|
24948
|
-
}) : null,
|
|
24949
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
24950
|
-
marginTop: 1,
|
|
24951
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
24952
|
-
dimColor: true,
|
|
24953
|
-
children: "↑/↓ move · enter select · esc back · q quit"
|
|
24954
|
-
})
|
|
24955
|
-
})
|
|
24956
|
-
]
|
|
24957
|
-
});
|
|
24958
|
-
};
|
|
24959
|
-
//#endregion
|
|
24960
|
-
//#region src/cli/ink/hooks/use-scroll-viewport.ts
|
|
24961
|
-
const useScrollViewport = (options) => {
|
|
24962
|
-
const { itemCount, height, initialSelectedIndex = 0, isActive = true, isSelectable, onSelectedIndexChange } = options;
|
|
24963
|
-
const canSelect = (index) => index >= 0 && index < itemCount && (isSelectable ? isSelectable(index) : true);
|
|
24964
|
-
const seekSelectable = (start, step) => {
|
|
24965
|
-
for (let index = start; index >= 0 && index < itemCount; index += step) if (canSelect(index)) return index;
|
|
24966
|
-
return -1;
|
|
24967
|
-
};
|
|
24968
|
-
const nearestSelectable = (target, step) => {
|
|
24969
|
-
const ahead = seekSelectable(target, step);
|
|
24970
|
-
if (ahead !== -1) return ahead;
|
|
24971
|
-
const behind = seekSelectable(target, -step);
|
|
24972
|
-
return behind === -1 ? target : behind;
|
|
24973
|
-
};
|
|
24974
|
-
const [selectedIndex, setSelectedIndex] = (0, import_react.useState)(() => {
|
|
24975
|
-
const first = seekSelectable(clampNumber(initialSelectedIndex, 0, itemCount - 1), 1);
|
|
24976
|
-
return first === -1 ? 0 : first;
|
|
24977
|
-
});
|
|
24978
|
-
const [offset, setOffset] = (0, import_react.useState)(0);
|
|
24979
|
-
const awaitingSecondG = (0, import_react.useRef)(false);
|
|
24980
|
-
const moveTo = (rawIndex, step) => {
|
|
24981
|
-
const nextSelectedIndex = nearestSelectable(clampNumber(rawIndex, 0, itemCount - 1), step);
|
|
24982
|
-
setSelectedIndex(nextSelectedIndex);
|
|
24983
|
-
onSelectedIndexChange?.(nextSelectedIndex);
|
|
24984
|
-
setOffset((currentOffset) => {
|
|
24985
|
-
if (nextSelectedIndex < currentOffset) return nextSelectedIndex;
|
|
24986
|
-
if (nextSelectedIndex >= currentOffset + height) return nextSelectedIndex - height + 1;
|
|
24987
|
-
return currentOffset;
|
|
24988
|
-
});
|
|
24989
|
-
};
|
|
24990
|
-
useInput((input, key) => {
|
|
24991
|
-
if (itemCount === 0) return;
|
|
24992
|
-
const isSecondG = awaitingSecondG.current && input === "g";
|
|
24993
|
-
if (input !== "g") awaitingSecondG.current = false;
|
|
24994
|
-
if (key.downArrow || input === "j") return moveTo(selectedIndex + 1, 1);
|
|
24995
|
-
if (key.upArrow || input === "k") return moveTo(selectedIndex - 1, -1);
|
|
24996
|
-
if (key.pageDown) return moveTo(selectedIndex + height, 1);
|
|
24997
|
-
if (key.pageUp) return moveTo(selectedIndex - height, -1);
|
|
24998
|
-
if (key.ctrl && input === "d") return moveTo(selectedIndex + Math.floor(height / 2), 1);
|
|
24999
|
-
if (key.ctrl && input === "u") return moveTo(selectedIndex - Math.floor(height / 2), -1);
|
|
25000
|
-
if (input === "G") return moveTo(itemCount - 1, -1);
|
|
25001
|
-
if (isSecondG) {
|
|
25002
|
-
awaitingSecondG.current = false;
|
|
25003
|
-
return moveTo(0, 1);
|
|
25004
|
-
}
|
|
25005
|
-
if (input === "g") awaitingSecondG.current = true;
|
|
25006
|
-
}, { isActive });
|
|
25007
|
-
const resolvedSelected = canSelect(selectedIndex) ? selectedIndex : nearestSelectable(clampNumber(selectedIndex, 0, itemCount - 1), 1);
|
|
25008
|
-
const visibleStart = resolveVisibleStart({
|
|
25009
|
-
itemCount,
|
|
25010
|
-
offset,
|
|
25011
|
-
selectedIndex: resolvedSelected,
|
|
25012
|
-
viewportHeight: height
|
|
25013
|
-
});
|
|
25014
|
-
return {
|
|
25015
|
-
selectedIndex: resolvedSelected,
|
|
25016
|
-
visibleStart,
|
|
25017
|
-
visibleEnd: Math.min(itemCount, visibleStart + height)
|
|
25018
|
-
};
|
|
25019
|
-
};
|
|
25020
|
-
//#endregion
|
|
25021
|
-
//#region src/cli/ink/lib/build-issue-prompt.ts
|
|
25022
|
-
const buildIssuePrompt = ({ row, projectName }) => {
|
|
25023
|
-
const { representative } = row;
|
|
25024
|
-
const severityLabel = row.severity === "error" ? "ERROR" : "WARN";
|
|
25025
|
-
const uniqueSites = [...new Set(row.diagnostics.map(formatDiagnosticSite))];
|
|
25026
|
-
const inlineSites = uniqueSites.slice(0, 8);
|
|
25027
|
-
const remainingSiteCount = uniqueSites.length - inlineSites.length;
|
|
25028
|
-
const lines = [
|
|
25029
|
-
`Fix exactly one React Doctor rule in ${projectName}:`,
|
|
25030
|
-
"",
|
|
25031
|
-
`${severityLabel} ${row.category}: ${row.title} (${row.ruleKey}, ×${row.siteCount})`,
|
|
25032
|
-
representative.message
|
|
25033
|
-
];
|
|
25034
|
-
if (representative.help) lines.push("", `Suggested fix: ${representative.help}`);
|
|
25035
|
-
const fixRecipeLine = formatFixRecipeLine(representative);
|
|
25036
|
-
if (fixRecipeLine) lines.push("", fixRecipeLine);
|
|
25037
|
-
lines.push("", "Scope:", `- Fix only ${row.ruleKey}.`, "- Fix the root cause; do not suppress, disable, or silence the rule.", "- Keep unrelated refactors out of this pass.", "", "Affected sites:", ...inlineSites.map((site) => `- ${site}`));
|
|
25038
|
-
if (remainingSiteCount > 0) lines.push(`- +${remainingSiteCount} more sites`);
|
|
25039
|
-
const learnMoreLine = formatLearnMoreLine(representative);
|
|
25040
|
-
if (learnMoreLine) lines.push("", learnMoreLine);
|
|
25041
|
-
lines.push("", `Verify with \`npx react-doctor@latest --verbose\` and confirm ${row.ruleKey} is gone before moving on.`);
|
|
25042
|
-
return lines.join("\n");
|
|
25043
|
-
};
|
|
25044
|
-
//#endregion
|
|
25045
|
-
//#region src/cli/ink/lib/severity-variants.ts
|
|
25046
|
-
const ICONS = isUnicodeSupported() ? {
|
|
25047
|
-
error: "✖",
|
|
25048
|
-
warning: "⚠"
|
|
25049
|
-
} : {
|
|
25050
|
-
error: "x",
|
|
25051
|
-
warning: "!"
|
|
25052
|
-
};
|
|
25053
|
-
const severityVariant = (severity) => severity === "error" ? {
|
|
25054
|
-
color: "red",
|
|
25055
|
-
icon: ICONS.error,
|
|
25056
|
-
label: "error"
|
|
25057
|
-
} : {
|
|
25058
|
-
color: "yellow",
|
|
25059
|
-
icon: ICONS.warning,
|
|
25060
|
-
label: "warning"
|
|
25061
|
-
};
|
|
25062
|
-
//#endregion
|
|
25063
|
-
//#region src/cli/ink/components/diagnostic-detail.tsx
|
|
25064
|
-
const DiagnosticDetail = ({ row, rootDirectory }) => {
|
|
25065
|
-
const codeFrame = (0, import_react.useMemo)(() => {
|
|
25066
|
-
if (!row) return null;
|
|
25067
|
-
const { representative } = row;
|
|
25068
|
-
return buildCodeFrame({
|
|
25069
|
-
filePath: representative.filePath,
|
|
25070
|
-
line: representative.line,
|
|
25071
|
-
column: representative.column,
|
|
25072
|
-
rootDirectory
|
|
25073
|
-
});
|
|
25074
|
-
}, [row, rootDirectory]);
|
|
25075
|
-
if (!row) return null;
|
|
25076
|
-
const variant = severityVariant(row.severity);
|
|
25077
|
-
const { representative } = row;
|
|
25078
|
-
const impact = getCategoryImpact(row.category);
|
|
25079
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25080
|
-
flexDirection: "column",
|
|
25081
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25082
|
-
wrap: "truncate-end",
|
|
25083
|
-
children: [
|
|
25084
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25085
|
-
color: variant.color,
|
|
25086
|
-
children: [variant.icon, " "]
|
|
25087
|
-
}),
|
|
25088
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25089
|
-
color: variant.color,
|
|
25090
|
-
bold: true,
|
|
25091
|
-
children: row.title
|
|
25092
|
-
}),
|
|
25093
|
-
row.siteCount > 1 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25094
|
-
dimColor: true,
|
|
25095
|
-
children: [" ×", row.siteCount]
|
|
25096
|
-
}) : null
|
|
25097
|
-
]
|
|
25098
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25099
|
-
flexDirection: "column",
|
|
25100
|
-
paddingLeft: 2,
|
|
25101
|
-
children: [
|
|
25102
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25103
|
-
dimColor: true,
|
|
25104
|
-
wrap: "truncate-end",
|
|
25105
|
-
children: [
|
|
25106
|
-
row.category,
|
|
25107
|
-
" · ",
|
|
25108
|
-
variant.label,
|
|
25109
|
-
" · ",
|
|
25110
|
-
row.location,
|
|
25111
|
-
representative.fileContext ? ` · ${representative.fileContext} file` : ""
|
|
25112
|
-
]
|
|
25113
|
-
}),
|
|
25114
|
-
impact ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25115
|
-
marginTop: 1,
|
|
25116
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25117
|
-
wrap: "wrap",
|
|
25118
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25119
|
-
color: "cyan",
|
|
25120
|
-
children: "Impact "
|
|
25121
|
-
}), impact]
|
|
25122
|
-
})
|
|
25123
|
-
}) : null,
|
|
25124
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25125
|
-
marginTop: 1,
|
|
25126
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25127
|
-
wrap: "wrap",
|
|
25128
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25129
|
-
color: "cyan",
|
|
25130
|
-
children: "Why "
|
|
25131
|
-
}), representative.message]
|
|
25132
|
-
})
|
|
25133
|
-
}),
|
|
25134
|
-
codeFrame ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25135
|
-
marginTop: 1,
|
|
25136
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: codeFrame })
|
|
25137
|
-
}) : null,
|
|
25138
|
-
representative.help ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25139
|
-
marginTop: 1,
|
|
25140
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25141
|
-
wrap: "wrap",
|
|
25142
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25143
|
-
color: "cyan",
|
|
25144
|
-
children: "Fix "
|
|
25145
|
-
}), representative.help]
|
|
25146
|
-
})
|
|
25147
|
-
}) : null,
|
|
25148
|
-
row.ruleGuideUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25149
|
-
marginTop: 1,
|
|
25150
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25151
|
-
color: "blue",
|
|
25152
|
-
wrap: "truncate-end",
|
|
25153
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TuiLink, {
|
|
25154
|
-
url: row.ruleGuideUrl,
|
|
25155
|
-
children: ["Rule guide: ", row.ruleGuideUrl]
|
|
25156
|
-
})
|
|
25157
|
-
})
|
|
25158
|
-
}) : null
|
|
25159
|
-
]
|
|
25160
|
-
})]
|
|
25161
|
-
});
|
|
25162
|
-
};
|
|
25163
|
-
//#endregion
|
|
25164
|
-
//#region src/cli/ink/components/diagnostic-item.tsx
|
|
25165
|
-
const DiagnosticItem = ({ row, isSelected, isRead }) => {
|
|
25166
|
-
const variant = severityVariant(row.severity);
|
|
25167
|
-
const shouldHighlightSeverity = isSelected || !isRead;
|
|
25168
|
-
let marker = "• ";
|
|
25169
|
-
if (isRead) marker = " ";
|
|
25170
|
-
if (isSelected) marker = "› ";
|
|
25171
|
-
let markerColor = shouldHighlightSeverity ? variant.color : void 0;
|
|
25172
|
-
if (isSelected) markerColor = "cyan";
|
|
25173
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25174
|
-
wrap: "truncate-end",
|
|
25175
|
-
dimColor: isRead && !isSelected,
|
|
25176
|
-
children: [
|
|
25177
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25178
|
-
color: markerColor,
|
|
25179
|
-
children: marker
|
|
25180
|
-
}),
|
|
25181
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25182
|
-
color: shouldHighlightSeverity ? variant.color : void 0,
|
|
25183
|
-
children: `${variant.icon} `
|
|
25184
|
-
}),
|
|
25185
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25186
|
-
color: shouldHighlightSeverity ? variant.color : void 0,
|
|
25187
|
-
bold: isSelected,
|
|
25188
|
-
children: row.title
|
|
25189
|
-
}),
|
|
25190
|
-
row.siteCount > 1 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25191
|
-
dimColor: true,
|
|
25192
|
-
children: [" ×", row.siteCount]
|
|
25193
|
-
}) : null
|
|
25194
|
-
]
|
|
25195
|
-
});
|
|
25196
|
-
};
|
|
25197
|
-
//#endregion
|
|
25198
|
-
//#region src/cli/ink/components/status-bar.tsx
|
|
25199
|
-
const StatusBar = ({ total, errorCount, warningCount, position, issueCount, unreadCount, projectCount, keyHints = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25200
|
-
dimColor: true,
|
|
25201
|
-
children: "↑/↓ to move"
|
|
25202
|
-
}), exitHint = "q to quit", compact = false }) => {
|
|
25203
|
-
const counts = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
25204
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25205
|
-
bold: true,
|
|
25206
|
-
children: pluralize(total, "finding")
|
|
25207
|
-
}),
|
|
25208
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25209
|
-
dimColor: true,
|
|
25210
|
-
children: " "
|
|
25211
|
-
}),
|
|
25212
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25213
|
-
color: "red",
|
|
25214
|
-
children: pluralize(errorCount, "error")
|
|
25215
|
-
}),
|
|
25216
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25217
|
-
dimColor: true,
|
|
25218
|
-
children: " "
|
|
25219
|
-
}),
|
|
25220
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25221
|
-
color: "yellow",
|
|
25222
|
-
children: pluralize(warningCount, "warning")
|
|
25223
|
-
})
|
|
25224
|
-
] });
|
|
25225
|
-
if (compact) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25226
|
-
wrap: "truncate-end",
|
|
25227
|
-
children: [
|
|
25228
|
-
counts,
|
|
25229
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25230
|
-
dimColor: true,
|
|
25231
|
-
children: [
|
|
25232
|
-
" · ",
|
|
25233
|
-
"issue ",
|
|
25234
|
-
position,
|
|
25235
|
-
"/",
|
|
25236
|
-
issueCount,
|
|
25237
|
-
" · "
|
|
25238
|
-
]
|
|
25239
|
-
}),
|
|
25240
|
-
keyHints,
|
|
25241
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25242
|
-
dimColor: true,
|
|
25243
|
-
children: [" · ", exitHint]
|
|
25244
|
-
})
|
|
25245
|
-
]
|
|
25246
|
-
});
|
|
25247
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25248
|
-
flexDirection: "column",
|
|
25249
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25250
|
-
wrap: "truncate-end",
|
|
25251
|
-
children: [
|
|
25252
|
-
counts,
|
|
25253
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25254
|
-
dimColor: true,
|
|
25255
|
-
children: [
|
|
25256
|
-
" · ",
|
|
25257
|
-
"issue ",
|
|
25258
|
-
position,
|
|
25259
|
-
"/",
|
|
25260
|
-
issueCount
|
|
25261
|
-
]
|
|
25262
|
-
}),
|
|
25263
|
-
projectCount !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25264
|
-
dimColor: true,
|
|
25265
|
-
children: [" · ", pluralize(projectCount, "project")]
|
|
25266
|
-
}) : null
|
|
25267
|
-
]
|
|
25268
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25269
|
-
wrap: "truncate-end",
|
|
25270
|
-
children: [
|
|
25271
|
-
unreadCount !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25272
|
-
color: unreadCount > 0 ? "cyan" : void 0,
|
|
25273
|
-
dimColor: unreadCount === 0,
|
|
25274
|
-
children: [
|
|
25275
|
-
pluralize(unreadCount, "issue"),
|
|
25276
|
-
" unread",
|
|
25277
|
-
" · "
|
|
25278
|
-
]
|
|
25279
|
-
}) : null,
|
|
25280
|
-
keyHints,
|
|
25281
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25282
|
-
dimColor: true,
|
|
25283
|
-
children: [" · ", exitHint]
|
|
25284
|
-
})
|
|
25285
|
-
]
|
|
25286
|
-
})]
|
|
25287
|
-
});
|
|
25288
|
-
};
|
|
25289
|
-
//#endregion
|
|
25290
|
-
//#region src/cli/ink/components/diagnostic-list.tsx
|
|
25291
|
-
const DIAGNOSTIC_KEY_HINTS = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
25292
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25293
|
-
dimColor: true,
|
|
25294
|
-
children: "↑/↓ move · "
|
|
25295
|
-
}),
|
|
25296
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25297
|
-
color: "cyan",
|
|
25298
|
-
children: "enter"
|
|
25299
|
-
}),
|
|
25300
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25301
|
-
dimColor: true,
|
|
25302
|
-
children: " copy context"
|
|
25303
|
-
})
|
|
25304
|
-
] });
|
|
25305
|
-
const DiagnosticList = ({ header, rows, entries, width, listColumnWidth, detailColumnWidth, listHeight, detailHeight, layout, rootDirectory, projectName, projectCount, initialSelectedRowIndex, readRuleKeys, onSelectedRowIndexChange, onQuit, onBack = onQuit, exitHint }) => {
|
|
25306
|
-
const isSplit = layout === "split";
|
|
25307
|
-
const isCompact = layout === "compact";
|
|
25308
|
-
const initialSelectedEntryIndex = initialSelectedRowIndex === null ? 0 : Math.max(0, entries.findIndex((entry) => entry.kind === "item" && entry.rowIndex === initialSelectedRowIndex));
|
|
25309
|
-
const { selectedIndex: selectedEntryIndex, visibleStart: visibleEntryStart, visibleEnd: visibleEntryEnd } = useScrollViewport({
|
|
25310
|
-
itemCount: entries.length,
|
|
25311
|
-
height: listHeight,
|
|
25312
|
-
initialSelectedIndex: initialSelectedEntryIndex,
|
|
25313
|
-
isSelectable: (entryIndex) => entries[entryIndex]?.kind === "item",
|
|
25314
|
-
onSelectedIndexChange: (entryIndex) => {
|
|
25315
|
-
const entry = entries[entryIndex];
|
|
25316
|
-
if (entry?.kind === "item") onSelectedRowIndexChange(entry.rowIndex);
|
|
25317
|
-
}
|
|
25318
|
-
});
|
|
25319
|
-
const visibleEntries = entries.slice(visibleEntryStart, visibleEntryEnd);
|
|
25320
|
-
const selectedEntry = entries[selectedEntryIndex];
|
|
25321
|
-
const selected = selectedEntry?.kind === "item" ? selectedEntry.row : null;
|
|
25322
|
-
const selectedRuleKey = selected?.ruleKey ?? null;
|
|
25323
|
-
const initialSelectedRuleKey = (0, import_react.useRef)(selectedRuleKey);
|
|
25324
|
-
const didRecordFindingNavigation = (0, import_react.useRef)(false);
|
|
25325
|
-
const [copiedRuleKey, setCopiedRuleKey] = (0, import_react.useState)(null);
|
|
25326
|
-
const [copyFailedRuleKey, setCopyFailedRuleKey] = (0, import_react.useState)(null);
|
|
25327
|
-
const effectiveReadRuleKeys = (0, import_react.useMemo)(() => {
|
|
25328
|
-
if (!selectedRuleKey || readRuleKeys.has(selectedRuleKey)) return readRuleKeys;
|
|
25329
|
-
return new Set(readRuleKeys).add(selectedRuleKey);
|
|
25330
|
-
}, [readRuleKeys, selectedRuleKey]);
|
|
25331
|
-
(0, import_react.useEffect)(() => {
|
|
25332
|
-
if (!selectedRuleKey || selectedRuleKey === initialSelectedRuleKey.current || didRecordFindingNavigation.current) return;
|
|
25333
|
-
didRecordFindingNavigation.current = true;
|
|
25334
|
-
recordCount(METRIC.tuiFindingNavigated);
|
|
25335
|
-
}, [selectedRuleKey]);
|
|
25336
|
-
const copySelectedIssueContext = () => {
|
|
25337
|
-
if (!selected) return;
|
|
25338
|
-
const issuePrompt = buildIssuePrompt({
|
|
25339
|
-
row: selected,
|
|
25340
|
-
projectName
|
|
25341
|
-
});
|
|
25342
|
-
const ruleKey = selected.ruleKey;
|
|
25343
|
-
copyToClipboard(issuePrompt).then((didCopyIssueContext) => {
|
|
25344
|
-
if (didCopyIssueContext) {
|
|
25345
|
-
setCopiedRuleKey(ruleKey);
|
|
25346
|
-
setCopyFailedRuleKey(null);
|
|
25347
|
-
return;
|
|
25348
|
-
}
|
|
25349
|
-
recordCount(METRIC.tuiReportActionSelected, 1, { action: "copy-issue-context-failed" });
|
|
25350
|
-
setCopiedRuleKey(null);
|
|
25351
|
-
setCopyFailedRuleKey(ruleKey);
|
|
25352
|
-
});
|
|
25353
|
-
};
|
|
25354
|
-
useInput((input, key) => {
|
|
25355
|
-
if (input === "q") return onQuit();
|
|
25356
|
-
if (key.escape) return onBack();
|
|
25357
|
-
if (key.return && selected) {
|
|
25358
|
-
recordCount(METRIC.tuiReportActionSelected, 1, { action: "copy-issue-context" });
|
|
25359
|
-
copySelectedIssueContext();
|
|
25360
|
-
}
|
|
25361
|
-
});
|
|
25362
|
-
let totalFindingCount = 0;
|
|
25363
|
-
let errorFindingCount = 0;
|
|
25364
|
-
let warningFindingCount = 0;
|
|
25365
|
-
for (const row of rows) {
|
|
25366
|
-
totalFindingCount += row.siteCount;
|
|
25367
|
-
if (row.severity === "error") errorFindingCount += row.siteCount;
|
|
25368
|
-
else warningFindingCount += row.siteCount;
|
|
25369
|
-
}
|
|
25370
|
-
const selectedIssuePosition = entries.slice(0, selectedEntryIndex + 1).filter((entry) => entry.kind === "item").length;
|
|
25371
|
-
const unreadIssueCount = rows.length - rows.filter((row) => effectiveReadRuleKeys.has(row.ruleKey)).length;
|
|
25372
|
-
const listColumn = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25373
|
-
flexDirection: "column",
|
|
25374
|
-
height: listHeight,
|
|
25375
|
-
width: isSplit ? listColumnWidth : width,
|
|
25376
|
-
children: visibleEntries.map((entry, index) => {
|
|
25377
|
-
const entryIndex = visibleEntryStart + index;
|
|
25378
|
-
if (entry.kind === "header") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25379
|
-
bold: true,
|
|
25380
|
-
children: entry.category
|
|
25381
|
-
}, `header-${entry.category}`);
|
|
25382
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DiagnosticItem, {
|
|
25383
|
-
row: entry.row,
|
|
25384
|
-
isSelected: entryIndex === selectedEntryIndex,
|
|
25385
|
-
isRead: effectiveReadRuleKeys.has(entry.row.ruleKey)
|
|
25386
|
-
}, entry.row.ruleKey);
|
|
25387
|
-
})
|
|
25388
|
-
});
|
|
25389
|
-
let copyFeedback = null;
|
|
25390
|
-
if (copiedRuleKey === selectedRuleKey) copyFeedback = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25391
|
-
marginTop: 1,
|
|
25392
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25393
|
-
color: "green",
|
|
25394
|
-
children: "✓ Copied issue context"
|
|
25395
|
-
})
|
|
25396
|
-
});
|
|
25397
|
-
else if (copyFailedRuleKey === selectedRuleKey) copyFeedback = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25398
|
-
marginTop: 1,
|
|
25399
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25400
|
-
color: "yellow",
|
|
25401
|
-
children: "Couldn't copy issue context. Press Enter to try again."
|
|
25402
|
-
})
|
|
25403
|
-
});
|
|
25404
|
-
const detailContent = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DiagnosticDetail, {
|
|
25405
|
-
row: selected,
|
|
25406
|
-
rootDirectory
|
|
25407
|
-
}), copyFeedback] });
|
|
25408
|
-
let visibleKeyHints = DIAGNOSTIC_KEY_HINTS;
|
|
25409
|
-
if (isCompact && copiedRuleKey === selectedRuleKey) visibleKeyHints = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25410
|
-
color: "green",
|
|
25411
|
-
children: "✓ Copied issue context"
|
|
25412
|
-
});
|
|
25413
|
-
else if (isCompact && copyFailedRuleKey === selectedRuleKey) visibleKeyHints = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25414
|
-
color: "yellow",
|
|
25415
|
-
children: "Copy failed · enter retry"
|
|
25416
|
-
});
|
|
25417
|
-
const statusBar = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25418
|
-
marginTop: isCompact ? 0 : 1,
|
|
25419
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBar, {
|
|
25420
|
-
total: totalFindingCount,
|
|
25421
|
-
errorCount: errorFindingCount,
|
|
25422
|
-
warningCount: warningFindingCount,
|
|
25423
|
-
position: selectedIssuePosition,
|
|
25424
|
-
issueCount: rows.length,
|
|
25425
|
-
unreadCount: unreadIssueCount,
|
|
25426
|
-
projectCount,
|
|
25427
|
-
keyHints: visibleKeyHints,
|
|
25428
|
-
exitHint,
|
|
25429
|
-
compact: isCompact
|
|
25430
|
-
})
|
|
25431
|
-
});
|
|
25432
|
-
if (isCompact) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25433
|
-
flexDirection: "column",
|
|
25434
|
-
width,
|
|
25435
|
-
children: [
|
|
25436
|
-
header,
|
|
25437
|
-
listColumn,
|
|
25438
|
-
statusBar
|
|
25439
|
-
]
|
|
25440
|
-
});
|
|
25441
|
-
if (isSplit) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25442
|
-
flexDirection: "column",
|
|
25443
|
-
width,
|
|
25444
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25445
|
-
flexDirection: "row",
|
|
25446
|
-
maxHeight: detailHeight,
|
|
25447
|
-
overflowY: "hidden",
|
|
25448
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25449
|
-
flexDirection: "column",
|
|
25450
|
-
width: listColumnWidth,
|
|
25451
|
-
marginRight: 1,
|
|
25452
|
-
children: [header, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25453
|
-
marginTop: 1,
|
|
25454
|
-
children: listColumn
|
|
25455
|
-
})]
|
|
25456
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25457
|
-
flexDirection: "column",
|
|
25458
|
-
width: detailColumnWidth,
|
|
25459
|
-
borderStyle: "single",
|
|
25460
|
-
borderColor: "gray",
|
|
25461
|
-
borderTop: false,
|
|
25462
|
-
borderRight: false,
|
|
25463
|
-
borderBottom: false,
|
|
25464
|
-
paddingLeft: 1,
|
|
25465
|
-
overflowY: "hidden",
|
|
25466
|
-
children: detailContent
|
|
25467
|
-
})]
|
|
25468
|
-
}), statusBar]
|
|
25469
|
-
});
|
|
25470
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25471
|
-
flexDirection: "column",
|
|
25472
|
-
width,
|
|
25473
|
-
children: [
|
|
25474
|
-
header,
|
|
25475
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25476
|
-
marginTop: 1,
|
|
25477
|
-
children: listColumn
|
|
25478
|
-
}),
|
|
25479
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25480
|
-
dimColor: true,
|
|
25481
|
-
children: "─".repeat(width)
|
|
25482
|
-
}),
|
|
25483
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25484
|
-
flexDirection: "column",
|
|
25485
|
-
maxHeight: detailHeight,
|
|
25486
|
-
overflowY: "hidden",
|
|
25487
|
-
children: detailContent
|
|
25488
|
-
}),
|
|
25489
|
-
statusBar
|
|
25490
|
-
]
|
|
25491
|
-
});
|
|
25492
|
-
};
|
|
25493
|
-
//#endregion
|
|
25494
|
-
//#region src/cli/ink/components/handoff-ci-recommendation.tsx
|
|
25495
|
-
const HandoffCiRecommendation = ({ onAddToCi, onContinue, onQuit }) => {
|
|
25496
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25497
|
-
flexDirection: "column",
|
|
25498
|
-
children: [
|
|
25499
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25500
|
-
paddingLeft: 2,
|
|
25501
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25502
|
-
bold: true,
|
|
25503
|
-
children: "Add React Doctor to GitHub Actions first"
|
|
25504
|
-
})
|
|
25505
|
-
}),
|
|
25506
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CiJustification, {}),
|
|
25507
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ActionMenu, {
|
|
25508
|
-
actions: [{
|
|
25509
|
-
id: "add-to-ci",
|
|
25510
|
-
label: "Add to GitHub Actions first (Recommended)",
|
|
25511
|
-
onSelect: onAddToCi
|
|
25512
|
-
}, {
|
|
25513
|
-
id: "continue",
|
|
25514
|
-
label: "Continue without GitHub Actions",
|
|
25515
|
-
onSelect: onContinue
|
|
25516
|
-
}],
|
|
25517
|
-
onEscape: onContinue,
|
|
25518
|
-
onQuit
|
|
25519
|
-
}),
|
|
25520
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25521
|
-
marginTop: 1,
|
|
25522
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25523
|
-
dimColor: true,
|
|
25524
|
-
children: "↑/↓ move · enter select · esc skip · q quit"
|
|
25525
|
-
})
|
|
25526
|
-
})
|
|
25527
|
-
]
|
|
25528
|
-
});
|
|
25529
|
-
};
|
|
25530
|
-
//#endregion
|
|
25531
|
-
//#region src/cli/ink/components/report-landing.tsx
|
|
25532
|
-
const ReportLanding = ({ header, phase, issueCount, emptyStateMessage, lintFailureReason, skippedChecks, incompleteMessage, actions, selectedIndex, onSelectionChange, onQuit }) => {
|
|
25533
|
-
const showScore = phase === "actions" || phase === "score";
|
|
25534
|
-
const skippedCheckLabel = skippedChecks?.filter((skippedCheck) => skippedCheck !== "lint" || !lintFailureReason).join(" and ");
|
|
25535
|
-
const hasIncompleteResult = Boolean(incompleteMessage || lintFailureReason || skippedCheckLabel);
|
|
25536
|
-
useInput((input) => {
|
|
25537
|
-
if (input === "q") onQuit();
|
|
25538
|
-
}, { isActive: phase !== "actions" });
|
|
25539
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25540
|
-
flexDirection: "column",
|
|
25541
|
-
children: [
|
|
25542
|
-
showScore ? header : null,
|
|
25543
|
-
hasIncompleteResult || issueCount === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25544
|
-
flexDirection: "column",
|
|
25545
|
-
marginTop: 1,
|
|
25546
|
-
children: [
|
|
25547
|
-
incompleteMessage ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25548
|
-
color: "yellow",
|
|
25549
|
-
children: ["⚠ ", incompleteMessage]
|
|
25550
|
-
}) : null,
|
|
25551
|
-
lintFailureReason ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25552
|
-
color: "yellow",
|
|
25553
|
-
children: ["⚠ Lint did not run: ", lintFailureReason]
|
|
25554
|
-
}) : null,
|
|
25555
|
-
skippedCheckLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25556
|
-
color: "yellow",
|
|
25557
|
-
children: [
|
|
25558
|
-
"⚠ ",
|
|
25559
|
-
issueCount === 0 ? "No issues detected, but " : "",
|
|
25560
|
-
skippedCheckLabel,
|
|
25561
|
-
" checks failed — results are incomplete."
|
|
25562
|
-
]
|
|
25563
|
-
}) : null,
|
|
25564
|
-
issueCount === 0 && !hasIncompleteResult ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25565
|
-
color: "green",
|
|
25566
|
-
children: ["✔ ", emptyStateMessage ?? "No issues found. Nice work."]
|
|
25567
|
-
}) : null
|
|
25568
|
-
]
|
|
25569
|
-
}) : null,
|
|
25570
|
-
phase === "actions" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ActionMenu, {
|
|
25571
|
-
actions,
|
|
25572
|
-
selectedIndex,
|
|
25573
|
-
onSelectionChange,
|
|
25574
|
-
onEscape: onQuit,
|
|
25575
|
-
onQuit
|
|
25576
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25577
|
-
marginTop: 1,
|
|
25578
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25579
|
-
dimColor: true,
|
|
25580
|
-
children: actions.length === 0 ? "q quit" : "↑/↓ move · enter select · q quit"
|
|
25581
|
-
})
|
|
25582
|
-
})] }) : null
|
|
25583
|
-
]
|
|
25584
|
-
});
|
|
25585
|
-
};
|
|
25586
|
-
//#endregion
|
|
25587
|
-
//#region src/cli/ink/components/report-issue-stream.tsx
|
|
25588
|
-
const ReportIssueStream = ({ rows, selectedIndex, width }) => {
|
|
25589
|
-
const visibleRowCount = Math.min(rows.length, 3);
|
|
25590
|
-
const visibleRows = Array.from({ length: visibleRowCount }, (_, visibleRowIndex) => {
|
|
25591
|
-
const rowIndex = (selectedIndex - visibleRowCount + visibleRowIndex + 1 + rows.length) % rows.length;
|
|
25592
|
-
return {
|
|
25593
|
-
row: rows[rowIndex],
|
|
25594
|
-
rowIndex
|
|
25595
|
-
};
|
|
25596
|
-
});
|
|
25597
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25598
|
-
flexDirection: "column",
|
|
25599
|
-
width: Math.min(width, 60),
|
|
25600
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25601
|
-
bold: true,
|
|
25602
|
-
children: "Reviewing issues"
|
|
25603
|
-
}), visibleRows.map(({ row, rowIndex }) => {
|
|
25604
|
-
if (!row) return null;
|
|
25605
|
-
const variant = severityVariant(row.severity);
|
|
25606
|
-
const isSelected = rowIndex === selectedIndex;
|
|
25607
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25608
|
-
dimColor: !isSelected,
|
|
25609
|
-
wrap: "truncate-end",
|
|
25610
|
-
children: [
|
|
25611
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25612
|
-
color: isSelected ? variant.color : void 0,
|
|
25613
|
-
children: [isSelected ? "›" : " ", " "]
|
|
25614
|
-
}),
|
|
25615
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25616
|
-
color: isSelected ? variant.color : void 0,
|
|
25617
|
-
bold: isSelected,
|
|
25618
|
-
children: [
|
|
25619
|
-
row.category,
|
|
25620
|
-
": ",
|
|
25621
|
-
row.title
|
|
25622
|
-
]
|
|
25623
|
-
}),
|
|
25624
|
-
row.siteCount > 1 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25625
|
-
dimColor: true,
|
|
25626
|
-
children: [" ×", row.siteCount]
|
|
25627
|
-
}) : null
|
|
25628
|
-
]
|
|
25629
|
-
}, row.ruleKey);
|
|
25630
|
-
})]
|
|
25631
|
-
});
|
|
25632
|
-
};
|
|
25633
|
-
//#endregion
|
|
25634
|
-
//#region src/cli/utils/doctor-face.ts
|
|
25635
|
-
const doctorFace = (score) => {
|
|
25636
|
-
if (score >= 75) return ["◠ ◠", " ▽ "];
|
|
25637
|
-
if (score >= 50) return ["• •", " ─ "];
|
|
25638
|
-
return ["x x", " ▽ "];
|
|
25639
|
-
};
|
|
25640
|
-
//#endregion
|
|
25641
|
-
//#region src/cli/utils/ease-out-cubic.ts
|
|
25642
|
-
const easeOutCubic = (progress) => 1 - (1 - progress) ** 3;
|
|
25643
|
-
//#endregion
|
|
25644
|
-
//#region src/cli/ink/hooks/use-animated-score.ts
|
|
25645
|
-
const useAnimatedScore = ({ score, projectedScore, shouldAnimate }) => {
|
|
25646
|
-
const projectionTarget = projectedScore ?? score;
|
|
25647
|
-
const hasProjection = projectionTarget > score;
|
|
25648
|
-
const initialProjectedScore = !shouldAnimate && hasProjection ? projectionTarget : null;
|
|
25649
|
-
const [displayScore, setDisplayScore] = (0, import_react.useState)(shouldAnimate ? 0 : score);
|
|
25650
|
-
const [displayProjectedScore, setDisplayProjectedScore] = (0, import_react.useState)(initialProjectedScore);
|
|
25651
|
-
(0, import_react.useEffect)(() => {
|
|
25652
|
-
if (!shouldAnimate) {
|
|
25653
|
-
setDisplayScore(score);
|
|
25654
|
-
setDisplayProjectedScore(hasProjection ? projectionTarget : null);
|
|
25655
|
-
return;
|
|
25656
|
-
}
|
|
25657
|
-
let timeoutId;
|
|
25658
|
-
const runProjection = () => {
|
|
25659
|
-
let projectionFrame = 1;
|
|
25660
|
-
const renderProjectionFrame = () => {
|
|
25661
|
-
const progress = easeOutCubic(projectionFrame / 16);
|
|
25662
|
-
setDisplayProjectedScore(score + (projectionTarget - score) * progress);
|
|
25663
|
-
if (projectionFrame < 16) {
|
|
25664
|
-
projectionFrame += 1;
|
|
25665
|
-
timeoutId = setTimeout(renderProjectionFrame, 35);
|
|
25666
|
-
} else setDisplayProjectedScore(projectionTarget);
|
|
25667
|
-
};
|
|
25668
|
-
renderProjectionFrame();
|
|
25669
|
-
};
|
|
25670
|
-
let scoreFrame = 0;
|
|
25671
|
-
const renderScoreFrame = () => {
|
|
25672
|
-
const progress = easeOutCubic(scoreFrame / 40);
|
|
25673
|
-
setDisplayScore(Math.round(score * progress));
|
|
25674
|
-
if (scoreFrame < 40) {
|
|
25675
|
-
scoreFrame += 1;
|
|
25676
|
-
timeoutId = setTimeout(renderScoreFrame, 50);
|
|
25677
|
-
return;
|
|
25678
|
-
}
|
|
25679
|
-
setDisplayScore(score);
|
|
25680
|
-
if (hasProjection) runProjection();
|
|
25681
|
-
};
|
|
25682
|
-
renderScoreFrame();
|
|
25683
|
-
return () => {
|
|
25684
|
-
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
25685
|
-
};
|
|
25686
|
-
}, [
|
|
25687
|
-
shouldAnimate,
|
|
25688
|
-
score,
|
|
25689
|
-
projectionTarget,
|
|
25690
|
-
hasProjection
|
|
25691
|
-
]);
|
|
25692
|
-
return {
|
|
25693
|
-
displayScore,
|
|
25694
|
-
displayProjectedScore
|
|
25695
|
-
};
|
|
25696
|
-
};
|
|
25697
|
-
//#endregion
|
|
25698
|
-
//#region src/cli/ink/lib/score-color.ts
|
|
25699
|
-
const scoreColorName = (score) => {
|
|
25700
|
-
if (score >= 75) return "green";
|
|
25701
|
-
if (score >= 50) return "yellow";
|
|
25702
|
-
return "red";
|
|
25703
|
-
};
|
|
25704
|
-
//#endregion
|
|
25705
|
-
//#region src/cli/ink/components/score-header.tsx
|
|
25706
|
-
const REACT_DOCTOR_URL = "https://react.doctor";
|
|
25707
|
-
const ReactDoctorLink = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TuiLink, {
|
|
25708
|
-
url: REACT_DOCTOR_URL,
|
|
25709
|
-
children: ["React Doctor ", /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25710
|
-
dimColor: true,
|
|
25711
|
-
children: [
|
|
25712
|
-
"(",
|
|
25713
|
-
REACT_DOCTOR_URL,
|
|
25714
|
-
")"
|
|
25715
|
-
]
|
|
25716
|
-
})]
|
|
25717
|
-
});
|
|
25718
|
-
const ScoreHeader = ({ variant, score, projectedScore, projectName, issueCount, noScoreMessage, width }) => {
|
|
25719
|
-
const { columns } = useStdoutDimensions();
|
|
25720
|
-
const availableWidth = width ?? columns;
|
|
25721
|
-
const { stdout } = useStdout();
|
|
25722
|
-
const shouldAnimateScore = canAnimateOnboarding(stdout ?? void 0);
|
|
25723
|
-
const visibleProjectedScore = variant === "landing" ? projectedScore : null;
|
|
25724
|
-
const { displayScore, displayProjectedScore } = useAnimatedScore({
|
|
25725
|
-
score: score?.score ?? 0,
|
|
25726
|
-
projectedScore: visibleProjectedScore,
|
|
25727
|
-
shouldAnimate: variant === "landing" && shouldAnimateScore && score !== null
|
|
25728
|
-
});
|
|
25729
|
-
if (!score) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25730
|
-
flexDirection: "column",
|
|
25731
|
-
paddingLeft: 2,
|
|
25732
|
-
width: availableWidth,
|
|
25733
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25734
|
-
wrap: "truncate-end",
|
|
25735
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReactDoctorLink, {})
|
|
25736
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25737
|
-
dimColor: true,
|
|
25738
|
-
wrap: "wrap",
|
|
25739
|
-
children: noScoreMessage ?? `${pluralize(issueCount, "finding")} · ${projectName}`
|
|
25740
|
-
})]
|
|
25741
|
-
});
|
|
25742
|
-
const scoreColor = scoreColorName(score.score);
|
|
25743
|
-
const scoreSummaryLine = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25744
|
-
wrap: "truncate-end",
|
|
25745
|
-
children: [
|
|
25746
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25747
|
-
color: scoreColor,
|
|
25748
|
-
bold: true,
|
|
25749
|
-
children: displayScore
|
|
25750
|
-
}),
|
|
25751
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25752
|
-
dimColor: true,
|
|
25753
|
-
children: [
|
|
25754
|
-
" / ",
|
|
25755
|
-
100,
|
|
25756
|
-
" "
|
|
25757
|
-
]
|
|
25758
|
-
}),
|
|
25759
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25760
|
-
color: scoreColor,
|
|
25761
|
-
children: score.label
|
|
25762
|
-
}),
|
|
25763
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25764
|
-
dimColor: true,
|
|
25765
|
-
children: [" · ", projectName]
|
|
25766
|
-
})
|
|
25767
|
-
]
|
|
25768
|
-
});
|
|
25769
|
-
if (availableWidth < 23) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25770
|
-
flexDirection: "column",
|
|
25771
|
-
width: availableWidth,
|
|
25772
|
-
children: [scoreSummaryLine, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25773
|
-
wrap: "truncate-end",
|
|
25774
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReactDoctorLink, {})
|
|
25775
|
-
})]
|
|
25776
|
-
});
|
|
25777
|
-
const barWidth = Math.max(10, Math.min(50, availableWidth - 11 - 2));
|
|
25778
|
-
const filledBarWidth = Math.round(displayScore / 100 * barWidth);
|
|
25779
|
-
const projectedBarWidth = displayProjectedScore != null ? Math.min(barWidth, Math.round(displayProjectedScore / 100 * barWidth)) : filledBarWidth;
|
|
25780
|
-
const projectedGainWidth = Math.max(0, projectedBarWidth - filledBarWidth);
|
|
25781
|
-
const emptyBarWidth = Math.max(0, barWidth - filledBarWidth - projectedGainWidth);
|
|
25782
|
-
const [eyes, mouth] = doctorFace(score.score);
|
|
25783
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25784
|
-
flexDirection: "column",
|
|
25785
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25786
|
-
paddingLeft: 2,
|
|
25787
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
|
|
25788
|
-
flexDirection: "column",
|
|
25789
|
-
marginRight: 2,
|
|
25790
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25791
|
-
color: scoreColor,
|
|
25792
|
-
children: `┌─────┐\n│ ${eyes} │\n│ ${mouth} │\n└─────┘`
|
|
25793
|
-
})
|
|
25794
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
25795
|
-
flexDirection: "column",
|
|
25796
|
-
children: [
|
|
25797
|
-
scoreSummaryLine,
|
|
25798
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25799
|
-
wrap: "truncate-end",
|
|
25800
|
-
children: [
|
|
25801
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25802
|
-
color: scoreColor,
|
|
25803
|
-
children: "█".repeat(filledBarWidth)
|
|
25804
|
-
}),
|
|
25805
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25806
|
-
color: scoreColor,
|
|
25807
|
-
dimColor: true,
|
|
25808
|
-
children: "▓".repeat(projectedGainWidth)
|
|
25809
|
-
}),
|
|
25810
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25811
|
-
dimColor: true,
|
|
25812
|
-
children: "░".repeat(emptyBarWidth)
|
|
25813
|
-
})
|
|
25814
|
-
]
|
|
25815
|
-
}),
|
|
25816
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25817
|
-
wrap: "truncate-end",
|
|
25818
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReactDoctorLink, {})
|
|
25819
|
-
}),
|
|
25820
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: " " })
|
|
25821
|
-
]
|
|
25822
|
-
})]
|
|
25823
|
-
}), variant === "landing" && projectedScore != null && projectedScore > score.score ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25824
|
-
wrap: "truncate-end",
|
|
25825
|
-
children: [
|
|
25826
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25827
|
-
dimColor: true,
|
|
25828
|
-
children: " Potential score "
|
|
25829
|
-
}),
|
|
25830
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25831
|
-
color: scoreColorName(projectedScore),
|
|
25832
|
-
children: projectedScore
|
|
25833
|
-
}),
|
|
25834
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
25835
|
-
dimColor: true,
|
|
25836
|
-
children: " after priority fixes "
|
|
25837
|
-
}),
|
|
25838
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
25839
|
-
color: scoreColorName(projectedScore),
|
|
25840
|
-
children: ["+", projectedScore - score.score]
|
|
25841
|
-
})
|
|
25842
|
-
]
|
|
25843
|
-
}) : null]
|
|
25844
|
-
});
|
|
25845
|
-
};
|
|
25846
|
-
//#endregion
|
|
25847
|
-
//#region src/cli/ink/components/report.tsx
|
|
25848
|
-
const EMPTY_LAUNCHABLE_AGENTS = [];
|
|
25849
|
-
const recordReportAction = (action) => {
|
|
25850
|
-
recordCount(METRIC.tuiReportActionSelected, 1, { action });
|
|
25851
|
-
};
|
|
25852
|
-
const completeReportOnboarding = () => {
|
|
25853
|
-
if (shouldRecordOnboarding({
|
|
25854
|
-
paceOnboardingSections: true,
|
|
25855
|
-
forceOnboarding: isOnboardingForced(),
|
|
25856
|
-
verbose: false,
|
|
25857
|
-
isNonInteractiveEnvironment: false
|
|
25858
|
-
})) markOnboardingComplete();
|
|
25859
|
-
};
|
|
25860
|
-
const Report = ({ report, onExit, onQuit = onExit, launchableAgents = EMPTY_LAUNCHABLE_AGENTS, onHandoff, canAddToCi, onAddToCi, projectCount, priorityScores, exitHint = "q to quit" }) => {
|
|
25861
|
-
const { rows: terminalRows, columns } = useStdoutDimensions();
|
|
25862
|
-
const diagnosticRows = (0, import_react.useMemo)(() => buildDiagnosticRows(report.diagnostics, priorityScores ?? [report.score]), [
|
|
25863
|
-
report.diagnostics,
|
|
25864
|
-
report.score,
|
|
25865
|
-
priorityScores
|
|
25866
|
-
]);
|
|
25867
|
-
const diagnosticListEntries = (0, import_react.useMemo)(() => buildDiagnosticListEntries(diagnosticRows), [diagnosticRows]);
|
|
25868
|
-
const reportLayout = resolveReportLayout({
|
|
25869
|
-
columns,
|
|
25870
|
-
diagnosticEntryCount: diagnosticListEntries.length,
|
|
25871
|
-
terminalRows
|
|
25872
|
-
});
|
|
25873
|
-
const reportReveal = useReportReveal({
|
|
25874
|
-
issueCount: diagnosticRows.length,
|
|
25875
|
-
onRevealComplete: completeReportOnboarding
|
|
25876
|
-
});
|
|
25877
|
-
const [activeReportScreen, setActiveReportScreen] = (0, import_react.useState)("landing");
|
|
25878
|
-
const [ciSetupFeedback, setCiSetupFeedback] = (0, import_react.useState)();
|
|
25879
|
-
const [landingSelectedIndex, setLandingSelectedIndex] = (0, import_react.useState)(0);
|
|
25880
|
-
const [viewerSelectedRowIndex, setViewerSelectedRowIndex] = (0, import_react.useState)(null);
|
|
25881
|
-
const [viewerReadRuleKeys, setViewerReadRuleKeys] = (0, import_react.useState)(() => /* @__PURE__ */ new Set());
|
|
25882
|
-
const [isCiSetupQueued, setIsCiSetupQueued] = (0, import_react.useState)(false);
|
|
25883
|
-
const [shouldShowIssueStream, setShouldShowIssueStream] = (0, import_react.useState)(true);
|
|
25884
|
-
const didRecordCompactReport = (0, import_react.useRef)(false);
|
|
25885
|
-
const didRecordIssueStream = (0, import_react.useRef)(false);
|
|
25886
|
-
const didRecordStackedReportCap = (0, import_react.useRef)(false);
|
|
25887
|
-
const isCompact = reportLayout.layout === "compact";
|
|
25888
|
-
const isWide = reportLayout.layout === "split";
|
|
25889
|
-
(0, import_react.useEffect)(() => {
|
|
25890
|
-
if (!isCompact || didRecordCompactReport.current) return;
|
|
25891
|
-
didRecordCompactReport.current = true;
|
|
25892
|
-
recordCount(METRIC.tuiCompactReportShown);
|
|
25893
|
-
}, [isCompact]);
|
|
25894
|
-
(0, import_react.useEffect)(() => {
|
|
25895
|
-
if (!reportLayout.isStackedReportCapped || didRecordStackedReportCap.current) return;
|
|
25896
|
-
didRecordStackedReportCap.current = true;
|
|
25897
|
-
recordCount(METRIC.tuiStackedReportCapped);
|
|
25898
|
-
}, [reportLayout.isStackedReportCapped]);
|
|
25899
|
-
(0, import_react.useEffect)(() => {
|
|
25900
|
-
if (reportReveal.phase !== "streaming" || didRecordIssueStream.current) return;
|
|
25901
|
-
didRecordIssueStream.current = true;
|
|
25902
|
-
recordCount(METRIC.tuiIssueStreamShown);
|
|
25903
|
-
}, [reportReveal.phase]);
|
|
25904
|
-
const scoreHeaderProps = {
|
|
25905
|
-
score: report.score,
|
|
25906
|
-
projectedScore: report.projectedScore,
|
|
25907
|
-
projectName: report.projectName,
|
|
25908
|
-
issueCount: report.diagnostics.length,
|
|
25909
|
-
noScoreMessage: report.noScoreMessage,
|
|
25910
|
-
width: isWide ? reportLayout.listColumnWidth : reportLayout.width
|
|
25911
|
-
};
|
|
25912
|
-
const isCiSetupAvailable = Boolean(canAddToCi && onAddToCi && !isCiSetupQueued);
|
|
25913
|
-
const isHandoffAvailable = diagnosticRows.length > 0 && Boolean(onHandoff);
|
|
25914
|
-
const completeHandoff = (destination) => {
|
|
25915
|
-
if (!onHandoff) return;
|
|
25916
|
-
onHandoff({
|
|
25917
|
-
destination,
|
|
25918
|
-
prompt: buildHandoffPayload({
|
|
25919
|
-
diagnostics: report.diagnostics,
|
|
25920
|
-
projectName: report.projectName
|
|
25921
|
-
})
|
|
25922
|
-
});
|
|
25923
|
-
onExit();
|
|
25924
|
-
};
|
|
25925
|
-
const firstDiagnosticEntry = diagnosticListEntries.find((entry) => entry.kind === "item");
|
|
25926
|
-
const resolvedViewerSelectedRowIndex = viewerSelectedRowIndex ?? (firstDiagnosticEntry?.kind === "item" ? firstDiagnosticEntry.rowIndex : null);
|
|
25927
|
-
const markViewerRuleRead = (index) => {
|
|
25928
|
-
const ruleKey = diagnosticRows[index]?.ruleKey;
|
|
25929
|
-
if (!ruleKey) return;
|
|
25930
|
-
setViewerReadRuleKeys((previous) => previous.has(ruleKey) ? previous : new Set(previous).add(ruleKey));
|
|
25931
|
-
};
|
|
25932
|
-
const handleViewerSelectionChange = (index) => {
|
|
25933
|
-
setViewerSelectedRowIndex(index);
|
|
25934
|
-
markViewerRuleRead(index);
|
|
25935
|
-
};
|
|
25936
|
-
const openReportScreen = (nextScreen) => {
|
|
25937
|
-
setShouldShowIssueStream(false);
|
|
25938
|
-
setCiSetupFeedback(void 0);
|
|
25939
|
-
setActiveReportScreen(nextScreen);
|
|
25940
|
-
};
|
|
25941
|
-
const landingActions = [];
|
|
25942
|
-
if (report.diagnostics.length > 0) landingActions.push({
|
|
25943
|
-
id: "view-issues",
|
|
25944
|
-
label: `Review ${pluralize(diagnosticRows.length, "issue")}`,
|
|
25945
|
-
onSelect: () => {
|
|
25946
|
-
recordReportAction("view-issues");
|
|
25947
|
-
if (resolvedViewerSelectedRowIndex !== null) {
|
|
25948
|
-
setViewerSelectedRowIndex(resolvedViewerSelectedRowIndex);
|
|
25949
|
-
markViewerRuleRead(resolvedViewerSelectedRowIndex);
|
|
25950
|
-
}
|
|
25951
|
-
openReportScreen("issues");
|
|
25952
|
-
}
|
|
25953
|
-
});
|
|
25954
|
-
if (isCiSetupAvailable) landingActions.push({
|
|
25955
|
-
id: "add-to-ci",
|
|
25956
|
-
label: "Add to GitHub Actions (Recommended)",
|
|
25957
|
-
description: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CiJustification, {}),
|
|
25958
|
-
onSelect: () => {
|
|
25959
|
-
recordReportAction("add-to-ci");
|
|
25960
|
-
openReportScreen("ci");
|
|
25961
|
-
}
|
|
25962
|
-
});
|
|
25963
|
-
if (isHandoffAvailable) landingActions.push({
|
|
25964
|
-
id: "handoff",
|
|
25965
|
-
label: "Hand off to an agent",
|
|
25966
|
-
onSelect: () => {
|
|
25967
|
-
recordReportAction("handoff");
|
|
25968
|
-
openReportScreen(isCiSetupAvailable ? "handoff-ci" : "handoff");
|
|
25969
|
-
}
|
|
25970
|
-
});
|
|
25971
|
-
const postReviewLandingActionIndex = landingActions.findIndex((action) => action.id !== "view-issues");
|
|
25972
|
-
const resolvedLandingSelectedIndex = Math.min(landingSelectedIndex, Math.max(0, landingActions.length - 1));
|
|
25973
|
-
const issueStream = reportReveal.phase === "streaming" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReportIssueStream, {
|
|
25974
|
-
rows: diagnosticRows,
|
|
25975
|
-
selectedIndex: reportReveal.streamSelectedIndex,
|
|
25976
|
-
width: reportLayout.width
|
|
25977
|
-
}) : null;
|
|
25978
|
-
let activeScreenContent;
|
|
25979
|
-
if (activeReportScreen === "ci") activeScreenContent = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CiSetup, {
|
|
25980
|
-
feedback: ciSetupFeedback,
|
|
25981
|
-
onConfirm: () => {
|
|
25982
|
-
onAddToCi?.();
|
|
25983
|
-
onExit();
|
|
25984
|
-
},
|
|
25985
|
-
onLearnMore: () => {
|
|
25986
|
-
recordReportAction("ci-learn-more");
|
|
25987
|
-
openUrl(GITHUB_ACTIONS_SETUP_URL).then((didOpen) => {
|
|
25988
|
-
setCiSetupFeedback({
|
|
25989
|
-
didSucceed: didOpen,
|
|
25990
|
-
message: didOpen ? "✓ Opened the GitHub Actions guide in your browser" : `Couldn't open a browser. Visit ${GITHUB_ACTIONS_SETUP_URL}`
|
|
25991
|
-
});
|
|
25992
|
-
});
|
|
25993
|
-
},
|
|
25994
|
-
onBack: () => {
|
|
25995
|
-
setCiSetupFeedback(void 0);
|
|
25996
|
-
setActiveReportScreen("landing");
|
|
25997
|
-
},
|
|
25998
|
-
onQuit
|
|
25999
|
-
});
|
|
26000
|
-
else if (activeReportScreen === "handoff") activeScreenContent = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentHandoff, {
|
|
26001
|
-
agents: launchableAgents,
|
|
26002
|
-
onSelect: completeHandoff,
|
|
26003
|
-
onCopyPrompt: () => completeHandoff("clipboard"),
|
|
26004
|
-
onBack: () => setActiveReportScreen("landing"),
|
|
26005
|
-
onQuit
|
|
26006
|
-
});
|
|
26007
|
-
else if (activeReportScreen === "handoff-ci") activeScreenContent = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HandoffCiRecommendation, {
|
|
26008
|
-
onAddToCi: () => {
|
|
26009
|
-
onAddToCi?.();
|
|
26010
|
-
setIsCiSetupQueued(true);
|
|
26011
|
-
setActiveReportScreen("handoff");
|
|
26012
|
-
},
|
|
26013
|
-
onContinue: () => setActiveReportScreen("handoff"),
|
|
26014
|
-
onQuit
|
|
26015
|
-
});
|
|
26016
|
-
else if (activeReportScreen === "landing") activeScreenContent = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReportLanding, {
|
|
26017
|
-
header: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScoreHeader, {
|
|
26018
|
-
variant: "landing",
|
|
26019
|
-
...scoreHeaderProps
|
|
26020
|
-
}),
|
|
26021
|
-
phase: reportReveal.phase,
|
|
26022
|
-
issueCount: report.diagnostics.length,
|
|
26023
|
-
emptyStateMessage: report.emptyStateMessage,
|
|
26024
|
-
lintFailureReason: report.lintFailureReason,
|
|
26025
|
-
skippedChecks: report.skippedChecks,
|
|
26026
|
-
incompleteMessage: report.incompleteMessage,
|
|
26027
|
-
actions: landingActions,
|
|
26028
|
-
selectedIndex: resolvedLandingSelectedIndex,
|
|
26029
|
-
onSelectionChange: setLandingSelectedIndex,
|
|
26030
|
-
onQuit
|
|
26031
|
-
});
|
|
26032
|
-
else activeScreenContent = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DiagnosticList, {
|
|
26033
|
-
header: reportLayout.showsViewerScoreHeader ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScoreHeader, {
|
|
26034
|
-
variant: "viewer",
|
|
26035
|
-
...scoreHeaderProps
|
|
26036
|
-
}) : null,
|
|
26037
|
-
rows: diagnosticRows,
|
|
26038
|
-
entries: diagnosticListEntries,
|
|
26039
|
-
width: reportLayout.width,
|
|
26040
|
-
listColumnWidth: reportLayout.listColumnWidth,
|
|
26041
|
-
detailColumnWidth: reportLayout.detailColumnWidth,
|
|
26042
|
-
listHeight: reportLayout.listHeight,
|
|
26043
|
-
detailHeight: reportLayout.detailHeight,
|
|
26044
|
-
layout: reportLayout.layout,
|
|
26045
|
-
rootDirectory: report.rootDirectory,
|
|
26046
|
-
projectName: report.projectName,
|
|
26047
|
-
projectCount,
|
|
26048
|
-
initialSelectedRowIndex: resolvedViewerSelectedRowIndex,
|
|
26049
|
-
readRuleKeys: viewerReadRuleKeys,
|
|
26050
|
-
onSelectedRowIndexChange: handleViewerSelectionChange,
|
|
26051
|
-
onQuit,
|
|
26052
|
-
onBack: () => {
|
|
26053
|
-
setLandingSelectedIndex(Math.max(0, postReviewLandingActionIndex));
|
|
26054
|
-
setActiveReportScreen("landing");
|
|
26055
|
-
},
|
|
26056
|
-
exitHint: `esc back · ${exitHint}`
|
|
26057
|
-
});
|
|
26058
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [activeReportScreen === "landing" && shouldShowIssueStream ? issueStream : null, activeScreenContent] });
|
|
26059
|
-
};
|
|
26060
|
-
//#endregion
|
|
26061
23958
|
//#region ../../node_modules/.pnpm/cli-spinners@2.9.2/node_modules/cli-spinners/spinners.json
|
|
26062
23959
|
var require_spinners = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
26063
23960
|
module.exports = {
|
|
@@ -27670,232 +25567,52 @@ function Spinner({ type = "dots" }) {
|
|
|
27670
25567
|
return import_react.createElement(Text, null, spinner.frames[frame]);
|
|
27671
25568
|
}
|
|
27672
25569
|
//#endregion
|
|
27673
|
-
//#region src/cli/
|
|
27674
|
-
const
|
|
27675
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
|
|
27676
|
-
flexDirection: "column",
|
|
27677
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
27678
|
-
wrap: "truncate-end",
|
|
27679
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
27680
|
-
color: "cyan",
|
|
27681
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { type: "dots" })
|
|
27682
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [" ", progressText ?? "Scanning…"] })]
|
|
27683
|
-
}), recent.map((diagnostic, diagnosticIndex) => {
|
|
27684
|
-
const variant = severityVariant(diagnostic.severity === "error" ? "error" : "warning");
|
|
27685
|
-
const location = formatDiagnosticSite(diagnostic);
|
|
27686
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
27687
|
-
wrap: "truncate-end",
|
|
27688
|
-
children: [
|
|
27689
|
-
" ",
|
|
27690
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
|
|
27691
|
-
color: variant.color,
|
|
27692
|
-
children: variant.icon
|
|
27693
|
-
}),
|
|
27694
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [" ", diagnostic.title ?? `${diagnostic.plugin}/${diagnostic.rule}`] }),
|
|
27695
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
|
|
27696
|
-
dimColor: true,
|
|
27697
|
-
children: [" ", location]
|
|
27698
|
-
})
|
|
27699
|
-
]
|
|
27700
|
-
}, `${diagnostic.filePath}:${diagnostic.line}:${diagnostic.column}:${diagnostic.plugin}:${diagnostic.rule}:${diagnosticIndex}`);
|
|
27701
|
-
})]
|
|
27702
|
-
});
|
|
27703
|
-
};
|
|
25570
|
+
//#region src/cli/utils/is-printable-input.ts
|
|
25571
|
+
const isPrintableInput = (input) => input.length > 0 && [...input].every((character) => character.charCodeAt(0) >= 32);
|
|
27704
25572
|
//#endregion
|
|
27705
|
-
//#region src/cli/
|
|
27706
|
-
const
|
|
27707
|
-
|
|
27708
|
-
|
|
27709
|
-
|
|
27710
|
-
|
|
27711
|
-
|
|
27712
|
-
projectedScore: summary.projectedScore,
|
|
27713
|
-
projectName: summary.projectName,
|
|
27714
|
-
rootDirectory: summary.rootDirectory,
|
|
27715
|
-
scannedFileCount: summary.scannedFileCount,
|
|
27716
|
-
elapsedMilliseconds: summary.elapsedMilliseconds,
|
|
27717
|
-
isOffline: summary.isOffline,
|
|
27718
|
-
noScoreMessage: summary.noScoreMessage,
|
|
27719
|
-
skippedChecks: [...new Set(summary.projects.flatMap((project) => project.skippedChecks ?? []))],
|
|
27720
|
-
...skippedProjects.length > 0 ? { incompleteMessage: formatSkippedProjectsMessage(skippedProjects.length) } : {},
|
|
27721
|
-
...summary.emptyStateMessage ? { emptyStateMessage: summary.emptyStateMessage } : {},
|
|
27722
|
-
...summary.lintFailureReason ? { lintFailureReason: summary.lintFailureReason } : {}
|
|
27723
|
-
},
|
|
27724
|
-
onExit,
|
|
27725
|
-
onQuit,
|
|
27726
|
-
launchableAgents,
|
|
27727
|
-
onHandoff,
|
|
27728
|
-
canAddToCi,
|
|
27729
|
-
onAddToCi,
|
|
27730
|
-
projectCount: summary.projects.length + skippedProjects.length,
|
|
27731
|
-
priorityScores: summary.projects.map((project) => project.score)
|
|
27732
|
-
});
|
|
25573
|
+
//#region src/cli/utils/terminal-symbols.ts
|
|
25574
|
+
const supportsUnicodeSymbols = process.platform !== "win32" ? process.env.TERM !== "linux" : Boolean(process.env.WT_SESSION) || Boolean(process.env.TERMINUS_SUBLIME) || process.env.ConEmuTask === "{cmd::Cmder}" || process.env.TERM_PROGRAM === "Terminus-Sublime" || process.env.TERM_PROGRAM === "vscode" || process.env.TERM === "xterm-256color" || process.env.TERM === "alacritty" || process.env.TERM === "rxvt-unicode" || process.env.TERM === "rxvt-unicode-256color" || process.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
25575
|
+
const terminalSymbols = {
|
|
25576
|
+
pointer: supportsUnicodeSymbols ? "❯" : ">",
|
|
25577
|
+
pointerSmall: "›",
|
|
25578
|
+
radioOn: supportsUnicodeSymbols ? "◉" : "(*)",
|
|
25579
|
+
radioOff: supportsUnicodeSymbols ? "◯" : "( )"
|
|
27733
25580
|
};
|
|
27734
25581
|
//#endregion
|
|
27735
|
-
//#region src/cli/ink/hooks/use-
|
|
27736
|
-
const
|
|
27737
|
-
|
|
27738
|
-
|
|
27739
|
-
|
|
27740
|
-
|
|
27741
|
-
|
|
27742
|
-
|
|
27743
|
-
|
|
27744
|
-
|
|
27745
|
-
|
|
27746
|
-
};
|
|
27747
|
-
if (displayMode === "report" && snapshot.phase === "summary") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Summary, {
|
|
27748
|
-
summary: snapshot.summary,
|
|
27749
|
-
launchableAgents,
|
|
27750
|
-
onHandoff,
|
|
27751
|
-
canAddToCi,
|
|
27752
|
-
onAddToCi,
|
|
27753
|
-
onExit: exit,
|
|
27754
|
-
onQuit: handleQuit
|
|
27755
|
-
});
|
|
27756
|
-
if (displayMode === "report" && snapshot.phase === "report") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Report, {
|
|
27757
|
-
report: snapshot.report,
|
|
27758
|
-
launchableAgents,
|
|
27759
|
-
onHandoff,
|
|
27760
|
-
canAddToCi,
|
|
27761
|
-
onAddToCi,
|
|
27762
|
-
onExit: exit,
|
|
27763
|
-
onQuit: handleQuit
|
|
27764
|
-
});
|
|
27765
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Scanning, {
|
|
27766
|
-
progressText: snapshot.progress,
|
|
27767
|
-
recent: snapshot.liveDiagnostics.slice(-5)
|
|
25582
|
+
//#region src/cli/ink/hooks/use-exit-on-ctrl-c.ts
|
|
25583
|
+
const SHOW_CURSOR = "\x1B[?25h";
|
|
25584
|
+
const useExitOnCtrlC = (onCancel) => {
|
|
25585
|
+
useInput((input, key) => {
|
|
25586
|
+
if (key.ctrl && input === "c") {
|
|
25587
|
+
onCancel?.();
|
|
25588
|
+
recordCount(METRIC.tuiCancelled, 1, { resourceFooter: true });
|
|
25589
|
+
process.stdin.setRawMode?.(false);
|
|
25590
|
+
process.stdout.write(SHOW_CURSOR);
|
|
25591
|
+
exitGracefully();
|
|
25592
|
+
}
|
|
27768
25593
|
});
|
|
27769
25594
|
};
|
|
27770
25595
|
//#endregion
|
|
27771
|
-
//#region src/cli/ink/
|
|
27772
|
-
const
|
|
27773
|
-
|
|
27774
|
-
|
|
27775
|
-
})
|
|
27776
|
-
const
|
|
27777
|
-
const
|
|
27778
|
-
|
|
27779
|
-
|
|
27780
|
-
|
|
27781
|
-
|
|
27782
|
-
|
|
27783
|
-
|
|
27784
|
-
|
|
27785
|
-
};
|
|
27786
|
-
|
|
27787
|
-
|
|
27788
|
-
//#region src/cli/ink/scan-store.ts
|
|
27789
|
-
const INITIAL_SNAPSHOT = {
|
|
27790
|
-
phase: "scanning",
|
|
27791
|
-
liveDiagnostics: [],
|
|
27792
|
-
progress: null
|
|
27793
|
-
};
|
|
27794
|
-
const createScanStore = () => {
|
|
27795
|
-
let snapshot = INITIAL_SNAPSHOT;
|
|
27796
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
27797
|
-
let pendingProgress = null;
|
|
27798
|
-
let progressTimer = null;
|
|
27799
|
-
const commit = (next) => {
|
|
27800
|
-
snapshot = next;
|
|
27801
|
-
for (const listener of [...listeners]) listener();
|
|
27802
|
-
};
|
|
27803
|
-
const cancelPendingProgress = () => {
|
|
27804
|
-
pendingProgress = null;
|
|
27805
|
-
if (progressTimer === null) return;
|
|
27806
|
-
clearTimeout(progressTimer);
|
|
27807
|
-
progressTimer = null;
|
|
27808
|
-
};
|
|
27809
|
-
const setProgress = (progress) => {
|
|
27810
|
-
cancelPendingProgress();
|
|
27811
|
-
commit({
|
|
27812
|
-
...snapshot,
|
|
27813
|
-
progress
|
|
27814
|
-
});
|
|
27815
|
-
};
|
|
27816
|
-
return {
|
|
27817
|
-
subscribe: (listener) => {
|
|
27818
|
-
listeners.add(listener);
|
|
27819
|
-
return () => {
|
|
27820
|
-
listeners.delete(listener);
|
|
27821
|
-
};
|
|
27822
|
-
},
|
|
27823
|
-
getSnapshot: () => snapshot,
|
|
27824
|
-
emitDiagnostic: (diagnostic) => commit({
|
|
27825
|
-
...snapshot,
|
|
27826
|
-
liveDiagnostics: [...snapshot.liveDiagnostics, diagnostic].slice(-25)
|
|
27827
|
-
}),
|
|
27828
|
-
scheduleProgress: (progress) => {
|
|
27829
|
-
pendingProgress = progress;
|
|
27830
|
-
if (progressTimer !== null) return;
|
|
27831
|
-
progressTimer = setTimeout(() => {
|
|
27832
|
-
progressTimer = null;
|
|
27833
|
-
const progressToCommit = pendingProgress;
|
|
27834
|
-
pendingProgress = null;
|
|
27835
|
-
if (progressToCommit !== null) commit({
|
|
27836
|
-
...snapshot,
|
|
27837
|
-
progress: progressToCommit
|
|
27838
|
-
});
|
|
27839
|
-
}, 250);
|
|
27840
|
-
progressTimer.unref?.();
|
|
27841
|
-
},
|
|
27842
|
-
setProgress,
|
|
27843
|
-
setReport: (report) => {
|
|
27844
|
-
cancelPendingProgress();
|
|
27845
|
-
commit({
|
|
27846
|
-
phase: "report",
|
|
27847
|
-
liveDiagnostics: snapshot.liveDiagnostics,
|
|
27848
|
-
progress: snapshot.progress,
|
|
27849
|
-
report
|
|
27850
|
-
});
|
|
27851
|
-
},
|
|
27852
|
-
setSummary: (summary) => {
|
|
27853
|
-
cancelPendingProgress();
|
|
27854
|
-
commit({
|
|
27855
|
-
phase: "summary",
|
|
27856
|
-
liveDiagnostics: snapshot.liveDiagnostics,
|
|
27857
|
-
progress: snapshot.progress,
|
|
27858
|
-
summary
|
|
27859
|
-
});
|
|
27860
|
-
}
|
|
27861
|
-
};
|
|
25596
|
+
//#region src/cli/ink/hooks/use-stdout-dimensions.ts
|
|
25597
|
+
const readDimensions = (stdout) => ({
|
|
25598
|
+
columns: stdout?.columns ?? 80,
|
|
25599
|
+
rows: stdout?.rows ?? 24
|
|
25600
|
+
});
|
|
25601
|
+
const useStdoutDimensions = () => {
|
|
25602
|
+
const { stdout } = useStdout();
|
|
25603
|
+
const [dimensions, setDimensions] = (0, import_react.useState)(() => readDimensions(stdout));
|
|
25604
|
+
(0, import_react.useEffect)(() => {
|
|
25605
|
+
if (!stdout) return;
|
|
25606
|
+
const onResize = () => setDimensions(readDimensions(stdout));
|
|
25607
|
+
stdout.on("resize", onResize);
|
|
25608
|
+
return () => {
|
|
25609
|
+
stdout.off("resize", onResize);
|
|
25610
|
+
};
|
|
25611
|
+
}, [stdout]);
|
|
25612
|
+
return dimensions;
|
|
27862
25613
|
};
|
|
27863
25614
|
//#endregion
|
|
27864
|
-
//#region src/cli/ink/
|
|
27865
|
-
const qualifyDiagnosticPaths = (diagnostics, rootDirectory, projectDirectory) => {
|
|
27866
|
-
const prefix = path.relative(rootDirectory, projectDirectory);
|
|
27867
|
-
if (prefix === "" || prefix.startsWith("..")) return [...diagnostics];
|
|
27868
|
-
return diagnostics.map((diagnostic) => path.isAbsolute(diagnostic.filePath) ? diagnostic : {
|
|
27869
|
-
...diagnostic,
|
|
27870
|
-
filePath: toForwardSlashes(path.join(prefix, diagnostic.filePath))
|
|
27871
|
-
});
|
|
27872
|
-
};
|
|
27873
|
-
const resolveScanPresentation = (input, projectScans) => {
|
|
27874
|
-
const isScoreDisabled = input.options?.noScore === true || projectScans.some((projectScan) => projectScan.config?.noScore === true);
|
|
27875
|
-
return {
|
|
27876
|
-
isOffline: isCiEnvironment() || input.share === false || isShareOptedOut(projectScans, input.options?.noScore),
|
|
27877
|
-
initialProgress: projectScans.length > 1 ? "Indexing workspace files…" : "Scanning project…",
|
|
27878
|
-
noScoreMessage: buildNoScoreMessage({ isScoreDisabled }),
|
|
27879
|
-
outputDirectory: input.options?.outputDirectory,
|
|
27880
|
-
shouldRecommendCi: projectScans.length > 1 || projectScans.some((projectScan) => isCiUnconfigured(projectScan.directory)),
|
|
27881
|
-
verbose: input.options?.verbose === true
|
|
27882
|
-
};
|
|
27883
|
-
};
|
|
27884
|
-
const resolveTuiInspectOptions = (input, config) => {
|
|
27885
|
-
const warnings = resolveCliInspectOptions({
|
|
27886
|
-
blocking: input.blocking,
|
|
27887
|
-
warnings: input.options?.warnings
|
|
27888
|
-
}, config).warnings;
|
|
27889
|
-
return warnings === void 0 ? { ...input.options } : {
|
|
27890
|
-
...input.options,
|
|
27891
|
-
warnings
|
|
27892
|
-
};
|
|
27893
|
-
};
|
|
27894
|
-
const resolveSelectedDirectories = async (rootDirectory, input) => {
|
|
27895
|
-
const packages = discoverWorkspacePackages(rootDirectory);
|
|
27896
|
-
if (!(packages.length > 1 && !input.projectFlag && !input.skipPrompts && (input.configProjects ?? []).length === 0 && process.stdin.isTTY === true)) return selectProjects(rootDirectory, input.projectFlag, input.skipPrompts ?? false, input.configProjects);
|
|
27897
|
-
return promptProjectSelection(packages, rootDirectory);
|
|
27898
|
-
};
|
|
25615
|
+
//#region src/cli/ink/register-mounted-tui-renderer.ts
|
|
27899
25616
|
const registerMountedTuiRenderer = (instance) => {
|
|
27900
25617
|
let didDisposeRenderer = false;
|
|
27901
25618
|
const disposeRenderer = (shouldClearOutput) => {
|
|
@@ -27910,442 +25627,247 @@ const registerMountedTuiRenderer = (instance) => {
|
|
|
27910
25627
|
disposeRenderer(true);
|
|
27911
25628
|
};
|
|
27912
25629
|
};
|
|
27913
|
-
|
|
27914
|
-
|
|
27915
|
-
|
|
27916
|
-
|
|
27917
|
-
|
|
27918
|
-
|
|
27919
|
-
|
|
27920
|
-
|
|
27921
|
-
|
|
27922
|
-
|
|
27923
|
-
|
|
27924
|
-
|
|
27925
|
-
|
|
27926
|
-
|
|
27927
|
-
|
|
27928
|
-
|
|
27929
|
-
|
|
27930
|
-
if (
|
|
27931
|
-
|
|
27932
|
-
|
|
27933
|
-
|
|
27934
|
-
|
|
27935
|
-
const toScanReport = ({ result, diagnostics, rootDirectory, projectedScore, isOffline, noScoreMessage, emptyStateMessage }) => {
|
|
27936
|
-
const lintFailureReason = resolveLintFailureReason([result]);
|
|
27937
|
-
return {
|
|
27938
|
-
diagnostics: diagnostics ?? result.diagnostics,
|
|
27939
|
-
score: result.score,
|
|
27940
|
-
projectedScore,
|
|
27941
|
-
projectName: result.project.projectName,
|
|
27942
|
-
rootDirectory,
|
|
27943
|
-
scannedFileCount: result.scannedFileCount ?? 0,
|
|
27944
|
-
elapsedMilliseconds: result.elapsedMilliseconds,
|
|
27945
|
-
isOffline,
|
|
27946
|
-
noScoreMessage,
|
|
27947
|
-
emptyStateMessage,
|
|
27948
|
-
skippedChecks: result.skippedChecks,
|
|
27949
|
-
...lintFailureReason ? { lintFailureReason } : {}
|
|
27950
|
-
};
|
|
27951
|
-
};
|
|
27952
|
-
const findLowestScoredReport = (reports) => {
|
|
27953
|
-
let lowestScoredReport = null;
|
|
27954
|
-
for (const report of reports) {
|
|
27955
|
-
if (report.score === null) continue;
|
|
27956
|
-
if (lowestScoredReport === null || report.score.score < lowestScoredReport.score.score) lowestScoredReport = {
|
|
27957
|
-
score: report.score,
|
|
27958
|
-
scoreDiagnostics: report.scoreDiagnostics
|
|
27959
|
-
};
|
|
27960
|
-
}
|
|
27961
|
-
return lowestScoredReport;
|
|
27962
|
-
};
|
|
27963
|
-
const resolveEmptyStateMessage = (input, demotedDiagnosticCount) => buildEmptyReportMessage({
|
|
27964
|
-
categoryFilters: input.options?.categoryFilters ?? [],
|
|
27965
|
-
demotedDiagnosticCount,
|
|
27966
|
-
outputSurface: input.options?.outputSurface ?? "cli"
|
|
27967
|
-
});
|
|
27968
|
-
const printExitFooter = async (input) => {
|
|
27969
|
-
process.stdout.write(`${highlighter.success("✔")} Scanned ${pluralize(input.scannedFileCount, "file")} in ${formatElapsedTime(input.elapsedMilliseconds)}\n`);
|
|
27970
|
-
if (input.lintFailureReason !== null) process.stdout.write(`${highlighter.warn("⚠")} Lint did not run: ${input.lintFailureReason}\n`);
|
|
27971
|
-
await runPromise(printFooter({
|
|
27972
|
-
diagnostics: [...input.diagnostics],
|
|
27973
|
-
scoreResult: input.scoreResult,
|
|
27974
|
-
projectName: input.projectName,
|
|
27975
|
-
isOffline: input.isOffline
|
|
27976
|
-
}));
|
|
27977
|
-
};
|
|
27978
|
-
const performTuiHandoff = async (request, rootDirectory) => {
|
|
27979
|
-
let failureMessage = null;
|
|
27980
|
-
if (request.destination === "clipboard") {
|
|
27981
|
-
const didCopy = await copyToClipboard(request.prompt);
|
|
27982
|
-
recordCount(METRIC.agentHandoff, 1, {
|
|
27983
|
-
outcome: "clipboard",
|
|
27984
|
-
source: "tui",
|
|
27985
|
-
copied: didCopy
|
|
27986
|
-
});
|
|
27987
|
-
if (didCopy) {
|
|
27988
|
-
process.stdout.write(`${highlighter.success("✔")} Copied the prompt to your clipboard.\n`);
|
|
27989
|
-
return;
|
|
27990
|
-
}
|
|
27991
|
-
failureMessage = "Couldn't access the clipboard. Here's the prompt instead:";
|
|
27992
|
-
} else try {
|
|
27993
|
-
await launchCliAgent(request.destination, request.prompt, rootDirectory);
|
|
27994
|
-
return;
|
|
27995
|
-
} catch {
|
|
27996
|
-
failureMessage = `Couldn't launch ${CLI_AGENT_BINARIES[request.destination]}. Here's the prompt instead:`;
|
|
27997
|
-
}
|
|
27998
|
-
process.stdout.write(`${highlighter.warn("⚠")} ${failureMessage}\n`);
|
|
27999
|
-
process.stdout.write(`${highlighter.dim("──── Agent prompt ────")}\n`);
|
|
28000
|
-
process.stdout.write(`${request.prompt}\n`);
|
|
28001
|
-
process.stdout.write(`${highlighter.dim("──────────────────────")}\n`);
|
|
28002
|
-
};
|
|
28003
|
-
const isCiUnconfigured = (directory) => !isReactDoctorWorkflowInstalled(findNearestPackageDirectory(directory) ?? directory);
|
|
28004
|
-
const performCiSetup = async (rootDirectory) => {
|
|
28005
|
-
const didCreateWorkflow = await setUpGitHubActions({ rootDirectory });
|
|
28006
|
-
recordCount(METRIC.agentHandoff, 1, {
|
|
28007
|
-
outcome: "ci-yes",
|
|
28008
|
-
source: "tui",
|
|
28009
|
-
created: didCreateWorkflow
|
|
28010
|
-
});
|
|
28011
|
-
};
|
|
28012
|
-
const mountScanApp = async (rootDirectory, shouldRecommendCi, initialProgress) => {
|
|
28013
|
-
const store = createScanStore();
|
|
28014
|
-
store.setProgress(initialProgress);
|
|
28015
|
-
const launchableAgents = await detectLaunchableAgents();
|
|
28016
|
-
const pendingActions = {
|
|
28017
|
-
handoffRequest: null,
|
|
28018
|
-
shouldSetUpCi: false,
|
|
28019
|
-
didQuit: false
|
|
28020
|
-
};
|
|
28021
|
-
const mountRenderer = (displayMode) => {
|
|
28022
|
-
const instance = render(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScanApp, {
|
|
28023
|
-
store,
|
|
28024
|
-
displayMode,
|
|
28025
|
-
launchableAgents,
|
|
28026
|
-
onHandoff: (request) => {
|
|
28027
|
-
pendingActions.handoffRequest = request;
|
|
28028
|
-
},
|
|
28029
|
-
canAddToCi: shouldRecommendCi,
|
|
28030
|
-
onAddToCi: () => {
|
|
28031
|
-
pendingActions.shouldSetUpCi = true;
|
|
28032
|
-
},
|
|
28033
|
-
onQuit: () => {
|
|
28034
|
-
pendingActions.didQuit = true;
|
|
28035
|
-
}
|
|
28036
|
-
}), {
|
|
28037
|
-
alternateScreen: false,
|
|
28038
|
-
exitOnCtrlC: false
|
|
28039
|
-
});
|
|
25630
|
+
//#endregion
|
|
25631
|
+
//#region ../../node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react-jsx-runtime.production.js
|
|
25632
|
+
/**
|
|
25633
|
+
* @license React
|
|
25634
|
+
* react-jsx-runtime.production.js
|
|
25635
|
+
*
|
|
25636
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
25637
|
+
*
|
|
25638
|
+
* This source code is licensed under the MIT license found in the
|
|
25639
|
+
* LICENSE file in the root directory of this source tree.
|
|
25640
|
+
*/
|
|
25641
|
+
var require_react_jsx_runtime_production = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
25642
|
+
var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment");
|
|
25643
|
+
function jsxProd(type, config, maybeKey) {
|
|
25644
|
+
var key = null;
|
|
25645
|
+
void 0 !== maybeKey && (key = "" + maybeKey);
|
|
25646
|
+
void 0 !== config.key && (key = "" + config.key);
|
|
25647
|
+
if ("key" in config) {
|
|
25648
|
+
maybeKey = {};
|
|
25649
|
+
for (var propName in config) "key" !== propName && (maybeKey[propName] = config[propName]);
|
|
25650
|
+
} else maybeKey = config;
|
|
25651
|
+
config = maybeKey.ref;
|
|
28040
25652
|
return {
|
|
28041
|
-
|
|
28042
|
-
|
|
25653
|
+
$$typeof: REACT_ELEMENT_TYPE,
|
|
25654
|
+
type,
|
|
25655
|
+
key,
|
|
25656
|
+
ref: void 0 !== config ? config : null,
|
|
25657
|
+
props: maybeKey
|
|
28043
25658
|
};
|
|
28044
|
-
};
|
|
28045
|
-
const executePendingActions = async () => {
|
|
28046
|
-
if (pendingActions.shouldSetUpCi) await performCiSetup(rootDirectory);
|
|
28047
|
-
if (pendingActions.didQuit) return;
|
|
28048
|
-
if (pendingActions.handoffRequest) await performTuiHandoff(pendingActions.handoffRequest, rootDirectory);
|
|
28049
|
-
};
|
|
28050
|
-
return {
|
|
28051
|
-
store,
|
|
28052
|
-
pendingActions,
|
|
28053
|
-
mountRenderer,
|
|
28054
|
-
executePendingActions
|
|
28055
|
-
};
|
|
28056
|
-
};
|
|
28057
|
-
const runMountedScan = async (rootDirectory, presentation, blockingLevel, executeScan) => {
|
|
28058
|
-
const { store, pendingActions, mountRenderer, executePendingActions } = await mountScanApp(rootDirectory, presentation.shouldRecommendCi, presentation.initialProgress);
|
|
28059
|
-
let mountedRenderer = mountRenderer("scan");
|
|
28060
|
-
recordCount(METRIC.tuiScanInlineShown);
|
|
28061
|
-
const context = {
|
|
28062
|
-
store,
|
|
28063
|
-
...presentation
|
|
28064
|
-
};
|
|
28065
|
-
try {
|
|
28066
|
-
const completedScan = await executeScan(context);
|
|
28067
|
-
mountedRenderer.dispose();
|
|
28068
|
-
mountedRenderer = mountRenderer("report");
|
|
28069
|
-
await mountedRenderer.instance.waitUntilExit();
|
|
28070
|
-
mountedRenderer.dispose();
|
|
28071
|
-
if (presentation.outputDirectory !== void 0 || presentation.verbose) await runPromise(printDiagnosticsDump([...completedScan.diagnostics], presentation.outputDirectory, presentation.verbose));
|
|
28072
|
-
if (!pendingActions.didQuit) await printExitFooter({
|
|
28073
|
-
diagnostics: completedScan.diagnostics,
|
|
28074
|
-
scoreResult: completedScan.scoreResult,
|
|
28075
|
-
projectName: completedScan.projectName,
|
|
28076
|
-
scannedFileCount: completedScan.scannedFileCount,
|
|
28077
|
-
elapsedMilliseconds: completedScan.elapsedMilliseconds,
|
|
28078
|
-
isOffline: context.isOffline,
|
|
28079
|
-
lintFailureReason: resolveLintFailureReason(completedScan.scans.map(({ result }) => result))
|
|
28080
|
-
});
|
|
28081
|
-
await executePendingActions();
|
|
28082
|
-
return { shouldFail: shouldFailScanGate({
|
|
28083
|
-
scans: completedScan.scans,
|
|
28084
|
-
blockingLevel,
|
|
28085
|
-
diagnosticsAreGateExempt: completedScan.diagnosticsAreGateExempt
|
|
28086
|
-
}) };
|
|
28087
|
-
} catch (error) {
|
|
28088
|
-
mountedRenderer.dispose();
|
|
28089
|
-
throw error;
|
|
28090
|
-
}
|
|
28091
|
-
};
|
|
28092
|
-
const runSingleProjectScan = async (rootScanTarget, projectDirectory, input, scopePlan, blockingLevel, inspectProject) => {
|
|
28093
|
-
const projectScan = await resolveProjectScan(rootScanTarget, projectDirectory);
|
|
28094
|
-
const isSupplyChainEnabled = input.options?.supplyChain ?? projectScan.config?.supplyChain?.enabled ?? true;
|
|
28095
|
-
const scopeOptions = resolveProjectTuiScanScope({
|
|
28096
|
-
plan: scopePlan,
|
|
28097
|
-
projectDirectory: projectScan.directory,
|
|
28098
|
-
rootDirectory: rootScanTarget.resolvedDirectory,
|
|
28099
|
-
supplyChainEnabled: isSupplyChainEnabled
|
|
28100
|
-
});
|
|
28101
|
-
if (scopeOptions === null) {
|
|
28102
|
-
process.stdout.write("No changed source files in the selected project.\n");
|
|
28103
|
-
return { shouldFail: false };
|
|
28104
25659
|
}
|
|
28105
|
-
|
|
28106
|
-
|
|
28107
|
-
|
|
28108
|
-
|
|
28109
|
-
|
|
28110
|
-
|
|
28111
|
-
|
|
28112
|
-
|
|
28113
|
-
|
|
28114
|
-
|
|
28115
|
-
|
|
25660
|
+
exports.Fragment = REACT_FRAGMENT_TYPE;
|
|
25661
|
+
exports.jsx = jsxProd;
|
|
25662
|
+
exports.jsxs = jsxProd;
|
|
25663
|
+
}));
|
|
25664
|
+
//#endregion
|
|
25665
|
+
//#region ../../node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react-jsx-runtime.development.js
|
|
25666
|
+
/**
|
|
25667
|
+
* @license React
|
|
25668
|
+
* react-jsx-runtime.development.js
|
|
25669
|
+
*
|
|
25670
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
25671
|
+
*
|
|
25672
|
+
* This source code is licensed under the MIT license found in the
|
|
25673
|
+
* LICENSE file in the root directory of this source tree.
|
|
25674
|
+
*/
|
|
25675
|
+
var require_react_jsx_runtime_development = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
25676
|
+
"production" !== process.env.NODE_ENV && (function() {
|
|
25677
|
+
function getComponentNameFromType(type) {
|
|
25678
|
+
if (null == type) return null;
|
|
25679
|
+
if ("function" === typeof type) return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
|
|
25680
|
+
if ("string" === typeof type) return type;
|
|
25681
|
+
switch (type) {
|
|
25682
|
+
case REACT_FRAGMENT_TYPE: return "Fragment";
|
|
25683
|
+
case REACT_PROFILER_TYPE: return "Profiler";
|
|
25684
|
+
case REACT_STRICT_MODE_TYPE: return "StrictMode";
|
|
25685
|
+
case REACT_SUSPENSE_TYPE: return "Suspense";
|
|
25686
|
+
case REACT_SUSPENSE_LIST_TYPE: return "SuspenseList";
|
|
25687
|
+
case REACT_ACTIVITY_TYPE: return "Activity";
|
|
28116
25688
|
}
|
|
28117
|
-
|
|
28118
|
-
|
|
28119
|
-
|
|
28120
|
-
|
|
28121
|
-
|
|
28122
|
-
|
|
28123
|
-
|
|
28124
|
-
|
|
28125
|
-
|
|
28126
|
-
|
|
28127
|
-
|
|
28128
|
-
|
|
28129
|
-
|
|
28130
|
-
|
|
28131
|
-
|
|
28132
|
-
|
|
28133
|
-
diagnostics: reportSelection.diagnostics,
|
|
28134
|
-
rootDirectory: projectScan.directory,
|
|
28135
|
-
projectedScore,
|
|
28136
|
-
isOffline: context.isOffline,
|
|
28137
|
-
noScoreMessage: buildNoScoreMessage({
|
|
28138
|
-
isScoreDisabled: input.options?.noScore === true || projectScan.config?.noScore === true,
|
|
28139
|
-
isAnalysisIncomplete: hasIncompleteScoreAnalysis(result.skippedChecks),
|
|
28140
|
-
disabledMessage: input.options?.scoreDisabledMessage
|
|
28141
|
-
}),
|
|
28142
|
-
emptyStateMessage: resolveEmptyStateMessage(input, reportSelection.demotedDiagnosticCount)
|
|
28143
|
-
}));
|
|
28144
|
-
return {
|
|
28145
|
-
scans: [{
|
|
28146
|
-
result,
|
|
28147
|
-
config: projectScan.config
|
|
28148
|
-
}],
|
|
28149
|
-
diagnostics: reportSelection.diagnostics,
|
|
28150
|
-
diagnosticsAreGateExempt: scopePlan.baselineIntended && result.baselineDelta === void 0,
|
|
28151
|
-
scoreResult: result.score,
|
|
28152
|
-
projectName: result.project.projectName,
|
|
28153
|
-
scannedFileCount: result.scannedFileCount ?? 0,
|
|
28154
|
-
elapsedMilliseconds: result.elapsedMilliseconds
|
|
28155
|
-
};
|
|
28156
|
-
});
|
|
28157
|
-
};
|
|
28158
|
-
const runMultiProjectScan = async (rootScanTarget, directories, input, scopePlan, blockingLevel, inspectProject) => {
|
|
28159
|
-
const feedbackStartTime = performance$1.now();
|
|
28160
|
-
const rootDirectory = rootScanTarget.resolvedDirectory;
|
|
28161
|
-
const discoveredProjectScans = deduplicateProjectScans(await mapWithConcurrency([...directories], 4, (projectDirectory) => resolveProjectScan(rootScanTarget, projectDirectory)));
|
|
28162
|
-
const projectScans = discoveredProjectScans.flatMap((projectScan) => {
|
|
28163
|
-
const isSupplyChainEnabled = input.options?.supplyChain ?? projectScan.config?.supplyChain?.enabled ?? true;
|
|
28164
|
-
const scopeOptions = resolveProjectTuiScanScope({
|
|
28165
|
-
plan: scopePlan,
|
|
28166
|
-
projectDirectory: projectScan.directory,
|
|
28167
|
-
rootDirectory,
|
|
28168
|
-
supplyChainEnabled: isSupplyChainEnabled
|
|
28169
|
-
});
|
|
28170
|
-
return scopeOptions === null ? [] : [{
|
|
28171
|
-
projectScan,
|
|
28172
|
-
scopeOptions
|
|
28173
|
-
}];
|
|
28174
|
-
});
|
|
28175
|
-
if (projectScans.length === 0) {
|
|
28176
|
-
process.stdout.write("No changed source files in the selected projects.\n");
|
|
28177
|
-
return { shouldFail: false };
|
|
28178
|
-
}
|
|
28179
|
-
const projectCount = projectScans.length;
|
|
28180
|
-
const rootProjectScan = discoveredProjectScans.find((projectScan) => path.resolve(projectScan.directory) === path.resolve(rootDirectory));
|
|
28181
|
-
const workspaceDeadCodeOwner = resolveWorkspaceDeadCodeOwner({
|
|
28182
|
-
rootDirectory,
|
|
28183
|
-
projectDirectories: discoveredProjectScans.map((projectScan) => projectScan.directory),
|
|
28184
|
-
isRootDeadCodeEnabled: input.options?.deadCode ?? rootProjectScan?.config?.deadCode ?? true
|
|
28185
|
-
});
|
|
28186
|
-
if (workspaceDeadCodeOwner !== null) recordCount(METRIC.scanWorkspaceDeadCodeShared, 1, { projectCount: discoveredProjectScans.length });
|
|
28187
|
-
return runMountedScan(rootDirectory, resolveScanPresentation(input, projectScans.map(({ projectScan }) => projectScan)), blockingLevel, async (context) => {
|
|
28188
|
-
const startTime = performance$1.now();
|
|
28189
|
-
let finishedCount = 0;
|
|
28190
|
-
recordDistribution(METRIC.scanFeedbackDelay, performance$1.now() - feedbackStartTime, {
|
|
28191
|
-
unit: "millisecond",
|
|
28192
|
-
attributes: {
|
|
28193
|
-
surface: "tui",
|
|
28194
|
-
projectCount
|
|
25689
|
+
if ("object" === typeof type) switch ("number" === typeof type.tag && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), type.$$typeof) {
|
|
25690
|
+
case REACT_PORTAL_TYPE: return "Portal";
|
|
25691
|
+
case REACT_CONTEXT_TYPE: return type.displayName || "Context";
|
|
25692
|
+
case REACT_CONSUMER_TYPE: return (type._context.displayName || "Context") + ".Consumer";
|
|
25693
|
+
case REACT_FORWARD_REF_TYPE:
|
|
25694
|
+
var innerType = type.render;
|
|
25695
|
+
type = type.displayName;
|
|
25696
|
+
type || (type = innerType.displayName || innerType.name || "", type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef");
|
|
25697
|
+
return type;
|
|
25698
|
+
case REACT_MEMO_TYPE: return innerType = type.displayName || null, null !== innerType ? innerType : getComponentNameFromType(type.type) || "Memo";
|
|
25699
|
+
case REACT_LAZY_TYPE:
|
|
25700
|
+
innerType = type._payload;
|
|
25701
|
+
type = type._init;
|
|
25702
|
+
try {
|
|
25703
|
+
return getComponentNameFromType(type(innerType));
|
|
25704
|
+
} catch (x) {}
|
|
28195
25705
|
}
|
|
28196
|
-
|
|
28197
|
-
|
|
28198
|
-
|
|
28199
|
-
|
|
28200
|
-
|
|
28201
|
-
|
|
28202
|
-
|
|
28203
|
-
|
|
28204
|
-
|
|
28205
|
-
|
|
28206
|
-
|
|
28207
|
-
directory: projectScan.directory,
|
|
28208
|
-
reason: "max-duration"
|
|
28209
|
-
}
|
|
28210
|
-
};
|
|
25706
|
+
return null;
|
|
25707
|
+
}
|
|
25708
|
+
function testStringCoercion(value) {
|
|
25709
|
+
return "" + value;
|
|
25710
|
+
}
|
|
25711
|
+
function checkKeyStringCoercion(value) {
|
|
25712
|
+
try {
|
|
25713
|
+
testStringCoercion(value);
|
|
25714
|
+
var JSCompiler_inline_result = !1;
|
|
25715
|
+
} catch (e) {
|
|
25716
|
+
JSCompiler_inline_result = !0;
|
|
28211
25717
|
}
|
|
28212
|
-
|
|
28213
|
-
|
|
28214
|
-
|
|
28215
|
-
|
|
28216
|
-
|
|
28217
|
-
|
|
28218
|
-
|
|
28219
|
-
|
|
28220
|
-
|
|
28221
|
-
|
|
28222
|
-
|
|
28223
|
-
|
|
28224
|
-
|
|
28225
|
-
|
|
28226
|
-
|
|
28227
|
-
|
|
28228
|
-
|
|
28229
|
-
|
|
28230
|
-
|
|
28231
|
-
|
|
28232
|
-
|
|
28233
|
-
|
|
25718
|
+
if (JSCompiler_inline_result) {
|
|
25719
|
+
JSCompiler_inline_result = console;
|
|
25720
|
+
var JSCompiler_temp_const = JSCompiler_inline_result.error;
|
|
25721
|
+
var JSCompiler_inline_result$jscomp$0 = "function" === typeof Symbol && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
|
|
25722
|
+
JSCompiler_temp_const.call(JSCompiler_inline_result, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", JSCompiler_inline_result$jscomp$0);
|
|
25723
|
+
return testStringCoercion(value);
|
|
25724
|
+
}
|
|
25725
|
+
}
|
|
25726
|
+
function getTaskName(type) {
|
|
25727
|
+
if (type === REACT_FRAGMENT_TYPE) return "<>";
|
|
25728
|
+
if ("object" === typeof type && null !== type && type.$$typeof === REACT_LAZY_TYPE) return "<...>";
|
|
25729
|
+
try {
|
|
25730
|
+
var name = getComponentNameFromType(type);
|
|
25731
|
+
return name ? "<" + name + ">" : "<...>";
|
|
25732
|
+
} catch (x) {
|
|
25733
|
+
return "<...>";
|
|
25734
|
+
}
|
|
25735
|
+
}
|
|
25736
|
+
function getOwner() {
|
|
25737
|
+
var dispatcher = ReactSharedInternals.A;
|
|
25738
|
+
return null === dispatcher ? null : dispatcher.getOwner();
|
|
25739
|
+
}
|
|
25740
|
+
function UnknownOwner() {
|
|
25741
|
+
return Error("react-stack-top-frame");
|
|
25742
|
+
}
|
|
25743
|
+
function hasValidKey(config) {
|
|
25744
|
+
if (hasOwnProperty.call(config, "key")) {
|
|
25745
|
+
var getter = Object.getOwnPropertyDescriptor(config, "key").get;
|
|
25746
|
+
if (getter && getter.isReactWarning) return !1;
|
|
25747
|
+
}
|
|
25748
|
+
return void 0 !== config.key;
|
|
25749
|
+
}
|
|
25750
|
+
function defineKeyPropWarningGetter(props, displayName) {
|
|
25751
|
+
function warnAboutAccessingKey() {
|
|
25752
|
+
specialPropKeyWarningShown || (specialPropKeyWarningShown = !0, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", displayName));
|
|
25753
|
+
}
|
|
25754
|
+
warnAboutAccessingKey.isReactWarning = !0;
|
|
25755
|
+
Object.defineProperty(props, "key", {
|
|
25756
|
+
get: warnAboutAccessingKey,
|
|
25757
|
+
configurable: !0
|
|
28234
25758
|
});
|
|
28235
|
-
|
|
28236
|
-
|
|
28237
|
-
|
|
28238
|
-
|
|
28239
|
-
|
|
28240
|
-
|
|
28241
|
-
|
|
28242
|
-
|
|
28243
|
-
|
|
28244
|
-
|
|
25759
|
+
}
|
|
25760
|
+
function elementRefGetterWithDeprecationWarning() {
|
|
25761
|
+
var componentName = getComponentNameFromType(this.type);
|
|
25762
|
+
didWarnAboutElementRef[componentName] || (didWarnAboutElementRef[componentName] = !0, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."));
|
|
25763
|
+
componentName = this.props.ref;
|
|
25764
|
+
return void 0 !== componentName ? componentName : null;
|
|
25765
|
+
}
|
|
25766
|
+
function ReactElement(type, key, props, owner, debugStack, debugTask) {
|
|
25767
|
+
var refProp = props.ref;
|
|
25768
|
+
type = {
|
|
25769
|
+
$$typeof: REACT_ELEMENT_TYPE,
|
|
25770
|
+
type,
|
|
25771
|
+
key,
|
|
25772
|
+
props,
|
|
25773
|
+
_owner: owner
|
|
28245
25774
|
};
|
|
28246
|
-
|
|
28247
|
-
|
|
28248
|
-
|
|
28249
|
-
|
|
28250
|
-
|
|
28251
|
-
|
|
28252
|
-
if (skippedProjects.length > 0) recordCount(METRIC.scanProjectSkipped, skippedProjects.length, { reason: "max-duration" });
|
|
28253
|
-
const projectEntries = results.map(({ directory, result, config }) => {
|
|
28254
|
-
const reportSelection = selectReportDiagnostics({
|
|
28255
|
-
scan: {
|
|
28256
|
-
result,
|
|
28257
|
-
config
|
|
28258
|
-
},
|
|
28259
|
-
categoryFilters: input.options?.categoryFilters,
|
|
28260
|
-
surface: input.options?.outputSurface
|
|
25775
|
+
null !== (void 0 !== refProp ? refProp : null) ? Object.defineProperty(type, "ref", {
|
|
25776
|
+
enumerable: !1,
|
|
25777
|
+
get: elementRefGetterWithDeprecationWarning
|
|
25778
|
+
}) : Object.defineProperty(type, "ref", {
|
|
25779
|
+
enumerable: !1,
|
|
25780
|
+
value: null
|
|
28261
25781
|
});
|
|
28262
|
-
|
|
28263
|
-
|
|
28264
|
-
|
|
28265
|
-
|
|
28266
|
-
|
|
28267
|
-
|
|
28268
|
-
|
|
28269
|
-
|
|
28270
|
-
|
|
28271
|
-
|
|
28272
|
-
|
|
28273
|
-
|
|
28274
|
-
|
|
28275
|
-
|
|
28276
|
-
|
|
28277
|
-
|
|
28278
|
-
|
|
28279
|
-
|
|
28280
|
-
|
|
28281
|
-
|
|
28282
|
-
|
|
28283
|
-
|
|
28284
|
-
|
|
28285
|
-
|
|
28286
|
-
|
|
28287
|
-
|
|
28288
|
-
|
|
28289
|
-
|
|
28290
|
-
|
|
28291
|
-
|
|
28292
|
-
|
|
28293
|
-
|
|
28294
|
-
|
|
28295
|
-
|
|
28296
|
-
|
|
28297
|
-
|
|
28298
|
-
|
|
28299
|
-
|
|
28300
|
-
|
|
28301
|
-
|
|
28302
|
-
|
|
28303
|
-
|
|
28304
|
-
|
|
28305
|
-
|
|
28306
|
-
|
|
28307
|
-
|
|
28308
|
-
|
|
25782
|
+
type._store = {};
|
|
25783
|
+
Object.defineProperty(type._store, "validated", {
|
|
25784
|
+
configurable: !1,
|
|
25785
|
+
enumerable: !1,
|
|
25786
|
+
writable: !0,
|
|
25787
|
+
value: 0
|
|
25788
|
+
});
|
|
25789
|
+
Object.defineProperty(type, "_debugInfo", {
|
|
25790
|
+
configurable: !1,
|
|
25791
|
+
enumerable: !1,
|
|
25792
|
+
writable: !0,
|
|
25793
|
+
value: null
|
|
25794
|
+
});
|
|
25795
|
+
Object.defineProperty(type, "_debugStack", {
|
|
25796
|
+
configurable: !1,
|
|
25797
|
+
enumerable: !1,
|
|
25798
|
+
writable: !0,
|
|
25799
|
+
value: debugStack
|
|
25800
|
+
});
|
|
25801
|
+
Object.defineProperty(type, "_debugTask", {
|
|
25802
|
+
configurable: !1,
|
|
25803
|
+
enumerable: !1,
|
|
25804
|
+
writable: !0,
|
|
25805
|
+
value: debugTask
|
|
25806
|
+
});
|
|
25807
|
+
Object.freeze && (Object.freeze(type.props), Object.freeze(type));
|
|
25808
|
+
return type;
|
|
25809
|
+
}
|
|
25810
|
+
function jsxDEVImpl(type, config, maybeKey, isStaticChildren, debugStack, debugTask) {
|
|
25811
|
+
var children = config.children;
|
|
25812
|
+
if (void 0 !== children) if (isStaticChildren) if (isArrayImpl(children)) {
|
|
25813
|
+
for (isStaticChildren = 0; isStaticChildren < children.length; isStaticChildren++) validateChildKeys(children[isStaticChildren]);
|
|
25814
|
+
Object.freeze && Object.freeze(children);
|
|
25815
|
+
} else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
|
|
25816
|
+
else validateChildKeys(children);
|
|
25817
|
+
if (hasOwnProperty.call(config, "key")) {
|
|
25818
|
+
children = getComponentNameFromType(type);
|
|
25819
|
+
var keys = Object.keys(config).filter(function(k) {
|
|
25820
|
+
return "key" !== k;
|
|
25821
|
+
});
|
|
25822
|
+
isStaticChildren = 0 < keys.length ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" : "{key: someKey}";
|
|
25823
|
+
didWarnAboutKeySpread[children + isStaticChildren] || (keys = 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}", console.error("A props object containing a \"key\" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />", isStaticChildren, children, keys, children), didWarnAboutKeySpread[children + isStaticChildren] = !0);
|
|
25824
|
+
}
|
|
25825
|
+
children = null;
|
|
25826
|
+
void 0 !== maybeKey && (checkKeyStringCoercion(maybeKey), children = "" + maybeKey);
|
|
25827
|
+
hasValidKey(config) && (checkKeyStringCoercion(config.key), children = "" + config.key);
|
|
25828
|
+
if ("key" in config) {
|
|
25829
|
+
maybeKey = {};
|
|
25830
|
+
for (var propName in config) "key" !== propName && (maybeKey[propName] = config[propName]);
|
|
25831
|
+
} else maybeKey = config;
|
|
25832
|
+
children && defineKeyPropWarningGetter(maybeKey, "function" === typeof type ? type.displayName || type.name || "Unknown" : type);
|
|
25833
|
+
return ReactElement(type, children, maybeKey, getOwner(), debugStack, debugTask);
|
|
25834
|
+
}
|
|
25835
|
+
function validateChildKeys(node) {
|
|
25836
|
+
isValidElement(node) ? node._store && (node._store.validated = 1) : "object" === typeof node && null !== node && node.$$typeof === REACT_LAZY_TYPE && ("fulfilled" === node._payload.status ? isValidElement(node._payload.value) && node._payload.value._store && (node._payload.value._store.validated = 1) : node._store && (node._store.validated = 1));
|
|
25837
|
+
}
|
|
25838
|
+
function isValidElement(object) {
|
|
25839
|
+
return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
|
|
25840
|
+
}
|
|
25841
|
+
var React = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
|
|
25842
|
+
return null;
|
|
28309
25843
|
};
|
|
28310
|
-
|
|
28311
|
-
|
|
28312
|
-
|
|
28313
|
-
|
|
28314
|
-
|
|
28315
|
-
|
|
28316
|
-
|
|
28317
|
-
|
|
28318
|
-
|
|
25844
|
+
React = { react_stack_bottom_frame: function(callStackForError) {
|
|
25845
|
+
return callStackForError();
|
|
25846
|
+
} };
|
|
25847
|
+
var specialPropKeyWarningShown;
|
|
25848
|
+
var didWarnAboutElementRef = {};
|
|
25849
|
+
var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(React, UnknownOwner)();
|
|
25850
|
+
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
|
|
25851
|
+
var didWarnAboutKeySpread = {};
|
|
25852
|
+
exports.Fragment = REACT_FRAGMENT_TYPE;
|
|
25853
|
+
exports.jsx = function(type, config, maybeKey) {
|
|
25854
|
+
var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
|
|
25855
|
+
return jsxDEVImpl(type, config, maybeKey, !1, trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack, trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
|
|
28319
25856
|
};
|
|
28320
|
-
|
|
28321
|
-
|
|
28322
|
-
|
|
28323
|
-
|
|
28324
|
-
|
|
28325
|
-
|
|
28326
|
-
|
|
28327
|
-
|
|
28328
|
-
|
|
28329
|
-
|
|
28330
|
-
|
|
28331
|
-
|
|
28332
|
-
...input,
|
|
28333
|
-
options: {
|
|
28334
|
-
...input.options,
|
|
28335
|
-
deadlineEpochMs
|
|
28336
|
-
},
|
|
28337
|
-
configProjects: input.configProjects ?? scanTarget.userConfig?.projects,
|
|
28338
|
-
share: input.share ?? scanTarget.userConfig?.share ?? true
|
|
28339
|
-
};
|
|
28340
|
-
const selectedDirectories = await resolveSelectedDirectories(rootDirectory, resolvedInput);
|
|
28341
|
-
const inspectProject = createInvocationInspect(input.options?.concurrency);
|
|
28342
|
-
const blockingLevel = resolveBlockingLevel({ blocking: resolvedInput.blocking }, scanTarget.userConfig);
|
|
28343
|
-
if (selectedDirectories.length === 0) return { shouldFail: false };
|
|
28344
|
-
if (selectedDirectories.length === 1) return runSingleProjectScan(scanTarget, selectedDirectories[0], resolvedInput, scopePlan, blockingLevel, inspectProject);
|
|
28345
|
-
return runMultiProjectScan(scanTarget, selectedDirectories, resolvedInput, scopePlan, blockingLevel, inspectProject);
|
|
28346
|
-
};
|
|
25857
|
+
exports.jsxs = function(type, config, maybeKey) {
|
|
25858
|
+
var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
|
|
25859
|
+
return jsxDEVImpl(type, config, maybeKey, !0, trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack, trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
|
|
25860
|
+
};
|
|
25861
|
+
})();
|
|
25862
|
+
}));
|
|
25863
|
+
//#endregion
|
|
25864
|
+
//#region ../../node_modules/.pnpm/react@19.2.5/node_modules/react/jsx-runtime.js
|
|
25865
|
+
var require_jsx_runtime = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
25866
|
+
if (process.env.NODE_ENV === "production") module.exports = require_react_jsx_runtime_production();
|
|
25867
|
+
else module.exports = require_react_jsx_runtime_development();
|
|
25868
|
+
}));
|
|
28347
25869
|
//#endregion
|
|
28348
|
-
export {
|
|
25870
|
+
export { useExitOnCtrlC as a, Spinner as c, useInput as d, Transform as f, Box as h, import_react as i, useStdout as l, Text as m, registerMountedTuiRenderer as n, terminalSymbols as o, render as p, useStdoutDimensions as r, isPrintableInput as s, require_jsx_runtime as t, useApp as u };
|
|
28349
25871
|
|
|
28350
|
-
//# sourceMappingURL=
|
|
28351
|
-
//# debugId=
|
|
25872
|
+
//# sourceMappingURL=jsx-runtime-COe_zui7.js.map
|
|
25873
|
+
//# debugId=d7867bb3-5dd2-5798-b5dc-3fb046c80d68
|