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
|
@@ -2281,15 +2281,91 @@ const detectFramework = (dependencies) => {
|
|
|
2281
2281
|
if (dependencies.preact && !dependencies.react) return "preact";
|
|
2282
2282
|
return "unknown";
|
|
2283
2283
|
};
|
|
2284
|
-
const UPPER_BOUND_COMPARATOR = /<\s*=?\s*\d+(?:\.\d+){0,2}(?:-[^\s,|]+)?/g;
|
|
2285
|
-
const HAS_UPPER_BOUND_COMPARATOR = /<\s*=?\s*\d+(?:\.\d+){0,2}(?:-[^\s,|]+)?/;
|
|
2286
|
-
const OR_SEPARATOR = /\s*\|\|\s*/;
|
|
2287
2284
|
const UNRESOLVABLE_PROTOCOL_VERSION = /^(?:file|git|github|https?|link|patch|portal|workspace|npm):/i;
|
|
2288
2285
|
const DIST_TAG_VERSION = /^[a-z][a-z0-9._-]*$/i;
|
|
2289
2286
|
const WILDCARD_VERSION = /^[*xX](?:\.[*xX])*$/;
|
|
2290
|
-
const NON_LOWER_BOUND_COMPARATOR = /(?:^|[\s,|])(?:>(?!=)|!={0,2})\s*\d/;
|
|
2291
|
-
const LOWER_BOUND_MAJOR = /(?:^|[\s,|])(?:>=\s*|[~^=v]\s*)?(\d+)(?=$|[\s,|.*xX-])/g;
|
|
2292
2287
|
const NPM_ALIAS_VERSION = /^npm:(?:@[^/]+\/[^@]+|[^@]+)@(.+)$/i;
|
|
2288
|
+
const isDigit = (value) => value !== void 0 && value >= "0" && value <= "9";
|
|
2289
|
+
const isWhitespace = (value) => value === " " || value === " " || value === "\n" || value === "\r" || value === "\f" || value === "\v";
|
|
2290
|
+
const isSeparator = (value) => isWhitespace(value) || value === "," || value === "|";
|
|
2291
|
+
const skipWhitespace = (value, start) => {
|
|
2292
|
+
let index = start;
|
|
2293
|
+
while (isWhitespace(value[index])) index += 1;
|
|
2294
|
+
return index;
|
|
2295
|
+
};
|
|
2296
|
+
const skipSeparators = (value, start) => {
|
|
2297
|
+
let index = start;
|
|
2298
|
+
while (isSeparator(value[index])) index += 1;
|
|
2299
|
+
return index;
|
|
2300
|
+
};
|
|
2301
|
+
const readDigits = (value, start) => {
|
|
2302
|
+
let index = start;
|
|
2303
|
+
while (isDigit(value[index])) index += 1;
|
|
2304
|
+
return index;
|
|
2305
|
+
};
|
|
2306
|
+
const getUpperBoundComparatorEnd = (version, start) => {
|
|
2307
|
+
if (version[start] !== "<") return null;
|
|
2308
|
+
let index = skipWhitespace(version, start + 1);
|
|
2309
|
+
if (version[index] === "=") index = skipWhitespace(version, index + 1);
|
|
2310
|
+
const majorStart = index;
|
|
2311
|
+
index = readDigits(version, index);
|
|
2312
|
+
if (index === majorStart) return null;
|
|
2313
|
+
for (let segments = 0; segments < 2 && version[index] === "."; segments += 1) {
|
|
2314
|
+
const segmentStart = index + 1;
|
|
2315
|
+
const segmentEnd = readDigits(version, segmentStart);
|
|
2316
|
+
if (segmentEnd === segmentStart) break;
|
|
2317
|
+
index = segmentEnd;
|
|
2318
|
+
}
|
|
2319
|
+
if (version[index] === "-") {
|
|
2320
|
+
index += 1;
|
|
2321
|
+
while (index < version.length && !isSeparator(version[index])) index += 1;
|
|
2322
|
+
}
|
|
2323
|
+
return index;
|
|
2324
|
+
};
|
|
2325
|
+
const stripUpperBoundComparators = (version) => {
|
|
2326
|
+
let stripped = "";
|
|
2327
|
+
let index = 0;
|
|
2328
|
+
while (index < version.length) {
|
|
2329
|
+
const comparatorEnd = getUpperBoundComparatorEnd(version, index);
|
|
2330
|
+
if (comparatorEnd === null) {
|
|
2331
|
+
stripped += version[index];
|
|
2332
|
+
index += 1;
|
|
2333
|
+
continue;
|
|
2334
|
+
}
|
|
2335
|
+
stripped += " ";
|
|
2336
|
+
index = comparatorEnd;
|
|
2337
|
+
}
|
|
2338
|
+
return stripped;
|
|
2339
|
+
};
|
|
2340
|
+
const hasNonLowerBoundComparator = (branch) => {
|
|
2341
|
+
for (let index = 0; index < branch.length; index += 1) {
|
|
2342
|
+
if (index > 0 && !isSeparator(branch[index - 1])) continue;
|
|
2343
|
+
if (branch[index] === ">" && branch[index + 1] !== "=") {
|
|
2344
|
+
if (isDigit(branch[skipWhitespace(branch, index + 1)])) return true;
|
|
2345
|
+
continue;
|
|
2346
|
+
}
|
|
2347
|
+
if (branch[index] !== "!") continue;
|
|
2348
|
+
let valueIndex = index + 1;
|
|
2349
|
+
if (branch[valueIndex] === "=") valueIndex += 1;
|
|
2350
|
+
if (branch[valueIndex] === "=") valueIndex += 1;
|
|
2351
|
+
valueIndex = skipWhitespace(branch, valueIndex);
|
|
2352
|
+
if (isDigit(branch[valueIndex])) return true;
|
|
2353
|
+
}
|
|
2354
|
+
return false;
|
|
2355
|
+
};
|
|
2356
|
+
const isMajorTerminator = (value) => value === void 0 || isSeparator(value) || value === "." || value === "*" || value === "x" || value === "X" || value === "-";
|
|
2357
|
+
const getLowerBoundMajorAt = (branch, start) => {
|
|
2358
|
+
let index = start;
|
|
2359
|
+
if (branch[index] === ">" && branch[index + 1] === "=") index = skipWhitespace(branch, index + 2);
|
|
2360
|
+
else if (branch[index] === "~" || branch[index] === "^" || branch[index] === "=" || branch[index] === "v") index = skipWhitespace(branch, index + 1);
|
|
2361
|
+
const majorStart = index;
|
|
2362
|
+
const majorEnd = readDigits(branch, majorStart);
|
|
2363
|
+
if (majorEnd === majorStart || !isMajorTerminator(branch[majorEnd])) return null;
|
|
2364
|
+
return {
|
|
2365
|
+
end: majorEnd,
|
|
2366
|
+
major: Number.parseInt(branch.slice(majorStart, majorEnd), 10)
|
|
2367
|
+
};
|
|
2368
|
+
};
|
|
2293
2369
|
const normalizeDependencyVersion = (version) => {
|
|
2294
2370
|
const trimmed = version.trim();
|
|
2295
2371
|
if (trimmed.length === 0) return null;
|
|
@@ -2299,17 +2375,29 @@ const normalizeDependencyVersion = (version) => {
|
|
|
2299
2375
|
if (WILDCARD_VERSION.test(normalizedVersion)) return null;
|
|
2300
2376
|
return normalizedVersion;
|
|
2301
2377
|
};
|
|
2302
|
-
const splitDependencyVersionBranches = (version) => version.split(
|
|
2303
|
-
const hasUpperBoundComparator = (version) =>
|
|
2378
|
+
const splitDependencyVersionBranches = (version) => version.split("||").map((branch) => branch.trim()).filter(Boolean);
|
|
2379
|
+
const hasUpperBoundComparator = (version) => {
|
|
2380
|
+
for (let index = 0; index < version.length; index += 1) if (getUpperBoundComparatorEnd(version, index) !== null) return true;
|
|
2381
|
+
return false;
|
|
2382
|
+
};
|
|
2304
2383
|
const getBranchLowestMajor = (branch) => {
|
|
2305
|
-
if (
|
|
2306
|
-
const lowerBoundComparators = branch
|
|
2384
|
+
if (hasNonLowerBoundComparator(branch)) return null;
|
|
2385
|
+
const lowerBoundComparators = stripUpperBoundComparators(branch).trim();
|
|
2307
2386
|
if (lowerBoundComparators.length === 0) return null;
|
|
2308
2387
|
let branchLowestMajor = null;
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
if (
|
|
2388
|
+
let index = 0;
|
|
2389
|
+
while (index < lowerBoundComparators.length) {
|
|
2390
|
+
const lowerBoundStart = skipSeparators(lowerBoundComparators, index);
|
|
2391
|
+
if (lowerBoundStart > 0 && !isSeparator(lowerBoundComparators[lowerBoundStart - 1])) {
|
|
2392
|
+
index = lowerBoundStart + 1;
|
|
2393
|
+
continue;
|
|
2394
|
+
}
|
|
2395
|
+
const lowerBoundMajor = getLowerBoundMajorAt(lowerBoundComparators, lowerBoundStart);
|
|
2396
|
+
if (lowerBoundMajor !== null && Number.isFinite(lowerBoundMajor.major) && lowerBoundMajor.major > 0) {
|
|
2397
|
+
const major = lowerBoundMajor.major;
|
|
2398
|
+
if (branchLowestMajor === null || major < branchLowestMajor) branchLowestMajor = major;
|
|
2399
|
+
}
|
|
2400
|
+
index = lowerBoundMajor?.end ?? lowerBoundStart + 1;
|
|
2313
2401
|
}
|
|
2314
2402
|
return branchLowestMajor;
|
|
2315
2403
|
};
|
|
@@ -2478,6 +2566,7 @@ const resolveCatalogVersion = (packageJson, packageName, rootDirectory, explicit
|
|
|
2478
2566
|
const EMPTY_DEPENDENCY_INFO = {
|
|
2479
2567
|
reactVersion: null,
|
|
2480
2568
|
tailwindVersion: null,
|
|
2569
|
+
zodVersion: null,
|
|
2481
2570
|
framework: "unknown"
|
|
2482
2571
|
};
|
|
2483
2572
|
const pickConcreteVersion = (packageJson, packageName, sections) => {
|
|
@@ -2506,6 +2595,11 @@ const extractDependencyInfo = (packageJson) => {
|
|
|
2506
2595
|
"devDependencies",
|
|
2507
2596
|
"peerDependencies"
|
|
2508
2597
|
]),
|
|
2598
|
+
zodVersion: pickConcreteVersion(packageJson, "zod", [
|
|
2599
|
+
"dependencies",
|
|
2600
|
+
"devDependencies",
|
|
2601
|
+
"peerDependencies"
|
|
2602
|
+
]),
|
|
2509
2603
|
framework: detectFramework(allDependencies)
|
|
2510
2604
|
};
|
|
2511
2605
|
};
|
|
@@ -2650,8 +2744,22 @@ const findReactInWorkspaces = (rootDirectory, packageJson) => {
|
|
|
2650
2744
|
workspaceDirectory,
|
|
2651
2745
|
workspacePackageJson
|
|
2652
2746
|
});
|
|
2747
|
+
const zodVersion = resolveWorkspaceDependencyVersion({
|
|
2748
|
+
concreteVersion: info.zodVersion,
|
|
2749
|
+
packageName: "zod",
|
|
2750
|
+
rootDirectory,
|
|
2751
|
+
rootPackageJson: packageJson,
|
|
2752
|
+
sections: [
|
|
2753
|
+
"dependencies",
|
|
2754
|
+
"devDependencies",
|
|
2755
|
+
"peerDependencies"
|
|
2756
|
+
],
|
|
2757
|
+
workspaceDirectory,
|
|
2758
|
+
workspacePackageJson
|
|
2759
|
+
});
|
|
2653
2760
|
if (reactVersion && shouldReplaceReactVersion(result.reactVersion, reactVersion)) result.reactVersion = reactVersion;
|
|
2654
2761
|
if (tailwindVersion && !result.tailwindVersion) result.tailwindVersion = tailwindVersion;
|
|
2762
|
+
if (zodVersion && !result.zodVersion) result.zodVersion = zodVersion;
|
|
2655
2763
|
if (info.framework !== "unknown" && result.framework === "unknown") result.framework = info.framework;
|
|
2656
2764
|
const resultReactMajor = parseReactMajor(result.reactVersion);
|
|
2657
2765
|
if (result.reactVersion && result.tailwindVersion && result.framework !== "unknown" && resultReactMajor !== null && resultReactMajor <= 17) return result;
|
|
@@ -2686,14 +2794,26 @@ const findDependencyInfoFromMonorepoRoot = (directory) => {
|
|
|
2686
2794
|
"peerDependencies"
|
|
2687
2795
|
]
|
|
2688
2796
|
}) : null;
|
|
2797
|
+
const leafZodDeclaration = leafPackageJson ? getDependencyDeclaration({
|
|
2798
|
+
packageJson: leafPackageJson,
|
|
2799
|
+
packageName: "zod",
|
|
2800
|
+
sections: [
|
|
2801
|
+
"dependencies",
|
|
2802
|
+
"devDependencies",
|
|
2803
|
+
"peerDependencies"
|
|
2804
|
+
]
|
|
2805
|
+
}) : null;
|
|
2689
2806
|
const shouldUseReactFallback = !leafReactDeclaration?.hasDeclaration;
|
|
2690
2807
|
const shouldUseTailwindFallback = leafTailwindDeclaration?.hasDeclaration ?? true;
|
|
2808
|
+
const shouldUseZodFallback = leafZodDeclaration?.hasDeclaration ?? true;
|
|
2691
2809
|
const reactCatalogVersion = shouldUseReactFallback ? resolveCatalogVersion(rootPackageJson, "react", monorepoRoot, leafReactDeclaration?.catalogReference) : null;
|
|
2692
2810
|
const tailwindCatalogVersion = shouldUseTailwindFallback ? resolveCatalogVersion(rootPackageJson, "tailwindcss", monorepoRoot, leafTailwindDeclaration?.catalogReference) : null;
|
|
2811
|
+
const zodCatalogVersion = shouldUseZodFallback ? resolveCatalogVersion(rootPackageJson, "zod", monorepoRoot, leafZodDeclaration?.catalogReference) : null;
|
|
2693
2812
|
const workspaceInfo = findReactInWorkspaces(monorepoRoot, rootPackageJson);
|
|
2694
2813
|
return {
|
|
2695
2814
|
reactVersion: shouldUseReactFallback ? reactCatalogVersion ?? rootInfo.reactVersion ?? workspaceInfo.reactVersion : rootInfo.reactVersion ?? workspaceInfo.reactVersion,
|
|
2696
2815
|
tailwindVersion: shouldUseTailwindFallback ? tailwindCatalogVersion ?? rootInfo.tailwindVersion ?? workspaceInfo.tailwindVersion : null,
|
|
2816
|
+
zodVersion: shouldUseZodFallback ? zodCatalogVersion ?? rootInfo.zodVersion ?? workspaceInfo.zodVersion : null,
|
|
2697
2817
|
framework: rootInfo.framework !== "unknown" ? rootInfo.framework : workspaceInfo.framework
|
|
2698
2818
|
};
|
|
2699
2819
|
};
|
|
@@ -2743,12 +2863,12 @@ const isPackageJsonReactNativeAware = (packageJson) => {
|
|
|
2743
2863
|
return false;
|
|
2744
2864
|
};
|
|
2745
2865
|
const hasReactNativeWorkspaceAnywhere = (rootDirectory, rootPackageJson) => someWorkspacePackageJson(rootDirectory, rootPackageJson, isPackageJsonReactNativeAware);
|
|
2746
|
-
const
|
|
2747
|
-
return
|
|
2866
|
+
const getPreactVersion = (packageJson) => {
|
|
2867
|
+
return {
|
|
2748
2868
|
...packageJson.peerDependencies,
|
|
2749
2869
|
...packageJson.dependencies,
|
|
2750
2870
|
...packageJson.devDependencies
|
|
2751
|
-
};
|
|
2871
|
+
}.preact ?? null;
|
|
2752
2872
|
};
|
|
2753
2873
|
const TANSTACK_QUERY_PACKAGES = new Set([
|
|
2754
2874
|
"@tanstack/react-query",
|
|
@@ -2773,6 +2893,10 @@ const isPackageJsonReanimatedAware = (packageJson) => {
|
|
|
2773
2893
|
};
|
|
2774
2894
|
return Object.hasOwn(allDependencies, REANIMATED_DEPENDENCY_NAME);
|
|
2775
2895
|
};
|
|
2896
|
+
const parseZodMajor = (zodVersion) => {
|
|
2897
|
+
if (typeof zodVersion !== "string") return null;
|
|
2898
|
+
return getLowestDependencyMajor(zodVersion);
|
|
2899
|
+
};
|
|
2776
2900
|
const hasUpperBoundOnlyPeerRange = (range) => {
|
|
2777
2901
|
if (typeof range !== "string") return false;
|
|
2778
2902
|
const normalizedRange = normalizeDependencyVersion(range);
|
|
@@ -2859,12 +2983,22 @@ const listManifestWorkspacePackages = (rootDirectory) => {
|
|
|
2859
2983
|
const nxPatterns = patterns.length > 0 ? [] : getNxWorkspaceDirectories(rootDirectory);
|
|
2860
2984
|
return toReactWorkspacePackages((patterns.length > 0 ? patterns : nxPatterns).flatMap((pattern) => resolveWorkspaceDirectories(rootDirectory, pattern)));
|
|
2861
2985
|
};
|
|
2986
|
+
const NON_PROJECT_DIRECTORIES = new Set([
|
|
2987
|
+
"AppData",
|
|
2988
|
+
"Application Data",
|
|
2989
|
+
"Library"
|
|
2990
|
+
]);
|
|
2991
|
+
const MAX_SCAN_DEPTH = 6;
|
|
2862
2992
|
const discoverReactSubprojectsByFilesystem = (rootDirectory) => {
|
|
2863
2993
|
const packages = [];
|
|
2864
|
-
const pendingDirectories = [
|
|
2994
|
+
const pendingDirectories = [{
|
|
2995
|
+
directory: rootDirectory,
|
|
2996
|
+
depth: 0
|
|
2997
|
+
}];
|
|
2865
2998
|
while (pendingDirectories.length > 0) {
|
|
2866
|
-
const
|
|
2867
|
-
if (!
|
|
2999
|
+
const current = pendingDirectories.pop();
|
|
3000
|
+
if (!current) continue;
|
|
3001
|
+
const { directory: currentDirectory, depth } = current;
|
|
2868
3002
|
const packageJsonPath = path.join(currentDirectory, "package.json");
|
|
2869
3003
|
if (isFile(packageJsonPath)) {
|
|
2870
3004
|
const packageJson = readPackageJson(packageJsonPath);
|
|
@@ -2876,10 +3010,14 @@ const discoverReactSubprojectsByFilesystem = (rootDirectory) => {
|
|
|
2876
3010
|
});
|
|
2877
3011
|
}
|
|
2878
3012
|
}
|
|
3013
|
+
if (depth >= MAX_SCAN_DEPTH) continue;
|
|
2879
3014
|
const entries = readDirectoryEntries(currentDirectory).toSorted((firstEntry, secondEntry) => firstEntry.name.localeCompare(secondEntry.name));
|
|
2880
3015
|
for (const entry of entries) {
|
|
2881
|
-
if (!entry.isDirectory() || entry.name.startsWith(".") || IGNORED_DIRECTORIES.has(entry.name)) continue;
|
|
2882
|
-
pendingDirectories.push(
|
|
3016
|
+
if (!entry.isDirectory() || entry.name.startsWith(".") || IGNORED_DIRECTORIES.has(entry.name) || NON_PROJECT_DIRECTORIES.has(entry.name)) continue;
|
|
3017
|
+
pendingDirectories.push({
|
|
3018
|
+
directory: path.join(currentDirectory, entry.name),
|
|
3019
|
+
depth: depth + 1
|
|
3020
|
+
});
|
|
2883
3021
|
}
|
|
2884
3022
|
}
|
|
2885
3023
|
return packages;
|
|
@@ -2897,7 +3035,7 @@ const discoverProject = (directory) => {
|
|
|
2897
3035
|
const packageJsonPath = path.join(directory, "package.json");
|
|
2898
3036
|
if (!isFile(packageJsonPath)) throw new PackageJsonNotFoundError(directory);
|
|
2899
3037
|
const packageJson = readPackageJson(packageJsonPath);
|
|
2900
|
-
let { reactVersion, tailwindVersion, framework } = extractDependencyInfo(packageJson);
|
|
3038
|
+
let { reactVersion, tailwindVersion, zodVersion, framework } = extractDependencyInfo(packageJson);
|
|
2901
3039
|
const reactDeclaration = getDependencyDeclaration({
|
|
2902
3040
|
packageJson,
|
|
2903
3041
|
packageName: "react",
|
|
@@ -2916,9 +3054,19 @@ const discoverProject = (directory) => {
|
|
|
2916
3054
|
"peerDependencies"
|
|
2917
3055
|
]
|
|
2918
3056
|
});
|
|
3057
|
+
const zodDeclaration = getDependencyDeclaration({
|
|
3058
|
+
packageJson,
|
|
3059
|
+
packageName: "zod",
|
|
3060
|
+
sections: [
|
|
3061
|
+
"dependencies",
|
|
3062
|
+
"devDependencies",
|
|
3063
|
+
"peerDependencies"
|
|
3064
|
+
]
|
|
3065
|
+
});
|
|
2919
3066
|
if (!reactVersion && reactDeclaration.hasDeclaration) reactVersion = resolveCatalogVersion(packageJson, "react", directory, reactDeclaration.catalogReference);
|
|
2920
3067
|
if (!tailwindVersion && tailwindDeclaration.hasDeclaration) tailwindVersion = resolveCatalogVersion(packageJson, "tailwindcss", directory, tailwindDeclaration.catalogReference);
|
|
2921
|
-
if (!
|
|
3068
|
+
if (!zodVersion && zodDeclaration.hasDeclaration) zodVersion = resolveCatalogVersion(packageJson, "zod", directory, zodDeclaration.catalogReference);
|
|
3069
|
+
if (!reactVersion || !tailwindVersion || !zodVersion) {
|
|
2922
3070
|
const monorepoRoot = findMonorepoRoot(directory);
|
|
2923
3071
|
if (monorepoRoot) {
|
|
2924
3072
|
const monorepoPackageJsonPath = path.join(monorepoRoot, "package.json");
|
|
@@ -2926,6 +3074,7 @@ const discoverProject = (directory) => {
|
|
|
2926
3074
|
const rootPackageJson = readPackageJson(monorepoPackageJsonPath);
|
|
2927
3075
|
if (!reactVersion && reactDeclaration.hasDeclaration) reactVersion = resolveCatalogVersion(rootPackageJson, "react", monorepoRoot, reactDeclaration.catalogReference);
|
|
2928
3076
|
if (!tailwindVersion && tailwindDeclaration.hasDeclaration) tailwindVersion = resolveCatalogVersion(rootPackageJson, "tailwindcss", monorepoRoot, tailwindDeclaration.catalogReference);
|
|
3077
|
+
if (!zodVersion && zodDeclaration.hasDeclaration) zodVersion = resolveCatalogVersion(rootPackageJson, "zod", monorepoRoot, zodDeclaration.catalogReference);
|
|
2929
3078
|
}
|
|
2930
3079
|
}
|
|
2931
3080
|
}
|
|
@@ -2933,32 +3082,39 @@ const discoverProject = (directory) => {
|
|
|
2933
3082
|
const workspaceInfo = findReactInWorkspaces(directory, packageJson);
|
|
2934
3083
|
if (!reactVersion && workspaceInfo.reactVersion) reactVersion = workspaceInfo.reactVersion;
|
|
2935
3084
|
if (!tailwindVersion && workspaceInfo.tailwindVersion) tailwindVersion = workspaceInfo.tailwindVersion;
|
|
3085
|
+
if (!zodVersion && workspaceInfo.zodVersion) zodVersion = workspaceInfo.zodVersion;
|
|
2936
3086
|
if (framework === "unknown" && workspaceInfo.framework !== "unknown") framework = workspaceInfo.framework;
|
|
2937
3087
|
}
|
|
2938
3088
|
if ((!reactVersion || framework === "unknown") && !isMonorepoRoot(directory)) {
|
|
2939
3089
|
const monorepoInfo = findDependencyInfoFromMonorepoRoot(directory);
|
|
2940
3090
|
if (!reactVersion) reactVersion = monorepoInfo.reactVersion;
|
|
2941
3091
|
if (!tailwindVersion) tailwindVersion = monorepoInfo.tailwindVersion;
|
|
3092
|
+
if (!zodVersion) zodVersion = monorepoInfo.zodVersion;
|
|
2942
3093
|
if (framework === "unknown") framework = monorepoInfo.framework;
|
|
2943
3094
|
}
|
|
2944
3095
|
if (!reactVersion && reactDeclaration.version && !isCatalogReference(reactDeclaration.version)) reactVersion = reactDeclaration.version;
|
|
2945
3096
|
if (!tailwindVersion && tailwindDeclaration.version && !isCatalogReference(tailwindDeclaration.version)) tailwindVersion = tailwindDeclaration.version;
|
|
3097
|
+
if (!zodVersion && zodDeclaration.version && !isCatalogReference(zodDeclaration.version)) zodVersion = zodDeclaration.version;
|
|
2946
3098
|
const projectName = packageJson.name ?? path.basename(directory);
|
|
2947
3099
|
const hasTypeScript = fs.existsSync(path.join(directory, "tsconfig.json"));
|
|
2948
3100
|
const sourceFileCount = countSourceFiles(directory);
|
|
2949
3101
|
const hasReactNativeWorkspace = framework === "expo" || framework === "react-native" || hasReactNativeWorkspaceAnywhere(directory, packageJson);
|
|
2950
3102
|
const hasReanimated = hasReactNativeWorkspace && someWorkspacePackageJson(directory, packageJson, isPackageJsonReanimatedAware);
|
|
3103
|
+
const preactVersion = getPreactVersion(packageJson);
|
|
2951
3104
|
const projectInfo = {
|
|
2952
3105
|
rootDirectory: directory,
|
|
2953
3106
|
projectName,
|
|
2954
3107
|
reactVersion,
|
|
2955
3108
|
reactMajorVersion: resolveEffectiveReactMajor(reactVersion, packageJson),
|
|
2956
3109
|
tailwindVersion,
|
|
3110
|
+
zodVersion,
|
|
3111
|
+
zodMajorVersion: parseZodMajor(zodVersion),
|
|
2957
3112
|
framework,
|
|
2958
3113
|
hasTypeScript,
|
|
2959
3114
|
hasReactCompiler: detectReactCompiler(directory, packageJson),
|
|
2960
3115
|
hasTanStackQuery: hasTanStackQuery(packageJson),
|
|
2961
|
-
|
|
3116
|
+
preactVersion,
|
|
3117
|
+
preactMajorVersion: parseReactMajor(preactVersion),
|
|
2962
3118
|
hasReactNativeWorkspace,
|
|
2963
3119
|
hasReanimated,
|
|
2964
3120
|
sourceFileCount
|
|
@@ -2966,6 +3122,7 @@ const discoverProject = (directory) => {
|
|
|
2966
3122
|
cachedProjectInfos.set(directory, projectInfo);
|
|
2967
3123
|
return projectInfo;
|
|
2968
3124
|
};
|
|
3125
|
+
const isAnalyzableProject = (project) => project.reactVersion !== null || project.preactVersion !== null;
|
|
2969
3126
|
const MAJOR_MINOR_PATTERN = /(\d{1,4})\.(\d{1,4})/;
|
|
2970
3127
|
const MAJOR_ONLY_PATTERN = /(\d{1,4})/;
|
|
2971
3128
|
const UPPER_BOUND_COMPARATOR_PATTERN = /<=?\s{0,8}\d{1,4}(?:\.\d{1,4}){0,2}(?:-[^\s,|]+)?/g;
|
|
@@ -3033,6 +3190,7 @@ const JSX_FILE_PATTERN = /\.(tsx|jsx)$/;
|
|
|
3033
3190
|
const MILLISECONDS_PER_SECOND = 1e3;
|
|
3034
3191
|
const SCORE_API_URL = "https://www.react.doctor/api/score";
|
|
3035
3192
|
const SHARE_BASE_URL = "https://www.react.doctor/share";
|
|
3193
|
+
const PROMPTS_RULES_BASE_URL = "https://www.react.doctor/prompts/rules";
|
|
3036
3194
|
const FETCH_TIMEOUT_MS = 1e4;
|
|
3037
3195
|
const GITHUB_VIEWER_PERMISSION_TIMEOUT_MS = 2e3;
|
|
3038
3196
|
const DEFAULT_BRANCH_CANDIDATES = ["main", "master"];
|
|
@@ -3935,17 +4093,26 @@ const layerOtlp = Layer.unwrap(Effect.gen(function* () {
|
|
|
3935
4093
|
headers
|
|
3936
4094
|
}).pipe(Layer.provide(FetchHttpClient.layer));
|
|
3937
4095
|
}).pipe(Effect.orDie));
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
4096
|
+
/**
|
|
4097
|
+
* Per-batch oxlint wall-clock budget. Reads from the env var on
|
|
4098
|
+
* startup so the eval harness can raise the budget under sandbox
|
|
4099
|
+
* microVMs without recompiling react-doctor. Tests override via
|
|
4100
|
+
* `Layer.succeed(OxlintSpawnTimeoutMs, ...)`.
|
|
4101
|
+
*/
|
|
4102
|
+
var OxlintSpawnTimeoutMs = class extends Context.Reference("react-doctor/OxlintSpawnTimeoutMs", { defaultValue: () => {
|
|
3941
4103
|
const raw = process.env["REACT_DOCTOR_OXLINT_SPAWN_TIMEOUT_MS"];
|
|
3942
4104
|
if (raw === void 0) return OXLINT_SPAWN_TIMEOUT_MS;
|
|
3943
4105
|
const parsed = Number(raw);
|
|
3944
4106
|
if (!Number.isFinite(parsed) || parsed <= 0) return OXLINT_SPAWN_TIMEOUT_MS;
|
|
3945
4107
|
return parsed;
|
|
3946
|
-
} });
|
|
3947
|
-
|
|
3948
|
-
|
|
4108
|
+
} }) {};
|
|
4109
|
+
/**
|
|
4110
|
+
* Hard cap on combined stdout+stderr bytes per oxlint batch. The
|
|
4111
|
+
* subprocess gets SIGKILL'd if it produces more; the recovery path
|
|
4112
|
+
* suggests narrowing the scan with --diff. Override via Layer in
|
|
4113
|
+
* tests that exercise the cap behavior.
|
|
4114
|
+
*/
|
|
4115
|
+
var OxlintOutputMaxBytes = class extends Context.Reference("react-doctor/OxlintOutputMaxBytes", { defaultValue: () => OXLINT_OUTPUT_MAX_BYTES }) {};
|
|
3949
4116
|
const DIAGNOSTIC_SURFACES = [
|
|
3950
4117
|
"cli",
|
|
3951
4118
|
"prComment",
|
|
@@ -5013,8 +5180,15 @@ var Git = class Git extends Context.Service()("react-doctor/Git") {
|
|
|
5013
5180
|
env: input.env,
|
|
5014
5181
|
extendEnv: true
|
|
5015
5182
|
}));
|
|
5183
|
+
const maxStdoutBytes = input.maxStdoutBytes;
|
|
5184
|
+
const stdoutByteCount = yield* Ref.make(0);
|
|
5185
|
+
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({
|
|
5186
|
+
args: [...input.args],
|
|
5187
|
+
directory: input.directory,
|
|
5188
|
+
cause: /* @__PURE__ */ new Error(`git stdout exceeded ${maxStdoutBytes} bytes`)
|
|
5189
|
+
}) })) : Effect.void))));
|
|
5016
5190
|
const [stdout, stderr, status] = yield* Effect.all([
|
|
5017
|
-
Stream.mkString(Stream.decodeText(
|
|
5191
|
+
Stream.mkString(Stream.decodeText(stdoutStream)),
|
|
5018
5192
|
Stream.mkString(Stream.decodeText(handle.stderr)),
|
|
5019
5193
|
handle.exitCode
|
|
5020
5194
|
], { concurrency: 3 });
|
|
@@ -5176,7 +5350,12 @@ var Git = class Git extends Context.Service()("react-doctor/Git") {
|
|
|
5176
5350
|
if (result.status !== 0) return [];
|
|
5177
5351
|
return splitNullSeparated(result.stdout);
|
|
5178
5352
|
})),
|
|
5179
|
-
showStagedContent: (directory, relativePath) =>
|
|
5353
|
+
showStagedContent: (directory, relativePath, options) => runCommand({
|
|
5354
|
+
command: "git",
|
|
5355
|
+
args: ["show", `:${relativePath}`],
|
|
5356
|
+
directory,
|
|
5357
|
+
maxStdoutBytes: options?.maxBufferBytes
|
|
5358
|
+
}).pipe(Effect.map((result) => result.status === 0 ? result.stdout : null)),
|
|
5180
5359
|
grep: (input) => Effect.gen(function* () {
|
|
5181
5360
|
const args = ["grep"];
|
|
5182
5361
|
if (input.listMatchingFiles ?? true) args.push("-l");
|
|
@@ -5184,7 +5363,12 @@ var Git = class Git extends Context.Service()("react-doctor/Git") {
|
|
|
5184
5363
|
if (input.extendedRegexp ?? false) args.push("-E");
|
|
5185
5364
|
args.push(input.pattern);
|
|
5186
5365
|
if (input.includePaths && input.includePaths.length > 0) args.push("--", ...input.includePaths);
|
|
5187
|
-
const result = yield*
|
|
5366
|
+
const result = yield* runCommand({
|
|
5367
|
+
command: "git",
|
|
5368
|
+
args,
|
|
5369
|
+
directory: input.directory,
|
|
5370
|
+
maxStdoutBytes: input.maxBufferBytes
|
|
5371
|
+
});
|
|
5188
5372
|
if (result.status === 128) return null;
|
|
5189
5373
|
return {
|
|
5190
5374
|
status: result.status,
|
|
@@ -5432,7 +5616,8 @@ const buildCapabilities = (project) => {
|
|
|
5432
5616
|
if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
|
|
5433
5617
|
const reactMajor = project.reactMajorVersion;
|
|
5434
5618
|
if (reactMajor !== null) {
|
|
5435
|
-
|
|
5619
|
+
const cappedReactMajor = Math.min(reactMajor, 30);
|
|
5620
|
+
for (let major = 17; major <= cappedReactMajor; major++) capabilities.add(`react:${major}`);
|
|
5436
5621
|
if (reactMajor >= 19) {
|
|
5437
5622
|
if (isReactAtLeast(parseReactMajorMinor(project.reactVersion), {
|
|
5438
5623
|
major: 19,
|
|
@@ -5447,11 +5632,20 @@ const buildCapabilities = (project) => {
|
|
|
5447
5632
|
minor: 4
|
|
5448
5633
|
})) capabilities.add("tailwind:3.4");
|
|
5449
5634
|
}
|
|
5635
|
+
if (project.zodVersion !== null) {
|
|
5636
|
+
capabilities.add("zod");
|
|
5637
|
+
if (project.zodMajorVersion !== null && project.zodMajorVersion >= 4) capabilities.add("zod:4");
|
|
5638
|
+
}
|
|
5450
5639
|
if (project.hasReactCompiler) capabilities.add("react-compiler");
|
|
5451
5640
|
if (project.hasTanStackQuery) capabilities.add("tanstack-query");
|
|
5452
5641
|
if (project.hasTypeScript) capabilities.add("typescript");
|
|
5453
|
-
if (project.
|
|
5642
|
+
if (project.preactVersion !== null) {
|
|
5454
5643
|
capabilities.add("preact");
|
|
5644
|
+
const preactMajor = project.preactMajorVersion;
|
|
5645
|
+
if (preactMajor !== null) {
|
|
5646
|
+
const cappedPreactMajor = Math.min(preactMajor, 20);
|
|
5647
|
+
for (let major = 10; major <= cappedPreactMajor; major++) capabilities.add(`preact:${major}`);
|
|
5648
|
+
}
|
|
5455
5649
|
if (project.reactVersion === null) capabilities.add("pure-preact");
|
|
5456
5650
|
}
|
|
5457
5651
|
return capabilities;
|
|
@@ -6107,13 +6301,6 @@ const SANITIZED_ENV = (() => {
|
|
|
6107
6301
|
}
|
|
6108
6302
|
return sanitized;
|
|
6109
6303
|
})();
|
|
6110
|
-
const OXLINT_SPAWN_TIMEOUT_MS$1 = (() => {
|
|
6111
|
-
const raw = process.env["REACT_DOCTOR_OXLINT_SPAWN_TIMEOUT_MS"];
|
|
6112
|
-
if (raw === void 0) return OXLINT_SPAWN_TIMEOUT_MS;
|
|
6113
|
-
const parsed = Number(raw);
|
|
6114
|
-
if (!Number.isFinite(parsed) || parsed <= 0) return OXLINT_SPAWN_TIMEOUT_MS;
|
|
6115
|
-
return parsed;
|
|
6116
|
-
})();
|
|
6117
6304
|
/**
|
|
6118
6305
|
* Spawn one oxlint subprocess with hard ceilings on wall time and
|
|
6119
6306
|
* output size. Returns stdout on success; raises a tagged
|
|
@@ -6130,7 +6317,7 @@ const OXLINT_SPAWN_TIMEOUT_MS$1 = (() => {
|
|
|
6130
6317
|
* The first three are splittable (the caller's binary-split retry
|
|
6131
6318
|
* shrinks the batch and re-spawns); the fourth isn't.
|
|
6132
6319
|
*/
|
|
6133
|
-
const spawnOxlint = (args, rootDirectory, nodeBinaryPath) => new Promise((resolve, reject) => {
|
|
6320
|
+
const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLINT_SPAWN_TIMEOUT_MS, outputMaxBytes = OXLINT_OUTPUT_MAX_BYTES) => new Promise((resolve, reject) => {
|
|
6134
6321
|
const child = spawn(nodeBinaryPath, args, {
|
|
6135
6322
|
cwd: rootDirectory,
|
|
6136
6323
|
env: SANITIZED_ENV
|
|
@@ -6139,9 +6326,9 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath) => new Promise((resolv
|
|
|
6139
6326
|
child.kill("SIGKILL");
|
|
6140
6327
|
reject(new ReactDoctorError({ reason: new OxlintBatchExceeded({
|
|
6141
6328
|
kind: "timeout",
|
|
6142
|
-
detail: `${
|
|
6329
|
+
detail: `${spawnTimeoutMs / 1e3}s budget exceeded`
|
|
6143
6330
|
}) }));
|
|
6144
|
-
},
|
|
6331
|
+
}, spawnTimeoutMs);
|
|
6145
6332
|
timeoutHandle.unref?.();
|
|
6146
6333
|
const stdoutBuffers = [];
|
|
6147
6334
|
const stderrBuffers = [];
|
|
@@ -6151,7 +6338,7 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath) => new Promise((resolv
|
|
|
6151
6338
|
const killIfTooLarge = (incomingBytes, isStdout) => {
|
|
6152
6339
|
if (isStdout) stdoutByteCount += incomingBytes;
|
|
6153
6340
|
else stderrByteCount += incomingBytes;
|
|
6154
|
-
if (stdoutByteCount + stderrByteCount >
|
|
6341
|
+
if (stdoutByteCount + stderrByteCount > outputMaxBytes && !didKillForSize) {
|
|
6155
6342
|
didKillForSize = true;
|
|
6156
6343
|
child.kill("SIGKILL");
|
|
6157
6344
|
return true;
|
|
@@ -6177,7 +6364,7 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath) => new Promise((resolv
|
|
|
6177
6364
|
if (didKillForSize) {
|
|
6178
6365
|
reject(new ReactDoctorError({ reason: new OxlintBatchExceeded({
|
|
6179
6366
|
kind: "output-too-large",
|
|
6180
|
-
detail: `exceeded ${
|
|
6367
|
+
detail: `exceeded ${outputMaxBytes} bytes — scan a smaller subset with --diff or --staged`
|
|
6181
6368
|
}) }));
|
|
6182
6369
|
return;
|
|
6183
6370
|
}
|
|
@@ -6218,7 +6405,7 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath) => new Promise((resolv
|
|
|
6218
6405
|
* with a slimmer config in that case.
|
|
6219
6406
|
*/
|
|
6220
6407
|
const spawnLintBatches = async (input) => {
|
|
6221
|
-
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, onPartialFailure, onFileProgress } = input;
|
|
6408
|
+
const { baseArgs, fileBatches, rootDirectory, nodeBinaryPath, project, onPartialFailure, onFileProgress, spawnTimeoutMs, outputMaxBytes } = input;
|
|
6222
6409
|
const totalFileCount = fileBatches.reduce((sum, batch) => sum + batch.length, 0);
|
|
6223
6410
|
const allDiagnostics = [];
|
|
6224
6411
|
const droppedFiles = [];
|
|
@@ -6226,7 +6413,7 @@ const spawnLintBatches = async (input) => {
|
|
|
6226
6413
|
const spawnLintBatch = async (batch) => {
|
|
6227
6414
|
const batchArgs = [...baseArgs, ...batch];
|
|
6228
6415
|
try {
|
|
6229
|
-
return parseOxlintOutput(await spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath), project, rootDirectory);
|
|
6416
|
+
return parseOxlintOutput(await spawnOxlint(batchArgs, rootDirectory, nodeBinaryPath, spawnTimeoutMs, outputMaxBytes), project, rootDirectory);
|
|
6230
6417
|
} catch (error) {
|
|
6231
6418
|
if (!isSplittableReactDoctorError(error)) throw error;
|
|
6232
6419
|
if (batch.length <= 1) {
|
|
@@ -6329,13 +6516,11 @@ const writeOxlintConfig = (configPath, configToWrite) => {
|
|
|
6329
6516
|
* 6. always restore disable directives + clean up the temp dir
|
|
6330
6517
|
*/
|
|
6331
6518
|
const runOxlint = async (options) => {
|
|
6332
|
-
const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure } = options;
|
|
6519
|
+
const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure, spawnTimeoutMs, outputMaxBytes } = options;
|
|
6333
6520
|
const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
6334
6521
|
const severityControls = buildRuleSeverityControls(userConfig);
|
|
6335
6522
|
validateRuleRegistration();
|
|
6336
6523
|
if (includePaths !== void 0 && includePaths.length === 0) return [];
|
|
6337
|
-
const configDirectory = fs.mkdtempSync(path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
|
|
6338
|
-
const configPath = path.join(configDirectory, "oxlintrc.json");
|
|
6339
6524
|
const pluginPath = resolvePluginPath();
|
|
6340
6525
|
const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
|
|
6341
6526
|
const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
|
|
@@ -6350,6 +6535,8 @@ const runOxlint = async (options) => {
|
|
|
6350
6535
|
userPlugins
|
|
6351
6536
|
});
|
|
6352
6537
|
const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
|
|
6538
|
+
const configDirectory = fs.mkdtempSync(path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
|
|
6539
|
+
const configPath = path.join(configDirectory, "oxlintrc.json");
|
|
6353
6540
|
try {
|
|
6354
6541
|
const baseArgs = [
|
|
6355
6542
|
resolveOxlintBinary(),
|
|
@@ -6376,7 +6563,9 @@ const runOxlint = async (options) => {
|
|
|
6376
6563
|
nodeBinaryPath,
|
|
6377
6564
|
project,
|
|
6378
6565
|
onPartialFailure,
|
|
6379
|
-
onFileProgress: options.onFileProgress
|
|
6566
|
+
onFileProgress: options.onFileProgress,
|
|
6567
|
+
spawnTimeoutMs,
|
|
6568
|
+
outputMaxBytes
|
|
6380
6569
|
});
|
|
6381
6570
|
writeOxlintConfig(configPath, buildConfig(extendsPaths));
|
|
6382
6571
|
try {
|
|
@@ -6442,6 +6631,8 @@ var Linter = class Linter extends Context.Service()("react-doctor/Linter") {
|
|
|
6442
6631
|
*/
|
|
6443
6632
|
static layerOxlint = Layer.succeed(Linter, Linter.of({ run: (input) => Stream.unwrap(Effect.fn("Linter.run")(function* () {
|
|
6444
6633
|
const partialFailures = yield* LintPartialFailures;
|
|
6634
|
+
const spawnTimeoutMs = yield* OxlintSpawnTimeoutMs;
|
|
6635
|
+
const outputMaxBytes = yield* OxlintOutputMaxBytes;
|
|
6445
6636
|
const collectedFailures = [];
|
|
6446
6637
|
const diagnostics = yield* Effect.tryPromise({
|
|
6447
6638
|
try: () => runOxlint({
|
|
@@ -6458,7 +6649,9 @@ var Linter = class Linter extends Context.Service()("react-doctor/Linter") {
|
|
|
6458
6649
|
onPartialFailure: (reason) => {
|
|
6459
6650
|
collectedFailures.push(reason);
|
|
6460
6651
|
},
|
|
6461
|
-
onFileProgress: input.onFileProgress
|
|
6652
|
+
onFileProgress: input.onFileProgress,
|
|
6653
|
+
spawnTimeoutMs,
|
|
6654
|
+
outputMaxBytes
|
|
6462
6655
|
}),
|
|
6463
6656
|
catch: ensureReactDoctorError
|
|
6464
6657
|
});
|
|
@@ -6756,7 +6949,7 @@ const runInspect = (input, hooks = {}) => Effect.gen(function* () {
|
|
|
6756
6949
|
const resolvedConfig = yield* configService.resolve(input.directory);
|
|
6757
6950
|
const scanDirectory = resolvedConfig.resolvedDirectory;
|
|
6758
6951
|
const project = yield* projectService.discover(scanDirectory);
|
|
6759
|
-
if (project
|
|
6952
|
+
if (!isAnalyzableProject(project)) return yield* new ReactDoctorError({ reason: new NoReactDependency({ directory: scanDirectory }) });
|
|
6760
6953
|
const [repo, sha, defaultBranch] = yield* Effect.all([
|
|
6761
6954
|
gitService.githubRepo(scanDirectory).pipe(Effect.orElseSucceed(() => null)),
|
|
6762
6955
|
gitService.headSha(scanDirectory).pipe(Effect.orElseSucceed(() => null)),
|
|
@@ -6784,7 +6977,8 @@ const runInspect = (input, hooks = {}) => Effect.gen(function* () {
|
|
|
6784
6977
|
const lintFailure = yield* Ref.make({
|
|
6785
6978
|
didFail: false,
|
|
6786
6979
|
reason: null,
|
|
6787
|
-
reasonTag: null
|
|
6980
|
+
reasonTag: null,
|
|
6981
|
+
reasonKind: null
|
|
6788
6982
|
});
|
|
6789
6983
|
const deadCodeFailure = yield* Ref.make({
|
|
6790
6984
|
didFail: false,
|
|
@@ -6806,13 +7000,14 @@ const runInspect = (input, hooks = {}) => Effect.gen(function* () {
|
|
|
6806
7000
|
configSourceDirectory: resolvedConfig.configSourceDirectory ?? void 0,
|
|
6807
7001
|
onFileProgress: (scannedFileCount, totalFileCount) => {
|
|
6808
7002
|
lastReportedTotalFileCount = totalFileCount;
|
|
6809
|
-
Effect.runSync(scanProgress.update(`Scanning (${scannedFileCount}/${totalFileCount})...`));
|
|
7003
|
+
Effect.runSync(scanProgress.update(`Scanning files (${scannedFileCount}/${totalFileCount})...`));
|
|
6810
7004
|
}
|
|
6811
7005
|
}).pipe(Stream.catchTag("ReactDoctorError", (error) => Stream.unwrap(Effect.gen(function* () {
|
|
6812
7006
|
yield* Ref.set(lintFailure, {
|
|
6813
7007
|
didFail: true,
|
|
6814
7008
|
reason: error.message,
|
|
6815
|
-
reasonTag: error.reason._tag
|
|
7009
|
+
reasonTag: error.reason._tag,
|
|
7010
|
+
reasonKind: error.reason._tag === "OxlintUnavailable" ? error.reason.kind : null
|
|
6816
7011
|
});
|
|
6817
7012
|
return Stream.empty;
|
|
6818
7013
|
}))));
|
|
@@ -6872,6 +7067,7 @@ const runInspect = (input, hooks = {}) => Effect.gen(function* () {
|
|
|
6872
7067
|
didLintFail: lintFailureState.didFail,
|
|
6873
7068
|
lintFailureReason: lintFailureState.reason,
|
|
6874
7069
|
lintFailureReasonTag: lintFailureState.reasonTag,
|
|
7070
|
+
lintFailureReasonKind: lintFailureState.reasonKind,
|
|
6875
7071
|
lintPartialFailures,
|
|
6876
7072
|
didDeadCodeFail: deadCodeFailureState.didFail,
|
|
6877
7073
|
deadCodeFailureReason: deadCodeFailureState.reason
|
|
@@ -7309,6 +7505,13 @@ const highlighter = {
|
|
|
7309
7505
|
gray: import_picocolors.default.gray,
|
|
7310
7506
|
bold: import_picocolors.default.bold
|
|
7311
7507
|
};
|
|
7508
|
+
/**
|
|
7509
|
+
* Canonical URL for a rule's reviewer-tested fix recipe, served at
|
|
7510
|
+
* `https://www.react.doctor/prompts/rules/<plugin>/<rule>.md`. The
|
|
7511
|
+
* `/doctor` playbook fetches it on demand so each fix follows the
|
|
7512
|
+
* canonical recipe instead of being improvised per diagnostic.
|
|
7513
|
+
*/
|
|
7514
|
+
const buildRulePromptUrl = (plugin, rule) => `${PROMPTS_RULES_BASE_URL}/${plugin}/${rule}.md`;
|
|
7312
7515
|
const groupBy = (items, keyFn) => {
|
|
7313
7516
|
const groups = /* @__PURE__ */ new Map();
|
|
7314
7517
|
for (const item of items) {
|
|
@@ -7356,6 +7559,6 @@ const cliLogger = {
|
|
|
7356
7559
|
}
|
|
7357
7560
|
};
|
|
7358
7561
|
//#endregion
|
|
7359
|
-
export {
|
|
7562
|
+
export { isMonorepoRoot as A, filterDiagnosticsForSurface as C, getDiffInfo as D, formatReactDoctorError as E, restoreLegacyThrow as F, runInspect as I, toRelativePath as L, layerOtlp as M, listWorkspacePackages as N, groupBy as O, resolveScanTarget as P, discoverReactSubprojects as S, formatErrorChain as T, Score as _, DeadCode as a, buildJsonReportError as b, LintPartialFailures as c, OXLINT_NODE_REQUIREMENT as d, Progress as f, SKILL_NAME as g, SHARE_BASE_URL as h, Config as i, isReactDoctorError as j, highlighter as k, Linter as l, Reporter as m, cli_logger_exports as n, Files as o, Project as p, CANONICAL_GITHUB_URL as r, Git as s, cliLogger as t, NodeResolver as u, StagedFiles as v, filterSourceFiles as w, buildRulePromptUrl as x, buildJsonReport as y };
|
|
7360
7563
|
|
|
7361
|
-
//# sourceMappingURL=cli-logger-
|
|
7564
|
+
//# sourceMappingURL=cli-logger-CSZagq1E.js.map
|