@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/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.interceptAttributes = options.interceptAttributes;
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, attributes) {
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 = attributes[attributeKey];
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, attributes, result);
193
+ return this.configureBucketKey(feature, context, result);
191
194
  }
192
195
  return result;
193
196
  };
194
- FeaturevisorInstance.prototype.getBucketValue = function (feature, attributes) {
195
- var bucketKey = this.getBucketKey(feature, attributes);
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, attributes, value);
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, attributes) {
264
- if (attributes === void 0) { attributes = {}; }
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 feature_1 = this.getFeature(featureKey);
451
+ var feature = this.getFeature(featureKey);
297
452
  // not found
298
- if (!feature_1) {
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 in datafile", evaluation);
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 finalAttributes = this.interceptAttributes
307
- ? this.interceptAttributes(attributes)
308
- : attributes;
470
+ var finalContext = this.interceptContext ? this.interceptContext(context) : context;
309
471
  // forced
310
- var force_1 = findForceFromFeature(feature_1, attributes, this.datafileReader);
472
+ var force_1 = findForceFromFeature(feature, context, this.datafileReader);
311
473
  if (force_1 && force_1.variation) {
312
- var variation_1 = feature_1.variations.find(function (v) { return v.value === force_1.variation; });
313
- if (variation_1) {
474
+ var variation = feature.variations.find(function (v) { return v.value === force_1.variation; });
475
+ if (variation) {
314
476
  evaluation = {
315
- featureKey: feature_1.key,
477
+ featureKey: feature.key,
316
478
  reason: EvaluationReason.FORCED,
317
- variation: variation_1,
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(feature_1, finalAttributes);
325
- var _a = getMatchedTrafficAndAllocation(feature_1.traffic, finalAttributes, bucketValue, this.datafileReader, this.logger), matchedTraffic_1 = _a.matchedTraffic, matchedAllocation_1 = _a.matchedAllocation;
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 variation_2 = feature_1.variations.find(function (v) { return v.value === matchedTraffic_1.variation; });
330
- if (variation_2) {
491
+ var variation = feature.variations.find(function (v) { return v.value === matchedTraffic_1.variation; });
492
+ if (variation) {
331
493
  evaluation = {
332
- featureKey: feature_1.key,
494
+ featureKey: feature.key,
333
495
  reason: EvaluationReason.RULE,
334
- variation: variation_2,
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 variation_3 = feature_1.variations.find(function (v) { return v.value === matchedAllocation_1.variation; });
345
- if (variation_3) {
506
+ var variation = feature.variations.find(function (v) { return v.value === matchedAllocation_1.variation; });
507
+ if (variation) {
346
508
  evaluation = {
347
- featureKey: feature_1.key,
509
+ featureKey: feature.key,
348
510
  reason: EvaluationReason.ALLOCATED,
349
511
  bucketValue: bucketValue,
350
- variation: variation_3,
512
+ variation: variation,
351
513
  };
352
514
  this.logger.debug("allocated variation", evaluation);
353
515
  return evaluation;
354
516
  }
355
517
  }
356
518
  }
357
- // fall back to default
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: feature_1.key,
521
+ featureKey: feature.key,
372
522
  reason: EvaluationReason.ERROR,
373
523
  bucketValue: bucketValue,
374
524
  };
375
- this.logger.error("no matched variation", evaluation);
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, attributes) {
388
- if (attributes === void 0) { attributes = {}; }
537
+ FeaturevisorInstance.prototype.getVariation = function (featureKey, context) {
538
+ if (context === void 0) { context = {}; }
389
539
  try {
390
- var evaluation = this.evaluateVariation(featureKey, attributes);
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, attributes) {
428
- if (attributes === void 0) { attributes = {}; }
557
+ FeaturevisorInstance.prototype.activate = function (featureKey, context) {
558
+ if (context === void 0) { context = {}; }
429
559
  try {
430
- var evaluation = this.evaluateVariation(featureKey, attributes);
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 finalAttributes_1 = this.interceptAttributes
438
- ? this.interceptAttributes(attributes)
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 finalAttributes_1[a.key] !== "undefined") {
446
- captureAttributes_1[a.key] = attributes[a.key];
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, finalAttributes_1, captureAttributes_1, evaluation);
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, attributes) {
458
- if (attributes === void 0) { attributes = {}; }
459
- var variationValue = this.activate(featureKey, attributes);
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, attributes) {
463
- if (attributes === void 0) { attributes = {}; }
464
- var variationValue = this.activate(featureKey, attributes);
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, attributes) {
468
- if (attributes === void 0) { attributes = {}; }
469
- var variationValue = this.activate(featureKey, attributes);
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, attributes) {
473
- if (attributes === void 0) { attributes = {}; }
474
- var variationValue = this.activate(featureKey, attributes);
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, attributes) {
608
+ FeaturevisorInstance.prototype.evaluateVariable = function (featureKey, variableKey, context) {
481
609
  var _this = this;
482
- if (attributes === void 0) { attributes = {}; }
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] && this.stickyFeatures[key].variables) {
488
- var result = this.stickyFeatures[key].variables[variableKey];
489
- if (typeof result !== "undefined") {
490
- evaluation = {
491
- featureKey: key,
492
- reason: EvaluationReason.STICKY,
493
- variableKey: variableKey,
494
- variableValue: result,
495
- };
496
- this.logger.debug("using sticky variable", evaluation);
497
- return evaluation;
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
- typeof this.initialFeatures[key].variables[variableKey] !== "undefined") {
507
- evaluation = {
508
- featureKey: key,
509
- reason: EvaluationReason.INITIAL,
510
- variableKey: variableKey,
511
- variableValue: this.initialFeatures[key].variables[variableKey],
512
- };
513
- this.logger.debug("using initial variable", evaluation);
514
- return evaluation;
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 finalAttributes_2 = this.interceptAttributes
541
- ? this.interceptAttributes(attributes)
542
- : attributes;
683
+ var finalContext_2 = this.interceptContext ? this.interceptContext(context) : context;
543
684
  // forced
544
- var force = findForceFromFeature(feature, attributes, this.datafileReader);
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, finalAttributes_2);
558
- var _a = getMatchedTrafficAndAllocation(feature.traffic, finalAttributes_2, bucketValue, this.datafileReader, this.logger), matchedTraffic = _a.matchedTraffic, matchedAllocation_2 = _a.matchedAllocation;
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, finalAttributes_2);
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, finalAttributes_2, _this.datafileReader);
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, attributes) {
647
- if (attributes === void 0) { attributes = {}; }
787
+ FeaturevisorInstance.prototype.getVariable = function (featureKey, variableKey, context) {
788
+ if (context === void 0) { context = {}; }
648
789
  try {
649
- var evaluation = this.evaluateVariable(featureKey, variableKey, attributes);
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, attributes) {
666
- if (attributes === void 0) { attributes = {}; }
667
- var variableValue = this.getVariable(featureKey, variableKey, attributes);
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, attributes) {
671
- if (attributes === void 0) { attributes = {}; }
672
- var variableValue = this.getVariable(featureKey, variableKey, attributes);
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, attributes) {
676
- if (attributes === void 0) { attributes = {}; }
677
- var variableValue = this.getVariable(featureKey, variableKey, attributes);
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, attributes) {
681
- if (attributes === void 0) { attributes = {}; }
682
- var variableValue = this.getVariable(featureKey, variableKey, attributes);
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, attributes) {
686
- if (attributes === void 0) { attributes = {}; }
687
- var variableValue = this.getVariable(featureKey, variableKey, attributes);
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, attributes) {
691
- if (attributes === void 0) { attributes = {}; }
692
- var variableValue = this.getVariable(featureKey, variableKey, attributes);
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, attributes) {
696
- if (attributes === void 0) { attributes = {}; }
697
- var variableValue = this.getVariable(featureKey, variableKey, attributes);
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;