react-doctor 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cli.js +1043 -226
- package/dist/index.d.ts +9 -3
- package/dist/index.js +719 -124
- package/dist/lsp.js +706 -120
- package/dist/{run-scan-app-DZ5jGWFf.js → run-scan-app-DHRvqfkX.js} +288 -216
- package/package.json +8 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
-
import { A as toForwardSlashes, B as
|
|
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]="898bdb3e-afed-5fca-92a2-f14d1e8ca6fb")}catch(e){}}();
|
|
3
|
+
import { A as toForwardSlashes, B as getCategoryImpact, C as buildRulePriorityMap, D as resolveBlockingLevel, E as formatLearnMoreLine, F as TUI_REPORT_DETAIL_WIDTH_FRACTION, G as runPromise, H as mapWithConcurrency, I as isCiEnvironment, J as succeed, K as sync, L as DIAGNOSTIC_CATEGORY_BUCKETS, M as isUnicodeSupported, N as METRIC, O as isReactDoctorWorkflowInstalled, P as TUI_REPORT_COMPACT_MAX_ROWS, R as Progress, S as hasLintHardFailure, T as formatFixRecipeLine, U as mergeReactDoctorConfigs, V as highlighter, W as resolveScanTarget, _ as canAnimateOnboarding, a as resolveCliInspectOptions, b as buildCodeFrame, c as detectLaunchableAgents, d as launchCliAgent, f as isShareOptedOut, g as doctorFace, h as easeOutCubic, i as selectProjects, j as findNearestPackageDirectory, k as recordCount, l as CLI_AGENT_BINARIES, m as printFooter, n as shouldFailScanGate, o as countUniqueScannedFiles, p as createInvocationInspect, q as void_, r as discoverWorkspacePackages, s as setUpGitHubActions, t as exitGracefully, u as copyToClipboard, v as computeProjectedScore, w as buildSortedRuleGroups, x as buildNoScoreMessage, y as formatElapsedTime, z as Reporter } from "./cli.js";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { performance } from "node:perf_hooks";
|
|
6
6
|
import { getSkillAgentConfig } from "agent-install";
|
|
@@ -428,14 +428,11 @@ const buildIssuePrompt = ({ row, projectName }) => {
|
|
|
428
428
|
};
|
|
429
429
|
//#endregion
|
|
430
430
|
//#region src/cli/ink/components/diagnostic-action-menu.tsx
|
|
431
|
-
const MODAL_BACKGROUND = "black";
|
|
432
|
-
const MODAL_SELECTED_BACKGROUND = "white";
|
|
433
431
|
const DiagnosticActionMenu = ({ title, itemLabels, focusedIndex, maxWidth }) => {
|
|
434
432
|
return /* @__PURE__ */ jsxs(Box, {
|
|
435
433
|
width: Math.max(24, Math.min(44, maxWidth)),
|
|
436
434
|
borderStyle: "round",
|
|
437
|
-
borderColor: "
|
|
438
|
-
backgroundColor: MODAL_BACKGROUND,
|
|
435
|
+
borderColor: "cyan",
|
|
439
436
|
paddingX: 2,
|
|
440
437
|
paddingY: 1,
|
|
441
438
|
flexDirection: "column",
|
|
@@ -455,14 +452,12 @@ const DiagnosticActionMenu = ({ title, itemLabels, focusedIndex, maxWidth }) =>
|
|
|
455
452
|
flexDirection: "column",
|
|
456
453
|
children: itemLabels.map((label, index) => {
|
|
457
454
|
const isFocused = index === focusedIndex;
|
|
458
|
-
return /* @__PURE__ */
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
children: [isFocused ? "› " : " ", label]
|
|
465
|
-
})
|
|
455
|
+
return /* @__PURE__ */ jsxs(Text, {
|
|
456
|
+
wrap: "truncate-end",
|
|
457
|
+
bold: isFocused,
|
|
458
|
+
color: isFocused ? "cyan" : void 0,
|
|
459
|
+
dimColor: !isFocused,
|
|
460
|
+
children: [isFocused ? "› " : " ", label]
|
|
466
461
|
}, label);
|
|
467
462
|
})
|
|
468
463
|
}),
|
|
@@ -514,110 +509,97 @@ const DiagnosticDetail = ({ row, rootDirectory }) => {
|
|
|
514
509
|
const impact = getCategoryImpact(row.category);
|
|
515
510
|
return /* @__PURE__ */ jsxs(Box, {
|
|
516
511
|
flexDirection: "column",
|
|
517
|
-
children: [
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
512
|
+
children: [/* @__PURE__ */ jsxs(Text, {
|
|
513
|
+
wrap: "truncate-end",
|
|
514
|
+
children: [
|
|
515
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
516
|
+
color: variant.color,
|
|
517
|
+
children: [variant.icon, " "]
|
|
518
|
+
}),
|
|
519
|
+
/* @__PURE__ */ jsx(Text, {
|
|
520
|
+
color: variant.color,
|
|
521
|
+
bold: true,
|
|
522
|
+
children: row.title
|
|
523
|
+
}),
|
|
524
|
+
row.siteCount > 1 ? /* @__PURE__ */ jsxs(Text, {
|
|
525
|
+
dimColor: true,
|
|
526
|
+
children: [" ×", row.siteCount]
|
|
527
|
+
}) : null
|
|
528
|
+
]
|
|
529
|
+
}), /* @__PURE__ */ jsxs(Box, {
|
|
530
|
+
flexDirection: "column",
|
|
531
|
+
paddingLeft: 2,
|
|
532
|
+
children: [
|
|
533
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
534
|
+
dimColor: true,
|
|
535
|
+
wrap: "truncate-end",
|
|
536
|
+
children: [
|
|
537
|
+
row.category,
|
|
538
|
+
" · ",
|
|
539
|
+
variant.label,
|
|
540
|
+
" · ",
|
|
541
|
+
row.location
|
|
542
|
+
]
|
|
543
|
+
}),
|
|
544
|
+
impact ? /* @__PURE__ */ jsx(Text, {
|
|
545
|
+
dimColor: true,
|
|
546
|
+
wrap: "wrap",
|
|
547
|
+
children: impact
|
|
548
|
+
}) : null,
|
|
549
|
+
/* @__PURE__ */ jsx(Text, {
|
|
550
|
+
wrap: "wrap",
|
|
551
|
+
children: representative.message
|
|
552
|
+
}),
|
|
553
|
+
codeFrame ? /* @__PURE__ */ jsx(Box, {
|
|
554
|
+
marginTop: 1,
|
|
555
|
+
children: /* @__PURE__ */ jsx(Text, { children: codeFrame })
|
|
556
|
+
}) : null,
|
|
557
|
+
representative.help ? /* @__PURE__ */ jsx(Box, {
|
|
558
|
+
marginTop: 1,
|
|
559
|
+
children: /* @__PURE__ */ jsxs(Text, {
|
|
559
560
|
wrap: "wrap",
|
|
560
|
-
children:
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
561
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
562
|
+
color: "cyan",
|
|
563
|
+
children: "Fix "
|
|
564
|
+
}), representative.help]
|
|
565
|
+
})
|
|
566
|
+
}) : null,
|
|
567
|
+
row.learnMore ? /* @__PURE__ */ jsx(Box, {
|
|
568
|
+
marginTop: 1,
|
|
569
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
570
|
+
color: "blue",
|
|
564
571
|
wrap: "truncate-end",
|
|
565
|
-
children: row.
|
|
572
|
+
children: row.learnMore
|
|
566
573
|
})
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
marginTop: 1,
|
|
571
|
-
marginLeft: 4,
|
|
572
|
-
borderStyle: "round",
|
|
573
|
-
borderColor: "gray",
|
|
574
|
-
paddingX: 1,
|
|
575
|
-
alignSelf: "flex-start",
|
|
576
|
-
children: /* @__PURE__ */ jsx(Text, { children: codeFrame })
|
|
577
|
-
}) : null,
|
|
578
|
-
representative.help ? /* @__PURE__ */ jsx(Box, {
|
|
579
|
-
marginTop: 1,
|
|
580
|
-
paddingLeft: 4,
|
|
581
|
-
children: /* @__PURE__ */ jsxs(Text, {
|
|
582
|
-
dimColor: true,
|
|
583
|
-
wrap: "wrap",
|
|
584
|
-
children: ["→ ", representative.help]
|
|
585
|
-
})
|
|
586
|
-
}) : null,
|
|
587
|
-
row.learnMore ? /* @__PURE__ */ jsx(Box, {
|
|
588
|
-
marginTop: 1,
|
|
589
|
-
paddingLeft: 4,
|
|
590
|
-
children: /* @__PURE__ */ jsx(Text, {
|
|
591
|
-
color: "cyan",
|
|
592
|
-
wrap: "truncate-end",
|
|
593
|
-
children: row.learnMore
|
|
594
|
-
})
|
|
595
|
-
}) : null
|
|
596
|
-
]
|
|
574
|
+
}) : null
|
|
575
|
+
]
|
|
576
|
+
})]
|
|
597
577
|
});
|
|
598
578
|
};
|
|
599
579
|
//#endregion
|
|
600
580
|
//#region src/cli/ink/components/diagnostic-item.tsx
|
|
601
581
|
const DiagnosticItem = ({ row, isSelected, isRead }) => {
|
|
602
582
|
const variant = severityVariant(row.severity);
|
|
583
|
+
const shouldHighlightSeverity = isSelected || !isRead;
|
|
584
|
+
let marker = "• ";
|
|
585
|
+
if (isRead) marker = " ";
|
|
586
|
+
if (isSelected) marker = "› ";
|
|
587
|
+
let markerColor = shouldHighlightSeverity ? variant.color : void 0;
|
|
588
|
+
if (isSelected) markerColor = "cyan";
|
|
603
589
|
return /* @__PURE__ */ jsxs(Text, {
|
|
604
590
|
wrap: "truncate-end",
|
|
605
|
-
dimColor: isRead,
|
|
591
|
+
dimColor: isRead && !isSelected,
|
|
606
592
|
children: [
|
|
607
593
|
/* @__PURE__ */ jsx(Text, {
|
|
608
|
-
color:
|
|
609
|
-
children:
|
|
610
|
-
}),
|
|
611
|
-
/* @__PURE__ */ jsx(Text, {
|
|
612
|
-
color: isRead ? void 0 : variant.color,
|
|
613
|
-
children: isRead ? " " : " •"
|
|
594
|
+
color: markerColor,
|
|
595
|
+
children: marker
|
|
614
596
|
}),
|
|
615
597
|
/* @__PURE__ */ jsx(Text, {
|
|
616
|
-
color:
|
|
617
|
-
children:
|
|
598
|
+
color: shouldHighlightSeverity ? variant.color : void 0,
|
|
599
|
+
children: `${variant.icon} `
|
|
618
600
|
}),
|
|
619
601
|
/* @__PURE__ */ jsx(Text, {
|
|
620
|
-
color:
|
|
602
|
+
color: shouldHighlightSeverity ? variant.color : void 0,
|
|
621
603
|
bold: isSelected,
|
|
622
604
|
children: row.title
|
|
623
605
|
}),
|
|
@@ -633,9 +615,8 @@ const DiagnosticItem = ({ row, isSelected, isRead }) => {
|
|
|
633
615
|
const StatusBar = ({ total, errorCount, warningCount, position, groupCount, unreadCount, projectCount, keyHints = /* @__PURE__ */ jsx(Text, {
|
|
634
616
|
dimColor: true,
|
|
635
617
|
children: "↑/↓ to move"
|
|
636
|
-
}), exitHint = "q to quit" }) =>
|
|
637
|
-
|
|
638
|
-
children: [
|
|
618
|
+
}), exitHint = "q to quit", compact = false }) => {
|
|
619
|
+
const counts = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
639
620
|
/* @__PURE__ */ jsxs(Text, {
|
|
640
621
|
bold: true,
|
|
641
622
|
children: [
|
|
@@ -646,7 +627,7 @@ const StatusBar = ({ total, errorCount, warningCount, position, groupCount, unre
|
|
|
646
627
|
}),
|
|
647
628
|
/* @__PURE__ */ jsx(Text, {
|
|
648
629
|
dimColor: true,
|
|
649
|
-
children: "
|
|
630
|
+
children: " "
|
|
650
631
|
}),
|
|
651
632
|
/* @__PURE__ */ jsxs(Text, {
|
|
652
633
|
color: "red",
|
|
@@ -654,46 +635,80 @@ const StatusBar = ({ total, errorCount, warningCount, position, groupCount, unre
|
|
|
654
635
|
}),
|
|
655
636
|
/* @__PURE__ */ jsx(Text, {
|
|
656
637
|
dimColor: true,
|
|
657
|
-
children: "
|
|
638
|
+
children: " "
|
|
658
639
|
}),
|
|
659
640
|
/* @__PURE__ */ jsxs(Text, {
|
|
660
641
|
color: "yellow",
|
|
661
|
-
dimColor: true,
|
|
662
642
|
children: [warningCount, " warnings"]
|
|
663
|
-
})
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
643
|
+
})
|
|
644
|
+
] });
|
|
645
|
+
if (compact) return /* @__PURE__ */ jsxs(Text, {
|
|
646
|
+
wrap: "truncate-end",
|
|
647
|
+
children: [
|
|
648
|
+
counts,
|
|
649
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
650
|
+
dimColor: true,
|
|
651
|
+
children: [
|
|
652
|
+
" · ",
|
|
653
|
+
position,
|
|
654
|
+
"/",
|
|
655
|
+
groupCount,
|
|
656
|
+
" · "
|
|
657
|
+
]
|
|
658
|
+
}),
|
|
659
|
+
keyHints,
|
|
660
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
661
|
+
dimColor: true,
|
|
662
|
+
children: [" · ", exitHint]
|
|
663
|
+
})
|
|
664
|
+
]
|
|
665
|
+
});
|
|
666
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
667
|
+
flexDirection: "column",
|
|
668
|
+
children: [/* @__PURE__ */ jsxs(Text, {
|
|
669
|
+
wrap: "truncate-end",
|
|
675
670
|
children: [
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
671
|
+
counts,
|
|
672
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
673
|
+
dimColor: true,
|
|
674
|
+
children: [
|
|
675
|
+
" · ",
|
|
676
|
+
position,
|
|
677
|
+
"/",
|
|
678
|
+
groupCount
|
|
679
|
+
]
|
|
680
|
+
}),
|
|
681
|
+
projectCount !== void 0 ? /* @__PURE__ */ jsxs(Text, {
|
|
682
|
+
dimColor: true,
|
|
683
|
+
children: [
|
|
684
|
+
" · ",
|
|
685
|
+
projectCount,
|
|
686
|
+
" ",
|
|
687
|
+
projectCount === 1 ? "project" : "projects"
|
|
688
|
+
]
|
|
689
|
+
}) : null
|
|
680
690
|
]
|
|
681
|
-
})
|
|
682
|
-
|
|
683
|
-
dimColor: true,
|
|
691
|
+
}), /* @__PURE__ */ jsxs(Text, {
|
|
692
|
+
wrap: "truncate-end",
|
|
684
693
|
children: [
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
694
|
+
unreadCount !== void 0 ? /* @__PURE__ */ jsxs(Text, {
|
|
695
|
+
color: unreadCount > 0 ? "cyan" : void 0,
|
|
696
|
+
dimColor: unreadCount === 0,
|
|
697
|
+
children: [
|
|
698
|
+
unreadCount,
|
|
699
|
+
" unread",
|
|
700
|
+
" · "
|
|
701
|
+
]
|
|
702
|
+
}) : null,
|
|
690
703
|
keyHints,
|
|
691
|
-
|
|
692
|
-
|
|
704
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
705
|
+
dimColor: true,
|
|
706
|
+
children: [" · ", exitHint]
|
|
707
|
+
})
|
|
693
708
|
]
|
|
694
|
-
})
|
|
695
|
-
|
|
696
|
-
}
|
|
709
|
+
})]
|
|
710
|
+
});
|
|
711
|
+
};
|
|
697
712
|
//#endregion
|
|
698
713
|
//#region src/cli/ink/components/diagnostic-list.tsx
|
|
699
714
|
const ADD_TO_CI_KEY = "a";
|
|
@@ -715,6 +730,7 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
715
730
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
716
731
|
const [menuIndex, setMenuIndex] = useState(0);
|
|
717
732
|
const isSplit = layout === "split";
|
|
733
|
+
const isCompact = layout === "compact";
|
|
718
734
|
const { rows: terminalRows } = useStdoutDimensions();
|
|
719
735
|
const { selectedIndex, visibleStart, visibleEnd } = useScrollViewport({
|
|
720
736
|
itemCount: entries.length,
|
|
@@ -726,6 +742,8 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
726
742
|
const selectedEntry = entries[selectedIndex];
|
|
727
743
|
const selected = selectedEntry?.kind === "item" ? selectedEntry.row : null;
|
|
728
744
|
const selectedRuleKey = selected?.ruleKey ?? null;
|
|
745
|
+
const initialSelectedRuleKey = useRef(selectedRuleKey);
|
|
746
|
+
const didRecordFindingNavigation = useRef(false);
|
|
729
747
|
const [readRuleKeys, setReadRuleKeys] = useState(() => /* @__PURE__ */ new Set());
|
|
730
748
|
const [copiedRuleKey, setCopiedRuleKey] = useState(null);
|
|
731
749
|
const menuLabels = useMemo(() => ["Copy prompt", ...launchableAgents.map((agentId) => getSkillAgentConfig(agentId).displayName)], [launchableAgents]);
|
|
@@ -733,6 +751,11 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
733
751
|
if (!selectedRuleKey) return;
|
|
734
752
|
setReadRuleKeys((previous) => previous.has(selectedRuleKey) ? previous : new Set(previous).add(selectedRuleKey));
|
|
735
753
|
}, [selectedRuleKey]);
|
|
754
|
+
useEffect(() => {
|
|
755
|
+
if (!selectedRuleKey || selectedRuleKey === initialSelectedRuleKey.current || didRecordFindingNavigation.current) return;
|
|
756
|
+
didRecordFindingNavigation.current = true;
|
|
757
|
+
recordCount(METRIC.tuiFindingNavigated);
|
|
758
|
+
}, [selectedRuleKey]);
|
|
736
759
|
const copySelectedPrompt = () => {
|
|
737
760
|
if (!selected) return;
|
|
738
761
|
const prompt = buildIssuePrompt({
|
|
@@ -772,6 +795,7 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
772
795
|
return onExit();
|
|
773
796
|
}
|
|
774
797
|
if (key.return && selected) {
|
|
798
|
+
recordCount(METRIC.tuiActionMenuOpened);
|
|
775
799
|
setMenuIndex(0);
|
|
776
800
|
setIsMenuOpen(true);
|
|
777
801
|
}
|
|
@@ -782,6 +806,18 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
782
806
|
if (key.downArrow || input === "j") return setMenuIndex((index) => Math.min(menuLabels.length - 1, index + 1));
|
|
783
807
|
if (key.return) return runMenuItem();
|
|
784
808
|
}, { isActive: isMenuOpen });
|
|
809
|
+
if (isMenuOpen && selected) return /* @__PURE__ */ jsx(Box, {
|
|
810
|
+
width,
|
|
811
|
+
height: Math.max(6, terminalRows - 2),
|
|
812
|
+
justifyContent: "center",
|
|
813
|
+
alignItems: "center",
|
|
814
|
+
children: /* @__PURE__ */ jsx(DiagnosticActionMenu, {
|
|
815
|
+
title: selected.title,
|
|
816
|
+
itemLabels: menuLabels,
|
|
817
|
+
focusedIndex: menuIndex,
|
|
818
|
+
maxWidth: width
|
|
819
|
+
})
|
|
820
|
+
});
|
|
785
821
|
const errorRows = rows.filter((row) => row.severity === "error");
|
|
786
822
|
const warningRows = rows.filter((row) => row.severity === "warning");
|
|
787
823
|
const itemPosition = entries.slice(0, selectedIndex + 1).filter((entry) => entry.kind === "item").length;
|
|
@@ -802,20 +838,7 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
802
838
|
children: "✓ Copied fix prompt"
|
|
803
839
|
})
|
|
804
840
|
}) : null] });
|
|
805
|
-
const keyHints =
|
|
806
|
-
/* @__PURE__ */ jsx(Text, {
|
|
807
|
-
dimColor: true,
|
|
808
|
-
children: "↑/↓ select · "
|
|
809
|
-
}),
|
|
810
|
-
/* @__PURE__ */ jsx(Text, {
|
|
811
|
-
color: "cyan",
|
|
812
|
-
children: "enter"
|
|
813
|
-
}),
|
|
814
|
-
/* @__PURE__ */ jsx(Text, {
|
|
815
|
-
dimColor: true,
|
|
816
|
-
children: " run · esc close"
|
|
817
|
-
})
|
|
818
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
841
|
+
const keyHints = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
819
842
|
/* @__PURE__ */ jsx(Text, {
|
|
820
843
|
dimColor: true,
|
|
821
844
|
children: "↑/↓ move · "
|
|
@@ -842,9 +865,9 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
842
865
|
children: " add CI"
|
|
843
866
|
})
|
|
844
867
|
] }) : null
|
|
845
|
-
] })
|
|
868
|
+
] });
|
|
846
869
|
const statusBar = /* @__PURE__ */ jsx(Box, {
|
|
847
|
-
marginTop: 1,
|
|
870
|
+
marginTop: isCompact ? 0 : 1,
|
|
848
871
|
children: /* @__PURE__ */ jsx(StatusBar, {
|
|
849
872
|
total: sumSites(rows),
|
|
850
873
|
errorCount: sumSites(errorRows),
|
|
@@ -853,62 +876,54 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
853
876
|
groupCount: rows.length,
|
|
854
877
|
unreadCount,
|
|
855
878
|
projectCount,
|
|
856
|
-
keyHints,
|
|
857
|
-
|
|
879
|
+
keyHints: isCompact && copiedRuleKey === selectedRuleKey ? /* @__PURE__ */ jsx(Text, {
|
|
880
|
+
color: "green",
|
|
881
|
+
children: "✓ Copied fix prompt"
|
|
882
|
+
}) : keyHints,
|
|
883
|
+
exitHint,
|
|
884
|
+
compact: isCompact
|
|
858
885
|
})
|
|
859
886
|
});
|
|
860
|
-
const overlay = isMenuOpen && selected ? /* @__PURE__ */ jsx(Box, {
|
|
861
|
-
position: "absolute",
|
|
862
|
-
top: 0,
|
|
863
|
-
left: 0,
|
|
864
|
-
width,
|
|
865
|
-
height: Math.max(6, terminalRows - 2),
|
|
866
|
-
justifyContent: "center",
|
|
867
|
-
alignItems: "center",
|
|
868
|
-
children: /* @__PURE__ */ jsx(DiagnosticActionMenu, {
|
|
869
|
-
title: selected.title,
|
|
870
|
-
itemLabels: menuLabels,
|
|
871
|
-
focusedIndex: menuIndex,
|
|
872
|
-
maxWidth: width
|
|
873
|
-
})
|
|
874
|
-
}) : null;
|
|
875
887
|
if (isSplit) return /* @__PURE__ */ jsxs(Box, {
|
|
876
888
|
flexDirection: "column",
|
|
877
889
|
width,
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
/* @__PURE__ */ jsxs(Box, {
|
|
881
|
-
flexDirection: "
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
children:
|
|
887
|
-
marginTop: 1,
|
|
888
|
-
children: listColumn
|
|
889
|
-
})]
|
|
890
|
-
}), /* @__PURE__ */ jsx(Box, {
|
|
891
|
-
flexDirection: "column",
|
|
892
|
-
width: detailColumnWidth,
|
|
893
|
-
borderStyle: "single",
|
|
894
|
-
borderColor: "gray",
|
|
895
|
-
borderTop: false,
|
|
896
|
-
borderRight: false,
|
|
897
|
-
borderBottom: false,
|
|
898
|
-
paddingLeft: 1,
|
|
899
|
-
height: detailHeight,
|
|
900
|
-
overflowY: "hidden",
|
|
901
|
-
children: detailContent
|
|
890
|
+
children: [/* @__PURE__ */ jsxs(Box, {
|
|
891
|
+
flexDirection: "row",
|
|
892
|
+
children: [/* @__PURE__ */ jsxs(Box, {
|
|
893
|
+
flexDirection: "column",
|
|
894
|
+
width: listColumnWidth,
|
|
895
|
+
marginRight: 1,
|
|
896
|
+
children: [header, /* @__PURE__ */ jsx(Box, {
|
|
897
|
+
marginTop: 1,
|
|
898
|
+
children: listColumn
|
|
902
899
|
})]
|
|
903
|
-
}),
|
|
904
|
-
|
|
905
|
-
|
|
900
|
+
}), /* @__PURE__ */ jsx(Box, {
|
|
901
|
+
flexDirection: "column",
|
|
902
|
+
width: detailColumnWidth,
|
|
903
|
+
borderStyle: "single",
|
|
904
|
+
borderColor: "gray",
|
|
905
|
+
borderTop: false,
|
|
906
|
+
borderRight: false,
|
|
907
|
+
borderBottom: false,
|
|
908
|
+
paddingLeft: 1,
|
|
909
|
+
height: detailHeight,
|
|
910
|
+
overflowY: "hidden",
|
|
911
|
+
children: detailContent
|
|
912
|
+
})]
|
|
913
|
+
}), statusBar]
|
|
914
|
+
});
|
|
915
|
+
if (isCompact) return /* @__PURE__ */ jsxs(Box, {
|
|
916
|
+
flexDirection: "column",
|
|
917
|
+
width,
|
|
918
|
+
children: [
|
|
919
|
+
header,
|
|
920
|
+
listColumn,
|
|
921
|
+
statusBar
|
|
906
922
|
]
|
|
907
923
|
});
|
|
908
924
|
return /* @__PURE__ */ jsxs(Box, {
|
|
909
925
|
flexDirection: "column",
|
|
910
926
|
width,
|
|
911
|
-
position: "relative",
|
|
912
927
|
children: [
|
|
913
928
|
header,
|
|
914
929
|
/* @__PURE__ */ jsx(Box, {
|
|
@@ -925,8 +940,7 @@ const DiagnosticList = ({ header, rows, width, listColumnWidth, detailColumnWidt
|
|
|
925
940
|
overflowY: "hidden",
|
|
926
941
|
children: detailContent
|
|
927
942
|
}),
|
|
928
|
-
statusBar
|
|
929
|
-
overlay
|
|
943
|
+
statusBar
|
|
930
944
|
]
|
|
931
945
|
});
|
|
932
946
|
};
|
|
@@ -991,7 +1005,7 @@ const scoreColorName = (score) => {
|
|
|
991
1005
|
//#endregion
|
|
992
1006
|
//#region src/cli/ink/components/score-header.tsx
|
|
993
1007
|
const BRANDING = "https://react.doctor";
|
|
994
|
-
const ScoreHeader = ({ score, projectedScore, projectName, issueCount, noScoreMessage, width }) => {
|
|
1008
|
+
const ScoreHeader = ({ score, projectedScore, projectName, issueCount, noScoreMessage, width, compact = false }) => {
|
|
995
1009
|
const { columns } = useStdoutDimensions();
|
|
996
1010
|
const availableWidth = width ?? columns;
|
|
997
1011
|
const { stdout } = useStdout();
|
|
@@ -1001,6 +1015,42 @@ const ScoreHeader = ({ score, projectedScore, projectName, issueCount, noScoreMe
|
|
|
1001
1015
|
projectedScore,
|
|
1002
1016
|
animate: animate && score !== null
|
|
1003
1017
|
});
|
|
1018
|
+
if (compact) return score ? /* @__PURE__ */ jsxs(Text, {
|
|
1019
|
+
wrap: "truncate-end",
|
|
1020
|
+
children: [
|
|
1021
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1022
|
+
color: scoreColorName(score.score),
|
|
1023
|
+
bold: true,
|
|
1024
|
+
children: displayScore
|
|
1025
|
+
}),
|
|
1026
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
1027
|
+
dimColor: true,
|
|
1028
|
+
children: [
|
|
1029
|
+
" / ",
|
|
1030
|
+
100,
|
|
1031
|
+
" "
|
|
1032
|
+
]
|
|
1033
|
+
}),
|
|
1034
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1035
|
+
color: scoreColorName(score.score),
|
|
1036
|
+
children: score.label
|
|
1037
|
+
}),
|
|
1038
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
1039
|
+
dimColor: true,
|
|
1040
|
+
children: [" · ", projectName]
|
|
1041
|
+
})
|
|
1042
|
+
]
|
|
1043
|
+
}) : /* @__PURE__ */ jsxs(Text, {
|
|
1044
|
+
wrap: "truncate-end",
|
|
1045
|
+
children: [
|
|
1046
|
+
"React Doctor",
|
|
1047
|
+
" ",
|
|
1048
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
1049
|
+
dimColor: true,
|
|
1050
|
+
children: ["· ", noScoreMessage ?? `${issueCount} issues · ${projectName}`]
|
|
1051
|
+
})
|
|
1052
|
+
]
|
|
1053
|
+
});
|
|
1004
1054
|
if (!score) return /* @__PURE__ */ jsxs(Box, {
|
|
1005
1055
|
flexDirection: "column",
|
|
1006
1056
|
paddingLeft: 2,
|
|
@@ -1136,8 +1186,8 @@ const ScoreHeader = ({ score, projectedScore, projectName, issueCount, noScoreMe
|
|
|
1136
1186
|
};
|
|
1137
1187
|
//#endregion
|
|
1138
1188
|
//#region src/cli/ink/components/report.tsx
|
|
1139
|
-
const STACKED_FIXED_ROWS =
|
|
1140
|
-
const SPLIT_CHROME_ROWS =
|
|
1189
|
+
const STACKED_FIXED_ROWS = 11;
|
|
1190
|
+
const SPLIT_CHROME_ROWS = 10;
|
|
1141
1191
|
const EMPTY_LAUNCHABLE_AGENTS = [];
|
|
1142
1192
|
const Report = ({ report, onExit, launchableAgents = EMPTY_LAUNCHABLE_AGENTS, onHandoff, canAddToCi, onAddToCi, projectCount, priorityScores, exitHint = "q to quit" }) => {
|
|
1143
1193
|
const { rows: terminalRows, columns } = useStdoutDimensions();
|
|
@@ -1151,17 +1201,38 @@ const Report = ({ report, onExit, launchableAgents = EMPTY_LAUNCHABLE_AGENTS, on
|
|
|
1151
1201
|
}, { isActive: diagnosticRows.length === 0 });
|
|
1152
1202
|
const width = Math.max(24, columns - 2);
|
|
1153
1203
|
const isWide = columns >= 120 && terminalRows >= 22;
|
|
1154
|
-
const
|
|
1155
|
-
const
|
|
1204
|
+
const isCompact = !isWide && terminalRows <= TUI_REPORT_COMPACT_MAX_ROWS;
|
|
1205
|
+
const didRecordCompactReport = useRef(false);
|
|
1206
|
+
const didRecordStackedReportCap = useRef(false);
|
|
1207
|
+
useEffect(() => {
|
|
1208
|
+
if (!isCompact || didRecordCompactReport.current) return;
|
|
1209
|
+
didRecordCompactReport.current = true;
|
|
1210
|
+
recordCount(METRIC.tuiCompactReportShown);
|
|
1211
|
+
}, [isCompact]);
|
|
1212
|
+
const detailHeight = isWide ? Math.max(0, terminalRows - 3) : Math.max(0, Math.min(15, terminalRows - STACKED_FIXED_ROWS - 3));
|
|
1213
|
+
const availableListHeight = Math.max(3, terminalRows - (isWide ? SPLIT_CHROME_ROWS : STACKED_FIXED_ROWS + detailHeight));
|
|
1214
|
+
const isStackedReportCapped = !isCompact && !isWide && availableListHeight > 16;
|
|
1215
|
+
useEffect(() => {
|
|
1216
|
+
if (!isStackedReportCapped || didRecordStackedReportCap.current) return;
|
|
1217
|
+
didRecordStackedReportCap.current = true;
|
|
1218
|
+
recordCount(METRIC.tuiStackedReportCapped);
|
|
1219
|
+
}, [isStackedReportCapped]);
|
|
1220
|
+
let listHeight = availableListHeight;
|
|
1221
|
+
if (isCompact) listHeight = Math.max(3, terminalRows - 1 - 1);
|
|
1222
|
+
else if (!isWide) listHeight = Math.min(16, availableListHeight);
|
|
1156
1223
|
const detailColumnWidth = Math.max(20, Math.floor(width * TUI_REPORT_DETAIL_WIDTH_FRACTION));
|
|
1157
1224
|
const listColumnWidth = Math.max(20, width - detailColumnWidth - 3);
|
|
1225
|
+
let layout = "stacked";
|
|
1226
|
+
if (isCompact) layout = "compact";
|
|
1227
|
+
else if (isWide) layout = "split";
|
|
1158
1228
|
const scoreHeader = /* @__PURE__ */ jsx(ScoreHeader, {
|
|
1159
1229
|
score: report.score,
|
|
1160
1230
|
projectedScore: report.projectedScore,
|
|
1161
1231
|
projectName: report.projectName,
|
|
1162
1232
|
issueCount: report.diagnostics.length,
|
|
1163
1233
|
noScoreMessage: report.noScoreMessage,
|
|
1164
|
-
width: isWide ? listColumnWidth : width
|
|
1234
|
+
width: isWide ? listColumnWidth : width,
|
|
1235
|
+
compact: isCompact
|
|
1165
1236
|
});
|
|
1166
1237
|
if (diagnosticRows.length === 0) {
|
|
1167
1238
|
const lintFailureReason = report.lintFailureReason;
|
|
@@ -1194,7 +1265,7 @@ const Report = ({ report, onExit, launchableAgents = EMPTY_LAUNCHABLE_AGENTS, on
|
|
|
1194
1265
|
detailColumnWidth,
|
|
1195
1266
|
listHeight,
|
|
1196
1267
|
detailHeight,
|
|
1197
|
-
layout
|
|
1268
|
+
layout,
|
|
1198
1269
|
rootDirectory: report.rootDirectory,
|
|
1199
1270
|
projectName: report.projectName,
|
|
1200
1271
|
launchableAgents,
|
|
@@ -1228,7 +1299,7 @@ const Scanning = ({ progressText, liveCount, recent }) => {
|
|
|
1228
1299
|
]
|
|
1229
1300
|
}) : null
|
|
1230
1301
|
]
|
|
1231
|
-
}), recent.map((diagnostic) => {
|
|
1302
|
+
}), recent.map((diagnostic, diagnosticIndex) => {
|
|
1232
1303
|
const variant = severityVariant(diagnostic.severity === "error" ? "error" : "warning");
|
|
1233
1304
|
const location = formatDiagnosticSite(diagnostic);
|
|
1234
1305
|
return /* @__PURE__ */ jsxs(Text, {
|
|
@@ -1245,7 +1316,7 @@ const Scanning = ({ progressText, liveCount, recent }) => {
|
|
|
1245
1316
|
children: [" ", location]
|
|
1246
1317
|
})
|
|
1247
1318
|
]
|
|
1248
|
-
}, `${diagnostic.filePath}:${diagnostic.line}:${diagnostic.column}:${diagnostic.plugin}:${diagnostic.rule}`);
|
|
1319
|
+
}, `${diagnostic.filePath}:${diagnostic.line}:${diagnostic.column}:${diagnostic.plugin}:${diagnostic.rule}:${diagnosticIndex}`);
|
|
1249
1320
|
})]
|
|
1250
1321
|
});
|
|
1251
1322
|
};
|
|
@@ -1539,11 +1610,11 @@ const runMountedScan = async (rootDirectory, presentation, blockingLevel, execut
|
|
|
1539
1610
|
throw error;
|
|
1540
1611
|
}
|
|
1541
1612
|
};
|
|
1542
|
-
const runSingleProjectScan = async (rootScanTarget, projectDirectory, input, blockingLevel) => {
|
|
1613
|
+
const runSingleProjectScan = async (rootScanTarget, projectDirectory, input, blockingLevel, inspectProject) => {
|
|
1543
1614
|
const projectScan = await resolveProjectScan(rootScanTarget, projectDirectory);
|
|
1544
1615
|
const presentation = resolveScanPresentation(input, [projectScan]);
|
|
1545
1616
|
return runMountedScan(projectScan.directory, presentation, blockingLevel, async (context) => {
|
|
1546
|
-
const result = await
|
|
1617
|
+
const result = await inspectProject(projectScan.directory, {
|
|
1547
1618
|
...resolveTuiInspectOptions(input, projectScan.config),
|
|
1548
1619
|
isCi: isCiEnvironment(),
|
|
1549
1620
|
configOverride: projectScan.config,
|
|
@@ -1574,7 +1645,7 @@ const runSingleProjectScan = async (rootScanTarget, projectDirectory, input, blo
|
|
|
1574
1645
|
};
|
|
1575
1646
|
});
|
|
1576
1647
|
};
|
|
1577
|
-
const runMultiProjectScan = async (rootScanTarget, directories, input, blockingLevel) => {
|
|
1648
|
+
const runMultiProjectScan = async (rootScanTarget, directories, input, blockingLevel, inspectProject) => {
|
|
1578
1649
|
const rootDirectory = rootScanTarget.resolvedDirectory;
|
|
1579
1650
|
const projectScans = await mapWithConcurrency([...directories], 4, (projectDirectory) => resolveProjectScan(rootScanTarget, projectDirectory));
|
|
1580
1651
|
return runMountedScan(rootDirectory, resolveScanPresentation(input, projectScans), blockingLevel, async (context) => {
|
|
@@ -1582,7 +1653,7 @@ const runMultiProjectScan = async (rootScanTarget, directories, input, blockingL
|
|
|
1582
1653
|
let finishedCount = 0;
|
|
1583
1654
|
context.store.setProgress(`Scanning ${directories.length} projects…`);
|
|
1584
1655
|
const results = await mapWithConcurrency(projectScans, 4, async (projectScan) => {
|
|
1585
|
-
const result = await
|
|
1656
|
+
const result = await inspectProject(projectScan.directory, {
|
|
1586
1657
|
...resolveTuiInspectOptions(input, projectScan.config),
|
|
1587
1658
|
isCi: isCiEnvironment(),
|
|
1588
1659
|
configOverride: projectScan.config,
|
|
@@ -1649,13 +1720,14 @@ const runScanApp = async (input) => {
|
|
|
1649
1720
|
share: input.share ?? scanTarget.userConfig?.share ?? true
|
|
1650
1721
|
};
|
|
1651
1722
|
const selectedDirectories = await resolveSelectedDirectories(rootDirectory, resolvedInput);
|
|
1723
|
+
const inspectProject = createInvocationInspect(input.options?.concurrency);
|
|
1652
1724
|
const blockingLevel = resolveBlockingLevel({ blocking: resolvedInput.blocking }, scanTarget.userConfig);
|
|
1653
1725
|
if (selectedDirectories.length === 0) return { shouldFail: false };
|
|
1654
|
-
if (selectedDirectories.length === 1) return runSingleProjectScan(scanTarget, selectedDirectories[0], resolvedInput, blockingLevel);
|
|
1655
|
-
return runMultiProjectScan(scanTarget, selectedDirectories, resolvedInput, blockingLevel);
|
|
1726
|
+
if (selectedDirectories.length === 1) return runSingleProjectScan(scanTarget, selectedDirectories[0], resolvedInput, blockingLevel, inspectProject);
|
|
1727
|
+
return runMultiProjectScan(scanTarget, selectedDirectories, resolvedInput, blockingLevel, inspectProject);
|
|
1656
1728
|
};
|
|
1657
1729
|
//#endregion
|
|
1658
1730
|
export { runScanApp };
|
|
1659
1731
|
|
|
1660
|
-
//# sourceMappingURL=run-scan-app-
|
|
1661
|
-
//# debugId=
|
|
1732
|
+
//# sourceMappingURL=run-scan-app-DHRvqfkX.js.map
|
|
1733
|
+
//# debugId=898bdb3e-afed-5fca-92a2-f14d1e8ca6fb
|