react-doctor 0.7.0-dev.c0c3fc1 → 0.7.0

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]="5d16dd1c-3fc1-567b-943f-887174c145c1")}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]="96cac03b-44a6-5d88-a5c9-697a5e8cf45e")}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";
@@ -22405,7 +22405,6 @@ var Diagnostic = class extends Class("Diagnostic")({
22405
22405
  endLine: optional(Number$1),
22406
22406
  endColumn: optional(Number$1),
22407
22407
  category: String$1,
22408
- matchByOccurrence: optional(Boolean$1),
22409
22408
  fileContext: optional(Literals(["test", "story"])),
22410
22409
  suppressionHint: optional(String$1),
22411
22410
  relatedLocations: optional(ArraySchema(DiagnosticRelatedLocation)),
@@ -22476,16 +22475,6 @@ var JsonReportV1 = class extends Class("JsonReportV1")({
22476
22475
  * successful `baseline` run (`schemaVersion: 2`) and on non-compare scopes.
22477
22476
  */
22478
22477
  baselineDegraded: optional(Boolean$1),
22479
- /**
22480
- * Whether any scanned project resolved a React-compatible runtime (React
22481
- * or Preact). `false` means every React-runtime rule family was gated off,
22482
- * so an empty `diagnostics` array is vacuous — NOT the same as a clean
22483
- * React scan. Consumers gating on the report (CI, verifiers, hooks) should
22484
- * treat `reactDetected === false` as "wrong scan target", not "all clear".
22485
- * Absent when nothing was scanned (`projects` is empty), on error reports,
22486
- * and on reports from older CLI versions.
22487
- */
22488
- reactDetected: optional(Boolean$1),
22489
22478
  diff: NullOr(JsonReportDiffInfo),
22490
22479
  projects: ArraySchema(JsonReportProjectEntry),
22491
22480
  diagnostics: ArraySchema(Diagnostic),
@@ -22511,8 +22500,6 @@ var JsonReportV2 = class extends Class("JsonReportV2")({
22511
22500
  ok: Boolean$1,
22512
22501
  directory: String$1,
22513
22502
  mode: JsonReportMode,
22514
- /** See `JsonReportV1.reactDetected`. */
22515
- reactDetected: optional(Boolean$1),
22516
22503
  diff: NullOr(JsonReportDiffInfo),
22517
22504
  baseline: JsonReportBaseline,
22518
22505
  projects: ArraySchema(JsonReportProjectEntry),
@@ -36121,7 +36108,6 @@ const DIAGNOSTIC_CATEGORY_BUCKETS = [
36121
36108
  "Accessibility",
36122
36109
  "Maintainability"
36123
36110
  ];
36124
- const OCCURRENCE_MATCHED_CATEGORIES = new Set(["Accessibility"]);
36125
36111
  const APP_ONLY_RULE_KEYS = new Set([
36126
36112
  "react-hooks-js/static-components",
36127
36113
  "react-doctor/no-render-prop-children",
@@ -40251,17 +40237,10 @@ function* collectSecurityScanFiles(rootDirectory) {
40251
40237
  }
40252
40238
  }
40253
40239
  }
40254
- /**
40255
- * Whether project discovery resolved a React-compatible runtime (React or
40256
- * Preact, which ships the same hooks + JSX model). This is the same
40257
- * predicate that grants the `react` capability, so `false` means every
40258
- * React-runtime rule family was gated off for the project.
40259
- */
40260
- const hasReactRuntime = (project) => project.reactVersion !== null || project.preactVersion !== null;
40261
40240
  const buildCapabilities = (project) => {
40262
40241
  const capabilities = /* @__PURE__ */ new Set();
40263
40242
  capabilities.add(project.framework);
40264
- if (hasReactRuntime(project)) capabilities.add("react");
40243
+ if (project.reactVersion !== null || project.preactVersion !== null) capabilities.add("react");
40265
40244
  if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
40266
40245
  if (project.expoVersion !== null) capabilities.add("expo");
40267
40246
  if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 15) capabilities.add("nextjs:15");
@@ -43113,7 +43092,6 @@ const parseRuleCode = (code) => {
43113
43092
  };
43114
43093
  };
43115
43094
  const resolveDiagnosticCategory = (plugin, rule) => getRuleCategory(rule) ?? lookupOwnString(PLUGIN_CATEGORY_MAP, plugin) ?? "Bugs";
43116
- const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORIES.has(category) || Boolean(reactDoctorPlugin.rules[rule]?.matchByOccurrence);
43117
43095
  /**
43118
43096
  * Maps oxlint's non-primary labels (`labels[1..]`) into related source
43119
43097
  * locations. Editors surface these as a diagnostic's
@@ -43177,7 +43155,6 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
43177
43155
  const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
43178
43156
  const primarySpan = primaryLabel?.span;
43179
43157
  const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
43180
- const category = resolveDiagnosticCategory(plugin, rule);
43181
43158
  return {
43182
43159
  filePath: normalizedFilePath,
43183
43160
  plugin,
@@ -43193,8 +43170,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
43193
43170
  offset: primarySpan.offset,
43194
43171
  length: primarySpan.length
43195
43172
  } : {},
43196
- category,
43197
- ...resolveMatchByOccurrence(rule, category) ? { matchByOccurrence: true } : {},
43173
+ category: resolveDiagnosticCategory(plugin, rule),
43198
43174
  ...relatedLocations.length > 0 ? { relatedLocations } : {}
43199
43175
  };
43200
43176
  });
@@ -45379,7 +45355,6 @@ const buildJsonReport = (input) => {
45379
45355
  const worstScoredProject = findWorstScoredProject(projects);
45380
45356
  const summary = summarizeDiagnostics(flattenedDiagnostics, worstScoredProject?.score?.score ?? null, worstScoredProject?.score?.label ?? null);
45381
45357
  const shared = {
45382
- ...input.scans.length > 0 ? { reactDetected: input.scans.some((scan) => hasReactRuntime(scan.result.project)) } : {},
45383
45358
  version: input.version,
45384
45359
  ok: true,
45385
45360
  directory: input.directory,
@@ -45430,7 +45405,7 @@ const buildSkippedChecks = (input) => {
45430
45405
  };
45431
45406
  const fingerprintDiagnostic = (diagnostic, lineText) => {
45432
45407
  const ruleKey = `${diagnostic.plugin}/${diagnostic.rule}`;
45433
- const snippet = lineText === null || diagnostic.matchByOccurrence ? "" : createHash("sha1").update(lineText.trim()).digest("hex");
45408
+ const snippet = lineText === null ? "" : createHash("sha1").update(lineText.trim()).digest("hex");
45434
45409
  return `${diagnostic.filePath}\u0000${ruleKey}\u0000${snippet}`;
45435
45410
  };
45436
45411
  /**
@@ -45441,17 +45416,6 @@ const fingerprintDiagnostic = (diagnostic, lineText) => {
45441
45416
  * look new, while a genuinely new occurrence (new line text, or one more of
45442
45417
  * the same) surfaces. Identical repeated findings are matched by count.
45443
45418
  *
45444
- * Diagnostics carrying `matchByOccurrence` (resolved at diagnostic creation:
45445
- * every Accessibility-category finding, plus rules opting in via their
45446
- * `matchByOccurrence` metadata flag) drop the line-text snippet and match by
45447
- * `(filePath, plugin/rule)` occurrence count alone. Their identity is the
45448
- * flagged element, not the line's text, so editing the line (reindentation,
45449
- * prettier reflow, collapsing a multi-line JSX element) doesn't reclassify a
45450
- * pre-existing finding as new — while one MORE occurrence of the same rule in
45451
- * the file still surfaces. Expression-level rules keep the line-text snippet:
45452
- * there the flagged expression IS the finding, so changed text means new +
45453
- * fixed.
45454
- *
45455
45419
  * v1 limitation: the fingerprint keys on the head-relative `filePath`, and base
45456
45420
  * content is read at that same path. A file renamed by the change therefore has
45457
45421
  * no base match, so its pre-existing findings are reported as new. This
@@ -45854,7 +45818,6 @@ const METRIC = {
45854
45818
  scanScore: "scan.score",
45855
45819
  scanClean: "scan.clean",
45856
45820
  scanCheckSkipped: "scan.check_skipped",
45857
- scanNoReactDetected: "scan.no_react_detected",
45858
45821
  baselineDegraded: "baseline.degraded",
45859
45822
  ruleFired: "rule.fired",
45860
45823
  ruleDisabled: "rule.disabled",
@@ -45924,7 +45887,7 @@ const makeNoopConsole = () => ({
45924
45887
  });
45925
45888
  //#endregion
45926
45889
  //#region src/cli/utils/version.ts
45927
- const VERSION = "0.7.0-dev.c0c3fc1";
45890
+ const VERSION = "0.7.0";
45928
45891
  //#endregion
45929
45892
  //#region src/cli/utils/json-mode.ts
45930
45893
  let context = null;
@@ -46293,13 +46256,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
46293
46256
  * uploads source-map artifacts under, so stack frames symbolicate. Honors the
46294
46257
  * standard `SENTRY_RELEASE` override.
46295
46258
  */
46296
- const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.0-dev.c0c3fc1`;
46259
+ const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.0`;
46297
46260
  /**
46298
46261
  * Deployment environment shown in Sentry's environment filter. Defaults to
46299
46262
  * `production` for tagged releases and `development` for dev/unbuilt versions,
46300
46263
  * overridable via the standard `SENTRY_ENVIRONMENT` env var.
46301
46264
  */
46302
- const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.0-dev.c0c3fc1") ? "development" : "production");
46265
+ const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.0") ? "development" : "production");
46303
46266
  /**
46304
46267
  * Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
46305
46268
  * (set to `0` to disable tracing) and falls back to
@@ -63012,11 +62975,6 @@ const finalizeScans = (input) => {
63012
62975
  const baselineComputed = input.completedScans.length > 0 && input.completedScans.every((scan) => scan.result.baselineDelta !== void 0);
63013
62976
  const baselineDegraded = input.baselineIntended && !baselineComputed;
63014
62977
  const mode = baselineDegraded ? "diff" : input.mode;
63015
- const isReactDetected = input.completedScans.some((scan) => hasReactRuntime(scan.result.project));
63016
- if (input.completedScans.length > 0 && !isReactDetected) {
63017
- recordCount(METRIC.scanNoReactDetected, 1);
63018
- cliLogger.warn(`No React project detected at ${input.resolvedDirectory} — React rules were gated off; this is not the same as a clean scan.`);
63019
- }
63020
62978
  const jsonCompletedScans = filterCompletedScansByCategories(input.completedScans, input.categoryFilters);
63021
62979
  if (input.isJsonMode) {
63022
62980
  const baseline = baselineComputed && baselineDeltas.length > 0 ? {
@@ -64454,4 +64412,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
64454
64412
  export {};
64455
64413
 
64456
64414
  //# sourceMappingURL=cli.js.map
64457
- //# debugId=5d16dd1c-3fc1-567b-943f-887174c145c1
64415
+ //# debugId=96cac03b-44a6-5d88-a5c9-697a5e8cf45e
package/dist/index.d.ts CHANGED
@@ -9493,17 +9493,6 @@ interface Diagnostic {
9493
9493
  /** 1-indexed end column of the primary span, when derivable. */
9494
9494
  endColumn?: number;
9495
9495
  category: string;
9496
- /**
9497
- * Set when the finding's identity is the flagged element itself (a missing
9498
- * attribute, a wrong element) rather than the flagged line's text — every
9499
- * Accessibility-category finding, plus rules that opt in via their
9500
- * `matchByOccurrence` metadata flag. `computeDiagnosticDelta` matches these
9501
- * by `(filePath, plugin/rule)` occurrence count, so reformatting the flagged
9502
- * line doesn't reclassify a pre-existing finding as new. Resolved at
9503
- * diagnostic creation, where rule metadata is available. Absent means
9504
- * line-text-sensitive matching (the default).
9505
- */
9506
- matchByOccurrence?: boolean;
9507
9496
  /**
9508
9497
  * Set when the file never ships to users (`"test"` / `"story"`), so
9509
9498
  * renderers can label the site instead of implying production impact.
@@ -9655,17 +9644,6 @@ interface DiagnoseResult {
9655
9644
  /** See `InspectResult.skippedCheckReasons`. */
9656
9645
  skippedCheckReasons?: Record<string, string>;
9657
9646
  project: ProjectInfo;
9658
- /**
9659
- * Whether the scanned project resolved a React-compatible runtime (React
9660
- * or Preact). `false` means every React-runtime rule family was gated
9661
- * off, so an empty `diagnostics` array is vacuous — NOT the same as a
9662
- * clean React scan. Consumers gating on the result should treat
9663
- * `reactDetected === false` as "wrong scan target", not "all clear".
9664
- * Mirrors `JsonReport.reactDetected`; same predicate as
9665
- * `hasReactRuntime(result.project)`. Always set by `diagnose()`;
9666
- * optional so hand-constructed results keep compiling.
9667
- */
9668
- reactDetected?: boolean;
9669
9647
  elapsedMilliseconds: number;
9670
9648
  }
9671
9649
  /**
@@ -9715,13 +9693,6 @@ interface DiagnoseProjectsResult {
9715
9693
  projects: ProjectResult[];
9716
9694
  diagnostics: Diagnostic[];
9717
9695
  score: ScoreResult | null;
9718
- /**
9719
- * Whether any successfully scanned project resolved a React-compatible
9720
- * runtime (React or Preact). Absent when no project scanned successfully.
9721
- * See `DiagnoseResult.reactDetected` for gating guidance; per-project
9722
- * detail is on each `ProjectResultOk.reactDetected`.
9723
- */
9724
- reactDetected?: boolean;
9725
9696
  elapsedMilliseconds: number;
9726
9697
  } //#endregion
9727
9698
  //#region src/types/handle-error.d.ts
@@ -9917,17 +9888,6 @@ interface JsonReportV1$1 {
9917
9888
  ok: boolean;
9918
9889
  directory: string;
9919
9890
  mode: JsonReportMode;
9920
- /**
9921
- * Whether any scanned project resolved a React-compatible runtime (React
9922
- * or Preact). `false` means every React-runtime rule family was gated off,
9923
- * so an empty `diagnostics` array is vacuous — NOT the same as a clean
9924
- * React scan. Consumers gating on the report (CI, verifiers, hooks) should
9925
- * treat `reactDetected === false` as "wrong scan target", not "all clear"
9926
- * (per project, `projects[].project.reactVersion` / `preactVersion` say
9927
- * which roots were non-React). Absent when nothing was scanned (`projects`
9928
- * is empty), on error reports, and on reports from older CLI versions.
9929
- */
9930
- reactDetected?: boolean;
9931
9891
  diff: JsonReportDiffInfo | null;
9932
9892
  projects: JsonReportProjectEntry[];
9933
9893
  /**
@@ -10212,16 +10172,6 @@ declare const summarizeDiagnostics: (diagnostics: Diagnostic[], worstScore?: num
10212
10172
  declare const defineConfig: (config: ReactDoctorConfig) => ReactDoctorConfig; //#endregion
10213
10173
  //#region src/utils/detect-ai-training-environment.d.ts
10214
10174
  //#endregion
10215
- //#region src/utils/has-react-runtime.d.ts
10216
- /**
10217
- * Whether project discovery resolved a React-compatible runtime (React or
10218
- * Preact, which ships the same hooks + JSX model). This is the same
10219
- * predicate that grants the `react` capability, so `false` means every
10220
- * React-runtime rule family was gated off for the project.
10221
- */
10222
- declare const hasReactRuntime: (project: ProjectInfo) => boolean; //#endregion
10223
- //#region src/utils/is-errno-exception.d.ts
10224
- //#endregion
10225
10175
  //#region ../api/dist/index.d.ts
10226
10176
  //#region src/diagnose.d.ts
10227
10177
  interface Diagnose {
@@ -10248,5 +10198,5 @@ interface ToJsonReportOptions {
10248
10198
  }
10249
10199
  declare const toJsonReport: (result: DiagnoseResult, options: ToJsonReportOptions) => JsonReport;
10250
10200
  //#endregion
10251
- export { AmbiguousProjectError, type DiagnoseOptions, type DiagnoseProjectsInput, type DiagnoseProjectsResult, type DiagnoseResult, type Diagnostic, type DiffInfo, type JsonReport, type JsonReportDiffInfo, type JsonReportError, type JsonReportMode, type JsonReportProjectEntry, type JsonReportSummary, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, type ProjectDefinition, type ProjectInfo, ProjectNotFoundError, type ProjectResult, type ProjectResultError, type ProjectResultOk, type ReactDoctorConfig, ReactDoctorError, type ScoreResult, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
10201
+ export { AmbiguousProjectError, type DiagnoseOptions, type DiagnoseProjectsInput, type DiagnoseProjectsResult, type DiagnoseResult, type Diagnostic, type DiffInfo, type JsonReport, type JsonReportDiffInfo, type JsonReportError, type JsonReportMode, type JsonReportProjectEntry, type JsonReportSummary, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, type ProjectDefinition, type ProjectInfo, ProjectNotFoundError, type ProjectResult, type ProjectResultError, type ProjectResultOk, type ReactDoctorConfig, ReactDoctorError, type ScoreResult, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
10252
10202
  //# sourceMappingURL=index.d.ts.map
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]="cf5e895a-deab-574a-b55b-a973e310d0e0")}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]="5c52dece-7b5e-5102-9381-7d05fa45734f")}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 * as NFS from "node:fs";
@@ -19304,7 +19304,6 @@ var Diagnostic = class extends Class("Diagnostic")({
19304
19304
  endLine: optional(Number$1),
19305
19305
  endColumn: optional(Number$1),
19306
19306
  category: String$1,
19307
- matchByOccurrence: optional(Boolean$1),
19308
19307
  fileContext: optional(Literals(["test", "story"])),
19309
19308
  suppressionHint: optional(String$1),
19310
19309
  relatedLocations: optional(ArraySchema(DiagnosticRelatedLocation)),
@@ -19375,16 +19374,6 @@ var JsonReportV1 = class extends Class("JsonReportV1")({
19375
19374
  * successful `baseline` run (`schemaVersion: 2`) and on non-compare scopes.
19376
19375
  */
19377
19376
  baselineDegraded: optional(Boolean$1),
19378
- /**
19379
- * Whether any scanned project resolved a React-compatible runtime (React
19380
- * or Preact). `false` means every React-runtime rule family was gated off,
19381
- * so an empty `diagnostics` array is vacuous — NOT the same as a clean
19382
- * React scan. Consumers gating on the report (CI, verifiers, hooks) should
19383
- * treat `reactDetected === false` as "wrong scan target", not "all clear".
19384
- * Absent when nothing was scanned (`projects` is empty), on error reports,
19385
- * and on reports from older CLI versions.
19386
- */
19387
- reactDetected: optional(Boolean$1),
19388
19377
  diff: NullOr(JsonReportDiffInfo),
19389
19378
  projects: ArraySchema(JsonReportProjectEntry),
19390
19379
  diagnostics: ArraySchema(Diagnostic),
@@ -19410,8 +19399,6 @@ var JsonReportV2 = class extends Class("JsonReportV2")({
19410
19399
  ok: Boolean$1,
19411
19400
  directory: String$1,
19412
19401
  mode: JsonReportMode,
19413
- /** See `JsonReportV1.reactDetected`. */
19414
- reactDetected: optional(Boolean$1),
19415
19402
  diff: NullOr(JsonReportDiffInfo),
19416
19403
  baseline: JsonReportBaseline,
19417
19404
  projects: ArraySchema(JsonReportProjectEntry),
@@ -32920,7 +32907,6 @@ const DIAGNOSTIC_CATEGORY_BUCKETS = [
32920
32907
  "Accessibility",
32921
32908
  "Maintainability"
32922
32909
  ];
32923
- const OCCURRENCE_MATCHED_CATEGORIES = new Set(["Accessibility"]);
32924
32910
  const APP_ONLY_RULE_KEYS = new Set([
32925
32911
  "react-hooks-js/static-components",
32926
32912
  "react-doctor/no-render-prop-children",
@@ -37024,17 +37010,10 @@ function* collectSecurityScanFiles(rootDirectory) {
37024
37010
  }
37025
37011
  }
37026
37012
  }
37027
- /**
37028
- * Whether project discovery resolved a React-compatible runtime (React or
37029
- * Preact, which ships the same hooks + JSX model). This is the same
37030
- * predicate that grants the `react` capability, so `false` means every
37031
- * React-runtime rule family was gated off for the project.
37032
- */
37033
- const hasReactRuntime = (project) => project.reactVersion !== null || project.preactVersion !== null;
37034
37013
  const buildCapabilities = (project) => {
37035
37014
  const capabilities = /* @__PURE__ */ new Set();
37036
37015
  capabilities.add(project.framework);
37037
- if (hasReactRuntime(project)) capabilities.add("react");
37016
+ if (project.reactVersion !== null || project.preactVersion !== null) capabilities.add("react");
37038
37017
  if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
37039
37018
  if (project.expoVersion !== null) capabilities.add("expo");
37040
37019
  if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 15) capabilities.add("nextjs:15");
@@ -39870,7 +39849,6 @@ const parseRuleCode = (code) => {
39870
39849
  };
39871
39850
  };
39872
39851
  const resolveDiagnosticCategory = (plugin, rule) => getRuleCategory(rule) ?? lookupOwnString(PLUGIN_CATEGORY_MAP, plugin) ?? "Bugs";
39873
- const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORIES.has(category) || Boolean(reactDoctorPlugin.rules[rule]?.matchByOccurrence);
39874
39852
  /**
39875
39853
  * Maps oxlint's non-primary labels (`labels[1..]`) into related source
39876
39854
  * locations. Editors surface these as a diagnostic's
@@ -39934,7 +39912,6 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
39934
39912
  const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
39935
39913
  const primarySpan = primaryLabel?.span;
39936
39914
  const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
39937
- const category = resolveDiagnosticCategory(plugin, rule);
39938
39915
  return {
39939
39916
  filePath: normalizedFilePath,
39940
39917
  plugin,
@@ -39950,8 +39927,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
39950
39927
  offset: primarySpan.offset,
39951
39928
  length: primarySpan.length
39952
39929
  } : {},
39953
- category,
39954
- ...resolveMatchByOccurrence(rule, category) ? { matchByOccurrence: true } : {},
39930
+ category: resolveDiagnosticCategory(plugin, rule),
39955
39931
  ...relatedLocations.length > 0 ? { relatedLocations } : {}
39956
39932
  };
39957
39933
  });
@@ -42112,7 +42088,6 @@ const buildJsonReport = (input) => {
42112
42088
  const worstScoredProject = findWorstScoredProject(projects);
42113
42089
  const summary = summarizeDiagnostics(flattenedDiagnostics, worstScoredProject?.score?.score ?? null, worstScoredProject?.score?.label ?? null);
42114
42090
  const shared = {
42115
- ...input.scans.length > 0 ? { reactDetected: input.scans.some((scan) => hasReactRuntime(scan.result.project)) } : {},
42116
42091
  version: input.version,
42117
42092
  ok: true,
42118
42093
  directory: input.directory,
@@ -42342,7 +42317,6 @@ const outputToDiagnoseResult = (output, elapsedMilliseconds) => {
42342
42317
  skippedChecks,
42343
42318
  ...Object.keys(skippedCheckReasons).length > 0 ? { skippedCheckReasons } : {},
42344
42319
  project: output.project,
42345
- reactDetected: hasReactRuntime(output.project),
42346
42320
  elapsedMilliseconds
42347
42321
  };
42348
42322
  };
@@ -42398,12 +42372,10 @@ const diagnoseProjectBatch = async (input) => {
42398
42372
  const startTime = globalThis.performance.now();
42399
42373
  const { projects, concurrency, config: batchConfig, ...baseOptions } = input;
42400
42374
  const projectResults = await mapWithConcurrency(projects, concurrency ?? 4, (projectDefinition) => diagnoseProject(projectDefinition, baseOptions, batchConfig));
42401
- const succeededProjects = projectResults.filter((projectResult) => projectResult.ok);
42402
42375
  return {
42403
42376
  projects: projectResults,
42404
- diagnostics: succeededProjects.flatMap((projectResult) => projectResult.diagnostics),
42377
+ diagnostics: projectResults.flatMap((projectResult) => projectResult.ok ? projectResult.diagnostics : []),
42405
42378
  score: findWorstScore(projectResults),
42406
- ...succeededProjects.length > 0 ? { reactDetected: succeededProjects.some((projectResult) => projectResult.reactDetected) } : {},
42407
42379
  elapsedMilliseconds: globalThis.performance.now() - startTime
42408
42380
  };
42409
42381
  };
@@ -42438,7 +42410,7 @@ const toJsonReport = (result, options) => buildJsonReport({
42438
42410
  totalElapsedMilliseconds: result.elapsedMilliseconds
42439
42411
  });
42440
42412
  //#endregion
42441
- export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
42413
+ export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
42442
42414
 
42443
42415
  //# sourceMappingURL=index.js.map
42444
- //# debugId=cf5e895a-deab-574a-b55b-a973e310d0e0
42416
+ //# debugId=5c52dece-7b5e-5102-9381-7d05fa45734f
package/dist/lsp.js CHANGED
@@ -19333,7 +19333,6 @@ var Diagnostic = class extends Class("Diagnostic")({
19333
19333
  endLine: optional(Number$1),
19334
19334
  endColumn: optional(Number$1),
19335
19335
  category: String$1,
19336
- matchByOccurrence: optional(Boolean$1),
19337
19336
  fileContext: optional(Literals(["test", "story"])),
19338
19337
  suppressionHint: optional(String$1),
19339
19338
  relatedLocations: optional(ArraySchema(DiagnosticRelatedLocation)),
@@ -19411,16 +19410,6 @@ var JsonReportV1 = class extends Class("JsonReportV1")({
19411
19410
  * successful `baseline` run (`schemaVersion: 2`) and on non-compare scopes.
19412
19411
  */
19413
19412
  baselineDegraded: optional(Boolean$1),
19414
- /**
19415
- * Whether any scanned project resolved a React-compatible runtime (React
19416
- * or Preact). `false` means every React-runtime rule family was gated off,
19417
- * so an empty `diagnostics` array is vacuous — NOT the same as a clean
19418
- * React scan. Consumers gating on the report (CI, verifiers, hooks) should
19419
- * treat `reactDetected === false` as "wrong scan target", not "all clear".
19420
- * Absent when nothing was scanned (`projects` is empty), on error reports,
19421
- * and on reports from older CLI versions.
19422
- */
19423
- reactDetected: optional(Boolean$1),
19424
19413
  diff: NullOr(JsonReportDiffInfo),
19425
19414
  projects: ArraySchema(JsonReportProjectEntry),
19426
19415
  diagnostics: ArraySchema(Diagnostic),
@@ -19446,8 +19435,6 @@ var JsonReportV2 = class extends Class("JsonReportV2")({
19446
19435
  ok: Boolean$1,
19447
19436
  directory: String$1,
19448
19437
  mode: JsonReportMode,
19449
- /** See `JsonReportV1.reactDetected`. */
19450
- reactDetected: optional(Boolean$1),
19451
19438
  diff: NullOr(JsonReportDiffInfo),
19452
19439
  baseline: JsonReportBaseline,
19453
19440
  projects: ArraySchema(JsonReportProjectEntry),
@@ -32979,7 +32966,6 @@ const DIAGNOSTIC_CATEGORY_BUCKETS = [
32979
32966
  "Accessibility",
32980
32967
  "Maintainability"
32981
32968
  ];
32982
- const OCCURRENCE_MATCHED_CATEGORIES = new Set(["Accessibility"]);
32983
32969
  const APP_ONLY_RULE_KEYS = new Set([
32984
32970
  "react-hooks-js/static-components",
32985
32971
  "react-doctor/no-render-prop-children",
@@ -37009,17 +36995,10 @@ function* collectSecurityScanFiles(rootDirectory) {
37009
36995
  }
37010
36996
  }
37011
36997
  }
37012
- /**
37013
- * Whether project discovery resolved a React-compatible runtime (React or
37014
- * Preact, which ships the same hooks + JSX model). This is the same
37015
- * predicate that grants the `react` capability, so `false` means every
37016
- * React-runtime rule family was gated off for the project.
37017
- */
37018
- const hasReactRuntime = (project) => project.reactVersion !== null || project.preactVersion !== null;
37019
36998
  const buildCapabilities = (project) => {
37020
36999
  const capabilities = /* @__PURE__ */ new Set();
37021
37000
  capabilities.add(project.framework);
37022
- if (hasReactRuntime(project)) capabilities.add("react");
37001
+ if (project.reactVersion !== null || project.preactVersion !== null) capabilities.add("react");
37023
37002
  if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
37024
37003
  if (project.expoVersion !== null) capabilities.add("expo");
37025
37004
  if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 15) capabilities.add("nextjs:15");
@@ -39855,7 +39834,6 @@ const parseRuleCode = (code) => {
39855
39834
  };
39856
39835
  };
39857
39836
  const resolveDiagnosticCategory = (plugin, rule) => getRuleCategory(rule) ?? lookupOwnString(PLUGIN_CATEGORY_MAP, plugin) ?? "Bugs";
39858
- const resolveMatchByOccurrence = (rule, category) => OCCURRENCE_MATCHED_CATEGORIES.has(category) || Boolean(reactDoctorPlugin.rules[rule]?.matchByOccurrence);
39859
39837
  /**
39860
39838
  * Maps oxlint's non-primary labels (`labels[1..]`) into related source
39861
39839
  * locations. Editors surface these as a diagnostic's
@@ -39919,7 +39897,6 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
39919
39897
  const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
39920
39898
  const primarySpan = primaryLabel?.span;
39921
39899
  const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
39922
- const category = resolveDiagnosticCategory(plugin, rule);
39923
39900
  return {
39924
39901
  filePath: normalizedFilePath,
39925
39902
  plugin,
@@ -39935,8 +39912,7 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
39935
39912
  offset: primarySpan.offset,
39936
39913
  length: primarySpan.length
39937
39914
  } : {},
39938
- category,
39939
- ...resolveMatchByOccurrence(rule, category) ? { matchByOccurrence: true } : {},
39915
+ category: resolveDiagnosticCategory(plugin, rule),
39940
39916
  ...relatedLocations.length > 0 ? { relatedLocations } : {}
39941
39917
  };
39942
39918
  });
@@ -43816,7 +43792,6 @@ const METRIC = {
43816
43792
  scanScore: "scan.score",
43817
43793
  scanClean: "scan.clean",
43818
43794
  scanCheckSkipped: "scan.check_skipped",
43819
- scanNoReactDetected: "scan.no_react_detected",
43820
43795
  baselineDegraded: "baseline.degraded",
43821
43796
  ruleFired: "rule.fired",
43822
43797
  ruleDisabled: "rule.disabled",
@@ -44160,5 +44135,5 @@ const startLanguageServer = () => {
44160
44135
  };
44161
44136
  //#endregion
44162
44137
  export { startLanguageServer };
44163
- !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]="07f4ef15-cbc2-553c-ac41-b73f1d3b7bf8")}catch(e){}}();
44164
- //# debugId=07f4ef15-cbc2-553c-ac41-b73f1d3b7bf8
44138
+ !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]="1b40bd68-7ad4-55e0-a6bd-91b6cdcd0ba8")}catch(e){}}();
44139
+ //# debugId=1b40bd68-7ad4-55e0-a6bd-91b6cdcd0ba8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-doctor",
3
- "version": "0.7.0-dev.c0c3fc1",
3
+ "version": "0.7.0",
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.0",
69
- "oxlint-plugin-react-doctor": "0.7.0-dev.c0c3fc1"
69
+ "oxlint-plugin-react-doctor": "0.7.0"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/babel__code-frame": "^7.27.0",