Skip to content

Commit f2e890e

Browse files
authored
Ignore invalid ranges for external packages (#68)
* Ignore invalid ranges on external packates * Finish things * Update changeset * Words * Update ten-pens-fry.md * docs
1 parent 35fcc9c commit f2e890e

File tree

9 files changed

+1638
-944
lines changed

9 files changed

+1638
-944
lines changed

.changeset/ten-pens-fry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@manypkg/cli": minor
3+
---
4+
5+
Ignore invalid ranges on external dependencies to allow git and other types of dependencies and allow people to ignore the external mismatch rule for certain dependencies by making dependencies `npm:^1.0.0` instead of `^1.0.0`.

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ This example will not cause an error because the range `1.0.0` for `some-externa
159159

160160
</details>
161161

162+
### Ignoring this rule
163+
164+
There are some cases where you might want to intentionally have conflicts between versions. To do this, you can use something that isn't a valid semver range instead of a range such as a git url or etc. If you'd like a conflicting version of an npm package, you can use `npm:your-range-here`.
165+
166+
> Note: Do this with care, having different versions of the same package can lead to strange bugs
167+
162168
## Internal mismatch
163169

164170
The ranges for all regular dependencies and optionalDependencies(not peerDependencies or devDependencies) on internal packages should include the version of the internal package.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
"@changesets/changelog-github": "^0.2.1",
1515
"@changesets/cli": "^2.5.0",
1616
"@types/fs-extra": "^8.0.1",
17-
"@types/jest": "^24.0.17",
17+
"@types/jest": "^26.0.4",
1818
"@types/normalize-path": "^3.0.0",
1919
"@types/parse-github-url": "^1.0.0",
2020
"@types/semver": "^6.0.1",
21-
"jest": "^24.8.0",
22-
"jest-watch-typeahead": "^0.4.2",
21+
"jest": "^26.1.0",
22+
"jest-watch-typeahead": "^0.6.0",
2323
"preconstruct": "^0.0.89",
2424
"typescript": "^3.5.3"
2525
},

packages/cli/src/checks/EXTERNAL_MISMATCH.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
NORMAL_DEPENDENCY_TYPES
55
} from "./utils";
66
import { Package } from "@manypkg/get-packages";
7+
import { validRange } from "semver";
78

89
type ErrorType = {
910
type: "EXTERNAL_MISMATCH";
@@ -19,11 +20,16 @@ export default makeCheck<ErrorType>({
1920
let highestExternalRanges = getHighestExternalRanges(allWorkspace);
2021
for (let depType of NORMAL_DEPENDENCY_TYPES) {
2122
let deps = workspace.packageJson[depType];
23+
2224
if (deps) {
2325
for (let depName in deps) {
2426
let range = deps[depName];
2527
let highestRange = highestExternalRanges.get(depName);
26-
if (highestRange !== undefined && highestRange !== range) {
28+
if (
29+
highestRange !== undefined &&
30+
highestRange !== range &&
31+
validRange(range)
32+
) {
2733
errors.push({
2834
type: "EXTERNAL_MISMATCH",
2935
workspace,

packages/cli/src/checks/INVALID_DEV_AND_PEER_DEPENDENCY_RELATIONSHIP.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { makeCheck, getHighestExternalRanges } from "./utils";
22
import { Package } from "@manypkg/get-packages";
33
import { upperBoundOfRangeAWithinBoundsOfB } from "sembear";
4+
import semver from "semver";
45

56
type ErrorType = {
67
type: "INVALID_DEV_AND_PEER_DEPENDENCY_RELATIONSHIP";
@@ -38,6 +39,10 @@ export default makeCheck<ErrorType>({
3839
idealDevVersion
3940
});
4041
} else if (
42+
semver.validRange(devDeps[depName]) &&
43+
// TODO: we should probably error when a peer dep has an invalid range (in a seperate rule)
44+
// (also would be good to do a bit more validation instead of just ignoring invalid ranges for normal dep types)
45+
semver.validRange(peerDeps[depName]) &&
4146
!upperBoundOfRangeAWithinBoundsOfB(
4247
devDeps[depName],
4348
peerDeps[depName]
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import internalMismatch from "../EXTERNAL_MISMATCH";
2+
import { getWS, getFakeWS } from "../../test-helpers";
3+
4+
let rootWorkspace = getFakeWS("root");
5+
6+
it("should error if the ranges are valid and they are not equal", () => {
7+
let ws = getWS();
8+
9+
ws.get("pkg-1")!.packageJson.dependencies = { something: "1.0.0" };
10+
11+
let pkg2 = getFakeWS("pkg-2");
12+
pkg2.packageJson.dependencies = {
13+
something: "2.0.0"
14+
};
15+
ws.set("pkg-2", pkg2);
16+
17+
let errors = internalMismatch.validate(pkg2, ws, rootWorkspace, {});
18+
expect(errors.length).toEqual(0);
19+
20+
errors = internalMismatch.validate(ws.get("pkg-1")!, ws, rootWorkspace, {});
21+
expect(errors.length).toEqual(1);
22+
expect(errors).toMatchInlineSnapshot(`
23+
Array [
24+
Object {
25+
"dependencyName": "something",
26+
"dependencyRange": "1.0.0",
27+
"highestDependencyRange": "2.0.0",
28+
"type": "EXTERNAL_MISMATCH",
29+
"workspace": Object {
30+
"dir": "some/fake/dir/pkg-1",
31+
"packageJson": Object {
32+
"dependencies": Object {
33+
"something": "1.0.0",
34+
},
35+
"name": "pkg-1",
36+
"version": "1.0.0",
37+
},
38+
},
39+
},
40+
]
41+
`);
42+
});
43+
44+
it("should not error if the value is not a valid semver range", () => {
45+
let ws = getWS();
46+
47+
ws.get("pkg-1")!.packageJson.dependencies = { something: "1.0.0" };
48+
49+
let pkg2 = getFakeWS("pkg-2");
50+
pkg2.packageJson.dependencies = {
51+
something: "git:x"
52+
};
53+
ws.set("pkg-2", pkg2);
54+
55+
let errors = internalMismatch.validate(pkg2, ws, rootWorkspace, {});
56+
expect(errors.length).toEqual(0);
57+
58+
errors = internalMismatch.validate(ws.get("pkg-1")!, ws, rootWorkspace, {});
59+
expect(errors.length).toEqual(0);
60+
});

packages/cli/src/checks/__tests__/INVALID_DEV_AND_PEER_DEPENDENCY.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,32 @@ describe("invalid dev and peer dependency", () => {
153153
let errors = makeCheck.validate(pkg1, ws, rootWorkspace, {});
154154
expect(errors).toHaveLength(0);
155155
});
156+
157+
it("invalid range on peerDependencies", () => {
158+
let ws = getWS();
159+
let pkg1 = ws.get("pkg-1")!;
160+
161+
pkg1.packageJson.peerDependencies = {
162+
"external-dep": "not a range"
163+
};
164+
pkg1.packageJson.devDependencies = {
165+
"external-dep": "^1.1.0"
166+
};
167+
let errors = makeCheck.validate(pkg1, ws, rootWorkspace, {});
168+
expect(errors).toHaveLength(0);
169+
});
170+
171+
it("invalid range on devDependencies", () => {
172+
let ws = getWS();
173+
let pkg1 = ws.get("pkg-1")!;
174+
175+
pkg1.packageJson.peerDependencies = {
176+
"external-dep": "^1.0.0"
177+
};
178+
pkg1.packageJson.devDependencies = {
179+
"external-dep": "not a range"
180+
};
181+
let errors = makeCheck.validate(pkg1, ws, rootWorkspace, {});
182+
expect(errors).toHaveLength(0);
183+
});
156184
});

packages/cli/src/checks/utils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Package } from "@manypkg/get-packages";
2+
import * as semver from "semver";
23
import { highest } from "sembear";
34

45
export const NORMAL_DEPENDENCY_TYPES = [
@@ -126,6 +127,9 @@ export let getHighestExternalRanges = weakMemoize(function getHighestVersions(
126127
if (deps) {
127128
for (let depName in deps) {
128129
if (!allPackages.has(depName)) {
130+
if (!semver.validRange(deps[depName])) {
131+
continue;
132+
}
129133
let highestExternalRange = highestExternalRanges.get(depName);
130134
if (
131135
!highestExternalRange ||

0 commit comments

Comments
 (0)