-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3011 from dependabot/feelepxyz/use-npm7
Add support for npm 7 lockfiles
- Loading branch information
Showing
25 changed files
with
6,883 additions
and
1,513 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
const peerDependencyChecker = require("./peer-dependency-checker"); | ||
|
||
module.exports = { | ||
checkPeerDependencies: peerDependencyChecker.checkPeerDependencies, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* PEER DEPENDENCY CHECKER | ||
* | ||
* Inputs: | ||
* - directory containing a package.json and a yarn.lock | ||
* - dependency name | ||
* - new dependency version | ||
* - requirements for this dependency | ||
* | ||
* Outputs: | ||
* - successful completion, or an error if there are peer dependency warnings | ||
*/ | ||
|
||
const npm = require("npm7"); | ||
const Arborist = require("@npmcli/arborist"); | ||
const { promisify } = require("util"); | ||
|
||
async function checkPeerDependencies( | ||
directory, | ||
depName, | ||
desiredVersion, | ||
requirements, | ||
_topLevelDependencies // included for compatibility with npm 6 implementation | ||
) { | ||
await promisify(npm.load).bind(npm)(); | ||
|
||
// `ignoreScripts` is used to disable prepare and prepack scripts which are | ||
// run when installing git dependencies | ||
const arb = new Arborist({ | ||
...npm.flatOptions, | ||
path: directory, | ||
packageLockOnly: true, | ||
dryRun: true, | ||
save: false, | ||
ignoreScripts: true, | ||
engineStrict: false, | ||
// NOTE: there seems to be no way to disable platform checks in arborist | ||
// without force installing invalid peer dependencies | ||
// | ||
// TODO: ignore platform checks | ||
force: false, | ||
}); | ||
|
||
// Returns dep name and version for npm install, example: ["react@16.6.0"] | ||
let args = installArgsWithVersion(depName, desiredVersion, requirements); | ||
|
||
return await arb | ||
.buildIdealTree({ | ||
add: args, | ||
}) | ||
.catch((er) => { | ||
if (er.code === "ERESOLVE") { | ||
// NOTE: Emulate the error message in npm 6 for compatibility with the | ||
// version resolver | ||
const conflictingDependencies = [ | ||
`${er.edge.from.name}@${er.edge.from.version} requires a peer of ${er.current.name}@${er.edge.spec} but none is installed.`, | ||
]; | ||
throw new Error(conflictingDependencies.join("\n")); | ||
} else { | ||
// NOTE: Hand over exception handling to the file updater. This is | ||
// consistent with npm6 behaviour. | ||
return []; | ||
} | ||
}) | ||
.then(() => []); | ||
} | ||
|
||
function installArgsWithVersion(depName, desiredVersion, reqs) { | ||
const source = (reqs.find((req) => req.source) || {}).source; | ||
|
||
if (source && source.type === "git") { | ||
return [`${depName}@${source.url}#${desiredVersion}`]; | ||
} else { | ||
return [`${depName}@${desiredVersion}`]; | ||
} | ||
} | ||
|
||
module.exports = { checkPeerDependencies }; |
67 changes: 67 additions & 0 deletions
67
npm_and_yarn/helpers/test/npm7/conflicting-dependency-parser.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
const path = require("path"); | ||
const os = require("os"); | ||
const fs = require("fs"); | ||
const rimraf = require("rimraf"); | ||
const { | ||
findConflictingDependencies, | ||
} = require("../../lib/npm/conflicting-dependency-parser"); | ||
const helpers = require("./helpers"); | ||
|
||
describe("findConflictingDependencies", () => { | ||
let tempDir; | ||
beforeEach(() => { | ||
tempDir = fs.mkdtempSync(os.tmpdir() + path.sep); | ||
}); | ||
afterEach(() => rimraf.sync(tempDir)); | ||
|
||
it("finds conflicting dependencies", async () => { | ||
helpers.copyDependencies("conflicting-dependency-parser/simple", tempDir); | ||
|
||
const result = await findConflictingDependencies(tempDir, "abind", "2.0.0"); | ||
expect(result).toEqual([ | ||
{ | ||
explanation: "objnest@4.1.2 requires abind@^1.0.0", | ||
name: "objnest", | ||
version: "4.1.2", | ||
requirement: "^1.0.0", | ||
}, | ||
]); | ||
}); | ||
|
||
it("finds the top-level conflicting dependency", async () => { | ||
helpers.copyDependencies("conflicting-dependency-parser/nested", tempDir); | ||
|
||
const result = await findConflictingDependencies(tempDir, "abind", "2.0.0"); | ||
expect(result).toEqual([ | ||
{ | ||
explanation: "askconfig@4.0.4 requires abind@^1.0.5 via objnest@5.1.0", | ||
name: "objnest", | ||
version: "5.1.0", | ||
requirement: "^1.0.5", | ||
}, | ||
]); | ||
}); | ||
|
||
it("explains a deeply nested dependency", async () => { | ||
helpers.copyDependencies( | ||
"conflicting-dependency-parser/deeply-nested", | ||
tempDir | ||
); | ||
|
||
const result = await findConflictingDependencies(tempDir, "abind", "2.0.0"); | ||
expect(result).toEqual([ | ||
{ | ||
explanation: "apass@1.1.0 requires abind@^1.0.0 via cipherjson@2.1.0", | ||
name: "cipherjson", | ||
version: "2.1.0", | ||
requirement: "^1.0.0", | ||
}, | ||
{ | ||
explanation: `apass@1.1.0 requires abind@^1.0.0 via a transitive dependency on objnest@3.0.9`, | ||
name: "objnest", | ||
version: "3.0.9", | ||
requirement: "^1.0.0", | ||
}, | ||
]); | ||
}); | ||
}); |
Oops, something went wrong.