version-range
Advanced tools
Comparing version 3.2.0 to 4.0.0-next.1700378011.3a0ce9ad3bec6097316362b17b8fa53c489b897c
export type Version = string | number; | ||
export type Range = Version | Version[]; | ||
/** | ||
* Compare two versions quickly. | ||
* @param current Is this version greater, equal to, or less than the other? | ||
* @param other The version to compare against the current version | ||
* @return 1 if current is greater than other, 0 if they are equal or equivalent, and -1 if current is less than other | ||
* Check if the version is within the range | ||
* @param subject The version to check against the range | ||
* @param range The range to check the version against | ||
*/ | ||
export default function withinVersionRange(subject: Version, range: Range): boolean; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -1,13 +0,11 @@ | ||
import versionCompare from 'https://unpkg.com/version-compare@^3.2.0/edition-deno/index.ts' | ||
export type Version = string | number | ||
export type Range = Version | Version[] | ||
const regex = /^([<>=]*)\s*([\d.]+)\s*$/ | ||
const orRegex = /\s*\|\|\s*/ | ||
const rangeRegex = /^\s*([<>=~^]*)\s*([\d.]+)(-.+)?\s*$/ | ||
/** | ||
* Compare two versions quickly. | ||
* @param current Is this version greater, equal to, or less than the other? | ||
* @param other The version to compare against the current version | ||
* @return 1 if current is greater than other, 0 if they are equal or equivalent, and -1 if current is less than other | ||
* Check if the version is within the range | ||
* @param subject The version to check against the range | ||
* @param range The range to check the version against | ||
*/ | ||
@@ -18,36 +16,159 @@ export default function withinVersionRange( | ||
): boolean { | ||
let result: boolean = false | ||
if (!Array.isArray(range)) range = String(range).split(/\s*\|\|\s*/) | ||
for (const part of range) { | ||
const parts = String(part).match(regex) || [] | ||
const [_, comparator, version] = parts | ||
if (!version) | ||
throw new Error(`version range was invalid: ${JSON.stringify(part)}`) | ||
const diff = versionCompare(subject, version) | ||
let pass: boolean = false | ||
// prepare and verify subject | ||
subject = String(subject) | ||
const [subjectMajor = null, subjectMinor = null, subjectPatch = null] = | ||
subject.split('.') | ||
if (subjectMajor === null) | ||
throw new Error(`subject was invalid: ${JSON.stringify(subject)}`) | ||
const subjectMajorNumber = Number(subjectMajor || 0) | ||
const subjectMinorNumber = Number(subjectMinor || 0) | ||
const subjectPatchNumber = Number(subjectPatch || 0) | ||
// cycle through the or conditions | ||
let combinedResult: boolean = false | ||
if (!Array.isArray(range)) range = String(range).split(orRegex) | ||
for (const orRange of range) { | ||
// process range | ||
const [_, comparator, target, prerelease] = | ||
String(orRange).match(rangeRegex) || [] | ||
// prepare and verify target | ||
const [targetMajor = null, targetMinor = null, targetPatch = null] = ( | ||
target || '' | ||
).split('.') | ||
if (!target || targetMajor == null || prerelease) | ||
throw new Error(`range was invalid: ${JSON.stringify(orRange)}`) | ||
const targetMajorNumber = Number(targetMajor || 0) | ||
const targetMinorNumber = Number(targetMinor || 0) | ||
const targetPatchNumber = Number(targetPatch || 0) | ||
// handle comparator | ||
const pass: boolean = false | ||
switch (comparator) { | ||
case '^': | ||
if (subjectMajorNumber === targetMajorNumber) { | ||
if (subjectMinorNumber === targetMinorNumber) { | ||
if (subjectPatchNumber >= targetPatchNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMinorNumber >= targetMinorNumber) { | ||
combinedResult = true | ||
} | ||
} | ||
break | ||
case '~': | ||
if (subjectMajorNumber === targetMajorNumber) { | ||
if ( | ||
subjectMinor !== null && | ||
subjectMinorNumber === targetMinorNumber | ||
) { | ||
if (subjectPatchNumber >= targetPatchNumber) { | ||
combinedResult = true | ||
} | ||
} | ||
} | ||
break | ||
case '>=': | ||
pass = diff >= 0 | ||
if (subjectMajorNumber === targetMajorNumber) { | ||
if (subjectMinorNumber === targetMinorNumber) { | ||
if (subjectPatchNumber >= targetPatchNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMinorNumber >= targetMinorNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMajorNumber >= targetMajorNumber) { | ||
combinedResult = true | ||
} | ||
break | ||
case '>': | ||
pass = diff === 1 | ||
if (subjectMajorNumber === targetMajorNumber) { | ||
if (targetMinor === null) { | ||
// x > x = false | ||
// x.y > x = false | ||
} else if (subjectMinorNumber === targetMinorNumber) { | ||
if (targetPatch === null) { | ||
// x.y > x.y = false | ||
// x.y.z > x.y = false | ||
} else if (subjectPatchNumber > targetPatchNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMinorNumber > targetMinorNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMajorNumber > targetMajorNumber) { | ||
combinedResult = true | ||
} | ||
break | ||
case '<': | ||
pass = diff === -1 | ||
if (subjectMajorNumber === targetMajorNumber) { | ||
if (subjectMinor === null) { | ||
// x < x = false | ||
// x < x.y = false | ||
} else if (subjectMinorNumber === targetMinorNumber) { | ||
if (subjectPatch === null) { | ||
// x.y < x.y = false | ||
// x.y < x.y.z = false | ||
} else if (subjectPatchNumber < targetPatchNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMinorNumber < targetMinorNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMajorNumber < targetMajorNumber) { | ||
combinedResult = true | ||
} | ||
break | ||
case '<=': | ||
pass = diff <= 0 | ||
if (subjectMajorNumber === targetMajorNumber) { | ||
if (subjectMinor === null) { | ||
if (targetMinor === null) { | ||
// x <= x = true | ||
combinedResult = true | ||
} | ||
// x <= x.y = false | ||
} else if (targetMinor === null) { | ||
// x.y <= x = true | ||
combinedResult = true | ||
} else if (subjectMinorNumber === targetMinorNumber) { | ||
if (subjectPatch === null) { | ||
if (targetPatch === null) { | ||
// x.y <= x.y = true | ||
combinedResult = true | ||
} | ||
// x.y <= x.y.z = false | ||
} else if (targetPatch === null) { | ||
// x.y.z <= x.y = true | ||
combinedResult = true | ||
} else if (subjectPatchNumber <= targetPatchNumber) { | ||
// x.y.z <= x.y.z = true | ||
combinedResult = true | ||
} | ||
} else if (subjectMinorNumber <= targetMinorNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMajorNumber <= targetMajorNumber) { | ||
combinedResult = true | ||
} | ||
break | ||
case '=': | ||
case '': | ||
pass = diff === 0 | ||
if (subjectMajor === targetMajor) { | ||
if (targetMinor === null) { | ||
combinedResult = true | ||
} else if (subjectMinor === targetMinor) { | ||
if (targetPatch === null || subjectPatch === targetPatch) { | ||
combinedResult = true | ||
} | ||
} | ||
} | ||
break | ||
default: | ||
throw new Error( | ||
`version range comparator was invalid: ${JSON.stringify(part)}` | ||
`range comparator was invalid: ${JSON.stringify(orRange)}` | ||
) | ||
} | ||
if (pass) result = true | ||
if (pass) combinedResult = true | ||
} | ||
return result | ||
return combinedResult | ||
} |
{ | ||
"name": "version-range", | ||
"version": "3.2.0", | ||
"version": "4.0.0-next.1700378011.3a0ce9ad3bec6097316362b17b8fa53c489b897c", | ||
"description": "Check version ranges like `>=N` and `X || Y || Z` with support for Node.js, Web Browsers, Deno, and TypeScript.", | ||
@@ -14,3 +14,3 @@ "homepage": "https://github.com/bevry/version-range", | ||
"denoland", | ||
"es5", | ||
"es2022", | ||
"export-default", | ||
@@ -39,3 +39,2 @@ "gte", | ||
"patreon", | ||
"flattr", | ||
"liberapay", | ||
@@ -46,3 +45,5 @@ "buymeacoffee", | ||
"paypal", | ||
"wishlist" | ||
"---", | ||
"discord", | ||
"twitch" | ||
], | ||
@@ -52,3 +53,3 @@ "config": { | ||
"githubSponsorsUsername": "balupton", | ||
"thanksdevGithubUsername": "balupton", | ||
"thanksdevGithubUsername": "bevry", | ||
"buymeacoffeeUsername": "balupton", | ||
@@ -62,2 +63,5 @@ "cryptoURL": "https://bevry.me/crypto", | ||
"wishlistURL": "https://bevry.me/wishlist", | ||
"discordServerID": "1147436445783560193", | ||
"discordServerInvite": "nQuXddV7VP", | ||
"twitchUsername": "balupton", | ||
"githubUsername": "bevry", | ||
@@ -100,4 +104,4 @@ "githubRepository": "version-range", | ||
{ | ||
"description": "TypeScript compiled against ES5 for Node.js with Require for modules", | ||
"directory": "edition-es5", | ||
"description": "TypeScript compiled against ES2022 for Node.js 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21 with Require for modules", | ||
"directory": "edition-es2022", | ||
"entry": "index.js", | ||
@@ -107,7 +111,7 @@ "tags": [ | ||
"javascript", | ||
"es5", | ||
"es2022", | ||
"require" | ||
], | ||
"engines": { | ||
"node": "4 || 6 || 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21", | ||
"node": "8 || 10 || 12 || 14 || 16 || 18 || 20 || 21", | ||
"browsers": false | ||
@@ -117,4 +121,4 @@ } | ||
{ | ||
"description": "TypeScript compiled against ES5 for Node.js with Import for modules", | ||
"directory": "edition-es5-esm", | ||
"description": "TypeScript compiled against ES2022 for Node.js 12 || 14 || 16 || 18 || 20 || 21 with Import for modules", | ||
"directory": "edition-es2022-esm", | ||
"entry": "index.js", | ||
@@ -124,3 +128,3 @@ "tags": [ | ||
"javascript", | ||
"es5", | ||
"es2022", | ||
"import" | ||
@@ -150,38 +154,36 @@ ], | ||
"type": "module", | ||
"main": "edition-es5/index.js", | ||
"main": "edition-es2022/index.js", | ||
"exports": { | ||
"node": { | ||
"import": "./edition-es5-esm/index.js", | ||
"require": "./edition-es5/index.js" | ||
"import": "./edition-es2022-esm/index.js", | ||
"require": "./edition-es2022/index.js" | ||
} | ||
}, | ||
"deno": "edition-deno/index.ts", | ||
"dependencies": { | ||
"version-compare": "^3.2.0" | ||
}, | ||
"devDependencies": { | ||
"@bevry/json": "^1.9.0", | ||
"@bevry/update-contributors": "^1.23.0", | ||
"@types/node": "^20.9.0", | ||
"@types/node": "^20.9.2", | ||
"@typescript-eslint/eslint-plugin": "^6.11.0", | ||
"@typescript-eslint/parser": "^6.11.0", | ||
"assert-helpers": "^11.4.0", | ||
"eslint": "^8.53.0", | ||
"eslint-config-bevry": "^4.0.0", | ||
"eslint": "^8.54.0", | ||
"eslint-config-bevry": "^5.0.0", | ||
"eslint-config-prettier": "^9.0.0", | ||
"eslint-plugin-prettier": "^5.0.1", | ||
"kava": "^7.1.0", | ||
"kava": "^7.2.0", | ||
"make-deno-edition": "^1.3.0", | ||
"prettier": "^3.1.0", | ||
"projectz": "^3.0.0", | ||
"projectz": "^3.2.0", | ||
"surge": "^0.23.1", | ||
"typedoc": "^0.25.3", | ||
"typescript": "5.2.2", | ||
"valid-directory": "^4.2.0" | ||
"valid-directory": "^4.4.0" | ||
}, | ||
"scripts": { | ||
"our:clean": "rm -rf ./docs ./edition* ./es2015 ./es5 ./out ./.next", | ||
"our:compile": "npm run our:compile:deno && npm run our:compile:edition-es5 && npm run our:compile:edition-es5-esm && npm run our:compile:types", | ||
"our:compile": "npm run our:compile:deno && npm run our:compile:edition-es2022 && npm run our:compile:edition-es2022-esm && npm run our:compile:types", | ||
"our:compile:deno": "make-deno-edition --attempt", | ||
"our:compile:edition-es5": "tsc --module commonjs --target ES5 --outDir ./edition-es5 --project tsconfig.json && ( test ! -d edition-es5/source || ( mv edition-es5/source edition-temp && rm -rf edition-es5 && mv edition-temp edition-es5 ) ) && printf '%s' '{\"type\": \"commonjs\"}' > edition-es5/package.json", | ||
"our:compile:edition-es5-esm": "tsc --module ESNext --target ES5 --outDir ./edition-es5-esm --project tsconfig.json && ( test ! -d edition-es5-esm/source || ( mv edition-es5-esm/source edition-temp && rm -rf edition-es5-esm && mv edition-temp edition-es5-esm ) ) && printf '%s' '{\"type\": \"module\"}' > edition-es5-esm/package.json", | ||
"our:compile:edition-es2022": "tsc --module commonjs --target ES2022 --outDir ./edition-es2022 --project tsconfig.json && ( test ! -d edition-es2022/source || ( mv edition-es2022/source edition-temp && rm -rf edition-es2022 && mv edition-temp edition-es2022 ) ) && printf '%s' '{\"type\": \"commonjs\"}' > edition-es2022/package.json", | ||
"our:compile:edition-es2022-esm": "tsc --module ESNext --target ES2022 --outDir ./edition-es2022-esm --project tsconfig.json && ( test ! -d edition-es2022-esm/source || ( mv edition-es2022-esm/source edition-temp && rm -rf edition-es2022-esm && mv edition-temp edition-es2022-esm ) ) && printf '%s' '{\"type\": \"module\"}' > edition-es2022-esm/package.json", | ||
"our:compile:types": "tsc --project tsconfig.json --emitDeclarationOnly --declaration --declarationMap --declarationDir ./compiled-types && ( test ! -d compiled-types/source || ( mv compiled-types/source edition-temp && rm -rf compiled-types && mv edition-temp compiled-types ) )", | ||
@@ -207,3 +209,3 @@ "our:deploy": "printf '%s\n' 'no need for this project'", | ||
"our:verify:prettier": "prettier --write .", | ||
"test": "node ./edition-es5/test.js" | ||
"test": "node ./edition-es2022/test.js" | ||
}, | ||
@@ -221,7 +223,4 @@ "eslintConfig": { | ||
"boundation": { | ||
"compiler": "typescript", | ||
"targets": [ | ||
"ES5" | ||
] | ||
"nodeVersionTestedMinimum": 8 | ||
} | ||
} | ||
} |
@@ -15,5 +15,4 @@ <!-- TITLE/ --> | ||
<span class="badge-githubsponsors"><a href="https://github.com/sponsors/balupton" title="Donate to this project using GitHub Sponsors"><img src="https://img.shields.io/badge/github-donate-yellow.svg" alt="GitHub Sponsors donate button" /></a></span> | ||
<span class="badge-thanksdev"><a href="https://thanks.dev/u/gh/balupton" title="Donate to this project using ThanksDev"><img src="https://img.shields.io/badge/thanksdev-donate-yellow.svg" alt="ThanksDev donate button" /></a></span> | ||
<span class="badge-thanksdev"><a href="https://thanks.dev/u/gh/bevry" title="Donate to this project using ThanksDev"><img src="https://img.shields.io/badge/thanksdev-donate-yellow.svg" alt="ThanksDev donate button" /></a></span> | ||
<span class="badge-patreon"><a href="https://patreon.com/bevry" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span> | ||
<span class="badge-flattr"><a href="https://flattr.com/profile/balupton" title="Donate to this project using Flattr"><img src="https://img.shields.io/badge/flattr-donate-yellow.svg" alt="Flattr donate button" /></a></span> | ||
<span class="badge-liberapay"><a href="https://liberapay.com/bevry" title="Donate to this project using Liberapay"><img src="https://img.shields.io/badge/liberapay-donate-yellow.svg" alt="Liberapay donate button" /></a></span> | ||
@@ -24,3 +23,5 @@ <span class="badge-buymeacoffee"><a href="https://buymeacoffee.com/balupton" title="Donate to this project using Buy Me A Coffee"><img src="https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg" alt="Buy Me A Coffee donate button" /></a></span> | ||
<span class="badge-paypal"><a href="https://bevry.me/paypal" title="Donate to this project using Paypal"><img src="https://img.shields.io/badge/paypal-donate-yellow.svg" alt="PayPal donate button" /></a></span> | ||
<span class="badge-wishlist"><a href="https://bevry.me/wishlist" title="Buy an item on our wishlist for us"><img src="https://img.shields.io/badge/wishlist-donate-yellow.svg" alt="Wishlist browse button" /></a></span> | ||
<br class="badge-separator" /> | ||
<span class="badge-discord"><a href="https://discord.gg/nQuXddV7VP" title="Join this project's community on Discord"><img src="https://img.shields.io/discord/1147436445783560193?logo=discord&label=discord" alt="Discord server badge" /></a></span> | ||
<span class="badge-twitch"><a href="https://www.twitch.tv/balupton" title="Join this project's community on Twitch"><img src="https://img.shields.io/twitch/status/balupton?logo=twitch" alt="Twitch community badge" /></a></span> | ||
@@ -41,3 +42,3 @@ <!-- /BADGES --> | ||
Super fast and super compatible version range comparison for the most common use cases. | ||
Super fast and super compatible version range comparison for the most common use cases. As semver has two different behaviours based on whether the version is coerced or not, this library differs to match our actual expectations, unlike semver. For example: | ||
@@ -49,6 +50,26 @@ ```typescript | ||
console.log(satisfies('1.0', '1 || 2')) // true | ||
console.log(satisfies('1.1.0', '^1.1')) // true | ||
console.log(satisfies('1.1.0', '~1.1')) // true | ||
console.log(satisfies('1.0.0', '5 || <=2')) // true | ||
console.log(satisfies('1', '<=2')) // true | ||
console.log(satisfies('1.0', '<=2')) // true | ||
console.log(satisfies('1.0.0', '<=2')) // true | ||
console.log(satisfies('2', '>1')) // true | ||
console.log(satisfies('2', '>=1')) // true | ||
console.log(satisfies('1', '>=1')) // true | ||
console.log(satisfies('1.0', '>=1')) // true | ||
console.log(satisfies('1.0.0', '>=1')) // true | ||
console.log(satisfies('1', '>=1.0.0')) // true | ||
console.log(satisfies('1.0', '>=1.0.0')) // true | ||
console.log(satisfies('1.0.0', '>=1.0.0')) // true | ||
console.log(satisfies('1', '^1')) // true | ||
console.log(satisfies('1', '~1')) // false | ||
console.log(satisfies('1.0.0', '^1')) // true | ||
console.log(satisfies('1.0.0', '~1')) // true | ||
``` | ||
Doesn't support `&&` and `-releaseTag`. | ||
Doesn't support ranges that include `.x`, `&&`, `-releaseTag`, and `>X <Y`. | ||
@@ -69,3 +90,3 @@ <!-- INSTALL/ --> | ||
``` typescript | ||
import pkg from 'https://unpkg.com/version-range@^3.2.0/edition-deno/index.ts' | ||
import pkg from 'https://unpkg.com/version-range@^4.0.0/edition-deno/index.ts' | ||
``` | ||
@@ -78,5 +99,5 @@ | ||
<ul><li><code>version-range/source/index.ts</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> source code with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li> | ||
<li><code>version-range</code> aliases <code>version-range/edition-es5/index.js</code></li> | ||
<li><code>version-range/edition-es5/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against ES5 for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li> | ||
<li><code>version-range/edition-es5-esm/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against ES5 for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li> | ||
<li><code>version-range</code> aliases <code>version-range/edition-es2022/index.js</code></li> | ||
<li><code>version-range/edition-es2022/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against ES2022 for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21 with <a href="https://nodejs.org/dist/latest-v5.x/docs/api/modules.html" title="Node/CJS Modules">Require</a> for modules</li> | ||
<li><code>version-range/edition-es2022-esm/index.js</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> compiled against ES2022 for <a href="https://nodejs.org" title="Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine">Node.js</a> 12 || 14 || 16 || 18 || 20 || 21 with <a href="https://babeljs.io/docs/learn-es2015/#modules" title="ECMAScript Modules">Import</a> for modules</li> | ||
<li><code>version-range/edition-deno/index.ts</code> is <a href="https://www.typescriptlang.org/" title="TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ">TypeScript</a> source code made to be compatible with <a href="https://deno.land" title="Deno is a secure runtime for JavaScript and TypeScript, it is an alternative to Node.js">Deno</a></li></ul> | ||
@@ -120,5 +141,4 @@ | ||
<span class="badge-githubsponsors"><a href="https://github.com/sponsors/balupton" title="Donate to this project using GitHub Sponsors"><img src="https://img.shields.io/badge/github-donate-yellow.svg" alt="GitHub Sponsors donate button" /></a></span> | ||
<span class="badge-thanksdev"><a href="https://thanks.dev/u/gh/balupton" title="Donate to this project using ThanksDev"><img src="https://img.shields.io/badge/thanksdev-donate-yellow.svg" alt="ThanksDev donate button" /></a></span> | ||
<span class="badge-thanksdev"><a href="https://thanks.dev/u/gh/bevry" title="Donate to this project using ThanksDev"><img src="https://img.shields.io/badge/thanksdev-donate-yellow.svg" alt="ThanksDev donate button" /></a></span> | ||
<span class="badge-patreon"><a href="https://patreon.com/bevry" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span> | ||
<span class="badge-flattr"><a href="https://flattr.com/profile/balupton" title="Donate to this project using Flattr"><img src="https://img.shields.io/badge/flattr-donate-yellow.svg" alt="Flattr donate button" /></a></span> | ||
<span class="badge-liberapay"><a href="https://liberapay.com/bevry" title="Donate to this project using Liberapay"><img src="https://img.shields.io/badge/liberapay-donate-yellow.svg" alt="Liberapay donate button" /></a></span> | ||
@@ -129,3 +149,2 @@ <span class="badge-buymeacoffee"><a href="https://buymeacoffee.com/balupton" title="Donate to this project using Buy Me A Coffee"><img src="https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg" alt="Buy Me A Coffee donate button" /></a></span> | ||
<span class="badge-paypal"><a href="https://bevry.me/paypal" title="Donate to this project using Paypal"><img src="https://img.shields.io/badge/paypal-donate-yellow.svg" alt="PayPal donate button" /></a></span> | ||
<span class="badge-wishlist"><a href="https://bevry.me/wishlist" title="Buy an item on our wishlist for us"><img src="https://img.shields.io/badge/wishlist-donate-yellow.svg" alt="Wishlist browse button" /></a></span> | ||
@@ -132,0 +151,0 @@ <h3>Contributors</h3> |
@@ -5,3 +5,3 @@ # Security Policy | ||
This project meets standardized secure software development practices, including 2FA for all members, password managers with monitoring, secure secret retrieval instead of storage. [Learn more about our practices.](https://tidelift.com/funding/github/npm/version-range) | ||
This project meets standardized secure software development practices, including 2FA for all members, password managers with monitoring, secure secret retrieval instead of storage. [Learn about our practices.](https://tidelift.com/funding/github/npm/version-range) | ||
@@ -12,5 +12,5 @@ ## Supported Versions | ||
[Refer to supported ecosystem versions: `Editions` section in `README.md`.](https://github.com/bevry/version-range/blob/master/README.md#Editions) | ||
[Refer to supported ecosystem versions: `Editions` section in `README.md`](https://github.com/bevry/version-range/blob/master/README.md#Editions) | ||
[Refer to automated support of ecosystem versions: `boundation` entries in `HISTORY.md`.](https://github.com/bevry/version-range/blob/master/HISTORY.md) | ||
[Refer to automated support of ecosystem versions: `boundation` entries in `HISTORY.md`](https://github.com/bevry/version-range/blob/master/HISTORY.md) | ||
@@ -17,0 +17,0 @@ Besides testing and verification, out CI also [auto-merges](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/automating-dependabot-with-github-actions) [Dependabot security updates](https://docs.github.com/en/code-security/dependabot/dependabot-security-updates/about-dependabot-security-updates) and [auto-publishes](https://github.com/bevry-actions/npm) successful builds of the [`master` branch](https://github.com/bevry/wait/actions?query=branch%3Amaster) to the [`next` version tag](https://www.npmjs.com/package/version-range?activeTab=versions), offering immediate resolutions before scheduled maintenance releases. |
@@ -1,13 +0,11 @@ | ||
import versionCompare from 'version-compare' | ||
export type Version = string | number | ||
export type Range = Version | Version[] | ||
const regex = /^([<>=]*)\s*([\d.]+)\s*$/ | ||
const orRegex = /\s*\|\|\s*/ | ||
const rangeRegex = /^\s*([<>=~^]*)\s*([\d.]+)(-.+)?\s*$/ | ||
/** | ||
* Compare two versions quickly. | ||
* @param current Is this version greater, equal to, or less than the other? | ||
* @param other The version to compare against the current version | ||
* @return 1 if current is greater than other, 0 if they are equal or equivalent, and -1 if current is less than other | ||
* Check if the version is within the range | ||
* @param subject The version to check against the range | ||
* @param range The range to check the version against | ||
*/ | ||
@@ -18,36 +16,159 @@ export default function withinVersionRange( | ||
): boolean { | ||
let result: boolean = false | ||
if (!Array.isArray(range)) range = String(range).split(/\s*\|\|\s*/) | ||
for (const part of range) { | ||
const parts = String(part).match(regex) || [] | ||
const [_, comparator, version] = parts | ||
if (!version) | ||
throw new Error(`version range was invalid: ${JSON.stringify(part)}`) | ||
const diff = versionCompare(subject, version) | ||
let pass: boolean = false | ||
// prepare and verify subject | ||
subject = String(subject) | ||
const [subjectMajor = null, subjectMinor = null, subjectPatch = null] = | ||
subject.split('.') | ||
if (subjectMajor === null) | ||
throw new Error(`subject was invalid: ${JSON.stringify(subject)}`) | ||
const subjectMajorNumber = Number(subjectMajor || 0) | ||
const subjectMinorNumber = Number(subjectMinor || 0) | ||
const subjectPatchNumber = Number(subjectPatch || 0) | ||
// cycle through the or conditions | ||
let combinedResult: boolean = false | ||
if (!Array.isArray(range)) range = String(range).split(orRegex) | ||
for (const orRange of range) { | ||
// process range | ||
const [_, comparator, target, prerelease] = | ||
String(orRange).match(rangeRegex) || [] | ||
// prepare and verify target | ||
const [targetMajor = null, targetMinor = null, targetPatch = null] = ( | ||
target || '' | ||
).split('.') | ||
if (!target || targetMajor == null || prerelease) | ||
throw new Error(`range was invalid: ${JSON.stringify(orRange)}`) | ||
const targetMajorNumber = Number(targetMajor || 0) | ||
const targetMinorNumber = Number(targetMinor || 0) | ||
const targetPatchNumber = Number(targetPatch || 0) | ||
// handle comparator | ||
const pass: boolean = false | ||
switch (comparator) { | ||
case '^': | ||
if (subjectMajorNumber === targetMajorNumber) { | ||
if (subjectMinorNumber === targetMinorNumber) { | ||
if (subjectPatchNumber >= targetPatchNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMinorNumber >= targetMinorNumber) { | ||
combinedResult = true | ||
} | ||
} | ||
break | ||
case '~': | ||
if (subjectMajorNumber === targetMajorNumber) { | ||
if ( | ||
subjectMinor !== null && | ||
subjectMinorNumber === targetMinorNumber | ||
) { | ||
if (subjectPatchNumber >= targetPatchNumber) { | ||
combinedResult = true | ||
} | ||
} | ||
} | ||
break | ||
case '>=': | ||
pass = diff >= 0 | ||
if (subjectMajorNumber === targetMajorNumber) { | ||
if (subjectMinorNumber === targetMinorNumber) { | ||
if (subjectPatchNumber >= targetPatchNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMinorNumber >= targetMinorNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMajorNumber >= targetMajorNumber) { | ||
combinedResult = true | ||
} | ||
break | ||
case '>': | ||
pass = diff === 1 | ||
if (subjectMajorNumber === targetMajorNumber) { | ||
if (targetMinor === null) { | ||
// x > x = false | ||
// x.y > x = false | ||
} else if (subjectMinorNumber === targetMinorNumber) { | ||
if (targetPatch === null) { | ||
// x.y > x.y = false | ||
// x.y.z > x.y = false | ||
} else if (subjectPatchNumber > targetPatchNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMinorNumber > targetMinorNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMajorNumber > targetMajorNumber) { | ||
combinedResult = true | ||
} | ||
break | ||
case '<': | ||
pass = diff === -1 | ||
if (subjectMajorNumber === targetMajorNumber) { | ||
if (subjectMinor === null) { | ||
// x < x = false | ||
// x < x.y = false | ||
} else if (subjectMinorNumber === targetMinorNumber) { | ||
if (subjectPatch === null) { | ||
// x.y < x.y = false | ||
// x.y < x.y.z = false | ||
} else if (subjectPatchNumber < targetPatchNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMinorNumber < targetMinorNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMajorNumber < targetMajorNumber) { | ||
combinedResult = true | ||
} | ||
break | ||
case '<=': | ||
pass = diff <= 0 | ||
if (subjectMajorNumber === targetMajorNumber) { | ||
if (subjectMinor === null) { | ||
if (targetMinor === null) { | ||
// x <= x = true | ||
combinedResult = true | ||
} | ||
// x <= x.y = false | ||
} else if (targetMinor === null) { | ||
// x.y <= x = true | ||
combinedResult = true | ||
} else if (subjectMinorNumber === targetMinorNumber) { | ||
if (subjectPatch === null) { | ||
if (targetPatch === null) { | ||
// x.y <= x.y = true | ||
combinedResult = true | ||
} | ||
// x.y <= x.y.z = false | ||
} else if (targetPatch === null) { | ||
// x.y.z <= x.y = true | ||
combinedResult = true | ||
} else if (subjectPatchNumber <= targetPatchNumber) { | ||
// x.y.z <= x.y.z = true | ||
combinedResult = true | ||
} | ||
} else if (subjectMinorNumber <= targetMinorNumber) { | ||
combinedResult = true | ||
} | ||
} else if (subjectMajorNumber <= targetMajorNumber) { | ||
combinedResult = true | ||
} | ||
break | ||
case '=': | ||
case '': | ||
pass = diff === 0 | ||
if (subjectMajor === targetMajor) { | ||
if (targetMinor === null) { | ||
combinedResult = true | ||
} else if (subjectMinor === targetMinor) { | ||
if (targetPatch === null || subjectPatch === targetPatch) { | ||
combinedResult = true | ||
} | ||
} | ||
} | ||
break | ||
default: | ||
throw new Error( | ||
`version range comparator was invalid: ${JSON.stringify(part)}` | ||
`range comparator was invalid: ${JSON.stringify(orRange)}` | ||
) | ||
} | ||
if (pass) result = true | ||
if (pass) combinedResult = true | ||
} | ||
return result | ||
return combinedResult | ||
} |
@@ -9,3 +9,3 @@ { | ||
"strict": true, | ||
"target": "ES5", | ||
"target": "ES2022", | ||
"module": "ESNext" | ||
@@ -12,0 +12,0 @@ }, |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
56936
0
710
167
18
1
1
- Removedversion-compare@^3.2.0
- Removededitions@6.21.0(transitive)
- Removedversion-compare@3.11.0(transitive)
- Removedversion-range@4.14.0(transitive)