react-doctor 0.6.3-dev.bdf8074 → 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 +319 -737
- package/dist/index.d.ts +0 -8
- package/dist/index.js +42 -379
- package/dist/lsp.js +42 -379
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -9743,14 +9743,6 @@ interface InspectResult {
|
|
|
9743
9743
|
*/
|
|
9744
9744
|
lintCacheHitFileCount?: number | null;
|
|
9745
9745
|
lintCacheTotalFileCount?: number | null;
|
|
9746
|
-
/**
|
|
9747
|
-
* Sidecar lint cache outcome: cache-hit files whose cross-file diagnostics
|
|
9748
|
-
* replayed from the sidecar store, and the hits considered. Both absent
|
|
9749
|
-
* when the sidecar cache was off or bypassed. The CLI projects these onto
|
|
9750
|
-
* the Sentry wide event as `lint.sidecarReplayRatio`.
|
|
9751
|
-
*/
|
|
9752
|
-
lintSidecarReplayedFileCount?: number | null;
|
|
9753
|
-
lintSidecarTotalFileCount?: number | null;
|
|
9754
9746
|
/**
|
|
9755
9747
|
* Dead-code result cache outcome: `true` when the pass replayed a cached
|
|
9756
9748
|
* result (the analysis never ran), `false` on a fresh analysis. Absent when
|
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";
|
|
@@ -9,7 +9,7 @@ import path from "node:path";
|
|
|
9
9
|
import * as NodeChildProcess from "node:child_process";
|
|
10
10
|
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
11
11
|
import * as ts from "typescript";
|
|
12
|
-
import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS,
|
|
12
|
+
import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
|
|
13
13
|
import * as OS from "node:os";
|
|
14
14
|
import os from "node:os";
|
|
15
15
|
import { parseJSON5 } from "confbox";
|
|
@@ -32928,7 +32928,6 @@ const SOCKET_PACKAGE_PAGE_BASE = "https://socket.dev/npm/package";
|
|
|
32928
32928
|
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
|
-
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
32932
32931
|
const CORE_PACKAGE_VERSION = "0.6.3";
|
|
32933
32932
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
32934
32933
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
@@ -35619,29 +35618,6 @@ var PerFileLintCacheEnabled = class extends Reference("react-doctor/PerFileLintC
|
|
|
35619
35618
|
return true;
|
|
35620
35619
|
} }) {};
|
|
35621
35620
|
/**
|
|
35622
|
-
* Whether the sidecar lint cache (`runners/oxlint/sidecar-lint-cache.ts`) is
|
|
35623
|
-
* active. Defaults ON — warm rescans replay the cross-file rules' cached
|
|
35624
|
-
* diagnostics for every file whose dependency fingerprint (the probe set the
|
|
35625
|
-
* plugin's collectors recorded) still matches the tree, and re-lint only the
|
|
35626
|
-
* rest. Only reachable when the per-file lint cache itself is on (the
|
|
35627
|
-
* sidecar covers its cache hits), so `REACT_DOCTOR_NO_CACHE` /
|
|
35628
|
-
* `REACT_DOCTOR_NO_FILE_CACHE` implicitly disable it too. Opt-OUT knobs:
|
|
35629
|
-
*
|
|
35630
|
-
* - `REACT_DOCTOR_NO_CACHE` — the global off-switch.
|
|
35631
|
-
* - `REACT_DOCTOR_NO_SIDECAR_CACHE` — granular rollback hatch: keep the
|
|
35632
|
-
* per-file cache but run the always-fresh sidecar over every hit
|
|
35633
|
-
* (the pre-cache behavior).
|
|
35634
|
-
*
|
|
35635
|
-
* Tests override via `Layer.succeed(SidecarLintCacheEnabled, false)`.
|
|
35636
|
-
*/
|
|
35637
|
-
var SidecarLintCacheEnabled = class extends Reference("react-doctor/SidecarLintCacheEnabled", { defaultValue: () => {
|
|
35638
|
-
const noCache = process.env["REACT_DOCTOR_NO_CACHE"]?.toLowerCase() ?? "";
|
|
35639
|
-
const noSidecarCache = process.env["REACT_DOCTOR_NO_SIDECAR_CACHE"]?.toLowerCase() ?? "";
|
|
35640
|
-
if (CACHE_DISABLED_VALUES.has(noCache)) return false;
|
|
35641
|
-
if (CACHE_DISABLED_VALUES.has(noSidecarCache)) return false;
|
|
35642
|
-
return true;
|
|
35643
|
-
} }) {};
|
|
35644
|
-
/**
|
|
35645
35621
|
* Whether the whole-project dead-code result cache
|
|
35646
35622
|
* (`dead-code/dead-code-result-cache.ts`) is active. Defaults ON — a rescan
|
|
35647
35623
|
* whose inputs (source tree, manifests, configs, analyzer version) are
|
|
@@ -37401,10 +37377,10 @@ const computeDeadCodeCacheKey = (input) => crypto.createHash("sha1").update(JSON
|
|
|
37401
37377
|
tsConfigFile: input.tsConfigPath === void 0 ? null : Path.relative(input.rootDirectory, input.tsConfigPath).replace(/\\/g, "/"),
|
|
37402
37378
|
files: collectAnalyzedFileFingerprints(input.rootDirectory)
|
|
37403
37379
|
})).digest("hex");
|
|
37404
|
-
const validateDiagnostic$
|
|
37380
|
+
const validateDiagnostic$1 = decodeUnknownSync(Diagnostic);
|
|
37405
37381
|
const decodeCachedDiagnostics = (raw) => {
|
|
37406
37382
|
try {
|
|
37407
|
-
for (const entry of raw) validateDiagnostic$
|
|
37383
|
+
for (const entry of raw) validateDiagnostic$1(entry);
|
|
37408
37384
|
return raw;
|
|
37409
37385
|
} catch {
|
|
37410
37386
|
return null;
|
|
@@ -38894,7 +38870,7 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
|
|
|
38894
38870
|
}
|
|
38895
38871
|
return enabled;
|
|
38896
38872
|
};
|
|
38897
|
-
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection
|
|
38873
|
+
const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection }) => {
|
|
38898
38874
|
const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" ? null : resolveReactHooksJsPlugin(project.hasReactCompiler, customRulesOnly);
|
|
38899
38875
|
const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
|
|
38900
38876
|
const jsPlugins = [];
|
|
@@ -38906,7 +38882,6 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
38906
38882
|
if (!rule) continue;
|
|
38907
38883
|
if (ruleSelection === "cacheable" && CROSS_FILE_RULE_IDS.has(registryEntry.id)) continue;
|
|
38908
38884
|
if (ruleSelection === "sidecar" && !CROSS_FILE_RULE_IDS.has(registryEntry.id)) continue;
|
|
38909
|
-
if (ruleSelection === "sidecar" && sidecarRuleIdFilter !== void 0 && !sidecarRuleIdFilter.has(registryEntry.id)) continue;
|
|
38910
38885
|
if (rule.scan !== void 0) continue;
|
|
38911
38886
|
if (customRulesOnly && registryEntry.originallyExternal) continue;
|
|
38912
38887
|
if (rule.framework !== "global" && !rule.requires) continue;
|
|
@@ -38951,23 +38926,23 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
|
|
|
38951
38926
|
}
|
|
38952
38927
|
};
|
|
38953
38928
|
};
|
|
38954
|
-
const validateDiagnostic
|
|
38929
|
+
const validateDiagnostic = decodeUnknownSync(Diagnostic);
|
|
38955
38930
|
const decodeFileDiagnostics = (raw) => {
|
|
38956
38931
|
if (!Array.isArray(raw)) return null;
|
|
38957
38932
|
try {
|
|
38958
|
-
for (const entry of raw) validateDiagnostic
|
|
38933
|
+
for (const entry of raw) validateDiagnostic(entry);
|
|
38959
38934
|
return raw;
|
|
38960
38935
|
} catch {
|
|
38961
38936
|
return null;
|
|
38962
38937
|
}
|
|
38963
38938
|
};
|
|
38964
|
-
const emptyCache
|
|
38939
|
+
const emptyCache = () => ({
|
|
38965
38940
|
version: 1,
|
|
38966
38941
|
rulesets: {}
|
|
38967
38942
|
});
|
|
38968
|
-
const loadRulesetEntries
|
|
38943
|
+
const loadRulesetEntries = (cacheFilePath, rulesetHash) => {
|
|
38969
38944
|
const entries = /* @__PURE__ */ new Map();
|
|
38970
|
-
const persisted = failOpenReadJson(cacheFilePath, emptyCache
|
|
38945
|
+
const persisted = failOpenReadJson(cacheFilePath, emptyCache());
|
|
38971
38946
|
if (persisted.version !== 1 || !isRecord(persisted.rulesets)) return entries;
|
|
38972
38947
|
const bucket = persisted.rulesets[rulesetHash];
|
|
38973
38948
|
if (!isRecord(bucket) || !isRecord(bucket.files)) return entries;
|
|
@@ -38979,156 +38954,20 @@ const loadRulesetEntries$1 = (cacheFilePath, rulesetHash) => {
|
|
|
38979
38954
|
};
|
|
38980
38955
|
const createFileLintCache = (cacheDirectory, rulesetHash) => {
|
|
38981
38956
|
const cacheFilePath = Path.join(cacheDirectory, FILE_LINT_CACHE_FILENAME);
|
|
38982
|
-
const entries = loadRulesetEntries
|
|
38957
|
+
const entries = loadRulesetEntries(cacheFilePath, rulesetHash);
|
|
38983
38958
|
return {
|
|
38984
38959
|
lookup: (fileKey) => entries.get(fileKey) ?? null,
|
|
38985
38960
|
store: (fileKey, diagnostics) => {
|
|
38986
38961
|
entries.delete(fileKey);
|
|
38987
38962
|
entries.set(fileKey, diagnostics);
|
|
38988
38963
|
},
|
|
38989
|
-
persist: () => {
|
|
38990
|
-
const onDisk = failOpenReadJson(cacheFilePath, emptyCache$1());
|
|
38991
|
-
const rulesets = onDisk.version === 1 && isRecord(onDisk.rulesets) ? { ...onDisk.rulesets } : {};
|
|
38992
|
-
const existingBucket = rulesets[rulesetHash];
|
|
38993
|
-
const existingFiles = isRecord(existingBucket) && isRecord(existingBucket.files) ? existingBucket.files : {};
|
|
38994
|
-
const ourFiles = {};
|
|
38995
|
-
for (const [fileKey, diagnostics] of entries) ourFiles[fileKey] = diagnostics;
|
|
38996
|
-
const cappedEntries = Object.entries({
|
|
38997
|
-
...existingFiles,
|
|
38998
|
-
...ourFiles
|
|
38999
|
-
}).slice(-FILE_LINT_CACHE_MAX_FILE_COUNT);
|
|
39000
|
-
rulesets[rulesetHash] = {
|
|
39001
|
-
updatedAtMs: Date.now(),
|
|
39002
|
-
files: Object.fromEntries(cappedEntries)
|
|
39003
|
-
};
|
|
39004
|
-
atomicWriteJson(cacheFilePath, {
|
|
39005
|
-
version: 1,
|
|
39006
|
-
rulesets: Object.fromEntries(Object.entries(rulesets).filter(([, bucket]) => isRecord(bucket) && typeof bucket.updatedAtMs === "number").sort(([, first], [, second]) => second.updatedAtMs - first.updatedAtMs).slice(0, 8))
|
|
39007
|
-
});
|
|
39008
|
-
}
|
|
39009
|
-
};
|
|
39010
|
-
};
|
|
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
|
-
const ABSENT_CONTENT_ANSWER = "absent";
|
|
39019
|
-
/**
|
|
39020
|
-
* Answers dependency probes for the sidecar lint cache — used both when
|
|
39021
|
-
* STORING an entry (turn the collector's probe paths into answers) and when
|
|
39022
|
-
* VERIFYING one (re-answer each stored probe against the current tree).
|
|
39023
|
-
* Store and verify must agree exactly, so both go through this one resolver.
|
|
39024
|
-
*
|
|
39025
|
-
* - `content` — SHA-1 of the file's bytes, `"absent"` when unreadable
|
|
39026
|
-
* (missing, a directory, permission failure). Source files reuse the
|
|
39027
|
-
* hashes the cache-partition loop already computed
|
|
39028
|
-
* (`contentHashByRelativePath`); everything else (package.json,
|
|
39029
|
-
* tsconfig, ignored files) is hashed on demand.
|
|
39030
|
-
* - `exists` — the existence class a module-resolution candidate probe
|
|
39031
|
-
* sees: `"file"`, `"dir"`, or `"none"` (missing or an exotic entry —
|
|
39032
|
-
* `statSync` follows symlinks, matching the resolvers).
|
|
39033
|
-
*
|
|
39034
|
-
* Answers are memoized per scan: the filesystem is frozen for the run, and
|
|
39035
|
-
* hot dependency paths (a barrel imported by hundreds of files, the shared
|
|
39036
|
-
* tsconfig chain) repeat across many files' probe sets.
|
|
39037
|
-
*/
|
|
39038
|
-
const createSidecarProbeAnswerResolver = (input) => {
|
|
39039
|
-
const contentAnswerByPath = /* @__PURE__ */ new Map();
|
|
39040
|
-
const existsAnswerByPath = /* @__PURE__ */ new Map();
|
|
39041
|
-
const toRelativePath = (absolutePath) => Path.relative(input.rootDirectory, absolutePath).replaceAll("\\", "/");
|
|
39042
|
-
const contentAnswer = (relativePath) => {
|
|
39043
|
-
const memoized = contentAnswerByPath.get(relativePath);
|
|
39044
|
-
if (memoized !== void 0) return memoized;
|
|
39045
|
-
const answer = input.contentHashByRelativePath.get(relativePath) ?? hashFileContents(Path.resolve(input.rootDirectory, relativePath)) ?? ABSENT_CONTENT_ANSWER;
|
|
39046
|
-
contentAnswerByPath.set(relativePath, answer);
|
|
39047
|
-
return answer;
|
|
39048
|
-
};
|
|
39049
|
-
const existsAnswer = (relativePath) => {
|
|
39050
|
-
const memoized = existsAnswerByPath.get(relativePath);
|
|
39051
|
-
if (memoized !== void 0) return memoized;
|
|
39052
|
-
let answer;
|
|
39053
|
-
try {
|
|
39054
|
-
const stat = NFS.statSync(Path.resolve(input.rootDirectory, relativePath));
|
|
39055
|
-
answer = stat.isFile() ? "file" : stat.isDirectory() ? "dir" : "none";
|
|
39056
|
-
} catch {
|
|
39057
|
-
answer = "none";
|
|
39058
|
-
}
|
|
39059
|
-
existsAnswerByPath.set(relativePath, answer);
|
|
39060
|
-
return answer;
|
|
39061
|
-
};
|
|
39062
|
-
return {
|
|
39063
|
-
answerFor: (kind, relativePath) => kind === "content" ? contentAnswer(relativePath) : existsAnswer(relativePath),
|
|
39064
|
-
toRelativePath
|
|
39065
|
-
};
|
|
39066
|
-
};
|
|
39067
|
-
const validateDiagnostic = decodeUnknownSync(Diagnostic);
|
|
39068
|
-
const isProbeKind = (value) => value === "content" || value === "exists";
|
|
39069
|
-
const decodeSidecarFileEntry = (raw) => {
|
|
39070
|
-
if (!isRecord(raw) || !Array.isArray(raw.probes) || !Array.isArray(raw.diagnostics)) return null;
|
|
39071
|
-
const probes = [];
|
|
39072
|
-
for (const rawProbe of raw.probes) {
|
|
39073
|
-
if (!Array.isArray(rawProbe) || rawProbe.length !== 3) return null;
|
|
39074
|
-
const [kind, probePath, answer] = rawProbe;
|
|
39075
|
-
if (!isProbeKind(kind) || typeof probePath !== "string" || typeof answer !== "string") return null;
|
|
39076
|
-
probes.push({
|
|
39077
|
-
kind,
|
|
39078
|
-
path: probePath,
|
|
39079
|
-
answer
|
|
39080
|
-
});
|
|
39081
|
-
}
|
|
39082
|
-
try {
|
|
39083
|
-
for (const entry of raw.diagnostics) validateDiagnostic(entry);
|
|
39084
|
-
} catch {
|
|
39085
|
-
return null;
|
|
39086
|
-
}
|
|
39087
|
-
return {
|
|
39088
|
-
probes,
|
|
39089
|
-
diagnostics: raw.diagnostics
|
|
39090
|
-
};
|
|
39091
|
-
};
|
|
39092
|
-
const encodeSidecarFileEntry = (entry) => ({
|
|
39093
|
-
probes: entry.probes.map((probe) => [
|
|
39094
|
-
probe.kind,
|
|
39095
|
-
probe.path,
|
|
39096
|
-
probe.answer
|
|
39097
|
-
]),
|
|
39098
|
-
diagnostics: entry.diagnostics
|
|
39099
|
-
});
|
|
39100
|
-
const emptyCache = () => ({
|
|
39101
|
-
version: 1,
|
|
39102
|
-
rulesets: {}
|
|
39103
|
-
});
|
|
39104
|
-
const loadRulesetEntries = (cacheFilePath, rulesetHash) => {
|
|
39105
|
-
const entries = /* @__PURE__ */ new Map();
|
|
39106
|
-
const persisted = failOpenReadJson(cacheFilePath, emptyCache());
|
|
39107
|
-
if (persisted.version !== 1 || !isRecord(persisted.rulesets)) return entries;
|
|
39108
|
-
const bucket = persisted.rulesets[rulesetHash];
|
|
39109
|
-
if (!isRecord(bucket) || !isRecord(bucket.files)) return entries;
|
|
39110
|
-
for (const [fileKey, rawEntry] of Object.entries(bucket.files)) {
|
|
39111
|
-
const decoded = decodeSidecarFileEntry(rawEntry);
|
|
39112
|
-
if (decoded !== null) entries.set(fileKey, decoded);
|
|
39113
|
-
}
|
|
39114
|
-
return entries;
|
|
39115
|
-
};
|
|
39116
|
-
const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
|
|
39117
|
-
const cacheFilePath = Path.join(cacheDirectory, SIDECAR_LINT_CACHE_FILENAME);
|
|
39118
|
-
const entries = loadRulesetEntries(cacheFilePath, rulesetHash);
|
|
39119
|
-
return {
|
|
39120
|
-
lookup: (fileKey) => entries.get(fileKey) ?? null,
|
|
39121
|
-
store: (fileKey, entry) => {
|
|
39122
|
-
entries.delete(fileKey);
|
|
39123
|
-
entries.set(fileKey, entry);
|
|
39124
|
-
},
|
|
39125
38964
|
persist: () => {
|
|
39126
38965
|
const onDisk = failOpenReadJson(cacheFilePath, emptyCache());
|
|
39127
38966
|
const rulesets = onDisk.version === 1 && isRecord(onDisk.rulesets) ? { ...onDisk.rulesets } : {};
|
|
39128
38967
|
const existingBucket = rulesets[rulesetHash];
|
|
39129
38968
|
const existingFiles = isRecord(existingBucket) && isRecord(existingBucket.files) ? existingBucket.files : {};
|
|
39130
38969
|
const ourFiles = {};
|
|
39131
|
-
for (const [fileKey,
|
|
38970
|
+
for (const [fileKey, diagnostics] of entries) ourFiles[fileKey] = diagnostics;
|
|
39132
38971
|
const cappedEntries = Object.entries({
|
|
39133
38972
|
...existingFiles,
|
|
39134
38973
|
...ourFiles
|
|
@@ -40143,6 +39982,13 @@ const validateRuleRegistration = () => {
|
|
|
40143
39982
|
].filter((entry) => entry !== null).join("; ");
|
|
40144
39983
|
console.warn(`[react-doctor] rule-registration drift: ${detail}`);
|
|
40145
39984
|
};
|
|
39985
|
+
const hashFileContents = (filePath) => {
|
|
39986
|
+
try {
|
|
39987
|
+
return crypto.createHash("sha1").update(NFS.readFileSync(filePath)).digest("hex");
|
|
39988
|
+
} catch {
|
|
39989
|
+
return null;
|
|
39990
|
+
}
|
|
39991
|
+
};
|
|
40146
39992
|
/**
|
|
40147
39993
|
* Balanced LPT (longest-processing-time-first) lint batch planner. Where
|
|
40148
39994
|
* `batchIncludePaths` greedily fills 100-file batches and leaves a small
|
|
@@ -40224,106 +40070,6 @@ const writeOxlintConfig = (configPath, configToWrite) => {
|
|
|
40224
40070
|
NFS.closeSync(fileHandle);
|
|
40225
40071
|
}
|
|
40226
40072
|
};
|
|
40227
|
-
/**
|
|
40228
|
-
* Attributes diagnostics back to the file that produced them by the
|
|
40229
|
-
* normalized path oxlint echoes. Returns `null` when ANY diagnostic can't be
|
|
40230
|
-
* attributed — the path forms don't align, so the caller must skip its cache
|
|
40231
|
-
* store rather than risk caching a wrong empty result for a file that
|
|
40232
|
-
* actually had diagnostics.
|
|
40233
|
-
*/
|
|
40234
|
-
const attributeDiagnosticsToFiles = (diagnostics, files) => {
|
|
40235
|
-
const fileByNormalizedPath = /* @__PURE__ */ new Map();
|
|
40236
|
-
for (const file of files) fileByNormalizedPath.set(file.replaceAll("\\", "/"), file);
|
|
40237
|
-
const diagnosticsByFile = /* @__PURE__ */ new Map();
|
|
40238
|
-
for (const diagnostic of diagnostics) {
|
|
40239
|
-
const file = fileByNormalizedPath.get(diagnostic.filePath);
|
|
40240
|
-
if (file === void 0) return null;
|
|
40241
|
-
const fileDiagnostics = diagnosticsByFile.get(file) ?? [];
|
|
40242
|
-
fileDiagnostics.push(diagnostic);
|
|
40243
|
-
diagnosticsByFile.set(file, fileDiagnostics);
|
|
40244
|
-
}
|
|
40245
|
-
return diagnosticsByFile;
|
|
40246
|
-
};
|
|
40247
|
-
/**
|
|
40248
|
-
* Collects each file's cross-file dependency probes (via the plugin's
|
|
40249
|
-
* collectors) with their current answers. Fail-open per file: an unreadable /
|
|
40250
|
-
* unparseable / collector-failing file maps to `null` (no entry stored — it
|
|
40251
|
-
* re-lints next scan). The filesystem is frozen for the scan, so this can run
|
|
40252
|
-
* CONCURRENTLY with an oxlint child-process await — the caller starts it
|
|
40253
|
-
* unawaited before a lint pass and awaits it at store time, hiding the
|
|
40254
|
-
* in-process parse + resolution cost under the subprocess wait. The loop
|
|
40255
|
-
* yields on the cooperative time budget so the child's stdout handling (and
|
|
40256
|
-
* sibling fibers) keep flowing; each per-file collection is synchronous, so
|
|
40257
|
-
* the module-level probe recorder never sees interleaved use. Never rejects.
|
|
40258
|
-
*/
|
|
40259
|
-
const collectSidecarProbesForFiles = async (input) => {
|
|
40260
|
-
const buildProbes = (file) => {
|
|
40261
|
-
const absoluteFilePath = Path.resolve(input.rootDirectory, file);
|
|
40262
|
-
let trace;
|
|
40263
|
-
try {
|
|
40264
|
-
trace = collectCrossFileDependencyProbes({
|
|
40265
|
-
absoluteFilePath,
|
|
40266
|
-
sourceText: NFS.readFileSync(absoluteFilePath, "utf8"),
|
|
40267
|
-
ruleIds: input.boundedSidecarRuleIds
|
|
40268
|
-
});
|
|
40269
|
-
} catch {
|
|
40270
|
-
return null;
|
|
40271
|
-
}
|
|
40272
|
-
if (trace === null) return null;
|
|
40273
|
-
const probes = [];
|
|
40274
|
-
for (const contentPath of trace.contentPaths) {
|
|
40275
|
-
const relativePath = input.probeAnswers.toRelativePath(contentPath);
|
|
40276
|
-
probes.push({
|
|
40277
|
-
kind: "content",
|
|
40278
|
-
path: relativePath,
|
|
40279
|
-
answer: input.probeAnswers.answerFor("content", relativePath)
|
|
40280
|
-
});
|
|
40281
|
-
}
|
|
40282
|
-
for (const existencePath of trace.existencePaths) {
|
|
40283
|
-
const relativePath = input.probeAnswers.toRelativePath(existencePath);
|
|
40284
|
-
probes.push({
|
|
40285
|
-
kind: "exists",
|
|
40286
|
-
path: relativePath,
|
|
40287
|
-
answer: input.probeAnswers.answerFor("exists", relativePath)
|
|
40288
|
-
});
|
|
40289
|
-
}
|
|
40290
|
-
return probes;
|
|
40291
|
-
};
|
|
40292
|
-
const probesByFile = /* @__PURE__ */ new Map();
|
|
40293
|
-
let collectSliceStartedAt = performance.now();
|
|
40294
|
-
for (const file of input.files) {
|
|
40295
|
-
probesByFile.set(file, buildProbes(file));
|
|
40296
|
-
if (performance.now() - collectSliceStartedAt >= 12) {
|
|
40297
|
-
await yieldToEventLoop();
|
|
40298
|
-
collectSliceStartedAt = performance.now();
|
|
40299
|
-
}
|
|
40300
|
-
}
|
|
40301
|
-
return probesByFile;
|
|
40302
|
-
};
|
|
40303
|
-
/**
|
|
40304
|
-
* Stores each freshly-linted file's probe set + cross-file diagnostics so
|
|
40305
|
-
* the next scan can replay instead of re-linting.
|
|
40306
|
-
*/
|
|
40307
|
-
const storeSidecarEntries = (input) => {
|
|
40308
|
-
let didStoreAnyEntry = false;
|
|
40309
|
-
for (const pass of input.storablePasses) {
|
|
40310
|
-
if (!pass.isTrusted) continue;
|
|
40311
|
-
const diagnosticsByFile = attributeDiagnosticsToFiles(pass.diagnostics, pass.files);
|
|
40312
|
-
if (diagnosticsByFile === null) continue;
|
|
40313
|
-
for (const file of pass.files) {
|
|
40314
|
-
const cacheKey = input.cacheKeyByFile.get(file);
|
|
40315
|
-
if (cacheKey === void 0) continue;
|
|
40316
|
-
const probes = pass.probesByFile.get(file);
|
|
40317
|
-
if (probes === void 0 || probes === null) continue;
|
|
40318
|
-
input.sidecarCache.store(cacheKey, {
|
|
40319
|
-
probes,
|
|
40320
|
-
diagnostics: diagnosticsByFile.get(file) ?? []
|
|
40321
|
-
});
|
|
40322
|
-
didStoreAnyEntry = true;
|
|
40323
|
-
}
|
|
40324
|
-
}
|
|
40325
|
-
if (didStoreAnyEntry) input.sidecarCache.persist();
|
|
40326
|
-
};
|
|
40327
40073
|
const REACT_HOOKS_JS_DROP_PREFIX = "React Compiler rules (react-hooks-js/*) skipped — eslint-plugin-react-hooks failed to load in this environment";
|
|
40328
40074
|
/**
|
|
40329
40075
|
* Detects an oxlint config-load crash caused by the optional
|
|
@@ -40365,7 +40111,7 @@ const reactHooksJsPluginDropNote = (error) => {
|
|
|
40365
40111
|
* 6. always restore disable directives + clean up the temp dir
|
|
40366
40112
|
*/
|
|
40367
40113
|
const runOxlint = async (options) => {
|
|
40368
|
-
const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure, perFileLintCacheEnabled = false,
|
|
40114
|
+
const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure, perFileLintCacheEnabled = false, onCacheStats, spawnTimeoutMs, outputMaxBytes, lintBatchOrdering = "cost" } = options;
|
|
40369
40115
|
const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
40370
40116
|
const severityControls = buildRuleSeverityControls(userConfig);
|
|
40371
40117
|
validateRuleRegistration();
|
|
@@ -40383,8 +40129,7 @@ const runOxlint = async (options) => {
|
|
|
40383
40129
|
severityControls,
|
|
40384
40130
|
userPlugins,
|
|
40385
40131
|
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
|
|
40386
|
-
ruleSelection: overrides.ruleSelection
|
|
40387
|
-
sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
|
|
40132
|
+
ruleSelection: overrides.ruleSelection
|
|
40388
40133
|
});
|
|
40389
40134
|
const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
|
|
40390
40135
|
const configDirectory = NFS.mkdtempSync(Path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
|
|
@@ -40487,18 +40232,15 @@ const runOxlint = async (options) => {
|
|
|
40487
40232
|
});
|
|
40488
40233
|
const cache = createFileLintCache(resolveReactDoctorCacheDir(rootDirectory), rulesetHash);
|
|
40489
40234
|
const cacheKeyByFile = /* @__PURE__ */ new Map();
|
|
40490
|
-
const contentHashByRelativePath = /* @__PURE__ */ new Map();
|
|
40491
40235
|
const missFiles = [];
|
|
40492
40236
|
const replayedDiagnostics = [];
|
|
40493
40237
|
let hashSliceStartedAt = performance.now();
|
|
40494
40238
|
for (const candidateFile of candidateFiles) {
|
|
40495
|
-
const
|
|
40496
|
-
const contentHash = hashFileContents(absoluteCandidatePath);
|
|
40239
|
+
const contentHash = hashFileContents(Path.resolve(rootDirectory, candidateFile));
|
|
40497
40240
|
if (contentHash === null) {
|
|
40498
40241
|
missFiles.push(candidateFile);
|
|
40499
40242
|
continue;
|
|
40500
40243
|
}
|
|
40501
|
-
contentHashByRelativePath.set(Path.relative(rootDirectory, absoluteCandidatePath).replaceAll("\\", "/"), contentHash);
|
|
40502
40244
|
const cacheKey = `${candidateFile.replaceAll("\\", "/")}\u0000${contentHash}`;
|
|
40503
40245
|
cacheKeyByFile.set(candidateFile, cacheKey);
|
|
40504
40246
|
const cachedDiagnostics = cache.lookup(cacheKey);
|
|
@@ -40510,111 +40252,43 @@ const runOxlint = async (options) => {
|
|
|
40510
40252
|
}
|
|
40511
40253
|
}
|
|
40512
40254
|
const cacheHitFileCount = candidateFiles.length - missFiles.length;
|
|
40513
|
-
const enabledSidecarRuleIds = Object.keys(buildConfig({
|
|
40514
|
-
extendsPaths: [],
|
|
40515
|
-
ruleSelection: "sidecar"
|
|
40516
|
-
}).rules).map((ruleKey) => ruleKey.slice(ruleKey.lastIndexOf("/") + 1)).filter((ruleId) => CROSS_FILE_RULE_IDS.has(ruleId));
|
|
40517
|
-
const boundedSidecarRuleIds = enabledSidecarRuleIds.filter((ruleId) => CROSS_FILE_DEPENDENCY_COLLECTORS.has(ruleId));
|
|
40518
|
-
const boundedSidecarRuleIdSet = new Set(boundedSidecarRuleIds);
|
|
40519
|
-
const unboundedSidecarRuleIds = enabledSidecarRuleIds.filter((ruleId) => !CROSS_FILE_DEPENDENCY_COLLECTORS.has(ruleId));
|
|
40520
|
-
const useSidecarCache = sidecarLintCacheEnabled && boundedSidecarRuleIds.length > 0;
|
|
40521
|
-
const sidecarCache = useSidecarCache ? createSidecarLintCache(resolveReactDoctorCacheDir(rootDirectory), computeRulesetHash({
|
|
40522
|
-
config: buildConfig({
|
|
40523
|
-
extendsPaths: [],
|
|
40524
|
-
ruleSelection: "sidecar",
|
|
40525
|
-
sidecarRuleIdFilter: boundedSidecarRuleIdSet
|
|
40526
|
-
}),
|
|
40527
|
-
toolchainVersions: resolveOxlintToolchainVersions(nodeBinaryPath),
|
|
40528
|
-
ignorePatterns: combinedPatterns,
|
|
40529
|
-
tsconfigContent
|
|
40530
|
-
})) : null;
|
|
40531
|
-
const probeAnswers = createSidecarProbeAnswerResolver({
|
|
40532
|
-
rootDirectory,
|
|
40533
|
-
contentHashByRelativePath
|
|
40534
|
-
});
|
|
40535
|
-
const missProbesTask = sidecarCache === null ? null : collectSidecarProbesForFiles({
|
|
40536
|
-
files: missFiles,
|
|
40537
|
-
rootDirectory,
|
|
40538
|
-
boundedSidecarRuleIds,
|
|
40539
|
-
probeAnswers
|
|
40540
|
-
});
|
|
40541
40255
|
const fullResult = await runConfigOverFiles((overrides) => buildConfig({
|
|
40542
40256
|
extendsPaths: [],
|
|
40543
40257
|
disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin
|
|
40544
40258
|
}), "oxlintrc.full.json", missFiles, options.onFileProgress && ((scannedFileCount) => options.onFileProgress?.(scannedFileCount, candidateFiles.length)));
|
|
40545
40259
|
const missFileSet = new Set(missFiles);
|
|
40546
|
-
const
|
|
40547
|
-
const sidecarReplayedDiagnostics = [];
|
|
40548
|
-
const sidecarLintFiles = [];
|
|
40549
|
-
if (sidecarCache === null) sidecarLintFiles.push(...hitFiles);
|
|
40550
|
-
else {
|
|
40551
|
-
let verifySliceStartedAt = performance.now();
|
|
40552
|
-
for (const hitFile of hitFiles) {
|
|
40553
|
-
const cacheKey = cacheKeyByFile.get(hitFile);
|
|
40554
|
-
const entry = cacheKey === void 0 ? null : sidecarCache.lookup(cacheKey);
|
|
40555
|
-
if (entry !== null && entry.probes.every((probe) => probeAnswers.answerFor(probe.kind, probe.path) === probe.answer)) sidecarReplayedDiagnostics.push(...entry.diagnostics);
|
|
40556
|
-
else sidecarLintFiles.push(hitFile);
|
|
40557
|
-
if (performance.now() - verifySliceStartedAt >= 12) {
|
|
40558
|
-
await yieldToEventLoop();
|
|
40559
|
-
verifySliceStartedAt = performance.now();
|
|
40560
|
-
}
|
|
40561
|
-
}
|
|
40562
|
-
}
|
|
40563
|
-
const sidecarProbesTask = sidecarCache === null ? null : collectSidecarProbesForFiles({
|
|
40564
|
-
files: sidecarLintFiles,
|
|
40565
|
-
rootDirectory,
|
|
40566
|
-
boundedSidecarRuleIds,
|
|
40567
|
-
probeAnswers
|
|
40568
|
-
});
|
|
40569
|
-
const sidecarReplayedFileCount = hitFiles.length - sidecarLintFiles.length;
|
|
40570
|
-
if (sidecarReplayedFileCount > 0) options.onFileProgress?.(missFiles.length + sidecarReplayedFileCount, candidateFiles.length);
|
|
40571
|
-
const boundedSidecarResult = await runConfigOverFiles(() => buildConfig({
|
|
40572
|
-
extendsPaths: [],
|
|
40573
|
-
ruleSelection: "sidecar",
|
|
40574
|
-
...useSidecarCache ? { sidecarRuleIdFilter: boundedSidecarRuleIdSet } : {}
|
|
40575
|
-
}), "oxlintrc.sidecar.json", sidecarLintFiles, options.onFileProgress && ((scannedFileCount) => options.onFileProgress?.(missFiles.length + sidecarReplayedFileCount + scannedFileCount, candidateFiles.length)));
|
|
40576
|
-
const unboundedSidecarResult = useSidecarCache && unboundedSidecarRuleIds.length > 0 ? await runConfigOverFiles(() => buildConfig({
|
|
40260
|
+
const sidecarResult = await runConfigOverFiles(() => buildConfig({
|
|
40577
40261
|
extendsPaths: [],
|
|
40578
|
-
ruleSelection: "sidecar"
|
|
40579
|
-
|
|
40580
|
-
}), "oxlintrc.sidecar-unbounded.json", hitFiles, void 0) : {
|
|
40581
|
-
diagnostics: [],
|
|
40582
|
-
didDropReactHooksJsPlugin: false,
|
|
40583
|
-
hadPartialFailure: false
|
|
40584
|
-
};
|
|
40262
|
+
ruleSelection: "sidecar"
|
|
40263
|
+
}), "oxlintrc.sidecar.json", candidateFiles.filter((candidateFile) => !missFileSet.has(candidateFile)), options.onFileProgress && ((scannedFileCount) => options.onFileProgress?.(missFiles.length + scannedFileCount, candidateFiles.length)));
|
|
40585
40264
|
const freshCacheableDiagnostics = [];
|
|
40586
40265
|
for (const diagnostic of fullResult.diagnostics) if (!CROSS_FILE_RULE_IDS.has(diagnostic.rule)) freshCacheableDiagnostics.push(diagnostic);
|
|
40587
40266
|
onCacheStats?.(cacheHitFileCount, candidateFiles.length);
|
|
40588
|
-
|
|
40589
|
-
const
|
|
40590
|
-
|
|
40267
|
+
const missFileByNormalizedPath = /* @__PURE__ */ new Map();
|
|
40268
|
+
for (const missFile of missFiles) missFileByNormalizedPath.set(missFile.replaceAll("\\", "/"), missFile);
|
|
40269
|
+
const freshDiagnosticsByFile = /* @__PURE__ */ new Map();
|
|
40270
|
+
let isAttributionSound = true;
|
|
40271
|
+
for (const diagnostic of freshCacheableDiagnostics) {
|
|
40272
|
+
const missFile = missFileByNormalizedPath.get(diagnostic.filePath);
|
|
40273
|
+
if (missFile === void 0) {
|
|
40274
|
+
isAttributionSound = false;
|
|
40275
|
+
break;
|
|
40276
|
+
}
|
|
40277
|
+
const fileDiagnostics = freshDiagnosticsByFile.get(missFile) ?? [];
|
|
40278
|
+
fileDiagnostics.push(diagnostic);
|
|
40279
|
+
freshDiagnosticsByFile.set(missFile, fileDiagnostics);
|
|
40280
|
+
}
|
|
40281
|
+
if (!fullResult.didDropReactHooksJsPlugin && !fullResult.hadPartialFailure && isAttributionSound) {
|
|
40591
40282
|
for (const missFile of missFiles) {
|
|
40592
40283
|
const cacheKey = cacheKeyByFile.get(missFile);
|
|
40593
40284
|
if (cacheKey !== void 0) cache.store(cacheKey, freshDiagnosticsByFile.get(missFile) ?? []);
|
|
40594
40285
|
}
|
|
40595
40286
|
cache.persist();
|
|
40596
40287
|
}
|
|
40597
|
-
if (sidecarCache !== null && missProbesTask !== null && sidecarProbesTask !== null) storeSidecarEntries({
|
|
40598
|
-
sidecarCache,
|
|
40599
|
-
cacheKeyByFile,
|
|
40600
|
-
storablePasses: [{
|
|
40601
|
-
files: sidecarLintFiles,
|
|
40602
|
-
diagnostics: boundedSidecarResult.diagnostics,
|
|
40603
|
-
isTrusted: !boundedSidecarResult.hadPartialFailure,
|
|
40604
|
-
probesByFile: await sidecarProbesTask
|
|
40605
|
-
}, {
|
|
40606
|
-
files: missFiles,
|
|
40607
|
-
diagnostics: fullResult.diagnostics.filter((diagnostic) => boundedSidecarRuleIdSet.has(diagnostic.rule)),
|
|
40608
|
-
isTrusted: !fullResult.didDropReactHooksJsPlugin && !fullResult.hadPartialFailure,
|
|
40609
|
-
probesByFile: await missProbesTask
|
|
40610
|
-
}]
|
|
40611
|
-
});
|
|
40612
40288
|
return dedupeDiagnostics([
|
|
40613
40289
|
...replayedDiagnostics,
|
|
40614
40290
|
...fullResult.diagnostics,
|
|
40615
|
-
...
|
|
40616
|
-
...boundedSidecarResult.diagnostics,
|
|
40617
|
-
...unboundedSidecarResult.diagnostics
|
|
40291
|
+
...sidecarResult.diagnostics
|
|
40618
40292
|
]);
|
|
40619
40293
|
}
|
|
40620
40294
|
const baseArgs = makeBaseArgs(configPath);
|
|
@@ -40712,7 +40386,6 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
|
|
|
40712
40386
|
const concurrency = yield* OxlintConcurrency;
|
|
40713
40387
|
const lintBatchOrdering = yield* LintBatchOrdering;
|
|
40714
40388
|
const perFileLintCacheEnabled = yield* PerFileLintCacheEnabled;
|
|
40715
|
-
const sidecarLintCacheEnabled = yield* SidecarLintCacheEnabled;
|
|
40716
40389
|
const collectedFailures = [];
|
|
40717
40390
|
const diagnostics = yield* tryPromise({
|
|
40718
40391
|
try: (signal) => runOxlint({
|
|
@@ -40731,9 +40404,7 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
|
|
|
40731
40404
|
},
|
|
40732
40405
|
onFileProgress: input.onFileProgress,
|
|
40733
40406
|
perFileLintCacheEnabled,
|
|
40734
|
-
sidecarLintCacheEnabled,
|
|
40735
40407
|
onCacheStats: input.onCacheStats,
|
|
40736
|
-
onSidecarStats: input.onSidecarStats,
|
|
40737
40408
|
spawnTimeoutMs,
|
|
40738
40409
|
outputMaxBytes,
|
|
40739
40410
|
concurrency,
|
|
@@ -41543,8 +41214,6 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
41543
41214
|
let lastReportedTotalFileCount = 0;
|
|
41544
41215
|
let lintCacheHitFileCount = null;
|
|
41545
41216
|
let lintCacheTotalFileCount = null;
|
|
41546
|
-
let lintSidecarReplayedFileCount = null;
|
|
41547
|
-
let lintSidecarTotalFileCount = null;
|
|
41548
41217
|
let deadCodeCacheHit = null;
|
|
41549
41218
|
let deadCodeSummaryCacheHits = null;
|
|
41550
41219
|
let deadCodeSummaryCacheMisses = null;
|
|
@@ -41567,10 +41236,6 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
41567
41236
|
lintCacheHitFileCount = cacheHitFileCount;
|
|
41568
41237
|
lintCacheTotalFileCount = totalConsideredFileCount;
|
|
41569
41238
|
},
|
|
41570
|
-
onSidecarStats: (sidecarReplayedFileCount, sidecarConsideredFileCount) => {
|
|
41571
|
-
lintSidecarReplayedFileCount = sidecarReplayedFileCount;
|
|
41572
|
-
lintSidecarTotalFileCount = sidecarConsideredFileCount;
|
|
41573
|
-
},
|
|
41574
41239
|
deadlineEpochMs: input.deadlineEpochMs
|
|
41575
41240
|
}).pipe(catchTag("ReactDoctorError", (error) => unwrap(gen(function* () {
|
|
41576
41241
|
yield* set(lintFailure, {
|
|
@@ -41681,8 +41346,6 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
41681
41346
|
securityScanFailed,
|
|
41682
41347
|
lintCacheHitFileCount,
|
|
41683
41348
|
lintCacheTotalFileCount,
|
|
41684
|
-
lintSidecarReplayedFileCount,
|
|
41685
|
-
lintSidecarTotalFileCount,
|
|
41686
41349
|
deadCodeCacheHit: lintFailureState.didFail ? null : deadCodeCacheHit,
|
|
41687
41350
|
deadCodeSummaryCacheHits: lintFailureState.didFail ? null : deadCodeSummaryCacheHits,
|
|
41688
41351
|
deadCodeSummaryCacheMisses: lintFailureState.didFail ? null : deadCodeSummaryCacheMisses,
|
|
@@ -42326,4 +41989,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
42326
41989
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
42327
41990
|
|
|
42328
41991
|
//# sourceMappingURL=index.js.map
|
|
42329
|
-
//# debugId=
|
|
41992
|
+
//# debugId=f615f76d-a949-5fb6-ace8-145f3e137af4
|