react-doctor 0.6.3-dev.8c004f0 → 0.6.3-dev.ce49250

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]="e34cb22b-7751-5b1a-8422-6c5eb384dbef")}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]="cb06d1e4-d50b-5715-af77-13eb97c43e07")}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";
@@ -18,6 +18,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
18
18
  import { createJiti } from "jiti";
19
19
  import * as Crypto from "node:crypto";
20
20
  import crypto, { createHash, randomUUID } from "node:crypto";
21
+ import { ANALYZED_MANIFEST_FILENAMES, DEFAULT_EXTENSIONS } from "deslop-js/analyzed-inputs";
21
22
  import { gzipSync } from "node:zlib";
22
23
  import * as Sentry from "@sentry/node";
23
24
  import { performance as performance$1 } from "node:perf_hooks";
@@ -36128,7 +36129,9 @@ const SOCKET_PACKAGE_PAGE_BASE = "https://socket.dev/npm/package";
36128
36129
  const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
36129
36130
  const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
36130
36131
  const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
36132
+ const CORE_PACKAGE_VERSION = "0.6.3";
36131
36133
  const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
36134
+ const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
36132
36135
  const SUPPLY_CHAIN_PLUGIN = "socket";
36133
36136
  const SUPPLY_CHAIN_RULE = "low-supply-chain-score";
36134
36137
  const SUPPLY_CHAIN_CATEGORY = "Security";
@@ -40581,38 +40584,9 @@ const failOpenReadJson = (filePath, fallback) => {
40581
40584
  return fallback;
40582
40585
  }
40583
40586
  };
40584
- const ANALYZED_FILE_EXTENSIONS = new Set([
40585
- ".ts",
40586
- ".tsx",
40587
- ".js",
40588
- ".jsx",
40589
- ".mts",
40590
- ".mjs",
40591
- ".cts",
40592
- ".cjs",
40593
- ".mdx",
40594
- ".astro",
40595
- ".graphql",
40596
- ".gql",
40597
- ".css",
40598
- ".scss",
40599
- ".vue",
40600
- ".svelte"
40601
- ]);
40602
- const ANALYZED_MANIFEST_NAMES = new Set([
40603
- "package.json",
40604
- "knip.json",
40605
- "app.json",
40606
- "pnpm-workspace.yaml",
40607
- "lerna.json",
40608
- "pnpm-lock.yaml",
40609
- "package-lock.json",
40610
- "yarn.lock",
40611
- "bun.lock",
40612
- "bun.lockb",
40613
- "deno.lock",
40614
- ".gitignore"
40615
- ]);
40587
+ const ANALYZED_FILE_EXTENSIONS = new Set(DEFAULT_EXTENSIONS);
40588
+ const CORE_SIDE_MANIFEST_NAMES = ["knip.json", "deno.lock"];
40589
+ const ANALYZED_MANIFEST_NAMES = new Set([...ANALYZED_MANIFEST_FILENAMES, ...CORE_SIDE_MANIFEST_NAMES]);
40616
40590
  const isTsConfigLikeFile = (fileName) => (fileName.startsWith("tsconfig") || fileName.startsWith("jsconfig")) && fileName.endsWith(".json");
40617
40591
  const isFingerprintedFile = (fileName) => ANALYZED_FILE_EXTENSIONS.has(Path.extname(fileName).toLowerCase()) || ANALYZED_MANIFEST_NAMES.has(fileName) || isTsConfigLikeFile(fileName);
40618
40592
  const collectAnalyzedFileFingerprints = (rootDirectory) => {
@@ -40638,6 +40612,7 @@ const resolveDeslopVersion = () => {
40638
40612
  };
40639
40613
  const computeDeadCodeCacheKey = (input) => crypto.createHash("sha1").update(JSON.stringify({
40640
40614
  schemaVersion: 1,
40615
+ coreVersion: input.coreVersion,
40641
40616
  deslopVersion: resolveDeslopVersion(),
40642
40617
  deslopJsModuleSpecifier: input.deslopJsModuleSpecifier,
40643
40618
  entryPatterns: input.entryPatterns,
@@ -40802,6 +40777,14 @@ process.stdin.on("end", () => {
40802
40777
  circularDependencies: result.circularDependencies.map((cycle) => ({
40803
40778
  files: cycle.files,
40804
40779
  })),
40780
+ ...(result.incrementalCacheStats
40781
+ ? {
40782
+ summaryCacheStats: {
40783
+ hits: result.incrementalCacheStats.summaryHits,
40784
+ misses: result.incrementalCacheStats.summaryMisses,
40785
+ },
40786
+ }
40787
+ : {}),
40805
40788
  });
40806
40789
 
40807
40790
  const serializeError = (error) =>
@@ -40825,6 +40808,9 @@ process.stdin.on("end", () => {
40825
40808
  ...(workerInput.ignorePatterns.length > 0
40826
40809
  ? { ignorePatterns: workerInput.ignorePatterns }
40827
40810
  : {}),
40811
+ ...(workerInput.incrementalCachePath
40812
+ ? { incrementalCachePath: workerInput.incrementalCachePath }
40813
+ : {}),
40828
40814
  // We consume only deslop's GRAPH-based findings (unusedFiles, unusedExports,
40829
40815
  // unusedDependencies, circularDependencies). Everything else deslop can compute
40830
40816
  // is pure wasted work for us, and it's the bulk of the runtime:
@@ -40835,12 +40821,18 @@ process.stdin.on("end", () => {
40835
40821
  // are the single most expensive pass — duplicate-block detection alone was
40836
40822
  // ~83s of a ~130s Sentry scan — so skipping them is an ~8.5x dead-code
40837
40823
  // speedup on a large repo.
40838
- // Both are provably safe: the consumed graph findings are computed by their own
40824
+ // - reportRedundancy: the DRY-pattern detectors (duplicate types/constants,
40825
+ // simplifiable functions, identity wrappers, …) — ~120 ms of discarded
40826
+ // output per scan, and skipping them lets the incremental cache drop the
40827
+ // DRY-pattern summary fields (the largest slice of the cache file).
40828
+ // All are provably safe: the consumed graph findings are computed by their own
40839
40829
  // detectors, independent of these passes (confirmed byte-identical on
40840
- // excalidraw + mui-material + sentry). tsConfigPath stays — the module resolver
40841
- // needs it for path-alias resolution in the import graph.
40830
+ // excalidraw + mui-material + sentry; re-verified on sentry after the
40831
+ // reportRedundancy flip). tsConfigPath stays — the module resolver needs it
40832
+ // for path-alias resolution in the import graph.
40842
40833
  semantic: { enabled: false },
40843
40834
  reportCodeQuality: false,
40835
+ reportRedundancy: false,
40844
40836
  };
40845
40837
  const result = await analyze(defineConfig(config));
40846
40838
  emit({ ok: true, result: normalizeResult(result) });
@@ -40924,13 +40916,23 @@ const parseCircularDependencies = (value) => {
40924
40916
  }
40925
40917
  return circularDependencies;
40926
40918
  };
40919
+ const parseSummaryCacheStats = (value) => {
40920
+ if (!isRecord$1(value)) return void 0;
40921
+ if (typeof value.hits !== "number" || typeof value.misses !== "number") return void 0;
40922
+ return {
40923
+ hits: value.hits,
40924
+ misses: value.misses
40925
+ };
40926
+ };
40927
40927
  const parseDeadCodeWorkerResult = (value) => {
40928
40928
  if (!isRecord$1(value)) throw new Error("Dead-code worker returned an invalid result.");
40929
+ const summaryCacheStats = parseSummaryCacheStats(value.summaryCacheStats);
40929
40930
  return {
40930
40931
  unusedFiles: parseUnusedFiles(value.unusedFiles),
40931
40932
  unusedExports: parseUnusedExports(value.unusedExports),
40932
40933
  unusedDependencies: parseUnusedDependencies(value.unusedDependencies),
40933
- circularDependencies: parseCircularDependencies(value.circularDependencies)
40934
+ circularDependencies: parseCircularDependencies(value.circularDependencies),
40935
+ ...summaryCacheStats ? { summaryCacheStats } : {}
40934
40936
  };
40935
40937
  };
40936
40938
  const parseDeadCodeWorkerError = (value) => {
@@ -41051,13 +41053,15 @@ const checkDeadCode = async (options) => {
41051
41053
  entryPatterns,
41052
41054
  ignorePatterns,
41053
41055
  tsConfigPath,
41054
- deslopJsModuleSpecifier
41056
+ deslopJsModuleSpecifier,
41057
+ coreVersion: CORE_PACKAGE_VERSION
41055
41058
  }) : null;
41056
41059
  if (cacheKey !== null) {
41057
41060
  const cachedDiagnostics = lookupDeadCodeResultCache(resolveReactDoctorCacheDir(rootDirectory), cacheKey);
41058
41061
  options.onCacheOutcome?.(cachedDiagnostics !== null);
41059
41062
  if (cachedDiagnostics !== null) return [...cachedDiagnostics];
41060
41063
  }
41064
+ const incrementalCachePath = options.cacheEnabled === true ? Path.join(resolveReactDoctorCacheDir(rootDirectory), DEAD_CODE_SUMMARY_CACHE_FILENAME) : void 0;
41061
41065
  const spawnAndRun = () => {
41062
41066
  return runDeadCodeWorkerWithTimeout((options.createWorker ?? createDeadCodeWorker)({
41063
41067
  rootDirectory,
@@ -41065,10 +41069,12 @@ const checkDeadCode = async (options) => {
41065
41069
  tsConfigPath,
41066
41070
  ignorePatterns,
41067
41071
  deslopJsModuleSpecifier,
41068
- parseConcurrency: options.parseConcurrency
41072
+ parseConcurrency: options.parseConcurrency,
41073
+ incrementalCachePath
41069
41074
  }), options.workerTimeoutMs ?? 12e4, options.abortSignal);
41070
41075
  };
41071
41076
  const result = parseDeadCodeWorkerResult(options.createWorker === void 0 ? await withDeadCodeWorkerSlot(spawnAndRun, options.abortSignal) : await spawnAndRun());
41077
+ if (result.summaryCacheStats !== void 0) options.onSummaryCacheStats?.(result.summaryCacheStats);
41072
41078
  const toRelative = (filePath) => toRelativeFilePath(rootDirectory, filePath);
41073
41079
  const diagnostics = [];
41074
41080
  for (const unusedFile of result.unusedFiles) diagnostics.push({
@@ -41236,7 +41242,8 @@ var DeadCode = class DeadCode extends Service()("react-doctor/DeadCode") {
41236
41242
  workerTimeoutMs: input.workerTimeoutMs,
41237
41243
  abortSignal: signal,
41238
41244
  cacheEnabled,
41239
- onCacheOutcome: input.onCacheOutcome
41245
+ onCacheOutcome: input.onCacheOutcome,
41246
+ onSummaryCacheStats: input.onSummaryCacheStats
41240
41247
  }),
41241
41248
  catch: (cause) => new ReactDoctorError({ reason: new DeadCodeAnalysisFailed({ cause }) })
41242
41249
  }).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)));
@@ -44418,6 +44425,10 @@ const runInspect = (input, hooks = {}) => gen(function* () {
44418
44425
  workerTimeoutMs: deadCodeTimeout.workerTimeoutMs,
44419
44426
  onCacheOutcome: (didHitCache) => {
44420
44427
  deadCodeCacheHit = didHitCache;
44428
+ },
44429
+ onSummaryCacheStats: (stats) => {
44430
+ deadCodeSummaryCacheHits = stats.hits;
44431
+ deadCodeSummaryCacheMisses = stats.misses;
44421
44432
  }
44422
44433
  }).pipe(catchTag("ReactDoctorError", (error) => unwrap(gen(function* () {
44423
44434
  yield* set(deadCodeFailure, {
@@ -44447,6 +44458,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
44447
44458
  let lintCacheHitFileCount = null;
44448
44459
  let lintCacheTotalFileCount = null;
44449
44460
  let deadCodeCacheHit = null;
44461
+ let deadCodeSummaryCacheHits = null;
44462
+ let deadCodeSummaryCacheMisses = null;
44450
44463
  const baseLintStream = linterService.run({
44451
44464
  rootDirectory: scanDirectory,
44452
44465
  project,
@@ -44577,6 +44590,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
44577
44590
  lintCacheHitFileCount,
44578
44591
  lintCacheTotalFileCount,
44579
44592
  deadCodeCacheHit: lintFailureState.didFail ? null : deadCodeCacheHit,
44593
+ deadCodeSummaryCacheHits: lintFailureState.didFail ? null : deadCodeSummaryCacheHits,
44594
+ deadCodeSummaryCacheMisses: lintFailureState.didFail ? null : deadCodeSummaryCacheMisses,
44580
44595
  suppressedRuleCounts: transform.summarizeSuppressions()
44581
44596
  };
44582
44597
  }).pipe(withSpan("runInspect", { attributes: {
@@ -45449,7 +45464,7 @@ const makeNoopConsole = () => ({
45449
45464
  });
45450
45465
  //#endregion
45451
45466
  //#region src/cli/utils/version.ts
45452
- const VERSION = "0.6.3-dev.8c004f0";
45467
+ const VERSION = "0.6.3-dev.ce49250";
45453
45468
  //#endregion
45454
45469
  //#region src/cli/utils/json-mode.ts
45455
45470
  let context = null;
@@ -45818,13 +45833,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
45818
45833
  * uploads source-map artifacts under, so stack frames symbolicate. Honors the
45819
45834
  * standard `SENTRY_RELEASE` override.
45820
45835
  */
45821
- const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.6.3-dev.8c004f0`;
45836
+ const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.6.3-dev.ce49250`;
45822
45837
  /**
45823
45838
  * Deployment environment shown in Sentry's environment filter. Defaults to
45824
45839
  * `production` for tagged releases and `development` for dev/unbuilt versions,
45825
45840
  * overridable via the standard `SENTRY_ENVIRONMENT` env var.
45826
45841
  */
45827
- const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.6.3-dev.8c004f0") ? "development" : "production");
45842
+ const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.6.3-dev.ce49250") ? "development" : "production");
45828
45843
  /**
45829
45844
  * Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
45830
45845
  * (set to `0` to disable tracing) and falls back to
@@ -58053,7 +58068,9 @@ const buildOutcomeAttributes = (input) => {
58053
58068
  ...withNamespace("deadCode", {
58054
58069
  failed: input.didDeadCodeFail ?? null,
58055
58070
  overlapped: input.deadCodeOverlapped ?? null,
58056
- cacheHit: result.deadCodeCacheHit ?? null
58071
+ cacheHit: result.deadCodeCacheHit ?? null,
58072
+ summaryCacheHits: result.deadCodeSummaryCacheHits ?? null,
58073
+ summaryCacheMisses: result.deadCodeSummaryCacheMisses ?? null
58057
58074
  }),
58058
58075
  ...withNamespace("supplyChain", { overlapTimedOut: input.supplyChainOverlapTimedOut ?? null }),
58059
58076
  ...withNamespace("securityScan", { failed: input.securityScanFailed ?? null }),
@@ -59946,7 +59963,9 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
59946
59963
  baselineDegraded,
59947
59964
  lintCacheHitFileCount: output.lintCacheHitFileCount,
59948
59965
  lintCacheTotalFileCount: output.lintCacheTotalFileCount,
59949
- deadCodeCacheHit: output.deadCodeCacheHit
59966
+ deadCodeCacheHit: output.deadCodeCacheHit,
59967
+ deadCodeSummaryCacheHits: output.deadCodeSummaryCacheHits,
59968
+ deadCodeSummaryCacheMisses: output.deadCodeSummaryCacheMisses
59950
59969
  });
59951
59970
  recordOnboardingCompletion(options);
59952
59971
  return result;
@@ -59982,6 +60001,8 @@ const renderAndRecordScan = async (input) => {
59982
60001
  lintCacheHitFileCount: input.lintCacheHitFileCount ?? null,
59983
60002
  lintCacheTotalFileCount: input.lintCacheTotalFileCount ?? null,
59984
60003
  deadCodeCacheHit: input.deadCodeCacheHit ?? null,
60004
+ deadCodeSummaryCacheHits: input.deadCodeSummaryCacheHits ?? null,
60005
+ deadCodeSummaryCacheMisses: input.deadCodeSummaryCacheMisses ?? null,
59985
60006
  baselineDelta: input.payload.baselineDelta
59986
60007
  }), input.options.silent));
59987
60008
  const { workerCount: resolvedWorkerCount, parallel } = resolveWorkerTelemetry(input.payload.scanConcurrency, input.options.concurrency);
@@ -60020,7 +60041,7 @@ const renderAndRecordScan = async (input) => {
60020
60041
  return result;
60021
60042
  };
60022
60043
  const finalizeAndRender = (input) => gen(function* () {
60023
- const { options, elapsedMilliseconds, diagnostics, score, project, userConfig, didLintFail, lintFailureReason, lintPartialFailures, didDeadCodeFail, deadCodeFailureReason, directory, scannedFileCount, scannedFilePaths, scanElapsedMilliseconds, lintCacheHitFileCount, lintCacheTotalFileCount, deadCodeCacheHit, baselineDelta } = input;
60044
+ const { options, elapsedMilliseconds, diagnostics, score, project, userConfig, didLintFail, lintFailureReason, lintPartialFailures, didDeadCodeFail, deadCodeFailureReason, directory, scannedFileCount, scannedFilePaths, scanElapsedMilliseconds, lintCacheHitFileCount, lintCacheTotalFileCount, deadCodeCacheHit, deadCodeSummaryCacheHits, deadCodeSummaryCacheMisses, baselineDelta } = input;
60024
60045
  const { skippedChecks, skippedCheckReasons } = buildSkippedChecks({
60025
60046
  didLintFail,
60026
60047
  lintFailureReason,
@@ -60045,6 +60066,10 @@ const finalizeAndRender = (input) => gen(function* () {
60045
60066
  lintCacheTotalFileCount
60046
60067
  } : {},
60047
60068
  ...deadCodeCacheHit !== null ? { deadCodeCacheHit } : {},
60069
+ ...deadCodeSummaryCacheHits !== null && deadCodeSummaryCacheMisses !== null ? {
60070
+ deadCodeSummaryCacheHits,
60071
+ deadCodeSummaryCacheMisses
60072
+ } : {},
60048
60073
  ...baselineDelta ? { baselineDelta } : {}
60049
60074
  });
60050
60075
  if (options.suppressRendering) return buildResult();
@@ -63891,4 +63916,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
63891
63916
  export {};
63892
63917
 
63893
63918
  //# sourceMappingURL=cli.js.map
63894
- //# debugId=e34cb22b-7751-5b1a-8422-6c5eb384dbef
63919
+ //# debugId=cb06d1e4-d50b-5715-af77-13eb97c43e07
package/dist/index.d.ts CHANGED
@@ -9751,6 +9751,16 @@ interface InspectResult {
9751
9751
  * projects it onto the Sentry wide event as `deadCode.cacheHit`.
9752
9752
  */
9753
9753
  deadCodeCacheHit?: boolean | null;
9754
+ /**
9755
+ * deslop's incremental summary-cache outcome for the dead-code analysis:
9756
+ * collected files served from cached parse summaries vs freshly parsed.
9757
+ * Both absent whenever no analysis consulted the incremental store — a
9758
+ * whole-result cache hit, the cache disabled, or dead-code skipped. The CLI
9759
+ * projects them onto the Sentry wide event as `deadCode.summaryCacheHits` /
9760
+ * `deadCode.summaryCacheMisses`.
9761
+ */
9762
+ deadCodeSummaryCacheHits?: number | null;
9763
+ deadCodeSummaryCacheMisses?: number | null;
9754
9764
  /**
9755
9765
  * Present only for a baseline run (`InspectOptions.baseline` set). The
9756
9766
  * `diagnostics` above are then the *introduced* findings only; this
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]="367db57b-e5c7-577e-9efa-ed68817a8271")}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]="f615f76d-a949-5fb6-ace8-145f3e137af4")}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";
@@ -18,6 +18,7 @@ import { fileURLToPath } from "node:url";
18
18
  import { createJiti } from "jiti";
19
19
  import * as Crypto from "node:crypto";
20
20
  import crypto, { createHash } from "node:crypto";
21
+ import { ANALYZED_MANIFEST_FILENAMES, DEFAULT_EXTENSIONS } from "deslop-js/analyzed-inputs";
21
22
  import { gzipSync } from "node:zlib";
22
23
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.70/node_modules/effect/dist/Pipeable.js
23
24
  /**
@@ -32927,7 +32928,9 @@ const SOCKET_PACKAGE_PAGE_BASE = "https://socket.dev/npm/package";
32927
32928
  const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
32928
32929
  const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
32929
32930
  const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
32931
+ const CORE_PACKAGE_VERSION = "0.6.3";
32930
32932
  const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
32933
+ const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
32931
32934
  const SUPPLY_CHAIN_PLUGIN = "socket";
32932
32935
  const SUPPLY_CHAIN_RULE = "low-supply-chain-score";
32933
32936
  const SUPPLY_CHAIN_CATEGORY = "Security";
@@ -37338,38 +37341,9 @@ const failOpenReadJson = (filePath, fallback) => {
37338
37341
  return fallback;
37339
37342
  }
37340
37343
  };
37341
- const ANALYZED_FILE_EXTENSIONS = new Set([
37342
- ".ts",
37343
- ".tsx",
37344
- ".js",
37345
- ".jsx",
37346
- ".mts",
37347
- ".mjs",
37348
- ".cts",
37349
- ".cjs",
37350
- ".mdx",
37351
- ".astro",
37352
- ".graphql",
37353
- ".gql",
37354
- ".css",
37355
- ".scss",
37356
- ".vue",
37357
- ".svelte"
37358
- ]);
37359
- const ANALYZED_MANIFEST_NAMES = new Set([
37360
- "package.json",
37361
- "knip.json",
37362
- "app.json",
37363
- "pnpm-workspace.yaml",
37364
- "lerna.json",
37365
- "pnpm-lock.yaml",
37366
- "package-lock.json",
37367
- "yarn.lock",
37368
- "bun.lock",
37369
- "bun.lockb",
37370
- "deno.lock",
37371
- ".gitignore"
37372
- ]);
37344
+ const ANALYZED_FILE_EXTENSIONS = new Set(DEFAULT_EXTENSIONS);
37345
+ const CORE_SIDE_MANIFEST_NAMES = ["knip.json", "deno.lock"];
37346
+ const ANALYZED_MANIFEST_NAMES = new Set([...ANALYZED_MANIFEST_FILENAMES, ...CORE_SIDE_MANIFEST_NAMES]);
37373
37347
  const isTsConfigLikeFile = (fileName) => (fileName.startsWith("tsconfig") || fileName.startsWith("jsconfig")) && fileName.endsWith(".json");
37374
37348
  const isFingerprintedFile = (fileName) => ANALYZED_FILE_EXTENSIONS.has(Path.extname(fileName).toLowerCase()) || ANALYZED_MANIFEST_NAMES.has(fileName) || isTsConfigLikeFile(fileName);
37375
37349
  const collectAnalyzedFileFingerprints = (rootDirectory) => {
@@ -37395,6 +37369,7 @@ const resolveDeslopVersion = () => {
37395
37369
  };
37396
37370
  const computeDeadCodeCacheKey = (input) => crypto.createHash("sha1").update(JSON.stringify({
37397
37371
  schemaVersion: 1,
37372
+ coreVersion: input.coreVersion,
37398
37373
  deslopVersion: resolveDeslopVersion(),
37399
37374
  deslopJsModuleSpecifier: input.deslopJsModuleSpecifier,
37400
37375
  entryPatterns: input.entryPatterns,
@@ -37559,6 +37534,14 @@ process.stdin.on("end", () => {
37559
37534
  circularDependencies: result.circularDependencies.map((cycle) => ({
37560
37535
  files: cycle.files,
37561
37536
  })),
37537
+ ...(result.incrementalCacheStats
37538
+ ? {
37539
+ summaryCacheStats: {
37540
+ hits: result.incrementalCacheStats.summaryHits,
37541
+ misses: result.incrementalCacheStats.summaryMisses,
37542
+ },
37543
+ }
37544
+ : {}),
37562
37545
  });
37563
37546
 
37564
37547
  const serializeError = (error) =>
@@ -37582,6 +37565,9 @@ process.stdin.on("end", () => {
37582
37565
  ...(workerInput.ignorePatterns.length > 0
37583
37566
  ? { ignorePatterns: workerInput.ignorePatterns }
37584
37567
  : {}),
37568
+ ...(workerInput.incrementalCachePath
37569
+ ? { incrementalCachePath: workerInput.incrementalCachePath }
37570
+ : {}),
37585
37571
  // We consume only deslop's GRAPH-based findings (unusedFiles, unusedExports,
37586
37572
  // unusedDependencies, circularDependencies). Everything else deslop can compute
37587
37573
  // is pure wasted work for us, and it's the bulk of the runtime:
@@ -37592,12 +37578,18 @@ process.stdin.on("end", () => {
37592
37578
  // are the single most expensive pass — duplicate-block detection alone was
37593
37579
  // ~83s of a ~130s Sentry scan — so skipping them is an ~8.5x dead-code
37594
37580
  // speedup on a large repo.
37595
- // Both are provably safe: the consumed graph findings are computed by their own
37581
+ // - reportRedundancy: the DRY-pattern detectors (duplicate types/constants,
37582
+ // simplifiable functions, identity wrappers, …) — ~120 ms of discarded
37583
+ // output per scan, and skipping them lets the incremental cache drop the
37584
+ // DRY-pattern summary fields (the largest slice of the cache file).
37585
+ // All are provably safe: the consumed graph findings are computed by their own
37596
37586
  // detectors, independent of these passes (confirmed byte-identical on
37597
- // excalidraw + mui-material + sentry). tsConfigPath stays — the module resolver
37598
- // needs it for path-alias resolution in the import graph.
37587
+ // excalidraw + mui-material + sentry; re-verified on sentry after the
37588
+ // reportRedundancy flip). tsConfigPath stays — the module resolver needs it
37589
+ // for path-alias resolution in the import graph.
37599
37590
  semantic: { enabled: false },
37600
37591
  reportCodeQuality: false,
37592
+ reportRedundancy: false,
37601
37593
  };
37602
37594
  const result = await analyze(defineConfig(config));
37603
37595
  emit({ ok: true, result: normalizeResult(result) });
@@ -37681,13 +37673,23 @@ const parseCircularDependencies = (value) => {
37681
37673
  }
37682
37674
  return circularDependencies;
37683
37675
  };
37676
+ const parseSummaryCacheStats = (value) => {
37677
+ if (!isRecord(value)) return void 0;
37678
+ if (typeof value.hits !== "number" || typeof value.misses !== "number") return void 0;
37679
+ return {
37680
+ hits: value.hits,
37681
+ misses: value.misses
37682
+ };
37683
+ };
37684
37684
  const parseDeadCodeWorkerResult = (value) => {
37685
37685
  if (!isRecord(value)) throw new Error("Dead-code worker returned an invalid result.");
37686
+ const summaryCacheStats = parseSummaryCacheStats(value.summaryCacheStats);
37686
37687
  return {
37687
37688
  unusedFiles: parseUnusedFiles(value.unusedFiles),
37688
37689
  unusedExports: parseUnusedExports(value.unusedExports),
37689
37690
  unusedDependencies: parseUnusedDependencies(value.unusedDependencies),
37690
- circularDependencies: parseCircularDependencies(value.circularDependencies)
37691
+ circularDependencies: parseCircularDependencies(value.circularDependencies),
37692
+ ...summaryCacheStats ? { summaryCacheStats } : {}
37691
37693
  };
37692
37694
  };
37693
37695
  const parseDeadCodeWorkerError = (value) => {
@@ -37808,13 +37810,15 @@ const checkDeadCode = async (options) => {
37808
37810
  entryPatterns,
37809
37811
  ignorePatterns,
37810
37812
  tsConfigPath,
37811
- deslopJsModuleSpecifier
37813
+ deslopJsModuleSpecifier,
37814
+ coreVersion: CORE_PACKAGE_VERSION
37812
37815
  }) : null;
37813
37816
  if (cacheKey !== null) {
37814
37817
  const cachedDiagnostics = lookupDeadCodeResultCache(resolveReactDoctorCacheDir(rootDirectory), cacheKey);
37815
37818
  options.onCacheOutcome?.(cachedDiagnostics !== null);
37816
37819
  if (cachedDiagnostics !== null) return [...cachedDiagnostics];
37817
37820
  }
37821
+ const incrementalCachePath = options.cacheEnabled === true ? Path.join(resolveReactDoctorCacheDir(rootDirectory), DEAD_CODE_SUMMARY_CACHE_FILENAME) : void 0;
37818
37822
  const spawnAndRun = () => {
37819
37823
  return runDeadCodeWorkerWithTimeout((options.createWorker ?? createDeadCodeWorker)({
37820
37824
  rootDirectory,
@@ -37822,10 +37826,12 @@ const checkDeadCode = async (options) => {
37822
37826
  tsConfigPath,
37823
37827
  ignorePatterns,
37824
37828
  deslopJsModuleSpecifier,
37825
- parseConcurrency: options.parseConcurrency
37829
+ parseConcurrency: options.parseConcurrency,
37830
+ incrementalCachePath
37826
37831
  }), options.workerTimeoutMs ?? 12e4, options.abortSignal);
37827
37832
  };
37828
37833
  const result = parseDeadCodeWorkerResult(options.createWorker === void 0 ? await withDeadCodeWorkerSlot(spawnAndRun, options.abortSignal) : await spawnAndRun());
37834
+ if (result.summaryCacheStats !== void 0) options.onSummaryCacheStats?.(result.summaryCacheStats);
37829
37835
  const toRelative = (filePath) => toRelativeFilePath(rootDirectory, filePath);
37830
37836
  const diagnostics = [];
37831
37837
  for (const unusedFile of result.unusedFiles) diagnostics.push({
@@ -37993,7 +37999,8 @@ var DeadCode = class DeadCode extends Service()("react-doctor/DeadCode") {
37993
37999
  workerTimeoutMs: input.workerTimeoutMs,
37994
38000
  abortSignal: signal,
37995
38001
  cacheEnabled,
37996
- onCacheOutcome: input.onCacheOutcome
38002
+ onCacheOutcome: input.onCacheOutcome,
38003
+ onSummaryCacheStats: input.onSummaryCacheStats
37997
38004
  }),
37998
38005
  catch: (cause) => new ReactDoctorError({ reason: new DeadCodeAnalysisFailed({ cause }) })
37999
38006
  }).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)));
@@ -41175,6 +41182,10 @@ const runInspect = (input, hooks = {}) => gen(function* () {
41175
41182
  workerTimeoutMs: deadCodeTimeout.workerTimeoutMs,
41176
41183
  onCacheOutcome: (didHitCache) => {
41177
41184
  deadCodeCacheHit = didHitCache;
41185
+ },
41186
+ onSummaryCacheStats: (stats) => {
41187
+ deadCodeSummaryCacheHits = stats.hits;
41188
+ deadCodeSummaryCacheMisses = stats.misses;
41178
41189
  }
41179
41190
  }).pipe(catchTag("ReactDoctorError", (error) => unwrap(gen(function* () {
41180
41191
  yield* set(deadCodeFailure, {
@@ -41204,6 +41215,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
41204
41215
  let lintCacheHitFileCount = null;
41205
41216
  let lintCacheTotalFileCount = null;
41206
41217
  let deadCodeCacheHit = null;
41218
+ let deadCodeSummaryCacheHits = null;
41219
+ let deadCodeSummaryCacheMisses = null;
41207
41220
  const baseLintStream = linterService.run({
41208
41221
  rootDirectory: scanDirectory,
41209
41222
  project,
@@ -41334,6 +41347,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
41334
41347
  lintCacheHitFileCount,
41335
41348
  lintCacheTotalFileCount,
41336
41349
  deadCodeCacheHit: lintFailureState.didFail ? null : deadCodeCacheHit,
41350
+ deadCodeSummaryCacheHits: lintFailureState.didFail ? null : deadCodeSummaryCacheHits,
41351
+ deadCodeSummaryCacheMisses: lintFailureState.didFail ? null : deadCodeSummaryCacheMisses,
41337
41352
  suppressedRuleCounts: transform.summarizeSuppressions()
41338
41353
  };
41339
41354
  }).pipe(withSpan("runInspect", { attributes: {
@@ -41974,4 +41989,4 @@ const toJsonReport = (result, options) => buildJsonReport({
41974
41989
  export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
41975
41990
 
41976
41991
  //# sourceMappingURL=index.js.map
41977
- //# debugId=367db57b-e5c7-577e-9efa-ed68817a8271
41992
+ //# debugId=f615f76d-a949-5fb6-ace8-145f3e137af4
package/dist/lsp.js CHANGED
@@ -15,6 +15,7 @@ import { fileURLToPath } from "node:url";
15
15
  import { createJiti } from "jiti";
16
16
  import * as Crypto from "node:crypto";
17
17
  import crypto, { createHash } from "node:crypto";
18
+ import { ANALYZED_MANIFEST_FILENAMES, DEFAULT_EXTENSIONS } from "deslop-js/analyzed-inputs";
18
19
  import { gzipSync } from "node:zlib";
19
20
  import { CodeActionKind, CodeActionTriggerKind, DidChangeWatchedFilesNotification, DocumentDiagnosticReportKind, FileChangeType, TextDocumentSyncKind, TextDocuments, createConnection } from "vscode-languageserver/node.js";
20
21
  import { TextDocument } from "vscode-languageserver-textdocument";
@@ -32986,7 +32987,9 @@ const SOCKET_PACKAGE_PAGE_BASE = "https://socket.dev/npm/package";
32986
32987
  const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
32987
32988
  const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
32988
32989
  const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
32990
+ const CORE_PACKAGE_VERSION = "0.6.3";
32989
32991
  const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
32992
+ const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
32990
32993
  const SUPPLY_CHAIN_PLUGIN = "socket";
32991
32994
  const SUPPLY_CHAIN_RULE = "low-supply-chain-score";
32992
32995
  const SUPPLY_CHAIN_CATEGORY = "Security";
@@ -37323,38 +37326,9 @@ const failOpenReadJson = (filePath, fallback) => {
37323
37326
  return fallback;
37324
37327
  }
37325
37328
  };
37326
- const ANALYZED_FILE_EXTENSIONS = new Set([
37327
- ".ts",
37328
- ".tsx",
37329
- ".js",
37330
- ".jsx",
37331
- ".mts",
37332
- ".mjs",
37333
- ".cts",
37334
- ".cjs",
37335
- ".mdx",
37336
- ".astro",
37337
- ".graphql",
37338
- ".gql",
37339
- ".css",
37340
- ".scss",
37341
- ".vue",
37342
- ".svelte"
37343
- ]);
37344
- const ANALYZED_MANIFEST_NAMES = new Set([
37345
- "package.json",
37346
- "knip.json",
37347
- "app.json",
37348
- "pnpm-workspace.yaml",
37349
- "lerna.json",
37350
- "pnpm-lock.yaml",
37351
- "package-lock.json",
37352
- "yarn.lock",
37353
- "bun.lock",
37354
- "bun.lockb",
37355
- "deno.lock",
37356
- ".gitignore"
37357
- ]);
37329
+ const ANALYZED_FILE_EXTENSIONS = new Set(DEFAULT_EXTENSIONS);
37330
+ const CORE_SIDE_MANIFEST_NAMES = ["knip.json", "deno.lock"];
37331
+ const ANALYZED_MANIFEST_NAMES = new Set([...ANALYZED_MANIFEST_FILENAMES, ...CORE_SIDE_MANIFEST_NAMES]);
37358
37332
  const isTsConfigLikeFile = (fileName) => (fileName.startsWith("tsconfig") || fileName.startsWith("jsconfig")) && fileName.endsWith(".json");
37359
37333
  const isFingerprintedFile = (fileName) => ANALYZED_FILE_EXTENSIONS.has(Path.extname(fileName).toLowerCase()) || ANALYZED_MANIFEST_NAMES.has(fileName) || isTsConfigLikeFile(fileName);
37360
37334
  const collectAnalyzedFileFingerprints = (rootDirectory) => {
@@ -37380,6 +37354,7 @@ const resolveDeslopVersion = () => {
37380
37354
  };
37381
37355
  const computeDeadCodeCacheKey = (input) => crypto.createHash("sha1").update(JSON.stringify({
37382
37356
  schemaVersion: 1,
37357
+ coreVersion: input.coreVersion,
37383
37358
  deslopVersion: resolveDeslopVersion(),
37384
37359
  deslopJsModuleSpecifier: input.deslopJsModuleSpecifier,
37385
37360
  entryPatterns: input.entryPatterns,
@@ -37544,6 +37519,14 @@ process.stdin.on("end", () => {
37544
37519
  circularDependencies: result.circularDependencies.map((cycle) => ({
37545
37520
  files: cycle.files,
37546
37521
  })),
37522
+ ...(result.incrementalCacheStats
37523
+ ? {
37524
+ summaryCacheStats: {
37525
+ hits: result.incrementalCacheStats.summaryHits,
37526
+ misses: result.incrementalCacheStats.summaryMisses,
37527
+ },
37528
+ }
37529
+ : {}),
37547
37530
  });
37548
37531
 
37549
37532
  const serializeError = (error) =>
@@ -37567,6 +37550,9 @@ process.stdin.on("end", () => {
37567
37550
  ...(workerInput.ignorePatterns.length > 0
37568
37551
  ? { ignorePatterns: workerInput.ignorePatterns }
37569
37552
  : {}),
37553
+ ...(workerInput.incrementalCachePath
37554
+ ? { incrementalCachePath: workerInput.incrementalCachePath }
37555
+ : {}),
37570
37556
  // We consume only deslop's GRAPH-based findings (unusedFiles, unusedExports,
37571
37557
  // unusedDependencies, circularDependencies). Everything else deslop can compute
37572
37558
  // is pure wasted work for us, and it's the bulk of the runtime:
@@ -37577,12 +37563,18 @@ process.stdin.on("end", () => {
37577
37563
  // are the single most expensive pass — duplicate-block detection alone was
37578
37564
  // ~83s of a ~130s Sentry scan — so skipping them is an ~8.5x dead-code
37579
37565
  // speedup on a large repo.
37580
- // Both are provably safe: the consumed graph findings are computed by their own
37566
+ // - reportRedundancy: the DRY-pattern detectors (duplicate types/constants,
37567
+ // simplifiable functions, identity wrappers, …) — ~120 ms of discarded
37568
+ // output per scan, and skipping them lets the incremental cache drop the
37569
+ // DRY-pattern summary fields (the largest slice of the cache file).
37570
+ // All are provably safe: the consumed graph findings are computed by their own
37581
37571
  // detectors, independent of these passes (confirmed byte-identical on
37582
- // excalidraw + mui-material + sentry). tsConfigPath stays — the module resolver
37583
- // needs it for path-alias resolution in the import graph.
37572
+ // excalidraw + mui-material + sentry; re-verified on sentry after the
37573
+ // reportRedundancy flip). tsConfigPath stays — the module resolver needs it
37574
+ // for path-alias resolution in the import graph.
37584
37575
  semantic: { enabled: false },
37585
37576
  reportCodeQuality: false,
37577
+ reportRedundancy: false,
37586
37578
  };
37587
37579
  const result = await analyze(defineConfig(config));
37588
37580
  emit({ ok: true, result: normalizeResult(result) });
@@ -37666,13 +37658,23 @@ const parseCircularDependencies = (value) => {
37666
37658
  }
37667
37659
  return circularDependencies;
37668
37660
  };
37661
+ const parseSummaryCacheStats = (value) => {
37662
+ if (!isRecord(value)) return void 0;
37663
+ if (typeof value.hits !== "number" || typeof value.misses !== "number") return void 0;
37664
+ return {
37665
+ hits: value.hits,
37666
+ misses: value.misses
37667
+ };
37668
+ };
37669
37669
  const parseDeadCodeWorkerResult = (value) => {
37670
37670
  if (!isRecord(value)) throw new Error("Dead-code worker returned an invalid result.");
37671
+ const summaryCacheStats = parseSummaryCacheStats(value.summaryCacheStats);
37671
37672
  return {
37672
37673
  unusedFiles: parseUnusedFiles(value.unusedFiles),
37673
37674
  unusedExports: parseUnusedExports(value.unusedExports),
37674
37675
  unusedDependencies: parseUnusedDependencies(value.unusedDependencies),
37675
- circularDependencies: parseCircularDependencies(value.circularDependencies)
37676
+ circularDependencies: parseCircularDependencies(value.circularDependencies),
37677
+ ...summaryCacheStats ? { summaryCacheStats } : {}
37676
37678
  };
37677
37679
  };
37678
37680
  const parseDeadCodeWorkerError = (value) => {
@@ -37793,13 +37795,15 @@ const checkDeadCode = async (options) => {
37793
37795
  entryPatterns,
37794
37796
  ignorePatterns,
37795
37797
  tsConfigPath,
37796
- deslopJsModuleSpecifier
37798
+ deslopJsModuleSpecifier,
37799
+ coreVersion: CORE_PACKAGE_VERSION
37797
37800
  }) : null;
37798
37801
  if (cacheKey !== null) {
37799
37802
  const cachedDiagnostics = lookupDeadCodeResultCache(resolveReactDoctorCacheDir(rootDirectory), cacheKey);
37800
37803
  options.onCacheOutcome?.(cachedDiagnostics !== null);
37801
37804
  if (cachedDiagnostics !== null) return [...cachedDiagnostics];
37802
37805
  }
37806
+ const incrementalCachePath = options.cacheEnabled === true ? Path.join(resolveReactDoctorCacheDir(rootDirectory), DEAD_CODE_SUMMARY_CACHE_FILENAME) : void 0;
37803
37807
  const spawnAndRun = () => {
37804
37808
  return runDeadCodeWorkerWithTimeout((options.createWorker ?? createDeadCodeWorker)({
37805
37809
  rootDirectory,
@@ -37807,10 +37811,12 @@ const checkDeadCode = async (options) => {
37807
37811
  tsConfigPath,
37808
37812
  ignorePatterns,
37809
37813
  deslopJsModuleSpecifier,
37810
- parseConcurrency: options.parseConcurrency
37814
+ parseConcurrency: options.parseConcurrency,
37815
+ incrementalCachePath
37811
37816
  }), options.workerTimeoutMs ?? 12e4, options.abortSignal);
37812
37817
  };
37813
37818
  const result = parseDeadCodeWorkerResult(options.createWorker === void 0 ? await withDeadCodeWorkerSlot(spawnAndRun, options.abortSignal) : await spawnAndRun());
37819
+ if (result.summaryCacheStats !== void 0) options.onSummaryCacheStats?.(result.summaryCacheStats);
37814
37820
  const toRelative = (filePath) => toRelativeFilePath(rootDirectory, filePath);
37815
37821
  const diagnostics = [];
37816
37822
  for (const unusedFile of result.unusedFiles) diagnostics.push({
@@ -37978,7 +37984,8 @@ var DeadCode = class DeadCode extends Service()("react-doctor/DeadCode") {
37978
37984
  workerTimeoutMs: input.workerTimeoutMs,
37979
37985
  abortSignal: signal,
37980
37986
  cacheEnabled,
37981
- onCacheOutcome: input.onCacheOutcome
37987
+ onCacheOutcome: input.onCacheOutcome,
37988
+ onSummaryCacheStats: input.onSummaryCacheStats
37982
37989
  }),
37983
37990
  catch: (cause) => new ReactDoctorError({ reason: new DeadCodeAnalysisFailed({ cause }) })
37984
37991
  }).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)));
@@ -41160,6 +41167,10 @@ const runInspect = (input, hooks = {}) => gen(function* () {
41160
41167
  workerTimeoutMs: deadCodeTimeout.workerTimeoutMs,
41161
41168
  onCacheOutcome: (didHitCache) => {
41162
41169
  deadCodeCacheHit = didHitCache;
41170
+ },
41171
+ onSummaryCacheStats: (stats) => {
41172
+ deadCodeSummaryCacheHits = stats.hits;
41173
+ deadCodeSummaryCacheMisses = stats.misses;
41163
41174
  }
41164
41175
  }).pipe(catchTag("ReactDoctorError", (error) => unwrap(gen(function* () {
41165
41176
  yield* set(deadCodeFailure, {
@@ -41189,6 +41200,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
41189
41200
  let lintCacheHitFileCount = null;
41190
41201
  let lintCacheTotalFileCount = null;
41191
41202
  let deadCodeCacheHit = null;
41203
+ let deadCodeSummaryCacheHits = null;
41204
+ let deadCodeSummaryCacheMisses = null;
41192
41205
  const baseLintStream = linterService.run({
41193
41206
  rootDirectory: scanDirectory,
41194
41207
  project,
@@ -41319,6 +41332,8 @@ const runInspect = (input, hooks = {}) => gen(function* () {
41319
41332
  lintCacheHitFileCount,
41320
41333
  lintCacheTotalFileCount,
41321
41334
  deadCodeCacheHit: lintFailureState.didFail ? null : deadCodeCacheHit,
41335
+ deadCodeSummaryCacheHits: lintFailureState.didFail ? null : deadCodeSummaryCacheHits,
41336
+ deadCodeSummaryCacheMisses: lintFailureState.didFail ? null : deadCodeSummaryCacheMisses,
41322
41337
  suppressedRuleCounts: transform.summarizeSuppressions()
41323
41338
  };
41324
41339
  }).pipe(withSpan("runInspect", { attributes: {
@@ -43698,5 +43713,5 @@ const startLanguageServer = () => {
43698
43713
  };
43699
43714
  //#endregion
43700
43715
  export { startLanguageServer };
43701
- !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]="46e851cc-7b86-5c73-afb0-e09296beab28")}catch(e){}}();
43702
- //# debugId=46e851cc-7b86-5c73-afb0-e09296beab28
43716
+ !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]="c5ee1532-72b6-5d6f-83ae-7bb4dccf2226")}catch(e){}}();
43717
+ //# debugId=c5ee1532-72b6-5d6f-83ae-7bb4dccf2226
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-doctor",
3
- "version": "0.6.3-dev.8c004f0",
3
+ "version": "0.6.3-dev.ce49250",
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.6.3",
69
- "oxlint-plugin-react-doctor": "0.6.3-dev.8c004f0"
69
+ "oxlint-plugin-react-doctor": "0.6.3-dev.ce49250"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/babel__code-frame": "^7.27.0",