@launchdarkly/js-server-sdk-common
Version:
LaunchDarkly Server SDK for JavaScript - common code
104 lines • 4.37 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
const semver_1 = require("semver");
const js_sdk_common_1 = require("@launchdarkly/js-sdk-common");
const VERSION_COMPONENTS_REGEX = /^\d+(\.\d+)?(\.\d+)?/;
function parseSemver(input) {
// A leading 'v' is not supported by the standard, but may be by the semver library.
if (js_sdk_common_1.TypeValidators.String.is(input) && !input.startsWith('v')) {
// If the input is able to be parsed, then return that.
const parsed = (0, semver_1.parse)(input);
if (parsed) {
return parsed;
}
// If not, then we are going to make some exceptions to the format.
// Specifically semver requires 3 components, but we allow versions with
// less. For instance we allow '1' to be equivalent to '1.0.0'.
const components = VERSION_COMPONENTS_REGEX.exec(input);
if (components) {
let transformed = components[0];
// Start after the match.
for (let i = 1; i < components.length; i += 1) {
// The regex will return a match followed by each group.
// Unmatched groups are 'undefined'.
// So we will always have 3 entries, the match and 2 groups.
// For each missing group we need to append a '.0' until we have the
// standard 3.
if (components[i] === undefined) {
transformed += '.0';
}
}
// If the original version contains pre-release information like '-beta.1',
// then this will re-incorporate that into the string.
transformed += input.substring(components[0].length);
return (0, semver_1.parse)(transformed);
}
}
return null;
}
function semVerOperator(fn) {
return (a, b) => {
const aVer = parseSemver(a);
const bVer = parseSemver(b);
return !!(aVer && bVer && fn(aVer, bVer));
};
}
function makeOperator(fn, validator, converter) {
return (a, b) => {
if (validator.is(a) && validator.is(b)) {
if (converter) {
return fn(converter(a), converter(b));
}
return fn(a, b);
}
return false;
};
}
function parseDate(input) {
// Before calling this function we know the value is a date in a number
// or as a string.
if (typeof input === 'number') {
return input;
}
return Date.parse(input);
}
function safeRegexMatch(pattern, value) {
try {
return new RegExp(pattern).test(value);
}
catch (_a) {
return false;
}
}
const operators = {
in: (a, b) => a === b,
endsWith: makeOperator((a, b) => a.endsWith(b), js_sdk_common_1.TypeValidators.String),
startsWith: makeOperator((a, b) => a.startsWith(b), js_sdk_common_1.TypeValidators.String),
matches: makeOperator((value, pattern) => safeRegexMatch(pattern, value), js_sdk_common_1.TypeValidators.String),
contains: makeOperator((a, b) => a.indexOf(b) > -1, js_sdk_common_1.TypeValidators.String),
lessThan: makeOperator((a, b) => a < b, js_sdk_common_1.TypeValidators.Number),
lessThanOrEqual: makeOperator((a, b) => a <= b, js_sdk_common_1.TypeValidators.Number),
greaterThan: makeOperator((a, b) => a > b, js_sdk_common_1.TypeValidators.Number),
greaterThanOrEqual: makeOperator((a, b) => a >= b, js_sdk_common_1.TypeValidators.Number),
before: makeOperator((a, b) => a < b, js_sdk_common_1.TypeValidators.Date, parseDate),
after: makeOperator((a, b) => a > b, js_sdk_common_1.TypeValidators.Date, parseDate),
semVerEqual: semVerOperator((a, b) => a.compare(b) === 0),
semVerLessThan: semVerOperator((a, b) => a.compare(b) < 0),
semVerGreaterThan: semVerOperator((a, b) => a.compare(b) > 0),
};
/**
* Allows checking if a specific operator is defined and allows execution of an operator on data.
*
* @internal
*/
class Operators {
static is(op) {
return Object.prototype.hasOwnProperty.call(operators, op);
}
static execute(op, a, b) {
var _a, _b;
return (_b = (_a = operators[op]) === null || _a === void 0 ? void 0 : _a.call(operators, a, b)) !== null && _b !== void 0 ? _b : false;
}
}
exports.default = Operators;
//# sourceMappingURL=Operations.js.map
;