@featurevisor/sdk 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/index.js +1 -1
- package/dist/index.js.gz +0 -0
- package/dist/index.js.map +1 -1
- package/lib/client.d.ts +4 -1
- package/lib/client.js +28 -0
- package/lib/client.js.map +1 -1
- package/lib/createInstance.d.ts +3 -1
- package/lib/createInstance.js +3 -0
- package/lib/createInstance.js.map +1 -1
- package/lib/feature.d.ts +9 -2
- package/lib/feature.js +43 -31
- package/lib/feature.js.map +1 -1
- package/package.json +3 -3
- package/src/client.ts +41 -0
- package/src/createInstance.spec.ts +76 -6
- package/src/createInstance.ts +7 -2
- package/src/feature.ts +61 -41
package/src/feature.ts
CHANGED
|
@@ -13,24 +13,56 @@ import { allConditionsAreMatched } from "./conditions";
|
|
|
13
13
|
import { VariableSchema } from "@featurevisor/types/src";
|
|
14
14
|
import { Logger } from "./logger";
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Traffic
|
|
18
|
+
*/
|
|
19
|
+
export function getMatchedAllocation(
|
|
20
|
+
traffic: Traffic,
|
|
21
|
+
bucketValue: number,
|
|
22
|
+
): Allocation | undefined {
|
|
23
|
+
let total = 0; // @TODO: remove it in next breaking semver
|
|
24
|
+
const usePercentage =
|
|
25
|
+
traffic.allocation.length > 0 && typeof traffic.allocation[0].range === "undefined"; // @TODO: remove it in next breaking semver
|
|
26
|
+
|
|
27
|
+
for (const allocation of traffic.allocation) {
|
|
28
|
+
if (
|
|
29
|
+
allocation.range &&
|
|
30
|
+
allocation.range.start <= bucketValue &&
|
|
31
|
+
allocation.range.end >= bucketValue
|
|
32
|
+
) {
|
|
33
|
+
return allocation;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// @TODO: remove it in next breaking semver
|
|
37
|
+
if (usePercentage) {
|
|
38
|
+
total += allocation.percentage || 0;
|
|
39
|
+
if (bucketValue <= total) {
|
|
40
|
+
return allocation;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface MatchedTrafficAndAllocation {
|
|
49
|
+
matchedTraffic: Traffic | undefined;
|
|
50
|
+
matchedAllocation: Allocation | undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function getMatchedTrafficAndAllocation(
|
|
17
54
|
traffic: Traffic[],
|
|
18
55
|
attributes: Attributes,
|
|
19
56
|
bucketValue: number,
|
|
20
57
|
datafileReader: DatafileReader,
|
|
21
58
|
logger: Logger,
|
|
22
|
-
):
|
|
23
|
-
|
|
24
|
-
if (bucketValue > traffic.percentage) {
|
|
25
|
-
// out of bucket range
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
59
|
+
): MatchedTrafficAndAllocation {
|
|
60
|
+
let matchedAllocation: Allocation | undefined;
|
|
28
61
|
|
|
62
|
+
const matchedTraffic = traffic.find((t) => {
|
|
29
63
|
if (
|
|
30
64
|
!allGroupSegmentsAreMatched(
|
|
31
|
-
typeof
|
|
32
|
-
? JSON.parse(traffic.segments)
|
|
33
|
-
: traffic.segments,
|
|
65
|
+
typeof t.segments === "string" && t.segments !== "*" ? JSON.parse(t.segments) : t.segments,
|
|
34
66
|
attributes,
|
|
35
67
|
datafileReader,
|
|
36
68
|
)
|
|
@@ -38,32 +70,24 @@ export function getMatchedTraffic(
|
|
|
38
70
|
return false;
|
|
39
71
|
}
|
|
40
72
|
|
|
41
|
-
|
|
42
|
-
ruleKey: traffic.key,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
return true;
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// @TODO: make this function better with tests
|
|
50
|
-
export function getMatchedAllocation(
|
|
51
|
-
matchedTraffic: Traffic,
|
|
52
|
-
bucketValue: number,
|
|
53
|
-
): Allocation | undefined {
|
|
54
|
-
let total = 0;
|
|
55
|
-
|
|
56
|
-
for (const allocation of matchedTraffic.allocation) {
|
|
57
|
-
total += allocation.percentage;
|
|
73
|
+
matchedAllocation = getMatchedAllocation(t, bucketValue);
|
|
58
74
|
|
|
59
|
-
if (
|
|
60
|
-
return
|
|
75
|
+
if (matchedAllocation) {
|
|
76
|
+
return true;
|
|
61
77
|
}
|
|
62
|
-
}
|
|
63
78
|
|
|
64
|
-
|
|
79
|
+
return false;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
matchedTraffic,
|
|
84
|
+
matchedAllocation,
|
|
85
|
+
};
|
|
65
86
|
}
|
|
66
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Variations and variables
|
|
90
|
+
*/
|
|
67
91
|
function findForceFromFeature(
|
|
68
92
|
feature: Feature,
|
|
69
93
|
attributes: Attributes,
|
|
@@ -107,7 +131,7 @@ export function getBucketedVariation(
|
|
|
107
131
|
datafileReader: DatafileReader,
|
|
108
132
|
logger: Logger,
|
|
109
133
|
): Variation | undefined {
|
|
110
|
-
const matchedTraffic =
|
|
134
|
+
const { matchedTraffic, matchedAllocation } = getMatchedTrafficAndAllocation(
|
|
111
135
|
feature.traffic,
|
|
112
136
|
attributes,
|
|
113
137
|
bucketValue,
|
|
@@ -140,9 +164,7 @@ export function getBucketedVariation(
|
|
|
140
164
|
}
|
|
141
165
|
}
|
|
142
166
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if (!allocation) {
|
|
167
|
+
if (!matchedAllocation) {
|
|
146
168
|
logger.debug("no matched allocation found", {
|
|
147
169
|
featureKey: feature.key,
|
|
148
170
|
bucketValue,
|
|
@@ -151,7 +173,7 @@ export function getBucketedVariation(
|
|
|
151
173
|
return undefined;
|
|
152
174
|
}
|
|
153
175
|
|
|
154
|
-
const variationValue =
|
|
176
|
+
const variationValue = matchedAllocation.variation;
|
|
155
177
|
|
|
156
178
|
const variation = feature.variations.find((v) => {
|
|
157
179
|
return v.value === variationValue;
|
|
@@ -207,7 +229,7 @@ export function getBucketedVariableValue(
|
|
|
207
229
|
logger: Logger,
|
|
208
230
|
): VariableValue | undefined {
|
|
209
231
|
// get traffic
|
|
210
|
-
const matchedTraffic =
|
|
232
|
+
const { matchedTraffic, matchedAllocation } = getMatchedTrafficAndAllocation(
|
|
211
233
|
feature.traffic,
|
|
212
234
|
attributes,
|
|
213
235
|
bucketValue,
|
|
@@ -238,9 +260,7 @@ export function getBucketedVariableValue(
|
|
|
238
260
|
return matchedTraffic.variables[variableKey];
|
|
239
261
|
}
|
|
240
262
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (!allocation) {
|
|
263
|
+
if (!matchedAllocation) {
|
|
244
264
|
logger.debug("no matched allocation found", {
|
|
245
265
|
featureKey: feature.key,
|
|
246
266
|
variableKey,
|
|
@@ -250,7 +270,7 @@ export function getBucketedVariableValue(
|
|
|
250
270
|
return undefined;
|
|
251
271
|
}
|
|
252
272
|
|
|
253
|
-
const variationValue =
|
|
273
|
+
const variationValue = matchedAllocation.variation;
|
|
254
274
|
|
|
255
275
|
const variation = feature.variations.find((v) => {
|
|
256
276
|
return v.value === variationValue;
|