const VersionCompare = require('compare-versions');
/** Version Number related methods */
class Versions {
/**
* Compare [semver](https://semver.org/) version strings.
*
* @param {string} firstVersion First version to compare
* @param {string} secondVersion Second version to compare
* @param {string|null} operator Optional; Arithmetic operator to use (>, >=, =, <=, <, !=). Defaults to `null`.
* @returns {boolean|integer} If operator is not `null`: true` if the comparison between the firstVersion and the secondVersion satisfies the operator, `false` otherwise. If operator is `null`: Numeric value compatible with the [Array.sort(fn) interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters).
* ```
*/
static compare(v1, v2, operator = null) {
if (operator !== null) {
return VersionCompare.compare(v1, v2, operator);
}
else {
return VersionCompare(v1, v2);
}
}
/**
* Validate [semver](https://semver.org/) version strings.
*
* @param {*} version - Version number to validate
* @returns - `true` if the version number is a valid semver version number, `false` otherwise.
*/
static validate(version) {
return VersionCompare.validate(version);
}
/**
* Tries to determine the most suitable version from a well-known discovery document that software is compatible to.
*
* @static
* @param {array} wkVersions - A well-known discovery document compliant to the API specification.
* @param {boolean} preferProduction - Set to `false` to make no difference between production and non-production versions.
* @param {string|null} minVersion - The minimum version that should be returned.
* @param {string|null} maxVersion - The maximum version that should be returned.
* @returns {object[]} - Gives a list that lists all compatible versions (as still API compliant objects) ordered from the most suitable to the least suitable.
*/
static findCompatible(wkVersions, preferProduction = true, minVersion = null, maxVersion = null) {
if (!Array.isArray(wkVersions) || wkVersions.length === 0) {
return [];
}
let compatible = wkVersions.filter(c => {
if (typeof c.url === 'string' && Versions.validate(c.api_version)) {
let hasMinVer = Versions.validate(minVersion);
let hasMaxVer = Versions.validate(maxVersion);
if (hasMinVer && hasMaxVer) {
return Versions.compare(c.api_version, minVersion, ">=") && Versions.compare(c.api_version, maxVersion, "<=");
}
else if (hasMinVer) {
return Versions.compare(c.api_version, minVersion, ">=");
}
else if (hasMaxVer) {
return Versions.compare(c.api_version, maxVersion, "<=");
}
else {
return true;
}
}
return false;
});
if (compatible.length === 0) {
return [];
}
return compatible.sort((c1, c2) => {
let p1 = c1.production === true;
let p2 = c2.production === true;
if (!preferProduction || p1 === p2) {
return Versions.compare(c1.api_version, c2.api_version) * -1; // `* -1` to sort in descending order.
}
else if (p1) {
return -1;
}
else {
return 1;
}
});
}
/**
* Find the latest version from well-known discovery that applies to the specified rules.
*
* This is basically the same as calling `findCompatible` and using the first element from the result.
*
* @param {array} wkVersions - A well-known discovery document compliant to the API specification.
* @param {boolean} preferProduction - Set to `false` to make no difference between production and non-production versions.
* @param {string|null} minVersion - The minimum version that should be returned.
* @param {string|null} maxVersion - The maximum version that should be returned.
* @returns {object|null}
*/
static findLatest(wkVersions, preferProduction = true, minVersion = null, maxVersion = null) {
let versions = Versions.findCompatible(wkVersions, preferProduction, minVersion, maxVersion);
if (versions.length > 0) {
return versions[0];
}
else {
return null;
}
}
}
module.exports = Versions;