flagsmith-nodejs
Version:
Flagsmith lets you manage features flags and remote config across web, mobile and server side applications. Deliver true Continuous Integration. Get builds out faster. Control who has access to new features.
112 lines (111 loc) • 5.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SegmentModel = exports.SegmentRuleModel = exports.SegmentConditionModel = exports.getMatchingFunctions = exports.semverMatchingFunction = exports.matchingFunctions = exports.any = exports.all = void 0;
const semver = require("semver");
const index_js_1 = require("../utils/index.js");
const constants_js_1 = require("./constants.js");
const util_js_1 = require("./util.js");
const all = (iterable) => iterable.filter(e => !!e).length === iterable.length;
exports.all = all;
const any = (iterable) => iterable.filter(e => !!e).length > 0;
exports.any = any;
exports.matchingFunctions = {
[constants_js_1.CONDITION_OPERATORS.EQUAL]: (thisValue, otherValue) => thisValue == otherValue,
[constants_js_1.CONDITION_OPERATORS.GREATER_THAN]: (thisValue, otherValue) => otherValue > thisValue,
[constants_js_1.CONDITION_OPERATORS.GREATER_THAN_INCLUSIVE]: (thisValue, otherValue) => otherValue >= thisValue,
[constants_js_1.CONDITION_OPERATORS.LESS_THAN]: (thisValue, otherValue) => thisValue > otherValue,
[constants_js_1.CONDITION_OPERATORS.LESS_THAN_INCLUSIVE]: (thisValue, otherValue) => thisValue >= otherValue,
[constants_js_1.CONDITION_OPERATORS.NOT_EQUAL]: (thisValue, otherValue) => thisValue != otherValue,
[constants_js_1.CONDITION_OPERATORS.CONTAINS]: (thisValue, otherValue) => !!otherValue && otherValue.includes(thisValue)
};
exports.semverMatchingFunction = {
...exports.matchingFunctions,
[constants_js_1.CONDITION_OPERATORS.EQUAL]: (thisValue, otherValue) => semver.eq(thisValue, otherValue),
[constants_js_1.CONDITION_OPERATORS.GREATER_THAN]: (thisValue, otherValue) => semver.gt(otherValue, thisValue),
[constants_js_1.CONDITION_OPERATORS.GREATER_THAN_INCLUSIVE]: (thisValue, otherValue) => semver.gte(otherValue, thisValue),
[constants_js_1.CONDITION_OPERATORS.LESS_THAN]: (thisValue, otherValue) => semver.gt(thisValue, otherValue),
[constants_js_1.CONDITION_OPERATORS.LESS_THAN_INCLUSIVE]: (thisValue, otherValue) => semver.gte(thisValue, otherValue)
};
const getMatchingFunctions = (semver) => semver ? exports.semverMatchingFunction : exports.matchingFunctions;
exports.getMatchingFunctions = getMatchingFunctions;
class SegmentConditionModel {
EXCEPTION_OPERATOR_METHODS = {
[constants_js_1.NOT_CONTAINS]: 'evaluateNotContains',
[constants_js_1.REGEX]: 'evaluateRegex',
[constants_js_1.MODULO]: 'evaluateModulo',
[constants_js_1.IN]: 'evaluateIn'
};
operator;
value;
property_;
constructor(operator, value, property) {
this.operator = operator;
this.value = value;
this.property_ = property;
}
matchesTraitValue(traitValue) {
const evaluators = {
evaluateNotContains: (traitValue) => {
return (typeof traitValue == 'string' &&
!!this.value &&
!traitValue.includes(this.value?.toString()));
},
evaluateRegex: (traitValue) => {
return !!this.value && !!traitValue?.toString().match(new RegExp(this.value));
},
evaluateModulo: (traitValue) => {
if (isNaN(parseFloat(traitValue)) || !this.value) {
return false;
}
const parts = this.value.split('|');
const [divisor, reminder] = [parseFloat(parts[0]), parseFloat(parts[1])];
return traitValue % divisor === reminder;
},
evaluateIn: (traitValue) => {
return this.value?.split(',').includes(traitValue.toString());
}
};
// TODO: move this logic to the evaluator module
if (this.EXCEPTION_OPERATOR_METHODS[this.operator]) {
const evaluatorFunction = evaluators[this.EXCEPTION_OPERATOR_METHODS[this.operator]];
return evaluatorFunction(traitValue);
}
const defaultFunction = (x, y) => false;
const matchingFunctionSet = (0, exports.getMatchingFunctions)((0, util_js_1.isSemver)(this.value));
const matchingFunction = matchingFunctionSet[this.operator] || defaultFunction;
const traitType = (0, util_js_1.isSemver)(this.value) ? 'semver' : typeof traitValue;
const castToTypeOfTraitValue = (0, index_js_1.getCastingFunction)(traitType);
return matchingFunction(castToTypeOfTraitValue(this.value), traitValue);
}
}
exports.SegmentConditionModel = SegmentConditionModel;
class SegmentRuleModel {
type;
rules = [];
conditions = [];
constructor(type) {
this.type = type;
}
static none(iterable) {
return iterable.filter(e => !!e).length === 0;
}
matchingFunction() {
return {
[constants_js_1.ANY_RULE]: exports.any,
[constants_js_1.ALL_RULE]: exports.all,
[constants_js_1.NONE_RULE]: SegmentRuleModel.none
}[this.type];
}
}
exports.SegmentRuleModel = SegmentRuleModel;
class SegmentModel {
id;
name;
rules = [];
featureStates = [];
constructor(id, name) {
this.id = id;
this.name = name;
}
}
exports.SegmentModel = SegmentModel;