Farmbot-Web-App/frontend/util/version.ts

166 lines
5.0 KiB
TypeScript
Raw Normal View History

2018-03-08 18:02:50 -07:00
import { isString, isUndefined } from "lodash";
import { BotState, Feature, MinOsFeatureLookup } from "../devices/interfaces";
2018-08-01 07:33:39 -06:00
import { TaggedDevice } from "farmbot";
2018-12-30 11:05:45 -07:00
import { DevSettings } from "../account/dev/dev_support";
/**
2018-03-08 18:02:50 -07:00
* for semverCompare()
*/
export enum SemverResult {
LEFT_IS_GREATER = 1,
RIGHT_IS_GREATER = -1,
EQUAL = 0
}
2018-03-08 18:02:50 -07:00
/**
* Determine which version string is greater.
* Supports major, minor, and patch number comparison
* and checks the presence of pre-release identifiers.
*
* CREDIT: https://github.com/substack/semver-compare
*
* @param left semver string, ex: "0.0.0-rc0"
* @param right semver string, ex: "0.0.0-rc0"
*/
export function semverCompare(left: string, right: string): SemverResult {
const leftSemVer = left.split("-")[0];
const rightSemVer = right.split("-")[0];
const leftHasSuffix = left.includes("-");
const rightHasSuffix = right.includes("-");
const pa: Array<string | undefined> = leftSemVer.split(".");
const pb: Array<string | undefined> = rightSemVer.split(".");
for (let i = 0; i < 3; i++) {
const num_left = Number(pa[i]);
const num_right = Number(pb[i]);
if (num_left > num_right) {
return SemverResult.LEFT_IS_GREATER;
}
if (num_right > num_left) {
return SemverResult.RIGHT_IS_GREATER;
}
if (!isNaN(num_left) && isNaN(num_right)) {
return SemverResult.LEFT_IS_GREATER;
}
if (isNaN(num_left) && !isNaN(num_right)) {
return SemverResult.RIGHT_IS_GREATER;
}
}
// num_left === num_right. Check presence of pre-release identifiers.
if (!leftHasSuffix && rightHasSuffix) {
return SemverResult.LEFT_IS_GREATER;
}
if (leftHasSuffix && !rightHasSuffix) {
return SemverResult.RIGHT_IS_GREATER;
}
return SemverResult.EQUAL;
}
/**
2018-03-08 18:02:50 -07:00
* Conditionally display firmware settings based on
* the user's current Arduino firmware version.
2018-03-08 18:02:50 -07:00
*
* @param current installed firmware version string ("0.0.0")
* @param min minimum firmware version string required ("0.0.0")
*/
export function minFwVersionCheck(current: string | undefined, min: string) {
if (isString(current)) {
switch (semverCompare(current.slice(0, -1), min)) {
case SemverResult.LEFT_IS_GREATER:
case SemverResult.EQUAL:
return true;
default:
return false;
}
} else {
return false;
}
}
/**
2018-03-08 18:02:50 -07:00
* for shouldDisplay()
*/
export enum MinVersionOverride {
ALWAYS = "0.0.0",
NEVER = "999.999.999",
}
2018-03-08 18:02:50 -07:00
/**
* Determine whether a feature should be displayed based on
* the user's current FBOS version. Min FBOS version feature data is pulled
* from an external source to allow App and FBOS development flexibility.
*
* @param current installed OS version string to compare against data ("0.0.0")
* @param lookupData min req versions data, for example {"feature": "1.0.0"}
*/
export function shouldDisplay(
2018-03-08 18:02:50 -07:00
current: string | undefined, lookupData: MinOsFeatureLookup | undefined) {
return function (feature: Feature): boolean {
2018-12-30 11:05:45 -07:00
const override = DevSettings.overriddenFbosVersion();
2018-03-14 12:19:52 -06:00
const target = override || current;
if (isString(target)) {
2018-03-08 18:02:50 -07:00
const min = (lookupData || {})[feature] || MinVersionOverride.NEVER;
2018-03-14 12:19:52 -06:00
switch (semverCompare(target, min)) {
2018-03-07 20:42:34 -07:00
case SemverResult.LEFT_IS_GREATER:
case SemverResult.EQUAL:
return true;
default:
return false;
}
}
2018-03-07 20:42:34 -07:00
return false;
};
}
/**
2018-03-08 18:02:50 -07:00
* Compare the current FBOS version in the bot's
2018-03-19 09:25:42 -06:00
* state with the API's fbos_version string and return the greatest version. */
2018-03-07 20:42:34 -07:00
export function determineInstalledOsVersion(
bot: BotState, device: TaggedDevice | undefined): string | undefined {
const fromBotState = bot.hardware.informational_settings.controller_version;
const fromAPI = device ? device.body.fbos_version : undefined;
if (isUndefined(fromBotState) && isUndefined(fromAPI)) { return undefined; }
switch (semverCompare(fromBotState || "", fromAPI || "")) {
case SemverResult.LEFT_IS_GREATER:
case SemverResult.EQUAL:
return fromBotState === "" ? undefined : fromBotState;
case SemverResult.RIGHT_IS_GREATER:
return fromAPI === "" ? undefined : fromAPI;
default:
return undefined;
}
}
/**
* Compare installed FBOS version against the lowest version compatible
* with the web app to lock out incompatible FBOS versions from the App.
* It uses a different method than semverCompare() to only look at
* major and minor numeric versions and ignores patch and pre-release
* identifiers.
2018-03-08 18:02:50 -07:00
*
* @param stringyVersion version string to check ("0.0.0")
* @param _EXPECTED_MAJOR minimum required major version number
* @param _EXPECTED_MINOR minimum required minor version number
2018-03-07 20:42:34 -07:00
*/
export function versionOK(stringyVersion = "0.0.0",
_EXPECTED_MAJOR: number,
_EXPECTED_MINOR: number) {
const [actual_major, actual_minor] = stringyVersion
.split(".")
.map(x => parseInt(x, 10));
if (actual_major > _EXPECTED_MAJOR) {
return true;
} else {
const majorOK = (actual_major == _EXPECTED_MAJOR);
const minorOK = (actual_minor >= _EXPECTED_MINOR);
return (majorOK && minorOK);
}
}