Skip to content

Commit

Permalink
fix: properly check peer dependency's dependencies for non-matching v…
Browse files Browse the repository at this point in the history
…ersion when it is in pkg peer dependency
  • Loading branch information
christophehurpeau committed Jun 9, 2024
1 parent 0e4e13c commit b40fdaa
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 27 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/definitions/checks/checkPeerDependencies.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ReportError } from "../utils/createReportError";
import type { PackageJson, DependencyTypes } from "../utils/packageTypes";
import type { OnlyWarnsForCheck } from "../utils/warnForUtils";
export declare function checkPeerDependencies(pkg: PackageJson, reportError: ReportError, type: DependencyTypes, allowedPeerIn: DependencyTypes[], providedDependencies: [string, string][], depPkg: PackageJson, missingOnlyWarnsForCheck: OnlyWarnsForCheck, invalidOnlyWarnsForCheck: OnlyWarnsForCheck): void;
export declare function checkPeerDependencies(pkg: PackageJson, reportError: ReportError, type: DependencyTypes, allowedPeerIn: DependencyTypes[], allowMissing: boolean, providedDependencies: [string, string][], depPkg: PackageJson, missingOnlyWarnsForCheck: OnlyWarnsForCheck, invalidOnlyWarnsForCheck: OnlyWarnsForCheck): void;
//# sourceMappingURL=checkPeerDependencies.d.ts.map
2 changes: 1 addition & 1 deletion dist/definitions/checks/checkPeerDependencies.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 19 additions & 10 deletions dist/index-node18.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ async function checkDirectDuplicateDependencies(pkg, pkgPathName, isPackageALibr
reportNotWarnedForMapping(reportError, onlyWarnsForCheck);
}

function checkPeerDependencies(pkg, reportError, type, allowedPeerIn, providedDependencies, depPkg, missingOnlyWarnsForCheck, invalidOnlyWarnsForCheck) {
function checkPeerDependencies(pkg, reportError, type, allowedPeerIn, allowMissing, providedDependencies, depPkg, missingOnlyWarnsForCheck, invalidOnlyWarnsForCheck) {
const { peerDependencies, peerDependenciesMeta } = depPkg;
if (!peerDependencies) return;
const allowedPeerInExisting = allowedPeerIn.filter(
Expand All @@ -178,6 +178,9 @@ function checkPeerDependencies(pkg, reportError, type, allowedPeerIn, providedDe
(allowedPeerInExistingType) => pkg[allowedPeerInExistingType]?.[peerDepName]
);
if (versionsIn.length === 0) {
if (allowMissing) {
continue;
}
const peerDependenciesMetaPeerDep = peerDependenciesMeta?.[peerDepName];
if (peerDependenciesMetaPeerDep?.optional) {
continue;
Expand Down Expand Up @@ -251,16 +254,16 @@ async function checkDirectPeerDependencies(isLibrary, pkg, pkgPathName, getDepen
const dependencies = pkg[depType];
if (!dependencies) return;
for (const depName of getKeys(dependencies)) {
if (pkg.peerDependencies?.[depName]) {
if (semver.intersects(
const depPkg = getDependencyPackageJson(depName);
allDepPkgs.push({
name: depName,
type: depType,
pkg: depPkg,
hasDirectMatchingPeerDependency: pkg.peerDependencies?.[depName] ? semver.intersects(
dependencies[depName],
pkg.peerDependencies[depName]
)) {
continue;
}
}
const depPkg = getDependencyPackageJson(depName);
allDepPkgs.push({ name: depName, type: depType, pkg: depPkg });
) : false
});
if (depPkg.dependencies && !isLibrary) {
allDirectDependenciesDependencies.push(
...Object.entries(depPkg.dependencies)
Expand All @@ -269,13 +272,19 @@ async function checkDirectPeerDependencies(isLibrary, pkg, pkgPathName, getDepen
}
})
);
for (const { name: depName, type: depType, pkg: depPkg } of allDepPkgs) {
for (const {
name: depName,
type: depType,
pkg: depPkg,
hasDirectMatchingPeerDependency
} of allDepPkgs) {
if (depPkg.peerDependencies) {
checkPeerDependencies(
pkg,
reportError,
depType,
getAllowedPeerInFromType(depType, isLibrary),
hasDirectMatchingPeerDependency,
allDirectDependenciesDependencies,
depPkg,
missingOnlyWarnsForCheck.createFor(depName),
Expand Down
2 changes: 1 addition & 1 deletion dist/index-node18.mjs.map

Large diffs are not rendered by default.

72 changes: 72 additions & 0 deletions src/checks/checkDirectPeerDependencies.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,4 +364,76 @@ describe("checkDirectPeerDependencies", () => {
);
expect(mockReportError).not.toHaveBeenCalled();
});

it("should error when peer dependency is marked as peer dependency but has wrong version", async () => {
await checkDirectPeerDependencies(
false,
{
name: "test",
devDependencies: {
"some-lib-using-rollup": "1.0.0",
rollup: "^2.0.0",
},
peerDependencies: {
"some-lib-using-rollup": "^1.0.0",
},
},
"path",
vi.fn().mockImplementation((name) =>
name === "rollup"
? {
name: "rollup",
}
: {
name: "some-lib-using-rollup",
peerDependencies: { rollup: "^1.0.0" },
},
),
createOnlyWarnsForMappingCheck("test", []),
createOnlyWarnsForMappingCheck("test", []),
createReportError,
);
expect(mockReportError).toHaveBeenCalledTimes(1);
expect(mockReportError).toHaveBeenLastCalledWith(
'Invalid "rollup" peer dependency',
'"^2.0.0" (in devDependencies) should satisfies "^1.0.0" from "some-lib-using-rollup" devDependencies',
false,
);
});

it("should error when peer dependency is marked as peer dependency but has wrong dependency version", async () => {
await checkDirectPeerDependencies(
false,
{
name: "test",
devDependencies: {
"react-native": "1.0.0",
react: "18.3.0",
},
peerDependencies: {
"react-native": "*",
},
},
"path",
vi.fn().mockImplementation((name) =>
name === "react-native"
? {
name: "react-native",
peerDependencies: { react: "18.2.0" },
}
: {
name: "react",
},
),
createOnlyWarnsForMappingCheck("test", []),
createOnlyWarnsForMappingCheck("test", []),
createReportError,
);
expect(mockReportError).toHaveBeenCalledTimes(1);
expect(mockReportError).toHaveBeenLastCalledWith(
'Invalid "react" peer dependency',
'"18.3.0" (in devDependencies) should satisfies "18.2.0" from "react-native" devDependencies',
false,
);
});
});
32 changes: 19 additions & 13 deletions src/checks/checkDirectPeerDependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export async function checkDirectPeerDependencies(
name: string;
type: RegularDependencyTypes;
pkg: PackageJson;
hasDirectMatchingPeerDependency: boolean;
}[] = [];
const allDirectDependenciesDependencies: [string, string][] = [];

Expand All @@ -62,19 +63,18 @@ export async function checkDirectPeerDependencies(
const dependencies = pkg[depType];
if (!dependencies) return;
for (const depName of getKeys(dependencies)) {
if (pkg.peerDependencies?.[depName]) {
if (
semver.intersects(
dependencies[depName],
pkg.peerDependencies[depName],
)
) {
continue;
}
}

const depPkg = getDependencyPackageJson(depName);
allDepPkgs.push({ name: depName, type: depType, pkg: depPkg });
allDepPkgs.push({
name: depName,
type: depType,
pkg: depPkg,
hasDirectMatchingPeerDependency: pkg.peerDependencies?.[depName]
? semver.intersects(
dependencies[depName],
pkg.peerDependencies[depName],
)
: false,
});

if (depPkg.dependencies && !isLibrary) {
allDirectDependenciesDependencies.push(
Expand All @@ -85,13 +85,19 @@ export async function checkDirectPeerDependencies(
}),
);

for (const { name: depName, type: depType, pkg: depPkg } of allDepPkgs) {
for (const {
name: depName,
type: depType,
pkg: depPkg,
hasDirectMatchingPeerDependency,
} of allDepPkgs) {
if (depPkg.peerDependencies) {
checkPeerDependencies(
pkg,
reportError,
depType,
getAllowedPeerInFromType(depType, isLibrary),
hasDirectMatchingPeerDependency,
allDirectDependenciesDependencies,
depPkg,
missingOnlyWarnsForCheck.createFor(depName),
Expand Down
5 changes: 5 additions & 0 deletions src/checks/checkPeerDependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export function checkPeerDependencies(
reportError: ReportError,
type: DependencyTypes,
allowedPeerIn: DependencyTypes[],
allowMissing: boolean,
providedDependencies: [string, string][],
depPkg: PackageJson,
missingOnlyWarnsForCheck: OnlyWarnsForCheck,
Expand All @@ -26,6 +27,10 @@ export function checkPeerDependencies(
pkg[allowedPeerInExistingType]?.[peerDepName],
);
if (versionsIn.length === 0) {
if (allowMissing) {
continue;
}

const peerDependenciesMetaPeerDep = peerDependenciesMeta?.[peerDepName];
if (peerDependenciesMetaPeerDep?.optional) {
continue;
Expand Down

0 comments on commit b40fdaa

Please sign in to comment.