react-doctor 0.8.1-dev.7818922 → 0.8.1-dev.7eca0ee
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.js +749 -92
- package/dist/index.d.ts +33 -15
- package/dist/index.js +254 -23
- package/dist/lsp.js +254 -23
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -9030,11 +9030,12 @@ interface Diagnostic {
|
|
|
9030
9030
|
* Set when the finding's identity is the flagged element itself (a missing
|
|
9031
9031
|
* attribute, a wrong element) rather than the flagged line's text — every
|
|
9032
9032
|
* Accessibility-category finding, plus rules that opt in via their
|
|
9033
|
-
* `matchByOccurrence` metadata flag.
|
|
9034
|
-
* by `(
|
|
9035
|
-
*
|
|
9036
|
-
*
|
|
9037
|
-
*
|
|
9033
|
+
* `matchByOccurrence` metadata flag. After strict evidence matching,
|
|
9034
|
+
* `computeDiagnosticDelta` may match these by same-file `(plugin/rule,
|
|
9035
|
+
* message)` occurrence count, so reformatting the flagged element doesn't
|
|
9036
|
+
* reclassify a pre-existing finding as new. Resolved at diagnostic creation,
|
|
9037
|
+
* where rule metadata is available. Absent means diagnosed-source-sensitive
|
|
9038
|
+
* matching (the default).
|
|
9038
9039
|
*/
|
|
9039
9040
|
matchByOccurrence?: boolean;
|
|
9040
9041
|
/**
|
|
@@ -9542,11 +9543,35 @@ interface ProjectInfo {
|
|
|
9542
9543
|
zodVersion: string | null;
|
|
9543
9544
|
/** Parsed major from `zodVersion`, or `null` when absent/unparseable. Mirrors `reactMajorVersion`. */
|
|
9544
9545
|
zodMajorVersion: number | null;
|
|
9546
|
+
/** Declared MobX core version spec. Optional so existing `ProjectInfo` consumers remain source-compatible. */
|
|
9547
|
+
mobxVersion?: string | null;
|
|
9548
|
+
/** Parsed major from `mobxVersion`, or `null` when absent/unparseable. */
|
|
9549
|
+
mobxMajorVersion?: number | null;
|
|
9550
|
+
hasMobxReact?: boolean;
|
|
9551
|
+
hasMobxReactLite?: boolean;
|
|
9552
|
+
hasMobxStateTree?: boolean;
|
|
9553
|
+
hasMobxReactObserver?: boolean;
|
|
9554
|
+
/** Declared Zustand version spec. Optional so existing `ProjectInfo` consumers remain source-compatible. */
|
|
9555
|
+
zustandVersion?: string | null;
|
|
9556
|
+
/** Parsed major from `zustandVersion`, or `null` when absent/unparseable. */
|
|
9557
|
+
zustandMajorVersion?: number | null;
|
|
9545
9558
|
framework: Framework;
|
|
9546
9559
|
hasTypeScript: boolean;
|
|
9547
9560
|
hasReactCompiler: boolean;
|
|
9548
9561
|
hasReactCompilerLintPlugin?: boolean;
|
|
9549
9562
|
hasTanStackQuery: boolean;
|
|
9563
|
+
hasRemotion?: boolean;
|
|
9564
|
+
remotionVersion?: string | null;
|
|
9565
|
+
remotionMajorVersion?: number | null;
|
|
9566
|
+
/**
|
|
9567
|
+
* The declared `valtio` version spec, or `null` when no package in the
|
|
9568
|
+
* analyzed project declares Valtio. `useSnapshot` has kept the same
|
|
9569
|
+
* render-read contract across Valtio 1 and 2, so presence alone drives the
|
|
9570
|
+
* `valtio` capability and its parsed major-version ladder.
|
|
9571
|
+
*/
|
|
9572
|
+
valtioVersion: string | null;
|
|
9573
|
+
/** Parsed major from `valtioVersion`, or `null` when absent/unparseable. */
|
|
9574
|
+
valtioMajorVersion: number | null;
|
|
9550
9575
|
/**
|
|
9551
9576
|
* `true` when the project or a workspace declares a Vite-based SSR runtime
|
|
9552
9577
|
* such as React Router's Node adapter, Vike, or vite-plugin-ssr.
|
|
@@ -9847,7 +9872,8 @@ interface InspectResult {
|
|
|
9847
9872
|
baselineDelta?: {
|
|
9848
9873
|
/** The commit the base content was read from (resolved merge-base). */baseRef: string; /** Findings present at base but gone at head — resolved by the change. */
|
|
9849
9874
|
fixedCount: number; /** Total findings at base (over the same files), for context. */
|
|
9850
|
-
baseTotalCount: number;
|
|
9875
|
+
baseTotalCount: number; /** Pre-existing findings matched after moving to a different file. */
|
|
9876
|
+
crossFileMatchCount?: number;
|
|
9851
9877
|
};
|
|
9852
9878
|
}
|
|
9853
9879
|
/**
|
|
@@ -10263,15 +10289,7 @@ declare const buildJsonReport: (input: BuildJsonReportInput) => JsonReportV3$1;
|
|
|
10263
10289
|
* `GitBaseBranchMissing`) as clean user errors instead of crashes.
|
|
10264
10290
|
*/
|
|
10265
10291
|
declare const getDiffInfo: (directory: string, explicitBaseBranch?: string, includeUntracked?: boolean) => Promise<DiffInfo | null>;
|
|
10266
|
-
declare const filterSourceFiles: (filePaths: string
|
|
10267
|
-
/**
|
|
10268
|
-
* Programmatic façade over `Git.changedLineRanges` (the `lines` scope). Diffs
|
|
10269
|
-
* `files` with `--unified=0` against `baseRef` (or the index when `cached`),
|
|
10270
|
-
* returning per-file changed line ranges relative to `directory`. Returns
|
|
10271
|
-
* `null` when the ranges can't be computed (git unavailable / unsafe ref /
|
|
10272
|
-
* non-zero exit) so the caller degrades to file-level scope; an empty array
|
|
10273
|
-
* means git succeeded but the files added no lines.
|
|
10274
|
-
*/
|
|
10292
|
+
declare const filterSourceFiles: (filePaths: ReadonlyArray<string>) => string[];
|
|
10275
10293
|
//#endregion
|
|
10276
10294
|
//#region src/summarize-diagnostics.d.ts
|
|
10277
10295
|
declare const summarizeDiagnostics: (diagnostics: Diagnostic[], worstScore?: number | null, worstScoreLabel?: string | null) => JsonReportSummary; //#endregion
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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]="
|
|
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]="6aa1c6e1-8fcc-50d4-a076-3e864425bdc5")}catch(e){}}();
|
|
3
3
|
import { r as __toESM$1, t as __commonJSMin$1 } from "./chunk-N93fKeF6.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, FRAMEWORK_TOKENS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
|
|
@@ -34121,6 +34121,10 @@ const listWorkspacePackages = (rootDirectory) => {
|
|
|
34121
34121
|
return packages;
|
|
34122
34122
|
};
|
|
34123
34123
|
const REANIMATED_DEPENDENCY_NAME = "react-native-reanimated";
|
|
34124
|
+
const MOBX_REACT_PACKAGE_NAME = "mobx-react";
|
|
34125
|
+
const MOBX_REACT_LITE_PACKAGE_NAME = "mobx-react-lite";
|
|
34126
|
+
const MOBX_STATE_TREE_PACKAGE_NAME = "mobx-state-tree";
|
|
34127
|
+
const MOBX_REACT_OBSERVER_PACKAGE_NAME = "mobx-react-observer";
|
|
34124
34128
|
const SHOPIFY_FLASH_LIST_PACKAGE_NAME = "@shopify/flash-list";
|
|
34125
34129
|
const resolveWorkspaceDependencyVersion = ({ concreteVersion, packageName, rootDirectory, rootPackageJson, sections, workspaceDirectory, workspacePackageJson }) => {
|
|
34126
34130
|
const dependencyDeclaration = getDependencyDeclaration({
|
|
@@ -34139,7 +34143,18 @@ const shouldReplaceReactVersion = (currentVersion, nextVersion) => {
|
|
|
34139
34143
|
if (nextMajor === null) return false;
|
|
34140
34144
|
return nextMajor < currentMajor;
|
|
34141
34145
|
};
|
|
34142
|
-
const
|
|
34146
|
+
const shouldReplaceSupportedDependencyFact = (currentFact, nextFact, latestSupportedMajor) => {
|
|
34147
|
+
if (currentFact.version === null) return true;
|
|
34148
|
+
if (nextFact.version === null) return false;
|
|
34149
|
+
const currentMajor = getLowestDependencyMajor(currentFact.version);
|
|
34150
|
+
const nextMajor = getLowestDependencyMajor(nextFact.version);
|
|
34151
|
+
if (currentMajor === null) return false;
|
|
34152
|
+
if (nextMajor === null) return true;
|
|
34153
|
+
if (currentMajor > latestSupportedMajor) return false;
|
|
34154
|
+
if (nextMajor > latestSupportedMajor) return true;
|
|
34155
|
+
return nextMajor < currentMajor;
|
|
34156
|
+
};
|
|
34157
|
+
const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, rootPackageJson) => {
|
|
34143
34158
|
if (facts.expo.version === null) {
|
|
34144
34159
|
const spec = getDependencySpec(packageJson, "expo");
|
|
34145
34160
|
if (spec !== null) facts.expo = {
|
|
@@ -34161,13 +34176,65 @@ const evaluateManifestFacts = (facts, packageJson, directory) => {
|
|
|
34161
34176
|
sourceDirectory: directory
|
|
34162
34177
|
};
|
|
34163
34178
|
}
|
|
34179
|
+
const mobxSpec = getDependencySpec(packageJson, "mobx");
|
|
34180
|
+
if (mobxSpec !== null) {
|
|
34181
|
+
const nextMobxFact = {
|
|
34182
|
+
version: resolveCatalogBackedDependencyVersion({
|
|
34183
|
+
rootDirectory: directory,
|
|
34184
|
+
rootPackageJson: packageJson,
|
|
34185
|
+
packageName: "mobx",
|
|
34186
|
+
version: mobxSpec
|
|
34187
|
+
}),
|
|
34188
|
+
sourceDirectory: directory
|
|
34189
|
+
};
|
|
34190
|
+
if (shouldReplaceSupportedDependencyFact(facts.mobx, nextMobxFact, 6)) facts.mobx = nextMobxFact;
|
|
34191
|
+
}
|
|
34192
|
+
facts.hasMobxReact = facts.hasMobxReact || getDependencySpec(packageJson, MOBX_REACT_PACKAGE_NAME) !== null;
|
|
34193
|
+
facts.hasMobxReactLite = facts.hasMobxReactLite || getDependencySpec(packageJson, MOBX_REACT_LITE_PACKAGE_NAME) !== null;
|
|
34194
|
+
facts.hasMobxStateTree = facts.hasMobxStateTree || getDependencySpec(packageJson, MOBX_STATE_TREE_PACKAGE_NAME) !== null;
|
|
34195
|
+
facts.hasMobxReactObserver = facts.hasMobxReactObserver || getDependencySpec(packageJson, MOBX_REACT_OBSERVER_PACKAGE_NAME) !== null;
|
|
34196
|
+
const zustandSpec = getDependencySpec(packageJson, "zustand");
|
|
34197
|
+
if (zustandSpec !== null) {
|
|
34198
|
+
const nextZustandFact = {
|
|
34199
|
+
version: resolveCatalogBackedDependencyVersion({
|
|
34200
|
+
rootDirectory: directory,
|
|
34201
|
+
rootPackageJson: packageJson,
|
|
34202
|
+
packageName: "zustand",
|
|
34203
|
+
version: zustandSpec
|
|
34204
|
+
}),
|
|
34205
|
+
sourceDirectory: directory
|
|
34206
|
+
};
|
|
34207
|
+
if (shouldReplaceSupportedDependencyFact(facts.zustand, nextZustandFact, 5)) facts.zustand = nextZustandFact;
|
|
34208
|
+
}
|
|
34164
34209
|
if (facts.reanimatedVersion === null) {
|
|
34165
34210
|
const spec = getDependencySpec(packageJson, REANIMATED_DEPENDENCY_NAME);
|
|
34166
34211
|
if (spec !== null) facts.reanimatedVersion = spec;
|
|
34167
34212
|
}
|
|
34213
|
+
if (facts.valtioVersion === null) {
|
|
34214
|
+
const spec = getDependencySpec(packageJson, "valtio");
|
|
34215
|
+
if (spec !== null) facts.valtioVersion = spec;
|
|
34216
|
+
}
|
|
34168
34217
|
facts.hasReactNativeAwarePackage = facts.hasReactNativeAwarePackage || isPackageJsonReactNativeAware(packageJson);
|
|
34169
34218
|
facts.hasReanimatedAwarePackage = facts.hasReanimatedAwarePackage || isPackageJsonReanimatedAware(packageJson);
|
|
34170
34219
|
facts.hasSsrDependency = facts.hasSsrDependency || isPackageJsonSsrAware(packageJson);
|
|
34220
|
+
const remotionSpec = getDependencySpec(packageJson, "remotion");
|
|
34221
|
+
if (remotionSpec !== null) {
|
|
34222
|
+
facts.hasRemotionDependency = true;
|
|
34223
|
+
const resolvedRemotionVersion = resolveCatalogBackedDependencyVersion({
|
|
34224
|
+
rootDirectory,
|
|
34225
|
+
rootPackageJson,
|
|
34226
|
+
packageName: "remotion",
|
|
34227
|
+
version: remotionSpec
|
|
34228
|
+
});
|
|
34229
|
+
const remotionMajorVersion = resolvedRemotionVersion === null ? null : getLowestDependencyMajor(resolvedRemotionVersion);
|
|
34230
|
+
if (remotionMajorVersion === null) {
|
|
34231
|
+
facts.hasUnknownRemotionVersion = true;
|
|
34232
|
+
facts.remotionVersion = null;
|
|
34233
|
+
} else if (!facts.hasUnknownRemotionVersion) {
|
|
34234
|
+
const currentRemotionMajorVersion = facts.remotionVersion === null ? null : getLowestDependencyMajor(facts.remotionVersion);
|
|
34235
|
+
if (currentRemotionMajorVersion === null || remotionMajorVersion < currentRemotionMajorVersion) facts.remotionVersion = resolvedRemotionVersion;
|
|
34236
|
+
}
|
|
34237
|
+
}
|
|
34171
34238
|
};
|
|
34172
34239
|
const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGroup }) => {
|
|
34173
34240
|
const facts = {
|
|
@@ -34187,12 +34254,28 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
|
|
|
34187
34254
|
version: null,
|
|
34188
34255
|
sourceDirectory: null
|
|
34189
34256
|
},
|
|
34257
|
+
valtioVersion: null,
|
|
34258
|
+
mobx: {
|
|
34259
|
+
version: null,
|
|
34260
|
+
sourceDirectory: null
|
|
34261
|
+
},
|
|
34262
|
+
hasMobxReact: false,
|
|
34263
|
+
hasMobxReactLite: false,
|
|
34264
|
+
hasMobxStateTree: false,
|
|
34265
|
+
hasMobxReactObserver: false,
|
|
34266
|
+
zustand: {
|
|
34267
|
+
version: null,
|
|
34268
|
+
sourceDirectory: null
|
|
34269
|
+
},
|
|
34190
34270
|
hasReactNativeAwarePackage: false,
|
|
34191
34271
|
hasReanimatedAwarePackage: false,
|
|
34192
34272
|
hasSsrDependency: false,
|
|
34273
|
+
hasRemotionDependency: false,
|
|
34274
|
+
hasUnknownRemotionVersion: false,
|
|
34275
|
+
remotionVersion: null,
|
|
34193
34276
|
reanimatedVersion: null
|
|
34194
34277
|
};
|
|
34195
|
-
evaluateManifestFacts(facts, rootPackageJson, rootDirectory);
|
|
34278
|
+
evaluateManifestFacts(facts, rootPackageJson, rootDirectory, rootDirectory, rootPackageJson);
|
|
34196
34279
|
let isReactGroupSettled = !collectReactGroup;
|
|
34197
34280
|
const visitedDirectories = /* @__PURE__ */ new Set();
|
|
34198
34281
|
for (const pattern of getWorkspacePatterns(rootDirectory, rootPackageJson)) {
|
|
@@ -34201,7 +34284,7 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
|
|
|
34201
34284
|
if (visitedDirectories.has(workspaceDirectory)) continue;
|
|
34202
34285
|
visitedDirectories.add(workspaceDirectory);
|
|
34203
34286
|
const workspacePackageJson = readPackageJson(Path.join(workspaceDirectory, "package.json"));
|
|
34204
|
-
evaluateManifestFacts(facts, workspacePackageJson, workspaceDirectory);
|
|
34287
|
+
evaluateManifestFacts(facts, workspacePackageJson, workspaceDirectory, rootDirectory, rootPackageJson);
|
|
34205
34288
|
const info = extractDependencyInfo(workspacePackageJson);
|
|
34206
34289
|
if (info.framework !== "unknown" && frameworkMergeRank(info.framework) < frameworkMergeRank(facts.framework)) facts.framework = info.framework;
|
|
34207
34290
|
if (isReactGroupSettled) continue;
|
|
@@ -34425,11 +34508,24 @@ const discoverProjectWithoutPackageJson = (directory) => {
|
|
|
34425
34508
|
tailwindVersion: null,
|
|
34426
34509
|
zodVersion: null,
|
|
34427
34510
|
zodMajorVersion: null,
|
|
34511
|
+
mobxVersion: null,
|
|
34512
|
+
mobxMajorVersion: null,
|
|
34513
|
+
hasMobxReact: false,
|
|
34514
|
+
hasMobxReactLite: false,
|
|
34515
|
+
hasMobxStateTree: false,
|
|
34516
|
+
hasMobxReactObserver: false,
|
|
34517
|
+
zustandVersion: null,
|
|
34518
|
+
zustandMajorVersion: null,
|
|
34428
34519
|
framework: "unknown",
|
|
34429
34520
|
hasTypeScript: hasOwnTsConfig,
|
|
34430
34521
|
hasReactCompiler: false,
|
|
34431
34522
|
hasReactCompilerLintPlugin: false,
|
|
34432
34523
|
hasTanStackQuery: false,
|
|
34524
|
+
valtioVersion: null,
|
|
34525
|
+
valtioMajorVersion: null,
|
|
34526
|
+
hasRemotion: false,
|
|
34527
|
+
remotionVersion: null,
|
|
34528
|
+
remotionMajorVersion: null,
|
|
34433
34529
|
hasSsrDependency: false,
|
|
34434
34530
|
preactVersion: null,
|
|
34435
34531
|
preactMajorVersion: null,
|
|
@@ -34528,6 +34624,12 @@ const discoverProject = (directory) => {
|
|
|
34528
34624
|
packageName: SHOPIFY_FLASH_LIST_PACKAGE_NAME,
|
|
34529
34625
|
version: workspaceFacts.shopifyFlashList.version
|
|
34530
34626
|
}) : null;
|
|
34627
|
+
const zustandVersion = resolveCatalogBackedDependencyVersion({
|
|
34628
|
+
rootDirectory: directory,
|
|
34629
|
+
rootPackageJson: packageJson,
|
|
34630
|
+
packageName: "zustand",
|
|
34631
|
+
version: workspaceFacts.zustand.version
|
|
34632
|
+
});
|
|
34531
34633
|
const hasReanimated = hasReactNativeWorkspace && workspaceFacts.hasReanimatedAwarePackage;
|
|
34532
34634
|
const reanimatedVersion = hasReanimated ? workspaceFacts.reanimatedVersion : null;
|
|
34533
34635
|
const nextjsVersion = framework === "nextjs" ? resolveCatalogBackedDependencyVersion({
|
|
@@ -34536,7 +34638,20 @@ const discoverProject = (directory) => {
|
|
|
34536
34638
|
packageName: "next",
|
|
34537
34639
|
version: workspaceFacts.next.version
|
|
34538
34640
|
}) : null;
|
|
34641
|
+
const valtioVersion = resolveCatalogBackedDependencyVersion({
|
|
34642
|
+
rootDirectory: directory,
|
|
34643
|
+
rootPackageJson: packageJson,
|
|
34644
|
+
packageName: "valtio",
|
|
34645
|
+
version: workspaceFacts.valtioVersion
|
|
34646
|
+
});
|
|
34647
|
+
const mobxVersion = resolveCatalogBackedDependencyVersion({
|
|
34648
|
+
rootDirectory: directory,
|
|
34649
|
+
rootPackageJson: packageJson,
|
|
34650
|
+
packageName: "mobx",
|
|
34651
|
+
version: workspaceFacts.mobx.version
|
|
34652
|
+
});
|
|
34539
34653
|
const preactVersion = getPreactVersion(packageJson);
|
|
34654
|
+
const remotionVersion = workspaceFacts.remotionVersion;
|
|
34540
34655
|
const isPreES2023Target = hasTypeScript && detectPreES2023Target(directory);
|
|
34541
34656
|
const projectInfo = {
|
|
34542
34657
|
rootDirectory: directory,
|
|
@@ -34546,11 +34661,24 @@ const discoverProject = (directory) => {
|
|
|
34546
34661
|
tailwindVersion,
|
|
34547
34662
|
zodVersion,
|
|
34548
34663
|
zodMajorVersion: zodVersion === null ? null : getLowestDependencyMajor(zodVersion),
|
|
34664
|
+
mobxVersion,
|
|
34665
|
+
mobxMajorVersion: mobxVersion === null ? null : getLowestDependencyMajor(mobxVersion),
|
|
34666
|
+
hasMobxReact: workspaceFacts.hasMobxReact,
|
|
34667
|
+
hasMobxReactLite: workspaceFacts.hasMobxReactLite,
|
|
34668
|
+
hasMobxStateTree: workspaceFacts.hasMobxStateTree,
|
|
34669
|
+
hasMobxReactObserver: workspaceFacts.hasMobxReactObserver,
|
|
34670
|
+
zustandVersion,
|
|
34671
|
+
zustandMajorVersion: zustandVersion === null ? null : getLowestDependencyMajor(zustandVersion),
|
|
34549
34672
|
framework,
|
|
34550
34673
|
hasTypeScript,
|
|
34551
34674
|
hasReactCompiler: detectReactCompiler(directory, packageJson),
|
|
34552
34675
|
hasReactCompilerLintPlugin: detectReactCompilerLintPlugin(directory, packageJson),
|
|
34553
34676
|
hasTanStackQuery: hasTanStackQuery(packageJson),
|
|
34677
|
+
valtioVersion,
|
|
34678
|
+
valtioMajorVersion: valtioVersion === null ? null : getLowestDependencyMajor(valtioVersion),
|
|
34679
|
+
hasRemotion: workspaceFacts.hasRemotionDependency,
|
|
34680
|
+
remotionVersion,
|
|
34681
|
+
remotionMajorVersion: remotionVersion === null ? null : getLowestDependencyMajor(remotionVersion),
|
|
34554
34682
|
hasSsrDependency: workspaceFacts.hasSsrDependency,
|
|
34555
34683
|
preactVersion,
|
|
34556
34684
|
preactMajorVersion: parseReactMajor(preactVersion),
|
|
@@ -34784,7 +34912,6 @@ const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
|
|
|
34784
34912
|
"react/jsx-no-new-function-as-prop": "react-doctor/jsx-no-new-function-as-prop",
|
|
34785
34913
|
"react/jsx-no-new-object-as-prop": "react-doctor/jsx-no-new-object-as-prop",
|
|
34786
34914
|
"react/jsx-no-script-url": "react-doctor/jsx-no-script-url",
|
|
34787
|
-
"react/jsx-no-target-blank": "react-doctor/jsx-no-target-blank",
|
|
34788
34915
|
"react/jsx-no-undef": "react-doctor/jsx-no-undef",
|
|
34789
34916
|
"react/jsx-no-useless-fragment": "react-doctor/jsx-no-useless-fragment",
|
|
34790
34917
|
"react/jsx-pascal-case": "react-doctor/jsx-pascal-case",
|
|
@@ -37071,9 +37198,25 @@ const BABEL_CONFIG_FILE_NAMES = [
|
|
|
37071
37198
|
".babelrc.json"
|
|
37072
37199
|
];
|
|
37073
37200
|
const LEGACY_PRESET_SPEC = "module:metro-react-native-babel-preset";
|
|
37201
|
+
const LEGACY_PRESET_PACKAGE = "metro-react-native-babel-preset";
|
|
37202
|
+
const REACT_NATIVE_PACKAGE = "react-native";
|
|
37203
|
+
const PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION = "0.73.0";
|
|
37204
|
+
const LEGACY_PRESET_REFERENCE = new RegExp(`['"]${LEGACY_PRESET_SPEC}['"]`);
|
|
37074
37205
|
const MODERN_PRESET_REFERENCE = new RegExp(`['"]module:@react-native/babel-preset['"]`);
|
|
37075
37206
|
const ENABLE_BABEL_RUNTIME_VERSION = /enableBabelRuntime["']?\s*:\s*['"]/;
|
|
37207
|
+
const isReactNativeVersionAtLeastPresetRename = (rootDirectory, packageJson) => {
|
|
37208
|
+
const installedReactNativeManifestPath = Path.join(rootDirectory, "node_modules", REACT_NATIVE_PACKAGE, "package.json");
|
|
37209
|
+
const reactNativeVersionSpec = (isFile(installedReactNativeManifestPath) ? readPackageJson(installedReactNativeManifestPath).version : void 0) ?? getDependencySpec(packageJson, REACT_NATIVE_PACKAGE);
|
|
37210
|
+
if (reactNativeVersionSpec === null || reactNativeVersionSpec === void 0) return false;
|
|
37211
|
+
const normalizedVersionRange = import_semver.validRange(reactNativeVersionSpec);
|
|
37212
|
+
if (normalizedVersionRange === null) return false;
|
|
37213
|
+
const minimumVersion = import_semver.minVersion(normalizedVersionRange);
|
|
37214
|
+
return minimumVersion !== null && import_semver.gte(minimumVersion, PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION);
|
|
37215
|
+
};
|
|
37216
|
+
const canResolveLegacyPreset = (rootDirectory, packageJson) => getDependencySpec(packageJson, LEGACY_PRESET_PACKAGE) !== null || isFile(Path.join(rootDirectory, "node_modules", LEGACY_PRESET_PACKAGE, "package.json"));
|
|
37076
37217
|
const checkReactNativeMetroBabelPreset = (rootDirectory) => {
|
|
37218
|
+
const packageJson = readPackageJson(Path.join(rootDirectory, "package.json"));
|
|
37219
|
+
const shouldReportLegacyPreset = isReactNativeVersionAtLeastPresetRename(rootDirectory, packageJson) && !canResolveLegacyPreset(rootDirectory, packageJson);
|
|
37077
37220
|
for (const fileName of BABEL_CONFIG_FILE_NAMES) {
|
|
37078
37221
|
const filePath = Path.join(rootDirectory, fileName);
|
|
37079
37222
|
if (!isFile(filePath)) continue;
|
|
@@ -37083,7 +37226,7 @@ const checkReactNativeMetroBabelPreset = (rootDirectory) => {
|
|
|
37083
37226
|
} catch {
|
|
37084
37227
|
continue;
|
|
37085
37228
|
}
|
|
37086
|
-
if (
|
|
37229
|
+
if (shouldReportLegacyPreset && LEGACY_PRESET_REFERENCE.test(contents)) return [buildReactNativeDiagnostic({
|
|
37087
37230
|
filePath: fileName,
|
|
37088
37231
|
rule: "rn-no-metro-babel-preset",
|
|
37089
37232
|
severity: "error",
|
|
@@ -37106,12 +37249,6 @@ const checkReactNativeProject = (rootDirectory, project) => {
|
|
|
37106
37249
|
return [...checkReactNativeMetroBabelPreset(rootDirectory), ...checkReactNativeLibraryDependencies(rootDirectory)];
|
|
37107
37250
|
};
|
|
37108
37251
|
const RULE_KEY = "no-vulnerable-react-server-components";
|
|
37109
|
-
const DEPENDENCY_SECTIONS = [
|
|
37110
|
-
"dependencies",
|
|
37111
|
-
"devDependencies",
|
|
37112
|
-
"peerDependencies",
|
|
37113
|
-
"optionalDependencies"
|
|
37114
|
-
];
|
|
37115
37252
|
const REACT_RSC_ADVISORIES_BY_MINOR = {
|
|
37116
37253
|
"19.0": {
|
|
37117
37254
|
rceFixedVersion: "19.0.1",
|
|
@@ -37158,20 +37295,13 @@ const enumerateWorkspaceDirectories = (workspaceRoot) => {
|
|
|
37158
37295
|
for (const pattern of patterns) for (const directory of resolveWorkspaceDirectories(workspaceRoot, pattern)) directories.add(directory);
|
|
37159
37296
|
return [...directories];
|
|
37160
37297
|
};
|
|
37161
|
-
const readDeclaredSpec = (packageJson, packageName) => {
|
|
37162
|
-
for (const section of DEPENDENCY_SECTIONS) {
|
|
37163
|
-
const spec = packageJson[section]?.[packageName];
|
|
37164
|
-
if (typeof spec === "string") return spec;
|
|
37165
|
-
}
|
|
37166
|
-
return null;
|
|
37167
|
-
};
|
|
37168
37298
|
const resolveVersionInDirectory = (directory, packageName, declaredSpecOverride) => {
|
|
37169
37299
|
const manifestPath = Path.join(directory, "node_modules", packageName, "package.json");
|
|
37170
37300
|
if (isFile(manifestPath)) {
|
|
37171
37301
|
const installedVersion = import_semver.valid(readPackageJson(manifestPath).version ?? null);
|
|
37172
37302
|
if (installedVersion !== null) return installedVersion;
|
|
37173
37303
|
}
|
|
37174
|
-
const candidateSpecs = [
|
|
37304
|
+
const candidateSpecs = [getDependencySpec(readPackageJson(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
|
|
37175
37305
|
for (const spec of candidateSpecs) {
|
|
37176
37306
|
const pinnedVersion = spec === null ? null : import_semver.valid(spec);
|
|
37177
37307
|
if (pinnedVersion !== null) return pinnedVersion;
|
|
@@ -37851,9 +37981,24 @@ const buildCapabilities = (project) => {
|
|
|
37851
37981
|
})) capabilities.add("tailwind:3.4");
|
|
37852
37982
|
if (project.zodVersion !== null) capabilities.add("zod");
|
|
37853
37983
|
if (project.zodMajorVersion !== null && project.zodMajorVersion >= 4) capabilities.add("zod:4");
|
|
37984
|
+
if (project.mobxVersion !== void 0 && project.mobxVersion !== null || project.hasMobxReact === true || project.hasMobxReactLite === true || project.hasMobxStateTree === true || project.hasMobxReactObserver === true) capabilities.add("mobx");
|
|
37985
|
+
if (project.hasMobxReact === true) capabilities.add("mobx-react");
|
|
37986
|
+
if (project.hasMobxReactLite === true) capabilities.add("mobx-react-lite");
|
|
37987
|
+
if (project.hasMobxReact === true || project.hasMobxReactLite === true) capabilities.add("mobx-react-binding");
|
|
37988
|
+
if (project.hasMobxStateTree === true) capabilities.add("mobx-state-tree");
|
|
37989
|
+
if (project.hasMobxReactObserver === true) capabilities.add("mobx-react-observer");
|
|
37990
|
+
if (project.mobxMajorVersion !== void 0 && project.mobxMajorVersion !== null && project.mobxMajorVersion >= 4 && project.mobxMajorVersion <= 6) addMajorLadder(capabilities, "mobx", project.mobxMajorVersion, 4, 6);
|
|
37991
|
+
if (project.zustandVersion !== void 0 && project.zustandVersion !== null) capabilities.add("zustand");
|
|
37992
|
+
if (project.zustandMajorVersion !== void 0 && project.zustandMajorVersion !== null && project.zustandMajorVersion >= 1 && project.zustandMajorVersion <= 5) addMajorLadder(capabilities, "zustand", project.zustandMajorVersion, 1, 5);
|
|
37854
37993
|
if (project.isPreES2023Target) capabilities.add("pre-es2023");
|
|
37855
37994
|
if (project.hasReactCompiler) capabilities.add("react-compiler");
|
|
37856
37995
|
if (project.hasTanStackQuery) capabilities.add("tanstack-query");
|
|
37996
|
+
if (project.valtioVersion !== null) capabilities.add("valtio");
|
|
37997
|
+
addMajorLadder(capabilities, "valtio", project.valtioMajorVersion, 1, 10);
|
|
37998
|
+
if (project.hasRemotion) {
|
|
37999
|
+
capabilities.add("remotion");
|
|
38000
|
+
addMajorLadder(capabilities, "remotion", project.remotionMajorVersion ?? null, 4, 30);
|
|
38001
|
+
}
|
|
37857
38002
|
if (project.hasTypeScript) capabilities.add("typescript");
|
|
37858
38003
|
if (project.preactVersion !== null) capabilities.add("preact");
|
|
37859
38004
|
addMajorLadder(capabilities, "preact", project.preactMajorVersion, 10, 20);
|
|
@@ -39090,6 +39235,35 @@ const parseGithubViewerPermission = (stdout) => {
|
|
|
39090
39235
|
return /^[A-Z_]+$/.test(value) ? value.toLowerCase() : null;
|
|
39091
39236
|
};
|
|
39092
39237
|
const splitNullSeparated = (value) => value.split("\0").filter((entry) => entry.length > 0);
|
|
39238
|
+
const parseBaselineDiffPlan = (value) => {
|
|
39239
|
+
const entries = splitNullSeparated(value);
|
|
39240
|
+
const baseFiles = /* @__PURE__ */ new Set();
|
|
39241
|
+
const headFiles = /* @__PURE__ */ new Set();
|
|
39242
|
+
for (let entryIndex = 0; entryIndex < entries.length; entryIndex += 2) {
|
|
39243
|
+
const status = entries[entryIndex];
|
|
39244
|
+
const filePath = entries[entryIndex + 1];
|
|
39245
|
+
if (status === void 0 || filePath === void 0 || status.length !== 1) return null;
|
|
39246
|
+
if (status === "A") {
|
|
39247
|
+
headFiles.add(filePath);
|
|
39248
|
+
continue;
|
|
39249
|
+
}
|
|
39250
|
+
if (status === "D") {
|
|
39251
|
+
baseFiles.add(filePath);
|
|
39252
|
+
continue;
|
|
39253
|
+
}
|
|
39254
|
+
if (status === "M" || status === "T") {
|
|
39255
|
+
baseFiles.add(filePath);
|
|
39256
|
+
headFiles.add(filePath);
|
|
39257
|
+
continue;
|
|
39258
|
+
}
|
|
39259
|
+
return null;
|
|
39260
|
+
}
|
|
39261
|
+
return {
|
|
39262
|
+
baseFiles: [...baseFiles],
|
|
39263
|
+
headFiles: [...headFiles],
|
|
39264
|
+
untrackedFiles: []
|
|
39265
|
+
};
|
|
39266
|
+
};
|
|
39093
39267
|
const UNTRACKED_FILE_LAST_LINE = Number.MAX_SAFE_INTEGER;
|
|
39094
39268
|
/**
|
|
39095
39269
|
* `Git` wraps every `git`-via-subprocess call react-doctor makes
|
|
@@ -39292,6 +39466,45 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
39292
39466
|
githubViewerPermission,
|
|
39293
39467
|
branchExists,
|
|
39294
39468
|
mergeBase,
|
|
39469
|
+
baselineDiffPlan: (input) => {
|
|
39470
|
+
if (!isSafeGitRevision(input.ref)) return succeed$2(null);
|
|
39471
|
+
return gen(function* () {
|
|
39472
|
+
const unmerged = yield* runGit(input.directory, [
|
|
39473
|
+
"diff",
|
|
39474
|
+
"--no-ext-diff",
|
|
39475
|
+
"-z",
|
|
39476
|
+
"--name-only",
|
|
39477
|
+
"--diff-filter=U",
|
|
39478
|
+
"--relative"
|
|
39479
|
+
]);
|
|
39480
|
+
if (unmerged.status !== 0 || unmerged.stdout.length > 0) return null;
|
|
39481
|
+
const result = yield* runGit(input.directory, [
|
|
39482
|
+
"diff",
|
|
39483
|
+
"--no-ext-diff",
|
|
39484
|
+
"--no-textconv",
|
|
39485
|
+
"--no-renames",
|
|
39486
|
+
"-z",
|
|
39487
|
+
"--name-status",
|
|
39488
|
+
"--relative",
|
|
39489
|
+
input.ref
|
|
39490
|
+
]);
|
|
39491
|
+
if (result.status !== 0) return null;
|
|
39492
|
+
const plan = parseBaselineDiffPlan(result.stdout);
|
|
39493
|
+
if (plan === null) return null;
|
|
39494
|
+
const untracked = yield* runGit(input.directory, [
|
|
39495
|
+
"ls-files",
|
|
39496
|
+
"--others",
|
|
39497
|
+
"--exclude-standard",
|
|
39498
|
+
"-z"
|
|
39499
|
+
]);
|
|
39500
|
+
if (untracked.status !== 0) return null;
|
|
39501
|
+
return {
|
|
39502
|
+
baseFiles: plan.baseFiles,
|
|
39503
|
+
headFiles: plan.headFiles,
|
|
39504
|
+
untrackedFiles: splitNullSeparated(untracked.stdout)
|
|
39505
|
+
};
|
|
39506
|
+
}).pipe(catch_$1(() => succeed$2(null)), withSpan("Git.baselineDiffPlan"));
|
|
39507
|
+
},
|
|
39295
39508
|
diffSelection: ({ directory, explicitBaseBranch, includeUntracked = false }) => gen(function* () {
|
|
39296
39509
|
if (explicitBaseBranch !== void 0 && explicitBaseBranch.trim().length === 0) return yield* fail$4(new ReactDoctorError({ reason: new GitBaseBranchInvalid({ detail: "Diff base branch cannot be empty." }) }));
|
|
39297
39510
|
if (explicitBaseBranch !== void 0) {
|
|
@@ -39441,6 +39654,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
39441
39654
|
githubViewerPermission: () => succeed$2(snapshot.githubViewerPermission ?? null),
|
|
39442
39655
|
branchExists: (_directory, branch) => succeed$2(snapshot.branchExists?.get(branch) ?? false),
|
|
39443
39656
|
mergeBase: ({ ref }) => succeed$2(snapshot.mergeBase?.get(ref) ?? null),
|
|
39657
|
+
baselineDiffPlan: () => succeed$2(snapshot.baselineDiffPlan ?? null),
|
|
39444
39658
|
diffSelection: () => succeed$2(snapshot.diffSelection ?? null),
|
|
39445
39659
|
stagedFilePaths: () => succeed$2(snapshot.stagedFiles ?? []),
|
|
39446
39660
|
showStagedContent: (_directory, relativePath) => succeed$2(snapshot.stagedContent?.get(relativePath) ?? null),
|
|
@@ -40778,12 +40992,17 @@ const REACT_ERROR_BOUNDARY_MESSAGE = "This try/catch cannot catch errors thrown
|
|
|
40778
40992
|
const REACT_COMPILER_IMPACT = "This component misses React Compiler's automatic memoization & re-renders more than it should";
|
|
40779
40993
|
const REACT_COMPILER_ACTION = "Rewrite the flagged code so the compiler can optimize it.";
|
|
40780
40994
|
const REACT_COMPILER_INCOMPATIBLE_LIBRARY_ACTION = "It's how the library works, not a bug in your code. Memoize values you pass from it into other memoized components, or suppress it with `// react-doctor-disable-next-line react-hooks-js/incompatible-library`.";
|
|
40995
|
+
const SET_STATE_IN_EFFECT_ACTION = "Prefer deriving or initializing the value before render. If the effect must read a browser API after mount, treat this as advisory or suppress it with `// react-doctor-disable-next-line react-hooks-js/set-state-in-effect`.";
|
|
40781
40996
|
const REACT_COMPILER_GENERIC_MESSAGE = `${REACT_COMPILER_IMPACT}. ${REACT_COMPILER_ACTION}`;
|
|
40782
40997
|
const buildReactCompilerMessage = (reasonSummary, action = REACT_COMPILER_ACTION) => {
|
|
40783
40998
|
const normalizedSummary = reasonSummary.replace(TRAILING_PERIOD_PATTERN, "");
|
|
40784
40999
|
if (!normalizedSummary) return `${REACT_COMPILER_IMPACT}. ${action}`;
|
|
40785
41000
|
return `${REACT_COMPILER_IMPACT}: ${normalizedSummary}. ${action}`;
|
|
40786
41001
|
};
|
|
41002
|
+
const buildSetStateInEffectMessage = (reasonSummary) => {
|
|
41003
|
+
const normalizedSummary = reasonSummary.replace(TRAILING_PERIOD_PATTERN, "");
|
|
41004
|
+
return `This synchronous effect update causes an extra render${normalizedSummary ? `: ${normalizedSummary}` : ""}. ${SET_STATE_IN_EFFECT_ACTION}`;
|
|
41005
|
+
};
|
|
40787
41006
|
const PLUGIN_CATEGORY_MAP = {
|
|
40788
41007
|
react: "Bugs",
|
|
40789
41008
|
"react-hooks": "Bugs",
|
|
@@ -40841,6 +41060,10 @@ const resolveCleanedDiagnostic = (message, help, plugin, rule, project) => {
|
|
|
40841
41060
|
message: REACT_ERROR_BOUNDARY_MESSAGE,
|
|
40842
41061
|
help: reasonDetail || help
|
|
40843
41062
|
};
|
|
41063
|
+
if (rule === "set-state-in-effect") return {
|
|
41064
|
+
message: buildSetStateInEffectMessage(reasonSummary.trim()),
|
|
41065
|
+
help: reasonDetail || help
|
|
41066
|
+
};
|
|
40844
41067
|
return {
|
|
40845
41068
|
message: buildReactCompilerMessage(reasonSummary.trim(), rule === "incompatible-library" ? REACT_COMPILER_INCOMPATIBLE_LIBRARY_ACTION : REACT_COMPILER_ACTION),
|
|
40846
41069
|
help: appendReanimatedSharedValueHint(reasonDetail || help, rule, project)
|
|
@@ -43166,12 +43389,19 @@ const isPathInsideDirectory = (childAbsolutePath, parentAbsolutePath) => {
|
|
|
43166
43389
|
*/
|
|
43167
43390
|
const materializeSourceTree = (input) => gen(function* () {
|
|
43168
43391
|
const materializedFiles = [];
|
|
43392
|
+
const unmaterializedFiles = [];
|
|
43169
43393
|
const resolvedTempDirectory = path.resolve(input.tempDirectory);
|
|
43170
43394
|
for (const relativePath of input.files) {
|
|
43171
43395
|
const content = yield* input.readContent(relativePath).pipe(orElseSucceed(() => null));
|
|
43172
|
-
if (content === null)
|
|
43396
|
+
if (content === null) {
|
|
43397
|
+
unmaterializedFiles.push(relativePath);
|
|
43398
|
+
continue;
|
|
43399
|
+
}
|
|
43173
43400
|
const candidateTargetPath = path.resolve(resolvedTempDirectory, relativePath);
|
|
43174
|
-
if (!isPathInsideDirectory(candidateTargetPath, resolvedTempDirectory))
|
|
43401
|
+
if (!isPathInsideDirectory(candidateTargetPath, resolvedTempDirectory)) {
|
|
43402
|
+
unmaterializedFiles.push(relativePath);
|
|
43403
|
+
continue;
|
|
43404
|
+
}
|
|
43175
43405
|
yield* sync(() => {
|
|
43176
43406
|
fs.mkdirSync(path.dirname(candidateTargetPath), { recursive: true });
|
|
43177
43407
|
fs.writeFileSync(candidateTargetPath, content);
|
|
@@ -43188,6 +43418,7 @@ const materializeSourceTree = (input) => gen(function* () {
|
|
|
43188
43418
|
return {
|
|
43189
43419
|
tempDirectory: input.tempDirectory,
|
|
43190
43420
|
materializedFiles,
|
|
43421
|
+
unmaterializedFiles,
|
|
43191
43422
|
cleanup: () => {
|
|
43192
43423
|
try {
|
|
43193
43424
|
fs.rmSync(input.tempDirectory, {
|
|
@@ -43751,4 +43982,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
43751
43982
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
43752
43983
|
|
|
43753
43984
|
//# sourceMappingURL=index.js.map
|
|
43754
|
-
//# debugId=
|
|
43985
|
+
//# debugId=6aa1c6e1-8fcc-50d4-a076-3e864425bdc5
|