react-doctor 0.2.14-dev.7b4ddf7 → 0.2.14-dev.8921575
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 +59 -0
- package/dist/cli.js +14227 -3799
- package/dist/index.d.ts +119 -16
- package/dist/index.js +1294 -256
- package/dist/skills/doctor-explain/SKILL.md +75 -0
- package/dist/skills/react-doctor/SKILL.md +4 -0
- package/package.json +12 -5
- package/dist/cli-logger-CSZagq1E.js +0 -7564
- package/dist/rolldown-runtime-uZX_iqCz.js +0 -35
package/dist/index.d.ts
CHANGED
|
@@ -5,13 +5,35 @@ import * as Cause from "effect/Cause";
|
|
|
5
5
|
//#region src/types/config.d.ts
|
|
6
6
|
type FailOnLevel = "error" | "warning" | "none";
|
|
7
7
|
interface ReactDoctorIgnoreOverride {
|
|
8
|
+
/** Glob patterns the override applies to (e.g. `["src/legacy/**"]`). */
|
|
8
9
|
files: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Rule keys to suppress for the matched files. Omit (or leave empty) to
|
|
12
|
+
* suppress every rule for those files.
|
|
13
|
+
*/
|
|
9
14
|
rules?: string[];
|
|
10
15
|
}
|
|
11
16
|
interface ReactDoctorIgnoreConfig {
|
|
17
|
+
/**
|
|
18
|
+
* Fully-qualified rule keys (`"<plugin>/<rule>"`) whose diagnostics are
|
|
19
|
+
* dropped AFTER linting. The rule still runs; its findings are filtered
|
|
20
|
+
* out. To stop a rule from running at all, set it to `"off"` in the
|
|
21
|
+
* top-level `rules` map instead. Prefer `react-doctor rules disable
|
|
22
|
+
* <rule>` to edit this safely.
|
|
23
|
+
*/
|
|
12
24
|
rules?: string[];
|
|
25
|
+
/**
|
|
26
|
+
* Glob patterns whose files are excluded from scanning entirely (matched
|
|
27
|
+
* against paths relative to the scanned directory).
|
|
28
|
+
*/
|
|
13
29
|
files?: string[];
|
|
30
|
+
/** Per-path rule suppressions — narrower than the top-level `rules`/`files`. */
|
|
14
31
|
overrides?: ReactDoctorIgnoreOverride[];
|
|
32
|
+
/**
|
|
33
|
+
* Behavioral tags whose rules are disabled BEFORE linting, skipping a
|
|
34
|
+
* whole family at once (e.g. `["design", "test-noise", "migration-hint"]`).
|
|
35
|
+
* Prefer `react-doctor rules ignore-tag <tag>` to edit this safely.
|
|
36
|
+
*/
|
|
15
37
|
tags?: string[];
|
|
16
38
|
}
|
|
17
39
|
/**
|
|
@@ -20,9 +42,9 @@ interface ReactDoctorIgnoreConfig {
|
|
|
20
42
|
* locally but excluded from PR comments, the score, or the CI gate:
|
|
21
43
|
*
|
|
22
44
|
* - `cli` — local terminal output from `react-doctor` (`printDiagnostics`).
|
|
23
|
-
* - `prComment` —
|
|
24
|
-
*
|
|
25
|
-
*
|
|
45
|
+
* - `prComment` — diagnostics destined for a sticky pull-request
|
|
46
|
+
* summary comment. Selected by running the CLI with `--pr-comment`
|
|
47
|
+
* (sets `outputSurface: "prComment"`).
|
|
26
48
|
* - `score` — diagnostics shipped to the React Doctor score API
|
|
27
49
|
* (or counted toward local score calculations).
|
|
28
50
|
* - `ciFailure` — diagnostics that count toward the `--fail-on` exit
|
|
@@ -53,6 +75,14 @@ type RuleSeverityOverride = "error" | "warn" | "off";
|
|
|
53
75
|
* `rules` and `categories` fields on `ReactDoctorConfig`. Per-rule
|
|
54
76
|
* wins over per-category when both match the same diagnostic.
|
|
55
77
|
*/
|
|
78
|
+
/**
|
|
79
|
+
* Closed set of severity buckets. Spelled out (rather than
|
|
80
|
+
* `Record<string, …>`) so an unknown/typo'd bucket key is a type error
|
|
81
|
+
* instead of a silent no-op.
|
|
82
|
+
*/
|
|
83
|
+
interface SeverityBuckets {
|
|
84
|
+
"compiler-cleanup"?: RuleSeverityOverride;
|
|
85
|
+
}
|
|
56
86
|
interface SurfaceControls {
|
|
57
87
|
/**
|
|
58
88
|
* Tag names whose diagnostics should be force-included on the surface,
|
|
@@ -66,9 +96,9 @@ interface SurfaceControls {
|
|
|
66
96
|
* `["test-noise"]`) for a single channel without touching others.
|
|
67
97
|
*/
|
|
68
98
|
excludeTags?: string[];
|
|
69
|
-
/** Category names (e.g. `"
|
|
99
|
+
/** Category names (e.g. `"Maintainability"`) to force-include. */
|
|
70
100
|
includeCategories?: string[];
|
|
71
|
-
/** Category names (e.g. `"
|
|
101
|
+
/** Category names (e.g. `"Maintainability"`) to exclude. */
|
|
72
102
|
excludeCategories?: string[];
|
|
73
103
|
/**
|
|
74
104
|
* Fully-qualified rule keys (`"<plugin>/<rule>"`, e.g.
|
|
@@ -85,12 +115,23 @@ interface ReactDoctorConfig {
|
|
|
85
115
|
/**
|
|
86
116
|
* Whether to run dead-code analysis (via `deslop-js`) alongside lint.
|
|
87
117
|
* Reports unused files, unused exports, unused dependencies, and
|
|
88
|
-
* circular imports under the "
|
|
118
|
+
* circular imports under the "Maintainability" category. Default: `true`.
|
|
89
119
|
* Always skipped in `--diff` / `--staged` modes because reachability
|
|
90
120
|
* is a whole-project property.
|
|
91
121
|
*/
|
|
92
122
|
deadCode?: boolean;
|
|
93
123
|
verbose?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Whether to surface `"warning"`-severity diagnostics. Default: `true`
|
|
126
|
+
* — every warning reaches every surface (CLI, PR comment, score,
|
|
127
|
+
* `--fail-on`).
|
|
128
|
+
*
|
|
129
|
+
* Set to `false` to surface only `"error"`-severity findings. This is the
|
|
130
|
+
* master toggle and runs after per-rule / per-category severity
|
|
131
|
+
* overrides: a rule the user explicitly restamps to `"warn"` (via
|
|
132
|
+
* `rules` / `categories`) still shows even when `warnings` is `false`.
|
|
133
|
+
*/
|
|
134
|
+
warnings?: boolean;
|
|
94
135
|
diff?: boolean | string;
|
|
95
136
|
failOn?: FailOnLevel;
|
|
96
137
|
customRulesOnly?: boolean;
|
|
@@ -103,7 +144,7 @@ interface ReactDoctorConfig {
|
|
|
103
144
|
* the redirect is stable no matter where the CLI / `diagnose()` is
|
|
104
145
|
* run from. Absolute paths are used as-is.
|
|
105
146
|
*
|
|
106
|
-
* Typical use: a monorepo root holds the only `
|
|
147
|
+
* Typical use: a monorepo root holds the only `doctor.config.*`
|
|
107
148
|
* (so editor tooling and child commands all find it), but the React
|
|
108
149
|
* app lives in `apps/web`. Setting `"rootDir": "apps/web"` makes
|
|
109
150
|
* every invocation that loads this config scan that subproject
|
|
@@ -229,15 +270,12 @@ interface ReactDoctorConfig {
|
|
|
229
270
|
rules?: Record<string, RuleSeverityOverride>;
|
|
230
271
|
/**
|
|
231
272
|
* Per-category severity map. Mirrors oxlint's top-level
|
|
232
|
-
* `categories` field, but keyed by React Doctor's
|
|
233
|
-
*
|
|
234
|
-
* `"
|
|
235
|
-
* `"Accessibility"`, `"Performance"`, `"Correctness"`,
|
|
236
|
-
* `"Next.js"`, `"Preact"`, `"TanStack Query"`,
|
|
237
|
-
* `"TanStack Start"`, …).
|
|
273
|
+
* `categories` field, but keyed by React Doctor's five user-facing
|
|
274
|
+
* buckets: `"Security"`, `"Bugs"`, `"Performance"`,
|
|
275
|
+
* `"Accessibility"`, `"Maintainability"`.
|
|
238
276
|
*
|
|
239
277
|
* ```json
|
|
240
|
-
* { "categories": { "
|
|
278
|
+
* { "categories": { "Maintainability": "off", "Performance": "warn" } }
|
|
241
279
|
* ```
|
|
242
280
|
*
|
|
243
281
|
* To silence a whole tag-defined rule family (e.g. `"design"`,
|
|
@@ -245,6 +283,20 @@ interface ReactDoctorConfig {
|
|
|
245
283
|
* single category, use `ignore.tags` instead.
|
|
246
284
|
*/
|
|
247
285
|
categories?: Record<string, RuleSeverityOverride>;
|
|
286
|
+
/**
|
|
287
|
+
* Per-bucket severity map. Buckets are curated rule families with a
|
|
288
|
+
* shared gating story (not categories). Today the only bucket is
|
|
289
|
+
* `"compiler-cleanup"`: the redundant-memoization rule
|
|
290
|
+
* (`react-compiler-no-manual-memoization`) that ships as a warning once
|
|
291
|
+
* React Compiler is detected. Set it to `"error"` to re-enable strictness.
|
|
292
|
+
*
|
|
293
|
+
* ```json
|
|
294
|
+
* { "buckets": { "compiler-cleanup": "error" } }
|
|
295
|
+
* ```
|
|
296
|
+
*
|
|
297
|
+
* A per-rule override in `rules` still wins over a bucket entry.
|
|
298
|
+
*/
|
|
299
|
+
buckets?: SeverityBuckets;
|
|
248
300
|
/**
|
|
249
301
|
* User-defined oxlint plugins to load alongside the built-in
|
|
250
302
|
* `react-doctor` plugin. Each entry is either:
|
|
@@ -288,6 +340,7 @@ interface Diagnostic {
|
|
|
288
340
|
plugin: string;
|
|
289
341
|
rule: string;
|
|
290
342
|
severity: "error" | "warning";
|
|
343
|
+
title?: string;
|
|
291
344
|
message: string;
|
|
292
345
|
help: string;
|
|
293
346
|
url?: string;
|
|
@@ -338,6 +391,22 @@ interface ProjectInfo {
|
|
|
338
391
|
* — no `rn-*` rules load for the project at all.
|
|
339
392
|
*/
|
|
340
393
|
hasReactNativeWorkspace: boolean;
|
|
394
|
+
/**
|
|
395
|
+
* The declared `expo` package version spec (e.g. `"~51.0.0"`), looked up
|
|
396
|
+
* in the project or any of its workspace packages, or `null` when `expo`
|
|
397
|
+
* isn't a dependency. Doubles as react-doctor's "is this an Expo project?"
|
|
398
|
+
* signal (`expoVersion !== null`) and its SDK-version source — the `expo`
|
|
399
|
+
* major tracks the Expo SDK release one-to-one — paralleling how
|
|
400
|
+
* `reactVersion` models the React runtime.
|
|
401
|
+
*
|
|
402
|
+
* Keyed off the dependency rather than `framework === "expo"` because
|
|
403
|
+
* `detectFramework` returns the first matching package, so a project
|
|
404
|
+
* declaring both `expo` and a web bundler (`vite` / `next`) classifies as
|
|
405
|
+
* the web framework yet is still an Expo project. Drives the `expo`
|
|
406
|
+
* capability in `buildCapabilities` (which gates every Expo-specific
|
|
407
|
+
* rule) and the ported expo-doctor checks.
|
|
408
|
+
*/
|
|
409
|
+
expoVersion: string | null;
|
|
341
410
|
/**
|
|
342
411
|
* `true` when the project (or any of its workspace packages) declares
|
|
343
412
|
* `react-native-reanimated`. Lets diagnostics surface reanimated's
|
|
@@ -349,9 +418,15 @@ interface ProjectInfo {
|
|
|
349
418
|
}
|
|
350
419
|
//#endregion
|
|
351
420
|
//#region src/types/score.d.ts
|
|
421
|
+
type RuleTier = "P0" | "P1" | "P2" | "P3";
|
|
422
|
+
interface RulePriority {
|
|
423
|
+
readonly priority: number | null;
|
|
424
|
+
readonly tier: RuleTier;
|
|
425
|
+
}
|
|
352
426
|
interface ScoreResult {
|
|
353
427
|
score: number;
|
|
354
428
|
label: string;
|
|
429
|
+
readonly rules?: Readonly<Record<string, RulePriority>>;
|
|
355
430
|
} //#endregion
|
|
356
431
|
//#region src/types/diagnose.d.ts
|
|
357
432
|
interface DiagnoseOptions {
|
|
@@ -365,6 +440,12 @@ interface DiagnoseOptions {
|
|
|
365
440
|
* See that field's docs for the full contract.
|
|
366
441
|
*/
|
|
367
442
|
respectInlineDisables?: boolean;
|
|
443
|
+
/**
|
|
444
|
+
* Per-call override for `ReactDoctorConfig.warnings`. See that field's
|
|
445
|
+
* docs — `"warning"`-severity diagnostics surface by default unless this
|
|
446
|
+
* (or the config) opts out via `false`.
|
|
447
|
+
*/
|
|
448
|
+
warnings?: boolean;
|
|
368
449
|
}
|
|
369
450
|
interface DiagnoseResult {
|
|
370
451
|
diagnostics: Diagnostic[];
|
|
@@ -385,7 +466,7 @@ interface DiagnoseResult {
|
|
|
385
466
|
* Scan options (`deadCode`, `lint`, etc.) are flat on the entry and
|
|
386
467
|
* layer on top of the global defaults — omitted fields fall through.
|
|
387
468
|
* `config` is a full `ReactDoctorConfig` override that replaces the
|
|
388
|
-
* on-disk `
|
|
469
|
+
* on-disk `doctor.config.*` for this project's scan.
|
|
389
470
|
*/
|
|
390
471
|
//#endregion
|
|
391
472
|
//#region src/types/inspect.d.ts
|
|
@@ -404,6 +485,28 @@ interface InspectResult {
|
|
|
404
485
|
skippedCheckReasons?: Record<string, string>;
|
|
405
486
|
project: ProjectInfo;
|
|
406
487
|
elapsedMilliseconds: number;
|
|
488
|
+
/**
|
|
489
|
+
* Number of files the scan reported. Distinct from
|
|
490
|
+
* `project.sourceFileCount` in diff / staged mode (where only changed
|
|
491
|
+
* files are scanned). Optional so non-orchestrator constructors keep
|
|
492
|
+
* working; the multi-project summary falls back to
|
|
493
|
+
* `project.sourceFileCount` when absent.
|
|
494
|
+
*/
|
|
495
|
+
scannedFileCount?: number;
|
|
496
|
+
/**
|
|
497
|
+
* Absolute paths of every file the scan considered. Lets the
|
|
498
|
+
* multi-project summary count UNIQUE files across projects instead of
|
|
499
|
+
* summing per-project counts, which double-counts shared files when one
|
|
500
|
+
* workspace package's tree is nested inside another's.
|
|
501
|
+
*/
|
|
502
|
+
scannedFilePaths?: ReadonlyArray<string>;
|
|
503
|
+
/**
|
|
504
|
+
* Wall-clock duration of the scan phase, in milliseconds. Distinct
|
|
505
|
+
* from `elapsedMilliseconds` (which spans the full `inspect()` call
|
|
506
|
+
* including score fetch + rendering). Used by the multi-project
|
|
507
|
+
* summary to report combined scan time.
|
|
508
|
+
*/
|
|
509
|
+
scanElapsedMilliseconds?: number;
|
|
407
510
|
}
|
|
408
511
|
/**
|
|
409
512
|
* Options accepted by `inspect()`. Mixes two concern groups; ordered
|
|
@@ -661,7 +764,7 @@ interface BuildJsonReportInput {
|
|
|
661
764
|
totalElapsedMilliseconds: number;
|
|
662
765
|
}
|
|
663
766
|
declare const buildJsonReport: (input: BuildJsonReportInput) => JsonReport; //#endregion
|
|
664
|
-
//#region src/
|
|
767
|
+
//#region src/build-skipped-checks.d.ts
|
|
665
768
|
//#endregion
|
|
666
769
|
//#region src/get-diff-files.d.ts
|
|
667
770
|
/**
|