Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "tests/engine/engine-tests/engine-test-data"]
path = tests/engine/engine-tests/engine-test-data
url = git@github.com:Flagsmith/engine-test-data.git
branch = v3.4.1
branch = v3.5.0
31 changes: 27 additions & 4 deletions flagsmith-engine/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import {
EvaluationResultWithMetadata,
FeatureContextWithMetadata,
SDKFeatureMetadata,
FlagResultWithMetadata
FlagResultWithMetadata,
GenericEvaluationContext
} from './evaluation/models.js';
import { getIdentitySegments, getIdentityKey } from './segments/evaluators.js';
import { getIdentitySegments } from './segments/evaluators.js';
import { EvaluationResultFlags } from './evaluation/models.js';
import { TARGETING_REASONS } from './features/types.js';
import { getHashedPercentageForObjIds } from './utils/hashing/index.js';
Expand Down Expand Up @@ -37,12 +38,29 @@ export type SegmentOverrides = Record<string, SegmentOverride>;
export function getEvaluationResult(
context: EvaluationContextWithMetadata
): EvaluationResultWithMetadata {
const { segments, segmentOverrides } = evaluateSegments(context);
const flags = evaluateFeatures(context, segmentOverrides);
const enrichedContext = getEnrichedContext(context);
const { segments, segmentOverrides } = evaluateSegments(enrichedContext);
const flags = evaluateFeatures(enrichedContext, segmentOverrides);

return { flags, segments };
}

function getEnrichedContext(context: EvaluationContextWithMetadata): EvaluationContextWithMetadata {
const identityKey = getIdentityKey(context);
if (!identityKey) return context;

return {
...context,
...(context.identity && {
identity: {
identifier: context.identity.identifier,
key: identityKey,
traits: context.identity.traits || {}
}
})
};
}

/**
* Evaluates which segments the identity belongs to and collects feature overrides.
*
Expand Down Expand Up @@ -234,3 +252,8 @@ const getTargetingMatchReason = (matchObject: TargetingMatchReason) => {

return TARGETING_REASONS.DEFAULT;
};

const getIdentityKey = (context: GenericEvaluationContext): string | undefined => {
if (!context.identity) return undefined;
return context.identity.key || `${context.environment.key}_${context.identity?.identifier}`;
};
21 changes: 12 additions & 9 deletions flagsmith-engine/segments/evaluators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,18 @@ export function traitsMatchSegmentCondition(
context?: GenericEvaluationContext
): boolean {
if (condition.operator === PERCENTAGE_SPLIT) {
const contextValueKey =
getContextValue(condition.property, context) || getIdentityKey(context);
const hashedPercentage = getHashedPercentageForObjIds([segmentKey, contextValueKey]);
let splitKey: string | undefined;

if (!condition.property) {
splitKey = context?.identity?.key;
} else {
splitKey = getContextValue(condition.property, context);
}

if (!splitKey) {
return false;
}
const hashedPercentage = getHashedPercentageForObjIds([segmentKey, splitKey]);
return hashedPercentage <= parseFloat(String(condition.value));
}
if (!condition.property) {
Expand Down Expand Up @@ -175,12 +184,6 @@ export function getContextValue(jsonPath: string, context?: GenericEvaluationCon
}
}

export function getIdentityKey(context?: GenericEvaluationContext): string | undefined {
if (!context?.identity) return undefined;

return context.identity.key || `${context.environment.key}_${context.identity.identifier}`;
}

function normalizeJsonPath(jsonPath: string): string {
return jsonPath.replace(/\.([^.\[\]]+)$/, "['$1']");
}
12 changes: 2 additions & 10 deletions tests/engine/unit/segments/segment_evaluators.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import {
ALL_RULE,
CONDITION_OPERATORS,
PERCENTAGE_SPLIT
} from '../../../../flagsmith-engine/segments/constants.js';
import { ALL_RULE, CONDITION_OPERATORS } from '../../../../flagsmith-engine/segments/constants.js';

import {
traitsMatchSegmentCondition,
getContextValue,
getIdentitySegments
} from '../../../../flagsmith-engine/segments/evaluators.js';
import { TraitModel, IdentityModel } from '../../../../flagsmith-engine/index.js';
import { environment } from '../utils.js';
import { buildSegmentModel } from '../../../../flagsmith-engine/segments/util.js';
import { TraitModel } from '../../../../flagsmith-engine/index.js';
import { getHashedPercentageForObjIds } from '../../../../flagsmith-engine/utils/hashing/index.js';
import { getEvaluationContext } from '../../../../flagsmith-engine/evaluation/evaluationContext/mappers.js';
import {
EvaluationContext,
InSegmentCondition,
Expand Down Expand Up @@ -431,7 +424,6 @@ describe('percentage split operator', () => {
const mockHashFn = getHashedPercentageForObjIds;
mockHashFn.mockReturnValue(hashedValue);
const condition = {
property: 'any',
operator: 'PERCENTAGE_SPLIT',
value: threshold.toString()
} as SegmentCondition1 | InSegmentCondition;
Expand Down