@featurevisor/sdk 0.36.0 → 0.38.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/README.md +14 -14
- package/coverage/clover.xml +378 -315
- package/coverage/coverage-final.json +7 -7
- package/coverage/lcov-report/bucket.ts.html +4 -4
- package/coverage/lcov-report/conditions.ts.html +38 -38
- package/coverage/lcov-report/datafileReader.ts.html +4 -4
- package/coverage/lcov-report/emitter.ts.html +1 -1
- package/coverage/lcov-report/feature.ts.html +80 -20
- package/coverage/lcov-report/index.html +28 -28
- package/coverage/lcov-report/instance.ts.html +754 -220
- package/coverage/lcov-report/logger.ts.html +3 -3
- package/coverage/lcov-report/segments.ts.html +12 -12
- package/coverage/lcov.info +661 -559
- package/dist/index.js +1 -1
- package/dist/index.js.gz +0 -0
- package/dist/index.js.map +1 -1
- package/lib/conditions.d.ts +3 -3
- package/lib/conditions.js +35 -35
- package/lib/conditions.js.map +1 -1
- package/lib/feature.d.ts +4 -3
- package/lib/feature.js +13 -5
- package/lib/feature.js.map +1 -1
- package/lib/instance.d.ts +36 -27
- package/lib/instance.js +289 -148
- package/lib/instance.js.map +1 -1
- package/lib/segments.d.ts +3 -3
- package/lib/segments.js +8 -8
- package/lib/segments.js.map +1 -1
- package/package.json +3 -3
- package/src/conditions.ts +37 -37
- package/src/feature.ts +26 -6
- package/src/instance.spec.ts +64 -61
- package/src/instance.ts +325 -147
- package/src/segments.ts +9 -9
package/lib/instance.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createLogger } from "./logger";
|
|
|
2
2
|
import { DatafileReader } from "./datafileReader";
|
|
3
3
|
import { Emitter } from "./emitter";
|
|
4
4
|
import { getBucketedNumber } from "./bucket";
|
|
5
|
-
import { findForceFromFeature, getMatchedTrafficAndAllocation } from "./feature";
|
|
5
|
+
import { findForceFromFeature, getMatchedTraffic, getMatchedTrafficAndAllocation } from "./feature";
|
|
6
6
|
import { allConditionsAreMatched } from "./conditions";
|
|
7
7
|
import { allGroupSegmentsAreMatched } from "./segments";
|
|
8
8
|
var DEFAULT_BUCKET_KEY_SEPARATOR = ".";
|
|
@@ -16,6 +16,9 @@ var emptyDatafile = {
|
|
|
16
16
|
export var EvaluationReason;
|
|
17
17
|
(function (EvaluationReason) {
|
|
18
18
|
EvaluationReason["NOT_FOUND"] = "not_found";
|
|
19
|
+
EvaluationReason["NO_VARIATIONS"] = "no_variations";
|
|
20
|
+
EvaluationReason["DISABLED"] = "disabled";
|
|
21
|
+
EvaluationReason["OUT_OF_RANGE"] = "out_of_range";
|
|
19
22
|
EvaluationReason["FORCED"] = "forced";
|
|
20
23
|
EvaluationReason["INITIAL"] = "initial";
|
|
21
24
|
EvaluationReason["STICKY"] = "sticky";
|
|
@@ -68,7 +71,7 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
68
71
|
this.datafileUrl = options.datafileUrl;
|
|
69
72
|
this.handleDatafileFetch = options.handleDatafileFetch;
|
|
70
73
|
this.initialFeatures = options.initialFeatures;
|
|
71
|
-
this.
|
|
74
|
+
this.interceptContext = options.interceptContext;
|
|
72
75
|
this.logger = options.logger || createLogger();
|
|
73
76
|
this.refreshInterval = options.refreshInterval;
|
|
74
77
|
this.stickyFeatures = options.stickyFeatures;
|
|
@@ -148,7 +151,7 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
148
151
|
/**
|
|
149
152
|
* Bucketing
|
|
150
153
|
*/
|
|
151
|
-
FeaturevisorInstance.prototype.getBucketKey = function (feature,
|
|
154
|
+
FeaturevisorInstance.prototype.getBucketKey = function (feature, context) {
|
|
152
155
|
var featureKey = feature.key;
|
|
153
156
|
var type;
|
|
154
157
|
var attributeKeys;
|
|
@@ -170,7 +173,7 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
170
173
|
}
|
|
171
174
|
var bucketKey = [];
|
|
172
175
|
attributeKeys.forEach(function (attributeKey) {
|
|
173
|
-
var attributeValue =
|
|
176
|
+
var attributeValue = context[attributeKey];
|
|
174
177
|
if (typeof attributeValue === "undefined") {
|
|
175
178
|
return;
|
|
176
179
|
}
|
|
@@ -187,15 +190,15 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
187
190
|
bucketKey.push(featureKey);
|
|
188
191
|
var result = bucketKey.join(this.bucketKeySeparator);
|
|
189
192
|
if (this.configureBucketKey) {
|
|
190
|
-
return this.configureBucketKey(feature,
|
|
193
|
+
return this.configureBucketKey(feature, context, result);
|
|
191
194
|
}
|
|
192
195
|
return result;
|
|
193
196
|
};
|
|
194
|
-
FeaturevisorInstance.prototype.getBucketValue = function (feature,
|
|
195
|
-
var bucketKey = this.getBucketKey(feature,
|
|
197
|
+
FeaturevisorInstance.prototype.getBucketValue = function (feature, context) {
|
|
198
|
+
var bucketKey = this.getBucketKey(feature, context);
|
|
196
199
|
var value = getBucketedNumber(bucketKey);
|
|
197
200
|
if (this.configureBucketValue) {
|
|
198
|
-
return this.configureBucketValue(feature,
|
|
201
|
+
return this.configureBucketValue(feature, context, value);
|
|
199
202
|
}
|
|
200
203
|
return value;
|
|
201
204
|
};
|
|
@@ -257,14 +260,166 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
257
260
|
}
|
|
258
261
|
clearInterval(this.intervalId);
|
|
259
262
|
};
|
|
263
|
+
/**
|
|
264
|
+
* Flag
|
|
265
|
+
*/
|
|
266
|
+
FeaturevisorInstance.prototype.evaluateFlag = function (featureKey, context) {
|
|
267
|
+
if (context === void 0) { context = {}; }
|
|
268
|
+
var evaluation;
|
|
269
|
+
try {
|
|
270
|
+
var key = typeof featureKey === "string" ? featureKey : featureKey.key;
|
|
271
|
+
// sticky
|
|
272
|
+
if (this.stickyFeatures &&
|
|
273
|
+
this.stickyFeatures[key] &&
|
|
274
|
+
typeof this.stickyFeatures[key].enabled !== "undefined") {
|
|
275
|
+
evaluation = {
|
|
276
|
+
featureKey: key,
|
|
277
|
+
reason: EvaluationReason.STICKY,
|
|
278
|
+
enabled: this.stickyFeatures[key].enabled,
|
|
279
|
+
sticky: this.stickyFeatures[key],
|
|
280
|
+
};
|
|
281
|
+
this.logger.debug("using sticky enabled", evaluation);
|
|
282
|
+
return evaluation;
|
|
283
|
+
}
|
|
284
|
+
// initial
|
|
285
|
+
if (this.statuses &&
|
|
286
|
+
!this.statuses.ready &&
|
|
287
|
+
this.initialFeatures &&
|
|
288
|
+
this.initialFeatures[key] &&
|
|
289
|
+
typeof this.initialFeatures[key].enabled !== "undefined") {
|
|
290
|
+
evaluation = {
|
|
291
|
+
featureKey: key,
|
|
292
|
+
reason: EvaluationReason.INITIAL,
|
|
293
|
+
enabled: this.initialFeatures[key].enabled,
|
|
294
|
+
initial: this.initialFeatures[key],
|
|
295
|
+
};
|
|
296
|
+
this.logger.debug("using initial enabled", evaluation);
|
|
297
|
+
return evaluation;
|
|
298
|
+
}
|
|
299
|
+
var feature = this.getFeature(featureKey);
|
|
300
|
+
// not found
|
|
301
|
+
if (!feature) {
|
|
302
|
+
evaluation = {
|
|
303
|
+
featureKey: key,
|
|
304
|
+
reason: EvaluationReason.NOT_FOUND,
|
|
305
|
+
};
|
|
306
|
+
this.logger.warn("feature not found", evaluation);
|
|
307
|
+
return evaluation;
|
|
308
|
+
}
|
|
309
|
+
var finalContext = this.interceptContext ? this.interceptContext(context) : context;
|
|
310
|
+
// forced
|
|
311
|
+
var force = findForceFromFeature(feature, context, this.datafileReader);
|
|
312
|
+
if (force && typeof force.enabled !== "undefined") {
|
|
313
|
+
evaluation = {
|
|
314
|
+
featureKey: feature.key,
|
|
315
|
+
reason: EvaluationReason.FORCED,
|
|
316
|
+
enabled: force.enabled,
|
|
317
|
+
};
|
|
318
|
+
this.logger.debug("forced enabled found", evaluation);
|
|
319
|
+
return evaluation;
|
|
320
|
+
}
|
|
321
|
+
// bucketing
|
|
322
|
+
var bucketValue_1 = this.getBucketValue(feature, finalContext);
|
|
323
|
+
var matchedTraffic = getMatchedTraffic(feature.traffic, finalContext, this.datafileReader);
|
|
324
|
+
if (matchedTraffic) {
|
|
325
|
+
// check if mutually exclusive
|
|
326
|
+
if (feature.ranges && feature.ranges.length > 0) {
|
|
327
|
+
var matchedRange = feature.ranges.find(function (range) {
|
|
328
|
+
return bucketValue_1 >= range[0] && bucketValue_1 < range[1];
|
|
329
|
+
});
|
|
330
|
+
// matched
|
|
331
|
+
if (matchedRange) {
|
|
332
|
+
evaluation = {
|
|
333
|
+
featureKey: feature.key,
|
|
334
|
+
reason: EvaluationReason.ALLOCATED,
|
|
335
|
+
enabled: typeof matchedTraffic.enabled === "undefined" ? true : matchedTraffic.enabled,
|
|
336
|
+
bucketValue: bucketValue_1,
|
|
337
|
+
};
|
|
338
|
+
return evaluation;
|
|
339
|
+
}
|
|
340
|
+
// no match
|
|
341
|
+
evaluation = {
|
|
342
|
+
featureKey: feature.key,
|
|
343
|
+
reason: EvaluationReason.OUT_OF_RANGE,
|
|
344
|
+
enabled: false,
|
|
345
|
+
bucketValue: bucketValue_1,
|
|
346
|
+
};
|
|
347
|
+
this.logger.debug("not matched", evaluation);
|
|
348
|
+
return evaluation;
|
|
349
|
+
}
|
|
350
|
+
// override from rule
|
|
351
|
+
if (typeof matchedTraffic.enabled !== "undefined") {
|
|
352
|
+
evaluation = {
|
|
353
|
+
featureKey: feature.key,
|
|
354
|
+
reason: EvaluationReason.OVERRIDE,
|
|
355
|
+
enabled: matchedTraffic.enabled,
|
|
356
|
+
bucketValue: bucketValue_1,
|
|
357
|
+
ruleKey: matchedTraffic.key,
|
|
358
|
+
traffic: matchedTraffic,
|
|
359
|
+
};
|
|
360
|
+
this.logger.debug("override from rule", evaluation);
|
|
361
|
+
return evaluation;
|
|
362
|
+
}
|
|
363
|
+
// treated as enabled because of matched traffic
|
|
364
|
+
if (bucketValue_1 < matchedTraffic.percentage) {
|
|
365
|
+
// @TODO: verify if range check should be inclusive or not
|
|
366
|
+
evaluation = {
|
|
367
|
+
featureKey: feature.key,
|
|
368
|
+
reason: EvaluationReason.RULE,
|
|
369
|
+
enabled: true,
|
|
370
|
+
bucketValue: bucketValue_1,
|
|
371
|
+
ruleKey: matchedTraffic.key,
|
|
372
|
+
traffic: matchedTraffic,
|
|
373
|
+
};
|
|
374
|
+
return evaluation;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
// nothing matched
|
|
378
|
+
evaluation = {
|
|
379
|
+
featureKey: feature.key,
|
|
380
|
+
reason: EvaluationReason.ERROR,
|
|
381
|
+
enabled: false,
|
|
382
|
+
bucketValue: bucketValue_1,
|
|
383
|
+
};
|
|
384
|
+
return evaluation;
|
|
385
|
+
}
|
|
386
|
+
catch (e) {
|
|
387
|
+
evaluation = {
|
|
388
|
+
featureKey: typeof featureKey === "string" ? featureKey : featureKey.key,
|
|
389
|
+
reason: EvaluationReason.ERROR,
|
|
390
|
+
error: e,
|
|
391
|
+
};
|
|
392
|
+
return evaluation;
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
FeaturevisorInstance.prototype.isEnabled = function (featureKey, context) {
|
|
396
|
+
if (context === void 0) { context = {}; }
|
|
397
|
+
try {
|
|
398
|
+
var evaluation = this.evaluateFlag(featureKey, context);
|
|
399
|
+
return evaluation.enabled === true;
|
|
400
|
+
}
|
|
401
|
+
catch (e) {
|
|
402
|
+
this.logger.error("isEnabled", { featureKey: featureKey, error: e });
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
};
|
|
260
406
|
/**
|
|
261
407
|
* Variation
|
|
262
408
|
*/
|
|
263
|
-
FeaturevisorInstance.prototype.evaluateVariation = function (featureKey,
|
|
264
|
-
if (
|
|
409
|
+
FeaturevisorInstance.prototype.evaluateVariation = function (featureKey, context) {
|
|
410
|
+
if (context === void 0) { context = {}; }
|
|
265
411
|
var evaluation;
|
|
266
412
|
try {
|
|
267
413
|
var key = typeof featureKey === "string" ? featureKey : featureKey.key;
|
|
414
|
+
var flag = this.evaluateFlag(featureKey, context);
|
|
415
|
+
if (flag.enabled === false) {
|
|
416
|
+
evaluation = {
|
|
417
|
+
featureKey: key,
|
|
418
|
+
reason: EvaluationReason.DISABLED,
|
|
419
|
+
};
|
|
420
|
+
this.logger.debug("feature is disabled", evaluation);
|
|
421
|
+
return evaluation;
|
|
422
|
+
}
|
|
268
423
|
// sticky
|
|
269
424
|
if (this.stickyFeatures && this.stickyFeatures[key]) {
|
|
270
425
|
var variationValue = this.stickyFeatures[key].variation;
|
|
@@ -293,45 +448,52 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
293
448
|
this.logger.debug("using initial variation", evaluation);
|
|
294
449
|
return evaluation;
|
|
295
450
|
}
|
|
296
|
-
var
|
|
451
|
+
var feature = this.getFeature(featureKey);
|
|
297
452
|
// not found
|
|
298
|
-
if (!
|
|
453
|
+
if (!feature) {
|
|
299
454
|
evaluation = {
|
|
300
455
|
featureKey: key,
|
|
301
456
|
reason: EvaluationReason.NOT_FOUND,
|
|
302
457
|
};
|
|
303
|
-
this.logger.warn("feature not found
|
|
458
|
+
this.logger.warn("feature not found", evaluation);
|
|
459
|
+
return evaluation;
|
|
460
|
+
}
|
|
461
|
+
// no variations
|
|
462
|
+
if (!feature.variations || feature.variations.length === 0) {
|
|
463
|
+
evaluation = {
|
|
464
|
+
featureKey: key,
|
|
465
|
+
reason: EvaluationReason.NO_VARIATIONS,
|
|
466
|
+
};
|
|
467
|
+
this.logger.warn("no variations", evaluation);
|
|
304
468
|
return evaluation;
|
|
305
469
|
}
|
|
306
|
-
var
|
|
307
|
-
? this.interceptAttributes(attributes)
|
|
308
|
-
: attributes;
|
|
470
|
+
var finalContext = this.interceptContext ? this.interceptContext(context) : context;
|
|
309
471
|
// forced
|
|
310
|
-
var force_1 = findForceFromFeature(
|
|
472
|
+
var force_1 = findForceFromFeature(feature, context, this.datafileReader);
|
|
311
473
|
if (force_1 && force_1.variation) {
|
|
312
|
-
var
|
|
313
|
-
if (
|
|
474
|
+
var variation = feature.variations.find(function (v) { return v.value === force_1.variation; });
|
|
475
|
+
if (variation) {
|
|
314
476
|
evaluation = {
|
|
315
|
-
featureKey:
|
|
477
|
+
featureKey: feature.key,
|
|
316
478
|
reason: EvaluationReason.FORCED,
|
|
317
|
-
variation:
|
|
479
|
+
variation: variation,
|
|
318
480
|
};
|
|
319
481
|
this.logger.debug("forced variation found", evaluation);
|
|
320
482
|
return evaluation;
|
|
321
483
|
}
|
|
322
484
|
}
|
|
323
485
|
// bucketing
|
|
324
|
-
var bucketValue = this.getBucketValue(
|
|
325
|
-
var _a = getMatchedTrafficAndAllocation(
|
|
486
|
+
var bucketValue = this.getBucketValue(feature, finalContext);
|
|
487
|
+
var _a = getMatchedTrafficAndAllocation(feature.traffic, finalContext, bucketValue, this.datafileReader, this.logger), matchedTraffic_1 = _a.matchedTraffic, matchedAllocation_1 = _a.matchedAllocation;
|
|
326
488
|
if (matchedTraffic_1) {
|
|
327
489
|
// override from rule
|
|
328
490
|
if (matchedTraffic_1.variation) {
|
|
329
|
-
var
|
|
330
|
-
if (
|
|
491
|
+
var variation = feature.variations.find(function (v) { return v.value === matchedTraffic_1.variation; });
|
|
492
|
+
if (variation) {
|
|
331
493
|
evaluation = {
|
|
332
|
-
featureKey:
|
|
494
|
+
featureKey: feature.key,
|
|
333
495
|
reason: EvaluationReason.RULE,
|
|
334
|
-
variation:
|
|
496
|
+
variation: variation,
|
|
335
497
|
bucketValue: bucketValue,
|
|
336
498
|
ruleKey: matchedTraffic_1.key,
|
|
337
499
|
};
|
|
@@ -341,38 +503,26 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
341
503
|
}
|
|
342
504
|
// regular allocation
|
|
343
505
|
if (matchedAllocation_1 && matchedAllocation_1.variation) {
|
|
344
|
-
var
|
|
345
|
-
if (
|
|
506
|
+
var variation = feature.variations.find(function (v) { return v.value === matchedAllocation_1.variation; });
|
|
507
|
+
if (variation) {
|
|
346
508
|
evaluation = {
|
|
347
|
-
featureKey:
|
|
509
|
+
featureKey: feature.key,
|
|
348
510
|
reason: EvaluationReason.ALLOCATED,
|
|
349
511
|
bucketValue: bucketValue,
|
|
350
|
-
variation:
|
|
512
|
+
variation: variation,
|
|
351
513
|
};
|
|
352
514
|
this.logger.debug("allocated variation", evaluation);
|
|
353
515
|
return evaluation;
|
|
354
516
|
}
|
|
355
517
|
}
|
|
356
518
|
}
|
|
357
|
-
//
|
|
358
|
-
var variation = feature_1.variations.find(function (v) { return v.value === feature_1.defaultVariation; });
|
|
359
|
-
if (variation) {
|
|
360
|
-
evaluation = {
|
|
361
|
-
featureKey: feature_1.key,
|
|
362
|
-
reason: EvaluationReason.DEFAULTED,
|
|
363
|
-
bucketValue: bucketValue,
|
|
364
|
-
variation: variation,
|
|
365
|
-
};
|
|
366
|
-
this.logger.debug("using default variation", evaluation);
|
|
367
|
-
return evaluation;
|
|
368
|
-
}
|
|
369
|
-
// nothing matched (this should never happen)
|
|
519
|
+
// nothing matched
|
|
370
520
|
evaluation = {
|
|
371
|
-
featureKey:
|
|
521
|
+
featureKey: feature.key,
|
|
372
522
|
reason: EvaluationReason.ERROR,
|
|
373
523
|
bucketValue: bucketValue,
|
|
374
524
|
};
|
|
375
|
-
this.logger.
|
|
525
|
+
this.logger.debug("no matched variation", evaluation);
|
|
376
526
|
return evaluation;
|
|
377
527
|
}
|
|
378
528
|
catch (e) {
|
|
@@ -384,10 +534,10 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
384
534
|
return evaluation;
|
|
385
535
|
}
|
|
386
536
|
};
|
|
387
|
-
FeaturevisorInstance.prototype.getVariation = function (featureKey,
|
|
388
|
-
if (
|
|
537
|
+
FeaturevisorInstance.prototype.getVariation = function (featureKey, context) {
|
|
538
|
+
if (context === void 0) { context = {}; }
|
|
389
539
|
try {
|
|
390
|
-
var evaluation = this.evaluateVariation(featureKey,
|
|
540
|
+
var evaluation = this.evaluateVariation(featureKey, context);
|
|
391
541
|
if (typeof evaluation.variationValue !== "undefined") {
|
|
392
542
|
return evaluation.variationValue;
|
|
393
543
|
}
|
|
@@ -401,52 +551,30 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
401
551
|
return undefined;
|
|
402
552
|
}
|
|
403
553
|
};
|
|
404
|
-
FeaturevisorInstance.prototype.getVariationBoolean = function (featureKey, attributes) {
|
|
405
|
-
if (attributes === void 0) { attributes = {}; }
|
|
406
|
-
var variationValue = this.getVariation(featureKey, attributes);
|
|
407
|
-
return getValueByType(variationValue, "boolean");
|
|
408
|
-
};
|
|
409
|
-
FeaturevisorInstance.prototype.getVariationString = function (featureKey, attributes) {
|
|
410
|
-
if (attributes === void 0) { attributes = {}; }
|
|
411
|
-
var variationValue = this.getVariation(featureKey, attributes);
|
|
412
|
-
return getValueByType(variationValue, "string");
|
|
413
|
-
};
|
|
414
|
-
FeaturevisorInstance.prototype.getVariationInteger = function (featureKey, attributes) {
|
|
415
|
-
if (attributes === void 0) { attributes = {}; }
|
|
416
|
-
var variationValue = this.getVariation(featureKey, attributes);
|
|
417
|
-
return getValueByType(variationValue, "integer");
|
|
418
|
-
};
|
|
419
|
-
FeaturevisorInstance.prototype.getVariationDouble = function (featureKey, attributes) {
|
|
420
|
-
if (attributes === void 0) { attributes = {}; }
|
|
421
|
-
var variationValue = this.getVariation(featureKey, attributes);
|
|
422
|
-
return getValueByType(variationValue, "double");
|
|
423
|
-
};
|
|
424
554
|
/**
|
|
425
555
|
* Activate
|
|
426
556
|
*/
|
|
427
|
-
FeaturevisorInstance.prototype.activate = function (featureKey,
|
|
428
|
-
if (
|
|
557
|
+
FeaturevisorInstance.prototype.activate = function (featureKey, context) {
|
|
558
|
+
if (context === void 0) { context = {}; }
|
|
429
559
|
try {
|
|
430
|
-
var evaluation = this.evaluateVariation(featureKey,
|
|
560
|
+
var evaluation = this.evaluateVariation(featureKey, context);
|
|
431
561
|
var variationValue = evaluation.variation
|
|
432
562
|
? evaluation.variation.value
|
|
433
563
|
: evaluation.variationValue;
|
|
434
564
|
if (typeof variationValue === "undefined") {
|
|
435
565
|
return undefined;
|
|
436
566
|
}
|
|
437
|
-
var
|
|
438
|
-
|
|
439
|
-
: attributes;
|
|
440
|
-
var captureAttributes_1 = {};
|
|
567
|
+
var finalContext_1 = this.interceptContext ? this.interceptContext(context) : context;
|
|
568
|
+
var captureContext_1 = {};
|
|
441
569
|
var attributesForCapturing = this.datafileReader
|
|
442
570
|
.getAllAttributes()
|
|
443
571
|
.filter(function (a) { return a.capture === true; });
|
|
444
572
|
attributesForCapturing.forEach(function (a) {
|
|
445
|
-
if (typeof
|
|
446
|
-
|
|
573
|
+
if (typeof finalContext_1[a.key] !== "undefined") {
|
|
574
|
+
captureContext_1[a.key] = context[a.key];
|
|
447
575
|
}
|
|
448
576
|
});
|
|
449
|
-
this.emitter.emit("activation", featureKey, variationValue,
|
|
577
|
+
this.emitter.emit("activation", featureKey, variationValue, finalContext_1, captureContext_1, evaluation);
|
|
450
578
|
return variationValue;
|
|
451
579
|
}
|
|
452
580
|
catch (e) {
|
|
@@ -454,64 +582,79 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
454
582
|
return undefined;
|
|
455
583
|
}
|
|
456
584
|
};
|
|
457
|
-
FeaturevisorInstance.prototype.activateBoolean = function (featureKey,
|
|
458
|
-
if (
|
|
459
|
-
var variationValue = this.activate(featureKey,
|
|
585
|
+
FeaturevisorInstance.prototype.activateBoolean = function (featureKey, context) {
|
|
586
|
+
if (context === void 0) { context = {}; }
|
|
587
|
+
var variationValue = this.activate(featureKey, context);
|
|
460
588
|
return getValueByType(variationValue, "boolean");
|
|
461
589
|
};
|
|
462
|
-
FeaturevisorInstance.prototype.activateString = function (featureKey,
|
|
463
|
-
if (
|
|
464
|
-
var variationValue = this.activate(featureKey,
|
|
590
|
+
FeaturevisorInstance.prototype.activateString = function (featureKey, context) {
|
|
591
|
+
if (context === void 0) { context = {}; }
|
|
592
|
+
var variationValue = this.activate(featureKey, context);
|
|
465
593
|
return getValueByType(variationValue, "string");
|
|
466
594
|
};
|
|
467
|
-
FeaturevisorInstance.prototype.activateInteger = function (featureKey,
|
|
468
|
-
if (
|
|
469
|
-
var variationValue = this.activate(featureKey,
|
|
595
|
+
FeaturevisorInstance.prototype.activateInteger = function (featureKey, context) {
|
|
596
|
+
if (context === void 0) { context = {}; }
|
|
597
|
+
var variationValue = this.activate(featureKey, context);
|
|
470
598
|
return getValueByType(variationValue, "integer");
|
|
471
599
|
};
|
|
472
|
-
FeaturevisorInstance.prototype.activateDouble = function (featureKey,
|
|
473
|
-
if (
|
|
474
|
-
var variationValue = this.activate(featureKey,
|
|
600
|
+
FeaturevisorInstance.prototype.activateDouble = function (featureKey, context) {
|
|
601
|
+
if (context === void 0) { context = {}; }
|
|
602
|
+
var variationValue = this.activate(featureKey, context);
|
|
475
603
|
return getValueByType(variationValue, "double");
|
|
476
604
|
};
|
|
477
605
|
/**
|
|
478
606
|
* Variable
|
|
479
607
|
*/
|
|
480
|
-
FeaturevisorInstance.prototype.evaluateVariable = function (featureKey, variableKey,
|
|
608
|
+
FeaturevisorInstance.prototype.evaluateVariable = function (featureKey, variableKey, context) {
|
|
481
609
|
var _this = this;
|
|
482
|
-
if (
|
|
610
|
+
if (context === void 0) { context = {}; }
|
|
483
611
|
var evaluation;
|
|
484
612
|
try {
|
|
485
613
|
var key = typeof featureKey === "string" ? featureKey : featureKey.key;
|
|
614
|
+
var flag = this.evaluateFlag(featureKey, context);
|
|
615
|
+
if (flag.enabled === false) {
|
|
616
|
+
evaluation = {
|
|
617
|
+
featureKey: key,
|
|
618
|
+
reason: EvaluationReason.DISABLED,
|
|
619
|
+
};
|
|
620
|
+
this.logger.debug("feature is disabled", evaluation);
|
|
621
|
+
return evaluation;
|
|
622
|
+
}
|
|
486
623
|
// sticky
|
|
487
|
-
if (this.stickyFeatures && this.stickyFeatures[key]
|
|
488
|
-
var
|
|
489
|
-
if (
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
624
|
+
if (this.stickyFeatures && this.stickyFeatures[key]) {
|
|
625
|
+
var variables = this.stickyFeatures[key].variables;
|
|
626
|
+
if (variables) {
|
|
627
|
+
var result = variables[variableKey];
|
|
628
|
+
if (typeof result !== "undefined") {
|
|
629
|
+
evaluation = {
|
|
630
|
+
featureKey: key,
|
|
631
|
+
reason: EvaluationReason.STICKY,
|
|
632
|
+
variableKey: variableKey,
|
|
633
|
+
variableValue: result,
|
|
634
|
+
};
|
|
635
|
+
this.logger.debug("using sticky variable", evaluation);
|
|
636
|
+
return evaluation;
|
|
637
|
+
}
|
|
498
638
|
}
|
|
499
639
|
}
|
|
500
640
|
// initial
|
|
501
641
|
if (this.statuses &&
|
|
502
642
|
!this.statuses.ready &&
|
|
503
643
|
this.initialFeatures &&
|
|
504
|
-
this.initialFeatures[key]
|
|
505
|
-
this.initialFeatures[key].variables
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
644
|
+
this.initialFeatures[key]) {
|
|
645
|
+
var variables = this.initialFeatures[key].variables;
|
|
646
|
+
if (variables) {
|
|
647
|
+
if (typeof variables[variableKey] !== "undefined") {
|
|
648
|
+
evaluation = {
|
|
649
|
+
featureKey: key,
|
|
650
|
+
reason: EvaluationReason.INITIAL,
|
|
651
|
+
variableKey: variableKey,
|
|
652
|
+
variableValue: variables[variableKey],
|
|
653
|
+
};
|
|
654
|
+
this.logger.debug("using initial variable", evaluation);
|
|
655
|
+
return evaluation;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
515
658
|
}
|
|
516
659
|
var feature = this.getFeature(featureKey);
|
|
517
660
|
// not found
|
|
@@ -537,11 +680,9 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
537
680
|
this.logger.warn("variable schema not found", evaluation);
|
|
538
681
|
return evaluation;
|
|
539
682
|
}
|
|
540
|
-
var
|
|
541
|
-
? this.interceptAttributes(attributes)
|
|
542
|
-
: attributes;
|
|
683
|
+
var finalContext_2 = this.interceptContext ? this.interceptContext(context) : context;
|
|
543
684
|
// forced
|
|
544
|
-
var force = findForceFromFeature(feature,
|
|
685
|
+
var force = findForceFromFeature(feature, context, this.datafileReader);
|
|
545
686
|
if (force && force.variables && typeof force.variables[variableKey] !== "undefined") {
|
|
546
687
|
evaluation = {
|
|
547
688
|
featureKey: feature.key,
|
|
@@ -554,8 +695,8 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
554
695
|
return evaluation;
|
|
555
696
|
}
|
|
556
697
|
// bucketing
|
|
557
|
-
var bucketValue = this.getBucketValue(feature,
|
|
558
|
-
var _a = getMatchedTrafficAndAllocation(feature.traffic,
|
|
698
|
+
var bucketValue = this.getBucketValue(feature, finalContext_2);
|
|
699
|
+
var _a = getMatchedTrafficAndAllocation(feature.traffic, finalContext_2, bucketValue, this.datafileReader, this.logger), matchedTraffic = _a.matchedTraffic, matchedAllocation_2 = _a.matchedAllocation;
|
|
559
700
|
if (matchedTraffic) {
|
|
560
701
|
// override from rule
|
|
561
702
|
if (matchedTraffic.variables &&
|
|
@@ -573,7 +714,7 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
573
714
|
return evaluation;
|
|
574
715
|
}
|
|
575
716
|
// regular allocation
|
|
576
|
-
if (matchedAllocation_2 && matchedAllocation_2.variation) {
|
|
717
|
+
if (matchedAllocation_2 && matchedAllocation_2.variation && Array.isArray(feature.variations)) {
|
|
577
718
|
var variation = feature.variations.find(function (v) { return v.value === matchedAllocation_2.variation; });
|
|
578
719
|
if (variation && variation.variables) {
|
|
579
720
|
var variableFromVariation = variation.variables.find(function (v) { return v.key === variableKey; });
|
|
@@ -581,12 +722,12 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
581
722
|
if (variableFromVariation.overrides) {
|
|
582
723
|
var override = variableFromVariation.overrides.find(function (o) {
|
|
583
724
|
if (o.conditions) {
|
|
584
|
-
return allConditionsAreMatched(typeof o.conditions === "string" ? JSON.parse(o.conditions) : o.conditions,
|
|
725
|
+
return allConditionsAreMatched(typeof o.conditions === "string" ? JSON.parse(o.conditions) : o.conditions, finalContext_2);
|
|
585
726
|
}
|
|
586
727
|
if (o.segments) {
|
|
587
728
|
return allGroupSegmentsAreMatched(typeof o.segments === "string" && o.segments !== "*"
|
|
588
729
|
? JSON.parse(o.segments)
|
|
589
|
-
: o.segments,
|
|
730
|
+
: o.segments, finalContext_2, _this.datafileReader);
|
|
590
731
|
}
|
|
591
732
|
return false;
|
|
592
733
|
});
|
|
@@ -643,10 +784,10 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
643
784
|
return evaluation;
|
|
644
785
|
}
|
|
645
786
|
};
|
|
646
|
-
FeaturevisorInstance.prototype.getVariable = function (featureKey, variableKey,
|
|
647
|
-
if (
|
|
787
|
+
FeaturevisorInstance.prototype.getVariable = function (featureKey, variableKey, context) {
|
|
788
|
+
if (context === void 0) { context = {}; }
|
|
648
789
|
try {
|
|
649
|
-
var evaluation = this.evaluateVariable(featureKey, variableKey,
|
|
790
|
+
var evaluation = this.evaluateVariable(featureKey, variableKey, context);
|
|
650
791
|
if (typeof evaluation.variableValue !== "undefined") {
|
|
651
792
|
if (evaluation.variableSchema &&
|
|
652
793
|
evaluation.variableSchema.type === "json" &&
|
|
@@ -662,39 +803,39 @@ var FeaturevisorInstance = /** @class */ (function () {
|
|
|
662
803
|
return undefined;
|
|
663
804
|
}
|
|
664
805
|
};
|
|
665
|
-
FeaturevisorInstance.prototype.getVariableBoolean = function (featureKey, variableKey,
|
|
666
|
-
if (
|
|
667
|
-
var variableValue = this.getVariable(featureKey, variableKey,
|
|
806
|
+
FeaturevisorInstance.prototype.getVariableBoolean = function (featureKey, variableKey, context) {
|
|
807
|
+
if (context === void 0) { context = {}; }
|
|
808
|
+
var variableValue = this.getVariable(featureKey, variableKey, context);
|
|
668
809
|
return getValueByType(variableValue, "boolean");
|
|
669
810
|
};
|
|
670
|
-
FeaturevisorInstance.prototype.getVariableString = function (featureKey, variableKey,
|
|
671
|
-
if (
|
|
672
|
-
var variableValue = this.getVariable(featureKey, variableKey,
|
|
811
|
+
FeaturevisorInstance.prototype.getVariableString = function (featureKey, variableKey, context) {
|
|
812
|
+
if (context === void 0) { context = {}; }
|
|
813
|
+
var variableValue = this.getVariable(featureKey, variableKey, context);
|
|
673
814
|
return getValueByType(variableValue, "string");
|
|
674
815
|
};
|
|
675
|
-
FeaturevisorInstance.prototype.getVariableInteger = function (featureKey, variableKey,
|
|
676
|
-
if (
|
|
677
|
-
var variableValue = this.getVariable(featureKey, variableKey,
|
|
816
|
+
FeaturevisorInstance.prototype.getVariableInteger = function (featureKey, variableKey, context) {
|
|
817
|
+
if (context === void 0) { context = {}; }
|
|
818
|
+
var variableValue = this.getVariable(featureKey, variableKey, context);
|
|
678
819
|
return getValueByType(variableValue, "integer");
|
|
679
820
|
};
|
|
680
|
-
FeaturevisorInstance.prototype.getVariableDouble = function (featureKey, variableKey,
|
|
681
|
-
if (
|
|
682
|
-
var variableValue = this.getVariable(featureKey, variableKey,
|
|
821
|
+
FeaturevisorInstance.prototype.getVariableDouble = function (featureKey, variableKey, context) {
|
|
822
|
+
if (context === void 0) { context = {}; }
|
|
823
|
+
var variableValue = this.getVariable(featureKey, variableKey, context);
|
|
683
824
|
return getValueByType(variableValue, "double");
|
|
684
825
|
};
|
|
685
|
-
FeaturevisorInstance.prototype.getVariableArray = function (featureKey, variableKey,
|
|
686
|
-
if (
|
|
687
|
-
var variableValue = this.getVariable(featureKey, variableKey,
|
|
826
|
+
FeaturevisorInstance.prototype.getVariableArray = function (featureKey, variableKey, context) {
|
|
827
|
+
if (context === void 0) { context = {}; }
|
|
828
|
+
var variableValue = this.getVariable(featureKey, variableKey, context);
|
|
688
829
|
return getValueByType(variableValue, "array");
|
|
689
830
|
};
|
|
690
|
-
FeaturevisorInstance.prototype.getVariableObject = function (featureKey, variableKey,
|
|
691
|
-
if (
|
|
692
|
-
var variableValue = this.getVariable(featureKey, variableKey,
|
|
831
|
+
FeaturevisorInstance.prototype.getVariableObject = function (featureKey, variableKey, context) {
|
|
832
|
+
if (context === void 0) { context = {}; }
|
|
833
|
+
var variableValue = this.getVariable(featureKey, variableKey, context);
|
|
693
834
|
return getValueByType(variableValue, "object");
|
|
694
835
|
};
|
|
695
|
-
FeaturevisorInstance.prototype.getVariableJSON = function (featureKey, variableKey,
|
|
696
|
-
if (
|
|
697
|
-
var variableValue = this.getVariable(featureKey, variableKey,
|
|
836
|
+
FeaturevisorInstance.prototype.getVariableJSON = function (featureKey, variableKey, context) {
|
|
837
|
+
if (context === void 0) { context = {}; }
|
|
838
|
+
var variableValue = this.getVariable(featureKey, variableKey, context);
|
|
698
839
|
return getValueByType(variableValue, "json");
|
|
699
840
|
};
|
|
700
841
|
return FeaturevisorInstance;
|