diff --git a/HISTORY.md b/HISTORY.md index 39d1dcc..ff89fb7 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,11 @@ # History +## v4.1.0 2023 November 20 + +- Support `.x` and `.x.x` suffixes in version ranges +- Added browser export, close [#132](https://github.com/bevry/version-range/pull/132) +- Updated dependencies, [base files](https://github.com/bevry/base), and [editions](https://editions.bevry.me) using [boundation](https://github.com/bevry/boundation) + ## v4.0.0 2023 November 19 - Support `^` and `~` in version ranges diff --git a/README.md b/README.md index 0616efd..08523e9 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Check version ranges like `>=N` and `X || Y || Z` with support for Node.js, Web [Complete API Documentation.](http://master.version-range.bevry.surge.sh/docs/) -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: +Range comparison of versions for the most common use cases. Fast with broad ecosystem support. ```typescript import satisfies from 'version-range' @@ -62,12 +62,16 @@ 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', '~1')) // false, not all 1.x versions (1.1, 1.2, etc) match 1.0.x +console.log(satisfies('1', '^1.1')) // false, not all 1.x versions (1.0) match >=1.1<2 +console.log(satisfies('1', '~1.1')) // false, not all 1.x versions (1.0) match 1.1.x console.log(satisfies('1.0.0', '^1')) // true console.log(satisfies('1.0.0', '~1')) // true ``` -Doesn't support ranges that include `.x`, `&&`, `-releaseTag`, and `>X X @@ -83,7 +87,31 @@ Doesn't support ranges that include `.x`, `&&`, `-releaseTag`, and `>X

Deno

``` typescript -import pkg from 'https://unpkg.com/version-range@^4.0.0/edition-deno/index.ts' +import pkg from 'https://unpkg.com/version-range@^4.1.0/edition-deno/index.ts' +``` + +

Skypack

+ +``` html + +``` + +

unpkg

+ +``` html + +``` + +

jspm

+ +``` html + ```

Editions

@@ -91,6 +119,7 @@ import pkg from 'https://unpkg.com/version-range@^4.0.0/edition-deno/index.ts'

This package is published with the following editions:

  • version-range/source/index.ts is TypeScript source code with Import for modules
  • +
  • version-range/edition-browsers/index.js is TypeScript compiled against ES2022 for web browsers with Import for modules
  • version-range aliases version-range/edition-es2022/index.js
  • version-range/edition-es2022/index.js is TypeScript compiled against ES2022 for Node.js 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21 with Require for modules
  • version-range/edition-es2022-esm/index.js is TypeScript compiled against ES2022 for Node.js 12 || 14 || 16 || 18 || 20 || 21 with Import for modules
  • diff --git a/package-lock.json b/package-lock.json index bf55254..83b5d23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "version-range", - "version": "4.0.0", + "version": "4.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "version-range", - "version": "4.0.0", + "version": "4.1.0", "license": "Artistic-2.0", "devDependencies": { "@bevry/json": "^1.9.0", @@ -26,7 +26,8 @@ "surge": "^0.23.1", "typedoc": "^0.25.3", "typescript": "5.2.2", - "valid-directory": "^4.4.0" + "valid-directory": "^4.4.0", + "valid-module": "^2.3.0" }, "engines": { "node": ">=4" @@ -4143,6 +4144,24 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/valid-module": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/valid-module/-/valid-module-2.3.0.tgz", + "integrity": "sha512-yE+ZqXgVD8vkMTmeeh6/KB2iLwjK9t6bhebUO9ZHjqAU5r2eDe7WyCXJ2uDcuogC86SbrGPIPUVqkZuEHHo5xA==", + "dev": true, + "dependencies": { + "errlop": "^7.2.0" + }, + "bin": { + "valid-module": "bin.cjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", diff --git a/package.json b/package.json index d878806..8c9715b 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,11 @@ { "name": "version-range", - "version": "4.0.0", + "version": "4.1.0", "description": "Check version ranges like `>=N` and `X || Y || Z` with support for Node.js, Web Browsers, Deno, and TypeScript.", "homepage": "https://github.com/bevry/version-range", "license": "Artistic-2.0", "keywords": [ + "browser", "compare", "conditional", "deno", @@ -14,6 +15,7 @@ "es2022", "export-default", "gte", + "module", "node", "node.js", "nodejs", @@ -95,6 +97,20 @@ ], "engines": false }, + { + "description": "TypeScript compiled against ES2022 for web browsers with Import for modules", + "directory": "edition-browsers", + "entry": "index.js", + "tags": [ + "compiled", + "javascript", + "import" + ], + "engines": { + "node": false, + "browsers": "defaults" + } + }, { "description": "TypeScript compiled against ES2022 for Node.js 8 || 10 || 12 || 14 || 16 || 18 || 20 || 21 with Require for modules", "directory": "edition-es2022", @@ -136,7 +152,7 @@ ], "engines": { "deno": true, - "browsers": false + "browsers": true } } ], @@ -147,9 +163,14 @@ "node": { "import": "./edition-es2022-esm/index.js", "require": "./edition-es2022/index.js" + }, + "browser": { + "import": "./edition-browsers/index.js" } }, "deno": "edition-deno/index.ts", + "browser": "edition-browsers/index.js", + "module": "edition-browsers/index.js", "devDependencies": { "@bevry/json": "^1.9.0", "@bevry/update-contributors": "^1.23.0", @@ -168,12 +189,14 @@ "surge": "^0.23.1", "typedoc": "^0.25.3", "typescript": "5.2.2", - "valid-directory": "^4.4.0" + "valid-directory": "^4.4.0", + "valid-module": "^2.3.0" }, "scripts": { "our:clean": "rm -rf ./docs ./edition* ./es2015 ./es5 ./out ./.next", - "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": "npm run our:compile:deno && npm run our:compile:edition-browsers && 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-browsers": "tsc --module ESNext --target ES2022 --outDir ./edition-browsers --project tsconfig.json && ( test ! -d edition-browsers/source || ( mv edition-browsers/source edition-temp && rm -rf edition-browsers && mv edition-temp edition-browsers ) )", "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 ) )", @@ -192,9 +215,10 @@ "our:setup": "npm run our:setup:install", "our:setup:install": "npm install", "our:test": "npm run our:verify && npm test", - "our:verify": "npm run our:verify:directory && npm run our:verify:eslint && npm run our:verify:prettier", + "our:verify": "npm run our:verify:directory && npm run our:verify:eslint && npm run our:verify:module && npm run our:verify:prettier", "our:verify:directory": "valid-directory", "our:verify:eslint": "eslint --fix --ignore-pattern '**/*.d.ts' --ignore-pattern '**/vendor/' --ignore-pattern '**/node_modules/' --ext .mjs,.js,.jsx,.ts,.tsx ./source", + "our:verify:module": "valid-module", "our:verify:prettier": "prettier --write .", "test": "node ./edition-es2022/test.js" }, @@ -209,6 +233,7 @@ "trailingComma": "es5" }, "boundation": { + "browser": true, "nodeVersionTestedMinimum": 8 } } \ No newline at end of file diff --git a/source/index.ts b/source/index.ts index 9c1c87a..bba3378 100644 --- a/source/index.ts +++ b/source/index.ts @@ -2,7 +2,7 @@ export type Version = string | number export type Range = Version | Version[] const orRegex = /\s*\|\|\s*/ -const rangeRegex = /^\s*([<>=~^]*)\s*([\d.]+)(-.+)?\s*$/ +const rangeRegex = /^\s*([<>=~^]*)\s*([\d.]+?)[.x]*(-.+)?\s*$/ /** * Check if the version is within the range @@ -23,20 +23,22 @@ export default function withinVersionRange( const subjectMinorNumber = Number(subjectMinor || 0) const subjectPatchNumber = Number(subjectPatch || 0) - // cycle through the or conditions + // cycle through the conditions let combinedResult: boolean = false if (!Array.isArray(range)) range = String(range).split(orRegex) - for (const orRange of range) { + for (const condition of range) { // process range const [_, comparator, target, prerelease] = - String(orRange).match(rangeRegex) || [] + String(condition).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)}`) + throw new Error( + `range condition was invalid: ${JSON.stringify(condition)}` + ) const targetMajorNumber = Number(targetMajor || 0) const targetMinorNumber = Number(targetMinor || 0) const targetPatchNumber = Number(targetPatch || 0) @@ -164,7 +166,7 @@ export default function withinVersionRange( break default: throw new Error( - `range comparator was invalid: ${JSON.stringify(orRange)}` + `range comparator was invalid: ${JSON.stringify(condition)}` ) } if (pass) combinedResult = true diff --git a/source/test.ts b/source/test.ts index 1adc734..348d4dd 100644 --- a/source/test.ts +++ b/source/test.ts @@ -17,6 +17,7 @@ type Results = Array< > const versions = [ + // don't put .x.x here, as .x is a range, not a version '1', '2', '1.0', @@ -68,6 +69,8 @@ const readmeResults: Results = [ ['1', '^1', true], ['1', '~1', false], + ['1', '^1.1', false], + ['1', '~1.1', false], ['1.0.0', '^1', true], ['1.0.0', '~1', true], ] @@ -78,10 +81,21 @@ const indexResults: Results = [ ['1.1', '^1.0', true], ['1', '^1.1', false], + ['1', '^1', true], ['1', '~1', false], + ['1.0', '^1', true], ['1.0', '~1', true], + ['1.0', '^1.0', true], ['1.0', '~1.0', true], + ['1.0.0', '^1', true], + ['1.0.0', '~1', true], + ['1.0.1', '^1', true], + ['1.0.1', '~1', true], + ['1.1.0', '^1', true], + ['1.1.0', '~1', false], + ['1.1', '^1.0', true], ['1.1', '~1.0', false], + ['1', '^1.1', false], ['1', '~1.1', false], ['1', '>2', false], @@ -206,6 +220,28 @@ const indexResults: Results = [ ['1.1.1', '1', true], ['1.1.1', '1.1.1', true], ['1.1.1', '1.1.2', false], + + ['1', '1.x', true], + ['2', '1.x', false], + ['1.0', '1.x', true], + ['1.1', '1.x', true], + ['2.0', '1.x', false], + ['2.1', '1.x', false], + ['1.0.0', '1.x', true], + ['1.1.1', '1.x', true], + ['2.0.0', '1.x', false], + ['2.1.1', '1.x', false], + + ['1', '1.x.x', true], + ['2', '1.x.x', false], + ['1.0', '1.x.x', true], + ['1.1', '1.x.x', true], + ['2.0', '1.x.x', false], + ['2.1', '1.x.x', false], + ['1.0.0', '1.x.x', true], + ['1.1.1', '1.x.x', true], + ['2.0.0', '1.x.x', false], + ['2.1.1', '1.x.x', false], ] kava.suite('version-range', function (suite, test) {