diff --git a/src/index.js b/src/index.js index 355fc0a..bc3bd37 100644 --- a/src/index.js +++ b/src/index.js @@ -4,6 +4,7 @@ export * from './first-past' export * from './min-version' export * from './next-version' export * from './prerelease' +export * from './upper-bound' export * from './valid-version-or-range' export * from './version-compare' export * from './x-sort' diff --git a/src/test/min-version.test.mjs b/src/test/min-version.test.mjs index bc40826..e993c56 100644 --- a/src/test/min-version.test.mjs +++ b/src/test/min-version.test.mjs @@ -14,6 +14,7 @@ describe('minVersion', () => { ['1.0.x', '1.0.0'], ['1.0.0-alpha.x', '1.0.0-alpha.0'], ['1.0.0-beta.x', '1.0.0-beta.0'], - ['1.0.0-rc.x', '1.0.0-rc.0'] + ['1.0.0-rc.x', '1.0.0-rc.0'], + ['1.0.0 - 2', '1.0.0'] ])('%s => %s', (input, expected) => expect(minVersion(input)).toBe(expected)) }) diff --git a/src/test/next-version.test.js b/src/test/next-version.test.js index b41880d..37d9fcc 100644 --- a/src/test/next-version.test.js +++ b/src/test/next-version.test.js @@ -5,6 +5,7 @@ import * as ver from '../next-version' describe('nextVersion', () => { describe('handles semver style', () => { test.each([ + // currVer, increment, expected ['1.0.0', undefined, '1.0.1'], ['1.0.0-alpha.94', undefined, '1.0.0-alpha.95'], ['1.0.0-alpha.94', 'prerelease', '1.0.0-alpha.95'], diff --git a/src/test/upper-bound.test.mjs b/src/test/upper-bound.test.mjs new file mode 100644 index 0000000..17ff1fe --- /dev/null +++ b/src/test/upper-bound.test.mjs @@ -0,0 +1,14 @@ +/* global describe expect test */ +import { upperBound } from '../upper-bound' + +describe('upperBound', () => { + test.each([ + ['*', '*'], + ['1.0.0', '1.0.0'], + ['2', '<3.0.0-0'], + ['1.0.0 - 2', '<3.0.0-0'], + ['1.0.x', '<1.1.0-0'], + ['1.0.0-alpha.1', '1.0.0-alpha.1'], + ['1.0 - 1.2.3', '1.2.3'] + ])('%s => %s', (input, expected) => expect(upperBound(input)).toBe(expected)) +}) diff --git a/src/test/valid-version-or-range.test.mjs b/src/test/valid-version-or-range.test.mjs new file mode 100644 index 0000000..bce3fce --- /dev/null +++ b/src/test/valid-version-or-range.test.mjs @@ -0,0 +1,13 @@ +/* global describe expect test */ +import { validVersionOrRange } from '../valid-version-or-range' + +describe('validVersionOrRange', () => { + test.each([ + [{ input : '1.0.0' }, true], + [{ input : '1.0.0-alpha.0' }, true], + [{ input : '1.0.0-alpha.1' }, true], + [{ input : '1.0.0 - 2' }, true], + [{ input : '1.0.x', onlyXRange : true }, true], + [{ input : '1.0.0-alpha.1' }, true] + ])('%s => %s', (input, expected) => expect(validVersionOrRange(input)).toBe(expected)) +}) diff --git a/src/upper-bound.mjs b/src/upper-bound.mjs new file mode 100644 index 0000000..5c71083 --- /dev/null +++ b/src/upper-bound.mjs @@ -0,0 +1,22 @@ +import semver from 'semver' + +/** + * Finds the ceiling of a range. For '*', the ceiling is '*'. For specific versions or any range capped by a specific + * version, the ceiling is that version. For any open-ended range, the ceiling is defined by a '-0' range + * function where 'verision-0' least range above the given range. + * @param {string} range - The range to find the ceiling for. + * @returns {string} - Either '*', a specific version, or a '-0'. + */ +const upperBound = (range) => { + const normalizedRange = semver.validRange(range) + if (normalizedRange === null) { + return null + } + + const ranges = normalizedRange.split(' ') + const upperRange = ranges[ranges.length - 1] + + return upperRange.startsWith('<=') ? upperRange.slice(2) : upperRange +} + +export { upperBound } diff --git a/src/valid-version-or-range.mjs b/src/valid-version-or-range.mjs index f6f9f8a..b35e6a3 100644 --- a/src/valid-version-or-range.mjs +++ b/src/valid-version-or-range.mjs @@ -8,8 +8,8 @@ const validVersionOrRange = ({ input = throw new Error("'input' is required."), onlyXRange = false }) => - (dissallowVersions !== true && semver.valid(input)) + !!((dissallowVersions !== true && semver.valid(input)) || (onlyXRange !== true && dissallowRanges !== true && semver.validRange(input)) - || (onlyXRange === true && input.match(xRangeRE)) + || (onlyXRange === true && input.match(xRangeRE))) export { validVersionOrRange }