react-doctor 0.9.12-dev.ffc2d14 → 0.9.13-dev.d030b11

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.
Files changed (47) hide show
  1. package/README.md +33 -0
  2. package/dist/active-run-trace-dlIZeEvb.js +18 -0
  3. package/dist/active-scan-abort-registry-DwG6tSPy.js +28 -0
  4. package/dist/{build-section-divider-BuOtLrzK.js → build-section-divider-Dhl7C8kp.js} +8 -22
  5. package/dist/{ci-DVVsf25h.js → ci-CPJtbXo4.js} +12 -11
  6. package/dist/cli.js +116 -35
  7. package/dist/{design-Y1pcA2uj.js → design-CI6oM-NB.js} +4 -4
  8. package/dist/{devtools-D8NTVj81.js → devtools-CC2PAZ85.js} +3 -3
  9. package/dist/{exit-gracefully-DnXGONjj.js → exit-gracefully-Zhbpfy2i.js} +15 -9
  10. package/dist/get-east-asian-width-Bv2TD3Xj.js +444 -0
  11. package/dist/{report-error-MGKyeIns.js → handle-error-LYTGcmFr.js} +18 -68
  12. package/dist/index.d.ts +32 -0
  13. package/dist/index.js +593 -286
  14. package/dist/{inspect-g3_lzs3l.js → inspect-BZ-i49rK.js} +38 -28
  15. package/dist/{install-02Lq6wKC.js → install-Cf-tjrbB.js} +9 -8
  16. package/dist/{install-doctor-script-DmEWQpVJ.js → install-doctor-script-BGdm_niA.js} +7 -449
  17. package/dist/{install-github-workflow-Dx6Pl9Wl.js → install-github-workflow-CwcDLQCy.js} +10 -6
  18. package/dist/{install-react-doctor-CMCXgenA.js → install-react-doctor-DcJ90NzQ.js} +8 -8
  19. package/dist/{run-scan-app-CDDu7P32.js → jsx-runtime-Cq-_Fvkx.js} +280 -2774
  20. package/dist/path-format-DnHpmJwG.js +9 -0
  21. package/dist/{print-branded-header-kbvWYuGv.js → print-branded-header-DM0JRJnn.js} +4 -4
  22. package/dist/project-analysis-worker.js +59 -54
  23. package/dist/prompt-runtime-scan-url-BpHApg0d.js +240 -0
  24. package/dist/{read-object-file-Cwhr9OIi.js → read-object-file-DMUSluLA.js} +4 -4
  25. package/dist/{record-metric-CFfsgcVs.js → record-metric-BRc98SXW.js} +556 -235
  26. package/dist/report-error-BpWTkd5U.js +64 -0
  27. package/dist/{report-workflow-result-DGg9xopH.js → report-workflow-result-DXSpYstq.js} +5 -5
  28. package/dist/{resolve-scope-CXS-5jLR.js → resolve-scope-CJXv5ePP.js} +8 -10
  29. package/dist/{rules-CThlosPx.js → rules-CZk5ywQe.js} +6 -6
  30. package/dist/run-scan-app-BtY0jXpd.js +2511 -0
  31. package/dist/runtime-scan/browser-probe.iife.js +855 -0
  32. package/dist/runtime-scan-iztAEKV3.js +770 -0
  33. package/dist/sanitize-runtime-url-DbrHDuC1.js +76 -0
  34. package/dist/scan-GPvogJT-.js +47 -0
  35. package/dist/{should-fail-scan-gate-C0Bo5Gqy.js → should-fail-scan-gate-Uk7rJiMQ.js} +20 -112
  36. package/dist/{should-skip-prompts-BqrtVX4G.js → should-skip-prompts-DzpvkZcL.js} +4 -4
  37. package/dist/should-use-tui-CH5oI2Vu.js +25 -0
  38. package/dist/skills/improve-threejs/SKILL.md +102 -0
  39. package/dist/skills/performance/SKILL.md +113 -0
  40. package/dist/skills/react-doctor/SKILL.md +6 -0
  41. package/dist/{unref-stdin-BxyvqsOy.js → telemetry-runtime-hAsPFFEx.js} +55 -25
  42. package/dist/unref-stdin-SK3WfwxS.js +12 -0
  43. package/dist/{version-S-8vvWFi.js → version-BiWDQQgs.js} +4 -4
  44. package/dist/{why-DXfx0oL9.js → why-B8sLOroq.js} +4 -4
  45. package/dist/with-run-span-BWmpgEhA.js +110 -0
  46. package/package.json +9 -6
  47. package/dist/scan-4I1mvxBO.js +0 -53
@@ -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]="b88a5d25-b8e7-56ca-b67f-96a6090df2dc")}catch(e){}}();
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]="bea2a0ad-0793-5fc6-aee8-6d1ffc663594")}catch(e){}}();
3
3
  import { i as __toESM, r as __require, t as __commonJSMin } from "./chunk-ChKA3wi6.js";
4
- import { B as isGitHookEnvironment, Gn as succeed, Gt as highlighter, Ht as hasPublishedFixRecipe, I as TUI_REPORT_COMPACT_MAX_ROWS, It as getBaselineDiffPlan, L as TUI_REPORT_DETAIL_WIDTH_FRACTION, Ln as runPromise, Lt as getChangedLineRanges, S as CI_TRUST_COMPANIES, Vn as void_, W as isCiEnvironment, _r as getCategoryImpact, bn as yieldToEventLoop, dn as resolveScanTarget, ht as buildRuleDocsUrl, ir as DIAGNOSTIC_CATEGORY_BUCKETS, it as Progress, n as recordDistribution, on as remainingDeadlineBudgetMs, ot as Reporter, qt as isPathInsideDirectory, rn as mapWithConcurrency, sr as GITHUB_ACTIONS_SETUP_URL, t as recordCount, vt as calculateScore, w as METRIC, zn as sync, zt as getDiffInfo } from "./record-metric-CFfsgcVs.js";
5
- import { n as registerActiveTuiRenderer, t as exitGracefully } from "./exit-gracefully-DnXGONjj.js";
6
- import { L as cliLogger, d as stripAnsi, f as isUnicodeSupported, l as isFullWidth$1, n as findNearestPackageDirectory, p as chalk, u as isWide$1 } from "./install-doctor-script-DmEWQpVJ.js";
7
- import { i as isReactDoctorWorkflowInstalled } from "./install-github-workflow-Dx6Pl9Wl.js";
8
- import { r as resolveScope, s as resolveBlockingLevel, t as finalizeScope, u as toForwardSlashes } from "./resolve-scope-CXS-5jLR.js";
9
- import { A as resolveMergeBaseRef, B as buildNoScoreMessage, C as copyToClipboard, D as deduplicateProjectScans, E as collectProjectSourceFileCounts, F as printFooter, G as formatFixRecipeLine, H as hasLintHardFailure, I as printDiagnosticsDump, K as formatLearnMoreLine, L as formatDiagnosticSite, M as pluralize, N as formatSkippedCheckLabel, O as createInvocationInspect, P as formatElapsedTime, R as hasIncompleteScoreAnalysis, S as CLI_AGENT_BINARIES, T as buildHandoffPayload, U as buildRulePriorityMap, V as buildEmptyReportMessage, W as buildSortedRuleGroups, _ 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 filterDiagnosticsByCategories } from "./should-fail-scan-gate-C0Bo5Gqy.js";
10
- import { a as recordGate, f as ONBOARDING_EVENT, n as openUrl, r as isGatePending } from "./report-workflow-result-DGg9xopH.js";
4
+ import { T as METRIC, t as recordCount } from "./record-metric-BRc98SXW.js";
5
+ import { n as registerActiveTuiRenderer, t as exitGracefully } from "./exit-gracefully-Zhbpfy2i.js";
6
+ import { a as chalk, i as stripAnsi, n as isFullWidth$1, r as isWide$1 } from "./get-east-asian-width-Bv2TD3Xj.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-D8NTVj81.js");
20443
+ if (isDevtoolsInstalled) await import("./devtools-CC2PAZ85.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$1 = "]";
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$1.charCodeAt(0);
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$1}8;`;
20960
+ const linkCodePrefix = `${ESC}${OSC}8;`;
20968
20961
  const linkCodePrefixCharCodes = linkCodePrefix.split("").map((char) => char.charCodeAt(0));
20969
- const linkEndCode = `${ESC}${OSC$1}8;;${BEL}`;
20970
- const linkEndCodeST = `${ESC}${OSC$1}8;;${ESC}${BACKSLASH}`;
20971
- const linkEndCodeC1ST = `${ESC}${OSC$1}8;;${C1_ST}`;
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,2118 +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 ReportStatus = ({ issueCount, emptyStateMessage, lintFailureReason, skippedChecks, incompleteMessage }) => {
25533
- const skippedCheckLabel = skippedChecks?.flatMap((skippedCheck) => skippedCheck === "lint" && lintFailureReason ? [] : [formatSkippedCheckLabel(skippedCheck)]).join(" and ");
25534
- const hasIncompleteResult = Boolean(incompleteMessage || lintFailureReason || skippedCheckLabel);
25535
- if (!hasIncompleteResult && issueCount > 0) return null;
25536
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
25537
- flexDirection: "column",
25538
- marginTop: 1,
25539
- children: [
25540
- incompleteMessage ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25541
- color: "yellow",
25542
- children: ["⚠ ", incompleteMessage]
25543
- }) : null,
25544
- lintFailureReason ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25545
- color: "yellow",
25546
- children: ["⚠ Lint did not run: ", lintFailureReason]
25547
- }) : null,
25548
- skippedCheckLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25549
- color: "yellow",
25550
- children: [
25551
- "⚠ ",
25552
- issueCount === 0 ? "No issues detected, but " : "",
25553
- skippedCheckLabel,
25554
- " checks failed — results are incomplete."
25555
- ]
25556
- }) : null,
25557
- issueCount === 0 && !hasIncompleteResult ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25558
- color: "green",
25559
- children: ["✔ ", emptyStateMessage ?? "No issues found. Nice work."]
25560
- }) : null
25561
- ]
25562
- });
25563
- };
25564
- const ReportLanding = ({ header, phase, issueCount, emptyStateMessage, lintFailureReason, skippedChecks, incompleteMessage, actions, selectedIndex, onSelectionChange, onQuit }) => {
25565
- const showScore = phase === "actions" || phase === "score";
25566
- useInput((input) => {
25567
- if (input === "q") onQuit();
25568
- }, { isActive: phase !== "actions" });
25569
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
25570
- flexDirection: "column",
25571
- children: [
25572
- showScore ? header : null,
25573
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReportStatus, {
25574
- issueCount,
25575
- emptyStateMessage,
25576
- lintFailureReason,
25577
- skippedChecks,
25578
- incompleteMessage
25579
- }),
25580
- phase === "actions" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ActionMenu, {
25581
- actions,
25582
- selectedIndex,
25583
- onSelectionChange,
25584
- onEscape: onQuit,
25585
- onQuit
25586
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
25587
- marginTop: 1,
25588
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25589
- dimColor: true,
25590
- children: actions.length === 0 ? "q quit" : "↑/↓ move · enter select · q quit"
25591
- })
25592
- })] }) : null
25593
- ]
25594
- });
25595
- };
25596
- //#endregion
25597
- //#region src/cli/ink/components/report-issue-stream.tsx
25598
- const ReportIssueStream = ({ rows, selectedIndex, width }) => {
25599
- const visibleRowCount = Math.min(rows.length, 3);
25600
- const visibleRows = Array.from({ length: visibleRowCount }, (_, visibleRowIndex) => {
25601
- const rowIndex = (selectedIndex - visibleRowCount + visibleRowIndex + 1 + rows.length) % rows.length;
25602
- return {
25603
- row: rows[rowIndex],
25604
- rowIndex
25605
- };
25606
- });
25607
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
25608
- flexDirection: "column",
25609
- width: Math.min(width, 60),
25610
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25611
- bold: true,
25612
- children: "Reviewing issues"
25613
- }), visibleRows.map(({ row, rowIndex }) => {
25614
- if (!row) return null;
25615
- const variant = severityVariant(row.severity);
25616
- const isSelected = rowIndex === selectedIndex;
25617
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25618
- dimColor: !isSelected,
25619
- wrap: "truncate-end",
25620
- children: [
25621
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25622
- color: isSelected ? variant.color : void 0,
25623
- children: [isSelected ? "›" : " ", " "]
25624
- }),
25625
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25626
- color: isSelected ? variant.color : void 0,
25627
- bold: isSelected,
25628
- children: [
25629
- row.category,
25630
- ": ",
25631
- row.title
25632
- ]
25633
- }),
25634
- row.siteCount > 1 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25635
- dimColor: true,
25636
- children: [" ×", row.siteCount]
25637
- }) : null
25638
- ]
25639
- }, row.ruleKey);
25640
- })]
25641
- });
25642
- };
25643
- //#endregion
25644
- //#region src/cli/utils/doctor-face.ts
25645
- const doctorFace = (score) => {
25646
- if (score >= 75) return ["◠ ◠", " ▽ "];
25647
- if (score >= 50) return ["• •", " ─ "];
25648
- return ["x x", " ▽ "];
25649
- };
25650
- //#endregion
25651
- //#region src/cli/utils/ease-out-cubic.ts
25652
- const easeOutCubic = (progress) => 1 - (1 - progress) ** 3;
25653
- //#endregion
25654
- //#region src/cli/ink/hooks/use-animated-score.ts
25655
- const useAnimatedScore = ({ score, projectedScore, shouldAnimate }) => {
25656
- const projectionTarget = projectedScore ?? score;
25657
- const hasProjection = projectionTarget > score;
25658
- const initialProjectedScore = !shouldAnimate && hasProjection ? projectionTarget : null;
25659
- const [displayScore, setDisplayScore] = (0, import_react.useState)(shouldAnimate ? 0 : score);
25660
- const [displayProjectedScore, setDisplayProjectedScore] = (0, import_react.useState)(initialProjectedScore);
25661
- (0, import_react.useEffect)(() => {
25662
- if (!shouldAnimate) {
25663
- setDisplayScore(score);
25664
- setDisplayProjectedScore(hasProjection ? projectionTarget : null);
25665
- return;
25666
- }
25667
- let timeoutId;
25668
- const runProjection = () => {
25669
- let projectionFrame = 1;
25670
- const renderProjectionFrame = () => {
25671
- const progress = easeOutCubic(projectionFrame / 16);
25672
- setDisplayProjectedScore(score + (projectionTarget - score) * progress);
25673
- if (projectionFrame < 16) {
25674
- projectionFrame += 1;
25675
- timeoutId = setTimeout(renderProjectionFrame, 35);
25676
- } else setDisplayProjectedScore(projectionTarget);
25677
- };
25678
- renderProjectionFrame();
25679
- };
25680
- let scoreFrame = 0;
25681
- const renderScoreFrame = () => {
25682
- const progress = easeOutCubic(scoreFrame / 40);
25683
- setDisplayScore(Math.round(score * progress));
25684
- if (scoreFrame < 40) {
25685
- scoreFrame += 1;
25686
- timeoutId = setTimeout(renderScoreFrame, 50);
25687
- return;
25688
- }
25689
- setDisplayScore(score);
25690
- if (hasProjection) runProjection();
25691
- };
25692
- renderScoreFrame();
25693
- return () => {
25694
- if (timeoutId !== void 0) clearTimeout(timeoutId);
25695
- };
25696
- }, [
25697
- shouldAnimate,
25698
- score,
25699
- projectionTarget,
25700
- hasProjection
25701
- ]);
25702
- return {
25703
- displayScore,
25704
- displayProjectedScore
25705
- };
25706
- };
25707
- //#endregion
25708
- //#region src/cli/ink/lib/score-color.ts
25709
- const scoreColorName = (score) => {
25710
- if (score >= 75) return "green";
25711
- if (score >= 50) return "yellow";
25712
- return "red";
25713
- };
25714
- //#endregion
25715
- //#region src/cli/ink/components/score-header.tsx
25716
- const REACT_DOCTOR_URL = "https://react.doctor";
25717
- const ReactDoctorLink = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TuiLink, {
25718
- url: REACT_DOCTOR_URL,
25719
- children: ["React Doctor ", /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25720
- dimColor: true,
25721
- children: [
25722
- "(",
25723
- REACT_DOCTOR_URL,
25724
- ")"
25725
- ]
25726
- })]
25727
- });
25728
- const ScoreHeader = ({ variant, score, projectedScore, projectName, issueCount, noScoreMessage, width }) => {
25729
- const { columns } = useStdoutDimensions();
25730
- const availableWidth = width ?? columns;
25731
- const { stdout } = useStdout();
25732
- const shouldAnimateScore = canAnimateOnboarding(stdout ?? void 0);
25733
- const visibleProjectedScore = variant === "landing" ? projectedScore : null;
25734
- const { displayScore, displayProjectedScore } = useAnimatedScore({
25735
- score: score?.score ?? 0,
25736
- projectedScore: visibleProjectedScore,
25737
- shouldAnimate: variant === "landing" && shouldAnimateScore && score !== null
25738
- });
25739
- if (!score) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
25740
- flexDirection: "column",
25741
- paddingLeft: 2,
25742
- width: availableWidth,
25743
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25744
- wrap: "truncate-end",
25745
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReactDoctorLink, {})
25746
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25747
- dimColor: true,
25748
- wrap: "wrap",
25749
- children: noScoreMessage ?? `${pluralize(issueCount, "finding")} · ${projectName}`
25750
- })]
25751
- });
25752
- const scoreColor = scoreColorName(score.score);
25753
- const scoreSummaryLine = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25754
- wrap: "truncate-end",
25755
- children: [
25756
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25757
- color: scoreColor,
25758
- bold: true,
25759
- children: displayScore
25760
- }),
25761
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25762
- dimColor: true,
25763
- children: [
25764
- " / ",
25765
- 100,
25766
- " "
25767
- ]
25768
- }),
25769
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25770
- color: scoreColor,
25771
- children: score.label
25772
- }),
25773
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25774
- dimColor: true,
25775
- children: [" · ", projectName]
25776
- })
25777
- ]
25778
- });
25779
- if (availableWidth < 23) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
25780
- flexDirection: "column",
25781
- width: availableWidth,
25782
- children: [scoreSummaryLine, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25783
- wrap: "truncate-end",
25784
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReactDoctorLink, {})
25785
- })]
25786
- });
25787
- const barWidth = Math.max(10, Math.min(50, availableWidth - 11 - 2));
25788
- const filledBarWidth = Math.round(displayScore / 100 * barWidth);
25789
- const projectedBarWidth = displayProjectedScore != null ? Math.min(barWidth, Math.round(displayProjectedScore / 100 * barWidth)) : filledBarWidth;
25790
- const projectedGainWidth = Math.max(0, projectedBarWidth - filledBarWidth);
25791
- const emptyBarWidth = Math.max(0, barWidth - filledBarWidth - projectedGainWidth);
25792
- const [eyes, mouth] = doctorFace(score.score);
25793
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
25794
- flexDirection: "column",
25795
- width: availableWidth,
25796
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
25797
- paddingLeft: 2,
25798
- width: availableWidth,
25799
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
25800
- flexDirection: "column",
25801
- flexShrink: 0,
25802
- width: 7,
25803
- marginRight: 2,
25804
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25805
- color: scoreColor,
25806
- children: `┌─────┐\n│ ${eyes} │\n│ ${mouth} │\n└─────┘`
25807
- })
25808
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
25809
- flexDirection: "column",
25810
- width: availableWidth - 11,
25811
- children: [
25812
- scoreSummaryLine,
25813
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25814
- wrap: "truncate-end",
25815
- children: [
25816
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25817
- color: scoreColor,
25818
- children: "█".repeat(filledBarWidth)
25819
- }),
25820
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25821
- color: scoreColor,
25822
- dimColor: true,
25823
- children: "▓".repeat(projectedGainWidth)
25824
- }),
25825
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25826
- dimColor: true,
25827
- children: "░".repeat(emptyBarWidth)
25828
- })
25829
- ]
25830
- }),
25831
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25832
- wrap: "truncate-end",
25833
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReactDoctorLink, {})
25834
- }),
25835
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: " " })
25836
- ]
25837
- })]
25838
- }), variant === "landing" && projectedScore != null && projectedScore > score.score ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25839
- wrap: "truncate-end",
25840
- children: [
25841
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25842
- dimColor: true,
25843
- children: " Potential score "
25844
- }),
25845
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25846
- color: scoreColorName(projectedScore),
25847
- children: projectedScore
25848
- }),
25849
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
25850
- dimColor: true,
25851
- children: " after priority fixes "
25852
- }),
25853
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
25854
- color: scoreColorName(projectedScore),
25855
- children: ["+", projectedScore - score.score]
25856
- })
25857
- ]
25858
- }) : null]
25859
- });
25860
- };
25861
- //#endregion
25862
- //#region src/cli/ink/components/report.tsx
25863
- const EMPTY_LAUNCHABLE_AGENTS = [];
25864
- const recordReportAction = (action) => {
25865
- recordCount(METRIC.tuiReportActionSelected, 1, { action });
25866
- };
25867
- const completeReportOnboarding = () => {
25868
- if (shouldRecordOnboarding({
25869
- paceOnboardingSections: true,
25870
- forceOnboarding: isOnboardingForced(),
25871
- verbose: false,
25872
- isNonInteractiveEnvironment: false
25873
- })) markOnboardingComplete();
25874
- };
25875
- const Report = ({ report, onExit, onQuit = onExit, launchableAgents = EMPTY_LAUNCHABLE_AGENTS, onHandoff, canAddToCi, onAddToCi, projectCount, priorityScores, exitHint = "q to quit" }) => {
25876
- const { rows: terminalRows, columns } = useStdoutDimensions();
25877
- const diagnosticRows = (0, import_react.useMemo)(() => buildDiagnosticRows(report.diagnostics, priorityScores ?? [report.score]), [
25878
- report.diagnostics,
25879
- report.score,
25880
- priorityScores
25881
- ]);
25882
- const diagnosticListEntries = (0, import_react.useMemo)(() => buildDiagnosticListEntries(diagnosticRows), [diagnosticRows]);
25883
- const reportLayout = resolveReportLayout({
25884
- columns,
25885
- diagnosticEntryCount: diagnosticListEntries.length,
25886
- terminalRows
25887
- });
25888
- const reportReveal = useReportReveal({
25889
- issueCount: diagnosticRows.length,
25890
- onRevealComplete: completeReportOnboarding
25891
- });
25892
- const [activeReportScreen, setActiveReportScreen] = (0, import_react.useState)("landing");
25893
- const [ciSetupFeedback, setCiSetupFeedback] = (0, import_react.useState)();
25894
- const [landingSelectedIndex, setLandingSelectedIndex] = (0, import_react.useState)(0);
25895
- const [viewerSelectedRowIndex, setViewerSelectedRowIndex] = (0, import_react.useState)(null);
25896
- const [viewerReadRuleKeys, setViewerReadRuleKeys] = (0, import_react.useState)(() => /* @__PURE__ */ new Set());
25897
- const [isCiSetupQueued, setIsCiSetupQueued] = (0, import_react.useState)(false);
25898
- const [shouldShowIssueStream, setShouldShowIssueStream] = (0, import_react.useState)(true);
25899
- const didRecordCompactReport = (0, import_react.useRef)(false);
25900
- const didRecordIssueStream = (0, import_react.useRef)(false);
25901
- const didRecordStackedReportCap = (0, import_react.useRef)(false);
25902
- const isCompact = reportLayout.layout === "compact";
25903
- const isWide = reportLayout.layout === "split";
25904
- (0, import_react.useEffect)(() => {
25905
- if (!isCompact || didRecordCompactReport.current) return;
25906
- didRecordCompactReport.current = true;
25907
- recordCount(METRIC.tuiCompactReportShown);
25908
- }, [isCompact]);
25909
- (0, import_react.useEffect)(() => {
25910
- if (!reportLayout.isStackedReportCapped || didRecordStackedReportCap.current) return;
25911
- didRecordStackedReportCap.current = true;
25912
- recordCount(METRIC.tuiStackedReportCapped);
25913
- }, [reportLayout.isStackedReportCapped]);
25914
- (0, import_react.useEffect)(() => {
25915
- if (reportReveal.phase !== "streaming" || didRecordIssueStream.current) return;
25916
- didRecordIssueStream.current = true;
25917
- recordCount(METRIC.tuiIssueStreamShown);
25918
- }, [reportReveal.phase]);
25919
- const scoreHeaderProps = {
25920
- score: report.score,
25921
- projectedScore: report.projectedScore,
25922
- projectName: report.projectName,
25923
- issueCount: report.diagnostics.length,
25924
- noScoreMessage: report.noScoreMessage,
25925
- width: isWide ? reportLayout.listColumnWidth : reportLayout.width
25926
- };
25927
- const isCiSetupAvailable = Boolean(canAddToCi && onAddToCi && !isCiSetupQueued);
25928
- const isHandoffAvailable = diagnosticRows.length > 0 && Boolean(onHandoff);
25929
- const completeHandoff = (destination) => {
25930
- if (!onHandoff) return;
25931
- onHandoff({
25932
- destination,
25933
- prompt: buildHandoffPayload({
25934
- diagnostics: report.diagnostics,
25935
- projectName: report.projectName
25936
- })
25937
- });
25938
- onExit();
25939
- };
25940
- const firstDiagnosticEntry = diagnosticListEntries.find((entry) => entry.kind === "item");
25941
- const resolvedViewerSelectedRowIndex = viewerSelectedRowIndex ?? (firstDiagnosticEntry?.kind === "item" ? firstDiagnosticEntry.rowIndex : null);
25942
- const markViewerRuleRead = (index) => {
25943
- const ruleKey = diagnosticRows[index]?.ruleKey;
25944
- if (!ruleKey) return;
25945
- setViewerReadRuleKeys((previous) => previous.has(ruleKey) ? previous : new Set(previous).add(ruleKey));
25946
- };
25947
- const handleViewerSelectionChange = (index) => {
25948
- setViewerSelectedRowIndex(index);
25949
- markViewerRuleRead(index);
25950
- };
25951
- const openReportScreen = (nextScreen) => {
25952
- setShouldShowIssueStream(false);
25953
- setCiSetupFeedback(void 0);
25954
- setActiveReportScreen(nextScreen);
25955
- };
25956
- const landingActions = [];
25957
- if (report.diagnostics.length > 0) landingActions.push({
25958
- id: "view-issues",
25959
- label: `Review ${pluralize(diagnosticRows.length, "issue")}`,
25960
- onSelect: () => {
25961
- recordReportAction("view-issues");
25962
- if (resolvedViewerSelectedRowIndex !== null) {
25963
- setViewerSelectedRowIndex(resolvedViewerSelectedRowIndex);
25964
- markViewerRuleRead(resolvedViewerSelectedRowIndex);
25965
- }
25966
- openReportScreen("issues");
25967
- }
25968
- });
25969
- if (isCiSetupAvailable) landingActions.push({
25970
- id: "add-to-ci",
25971
- label: "Add to GitHub Actions (Recommended)",
25972
- description: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CiJustification, {}),
25973
- onSelect: () => {
25974
- recordReportAction("add-to-ci");
25975
- openReportScreen("ci");
25976
- }
25977
- });
25978
- if (isHandoffAvailable) landingActions.push({
25979
- id: "handoff",
25980
- label: "Hand off to an agent",
25981
- onSelect: () => {
25982
- recordReportAction("handoff");
25983
- openReportScreen(isCiSetupAvailable ? "handoff-ci" : "handoff");
25984
- }
25985
- });
25986
- const postReviewLandingActionIndex = landingActions.findIndex((action) => action.id !== "view-issues");
25987
- const resolvedLandingSelectedIndex = Math.min(landingSelectedIndex, Math.max(0, landingActions.length - 1));
25988
- const issueStream = reportReveal.phase === "streaming" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReportIssueStream, {
25989
- rows: diagnosticRows,
25990
- selectedIndex: reportReveal.streamSelectedIndex,
25991
- width: reportLayout.width
25992
- }) : null;
25993
- const screenContent = {
25994
- ci: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CiSetup, {
25995
- feedback: ciSetupFeedback,
25996
- onConfirm: () => {
25997
- onAddToCi?.();
25998
- onExit();
25999
- },
26000
- onLearnMore: () => {
26001
- recordReportAction("ci-learn-more");
26002
- openUrl(GITHUB_ACTIONS_SETUP_URL).then((didOpen) => {
26003
- setCiSetupFeedback({
26004
- didSucceed: didOpen,
26005
- message: didOpen ? "✓ Opened the GitHub Actions guide in your browser" : `Couldn't open a browser. Visit ${GITHUB_ACTIONS_SETUP_URL}`
26006
- });
26007
- });
26008
- },
26009
- onBack: () => {
26010
- setCiSetupFeedback(void 0);
26011
- setActiveReportScreen("landing");
26012
- },
26013
- onQuit
26014
- }),
26015
- handoff: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentHandoff, {
26016
- agents: launchableAgents,
26017
- onSelect: completeHandoff,
26018
- onCopyPrompt: () => completeHandoff("clipboard"),
26019
- onBack: () => setActiveReportScreen("landing"),
26020
- onQuit
26021
- }),
26022
- "handoff-ci": /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HandoffCiRecommendation, {
26023
- onAddToCi: () => {
26024
- onAddToCi?.();
26025
- setIsCiSetupQueued(true);
26026
- setActiveReportScreen("handoff");
26027
- },
26028
- onContinue: () => setActiveReportScreen("handoff"),
26029
- onQuit
26030
- }),
26031
- landing: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReportLanding, {
26032
- header: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScoreHeader, {
26033
- variant: "landing",
26034
- ...scoreHeaderProps
26035
- }),
26036
- phase: reportReveal.phase,
26037
- issueCount: report.diagnostics.length,
26038
- emptyStateMessage: report.emptyStateMessage,
26039
- lintFailureReason: report.lintFailureReason,
26040
- skippedChecks: report.skippedChecks,
26041
- incompleteMessage: report.incompleteMessage,
26042
- actions: landingActions,
26043
- selectedIndex: resolvedLandingSelectedIndex,
26044
- onSelectionChange: setLandingSelectedIndex,
26045
- onQuit
26046
- }),
26047
- issues: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DiagnosticList, {
26048
- header: reportLayout.showsViewerScoreHeader ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScoreHeader, {
26049
- variant: "viewer",
26050
- ...scoreHeaderProps
26051
- }) : null,
26052
- rows: diagnosticRows,
26053
- entries: diagnosticListEntries,
26054
- width: reportLayout.width,
26055
- listColumnWidth: reportLayout.listColumnWidth,
26056
- detailColumnWidth: reportLayout.detailColumnWidth,
26057
- listHeight: reportLayout.listHeight,
26058
- detailHeight: reportLayout.detailHeight,
26059
- layout: reportLayout.layout,
26060
- rootDirectory: report.rootDirectory,
26061
- projectName: report.projectName,
26062
- projectCount,
26063
- initialSelectedRowIndex: resolvedViewerSelectedRowIndex,
26064
- readRuleKeys: viewerReadRuleKeys,
26065
- onSelectedRowIndexChange: handleViewerSelectionChange,
26066
- onQuit,
26067
- onBack: () => {
26068
- setLandingSelectedIndex(Math.max(0, postReviewLandingActionIndex));
26069
- setActiveReportScreen("landing");
26070
- },
26071
- exitHint: `esc back · ${exitHint}`
26072
- })
26073
- };
26074
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [activeReportScreen === "landing" && shouldShowIssueStream ? issueStream : null, screenContent[activeReportScreen]] });
26075
- };
26076
- //#endregion
26077
23958
  //#region ../../node_modules/.pnpm/cli-spinners@2.9.2/node_modules/cli-spinners/spinners.json
26078
23959
  var require_spinners = /* @__PURE__ */ __commonJSMin(((exports, module) => {
26079
23960
  module.exports = {
@@ -27686,232 +25567,52 @@ function Spinner({ type = "dots" }) {
27686
25567
  return import_react.createElement(Text, null, spinner.frames[frame]);
27687
25568
  }
27688
25569
  //#endregion
27689
- //#region src/cli/ink/components/scanning.tsx
27690
- const Scanning = ({ progressText, recent }) => {
27691
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
27692
- flexDirection: "column",
27693
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
27694
- wrap: "truncate-end",
27695
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
27696
- color: "cyan",
27697
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { type: "dots" })
27698
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [" ", progressText ?? "Scanning…"] })]
27699
- }), recent.map((diagnostic, diagnosticIndex) => {
27700
- const variant = severityVariant(diagnostic.severity === "error" ? "error" : "warning");
27701
- const location = formatDiagnosticSite(diagnostic);
27702
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
27703
- wrap: "truncate-end",
27704
- children: [
27705
- " ",
27706
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
27707
- color: variant.color,
27708
- children: variant.icon
27709
- }),
27710
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { children: [" ", diagnostic.title ?? `${diagnostic.plugin}/${diagnostic.rule}`] }),
27711
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
27712
- dimColor: true,
27713
- children: [" ", location]
27714
- })
27715
- ]
27716
- }, `${diagnostic.filePath}:${diagnostic.line}:${diagnostic.column}:${diagnostic.plugin}:${diagnostic.rule}:${diagnosticIndex}`);
27717
- })]
27718
- });
27719
- };
25570
+ //#region src/cli/utils/is-printable-input.ts
25571
+ const isPrintableInput = (input) => input.length > 0 && [...input].every((character) => character.charCodeAt(0) >= 32);
27720
25572
  //#endregion
27721
- //#region src/cli/ink/components/summary.tsx
27722
- const Summary = ({ summary, onExit, onQuit, launchableAgents, onHandoff, canAddToCi, onAddToCi }) => {
27723
- const skippedProjects = summary.skippedProjects ?? [];
27724
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Report, {
27725
- report: {
27726
- diagnostics: summary.combinedDiagnostics,
27727
- score: summary.aggregateScore,
27728
- projectedScore: summary.projectedScore,
27729
- projectName: summary.projectName,
27730
- rootDirectory: summary.rootDirectory,
27731
- scannedFileCount: summary.scannedFileCount,
27732
- elapsedMilliseconds: summary.elapsedMilliseconds,
27733
- isOffline: summary.isOffline,
27734
- noScoreMessage: summary.noScoreMessage,
27735
- skippedChecks: [...new Set(summary.projects.flatMap((project) => project.skippedChecks ?? []))],
27736
- ...skippedProjects.length > 0 ? { incompleteMessage: formatSkippedProjectsMessage(skippedProjects.length) } : {},
27737
- ...summary.emptyStateMessage ? { emptyStateMessage: summary.emptyStateMessage } : {},
27738
- ...summary.lintFailureReason ? { lintFailureReason: summary.lintFailureReason } : {}
27739
- },
27740
- onExit,
27741
- onQuit,
27742
- launchableAgents,
27743
- onHandoff,
27744
- canAddToCi,
27745
- onAddToCi,
27746
- projectCount: summary.projects.length + skippedProjects.length,
27747
- priorityScores: summary.projects.map((project) => project.score)
27748
- });
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 ? "◯" : "( )"
27749
25580
  };
27750
25581
  //#endregion
27751
- //#region src/cli/ink/hooks/use-scan-store.ts
27752
- const useScanStore = (store) => (0, import_react.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
27753
- //#endregion
27754
- //#region src/cli/ink/scan-app.tsx
27755
- const ScanApp = ({ store, displayMode = "report", launchableAgents, onHandoff, canAddToCi, onAddToCi, onQuit }) => {
27756
- const snapshot = useScanStore(store);
27757
- const { exit } = useApp();
27758
- useExitOnCtrlC(onQuit);
27759
- const handleQuit = () => {
27760
- onQuit?.();
27761
- exit();
27762
- };
27763
- if (displayMode === "report" && snapshot.phase === "summary") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Summary, {
27764
- summary: snapshot.summary,
27765
- launchableAgents,
27766
- onHandoff,
27767
- canAddToCi,
27768
- onAddToCi,
27769
- onExit: exit,
27770
- onQuit: handleQuit
27771
- });
27772
- if (displayMode === "report" && snapshot.phase === "report") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Report, {
27773
- report: snapshot.report,
27774
- launchableAgents,
27775
- onHandoff,
27776
- canAddToCi,
27777
- onAddToCi,
27778
- onExit: exit,
27779
- onQuit: handleQuit
27780
- });
27781
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Scanning, {
27782
- progressText: snapshot.progress,
27783
- 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
+ }
27784
25593
  });
27785
25594
  };
27786
25595
  //#endregion
27787
- //#region src/cli/ink/scan-bridge-layers.ts
27788
- const reporterLayerForStore = (store) => succeed(Reporter, Reporter.of({
27789
- emit: (diagnostic) => sync(() => store.emitDiagnostic(diagnostic)),
27790
- finalize: void_
27791
- }));
27792
- const progressHandleForStore = (store, options = {}) => (text) => {
27793
- const transformText = options.transformText ?? ((displayText) => displayText);
27794
- store.setProgress(transformText(text));
27795
- return {
27796
- update: (displayText) => sync(() => store.scheduleProgress(transformText(displayText))),
27797
- succeed: (displayText) => sync(() => store.setProgress(transformText(displayText))),
27798
- fail: (displayText) => sync(() => store.setProgress(transformText(displayText))),
27799
- stop: () => sync(() => store.setProgress(options.shouldClearOnStop === false ? transformText(text) : null))
27800
- };
27801
- };
27802
- const progressLayerForStore = (store, options = {}) => Progress.layerOra(progressHandleForStore(store, options));
27803
- //#endregion
27804
- //#region src/cli/ink/scan-store.ts
27805
- const INITIAL_SNAPSHOT = {
27806
- phase: "scanning",
27807
- liveDiagnostics: [],
27808
- progress: null
27809
- };
27810
- const createScanStore = () => {
27811
- let snapshot = INITIAL_SNAPSHOT;
27812
- const listeners = /* @__PURE__ */ new Set();
27813
- let pendingProgress = null;
27814
- let progressTimer = null;
27815
- const commit = (next) => {
27816
- snapshot = next;
27817
- for (const listener of [...listeners]) listener();
27818
- };
27819
- const cancelPendingProgress = () => {
27820
- pendingProgress = null;
27821
- if (progressTimer === null) return;
27822
- clearTimeout(progressTimer);
27823
- progressTimer = null;
27824
- };
27825
- const setProgress = (progress) => {
27826
- cancelPendingProgress();
27827
- commit({
27828
- ...snapshot,
27829
- progress
27830
- });
27831
- };
27832
- return {
27833
- subscribe: (listener) => {
27834
- listeners.add(listener);
27835
- return () => {
27836
- listeners.delete(listener);
27837
- };
27838
- },
27839
- getSnapshot: () => snapshot,
27840
- emitDiagnostic: (diagnostic) => commit({
27841
- ...snapshot,
27842
- liveDiagnostics: [...snapshot.liveDiagnostics, diagnostic].slice(-25)
27843
- }),
27844
- scheduleProgress: (progress) => {
27845
- pendingProgress = progress;
27846
- if (progressTimer !== null) return;
27847
- progressTimer = setTimeout(() => {
27848
- progressTimer = null;
27849
- const progressToCommit = pendingProgress;
27850
- pendingProgress = null;
27851
- if (progressToCommit !== null) commit({
27852
- ...snapshot,
27853
- progress: progressToCommit
27854
- });
27855
- }, 250);
27856
- progressTimer.unref?.();
27857
- },
27858
- setProgress,
27859
- setReport: (report) => {
27860
- cancelPendingProgress();
27861
- commit({
27862
- phase: "report",
27863
- liveDiagnostics: snapshot.liveDiagnostics,
27864
- progress: snapshot.progress,
27865
- report
27866
- });
27867
- },
27868
- setSummary: (summary) => {
27869
- cancelPendingProgress();
27870
- commit({
27871
- phase: "summary",
27872
- liveDiagnostics: snapshot.liveDiagnostics,
27873
- progress: snapshot.progress,
27874
- summary
27875
- });
27876
- }
27877
- };
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;
27878
25613
  };
27879
25614
  //#endregion
27880
- //#region src/cli/ink/run-scan-app.tsx
27881
- const qualifyDiagnosticPaths = (diagnostics, rootDirectory, projectDirectory) => {
27882
- const prefix = path.relative(rootDirectory, projectDirectory);
27883
- if (prefix === "" || prefix.startsWith("..")) return [...diagnostics];
27884
- return diagnostics.map((diagnostic) => path.isAbsolute(diagnostic.filePath) ? diagnostic : {
27885
- ...diagnostic,
27886
- filePath: toForwardSlashes(path.join(prefix, diagnostic.filePath))
27887
- });
27888
- };
27889
- const resolveScanPresentation = (input, projectScans) => {
27890
- const isScoreDisabled = input.options?.noScore === true || projectScans.some((projectScan) => projectScan.config?.noScore === true);
27891
- return {
27892
- isOffline: isCiEnvironment() || input.share === false || isShareOptedOut(projectScans, input.options?.noScore),
27893
- initialProgress: projectScans.length > 1 ? "Indexing workspace files…" : "Scanning project…",
27894
- noScoreMessage: buildNoScoreMessage({ isScoreDisabled }),
27895
- outputDirectory: input.options?.outputDirectory,
27896
- shouldRecommendCi: projectScans.length > 1 || projectScans.some((projectScan) => isCiUnconfigured(projectScan.directory)),
27897
- verbose: input.options?.verbose === true
27898
- };
27899
- };
27900
- const resolveTuiInspectOptions = (input, config) => {
27901
- const warnings = resolveCliInspectOptions({
27902
- blocking: input.blocking,
27903
- warnings: input.options?.warnings
27904
- }, config).warnings;
27905
- return warnings === void 0 ? { ...input.options } : {
27906
- ...input.options,
27907
- warnings
27908
- };
27909
- };
27910
- const resolveSelectedDirectories = async (rootDirectory, input) => {
27911
- const packages = discoverWorkspacePackages(rootDirectory);
27912
- 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);
27913
- return promptProjectSelection(packages, rootDirectory);
27914
- };
25615
+ //#region src/cli/ink/register-mounted-tui-renderer.ts
27915
25616
  const registerMountedTuiRenderer = (instance) => {
27916
25617
  let didDisposeRenderer = false;
27917
25618
  const disposeRenderer = (shouldClearOutput) => {
@@ -27926,442 +25627,247 @@ const registerMountedTuiRenderer = (instance) => {
27926
25627
  disposeRenderer(true);
27927
25628
  };
27928
25629
  };
27929
- const promptProjectSelection = (packages, rootDirectory) => new Promise((resolve) => {
27930
- let disposeRenderer = () => {};
27931
- recordCount(METRIC.tuiProjectSelectShown);
27932
- disposeRenderer = registerMountedTuiRenderer(render(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectSelect, {
27933
- packages,
27934
- rootDirectory,
27935
- onSubmit: (directories) => {
27936
- disposeRenderer();
27937
- resolve(directories);
27938
- }
27939
- }), {
27940
- alternateScreen: true,
27941
- exitOnCtrlC: false
27942
- }));
27943
- });
27944
- const resolveLintFailureReason = (results) => {
27945
- for (const result of results) {
27946
- if (!hasLintHardFailure(result)) continue;
27947
- return result.skippedCheckReasons?.lint ?? "Lint failed before diagnostics were produced.";
27948
- }
27949
- return null;
27950
- };
27951
- const toScanReport = ({ result, diagnostics, rootDirectory, projectedScore, isOffline, noScoreMessage, emptyStateMessage }) => {
27952
- const lintFailureReason = resolveLintFailureReason([result]);
27953
- return {
27954
- diagnostics: diagnostics ?? result.diagnostics,
27955
- score: result.score,
27956
- projectedScore,
27957
- projectName: result.project.projectName,
27958
- rootDirectory,
27959
- scannedFileCount: result.scannedFileCount ?? 0,
27960
- elapsedMilliseconds: result.elapsedMilliseconds,
27961
- isOffline,
27962
- noScoreMessage,
27963
- emptyStateMessage,
27964
- skippedChecks: result.skippedChecks,
27965
- ...lintFailureReason ? { lintFailureReason } : {}
27966
- };
27967
- };
27968
- const findLowestScoredReport = (reports) => {
27969
- let lowestScoredReport = null;
27970
- for (const report of reports) {
27971
- if (report.score === null) continue;
27972
- if (lowestScoredReport === null || report.score.score < lowestScoredReport.score.score) lowestScoredReport = {
27973
- score: report.score,
27974
- scoreDiagnostics: report.scoreDiagnostics
27975
- };
27976
- }
27977
- return lowestScoredReport;
27978
- };
27979
- const resolveEmptyStateMessage = (input, demotedDiagnosticCount) => buildEmptyReportMessage({
27980
- categoryFilters: input.options?.categoryFilters ?? [],
27981
- demotedDiagnosticCount,
27982
- outputSurface: input.options?.outputSurface ?? "cli"
27983
- });
27984
- const printExitFooter = async (input) => {
27985
- process.stdout.write(`${highlighter.success("✔")} Scanned ${pluralize(input.scannedFileCount, "file")} in ${formatElapsedTime(input.elapsedMilliseconds)}\n`);
27986
- if (input.lintFailureReason !== null) process.stdout.write(`${highlighter.warn("⚠")} Lint did not run: ${input.lintFailureReason}\n`);
27987
- await runPromise(printFooter({
27988
- diagnostics: [...input.diagnostics],
27989
- scoreResult: input.scoreResult,
27990
- projectName: input.projectName,
27991
- isOffline: input.isOffline
27992
- }));
27993
- };
27994
- const performTuiHandoff = async (request, rootDirectory) => {
27995
- let failureMessage = null;
27996
- if (request.destination === "clipboard") {
27997
- const didCopy = await copyToClipboard(request.prompt);
27998
- recordCount(METRIC.agentHandoff, 1, {
27999
- outcome: "clipboard",
28000
- source: "tui",
28001
- copied: didCopy
28002
- });
28003
- if (didCopy) {
28004
- process.stdout.write(`${highlighter.success("✔")} Copied the prompt to your clipboard.\n`);
28005
- return;
28006
- }
28007
- failureMessage = "Couldn't access the clipboard. Here's the prompt instead:";
28008
- } else try {
28009
- await launchCliAgent(request.destination, request.prompt, rootDirectory);
28010
- return;
28011
- } catch {
28012
- failureMessage = `Couldn't launch ${CLI_AGENT_BINARIES[request.destination]}. Here's the prompt instead:`;
28013
- }
28014
- process.stdout.write(`${highlighter.warn("⚠")} ${failureMessage}\n`);
28015
- process.stdout.write(`${highlighter.dim("──── Agent prompt ────")}\n`);
28016
- process.stdout.write(`${request.prompt}\n`);
28017
- process.stdout.write(`${highlighter.dim("──────────────────────")}\n`);
28018
- };
28019
- const isCiUnconfigured = (directory) => !isReactDoctorWorkflowInstalled(findNearestPackageDirectory(directory) ?? directory);
28020
- const performCiSetup = async (rootDirectory) => {
28021
- const didCreateWorkflow = await setUpGitHubActions({ rootDirectory });
28022
- recordCount(METRIC.agentHandoff, 1, {
28023
- outcome: "ci-yes",
28024
- source: "tui",
28025
- created: didCreateWorkflow
28026
- });
28027
- };
28028
- const mountScanApp = async (rootDirectory, shouldRecommendCi, initialProgress) => {
28029
- const store = createScanStore();
28030
- store.setProgress(initialProgress);
28031
- const launchableAgents = await detectLaunchableAgents();
28032
- const pendingActions = {
28033
- handoffRequest: null,
28034
- shouldSetUpCi: false,
28035
- didQuit: false
28036
- };
28037
- const mountRenderer = (displayMode) => {
28038
- const instance = render(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScanApp, {
28039
- store,
28040
- displayMode,
28041
- launchableAgents,
28042
- onHandoff: (request) => {
28043
- pendingActions.handoffRequest = request;
28044
- },
28045
- canAddToCi: shouldRecommendCi,
28046
- onAddToCi: () => {
28047
- pendingActions.shouldSetUpCi = true;
28048
- },
28049
- onQuit: () => {
28050
- pendingActions.didQuit = true;
28051
- }
28052
- }), {
28053
- alternateScreen: false,
28054
- exitOnCtrlC: false
28055
- });
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;
28056
25652
  return {
28057
- instance,
28058
- dispose: registerMountedTuiRenderer(instance)
25653
+ $$typeof: REACT_ELEMENT_TYPE,
25654
+ type,
25655
+ key,
25656
+ ref: void 0 !== config ? config : null,
25657
+ props: maybeKey
28059
25658
  };
28060
- };
28061
- const executePendingActions = async () => {
28062
- if (pendingActions.shouldSetUpCi) await performCiSetup(rootDirectory);
28063
- if (pendingActions.didQuit) return;
28064
- if (pendingActions.handoffRequest) await performTuiHandoff(pendingActions.handoffRequest, rootDirectory);
28065
- };
28066
- return {
28067
- store,
28068
- pendingActions,
28069
- mountRenderer,
28070
- executePendingActions
28071
- };
28072
- };
28073
- const runMountedScan = async (rootDirectory, presentation, blockingLevel, executeScan) => {
28074
- const { store, pendingActions, mountRenderer, executePendingActions } = await mountScanApp(rootDirectory, presentation.shouldRecommendCi, presentation.initialProgress);
28075
- let mountedRenderer = mountRenderer("scan");
28076
- recordCount(METRIC.tuiScanInlineShown);
28077
- const context = {
28078
- store,
28079
- ...presentation
28080
- };
28081
- try {
28082
- const completedScan = await executeScan(context);
28083
- mountedRenderer.dispose();
28084
- mountedRenderer = mountRenderer("report");
28085
- await mountedRenderer.instance.waitUntilExit();
28086
- mountedRenderer.dispose();
28087
- if (presentation.outputDirectory !== void 0 || presentation.verbose) await runPromise(printDiagnosticsDump([...completedScan.diagnostics], presentation.outputDirectory, presentation.verbose));
28088
- if (!pendingActions.didQuit) await printExitFooter({
28089
- diagnostics: completedScan.diagnostics,
28090
- scoreResult: completedScan.scoreResult,
28091
- projectName: completedScan.projectName,
28092
- scannedFileCount: completedScan.scannedFileCount,
28093
- elapsedMilliseconds: completedScan.elapsedMilliseconds,
28094
- isOffline: context.isOffline,
28095
- lintFailureReason: resolveLintFailureReason(completedScan.scans.map(({ result }) => result))
28096
- });
28097
- await executePendingActions();
28098
- return { shouldFail: shouldFailScanGate({
28099
- scans: completedScan.scans,
28100
- blockingLevel,
28101
- diagnosticsAreGateExempt: completedScan.diagnosticsAreGateExempt
28102
- }) };
28103
- } catch (error) {
28104
- mountedRenderer.dispose();
28105
- throw error;
28106
- }
28107
- };
28108
- const runSingleProjectScan = async (rootScanTarget, projectDirectory, input, scopePlan, blockingLevel, inspectProject) => {
28109
- const projectScan = await resolveProjectScan(rootScanTarget, projectDirectory);
28110
- const isSupplyChainEnabled = input.options?.supplyChain ?? projectScan.config?.supplyChain?.enabled ?? true;
28111
- const scopeOptions = resolveProjectTuiScanScope({
28112
- plan: scopePlan,
28113
- projectDirectory: projectScan.directory,
28114
- rootDirectory: rootScanTarget.resolvedDirectory,
28115
- supplyChainEnabled: isSupplyChainEnabled
28116
- });
28117
- if (scopeOptions === null) {
28118
- process.stdout.write("No changed source files in the selected project.\n");
28119
- return { shouldFail: false };
28120
25659
  }
28121
- const presentation = resolveScanPresentation(input, [projectScan]);
28122
- return runMountedScan(projectScan.directory, presentation, blockingLevel, async (context) => {
28123
- const result = await inspectProject(projectScan.directory, {
28124
- ...resolveTuiInspectOptions(input, projectScan.config),
28125
- ...scopeOptions,
28126
- isCi: isCiEnvironment(),
28127
- configOverride: projectScan.config,
28128
- configSourceDirectory: projectScan.configSourceDirectory ?? void 0,
28129
- uiLayers: {
28130
- reporter: reporterLayerForStore(context.store),
28131
- progress: progressLayerForStore(context.store)
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";
28132
25688
  }
28133
- });
28134
- const reportSelection = selectReportDiagnostics({
28135
- scan: {
28136
- result,
28137
- config: projectScan.config
28138
- },
28139
- categoryFilters: input.options?.categoryFilters,
28140
- surface: input.options?.outputSurface
28141
- });
28142
- const scoreDiagnostics = filterScansForSurface([{
28143
- result,
28144
- config: projectScan.config
28145
- }], "score");
28146
- const projectedScore = result.score ? await computeProjectedScore([...reportSelection.diagnostics], scoreDiagnostics, result.score) : null;
28147
- context.store.setReport(toScanReport({
28148
- result,
28149
- diagnostics: reportSelection.diagnostics,
28150
- rootDirectory: projectScan.directory,
28151
- projectedScore,
28152
- isOffline: context.isOffline,
28153
- noScoreMessage: buildNoScoreMessage({
28154
- isScoreDisabled: input.options?.noScore === true || projectScan.config?.noScore === true,
28155
- isAnalysisIncomplete: hasIncompleteScoreAnalysis(result.skippedChecks),
28156
- disabledMessage: input.options?.scoreDisabledMessage
28157
- }),
28158
- emptyStateMessage: resolveEmptyStateMessage(input, reportSelection.demotedDiagnosticCount)
28159
- }));
28160
- return {
28161
- scans: [{
28162
- result,
28163
- config: projectScan.config
28164
- }],
28165
- diagnostics: reportSelection.diagnostics,
28166
- diagnosticsAreGateExempt: scopePlan.baselineIntended && result.baselineDelta === void 0,
28167
- scoreResult: result.score,
28168
- projectName: result.project.projectName,
28169
- scannedFileCount: result.scannedFileCount ?? 0,
28170
- elapsedMilliseconds: result.elapsedMilliseconds
28171
- };
28172
- });
28173
- };
28174
- const runMultiProjectScan = async (rootScanTarget, directories, input, scopePlan, blockingLevel, inspectProject) => {
28175
- const feedbackStartTime = performance$1.now();
28176
- const rootDirectory = rootScanTarget.resolvedDirectory;
28177
- const discoveredProjectScans = deduplicateProjectScans(await mapWithConcurrency([...directories], 4, (projectDirectory) => resolveProjectScan(rootScanTarget, projectDirectory)));
28178
- const projectScans = discoveredProjectScans.flatMap((projectScan) => {
28179
- const isSupplyChainEnabled = input.options?.supplyChain ?? projectScan.config?.supplyChain?.enabled ?? true;
28180
- const scopeOptions = resolveProjectTuiScanScope({
28181
- plan: scopePlan,
28182
- projectDirectory: projectScan.directory,
28183
- rootDirectory,
28184
- supplyChainEnabled: isSupplyChainEnabled
28185
- });
28186
- return scopeOptions === null ? [] : [{
28187
- projectScan,
28188
- scopeOptions
28189
- }];
28190
- });
28191
- if (projectScans.length === 0) {
28192
- process.stdout.write("No changed source files in the selected projects.\n");
28193
- return { shouldFail: false };
28194
- }
28195
- const projectCount = projectScans.length;
28196
- const rootProjectScan = discoveredProjectScans.find((projectScan) => path.resolve(projectScan.directory) === path.resolve(rootDirectory));
28197
- const workspaceDeadCodeOwner = resolveWorkspaceDeadCodeOwner({
28198
- rootDirectory,
28199
- projectDirectories: discoveredProjectScans.map((projectScan) => projectScan.directory),
28200
- isRootDeadCodeEnabled: input.options?.deadCode ?? rootProjectScan?.config?.deadCode ?? true
28201
- });
28202
- if (workspaceDeadCodeOwner !== null) recordCount(METRIC.scanWorkspaceMaintainabilityShared, 1, { projectCount: discoveredProjectScans.length });
28203
- return runMountedScan(rootDirectory, resolveScanPresentation(input, projectScans.map(({ projectScan }) => projectScan)), blockingLevel, async (context) => {
28204
- const startTime = performance$1.now();
28205
- let finishedCount = 0;
28206
- recordDistribution(METRIC.scanFeedbackDelay, performance$1.now() - feedbackStartTime, {
28207
- unit: "millisecond",
28208
- attributes: {
28209
- surface: "tui",
28210
- 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) {}
28211
25705
  }
28212
- });
28213
- context.store.setProgress(`Scanning ${projectCount} projects…`);
28214
- await yieldToEventLoop();
28215
- const precomputedSourceFileCounts = scopePlan.scope === "full" ? await collectProjectSourceFileCounts(rootDirectory, projectScans.map(({ projectScan }) => projectScan.directory)) : null;
28216
- const { completedScans, skippedScans } = partitionProjectScanOutcomes(await mapWithConcurrency(projectScans, 4, async ({ projectScan, scopeOptions }) => {
28217
- if (input.options?.deadlineEpochMs !== void 0 && remainingDeadlineBudgetMs(input.options.deadlineEpochMs) === 0) {
28218
- finishedCount += 1;
28219
- context.store.setProgress(`Scanning ${projectCount} projects… (${finishedCount}/${projectCount})`);
28220
- return {
28221
- status: "skipped",
28222
- value: {
28223
- directory: projectScan.directory,
28224
- reason: "max-duration"
28225
- }
28226
- };
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;
28227
25717
  }
28228
- const projectLabel = path.relative(rootDirectory, projectScan.directory) || path.basename(rootDirectory);
28229
- const formatProjectProgress = (displayText) => `Scanning ${projectCount} projects… (${finishedCount}/${projectCount}) · ${projectLabel}: ${displayText}`;
28230
- const inspectOptions = resolveTuiInspectOptions(input, projectScan.config);
28231
- const ownsWorkspaceDeadCode = projectScan.directory === workspaceDeadCodeOwner;
28232
- const result = await inspectProject(projectScan.directory, {
28233
- ...inspectOptions,
28234
- ...scopeOptions,
28235
- deadCode: workspaceDeadCodeOwner === null ? inspectOptions.deadCode : ownsWorkspaceDeadCode,
28236
- isCi: isCiEnvironment(),
28237
- configOverride: projectScan.config,
28238
- configSourceDirectory: projectScan.configSourceDirectory ?? void 0,
28239
- precomputedSourceFileCount: precomputedSourceFileCounts?.get(projectScan.directory),
28240
- uiLayers: {
28241
- reporter: Reporter.layerNoop,
28242
- progress: progressLayerForStore(context.store, {
28243
- transformText: formatProjectProgress,
28244
- shouldClearOnStop: false
28245
- })
28246
- },
28247
- concurrentScan: true,
28248
- excludedProjectDirectories: discoveredProjectScans.filter((candidateProjectScan) => isPathInsideDirectory(candidateProjectScan.directory, projectScan.directory)).map((candidateProjectScan) => candidateProjectScan.directory),
28249
- retainExcludedProjectDeadCodeDiagnostics: ownsWorkspaceDeadCode
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
28250
25758
  });
28251
- finishedCount += 1;
28252
- context.store.setProgress(`Scanning ${projectCount} projects… (${finishedCount}/${projectCount})`);
28253
- await yieldToEventLoop();
28254
- return {
28255
- status: "completed",
28256
- value: {
28257
- directory: projectScan.directory,
28258
- result,
28259
- config: projectScan.config
28260
- }
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
28261
25774
  };
28262
- }));
28263
- const results = await retryMissingProjectScores(completedScans.map((completedScan) => ({
28264
- ...completedScan,
28265
- isScoreDisabled: input.options?.noScore ?? completedScan.config?.noScore ?? false
28266
- })));
28267
- const skippedProjects = skippedScans.sort((left, right) => left.directory.localeCompare(right.directory));
28268
- if (skippedProjects.length > 0) recordCount(METRIC.scanProjectSkipped, skippedProjects.length, { reason: "max-duration" });
28269
- const projectEntries = results.map(({ directory, result, config }) => {
28270
- const reportSelection = selectReportDiagnostics({
28271
- scan: {
28272
- result,
28273
- config
28274
- },
28275
- categoryFilters: input.options?.categoryFilters,
28276
- 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
28277
25781
  });
28278
- return {
28279
- report: toScanReport({
28280
- result,
28281
- diagnostics: reportSelection.diagnostics,
28282
- rootDirectory: directory,
28283
- projectedScore: null,
28284
- isOffline: context.isOffline,
28285
- noScoreMessage: buildNoScoreMessage({
28286
- isScoreDisabled: input.options?.noScore === true || config?.noScore === true,
28287
- isAnalysisIncomplete: hasIncompleteScoreAnalysis(result.skippedChecks),
28288
- disabledMessage: input.options?.scoreDisabledMessage
28289
- }),
28290
- emptyStateMessage: resolveEmptyStateMessage(input, reportSelection.demotedDiagnosticCount)
28291
- }),
28292
- score: result.score,
28293
- scoreDiagnostics: filterScansForSurface([{
28294
- result,
28295
- config
28296
- }], "score"),
28297
- demotedDiagnosticCount: reportSelection.demotedDiagnosticCount
28298
- };
28299
- });
28300
- const projects = projectEntries.map(({ report }) => report);
28301
- const combinedDiagnostics = projects.flatMap((project) => qualifyDiagnosticPaths(project.diagnostics, rootDirectory, project.rootDirectory));
28302
- const lowestScoredReport = findLowestScoredReport(projectEntries);
28303
- const projectedScore = lowestScoredReport ? await computeProjectedScore(combinedDiagnostics, [...lowestScoredReport.scoreDiagnostics], lowestScoredReport.score) : null;
28304
- const scannedFileCount = countUniqueScannedFiles(results.map(({ result }) => result));
28305
- const elapsedMilliseconds = performance$1.now() - startTime;
28306
- const lintFailureReason = resolveLintFailureReason(results.map(({ result }) => result));
28307
- const summary = {
28308
- projects,
28309
- skippedProjects,
28310
- aggregateScore: lowestScoredReport?.score ?? null,
28311
- projectedScore,
28312
- combinedDiagnostics,
28313
- scannedFileCount,
28314
- elapsedMilliseconds,
28315
- projectName: path.basename(rootDirectory),
28316
- rootDirectory,
28317
- isOffline: context.isOffline,
28318
- noScoreMessage: buildNoScoreMessage({
28319
- isScoreDisabled: input.options?.noScore === true || results.some(({ config }) => config?.noScore === true),
28320
- isAnalysisIncomplete: results.some(({ result }) => hasIncompleteScoreAnalysis(result.skippedChecks)),
28321
- disabledMessage: input.options?.scoreDisabledMessage
28322
- }),
28323
- emptyStateMessage: resolveEmptyStateMessage(input, projectEntries.reduce((total, projectEntry) => total + projectEntry.demotedDiagnosticCount, 0)),
28324
- ...lintFailureReason ? { lintFailureReason } : {}
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;
28325
25843
  };
28326
- context.store.setSummary(summary);
28327
- return {
28328
- scans: results,
28329
- diagnostics: combinedDiagnostics,
28330
- diagnosticsAreGateExempt: scopePlan.baselineIntended && (skippedProjects.length > 0 || results.length === 0 || results.some(({ result }) => result.baselineDelta === void 0)),
28331
- scoreResult: summary.aggregateScore,
28332
- projectName: summary.projectName,
28333
- scannedFileCount,
28334
- elapsedMilliseconds
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);
28335
25856
  };
28336
- });
28337
- };
28338
- const runScanApp = async (input) => {
28339
- const scanTarget = input.scanTarget ?? await resolveScanTarget(input.directory, { allowAmbiguous: true });
28340
- const rootDirectory = scanTarget.resolvedDirectory;
28341
- const scopePlan = await resolveTuiScanScope({
28342
- directory: rootDirectory,
28343
- flags: input.flags ?? {},
28344
- userConfig: scanTarget.userConfig
28345
- });
28346
- const deadlineEpochMs = input.options?.deadlineEpochMs ?? (input.options?.maxDurationMs != null ? Date.now() + input.options.maxDurationMs : void 0);
28347
- const resolvedInput = {
28348
- ...input,
28349
- options: {
28350
- ...input.options,
28351
- deadlineEpochMs
28352
- },
28353
- configProjects: input.configProjects ?? scanTarget.userConfig?.projects,
28354
- share: input.share ?? scanTarget.userConfig?.share ?? true
28355
- };
28356
- const selectedDirectories = await resolveSelectedDirectories(rootDirectory, resolvedInput);
28357
- const inspectProject = createInvocationInspect(input.options?.concurrency);
28358
- const blockingLevel = resolveBlockingLevel({ blocking: resolvedInput.blocking }, scanTarget.userConfig);
28359
- if (selectedDirectories.length === 0) return { shouldFail: false };
28360
- if (selectedDirectories.length === 1) return runSingleProjectScan(scanTarget, selectedDirectories[0], resolvedInput, scopePlan, blockingLevel, inspectProject);
28361
- return runMultiProjectScan(scanTarget, selectedDirectories, resolvedInput, scopePlan, blockingLevel, inspectProject);
28362
- };
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
+ }));
28363
25869
  //#endregion
28364
- export { runScanApp };
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 };
28365
25871
 
28366
- //# sourceMappingURL=run-scan-app-CDDu7P32.js.map
28367
- //# debugId=b88a5d25-b8e7-56ca-b67f-96a6090df2dc
25872
+ //# sourceMappingURL=jsx-runtime-Cq-_Fvkx.js.map
25873
+ //# debugId=bea2a0ad-0793-5fc6-aee8-6d1ffc663594