react-doctor 0.7.6-dev.543ebfe → 0.7.6-dev.5699529

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 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]="5dcb5b0b-ca1e-5655-8f52-3c22b421256d")}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]="58e54b02-7ba2-5f13-a535-98c236467a86")}catch(e){}}();
3
3
  import { createRequire } from "node:module";
4
4
  import * as NodeChildProcess from "node:child_process";
5
5
  import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
@@ -43659,11 +43659,11 @@ const buildRelatedLocations = (labels, filePath) => {
43659
43659
  }
43660
43660
  return related;
43661
43661
  };
43662
- const isOxlintOutput = (value) => {
43663
- if (typeof value !== "object" || value === null) return false;
43664
- const candidate = value;
43665
- return Array.isArray(candidate.diagnostics);
43666
- };
43662
+ const isOxlintSpan = (value) => isRecord$1(value) && typeof value.offset === "number" && typeof value.length === "number" && typeof value.line === "number" && typeof value.column === "number";
43663
+ const isOxlintLabel = (value) => isRecord$1(value) && isOxlintSpan(value.span);
43664
+ const isMappableOxlintDiagnostic = (value) => isRecord$1(value) && typeof value.code === "string" && value.code.length > 0 && typeof value.filename === "string" && value.filename.length > 0 && (value.severity === "warning" || value.severity === "error") && Array.isArray(value.labels) && value.labels.every(isOxlintLabel);
43665
+ const isEngineFailureDiagnostic = (value) => !isRecord$1(value) || typeof value.filename !== "string" || value.filename.length === 0;
43666
+ const isOxlintOutput = (value) => isRecord$1(value) && Array.isArray(value.diagnostics);
43667
43667
  /**
43668
43668
  * Parses one oxlint subprocess's stdout into a flat `Diagnostic[]`.
43669
43669
  * Tolerates the leading-notice-line shape oxlint sometimes prints
@@ -43682,6 +43682,8 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
43682
43682
  throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
43683
43683
  }
43684
43684
  if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
43685
+ const engineFailureDiagnostic = parsed.diagnostics.find(isEngineFailureDiagnostic);
43686
+ if (engineFailureDiagnostic !== void 0) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: JSON.stringify(engineFailureDiagnostic).slice(0, 600) }) });
43685
43687
  const minifiedFileCache = /* @__PURE__ */ new Map();
43686
43688
  const sourceBufferCache = /* @__PURE__ */ new Map();
43687
43689
  const sourceLinesCache = /* @__PURE__ */ new Map();
@@ -43716,7 +43718,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
43716
43718
  minifiedFileCache.set(absolutePath, minified);
43717
43719
  return minified;
43718
43720
  };
43719
- return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
43721
+ return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => isMappableOxlintDiagnostic(diagnostic) && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
43720
43722
  const { plugin, rule } = parseRuleCode(diagnostic.code);
43721
43723
  const primaryLabel = diagnostic.labels[0];
43722
43724
  const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
@@ -46622,6 +46624,43 @@ const isNonInteractiveEnvironment = () => NON_INTERACTIVE_ENVIRONMENT_VARIABLES.
46622
46624
  //#region src/cli/utils/constants.ts
46623
46625
  const REACT_DOCTOR_CONFIG_PROJECT_NAME = "react-doctor";
46624
46626
  const STAGED_FILES_TEMP_DIR_PREFIX = "react-doctor-staged-";
46627
+ const STAGED_SNAPSHOT_ADDITIONAL_CONFIG_FILENAMES = [
46628
+ ".babelrc",
46629
+ ".babelrc.json",
46630
+ ".eslintignore",
46631
+ ".eslintrc.json",
46632
+ ".oxlintignore",
46633
+ "app.config.cjs",
46634
+ "app.config.js",
46635
+ "app.config.json",
46636
+ "app.config.mjs",
46637
+ "app.config.ts",
46638
+ "app.json",
46639
+ "babel.config.cjs",
46640
+ "babel.config.js",
46641
+ "babel.config.json",
46642
+ "babel.config.mjs",
46643
+ "eslint.config.cjs",
46644
+ "eslint.config.cts",
46645
+ "eslint.config.js",
46646
+ "eslint.config.mjs",
46647
+ "eslint.config.mts",
46648
+ "eslint.config.ts",
46649
+ "next.config.cjs",
46650
+ "next.config.js",
46651
+ "next.config.mjs",
46652
+ "next.config.ts",
46653
+ "oxlint.config.json",
46654
+ "react-doctor.config.json",
46655
+ "vite.config.cjs",
46656
+ "vite.config.cts",
46657
+ "vite.config.js",
46658
+ "vite.config.mjs",
46659
+ "vite.config.mts",
46660
+ "vite.config.ts",
46661
+ "vitest.config.js",
46662
+ "vitest.config.ts"
46663
+ ];
46625
46664
  const BASELINE_FILES_TEMP_DIR_PREFIX = "react-doctor-baseline-";
46626
46665
  const SCAN_RESULT_CACHE_FILENAME = "scan-cache.json";
46627
46666
  const RUN_GIT_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
@@ -46636,6 +46675,7 @@ const METRIC = {
46636
46675
  cliInvoked: "cli.invoked",
46637
46676
  cliError: "cli.error",
46638
46677
  cliEnvironmentError: "cli.env_error",
46678
+ stagedSnapshotDivergence: "staged.snapshot_divergence",
46639
46679
  projectDetected: "project.detected",
46640
46680
  projectPathSelected: "project.path_selected",
46641
46681
  projectConfigSelected: "project.config_selected",
@@ -46716,7 +46756,7 @@ const makeNoopConsole = () => ({
46716
46756
  });
46717
46757
  //#endregion
46718
46758
  //#region src/cli/utils/version.ts
46719
- const VERSION = "0.7.6-dev.543ebfe";
46759
+ const VERSION = "0.7.6-dev.5699529";
46720
46760
  //#endregion
46721
46761
  //#region src/cli/utils/json-mode.ts
46722
46762
  let context = null;
@@ -47085,13 +47125,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
47085
47125
  * uploads source-map artifacts under, so stack frames symbolicate. Honors the
47086
47126
  * standard `SENTRY_RELEASE` override.
47087
47127
  */
47088
- const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.6-dev.543ebfe`;
47128
+ const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.6-dev.5699529`;
47089
47129
  /**
47090
47130
  * Deployment environment shown in Sentry's environment filter. Defaults to
47091
47131
  * `production` for tagged releases and `development` for dev/unbuilt versions,
47092
47132
  * overridable via the standard `SENTRY_ENVIRONMENT` env var.
47093
47133
  */
47094
- const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.6-dev.543ebfe") ? "development" : "production");
47134
+ const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.6-dev.5699529") ? "development" : "production");
47095
47135
  /**
47096
47136
  * Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
47097
47137
  * (set to `0` to disable tracing) and falls back to
@@ -47283,7 +47323,7 @@ const NON_BLOCKING_REACT_DOCTOR_COMMAND = [
47283
47323
  "fi"
47284
47324
  ].join(" ");
47285
47325
  const PACKAGE_JSON_FILE_NAME = "package.json";
47286
- const runGit = (projectRoot, args) => {
47326
+ const runGitRaw = (projectRoot, args) => {
47287
47327
  try {
47288
47328
  return execFileSync("git", [...args], {
47289
47329
  cwd: projectRoot,
@@ -47294,11 +47334,12 @@ const runGit = (projectRoot, args) => {
47294
47334
  "ignore"
47295
47335
  ],
47296
47336
  maxBuffer: RUN_GIT_MAX_BUFFER_BYTES
47297
- }).trim();
47337
+ });
47298
47338
  } catch {
47299
47339
  return null;
47300
47340
  }
47301
47341
  };
47342
+ const runGit = (projectRoot, args) => runGitRaw(projectRoot, args)?.trim() ?? null;
47302
47343
  const resolveGitPath = (baseDirectory, value) => Path.isAbsolute(value) ? value : Path.resolve(baseDirectory, value);
47303
47344
  const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
47304
47345
  const getPackageJsonPath = (projectRoot) => Path.join(projectRoot, PACKAGE_JSON_FILE_NAME);
@@ -59169,6 +59210,17 @@ const buildRuleBlastRadii = (diagnostics) => buildSortedRuleGroups(diagnostics).
59169
59210
  })).toSorted((left, right) => right.fileCount - left.fileCount);
59170
59211
  const findMigrationScaleBuckets = (diagnostics) => buildRuleBlastRadii(diagnostics).filter((bucket) => bucket.fileCount >= 40);
59171
59212
  //#endregion
59213
+ //#region src/cli/utils/has-lint-hard-failure.ts
59214
+ const hasLintHardFailure = (result) => result.skippedChecks.includes("lint");
59215
+ //#endregion
59216
+ //#region src/cli/utils/is-inspect-result-complete.ts
59217
+ const isInspectResultComplete = (result) => isScanComplete({
59218
+ analyzedFileCount: result.analyzedFiles?.length,
59219
+ scannedFileCount: result.scannedFileCount,
59220
+ skippedCheckCount: result.skippedChecks.length,
59221
+ skippedCheckReasonCount: Object.keys(result.skippedCheckReasons ?? {}).length
59222
+ });
59223
+ //#endregion
59172
59224
  //#region src/cli/utils/scan-result-cache.ts
59173
59225
  const CACHE_DISABLED_VALUES = new Set(["1", "true"]);
59174
59226
  const TOOLCHAIN_PACKAGE_SPECIFIERS = [
@@ -59574,15 +59626,12 @@ const buildOutcomeAttributes = (input) => {
59574
59626
  const summary = summarizeDiagnostics(result.diagnostics);
59575
59627
  const blockingLevel = resolveTelemetryBlocking(input.userConfig);
59576
59628
  const gateDiagnostics = filterDiagnosticsForSurface(result.diagnostics, "ciFailure", input.userConfig);
59629
+ const complete = isInspectResultComplete(result);
59630
+ const didLintHardFail = hasLintHardFailure(result);
59631
+ const failsOnHardFailure = didLintHardFail && blockingLevel !== "none";
59577
59632
  const wouldBlock = !input.scoreOnly && !input.gateExempt && shouldBlockCi(gateDiagnostics, blockingLevel);
59578
- const complete = isScanComplete({
59579
- analyzedFileCount: result.analyzedFiles?.length,
59580
- scannedFileCount: result.scannedFileCount,
59581
- skippedCheckCount: result.skippedChecks.length,
59582
- skippedCheckReasonCount: Object.keys(result.skippedCheckReasons ?? {}).length
59583
- });
59584
59633
  const isClean = result.diagnostics.length === 0 && complete;
59585
- const outcome = wouldBlock ? "blocked" : isClean ? "clean" : "ok";
59634
+ const outcome = didLintHardFail ? "error" : wouldBlock ? "blocked" : isClean ? "clean" : "ok";
59586
59635
  const firings = summarizeRuleFirings(result.diagnostics);
59587
59636
  const countByRule = /* @__PURE__ */ new Map();
59588
59637
  const countByCategory = /* @__PURE__ */ new Map();
@@ -59627,7 +59676,7 @@ const buildOutcomeAttributes = (input) => {
59627
59676
  const attributes = {
59628
59677
  ...withNamespace("outcome", {
59629
59678
  status: outcome,
59630
- exitCode: wouldBlock ? 1 : 0,
59679
+ exitCode: failsOnHardFailure || wouldBlock ? 1 : 0,
59631
59680
  wouldBlock,
59632
59681
  blocking: blockingLevel,
59633
59682
  clean: isClean,
@@ -63826,6 +63875,39 @@ const validateModeFlags = (flags) => {
63826
63875
  }
63827
63876
  };
63828
63877
  //#endregion
63878
+ //#region src/cli/utils/parse-staged-snapshot-divergences.ts
63879
+ const SNAPSHOT_CONFIG_FILENAMES = new Set([...STAGED_FILES_PROJECT_CONFIG_FILENAMES, ...STAGED_SNAPSHOT_ADDITIONAL_CONFIG_FILENAMES]);
63880
+ const parseStagedSnapshotDivergences = (statusOutput) => {
63881
+ const divergentConfigFiles = /* @__PURE__ */ new Set();
63882
+ const statusEntries = statusOutput.split("\0").filter((entry) => entry.length > 0);
63883
+ for (let entryIndex = 0; entryIndex < statusEntries.length; entryIndex += 1) {
63884
+ const entry = statusEntries[entryIndex];
63885
+ const [indexStatus, worktreeStatus] = entry;
63886
+ const filePath = entry.slice(3);
63887
+ const hasRenameOrCopySource = indexStatus === "R" || indexStatus === "C" || worktreeStatus === "R" || worktreeStatus === "C";
63888
+ const sourcePath = hasRenameOrCopySource ? statusEntries[entryIndex + 1] : void 0;
63889
+ const worktreePaths = worktreeStatus === "R" || worktreeStatus === "C" ? [filePath, sourcePath] : [filePath];
63890
+ if (worktreeStatus !== " ") {
63891
+ for (const worktreePath of worktreePaths) if (worktreePath && SNAPSHOT_CONFIG_FILENAMES.has(Path.basename(worktreePath))) divergentConfigFiles.add(worktreePath);
63892
+ }
63893
+ if (hasRenameOrCopySource) entryIndex += 1;
63894
+ }
63895
+ return [...divergentConfigFiles].sort();
63896
+ };
63897
+ //#endregion
63898
+ //#region src/cli/utils/find-staged-snapshot-divergences.ts
63899
+ const findStagedSnapshotDivergences = (directory) => {
63900
+ const statusOutput = runGitRaw(directory, [
63901
+ "status",
63902
+ "--porcelain=v1",
63903
+ "-z",
63904
+ "--untracked-files=all",
63905
+ "--ignored=matching"
63906
+ ]);
63907
+ if (statusOutput === null) return null;
63908
+ return parseStagedSnapshotDivergences(statusOutput);
63909
+ };
63910
+ //#endregion
63829
63911
  //#region src/cli/commands/inspect.ts
63830
63912
  const filterCompletedScansByCategories = (completedScans, categoryFilters) => {
63831
63913
  if (categoryFilters.size === 0) return [...completedScans];
@@ -63840,9 +63922,14 @@ const filterCompletedScansByCategories = (completedScans, categoryFilters) => {
63840
63922
  /**
63841
63923
  * Post-scan finalization shared by the staged-arm and project-loop
63842
63924
  * paths of `inspectAction`: emit the JSON report (when in JSON mode)
63843
- * and set `process.exitCode = 1` when a diagnostic at or above the
63844
- * `--blocking` threshold (default `"error"`) reaches the `ciFailure`
63845
- * surface. `--blocking none` keeps the scan advisory (always exits 0).
63925
+ * and set `process.exitCode = 1` when any scan's lint pass hard-failed
63926
+ * (an engine/plugin/binding failure destroys the findings, so success
63927
+ * would be a false clean) or a diagnostic at or above the `--blocking`
63928
+ * threshold (default `"error"`) reaches the `ciFailure` surface.
63929
+ * `--blocking none` keeps the scan advisory (always exits 0), and
63930
+ * fail-open degradations — `--no-lint`, `--max-duration` truncation,
63931
+ * supply-chain/security skips — stay advisory too, surfaced through
63932
+ * `complete: false` in the JSON report.
63846
63933
  */
63847
63934
  const finalizeScans = (input) => {
63848
63935
  const baselineDeltas = input.completedScans.flatMap((scan) => scan.result.baselineDelta ? [scan.result.baselineDelta] : []);
@@ -63872,8 +63959,13 @@ const finalizeScans = (input) => {
63872
63959
  baselineDegraded
63873
63960
  }));
63874
63961
  }
63962
+ const blockingLevel = resolveBlockingLevel(input.flags, input.userConfig);
63963
+ if (input.completedScans.some(({ result }) => hasLintHardFailure(result)) && blockingLevel !== "none") {
63964
+ process.exitCode = 1;
63965
+ return;
63966
+ }
63875
63967
  if (input.isScoreOnly || baselineDegraded) return;
63876
- if (shouldBlockCi(filterScansForSurface(input.completedScans, "ciFailure"), resolveBlockingLevel(input.flags, input.userConfig))) process.exitCode = 1;
63968
+ if (shouldBlockCi(filterScansForSurface(input.completedScans, "ciFailure"), blockingLevel)) process.exitCode = 1;
63877
63969
  };
63878
63970
  const buildChangedFilesDiffInfo = (changedFiles) => ({
63879
63971
  currentBranch: process.env.GITHUB_HEAD_REF?.trim() || null,
@@ -63911,6 +64003,7 @@ const inspectAction = async (directory, flags) => {
63911
64003
  recordCount(METRIC.cliInvoked, 1, { command: "inspect" });
63912
64004
  try {
63913
64005
  validateModeFlags(flags);
64006
+ if (flags.staged) setJsonReportMode("staged");
63914
64007
  await maybeMigrateLegacyConfig(requestedDirectory, {
63915
64008
  isQuiet,
63916
64009
  isStaged: Boolean(flags.staged)
@@ -63926,6 +64019,14 @@ const inspectAction = async (directory, flags) => {
63926
64019
  cliLogger.dim(`Redirected to ${highlighter.info(toRelativePath(resolvedDirectory, requestedDirectory))} via react-doctor config "rootDir".`);
63927
64020
  cliLogger.break();
63928
64021
  }
64022
+ if (flags.staged) {
64023
+ const divergentConfigFiles = findStagedSnapshotDivergences(resolvedDirectory);
64024
+ if (divergentConfigFiles === null) throw new CliInputError("Could not verify that staged configuration matches the worktree. Run the command from a Git worktree with Git available.");
64025
+ if (divergentConfigFiles.length > 0) {
64026
+ recordCount(METRIC.stagedSnapshotDivergence, 1, { divergentInputCount: divergentConfigFiles.length });
64027
+ throw new CliInputError(`Cannot scan staged files while configuration differs between the index and worktree: ${divergentConfigFiles.join(", ")}. Stage or restore those files, then rerun react-doctor --staged.`);
64028
+ }
64029
+ }
63929
64030
  const explainArgument = flags.explain;
63930
64031
  if (explainArgument !== void 0) {
63931
64032
  await runExplain(explainArgument, {
@@ -63946,7 +64047,6 @@ const inspectAction = async (directory, flags) => {
63946
64047
  json: flags.json
63947
64048
  });
63948
64049
  if (flags.staged) {
63949
- setJsonReportMode("staged");
63950
64050
  const stagedFiles = await getStagedSourceFiles(resolvedDirectory);
63951
64051
  if (stagedFiles.length === 0) {
63952
64052
  if (isJsonMode) writeJsonReport(buildJsonReport({
@@ -65297,4 +65397,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
65297
65397
  export {};
65298
65398
 
65299
65399
  //# sourceMappingURL=cli.js.map
65300
- //# debugId=5dcb5b0b-ca1e-5655-8f52-3c22b421256d
65400
+ //# debugId=58e54b02-7ba2-5f13-a535-98c236467a86
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]="80f981d4-ebf0-5bc0-9643-8a68d27626a5")}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]="2aa6fc3c-96ab-5a4c-8a52-e74d27fb4b5a")}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";
@@ -40415,11 +40415,11 @@ const buildRelatedLocations = (labels, filePath) => {
40415
40415
  }
40416
40416
  return related;
40417
40417
  };
40418
- const isOxlintOutput = (value) => {
40419
- if (typeof value !== "object" || value === null) return false;
40420
- const candidate = value;
40421
- return Array.isArray(candidate.diagnostics);
40422
- };
40418
+ const isOxlintSpan = (value) => isRecord(value) && typeof value.offset === "number" && typeof value.length === "number" && typeof value.line === "number" && typeof value.column === "number";
40419
+ const isOxlintLabel = (value) => isRecord(value) && isOxlintSpan(value.span);
40420
+ const isMappableOxlintDiagnostic = (value) => isRecord(value) && typeof value.code === "string" && value.code.length > 0 && typeof value.filename === "string" && value.filename.length > 0 && (value.severity === "warning" || value.severity === "error") && Array.isArray(value.labels) && value.labels.every(isOxlintLabel);
40421
+ const isEngineFailureDiagnostic = (value) => !isRecord(value) || typeof value.filename !== "string" || value.filename.length === 0;
40422
+ const isOxlintOutput = (value) => isRecord(value) && Array.isArray(value.diagnostics);
40423
40423
  /**
40424
40424
  * Parses one oxlint subprocess's stdout into a flat `Diagnostic[]`.
40425
40425
  * Tolerates the leading-notice-line shape oxlint sometimes prints
@@ -40438,6 +40438,8 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
40438
40438
  throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
40439
40439
  }
40440
40440
  if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
40441
+ const engineFailureDiagnostic = parsed.diagnostics.find(isEngineFailureDiagnostic);
40442
+ if (engineFailureDiagnostic !== void 0) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: JSON.stringify(engineFailureDiagnostic).slice(0, 600) }) });
40441
40443
  const minifiedFileCache = /* @__PURE__ */ new Map();
40442
40444
  const sourceBufferCache = /* @__PURE__ */ new Map();
40443
40445
  const sourceLinesCache = /* @__PURE__ */ new Map();
@@ -40472,7 +40474,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
40472
40474
  minifiedFileCache.set(absolutePath, minified);
40473
40475
  return minified;
40474
40476
  };
40475
- return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
40477
+ return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => isMappableOxlintDiagnostic(diagnostic) && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
40476
40478
  const { plugin, rule } = parseRuleCode(diagnostic.code);
40477
40479
  const primaryLabel = diagnostic.labels[0];
40478
40480
  const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
@@ -43258,4 +43260,4 @@ const toJsonReport = (result, options) => buildJsonReport({
43258
43260
  export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
43259
43261
 
43260
43262
  //# sourceMappingURL=index.js.map
43261
- //# debugId=80f981d4-ebf0-5bc0-9643-8a68d27626a5
43263
+ //# debugId=2aa6fc3c-96ab-5a4c-8a52-e74d27fb4b5a
package/dist/lsp.js CHANGED
@@ -40393,11 +40393,11 @@ const buildRelatedLocations = (labels, filePath) => {
40393
40393
  }
40394
40394
  return related;
40395
40395
  };
40396
- const isOxlintOutput = (value) => {
40397
- if (typeof value !== "object" || value === null) return false;
40398
- const candidate = value;
40399
- return Array.isArray(candidate.diagnostics);
40400
- };
40396
+ const isOxlintSpan = (value) => isRecord(value) && typeof value.offset === "number" && typeof value.length === "number" && typeof value.line === "number" && typeof value.column === "number";
40397
+ const isOxlintLabel = (value) => isRecord(value) && isOxlintSpan(value.span);
40398
+ const isMappableOxlintDiagnostic = (value) => isRecord(value) && typeof value.code === "string" && value.code.length > 0 && typeof value.filename === "string" && value.filename.length > 0 && (value.severity === "warning" || value.severity === "error") && Array.isArray(value.labels) && value.labels.every(isOxlintLabel);
40399
+ const isEngineFailureDiagnostic = (value) => !isRecord(value) || typeof value.filename !== "string" || value.filename.length === 0;
40400
+ const isOxlintOutput = (value) => isRecord(value) && Array.isArray(value.diagnostics);
40401
40401
  /**
40402
40402
  * Parses one oxlint subprocess's stdout into a flat `Diagnostic[]`.
40403
40403
  * Tolerates the leading-notice-line shape oxlint sometimes prints
@@ -40416,6 +40416,8 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
40416
40416
  throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
40417
40417
  }
40418
40418
  if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
40419
+ const engineFailureDiagnostic = parsed.diagnostics.find(isEngineFailureDiagnostic);
40420
+ if (engineFailureDiagnostic !== void 0) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: JSON.stringify(engineFailureDiagnostic).slice(0, 600) }) });
40419
40421
  const minifiedFileCache = /* @__PURE__ */ new Map();
40420
40422
  const sourceBufferCache = /* @__PURE__ */ new Map();
40421
40423
  const sourceLinesCache = /* @__PURE__ */ new Map();
@@ -40450,7 +40452,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
40450
40452
  minifiedFileCache.set(absolutePath, minified);
40451
40453
  return minified;
40452
40454
  };
40453
- return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
40455
+ return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => isMappableOxlintDiagnostic(diagnostic) && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
40454
40456
  const { plugin, rule } = parseRuleCode(diagnostic.code);
40455
40457
  const primaryLabel = diagnostic.labels[0];
40456
40458
  const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
@@ -44540,6 +44542,7 @@ const METRIC = {
44540
44542
  cliInvoked: "cli.invoked",
44541
44543
  cliError: "cli.error",
44542
44544
  cliEnvironmentError: "cli.env_error",
44545
+ stagedSnapshotDivergence: "staged.snapshot_divergence",
44543
44546
  projectDetected: "project.detected",
44544
44547
  projectPathSelected: "project.path_selected",
44545
44548
  projectConfigSelected: "project.config_selected",
@@ -44894,5 +44897,5 @@ const startLanguageServer = () => {
44894
44897
  };
44895
44898
  //#endregion
44896
44899
  export { startLanguageServer };
44897
- !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]="288f7240-2ee1-5bcb-a56e-bca2b972818c")}catch(e){}}();
44898
- //# debugId=288f7240-2ee1-5bcb-a56e-bca2b972818c
44900
+ !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]="8ed74459-2a69-556c-bb95-8cdebdb094cd")}catch(e){}}();
44901
+ //# debugId=8ed74459-2a69-556c-bb95-8cdebdb094cd
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-doctor",
3
- "version": "0.7.6-dev.543ebfe",
3
+ "version": "0.7.6-dev.5699529",
4
4
  "description": "Your agent writes bad React. This catches it",
5
5
  "keywords": [
6
6
  "accessibility",
@@ -66,7 +66,7 @@
66
66
  "vscode-uri": "^3.1.0",
67
67
  "yaml": "^2.9.0",
68
68
  "deslop-js": "0.7.6",
69
- "oxlint-plugin-react-doctor": "0.7.6-dev.543ebfe"
69
+ "oxlint-plugin-react-doctor": "0.7.6-dev.5699529"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/babel__code-frame": "^7.27.0",
@@ -74,9 +74,9 @@
74
74
  "@xterm/headless": "^6.0.0",
75
75
  "commander": "^14.0.3",
76
76
  "ora": "^9.4.0",
77
+ "@react-doctor/api": "0.7.6",
77
78
  "@react-doctor/core": "0.7.6",
78
- "@react-doctor/language-server": "0.7.6",
79
- "@react-doctor/api": "0.7.6"
79
+ "@react-doctor/language-server": "0.7.6"
80
80
  },
81
81
  "engines": {
82
82
  "node": "^20.19.0 || >=22.13.0"