bulk-update-versions
Advanced tools
@@ -16,2 +16,3 @@ #!/usr/bin/env node | ||
const flags = mri(process.argv.slice(2), { | ||
boolean: { "force-latest": false }, | ||
alias: { help: ["h"] }, | ||
@@ -21,3 +22,8 @@ }); | ||
if (commands.length === 0 || (flags.help && commands.length === 0)) { | ||
const isForceLatest = Boolean(flags["force-latest"]); | ||
if ( | ||
(!isForceLatest && commands.length === 0) || | ||
(flags.help && commands.length === 0) | ||
) { | ||
console.log(` | ||
@@ -35,2 +41,3 @@ Usage: update-versions [version] [options] | ||
--match <pattern> A regular expression to match package names that needs to be updated. | ||
--force-latest Force using the latest published versions. The given version argument is ignored. | ||
`); | ||
@@ -40,8 +47,14 @@ process.exit(0); | ||
if (!flags.match) { | ||
throw new Error( | ||
"Missing required option --match. Please provide a valid regular expression." | ||
); | ||
} | ||
const [versionToUpdate] = commands; | ||
if (!versionToUpdate) { | ||
if (!isForceLatest && !versionToUpdate) { | ||
throw new Error("Missing command argument [version]."); | ||
} | ||
if (!semver.valid(versionToUpdate)) { | ||
if (!isForceLatest && !semver.valid(versionToUpdate)) { | ||
throw new Error( | ||
@@ -51,7 +64,2 @@ `Invalid [version] argument ${versionToUpdate}. Please provide a valid SemVer value.` | ||
} | ||
if (!flags.match) { | ||
throw new Error( | ||
"Missing required option --match. Please provide a valid regular expression." | ||
); | ||
} | ||
@@ -80,3 +88,3 @@ const matchingPackages = new RegExp(flags.match); | ||
const fetchRemotePublishedVersions = async (packageName) => { | ||
const fetchPackageInfo = async (packageName) => { | ||
const result = await execa("npm", ["view", packageName, "--json"], { | ||
@@ -89,3 +97,7 @@ silent: true, | ||
} | ||
return JSON.parse(result.stdout).versions; | ||
const packageInfo = JSON.parse(result.stdout); | ||
return { | ||
versions: packageInfo.versions, | ||
latest: packageInfo["dist-tags"].latest, | ||
}; | ||
}; | ||
@@ -107,26 +119,31 @@ | ||
// we should not update the version. | ||
if (!semver.satisfies(versionToUpdate, version)) { | ||
// If the flag `force-latest` is provided, the published version in the `latest` | ||
// dist-tag is used instead. | ||
if (isForceLatest || !semver.satisfies(versionToUpdate, version)) { | ||
log( | ||
`Package ${name} has version ${version} but requested version was ${versionToUpdate}` | ||
`Package ${name} has version ${version} but requested version was ${ | ||
isForceLatest ? "latest" : versionToUpdate | ||
}` | ||
); | ||
// Fetch the published versions of the given package, if it's not in the cache. | ||
if (!dependenciesCache.has(name)) { | ||
const remotePublishedVersions = await fetchRemotePublishedVersions( | ||
name | ||
); | ||
dependenciesCache.set(name, remotePublishedVersions); | ||
dependenciesCache.set(name, await fetchPackageInfo(name)); | ||
} | ||
const publishedVersions = dependenciesCache.get(name); | ||
const packageInfo = dependenciesCache.get(name); | ||
const matchedVersion = isForceLatest | ||
? packageInfo.latest | ||
: versionToUpdate; | ||
// If the requested version is included in the list of published versions, | ||
// then update the version in the package.json. | ||
if (publishedVersions.includes(versionToUpdate)) { | ||
log(`Package ${name} can be updated to version ${versionToUpdate}`); | ||
if (packageInfo.versions.includes(matchedVersion)) { | ||
log(`Package ${name} can be updated to version ${matchedVersion}`); | ||
// Attempt to keep the preserved range | ||
let versionToUpdateWithPreservedRange = version | ||
.replace(/\~(.*)$/, `~${versionToUpdate}`) | ||
.replace(/\^(.*)$/, `^${versionToUpdate}`); | ||
.replace(/\~(.*)$/, `~${matchedVersion}`) | ||
.replace(/\^(.*)$/, `^${matchedVersion}`); | ||
// ...otherwise fall back to the fixed given version | ||
if (versionToUpdateWithPreservedRange === version) { | ||
versionToUpdateWithPreservedRange = versionToUpdate; | ||
versionToUpdateWithPreservedRange = matchedVersion; | ||
} | ||
@@ -133,0 +150,0 @@ return { |
# bulk-update-versions | ||
## 0.0.0-canary-202057125444 | ||
### Patch Changes | ||
## 0.0.0-canary-20205910200 | ||
### Minor Changes | ||
- [`830ade8`](https://github.com/emmenko/bulk-update-versions/commit/830ade8d3dee669fb888d98e2737c46229bcd157) [#8](https://github.com/emmenko/bulk-update-versions/pull/8) Thanks [@emmenko](https://github.com/emmenko)! - Allow to update all the matching packages to their `latest` version by passing the `--force-latest` flag instead of a fixed version. | ||
## 1.0.1 | ||
### Patch Changes | ||
- [`d70ee92`](https://github.com/emmenko/bulk-update-versions/commit/d70ee923dac77e33a6c722ab1edf477fcd899e20) [#5](https://github.com/emmenko/bulk-update-versions/pull/5) Thanks [@emmenko](https://github.com/emmenko)! - Attempt to keep version range when updating to a newer version. |
{ | ||
"name": "bulk-update-versions", | ||
"version": "0.0.0-canary-202057125444", | ||
"version": "0.0.0-canary-20205910200", | ||
"description": "Script to bulk update versions matching a certain pattern", | ||
@@ -5,0 +5,0 @@ "bugs": "https://github.com/emmenko/bulk-update-versions/issues", |
@@ -22,3 +22,11 @@ # Bulk update versions | ||
``` | ||
$ bulk-update-versions 7.9.2 --match '^@babel/(.*)' | ||
$ bulk-update-versions --match '^@babel/(.*)' 7.9.2 | ||
``` | ||
### Force updating to `latest` version | ||
If you want to update all the matching packages to their `latest` version, you can pass the `--force-latest` flag instead of a fixed version. | ||
``` | ||
$ bulk-update-versions --match '^@babel/(.*)' --force-latest | ||
``` |
13426
9.45%265
5.58%32
33.33%