@ninetailed/experience.js 2.0.0-beta.6 → 2.0.0-beta.9
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/index.esm.js +36 -12
- package/index.umd.js +41 -14
- package/lib/experience/utils.d.ts +4 -0
- package/package.json +4 -3
package/index.esm.js
CHANGED
|
@@ -6,6 +6,7 @@ import flatten from 'lodash/flatten';
|
|
|
6
6
|
import find from 'lodash/find';
|
|
7
7
|
import includes from 'lodash/includes';
|
|
8
8
|
import pickBy from 'lodash/pickBy';
|
|
9
|
+
import { murmur3 } from 'murmurhash-js';
|
|
9
10
|
|
|
10
11
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
11
12
|
|
|
@@ -883,14 +884,14 @@ var isCallable$a = isCallable$j;
|
|
|
883
884
|
var replacement = /#|\.prototype\./;
|
|
884
885
|
|
|
885
886
|
var isForced$2 = function (feature, detection) {
|
|
886
|
-
var value = data[normalize(feature)];
|
|
887
|
+
var value = data[normalize$1(feature)];
|
|
887
888
|
return value == POLYFILL ? true
|
|
888
889
|
: value == NATIVE ? false
|
|
889
890
|
: isCallable$a(detection) ? fails$a(detection)
|
|
890
891
|
: !!detection;
|
|
891
892
|
};
|
|
892
893
|
|
|
893
|
-
var normalize = isForced$2.normalize = function (string) {
|
|
894
|
+
var normalize$1 = isForced$2.normalize = function (string) {
|
|
894
895
|
return String(string).replace(replacement, '.').toLowerCase();
|
|
895
896
|
};
|
|
896
897
|
|
|
@@ -4572,6 +4573,28 @@ const selectEglibleExperiences = ({
|
|
|
4572
4573
|
}));
|
|
4573
4574
|
};
|
|
4574
4575
|
|
|
4576
|
+
const LOWER_BOUND = 0;
|
|
4577
|
+
const UPPER_BOUND = 4294967295;
|
|
4578
|
+
|
|
4579
|
+
const normalize = (val, min, max) => (val - min) / (max - min);
|
|
4580
|
+
|
|
4581
|
+
const getRandom = text => {
|
|
4582
|
+
const hash = murmur3(text, 0);
|
|
4583
|
+
const random = normalize(hash, LOWER_BOUND, UPPER_BOUND);
|
|
4584
|
+
return random;
|
|
4585
|
+
};
|
|
4586
|
+
|
|
4587
|
+
const getTrafficRandom = (profile, experience) => getRandom(`traffic-${experience.id}-${profile.id}`);
|
|
4588
|
+
const getDistributionRandom = (profile, experience) => getRandom(`distribution-${experience.id}-${profile.id}`);
|
|
4589
|
+
|
|
4590
|
+
const getTrafficAllocation = experience => {
|
|
4591
|
+
if (experience.type === 'nt_personalization') {
|
|
4592
|
+
return 1 - experience.trafficAllocation;
|
|
4593
|
+
}
|
|
4594
|
+
|
|
4595
|
+
return experience.trafficAllocation;
|
|
4596
|
+
};
|
|
4597
|
+
|
|
4575
4598
|
const selectExperience = ({
|
|
4576
4599
|
experiences,
|
|
4577
4600
|
activeExperiments,
|
|
@@ -4581,11 +4604,13 @@ const selectExperience = ({
|
|
|
4581
4604
|
experiences,
|
|
4582
4605
|
activeExperiments
|
|
4583
4606
|
});
|
|
4584
|
-
const selectedExperience = eglibleExperiences.find(experience =>
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4607
|
+
const selectedExperience = eglibleExperiences.find(experience => {
|
|
4608
|
+
const trafficRandom = getTrafficRandom(profile, experience);
|
|
4609
|
+
return getTrafficAllocation(experience) > trafficRandom && (includes(profile.audiences, experience.audience.id) || // if the expriment is active already then it's selectible without further contraints to be fullfilled
|
|
4610
|
+
find(activeExperiments, {
|
|
4611
|
+
id: experience.id
|
|
4612
|
+
}));
|
|
4613
|
+
});
|
|
4589
4614
|
return selectedExperience;
|
|
4590
4615
|
};
|
|
4591
4616
|
|
|
@@ -4598,20 +4623,19 @@ const selectVariant = ({
|
|
|
4598
4623
|
|
|
4599
4624
|
if (!variants.length) {
|
|
4600
4625
|
return null;
|
|
4601
|
-
}
|
|
4602
|
-
|
|
4626
|
+
}
|
|
4603
4627
|
|
|
4604
4628
|
if (experience.type === 'nt_personalization') {
|
|
4605
|
-
// TODO check holdout
|
|
4606
4629
|
// Personalization Expriences can have only one variant.
|
|
4607
4630
|
return variants[0];
|
|
4608
|
-
}
|
|
4631
|
+
}
|
|
4609
4632
|
|
|
4633
|
+
const distributionRandom = getDistributionRandom(profile, experience); // Experiment
|
|
4610
4634
|
|
|
4611
4635
|
const distribution = find(experience.distribution, ({
|
|
4612
4636
|
start,
|
|
4613
4637
|
end
|
|
4614
|
-
}) =>
|
|
4638
|
+
}) => distributionRandom > start && distributionRandom < end);
|
|
4615
4639
|
|
|
4616
4640
|
if (!distribution) {
|
|
4617
4641
|
return null;
|
package/index.umd.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('lodash/get'), require('lodash/unionBy'), require('@ninetailed/experience.js-shared'), require('analytics'), require('lodash/flatten'), require('lodash/find'), require('lodash/includes'), require('lodash/pickBy')) :
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports', 'lodash/get', 'lodash/unionBy', '@ninetailed/experience.js-shared', 'analytics', 'lodash/flatten', 'lodash/find', 'lodash/includes', 'lodash/pickBy'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Javascript = {}, global.get$2, global.unionBy, global.experience_jsShared, global.Analytics, global.flatten, global.find, global.includes, global.pickBy));
|
|
5
|
-
})(this, (function (exports, get$2, unionBy, experience_jsShared, Analytics, flatten, find, includes, pickBy) { 'use strict';
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('lodash/get'), require('lodash/unionBy'), require('@ninetailed/experience.js-shared'), require('analytics'), require('lodash/flatten'), require('lodash/find'), require('lodash/includes'), require('lodash/pickBy'), require('murmurhash-js')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', 'lodash/get', 'lodash/unionBy', '@ninetailed/experience.js-shared', 'analytics', 'lodash/flatten', 'lodash/find', 'lodash/includes', 'lodash/pickBy', 'murmurhash-js'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Javascript = {}, global.get$2, global.unionBy, global.experience_jsShared, global.Analytics, global.flatten, global.find, global.includes, global.pickBy, global.murmurhashJs));
|
|
5
|
+
})(this, (function (exports, get$2, unionBy, experience_jsShared, Analytics, flatten, find, includes, pickBy, murmurhashJs) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
8
|
|
|
@@ -890,14 +890,14 @@
|
|
|
890
890
|
var replacement = /#|\.prototype\./;
|
|
891
891
|
|
|
892
892
|
var isForced$2 = function (feature, detection) {
|
|
893
|
-
var value = data[normalize(feature)];
|
|
893
|
+
var value = data[normalize$1(feature)];
|
|
894
894
|
return value == POLYFILL ? true
|
|
895
895
|
: value == NATIVE ? false
|
|
896
896
|
: isCallable$7(detection) ? fails$8(detection)
|
|
897
897
|
: !!detection;
|
|
898
898
|
};
|
|
899
899
|
|
|
900
|
-
var normalize = isForced$2.normalize = function (string) {
|
|
900
|
+
var normalize$1 = isForced$2.normalize = function (string) {
|
|
901
901
|
return String(string).replace(replacement, '.').toLowerCase();
|
|
902
902
|
};
|
|
903
903
|
|
|
@@ -4478,6 +4478,34 @@
|
|
|
4478
4478
|
});
|
|
4479
4479
|
};
|
|
4480
4480
|
|
|
4481
|
+
var LOWER_BOUND = 0;
|
|
4482
|
+
var UPPER_BOUND = 4294967295;
|
|
4483
|
+
|
|
4484
|
+
var normalize = function normalize(val, min, max) {
|
|
4485
|
+
return (val - min) / (max - min);
|
|
4486
|
+
};
|
|
4487
|
+
|
|
4488
|
+
var getRandom = function getRandom(text) {
|
|
4489
|
+
var hash = murmurhashJs.murmur3(text, 0);
|
|
4490
|
+
var random = normalize(hash, LOWER_BOUND, UPPER_BOUND);
|
|
4491
|
+
return random;
|
|
4492
|
+
};
|
|
4493
|
+
|
|
4494
|
+
var getTrafficRandom = function getTrafficRandom(profile, experience) {
|
|
4495
|
+
return getRandom("traffic-".concat(experience.id, "-").concat(profile.id));
|
|
4496
|
+
};
|
|
4497
|
+
var getDistributionRandom = function getDistributionRandom(profile, experience) {
|
|
4498
|
+
return getRandom("distribution-".concat(experience.id, "-").concat(profile.id));
|
|
4499
|
+
};
|
|
4500
|
+
|
|
4501
|
+
var getTrafficAllocation = function getTrafficAllocation(experience) {
|
|
4502
|
+
if (experience.type === 'nt_personalization') {
|
|
4503
|
+
return 1 - experience.trafficAllocation;
|
|
4504
|
+
}
|
|
4505
|
+
|
|
4506
|
+
return experience.trafficAllocation;
|
|
4507
|
+
};
|
|
4508
|
+
|
|
4481
4509
|
var selectExperience = function selectExperience(_a) {
|
|
4482
4510
|
var experiences = _a.experiences,
|
|
4483
4511
|
activeExperiments = _a.activeExperiments,
|
|
@@ -4487,11 +4515,11 @@
|
|
|
4487
4515
|
activeExperiments: activeExperiments
|
|
4488
4516
|
});
|
|
4489
4517
|
var selectedExperience = eglibleExperiences.find(function (experience) {
|
|
4490
|
-
|
|
4491
|
-
return includes__default["default"](profile.audiences, experience.audience.id) || // if the expriment is active already then it's selectible without further contraints to be fullfilled
|
|
4518
|
+
var trafficRandom = getTrafficRandom(profile, experience);
|
|
4519
|
+
return getTrafficAllocation(experience) > trafficRandom && (includes__default["default"](profile.audiences, experience.audience.id) || // if the expriment is active already then it's selectible without further contraints to be fullfilled
|
|
4492
4520
|
find__default["default"](activeExperiments, {
|
|
4493
4521
|
id: experience.id
|
|
4494
|
-
});
|
|
4522
|
+
}));
|
|
4495
4523
|
});
|
|
4496
4524
|
return selectedExperience;
|
|
4497
4525
|
};
|
|
@@ -4504,20 +4532,19 @@
|
|
|
4504
4532
|
|
|
4505
4533
|
if (!variants.length) {
|
|
4506
4534
|
return null;
|
|
4507
|
-
}
|
|
4508
|
-
|
|
4535
|
+
}
|
|
4509
4536
|
|
|
4510
4537
|
if (experience.type === 'nt_personalization') {
|
|
4511
|
-
// TODO check holdout
|
|
4512
4538
|
// Personalization Expriences can have only one variant.
|
|
4513
4539
|
return variants[0];
|
|
4514
|
-
}
|
|
4540
|
+
}
|
|
4515
4541
|
|
|
4542
|
+
var distributionRandom = getDistributionRandom(profile, experience); // Experiment
|
|
4516
4543
|
|
|
4517
4544
|
var distribution = find__default["default"](experience.distribution, function (_a) {
|
|
4518
4545
|
var start = _a.start,
|
|
4519
4546
|
end = _a.end;
|
|
4520
|
-
return
|
|
4547
|
+
return distributionRandom > start && distributionRandom < end;
|
|
4521
4548
|
});
|
|
4522
4549
|
|
|
4523
4550
|
if (!distribution) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Profile } from '@ninetailed/experience.js-shared';
|
|
2
|
+
import { ExperienceConfiguration } from './types';
|
|
3
|
+
export declare const getTrafficRandom: (profile: Profile, experience: ExperienceConfiguration) => number;
|
|
4
|
+
export declare const getDistributionRandom: (profile: Profile, experience: ExperienceConfiguration) => number;
|
package/package.json
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ninetailed/experience.js",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.9",
|
|
4
4
|
"main": "./index.umd.js",
|
|
5
5
|
"module": "./index.esm.js",
|
|
6
6
|
"typings": "./index.d.ts",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"analytics": "^0.8.0",
|
|
9
|
-
"@ninetailed/experience.js-shared": "2.0.0-beta.
|
|
9
|
+
"@ninetailed/experience.js-shared": "2.0.0-beta.9",
|
|
10
10
|
"uuid": "^8.3.2",
|
|
11
11
|
"ts-toolbelt": "^9.6.0",
|
|
12
12
|
"locale-enum": "^1.1.1",
|
|
13
13
|
"i18n-iso-countries": "^7.3.0",
|
|
14
|
-
"lodash": "^4.17.21"
|
|
14
|
+
"lodash": "^4.17.21",
|
|
15
|
+
"murmurhash-js": "^1.0.0"
|
|
15
16
|
},
|
|
16
17
|
"peerDependencies": {}
|
|
17
18
|
}
|