react-doctor 0.9.4-dev.8b97fdc → 0.9.4-dev.bafef41

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
@@ -1,4 +1,5 @@
1
1
  import { FrameworkToken } from "oxlint-plugin-react-doctor/core";
2
+ import fs from "node:fs";
2
3
 
3
4
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.70/node_modules/effect/dist/Types.d.ts
4
5
  /**
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]="e18e3c42-e18e-5087-9b71-eb1bcb203d6b")}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";
@@ -62298,17 +62298,20 @@ const SUPPLY_CHAIN_IGNORED_PACKAGES = new Set(["next"]);
62298
62298
  const isErrnoException = (error) => error instanceof Error && "code" in error;
62299
62299
  const IGNORABLE_READDIR_ERROR_CODES = new Set([
62300
62300
  "EACCES",
62301
+ "EBUSY",
62301
62302
  "EPERM",
62302
62303
  "ENOENT",
62303
62304
  "ENOTDIR",
62304
62305
  "EINVAL",
62305
62306
  "ELOOP",
62306
- "ENAMETOOLONG"
62307
+ "ENAMETOOLONG",
62308
+ "ETIMEDOUT",
62309
+ "UNKNOWN"
62307
62310
  ]);
62308
62311
  const isIgnorableReaddirError = (error) => isErrnoException(error) && typeof error.code === "string" && IGNORABLE_READDIR_ERROR_CODES.has(error.code);
62309
62312
  const readDirectoryEntries = (directoryPath) => {
62310
62313
  try {
62311
- return NFS.readdirSync(directoryPath, { withFileTypes: true });
62314
+ return fs.readdirSync(directoryPath, { withFileTypes: true });
62312
62315
  } catch (error) {
62313
62316
  if (isIgnorableReaddirError(error)) return [];
62314
62317
  throw error;
@@ -62316,14 +62319,14 @@ const readDirectoryEntries = (directoryPath) => {
62316
62319
  };
62317
62320
  const isFile = (filePath) => {
62318
62321
  try {
62319
- return NFS.statSync(filePath).isFile();
62322
+ return fs.statSync(filePath).isFile();
62320
62323
  } catch {
62321
62324
  return false;
62322
62325
  }
62323
62326
  };
62324
62327
  const isDirectory = (directoryPath) => {
62325
62328
  try {
62326
- return NFS.statSync(directoryPath).isDirectory();
62329
+ return fs.statSync(directoryPath).isDirectory();
62327
62330
  } catch {
62328
62331
  return false;
62329
62332
  }
@@ -62753,7 +62756,12 @@ const mergeCompilerOptions = (inherited, current) => {
62753
62756
  };
62754
62757
  };
62755
62758
  const readResolvedCompilerOptions = (tsConfigPath, extendsDepth, visitedPaths) => {
62756
- const realPath = NFS.realpathSync.native(tsConfigPath);
62759
+ let realPath;
62760
+ try {
62761
+ realPath = NFS.realpathSync.native(tsConfigPath);
62762
+ } catch {
62763
+ return null;
62764
+ }
62757
62765
  if (visitedPaths.has(realPath)) return null;
62758
62766
  const tsConfig = readTsConfig(realPath);
62759
62767
  if (!tsConfig) return null;
@@ -63281,27 +63289,30 @@ const getSelectedObjectProperty = (expression, propertyName, analysis, visitedEx
63281
63289
  }
63282
63290
  return null;
63283
63291
  };
63284
- const configExpressionMayDefineProperty = (expression, propertyName, analysis) => {
63292
+ const configExpressionMayDefineProperty = (expression, propertyName, analysis, visitedExpressions = /* @__PURE__ */ new Set()) => {
63285
63293
  let resolvedExpression = expression;
63286
63294
  while (ts.isParenthesizedExpression(resolvedExpression) || ts.isAsExpression(resolvedExpression) || ts.isTypeAssertionExpression(resolvedExpression) || ts.isSatisfiesExpression(resolvedExpression) || ts.isNonNullExpression(resolvedExpression)) resolvedExpression = resolvedExpression.expression;
63295
+ if (visitedExpressions.has(resolvedExpression)) return true;
63296
+ const nextVisitedExpressions = new Set(visitedExpressions);
63297
+ nextVisitedExpressions.add(resolvedExpression);
63287
63298
  if (ts.isIdentifier(resolvedExpression)) {
63288
63299
  if (analysis.localBindings.has(resolvedExpression.text)) {
63289
63300
  const localReference = analysis.localBindings.get(resolvedExpression.text);
63290
- return localReference?.expression ? configExpressionMayDefineProperty(localReference.expression, propertyName, localReference.analysis) : true;
63301
+ return localReference?.expression ? configExpressionMayDefineProperty(localReference.expression, propertyName, localReference.analysis, nextVisitedExpressions) : true;
63291
63302
  }
63292
63303
  const scopedBinding = getScopedConfigBinding(resolvedExpression);
63293
- if (scopedBinding.wasFound) return scopedBinding.initializer ? configExpressionMayDefineProperty(scopedBinding.initializer, propertyName, analysis) : true;
63304
+ if (scopedBinding.wasFound) return scopedBinding.initializer ? configExpressionMayDefineProperty(scopedBinding.initializer, propertyName, analysis, nextVisitedExpressions) : true;
63294
63305
  const topLevelBinding = getTopLevelBinding(analysis.sourceFile, resolvedExpression.text);
63295
- return topLevelBinding && ts.isExpression(topLevelBinding) ? configExpressionMayDefineProperty(topLevelBinding, propertyName, analysis) : true;
63306
+ return topLevelBinding && ts.isExpression(topLevelBinding) ? configExpressionMayDefineProperty(topLevelBinding, propertyName, analysis, nextVisitedExpressions) : true;
63296
63307
  }
63297
63308
  if (ts.isConditionalExpression(resolvedExpression)) {
63298
- if (isStaticallyTruthyConfigExpression(resolvedExpression.condition, analysis)) return configExpressionMayDefineProperty(resolvedExpression.whenTrue, propertyName, analysis);
63299
- if (isStaticallyDisabledConfigExpression(resolvedExpression.condition, analysis)) return configExpressionMayDefineProperty(resolvedExpression.whenFalse, propertyName, analysis);
63300
- return configExpressionMayDefineProperty(resolvedExpression.whenTrue, propertyName, analysis) || configExpressionMayDefineProperty(resolvedExpression.whenFalse, propertyName, analysis);
63309
+ if (isStaticallyTruthyConfigExpression(resolvedExpression.condition, analysis)) return configExpressionMayDefineProperty(resolvedExpression.whenTrue, propertyName, analysis, nextVisitedExpressions);
63310
+ if (isStaticallyDisabledConfigExpression(resolvedExpression.condition, analysis)) return configExpressionMayDefineProperty(resolvedExpression.whenFalse, propertyName, analysis, nextVisitedExpressions);
63311
+ return configExpressionMayDefineProperty(resolvedExpression.whenTrue, propertyName, analysis, nextVisitedExpressions) || configExpressionMayDefineProperty(resolvedExpression.whenFalse, propertyName, analysis, nextVisitedExpressions);
63301
63312
  }
63302
63313
  if (!ts.isObjectLiteralExpression(resolvedExpression)) return true;
63303
63314
  return resolvedExpression.properties.some((property) => {
63304
- if (ts.isSpreadAssignment(property)) return configExpressionMayDefineProperty(property.expression, propertyName, analysis);
63315
+ if (ts.isSpreadAssignment(property)) return configExpressionMayDefineProperty(property.expression, propertyName, analysis, nextVisitedExpressions);
63305
63316
  if (ts.isPropertyAssignment(property) || ts.isShorthandPropertyAssignment(property) || ts.isMethodDeclaration(property) || ts.isGetAccessorDeclaration(property) || ts.isSetAccessorDeclaration(property)) {
63306
63317
  const staticPropertyName = getStaticPropertyName$2(property.name);
63307
63318
  return staticPropertyName === null || staticPropertyName === propertyName;
@@ -63377,7 +63388,13 @@ const analyzeConfigModuleExport = (filePath, exportName, allowCompilerTransform,
63377
63388
  if (visitedModules.has(moduleVisitKey)) return false;
63378
63389
  const nextVisitedModules = new Set(visitedModules);
63379
63390
  nextVisitedModules.add(moduleVisitKey);
63380
- return analyzeConfigSourceFileExport(parseConfigSourceFile(filePath, NFS.readFileSync(filePath, "utf-8")), filePath, exportName, allowCompilerTransform, importDepth, nextVisitedModules, argumentsList, argumentAnalysis);
63391
+ let sourceText;
63392
+ try {
63393
+ sourceText = NFS.readFileSync(filePath, "utf-8");
63394
+ } catch {
63395
+ return false;
63396
+ }
63397
+ return analyzeConfigSourceFileExport(parseConfigSourceFile(filePath, sourceText), filePath, exportName, allowCompilerTransform, importDepth, nextVisitedModules, argumentsList, argumentAnalysis);
63381
63398
  };
63382
63399
  const analyzeConfigSourceFileExport = (sourceFile, filePath, exportName, allowCompilerTransform, importDepth, visitedModules, argumentsList = [], argumentAnalysis) => {
63383
63400
  const analysis = {
@@ -66880,6 +66897,43 @@ const validateStringArrayField = (fieldName, value) => {
66880
66897
  return false;
66881
66898
  });
66882
66899
  };
66900
+ const validateIgnoreOverride = (rawOverride, index) => {
66901
+ const fieldName = `ignore.overrides[${index}]`;
66902
+ if (!isRecord(rawOverride)) {
66903
+ warnConfigIssue(`config field "${fieldName}" must be an object (got ${typeof rawOverride}); ignoring this override.`);
66904
+ return;
66905
+ }
66906
+ const files = validateStringArrayField(`${fieldName}.files`, rawOverride.files);
66907
+ if (files === void 0) return void 0;
66908
+ const validatedOverride = { files };
66909
+ if (rawOverride.rules !== void 0) {
66910
+ const rules = validateStringArrayField(`${fieldName}.rules`, rawOverride.rules);
66911
+ if (rules !== void 0) validatedOverride.rules = rules;
66912
+ }
66913
+ return validatedOverride;
66914
+ };
66915
+ const validateIgnoreField = (rawIgnore) => {
66916
+ if (!isRecord(rawIgnore)) {
66917
+ warnConfigIssue(`config field "ignore" must be an object (got ${typeof rawIgnore}); ignoring this field.`);
66918
+ return;
66919
+ }
66920
+ const validatedIgnore = {};
66921
+ for (const fieldName of [
66922
+ "rules",
66923
+ "files",
66924
+ "tags"
66925
+ ]) {
66926
+ if (rawIgnore[fieldName] === void 0) continue;
66927
+ const validatedValues = validateStringArrayField(`ignore.${fieldName}`, rawIgnore[fieldName]);
66928
+ if (validatedValues !== void 0) validatedIgnore[fieldName] = validatedValues;
66929
+ }
66930
+ if (rawIgnore.overrides !== void 0) if (!Array.isArray(rawIgnore.overrides)) warnConfigIssue(`config field "ignore.overrides" must be an array (got ${typeof rawIgnore.overrides}); ignoring this field.`);
66931
+ else validatedIgnore.overrides = rawIgnore.overrides.flatMap((rawOverride, index) => {
66932
+ const validatedOverride = validateIgnoreOverride(rawOverride, index);
66933
+ return validatedOverride ? [validatedOverride] : [];
66934
+ });
66935
+ return validatedIgnore;
66936
+ };
66883
66937
  const validateSurfaceControls = (surface, rawControls) => {
66884
66938
  if (!isRecord(rawControls)) {
66885
66939
  warnConfigIssue(`config field "surfaces.${surface}" must be an object (got ${typeof rawControls}); ignoring this surface.`);
@@ -66955,6 +67009,7 @@ const validateConfigTypes = (config) => {
66955
67009
  for (const fieldName of BOOLEAN_FIELD_NAMES) applyFieldValidator(config, validated, fieldName, (value) => coerceMaybeBooleanString(fieldName, value));
66956
67010
  for (const fieldName of STRING_FIELD_NAMES) applyFieldValidator(config, validated, fieldName, (value) => validateString(fieldName, value));
66957
67011
  for (const fieldName of STRING_ARRAY_FIELD_NAMES) applyFieldValidator(config, validated, fieldName, (value) => validateStringArrayField(fieldName, value));
67012
+ applyFieldValidator(config, validated, "ignore", validateIgnoreField);
66958
67013
  applyFieldValidator(config, validated, "surfaces", validateSurfacesField);
66959
67014
  for (const fieldName of SEVERITY_FIELD_NAMES) applyFieldValidator(config, validated, fieldName, (value) => validateSeverityMap(fieldName, value, fieldName === "categories"));
66960
67015
  applyFieldValidator(config, validated, "plugins", (value) => validateStringArrayField("plugins", value));
@@ -68619,7 +68674,7 @@ const collectScriptMotionEvidence = (sourceFile, typeChecker, program) => {
68619
68674
  if (calleeEvidence.isReducedMotionHook && isExpressionValueConsumed(node)) evidence.hasReducedMotionHandling = true;
68620
68675
  }
68621
68676
  if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
68622
- const tagEvidence = ts.isJsxNamespacedName(node.tagName) ? EMPTY_MOTION_EXPRESSION_EVIDENCE : resolveMotionExpressionEvidence(node.tagName, typeChecker, program);
68677
+ const tagEvidence = ts.isIdentifier(node.tagName) || ts.isPropertyAccessExpression(node.tagName) ? resolveMotionExpressionEvidence(node.tagName, typeChecker, program) : EMPTY_MOTION_EXPRESSION_EVIDENCE;
68623
68678
  if (tagEvidence.isMotionComponent || tagEvidence.isMotionComponentFactory) evidence.hasMotionUse = true;
68624
68679
  if (tagEvidence.isMotionConfig && jsxElementHasReducedMotionConfiguration(node.attributes, typeChecker)) evidence.hasReducedMotionHandling = true;
68625
68680
  }
@@ -70603,7 +70658,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
70603
70658
  changedFiles: yield* mergeUntracked(directory, splitNullSeparated(diff.stdout), includeUntracked),
70604
70659
  isCurrentChanges: false
70605
70660
  };
70606
- }).pipe(withSpan("Git.diffSelection")),
70661
+ }).pipe(catchReasons("ReactDoctorError", { GitInvocationFailed: () => succeed$2(null) }, (_reason, error) => fail$4(error)), withSpan("Git.diffSelection")),
70607
70662
  stagedFilePaths: (directory) => runGit(directory, [
70608
70663
  "diff",
70609
70664
  "--no-ext-diff",
@@ -70819,6 +70874,33 @@ const detectUserLintConfigPaths = (rootDirectory) => {
70819
70874
  return [];
70820
70875
  };
70821
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
+ };
70822
70904
  const findFilesWithDisableDirectivesViaGit = async (rootDirectory, includePaths) => {
70823
70905
  const program = gen(function* () {
70824
70906
  return yield* (yield* Git).grep({
@@ -70861,34 +70943,84 @@ const findFilesWithDisableDirectivesViaFilesystem = (rootDirectory, includePaths
70861
70943
  };
70862
70944
  const findFilesWithDisableDirectives = async (rootDirectory, includePaths) => await findFilesWithDisableDirectivesViaGit(rootDirectory, includePaths) ?? findFilesWithDisableDirectivesViaFilesystem(rootDirectory, includePaths);
70863
70945
  const neutralizeContent = (content) => content.replaceAll("eslint-disable", "eslint_disable").replaceAll("oxlint-disable", "oxlint_disable");
70864
- const neutralizeDisableDirectives = async (rootDirectory, includePaths) => {
70865
- const filePaths = await findFilesWithDisableDirectives(rootDirectory, includePaths);
70866
- 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();
70867
70971
  let isRestored = false;
70868
70972
  const restore = () => {
70869
70973
  if (isRestored) return;
70870
70974
  isRestored = true;
70871
- for (const [absolutePath, originalContent] of originalContents) try {
70872
- NFS.writeFileSync(absolutePath, originalContent);
70873
- } catch (error) {
70874
- 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
+ }
70875
70986
  }
70876
70987
  };
70877
70988
  const onExit = () => restore();
70878
70989
  process.once("exit", onExit);
70879
- for (const relativePath of filePaths) {
70880
- 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
+ }
70881
70998
  let originalContent;
70882
70999
  try {
70883
71000
  originalContent = NFS.readFileSync(absolutePath, "utf-8");
70884
71001
  } catch {
70885
- continue;
71002
+ return;
70886
71003
  }
70887
71004
  const neutralizedContent = neutralizeContent(originalContent);
70888
71005
  if (neutralizedContent !== originalContent) {
70889
- originalContents.set(absolutePath, originalContent);
70890
71006
  NFS.writeFileSync(absolutePath, neutralizedContent);
71007
+ neutralizedFileLeases.set(absolutePath, {
71008
+ originalContent,
71009
+ referenceCount: 1
71010
+ });
71011
+ leasedPaths.add(absolutePath);
70891
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;
70892
71024
  }
70893
71025
  return () => {
70894
71026
  restore();
@@ -75223,7 +75355,7 @@ const materializeSourceTree = (input) => gen(function* () {
75223
75355
  const sourcePath = path.join(input.directory, subdirectory, configFilename);
75224
75356
  const targetPath = path.resolve(resolvedTempDirectory, subdirectory, configFilename);
75225
75357
  if (!isPathInsideDirectory(targetPath, resolvedTempDirectory)) continue;
75226
- if (fs.existsSync(sourcePath) && !fs.existsSync(targetPath)) {
75358
+ if (isFile(sourcePath) && !fs.existsSync(targetPath)) {
75227
75359
  fs.mkdirSync(path.dirname(targetPath), { recursive: true });
75228
75360
  fs.cpSync(sourcePath, targetPath);
75229
75361
  }
@@ -75564,16 +75696,17 @@ const detectAiTrainingEnvironment = (environment = process.env) => {
75564
75696
  for (const [environmentVariable, label] of AI_TRAINING_BY_ENVIRONMENT_VARIABLE) if (environment[environmentVariable]?.trim()) return label;
75565
75697
  return null;
75566
75698
  };
75567
- const unionValues = (baseValues, overrideValues) => [...new Set([...baseValues, ...overrideValues])];
75699
+ const stringValues = (values) => Array.isArray(values) ? values.filter((value) => typeof value === "string") : [];
75700
+ const unionValues = (baseValues, overrideValues) => [...new Set([...stringValues(baseValues), ...stringValues(overrideValues)])];
75568
75701
  const mergeIgnores = (baseIgnore, overrideIgnore) => {
75569
75702
  const mergedIgnore = {
75570
75703
  ...baseIgnore,
75571
75704
  ...overrideIgnore
75572
75705
  };
75573
- if (baseIgnore.rules && overrideIgnore.rules) mergedIgnore.rules = unionValues(baseIgnore.rules, overrideIgnore.rules);
75574
- if (baseIgnore.files && overrideIgnore.files) mergedIgnore.files = unionValues(baseIgnore.files, overrideIgnore.files);
75575
- if (baseIgnore.tags && overrideIgnore.tags) mergedIgnore.tags = unionValues(baseIgnore.tags, overrideIgnore.tags);
75576
- if (baseIgnore.overrides && overrideIgnore.overrides) mergedIgnore.overrides = [...baseIgnore.overrides, ...overrideIgnore.overrides];
75706
+ if (baseIgnore.rules !== void 0 || overrideIgnore.rules !== void 0) mergedIgnore.rules = unionValues(baseIgnore.rules, overrideIgnore.rules);
75707
+ if (baseIgnore.files !== void 0 || overrideIgnore.files !== void 0) mergedIgnore.files = unionValues(baseIgnore.files, overrideIgnore.files);
75708
+ if (baseIgnore.tags !== void 0 || overrideIgnore.tags !== void 0) mergedIgnore.tags = unionValues(baseIgnore.tags, overrideIgnore.tags);
75709
+ if (baseIgnore.overrides !== void 0 || overrideIgnore.overrides !== void 0) mergedIgnore.overrides = [...Array.isArray(baseIgnore.overrides) ? baseIgnore.overrides : [], ...Array.isArray(overrideIgnore.overrides) ? overrideIgnore.overrides : []];
75577
75710
  return mergedIgnore;
75578
75711
  };
75579
75712
  /**
@@ -75781,4 +75914,4 @@ const toJsonReport = (result, options) => buildJsonReport({
75781
75914
  export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
75782
75915
 
75783
75916
  //# sourceMappingURL=index.js.map
75784
- //# debugId=e18e3c42-e18e-5087-9b71-eb1bcb203d6b
75917
+ //# debugId=6d2e43de-ae97-5213-b1a7-a9905ce4b1d5