Socket
Socket
Sign inDemoInstall

yarn-deduplicate

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

yarn-deduplicate - npm Package Compare versions

Comparing version 2.0.0 to 2.1.0

index.d.ts

15

CHANGELOG.md

@@ -8,2 +8,17 @@ # Changelog

## [2.1.0] - 2020-07-10
### Chores
- Updated dependencies
- Move from CircleCI to GitHub actions
- Clean up and dedupe `yarn.lock`
### Added
- Option `--scopes` to limit changes to a list of scopes (thanks to @sgomes)
- Improve documentation for `--strategy` (thanks to @KubaJastrz)
- Clean up .npmignore (thanks to @bluelovers)
## [2.0.0] - 2020-02-29

@@ -10,0 +25,0 @@

27

cli.js

@@ -18,10 +18,20 @@ #!/usr/bin/env node

.option('-l, --list', 'do not change yarn.lock, just output the diagnosis')
.option('-f, --fail', 'if there are duplicates in yarn.lock, exit 1 for failure')
.option(
'-f, --fail',
'if there are duplicates in yarn.lock, terminate the script wuth exit status 1'
)
.option(
'--scopes <scopes>',
'a comma separated list of scopes to deduplicate. Defaults to all packages.',
(val) => val.split(',').map((v) => v.trim())
)
.option(
'--packages <packages>',
'a comma separated list of packages to deduplicate. Defaults to all packages.',
val => val.split(',').map(v => v.trim())
(val) => val.split(',').map((v) => v.trim())
)
.option('--exclude <exclude>', 'a comma separated list of packages not to deduplicate.', val =>
val.split(',').map(v => v.trim())
.option(
'--exclude <exclude>',
'a comma separated list of packages not to deduplicate.',
(val) => val.split(',').map((v) => v.trim())
)

@@ -32,2 +42,7 @@ .option('--print', 'instead of saving the deduplicated yarn.lock, print the result in stdout');

if (commander.scopes && commander.packages) {
console.error('Please specify either scopes or packages, not both.');
commander.help();
}
if (commander.strategy !== 'highest' && commander.strategy !== 'fewer') {

@@ -47,6 +62,7 @@ console.error(`Invalid strategy ${commander.strategy}`);

useMostCommon,
includeScopes: commander.scopes,
includePackages: commander.packages,
excludePackages: commander.exclude,
});
duplicates.forEach(logLine => console.log(logLine));
duplicates.forEach((logLine) => console.log(logLine));
if (commander.fail && duplicates.length > 0) {

@@ -58,2 +74,3 @@ process.exit(1);

useMostCommon,
includeScopes: commander.scopes,
includePackages: commander.packages,

@@ -60,0 +77,0 @@ excludePackages: commander.exclude,

61

index.js
const lockfile = require('@yarnpkg/lockfile');
const semver = require('semver');
const parseYarnLock = file => lockfile.parse(file).object;
const parseYarnLock = (file) => lockfile.parse(file).object;
const extractPackages = (json, includePackages = [], excludePackages = []) => {
const extractPackages = (json, includeScopes = [], includePackages = [], excludePackages = []) => {
const packages = {};
const re = /^(.*)@([^@]*?)$/;
Object.keys(json).forEach(name => {
Object.keys(json).forEach((name) => {
const pkg = json[name];

@@ -29,2 +29,10 @@ const match = name.match(re);

// If there is a list of scopes, only process those.
if (
includeScopes.length > 0 &&
!includeScopes.find((scope) => packageName.startsWith(`${scope}/`))
) {
return;
}
// If there is a list of package names, only process those.

@@ -62,5 +70,5 @@ if (includePackages.length > 0 && !includePackages.includes(packageName)) return;

// Link each package instance with all the versions it could satisfy.
Object.keys(versions).forEach(version => {
Object.keys(versions).forEach((version) => {
const satisfies = versions[version].satisfies;
packageInstances.forEach(packageInstance => {
packageInstances.forEach((packageInstance) => {
// We can assume that the installed version always satisfied the requested version.

@@ -81,3 +89,3 @@ packageInstance.satisfiedBy.add(packageInstance.installedVersion);

// Sort the list of satisfied versions
packageInstances.forEach(packageInstance => {
packageInstances.forEach((packageInstance) => {
// Save all versions for future reference

@@ -107,4 +115,7 @@ packageInstance.versions = versions;

const getDuplicatedPackages = (json, { includePackages, excludePackages, useMostCommon }) => {
const packages = extractPackages(json, includePackages, excludePackages);
const getDuplicatedPackages = (
json,
{ includeScopes, includePackages, excludePackages, useMostCommon }
) => {
const packages = extractPackages(json, includeScopes, includePackages, excludePackages);
return Object.keys(packages)

@@ -120,3 +131,3 @@ .reduce(

yarnLock,
{ includePackages = [], excludePackages = [], useMostCommon = false } = {}
{ includeScopes = [], includePackages = [], excludePackages = [], useMostCommon = false } = {}
) => {

@@ -126,9 +137,12 @@ const json = parseYarnLock(yarnLock);

getDuplicatedPackages(json, { includePackages, excludePackages, useMostCommon }).forEach(
({ bestVersion, name, installedVersion, requestedVersion }) => {
result.push(
`Package "${name}" wants ${requestedVersion} and could get ${bestVersion}, but got ${installedVersion}`
);
}
);
getDuplicatedPackages(json, {
includeScopes,
includePackages,
excludePackages,
useMostCommon,
}).forEach(({ bestVersion, name, installedVersion, requestedVersion }) => {
result.push(
`Package "${name}" wants ${requestedVersion} and could get ${bestVersion}, but got ${installedVersion}`
);
});

@@ -140,13 +154,16 @@ return result;

yarnLock,
{ includePackages = [], excludePackages = [], useMostCommon = false } = {}
{ includeScopes = [], includePackages = [], excludePackages = [], useMostCommon = false } = {}
) => {
const json = parseYarnLock(yarnLock);
getDuplicatedPackages(json, { includePackages, excludePackages, useMostCommon }).forEach(
({ bestVersion, name, versions, requestedVersion }) => {
json[`${name}@${requestedVersion}`] = versions[bestVersion].pkg;
}
);
getDuplicatedPackages(json, {
includeScopes,
includePackages,
excludePackages,
useMostCommon,
}).forEach(({ bestVersion, name, versions, requestedVersion }) => {
json[`${name}@${requestedVersion}`] = versions[bestVersion].pkg;
});
return lockfile.stringify(json);
};
{
"name": "yarn-deduplicate",
"version": "2.0.0",
"version": "2.1.0",
"bin": "./cli.js",

@@ -16,3 +16,3 @@ "description": "Deduplication tool for yarn.lock files",

"scripts": {
"test": "eslint . && jest",
"test": "jest",
"lint": "eslint ."

@@ -23,3 +23,3 @@ },

"license": "Apache-2.0",
"author": "Sergio Cinos <scinos@atlassian.com>",
"author": "Sergio Cinos <sergio.cinos@gmail.com>",
"main": "index.js",

@@ -32,24 +32,23 @@ "repository": {

"node": ">=10",
"yarn": "^1.0.0"
"yarn": "^1.22.4"
},
"dependencies": {
"@yarnpkg/lockfile": "^1.1.0",
"commander": "^4.1.1",
"semver": "7.1.3"
"commander": "^5.1.0",
"semver": "^7.3.2"
},
"devDependencies": {
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-jest": "^23.8.0",
"eslint-plugin-prettier": "^3.0.0",
"jest": "^25.1.0",
"outdent": "0.7.0",
"prettier": "^1.15.3"
"eslint": "^7.4.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-jest": "^23.18.0",
"eslint-plugin-prettier": "^3.1.4",
"jest": "^26.1.0",
"outdent": "^0.7.1",
"prettier": "^2.0.5"
},
"jest": {
"testPathIgnorePatterns": [
"<rootDir>/node_modules",
"<rootDir>/.history"
"<rootDir>/node_modules"
]
}
}

@@ -1,3 +0,4 @@

Builds: [![CircleCI](https://circleci.com/gh/atlassian/yarn-deduplicate.svg?style=svg)](https://circleci.com/gh/atlassian/yarn-deduplicate)
Builds: ![Node.js CI](https://github.com/atlassian/yarn-deduplicate/workflows/Node.js%20CI/badge.svg)
# Yarn deduplicate

@@ -98,2 +99,4 @@

`--strategy <strategy>`
`highest`

@@ -142,3 +145,3 @@ It will try to use the highest installed version. For example, with the following `yarn.lock`:

`--packages <package1> <package2> <packageN>`
`--packages <package1>,<package2>,<packageN>`

@@ -150,2 +153,22 @@ Receives a list of packages to deduplicate. It will ignore any other duplicated package not in the

`--scopes <scope1>,<scope2>,<scopeN>`
Receives a list of scopes to deduplicate. It will ignore any other duplicated package not in the
list. This option is recommended when deduplicating a large number of inter-dependent packages
from a single scope, such as @babel. This will allow for a more controlled and progressive
deduplication of `yarn.lock` without specifying each package individually.
### Usage in CI
This tool can be used as part of a CI workflow. Adding the flag `--fail` will force the process to
exit with status 1 if there are duplicated packages. Example:
```bash
# Print the list of duplicated packages and exit with status 1
yarn-deduplicate --list --fail
# Deduplicate yarn.lock and exit with status 1 if changes were required
yarn-deduplicate --fail
```
---

@@ -190,3 +213,2 @@

### Limit packages to deduplicate yarn.lock

@@ -202,3 +224,2 @@ ```bash

## Contributors

@@ -228,4 +249,4 @@

* [CLA for corporate contributors](https://na2.docusign.net/Member/PowerFormSigning.aspx?PowerFormId=e1c17c66-ca4d-4aab-a953-2c231af4a20b)
* [CLA for individuals](https://na2.docusign.net/Member/PowerFormSigning.aspx?PowerFormId=3f94fbdc-2fbe-46ac-b14c-5d152700ae5d)
* [CLA for corporate contributors](https://opensource.atlassian.com/corporate)
* [CLA for individuals](https://opensource.atlassian.com/individual)

@@ -232,0 +253,0 @@ ## License

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc