react-doctor 0.9.4-dev.212b8b4 → 0.9.4-dev.459c5d3

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/index.d.ts CHANGED
@@ -9834,13 +9834,13 @@ interface InspectResult {
9834
9834
  * Number of files the scan reported. Distinct from
9835
9835
  * `project.sourceFileCount` in diff / staged mode (where only changed
9836
9836
  * files are scanned). Optional so non-orchestrator constructors keep
9837
- * working; the multi-project summary falls back to
9837
+ * working; the multi-project report falls back to
9838
9838
  * `project.sourceFileCount` when absent.
9839
9839
  */
9840
9840
  scannedFileCount?: number;
9841
9841
  /**
9842
9842
  * Absolute paths of every file the scan considered. Lets the
9843
- * multi-project summary count UNIQUE files across projects instead of
9843
+ * multi-project report count UNIQUE files across projects instead of
9844
9844
  * summing per-project counts, which double-counts shared files when one
9845
9845
  * workspace package's tree is nested inside another's.
9846
9846
  */
@@ -9854,8 +9854,8 @@ interface InspectResult {
9854
9854
  /**
9855
9855
  * Wall-clock duration of the scan phase, in milliseconds. Distinct
9856
9856
  * from `elapsedMilliseconds` (which spans the full `inspect()` call
9857
- * including score fetch + rendering). Used by the multi-project
9858
- * summary to report combined scan time.
9857
+ * including score fetch + reporting). Used by the multi-project
9858
+ * report to show combined scan time.
9859
9859
  */
9860
9860
  scanElapsedMilliseconds?: number;
9861
9861
  /**
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]="8d6e3c06-44f8-589f-8e07-aaa4704b6112")}catch(e){}}();
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]="6d2e43de-ae97-5213-b1a7-a9905ce4b1d5")}catch(e){}}();
3
3
  import { i as __toESM$1, r as __require, t as __commonJSMin$1 } from "./chunk-ChKA3wi6.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { 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, REACT_DOCTOR_RULE_REGISTRY, REACT_DOCTOR_SCAN_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor/core";
@@ -70874,6 +70874,33 @@ const detectUserLintConfigPaths = (rootDirectory) => {
70874
70874
  return [];
70875
70875
  };
70876
70876
  const DISABLE_DIRECTIVE_PATTERN = /(eslint|oxlint)-disable/;
70877
+ const neutralizedFileLeases = /* @__PURE__ */ new Map();
70878
+ const activeNeutralizationInitializations = /* @__PURE__ */ new Set();
70879
+ const directoriesOverlap = (left, right) => {
70880
+ const isWithin = (parent, candidate) => {
70881
+ const relativePath = Path.relative(parent, candidate);
70882
+ return relativePath.length === 0 || !relativePath.startsWith(`..${Path.sep}`) && relativePath !== ".." && !Path.isAbsolute(relativePath);
70883
+ };
70884
+ return isWithin(left, right) || isWithin(right, left);
70885
+ };
70886
+ const withOverlappingInitializationLock = async (rootDirectory, operation) => {
70887
+ const blockers = [...activeNeutralizationInitializations].filter((initialization) => directoriesOverlap(initialization.rootDirectory, rootDirectory)).map((initialization) => initialization.done);
70888
+ let release;
70889
+ const initialization = {
70890
+ rootDirectory,
70891
+ done: new Promise((resolve) => {
70892
+ release = resolve;
70893
+ })
70894
+ };
70895
+ activeNeutralizationInitializations.add(initialization);
70896
+ await Promise.all(blockers);
70897
+ try {
70898
+ return await operation();
70899
+ } finally {
70900
+ activeNeutralizationInitializations.delete(initialization);
70901
+ release();
70902
+ }
70903
+ };
70877
70904
  const findFilesWithDisableDirectivesViaGit = async (rootDirectory, includePaths) => {
70878
70905
  const program = gen(function* () {
70879
70906
  return yield* (yield* Git).grep({
@@ -70916,34 +70943,84 @@ const findFilesWithDisableDirectivesViaFilesystem = (rootDirectory, includePaths
70916
70943
  };
70917
70944
  const findFilesWithDisableDirectives = async (rootDirectory, includePaths) => await findFilesWithDisableDirectivesViaGit(rootDirectory, includePaths) ?? findFilesWithDisableDirectivesViaFilesystem(rootDirectory, includePaths);
70918
70945
  const neutralizeContent = (content) => content.replaceAll("eslint-disable", "eslint_disable").replaceAll("oxlint-disable", "oxlint_disable");
70919
- const neutralizeDisableDirectives = async (rootDirectory, includePaths) => {
70920
- const filePaths = await findFilesWithDisableDirectives(rootDirectory, includePaths);
70921
- const originalContents = /* @__PURE__ */ new Map();
70946
+ const collectNeutralizationCandidatePaths = (rootDirectory, discoveredRelativePaths, includePaths) => {
70947
+ const resolvedRootDirectory = NFS.realpathSync(rootDirectory);
70948
+ const requestedPaths = includePaths && includePaths.length > 0 ? new Set(includePaths.flatMap((includePath) => {
70949
+ try {
70950
+ return [NFS.realpathSync(Path.resolve(resolvedRootDirectory, includePath))];
70951
+ } catch {
70952
+ return [];
70953
+ }
70954
+ })) : null;
70955
+ const candidatePaths = /* @__PURE__ */ new Set();
70956
+ for (const relativePath of discoveredRelativePaths) try {
70957
+ candidatePaths.add(NFS.realpathSync(Path.resolve(resolvedRootDirectory, relativePath)));
70958
+ } catch {
70959
+ continue;
70960
+ }
70961
+ for (const leasedPath of neutralizedFileLeases.keys()) {
70962
+ const relativePath = Path.relative(resolvedRootDirectory, leasedPath);
70963
+ if (!(relativePath.length === 0 || !relativePath.startsWith(`..${Path.sep}`) && relativePath !== ".." && !Path.isAbsolute(relativePath)) || requestedPaths && !requestedPaths.has(leasedPath)) continue;
70964
+ candidatePaths.add(leasedPath);
70965
+ }
70966
+ return candidatePaths;
70967
+ };
70968
+ const neutralizeDisableDirectives = async (rootDirectory, includePaths, options = {}) => {
70969
+ const resolvedRootDirectory = NFS.realpathSync(rootDirectory);
70970
+ const leasedPaths = /* @__PURE__ */ new Set();
70922
70971
  let isRestored = false;
70923
70972
  const restore = () => {
70924
70973
  if (isRestored) return;
70925
70974
  isRestored = true;
70926
- for (const [absolutePath, originalContent] of originalContents) try {
70927
- NFS.writeFileSync(absolutePath, originalContent);
70928
- } catch (error) {
70929
- process.stderr.write(`[react-doctor] Failed to restore inline disable directives in ${absolutePath}: ${messageFromUnknown(error)}\n[react-doctor] Run: git checkout -- ${absolutePath}\n`);
70975
+ for (const absolutePath of leasedPaths) {
70976
+ const lease = neutralizedFileLeases.get(absolutePath);
70977
+ if (!lease) continue;
70978
+ lease.referenceCount -= 1;
70979
+ if (lease.referenceCount > 0) continue;
70980
+ neutralizedFileLeases.delete(absolutePath);
70981
+ try {
70982
+ NFS.writeFileSync(absolutePath, lease.originalContent);
70983
+ } catch (error) {
70984
+ process.stderr.write(`[react-doctor] Failed to restore inline disable directives in ${absolutePath}: ${messageFromUnknown(error)}\n[react-doctor] Run: git checkout -- ${absolutePath}\n`);
70985
+ }
70930
70986
  }
70931
70987
  };
70932
70988
  const onExit = () => restore();
70933
70989
  process.once("exit", onExit);
70934
- for (const relativePath of filePaths) {
70935
- const absolutePath = Path.join(rootDirectory, relativePath);
70990
+ const leaseCandidatePath = (absolutePath) => {
70991
+ if (leasedPaths.has(absolutePath)) return;
70992
+ const existingLease = neutralizedFileLeases.get(absolutePath);
70993
+ if (existingLease) {
70994
+ existingLease.referenceCount += 1;
70995
+ leasedPaths.add(absolutePath);
70996
+ return;
70997
+ }
70936
70998
  let originalContent;
70937
70999
  try {
70938
71000
  originalContent = NFS.readFileSync(absolutePath, "utf-8");
70939
71001
  } catch {
70940
- continue;
71002
+ return;
70941
71003
  }
70942
71004
  const neutralizedContent = neutralizeContent(originalContent);
70943
71005
  if (neutralizedContent !== originalContent) {
70944
- originalContents.set(absolutePath, originalContent);
70945
71006
  NFS.writeFileSync(absolutePath, neutralizedContent);
71007
+ neutralizedFileLeases.set(absolutePath, {
71008
+ originalContent,
71009
+ referenceCount: 1
71010
+ });
71011
+ leasedPaths.add(absolutePath);
70946
71012
  }
71013
+ };
71014
+ try {
71015
+ await withOverlappingInitializationLock(resolvedRootDirectory, async () => {
71016
+ for (const absolutePath of collectNeutralizationCandidatePaths(resolvedRootDirectory, [], includePaths)) if (neutralizedFileLeases.has(absolutePath)) leaseCandidatePath(absolutePath);
71017
+ const discoveredRelativePaths = await (options.findFiles ?? findFilesWithDisableDirectives)(resolvedRootDirectory, includePaths);
71018
+ for (const absolutePath of collectNeutralizationCandidatePaths(resolvedRootDirectory, discoveredRelativePaths, includePaths)) leaseCandidatePath(absolutePath);
71019
+ });
71020
+ } catch (error) {
71021
+ restore();
71022
+ process.removeListener("exit", onExit);
71023
+ throw error;
70947
71024
  }
70948
71025
  return () => {
70949
71026
  restore();
@@ -75837,4 +75914,4 @@ const toJsonReport = (result, options) => buildJsonReport({
75837
75914
  export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
75838
75915
 
75839
75916
  //# sourceMappingURL=index.js.map
75840
- //# debugId=8d6e3c06-44f8-589f-8e07-aaa4704b6112
75917
+ //# debugId=6d2e43de-ae97-5213-b1a7-a9905ce4b1d5
package/dist/lsp.js CHANGED
@@ -70903,6 +70903,33 @@ const detectUserLintConfigPaths = (rootDirectory) => {
70903
70903
  return [];
70904
70904
  };
70905
70905
  const DISABLE_DIRECTIVE_PATTERN = /(eslint|oxlint)-disable/;
70906
+ const neutralizedFileLeases = /* @__PURE__ */ new Map();
70907
+ const activeNeutralizationInitializations = /* @__PURE__ */ new Set();
70908
+ const directoriesOverlap = (left, right) => {
70909
+ const isWithin = (parent, candidate) => {
70910
+ const relativePath = Path.relative(parent, candidate);
70911
+ return relativePath.length === 0 || !relativePath.startsWith(`..${Path.sep}`) && relativePath !== ".." && !Path.isAbsolute(relativePath);
70912
+ };
70913
+ return isWithin(left, right) || isWithin(right, left);
70914
+ };
70915
+ const withOverlappingInitializationLock = async (rootDirectory, operation) => {
70916
+ const blockers = [...activeNeutralizationInitializations].filter((initialization) => directoriesOverlap(initialization.rootDirectory, rootDirectory)).map((initialization) => initialization.done);
70917
+ let release;
70918
+ const initialization = {
70919
+ rootDirectory,
70920
+ done: new Promise((resolve) => {
70921
+ release = resolve;
70922
+ })
70923
+ };
70924
+ activeNeutralizationInitializations.add(initialization);
70925
+ await Promise.all(blockers);
70926
+ try {
70927
+ return await operation();
70928
+ } finally {
70929
+ activeNeutralizationInitializations.delete(initialization);
70930
+ release();
70931
+ }
70932
+ };
70906
70933
  const findFilesWithDisableDirectivesViaGit = async (rootDirectory, includePaths) => {
70907
70934
  const program = gen(function* () {
70908
70935
  return yield* (yield* Git).grep({
@@ -70945,34 +70972,84 @@ const findFilesWithDisableDirectivesViaFilesystem = (rootDirectory, includePaths
70945
70972
  };
70946
70973
  const findFilesWithDisableDirectives = async (rootDirectory, includePaths) => await findFilesWithDisableDirectivesViaGit(rootDirectory, includePaths) ?? findFilesWithDisableDirectivesViaFilesystem(rootDirectory, includePaths);
70947
70974
  const neutralizeContent = (content) => content.replaceAll("eslint-disable", "eslint_disable").replaceAll("oxlint-disable", "oxlint_disable");
70948
- const neutralizeDisableDirectives = async (rootDirectory, includePaths) => {
70949
- const filePaths = await findFilesWithDisableDirectives(rootDirectory, includePaths);
70950
- const originalContents = /* @__PURE__ */ new Map();
70975
+ const collectNeutralizationCandidatePaths = (rootDirectory, discoveredRelativePaths, includePaths) => {
70976
+ const resolvedRootDirectory = NFS.realpathSync(rootDirectory);
70977
+ const requestedPaths = includePaths && includePaths.length > 0 ? new Set(includePaths.flatMap((includePath) => {
70978
+ try {
70979
+ return [NFS.realpathSync(Path.resolve(resolvedRootDirectory, includePath))];
70980
+ } catch {
70981
+ return [];
70982
+ }
70983
+ })) : null;
70984
+ const candidatePaths = /* @__PURE__ */ new Set();
70985
+ for (const relativePath of discoveredRelativePaths) try {
70986
+ candidatePaths.add(NFS.realpathSync(Path.resolve(resolvedRootDirectory, relativePath)));
70987
+ } catch {
70988
+ continue;
70989
+ }
70990
+ for (const leasedPath of neutralizedFileLeases.keys()) {
70991
+ const relativePath = Path.relative(resolvedRootDirectory, leasedPath);
70992
+ if (!(relativePath.length === 0 || !relativePath.startsWith(`..${Path.sep}`) && relativePath !== ".." && !Path.isAbsolute(relativePath)) || requestedPaths && !requestedPaths.has(leasedPath)) continue;
70993
+ candidatePaths.add(leasedPath);
70994
+ }
70995
+ return candidatePaths;
70996
+ };
70997
+ const neutralizeDisableDirectives = async (rootDirectory, includePaths, options = {}) => {
70998
+ const resolvedRootDirectory = NFS.realpathSync(rootDirectory);
70999
+ const leasedPaths = /* @__PURE__ */ new Set();
70951
71000
  let isRestored = false;
70952
71001
  const restore = () => {
70953
71002
  if (isRestored) return;
70954
71003
  isRestored = true;
70955
- for (const [absolutePath, originalContent] of originalContents) try {
70956
- NFS.writeFileSync(absolutePath, originalContent);
70957
- } catch (error) {
70958
- process.stderr.write(`[react-doctor] Failed to restore inline disable directives in ${absolutePath}: ${messageFromUnknown(error)}\n[react-doctor] Run: git checkout -- ${absolutePath}\n`);
71004
+ for (const absolutePath of leasedPaths) {
71005
+ const lease = neutralizedFileLeases.get(absolutePath);
71006
+ if (!lease) continue;
71007
+ lease.referenceCount -= 1;
71008
+ if (lease.referenceCount > 0) continue;
71009
+ neutralizedFileLeases.delete(absolutePath);
71010
+ try {
71011
+ NFS.writeFileSync(absolutePath, lease.originalContent);
71012
+ } catch (error) {
71013
+ process.stderr.write(`[react-doctor] Failed to restore inline disable directives in ${absolutePath}: ${messageFromUnknown(error)}\n[react-doctor] Run: git checkout -- ${absolutePath}\n`);
71014
+ }
70959
71015
  }
70960
71016
  };
70961
71017
  const onExit = () => restore();
70962
71018
  process.once("exit", onExit);
70963
- for (const relativePath of filePaths) {
70964
- const absolutePath = Path.join(rootDirectory, relativePath);
71019
+ const leaseCandidatePath = (absolutePath) => {
71020
+ if (leasedPaths.has(absolutePath)) return;
71021
+ const existingLease = neutralizedFileLeases.get(absolutePath);
71022
+ if (existingLease) {
71023
+ existingLease.referenceCount += 1;
71024
+ leasedPaths.add(absolutePath);
71025
+ return;
71026
+ }
70965
71027
  let originalContent;
70966
71028
  try {
70967
71029
  originalContent = NFS.readFileSync(absolutePath, "utf-8");
70968
71030
  } catch {
70969
- continue;
71031
+ return;
70970
71032
  }
70971
71033
  const neutralizedContent = neutralizeContent(originalContent);
70972
71034
  if (neutralizedContent !== originalContent) {
70973
- originalContents.set(absolutePath, originalContent);
70974
71035
  NFS.writeFileSync(absolutePath, neutralizedContent);
71036
+ neutralizedFileLeases.set(absolutePath, {
71037
+ originalContent,
71038
+ referenceCount: 1
71039
+ });
71040
+ leasedPaths.add(absolutePath);
70975
71041
  }
71042
+ };
71043
+ try {
71044
+ await withOverlappingInitializationLock(resolvedRootDirectory, async () => {
71045
+ for (const absolutePath of collectNeutralizationCandidatePaths(resolvedRootDirectory, [], includePaths)) if (neutralizedFileLeases.has(absolutePath)) leaseCandidatePath(absolutePath);
71046
+ const discoveredRelativePaths = await (options.findFiles ?? findFilesWithDisableDirectives)(resolvedRootDirectory, includePaths);
71047
+ for (const absolutePath of collectNeutralizationCandidatePaths(resolvedRootDirectory, discoveredRelativePaths, includePaths)) leaseCandidatePath(absolutePath);
71048
+ });
71049
+ } catch (error) {
71050
+ restore();
71051
+ process.removeListener("exit", onExit);
71052
+ throw error;
70976
71053
  }
70977
71054
  return () => {
70978
71055
  restore();
@@ -77529,5 +77606,5 @@ const startLanguageServer = () => {
77529
77606
  };
77530
77607
  //#endregion
77531
77608
  export { startLanguageServer };
77532
- !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]="2d26cd21-f7f6-5e65-9c29-fabf32208583")}catch(e){}}();
77533
- //# debugId=2d26cd21-f7f6-5e65-9c29-fabf32208583
77609
+ !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]="8e8ec622-f2dc-5f52-bfe8-232b07051a7f")}catch(e){}}();
77610
+ //# debugId=8e8ec622-f2dc-5f52-bfe8-232b07051a7f