react-doctor 0.2.11 → 0.2.12-dev.269ca17
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/README.md +26 -0
- package/dist/{cli-logger-pbFEieEc.js → cli-logger-CSZagq1E.js} +263 -60
- package/dist/cli.js +89 -33
- package/dist/index.d.ts +13 -8
- package/dist/index.js +258 -62
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -2307,15 +2307,91 @@ const detectFramework = (dependencies) => {
|
|
|
2307
2307
|
if (dependencies.preact && !dependencies.react) return "preact";
|
|
2308
2308
|
return "unknown";
|
|
2309
2309
|
};
|
|
2310
|
-
const UPPER_BOUND_COMPARATOR = /<\s*=?\s*\d+(?:\.\d+){0,2}(?:-[^\s,|]+)?/g;
|
|
2311
|
-
const HAS_UPPER_BOUND_COMPARATOR = /<\s*=?\s*\d+(?:\.\d+){0,2}(?:-[^\s,|]+)?/;
|
|
2312
|
-
const OR_SEPARATOR = /\s*\|\|\s*/;
|
|
2313
2310
|
const UNRESOLVABLE_PROTOCOL_VERSION = /^(?:file|git|github|https?|link|patch|portal|workspace|npm):/i;
|
|
2314
2311
|
const DIST_TAG_VERSION = /^[a-z][a-z0-9._-]*$/i;
|
|
2315
2312
|
const WILDCARD_VERSION = /^[*xX](?:\.[*xX])*$/;
|
|
2316
|
-
const NON_LOWER_BOUND_COMPARATOR = /(?:^|[\s,|])(?:>(?!=)|!={0,2})\s*\d/;
|
|
2317
|
-
const LOWER_BOUND_MAJOR = /(?:^|[\s,|])(?:>=\s*|[~^=v]\s*)?(\d+)(?=$|[\s,|.*xX-])/g;
|
|
2318
2313
|
const NPM_ALIAS_VERSION = /^npm:(?:@[^/]+\/[^@]+|[^@]+)@(.+)$/i;
|
|
2314
|
+
const isDigit = (value) => value !== void 0 && value >= "0" && value <= "9";
|
|
2315
|
+
const isWhitespace = (value) => value === " " || value === " " || value === "\n" || value === "\r" || value === "\f" || value === "\v";
|
|
2316
|
+
const isSeparator = (value) => isWhitespace(value) || value === "," || value === "|";
|
|
2317
|
+
const skipWhitespace = (value, start) => {
|
|
2318
|
+
let index = start;
|
|
2319
|
+
while (isWhitespace(value[index])) index += 1;
|
|
2320
|
+
return index;
|
|
2321
|
+
};
|
|
2322
|
+
const skipSeparators = (value, start) => {
|
|
2323
|
+
let index = start;
|
|
2324
|
+
while (isSeparator(value[index])) index += 1;
|
|
2325
|
+
return index;
|
|
2326
|
+
};
|
|
2327
|
+
const readDigits = (value, start) => {
|
|
2328
|
+
let index = start;
|
|
2329
|
+
while (isDigit(value[index])) index += 1;
|
|
2330
|
+
return index;
|
|
2331
|
+
};
|
|
2332
|
+
const getUpperBoundComparatorEnd = (version, start) => {
|
|
2333
|
+
if (version[start] !== "<") return null;
|
|
2334
|
+
let index = skipWhitespace(version, start + 1);
|
|
2335
|
+
if (version[index] === "=") index = skipWhitespace(version, index + 1);
|
|
2336
|
+
const majorStart = index;
|
|
2337
|
+
index = readDigits(version, index);
|
|
2338
|
+
if (index === majorStart) return null;
|
|
2339
|
+
for (let segments = 0; segments < 2 && version[index] === "."; segments += 1) {
|
|
2340
|
+
const segmentStart = index + 1;
|
|
2341
|
+
const segmentEnd = readDigits(version, segmentStart);
|
|
2342
|
+
if (segmentEnd === segmentStart) break;
|
|
2343
|
+
index = segmentEnd;
|
|
2344
|
+
}
|
|
2345
|
+
if (version[index] === "-") {
|
|
2346
|
+
index += 1;
|
|
2347
|
+
while (index < version.length && !isSeparator(version[index])) index += 1;
|
|
2348
|
+
}
|
|
2349
|
+
return index;
|
|
2350
|
+
};
|
|
2351
|
+
const stripUpperBoundComparators = (version) => {
|
|
2352
|
+
let stripped = "";
|
|
2353
|
+
let index = 0;
|
|
2354
|
+
while (index < version.length) {
|
|
2355
|
+
const comparatorEnd = getUpperBoundComparatorEnd(version, index);
|
|
2356
|
+
if (comparatorEnd === null) {
|
|
2357
|
+
stripped += version[index];
|
|
2358
|
+
index += 1;
|
|
2359
|
+
continue;
|
|
2360
|
+
}
|
|
2361
|
+
stripped += " ";
|
|
2362
|
+
index = comparatorEnd;
|
|
2363
|
+
}
|
|
2364
|
+
return stripped;
|
|
2365
|
+
};
|
|
2366
|
+
const hasNonLowerBoundComparator = (branch) => {
|
|
2367
|
+
for (let index = 0; index < branch.length; index += 1) {
|
|
2368
|
+
if (index > 0 && !isSeparator(branch[index - 1])) continue;
|
|
2369
|
+
if (branch[index] === ">" && branch[index + 1] !== "=") {
|
|
2370
|
+
if (isDigit(branch[skipWhitespace(branch, index + 1)])) return true;
|
|
2371
|
+
continue;
|
|
2372
|
+
}
|
|
2373
|
+
if (branch[index] !== "!") continue;
|
|
2374
|
+
let valueIndex = index + 1;
|
|
2375
|
+
if (branch[valueIndex] === "=") valueIndex += 1;
|
|
2376
|
+
if (branch[valueIndex] === "=") valueIndex += 1;
|
|
2377
|
+
valueIndex = skipWhitespace(branch, valueIndex);
|
|
2378
|
+
if (isDigit(branch[valueIndex])) return true;
|
|
2379
|
+
}
|
|
2380
|
+
return false;
|
|
2381
|
+
};
|
|
2382
|
+
const isMajorTerminator = (value) => value === void 0 || isSeparator(value) || value === "." || value === "*" || value === "x" || value === "X" || value === "-";
|
|
2383
|
+
const getLowerBoundMajorAt = (branch, start) => {
|
|
2384
|
+
let index = start;
|
|
2385
|
+
if (branch[index] === ">" && branch[index + 1] === "=") index = skipWhitespace(branch, index + 2);
|
|
2386
|
+
else if (branch[index] === "~" || branch[index] === "^" || branch[index] === "=" || branch[index] === "v") index = skipWhitespace(branch, index + 1);
|
|
2387
|
+
const majorStart = index;
|
|
2388
|
+
const majorEnd = readDigits(branch, majorStart);
|
|
2389
|
+
if (majorEnd === majorStart || !isMajorTerminator(branch[majorEnd])) return null;
|
|
2390
|
+
return {
|
|
2391
|
+
end: majorEnd,
|
|
2392
|
+
major: Number.parseInt(branch.slice(majorStart, majorEnd), 10)
|
|
2393
|
+
};
|
|
2394
|
+
};
|
|
2319
2395
|
const normalizeDependencyVersion = (version) => {
|
|
2320
2396
|
const trimmed = version.trim();
|
|
2321
2397
|
if (trimmed.length === 0) return null;
|
|
@@ -2325,17 +2401,29 @@ const normalizeDependencyVersion = (version) => {
|
|
|
2325
2401
|
if (WILDCARD_VERSION.test(normalizedVersion)) return null;
|
|
2326
2402
|
return normalizedVersion;
|
|
2327
2403
|
};
|
|
2328
|
-
const splitDependencyVersionBranches = (version) => version.split(
|
|
2329
|
-
const hasUpperBoundComparator = (version) =>
|
|
2404
|
+
const splitDependencyVersionBranches = (version) => version.split("||").map((branch) => branch.trim()).filter(Boolean);
|
|
2405
|
+
const hasUpperBoundComparator = (version) => {
|
|
2406
|
+
for (let index = 0; index < version.length; index += 1) if (getUpperBoundComparatorEnd(version, index) !== null) return true;
|
|
2407
|
+
return false;
|
|
2408
|
+
};
|
|
2330
2409
|
const getBranchLowestMajor = (branch) => {
|
|
2331
|
-
if (
|
|
2332
|
-
const lowerBoundComparators = branch
|
|
2410
|
+
if (hasNonLowerBoundComparator(branch)) return null;
|
|
2411
|
+
const lowerBoundComparators = stripUpperBoundComparators(branch).trim();
|
|
2333
2412
|
if (lowerBoundComparators.length === 0) return null;
|
|
2334
2413
|
let branchLowestMajor = null;
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
if (
|
|
2414
|
+
let index = 0;
|
|
2415
|
+
while (index < lowerBoundComparators.length) {
|
|
2416
|
+
const lowerBoundStart = skipSeparators(lowerBoundComparators, index);
|
|
2417
|
+
if (lowerBoundStart > 0 && !isSeparator(lowerBoundComparators[lowerBoundStart - 1])) {
|
|
2418
|
+
index = lowerBoundStart + 1;
|
|
2419
|
+
continue;
|
|
2420
|
+
}
|
|
2421
|
+
const lowerBoundMajor = getLowerBoundMajorAt(lowerBoundComparators, lowerBoundStart);
|
|
2422
|
+
if (lowerBoundMajor !== null && Number.isFinite(lowerBoundMajor.major) && lowerBoundMajor.major > 0) {
|
|
2423
|
+
const major = lowerBoundMajor.major;
|
|
2424
|
+
if (branchLowestMajor === null || major < branchLowestMajor) branchLowestMajor = major;
|
|
2425
|
+
}
|
|
2426
|
+
index = lowerBoundMajor?.end ?? lowerBoundStart + 1;
|
|
2339
2427
|
}
|
|
2340
2428
|
return branchLowestMajor;
|
|
2341
2429
|
};
|
|
@@ -2504,6 +2592,7 @@ const resolveCatalogVersion = (packageJson, packageName, rootDirectory, explicit
|
|
|
2504
2592
|
const EMPTY_DEPENDENCY_INFO = {
|
|
2505
2593
|
reactVersion: null,
|
|
2506
2594
|
tailwindVersion: null,
|
|
2595
|
+
zodVersion: null,
|
|
2507
2596
|
framework: "unknown"
|
|
2508
2597
|
};
|
|
2509
2598
|
const pickConcreteVersion = (packageJson, packageName, sections) => {
|
|
@@ -2532,6 +2621,11 @@ const extractDependencyInfo = (packageJson) => {
|
|
|
2532
2621
|
"devDependencies",
|
|
2533
2622
|
"peerDependencies"
|
|
2534
2623
|
]),
|
|
2624
|
+
zodVersion: pickConcreteVersion(packageJson, "zod", [
|
|
2625
|
+
"dependencies",
|
|
2626
|
+
"devDependencies",
|
|
2627
|
+
"peerDependencies"
|
|
2628
|
+
]),
|
|
2535
2629
|
framework: detectFramework(allDependencies)
|
|
2536
2630
|
};
|
|
2537
2631
|
};
|
|
@@ -2676,8 +2770,22 @@ const findReactInWorkspaces = (rootDirectory, packageJson) => {
|
|
|
2676
2770
|
workspaceDirectory,
|
|
2677
2771
|
workspacePackageJson
|
|
2678
2772
|
});
|
|
2773
|
+
const zodVersion = resolveWorkspaceDependencyVersion({
|
|
2774
|
+
concreteVersion: info.zodVersion,
|
|
2775
|
+
packageName: "zod",
|
|
2776
|
+
rootDirectory,
|
|
2777
|
+
rootPackageJson: packageJson,
|
|
2778
|
+
sections: [
|
|
2779
|
+
"dependencies",
|
|
2780
|
+
"devDependencies",
|
|
2781
|
+
"peerDependencies"
|
|
2782
|
+
],
|
|
2783
|
+
workspaceDirectory,
|
|
2784
|
+
workspacePackageJson
|
|
2785
|
+
});
|
|
2679
2786
|
if (reactVersion && shouldReplaceReactVersion(result.reactVersion, reactVersion)) result.reactVersion = reactVersion;
|
|
2680
2787
|
if (tailwindVersion && !result.tailwindVersion) result.tailwindVersion = tailwindVersion;
|
|
2788
|
+
if (zodVersion && !result.zodVersion) result.zodVersion = zodVersion;
|
|
2681
2789
|
if (info.framework !== "unknown" && result.framework === "unknown") result.framework = info.framework;
|
|
2682
2790
|
const resultReactMajor = parseReactMajor(result.reactVersion);
|
|
2683
2791
|
if (result.reactVersion && result.tailwindVersion && result.framework !== "unknown" && resultReactMajor !== null && resultReactMajor <= 17) return result;
|
|
@@ -2712,14 +2820,26 @@ const findDependencyInfoFromMonorepoRoot = (directory) => {
|
|
|
2712
2820
|
"peerDependencies"
|
|
2713
2821
|
]
|
|
2714
2822
|
}) : null;
|
|
2823
|
+
const leafZodDeclaration = leafPackageJson ? getDependencyDeclaration({
|
|
2824
|
+
packageJson: leafPackageJson,
|
|
2825
|
+
packageName: "zod",
|
|
2826
|
+
sections: [
|
|
2827
|
+
"dependencies",
|
|
2828
|
+
"devDependencies",
|
|
2829
|
+
"peerDependencies"
|
|
2830
|
+
]
|
|
2831
|
+
}) : null;
|
|
2715
2832
|
const shouldUseReactFallback = !leafReactDeclaration?.hasDeclaration;
|
|
2716
2833
|
const shouldUseTailwindFallback = leafTailwindDeclaration?.hasDeclaration ?? true;
|
|
2834
|
+
const shouldUseZodFallback = leafZodDeclaration?.hasDeclaration ?? true;
|
|
2717
2835
|
const reactCatalogVersion = shouldUseReactFallback ? resolveCatalogVersion(rootPackageJson, "react", monorepoRoot, leafReactDeclaration?.catalogReference) : null;
|
|
2718
2836
|
const tailwindCatalogVersion = shouldUseTailwindFallback ? resolveCatalogVersion(rootPackageJson, "tailwindcss", monorepoRoot, leafTailwindDeclaration?.catalogReference) : null;
|
|
2837
|
+
const zodCatalogVersion = shouldUseZodFallback ? resolveCatalogVersion(rootPackageJson, "zod", monorepoRoot, leafZodDeclaration?.catalogReference) : null;
|
|
2719
2838
|
const workspaceInfo = findReactInWorkspaces(monorepoRoot, rootPackageJson);
|
|
2720
2839
|
return {
|
|
2721
2840
|
reactVersion: shouldUseReactFallback ? reactCatalogVersion ?? rootInfo.reactVersion ?? workspaceInfo.reactVersion : rootInfo.reactVersion ?? workspaceInfo.reactVersion,
|
|
2722
2841
|
tailwindVersion: shouldUseTailwindFallback ? tailwindCatalogVersion ?? rootInfo.tailwindVersion ?? workspaceInfo.tailwindVersion : null,
|
|
2842
|
+
zodVersion: shouldUseZodFallback ? zodCatalogVersion ?? rootInfo.zodVersion ?? workspaceInfo.zodVersion : null,
|
|
2723
2843
|
framework: rootInfo.framework !== "unknown" ? rootInfo.framework : workspaceInfo.framework
|
|
2724
2844
|
};
|
|
2725
2845
|
};
|
|
@@ -2769,12 +2889,12 @@ const isPackageJsonReactNativeAware = (packageJson) => {
|
|
|
2769
2889
|
return false;
|
|
2770
2890
|
};
|
|
2771
2891
|
const hasReactNativeWorkspaceAnywhere = (rootDirectory, rootPackageJson) => someWorkspacePackageJson(rootDirectory, rootPackageJson, isPackageJsonReactNativeAware);
|
|
2772
|
-
const
|
|
2773
|
-
return
|
|
2892
|
+
const getPreactVersion = (packageJson) => {
|
|
2893
|
+
return {
|
|
2774
2894
|
...packageJson.peerDependencies,
|
|
2775
2895
|
...packageJson.dependencies,
|
|
2776
2896
|
...packageJson.devDependencies
|
|
2777
|
-
};
|
|
2897
|
+
}.preact ?? null;
|
|
2778
2898
|
};
|
|
2779
2899
|
const TANSTACK_QUERY_PACKAGES = new Set([
|
|
2780
2900
|
"@tanstack/react-query",
|
|
@@ -2799,6 +2919,10 @@ const isPackageJsonReanimatedAware = (packageJson) => {
|
|
|
2799
2919
|
};
|
|
2800
2920
|
return Object.hasOwn(allDependencies, REANIMATED_DEPENDENCY_NAME);
|
|
2801
2921
|
};
|
|
2922
|
+
const parseZodMajor = (zodVersion) => {
|
|
2923
|
+
if (typeof zodVersion !== "string") return null;
|
|
2924
|
+
return getLowestDependencyMajor(zodVersion);
|
|
2925
|
+
};
|
|
2802
2926
|
const hasUpperBoundOnlyPeerRange = (range) => {
|
|
2803
2927
|
if (typeof range !== "string") return false;
|
|
2804
2928
|
const normalizedRange = normalizeDependencyVersion(range);
|
|
@@ -2885,12 +3009,22 @@ const listManifestWorkspacePackages = (rootDirectory) => {
|
|
|
2885
3009
|
const nxPatterns = patterns.length > 0 ? [] : getNxWorkspaceDirectories(rootDirectory);
|
|
2886
3010
|
return toReactWorkspacePackages((patterns.length > 0 ? patterns : nxPatterns).flatMap((pattern) => resolveWorkspaceDirectories(rootDirectory, pattern)));
|
|
2887
3011
|
};
|
|
3012
|
+
const NON_PROJECT_DIRECTORIES = new Set([
|
|
3013
|
+
"AppData",
|
|
3014
|
+
"Application Data",
|
|
3015
|
+
"Library"
|
|
3016
|
+
]);
|
|
3017
|
+
const MAX_SCAN_DEPTH = 6;
|
|
2888
3018
|
const discoverReactSubprojectsByFilesystem = (rootDirectory) => {
|
|
2889
3019
|
const packages = [];
|
|
2890
|
-
const pendingDirectories = [
|
|
3020
|
+
const pendingDirectories = [{
|
|
3021
|
+
directory: rootDirectory,
|
|
3022
|
+
depth: 0
|
|
3023
|
+
}];
|
|
2891
3024
|
while (pendingDirectories.length > 0) {
|
|
2892
|
-
const
|
|
2893
|
-
if (!
|
|
3025
|
+
const current = pendingDirectories.pop();
|
|
3026
|
+
if (!current) continue;
|
|
3027
|
+
const { directory: currentDirectory, depth } = current;
|
|
2894
3028
|
const packageJsonPath = path.join(currentDirectory, "package.json");
|
|
2895
3029
|
if (isFile(packageJsonPath)) {
|
|
2896
3030
|
const packageJson = readPackageJson(packageJsonPath);
|
|
@@ -2902,10 +3036,14 @@ const discoverReactSubprojectsByFilesystem = (rootDirectory) => {
|
|
|
2902
3036
|
});
|
|
2903
3037
|
}
|
|
2904
3038
|
}
|
|
3039
|
+
if (depth >= MAX_SCAN_DEPTH) continue;
|
|
2905
3040
|
const entries = readDirectoryEntries(currentDirectory).toSorted((firstEntry, secondEntry) => firstEntry.name.localeCompare(secondEntry.name));
|
|
2906
3041
|
for (const entry of entries) {
|
|
2907
|
-
if (!entry.isDirectory() || entry.name.startsWith(".") || IGNORED_DIRECTORIES.has(entry.name)) continue;
|
|
2908
|
-
pendingDirectories.push(
|
|
3042
|
+
if (!entry.isDirectory() || entry.name.startsWith(".") || IGNORED_DIRECTORIES.has(entry.name) || NON_PROJECT_DIRECTORIES.has(entry.name)) continue;
|
|
3043
|
+
pendingDirectories.push({
|
|
3044
|
+
directory: path.join(currentDirectory, entry.name),
|
|
3045
|
+
depth: depth + 1
|
|
3046
|
+
});
|
|
2909
3047
|
}
|
|
2910
3048
|
}
|
|
2911
3049
|
return packages;
|
|
@@ -2926,7 +3064,7 @@ const discoverProject = (directory) => {
|
|
|
2926
3064
|
const packageJsonPath = path.join(directory, "package.json");
|
|
2927
3065
|
if (!isFile(packageJsonPath)) throw new PackageJsonNotFoundError(directory);
|
|
2928
3066
|
const packageJson = readPackageJson(packageJsonPath);
|
|
2929
|
-
let { reactVersion, tailwindVersion, framework } = extractDependencyInfo(packageJson);
|
|
3067
|
+
let { reactVersion, tailwindVersion, zodVersion, framework } = extractDependencyInfo(packageJson);
|
|
2930
3068
|
const reactDeclaration = getDependencyDeclaration({
|
|
2931
3069
|
packageJson,
|
|
2932
3070
|
packageName: "react",
|
|
@@ -2945,9 +3083,19 @@ const discoverProject = (directory) => {
|
|
|
2945
3083
|
"peerDependencies"
|
|
2946
3084
|
]
|
|
2947
3085
|
});
|
|
3086
|
+
const zodDeclaration = getDependencyDeclaration({
|
|
3087
|
+
packageJson,
|
|
3088
|
+
packageName: "zod",
|
|
3089
|
+
sections: [
|
|
3090
|
+
"dependencies",
|
|
3091
|
+
"devDependencies",
|
|
3092
|
+
"peerDependencies"
|
|
3093
|
+
]
|
|
3094
|
+
});
|
|
2948
3095
|
if (!reactVersion && reactDeclaration.hasDeclaration) reactVersion = resolveCatalogVersion(packageJson, "react", directory, reactDeclaration.catalogReference);
|
|
2949
3096
|
if (!tailwindVersion && tailwindDeclaration.hasDeclaration) tailwindVersion = resolveCatalogVersion(packageJson, "tailwindcss", directory, tailwindDeclaration.catalogReference);
|
|
2950
|
-
if (!
|
|
3097
|
+
if (!zodVersion && zodDeclaration.hasDeclaration) zodVersion = resolveCatalogVersion(packageJson, "zod", directory, zodDeclaration.catalogReference);
|
|
3098
|
+
if (!reactVersion || !tailwindVersion || !zodVersion) {
|
|
2951
3099
|
const monorepoRoot = findMonorepoRoot(directory);
|
|
2952
3100
|
if (monorepoRoot) {
|
|
2953
3101
|
const monorepoPackageJsonPath = path.join(monorepoRoot, "package.json");
|
|
@@ -2955,6 +3103,7 @@ const discoverProject = (directory) => {
|
|
|
2955
3103
|
const rootPackageJson = readPackageJson(monorepoPackageJsonPath);
|
|
2956
3104
|
if (!reactVersion && reactDeclaration.hasDeclaration) reactVersion = resolveCatalogVersion(rootPackageJson, "react", monorepoRoot, reactDeclaration.catalogReference);
|
|
2957
3105
|
if (!tailwindVersion && tailwindDeclaration.hasDeclaration) tailwindVersion = resolveCatalogVersion(rootPackageJson, "tailwindcss", monorepoRoot, tailwindDeclaration.catalogReference);
|
|
3106
|
+
if (!zodVersion && zodDeclaration.hasDeclaration) zodVersion = resolveCatalogVersion(rootPackageJson, "zod", monorepoRoot, zodDeclaration.catalogReference);
|
|
2958
3107
|
}
|
|
2959
3108
|
}
|
|
2960
3109
|
}
|
|
@@ -2962,32 +3111,39 @@ const discoverProject = (directory) => {
|
|
|
2962
3111
|
const workspaceInfo = findReactInWorkspaces(directory, packageJson);
|
|
2963
3112
|
if (!reactVersion && workspaceInfo.reactVersion) reactVersion = workspaceInfo.reactVersion;
|
|
2964
3113
|
if (!tailwindVersion && workspaceInfo.tailwindVersion) tailwindVersion = workspaceInfo.tailwindVersion;
|
|
3114
|
+
if (!zodVersion && workspaceInfo.zodVersion) zodVersion = workspaceInfo.zodVersion;
|
|
2965
3115
|
if (framework === "unknown" && workspaceInfo.framework !== "unknown") framework = workspaceInfo.framework;
|
|
2966
3116
|
}
|
|
2967
3117
|
if ((!reactVersion || framework === "unknown") && !isMonorepoRoot(directory)) {
|
|
2968
3118
|
const monorepoInfo = findDependencyInfoFromMonorepoRoot(directory);
|
|
2969
3119
|
if (!reactVersion) reactVersion = monorepoInfo.reactVersion;
|
|
2970
3120
|
if (!tailwindVersion) tailwindVersion = monorepoInfo.tailwindVersion;
|
|
3121
|
+
if (!zodVersion) zodVersion = monorepoInfo.zodVersion;
|
|
2971
3122
|
if (framework === "unknown") framework = monorepoInfo.framework;
|
|
2972
3123
|
}
|
|
2973
3124
|
if (!reactVersion && reactDeclaration.version && !isCatalogReference(reactDeclaration.version)) reactVersion = reactDeclaration.version;
|
|
2974
3125
|
if (!tailwindVersion && tailwindDeclaration.version && !isCatalogReference(tailwindDeclaration.version)) tailwindVersion = tailwindDeclaration.version;
|
|
3126
|
+
if (!zodVersion && zodDeclaration.version && !isCatalogReference(zodDeclaration.version)) zodVersion = zodDeclaration.version;
|
|
2975
3127
|
const projectName = packageJson.name ?? path.basename(directory);
|
|
2976
3128
|
const hasTypeScript = fs.existsSync(path.join(directory, "tsconfig.json"));
|
|
2977
3129
|
const sourceFileCount = countSourceFiles(directory);
|
|
2978
3130
|
const hasReactNativeWorkspace = framework === "expo" || framework === "react-native" || hasReactNativeWorkspaceAnywhere(directory, packageJson);
|
|
2979
3131
|
const hasReanimated = hasReactNativeWorkspace && someWorkspacePackageJson(directory, packageJson, isPackageJsonReanimatedAware);
|
|
3132
|
+
const preactVersion = getPreactVersion(packageJson);
|
|
2980
3133
|
const projectInfo = {
|
|
2981
3134
|
rootDirectory: directory,
|
|
2982
3135
|
projectName,
|
|
2983
3136
|
reactVersion,
|
|
2984
3137
|
reactMajorVersion: resolveEffectiveReactMajor(reactVersion, packageJson),
|
|
2985
3138
|
tailwindVersion,
|
|
3139
|
+
zodVersion,
|
|
3140
|
+
zodMajorVersion: parseZodMajor(zodVersion),
|
|
2986
3141
|
framework,
|
|
2987
3142
|
hasTypeScript,
|
|
2988
3143
|
hasReactCompiler: detectReactCompiler(directory, packageJson),
|
|
2989
3144
|
hasTanStackQuery: hasTanStackQuery(packageJson),
|
|
2990
|
-
|
|
3145
|
+
preactVersion,
|
|
3146
|
+
preactMajorVersion: parseReactMajor(preactVersion),
|
|
2991
3147
|
hasReactNativeWorkspace,
|
|
2992
3148
|
hasReanimated,
|
|
2993
3149
|
sourceFileCount
|
|
@@ -2995,6 +3151,7 @@ const discoverProject = (directory) => {
|
|
|
2995
3151
|
cachedProjectInfos.set(directory, projectInfo);
|
|
2996
3152
|
return projectInfo;
|
|
2997
3153
|
};
|
|
3154
|
+
const isAnalyzableProject = (project) => project.reactVersion !== null || project.preactVersion !== null;
|
|
2998
3155
|
const MAJOR_MINOR_PATTERN = /(\d{1,4})\.(\d{1,4})/;
|
|
2999
3156
|
const MAJOR_ONLY_PATTERN = /(\d{1,4})/;
|
|
3000
3157
|
const UPPER_BOUND_COMPARATOR_PATTERN = /<=?\s{0,8}\d{1,4}(?:\.\d{1,4}){0,2}(?:-[^\s,|]+)?/g;
|
|
@@ -3960,17 +4117,26 @@ const layerOtlp = Layer.unwrap(Effect.gen(function* () {
|
|
|
3960
4117
|
headers
|
|
3961
4118
|
}).pipe(Layer.provide(FetchHttpClient.layer));
|
|
3962
4119
|
}).pipe(Effect.orDie));
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
4120
|
+
/**
|
|
4121
|
+
* Per-batch oxlint wall-clock budget. Reads from the env var on
|
|
4122
|
+
* startup so the eval harness can raise the budget under sandbox
|
|
4123
|
+
* microVMs without recompiling react-doctor. Tests override via
|
|
4124
|
+
* `Layer.succeed(OxlintSpawnTimeoutMs, ...)`.
|
|
4125
|
+
*/
|
|
4126
|
+
var OxlintSpawnTimeoutMs = class extends Context.Reference("react-doctor/OxlintSpawnTimeoutMs", { defaultValue: () => {
|
|
3966
4127
|
const raw = process.env["REACT_DOCTOR_OXLINT_SPAWN_TIMEOUT_MS"];
|
|
3967
4128
|
if (raw === void 0) return OXLINT_SPAWN_TIMEOUT_MS;
|
|
3968
4129
|
const parsed = Number(raw);
|
|
3969
4130
|
if (!Number.isFinite(parsed) || parsed <= 0) return OXLINT_SPAWN_TIMEOUT_MS;
|
|
3970
4131
|
return parsed;
|
|
3971
|
-
} });
|
|
3972
|
-
|
|
3973
|
-
|
|
4132
|
+
} }) {};
|
|
4133
|
+
/**
|
|
4134
|
+
* Hard cap on combined stdout+stderr bytes per oxlint batch. The
|
|
4135
|
+
* subprocess gets SIGKILL'd if it produces more; the recovery path
|
|
4136
|
+
* suggests narrowing the scan with --diff. Override via Layer in
|
|
4137
|
+
* tests that exercise the cap behavior.
|
|
4138
|
+
*/
|
|
4139
|
+
var OxlintOutputMaxBytes = class extends Context.Reference("react-doctor/OxlintOutputMaxBytes", { defaultValue: () => OXLINT_OUTPUT_MAX_BYTES }) {};
|
|
3974
4140
|
const DIAGNOSTIC_SURFACES = [
|
|
3975
4141
|
"cli",
|
|
3976
4142
|
"prComment",
|
|
@@ -5044,8 +5210,15 @@ var Git = class Git extends Context.Service()("react-doctor/Git") {
|
|
|
5044
5210
|
env: input.env,
|
|
5045
5211
|
extendEnv: true
|
|
5046
5212
|
}));
|
|
5213
|
+
const maxStdoutBytes = input.maxStdoutBytes;
|
|
5214
|
+
const stdoutByteCount = yield* Ref.make(0);
|
|
5215
|
+
const stdoutStream = maxStdoutBytes === void 0 ? handle.stdout : handle.stdout.pipe(Stream.tap((chunk) => Ref.updateAndGet(stdoutByteCount, (total) => total + chunk.length).pipe(Effect.flatMap((total) => total > maxStdoutBytes ? Effect.fail(new ReactDoctorError({ reason: new GitInvocationFailed({
|
|
5216
|
+
args: [...input.args],
|
|
5217
|
+
directory: input.directory,
|
|
5218
|
+
cause: /* @__PURE__ */ new Error(`git stdout exceeded ${maxStdoutBytes} bytes`)
|
|
5219
|
+
}) })) : Effect.void))));
|
|
5047
5220
|
const [stdout, stderr, status] = yield* Effect.all([
|
|
5048
|
-
Stream.mkString(Stream.decodeText(
|
|
5221
|
+
Stream.mkString(Stream.decodeText(stdoutStream)),
|
|
5049
5222
|
Stream.mkString(Stream.decodeText(handle.stderr)),
|
|
5050
5223
|
handle.exitCode
|
|
5051
5224
|
], { concurrency: 3 });
|
|
@@ -5207,7 +5380,12 @@ var Git = class Git extends Context.Service()("react-doctor/Git") {
|
|
|
5207
5380
|
if (result.status !== 0) return [];
|
|
5208
5381
|
return splitNullSeparated(result.stdout);
|
|
5209
5382
|
})),
|
|
5210
|
-
showStagedContent: (directory, relativePath) =>
|
|
5383
|
+
showStagedContent: (directory, relativePath, options) => runCommand({
|
|
5384
|
+
command: "git",
|
|
5385
|
+
args: ["show", `:${relativePath}`],
|
|
5386
|
+
directory,
|
|
5387
|
+
maxStdoutBytes: options?.maxBufferBytes
|
|
5388
|
+
}).pipe(Effect.map((result) => result.status === 0 ? result.stdout : null)),
|
|
5211
5389
|
grep: (input) => Effect.gen(function* () {
|
|
5212
5390
|
const args = ["grep"];
|
|
5213
5391
|
if (input.listMatchingFiles ?? true) args.push("-l");
|
|
@@ -5215,7 +5393,12 @@ var Git = class Git extends Context.Service()("react-doctor/Git") {
|
|
|
5215
5393
|
if (input.extendedRegexp ?? false) args.push("-E");
|
|
5216
5394
|
args.push(input.pattern);
|
|
5217
5395
|
if (input.includePaths && input.includePaths.length > 0) args.push("--", ...input.includePaths);
|
|
5218
|
-
const result = yield*
|
|
5396
|
+
const result = yield* runCommand({
|
|
5397
|
+
command: "git",
|
|
5398
|
+
args,
|
|
5399
|
+
directory: input.directory,
|
|
5400
|
+
maxStdoutBytes: input.maxBufferBytes
|
|
5401
|
+
});
|
|
5219
5402
|
if (result.status === 128) return null;
|
|
5220
5403
|
return {
|
|
5221
5404
|
status: result.status,
|
|
@@ -5463,7 +5646,8 @@ const buildCapabilities = (project) => {
|
|
|
5463
5646
|
if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
|
|
5464
5647
|
const reactMajor = project.reactMajorVersion;
|
|
5465
5648
|
if (reactMajor !== null) {
|
|
5466
|
-
|
|
5649
|
+
const cappedReactMajor = Math.min(reactMajor, 30);
|
|
5650
|
+
for (let major = 17; major <= cappedReactMajor; major++) capabilities.add(`react:${major}`);
|
|
5467
5651
|
if (reactMajor >= 19) {
|
|
5468
5652
|
if (isReactAtLeast(parseReactMajorMinor(project.reactVersion), {
|
|
5469
5653
|
major: 19,
|
|
@@ -5478,11 +5662,20 @@ const buildCapabilities = (project) => {
|
|
|
5478
5662
|
minor: 4
|
|
5479
5663
|
})) capabilities.add("tailwind:3.4");
|
|
5480
5664
|
}
|
|
5665
|
+
if (project.zodVersion !== null) {
|
|
5666
|
+
capabilities.add("zod");
|
|
5667
|
+
if (project.zodMajorVersion !== null && project.zodMajorVersion >= 4) capabilities.add("zod:4");
|
|
5668
|
+
}
|
|
5481
5669
|
if (project.hasReactCompiler) capabilities.add("react-compiler");
|
|
5482
5670
|
if (project.hasTanStackQuery) capabilities.add("tanstack-query");
|
|
5483
5671
|
if (project.hasTypeScript) capabilities.add("typescript");
|
|
5484
|
-
if (project.
|
|
5672
|
+
if (project.preactVersion !== null) {
|
|
5485
5673
|
capabilities.add("preact");
|
|
5674
|
+
const preactMajor = project.preactMajorVersion;
|
|
5675
|
+
if (preactMajor !== null) {
|
|
5676
|
+
const cappedPreactMajor = Math.min(preactMajor, 20);
|
|
5677
|
+
for (let major = 10; major <= cappedPreactMajor; major++) capabilities.add(`preact:${major}`);
|
|
5678
|
+
}
|
|
5486
5679
|
if (project.reactVersion === null) capabilities.add("pure-preact");
|
|
5487
5680
|
}
|
|
5488
5681
|
return capabilities;
|
|
@@ -6138,13 +6331,6 @@ const SANITIZED_ENV = (() => {
|
|
|
6138
6331
|
}
|
|
6139
6332
|
return sanitized;
|
|
6140
6333
|
})();
|
|
6141
|
-
const OXLINT_SPAWN_TIMEOUT_MS$1 = (() => {
|
|
6142
|
-
const raw = process.env["REACT_DOCTOR_OXLINT_SPAWN_TIMEOUT_MS"];
|
|
6143
|
-
if (raw === void 0) return OXLINT_SPAWN_TIMEOUT_MS;
|
|
6144
|
-
const parsed = Number(raw);
|
|
6145
|
-
if (!Number.isFinite(parsed) || parsed <= 0) return OXLINT_SPAWN_TIMEOUT_MS;
|
|
6146
|
-
return parsed;
|
|
6147
|
-
})();
|
|
6148
6334
|
/**
|
|
6149
6335
|
* Spawn one oxlint subprocess with hard ceilings on wall time and
|
|
6150
6336
|
* output size. Returns stdout on success; raises a tagged
|
|
@@ -6161,7 +6347,7 @@ const OXLINT_SPAWN_TIMEOUT_MS$1 = (() => {
|
|
|
6161
6347
|
* The first three are splittable (the caller's binary-split retry
|
|
6162
6348
|
* shrinks the batch and re-spawns); the fourth isn't.
|
|
6163
6349
|
*/
|
|
6164
|
-
const spawnOxlint = (args, rootDirectory, nodeBinaryPath) => new Promise((resolve, reject) => {
|
|
6350
|
+
const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLINT_SPAWN_TIMEOUT_MS, outputMaxBytes = OXLINT_OUTPUT_MAX_BYTES) => new Promise((resolve, reject) => {
|
|
6165
6351
|
const child = spawn(nodeBinaryPath, args, {
|
|
6166
6352
|
cwd: rootDirectory,
|
|
6167
6353
|
env: SANITIZED_ENV
|
|
@@ -6170,9 +6356,9 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath) => new Promise((resolv
|
|
|
6170
6356
|
child.kill("SIGKILL");
|
|
6171
6357
|
reject(new ReactDoctorError({ reason: new OxlintBatchExceeded({
|
|
6172
6358
|
kind: "timeout",
|
|
6173
|
-
detail: `${
|
|
6359
|
+
detail: `${spawnTimeoutMs / 1e3}s budget exceeded`
|
|
6174
6360
|
}) }));
|
|
6175
|
-
},
|
|
6361
|
+
}, spawnTimeoutMs);
|
|
6176
6362
|
timeoutHandle.unref?.();
|
|
6177
6363
|
const stdoutBuffers = [];
|
|
6178
6364
|
const stderrBuffers = [];
|
|
@@ -6182,7 +6368,7 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath) => new Promise((resolv
|
|
|
6182
6368
|
const killIfTooLarge = (incomingBytes, isStdout) => {
|
|
6183
6369
|
if (isStdout) stdoutByteCount += incomingBytes;
|
|
6184
6370
|
else stderrByteCount += incomingBytes;
|
|
6185
|
-
if (stdoutByteCount + stderrByteCount >
|
|
6371
|
+
if (stdoutByteCount + stderrByteCount > outputMaxBytes && !didKillForSize) {
|
|
6186
6372
|
didKillForSize = true;
|
|
6187
6373
|
child.kill("SIGKILL");
|
|
6188
6374
|
return true;
|
|
@@ -6208,7 +6394,7 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath) => new Promise((resolv
|
|
|
6208
6394
|
if (didKillForSize) {
|
|
6209
6395
|
reject(new ReactDoctorError({ reason: new OxlintBatchExceeded({
|
|
6210
6396
|
kind: "output-too-large",
|
|
6211
|
-
detail: `exceeded ${
|
|
6397
|
+
detail: `exceeded ${outputMaxBytes} bytes — scan a smaller subset with --diff or --staged`
|
|
6212
6398
|
}) }));
|
|
6213
6399
|
return;
|
|
6214
6400
|
}
|
|
@@ -6249,7 +6435,7 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath) => new Promise((resolv
|
|
|
6249
6435
|
* with a slimmer config in that case.
|
|
6250
6436
|
*/
|
|
6251
6437
|
const spawnLintBatches = async (input) => {
|
|
6252
|
-
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, onPartialFailure, onFileProgress } = input;
|
|
6438
|
+
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes } = input;
|
|
6253
6439
|
const totalFileCount = fileBatches.reduce((sum, batch) => sum + batch.length, 0);
|
|
6254
6440
|
const allDiagnostics = [];
|
|
6255
6441
|
const droppedFiles = [];
|
|
@@ -6257,7 +6443,7 @@ const spawnLintBatches = async (input) => {
|
|
|
6257
6443
|
const spawnLintBatch = async (batch) => {
|
|
6258
6444
|
const batchArgs = [...baseArgs, ...batch];
|
|
6259
6445
|
try {
|
|
6260
|
-
return parseOxlintOutput(await spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath), project, rootDirectory);
|
|
6446
|
+
return parseOxlintOutput(await spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, spawnTimeoutMs, outputMaxBytes), project, rootDirectory);
|
|
6261
6447
|
} catch (error) {
|
|
6262
6448
|
if (!isSplittableReactDoctorError(error)) throw error;
|
|
6263
6449
|
if (batch.length <= 1) {
|
|
@@ -6360,13 +6546,11 @@ const writeOxlintConfig = (configPath, configToWrite) => {
|
|
|
6360
6546
|
* 6. always restore disable directives + clean up the temp dir
|
|
6361
6547
|
*/
|
|
6362
6548
|
const runOxlint = async (options) => {
|
|
6363
|
-
const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure } = options;
|
|
6549
|
+
const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure, spawnTimeoutMs, outputMaxBytes } = options;
|
|
6364
6550
|
const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
6365
6551
|
const severityControls = buildRuleSeverityControls(userConfig);
|
|
6366
6552
|
validateRuleRegistration();
|
|
6367
6553
|
if (includePaths !== void 0 && includePaths.length === 0) return [];
|
|
6368
|
-
const configDirectory = fs.mkdtempSync(path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
|
|
6369
|
-
const configPath = path.join(configDirectory, "oxlintrc.json");
|
|
6370
6554
|
const pluginPath = resolvePluginPath();
|
|
6371
6555
|
const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
|
|
6372
6556
|
const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
|
|
@@ -6381,6 +6565,8 @@ const runOxlint = async (options) => {
|
|
|
6381
6565
|
userPlugins
|
|
6382
6566
|
});
|
|
6383
6567
|
const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
|
|
6568
|
+
const configDirectory = fs.mkdtempSync(path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
|
|
6569
|
+
const configPath = path.join(configDirectory, "oxlintrc.json");
|
|
6384
6570
|
try {
|
|
6385
6571
|
const baseArgs = [
|
|
6386
6572
|
resolveOxlintBinary(),
|
|
@@ -6407,7 +6593,9 @@ const runOxlint = async (options) => {
|
|
|
6407
6593
|
nodeBinaryPath,
|
|
6408
6594
|
project,
|
|
6409
6595
|
onPartialFailure,
|
|
6410
|
-
onFileProgress: options.onFileProgress
|
|
6596
|
+
onFileProgress: options.onFileProgress,
|
|
6597
|
+
spawnTimeoutMs,
|
|
6598
|
+
outputMaxBytes
|
|
6411
6599
|
});
|
|
6412
6600
|
writeOxlintConfig(configPath, buildConfig(extendsPaths));
|
|
6413
6601
|
try {
|
|
@@ -6473,6 +6661,8 @@ var Linter = class Linter extends Context.Service()("react-doctor/Linter") {
|
|
|
6473
6661
|
*/
|
|
6474
6662
|
static layerOxlint = Layer.succeed(Linter, Linter.of({ run: (input) => Stream.unwrap(Effect.fn("Linter.run")(function* () {
|
|
6475
6663
|
const partialFailures = yield* LintPartialFailures;
|
|
6664
|
+
const spawnTimeoutMs = yield* OxlintSpawnTimeoutMs;
|
|
6665
|
+
const outputMaxBytes = yield* OxlintOutputMaxBytes;
|
|
6476
6666
|
const collectedFailures = [];
|
|
6477
6667
|
const diagnostics = yield* Effect.tryPromise({
|
|
6478
6668
|
try: () => runOxlint({
|
|
@@ -6489,7 +6679,9 @@ var Linter = class Linter extends Context.Service()("react-doctor/Linter") {
|
|
|
6489
6679
|
onPartialFailure: (reason) => {
|
|
6490
6680
|
collectedFailures.push(reason);
|
|
6491
6681
|
},
|
|
6492
|
-
onFileProgress: input.onFileProgress
|
|
6682
|
+
onFileProgress: input.onFileProgress,
|
|
6683
|
+
spawnTimeoutMs,
|
|
6684
|
+
outputMaxBytes
|
|
6493
6685
|
}),
|
|
6494
6686
|
catch: ensureReactDoctorError
|
|
6495
6687
|
});
|
|
@@ -6787,7 +6979,7 @@ const runInspect = (input, hooks = {}) => Effect.gen(function* () {
|
|
|
6787
6979
|
const resolvedConfig = yield* configService.resolve(input.directory);
|
|
6788
6980
|
const scanDirectory = resolvedConfig.resolvedDirectory;
|
|
6789
6981
|
const project = yield* projectService.discover(scanDirectory);
|
|
6790
|
-
if (project
|
|
6982
|
+
if (!isAnalyzableProject(project)) return yield* new ReactDoctorError({ reason: new NoReactDependency({ directory: scanDirectory }) });
|
|
6791
6983
|
const [repo, sha, defaultBranch] = yield* Effect.all([
|
|
6792
6984
|
gitService.githubRepo(scanDirectory).pipe(Effect.orElseSucceed(() => null)),
|
|
6793
6985
|
gitService.headSha(scanDirectory).pipe(Effect.orElseSucceed(() => null)),
|
|
@@ -6815,7 +7007,8 @@ const runInspect = (input, hooks = {}) => Effect.gen(function* () {
|
|
|
6815
7007
|
const lintFailure = yield* Ref.make({
|
|
6816
7008
|
didFail: false,
|
|
6817
7009
|
reason: null,
|
|
6818
|
-
reasonTag: null
|
|
7010
|
+
reasonTag: null,
|
|
7011
|
+
reasonKind: null
|
|
6819
7012
|
});
|
|
6820
7013
|
const deadCodeFailure = yield* Ref.make({
|
|
6821
7014
|
didFail: false,
|
|
@@ -6837,13 +7030,14 @@ const runInspect = (input, hooks = {}) => Effect.gen(function* () {
|
|
|
6837
7030
|
configSourceDirectory: resolvedConfig.configSourceDirectory ?? void 0,
|
|
6838
7031
|
onFileProgress: (scannedFileCount, totalFileCount) => {
|
|
6839
7032
|
lastReportedTotalFileCount = totalFileCount;
|
|
6840
|
-
Effect.runSync(scanProgress.update(`Scanning (${scannedFileCount}/${totalFileCount})...`));
|
|
7033
|
+
Effect.runSync(scanProgress.update(`Scanning files (${scannedFileCount}/${totalFileCount})...`));
|
|
6841
7034
|
}
|
|
6842
7035
|
}).pipe(Stream.catchTag("ReactDoctorError", (error) => Stream.unwrap(Effect.gen(function* () {
|
|
6843
7036
|
yield* Ref.set(lintFailure, {
|
|
6844
7037
|
didFail: true,
|
|
6845
7038
|
reason: error.message,
|
|
6846
|
-
reasonTag: error.reason._tag
|
|
7039
|
+
reasonTag: error.reason._tag,
|
|
7040
|
+
reasonKind: error.reason._tag === "OxlintUnavailable" ? error.reason.kind : null
|
|
6847
7041
|
});
|
|
6848
7042
|
return Stream.empty;
|
|
6849
7043
|
}))));
|
|
@@ -6903,6 +7097,7 @@ const runInspect = (input, hooks = {}) => Effect.gen(function* () {
|
|
|
6903
7097
|
didLintFail: lintFailureState.didFail,
|
|
6904
7098
|
lintFailureReason: lintFailureState.reason,
|
|
6905
7099
|
lintFailureReasonTag: lintFailureState.reasonTag,
|
|
7100
|
+
lintFailureReasonKind: lintFailureState.reasonKind,
|
|
6906
7101
|
lintPartialFailures,
|
|
6907
7102
|
didDeadCodeFail: deadCodeFailureState.didFail,
|
|
6908
7103
|
deadCodeFailureReason: deadCodeFailureState.reason
|
|
@@ -7337,11 +7532,12 @@ const buildInspectProgram = (scanTarget, options, configOverride) => {
|
|
|
7337
7532
|
const outputToDiagnoseResult = (output, elapsedMilliseconds) => {
|
|
7338
7533
|
if (output.didLintFail && output.lintFailureReason !== null) console.error("Lint failed:", output.lintFailureReason);
|
|
7339
7534
|
const skippedChecks = [];
|
|
7535
|
+
if (output.didLintFail) skippedChecks.push("lint");
|
|
7536
|
+
if (output.didDeadCodeFail) skippedChecks.push("dead-code");
|
|
7340
7537
|
const skippedCheckReasons = {};
|
|
7341
|
-
if (output.
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
}
|
|
7538
|
+
if (output.didLintFail && output.lintFailureReason !== null) skippedCheckReasons.lint = output.lintFailureReason;
|
|
7539
|
+
else if (output.lintPartialFailures.length > 0) skippedCheckReasons["lint:partial"] = output.lintPartialFailures.join("; ");
|
|
7540
|
+
if (output.didDeadCodeFail && output.deadCodeFailureReason !== null) skippedCheckReasons["dead-code"] = output.deadCodeFailureReason;
|
|
7345
7541
|
return {
|
|
7346
7542
|
diagnostics: [...output.diagnostics],
|
|
7347
7543
|
score: output.score,
|