react-doctor 0.6.3-dev.ea9a775 → 0.7.0-dev.574cba6
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 +462 -314
- package/dist/index.js +118 -31
- package/dist/lsp.js +122 -37
- package/package.json +6 -6
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]="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";
|
|
@@ -32929,13 +32929,14 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
|
|
|
32929
32929
|
const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
|
|
32930
32930
|
const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
|
|
32931
32931
|
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
32932
|
-
const CORE_PACKAGE_VERSION = "0.
|
|
32932
|
+
const CORE_PACKAGE_VERSION = "0.7.0";
|
|
32933
32933
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
32934
32934
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
32935
32935
|
const SUPPLY_CHAIN_PLUGIN = "socket";
|
|
32936
32936
|
const SUPPLY_CHAIN_RULE = "low-supply-chain-score";
|
|
32937
32937
|
const SUPPLY_CHAIN_CATEGORY = "Security";
|
|
32938
32938
|
const SUPPLY_CHAIN_OVERLAP_TIMEOUT_MS = 9e4;
|
|
32939
|
+
const SUPPLY_CHAIN_CACHE_TTL_MS = 864e5;
|
|
32939
32940
|
const SUPPLY_CHAIN_CACHE_SUBDIR = "supply-chain";
|
|
32940
32941
|
const SUPPLY_CHAIN_IGNORED_PACKAGES = new Set(["next"]);
|
|
32941
32942
|
const hasIgnoredPathSegment = (relativePath) => relativePath.split(/[/\\]/).slice(0, -1).some((segment) => IGNORED_DIRECTORIES.has(segment));
|
|
@@ -37365,22 +37366,37 @@ const failOpenReadJson = (filePath, fallback) => {
|
|
|
37365
37366
|
return fallback;
|
|
37366
37367
|
}
|
|
37367
37368
|
};
|
|
37369
|
+
const hashFileContents = (filePath) => {
|
|
37370
|
+
try {
|
|
37371
|
+
return crypto.createHash("sha1").update(NFS.readFileSync(filePath)).digest("hex");
|
|
37372
|
+
} catch {
|
|
37373
|
+
return null;
|
|
37374
|
+
}
|
|
37375
|
+
};
|
|
37368
37376
|
const ANALYZED_FILE_EXTENSIONS = new Set(DEFAULT_EXTENSIONS);
|
|
37369
37377
|
const CORE_SIDE_MANIFEST_NAMES = ["knip.json", "deno.lock"];
|
|
37370
37378
|
const ANALYZED_MANIFEST_NAMES = new Set([...ANALYZED_MANIFEST_FILENAMES, ...CORE_SIDE_MANIFEST_NAMES]);
|
|
37371
37379
|
const isTsConfigLikeFile = (fileName) => (fileName.startsWith("tsconfig") || fileName.startsWith("jsconfig")) && fileName.endsWith(".json");
|
|
37372
37380
|
const isFingerprintedFile = (fileName) => ANALYZED_FILE_EXTENSIONS.has(Path.extname(fileName).toLowerCase()) || ANALYZED_MANIFEST_NAMES.has(fileName) || isTsConfigLikeFile(fileName);
|
|
37373
|
-
|
|
37374
|
-
|
|
37381
|
+
/**
|
|
37382
|
+
* Stat snapshot of every file the analysis reads, keyed by root-relative
|
|
37383
|
+
* `/`-separated path. Taken BEFORE the (long) analysis so a stored result is
|
|
37384
|
+
* verified against the tree it started from.
|
|
37385
|
+
*/
|
|
37386
|
+
const collectAnalyzedFileStats = (rootDirectory) => {
|
|
37387
|
+
const statByRelativePath = /* @__PURE__ */ new Map();
|
|
37375
37388
|
for (const { absolutePath, name } of walkSourceTreeFiles(rootDirectory)) {
|
|
37376
37389
|
if (!isFingerprintedFile(name)) continue;
|
|
37377
37390
|
try {
|
|
37378
37391
|
const fileStat = NFS.statSync(absolutePath);
|
|
37379
37392
|
const relativePath = Path.relative(rootDirectory, absolutePath).replace(/\\/g, "/");
|
|
37380
|
-
|
|
37393
|
+
statByRelativePath.set(relativePath, {
|
|
37394
|
+
mtimeMs: fileStat.mtimeMs,
|
|
37395
|
+
size: fileStat.size
|
|
37396
|
+
});
|
|
37381
37397
|
} catch {}
|
|
37382
37398
|
}
|
|
37383
|
-
return
|
|
37399
|
+
return statByRelativePath;
|
|
37384
37400
|
};
|
|
37385
37401
|
const bundledRequire$2 = createRequire(import.meta.url);
|
|
37386
37402
|
const resolveDeslopVersion = () => {
|
|
@@ -37392,14 +37408,13 @@ const resolveDeslopVersion = () => {
|
|
|
37392
37408
|
}
|
|
37393
37409
|
};
|
|
37394
37410
|
const computeDeadCodeCacheKey = (input) => crypto.createHash("sha1").update(JSON.stringify({
|
|
37395
|
-
schemaVersion:
|
|
37411
|
+
schemaVersion: 2,
|
|
37396
37412
|
coreVersion: input.coreVersion,
|
|
37397
37413
|
deslopVersion: resolveDeslopVersion(),
|
|
37398
37414
|
deslopJsModuleSpecifier: input.deslopJsModuleSpecifier,
|
|
37399
37415
|
entryPatterns: input.entryPatterns,
|
|
37400
37416
|
ignorePatterns: input.ignorePatterns,
|
|
37401
|
-
tsConfigFile: input.tsConfigPath === void 0 ? null : Path.relative(input.rootDirectory, input.tsConfigPath).replace(/\\/g, "/")
|
|
37402
|
-
files: collectAnalyzedFileFingerprints(input.rootDirectory)
|
|
37417
|
+
tsConfigFile: input.tsConfigPath === void 0 ? null : Path.relative(input.rootDirectory, input.tsConfigPath).replace(/\\/g, "/")
|
|
37403
37418
|
})).digest("hex");
|
|
37404
37419
|
const validateDiagnostic$2 = decodeUnknownSync(Diagnostic);
|
|
37405
37420
|
const decodeCachedDiagnostics = (raw) => {
|
|
@@ -37410,16 +37425,68 @@ const decodeCachedDiagnostics = (raw) => {
|
|
|
37410
37425
|
return null;
|
|
37411
37426
|
}
|
|
37412
37427
|
};
|
|
37413
|
-
const
|
|
37414
|
-
|
|
37415
|
-
|
|
37416
|
-
|
|
37428
|
+
const isPersistedFileIdentity = (value) => Array.isArray(value) && value.length === 3 && typeof value[0] === "number" && typeof value[1] === "number" && typeof value[2] === "string";
|
|
37429
|
+
const lookupDeadCodeResultCache = (input) => {
|
|
37430
|
+
const cacheFilePath = Path.join(input.cacheDirectory, DEAD_CODE_CACHE_FILENAME);
|
|
37431
|
+
const persisted = failOpenReadJson(cacheFilePath, null);
|
|
37432
|
+
if (persisted === null || !isRecord(persisted) || persisted.version !== 2 || persisted.key !== input.cacheKey || !isRecord(persisted.files) || !Array.isArray(persisted.diagnostics)) return null;
|
|
37433
|
+
const storedFileEntries = Object.entries(persisted.files);
|
|
37434
|
+
if (storedFileEntries.length !== input.currentFileStats.size) return null;
|
|
37435
|
+
const repairedFiles = {};
|
|
37436
|
+
let repairedCount = 0;
|
|
37437
|
+
for (const [relativePath, storedIdentity] of storedFileEntries) {
|
|
37438
|
+
if (!isPersistedFileIdentity(storedIdentity)) return null;
|
|
37439
|
+
const currentStat = input.currentFileStats.get(relativePath);
|
|
37440
|
+
if (currentStat === void 0) return null;
|
|
37441
|
+
const [storedMtimeMs, storedSize, storedContentHash] = storedIdentity;
|
|
37442
|
+
if (currentStat.mtimeMs === storedMtimeMs && currentStat.size === storedSize) {
|
|
37443
|
+
repairedFiles[relativePath] = storedIdentity;
|
|
37444
|
+
continue;
|
|
37445
|
+
}
|
|
37446
|
+
if (currentStat.size !== storedSize) return null;
|
|
37447
|
+
const currentContentHash = hashFileContents(Path.join(input.rootDirectory, relativePath));
|
|
37448
|
+
if (currentContentHash === null || currentContentHash !== storedContentHash) return null;
|
|
37449
|
+
repairedFiles[relativePath] = [
|
|
37450
|
+
currentStat.mtimeMs,
|
|
37451
|
+
currentStat.size,
|
|
37452
|
+
storedContentHash
|
|
37453
|
+
];
|
|
37454
|
+
repairedCount += 1;
|
|
37455
|
+
}
|
|
37456
|
+
const diagnostics = decodeCachedDiagnostics(persisted.diagnostics);
|
|
37457
|
+
if (diagnostics === null) return null;
|
|
37458
|
+
if (repairedCount > 0) atomicWriteJson(cacheFilePath, {
|
|
37459
|
+
version: 2,
|
|
37460
|
+
key: input.cacheKey,
|
|
37461
|
+
files: repairedFiles,
|
|
37462
|
+
diagnostics: persisted.diagnostics
|
|
37463
|
+
});
|
|
37464
|
+
return diagnostics;
|
|
37417
37465
|
};
|
|
37418
|
-
const storeDeadCodeResultCache = (
|
|
37419
|
-
|
|
37420
|
-
|
|
37421
|
-
|
|
37422
|
-
|
|
37466
|
+
const storeDeadCodeResultCache = (input) => {
|
|
37467
|
+
const persistedFiles = {};
|
|
37468
|
+
for (const [relativePath, snapshotStat] of input.snapshotFileStats) {
|
|
37469
|
+
const absolutePath = Path.join(input.rootDirectory, relativePath);
|
|
37470
|
+
const contentHash = hashFileContents(absolutePath);
|
|
37471
|
+
if (contentHash === null) return;
|
|
37472
|
+
let currentStat;
|
|
37473
|
+
try {
|
|
37474
|
+
currentStat = NFS.statSync(absolutePath);
|
|
37475
|
+
} catch {
|
|
37476
|
+
return;
|
|
37477
|
+
}
|
|
37478
|
+
if (currentStat.mtimeMs !== snapshotStat.mtimeMs || currentStat.size !== snapshotStat.size) return;
|
|
37479
|
+
persistedFiles[relativePath] = [
|
|
37480
|
+
snapshotStat.mtimeMs,
|
|
37481
|
+
snapshotStat.size,
|
|
37482
|
+
contentHash
|
|
37483
|
+
];
|
|
37484
|
+
}
|
|
37485
|
+
atomicWriteJson(Path.join(input.cacheDirectory, DEAD_CODE_CACHE_FILENAME), {
|
|
37486
|
+
version: 2,
|
|
37487
|
+
key: input.cacheKey,
|
|
37488
|
+
files: persistedFiles,
|
|
37489
|
+
diagnostics: input.diagnostics
|
|
37423
37490
|
});
|
|
37424
37491
|
};
|
|
37425
37492
|
const readSystemFacts = () => ({
|
|
@@ -37829,16 +37896,22 @@ const checkDeadCode = async (options) => {
|
|
|
37829
37896
|
const ignorePatterns = collectDeadCodeIgnorePatterns(rootDirectory);
|
|
37830
37897
|
const tsConfigPath = resolveTsConfigPath(rootDirectory);
|
|
37831
37898
|
const deslopJsModuleSpecifier = options.deslopJsModuleSpecifier ?? import.meta.resolve("deslop-js");
|
|
37832
|
-
const
|
|
37899
|
+
const fileStatsSnapshot = options.cacheEnabled ? collectAnalyzedFileStats(rootDirectory) : null;
|
|
37900
|
+
const cacheKey = fileStatsSnapshot === null ? null : computeDeadCodeCacheKey({
|
|
37833
37901
|
rootDirectory,
|
|
37834
37902
|
entryPatterns,
|
|
37835
37903
|
ignorePatterns,
|
|
37836
37904
|
tsConfigPath,
|
|
37837
37905
|
deslopJsModuleSpecifier,
|
|
37838
37906
|
coreVersion: CORE_PACKAGE_VERSION
|
|
37839
|
-
})
|
|
37840
|
-
if (cacheKey !== null) {
|
|
37841
|
-
const cachedDiagnostics = lookupDeadCodeResultCache(
|
|
37907
|
+
});
|
|
37908
|
+
if (cacheKey !== null && fileStatsSnapshot !== null) {
|
|
37909
|
+
const cachedDiagnostics = lookupDeadCodeResultCache({
|
|
37910
|
+
cacheDirectory: resolveReactDoctorCacheDir(rootDirectory),
|
|
37911
|
+
cacheKey,
|
|
37912
|
+
rootDirectory,
|
|
37913
|
+
currentFileStats: fileStatsSnapshot
|
|
37914
|
+
});
|
|
37842
37915
|
options.onCacheOutcome?.(cachedDiagnostics !== null);
|
|
37843
37916
|
if (cachedDiagnostics !== null) return [...cachedDiagnostics];
|
|
37844
37917
|
}
|
|
@@ -37912,7 +37985,13 @@ const checkDeadCode = async (options) => {
|
|
|
37912
37985
|
category: DEAD_CODE_CATEGORY
|
|
37913
37986
|
});
|
|
37914
37987
|
}
|
|
37915
|
-
if (cacheKey !== null) storeDeadCodeResultCache(
|
|
37988
|
+
if (cacheKey !== null && fileStatsSnapshot !== null) storeDeadCodeResultCache({
|
|
37989
|
+
cacheDirectory: resolveReactDoctorCacheDir(rootDirectory),
|
|
37990
|
+
cacheKey,
|
|
37991
|
+
rootDirectory,
|
|
37992
|
+
snapshotFileStats: fileStatsSnapshot,
|
|
37993
|
+
diagnostics
|
|
37994
|
+
});
|
|
37916
37995
|
return diagnostics;
|
|
37917
37996
|
};
|
|
37918
37997
|
const DEAD_CODE_RULE_KEY_PREFIX = `${DEAD_CODE_PLUGIN}/`;
|
|
@@ -39008,13 +39087,6 @@ const createFileLintCache = (cacheDirectory, rulesetHash) => {
|
|
|
39008
39087
|
}
|
|
39009
39088
|
};
|
|
39010
39089
|
};
|
|
39011
|
-
const hashFileContents = (filePath) => {
|
|
39012
|
-
try {
|
|
39013
|
-
return crypto.createHash("sha1").update(NFS.readFileSync(filePath)).digest("hex");
|
|
39014
|
-
} catch {
|
|
39015
|
-
return null;
|
|
39016
|
-
}
|
|
39017
|
-
};
|
|
39018
39090
|
const ABSENT_CONTENT_ANSWER = "absent";
|
|
39019
39091
|
/**
|
|
39020
39092
|
* Answers dependency probes for the sidecar lint cache — used both when
|
|
@@ -41155,6 +41227,20 @@ const writeCachedSocketBody = (cacheFile, body) => {
|
|
|
41155
41227
|
}));
|
|
41156
41228
|
} catch {}
|
|
41157
41229
|
};
|
|
41230
|
+
const pruneExpiredSocketCache = (cacheDirectory) => {
|
|
41231
|
+
try {
|
|
41232
|
+
const supplyChainCacheDirectory = Path.join(cacheDirectory, SUPPLY_CHAIN_CACHE_SUBDIR);
|
|
41233
|
+
const expiryThresholdMs = Date.now() - SUPPLY_CHAIN_CACHE_TTL_MS;
|
|
41234
|
+
for (const entryName of NFS.readdirSync(supplyChainCacheDirectory)) {
|
|
41235
|
+
const entryPath = Path.join(supplyChainCacheDirectory, entryName);
|
|
41236
|
+
try {
|
|
41237
|
+
if (NFS.statSync(entryPath).mtimeMs < expiryThresholdMs) NFS.rmSync(entryPath);
|
|
41238
|
+
} catch {
|
|
41239
|
+
continue;
|
|
41240
|
+
}
|
|
41241
|
+
}
|
|
41242
|
+
} catch {}
|
|
41243
|
+
};
|
|
41158
41244
|
const fetchSocketArtifact = (dependency, cacheDirectory) => tryPromise(async (signal) => {
|
|
41159
41245
|
const cacheFile = cacheDirectory === null ? null : supplyChainCacheFile(cacheDirectory, dependency);
|
|
41160
41246
|
if (cacheFile !== null) {
|
|
@@ -41282,6 +41368,7 @@ const checkSupplyChain = (input) => gen(function* () {
|
|
|
41282
41368
|
const dependencies = collectDependenciesToScore(readPackageJson(packageJsonPath), readPackageJsonText(packageJsonPath), options.includeDevDependencies);
|
|
41283
41369
|
if (dependencies.length === 0) return [];
|
|
41284
41370
|
const cacheDirectory = isSupplyChainCacheDisabled() ? null : resolveReactDoctorCacheDir(input.rootDirectory);
|
|
41371
|
+
if (cacheDirectory !== null) pruneExpiredSocketCache(cacheDirectory);
|
|
41285
41372
|
const artifacts = yield* forEach$1(dependencies, (dependency) => fetchSocketArtifact(dependency, cacheDirectory), { concurrency: 8 }).pipe(timeoutOption(input.totalTimeoutMs ?? 9e4), map$3((maybeArtifacts) => getOrElse$1(maybeArtifacts, () => [])));
|
|
41286
41373
|
const diagnostics = [];
|
|
41287
41374
|
for (let index = 0; index < dependencies.length; index += 1) {
|
|
@@ -42326,4 +42413,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
42326
42413
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
42327
42414
|
|
|
42328
42415
|
//# sourceMappingURL=index.js.map
|
|
42329
|
-
//# debugId=
|
|
42416
|
+
//# debugId=5c52dece-7b5e-5102-9381-7d05fa45734f
|
package/dist/lsp.js
CHANGED
|
@@ -32988,13 +32988,14 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
|
|
|
32988
32988
|
const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
|
|
32989
32989
|
const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
|
|
32990
32990
|
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
32991
|
-
const CORE_PACKAGE_VERSION = "0.
|
|
32991
|
+
const CORE_PACKAGE_VERSION = "0.7.0";
|
|
32992
32992
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
32993
32993
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
32994
32994
|
const SUPPLY_CHAIN_PLUGIN = "socket";
|
|
32995
32995
|
const SUPPLY_CHAIN_RULE = "low-supply-chain-score";
|
|
32996
32996
|
const SUPPLY_CHAIN_CATEGORY = "Security";
|
|
32997
32997
|
const SUPPLY_CHAIN_OVERLAP_TIMEOUT_MS = 9e4;
|
|
32998
|
+
const SUPPLY_CHAIN_CACHE_TTL_MS = 864e5;
|
|
32998
32999
|
const SUPPLY_CHAIN_CACHE_SUBDIR = "supply-chain";
|
|
32999
33000
|
const SUPPLY_CHAIN_IGNORED_PACKAGES = new Set(["next"]);
|
|
33000
33001
|
const hasIgnoredPathSegment = (relativePath) => relativePath.split(/[/\\]/).slice(0, -1).some((segment) => IGNORED_DIRECTORIES.has(segment));
|
|
@@ -37350,22 +37351,37 @@ const failOpenReadJson = (filePath, fallback) => {
|
|
|
37350
37351
|
return fallback;
|
|
37351
37352
|
}
|
|
37352
37353
|
};
|
|
37354
|
+
const hashFileContents = (filePath) => {
|
|
37355
|
+
try {
|
|
37356
|
+
return crypto.createHash("sha1").update(NFS.readFileSync(filePath)).digest("hex");
|
|
37357
|
+
} catch {
|
|
37358
|
+
return null;
|
|
37359
|
+
}
|
|
37360
|
+
};
|
|
37353
37361
|
const ANALYZED_FILE_EXTENSIONS = new Set(DEFAULT_EXTENSIONS);
|
|
37354
37362
|
const CORE_SIDE_MANIFEST_NAMES = ["knip.json", "deno.lock"];
|
|
37355
37363
|
const ANALYZED_MANIFEST_NAMES = new Set([...ANALYZED_MANIFEST_FILENAMES, ...CORE_SIDE_MANIFEST_NAMES]);
|
|
37356
37364
|
const isTsConfigLikeFile = (fileName) => (fileName.startsWith("tsconfig") || fileName.startsWith("jsconfig")) && fileName.endsWith(".json");
|
|
37357
37365
|
const isFingerprintedFile = (fileName) => ANALYZED_FILE_EXTENSIONS.has(Path.extname(fileName).toLowerCase()) || ANALYZED_MANIFEST_NAMES.has(fileName) || isTsConfigLikeFile(fileName);
|
|
37358
|
-
|
|
37359
|
-
|
|
37366
|
+
/**
|
|
37367
|
+
* Stat snapshot of every file the analysis reads, keyed by root-relative
|
|
37368
|
+
* `/`-separated path. Taken BEFORE the (long) analysis so a stored result is
|
|
37369
|
+
* verified against the tree it started from.
|
|
37370
|
+
*/
|
|
37371
|
+
const collectAnalyzedFileStats = (rootDirectory) => {
|
|
37372
|
+
const statByRelativePath = /* @__PURE__ */ new Map();
|
|
37360
37373
|
for (const { absolutePath, name } of walkSourceTreeFiles(rootDirectory)) {
|
|
37361
37374
|
if (!isFingerprintedFile(name)) continue;
|
|
37362
37375
|
try {
|
|
37363
37376
|
const fileStat = NFS.statSync(absolutePath);
|
|
37364
37377
|
const relativePath = Path.relative(rootDirectory, absolutePath).replace(/\\/g, "/");
|
|
37365
|
-
|
|
37378
|
+
statByRelativePath.set(relativePath, {
|
|
37379
|
+
mtimeMs: fileStat.mtimeMs,
|
|
37380
|
+
size: fileStat.size
|
|
37381
|
+
});
|
|
37366
37382
|
} catch {}
|
|
37367
37383
|
}
|
|
37368
|
-
return
|
|
37384
|
+
return statByRelativePath;
|
|
37369
37385
|
};
|
|
37370
37386
|
const bundledRequire$2 = createRequire(import.meta.url);
|
|
37371
37387
|
const resolveDeslopVersion = () => {
|
|
@@ -37377,14 +37393,13 @@ const resolveDeslopVersion = () => {
|
|
|
37377
37393
|
}
|
|
37378
37394
|
};
|
|
37379
37395
|
const computeDeadCodeCacheKey = (input) => crypto.createHash("sha1").update(JSON.stringify({
|
|
37380
|
-
schemaVersion:
|
|
37396
|
+
schemaVersion: 2,
|
|
37381
37397
|
coreVersion: input.coreVersion,
|
|
37382
37398
|
deslopVersion: resolveDeslopVersion(),
|
|
37383
37399
|
deslopJsModuleSpecifier: input.deslopJsModuleSpecifier,
|
|
37384
37400
|
entryPatterns: input.entryPatterns,
|
|
37385
37401
|
ignorePatterns: input.ignorePatterns,
|
|
37386
|
-
tsConfigFile: input.tsConfigPath === void 0 ? null : Path.relative(input.rootDirectory, input.tsConfigPath).replace(/\\/g, "/")
|
|
37387
|
-
files: collectAnalyzedFileFingerprints(input.rootDirectory)
|
|
37402
|
+
tsConfigFile: input.tsConfigPath === void 0 ? null : Path.relative(input.rootDirectory, input.tsConfigPath).replace(/\\/g, "/")
|
|
37388
37403
|
})).digest("hex");
|
|
37389
37404
|
const validateDiagnostic$2 = decodeUnknownSync(Diagnostic);
|
|
37390
37405
|
const decodeCachedDiagnostics = (raw) => {
|
|
@@ -37395,16 +37410,68 @@ const decodeCachedDiagnostics = (raw) => {
|
|
|
37395
37410
|
return null;
|
|
37396
37411
|
}
|
|
37397
37412
|
};
|
|
37398
|
-
const
|
|
37399
|
-
|
|
37400
|
-
|
|
37401
|
-
|
|
37413
|
+
const isPersistedFileIdentity = (value) => Array.isArray(value) && value.length === 3 && typeof value[0] === "number" && typeof value[1] === "number" && typeof value[2] === "string";
|
|
37414
|
+
const lookupDeadCodeResultCache = (input) => {
|
|
37415
|
+
const cacheFilePath = Path.join(input.cacheDirectory, DEAD_CODE_CACHE_FILENAME);
|
|
37416
|
+
const persisted = failOpenReadJson(cacheFilePath, null);
|
|
37417
|
+
if (persisted === null || !isRecord(persisted) || persisted.version !== 2 || persisted.key !== input.cacheKey || !isRecord(persisted.files) || !Array.isArray(persisted.diagnostics)) return null;
|
|
37418
|
+
const storedFileEntries = Object.entries(persisted.files);
|
|
37419
|
+
if (storedFileEntries.length !== input.currentFileStats.size) return null;
|
|
37420
|
+
const repairedFiles = {};
|
|
37421
|
+
let repairedCount = 0;
|
|
37422
|
+
for (const [relativePath, storedIdentity] of storedFileEntries) {
|
|
37423
|
+
if (!isPersistedFileIdentity(storedIdentity)) return null;
|
|
37424
|
+
const currentStat = input.currentFileStats.get(relativePath);
|
|
37425
|
+
if (currentStat === void 0) return null;
|
|
37426
|
+
const [storedMtimeMs, storedSize, storedContentHash] = storedIdentity;
|
|
37427
|
+
if (currentStat.mtimeMs === storedMtimeMs && currentStat.size === storedSize) {
|
|
37428
|
+
repairedFiles[relativePath] = storedIdentity;
|
|
37429
|
+
continue;
|
|
37430
|
+
}
|
|
37431
|
+
if (currentStat.size !== storedSize) return null;
|
|
37432
|
+
const currentContentHash = hashFileContents(Path.join(input.rootDirectory, relativePath));
|
|
37433
|
+
if (currentContentHash === null || currentContentHash !== storedContentHash) return null;
|
|
37434
|
+
repairedFiles[relativePath] = [
|
|
37435
|
+
currentStat.mtimeMs,
|
|
37436
|
+
currentStat.size,
|
|
37437
|
+
storedContentHash
|
|
37438
|
+
];
|
|
37439
|
+
repairedCount += 1;
|
|
37440
|
+
}
|
|
37441
|
+
const diagnostics = decodeCachedDiagnostics(persisted.diagnostics);
|
|
37442
|
+
if (diagnostics === null) return null;
|
|
37443
|
+
if (repairedCount > 0) atomicWriteJson(cacheFilePath, {
|
|
37444
|
+
version: 2,
|
|
37445
|
+
key: input.cacheKey,
|
|
37446
|
+
files: repairedFiles,
|
|
37447
|
+
diagnostics: persisted.diagnostics
|
|
37448
|
+
});
|
|
37449
|
+
return diagnostics;
|
|
37402
37450
|
};
|
|
37403
|
-
const storeDeadCodeResultCache = (
|
|
37404
|
-
|
|
37405
|
-
|
|
37406
|
-
|
|
37407
|
-
|
|
37451
|
+
const storeDeadCodeResultCache = (input) => {
|
|
37452
|
+
const persistedFiles = {};
|
|
37453
|
+
for (const [relativePath, snapshotStat] of input.snapshotFileStats) {
|
|
37454
|
+
const absolutePath = Path.join(input.rootDirectory, relativePath);
|
|
37455
|
+
const contentHash = hashFileContents(absolutePath);
|
|
37456
|
+
if (contentHash === null) return;
|
|
37457
|
+
let currentStat;
|
|
37458
|
+
try {
|
|
37459
|
+
currentStat = NFS.statSync(absolutePath);
|
|
37460
|
+
} catch {
|
|
37461
|
+
return;
|
|
37462
|
+
}
|
|
37463
|
+
if (currentStat.mtimeMs !== snapshotStat.mtimeMs || currentStat.size !== snapshotStat.size) return;
|
|
37464
|
+
persistedFiles[relativePath] = [
|
|
37465
|
+
snapshotStat.mtimeMs,
|
|
37466
|
+
snapshotStat.size,
|
|
37467
|
+
contentHash
|
|
37468
|
+
];
|
|
37469
|
+
}
|
|
37470
|
+
atomicWriteJson(Path.join(input.cacheDirectory, DEAD_CODE_CACHE_FILENAME), {
|
|
37471
|
+
version: 2,
|
|
37472
|
+
key: input.cacheKey,
|
|
37473
|
+
files: persistedFiles,
|
|
37474
|
+
diagnostics: input.diagnostics
|
|
37408
37475
|
});
|
|
37409
37476
|
};
|
|
37410
37477
|
const readSystemFacts = () => ({
|
|
@@ -37814,16 +37881,22 @@ const checkDeadCode = async (options) => {
|
|
|
37814
37881
|
const ignorePatterns = collectDeadCodeIgnorePatterns(rootDirectory);
|
|
37815
37882
|
const tsConfigPath = resolveTsConfigPath(rootDirectory);
|
|
37816
37883
|
const deslopJsModuleSpecifier = options.deslopJsModuleSpecifier ?? import.meta.resolve("deslop-js");
|
|
37817
|
-
const
|
|
37884
|
+
const fileStatsSnapshot = options.cacheEnabled ? collectAnalyzedFileStats(rootDirectory) : null;
|
|
37885
|
+
const cacheKey = fileStatsSnapshot === null ? null : computeDeadCodeCacheKey({
|
|
37818
37886
|
rootDirectory,
|
|
37819
37887
|
entryPatterns,
|
|
37820
37888
|
ignorePatterns,
|
|
37821
37889
|
tsConfigPath,
|
|
37822
37890
|
deslopJsModuleSpecifier,
|
|
37823
37891
|
coreVersion: CORE_PACKAGE_VERSION
|
|
37824
|
-
})
|
|
37825
|
-
if (cacheKey !== null) {
|
|
37826
|
-
const cachedDiagnostics = lookupDeadCodeResultCache(
|
|
37892
|
+
});
|
|
37893
|
+
if (cacheKey !== null && fileStatsSnapshot !== null) {
|
|
37894
|
+
const cachedDiagnostics = lookupDeadCodeResultCache({
|
|
37895
|
+
cacheDirectory: resolveReactDoctorCacheDir(rootDirectory),
|
|
37896
|
+
cacheKey,
|
|
37897
|
+
rootDirectory,
|
|
37898
|
+
currentFileStats: fileStatsSnapshot
|
|
37899
|
+
});
|
|
37827
37900
|
options.onCacheOutcome?.(cachedDiagnostics !== null);
|
|
37828
37901
|
if (cachedDiagnostics !== null) return [...cachedDiagnostics];
|
|
37829
37902
|
}
|
|
@@ -37897,7 +37970,13 @@ const checkDeadCode = async (options) => {
|
|
|
37897
37970
|
category: DEAD_CODE_CATEGORY
|
|
37898
37971
|
});
|
|
37899
37972
|
}
|
|
37900
|
-
if (cacheKey !== null) storeDeadCodeResultCache(
|
|
37973
|
+
if (cacheKey !== null && fileStatsSnapshot !== null) storeDeadCodeResultCache({
|
|
37974
|
+
cacheDirectory: resolveReactDoctorCacheDir(rootDirectory),
|
|
37975
|
+
cacheKey,
|
|
37976
|
+
rootDirectory,
|
|
37977
|
+
snapshotFileStats: fileStatsSnapshot,
|
|
37978
|
+
diagnostics
|
|
37979
|
+
});
|
|
37901
37980
|
return diagnostics;
|
|
37902
37981
|
};
|
|
37903
37982
|
const DEAD_CODE_RULE_KEY_PREFIX = `${DEAD_CODE_PLUGIN}/`;
|
|
@@ -38993,13 +39072,6 @@ const createFileLintCache = (cacheDirectory, rulesetHash) => {
|
|
|
38993
39072
|
}
|
|
38994
39073
|
};
|
|
38995
39074
|
};
|
|
38996
|
-
const hashFileContents = (filePath) => {
|
|
38997
|
-
try {
|
|
38998
|
-
return crypto.createHash("sha1").update(NFS.readFileSync(filePath)).digest("hex");
|
|
38999
|
-
} catch {
|
|
39000
|
-
return null;
|
|
39001
|
-
}
|
|
39002
|
-
};
|
|
39003
39075
|
const ABSENT_CONTENT_ANSWER = "absent";
|
|
39004
39076
|
/**
|
|
39005
39077
|
* Answers dependency probes for the sidecar lint cache — used both when
|
|
@@ -41140,6 +41212,20 @@ const writeCachedSocketBody = (cacheFile, body) => {
|
|
|
41140
41212
|
}));
|
|
41141
41213
|
} catch {}
|
|
41142
41214
|
};
|
|
41215
|
+
const pruneExpiredSocketCache = (cacheDirectory) => {
|
|
41216
|
+
try {
|
|
41217
|
+
const supplyChainCacheDirectory = Path.join(cacheDirectory, SUPPLY_CHAIN_CACHE_SUBDIR);
|
|
41218
|
+
const expiryThresholdMs = Date.now() - SUPPLY_CHAIN_CACHE_TTL_MS;
|
|
41219
|
+
for (const entryName of NFS.readdirSync(supplyChainCacheDirectory)) {
|
|
41220
|
+
const entryPath = Path.join(supplyChainCacheDirectory, entryName);
|
|
41221
|
+
try {
|
|
41222
|
+
if (NFS.statSync(entryPath).mtimeMs < expiryThresholdMs) NFS.rmSync(entryPath);
|
|
41223
|
+
} catch {
|
|
41224
|
+
continue;
|
|
41225
|
+
}
|
|
41226
|
+
}
|
|
41227
|
+
} catch {}
|
|
41228
|
+
};
|
|
41143
41229
|
const fetchSocketArtifact = (dependency, cacheDirectory) => tryPromise(async (signal) => {
|
|
41144
41230
|
const cacheFile = cacheDirectory === null ? null : supplyChainCacheFile(cacheDirectory, dependency);
|
|
41145
41231
|
if (cacheFile !== null) {
|
|
@@ -41267,6 +41353,7 @@ const checkSupplyChain = (input) => gen(function* () {
|
|
|
41267
41353
|
const dependencies = collectDependenciesToScore(readPackageJson(packageJsonPath), readPackageJsonText(packageJsonPath), options.includeDevDependencies);
|
|
41268
41354
|
if (dependencies.length === 0) return [];
|
|
41269
41355
|
const cacheDirectory = isSupplyChainCacheDisabled() ? null : resolveReactDoctorCacheDir(input.rootDirectory);
|
|
41356
|
+
if (cacheDirectory !== null) pruneExpiredSocketCache(cacheDirectory);
|
|
41270
41357
|
const artifacts = yield* forEach$1(dependencies, (dependency) => fetchSocketArtifact(dependency, cacheDirectory), { concurrency: 8 }).pipe(timeoutOption(input.totalTimeoutMs ?? 9e4), map$3((maybeArtifacts) => getOrElse$1(maybeArtifacts, () => [])));
|
|
41271
41358
|
const diagnostics = [];
|
|
41272
41359
|
for (let index = 0; index < dependencies.length; index += 1) {
|
|
@@ -41983,11 +42070,9 @@ const computeConfigFingerprint = (projectDirectory, version) => {
|
|
|
41983
42070
|
const parts = [`v=${version}`];
|
|
41984
42071
|
let directory = projectDirectory;
|
|
41985
42072
|
for (;;) {
|
|
41986
|
-
for (const filename of CONFIG_FINGERPRINT_FILENAMES)
|
|
41987
|
-
const
|
|
41988
|
-
parts.push(`${directory}/${filename}=${
|
|
41989
|
-
} catch {
|
|
41990
|
-
continue;
|
|
42073
|
+
for (const filename of CONFIG_FINGERPRINT_FILENAMES) {
|
|
42074
|
+
const contentHash = hashFileContents(path.join(directory, filename));
|
|
42075
|
+
if (contentHash !== null) parts.push(`${directory}/${filename}=${contentHash}`);
|
|
41991
42076
|
}
|
|
41992
42077
|
const parent = path.dirname(directory);
|
|
41993
42078
|
if (parent === directory) break;
|
|
@@ -42000,7 +42085,7 @@ const computeConfigFingerprint = (projectDirectory, version) => {
|
|
|
42000
42085
|
/** Display name used in client-facing messages and progress titles. */
|
|
42001
42086
|
const SERVER_DISPLAY_NAME = "React Doctor";
|
|
42002
42087
|
/** Server version reported in `serverInfo`; injected at build, `dev` from source. */
|
|
42003
|
-
const SERVER_VERSION = "0.
|
|
42088
|
+
const SERVER_VERSION = "0.7.0";
|
|
42004
42089
|
/** `Diagnostic.source` shown next to every published diagnostic. */
|
|
42005
42090
|
const DIAGNOSTIC_SOURCE = "react-doctor";
|
|
42006
42091
|
/**
|
|
@@ -44050,5 +44135,5 @@ const startLanguageServer = () => {
|
|
|
44050
44135
|
};
|
|
44051
44136
|
//#endregion
|
|
44052
44137
|
export { startLanguageServer };
|
|
44053
|
-
!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]="
|
|
44054
|
-
//# debugId=
|
|
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.
|
|
3
|
+
"version": "0.7.0-dev.574cba6",
|
|
4
4
|
"description": "Your agent writes bad React. This catches it",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"vscode-languageserver-textdocument": "^1.0.12",
|
|
66
66
|
"vscode-uri": "^3.1.0",
|
|
67
67
|
"yaml": "^2.9.0",
|
|
68
|
-
"
|
|
69
|
-
"
|
|
68
|
+
"deslop-js": "0.7.0",
|
|
69
|
+
"oxlint-plugin-react-doctor": "0.7.0-dev.574cba6"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/babel__code-frame": "^7.27.0",
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
"@xterm/headless": "^6.0.0",
|
|
75
75
|
"commander": "^14.0.3",
|
|
76
76
|
"ora": "^9.4.0",
|
|
77
|
-
"@react-doctor/api": "0.
|
|
78
|
-
"@react-doctor/core": "0.
|
|
79
|
-
"@react-doctor/language-server": "0.
|
|
77
|
+
"@react-doctor/api": "0.7.0",
|
|
78
|
+
"@react-doctor/core": "0.7.0",
|
|
79
|
+
"@react-doctor/language-server": "0.7.0"
|
|
80
80
|
},
|
|
81
81
|
"engines": {
|
|
82
82
|
"node": "^20.19.0 || >=22.13.0"
|