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 +72 -47
- package/dist/index.d.ts +10 -0
- package/dist/index.js +56 -41
- package/dist/lsp.js +56 -41
- package/package.json +2 -2
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]="
|
|
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
|
-
|
|
40586
|
-
|
|
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
|
-
//
|
|
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
|
|
40841
|
-
//
|
|
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.
|
|
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.
|
|
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.
|
|
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=
|
|
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]="
|
|
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
|
-
|
|
37343
|
-
|
|
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
|
-
//
|
|
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
|
|
37598
|
-
//
|
|
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=
|
|
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
|
-
|
|
37328
|
-
|
|
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
|
-
//
|
|
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
|
|
37583
|
-
//
|
|
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]="
|
|
43702
|
-
//# debugId=
|
|
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.
|
|
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.
|
|
69
|
+
"oxlint-plugin-react-doctor": "0.6.3-dev.ce49250"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/babel__code-frame": "^7.27.0",
|