UNPKG

@featurevisor/sdk

Version:

Featurevisor SDK for Node.js and the browser

128 lines (110 loc) 4.15 kB
import { compareVersions } from "compare-versions"; import { Context, Condition, PlainCondition } from "@featurevisor/types"; import { Logger } from "./logger"; export function conditionIsMatched(condition: PlainCondition, context: Context): boolean { const { attribute, operator, value } = condition; if (operator === "equals") { return context[attribute] === value; } else if (operator === "notEquals") { return context[attribute] !== value; } else if (operator === "before" || operator === "after") { // date comparisons const valueInContext = context[attribute] as string | Date; const dateInContext = valueInContext instanceof Date ? valueInContext : new Date(valueInContext); const dateInCondition = value instanceof Date ? value : new Date(value as string); return operator === "before" ? dateInContext < dateInCondition : dateInContext > dateInCondition; } else if ( Array.isArray(value) && (["string", "number"].indexOf(typeof context[attribute]) !== -1 || context[attribute] === null) ) { // array const valueInContext = context[attribute] as string; if (operator === "in") { return value.indexOf(valueInContext) !== -1; } else if (operator === "notIn") { return value.indexOf(valueInContext) === -1; } } else if (typeof context[attribute] === "string" && typeof value === "string") { // string const valueInContext = context[attribute] as string; if (operator === "contains") { return valueInContext.indexOf(value) !== -1; } else if (operator === "notContains") { return valueInContext.indexOf(value) === -1; } else if (operator === "startsWith") { return valueInContext.startsWith(value); } else if (operator === "endsWith") { return valueInContext.endsWith(value); } else if (operator === "semverEquals") { return compareVersions(valueInContext, value) === 0; } else if (operator === "semverNotEquals") { return compareVersions(valueInContext, value) !== 0; } else if (operator === "semverGreaterThan") { return compareVersions(valueInContext, value) === 1; } else if (operator === "semverGreaterThanOrEquals") { return compareVersions(valueInContext, value) >= 0; } else if (operator === "semverLessThan") { return compareVersions(valueInContext, value) === -1; } else if (operator === "semverLessThanOrEquals") { return compareVersions(valueInContext, value) <= 0; } } else if (typeof context[attribute] === "number" && typeof value === "number") { // numeric const valueInContext = context[attribute] as number; if (operator === "greaterThan") { return valueInContext > value; } else if (operator === "greaterThanOrEquals") { return valueInContext >= value; } else if (operator === "lessThan") { return valueInContext < value; } else if (operator === "lessThanOrEquals") { return valueInContext <= value; } } return false; } export function allConditionsAreMatched( conditions: Condition[] | Condition, context: Context, logger: Logger, ): boolean { if ("attribute" in conditions) { try { return conditionIsMatched(conditions, context); } catch (e) { logger.warn(e.message, { error: e, details: { condition: conditions, context, }, }); return false; } } if ("and" in conditions && Array.isArray(conditions.and)) { return conditions.and.every((c) => allConditionsAreMatched(c, context, logger)); } if ("or" in conditions && Array.isArray(conditions.or)) { return conditions.or.some((c) => allConditionsAreMatched(c, context, logger)); } if ("not" in conditions && Array.isArray(conditions.not)) { return conditions.not.every( () => allConditionsAreMatched( { and: conditions.not, }, context, logger, ) === false, ); } if (Array.isArray(conditions)) { return conditions.every((c) => allConditionsAreMatched(c, context, logger)); } return false; }