export class Version { /** * Construct a Version from components. * * @param {number} major The major version * @param {number} minor The minor version * @param {number} patch The patch version * @param {array|undefined} pr_ident A list of pre-release identifiers, if * any. * @param {array|undefined} build_ident A list of build identifiers, if * any. */ constructor(major, minor, patch, pr_ident, build_ident) { this.major = major; this.minor = minor; this.patch = patch; this.pr_ident = pr_ident; this.build_ident = build_ident; } /** * Construct a version from a semver 2 compliant string. * * This function is intended for use with semver 2 compliant strings. * Malformatted strins may still parse correctly, however. * * @param {string} version_string A semver 2.0.0 compliant version string. * @return {Version} A version object. */ static from_semver(version_string) { let build_split = version_string.split("+"), pr_split = build_split[0].split("-"), version_split = pr_split[0].split("."), version = []; version.push(parseInt(version_split[0])); if (version_split[1] != undefined) { version.push(parseInt(version_split[1])); } else { version.push(0); } if (version_split[2] != undefined) { version.push(parseInt(version_split[2])); } else { version.push(0); } if (pr_split[1] != undefined) { version.push(pr_split[1].split(".")); } else { version.push(undefined); } if (build_split[1] != undefined) { version.push(build_split[1].split(".")); } else { version.push(undefined); } return new Version(version[0], version[1], version[2], version[3], version[4]); } /** * Returns true if a given version is compatible with this one. * * Compatibility is defined as having the same nonzero major version * number, or if both major versions are zero, the same nonzero minor * version number, or if both minor versions are zero, the same nonzero * patch version number. * * This implements the ^ operator in npm's semver package, with the * exception of the prerelease exclusion rule. * * @param {Version} fver The other version to test against * @return {bool} */ is_compatible_with(fver) { return this.major !== 0 && this.major === fver.major || this.major === 0 && fver.major === 0 && this.minor === fver.minor || this.major === 0 && fver.major === 0 && this.minor === 0 && fver.minor === 0 && this.patch === fver.patch; } /** * Returns true if this version has precedence over (is newer than) another * version. * * Precedence is defined as in the Semver 2 spec. This implements the > * operator in npm's semver package, with the exception of the prerelease * exclusion rule. * * @param {Version} fver The other version to test against * @return {bool} True if this version has precedence over the other one. */ has_precedence_over(fver) { if (this.major > fver.major) { return true; } else if (this.major < fver.major) { return false; } if (this.minor > fver.minor) { return true; } else if (this.minor < fver.minor) { return false; } if (this.patch > fver.patch) { return true; } else if (this.patch < fver.patch) { return false; } if (this.pr_ident === undefined && fver.pr_ident !== undefined) { return true; } else if (this.pr_ident !== undefined && fver.pr_ident !== undefined) { let is_numeric = /^[0-9]*$/; for (let i = 0; i < this.pr_ident.length && i < fver.pr_ident.length; i += 1) { if (!is_numeric.test(this.pr_ident[i]) && is_numeric.test(fver.pr_ident[i])) { return true; } else if (is_numeric.test(this.pr_ident[i]) && is_numeric.test(fver.pr_ident[i])) { if (parseInt(this.pr_ident[i]) > parseInt(fver.pr_ident[i])) { return true; } else if (parseInt(this.pr_ident[i]) > parseInt(fver.pr_ident[i])) { return false; } } else if (!is_numeric.test(this.pr_ident[i]) && is_numeric.test(fver.pr_ident[i])) { return true; } else if (!is_numeric.test(this.pr_ident[i]) && !is_numeric.test(fver.pr_ident[i])) { if (this.pr_ident[i] > fver.pr_ident[i]) { return true; } else if (this.pr_ident[i] > fver.pr_ident[i]) { return false; } } } return this.pr_ident.length > fver.pr_ident.length; } return false; } /** * Tests if a given version is equivalent to this one. * * Build and prerelease tags are ignored. * * @param {Version} fver The other version to test against * @return {bool} True if the given version is equivalent. */ is_equal(fver) { return this.major === fver.major && this.minor === fver.minor && this.patch === fver.patch; } /** * Tests if a given version is stable or a compatible prerelease for this * version. * * This implements the prerelease exclusion rule of NPM semver: a * prerelease version can only pass this check if the major/minor/patch * components of both versions are the same. Otherwise, the prerelease * version always fails. * * @param {Version} fver The other version to test against * @return {bool} True if the given version is either stable, or a * prerelease in the same series as this one. */ is_stable_or_compatible_prerelease(fver) { if (fver.pr_ident === undefined) { return true; } else { return this.major === fver.major && this.minor === fver.minor && this.patch === fver.patch; } } }