react-doctor 0.2.14-dev.ac3ca1a → 0.2.14-dev.b612664
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 -0
- package/dist/{cli-logger-Cqq0L4Uo.js → cli-logger-BgVL1vBI.js} +16 -12
- package/dist/cli.js +34 -13
- package/dist/index.d.ts +6 -0
- package/dist/index.js +15 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -69,6 +69,8 @@ jobs:
|
|
|
69
69
|
|
|
70
70
|
React Doctor scans the files changed in the pull request, emits inline annotations, blocks on error-level findings, and updates one sticky PR comment with the score and issue summary. The built-in GitHub token is used automatically; no secret or PAT is required. On forked PRs where GitHub withholds write permissions, the scan and annotations still run, but the sticky comment may be skipped.
|
|
71
71
|
|
|
72
|
+
**Permissions:** set `permissions: { contents: read, pull-requests: write }` so React Doctor can read the pull request's changed files for a changed-files-only scan and post the sticky summary comment. If `pull-requests: read` is unavailable (for example on fork PRs or with a restricted default token), the action degrades gracefully to a full-project scan instead of failing.
|
|
73
|
+
|
|
72
74
|
[Add GitHub Action →](https://github.com/marketplace/actions/react-doctor)
|
|
73
75
|
|
|
74
76
|
### 4. Configure rules in `react-doctor.config.json`
|
|
@@ -6941,17 +6941,21 @@ var Reporter = class Reporter extends Context.Service()("react-doctor/Reporter")
|
|
|
6941
6941
|
});
|
|
6942
6942
|
}));
|
|
6943
6943
|
};
|
|
6944
|
-
const
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6944
|
+
const RulePrioritySchema = Schema.Struct({
|
|
6945
|
+
priority: Schema.NullOr(Schema.Number),
|
|
6946
|
+
tier: Schema.Literals([
|
|
6947
|
+
"P0",
|
|
6948
|
+
"P1",
|
|
6949
|
+
"P2",
|
|
6950
|
+
"P3"
|
|
6951
|
+
])
|
|
6952
|
+
});
|
|
6953
|
+
const ScoreApiResponseSchema = Schema.Struct({
|
|
6954
|
+
score: Schema.Number,
|
|
6955
|
+
label: Schema.String,
|
|
6956
|
+
rules: Schema.optional(Schema.Record(Schema.String, RulePrioritySchema))
|
|
6957
|
+
});
|
|
6958
|
+
const parseScoreResult = (value) => Option.getOrNull(Schema.decodeUnknownOption(ScoreApiResponseSchema)(value));
|
|
6955
6959
|
const stripFilePaths = (diagnostics) => diagnostics.map(({ filePath: _filePath, ...rest }) => rest);
|
|
6956
6960
|
const isAbortError = (error) => error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError");
|
|
6957
6961
|
const describeFailure = (error) => {
|
|
@@ -7715,4 +7719,4 @@ const cliLogger = {
|
|
|
7715
7719
|
//#endregion
|
|
7716
7720
|
export { highlighter as A, discoverReactSubprojects as C, formatReactDoctorError as D, formatErrorChain as E, resolveScanTarget as F, restoreLegacyThrow as I, runInspect as L, isReactDoctorError as M, layerOtlp as N, getDiffInfo as O, listWorkspacePackages as P, toRelativePath as R, buildRulePromptUrl as S, filterSourceFiles as T, SKILL_NAME as _, DeadCode as a, buildJsonReport as b, Git as c, NodeResolver as d, OXLINT_NODE_REQUIREMENT as f, SHARE_BASE_URL as g, Reporter as h, Config as i, isMonorepoRoot as j, groupBy as k, LintPartialFailures as l, Project as m, cli_logger_exports as n, ENTERPRISE_CONTACT_URL as o, Progress as p, CANONICAL_GITHUB_URL as r, Files as s, cliLogger as t, Linter as u, Score as v, filterDiagnosticsForSurface as w, buildJsonReportError as x, StagedFiles as y };
|
|
7717
7721
|
|
|
7718
|
-
//# sourceMappingURL=cli-logger-
|
|
7722
|
+
//# sourceMappingURL=cli-logger-BgVL1vBI.js.map
|
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 highlighter, C as discoverReactSubprojects, D as formatReactDoctorError, E as formatErrorChain, F as resolveScanTarget, I as restoreLegacyThrow, L as runInspect, M as isReactDoctorError, N as layerOtlp, O as getDiffInfo, P as listWorkspacePackages, R as toRelativePath, S as buildRulePromptUrl, T as filterSourceFiles, _ as SKILL_NAME, a as DeadCode, b as buildJsonReport, c as Git, d as NodeResolver, f as OXLINT_NODE_REQUIREMENT, g as SHARE_BASE_URL, h as Reporter, i as Config, j as isMonorepoRoot, k as groupBy, l as LintPartialFailures, m as Project, o as ENTERPRISE_CONTACT_URL, p as Progress, r as CANONICAL_GITHUB_URL, s as Files, t as cliLogger, u as Linter, v as Score, w as filterDiagnosticsForSurface, x as buildJsonReportError, y as StagedFiles } from "./cli-logger-
|
|
2
|
+
import { A as highlighter, C as discoverReactSubprojects, D as formatReactDoctorError, E as formatErrorChain, F as resolveScanTarget, I as restoreLegacyThrow, L as runInspect, M as isReactDoctorError, N as layerOtlp, O as getDiffInfo, P as listWorkspacePackages, R as toRelativePath, S as buildRulePromptUrl, T as filterSourceFiles, _ as SKILL_NAME, a as DeadCode, b as buildJsonReport, c as Git, d as NodeResolver, f as OXLINT_NODE_REQUIREMENT, g as SHARE_BASE_URL, h as Reporter, i as Config, j as isMonorepoRoot, k as groupBy, l as LintPartialFailures, m as Project, o as ENTERPRISE_CONTACT_URL, p as Progress, r as CANONICAL_GITHUB_URL, s as Files, t as cliLogger, u as Linter, v as Score, w as filterDiagnosticsForSurface, x as buildJsonReportError, y as StagedFiles } from "./cli-logger-BgVL1vBI.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";
|
|
@@ -6198,7 +6198,22 @@ const SEVERITY_ORDER = {
|
|
|
6198
6198
|
warning: 1
|
|
6199
6199
|
};
|
|
6200
6200
|
const colorizeBySeverity = (text, severity) => severity === "error" ? highlighter.error(text) : highlighter.warn(text);
|
|
6201
|
-
const
|
|
6201
|
+
const buildRulePriorityMap = (scores) => {
|
|
6202
|
+
const rulePriority = /* @__PURE__ */ new Map();
|
|
6203
|
+
for (const score of scores) {
|
|
6204
|
+
if (!score?.rules) continue;
|
|
6205
|
+
for (const [ruleKey, info] of Object.entries(score.rules)) if (typeof info.priority === "number") rulePriority.set(ruleKey, info.priority);
|
|
6206
|
+
}
|
|
6207
|
+
return rulePriority;
|
|
6208
|
+
};
|
|
6209
|
+
const effectivePriority = (ruleKey, diagnostics, rulePriority) => {
|
|
6210
|
+
const known = rulePriority?.get(ruleKey);
|
|
6211
|
+
if (known !== void 0) return known;
|
|
6212
|
+
return diagnostics[0].severity === "error" ? 55 : 35;
|
|
6213
|
+
};
|
|
6214
|
+
const sortByImportance = (diagnosticGroups, rulePriority) => diagnosticGroups.toSorted(([ruleKeyA, diagnosticsA], [ruleKeyB, diagnosticsB]) => {
|
|
6215
|
+
const priorityDelta = effectivePriority(ruleKeyB, diagnosticsB, rulePriority) - effectivePriority(ruleKeyA, diagnosticsA, rulePriority);
|
|
6216
|
+
if (priorityDelta !== 0) return priorityDelta;
|
|
6202
6217
|
const severityDelta = SEVERITY_ORDER[diagnosticsA[0].severity] - SEVERITY_ORDER[diagnosticsB[0].severity];
|
|
6203
6218
|
if (severityDelta !== 0) return severityDelta;
|
|
6204
6219
|
return diagnosticsB.length - diagnosticsA.length;
|
|
@@ -6235,14 +6250,20 @@ const buildCompactRuleGroupLine = (ruleKey, ruleDiagnostics, ruleNameColumnWidth
|
|
|
6235
6250
|
return ` ${icon} ${siteCountBadge.length > 0 ? colorizeBySeverity(padRuleNameToColumn(ruleKey, ruleNameColumnWidth), firstDiagnostic.severity) : colorizeBySeverity(ruleKey, firstDiagnostic.severity)}${siteCountBadge.length > 0 ? ` ${highlighter.gray(siteCountBadge)}` : ""}`;
|
|
6236
6251
|
};
|
|
6237
6252
|
const getWorstSeverity = (diagnostics) => diagnostics.some((diagnostic) => diagnostic.severity === "error") ? "error" : "warning";
|
|
6238
|
-
const
|
|
6253
|
+
const categoryTopPriority = (categoryGroup, rulePriority) => {
|
|
6254
|
+
const [topRuleKey, topDiagnostics] = categoryGroup.ruleGroups[0];
|
|
6255
|
+
return effectivePriority(topRuleKey, topDiagnostics, rulePriority);
|
|
6256
|
+
};
|
|
6257
|
+
const buildCategoryDiagnosticGroups = (diagnostics, rulePriority) => {
|
|
6239
6258
|
return [...groupBy(diagnostics, (diagnostic) => diagnostic.category).entries()].map(([category, categoryDiagnostics]) => {
|
|
6240
6259
|
return {
|
|
6241
6260
|
category,
|
|
6242
6261
|
diagnostics: categoryDiagnostics,
|
|
6243
|
-
ruleGroups: sortByImportance([...groupBy(categoryDiagnostics, (diagnostic) => `${diagnostic.plugin}/${diagnostic.rule}`).entries()])
|
|
6262
|
+
ruleGroups: sortByImportance([...groupBy(categoryDiagnostics, (diagnostic) => `${diagnostic.plugin}/${diagnostic.rule}`).entries()], rulePriority)
|
|
6244
6263
|
};
|
|
6245
6264
|
}).toSorted((categoryGroupA, categoryGroupB) => {
|
|
6265
|
+
const priorityDelta = categoryTopPriority(categoryGroupB, rulePriority) - categoryTopPriority(categoryGroupA, rulePriority);
|
|
6266
|
+
if (priorityDelta !== 0) return priorityDelta;
|
|
6246
6267
|
const severityDelta = SEVERITY_ORDER[getWorstSeverity(categoryGroupA.diagnostics)] - SEVERITY_ORDER[getWorstSeverity(categoryGroupB.diagnostics)];
|
|
6247
6268
|
if (severityDelta !== 0) return severityDelta;
|
|
6248
6269
|
if (categoryGroupA.diagnostics.length !== categoryGroupB.diagnostics.length) return categoryGroupB.diagnostics.length - categoryGroupA.diagnostics.length;
|
|
@@ -6273,8 +6294,8 @@ const buildVerboseRuleGroupLines = (ruleKey, ruleDiagnostics, ruleNameColumnWidt
|
|
|
6273
6294
|
lines.push("");
|
|
6274
6295
|
return lines;
|
|
6275
6296
|
};
|
|
6276
|
-
const buildDefaultDiagnosticsLines = (diagnostics) => {
|
|
6277
|
-
const categoryGroups = buildCategoryDiagnosticGroups(diagnostics);
|
|
6297
|
+
const buildDefaultDiagnosticsLines = (diagnostics, rulePriority) => {
|
|
6298
|
+
const categoryGroups = buildCategoryDiagnosticGroups(diagnostics, rulePriority);
|
|
6278
6299
|
const lines = [];
|
|
6279
6300
|
for (const categoryGroup of categoryGroups) lines.push(buildCompactCategoryLine(categoryGroup));
|
|
6280
6301
|
lines.push("");
|
|
@@ -6286,11 +6307,11 @@ const buildDefaultDiagnosticsLines = (diagnostics) => {
|
|
|
6286
6307
|
* single Effect.forEach over Console.log so failures or fiber
|
|
6287
6308
|
* interruption produce predictable partial output.
|
|
6288
6309
|
*/
|
|
6289
|
-
const printDiagnostics = (diagnostics, isVerbose, rootDirectory) => Effect.gen(function* () {
|
|
6310
|
+
const printDiagnostics = (diagnostics, isVerbose, rootDirectory, rulePriority) => Effect.gen(function* () {
|
|
6290
6311
|
let lines;
|
|
6291
|
-
if (!isVerbose) lines = buildDefaultDiagnosticsLines(diagnostics);
|
|
6312
|
+
if (!isVerbose) lines = buildDefaultDiagnosticsLines(diagnostics, rulePriority);
|
|
6292
6313
|
else {
|
|
6293
|
-
const sortedRuleGroups = sortByImportance([...groupBy(diagnostics, (diagnostic) => `${diagnostic.plugin}/${diagnostic.rule}`).entries()]);
|
|
6314
|
+
const sortedRuleGroups = sortByImportance([...groupBy(diagnostics, (diagnostic) => `${diagnostic.plugin}/${diagnostic.rule}`).entries()], rulePriority);
|
|
6294
6315
|
const ruleNameColumnWidth = computeRuleNameColumnWidth(sortedRuleGroups.map(([ruleKey]) => ruleKey));
|
|
6295
6316
|
lines = sortedRuleGroups.flatMap(([ruleKey, ruleDiagnostics]) => buildVerboseRuleGroupLines(ruleKey, ruleDiagnostics, ruleNameColumnWidth));
|
|
6296
6317
|
}
|
|
@@ -6686,7 +6707,7 @@ const resolveOxlintNodeEffect = (isLintEnabled, isQuiet) => Effect.gen(function*
|
|
|
6686
6707
|
const resolveOxlintNode = (isLintEnabled, isQuiet) => Effect.runPromise(resolveOxlintNodeEffect(isLintEnabled, isQuiet).pipe(Effect.provide(NodeResolver.layerNode)));
|
|
6687
6708
|
//#endregion
|
|
6688
6709
|
//#region src/cli/utils/version.ts
|
|
6689
|
-
const VERSION = "0.2.14-dev.
|
|
6710
|
+
const VERSION = "0.2.14-dev.b612664";
|
|
6690
6711
|
//#endregion
|
|
6691
6712
|
//#region src/inspect.ts
|
|
6692
6713
|
const silentConsole = makeNoopConsole();
|
|
@@ -6847,7 +6868,7 @@ const finalizeAndRender = (input) => Effect.gen(function* () {
|
|
|
6847
6868
|
return buildResult();
|
|
6848
6869
|
}
|
|
6849
6870
|
yield* Console.log("");
|
|
6850
|
-
yield* printDiagnostics([...surfaceDiagnostics], options.verbose, directory);
|
|
6871
|
+
yield* printDiagnostics([...surfaceDiagnostics], options.verbose, directory, buildRulePriorityMap([score]));
|
|
6851
6872
|
if (options.isNonInteractiveEnvironment && options.outputSurface !== "prComment") yield* printAgentGuidance();
|
|
6852
6873
|
if (demotedDiagnosticCount > 0) {
|
|
6853
6874
|
yield* Console.log(highlighter.gray(` ${demotedDiagnosticCount} demoted from the ${options.outputSurface} surface (e.g. design cleanup) — run \`npx react-doctor@latest .\` locally for the full list.`));
|
|
@@ -7236,7 +7257,7 @@ const printMultiProjectSummary = (input) => Effect.gen(function* () {
|
|
|
7236
7257
|
const surfaceDiagnostics = filterDiagnosticsForSurface(completedScans.flatMap((scan) => scan.result.diagnostics), "cli", userConfig);
|
|
7237
7258
|
if (surfaceDiagnostics.length > 0) {
|
|
7238
7259
|
yield* Console.log("");
|
|
7239
|
-
yield* printDiagnostics(surfaceDiagnostics, verbose, "");
|
|
7260
|
+
yield* printDiagnostics(surfaceDiagnostics, verbose, "", buildRulePriorityMap(completedScans.map((scan) => scan.result.score)));
|
|
7240
7261
|
}
|
|
7241
7262
|
const aggregateScore = computeAggregateScore(completedScans);
|
|
7242
7263
|
const totalSourceFileCount = completedScans.reduce((sum, scan) => sum + scan.result.project.sourceFileCount, 0);
|
|
@@ -7507,7 +7528,7 @@ const warnSetupPromptFailure = async (options, error) => {
|
|
|
7507
7528
|
return;
|
|
7508
7529
|
}
|
|
7509
7530
|
try {
|
|
7510
|
-
const { cliLogger } = await import("./cli-logger-
|
|
7531
|
+
const { cliLogger } = await import("./cli-logger-BgVL1vBI.js").then((n) => n.n);
|
|
7511
7532
|
cliLogger.warn(message);
|
|
7512
7533
|
} catch {}
|
|
7513
7534
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -349,9 +349,15 @@ interface ProjectInfo {
|
|
|
349
349
|
}
|
|
350
350
|
//#endregion
|
|
351
351
|
//#region src/types/score.d.ts
|
|
352
|
+
type RuleTier = "P0" | "P1" | "P2" | "P3";
|
|
353
|
+
interface RulePriority {
|
|
354
|
+
readonly priority: number | null;
|
|
355
|
+
readonly tier: RuleTier;
|
|
356
|
+
}
|
|
352
357
|
interface ScoreResult {
|
|
353
358
|
score: number;
|
|
354
359
|
label: string;
|
|
360
|
+
readonly rules?: Readonly<Record<string, RulePriority>>;
|
|
355
361
|
} //#endregion
|
|
356
362
|
//#region src/types/diagnose.d.ts
|
|
357
363
|
interface DiagnoseOptions {
|
package/dist/index.js
CHANGED
|
@@ -6970,17 +6970,21 @@ var Reporter = class Reporter extends Context.Service()("react-doctor/Reporter")
|
|
|
6970
6970
|
});
|
|
6971
6971
|
}));
|
|
6972
6972
|
};
|
|
6973
|
-
const
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6973
|
+
const RulePrioritySchema = Schema.Struct({
|
|
6974
|
+
priority: Schema.NullOr(Schema.Number),
|
|
6975
|
+
tier: Schema.Literals([
|
|
6976
|
+
"P0",
|
|
6977
|
+
"P1",
|
|
6978
|
+
"P2",
|
|
6979
|
+
"P3"
|
|
6980
|
+
])
|
|
6981
|
+
});
|
|
6982
|
+
const ScoreApiResponseSchema = Schema.Struct({
|
|
6983
|
+
score: Schema.Number,
|
|
6984
|
+
label: Schema.String,
|
|
6985
|
+
rules: Schema.optional(Schema.Record(Schema.String, RulePrioritySchema))
|
|
6986
|
+
});
|
|
6987
|
+
const parseScoreResult = (value) => Option.getOrNull(Schema.decodeUnknownOption(ScoreApiResponseSchema)(value));
|
|
6984
6988
|
const stripFilePaths = (diagnostics) => diagnostics.map(({ filePath: _filePath, ...rest }) => rest);
|
|
6985
6989
|
const isAbortError = (error) => error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError");
|
|
6986
6990
|
const describeFailure = (error) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-doctor",
|
|
3
|
-
"version": "0.2.14-dev.
|
|
3
|
+
"version": "0.2.14-dev.b612664",
|
|
4
4
|
"description": "Diagnose and fix React codebases for security, performance, correctness, accessibility, bundle-size, and architecture issues",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"oxlint": "^1.66.0",
|
|
59
59
|
"prompts": "^2.4.2",
|
|
60
60
|
"typescript": ">=5.0.4 <7",
|
|
61
|
-
"oxlint-plugin-react-doctor": "0.2.14-dev.
|
|
61
|
+
"oxlint-plugin-react-doctor": "0.2.14-dev.b612664"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/prompts": "^2.4.9",
|