@featurevisor/sdk 1.35.2 → 2.0.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 +8 -0
- package/README.md +2 -381
- package/coverage/clover.xml +707 -643
- package/coverage/coverage-final.json +11 -9
- package/coverage/lcov-report/{segments.ts.html → bucketer.ts.html} +155 -77
- package/coverage/lcov-report/child.ts.html +940 -0
- package/coverage/lcov-report/conditions.ts.html +107 -158
- package/coverage/lcov-report/datafileReader.ts.html +763 -103
- package/coverage/lcov-report/emitter.ts.html +77 -59
- package/coverage/lcov-report/evaluate.ts.html +689 -416
- package/coverage/lcov-report/events.ts.html +334 -0
- package/coverage/lcov-report/helpers.ts.html +184 -0
- package/coverage/lcov-report/{feature.ts.html → hooks.ts.html} +90 -237
- package/coverage/lcov-report/index.html +119 -89
- package/coverage/lcov-report/instance.ts.html +341 -773
- package/coverage/lcov-report/logger.ts.html +64 -64
- package/coverage/lcov.info +1433 -1223
- package/dist/bucketer.d.ts +11 -0
- package/dist/child.d.ts +26 -0
- package/dist/compareVersions.d.ts +4 -0
- package/dist/conditions.d.ts +4 -4
- package/dist/datafileReader.d.ts +26 -6
- package/dist/emitter.d.ts +8 -9
- package/dist/evaluate.d.ts +31 -29
- package/dist/events.d.ts +5 -0
- package/dist/helpers.d.ts +5 -0
- package/dist/hooks.d.ts +45 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.gz +0 -0
- package/dist/index.mjs.map +1 -1
- package/dist/instance.d.ts +40 -72
- package/dist/logger.d.ts +6 -5
- package/dist/murmurhash.d.ts +1 -0
- package/jest.config.js +2 -0
- package/lib/bucketer.d.ts +11 -0
- package/lib/child.d.ts +26 -0
- package/lib/compareVersions.d.ts +4 -0
- package/lib/conditions.d.ts +4 -4
- package/lib/datafileReader.d.ts +26 -6
- package/lib/emitter.d.ts +8 -9
- package/lib/evaluate.d.ts +31 -29
- package/lib/events.d.ts +5 -0
- package/lib/helpers.d.ts +5 -0
- package/lib/hooks.d.ts +45 -0
- package/lib/index.d.ts +3 -2
- package/lib/instance.d.ts +40 -72
- package/lib/logger.d.ts +6 -5
- package/lib/murmurhash.d.ts +1 -0
- package/package.json +3 -5
- package/src/bucketer.spec.ts +165 -0
- package/src/bucketer.ts +84 -0
- package/src/child.spec.ts +267 -0
- package/src/child.ts +285 -0
- package/src/compareVersions.ts +93 -0
- package/src/conditions.spec.ts +563 -353
- package/src/conditions.ts +46 -63
- package/src/datafileReader.spec.ts +396 -84
- package/src/datafileReader.ts +280 -60
- package/src/emitter.spec.ts +27 -86
- package/src/emitter.ts +38 -32
- package/src/evaluate.ts +349 -258
- package/src/events.spec.ts +154 -0
- package/src/events.ts +83 -0
- package/src/helpers.ts +33 -0
- package/src/hooks.ts +88 -0
- package/src/index.ts +3 -2
- package/src/instance.spec.ts +305 -489
- package/src/instance.ts +247 -391
- package/src/logger.spec.ts +212 -134
- package/src/logger.ts +36 -36
- package/src/murmurhash.ts +71 -0
- package/coverage/lcov-report/bucket.ts.html +0 -502
- package/dist/bucket.d.ts +0 -30
- package/dist/feature.d.ts +0 -16
- package/dist/segments.d.ts +0 -5
- package/lib/bucket.d.ts +0 -30
- package/lib/feature.d.ts +0 -16
- package/lib/segments.d.ts +0 -5
- package/src/bucket.spec.ts +0 -37
- package/src/bucket.ts +0 -139
- package/src/feature.ts +0 -137
- package/src/segments.spec.ts +0 -468
- package/src/segments.ts +0 -58
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e={784:e=>{!function(){const t=e=>(new TextEncoder).encode(e);function r(e,r){let a,i,n,s,o,u,l,c;for("string"==typeof e&&(e=t(e)),a=3&e.length,i=e.length-a,n=r,o=3432918353,u=461845907,c=0;c<i;)l=255&e[c]|(255&e[++c])<<8|(255&e[++c])<<16|(255&e[++c])<<24,++c,l=(65535&l)*o+(((l>>>16)*o&65535)<<16)&4294967295,l=l<<15|l>>>17,l=(65535&l)*u+(((l>>>16)*u&65535)<<16)&4294967295,n^=l,n=n<<13|n>>>19,s=5*(65535&n)+((5*(n>>>16)&65535)<<16)&4294967295,n=27492+(65535&s)+((58964+(s>>>16)&65535)<<16);switch(l=0,a){case 3:l^=(255&e[c+2])<<16;case 2:l^=(255&e[c+1])<<8;case 1:l^=255&e[c],l=(65535&l)*o+(((l>>>16)*o&65535)<<16)&4294967295,l=l<<15|l>>>17,l=(65535&l)*u+(((l>>>16)*u&65535)<<16)&4294967295,n^=l}return n^=e.length,n^=n>>>16,n=2246822507*(65535&n)+((2246822507*(n>>>16)&65535)<<16)&4294967295,n^=n>>>13,n=3266489909*(65535&n)+((3266489909*(n>>>16)&65535)<<16)&4294967295,n^=n>>>16,n>>>0}const a=r;a.v2=function(e,r){"string"==typeof e&&(e=t(e));let a,i=e.length,n=r^i,s=0;for(;i>=4;)a=255&e[s]|(255&e[++s])<<8|(255&e[++s])<<16|(255&e[++s])<<24,a=1540483477*(65535&a)+((1540483477*(a>>>16)&65535)<<16),a^=a>>>24,a=1540483477*(65535&a)+((1540483477*(a>>>16)&65535)<<16),n=1540483477*(65535&n)+((1540483477*(n>>>16)&65535)<<16)^a,i-=4,++s;switch(i){case 3:n^=(255&e[s+2])<<16;case 2:n^=(255&e[s+1])<<8;case 1:n^=255&e[s],n=1540483477*(65535&n)+((1540483477*(n>>>16)&65535)<<16)}return n^=n>>>13,n=1540483477*(65535&n)+((1540483477*(n>>>16)&65535)<<16),n^=n>>>15,n>>>0},a.v3=r,e.exports=a}()}},t={};function r(a){var i=t[a];if(void 0!==i)return i.exports;var n=t[a]={exports:{}};return e[a](n,n.exports,r),n.exports}r.d=(e,t)=>{for(var a in t)r.o(t,a)&&!r.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var a={};r.d(a,{vl:()=>b,f6:()=>S,Jr:()=>T,Vy:()=>y,lb:()=>o,i4:()=>R,mx:()=>I,Q_:()=>w,h:()=>g,K_:()=>h,DU:()=>d,_3:()=>F,bT:()=>c,eG:()=>l,dg:()=>u,Zy:()=>D,xE:()=>f});var i=r(784);const n=1,s=Math.pow(2,32),o=1e5;function u(e){const t=i.v3(e,n)/s;return Math.floor(t*o)}function l(e){const{feature:t,context:r,logger:a,bucketKeySeparator:i=".",configureBucketKey:n}=e,s=t.key;let o,u;if("string"==typeof t.bucketBy)o="plain",u=[t.bucketBy];else if(Array.isArray(t.bucketBy))o="and",u=t.bucketBy;else{if("object"!=typeof t.bucketBy||!Array.isArray(t.bucketBy.or))throw a.error("invalid bucketBy",{featureKey:s,bucketBy:t.bucketBy}),new Error("invalid bucketBy");o="or",u=t.bucketBy.or}const l=[];u.forEach((e=>{const t=r[e];void 0!==t&&("plain"===o||"and"===o||0===l.length)&&l.push(t)})),l.push(s);const c=l.join(i);return n?n(t,r,c):c}function c(e){const{feature:t,context:r,logger:a,bucketKeySeparator:i,configureBucketKey:n,configureBucketValue:s}=e,o=l({feature:t,context:r,logger:a,bucketKeySeparator:i,configureBucketKey:n}),c=u(o);return s?{bucketKey:o,bucketValue:s(t,r,c)}:{bucketKey:o,bucketValue:c}}const f="[Featurevisor]",d=["warn","error"],h=function(e,t,r={}){switch(e){case"debug":console.log(f,t,r);break;case"info":console.info(f,t,r);break;case"warn":console.warn(f,t,r);break;case"error":console.error(f,t,r)}};class y{constructor(e){this.levels=e.levels,this.handle=e.handler}setLevels(e){this.levels=e}log(e,t,r){-1!==this.levels.indexOf(e)&&this.handle(e,t,r)}debug(e,t){this.log("debug",e,t)}info(e,t){this.log("info",e,t)}warn(e,t){this.log("warn",e,t)}error(e,t){this.log("error",e,t)}}function g(e={}){const t=e.levels||d,r=e.handler||h;return new y({levels:t,handler:r})}class v{constructor(e){if(this.schemaVersion=e.schemaVersion,this.revision=e.revision,"2"===this.schemaVersion){const t=e;this.attributes=t.attributes,this.segments=t.segments,this.features=t.features}else{const t=e;this.attributes={},t.attributes.forEach((e=>{this.attributes[e.key]=e})),this.segments={},t.segments.forEach((e=>{this.segments[e.key]=e})),this.features={},t.features.forEach((e=>{Array.isArray(e.variablesSchema)&&(e.variablesSchema=e.variablesSchema.reduce(((e,t)=>(e[t.key]=t,e)),{})),this.features[e.key]=e}))}}getRevision(){return this.revision}getSchemaVersion(){return this.schemaVersion}getAllAttributes(){const e=[];return Object.keys(this.attributes).forEach((t=>{e.push(this.attributes[t])})),e}getAttribute(e){return this.attributes[e]}getSegment(e){const t=this.segments[e];if(t)return function(e,t){if("string"==typeof e[t]&&"*"!==e[t])try{e[t]=JSON.parse(e[t])}catch(e){console.error("Error parsing JSON",e)}return e}(t,"conditions")}getFeature(e){return this.features[e]}}class b{constructor(){this._listeners={}}addListener(e,t){void 0===this._listeners[e]&&(this._listeners[e]=[]),this._listeners[e].push(t)}removeListener(e,t){if(void 0===this._listeners[e])return;const r=this._listeners[e].indexOf(t);-1!==r&&this._listeners[e].splice(r,1)}removeAllListeners(e){e?this._listeners[e]=[]:Object.keys(this._listeners).forEach((e=>{this._listeners[e]=[]}))}emit(e,...t){void 0!==this._listeners[e]&&this._listeners[e].forEach((e=>{e(...t)}))}}const k=(e,t)=>{const r=K(e),a=K(t),i=r.pop(),n=a.pop(),s=E(r,a);return 0!==s?s:i&&n?E(i.split("."),n.split(".")):i||n?i?-1:1:0},p=/^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i,K=e=>{if("string"!=typeof e)throw new TypeError("Invalid argument expected string");const t=e.match(p);if(!t)throw new Error(`Invalid argument not valid semver ('${e}' received)`);return t.shift(),t},m=e=>"*"===e||"x"===e||"X"===e,V=e=>{const t=parseInt(e,10);return isNaN(t)?e:t},A=(e,t)=>{if(m(e)||m(t))return 0;const[r,a]=((e,t)=>typeof e!=typeof t?[String(e),String(t)]:[e,t])(V(e),V(t));return r>a?1:r<a?-1:0},E=(e,t)=>{for(let r=0;r<Math.max(e.length,t.length);r++){const a=A(e[r]||"0",t[r]||"0");if(0!==a)return a}return 0};function I(e,t){const{attribute:r,operator:a,value:i}=e;if("equals"===a)return t[r]===i;if("notEquals"===a)return t[r]!==i;if("before"===a||"after"===a){const e=t[r],n=e instanceof Date?e:new Date(e),s=i instanceof Date?i:new Date(i);return"before"===a?n<s:n>s}if(!Array.isArray(i)||-1===["string","number"].indexOf(typeof t[r])&&null!==t[r]){if("string"==typeof t[r]&&"string"==typeof i){const e=t[r];if("contains"===a)return-1!==e.indexOf(i);if("notContains"===a)return-1===e.indexOf(i);if("startsWith"===a)return e.startsWith(i);if("endsWith"===a)return e.endsWith(i);if("semverEquals"===a)return 0===k(e,i);if("semverNotEquals"===a)return 0!==k(e,i);if("semverGreaterThan"===a)return 1===k(e,i);if("semverGreaterThanOrEquals"===a)return k(e,i)>=0;if("semverLessThan"===a)return-1===k(e,i);if("semverLessThanOrEquals"===a)return k(e,i)<=0}else if("number"==typeof t[r]&&"number"==typeof i){const e=t[r];if("greaterThan"===a)return e>i;if("greaterThanOrEquals"===a)return e>=i;if("lessThan"===a)return e<i;if("lessThanOrEquals"===a)return e<=i}}else{const e=t[r];if("in"===a)return-1!==i.indexOf(e);if("notIn"===a)return-1===i.indexOf(e)}return!1}function R(e,t,r){if("attribute"in e)try{return I(e,t)}catch(a){return r.warn(a.message,{error:a,details:{condition:e,context:t}}),!1}return"and"in e&&Array.isArray(e.and)?e.and.every((e=>R(e,t,r))):"or"in e&&Array.isArray(e.or)?e.or.some((e=>R(e,t,r))):"not"in e&&Array.isArray(e.not)?e.not.every((()=>!1===R({and:e.not},t,r))):!!Array.isArray(e)&&e.every((e=>R(e,t,r)))}function x(e,t,r,a){if("*"===e)return!0;if("string"==typeof e){const i=r.getSegment(e);return!!i&&function(e,t,r){return R(e.conditions,t,r)}(i,t,a)}if("object"==typeof e){if("and"in e&&Array.isArray(e.and))return e.and.every((e=>x(e,t,r,a)));if("or"in e&&Array.isArray(e.or))return e.or.some((e=>x(e,t,r,a)));if("not"in e&&Array.isArray(e.not))return e.not.every((e=>!1===x(e,t,r,a)))}return!!Array.isArray(e)&&e.every((e=>x(e,t,r,a)))}function O(e){return"string"==typeof e&&(e.startsWith("{")||e.startsWith("["))?JSON.parse(e):e}var S;function F(e){let t;const{type:r,featureKey:a,variableKey:i,context:n,logger:s,datafileReader:o,statuses:u,stickyFeatures:l,initialFeatures:f,interceptContext:d,bucketKeySeparator:h,configureBucketKey:y,configureBucketValue:g}=e;try{const e="string"==typeof a?a:a.key;let v;if("flag"!==r&&(v=F({type:"flag",featureKey:e,context:n,logger:s,datafileReader:o,statuses:u,stickyFeatures:l,initialFeatures:f,bucketKeySeparator:h,configureBucketKey:y,configureBucketValue:g}),!1===v.enabled))return t={featureKey:e,reason:S.DISABLED},s.debug("feature is disabled",t),t;if(l&&l[e]){if("flag"===r&&void 0!==l[e].enabled)return t={featureKey:e,reason:S.STICKY,sticky:l[e],enabled:l[e].enabled},s.debug("using sticky enabled",t),t;if("variation"===r){const r=l[e].variation;if(void 0!==r)return t={featureKey:e,reason:S.STICKY,variationValue:r},s.debug("using sticky variation",t),t}if(i){const r=l[e].variables;if(r){const a=r[i];if(void 0!==a)return t={featureKey:e,reason:S.STICKY,variableKey:i,variableValue:a},s.debug("using sticky variable",t),t}}}if(u&&!u.ready&&f&&f[e]){if("flag"===r&&void 0!==f[e].enabled)return t={featureKey:e,reason:S.INITIAL,initial:f[e],enabled:f[e].enabled},s.debug("using initial enabled",t),t;if("variation"===r&&void 0!==f[e].variation){const r=f[e].variation;return t={featureKey:e,reason:S.INITIAL,variationValue:r},s.debug("using initial variation",t),t}if(i){const r=f[e].variables;if(r&&void 0!==r[i])return t={featureKey:e,reason:S.INITIAL,variableKey:i,variableValue:r[i]},s.debug("using initial variable",t),t}}const b="string"==typeof a?o.getFeature(a):a;if(!b)return t={featureKey:e,reason:S.NOT_FOUND},s.warn("feature not found",t),t;let k;if("flag"===r&&b.deprecated&&s.warn("feature is deprecated",{featureKey:b.key}),i){if(b.variablesSchema&&b.variablesSchema[i]&&(k=b.variablesSchema[i]),!k)return t={featureKey:e,reason:S.NOT_FOUND,variableKey:i},s.warn("variable schema not found",t),t;k.deprecated&&s.warn("variable is deprecated",{featureKey:b.key,variableKey:i})}if("variation"===r&&(!b.variations||0===b.variations.length))return t={featureKey:e,reason:S.NO_VARIATIONS},s.warn("no variations",t),t;const p=d?d(n):n,{force:K,forceIndex:m}=function(e,t,r,a){const i={force:void 0,forceIndex:void 0};if(!e.force)return i;for(let n=0;n<e.force.length;n++){const s=e.force[n];if(s.conditions&&R(s.conditions,t,a)){i.force=s,i.forceIndex=n;break}if(s.segments&&x(s.segments,t,r,a)){i.force=s,i.forceIndex=n;break}}return i}(b,n,o,s);if(K){if("flag"===r&&void 0!==K.enabled)return t={featureKey:b.key,reason:S.FORCED,forceIndex:m,force:K,enabled:K.enabled},s.debug("forced enabled found",t),t;if("variation"===r&&K.variation&&b.variations){const e=b.variations.find((e=>e.value===K.variation));if(e)return t={featureKey:b.key,reason:S.FORCED,forceIndex:m,force:K,variation:e},s.debug("forced variation found",t),t}if(i&&K.variables&&void 0!==K.variables[i])return t={featureKey:b.key,reason:S.FORCED,forceIndex:m,force:K,variableKey:i,variableSchema:k,variableValue:K.variables[i]},s.debug("forced variable",t),t}if("flag"===r&&b.required&&b.required.length>0){const e=b.required.every((e=>{let t,r;if("string"==typeof e?t=e:(t=e.key,r=e.variation),!F({type:"flag",featureKey:t,context:p,logger:s,datafileReader:o,statuses:u,stickyFeatures:l,initialFeatures:f,bucketKeySeparator:h,configureBucketKey:y,configureBucketValue:g}).enabled)return!1;if(void 0!==r){const e=F({type:"variation",featureKey:t,context:p,logger:s,datafileReader:o,statuses:u,stickyFeatures:l,initialFeatures:f,bucketKeySeparator:h,configureBucketKey:y,configureBucketValue:g});let a;return e.variationValue?a=e.variationValue:e.variation&&(a=e.variation.value),a===r}return!0}));if(!e)return t={featureKey:b.key,reason:S.REQUIRED,required:b.required,enabled:e},s.debug("required features not enabled",t),t}const{bucketKey:V,bucketValue:A}=c({feature:b,context:p,logger:s,bucketKeySeparator:h,configureBucketKey:y,configureBucketValue:g});let E,I;if("flag"!==r){const e=function(e,t,r,a,i){const n=e.find((e=>x(O(e.segments),t,a,i)));if(!n)return{matchedTraffic:void 0,matchedAllocation:void 0};const s=function(e,t){for(const r of e.allocation){const[e,a]=r.range;if(r.range&&e<=t&&a>=t)return r}}(n,r);return{matchedTraffic:n,matchedAllocation:s}}(b.traffic,p,A,o,s);E=e.matchedTraffic,I=e.matchedAllocation}else E=function(e,t,r,a){const i=e.find((e=>!!x(O(e.segments),t,r,a)));if(i&&i.percentage>0)return i}(b.traffic,p,o,s);if(E){if("flag"===r){if(b.ranges&&b.ranges.length>0)return b.ranges.find((e=>A>=e[0]&&A<e[1]))?(t={featureKey:b.key,reason:S.ALLOCATED,bucketKey:V,bucketValue:A,ruleKey:E.key,traffic:E,enabled:void 0===E.enabled||E.enabled},s.debug("matched",t),t):(t={featureKey:b.key,reason:S.OUT_OF_RANGE,bucketKey:V,bucketValue:A,enabled:!1},s.debug("not matched",t),t);if(void 0!==E.enabled)return t={featureKey:b.key,reason:S.OVERRIDE,bucketKey:V,bucketValue:A,ruleKey:E.key,traffic:E,enabled:E.enabled},s.debug("override from rule",t),t;if(A<=E.percentage)return t={featureKey:b.key,reason:S.RULE,bucketKey:V,bucketValue:A,ruleKey:E.key,traffic:E,enabled:!0},s.debug("matched traffic",t),t}if("variation"===r&&b.variations){if(E.variation){const e=b.variations.find((e=>e.value===E.variation));if(e)return t={featureKey:b.key,reason:S.RULE,bucketKey:V,bucketValue:A,ruleKey:E.key,traffic:E,variation:e},s.debug("override from rule",t),t}if(I&&I.variation){const e=b.variations.find((e=>e.value===I.variation));if(e)return t={featureKey:b.key,reason:S.ALLOCATED,bucketKey:V,bucketValue:A,ruleKey:E.key,traffic:E,variation:e},s.debug("allocated variation",t),t}}}if("variable"===r&&i){if(E&&E.variables&&void 0!==E.variables[i])return t={featureKey:b.key,reason:S.RULE,bucketKey:V,bucketValue:A,ruleKey:E.key,traffic:E,variableKey:i,variableSchema:k,variableValue:E.variables[i]},s.debug("override from rule",t),t;let e;if(K&&K.variation?e=K.variation:E&&E.variation?e=E.variation:I&&I.variation&&(e=I.variation),e&&Array.isArray(b.variations)){const r=b.variations.find((t=>t.value===e));if(r&&r.variables){const e=r.variables.find((e=>e.key===i));if(e){if(e.overrides){const r=e.overrides.find((e=>e.conditions?R("string"==typeof e.conditions?JSON.parse(e.conditions):e.conditions,p,s):!!e.segments&&x(O(e.segments),p,o,s)));if(r)return t={featureKey:b.key,reason:S.OVERRIDE,bucketKey:V,bucketValue:A,ruleKey:null==E?void 0:E.key,traffic:E,variableKey:i,variableSchema:k,variableValue:r.value},s.debug("variable override",t),t}if(void 0!==e.value)return t={featureKey:b.key,reason:S.ALLOCATED,bucketKey:V,bucketValue:A,ruleKey:null==E?void 0:E.key,traffic:E,variableKey:i,variableSchema:k,variableValue:e.value},s.debug("allocated variable",t),t}}}}return"variation"===r?(t={featureKey:b.key,reason:S.NO_MATCH,bucketKey:V,bucketValue:A},s.debug("no matched variation",t),t):"variable"===r&&k?(t={featureKey:b.key,reason:S.DEFAULTED,bucketKey:V,bucketValue:A,variableKey:i,variableSchema:k,variableValue:k.defaultValue},s.debug("using default value",t),t):(t={featureKey:b.key,reason:S.NO_MATCH,bucketKey:V,bucketValue:A,enabled:!1},s.debug("nothing matched",t),t)}catch(e){return t={featureKey:"string"==typeof a?a:a.key,reason:S.ERROR,error:e},s.error("error",t),t}}Object.keys({">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1]}),function(e){e.NOT_FOUND="not_found",e.NO_VARIATIONS="no_variations",e.NO_MATCH="no_match",e.DISABLED="disabled",e.REQUIRED="required",e.OUT_OF_RANGE="out_of_range",e.FORCED="forced",e.INITIAL="initial",e.STICKY="sticky",e.RULE="rule",e.ALLOCATED="allocated",e.DEFAULTED="defaulted",e.OVERRIDE="override",e.ERROR="error"}(S||(S={}));const B={schemaVersion:"1",revision:"unknown",attributes:[],segments:[],features:[]};function L(e,t){return t?t(e):fetch(e).then((e=>e.json()))}function D(e,t){try{if(void 0===e)return;switch(t){case"string":return"string"==typeof e?e:void 0;case"integer":return parseInt(e,10);case"double":return parseFloat(e);case"boolean":return!0===e;case"array":return Array.isArray(e)?e:void 0;case"object":return"object"==typeof e?e:void 0;default:return e}}catch(e){return}}class T{constructor(e){this.bucketKeySeparator=e.bucketKeySeparator||".",this.configureBucketKey=e.configureBucketKey,this.configureBucketValue=e.configureBucketValue,this.datafileUrl=e.datafileUrl,this.handleDatafileFetch=e.handleDatafileFetch,this.initialFeatures=e.initialFeatures,this.interceptContext=e.interceptContext,this.logger=e.logger||g(),this.refreshInterval=e.refreshInterval,this.stickyFeatures=e.stickyFeatures,this.emitter=new b,this.statuses={ready:!1,refreshInProgress:!1},e.onReady&&this.emitter.addListener("ready",e.onReady),e.onRefresh&&this.emitter.addListener("refresh",e.onRefresh),e.onUpdate&&this.emitter.addListener("update",e.onUpdate),e.onActivation&&this.emitter.addListener("activation",e.onActivation);const t=this.emitter.addListener.bind(this.emitter);this.on=t,this.addListener=t;const r=this.emitter.removeListener.bind(this.emitter);if(this.off=r,this.removeListener=r,this.removeAllListeners=this.emitter.removeAllListeners.bind(this.emitter),e.datafileUrl)this.setDatafile(e.datafile||B),L(e.datafileUrl,e.handleDatafileFetch).then((e=>{this.setDatafile(e),this.statuses.ready=!0,this.emitter.emit("ready"),this.refreshInterval&&this.startRefreshing()})).catch((e=>{this.logger.error("failed to fetch datafile",{error:e})}));else{if(!e.datafile)throw new Error("Featurevisor SDK instance cannot be created without both `datafile` and `datafileUrl` options");this.setDatafile(e.datafile),this.statuses.ready=!0,setTimeout((()=>{this.emitter.emit("ready")}),0)}}setLogLevels(e){this.logger.setLevels(e)}onReady(){return new Promise((e=>{if(this.statuses.ready)return e(this);const t=()=>{this.emitter.removeListener("ready",t),e(this)};this.emitter.addListener("ready",t)}))}setDatafile(e){try{this.datafileReader=new v("string"==typeof e?JSON.parse(e):e)}catch(e){this.logger.error("could not parse datafile",{error:e})}}setStickyFeatures(e){this.stickyFeatures=e}getRevision(){return this.datafileReader.getRevision()}getFeature(e){return"string"==typeof e?this.datafileReader.getFeature(e):e}isReady(){return this.statuses.ready}refresh(){return this.logger.debug("refreshing datafile"),this.statuses.refreshInProgress?this.logger.warn("refresh in progress, skipping"):this.datafileUrl?(this.statuses.refreshInProgress=!0,void L(this.datafileUrl,this.handleDatafileFetch).then((e=>{const t=this.getRevision()!==e.revision;this.setDatafile(e),this.logger.info("refreshed datafile"),this.emitter.emit("refresh"),t&&this.emitter.emit("update"),this.statuses.refreshInProgress=!1})).catch((e=>{this.logger.error("failed to refresh datafile",{error:e}),this.statuses.refreshInProgress=!1}))):this.logger.error("cannot refresh since `datafileUrl` is not provided")}startRefreshing(){return this.datafileUrl?this.intervalId?this.logger.warn("refreshing has already started"):this.refreshInterval?void(this.intervalId=setInterval((()=>{this.refresh()}),1e3*this.refreshInterval)):this.logger.warn("no `refreshInterval` option provided"):this.logger.error("cannot start refreshing since `datafileUrl` is not provided")}stopRefreshing(){if(!this.intervalId)return this.logger.warn("refreshing has not started yet");clearInterval(this.intervalId)}evaluateFlag(e,t={}){return F({type:"flag",featureKey:e,context:t,logger:this.logger,datafileReader:this.datafileReader,statuses:this.statuses,interceptContext:this.interceptContext,stickyFeatures:this.stickyFeatures,initialFeatures:this.initialFeatures,bucketKeySeparator:this.bucketKeySeparator,configureBucketKey:this.configureBucketKey,configureBucketValue:this.configureBucketValue})}isEnabled(e,t={}){try{return!0===this.evaluateFlag(e,t).enabled}catch(t){return this.logger.error("isEnabled",{featureKey:e,error:t}),!1}}evaluateVariation(e,t={}){return F({type:"variation",featureKey:e,context:t,logger:this.logger,datafileReader:this.datafileReader,statuses:this.statuses,interceptContext:this.interceptContext,stickyFeatures:this.stickyFeatures,initialFeatures:this.initialFeatures,bucketKeySeparator:this.bucketKeySeparator,configureBucketKey:this.configureBucketKey,configureBucketValue:this.configureBucketValue})}getVariation(e,t={}){try{const r=this.evaluateVariation(e,t);return void 0!==r.variationValue?r.variationValue:r.variation?r.variation.value:void 0}catch(t){return void this.logger.error("getVariation",{featureKey:e,error:t})}}activate(e,t={}){try{const r=this.evaluateVariation(e,t),a=r.variation?r.variation.value:r.variationValue;if(void 0===a)return;const i=this.interceptContext?this.interceptContext(t):t,n={};return this.datafileReader.getAllAttributes().filter((e=>!0===e.capture)).forEach((e=>{void 0!==i[e.key]&&(n[e.key]=t[e.key])})),this.emitter.emit("activation",e,a,i,n,r),a}catch(t){return void this.logger.error("activate",{featureKey:e,error:t})}}evaluateVariable(e,t,r={}){return F({type:"variable",featureKey:e,variableKey:t,context:r,logger:this.logger,datafileReader:this.datafileReader,statuses:this.statuses,interceptContext:this.interceptContext,stickyFeatures:this.stickyFeatures,initialFeatures:this.initialFeatures,bucketKeySeparator:this.bucketKeySeparator,configureBucketKey:this.configureBucketKey,configureBucketValue:this.configureBucketValue})}getVariable(e,t,r={}){try{const a=this.evaluateVariable(e,t,r);return void 0!==a.variableValue?a.variableSchema&&"json"===a.variableSchema.type&&"string"==typeof a.variableValue?JSON.parse(a.variableValue):a.variableValue:void 0}catch(r){return void this.logger.error("getVariable",{featureKey:e,variableKey:t,error:r})}}getVariableBoolean(e,t,r={}){return D(this.getVariable(e,t,r),"boolean")}getVariableString(e,t,r={}){return D(this.getVariable(e,t,r),"string")}getVariableInteger(e,t,r={}){return D(this.getVariable(e,t,r),"integer")}getVariableDouble(e,t,r={}){return D(this.getVariable(e,t,r),"double")}getVariableArray(e,t,r={}){return D(this.getVariable(e,t,r),"array")}getVariableObject(e,t,r={}){return D(this.getVariable(e,t,r),"object")}getVariableJSON(e,t,r={}){return D(this.getVariable(e,t,r),"json")}}function w(e){return new T(e)}var _=a.vl,N=a.f6,C=a.Jr,U=a.Vy,j=a.lb,q=a.i4,M=a.mx,J=a.Q_,P=a.h,G=a.K_,W=a.DU,z=a._3,H=a.bT,Q=a.eG,Y=a.dg,X=a.Zy,Z=a.xE;export{_ as Emitter,N as EvaluationReason,C as FeaturevisorInstance,U as Logger,j as MAX_BUCKETED_NUMBER,q as allConditionsAreMatched,M as conditionIsMatched,J as createInstance,P as createLogger,G as defaultLogHandler,W as defaultLogLevels,z as evaluate,H as getBucket,Q as getBucketKey,Y as getBucketedNumber,X as getValueByType,Z as loggerPrefix};
|
|
1
|
+
var e={d:(t,r)=>{for(var a in r)e.o(r,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:r[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{Il:()=>m,f6:()=>x,ps:()=>S,Jr:()=>D,Vy:()=>k,lb:()=>h,mx:()=>u,Q_:()=>L,h:()=>V,K_:()=>O,_3:()=>j,EM:()=>E,eG:()=>v,dg:()=>b,f:()=>c,xE:()=>p});const r=/^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i,a=e=>{if("string"!=typeof e)throw new TypeError("Invalid argument expected string");const t=e.match(r);if(!t)throw new Error(`Invalid argument not valid semver ('${e}' received)`);return t.shift(),t},i=e=>"*"===e||"x"===e||"X"===e,n=e=>{const t=parseInt(e,10);return isNaN(t)?e:t},s=(e,t)=>{if(i(e)||i(t))return 0;const[r,a]=((e,t)=>typeof e!=typeof t?[String(e),String(t)]:[e,t])(n(e),n(t));return r>a?1:r<a?-1:0},o=(e,t)=>{for(let r=0;r<Math.max(e.length,t.length);r++){const a=s(e[r]||"0",t[r]||"0");if(0!==a)return a}return 0},l=(e,t)=>{const r=a(e),i=a(t),n=r.pop(),s=i.pop(),l=o(r,i);return 0!==l?l:n&&s?o(n.split("."),s.split(".")):n||s?n?-1:1:0};function c(e,t){return-1===t.indexOf(".")?e[t]:t.split(".").reduce(((e,t)=>e?e[t]:void 0),e)}function u(e,t,r){const{attribute:a,operator:i,value:n,regexFlags:s}=e,o=c(t,a);if("equals"===i)return o===n;if("notEquals"===i)return o!==n;if("before"===i||"after"===i){const e=o instanceof Date?o:new Date(o),t=n instanceof Date?n:new Date(n);return"before"===i?e<t:e>t}if(!Array.isArray(n)||-1===["string","number"].indexOf(typeof o)&&null!==o)if("string"==typeof o&&"string"==typeof n){const e=o;if("contains"===i)return-1!==e.indexOf(n);if("notContains"===i)return-1===e.indexOf(n);if("startsWith"===i)return e.startsWith(n);if("endsWith"===i)return e.endsWith(n);if("semverEquals"===i)return 0===l(e,n);if("semverNotEquals"===i)return 0!==l(e,n);if("semverGreaterThan"===i)return 1===l(e,n);if("semverGreaterThanOrEquals"===i)return l(e,n)>=0;if("semverLessThan"===i)return-1===l(e,n);if("semverLessThanOrEquals"===i)return l(e,n)<=0;if("matches"===i)return r(n,s||"").test(e);if("notMatches"===i)return!r(n,s||"").test(e)}else if("number"==typeof o&&"number"==typeof n){if("greaterThan"===i)return o>n;if("greaterThanOrEquals"===i)return o>=n;if("lessThan"===i)return o<n;if("lessThanOrEquals"===i)return o<=n}else{if("exists"===i)return void 0!==o;if("notExists"===i)return void 0===o;if(Array.isArray(o)&&"string"==typeof n){const e=o;if("includes"===i)return e.indexOf(n)>-1;if("notIncludes"===i)return-1===e.indexOf(n)}}else{const e=o;if("in"===i)return-1!==n.indexOf(e);if("notIn"===i)return-1===n.indexOf(e)}return!1}const f=e=>(new TextEncoder).encode(e),g=1,d=Math.pow(2,32),h=1e5;function b(e){const t=function(e,t){let r,a,i,n,s,o,l,c;for("string"==typeof e&&(e=f(e)),r=3&e.length,a=e.length-r,i=t,s=3432918353,o=461845907,c=0;c<a;)l=255&e[c]|(255&e[++c])<<8|(255&e[++c])<<16|(255&e[++c])<<24,++c,l=(65535&l)*s+(((l>>>16)*s&65535)<<16)&4294967295,l=l<<15|l>>>17,l=(65535&l)*o+(((l>>>16)*o&65535)<<16)&4294967295,i^=l,i=i<<13|i>>>19,n=5*(65535&i)+((5*(i>>>16)&65535)<<16)&4294967295,i=27492+(65535&n)+((58964+(n>>>16)&65535)<<16);switch(l=0,r){case 3:l^=(255&e[c+2])<<16;case 2:l^=(255&e[c+1])<<8;case 1:l^=255&e[c],l=(65535&l)*s+(((l>>>16)*s&65535)<<16)&4294967295,l=l<<15|l>>>17,l=(65535&l)*o+(((l>>>16)*o&65535)<<16)&4294967295,i^=l}return i^=e.length,i^=i>>>16,i=2246822507*(65535&i)+((2246822507*(i>>>16)&65535)<<16)&4294967295,i^=i>>>13,i=3266489909*(65535&i)+((3266489909*(i>>>16)&65535)<<16)&4294967295,i^=i>>>16,i>>>0}(e,g)/d;return Math.floor(t*h)}const y=".";function v(e){const{featureKey:t,bucketBy:r,context:a,logger:i}=e;let n,s;if("string"==typeof r)n="plain",s=[r];else if(Array.isArray(r))n="and",s=r;else{if("object"!=typeof r||!Array.isArray(r.or))throw i.error("invalid bucketBy",{featureKey:t,bucketBy:r}),new Error("invalid bucketBy");n="or",s=r.or}const o=[];return s.forEach((e=>{const t=c(a,e);void 0!==t&&("plain"===n||"and"===n||0===o.length)&&o.push(t)})),o.push(t),o.join(y)}const p="[Featurevisor]",O=function(e,t,r={}){let a="log";"info"===e?a="info":"warn"===e?a="warn":"error"===e&&(a="error"),console[a](p,t,r)};class k{constructor(e){this.level=e.level||k.defaultLevel,this.handle=e.handler||O}setLevel(e){this.level=e}log(e,t,r){k.allLevels.indexOf(this.level)>=k.allLevels.indexOf(e)&&this.handle(e,t,r)}debug(e,t){this.log("debug",e,t)}info(e,t){this.log("info",e,t)}warn(e,t){this.log("warn",e,t)}error(e,t){this.log("error",e,t)}}function V(e={}){return new k(e)}k.allLevels=["fatal","error","warn","info","debug"],k.defaultLevel="info";class A{constructor(e){this.hooks=[],this.logger=e.logger,e.hooks&&e.hooks.forEach((e=>{this.add(e)}))}add(e){if(!this.hooks.some((t=>t.name===e.name)))return this.hooks.push(e),()=>{this.remove(e.name)};this.logger.error(`Hook with name "${e.name}" already exists.`,{name:e.name,hook:e})}remove(e){this.hooks=this.hooks.filter((t=>t.name!==e))}getAll(){return this.hooks}}class K{constructor(){this.listeners={}}on(e,t){this.listeners[e]||(this.listeners[e]=[]);const r=this.listeners[e];r.push(t);let a=!0;return function(){if(!a)return;a=!1;const e=r.indexOf(t);-1!==e&&r.splice(e,1)}}trigger(e,t={}){const r=this.listeners[e];r&&r.forEach((function(e){try{e(t)}catch(e){console.error(e)}}))}clearAll(){this.listeners={}}}class m{constructor(e){const{datafile:t,logger:r}=e;this.logger=r,this.schemaVersion=t.schemaVersion,this.revision=t.revision,this.segments=t.segments,this.features=t.features,this.regexCache={}}getRevision(){return this.revision}getSchemaVersion(){return this.schemaVersion}getSegment(e){const t=this.segments[e];if(t)return t.conditions=this.parseConditionsIfStringified(t.conditions),t}getFeatureKeys(){return Object.keys(this.features)}getFeature(e){return this.features[e]}getVariableKeys(e){const t=this.getFeature(e);return t?Object.keys(t.variablesSchema||{}):[]}hasVariations(e){const t=this.getFeature(e);return!!t&&Array.isArray(t.variations)&&t.variations.length>0}getRegex(e,t){const r=t||"",a=`${e}-${r}`;if(this.regexCache[a])return this.regexCache[a];const i=new RegExp(e,r);return this.regexCache[a]=i,i}allConditionsAreMatched(e,t){if("string"==typeof e)return"*"===e;const r=(e,t)=>this.getRegex(e,t);if("attribute"in e)try{return u(e,t,r)}catch(r){return this.logger.warn(r.message,{error:r,details:{condition:e,context:t}}),!1}return"and"in e&&Array.isArray(e.and)?e.and.every((e=>this.allConditionsAreMatched(e,t))):"or"in e&&Array.isArray(e.or)?e.or.some((e=>this.allConditionsAreMatched(e,t))):"not"in e&&Array.isArray(e.not)?e.not.every((()=>!1===this.allConditionsAreMatched({and:e.not},t))):!!Array.isArray(e)&&e.every((e=>this.allConditionsAreMatched(e,t)))}segmentIsMatched(e,t){return this.allConditionsAreMatched(e.conditions,t)}allSegmentsAreMatched(e,t){if("*"===e)return!0;if("string"==typeof e){const r=this.getSegment(e);return!!r&&this.segmentIsMatched(r,t)}if("object"==typeof e){if("and"in e&&Array.isArray(e.and))return e.and.every((e=>this.allSegmentsAreMatched(e,t)));if("or"in e&&Array.isArray(e.or))return e.or.some((e=>this.allSegmentsAreMatched(e,t)));if("not"in e&&Array.isArray(e.not))return e.not.every((e=>!1===this.allSegmentsAreMatched(e,t)))}return!!Array.isArray(e)&&e.every((e=>this.allSegmentsAreMatched(e,t)))}getMatchedTraffic(e,t){return e.find((e=>!!this.allSegmentsAreMatched(this.parseSegmentsIfStringified(e.segments),t)))}getMatchedAllocation(e,t){if(e.allocation)for(const r of e.allocation){const[e,a]=r.range;if(r.range&&e<=t&&a>=t)return r}}getMatchedForce(e,t){const r={force:void 0,forceIndex:void 0},a="string"==typeof e?this.getFeature(e):e;if(!a||!a.force)return r;for(let e=0;e<a.force.length;e++){const i=a.force[e];if(i.conditions&&this.allConditionsAreMatched(this.parseConditionsIfStringified(i.conditions),t)){r.force=i,r.forceIndex=e;break}if(i.segments&&this.allSegmentsAreMatched(this.parseSegmentsIfStringified(i.segments),t)){r.force=i,r.forceIndex=e;break}}return r}parseConditionsIfStringified(e){if("string"!=typeof e)return e;if("*"===e)return e;try{return JSON.parse(e)}catch(t){return this.logger.error("Error parsing conditions",{error:t,details:{conditions:e}}),e}}parseSegmentsIfStringified(e){return"string"==typeof e&&(e.startsWith("{")||e.startsWith("["))?JSON.parse(e):e}}var x;function E(e){try{const{hooksManager:t}=e,r=t.getAll();let a=e;for(const e of t.getAll())e.before&&(a=e.before(a));let i=j(a);void 0!==a.defaultVariationValue&&"variation"===i.type&&void 0===i.variationValue&&(i.variationValue=a.defaultVariationValue),void 0!==a.defaultVariableValue&&"variable"===i.type&&void 0===i.variableValue&&(i.variableValue=a.defaultVariableValue);for(const e of r)e.after&&(i=e.after(i,a));return i}catch(t){const{type:r,featureKey:a,variableKey:i,logger:n}=e,s={type:r,featureKey:a,variableKey:i,reason:x.ERROR,error:t};return n.error("error during evaluation",s),s}}function j(e){const{type:t,featureKey:r,variableKey:a,context:i,logger:n,datafileReader:s,sticky:o,hooksManager:l}=e,c=l.getAll();let u;try{let l;if("flag"!==t&&(l=j(Object.assign(Object.assign({},e),{type:"flag"})),!1===l.enabled)){u={type:t,featureKey:r,reason:x.DISABLED};const e=s.getFeature(r);if("variable"===t&&e&&a&&e.variablesSchema&&e.variablesSchema[a]){const i=e.variablesSchema[a];void 0!==i.disabledValue?u={type:t,featureKey:r,reason:x.VARIABLE_DISABLED,variableKey:a,variableValue:i.disabledValue,variableSchema:i,enabled:!1}:i.useDefaultWhenDisabled&&(u={type:t,featureKey:r,reason:x.VARIABLE_DEFAULT,variableKey:a,variableValue:i.defaultValue,variableSchema:i,enabled:!1})}return"variation"===t&&e&&e.disabledVariationValue&&(u={type:t,featureKey:r,reason:x.VARIATION_DISABLED,variationValue:e.disabledVariationValue,enabled:!1}),n.debug("feature is disabled",u),u}if(o&&o[r]){if("flag"===t&&void 0!==o[r].enabled)return u={type:t,featureKey:r,reason:x.STICKY,sticky:o[r],enabled:o[r].enabled},n.debug("using sticky enabled",u),u;if("variation"===t){const e=o[r].variation;if(void 0!==e)return u={type:t,featureKey:r,reason:x.STICKY,variationValue:e},n.debug("using sticky variation",u),u}if(a){const e=o[r].variables;if(e){const i=e[a];if(void 0!==i)return u={type:t,featureKey:r,reason:x.STICKY,variableKey:a,variableValue:i},n.debug("using sticky variable",u),u}}}const f="string"==typeof r?s.getFeature(r):r;if(!f)return u={type:t,featureKey:r,reason:x.FEATURE_NOT_FOUND},n.warn("feature not found",u),u;let g;if("flag"===t&&f.deprecated&&n.warn("feature is deprecated",{featureKey:r}),a){if(f.variablesSchema&&f.variablesSchema[a]&&(g=f.variablesSchema[a]),!g)return u={type:t,featureKey:r,reason:x.VARIABLE_NOT_FOUND,variableKey:a},n.warn("variable schema not found",u),u;g.deprecated&&n.warn("variable is deprecated",{featureKey:r,variableKey:a})}if("variation"===t&&(!f.variations||0===f.variations.length))return u={type:t,featureKey:r,reason:x.NO_VARIATIONS},n.warn("no variations",u),u;const{force:d,forceIndex:h}=s.getMatchedForce(f,i);if(d){if("flag"===t&&void 0!==d.enabled)return u={type:t,featureKey:r,reason:x.FORCED,forceIndex:h,force:d,enabled:d.enabled},n.debug("forced enabled found",u),u;if("variation"===t&&d.variation&&f.variations){const e=f.variations.find((e=>e.value===d.variation));if(e)return u={type:t,featureKey:r,reason:x.FORCED,forceIndex:h,force:d,variation:e},n.debug("forced variation found",u),u}if(a&&d.variables&&void 0!==d.variables[a])return u={type:t,featureKey:r,reason:x.FORCED,forceIndex:h,force:d,variableKey:a,variableSchema:g,variableValue:d.variables[a]},n.debug("forced variable",u),u}if("flag"===t&&f.required&&f.required.length>0){const a=f.required.every((t=>{let r,a;if("string"==typeof t?r=t:(r=t.key,a=t.variation),!j(Object.assign(Object.assign({},e),{type:"flag",featureKey:r})).enabled)return!1;if(void 0!==a){const t=j(Object.assign(Object.assign({},e),{type:"variation",featureKey:r}));let i;return t.variationValue?i=t.variationValue:t.variation&&(i=t.variation.value),i===a}return!0}));if(!a)return u={type:t,featureKey:r,reason:x.REQUIRED,required:f.required,enabled:a},n.debug("required features not enabled",u),u}let y=v({featureKey:r,bucketBy:f.bucketBy,context:i,logger:n});for(const e of c)e.bucketKey&&(y=e.bucketKey({featureKey:r,context:i,bucketBy:f.bucketBy,bucketKey:y}));let p,O,k=b(y);for(const e of c)e.bucketValue&&(k=e.bucketValue({featureKey:r,bucketKey:y,context:i,bucketValue:k}));if("flag"!==t?(p=s.getMatchedTraffic(f.traffic,i),p&&(O=s.getMatchedAllocation(p,k))):p=s.getMatchedTraffic(f.traffic,i),p){if(0===p.percentage)return u={type:t,featureKey:r,reason:x.RULE,bucketKey:y,bucketValue:k,ruleKey:p.key,traffic:p,enabled:!1},n.debug("matched rule with 0 percentage",u),u;if("flag"===t){if(f.ranges&&f.ranges.length>0)return f.ranges.find((e=>k>=e[0]&&k<e[1]))?(u={type:t,featureKey:r,reason:x.ALLOCATED,bucketKey:y,bucketValue:k,ruleKey:p.key,traffic:p,enabled:void 0===p.enabled||p.enabled},n.debug("matched",u),u):(u={type:t,featureKey:r,reason:x.OUT_OF_RANGE,bucketKey:y,bucketValue:k,enabled:!1},n.debug("not matched",u),u);if(void 0!==p.enabled)return u={type:t,featureKey:r,reason:x.RULE,bucketKey:y,bucketValue:k,ruleKey:p.key,traffic:p,enabled:p.enabled},n.debug("override from rule",u),u;if(k<=p.percentage)return u={type:t,featureKey:r,reason:x.RULE,bucketKey:y,bucketValue:k,ruleKey:p.key,traffic:p,enabled:!0},n.debug("matched traffic",u),u}if("variation"===t&&f.variations){if(p.variation){const e=f.variations.find((e=>e.value===p.variation));if(e)return u={type:t,featureKey:r,reason:x.RULE,bucketKey:y,bucketValue:k,ruleKey:p.key,traffic:p,variation:e},n.debug("override from rule",u),u}if(O&&O.variation){const e=f.variations.find((e=>e.value===O.variation));if(e)return u={type:t,featureKey:r,reason:x.ALLOCATED,bucketKey:y,bucketValue:k,ruleKey:p.key,traffic:p,variation:e},n.debug("allocated variation",u),u}}}if("variable"===t&&a){if(p&&p.variables&&void 0!==p.variables[a])return u={type:t,featureKey:r,reason:x.RULE,bucketKey:y,bucketValue:k,ruleKey:p.key,traffic:p,variableKey:a,variableSchema:g,variableValue:p.variables[a]},n.debug("override from rule",u),u;let e;if(d&&d.variation?e=d.variation:p&&p.variation?e=p.variation:O&&O.variation&&(e=O.variation),e&&Array.isArray(f.variations)){const o=f.variations.find((t=>t.value===e));if(o&&o.variableOverrides&&o.variableOverrides[a]){const e=o.variableOverrides[a].find((e=>e.conditions?s.allConditionsAreMatched("string"==typeof e.conditions&&"*"!==e.conditions?JSON.parse(e.conditions):e.conditions,i):!!e.segments&&s.allSegmentsAreMatched(s.parseSegmentsIfStringified(e.segments),i)));if(e)return u={type:t,featureKey:r,reason:x.VARIABLE_OVERRIDE,bucketKey:y,bucketValue:k,ruleKey:null==p?void 0:p.key,traffic:p,variableKey:a,variableSchema:g,variableValue:e.value},n.debug("variable override",u),u}if(o&&o.variables&&void 0!==o.variables[a])return u={type:t,featureKey:r,reason:x.ALLOCATED,bucketKey:y,bucketValue:k,ruleKey:null==p?void 0:p.key,traffic:p,variableKey:a,variableSchema:g,variableValue:o.variables[a]},n.debug("allocated variable",u),u}}return"variation"===t?(u={type:t,featureKey:r,reason:x.NO_MATCH,bucketKey:y,bucketValue:k},n.debug("no matched variation",u),u):"variable"===t?g?(u={type:t,featureKey:r,reason:x.VARIABLE_DEFAULT,bucketKey:y,bucketValue:k,variableKey:a,variableSchema:g,variableValue:g.defaultValue},n.debug("using default value",u),u):(u={type:t,featureKey:r,reason:x.VARIABLE_NOT_FOUND,variableKey:a,bucketKey:y,bucketValue:k},n.debug("variable not found",u),u):(u={type:t,featureKey:r,reason:x.NO_MATCH,bucketKey:y,bucketValue:k,enabled:!1},n.debug("nothing matched",u),u)}catch(e){return u={type:t,featureKey:r,variableKey:a,reason:x.ERROR,error:e},n.error("error",u),u}}function R(e={},t={},r){const a=[...Object.keys(e),...Object.keys(t)];return{features:a.filter(((e,t)=>a.indexOf(e)===t)),replaced:r}}!function(e){e.FEATURE_NOT_FOUND="feature_not_found",e.DISABLED="disabled",e.REQUIRED="required",e.OUT_OF_RANGE="out_of_range",e.NO_VARIATIONS="no_variations",e.VARIATION_DISABLED="variation_disabled",e.VARIABLE_NOT_FOUND="variable_not_found",e.VARIABLE_DEFAULT="variable_default",e.VARIABLE_DISABLED="variable_disabled",e.VARIABLE_OVERRIDE="variable_override",e.NO_MATCH="no_match",e.FORCED="forced",e.STICKY="sticky",e.RULE="rule",e.ALLOCATED="allocated",e.ERROR="error"}(x||(x={}));class S{constructor(e){this.parent=e.parent,this.context=e.context,this.sticky=e.sticky||{},this.emitter=new K}on(e,t){return"context_set"===e||"sticky_set"===e?this.emitter.on(e,t):this.parent.on(e,t)}close(){this.emitter.clearAll()}setContext(e,t=!1){this.context=t?e:Object.assign(Object.assign({},this.context),e),this.emitter.trigger("context_set",{context:this.context,replaced:t})}getContext(e){return this.parent.getContext(Object.assign(Object.assign({},this.context),e))}setSticky(e,t=!1){const r=this.sticky||{};this.sticky=t?Object.assign({},e):Object.assign(Object.assign({},this.sticky),e);const a=R(r,this.sticky,t);this.emitter.trigger("sticky_set",a)}isEnabled(e,t={},r={}){return this.parent.isEnabled(e,Object.assign(Object.assign({},this.context),t),Object.assign({sticky:this.sticky},r))}getVariation(e,t={},r={}){return this.parent.getVariation(e,Object.assign(Object.assign({},this.context),t),Object.assign({sticky:this.sticky},r))}getVariable(e,t,r={},a={}){return this.parent.getVariable(e,t,Object.assign(Object.assign({},this.context),r),Object.assign({sticky:this.sticky},a))}getVariableBoolean(e,t,r={},a={}){return this.parent.getVariableBoolean(e,t,Object.assign(Object.assign({},this.context),r),Object.assign({sticky:this.sticky},a))}getVariableString(e,t,r={},a={}){return this.parent.getVariableString(e,t,Object.assign(Object.assign({},this.context),r),Object.assign({sticky:this.sticky},a))}getVariableInteger(e,t,r={},a={}){return this.parent.getVariableInteger(e,t,Object.assign(Object.assign({},this.context),r),Object.assign({sticky:this.sticky},a))}getVariableDouble(e,t,r={},a={}){return this.parent.getVariableDouble(e,t,Object.assign(Object.assign({},this.context),r),Object.assign({sticky:this.sticky},a))}getVariableArray(e,t,r={},a={}){return this.parent.getVariableArray(e,t,Object.assign(Object.assign({},this.context),r),Object.assign({sticky:this.sticky},a))}getVariableObject(e,t,r={},a={}){return this.parent.getVariableObject(e,t,Object.assign(Object.assign({},this.context),r),Object.assign({sticky:this.sticky},a))}getVariableJSON(e,t,r={},a={}){return this.parent.getVariableJSON(e,t,Object.assign(Object.assign({},this.context),r),Object.assign({sticky:this.sticky},a))}getAllEvaluations(e={},t=[],r={}){return this.parent.getAllEvaluations(Object.assign(Object.assign({},this.context),e),t,Object.assign({sticky:this.sticky},r))}}function I(e,t){try{if(void 0===e)return null;switch(t){case"string":return"string"==typeof e?e:null;case"integer":return parseInt(e,10);case"double":return parseFloat(e);case"boolean":return!0===e;case"array":return Array.isArray(e)?e:null;case"object":return"object"==typeof e?e:null;default:return e}}catch(e){return null}}const _={schemaVersion:"2",revision:"unknown",segments:{},features:{}};class D{constructor(e){this.context={},this.context=e.context||{},this.logger=e.logger||V({level:e.logLevel||k.defaultLevel}),this.hooksManager=new A({hooks:e.hooks||[],logger:this.logger}),this.emitter=new K,this.sticky=e.sticky,this.datafileReader=new m({datafile:_,logger:this.logger}),e.datafile&&(this.datafileReader=new m({datafile:"string"==typeof e.datafile?JSON.parse(e.datafile):e.datafile,logger:this.logger})),this.logger.info("Featurevisor SDK initialized")}setLogLevel(e){this.logger.setLevel(e)}setDatafile(e){try{const t=new m({datafile:"string"==typeof e?JSON.parse(e):e,logger:this.logger}),r=function(e,t){const r=e.getRevision(),a=e.getFeatureKeys(),i=t.getRevision(),n=t.getFeatureKeys(),s=[],o=[],l=[];for(const r of a){if(-1===n.indexOf(r)){s.push(r);continue}const a=e.getFeature(r),i=t.getFeature(r);(null==a?void 0:a.hash)!==(null==i?void 0:i.hash)&&o.push(r)}for(const e of n)-1===a.indexOf(e)&&l.push(e);return{revision:i,previousRevision:r,revisionChanged:r!==i,features:[...s,...o,...l].filter(((e,t,r)=>r.indexOf(e)===t))}}(this.datafileReader,t);this.datafileReader=t,this.logger.info("datafile set",r),this.emitter.trigger("datafile_set",r)}catch(e){this.logger.error("could not parse datafile",{error:e})}}setSticky(e,t=!1){const r=this.sticky||{};this.sticky=t?Object.assign({},e):Object.assign(Object.assign({},this.sticky),e);const a=R(r,this.sticky,t);this.logger.info("sticky features set",a),this.emitter.trigger("sticky_set",a)}getRevision(){return this.datafileReader.getRevision()}getFeature(e){return this.datafileReader.getFeature(e)}addHook(e){return this.hooksManager.add(e)}on(e,t){return this.emitter.on(e,t)}close(){this.emitter.clearAll()}setContext(e,t=!1){this.context=t?e:Object.assign(Object.assign({},this.context),e),this.emitter.trigger("context_set",{context:this.context,replaced:t}),this.logger.debug(t?"context replaced":"context updated",{context:this.context,replaced:t})}getContext(e){return e?Object.assign(Object.assign({},this.context),e):this.context}spawn(e={},t={}){return new S({parent:this,context:this.getContext(e),sticky:t.sticky})}getEvaluationDependencies(e,t={}){return{context:this.getContext(e),logger:this.logger,hooksManager:this.hooksManager,datafileReader:this.datafileReader,sticky:t.sticky?Object.assign(Object.assign({},this.sticky),t.sticky):this.sticky,defaultVariationValue:t.defaultVariationValue,defaultVariableValue:t.defaultVariableValue}}evaluateFlag(e,t={},r={}){return E(Object.assign(Object.assign({},this.getEvaluationDependencies(t,r)),{type:"flag",featureKey:e}))}isEnabled(e,t={},r={}){try{return!0===this.evaluateFlag(e,t,r).enabled}catch(t){return this.logger.error("isEnabled",{featureKey:e,error:t}),!1}}evaluateVariation(e,t={},r={}){return E(Object.assign(Object.assign({},this.getEvaluationDependencies(t,r)),{type:"variation",featureKey:e}))}getVariation(e,t={},r={}){try{const a=this.evaluateVariation(e,t,r);return void 0!==a.variationValue?a.variationValue:a.variation?a.variation.value:null}catch(t){return this.logger.error("getVariation",{featureKey:e,error:t}),null}}evaluateVariable(e,t,r={},a={}){return E(Object.assign(Object.assign({},this.getEvaluationDependencies(r,a)),{type:"variable",featureKey:e,variableKey:t}))}getVariable(e,t,r={},a={}){try{const i=this.evaluateVariable(e,t,r,a);return void 0!==i.variableValue?i.variableSchema&&"json"===i.variableSchema.type&&"string"==typeof i.variableValue?JSON.parse(i.variableValue):i.variableValue:null}catch(r){return this.logger.error("getVariable",{featureKey:e,variableKey:t,error:r}),null}}getVariableBoolean(e,t,r={},a={}){return I(this.getVariable(e,t,r,a),"boolean")}getVariableString(e,t,r={},a={}){return I(this.getVariable(e,t,r,a),"string")}getVariableInteger(e,t,r={},a={}){return I(this.getVariable(e,t,r,a),"integer")}getVariableDouble(e,t,r={},a={}){return I(this.getVariable(e,t,r,a),"double")}getVariableArray(e,t,r={},a={}){return I(this.getVariable(e,t,r,a),"array")}getVariableObject(e,t,r={},a={}){return I(this.getVariable(e,t,r,a),"object")}getVariableJSON(e,t,r={},a={}){return I(this.getVariable(e,t,r,a),"json")}getAllEvaluations(e={},t=[],r={}){const a={},i=t.length>0?t:this.datafileReader.getFeatureKeys();for(const t of i){const i={enabled:this.isEnabled(t,e,r)};if(this.datafileReader.hasVariations(t)){const a=this.getVariation(t,e,r);a&&(i.variation=a)}const n=this.datafileReader.getVariableKeys(t);if(n.length>0){i.variables={};for(const a of n)i.variables[a]=this.getVariable(t,a,e,r)}a[t]=i}return a}}function L(e){return new D(e)}var M=t.Il,C=t.f6,F=t.ps,T=t.Jr,w=t.Vy,N=t.lb,B=t.mx,U=t.Q_,q=t.h,J=t.K_,W=t._3,H=t.EM,G=t.eG,z=t.dg,$=t.f,Q=t.xE;export{M as DatafileReader,C as EvaluationReason,F as FeaturevisorChildInstance,T as FeaturevisorInstance,w as Logger,N as MAX_BUCKETED_NUMBER,B as conditionIsMatched,U as createInstance,q as createLogger,J as defaultLogHandler,W as evaluate,H as evaluateWithHooks,G as getBucketKey,z as getBucketedNumber,$ as getValueFromContext,Q as loggerPrefix};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.gz
CHANGED
|
Binary file
|