react-doctor 0.2.10 → 0.2.11-dev.d917f62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{cli-logger-BRBUS1pE.js → cli-logger-Df45H6Lw.js} +221 -130
- package/dist/cli.js +21 -14
- package/dist/index.d.ts +17 -8
- package/dist/index.js +225 -133
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as __toESM, n as __exportAll, r as __require, t as __commonJSMin } from "./rolldown-runtime-uZX_iqCz.js";
|
|
2
|
-
import { A as isReactDoctorError, C as filterSourceFiles, D as groupBy, E as getDiffInfo, F as runInspect, I as toRelativePath, M as listWorkspacePackages, N as resolveScanTarget, O as highlighter, P as restoreLegacyThrow, S as filterDiagnosticsForSurface, T as formatReactDoctorError, _ as Score, a as DeadCode, b as buildJsonReportError, c as LintPartialFailures, d as OXLINT_NODE_REQUIREMENT, f as Progress, g as SKILL_NAME, h as SHARE_BASE_URL, i as Config, j as layerOtlp, k as isMonorepoRoot, l as Linter, m as Reporter, o as Files, p as Project, r as CANONICAL_GITHUB_URL, s as Git, t as cliLogger, u as NodeResolver, v as StagedFiles, w as formatErrorChain, x as discoverReactSubprojects, y as buildJsonReport } from "./cli-logger-
|
|
2
|
+
import { A as isReactDoctorError, C as filterSourceFiles, D as groupBy, E as getDiffInfo, F as runInspect, I as toRelativePath, M as listWorkspacePackages, N as resolveScanTarget, O as highlighter, P as restoreLegacyThrow, S as filterDiagnosticsForSurface, T as formatReactDoctorError, _ as Score, a as DeadCode, b as buildJsonReportError, c as LintPartialFailures, d as OXLINT_NODE_REQUIREMENT, f as Progress, g as SKILL_NAME, h as SHARE_BASE_URL, i as Config, j as layerOtlp, k as isMonorepoRoot, l as Linter, m as Reporter, o as Files, p as Project, r as CANONICAL_GITHUB_URL, s as Git, t as cliLogger, u as NodeResolver, v as StagedFiles, w as formatErrorChain, x as discoverReactSubprojects, y as buildJsonReport } from "./cli-logger-Df45H6Lw.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { execFileSync, execSync } from "node:child_process";
|
|
5
5
|
import path, { join } from "node:path";
|
|
@@ -6666,7 +6666,7 @@ const resolveOxlintNodeEffect = (isLintEnabled, isQuiet) => Effect.gen(function*
|
|
|
6666
6666
|
const resolveOxlintNode = (isLintEnabled, isQuiet) => Effect.runPromise(resolveOxlintNodeEffect(isLintEnabled, isQuiet).pipe(Effect.provide(NodeResolver.layerNode)));
|
|
6667
6667
|
//#endregion
|
|
6668
6668
|
//#region src/cli/utils/version.ts
|
|
6669
|
-
const VERSION = "0.2.
|
|
6669
|
+
const VERSION = "0.2.11-dev.d917f62";
|
|
6670
6670
|
//#endregion
|
|
6671
6671
|
//#region src/inspect.ts
|
|
6672
6672
|
const silentConsole = makeNoopConsole();
|
|
@@ -6764,9 +6764,7 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
|
|
|
6764
6764
|
const output = await Effect.runPromise(restoreLegacyThrow(programWithLayers));
|
|
6765
6765
|
const didLintFail = lintBindingMissing || output.didLintFail;
|
|
6766
6766
|
const lintFailureReason = lintBindingMissing ? `oxlint native binding not found for Node ${process.version}; expected one matching ${OXLINT_NODE_REQUIREMENT}` : output.lintFailureReason;
|
|
6767
|
-
|
|
6768
|
-
const isNativeBindingFailure = lintFailureReasonTag === "OxlintUnavailable" || lintFailureReasonTag === "OxlintSpawnFailed";
|
|
6769
|
-
if (!options.scoreOnly && !lintBindingMissing && output.didLintFail && lintFailureReason !== null) if (isNativeBindingFailure && /native binding/.test(lintFailureReason)) runConsole(Console.log(highlighter.gray(` Upgrade to Node ${OXLINT_NODE_REQUIREMENT} or run: npx -p oxlint@latest react-doctor@latest`)));
|
|
6767
|
+
if (!options.scoreOnly && !lintBindingMissing && output.didLintFail && lintFailureReason !== null) if (output.lintFailureReasonKind === "native-binding-missing") runConsole(Console.log(highlighter.gray(` Upgrade to Node ${OXLINT_NODE_REQUIREMENT} or run: npx -p oxlint@latest react-doctor@latest`)));
|
|
6770
6768
|
else runConsole(Console.error(highlighter.error(lintFailureReason)));
|
|
6771
6769
|
const inspectDiagnostics = output.diagnostics;
|
|
6772
6770
|
const score = didLintFail ? null : output.score;
|
|
@@ -7463,7 +7461,7 @@ const warnSetupPromptFailure = async (options, error) => {
|
|
|
7463
7461
|
return;
|
|
7464
7462
|
}
|
|
7465
7463
|
try {
|
|
7466
|
-
const { cliLogger } = await import("./cli-logger-
|
|
7464
|
+
const { cliLogger } = await import("./cli-logger-Df45H6Lw.js").then((n) => n.n);
|
|
7467
7465
|
cliLogger.warn(message);
|
|
7468
7466
|
} catch {}
|
|
7469
7467
|
};
|
|
@@ -7566,12 +7564,14 @@ const resolveDiffMode = async (diffInfo, effectiveDiff, shouldSkipPrompts, isQui
|
|
|
7566
7564
|
message: "Choose what to scan",
|
|
7567
7565
|
choices: [{
|
|
7568
7566
|
title: "Full codebase",
|
|
7567
|
+
description: "Scan every source file",
|
|
7569
7568
|
value: "full"
|
|
7570
7569
|
}, {
|
|
7571
|
-
title: `Changed files (${changedSourceFiles.length})`,
|
|
7570
|
+
title: diffInfo.isCurrentChanges ? `Uncommitted changes (${changedSourceFiles.length})` : `Changed files on ${diffInfo.currentBranch ?? "this branch"} (${changedSourceFiles.length})`,
|
|
7571
|
+
description: diffInfo.isCurrentChanges ? "Compare working tree changes against HEAD" : `Compare against ${diffInfo.baseBranch} from the branch merge-base`,
|
|
7572
7572
|
value: "branch"
|
|
7573
7573
|
}],
|
|
7574
|
-
initial: 0
|
|
7574
|
+
initial: diffInfo.isCurrentChanges ? 0 : 1
|
|
7575
7575
|
});
|
|
7576
7576
|
return scanScope === "branch";
|
|
7577
7577
|
};
|
|
@@ -7601,13 +7601,13 @@ const VALID_FAIL_ON_LEVELS = new Set([
|
|
|
7601
7601
|
"warning",
|
|
7602
7602
|
"none"
|
|
7603
7603
|
]);
|
|
7604
|
-
const DEFAULT_FAIL_ON_LEVEL = "
|
|
7604
|
+
const DEFAULT_FAIL_ON_LEVEL = "none";
|
|
7605
7605
|
const isValidFailOnLevel = (level) => VALID_FAIL_ON_LEVELS.has(level);
|
|
7606
7606
|
const resolveFailOnLevel = (flags, userConfig) => {
|
|
7607
7607
|
const sourceValue = flags.failOn ?? userConfig?.failOn ?? DEFAULT_FAIL_ON_LEVEL;
|
|
7608
7608
|
if (isValidFailOnLevel(sourceValue)) return sourceValue;
|
|
7609
|
-
cliLogger.warn(`Invalid failOn level "${sourceValue}". Expected one of: error, warning, none. Falling back to "
|
|
7610
|
-
return
|
|
7609
|
+
cliLogger.warn(`Invalid failOn level "${sourceValue}". Expected one of: error, warning, none. Falling back to "${DEFAULT_FAIL_ON_LEVEL}".`);
|
|
7610
|
+
return DEFAULT_FAIL_ON_LEVEL;
|
|
7611
7611
|
};
|
|
7612
7612
|
//#endregion
|
|
7613
7613
|
//#region src/cli/utils/resolve-project-diff-include-paths.ts
|
|
@@ -7892,7 +7892,14 @@ const inspectAction = async (directory, flags) => {
|
|
|
7892
7892
|
cliLogger.log(`Scanning ${highlighter.info(`${stagedFiles.length}`)} staged files...`);
|
|
7893
7893
|
cliLogger.break();
|
|
7894
7894
|
}
|
|
7895
|
-
const
|
|
7895
|
+
const tempDirectory = mkdtempSync(path.join(tmpdir(), STAGED_FILES_TEMP_DIR_PREFIX));
|
|
7896
|
+
const snapshot = await materializeStagedFiles(resolvedDirectory, stagedFiles, tempDirectory).catch((error) => {
|
|
7897
|
+
rmSync(tempDirectory, {
|
|
7898
|
+
recursive: true,
|
|
7899
|
+
force: true
|
|
7900
|
+
});
|
|
7901
|
+
throw error;
|
|
7902
|
+
});
|
|
7896
7903
|
try {
|
|
7897
7904
|
const scanResult = await inspect(snapshot.tempDirectory, {
|
|
7898
7905
|
...scanOptions,
|
|
@@ -7901,7 +7908,7 @@ const inspectAction = async (directory, flags) => {
|
|
|
7901
7908
|
});
|
|
7902
7909
|
const remappedDiagnostics = scanResult.diagnostics.map((diagnostic) => ({
|
|
7903
7910
|
...diagnostic,
|
|
7904
|
-
filePath: path.isAbsolute(diagnostic.filePath) ? diagnostic.filePath.replaceAll(snapshot.tempDirectory, resolvedDirectory) : diagnostic.filePath
|
|
7911
|
+
filePath: path.isAbsolute(diagnostic.filePath) ? diagnostic.filePath.replaceAll(snapshot.tempDirectory, () => resolvedDirectory) : diagnostic.filePath
|
|
7905
7912
|
}));
|
|
7906
7913
|
finalizeScans({
|
|
7907
7914
|
diagnostics: remappedDiagnostics,
|
|
@@ -9139,7 +9146,7 @@ const stripUnknownCliFlags = (argv) => {
|
|
|
9139
9146
|
//#region src/cli/index.ts
|
|
9140
9147
|
process.on("SIGINT", exitGracefully);
|
|
9141
9148
|
process.on("SIGTERM", exitGracefully);
|
|
9142
|
-
const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("-y, --yes", "skip prompts, scan all workspace projects").option("--full", "force a full scan (overrides any `diff` value in config or `--diff`)").option("--project <name>", "select workspace project (comma-separated for multiple)").option("--diff [base]", "scan only files changed vs base branch (pass `false` to disable; overridden by --full)").option("--no-score", "skip the score API and the share URL").option("--staged", "scan only staged (git index) files for pre-commit hooks").option("--fail-on <level>", "exit with error code on diagnostics: error, warning, none (default:
|
|
9149
|
+
const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("-y, --yes", "skip prompts, scan all workspace projects").option("--full", "force a full scan (overrides any `diff` value in config or `--diff`)").option("--project <name>", "select workspace project (comma-separated for multiple)").option("--diff [base]", "scan only files changed vs base branch (pass `false` to disable; overridden by --full)").option("--no-score", "skip the score API and the share URL").option("--staged", "scan only staged (git index) files for pre-commit hooks").option("--fail-on <level>", "exit with error code on diagnostics: error, warning, none (default: none)").option("--annotations", "output diagnostics as GitHub Actions annotations").option("--pr-comment", "tune CLI output for sticky PR comments (drops weak-signal rule families like `design` from the printed list and the fail-on gate; configure via config.surfaces)").option("--explain <file:line>", "diagnose why a rule fired or why a suppression didn't apply at a specific location").option("--why <file:line>", "alias for --explain").option("--respect-inline-disables", "respect inline `// eslint-disable*` / `// oxlint-disable*` comments (default)").option("--no-respect-inline-disables", "audit mode: neutralize inline lint suppressions before scanning").addHelpText("after", `
|
|
9143
9150
|
${highlighter.dim("Configuration:")}
|
|
9144
9151
|
Place a ${highlighter.info("react-doctor.config.json")} (or ${highlighter.info("\"reactDoctor\"")} key in your package.json) in the project root.
|
|
9145
9152
|
CLI flags always override config values. See the README for the full schema.
|
package/dist/index.d.ts
CHANGED
|
@@ -310,15 +310,17 @@ interface ProjectInfo {
|
|
|
310
310
|
hasReactCompiler: boolean;
|
|
311
311
|
hasTanStackQuery: boolean;
|
|
312
312
|
/**
|
|
313
|
-
*
|
|
314
|
-
* dependency
|
|
315
|
-
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
313
|
+
* The declared `preact` version spec, or `null` when Preact isn't a
|
|
314
|
+
* dependency. Parallels `reactVersion` so a React-compatible runtime is
|
|
315
|
+
* modeled the same way React is. Drives the `preact` capability in
|
|
316
|
+
* `buildCapabilities` (which gates every `preact-*` rule) — keyed off
|
|
317
|
+
* this rather than `framework` because the dominant Preact setup
|
|
318
|
+
* (Preact-on-Vite) classifies as `framework: "vite"` but still needs
|
|
319
|
+
* Preact rules to fire.
|
|
320
320
|
*/
|
|
321
|
-
|
|
321
|
+
preactVersion: string | null;
|
|
322
|
+
/** Parsed major from `preactVersion`, or `null` when absent/unparseable. Mirrors `reactMajorVersion`. */
|
|
323
|
+
preactMajorVersion: number | null;
|
|
322
324
|
/**
|
|
323
325
|
* `true` when the project (or any of its workspace packages) declares
|
|
324
326
|
* React Native or Expo as a dependency. Enables the `react-native`
|
|
@@ -333,6 +335,13 @@ interface ProjectInfo {
|
|
|
333
335
|
* — no `rn-*` rules load for the project at all.
|
|
334
336
|
*/
|
|
335
337
|
hasReactNativeWorkspace: boolean;
|
|
338
|
+
/**
|
|
339
|
+
* `true` when the project (or any of its workspace packages) declares
|
|
340
|
+
* `react-native-reanimated`. Lets diagnostics surface reanimated's
|
|
341
|
+
* Compiler-compatible `.get()` / `.set()` accessors only where they
|
|
342
|
+
* apply, instead of on every React Native project.
|
|
343
|
+
*/
|
|
344
|
+
hasReanimated: boolean;
|
|
336
345
|
sourceFileCount: number;
|
|
337
346
|
}
|
|
338
347
|
//#endregion
|