unleash-proxy-client
Advanced tools
Comparing version 3.2.0 to 3.3.0-alpha.1
@@ -28,2 +28,3 @@ import { TinyEmitter } from 'tiny-emitter'; | ||
fetch?: any; | ||
createAbortController?: () => AbortController; | ||
bootstrap?: IToggle[]; | ||
@@ -58,2 +59,3 @@ bootstrapOverride?: boolean; | ||
SENT: string; | ||
RECOVERED: string; | ||
}; | ||
@@ -74,2 +76,4 @@ export declare const resolveFetch: () => typeof fetch | undefined; | ||
private fetch; | ||
private createAbortController?; | ||
private abortController?; | ||
private bootstrap?; | ||
@@ -83,3 +87,4 @@ private bootstrapOverride; | ||
private started; | ||
constructor({ storageProvider, url, clientKey, disableRefresh, refreshInterval, metricsInterval, disableMetrics, appName, environment, context, fetch, bootstrap, bootstrapOverride, headerName, customHeaders, impressionDataAll, usePOSTrequests, }: IConfig); | ||
private sdkState; | ||
constructor({ storageProvider, url, clientKey, disableRefresh, refreshInterval, metricsInterval, disableMetrics, appName, environment, context, fetch, createAbortController, bootstrap, bootstrapOverride, headerName, customHeaders, impressionDataAll, usePOSTrequests, }: IConfig); | ||
getAllToggles(): IToggle[]; | ||
@@ -86,0 +91,0 @@ isEnabled(toggleName: string): boolean; |
@@ -1,2 +0,2 @@ | ||
var t=function(e,n){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},t(e,n)};var e=function(){return e=Object.assign||function(t){for(var e,n=1,r=arguments.length;n<r;n++)for(var i in e=arguments[n])Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t},e.apply(this,arguments)};function n(t,e,n,r){return new(n||(n=Promise))((function(i,o){function s(t){try{c(r.next(t))}catch(t){o(t)}}function a(t){try{c(r.throw(t))}catch(t){o(t)}}function c(t){var e;t.done?i(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(s,a)}c((r=r.apply(t,e||[])).next())}))}function r(t,e){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(a){return function(c){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;o&&(o=0,a[0]&&(s=0)),s;)try{if(n=1,r&&(i=2&a[0]?r.return:a[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,a[1])).done)return i;switch(r=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return s.label++,{value:a[1],done:!1};case 5:s.label++,r=a[1],a=[0];continue;case 7:a=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]<i[3])){s.label=a[1];break}if(6===a[0]&&s.label<i[1]){s.label=i[1],i=a;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(a);break}i[2]&&s.ops.pop(),s.trys.pop();continue}a=e.call(t,s)}catch(t){a=[6,t],r=0}finally{n=i=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,c])}}}"function"==typeof SuppressedError&&SuppressedError;var i={exports:{}};function o(){}o.prototype={on:function(t,e,n){var r=this.e||(this.e={});return(r[t]||(r[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){var r=this;function i(){r.off(t,i),e.apply(n,arguments)}return i._=e,this.on(t,i,n)},emit:function(t){for(var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),r=0,i=n.length;r<i;r++)n[r].fn.apply(n[r].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),r=n[t],i=[];if(r&&e)for(var o=0,s=r.length;o<s;o++)r[o].fn!==e&&r[o].fn._!==e&&i.push(r[o]);return i.length?n[t]=i:delete n[t],this}},i.exports=o;var s=i.exports.TinyEmitter=o,a=function(t){var e=t[1];return null!=e},c=function(){},u=function(){function t(t){var e=t.onError,n=t.onSent,r=t.appName,i=t.metricsInterval,o=t.disableMetrics,s=void 0!==o&&o,a=t.url,u=t.clientKey,h=t.fetch,l=t.headerName,p=t.customHeaders,f=void 0===p?{}:p;this.onError=e,this.onSent=n||c,this.disabled=s,this.metricsInterval=1e3*i,this.appName=r,this.url=a instanceof URL?a:new URL(a),this.clientKey=u,this.bucket=this.createEmptyBucket(),this.fetch=h,this.headerName=l,this.customHeaders=f}return t.prototype.start=function(){var t=this;if(this.disabled)return!1;"number"==typeof this.metricsInterval&&this.metricsInterval>0&&setTimeout((function(){t.startTimer(),t.sendMetrics()}),2e3)},t.prototype.stop=function(){this.timer&&(clearTimeout(this.timer),delete this.timer)},t.prototype.createEmptyBucket=function(){return{start:new Date,stop:null,toggles:{}}},t.prototype.getHeaders=function(){var t,e=((t={})[this.headerName]=this.clientKey,t.Accept="application/json",t["Content-Type"]="application/json",t);return Object.entries(this.customHeaders).filter(a).forEach((function(t){var n=t[0],r=t[1];return e[n]=r})),e},t.prototype.sendMetrics=function(){return n(this,void 0,void 0,(function(){var t,e,n;return r(this,(function(r){switch(r.label){case 0:if(t="".concat(this.url,"/client/metrics"),e=this.getPayload(),this.bucketIsEmpty(e))return[2];r.label=1;case 1:return r.trys.push([1,3,,4]),[4,this.fetch(t,{cache:"no-cache",method:"POST",headers:this.getHeaders(),body:JSON.stringify(e)})];case 2:return r.sent(),this.onSent(e),[3,4];case 3:return n=r.sent(),console.error("Unleash: unable to send feature metrics",n),this.onError(n),[3,4];case 4:return[2]}}))}))},t.prototype.count=function(t,e){return!(this.disabled||!this.bucket)&&(this.assertBucket(t),this.bucket.toggles[t][e?"yes":"no"]++,!0)},t.prototype.countVariant=function(t,e){return!(this.disabled||!this.bucket)&&(this.assertBucket(t),this.bucket.toggles[t].variants[e]?this.bucket.toggles[t].variants[e]+=1:this.bucket.toggles[t].variants[e]=1,!0)},t.prototype.assertBucket=function(t){if(this.disabled||!this.bucket)return!1;this.bucket.toggles[t]||(this.bucket.toggles[t]={yes:0,no:0,variants:{}})},t.prototype.startTimer=function(){var t=this;this.timer=setInterval((function(){t.sendMetrics()}),this.metricsInterval)},t.prototype.bucketIsEmpty=function(t){return 0===Object.keys(t.bucket.toggles).length},t.prototype.getPayload=function(){var t=e(e({},this.bucket),{stop:new Date});return this.bucket=this.createEmptyBucket(),{bucket:t,appName:this.appName,instanceId:"browser"}},t}(),h=function(){function t(){this.store=new Map}return t.prototype.save=function(t,e){return n(this,void 0,void 0,(function(){return r(this,(function(n){return this.store.set(t,e),[2]}))}))},t.prototype.get=function(t){return n(this,void 0,void 0,(function(){return r(this,(function(e){return[2,this.store.get(t)]}))}))},t}(),l=function(){function t(){this.prefix="unleash:repository"}return t.prototype.save=function(t,e){return n(this,void 0,void 0,(function(){var n,i;return r(this,(function(r){n=JSON.stringify(e),i="".concat(this.prefix,":").concat(t);try{window.localStorage.setItem(i,n)}catch(t){console.error(t)}return[2]}))}))},t.prototype.get=function(t){try{var e="".concat(this.prefix,":").concat(t),n=window.localStorage.getItem(e);return n?JSON.parse(n):void 0}catch(t){console.error(t)}},t}();let p;const f=new Uint8Array(16);function d(){if(!p&&(p="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!p))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return p(f)}const v=[];for(let t=0;t<256;++t)v.push((t+256).toString(16).slice(1));var m={randomUUID:"undefined"!=typeof crypto&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};function y(t,e,n){if(m.randomUUID&&!e&&!t)return m.randomUUID();const r=(t=t||{}).random||(t.rng||d)();if(r[6]=15&r[6]|64,r[8]=63&r[8]|128,e){n=n||0;for(let t=0;t<16;++t)e[n+t]=r[t];return e}return function(t,e=0){return v[t[e+0]]+v[t[e+1]]+v[t[e+2]]+v[t[e+3]]+"-"+v[t[e+4]]+v[t[e+5]]+"-"+v[t[e+6]]+v[t[e+7]]+"-"+v[t[e+8]]+v[t[e+9]]+"-"+v[t[e+10]]+v[t[e+11]]+v[t[e+12]]+v[t[e+13]]+v[t[e+14]]+v[t[e+15]]}(r)}var g=function(){function t(){}return t.prototype.generateEventId=function(){return y()},t.prototype.createImpressionEvent=function(t,n,r,i,o,s){var a=this.createBaseEvent(t,n,r,i,o);return s?e(e({},a),{variant:s}):a},t.prototype.createBaseEvent=function(t,e,n,r,i){return{eventType:r,eventId:this.generateEventId(),context:t,enabled:e,featureName:n,impressionData:i}},t}(),b=["userId","sessionId","remoteAddress"],w={INIT:"initialized",ERROR:"error",READY:"ready",UPDATE:"update",IMPRESSION:"impression",SENT:"sent"},E="isEnabled",I="getVariant",x={name:"disabled",enabled:!1,feature_enabled:!1},R="repo",S=function(){try{if("undefined"!=typeof window&&"fetch"in window)return fetch.bind(window);if("fetch"in globalThis)return fetch.bind(globalThis)}catch(t){console.error('Unleash failed to resolve "fetch"',t)}},T=function(i){function o(t){var n=t.storageProvider,r=t.url,o=t.clientKey,s=t.disableRefresh,a=void 0!==s&&s,c=t.refreshInterval,p=void 0===c?30:c,f=t.metricsInterval,d=void 0===f?30:f,v=t.disableMetrics,m=void 0!==v&&v,y=t.appName,b=t.environment,E=void 0===b?"default":b,I=t.context,x=t.fetch,R=void 0===x?S():x,T=t.bootstrap,O=t.bootstrapOverride,N=void 0===O||O,k=t.headerName,D=void 0===k?"Authorization":k,U=t.customHeaders,P=void 0===U?{}:U,A=t.impressionDataAll,j=void 0!==A&&A,H=t.usePOSTrequests,M=void 0!==H&&H,_=i.call(this)||this;if(_.toggles=[],_.etag="",_.readyEventEmitted=!1,_.usePOSTrequests=!1,_.started=!1,!r)throw new Error("url is required");if(!o)throw new Error("clientKey is required");if(!y)throw new Error("appName is required.");return _.eventsHandler=new g,_.impressionDataAll=j,_.toggles=T&&T.length>0?T:[],_.url=r instanceof URL?r:new URL(r),_.clientKey=o,_.headerName=D,_.customHeaders=P,_.storage=n||("undefined"!=typeof window?new l:new h),_.refreshInterval=a?0:1e3*p,_.context=e({appName:y,environment:E},I),_.usePOSTrequests=M,_.ready=new Promise((function(t){_.init().then(t).catch((function(e){console.error(e),_.emit(w.ERROR,e),t()}))})),R||console.error('Unleash: You must either provide your own "fetch" implementation or run in an environment where "fetch" is available.'),_.fetch=R,_.bootstrap=T&&T.length>0?T:void 0,_.bootstrapOverride=N,_.metrics=new u({onError:_.emit.bind(_,w.ERROR),onSent:_.emit.bind(_,w.SENT),appName:y,metricsInterval:d,disableMetrics:m,url:_.url,clientKey:o,fetch:R,headerName:D,customHeaders:P}),_}return function(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function r(){this.constructor=e}t(e,n),e.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}(o,i),o.prototype.getAllToggles=function(){return function(t,e,n){if(n||2===arguments.length)for(var r,i=0,o=e.length;i<o;i++)!r&&i in e||(r||(r=Array.prototype.slice.call(e,0,i)),r[i]=e[i]);return t.concat(r||Array.prototype.slice.call(e))}([],this.toggles,!0)},o.prototype.isEnabled=function(t){var e,n=this.toggles.find((function(e){return e.name===t})),r=!!n&&n.enabled;if(this.metrics.count(t,r),(null==n?void 0:n.impressionData)||this.impressionDataAll){var i=this.eventsHandler.createImpressionEvent(this.context,r,t,E,null!==(e=null==n?void 0:n.impressionData)&&void 0!==e?e:void 0);this.emit(w.IMPRESSION,i)}return r},o.prototype.getVariant=function(t){var n,r=this.toggles.find((function(e){return e.name===t})),i=(null==r?void 0:r.enabled)||!1,o=r?r.variant:x;if(o.name&&this.metrics.countVariant(t,o.name),this.metrics.count(t,i),(null==r?void 0:r.impressionData)||this.impressionDataAll){var s=this.eventsHandler.createImpressionEvent(this.context,i,t,I,null!==(n=null==r?void 0:r.impressionData)&&void 0!==n?n:void 0,o.name);this.emit(w.IMPRESSION,s)}return e(e({},o),{feature_enabled:i})},o.prototype.updateContext=function(t){return n(this,void 0,void 0,(function(){var n,i=this;return r(this,(function(r){switch(r.label){case 0:return(t.appName||t.environment)&&console.warn("appName and environment are static. They can't be updated with updateContext."),n={environment:this.context.environment,appName:this.context.appName,sessionId:this.context.sessionId},this.context=e(e({},n),t),this.timerRef||this.readyEventEmitted?[4,this.fetchToggles()]:[3,2];case 1:return r.sent(),[3,4];case 2:return this.started?[4,new Promise((function(t){var e=function(){i.fetchToggles().then((function(){i.off(w.READY,e),t()}))};i.once(w.READY,e)}))]:[3,4];case 3:r.sent(),r.label=4;case 4:return[2]}}))}))},o.prototype.getContext=function(){return e({},this.context)},o.prototype.setContextField=function(t,n){var r,i;if(b.includes(t))this.context=e(e({},this.context),((r={})[t]=n,r));else{var o=e(e({},this.context.properties),((i={})[t]=n,i));this.context=e(e({},this.context),{properties:o})}this.timerRef&&this.fetchToggles()},o.prototype.init=function(){return n(this,void 0,void 0,(function(){var t,n;return r(this,(function(r){switch(r.label){case 0:return[4,this.resolveSessionId()];case 1:return t=r.sent(),this.context=e({sessionId:t},this.context),n=this,[4,this.storage.get(R)];case 2:return n.toggles=r.sent()||[],!this.bootstrap||!this.bootstrapOverride&&0!==this.toggles.length?[3,4]:[4,this.storage.save(R,this.bootstrap)];case 3:r.sent(),this.toggles=this.bootstrap,this.emit(w.READY),r.label=4;case 4:return this.emit(w.INIT),[2]}}))}))},o.prototype.start=function(){return n(this,void 0,void 0,(function(){var t,e=this;return r(this,(function(n){switch(n.label){case 0:return this.started=!0,this.timerRef?(console.error("Unleash SDK has already started, if you want to restart the SDK you should call client.stop() before starting again."),[2]):[4,this.ready];case 1:return n.sent(),this.metrics.start(),t=this.refreshInterval,[4,this.fetchToggles()];case 2:return n.sent(),t>0&&(this.timerRef=setInterval((function(){return e.fetchToggles()}),t)),[2]}}))}))},o.prototype.stop=function(){this.timerRef&&(clearInterval(this.timerRef),this.timerRef=void 0),this.metrics.stop()},o.prototype.resolveSessionId=function(){return n(this,void 0,void 0,(function(){var t;return r(this,(function(e){switch(e.label){case 0:return this.context.sessionId?[2,this.context.sessionId]:[3,1];case 1:return[4,this.storage.get("sessionId")];case 2:return(t=e.sent())?[3,4]:(t=Math.floor(1e9*Math.random()),[4,this.storage.save("sessionId",t)]);case 3:e.sent(),e.label=4;case 4:return[2,t]}}))}))},o.prototype.getHeaders=function(){var t,e=((t={})[this.headerName]=this.clientKey,t.Accept="application/json",t["Content-Type"]="application/json",t["If-None-Match"]=this.etag,t);return Object.entries(this.customHeaders).filter(a).forEach((function(t){var n=t[0],r=t[1];return e[n]=r})),e},o.prototype.storeToggles=function(t){return n(this,void 0,void 0,(function(){return r(this,(function(e){switch(e.label){case 0:return this.toggles=t,this.emit(w.UPDATE),[4,this.storage.save(R,t)];case 1:return e.sent(),[2]}}))}))},o.prototype.fetchToggles=function(){return n(this,void 0,void 0,(function(){var t,e,n,i,o,s,c;return r(this,(function(r){switch(r.label){case 0:if(!this.fetch)return[3,8];r.label=1;case 1:return r.trys.push([1,7,,8]),t=this.usePOSTrequests,e=t?this.url:function(t,e){var n=new URL(t.toString());return Object.entries(e).filter(a).forEach((function(t){var e=t[0],r=t[1];"properties"===e&&r?Object.entries(r).filter(a).forEach((function(t){var e=t[0],r=t[1];return n.searchParams.append("properties[".concat(e,"]"),r)})):n.searchParams.append(e,r)})),n}(this.url,this.context),n=t?"POST":"GET",i=t?JSON.stringify({context:this.context}):void 0,[4,this.fetch(e.toString(),{method:n,cache:"no-cache",headers:this.getHeaders(),body:i})];case 2:return(o=r.sent()).ok&&304!==o.status?(this.etag=o.headers.get("ETag")||"",[4,o.json()]):[3,5];case 3:return s=r.sent(),[4,this.storeToggles(s.toggles)];case 4:return r.sent(),this.bootstrap||this.readyEventEmitted||(this.emit(w.READY),this.readyEventEmitted=!0),[3,6];case 5:o.ok||304===o.status||(console.error("Unleash: Fetching feature toggles did not have an ok response"),this.emit(w.ERROR,{type:"HttpError",code:o.status})),r.label=6;case 6:return[3,8];case 7:return c=r.sent(),console.error("Unleash: unable to fetch feature toggles",c),this.emit(w.ERROR,c),[3,8];case 8:return[2]}}))}))},o}(s);export{w as EVENTS,h as InMemoryStorageProvider,l as LocalStorageProvider,T as UnleashClient,S as resolveFetch}; | ||
var t=function(e,r){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])},t(e,r)};var e=function(){return e=Object.assign||function(t){for(var e,r=1,n=arguments.length;r<n;r++)for(var o in e=arguments[r])Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o]);return t},e.apply(this,arguments)};function r(t,e,r,n){return new(r||(r=Promise))((function(o,i){function s(t){try{c(n.next(t))}catch(t){i(t)}}function a(t){try{c(n.throw(t))}catch(t){i(t)}}function c(t){var e;t.done?o(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(s,a)}c((n=n.apply(t,e||[])).next())}))}function n(t,e){var r,n,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(a){return function(c){return function(a){if(r)throw new TypeError("Generator is already executing.");for(;i&&(i=0,a[0]&&(s=0)),s;)try{if(r=1,n&&(o=2&a[0]?n.return:a[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,a[1])).done)return o;switch(n=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return s.label++,{value:a[1],done:!1};case 5:s.label++,n=a[1],a=[0];continue;case 7:a=s.ops.pop(),s.trys.pop();continue;default:if(!(o=s.trys,(o=o.length>0&&o[o.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){s.label=a[1];break}if(6===a[0]&&s.label<o[1]){s.label=o[1],o=a;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(a);break}o[2]&&s.ops.pop(),s.trys.pop();continue}a=e.call(t,s)}catch(t){a=[6,t],n=0}finally{r=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,c])}}}"function"==typeof SuppressedError&&SuppressedError;var o={exports:{}};function i(){}i.prototype={on:function(t,e,r){var n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:r}),this},once:function(t,e,r){var n=this;function o(){n.off(t,o),e.apply(r,arguments)}return o._=e,this.on(t,o,r)},emit:function(t){for(var e=[].slice.call(arguments,1),r=((this.e||(this.e={}))[t]||[]).slice(),n=0,o=r.length;n<o;n++)r[n].fn.apply(r[n].ctx,e);return this},off:function(t,e){var r=this.e||(this.e={}),n=r[t],o=[];if(n&&e)for(var i=0,s=n.length;i<s;i++)n[i].fn!==e&&n[i].fn._!==e&&o.push(n[i]);return o.length?r[t]=o:delete r[t],this}},o.exports=i;var s=o.exports.TinyEmitter=i,a=function(t){var e=t[1];return null!=e},c=function(){},u=function(){function t(t){var e=t.onError,r=t.onSent,n=t.appName,o=t.metricsInterval,i=t.disableMetrics,s=void 0!==i&&i,a=t.url,u=t.clientKey,l=t.fetch,h=t.headerName,f=t.customHeaders,p=void 0===f?{}:f;this.onError=e,this.onSent=r||c,this.disabled=s,this.metricsInterval=1e3*o,this.appName=n,this.url=a instanceof URL?a:new URL(a),this.clientKey=u,this.bucket=this.createEmptyBucket(),this.fetch=l,this.headerName=h,this.customHeaders=p}return t.prototype.start=function(){var t=this;if(this.disabled)return!1;"number"==typeof this.metricsInterval&&this.metricsInterval>0&&setTimeout((function(){t.startTimer(),t.sendMetrics()}),2e3)},t.prototype.stop=function(){this.timer&&(clearTimeout(this.timer),delete this.timer)},t.prototype.createEmptyBucket=function(){return{start:new Date,stop:null,toggles:{}}},t.prototype.getHeaders=function(){var t,e=((t={})[this.headerName]=this.clientKey,t.Accept="application/json",t["Content-Type"]="application/json",t);return Object.entries(this.customHeaders).filter(a).forEach((function(t){var r=t[0],n=t[1];return e[r]=n})),e},t.prototype.sendMetrics=function(){return r(this,void 0,void 0,(function(){var t,e,r;return n(this,(function(n){switch(n.label){case 0:if(t="".concat(this.url,"/client/metrics"),e=this.getPayload(),this.bucketIsEmpty(e))return[2];n.label=1;case 1:return n.trys.push([1,3,,4]),[4,this.fetch(t,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(e)})];case 2:return n.sent(),this.onSent(e),[3,4];case 3:return r=n.sent(),console.error("Unleash: unable to send feature metrics",r),this.onError(r),[3,4];case 4:return[2]}}))}))},t.prototype.count=function(t,e){return!(this.disabled||!this.bucket)&&(this.assertBucket(t),this.bucket.toggles[t][e?"yes":"no"]++,!0)},t.prototype.countVariant=function(t,e){return!(this.disabled||!this.bucket)&&(this.assertBucket(t),this.bucket.toggles[t].variants[e]?this.bucket.toggles[t].variants[e]+=1:this.bucket.toggles[t].variants[e]=1,!0)},t.prototype.assertBucket=function(t){if(this.disabled||!this.bucket)return!1;this.bucket.toggles[t]||(this.bucket.toggles[t]={yes:0,no:0,variants:{}})},t.prototype.startTimer=function(){var t=this;this.timer=setInterval((function(){t.sendMetrics()}),this.metricsInterval)},t.prototype.bucketIsEmpty=function(t){return 0===Object.keys(t.bucket.toggles).length},t.prototype.getPayload=function(){var t=e(e({},this.bucket),{stop:new Date});return this.bucket=this.createEmptyBucket(),{bucket:t,appName:this.appName,instanceId:"browser"}},t}(),l=function(){function t(){this.store=new Map}return t.prototype.save=function(t,e){return r(this,void 0,void 0,(function(){return n(this,(function(r){return this.store.set(t,e),[2]}))}))},t.prototype.get=function(t){return r(this,void 0,void 0,(function(){return n(this,(function(e){return[2,this.store.get(t)]}))}))},t}(),h=function(){function t(){this.prefix="unleash:repository"}return t.prototype.save=function(t,e){return r(this,void 0,void 0,(function(){var r,o;return n(this,(function(n){r=JSON.stringify(e),o="".concat(this.prefix,":").concat(t);try{window.localStorage.setItem(o,r)}catch(t){console.error(t)}return[2]}))}))},t.prototype.get=function(t){try{var e="".concat(this.prefix,":").concat(t),r=window.localStorage.getItem(e);return r?JSON.parse(r):void 0}catch(t){console.error(t)}},t}();let f;const p=new Uint8Array(16);function d(){if(!f&&(f="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!f))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return f(p)}const v=[];for(let t=0;t<256;++t)v.push((t+256).toString(16).slice(1));var m={randomUUID:"undefined"!=typeof crypto&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};function y(t,e,r){if(m.randomUUID&&!e&&!t)return m.randomUUID();const n=(t=t||{}).random||(t.rng||d)();if(n[6]=15&n[6]|64,n[8]=63&n[8]|128,e){r=r||0;for(let t=0;t<16;++t)e[r+t]=n[t];return e}return function(t,e=0){return v[t[e+0]]+v[t[e+1]]+v[t[e+2]]+v[t[e+3]]+"-"+v[t[e+4]]+v[t[e+5]]+"-"+v[t[e+6]]+v[t[e+7]]+"-"+v[t[e+8]]+v[t[e+9]]+"-"+v[t[e+10]]+v[t[e+11]]+v[t[e+12]]+v[t[e+13]]+v[t[e+14]]+v[t[e+15]]}(n)}var g=function(){function t(){}return t.prototype.generateEventId=function(){return y()},t.prototype.createImpressionEvent=function(t,r,n,o,i,s){var a=this.createBaseEvent(t,r,n,o,i);return s?e(e({},a),{variant:s}):a},t.prototype.createBaseEvent=function(t,e,r,n,o){return{eventType:n,eventId:this.generateEventId(),context:t,enabled:e,featureName:r,impressionData:o}},t}(),b=["userId","sessionId","remoteAddress"],w={INIT:"initialized",ERROR:"error",READY:"ready",UPDATE:"update",IMPRESSION:"impression",SENT:"sent",RECOVERED:"recovered"},E="isEnabled",I="getVariant",S={name:"disabled",enabled:!1,feature_enabled:!1},R="repo",x=function(){try{if("undefined"!=typeof window&&"fetch"in window)return fetch.bind(window);if("fetch"in globalThis)return fetch.bind(globalThis)}catch(t){console.error('Unleash failed to resolve "fetch"',t)}},k=function(o){function i(t){var r=t.storageProvider,n=t.url,i=t.clientKey,s=t.disableRefresh,a=void 0!==s&&s,c=t.refreshInterval,f=void 0===c?30:c,p=t.metricsInterval,d=void 0===p?30:p,v=t.disableMetrics,m=void 0!==v&&v,y=t.appName,b=t.environment,E=void 0===b?"default":b,I=t.context,S=t.fetch,R=void 0===S?x():S,k=t.createAbortController,T=void 0===k?function(){try{if("undefined"!=typeof window&&"AbortController"in window)return function(){return new window.AbortController};if("fetch"in globalThis)return function(){return new globalThis.AbortController}}catch(t){console.error('Unleash failed to resolve "AbortController" factory',t)}}():k,O=t.bootstrap,N=t.bootstrapOverride,A=void 0===N||N,D=t.headerName,U=void 0===D?"Authorization":D,C=t.customHeaders,P=void 0===C?{}:C,j=t.impressionDataAll,H=void 0!==j&&j,M=t.usePOSTrequests,_=void 0!==M&&M,K=o.call(this)||this;if(K.toggles=[],K.etag="",K.readyEventEmitted=!1,K.usePOSTrequests=!1,K.started=!1,!n)throw new Error("url is required");if(!i)throw new Error("clientKey is required");if(!y)throw new Error("appName is required.");return K.eventsHandler=new g,K.impressionDataAll=H,K.toggles=O&&O.length>0?O:[],K.url=n instanceof URL?n:new URL(n),K.clientKey=i,K.headerName=U,K.customHeaders=P,K.storage=r||("undefined"!=typeof window?new h:new l),K.refreshInterval=a?0:1e3*f,K.context=e({appName:y,environment:E},I),K.usePOSTrequests=_,K.sdkState="initializing",K.ready=new Promise((function(t){K.init().then(t).catch((function(e){console.error(e),K.sdkState="error",K.emit(w.ERROR,e),t()}))})),R||console.error('Unleash: You must either provide your own "fetch" implementation or run in an environment where "fetch" is available.'),T||console.error('Unleash: You must either provide your own "AbortController" implementation or run in an environment where "AbortController" is available.'),K.fetch=R,K.createAbortController=T,K.bootstrap=O&&O.length>0?O:void 0,K.bootstrapOverride=A,K.metrics=new u({onError:K.emit.bind(K,w.ERROR),onSent:K.emit.bind(K,w.SENT),appName:y,metricsInterval:d,disableMetrics:m,url:K.url,clientKey:i,fetch:R,headerName:U,customHeaders:P}),K}return function(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function n(){this.constructor=e}t(e,r),e.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}(i,o),i.prototype.getAllToggles=function(){return function(t,e,r){if(r||2===arguments.length)for(var n,o=0,i=e.length;o<i;o++)!n&&o in e||(n||(n=Array.prototype.slice.call(e,0,o)),n[o]=e[o]);return t.concat(n||Array.prototype.slice.call(e))}([],this.toggles,!0)},i.prototype.isEnabled=function(t){var e,r=this.toggles.find((function(e){return e.name===t})),n=!!r&&r.enabled;if(this.metrics.count(t,n),(null==r?void 0:r.impressionData)||this.impressionDataAll){var o=this.eventsHandler.createImpressionEvent(this.context,n,t,E,null!==(e=null==r?void 0:r.impressionData)&&void 0!==e?e:void 0);this.emit(w.IMPRESSION,o)}return n},i.prototype.getVariant=function(t){var r,n=this.toggles.find((function(e){return e.name===t})),o=(null==n?void 0:n.enabled)||!1,i=n?n.variant:S;if(i.name&&this.metrics.countVariant(t,i.name),this.metrics.count(t,o),(null==n?void 0:n.impressionData)||this.impressionDataAll){var s=this.eventsHandler.createImpressionEvent(this.context,o,t,I,null!==(r=null==n?void 0:n.impressionData)&&void 0!==r?r:void 0,i.name);this.emit(w.IMPRESSION,s)}return e(e({},i),{feature_enabled:o})},i.prototype.updateContext=function(t){return r(this,void 0,void 0,(function(){var r,o=this;return n(this,(function(n){switch(n.label){case 0:return(t.appName||t.environment)&&console.warn("appName and environment are static. They can't be updated with updateContext."),r={environment:this.context.environment,appName:this.context.appName,sessionId:this.context.sessionId},this.context=e(e({},r),t),this.timerRef||this.readyEventEmitted?[4,this.fetchToggles()]:[3,2];case 1:return n.sent(),[3,4];case 2:return this.started?[4,new Promise((function(t){var e=function(){o.fetchToggles().then((function(){o.off(w.READY,e),t()}))};o.once(w.READY,e)}))]:[3,4];case 3:n.sent(),n.label=4;case 4:return[2]}}))}))},i.prototype.getContext=function(){return e({},this.context)},i.prototype.setContextField=function(t,r){var n,o;if(b.includes(t))this.context=e(e({},this.context),((n={})[t]=r,n));else{var i=e(e({},this.context.properties),((o={})[t]=r,o));this.context=e(e({},this.context),{properties:i})}this.timerRef&&this.fetchToggles()},i.prototype.init=function(){return r(this,void 0,void 0,(function(){var t,r;return n(this,(function(n){switch(n.label){case 0:return[4,this.resolveSessionId()];case 1:return t=n.sent(),this.context=e({sessionId:t},this.context),r=this,[4,this.storage.get(R)];case 2:return r.toggles=n.sent()||[],!this.bootstrap||!this.bootstrapOverride&&0!==this.toggles.length?[3,4]:[4,this.storage.save(R,this.bootstrap)];case 3:n.sent(),this.toggles=this.bootstrap,this.emit(w.READY),n.label=4;case 4:return this.sdkState="healthy",this.emit(w.INIT),[2]}}))}))},i.prototype.start=function(){return r(this,void 0,void 0,(function(){var t,e=this;return n(this,(function(r){switch(r.label){case 0:return this.started=!0,this.timerRef?(console.error("Unleash SDK has already started, if you want to restart the SDK you should call client.stop() before starting again."),[2]):[4,this.ready];case 1:return r.sent(),this.metrics.start(),t=this.refreshInterval,[4,this.fetchToggles()];case 2:return r.sent(),t>0&&(this.timerRef=setInterval((function(){return e.fetchToggles()}),t)),[2]}}))}))},i.prototype.stop=function(){this.timerRef&&(clearInterval(this.timerRef),this.timerRef=void 0),this.metrics.stop()},i.prototype.resolveSessionId=function(){return r(this,void 0,void 0,(function(){var t;return n(this,(function(e){switch(e.label){case 0:return this.context.sessionId?[2,this.context.sessionId]:[3,1];case 1:return[4,this.storage.get("sessionId")];case 2:return(t=e.sent())?[3,4]:(t=Math.floor(1e9*Math.random()),[4,this.storage.save("sessionId",t)]);case 3:e.sent(),e.label=4;case 4:return[2,t]}}))}))},i.prototype.getHeaders=function(){var t,e=((t={})[this.headerName]=this.clientKey,t.Accept="application/json",t["Content-Type"]="application/json",t["If-None-Match"]=this.etag,t);return Object.entries(this.customHeaders).filter(a).forEach((function(t){var r=t[0],n=t[1];return e[r]=n})),e},i.prototype.storeToggles=function(t){return r(this,void 0,void 0,(function(){return n(this,(function(e){switch(e.label){case 0:return this.toggles=t,this.emit(w.UPDATE),[4,this.storage.save(R,t)];case 1:return e.sent(),[2]}}))}))},i.prototype.fetchToggles=function(){return r(this,void 0,void 0,(function(){var t,e,r,o,i,s,c,u;return n(this,(function(n){switch(n.label){case 0:if(!this.fetch)return[3,9];this.abortController&&this.abortController.abort(),this.abortController=this.createAbortController&&this.createAbortController(),t=this.abortController?this.abortController.signal:void 0,n.label=1;case 1:return n.trys.push([1,7,8,9]),e=this.usePOSTrequests,r=e?this.url:function(t,e){var r=new URL(t.toString());return Object.entries(e).filter(a).forEach((function(t){var e=t[0],n=t[1];"properties"===e&&n?Object.entries(n).filter(a).forEach((function(t){var e=t[0],n=t[1];return r.searchParams.append("properties[".concat(e,"]"),n)})):r.searchParams.append(e,n)})),r}(this.url,this.context),o=e?"POST":"GET",i=e?JSON.stringify({context:this.context}):void 0,[4,this.fetch(r.toString(),{method:o,headers:this.getHeaders(),body:i,signal:t})];case 2:return s=n.sent(),"error"===this.sdkState&&s.status<400&&(this.sdkState="healthy",this.emit(w.RECOVERED)),s.ok&&304!==s.status?(this.etag=s.headers.get("ETag")||"",[4,s.json()]):[3,5];case 3:return c=n.sent(),[4,this.storeToggles(c.toggles)];case 4:return n.sent(),"healthy"!==this.sdkState&&(this.sdkState="healthy"),this.bootstrap||this.readyEventEmitted||(this.emit(w.READY),this.readyEventEmitted=!0),[3,6];case 5:s.ok||304===s.status||(console.error("Unleash: Fetching feature toggles did not have an ok response"),this.sdkState="error",this.emit(w.ERROR,{type:"HttpError",code:s.status})),n.label=6;case 6:return[3,9];case 7:return u=n.sent(),console.error("Unleash: unable to fetch feature toggles",u),this.sdkState="error",this.emit(w.ERROR,u),[3,9];case 8:return this.abortController=null,[7];case 9:return[2]}}))}))},i}(s);export{w as EVENTS,l as InMemoryStorageProvider,h as LocalStorageProvider,k as UnleashClient,x as resolveFetch}; | ||
//# sourceMappingURL=main.esm.js.map |
@@ -1,2 +0,2 @@ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).unleash={})}(this,(function(t){"use strict";var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},e(t,n)};var n=function(){return n=Object.assign||function(t){for(var e,n=1,r=arguments.length;n<r;n++)for(var o in e=arguments[n])Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o]);return t},n.apply(this,arguments)};function r(t,e,n,r){return new(n||(n=Promise))((function(o,i){function s(t){try{c(r.next(t))}catch(t){i(t)}}function a(t){try{c(r.throw(t))}catch(t){i(t)}}function c(t){var e;t.done?o(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(s,a)}c((r=r.apply(t,e||[])).next())}))}function o(t,e){var n,r,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(a){return function(c){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i&&(i=0,a[0]&&(s=0)),s;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return s.label++,{value:a[1],done:!1};case 5:s.label++,r=a[1],a=[0];continue;case 7:a=s.ops.pop(),s.trys.pop();continue;default:if(!(o=s.trys,(o=o.length>0&&o[o.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){s.label=a[1];break}if(6===a[0]&&s.label<o[1]){s.label=o[1],o=a;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(a);break}o[2]&&s.ops.pop(),s.trys.pop();continue}a=e.call(t,s)}catch(t){a=[6,t],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,c])}}}"function"==typeof SuppressedError&&SuppressedError;var i={exports:{}};function s(){}s.prototype={on:function(t,e,n){var r=this.e||(this.e={});return(r[t]||(r[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){var r=this;function o(){r.off(t,o),e.apply(n,arguments)}return o._=e,this.on(t,o,n)},emit:function(t){for(var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),r=0,o=n.length;r<o;r++)n[r].fn.apply(n[r].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),r=n[t],o=[];if(r&&e)for(var i=0,s=r.length;i<s;i++)r[i].fn!==e&&r[i].fn._!==e&&o.push(r[i]);return o.length?n[t]=o:delete n[t],this}},i.exports=s;var a=i.exports.TinyEmitter=s,c=function(t){var e=t[1];return null!=e},u=function(){},h=function(){function t(t){var e=t.onError,n=t.onSent,r=t.appName,o=t.metricsInterval,i=t.disableMetrics,s=void 0!==i&&i,a=t.url,c=t.clientKey,h=t.fetch,l=t.headerName,f=t.customHeaders,p=void 0===f?{}:f;this.onError=e,this.onSent=n||u,this.disabled=s,this.metricsInterval=1e3*o,this.appName=r,this.url=a instanceof URL?a:new URL(a),this.clientKey=c,this.bucket=this.createEmptyBucket(),this.fetch=h,this.headerName=l,this.customHeaders=p}return t.prototype.start=function(){var t=this;if(this.disabled)return!1;"number"==typeof this.metricsInterval&&this.metricsInterval>0&&setTimeout((function(){t.startTimer(),t.sendMetrics()}),2e3)},t.prototype.stop=function(){this.timer&&(clearTimeout(this.timer),delete this.timer)},t.prototype.createEmptyBucket=function(){return{start:new Date,stop:null,toggles:{}}},t.prototype.getHeaders=function(){var t,e=((t={})[this.headerName]=this.clientKey,t.Accept="application/json",t["Content-Type"]="application/json",t);return Object.entries(this.customHeaders).filter(c).forEach((function(t){var n=t[0],r=t[1];return e[n]=r})),e},t.prototype.sendMetrics=function(){return r(this,void 0,void 0,(function(){var t,e,n;return o(this,(function(r){switch(r.label){case 0:if(t="".concat(this.url,"/client/metrics"),e=this.getPayload(),this.bucketIsEmpty(e))return[2];r.label=1;case 1:return r.trys.push([1,3,,4]),[4,this.fetch(t,{cache:"no-cache",method:"POST",headers:this.getHeaders(),body:JSON.stringify(e)})];case 2:return r.sent(),this.onSent(e),[3,4];case 3:return n=r.sent(),console.error("Unleash: unable to send feature metrics",n),this.onError(n),[3,4];case 4:return[2]}}))}))},t.prototype.count=function(t,e){return!(this.disabled||!this.bucket)&&(this.assertBucket(t),this.bucket.toggles[t][e?"yes":"no"]++,!0)},t.prototype.countVariant=function(t,e){return!(this.disabled||!this.bucket)&&(this.assertBucket(t),this.bucket.toggles[t].variants[e]?this.bucket.toggles[t].variants[e]+=1:this.bucket.toggles[t].variants[e]=1,!0)},t.prototype.assertBucket=function(t){if(this.disabled||!this.bucket)return!1;this.bucket.toggles[t]||(this.bucket.toggles[t]={yes:0,no:0,variants:{}})},t.prototype.startTimer=function(){var t=this;this.timer=setInterval((function(){t.sendMetrics()}),this.metricsInterval)},t.prototype.bucketIsEmpty=function(t){return 0===Object.keys(t.bucket.toggles).length},t.prototype.getPayload=function(){var t=n(n({},this.bucket),{stop:new Date});return this.bucket=this.createEmptyBucket(),{bucket:t,appName:this.appName,instanceId:"browser"}},t}(),l=function(){function t(){this.store=new Map}return t.prototype.save=function(t,e){return r(this,void 0,void 0,(function(){return o(this,(function(n){return this.store.set(t,e),[2]}))}))},t.prototype.get=function(t){return r(this,void 0,void 0,(function(){return o(this,(function(e){return[2,this.store.get(t)]}))}))},t}(),f=function(){function t(){this.prefix="unleash:repository"}return t.prototype.save=function(t,e){return r(this,void 0,void 0,(function(){var n,r;return o(this,(function(o){n=JSON.stringify(e),r="".concat(this.prefix,":").concat(t);try{window.localStorage.setItem(r,n)}catch(t){console.error(t)}return[2]}))}))},t.prototype.get=function(t){try{var e="".concat(this.prefix,":").concat(t),n=window.localStorage.getItem(e);return n?JSON.parse(n):void 0}catch(t){console.error(t)}},t}();let p;const d=new Uint8Array(16);function v(){if(!p&&(p="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!p))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return p(d)}const m=[];for(let t=0;t<256;++t)m.push((t+256).toString(16).slice(1));var y={randomUUID:"undefined"!=typeof crypto&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};function g(t,e,n){if(y.randomUUID&&!e&&!t)return y.randomUUID();const r=(t=t||{}).random||(t.rng||v)();if(r[6]=15&r[6]|64,r[8]=63&r[8]|128,e){n=n||0;for(let t=0;t<16;++t)e[n+t]=r[t];return e}return function(t,e=0){return m[t[e+0]]+m[t[e+1]]+m[t[e+2]]+m[t[e+3]]+"-"+m[t[e+4]]+m[t[e+5]]+"-"+m[t[e+6]]+m[t[e+7]]+"-"+m[t[e+8]]+m[t[e+9]]+"-"+m[t[e+10]]+m[t[e+11]]+m[t[e+12]]+m[t[e+13]]+m[t[e+14]]+m[t[e+15]]}(r)}var b=function(){function t(){}return t.prototype.generateEventId=function(){return g()},t.prototype.createImpressionEvent=function(t,e,r,o,i,s){var a=this.createBaseEvent(t,e,r,o,i);return s?n(n({},a),{variant:s}):a},t.prototype.createBaseEvent=function(t,e,n,r,o){return{eventType:r,eventId:this.generateEventId(),context:t,enabled:e,featureName:n,impressionData:o}},t}(),w=["userId","sessionId","remoteAddress"],E={INIT:"initialized",ERROR:"error",READY:"ready",UPDATE:"update",IMPRESSION:"impression",SENT:"sent"},I="isEnabled",x="getVariant",S={name:"disabled",enabled:!1,feature_enabled:!1},R="repo",T=function(){try{if("undefined"!=typeof window&&"fetch"in window)return fetch.bind(window);if("fetch"in globalThis)return fetch.bind(globalThis)}catch(t){console.error('Unleash failed to resolve "fetch"',t)}},O=function(t){function i(e){var r=e.storageProvider,o=e.url,i=e.clientKey,s=e.disableRefresh,a=void 0!==s&&s,c=e.refreshInterval,u=void 0===c?30:c,p=e.metricsInterval,d=void 0===p?30:p,v=e.disableMetrics,m=void 0!==v&&v,y=e.appName,g=e.environment,w=void 0===g?"default":g,I=e.context,x=e.fetch,S=void 0===x?T():x,R=e.bootstrap,O=e.bootstrapOverride,N=void 0===O||O,k=e.headerName,D=void 0===k?"Authorization":k,U=e.customHeaders,P=void 0===U?{}:U,A=e.impressionDataAll,j=void 0!==A&&A,H=e.usePOSTrequests,M=void 0!==H&&H,_=t.call(this)||this;if(_.toggles=[],_.etag="",_.readyEventEmitted=!1,_.usePOSTrequests=!1,_.started=!1,!o)throw new Error("url is required");if(!i)throw new Error("clientKey is required");if(!y)throw new Error("appName is required.");return _.eventsHandler=new b,_.impressionDataAll=j,_.toggles=R&&R.length>0?R:[],_.url=o instanceof URL?o:new URL(o),_.clientKey=i,_.headerName=D,_.customHeaders=P,_.storage=r||("undefined"!=typeof window?new f:new l),_.refreshInterval=a?0:1e3*u,_.context=n({appName:y,environment:w},I),_.usePOSTrequests=M,_.ready=new Promise((function(t){_.init().then(t).catch((function(e){console.error(e),_.emit(E.ERROR,e),t()}))})),S||console.error('Unleash: You must either provide your own "fetch" implementation or run in an environment where "fetch" is available.'),_.fetch=S,_.bootstrap=R&&R.length>0?R:void 0,_.bootstrapOverride=N,_.metrics=new h({onError:_.emit.bind(_,E.ERROR),onSent:_.emit.bind(_,E.SENT),appName:y,metricsInterval:d,disableMetrics:m,url:_.url,clientKey:i,fetch:S,headerName:D,customHeaders:P}),_}return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}(i,t),i.prototype.getAllToggles=function(){return function(t,e,n){if(n||2===arguments.length)for(var r,o=0,i=e.length;o<i;o++)!r&&o in e||(r||(r=Array.prototype.slice.call(e,0,o)),r[o]=e[o]);return t.concat(r||Array.prototype.slice.call(e))}([],this.toggles,!0)},i.prototype.isEnabled=function(t){var e,n=this.toggles.find((function(e){return e.name===t})),r=!!n&&n.enabled;if(this.metrics.count(t,r),(null==n?void 0:n.impressionData)||this.impressionDataAll){var o=this.eventsHandler.createImpressionEvent(this.context,r,t,I,null!==(e=null==n?void 0:n.impressionData)&&void 0!==e?e:void 0);this.emit(E.IMPRESSION,o)}return r},i.prototype.getVariant=function(t){var e,r=this.toggles.find((function(e){return e.name===t})),o=(null==r?void 0:r.enabled)||!1,i=r?r.variant:S;if(i.name&&this.metrics.countVariant(t,i.name),this.metrics.count(t,o),(null==r?void 0:r.impressionData)||this.impressionDataAll){var s=this.eventsHandler.createImpressionEvent(this.context,o,t,x,null!==(e=null==r?void 0:r.impressionData)&&void 0!==e?e:void 0,i.name);this.emit(E.IMPRESSION,s)}return n(n({},i),{feature_enabled:o})},i.prototype.updateContext=function(t){return r(this,void 0,void 0,(function(){var e,r=this;return o(this,(function(o){switch(o.label){case 0:return(t.appName||t.environment)&&console.warn("appName and environment are static. They can't be updated with updateContext."),e={environment:this.context.environment,appName:this.context.appName,sessionId:this.context.sessionId},this.context=n(n({},e),t),this.timerRef||this.readyEventEmitted?[4,this.fetchToggles()]:[3,2];case 1:return o.sent(),[3,4];case 2:return this.started?[4,new Promise((function(t){var e=function(){r.fetchToggles().then((function(){r.off(E.READY,e),t()}))};r.once(E.READY,e)}))]:[3,4];case 3:o.sent(),o.label=4;case 4:return[2]}}))}))},i.prototype.getContext=function(){return n({},this.context)},i.prototype.setContextField=function(t,e){var r,o;if(w.includes(t))this.context=n(n({},this.context),((r={})[t]=e,r));else{var i=n(n({},this.context.properties),((o={})[t]=e,o));this.context=n(n({},this.context),{properties:i})}this.timerRef&&this.fetchToggles()},i.prototype.init=function(){return r(this,void 0,void 0,(function(){var t,e;return o(this,(function(r){switch(r.label){case 0:return[4,this.resolveSessionId()];case 1:return t=r.sent(),this.context=n({sessionId:t},this.context),e=this,[4,this.storage.get(R)];case 2:return e.toggles=r.sent()||[],!this.bootstrap||!this.bootstrapOverride&&0!==this.toggles.length?[3,4]:[4,this.storage.save(R,this.bootstrap)];case 3:r.sent(),this.toggles=this.bootstrap,this.emit(E.READY),r.label=4;case 4:return this.emit(E.INIT),[2]}}))}))},i.prototype.start=function(){return r(this,void 0,void 0,(function(){var t,e=this;return o(this,(function(n){switch(n.label){case 0:return this.started=!0,this.timerRef?(console.error("Unleash SDK has already started, if you want to restart the SDK you should call client.stop() before starting again."),[2]):[4,this.ready];case 1:return n.sent(),this.metrics.start(),t=this.refreshInterval,[4,this.fetchToggles()];case 2:return n.sent(),t>0&&(this.timerRef=setInterval((function(){return e.fetchToggles()}),t)),[2]}}))}))},i.prototype.stop=function(){this.timerRef&&(clearInterval(this.timerRef),this.timerRef=void 0),this.metrics.stop()},i.prototype.resolveSessionId=function(){return r(this,void 0,void 0,(function(){var t;return o(this,(function(e){switch(e.label){case 0:return this.context.sessionId?[2,this.context.sessionId]:[3,1];case 1:return[4,this.storage.get("sessionId")];case 2:return(t=e.sent())?[3,4]:(t=Math.floor(1e9*Math.random()),[4,this.storage.save("sessionId",t)]);case 3:e.sent(),e.label=4;case 4:return[2,t]}}))}))},i.prototype.getHeaders=function(){var t,e=((t={})[this.headerName]=this.clientKey,t.Accept="application/json",t["Content-Type"]="application/json",t["If-None-Match"]=this.etag,t);return Object.entries(this.customHeaders).filter(c).forEach((function(t){var n=t[0],r=t[1];return e[n]=r})),e},i.prototype.storeToggles=function(t){return r(this,void 0,void 0,(function(){return o(this,(function(e){switch(e.label){case 0:return this.toggles=t,this.emit(E.UPDATE),[4,this.storage.save(R,t)];case 1:return e.sent(),[2]}}))}))},i.prototype.fetchToggles=function(){return r(this,void 0,void 0,(function(){var t,e,n,r,i,s,a;return o(this,(function(o){switch(o.label){case 0:if(!this.fetch)return[3,8];o.label=1;case 1:return o.trys.push([1,7,,8]),t=this.usePOSTrequests,e=t?this.url:function(t,e){var n=new URL(t.toString());return Object.entries(e).filter(c).forEach((function(t){var e=t[0],r=t[1];"properties"===e&&r?Object.entries(r).filter(c).forEach((function(t){var e=t[0],r=t[1];return n.searchParams.append("properties[".concat(e,"]"),r)})):n.searchParams.append(e,r)})),n}(this.url,this.context),n=t?"POST":"GET",r=t?JSON.stringify({context:this.context}):void 0,[4,this.fetch(e.toString(),{method:n,cache:"no-cache",headers:this.getHeaders(),body:r})];case 2:return(i=o.sent()).ok&&304!==i.status?(this.etag=i.headers.get("ETag")||"",[4,i.json()]):[3,5];case 3:return s=o.sent(),[4,this.storeToggles(s.toggles)];case 4:return o.sent(),this.bootstrap||this.readyEventEmitted||(this.emit(E.READY),this.readyEventEmitted=!0),[3,6];case 5:i.ok||304===i.status||(console.error("Unleash: Fetching feature toggles did not have an ok response"),this.emit(E.ERROR,{type:"HttpError",code:i.status})),o.label=6;case 6:return[3,8];case 7:return a=o.sent(),console.error("Unleash: unable to fetch feature toggles",a),this.emit(E.ERROR,a),[3,8];case 8:return[2]}}))}))},i}(a);t.EVENTS=E,t.InMemoryStorageProvider=l,t.LocalStorageProvider=f,t.UnleashClient=O,t.resolveFetch=T})); | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).unleash={})}(this,(function(t){"use strict";var e=function(t,r){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])},e(t,r)};var r=function(){return r=Object.assign||function(t){for(var e,r=1,n=arguments.length;r<n;r++)for(var o in e=arguments[r])Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o]);return t},r.apply(this,arguments)};function n(t,e,r,n){return new(r||(r=Promise))((function(o,i){function s(t){try{c(n.next(t))}catch(t){i(t)}}function a(t){try{c(n.throw(t))}catch(t){i(t)}}function c(t){var e;t.done?o(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(s,a)}c((n=n.apply(t,e||[])).next())}))}function o(t,e){var r,n,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(a){return function(c){return function(a){if(r)throw new TypeError("Generator is already executing.");for(;i&&(i=0,a[0]&&(s=0)),s;)try{if(r=1,n&&(o=2&a[0]?n.return:a[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,a[1])).done)return o;switch(n=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return s.label++,{value:a[1],done:!1};case 5:s.label++,n=a[1],a=[0];continue;case 7:a=s.ops.pop(),s.trys.pop();continue;default:if(!(o=s.trys,(o=o.length>0&&o[o.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){s.label=a[1];break}if(6===a[0]&&s.label<o[1]){s.label=o[1],o=a;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(a);break}o[2]&&s.ops.pop(),s.trys.pop();continue}a=e.call(t,s)}catch(t){a=[6,t],n=0}finally{r=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,c])}}}"function"==typeof SuppressedError&&SuppressedError;var i={exports:{}};function s(){}s.prototype={on:function(t,e,r){var n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:r}),this},once:function(t,e,r){var n=this;function o(){n.off(t,o),e.apply(r,arguments)}return o._=e,this.on(t,o,r)},emit:function(t){for(var e=[].slice.call(arguments,1),r=((this.e||(this.e={}))[t]||[]).slice(),n=0,o=r.length;n<o;n++)r[n].fn.apply(r[n].ctx,e);return this},off:function(t,e){var r=this.e||(this.e={}),n=r[t],o=[];if(n&&e)for(var i=0,s=n.length;i<s;i++)n[i].fn!==e&&n[i].fn._!==e&&o.push(n[i]);return o.length?r[t]=o:delete r[t],this}},i.exports=s;var a=i.exports.TinyEmitter=s,c=function(t){var e=t[1];return null!=e},u=function(){},l=function(){function t(t){var e=t.onError,r=t.onSent,n=t.appName,o=t.metricsInterval,i=t.disableMetrics,s=void 0!==i&&i,a=t.url,c=t.clientKey,l=t.fetch,h=t.headerName,f=t.customHeaders,p=void 0===f?{}:f;this.onError=e,this.onSent=r||u,this.disabled=s,this.metricsInterval=1e3*o,this.appName=n,this.url=a instanceof URL?a:new URL(a),this.clientKey=c,this.bucket=this.createEmptyBucket(),this.fetch=l,this.headerName=h,this.customHeaders=p}return t.prototype.start=function(){var t=this;if(this.disabled)return!1;"number"==typeof this.metricsInterval&&this.metricsInterval>0&&setTimeout((function(){t.startTimer(),t.sendMetrics()}),2e3)},t.prototype.stop=function(){this.timer&&(clearTimeout(this.timer),delete this.timer)},t.prototype.createEmptyBucket=function(){return{start:new Date,stop:null,toggles:{}}},t.prototype.getHeaders=function(){var t,e=((t={})[this.headerName]=this.clientKey,t.Accept="application/json",t["Content-Type"]="application/json",t);return Object.entries(this.customHeaders).filter(c).forEach((function(t){var r=t[0],n=t[1];return e[r]=n})),e},t.prototype.sendMetrics=function(){return n(this,void 0,void 0,(function(){var t,e,r;return o(this,(function(n){switch(n.label){case 0:if(t="".concat(this.url,"/client/metrics"),e=this.getPayload(),this.bucketIsEmpty(e))return[2];n.label=1;case 1:return n.trys.push([1,3,,4]),[4,this.fetch(t,{method:"POST",headers:this.getHeaders(),body:JSON.stringify(e)})];case 2:return n.sent(),this.onSent(e),[3,4];case 3:return r=n.sent(),console.error("Unleash: unable to send feature metrics",r),this.onError(r),[3,4];case 4:return[2]}}))}))},t.prototype.count=function(t,e){return!(this.disabled||!this.bucket)&&(this.assertBucket(t),this.bucket.toggles[t][e?"yes":"no"]++,!0)},t.prototype.countVariant=function(t,e){return!(this.disabled||!this.bucket)&&(this.assertBucket(t),this.bucket.toggles[t].variants[e]?this.bucket.toggles[t].variants[e]+=1:this.bucket.toggles[t].variants[e]=1,!0)},t.prototype.assertBucket=function(t){if(this.disabled||!this.bucket)return!1;this.bucket.toggles[t]||(this.bucket.toggles[t]={yes:0,no:0,variants:{}})},t.prototype.startTimer=function(){var t=this;this.timer=setInterval((function(){t.sendMetrics()}),this.metricsInterval)},t.prototype.bucketIsEmpty=function(t){return 0===Object.keys(t.bucket.toggles).length},t.prototype.getPayload=function(){var t=r(r({},this.bucket),{stop:new Date});return this.bucket=this.createEmptyBucket(),{bucket:t,appName:this.appName,instanceId:"browser"}},t}(),h=function(){function t(){this.store=new Map}return t.prototype.save=function(t,e){return n(this,void 0,void 0,(function(){return o(this,(function(r){return this.store.set(t,e),[2]}))}))},t.prototype.get=function(t){return n(this,void 0,void 0,(function(){return o(this,(function(e){return[2,this.store.get(t)]}))}))},t}(),f=function(){function t(){this.prefix="unleash:repository"}return t.prototype.save=function(t,e){return n(this,void 0,void 0,(function(){var r,n;return o(this,(function(o){r=JSON.stringify(e),n="".concat(this.prefix,":").concat(t);try{window.localStorage.setItem(n,r)}catch(t){console.error(t)}return[2]}))}))},t.prototype.get=function(t){try{var e="".concat(this.prefix,":").concat(t),r=window.localStorage.getItem(e);return r?JSON.parse(r):void 0}catch(t){console.error(t)}},t}();let p;const d=new Uint8Array(16);function v(){if(!p&&(p="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!p))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return p(d)}const m=[];for(let t=0;t<256;++t)m.push((t+256).toString(16).slice(1));var y={randomUUID:"undefined"!=typeof crypto&&crypto.randomUUID&&crypto.randomUUID.bind(crypto)};function g(t,e,r){if(y.randomUUID&&!e&&!t)return y.randomUUID();const n=(t=t||{}).random||(t.rng||v)();if(n[6]=15&n[6]|64,n[8]=63&n[8]|128,e){r=r||0;for(let t=0;t<16;++t)e[r+t]=n[t];return e}return function(t,e=0){return m[t[e+0]]+m[t[e+1]]+m[t[e+2]]+m[t[e+3]]+"-"+m[t[e+4]]+m[t[e+5]]+"-"+m[t[e+6]]+m[t[e+7]]+"-"+m[t[e+8]]+m[t[e+9]]+"-"+m[t[e+10]]+m[t[e+11]]+m[t[e+12]]+m[t[e+13]]+m[t[e+14]]+m[t[e+15]]}(n)}var b=function(){function t(){}return t.prototype.generateEventId=function(){return g()},t.prototype.createImpressionEvent=function(t,e,n,o,i,s){var a=this.createBaseEvent(t,e,n,o,i);return s?r(r({},a),{variant:s}):a},t.prototype.createBaseEvent=function(t,e,r,n,o){return{eventType:n,eventId:this.generateEventId(),context:t,enabled:e,featureName:r,impressionData:o}},t}(),w=["userId","sessionId","remoteAddress"],E={INIT:"initialized",ERROR:"error",READY:"ready",UPDATE:"update",IMPRESSION:"impression",SENT:"sent",RECOVERED:"recovered"},I="isEnabled",S="getVariant",x={name:"disabled",enabled:!1,feature_enabled:!1},R="repo",T=function(){try{if("undefined"!=typeof window&&"fetch"in window)return fetch.bind(window);if("fetch"in globalThis)return fetch.bind(globalThis)}catch(t){console.error('Unleash failed to resolve "fetch"',t)}},k=function(t){function i(e){var n=e.storageProvider,o=e.url,i=e.clientKey,s=e.disableRefresh,a=void 0!==s&&s,c=e.refreshInterval,u=void 0===c?30:c,p=e.metricsInterval,d=void 0===p?30:p,v=e.disableMetrics,m=void 0!==v&&v,y=e.appName,g=e.environment,w=void 0===g?"default":g,I=e.context,S=e.fetch,x=void 0===S?T():S,R=e.createAbortController,k=void 0===R?function(){try{if("undefined"!=typeof window&&"AbortController"in window)return function(){return new window.AbortController};if("fetch"in globalThis)return function(){return new globalThis.AbortController}}catch(t){console.error('Unleash failed to resolve "AbortController" factory',t)}}():R,O=e.bootstrap,N=e.bootstrapOverride,A=void 0===N||N,D=e.headerName,U=void 0===D?"Authorization":D,C=e.customHeaders,P=void 0===C?{}:C,j=e.impressionDataAll,H=void 0!==j&&j,M=e.usePOSTrequests,_=void 0!==M&&M,K=t.call(this)||this;if(K.toggles=[],K.etag="",K.readyEventEmitted=!1,K.usePOSTrequests=!1,K.started=!1,!o)throw new Error("url is required");if(!i)throw new Error("clientKey is required");if(!y)throw new Error("appName is required.");return K.eventsHandler=new b,K.impressionDataAll=H,K.toggles=O&&O.length>0?O:[],K.url=o instanceof URL?o:new URL(o),K.clientKey=i,K.headerName=U,K.customHeaders=P,K.storage=n||("undefined"!=typeof window?new f:new h),K.refreshInterval=a?0:1e3*u,K.context=r({appName:y,environment:w},I),K.usePOSTrequests=_,K.sdkState="initializing",K.ready=new Promise((function(t){K.init().then(t).catch((function(e){console.error(e),K.sdkState="error",K.emit(E.ERROR,e),t()}))})),x||console.error('Unleash: You must either provide your own "fetch" implementation or run in an environment where "fetch" is available.'),k||console.error('Unleash: You must either provide your own "AbortController" implementation or run in an environment where "AbortController" is available.'),K.fetch=x,K.createAbortController=k,K.bootstrap=O&&O.length>0?O:void 0,K.bootstrapOverride=A,K.metrics=new l({onError:K.emit.bind(K,E.ERROR),onSent:K.emit.bind(K,E.SENT),appName:y,metricsInterval:d,disableMetrics:m,url:K.url,clientKey:i,fetch:x,headerName:U,customHeaders:P}),K}return function(t,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function n(){this.constructor=t}e(t,r),t.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}(i,t),i.prototype.getAllToggles=function(){return function(t,e,r){if(r||2===arguments.length)for(var n,o=0,i=e.length;o<i;o++)!n&&o in e||(n||(n=Array.prototype.slice.call(e,0,o)),n[o]=e[o]);return t.concat(n||Array.prototype.slice.call(e))}([],this.toggles,!0)},i.prototype.isEnabled=function(t){var e,r=this.toggles.find((function(e){return e.name===t})),n=!!r&&r.enabled;if(this.metrics.count(t,n),(null==r?void 0:r.impressionData)||this.impressionDataAll){var o=this.eventsHandler.createImpressionEvent(this.context,n,t,I,null!==(e=null==r?void 0:r.impressionData)&&void 0!==e?e:void 0);this.emit(E.IMPRESSION,o)}return n},i.prototype.getVariant=function(t){var e,n=this.toggles.find((function(e){return e.name===t})),o=(null==n?void 0:n.enabled)||!1,i=n?n.variant:x;if(i.name&&this.metrics.countVariant(t,i.name),this.metrics.count(t,o),(null==n?void 0:n.impressionData)||this.impressionDataAll){var s=this.eventsHandler.createImpressionEvent(this.context,o,t,S,null!==(e=null==n?void 0:n.impressionData)&&void 0!==e?e:void 0,i.name);this.emit(E.IMPRESSION,s)}return r(r({},i),{feature_enabled:o})},i.prototype.updateContext=function(t){return n(this,void 0,void 0,(function(){var e,n=this;return o(this,(function(o){switch(o.label){case 0:return(t.appName||t.environment)&&console.warn("appName and environment are static. They can't be updated with updateContext."),e={environment:this.context.environment,appName:this.context.appName,sessionId:this.context.sessionId},this.context=r(r({},e),t),this.timerRef||this.readyEventEmitted?[4,this.fetchToggles()]:[3,2];case 1:return o.sent(),[3,4];case 2:return this.started?[4,new Promise((function(t){var e=function(){n.fetchToggles().then((function(){n.off(E.READY,e),t()}))};n.once(E.READY,e)}))]:[3,4];case 3:o.sent(),o.label=4;case 4:return[2]}}))}))},i.prototype.getContext=function(){return r({},this.context)},i.prototype.setContextField=function(t,e){var n,o;if(w.includes(t))this.context=r(r({},this.context),((n={})[t]=e,n));else{var i=r(r({},this.context.properties),((o={})[t]=e,o));this.context=r(r({},this.context),{properties:i})}this.timerRef&&this.fetchToggles()},i.prototype.init=function(){return n(this,void 0,void 0,(function(){var t,e;return o(this,(function(n){switch(n.label){case 0:return[4,this.resolveSessionId()];case 1:return t=n.sent(),this.context=r({sessionId:t},this.context),e=this,[4,this.storage.get(R)];case 2:return e.toggles=n.sent()||[],!this.bootstrap||!this.bootstrapOverride&&0!==this.toggles.length?[3,4]:[4,this.storage.save(R,this.bootstrap)];case 3:n.sent(),this.toggles=this.bootstrap,this.emit(E.READY),n.label=4;case 4:return this.sdkState="healthy",this.emit(E.INIT),[2]}}))}))},i.prototype.start=function(){return n(this,void 0,void 0,(function(){var t,e=this;return o(this,(function(r){switch(r.label){case 0:return this.started=!0,this.timerRef?(console.error("Unleash SDK has already started, if you want to restart the SDK you should call client.stop() before starting again."),[2]):[4,this.ready];case 1:return r.sent(),this.metrics.start(),t=this.refreshInterval,[4,this.fetchToggles()];case 2:return r.sent(),t>0&&(this.timerRef=setInterval((function(){return e.fetchToggles()}),t)),[2]}}))}))},i.prototype.stop=function(){this.timerRef&&(clearInterval(this.timerRef),this.timerRef=void 0),this.metrics.stop()},i.prototype.resolveSessionId=function(){return n(this,void 0,void 0,(function(){var t;return o(this,(function(e){switch(e.label){case 0:return this.context.sessionId?[2,this.context.sessionId]:[3,1];case 1:return[4,this.storage.get("sessionId")];case 2:return(t=e.sent())?[3,4]:(t=Math.floor(1e9*Math.random()),[4,this.storage.save("sessionId",t)]);case 3:e.sent(),e.label=4;case 4:return[2,t]}}))}))},i.prototype.getHeaders=function(){var t,e=((t={})[this.headerName]=this.clientKey,t.Accept="application/json",t["Content-Type"]="application/json",t["If-None-Match"]=this.etag,t);return Object.entries(this.customHeaders).filter(c).forEach((function(t){var r=t[0],n=t[1];return e[r]=n})),e},i.prototype.storeToggles=function(t){return n(this,void 0,void 0,(function(){return o(this,(function(e){switch(e.label){case 0:return this.toggles=t,this.emit(E.UPDATE),[4,this.storage.save(R,t)];case 1:return e.sent(),[2]}}))}))},i.prototype.fetchToggles=function(){return n(this,void 0,void 0,(function(){var t,e,r,n,i,s,a,u;return o(this,(function(o){switch(o.label){case 0:if(!this.fetch)return[3,9];this.abortController&&this.abortController.abort(),this.abortController=this.createAbortController&&this.createAbortController(),t=this.abortController?this.abortController.signal:void 0,o.label=1;case 1:return o.trys.push([1,7,8,9]),e=this.usePOSTrequests,r=e?this.url:function(t,e){var r=new URL(t.toString());return Object.entries(e).filter(c).forEach((function(t){var e=t[0],n=t[1];"properties"===e&&n?Object.entries(n).filter(c).forEach((function(t){var e=t[0],n=t[1];return r.searchParams.append("properties[".concat(e,"]"),n)})):r.searchParams.append(e,n)})),r}(this.url,this.context),n=e?"POST":"GET",i=e?JSON.stringify({context:this.context}):void 0,[4,this.fetch(r.toString(),{method:n,headers:this.getHeaders(),body:i,signal:t})];case 2:return s=o.sent(),"error"===this.sdkState&&s.status<400&&(this.sdkState="healthy",this.emit(E.RECOVERED)),s.ok&&304!==s.status?(this.etag=s.headers.get("ETag")||"",[4,s.json()]):[3,5];case 3:return a=o.sent(),[4,this.storeToggles(a.toggles)];case 4:return o.sent(),"healthy"!==this.sdkState&&(this.sdkState="healthy"),this.bootstrap||this.readyEventEmitted||(this.emit(E.READY),this.readyEventEmitted=!0),[3,6];case 5:s.ok||304===s.status||(console.error("Unleash: Fetching feature toggles did not have an ok response"),this.sdkState="error",this.emit(E.ERROR,{type:"HttpError",code:s.status})),o.label=6;case 6:return[3,9];case 7:return u=o.sent(),console.error("Unleash: unable to fetch feature toggles",u),this.sdkState="error",this.emit(E.ERROR,u),[3,9];case 8:return this.abortController=null,[7];case 9:return[2]}}))}))},i}(a);t.EVENTS=E,t.InMemoryStorageProvider=h,t.LocalStorageProvider=f,t.UnleashClient=k,t.resolveFetch=T})); | ||
//# sourceMappingURL=main.min.js.map |
{ | ||
"name": "unleash-proxy-client", | ||
"version": "3.2.0", | ||
"version": "3.3.0-alpha.1", | ||
"description": "A browser client that can be used together with the unleash-proxy.", | ||
@@ -5,0 +5,0 @@ "type": "module", |
@@ -146,2 +146,4 @@ # Unleash Proxy Client for the browser (JS) | ||
- **update** - emitted every time the Unleash Proxy return a new feature toggle configuration. The SDK will emit this event as part of the initial fetch from the SDK. | ||
- **recovered** - emitted when the SDK has recovered from an error. This event will only be emitted if the SDK has previously emitted an error. | ||
- **sent** - emitted when the SDK has successfully sent metrics to Unleash. | ||
@@ -148,0 +150,0 @@ > PS! Please remember that you should always register your event listeners before your call `unleash.start()`. If you register them after you have started the SDK you risk loosing important events. |
@@ -600,2 +600,21 @@ import { FetchMock } from 'jest-fetch-mock'; | ||
test('Should abort previous request', async () => { | ||
fetchMock.mockResponse(JSON.stringify(data)); | ||
const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); | ||
const config: IConfig = { | ||
url: 'http://localhost/test', | ||
clientKey: '12', | ||
appName: 'web', | ||
}; | ||
const client = new UnleashClient(config); | ||
await client.start(); | ||
client.updateContext({ userId: '123' }); // abort 1 | ||
client.updateContext({ userId: '456' }); // abort 2 | ||
await client.updateContext({ userId: '789' }); | ||
expect(abortSpy).toBeCalledTimes(2); | ||
abortSpy.mockRestore(); | ||
}); | ||
test.each([400, 401, 403, 404, 429, 500, 502, 503])( | ||
@@ -1558,1 +1577,54 @@ 'Should publish error when fetch receives a %d error', | ||
}); | ||
test('Should emit RECOVERED event when sdkStatus is error and status is less than 400', (done) => { | ||
const data = { status: 200 }; // replace with the actual data you want to test | ||
fetchMock.mockResponseOnce(JSON.stringify(data), { status: 200 }); | ||
const config: IConfig = { | ||
url: 'http://localhost/test', | ||
clientKey: '12', | ||
appName: 'web', | ||
}; | ||
const client = new UnleashClient(config); | ||
client.start(); | ||
client.on(EVENTS.INIT, () => { | ||
// Set error after the SDK has moved through the sdk states internally | ||
// eslint-disable-next-line | ||
// @ts-ignore - Private method by design, but we want to access it in tests | ||
client.sdkState = 'error'; | ||
}); | ||
client.on(EVENTS.RECOVERED, () => { | ||
// eslint-disable-next-line | ||
// @ts-ignore - Private method by design. but we want to access it in tests | ||
expect(client.sdkState).toBe('healthy'); | ||
client.stop(); | ||
done(); | ||
}); | ||
}); | ||
test('Should set sdkState to healthy when client is started', (done) => { | ||
const config: IConfig = { | ||
url: 'http://localhost/test', | ||
clientKey: '12', | ||
appName: 'web', | ||
}; | ||
const client = new UnleashClient(config); | ||
// eslint-disable-next-line | ||
// @ts-ignore - Private method by design, but we want to access it in tests | ||
expect(client.sdkState).toBe('initializing'); | ||
client.start(); | ||
client.on(EVENTS.INIT, () => { | ||
// eslint-disable-next-line | ||
// @ts-ignore - Private method by design, but we want to access it in tests | ||
expect(client.sdkState).toBe('healthy'); | ||
client.stop(); | ||
done(); | ||
}); | ||
}); |
@@ -37,2 +37,3 @@ import { TinyEmitter } from 'tiny-emitter'; | ||
fetch?: any; | ||
createAbortController?: () => AbortController; | ||
bootstrap?: IToggle[]; | ||
@@ -70,2 +71,3 @@ bootstrapOverride?: boolean; | ||
SENT: 'sent', | ||
RECOVERED: 'recovered', | ||
}; | ||
@@ -85,2 +87,4 @@ | ||
type SdkState = 'initializing' | 'healthy' | 'error'; | ||
export const resolveFetch = () => { | ||
@@ -100,2 +104,14 @@ try { | ||
const resolveAbortController = () => { | ||
try { | ||
if (typeof window !== 'undefined' && 'AbortController' in window) { | ||
return () => new window.AbortController(); | ||
} else if ('fetch' in globalThis) { | ||
return () => new globalThis.AbortController(); | ||
} | ||
} catch (e) { | ||
console.error('Unleash failed to resolve "AbortController" factory', e); | ||
} | ||
}; | ||
export class UnleashClient extends TinyEmitter { | ||
@@ -114,2 +130,4 @@ private toggles: IToggle[] = []; | ||
private fetch: any; | ||
private createAbortController?: () => AbortController; | ||
private abortController?: AbortController | null; | ||
private bootstrap?: IToggle[]; | ||
@@ -123,2 +141,3 @@ private bootstrapOverride: boolean; | ||
private started = false; | ||
private sdkState: SdkState; | ||
@@ -137,2 +156,3 @@ constructor({ | ||
fetch = resolveFetch(), | ||
createAbortController = resolveAbortController(), | ||
bootstrap, | ||
@@ -171,2 +191,3 @@ bootstrapOverride = true, | ||
this.usePOSTrequests = usePOSTrequests; | ||
this.sdkState = 'initializing'; | ||
this.ready = new Promise((resolve) => { | ||
@@ -177,2 +198,3 @@ this.init() | ||
console.error(error); | ||
this.sdkState = 'error'; | ||
this.emit(EVENTS.ERROR, error); | ||
@@ -188,4 +210,10 @@ resolve(); | ||
} | ||
if (!createAbortController) { | ||
console.error( | ||
'Unleash: You must either provide your own "AbortController" implementation or run in an environment where "AbortController" is available.' | ||
); | ||
} | ||
this.fetch = fetch; | ||
this.createAbortController = createAbortController; | ||
this.bootstrap = | ||
@@ -315,2 +343,4 @@ bootstrap && bootstrap.length > 0 ? bootstrap : undefined; | ||
} | ||
this.sdkState = 'healthy'; | ||
this.emit(EVENTS.INIT); | ||
@@ -380,2 +410,11 @@ } | ||
if (this.fetch) { | ||
if (this.abortController) { | ||
this.abortController.abort(); | ||
} | ||
this.abortController = | ||
this.createAbortController && this.createAbortController(); | ||
const signal = this.abortController | ||
? this.abortController.signal | ||
: undefined; | ||
try { | ||
@@ -394,6 +433,11 @@ const isPOST = this.usePOSTrequests; | ||
method, | ||
cache: 'no-cache', | ||
headers: this.getHeaders(), | ||
body, | ||
signal, | ||
}); | ||
if (this.sdkState === 'error' && response.status < 400) { | ||
this.sdkState = 'healthy'; | ||
this.emit(EVENTS.RECOVERED); | ||
} | ||
if (response.ok && response.status !== 304) { | ||
@@ -404,2 +448,6 @@ this.etag = response.headers.get('ETag') || ''; | ||
if (this.sdkState !== 'healthy') { | ||
this.sdkState = 'healthy'; | ||
} | ||
if (!this.bootstrap && !this.readyEventEmitted) { | ||
@@ -413,2 +461,3 @@ this.emit(EVENTS.READY); | ||
); | ||
this.sdkState = 'error'; | ||
this.emit(EVENTS.ERROR, { | ||
@@ -421,3 +470,6 @@ type: 'HttpError', | ||
console.error('Unleash: unable to fetch feature toggles', e); | ||
this.sdkState = 'error'; | ||
this.emit(EVENTS.ERROR, e); | ||
} finally { | ||
this.abortController = null; | ||
} | ||
@@ -424,0 +476,0 @@ } |
@@ -138,3 +138,2 @@ // Simplified version of: https://github.com/Unleash/unleash-client-node/blob/main/src/metrics.ts | ||
await this.fetch(url, { | ||
cache: 'no-cache', | ||
method: 'POST', | ||
@@ -141,0 +140,0 @@ headers: this.getHeaders(), |
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
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
303753
2872
283
1