@featurevisor/sdk
Advanced tools
Comparing version 0.27.0 to 0.28.0
@@ -6,2 +6,13 @@ # Change Log | ||
# [0.28.0](https://github.com/fahad19/featurevisor/compare/v0.27.1...v0.28.0) (2023-06-08) | ||
### Features | ||
* make bucketing key configurable ([#79](https://github.com/fahad19/featurevisor/issues/79)) ([c05f0da](https://github.com/fahad19/featurevisor/commit/c05f0dae9e6e1d4ee68f2c457a49137bbd6727d9)) | ||
# [0.27.0](https://github.com/fahad19/featurevisor/compare/v0.26.0...v0.27.0) (2023-05-24) | ||
@@ -8,0 +19,0 @@ |
@@ -1,2 +0,2 @@ | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FeaturevisorSDK=t():e.FeaturevisorSDK=t()}(this,(()=>(()=>{var e={480:(e,t,r)=>{"use strict";r.r(t),r.d(t,{compare:()=>a,compareVersions:()=>i,satisfies:()=>o,validate:()=>n});const i=(e,t)=>{const r=u(e),i=u(t),n=r.pop(),a=i.pop(),o=d(r,i);return 0!==o?o:n&&a?d(n.split("."),a.split(".")):n||a?n?-1:1:0},n=e=>"string"==typeof e&&/^[v\d]/.test(e)&&s.test(e),a=(e,t,r)=>{h(r);const n=i(e,t);return g[r].includes(n)},o=(e,t)=>{if(t.includes("||"))return t.split("||").some((t=>o(e,t)));if(t.includes(" "))return t.trim().replace(/\s{2,}/g," ").split(" ").every((t=>o(e,t)));const r=t.match(/^([<>=~^]+)/),i=r?r[1]:"=";if("^"!==i&&"~"!==i)return a(e,t,i);const[n,s,f,,l]=u(e),[c,g,v,,h]=u(t),y=[n,s,f],p=[c,null!=g?g:"x",null!=v?v:"x"];if(h){if(!l)return!1;if(0!==d(y,p))return!1;if(-1===d(l.split("."),h.split(".")))return!1}const b=p.findIndex((e=>"0"!==e))+1,m="~"===i?2:b>1?b:1;return 0===d(y.slice(0,m),p.slice(0,m))&&-1!==d(y.slice(m),p.slice(m))},s=/^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i,u=e=>{if("string"!=typeof e)throw new TypeError("Invalid argument expected string");const t=e.match(s);if(!t)throw new Error(`Invalid argument not valid semver ('${e}' received)`);return t.shift(),t},f=e=>"*"===e||"x"===e||"X"===e,l=e=>{const t=parseInt(e,10);return isNaN(t)?e:t},c=(e,t)=>{if(f(e)||f(t))return 0;const[r,i]=((e,t)=>typeof e!=typeof t?[String(e),String(t)]:[e,t])(l(e),l(t));return r>i?1:r<i?-1:0},d=(e,t)=>{for(let r=0;r<Math.max(e.length,t.length);r++){const i=c(e[r]||"0",t[r]||"0");if(0!==i)return i}return 0},g={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1]},v=Object.keys(g),h=e=>{if("string"!=typeof e)throw new TypeError("Invalid operator type, expected string but got "+typeof e);if(-1===v.indexOf(e))throw new Error(`Invalid operator, expected one of ${v.join("|")}`)}},77:e=>{!function(){const t=e=>(new TextEncoder).encode(e);function r(e,r){let i,n,a,o,s,u,f,l;for("string"==typeof e&&(e=t(e)),i=3&e.length,n=e.length-i,a=r,s=3432918353,u=461845907,l=0;l<n;)f=255&e[l]|(255&e[++l])<<8|(255&e[++l])<<16|(255&e[++l])<<24,++l,f=(65535&f)*s+(((f>>>16)*s&65535)<<16)&4294967295,f=f<<15|f>>>17,f=(65535&f)*u+(((f>>>16)*u&65535)<<16)&4294967295,a^=f,a=a<<13|a>>>19,o=5*(65535&a)+((5*(a>>>16)&65535)<<16)&4294967295,a=27492+(65535&o)+((58964+(o>>>16)&65535)<<16);switch(f=0,i){case 3:f^=(255&e[l+2])<<16;case 2:f^=(255&e[l+1])<<8;case 1:f^=255&e[l],f=(65535&f)*s+(((f>>>16)*s&65535)<<16)&4294967295,f=f<<15|f>>>17,f=(65535&f)*u+(((f>>>16)*u&65535)<<16)&4294967295,a^=f}return a^=e.length,a^=a>>>16,a=2246822507*(65535&a)+((2246822507*(a>>>16)&65535)<<16)&4294967295,a^=a>>>13,a=3266489909*(65535&a)+((3266489909*(a>>>16)&65535)<<16)&4294967295,a^=a>>>16,a>>>0}const i=r;i.v2=function(e,r){"string"==typeof e&&(e=t(e));let i,n=e.length,a=r^n,o=0;for(;n>=4;)i=255&e[o]|(255&e[++o])<<8|(255&e[++o])<<16|(255&e[++o])<<24,i=1540483477*(65535&i)+((1540483477*(i>>>16)&65535)<<16),i^=i>>>24,i=1540483477*(65535&i)+((1540483477*(i>>>16)&65535)<<16),a=1540483477*(65535&a)+((1540483477*(a>>>16)&65535)<<16)^i,n-=4,++o;switch(n){case 3:a^=(255&e[o+2])<<16;case 2:a^=(255&e[o+1])<<8;case 1:a^=255&e[o],a=1540483477*(65535&a)+((1540483477*(a>>>16)&65535)<<16)}return a^=a>>>13,a=1540483477*(65535&a)+((1540483477*(a>>>16)&65535)<<16),a^=a>>>15,a>>>0},i.v3=r,e.exports=i}()},725:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getBucketedNumber=t.MAX_BUCKETED_NUMBER=void 0;var i=r(77),n=Math.pow(2,32);t.MAX_BUCKETED_NUMBER=1e5,t.getBucketedNumber=function(e){var r=i.v3(e,1)/n;return Math.floor(r*t.MAX_BUCKETED_NUMBER)}},243:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.allConditionsAreMatched=t.conditionIsMatched=void 0;var i=r(480);function n(e,t){var r=e.attribute,n=e.operator,a=e.value;if("equals"===n)return t[r]===a;if("notEquals"===n)return t[r]!==a;if("before"===n||"after"===n){var o=(u=t[r])instanceof Date?u:new Date(u),s=a instanceof Date?a:new Date(a);return"before"===n?o<s:o>s}if("string"==typeof t[r]&&Array.isArray(a)){var u=t[r];if("in"===n)return-1!==a.indexOf(u);if("notIn"===n)return-1===a.indexOf(u)}else if("string"==typeof t[r]&&"string"==typeof a){if(u=t[r],"contains"===n)return-1!==u.indexOf(a);if("notContains"===n)return-1===u.indexOf(a);if("startsWith"===n)return u.startsWith(a);if("endsWith"===n)return u.endsWith(a);if("semverEquals"===n)return 0===(0,i.compareVersions)(u,a);if("semverNotEquals"===n)return 0!==(0,i.compareVersions)(u,a);if("semverGreaterThan"===n)return 1===(0,i.compareVersions)(u,a);if("semverGreaterThanOrEquals"===n)return(0,i.compareVersions)(u,a)>=0;if("semverLessThan"===n)return-1===(0,i.compareVersions)(u,a);if("semverLessThanOrEquals"===n)return(0,i.compareVersions)(u,a)<=0}else if("number"==typeof t[r]&&"number"==typeof a){if(u=t[r],"greaterThan"===n)return u>a;if("greaterThanOrEquals"===n)return u>=a;if("lessThan"===n)return u<a;if("lessThanOrEquals"===n)return u<=a}return!1}t.conditionIsMatched=n,t.allConditionsAreMatched=function e(t,r){return"attribute"in t?n(t,r):"and"in t&&Array.isArray(t.and)?t.and.every((function(t){return e(t,r)})):"or"in t&&Array.isArray(t.or)?t.or.some((function(t){return e(t,r)})):"not"in t&&Array.isArray(t.not)?t.not.every((function(i){return!1===e({and:t.not},r)})):!!Array.isArray(t)&&t.every((function(t){return e(t,r)}))}},913:(e,t)=>{"use strict";function r(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}Object.defineProperty(t,"__esModule",{value:!0}),t.DatafileReader=t.parseJsonConditionsIfStringified=void 0,t.parseJsonConditionsIfStringified=r;var i=function(){function e(e){this.schemaVersion=e.schemaVersion,this.revision=e.revision,this.segments=e.segments,this.attributes=e.attributes,this.features=e.features}return e.prototype.getRevision=function(){return this.revision},e.prototype.getSchemaVersion=function(){return this.schemaVersion},e.prototype.getAllAttributes=function(){return this.attributes},e.prototype.getAttribute=function(e){return this.attributes.find((function(t){return t.key===e}))},e.prototype.getSegment=function(e){var t=this.segments.find((function(t){return t.key===e}));if(t)return r(t,"conditions")},e.prototype.getFeature=function(e){var t=this.features.find((function(t){return t.key===e}));if(t)return t},e}();t.DatafileReader=i},186:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Emitter=void 0;var r=function(){function e(){this._listeners={}}return e.prototype.addListener=function(e,t){void 0===this._listeners[e]&&(this._listeners[e]=[]),this._listeners[e].push(t)},e.prototype.removeListener=function(e,t){if(void 0!==this._listeners[e]){var r=this._listeners[e].indexOf(t);-1!==r&&this._listeners[e].splice(r,1)}},e.prototype.removeAllListeners=function(e){var t=this;e?this._listeners[e]=[]:Object.keys(this._listeners).forEach((function(e){t._listeners[e]=[]}))},e.prototype.emit=function(e){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];void 0!==this._listeners[e]&&this._listeners[e].forEach((function(e){e.apply(void 0,t)}))},e}();t.Emitter=r},522:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getBucketedVariableValue=t.getForcedVariableValue=t.getBucketedVariation=t.getForcedVariation=t.getMatchedTrafficAndAllocation=t.getMatchedAllocation=t.getStartEndFromRange=void 0;var i=r(590),n=r(243);function a(e){if(Array.isArray(e))return e;var t=e;return[t.start,t.end]}function o(e,t){for(var r=0,i=e.allocation.length>0&&void 0===e.allocation[0].range,n=0,o=e.allocation;n<o.length;n++){var s=o[n],u=a(s.range),f=u[0],l=u[1];if(s.range&&f<=t&&l>=t)return s;if(i&&t<=(r+=s.percentage||0))return s}}function s(e,t,r,n,a){var s;return{matchedTraffic:e.find((function(e){return!!(0,i.allGroupSegmentsAreMatched)("string"==typeof e.segments&&"*"!==e.segments?JSON.parse(e.segments):e.segments,t,n)&&!!(s=o(e,r))})),matchedAllocation:s}}function u(e,t,r){if(e.force)return e.force.find((function(e){return e.conditions?(0,n.allConditionsAreMatched)(e.conditions,t):!!e.segments&&(0,i.allGroupSegmentsAreMatched)(e.segments,t,r)}))}t.getStartEndFromRange=a,t.getMatchedAllocation=o,t.getMatchedTrafficAndAllocation=s,t.getForcedVariation=function(e,t,r){var i=u(e,t,r);if(i&&i.variation)return e.variations.find((function(e){return e.value===i.variation}))},t.getBucketedVariation=function(e,t,r,i,n){var a=s(e.traffic,t,r,i),o=a.matchedTraffic,u=a.matchedAllocation;if(o){if(o.variation){var f=e.variations.find((function(e){return e.value===o.variation}));if(f)return n.debug("using variation from rule",{featureKey:e.key,variation:f.value,ruleKey:o.key}),f}if(u){var l=u.variation,c=e.variations.find((function(e){return e.value===l}));if(c)return n.debug("matched variation",{featureKey:e.key,variation:c.value,bucketValue:r}),c;n.debug("no matched variation found",{featureKey:e.key,variation:l,bucketValue:r})}else n.debug("no matched allocation found",{featureKey:e.key,bucketValue:r})}else n.debug("no matched rule found",{featureKey:e.key,bucketValue:r})},t.getForcedVariableValue=function(e,t,r,i){var n=u(e,r,i);if(n&&n.variables){var a=n.variables[t.key];return"string"==typeof a&&"json"===t.type?JSON.parse(a):a}},t.getBucketedVariableValue=function(e,t,r,a,o,u){var f,l=s(e.traffic,r,a,o),c=l.matchedTraffic,d=l.matchedAllocation;if(c){var g=t.key;if(c.variables&&void 0!==c.variables[g])return u.debug("using variable from rule",{featureKey:e.key,variableKey:g,bucketValue:a}),c.variables[g];if(d){var v=d.variation,h=e.variations.find((function(e){return e.value===v}));if(h){var y=null===(f=h.variables)||void 0===f?void 0:f.find((function(e){return e.key===g}));if(!y)return u.debug("using default value as variation has no variable",{featureKey:e.key,variableKey:g,variation:v,bucketValue:a}),"json"===t.type?JSON.parse(t.defaultValue):t.defaultValue;if(y.overrides){var p=y.overrides.find((function(e){return e.conditions?(0,n.allConditionsAreMatched)("string"==typeof e.conditions?JSON.parse(e.conditions):e.conditions,r):!!e.segments&&(0,i.allGroupSegmentsAreMatched)("string"==typeof e.segments&&"*"!==e.segments?JSON.parse(e.segments):e.segments,r,o)}));if(p)return u.debug("using override value from variation",{feature:e.key,variableKey:g,variation:v,bucketValue:a}),"json"===t.type?JSON.parse(p.value):p.value}return u.debug("using value from variation",{feature:e.key,variableKey:g,variation:v,bucketValue:a}),"json"===t.type?JSON.parse(y.value):y.value}u.debug("no matched variation found",{feature:e.key,variableKey:g,variation:v,bucketValue:a})}else u.debug("no matched allocation found",{featureKey:e.key,variableKey:g,bucketValue:a})}else u.debug("no matched rule found",{featureKey:e.key,variableKey:t.key,bucketValue:a})}},97:function(e,t,r){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,r,i){void 0===i&&(i=r);var n=Object.getOwnPropertyDescriptor(t,r);n&&!("get"in n?!t.__esModule:n.writable||n.configurable)||(n={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,n)}:function(e,t,r,i){void 0===i&&(i=r),e[i]=t[r]}),n=this&&this.__exportStar||function(e,t){for(var r in e)"default"===r||Object.prototype.hasOwnProperty.call(t,r)||i(t,e,r)};Object.defineProperty(t,"__esModule",{value:!0}),t.getStartEndFromRange=void 0,n(r(725),t),n(r(681),t),n(r(687),t);var a=r(522);Object.defineProperty(t,"getStartEndFromRange",{enumerable:!0,get:function(){return a.getStartEndFromRange}})},681:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.createInstance=t.FeaturevisorInstance=t.getValueByType=void 0;var i=r(687),n=r(913),a=r(186),o=r(725),s=r(522),u=".",f={schemaVersion:"1",revision:"unknown",attributes:[],segments:[],features:[]};function l(e,t){return t?t(e):fetch(e).then((function(e){return e.json()}))}function c(e,t){if(void 0!==e)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}}t.getValueByType=c;var d=function(){function e(e){var t=this;this.bucketKeySeparator=e.bucketKeySeparator||u,this.configureBucketValue=e.configureBucketValue,this.datafileUrl=e.datafileUrl,this.handleDatafileFetch=e.handleDatafileFetch,this.initialFeatures=e.initialFeatures,this.interceptAttributes=e.interceptAttributes,this.logger=e.logger||(0,i.createLogger)(),this.refreshInterval=e.refreshInterval,this.stickyFeatures=e.stickyFeatures,this.emitter=new a.Emitter,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);var r=this.emitter.addListener.bind(this.emitter);this.on=r,this.addListener=r;var n=this.emitter.removeListener.bind(this.emitter);if(this.off=n,this.removeListener=n,this.removeAllListeners=this.emitter.removeAllListeners.bind(this.emitter),e.datafileUrl)this.setDatafile(e.datafile||f),l(e.datafileUrl,e.handleDatafileFetch).then((function(e){t.setDatafile(e),t.statuses.ready=!0,t.emitter.emit("ready"),t.refreshInterval&&t.startRefreshing()})).catch((function(e){t.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((function(){t.emitter.emit("ready")}),0)}}return e.prototype.setDatafile=function(e){try{this.datafileReader=new n.DatafileReader("string"==typeof e?JSON.parse(e):e)}catch(e){this.logger.error("could not parse datafile",{error:e})}},e.prototype.setStickyFeatures=function(e){this.stickyFeatures=e},e.prototype.getRevision=function(){return this.datafileReader.getRevision()},e.prototype.getFeature=function(e){return"string"==typeof e?this.datafileReader.getFeature(e):e},e.prototype.isReady=function(){return this.statuses.ready},e.prototype.refresh=function(){var e=this;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((function(t){var r=e.getRevision()!==t.revision;e.setDatafile(t),e.logger.info("refreshed datafile"),e.emitter.emit("refresh"),r&&e.emitter.emit("update"),e.statuses.refreshInProgress=!1})).catch((function(t){e.logger.error("failed to refresh datafile",{error:t}),e.statuses.refreshInProgress=!1}))):this.logger.error("cannot refresh since `datafileUrl` is not provided")},e.prototype.startRefreshing=function(){var e=this;return this.datafileUrl?this.intervalId?this.logger.warn("refreshing has already started"):this.refreshInterval?void(this.intervalId=setInterval((function(){e.refresh()}),1e3*this.refreshInterval)):this.logger.warn("no `refreshInterval` option provided"):this.logger.error("cannot start refreshing since `datafileUrl` is not provided")},e.prototype.stopRefreshing=function(){if(!this.intervalId)return this.logger.warn("refreshing has not started yet");clearInterval(this.intervalId)},e.prototype.getBucketKey=function(e,t){var r=e.key,i="string"==typeof e.bucketBy?[e.bucketBy]:e.bucketBy,n=[];return i.forEach((function(e){var r=t[e];void 0!==r&&n.push(r)})),n.push(r),n.join(this.bucketKeySeparator)},e.prototype.getBucketValue=function(e,t){var r=this.getBucketKey(e,t),i=(0,o.getBucketedNumber)(r);return this.configureBucketValue?this.configureBucketValue(e,t,i):i},e.prototype.getVariation=function(e,t){void 0===t&&(t={});try{var r,i="string"==typeof e?e:e.key;if(this.stickyFeatures&&this.stickyFeatures[i]&&void 0!==(r=this.stickyFeatures[i].variation))return this.logger.debug("using sticky variation",{featureKey:i,variation:r}),r;if(this.statuses&&!this.statuses.ready&&this.initialFeatures&&this.initialFeatures[i]&&void 0!==(r=this.initialFeatures[i].variation))return this.logger.debug("using initial variation",{featureKey:i,variation:r}),r;var n=this.getFeature(e);if(!n)return void this.logger.warn("feature not found in datafile",{featureKey:e});var a=this.interceptAttributes?this.interceptAttributes(t):t,o=(0,s.getForcedVariation)(n,a,this.datafileReader);if(o)return this.logger.debug("forced variation found",{featureKey:e,variation:o.value}),o.value;var u=this.getBucketValue(n,a),f=(0,s.getBucketedVariation)(n,a,u,this.datafileReader,this.logger);return f?f.value:(this.logger.debug("using default variation",{featureKey:e,bucketValue:u,variation:n.defaultVariation}),n.defaultVariation)}catch(t){return void this.logger.error("getVariation",{featureKey:e,error:t})}},e.prototype.getVariationBoolean=function(e,t){return void 0===t&&(t={}),c(this.getVariation(e,t),"boolean")},e.prototype.getVariationString=function(e,t){return void 0===t&&(t={}),c(this.getVariation(e,t),"string")},e.prototype.getVariationInteger=function(e,t){return void 0===t&&(t={}),c(this.getVariation(e,t),"integer")},e.prototype.getVariationDouble=function(e,t){return void 0===t&&(t={}),c(this.getVariation(e,t),"double")},e.prototype.activate=function(e,t){void 0===t&&(t={});try{var r=this.getVariation(e,t);if(void 0===r)return;var i=this.interceptAttributes?this.interceptAttributes(t):t,n={};return this.datafileReader.getAllAttributes().filter((function(e){return!0===e.capture})).forEach((function(e){void 0!==i[e.key]&&(n[e.key]=t[e.key])})),this.emitter.emit("activation",e,r,i,n),r}catch(t){return void this.logger.error("activate",{featureKey:e,error:t})}},e.prototype.activateBoolean=function(e,t){return void 0===t&&(t={}),c(this.activate(e,t),"boolean")},e.prototype.activateString=function(e,t){return void 0===t&&(t={}),c(this.activate(e,t),"string")},e.prototype.activateInteger=function(e,t){return void 0===t&&(t={}),c(this.activate(e,t),"integer")},e.prototype.activateDouble=function(e,t){return void 0===t&&(t={}),c(this.activate(e,t),"double")},e.prototype.getVariable=function(e,t,r){void 0===r&&(r={});try{var i,n="string"==typeof e?e:e.key;if(this.stickyFeatures&&this.stickyFeatures[n]&&this.stickyFeatures[n].variables&&void 0!==(i=this.stickyFeatures[n].variables[t]))return this.logger.debug("using sticky variable",{featureKey:n,variableKey:t}),i;if(this.statuses&&!this.statuses.ready&&this.initialFeatures&&this.initialFeatures[n]&&this.initialFeatures[n].variables&&void 0!==(i=this.initialFeatures[n].variables[t]))return this.logger.debug("using initial variable",{featureKey:n,variableKey:t}),i;var a=this.getFeature(e);if(!a)return void this.logger.warn("feature not found in datafile",{featureKey:e,variableKey:t});var o=Array.isArray(a.variablesSchema)?a.variablesSchema.find((function(e){return e.key===t})):void 0;if(!o)return void this.logger.warn("variable schema not found",{featureKey:e,variableKey:t});var u=this.interceptAttributes?this.interceptAttributes(r):r,f=(0,s.getForcedVariableValue)(a,o,u,this.datafileReader);if(void 0!==f)return this.logger.debug("forced variable value found",{featureKey:e,variableKey:t}),f;var l=this.getBucketValue(a,u);return(0,s.getBucketedVariableValue)(a,o,u,l,this.datafileReader,this.logger)}catch(r){return void this.logger.error("getVariable",{featureKey:e,variableKey:t,error:r})}},e.prototype.getVariableBoolean=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"boolean")},e.prototype.getVariableString=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"string")},e.prototype.getVariableInteger=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"integer")},e.prototype.getVariableDouble=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"double")},e.prototype.getVariableArray=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"array")},e.prototype.getVariableObject=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"object")},e.prototype.getVariableJSON=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"json")},e}();t.FeaturevisorInstance=d,t.createInstance=function(e){return new d(e)}},687:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.createLogger=t.Logger=t.defaultLogHandler=t.defaultLogLevels=t.loggerPrefix=void 0,t.loggerPrefix="[Featurevisor]",t.defaultLogLevels=["warn","error"],t.defaultLogHandler=function(e,r,i){switch(void 0===i&&(i={}),e){case"debug":console.log(t.loggerPrefix,r,i);case"info":console.info(t.loggerPrefix,r,i);case"warn":console.warn(t.loggerPrefix,r,i);case"error":console.error(t.loggerPrefix,r,i)}};var r=function(){function e(e){this.levels=e.levels,this.handle=e.handler}return e.prototype.setLevels=function(e){this.levels=e},e.prototype.log=function(e,t,r){-1!==this.levels.indexOf(e)&&this.handle(e,t,r)},e.prototype.debug=function(e,t){this.log("debug",e,t)},e.prototype.info=function(e,t){this.log("info",e,t)},e.prototype.warn=function(e,t){this.log("warn",e,t)},e.prototype.error=function(e,t){this.log("error",e,t)},e}();t.Logger=r,t.createLogger=function(e){void 0===e&&(e={});var i=e.levels||t.defaultLogLevels,n=e.handler||t.defaultLogHandler;return new r({levels:i,handler:n})}},590:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.allGroupSegmentsAreMatched=t.segmentIsMatched=void 0;var i=r(243);function n(e,t){return(0,i.allConditionsAreMatched)(e.conditions,t)}t.segmentIsMatched=n,t.allGroupSegmentsAreMatched=function e(t,r,i){if("*"===t)return!0;if("string"==typeof t){var a=i.getSegment(t);return!!a&&n(a,r)}if("object"==typeof t){if("and"in t&&Array.isArray(t.and))return t.and.every((function(t){return e(t,r,i)}));if("or"in t&&Array.isArray(t.or))return t.or.some((function(t){return e(t,r,i)}));if("not"in t&&Array.isArray(t.not))return t.not.every((function(t){return!1===e(t,r,i)}))}return!!Array.isArray(t)&&t.every((function(t){return e(t,r,i)}))}}},t={};function r(i){var n=t[i];if(void 0!==n)return n.exports;var a=t[i]={exports:{}};return e[i].call(a.exports,a,a.exports,r),a.exports}return r.d=(e,t)=>{for(var i in t)r.o(t,i)&&!r.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r(97)})())); | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FeaturevisorSDK=t():e.FeaturevisorSDK=t()}(this,(()=>(()=>{var e={480:(e,t,r)=>{"use strict";r.r(t),r.d(t,{compare:()=>a,compareVersions:()=>i,satisfies:()=>o,validate:()=>n});const i=(e,t)=>{const r=u(e),i=u(t),n=r.pop(),a=i.pop(),o=d(r,i);return 0!==o?o:n&&a?d(n.split("."),a.split(".")):n||a?n?-1:1:0},n=e=>"string"==typeof e&&/^[v\d]/.test(e)&&s.test(e),a=(e,t,r)=>{v(r);const n=i(e,t);return g[r].includes(n)},o=(e,t)=>{if(t.includes("||"))return t.split("||").some((t=>o(e,t)));if(t.includes(" "))return t.trim().replace(/\s{2,}/g," ").split(" ").every((t=>o(e,t)));const r=t.match(/^([<>=~^]+)/),i=r?r[1]:"=";if("^"!==i&&"~"!==i)return a(e,t,i);const[n,s,f,,l]=u(e),[c,g,h,,v]=u(t),y=[n,s,f],p=[c,null!=g?g:"x",null!=h?h:"x"];if(v){if(!l)return!1;if(0!==d(y,p))return!1;if(-1===d(l.split("."),v.split(".")))return!1}const b=p.findIndex((e=>"0"!==e))+1,m="~"===i?2:b>1?b:1;return 0===d(y.slice(0,m),p.slice(0,m))&&-1!==d(y.slice(m),p.slice(m))},s=/^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i,u=e=>{if("string"!=typeof e)throw new TypeError("Invalid argument expected string");const t=e.match(s);if(!t)throw new Error(`Invalid argument not valid semver ('${e}' received)`);return t.shift(),t},f=e=>"*"===e||"x"===e||"X"===e,l=e=>{const t=parseInt(e,10);return isNaN(t)?e:t},c=(e,t)=>{if(f(e)||f(t))return 0;const[r,i]=((e,t)=>typeof e!=typeof t?[String(e),String(t)]:[e,t])(l(e),l(t));return r>i?1:r<i?-1:0},d=(e,t)=>{for(let r=0;r<Math.max(e.length,t.length);r++){const i=c(e[r]||"0",t[r]||"0");if(0!==i)return i}return 0},g={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1]},h=Object.keys(g),v=e=>{if("string"!=typeof e)throw new TypeError("Invalid operator type, expected string but got "+typeof e);if(-1===h.indexOf(e))throw new Error(`Invalid operator, expected one of ${h.join("|")}`)}},77:e=>{!function(){const t=e=>(new TextEncoder).encode(e);function r(e,r){let i,n,a,o,s,u,f,l;for("string"==typeof e&&(e=t(e)),i=3&e.length,n=e.length-i,a=r,s=3432918353,u=461845907,l=0;l<n;)f=255&e[l]|(255&e[++l])<<8|(255&e[++l])<<16|(255&e[++l])<<24,++l,f=(65535&f)*s+(((f>>>16)*s&65535)<<16)&4294967295,f=f<<15|f>>>17,f=(65535&f)*u+(((f>>>16)*u&65535)<<16)&4294967295,a^=f,a=a<<13|a>>>19,o=5*(65535&a)+((5*(a>>>16)&65535)<<16)&4294967295,a=27492+(65535&o)+((58964+(o>>>16)&65535)<<16);switch(f=0,i){case 3:f^=(255&e[l+2])<<16;case 2:f^=(255&e[l+1])<<8;case 1:f^=255&e[l],f=(65535&f)*s+(((f>>>16)*s&65535)<<16)&4294967295,f=f<<15|f>>>17,f=(65535&f)*u+(((f>>>16)*u&65535)<<16)&4294967295,a^=f}return a^=e.length,a^=a>>>16,a=2246822507*(65535&a)+((2246822507*(a>>>16)&65535)<<16)&4294967295,a^=a>>>13,a=3266489909*(65535&a)+((3266489909*(a>>>16)&65535)<<16)&4294967295,a^=a>>>16,a>>>0}const i=r;i.v2=function(e,r){"string"==typeof e&&(e=t(e));let i,n=e.length,a=r^n,o=0;for(;n>=4;)i=255&e[o]|(255&e[++o])<<8|(255&e[++o])<<16|(255&e[++o])<<24,i=1540483477*(65535&i)+((1540483477*(i>>>16)&65535)<<16),i^=i>>>24,i=1540483477*(65535&i)+((1540483477*(i>>>16)&65535)<<16),a=1540483477*(65535&a)+((1540483477*(a>>>16)&65535)<<16)^i,n-=4,++o;switch(n){case 3:a^=(255&e[o+2])<<16;case 2:a^=(255&e[o+1])<<8;case 1:a^=255&e[o],a=1540483477*(65535&a)+((1540483477*(a>>>16)&65535)<<16)}return a^=a>>>13,a=1540483477*(65535&a)+((1540483477*(a>>>16)&65535)<<16),a^=a>>>15,a>>>0},i.v3=r,e.exports=i}()},725:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getBucketedNumber=t.MAX_BUCKETED_NUMBER=void 0;var i=r(77),n=Math.pow(2,32);t.MAX_BUCKETED_NUMBER=1e5,t.getBucketedNumber=function(e){var r=i.v3(e,1)/n;return Math.floor(r*t.MAX_BUCKETED_NUMBER)}},243:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.allConditionsAreMatched=t.conditionIsMatched=void 0;var i=r(480);function n(e,t){var r=e.attribute,n=e.operator,a=e.value;if("equals"===n)return t[r]===a;if("notEquals"===n)return t[r]!==a;if("before"===n||"after"===n){var o=(u=t[r])instanceof Date?u:new Date(u),s=a instanceof Date?a:new Date(a);return"before"===n?o<s:o>s}if("string"==typeof t[r]&&Array.isArray(a)){var u=t[r];if("in"===n)return-1!==a.indexOf(u);if("notIn"===n)return-1===a.indexOf(u)}else if("string"==typeof t[r]&&"string"==typeof a){if(u=t[r],"contains"===n)return-1!==u.indexOf(a);if("notContains"===n)return-1===u.indexOf(a);if("startsWith"===n)return u.startsWith(a);if("endsWith"===n)return u.endsWith(a);if("semverEquals"===n)return 0===(0,i.compareVersions)(u,a);if("semverNotEquals"===n)return 0!==(0,i.compareVersions)(u,a);if("semverGreaterThan"===n)return 1===(0,i.compareVersions)(u,a);if("semverGreaterThanOrEquals"===n)return(0,i.compareVersions)(u,a)>=0;if("semverLessThan"===n)return-1===(0,i.compareVersions)(u,a);if("semverLessThanOrEquals"===n)return(0,i.compareVersions)(u,a)<=0}else if("number"==typeof t[r]&&"number"==typeof a){if(u=t[r],"greaterThan"===n)return u>a;if("greaterThanOrEquals"===n)return u>=a;if("lessThan"===n)return u<a;if("lessThanOrEquals"===n)return u<=a}return!1}t.conditionIsMatched=n,t.allConditionsAreMatched=function e(t,r){return"attribute"in t?n(t,r):"and"in t&&Array.isArray(t.and)?t.and.every((function(t){return e(t,r)})):"or"in t&&Array.isArray(t.or)?t.or.some((function(t){return e(t,r)})):"not"in t&&Array.isArray(t.not)?t.not.every((function(i){return!1===e({and:t.not},r)})):!!Array.isArray(t)&&t.every((function(t){return e(t,r)}))}},913:(e,t)=>{"use strict";function r(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}Object.defineProperty(t,"__esModule",{value:!0}),t.DatafileReader=t.parseJsonConditionsIfStringified=void 0,t.parseJsonConditionsIfStringified=r;var i=function(){function e(e){this.schemaVersion=e.schemaVersion,this.revision=e.revision,this.segments=e.segments,this.attributes=e.attributes,this.features=e.features}return e.prototype.getRevision=function(){return this.revision},e.prototype.getSchemaVersion=function(){return this.schemaVersion},e.prototype.getAllAttributes=function(){return this.attributes},e.prototype.getAttribute=function(e){return this.attributes.find((function(t){return t.key===e}))},e.prototype.getSegment=function(e){var t=this.segments.find((function(t){return t.key===e}));if(t)return r(t,"conditions")},e.prototype.getFeature=function(e){var t=this.features.find((function(t){return t.key===e}));if(t)return t},e}();t.DatafileReader=i},186:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Emitter=void 0;var r=function(){function e(){this._listeners={}}return e.prototype.addListener=function(e,t){void 0===this._listeners[e]&&(this._listeners[e]=[]),this._listeners[e].push(t)},e.prototype.removeListener=function(e,t){if(void 0!==this._listeners[e]){var r=this._listeners[e].indexOf(t);-1!==r&&this._listeners[e].splice(r,1)}},e.prototype.removeAllListeners=function(e){var t=this;e?this._listeners[e]=[]:Object.keys(this._listeners).forEach((function(e){t._listeners[e]=[]}))},e.prototype.emit=function(e){for(var t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];void 0!==this._listeners[e]&&this._listeners[e].forEach((function(e){e.apply(void 0,t)}))},e}();t.Emitter=r},522:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getBucketedVariableValue=t.getForcedVariableValue=t.getBucketedVariation=t.getForcedVariation=t.getMatchedTrafficAndAllocation=t.getMatchedAllocation=t.getStartEndFromRange=void 0;var i=r(590),n=r(243);function a(e){if(Array.isArray(e))return e;var t=e;return[t.start,t.end]}function o(e,t){for(var r=0,i=e.allocation.length>0&&void 0===e.allocation[0].range,n=0,o=e.allocation;n<o.length;n++){var s=o[n],u=a(s.range),f=u[0],l=u[1];if(s.range&&f<=t&&l>=t)return s;if(i&&t<=(r+=s.percentage||0))return s}}function s(e,t,r,n,a){var s;return{matchedTraffic:e.find((function(e){return!!(0,i.allGroupSegmentsAreMatched)("string"==typeof e.segments&&"*"!==e.segments?JSON.parse(e.segments):e.segments,t,n)&&!!(s=o(e,r))})),matchedAllocation:s}}function u(e,t,r){if(e.force)return e.force.find((function(e){return e.conditions?(0,n.allConditionsAreMatched)(e.conditions,t):!!e.segments&&(0,i.allGroupSegmentsAreMatched)(e.segments,t,r)}))}t.getStartEndFromRange=a,t.getMatchedAllocation=o,t.getMatchedTrafficAndAllocation=s,t.getForcedVariation=function(e,t,r){var i=u(e,t,r);if(i&&i.variation)return e.variations.find((function(e){return e.value===i.variation}))},t.getBucketedVariation=function(e,t,r,i,n){var a=s(e.traffic,t,r,i),o=a.matchedTraffic,u=a.matchedAllocation;if(o){if(o.variation){var f=e.variations.find((function(e){return e.value===o.variation}));if(f)return n.debug("using variation from rule",{featureKey:e.key,variation:f.value,ruleKey:o.key}),f}if(u){var l=u.variation,c=e.variations.find((function(e){return e.value===l}));if(c)return n.debug("matched variation",{featureKey:e.key,variation:c.value,bucketValue:r}),c;n.debug("no matched variation found",{featureKey:e.key,variation:l,bucketValue:r})}else n.debug("no matched allocation found",{featureKey:e.key,bucketValue:r})}else n.debug("no matched rule found",{featureKey:e.key,bucketValue:r})},t.getForcedVariableValue=function(e,t,r,i){var n=u(e,r,i);if(n&&n.variables){var a=n.variables[t.key];return"string"==typeof a&&"json"===t.type?JSON.parse(a):a}},t.getBucketedVariableValue=function(e,t,r,a,o,u){var f,l=s(e.traffic,r,a,o),c=l.matchedTraffic,d=l.matchedAllocation;if(c){var g=t.key;if(c.variables&&void 0!==c.variables[g])return u.debug("using variable from rule",{featureKey:e.key,variableKey:g,bucketValue:a}),c.variables[g];if(d){var h=d.variation,v=e.variations.find((function(e){return e.value===h}));if(v){var y=null===(f=v.variables)||void 0===f?void 0:f.find((function(e){return e.key===g}));if(!y)return u.debug("using default value as variation has no variable",{featureKey:e.key,variableKey:g,variation:h,bucketValue:a}),"json"===t.type?JSON.parse(t.defaultValue):t.defaultValue;if(y.overrides){var p=y.overrides.find((function(e){return e.conditions?(0,n.allConditionsAreMatched)("string"==typeof e.conditions?JSON.parse(e.conditions):e.conditions,r):!!e.segments&&(0,i.allGroupSegmentsAreMatched)("string"==typeof e.segments&&"*"!==e.segments?JSON.parse(e.segments):e.segments,r,o)}));if(p)return u.debug("using override value from variation",{feature:e.key,variableKey:g,variation:h,bucketValue:a}),"json"===t.type?JSON.parse(p.value):p.value}return u.debug("using value from variation",{feature:e.key,variableKey:g,variation:h,bucketValue:a}),"json"===t.type?JSON.parse(y.value):y.value}u.debug("no matched variation found",{feature:e.key,variableKey:g,variation:h,bucketValue:a})}else u.debug("no matched allocation found",{featureKey:e.key,variableKey:g,bucketValue:a})}else u.debug("no matched rule found",{featureKey:e.key,variableKey:t.key,bucketValue:a})}},97:function(e,t,r){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,r,i){void 0===i&&(i=r);var n=Object.getOwnPropertyDescriptor(t,r);n&&!("get"in n?!t.__esModule:n.writable||n.configurable)||(n={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,n)}:function(e,t,r,i){void 0===i&&(i=r),e[i]=t[r]}),n=this&&this.__exportStar||function(e,t){for(var r in e)"default"===r||Object.prototype.hasOwnProperty.call(t,r)||i(t,e,r)};Object.defineProperty(t,"__esModule",{value:!0}),t.getStartEndFromRange=void 0,n(r(725),t),n(r(681),t),n(r(687),t);var a=r(522);Object.defineProperty(t,"getStartEndFromRange",{enumerable:!0,get:function(){return a.getStartEndFromRange}})},681:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.createInstance=t.FeaturevisorInstance=t.getValueByType=void 0;var i=r(687),n=r(913),a=r(186),o=r(725),s=r(522),u=".",f={schemaVersion:"1",revision:"unknown",attributes:[],segments:[],features:[]};function l(e,t){return t?t(e):fetch(e).then((function(e){return e.json()}))}function c(e,t){if(void 0!==e)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}}t.getValueByType=c;var d=function(){function e(e){var t=this;this.bucketKeySeparator=e.bucketKeySeparator||u,this.configureBucketKey=e.configureBucketKey,this.configureBucketValue=e.configureBucketValue,this.datafileUrl=e.datafileUrl,this.handleDatafileFetch=e.handleDatafileFetch,this.initialFeatures=e.initialFeatures,this.interceptAttributes=e.interceptAttributes,this.logger=e.logger||(0,i.createLogger)(),this.refreshInterval=e.refreshInterval,this.stickyFeatures=e.stickyFeatures,this.emitter=new a.Emitter,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);var r=this.emitter.addListener.bind(this.emitter);this.on=r,this.addListener=r;var n=this.emitter.removeListener.bind(this.emitter);if(this.off=n,this.removeListener=n,this.removeAllListeners=this.emitter.removeAllListeners.bind(this.emitter),e.datafileUrl)this.setDatafile(e.datafile||f),l(e.datafileUrl,e.handleDatafileFetch).then((function(e){t.setDatafile(e),t.statuses.ready=!0,t.emitter.emit("ready"),t.refreshInterval&&t.startRefreshing()})).catch((function(e){t.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((function(){t.emitter.emit("ready")}),0)}}return e.prototype.setDatafile=function(e){try{this.datafileReader=new n.DatafileReader("string"==typeof e?JSON.parse(e):e)}catch(e){this.logger.error("could not parse datafile",{error:e})}},e.prototype.setStickyFeatures=function(e){this.stickyFeatures=e},e.prototype.getRevision=function(){return this.datafileReader.getRevision()},e.prototype.getFeature=function(e){return"string"==typeof e?this.datafileReader.getFeature(e):e},e.prototype.getBucketKey=function(e,t){var r,i,n=e.key;if("string"==typeof e.bucketBy)r="plain",i=[e.bucketBy];else if(Array.isArray(e.bucketBy))r="and",i=e.bucketBy;else{if("object"!=typeof e.bucketBy||!Array.isArray(e.bucketBy.or))throw this.logger.error("invalid bucketBy",{featureKey:n,bucketBy:e.bucketBy}),new Error("invalid bucketBy");r="or",i=e.bucketBy.or}var a=[];i.forEach((function(e){var i=t[e];void 0!==i&&("plain"===r||"and"===r||0===a.length)&&a.push(i)})),a.push(n);var o=a.join(this.bucketKeySeparator);return this.configureBucketKey?this.configureBucketKey(e,t,o):o},e.prototype.getBucketValue=function(e,t){var r=this.getBucketKey(e,t),i=(0,o.getBucketedNumber)(r);return this.configureBucketValue?this.configureBucketValue(e,t,i):i},e.prototype.isReady=function(){return this.statuses.ready},e.prototype.refresh=function(){var e=this;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((function(t){var r=e.getRevision()!==t.revision;e.setDatafile(t),e.logger.info("refreshed datafile"),e.emitter.emit("refresh"),r&&e.emitter.emit("update"),e.statuses.refreshInProgress=!1})).catch((function(t){e.logger.error("failed to refresh datafile",{error:t}),e.statuses.refreshInProgress=!1}))):this.logger.error("cannot refresh since `datafileUrl` is not provided")},e.prototype.startRefreshing=function(){var e=this;return this.datafileUrl?this.intervalId?this.logger.warn("refreshing has already started"):this.refreshInterval?void(this.intervalId=setInterval((function(){e.refresh()}),1e3*this.refreshInterval)):this.logger.warn("no `refreshInterval` option provided"):this.logger.error("cannot start refreshing since `datafileUrl` is not provided")},e.prototype.stopRefreshing=function(){if(!this.intervalId)return this.logger.warn("refreshing has not started yet");clearInterval(this.intervalId)},e.prototype.getVariation=function(e,t){void 0===t&&(t={});try{var r,i="string"==typeof e?e:e.key;if(this.stickyFeatures&&this.stickyFeatures[i]&&void 0!==(r=this.stickyFeatures[i].variation))return this.logger.debug("using sticky variation",{featureKey:i,variation:r}),r;if(this.statuses&&!this.statuses.ready&&this.initialFeatures&&this.initialFeatures[i]&&void 0!==(r=this.initialFeatures[i].variation))return this.logger.debug("using initial variation",{featureKey:i,variation:r}),r;var n=this.getFeature(e);if(!n)return void this.logger.warn("feature not found in datafile",{featureKey:e});var a=this.interceptAttributes?this.interceptAttributes(t):t,o=(0,s.getForcedVariation)(n,a,this.datafileReader);if(o)return this.logger.debug("forced variation found",{featureKey:e,variation:o.value}),o.value;var u=this.getBucketValue(n,a),f=(0,s.getBucketedVariation)(n,a,u,this.datafileReader,this.logger);return f?f.value:(this.logger.debug("using default variation",{featureKey:e,bucketValue:u,variation:n.defaultVariation}),n.defaultVariation)}catch(t){return void this.logger.error("getVariation",{featureKey:e,error:t})}},e.prototype.getVariationBoolean=function(e,t){return void 0===t&&(t={}),c(this.getVariation(e,t),"boolean")},e.prototype.getVariationString=function(e,t){return void 0===t&&(t={}),c(this.getVariation(e,t),"string")},e.prototype.getVariationInteger=function(e,t){return void 0===t&&(t={}),c(this.getVariation(e,t),"integer")},e.prototype.getVariationDouble=function(e,t){return void 0===t&&(t={}),c(this.getVariation(e,t),"double")},e.prototype.activate=function(e,t){void 0===t&&(t={});try{var r=this.getVariation(e,t);if(void 0===r)return;var i=this.interceptAttributes?this.interceptAttributes(t):t,n={};return this.datafileReader.getAllAttributes().filter((function(e){return!0===e.capture})).forEach((function(e){void 0!==i[e.key]&&(n[e.key]=t[e.key])})),this.emitter.emit("activation",e,r,i,n),r}catch(t){return void this.logger.error("activate",{featureKey:e,error:t})}},e.prototype.activateBoolean=function(e,t){return void 0===t&&(t={}),c(this.activate(e,t),"boolean")},e.prototype.activateString=function(e,t){return void 0===t&&(t={}),c(this.activate(e,t),"string")},e.prototype.activateInteger=function(e,t){return void 0===t&&(t={}),c(this.activate(e,t),"integer")},e.prototype.activateDouble=function(e,t){return void 0===t&&(t={}),c(this.activate(e,t),"double")},e.prototype.getVariable=function(e,t,r){void 0===r&&(r={});try{var i,n="string"==typeof e?e:e.key;if(this.stickyFeatures&&this.stickyFeatures[n]&&this.stickyFeatures[n].variables&&void 0!==(i=this.stickyFeatures[n].variables[t]))return this.logger.debug("using sticky variable",{featureKey:n,variableKey:t}),i;if(this.statuses&&!this.statuses.ready&&this.initialFeatures&&this.initialFeatures[n]&&this.initialFeatures[n].variables&&void 0!==(i=this.initialFeatures[n].variables[t]))return this.logger.debug("using initial variable",{featureKey:n,variableKey:t}),i;var a=this.getFeature(e);if(!a)return void this.logger.warn("feature not found in datafile",{featureKey:e,variableKey:t});var o=Array.isArray(a.variablesSchema)?a.variablesSchema.find((function(e){return e.key===t})):void 0;if(!o)return void this.logger.warn("variable schema not found",{featureKey:e,variableKey:t});var u=this.interceptAttributes?this.interceptAttributes(r):r,f=(0,s.getForcedVariableValue)(a,o,u,this.datafileReader);if(void 0!==f)return this.logger.debug("forced variable value found",{featureKey:e,variableKey:t}),f;var l=this.getBucketValue(a,u);return(0,s.getBucketedVariableValue)(a,o,u,l,this.datafileReader,this.logger)}catch(r){return void this.logger.error("getVariable",{featureKey:e,variableKey:t,error:r})}},e.prototype.getVariableBoolean=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"boolean")},e.prototype.getVariableString=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"string")},e.prototype.getVariableInteger=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"integer")},e.prototype.getVariableDouble=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"double")},e.prototype.getVariableArray=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"array")},e.prototype.getVariableObject=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"object")},e.prototype.getVariableJSON=function(e,t,r){return void 0===r&&(r={}),c(this.getVariable(e,t,r),"json")},e}();t.FeaturevisorInstance=d,t.createInstance=function(e){return new d(e)}},687:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.createLogger=t.Logger=t.defaultLogHandler=t.defaultLogLevels=t.loggerPrefix=void 0,t.loggerPrefix="[Featurevisor]",t.defaultLogLevels=["warn","error"],t.defaultLogHandler=function(e,r,i){switch(void 0===i&&(i={}),e){case"debug":console.log(t.loggerPrefix,r,i);case"info":console.info(t.loggerPrefix,r,i);case"warn":console.warn(t.loggerPrefix,r,i);case"error":console.error(t.loggerPrefix,r,i)}};var r=function(){function e(e){this.levels=e.levels,this.handle=e.handler}return e.prototype.setLevels=function(e){this.levels=e},e.prototype.log=function(e,t,r){-1!==this.levels.indexOf(e)&&this.handle(e,t,r)},e.prototype.debug=function(e,t){this.log("debug",e,t)},e.prototype.info=function(e,t){this.log("info",e,t)},e.prototype.warn=function(e,t){this.log("warn",e,t)},e.prototype.error=function(e,t){this.log("error",e,t)},e}();t.Logger=r,t.createLogger=function(e){void 0===e&&(e={});var i=e.levels||t.defaultLogLevels,n=e.handler||t.defaultLogHandler;return new r({levels:i,handler:n})}},590:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.allGroupSegmentsAreMatched=t.segmentIsMatched=void 0;var i=r(243);function n(e,t){return(0,i.allConditionsAreMatched)(e.conditions,t)}t.segmentIsMatched=n,t.allGroupSegmentsAreMatched=function e(t,r,i){if("*"===t)return!0;if("string"==typeof t){var a=i.getSegment(t);return!!a&&n(a,r)}if("object"==typeof t){if("and"in t&&Array.isArray(t.and))return t.and.every((function(t){return e(t,r,i)}));if("or"in t&&Array.isArray(t.or))return t.or.some((function(t){return e(t,r,i)}));if("not"in t&&Array.isArray(t.not))return t.not.every((function(t){return!1===e(t,r,i)}))}return!!Array.isArray(t)&&t.every((function(t){return e(t,r,i)}))}}},t={};function r(i){var n=t[i];if(void 0!==n)return n.exports;var a=t[i]={exports:{}};return e[i].call(a.exports,a,a.exports,r),a.exports}return r.d=(e,t)=>{for(var i in t)r.o(t,i)&&!r.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r(97)})())); | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,2 @@ | ||
import { Attributes, BucketValue, DatafileContent, Feature, FeatureKey, InitialFeatures, StickyFeatures, VariableType, VariableValue, VariationType, VariationValue } from "@featurevisor/types"; | ||
import { Attributes, BucketKey, BucketValue, DatafileContent, Feature, FeatureKey, InitialFeatures, StickyFeatures, VariableType, VariableValue, VariationType, VariationValue } from "@featurevisor/types"; | ||
import { Logger } from "./logger"; | ||
@@ -6,2 +6,3 @@ import { Emitter } from "./emitter"; | ||
export type ActivationCallback = (featureName: string, variation: VariationValue, attributes: Attributes, captureAttributes: Attributes) => void; | ||
export type ConfigureBucketKey = (feature: any, attributes: any, bucketKey: BucketKey) => BucketKey; | ||
export type ConfigureBucketValue = (feature: any, attributes: any, bucketValue: BucketValue) => BucketValue; | ||
@@ -14,2 +15,3 @@ export interface Statuses { | ||
bucketKeySeparator?: string; | ||
configureBucketKey?: ConfigureBucketKey; | ||
configureBucketValue?: ConfigureBucketValue; | ||
@@ -35,2 +37,3 @@ datafile?: DatafileContent | string; | ||
private bucketKeySeparator; | ||
private configureBucketKey?; | ||
private configureBucketValue?; | ||
@@ -59,2 +62,7 @@ private datafileUrl?; | ||
/** | ||
* Bucketing | ||
*/ | ||
private getBucketKey; | ||
private getBucketValue; | ||
/** | ||
* Statuses | ||
@@ -70,7 +78,2 @@ */ | ||
/** | ||
* Bucketing | ||
*/ | ||
private getBucketKey; | ||
private getBucketValue; | ||
/** | ||
* Variation | ||
@@ -77,0 +80,0 @@ */ |
@@ -47,2 +47,3 @@ import { createLogger } from "./logger"; | ||
this.bucketKeySeparator = options.bucketKeySeparator || DEFAULT_BUCKET_KEY_SEPARATOR; | ||
this.configureBucketKey = options.configureBucketKey; | ||
this.configureBucketValue = options.configureBucketValue; | ||
@@ -130,2 +131,56 @@ this.datafileUrl = options.datafileUrl; | ||
/** | ||
* Bucketing | ||
*/ | ||
FeaturevisorInstance.prototype.getBucketKey = function (feature, attributes) { | ||
var featureKey = feature.key; | ||
var type; | ||
var attributeKeys; | ||
if (typeof feature.bucketBy === "string") { | ||
type = "plain"; | ||
attributeKeys = [feature.bucketBy]; | ||
} | ||
else if (Array.isArray(feature.bucketBy)) { | ||
type = "and"; | ||
attributeKeys = feature.bucketBy; | ||
} | ||
else if (typeof feature.bucketBy === "object" && Array.isArray(feature.bucketBy.or)) { | ||
type = "or"; | ||
attributeKeys = feature.bucketBy.or; | ||
} | ||
else { | ||
this.logger.error("invalid bucketBy", { featureKey: featureKey, bucketBy: feature.bucketBy }); | ||
throw new Error("invalid bucketBy"); | ||
} | ||
var bucketKey = []; | ||
attributeKeys.forEach(function (attributeKey) { | ||
var attributeValue = attributes[attributeKey]; | ||
if (typeof attributeValue === "undefined") { | ||
return; | ||
} | ||
if (type === "plain" || type === "and") { | ||
bucketKey.push(attributeValue); | ||
} | ||
else { | ||
// or | ||
if (bucketKey.length === 0) { | ||
bucketKey.push(attributeValue); | ||
} | ||
} | ||
}); | ||
bucketKey.push(featureKey); | ||
var result = bucketKey.join(this.bucketKeySeparator); | ||
if (this.configureBucketKey) { | ||
return this.configureBucketKey(feature, attributes, result); | ||
} | ||
return result; | ||
}; | ||
FeaturevisorInstance.prototype.getBucketValue = function (feature, attributes) { | ||
var bucketKey = this.getBucketKey(feature, attributes); | ||
var value = getBucketedNumber(bucketKey); | ||
if (this.configureBucketValue) { | ||
return this.configureBucketValue(feature, attributes, value); | ||
} | ||
return value; | ||
}; | ||
/** | ||
* Statuses | ||
@@ -189,27 +244,2 @@ */ | ||
/** | ||
* Bucketing | ||
*/ | ||
FeaturevisorInstance.prototype.getBucketKey = function (feature, attributes) { | ||
var featureKey = feature.key; | ||
var attributeKeys = typeof feature.bucketBy === "string" ? [feature.bucketBy] : feature.bucketBy; | ||
var bucketKey = []; | ||
attributeKeys.forEach(function (attributeKey) { | ||
var attributeValue = attributes[attributeKey]; | ||
if (typeof attributeValue === "undefined") { | ||
return; | ||
} | ||
bucketKey.push(attributeValue); | ||
}); | ||
bucketKey.push(featureKey); | ||
return bucketKey.join(this.bucketKeySeparator); | ||
}; | ||
FeaturevisorInstance.prototype.getBucketValue = function (feature, attributes) { | ||
var bucketKey = this.getBucketKey(feature, attributes); | ||
var value = getBucketedNumber(bucketKey); | ||
if (this.configureBucketValue) { | ||
return this.configureBucketValue(feature, attributes, value); | ||
} | ||
return value; | ||
}; | ||
/** | ||
* Variation | ||
@@ -216,0 +246,0 @@ */ |
{ | ||
"name": "@featurevisor/sdk", | ||
"version": "0.27.0", | ||
"version": "0.28.0", | ||
"description": "Featurevisor SDK for Node.js and the browser", | ||
@@ -45,7 +45,7 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"@featurevisor/types": "^0.27.0", | ||
"@featurevisor/types": "^0.28.0", | ||
"compare-versions": "^6.0.0-rc.1", | ||
"murmurhash": "^2.0.1" | ||
}, | ||
"gitHead": "ed546c01c10cc8fa9df9a9c8c6bc622af90c67f8" | ||
"gitHead": "349f2c213ee65025a4ee4cd6697fa45b8b5fd9eb" | ||
} |
@@ -11,2 +11,3 @@ # @featurevisor/sdk <!-- omit in toc --> | ||
- [`bucketKeySeparator`](#bucketkeyseparator) | ||
- [`configureBucketKey`](#configurebucketkey) | ||
- [`configureBucketValue`](#configurebucketvalue) | ||
@@ -64,2 +65,17 @@ - [`datafile`](#datafile) | ||
### `configureBucketKey` | ||
- Type: `function` | ||
- Required: no | ||
Use it to take over bucketing key generation process. | ||
```js | ||
const sdk = createInstance({ | ||
configureBucketKey: (feature, attributes, bucketKey) => { | ||
return bucketKey; | ||
} | ||
}); | ||
``` | ||
### `configureBucketValue` | ||
@@ -66,0 +82,0 @@ |
@@ -47,2 +47,143 @@ import { DatafileContent } from "@featurevisor/types"; | ||
it("should configure plain bucketBy", function () { | ||
let capturedBucketKey = ""; | ||
const sdk = createInstance({ | ||
datafile: { | ||
schemaVersion: "1", | ||
revision: "1.0", | ||
features: [ | ||
{ | ||
key: "test", | ||
defaultVariation: false, | ||
bucketBy: "userId", | ||
variations: [{ value: true }, { value: false }], | ||
traffic: [ | ||
{ | ||
key: "1", | ||
segments: "*", | ||
percentage: 100000, | ||
allocation: [ | ||
{ variation: true, range: { start: 0, end: 100000 } }, | ||
{ variation: false, range: { start: 0, end: 0 } }, | ||
], | ||
}, | ||
], | ||
}, | ||
], | ||
attributes: [], | ||
segments: [], | ||
}, | ||
configureBucketKey: function (feature, attributes, bucketKey) { | ||
capturedBucketKey = bucketKey; | ||
return bucketKey; | ||
}, | ||
}); | ||
const variation = sdk.getVariation("test", { | ||
userId: "123", | ||
}); | ||
expect(variation).toEqual(true); | ||
expect(capturedBucketKey).toEqual("123.test"); | ||
}); | ||
it("should configure and bucketBy", function () { | ||
let capturedBucketKey = ""; | ||
const sdk = createInstance({ | ||
datafile: { | ||
schemaVersion: "1", | ||
revision: "1.0", | ||
features: [ | ||
{ | ||
key: "test", | ||
defaultVariation: false, | ||
bucketBy: ["userId", "organizationId"], | ||
variations: [{ value: true }, { value: false }], | ||
traffic: [ | ||
{ | ||
key: "1", | ||
segments: "*", | ||
percentage: 100000, | ||
allocation: [ | ||
{ variation: true, range: { start: 0, end: 100000 } }, | ||
{ variation: false, range: { start: 0, end: 0 } }, | ||
], | ||
}, | ||
], | ||
}, | ||
], | ||
attributes: [], | ||
segments: [], | ||
}, | ||
configureBucketKey: function (feature, attributes, bucketKey) { | ||
capturedBucketKey = bucketKey; | ||
return bucketKey; | ||
}, | ||
}); | ||
const variation = sdk.getVariation("test", { | ||
userId: "123", | ||
organizationId: "456", | ||
}); | ||
expect(variation).toEqual(true); | ||
expect(capturedBucketKey).toEqual("123.456.test"); | ||
}); | ||
it("should configure or bucketBy", function () { | ||
let capturedBucketKey = ""; | ||
const sdk = createInstance({ | ||
datafile: { | ||
schemaVersion: "1", | ||
revision: "1.0", | ||
features: [ | ||
{ | ||
key: "test", | ||
defaultVariation: false, | ||
bucketBy: { or: ["userId", "deviceId"] }, | ||
variations: [{ value: true }, { value: false }], | ||
traffic: [ | ||
{ | ||
key: "1", | ||
segments: "*", | ||
percentage: 100000, | ||
allocation: [ | ||
{ variation: true, range: { start: 0, end: 100000 } }, | ||
{ variation: false, range: { start: 0, end: 0 } }, | ||
], | ||
}, | ||
], | ||
}, | ||
], | ||
attributes: [], | ||
segments: [], | ||
}, | ||
configureBucketKey: function (feature, attributes, bucketKey) { | ||
capturedBucketKey = bucketKey; | ||
return bucketKey; | ||
}, | ||
}); | ||
expect( | ||
sdk.getVariation("test", { | ||
userId: "123", | ||
deviceId: "456", | ||
}), | ||
).toEqual(true); | ||
expect(capturedBucketKey).toEqual("123.test"); | ||
expect( | ||
sdk.getVariation("test", { | ||
deviceId: "456", | ||
}), | ||
).toEqual(true); | ||
expect(capturedBucketKey).toEqual("456.test"); | ||
}); | ||
it("should intercept attributes", function () { | ||
@@ -49,0 +190,0 @@ let intercepted = false; |
@@ -37,2 +37,4 @@ import { | ||
export type ConfigureBucketKey = (feature, attributes, bucketKey: BucketKey) => BucketKey; | ||
export type ConfigureBucketValue = (feature, attributes, bucketValue: BucketValue) => BucketValue; | ||
@@ -49,2 +51,3 @@ | ||
bucketKeySeparator?: string; | ||
configureBucketKey?: ConfigureBucketKey; | ||
configureBucketValue?: ConfigureBucketValue; | ||
@@ -116,2 +119,3 @@ datafile?: DatafileContent | string; | ||
private bucketKeySeparator: string; | ||
private configureBucketKey?: ConfigureBucketKey; | ||
private configureBucketValue?: ConfigureBucketValue; | ||
@@ -142,2 +146,3 @@ private datafileUrl?: string; | ||
this.bucketKeySeparator = options.bucketKeySeparator || DEFAULT_BUCKET_KEY_SEPARATOR; | ||
this.configureBucketKey = options.configureBucketKey; | ||
this.configureBucketValue = options.configureBucketValue; | ||
@@ -244,2 +249,68 @@ this.datafileUrl = options.datafileUrl; | ||
/** | ||
* Bucketing | ||
*/ | ||
private getBucketKey(feature: Feature, attributes: Attributes): BucketKey { | ||
const featureKey = feature.key; | ||
let type; | ||
let attributeKeys; | ||
if (typeof feature.bucketBy === "string") { | ||
type = "plain"; | ||
attributeKeys = [feature.bucketBy]; | ||
} else if (Array.isArray(feature.bucketBy)) { | ||
type = "and"; | ||
attributeKeys = feature.bucketBy; | ||
} else if (typeof feature.bucketBy === "object" && Array.isArray(feature.bucketBy.or)) { | ||
type = "or"; | ||
attributeKeys = feature.bucketBy.or; | ||
} else { | ||
this.logger.error("invalid bucketBy", { featureKey, bucketBy: feature.bucketBy }); | ||
throw new Error("invalid bucketBy"); | ||
} | ||
const bucketKey: AttributeValue[] = []; | ||
attributeKeys.forEach((attributeKey) => { | ||
const attributeValue = attributes[attributeKey]; | ||
if (typeof attributeValue === "undefined") { | ||
return; | ||
} | ||
if (type === "plain" || type === "and") { | ||
bucketKey.push(attributeValue); | ||
} else { | ||
// or | ||
if (bucketKey.length === 0) { | ||
bucketKey.push(attributeValue); | ||
} | ||
} | ||
}); | ||
bucketKey.push(featureKey); | ||
const result = bucketKey.join(this.bucketKeySeparator); | ||
if (this.configureBucketKey) { | ||
return this.configureBucketKey(feature, attributes, result); | ||
} | ||
return result; | ||
} | ||
private getBucketValue(feature: Feature, attributes: Attributes): BucketValue { | ||
const bucketKey = this.getBucketKey(feature, attributes); | ||
const value = getBucketedNumber(bucketKey); | ||
if (this.configureBucketValue) { | ||
return this.configureBucketValue(feature, attributes, value); | ||
} | ||
return value; | ||
} | ||
/** | ||
* Statuses | ||
@@ -317,40 +388,2 @@ */ | ||
/** | ||
* Bucketing | ||
*/ | ||
private getBucketKey(feature: Feature, attributes: Attributes): BucketKey { | ||
const featureKey = feature.key; | ||
const attributeKeys = | ||
typeof feature.bucketBy === "string" ? [feature.bucketBy] : feature.bucketBy; | ||
const bucketKey: AttributeValue[] = []; | ||
attributeKeys.forEach((attributeKey) => { | ||
const attributeValue = attributes[attributeKey]; | ||
if (typeof attributeValue === "undefined") { | ||
return; | ||
} | ||
bucketKey.push(attributeValue); | ||
}); | ||
bucketKey.push(featureKey); | ||
return bucketKey.join(this.bucketKeySeparator); | ||
} | ||
private getBucketValue(feature: Feature, attributes: Attributes): BucketValue { | ||
const bucketKey = this.getBucketKey(feature, attributes); | ||
const value = getBucketedNumber(bucketKey); | ||
if (this.configureBucketValue) { | ||
return this.configureBucketValue(feature, attributes, value); | ||
} | ||
return value; | ||
} | ||
/** | ||
* Variation | ||
@@ -357,0 +390,0 @@ */ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
293720
3835
385
+ Added@featurevisor/types@0.28.0(transitive)
- Removed@featurevisor/types@0.27.0(transitive)
Updated@featurevisor/types@^0.28.0