Skip to content

Commit cfe6101

Browse files
committed
feat: removed-feature-key-and-segment-key-from-schema
1 parent fdf86bf commit cfe6101

File tree

12 files changed

+119
-100
lines changed

12 files changed

+119
-100
lines changed

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[submodule "tests/engine/engine-tests/engine-test-data"]
22
path = tests/engine/engine-tests/engine-test-data
33
url = [email protected]:Flagsmith/engine-test-data.git
4-
branch = v2.5.0
4+
branch = feat/remove-feature-key-fields

flagsmith-engine/evaluation/evaluationContext/evaluationContext.types.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,23 @@
66
*/
77

88
/**
9-
* An environment's unique identifier.
9+
* Unique environment key. May be used for selecting a value for a multivariate feature, or for % split segmentation.
1010
*/
1111
export type Key = string;
1212
/**
1313
* An environment's human-readable name.
1414
*/
1515
export type Name = string;
1616
/**
17-
* A unique identifier for an identity, used for segment and multivariate feature flag targeting, and displayed in the Flagsmith UI.
17+
* A unique identifier for an identity as displayed in the Flagsmith UI.
1818
*/
1919
export type Identifier = string;
2020
/**
2121
* Key used when selecting a value for a multivariate feature, or for % split segmentation. Set to an internal identifier or a composite value based on the environment key and identifier, depending on Flagsmith implementation.
2222
*/
2323
export type Key1 = string;
2424
/**
25-
* Key used for % split segmentation.
25+
* Unique segment key used for % split segmentation.
2626
*/
2727
export type Key2 = string;
2828
/**
@@ -85,13 +85,9 @@ export type SubRules = SegmentRule[];
8585
*/
8686
export type Rules = SegmentRule[];
8787
/**
88-
* Key used when selecting a value for a multivariate feature. Set to an internal identifier or a UUID, depending on Flagsmith implementation.
88+
* Unique feature key used when selecting a variant if the feature is multivariate. Set to an internal identifier or a UUID, depending on Flagsmith implementation.
8989
*/
9090
export type Key3 = string;
91-
/**
92-
* Unique feature identifier.
93-
*/
94-
export type FeatureKey = string;
9591
/**
9692
* Feature name.
9793
*/
@@ -155,7 +151,7 @@ export interface EnvironmentContext {
155151
*/
156152
export interface IdentityContext {
157153
identifier: Identifier;
158-
key: Key1;
154+
key?: Key1;
159155
traits?: Traits;
160156
[k: string]: unknown;
161157
}
@@ -214,7 +210,6 @@ export interface InSegmentCondition {
214210
*/
215211
export interface FeatureContext {
216212
key: Key3;
217-
feature_key: FeatureKey;
218213
name: Name2;
219214
enabled: Enabled;
220215
value: Value2;

flagsmith-engine/evaluation/evaluationContext/mappers.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,13 @@ function mapEnvironmentModelToEvaluationContext(
5353

5454
features[fs.feature.name] = {
5555
key: fs.djangoID?.toString() || fs.featurestateUUID,
56-
feature_key: fs.feature.id.toString(),
5756
name: fs.feature.name,
5857
enabled: fs.enabled,
5958
value: fs.getValue(),
6059
variants,
6160
priority: fs.featureSegment?.priority,
6261
metadata: {
63-
flagsmithId: fs.feature.id
62+
flagsmith_id: fs.feature.id
6463
}
6564
};
6665
}
@@ -75,11 +74,13 @@ function mapEnvironmentModelToEvaluationContext(
7574
segment.featureStates.length > 0
7675
? segment.featureStates.map(fs => ({
7776
key: fs.djangoID?.toString() || fs.featurestateUUID,
78-
feature_key: fs.feature.id.toString(),
7977
name: fs.feature.name,
8078
enabled: fs.enabled,
8179
value: fs.getValue(),
82-
priority: fs.featureSegment?.priority
80+
priority: fs.featureSegment?.priority,
81+
metadata: {
82+
flagsmith_id: fs.feature.id
83+
}
8384
}))
8485
: [],
8586
metadata: {
@@ -147,13 +148,12 @@ function mapIdentityOverridesToSegments(identityOverrides: IdentityModel[]): Seg
147148
a.feature.name.localeCompare(b.feature.name)
148149
);
149150
const overridesKey = sortedFeatures.map(fs => ({
150-
feature_key: fs.feature.id.toString(),
151151
name: fs.feature.name,
152152
enabled: fs.enabled,
153153
value: fs.getValue(),
154154
priority: -Infinity,
155155
metadata: {
156-
flagsmithId: fs.feature.id
156+
flagsmith_id: fs.feature.id
157157
}
158158
}));
159159

flagsmith-engine/evaluation/evaluationResult/evaluationResult.types.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55
* and run json-schema-to-typescript to regenerate this file.
66
*/
77

8-
/**
9-
* Unique feature identifier.
10-
*/
11-
export type FeatureKey = string;
128
/**
139
* Feature name.
1410
*/
@@ -25,10 +21,6 @@ export type Value = string | number | boolean | null;
2521
* Reason for the feature flag evaluation.
2622
*/
2723
export type Reason = string;
28-
/**
29-
* Unique segment identifier.
30-
*/
31-
export type Key = string;
3224
/**
3325
* Segment name.
3426
*/
@@ -53,7 +45,6 @@ export interface Flags {
5345
[k: string]: FlagResult;
5446
}
5547
export interface FlagResult {
56-
feature_key: FeatureKey;
5748
name: Name;
5849
enabled: Enabled;
5950
value: Value;
@@ -68,7 +59,6 @@ export interface FeatureMetadata {
6859
[k: string]: unknown;
6960
}
7061
export interface SegmentResult {
71-
key: Key;
7262
name: Name1;
7363
metadata?: SegmentMetadata;
7464
[k: string]: unknown;

flagsmith-engine/evaluation/models.ts

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,25 @@
55
import type {
66
EvaluationResult as EvaluationContextResult,
77
FlagResult,
8-
FeatureMetadata
8+
FeatureMetadata,
9+
SegmentMetadata
910
} from './evaluationResult/evaluationResult.types.js';
1011

1112
import type {
1213
FeatureContext,
1314
EnvironmentContext,
1415
IdentityContext,
15-
Segments
16+
Segments,
17+
SegmentContext
1618
} from './evaluationContext/evaluationContext.types.js';
1719

1820
export interface CustomFeatureMetadata extends FeatureMetadata {
19-
flagsmithId?: number;
21+
flagsmith_id: number;
22+
}
23+
24+
export interface CustomSegmentMetadata extends SegmentMetadata {
25+
flagsmith_id: number;
26+
source?: SegmentSource;
2027
}
2128

2229
export interface FeatureContextWithMetadata<T extends FeatureMetadata = FeatureMetadata>
@@ -29,10 +36,23 @@ export type FeaturesWithMetadata<T extends FeatureMetadata = FeatureMetadata> =
2936
[k: string]: FeatureContextWithMetadata<T>;
3037
};
3138

32-
export interface GenericEvaluationContext<T extends FeatureMetadata = FeatureMetadata> {
39+
export interface SegmentContextWithMetadata<T extends SegmentMetadata = SegmentMetadata>
40+
extends SegmentContext {
41+
metadata: T;
42+
overrides?: FeatureContextWithMetadata<FeatureMetadata>[];
43+
}
44+
45+
export type SegmentsWithMetadata<T extends SegmentMetadata = SegmentMetadata> = {
46+
[k: string]: SegmentContextWithMetadata<T>;
47+
};
48+
49+
export interface GenericEvaluationContext<
50+
T extends FeatureMetadata = FeatureMetadata,
51+
S extends SegmentMetadata = SegmentMetadata
52+
> {
3353
environment: EnvironmentContext;
3454
identity?: IdentityContext | null;
35-
segments?: Segments;
55+
segments?: SegmentsWithMetadata<S>;
3656
features?: FeaturesWithMetadata<T>;
3757
[k: string]: unknown;
3858
}
@@ -54,7 +74,15 @@ export type EvaluationResult<T extends FeatureMetadata = FeatureMetadata> = {
5474
};
5575

5676
export type EvaluationResultWithMetadata = EvaluationResult<CustomFeatureMetadata>;
57-
export type EvaluationContextWithMetadata = GenericEvaluationContext<CustomFeatureMetadata>;
77+
export type EvaluationContextWithMetadata = GenericEvaluationContext<
78+
CustomFeatureMetadata,
79+
CustomSegmentMetadata
80+
>;
81+
82+
export interface SegmentResultWithMetadata {
83+
name: string;
84+
metadata: CustomSegmentMetadata;
85+
}
5886

5987
export enum SegmentSource {
6088
API = 'api',

flagsmith-engine/index.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ export function evaluateSegments(context: EvaluationContextWithMetadata): {
6262
const identitySegments = getIdentitySegments(context);
6363

6464
const segments = identitySegments.map(segment => ({
65-
key: segment.key,
6665
name: segment.name,
6766
...(segment.metadata
6867
? {
@@ -96,7 +95,7 @@ export function processSegmentOverrides(identitySegments: any[]): Record<string,
9695

9796
for (const override of overridesList) {
9897
if (shouldApplyOverride(override, segmentOverrides)) {
99-
segmentOverrides[override.feature_key] = {
98+
segmentOverrides[override.name] = {
10099
feature: override,
101100
segmentName: segment.name
102101
};
@@ -126,7 +125,7 @@ export function evaluateFeatures(
126125
const flags: EvaluationResultFlags<CustomFeatureMetadata> = {};
127126

128127
for (const feature of Object.values(context.features || {})) {
129-
const segmentOverride = segmentOverrides[feature.feature_key];
128+
const segmentOverride = segmentOverrides[feature.name];
130129
const finalFeature = segmentOverride ? segmentOverride.feature : feature;
131130
const hasOverride = !!segmentOverride;
132131

@@ -135,7 +134,6 @@ export function evaluateFeatures(
135134
: evaluateFeatureValue(finalFeature, context.identity?.key);
136135

137136
flags[finalFeature.name] = {
138-
feature_key: finalFeature.feature_key,
139137
name: finalFeature.name,
140138
enabled: finalFeature.enabled,
141139
value: evaluatedValue,
@@ -198,7 +196,7 @@ export function shouldApplyOverride(
198196
override: any,
199197
existingOverrides: Record<string, SegmentOverride>
200198
): boolean {
201-
const currentOverride = existingOverrides[override.feature_key];
199+
const currentOverride = existingOverrides[override.name];
202200
return (
203201
!currentOverride || isHigherPriority(override.priority, currentOverride.feature.priority)
204202
);

flagsmith-engine/segments/models.ts

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,13 @@ export class SegmentModel {
224224
if (segmentResult.metadata?.source === SegmentSource.IDENTITY_OVERRIDE) {
225225
continue;
226226
}
227-
const segmentContext = evaluationContext.segments[segmentResult.key];
227+
const flagsmithId = segmentResult.metadata?.flagsmith_id;
228+
if (!flagsmithId) {
229+
continue;
230+
}
231+
const segmentContext = evaluationContext.segments[flagsmithId.toString()];
228232
if (segmentContext) {
229-
const segment = new SegmentModel(parseInt(segmentContext.key), segmentContext.name);
233+
const segment = new SegmentModel(flagsmithId, segmentContext.name);
230234
segment.rules = segmentContext.rules.map(rule => new SegmentRuleModel(rule.type));
231235
segment.featureStates = SegmentModel.createFeatureStatesFromOverrides(
232236
segmentContext.overrides || []
@@ -240,33 +244,39 @@ export class SegmentModel {
240244

241245
private static createFeatureStatesFromOverrides(overrides: Overrides): FeatureStateModel[] {
242246
if (!overrides) return [];
243-
return overrides.map(override => {
244-
const feature = new FeatureModel(
245-
parseInt(override.feature_key),
246-
override.name,
247-
override.variants?.length && override.variants.length > 0
248-
? CONSTANTS.MULTIVARIATE
249-
: CONSTANTS.STANDARD
250-
);
251-
252-
const featureState = new FeatureStateModel(
253-
feature,
254-
override.enabled,
255-
override.priority || 0
256-
);
257-
258-
if (override.value !== undefined) {
259-
featureState.setValue(override.value);
260-
}
247+
return overrides
248+
.filter(override => {
249+
const flagsmithId = override?.metadata?.flagsmith_id;
250+
return typeof flagsmithId === 'number';
251+
})
252+
.map(override => {
253+
const flagsmithId = override.metadata!.flagsmith_id as number;
254+
const feature = new FeatureModel(
255+
flagsmithId,
256+
override.name,
257+
override.variants?.length && override.variants.length > 0
258+
? CONSTANTS.MULTIVARIATE
259+
: CONSTANTS.STANDARD
260+
);
261261

262-
if (override.variants && override.variants.length > 0) {
263-
featureState.multivariateFeatureStateValues = this.createMultivariateValues(
264-
override.variants
262+
const featureState = new FeatureStateModel(
263+
feature,
264+
override.enabled,
265+
override.priority || 0
265266
);
266-
}
267267

268-
return featureState;
269-
});
268+
if (override.value !== undefined) {
269+
featureState.setValue(override.value);
270+
}
271+
272+
if (override.variants && override.variants.length > 0) {
273+
featureState.multivariateFeatureStateValues = this.createMultivariateValues(
274+
override.variants
275+
);
276+
}
277+
278+
return featureState;
279+
});
270280
}
271281

272282
private static createMultivariateValues(variants: any[]): MultivariateFeatureStateValueModel[] {

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@
5858
"deploy": "npm i && npm run build && npm publish",
5959
"deploy:beta": "npm i && npm run build && npm publish --tag beta",
6060
"prepare": "husky install",
61-
"generate-evaluation-result-types": "curl -o evaluation-result.json https://raw.githubusercontent.com/Flagsmith/flagsmith/main/sdk/evaluation-result.json && npx json2ts -i evaluation-result.json -o flagsmith-engine/evaluation/evaluationResult/evaluationResult.types.ts && rm evaluation-result.json",
62-
"generate-evaluation-context-types": "curl -o evaluation-context.json https://raw.githubusercontent.com/Flagsmith/flagsmith/main/sdk/evaluation-context.json && npx json2ts -i evaluation-context.json -o flagsmith-engine/evaluation/evaluationContext/evaluationContext.types.ts && rm evaluation-context.json",
61+
"generate-evaluation-result-types": "curl -o evaluation-result.json https://raw.githubusercontent.com/Flagsmith/flagsmith/chore%2Fevaluation-context0key/sdk/evaluation-result.json && npx json2ts -i evaluation-result.json -o flagsmith-engine/evaluation/evaluationResult/evaluationResult.types.ts && rm evaluation-result.json",
62+
"generate-evaluation-context-types": "curl -o evaluation-context.json https://raw.githubusercontent.com/Flagsmith/flagsmith/chore%2Fevaluation-context0key/sdk/evaluation-context.json && npx json2ts -i evaluation-context.json -o flagsmith-engine/evaluation/evaluationContext/evaluationContext.types.ts && rm evaluation-context.json",
6363
"generate-engine-types": "npm run generate-evaluation-result-types && npm run generate-evaluation-context-types"
6464
},
6565
"dependencies": {

sdk/models.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,15 @@ export class Flags {
118118
): Flags {
119119
const flags: { [key: string]: Flag } = {};
120120
for (const flag of Object.values(evaluationResult.flags)) {
121-
const flagsmithId = flag.metadata?.flagsmithId;
122-
if (!flagsmithId) {
121+
const flagsmith_id = flag.metadata?.flagsmith_id;
122+
if (!flagsmith_id) {
123123
continue;
124124
}
125125

126126
flags[flag.name] = new Flag({
127127
enabled: flag.enabled,
128128
value: flag.value ?? null,
129-
featureId: flagsmithId,
129+
featureId: flagsmith_id,
130130
featureName: flag.name,
131131
reason: flag.reason
132132
});
Submodule engine-test-data updated 152 files

0 commit comments

Comments
 (0)