react-doctor 0.0.19 → 0.0.20
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 +48 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.js +43 -1
- package/dist/index.js.map +1 -1
- package/dist/react-doctor-plugin.js +5 -2
- package/dist/react-doctor-plugin.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -765,6 +765,46 @@ const createOxlintConfig = ({ pluginPath, framework, hasReactCompiler }) => ({
|
|
|
765
765
|
}
|
|
766
766
|
});
|
|
767
767
|
|
|
768
|
+
//#endregion
|
|
769
|
+
//#region src/utils/neutralize-disable-directives.ts
|
|
770
|
+
const findFilesWithDisableDirectives = (rootDirectory) => {
|
|
771
|
+
const result = spawnSync("git", [
|
|
772
|
+
"grep",
|
|
773
|
+
"-l",
|
|
774
|
+
"--untracked",
|
|
775
|
+
"-E",
|
|
776
|
+
"(eslint|oxlint)-disable"
|
|
777
|
+
], {
|
|
778
|
+
cwd: rootDirectory,
|
|
779
|
+
encoding: "utf-8",
|
|
780
|
+
maxBuffer: GIT_LS_FILES_MAX_BUFFER_BYTES
|
|
781
|
+
});
|
|
782
|
+
if (result.error || result.status === null) return [];
|
|
783
|
+
return result.stdout.split("\n").filter((filePath) => filePath.length > 0 && SOURCE_FILE_PATTERN.test(filePath));
|
|
784
|
+
};
|
|
785
|
+
const neutralizeContent = (content) => content.replaceAll("eslint-disable", "eslint_disable").replaceAll("oxlint-disable", "oxlint_disable");
|
|
786
|
+
const neutralizeDisableDirectives = (rootDirectory) => {
|
|
787
|
+
const filePaths = findFilesWithDisableDirectives(rootDirectory);
|
|
788
|
+
const originalContents = /* @__PURE__ */ new Map();
|
|
789
|
+
for (const relativePath of filePaths) {
|
|
790
|
+
const absolutePath = path.join(rootDirectory, relativePath);
|
|
791
|
+
let originalContent;
|
|
792
|
+
try {
|
|
793
|
+
originalContent = fs.readFileSync(absolutePath, "utf-8");
|
|
794
|
+
} catch {
|
|
795
|
+
continue;
|
|
796
|
+
}
|
|
797
|
+
const neutralizedContent = neutralizeContent(originalContent);
|
|
798
|
+
if (neutralizedContent !== originalContent) {
|
|
799
|
+
originalContents.set(absolutePath, originalContent);
|
|
800
|
+
fs.writeFileSync(absolutePath, neutralizedContent);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return () => {
|
|
804
|
+
for (const [absolutePath, originalContent] of originalContents) fs.writeFileSync(absolutePath, originalContent);
|
|
805
|
+
};
|
|
806
|
+
};
|
|
807
|
+
|
|
768
808
|
//#endregion
|
|
769
809
|
//#region src/utils/run-oxlint.ts
|
|
770
810
|
const esmRequire = createRequire(import.meta.url);
|
|
@@ -832,7 +872,7 @@ const RULE_CATEGORY_MAP = {
|
|
|
832
872
|
"react-doctor/async-parallel": "Performance"
|
|
833
873
|
};
|
|
834
874
|
const RULE_HELP_MAP = {
|
|
835
|
-
"no-derived-state-effect": "
|
|
875
|
+
"no-derived-state-effect": "For derived state, compute inline: `const x = fn(dep)`. For state resets on prop change, use a key prop: `<Component key={prop} />`",
|
|
836
876
|
"no-fetch-in-effect": "Use `useQuery()` from @tanstack/react-query, `useSWR()`, or fetch in a Server Component instead",
|
|
837
877
|
"no-cascading-set-state": "Combine into useReducer: `const [state, dispatch] = useReducer(reducer, initialState)`",
|
|
838
878
|
"no-effect-event-handler": "Move the conditional logic into onClick, onChange, or onSubmit handlers directly",
|
|
@@ -934,6 +974,7 @@ const runOxlint = async (rootDirectory, hasTypeScript, framework, hasReactCompil
|
|
|
934
974
|
framework,
|
|
935
975
|
hasReactCompiler
|
|
936
976
|
});
|
|
977
|
+
const restoreDisableDirectives = neutralizeDisableDirectives(rootDirectory);
|
|
937
978
|
try {
|
|
938
979
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
939
980
|
const args = [
|
|
@@ -989,6 +1030,7 @@ const runOxlint = async (rootDirectory, hasTypeScript, framework, hasReactCompil
|
|
|
989
1030
|
};
|
|
990
1031
|
});
|
|
991
1032
|
} finally {
|
|
1033
|
+
restoreDisableDirectives();
|
|
992
1034
|
if (fs.existsSync(configPath)) fs.unlinkSync(configPath);
|
|
993
1035
|
}
|
|
994
1036
|
};
|
|
@@ -1266,7 +1308,10 @@ const scan = async (directory, inputOptions = {}) => {
|
|
|
1266
1308
|
return lintDiagnostics;
|
|
1267
1309
|
} catch (error) {
|
|
1268
1310
|
lintSpinner?.fail("Lint checks failed (non-fatal, skipping).");
|
|
1269
|
-
|
|
1311
|
+
if (error instanceof Error) {
|
|
1312
|
+
logger.error(error.message);
|
|
1313
|
+
if (error.stack) logger.dim(error.stack);
|
|
1314
|
+
} else logger.error(String(error));
|
|
1270
1315
|
return [];
|
|
1271
1316
|
}
|
|
1272
1317
|
})() : Promise.resolve([]);
|
|
@@ -1614,7 +1659,7 @@ const maybePromptSkillInstall = async (shouldSkipPrompts) => {
|
|
|
1614
1659
|
|
|
1615
1660
|
//#endregion
|
|
1616
1661
|
//#region src/cli.ts
|
|
1617
|
-
const VERSION = "0.0.
|
|
1662
|
+
const VERSION = "0.0.20";
|
|
1618
1663
|
process.on("SIGINT", () => process.exit(0));
|
|
1619
1664
|
process.on("SIGTERM", () => process.exit(0));
|
|
1620
1665
|
const resolveDiffMode = async (diffInfo, effectiveDiff, shouldSkipPrompts, isScoreOnly) => {
|