UNPKG

@harnessio/ff-javascript-client-sdk

Version:

Basic library for integrating CF into javascript applications.

3 lines (2 loc) 19.6 kB
var HarnessFFSDK=(()=>{var k=Object.defineProperty,Me=Object.defineProperties,xe=Object.getOwnPropertyDescriptor,Fe=Object.getOwnPropertyDescriptors,Ne=Object.getOwnPropertyNames,le=Object.getOwnPropertySymbols;var ue=Object.prototype.hasOwnProperty,Ve=Object.prototype.propertyIsEnumerable;var ce=(t,e,i)=>e in t?k(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[e]=i,I=(t,e)=>{for(var i in e||(e={}))ue.call(e,i)&&ce(t,i,e[i]);if(le)for(var i of le(e))Ve.call(e,i)&&ce(t,i,e[i]);return t},F=(t,e)=>Me(t,Fe(e));var ke=(t,e)=>{for(var i in e)k(t,i,{get:e[i],enumerable:!0})},_e=(t,e,i,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Ne(e))!ue.call(t,o)&&o!==i&&k(t,o,{get:()=>e[o],enumerable:!(a=xe(e,o))||a.enumerable});return t};var Le=t=>_e(k({},"__esModule",{value:!0}),t);var E=(t,e,i)=>new Promise((a,o)=>{var l=R=>{try{p(i.next(R))}catch(d){o(d)}},g=R=>{try{p(i.throw(R))}catch(d){o(d)}},p=R=>R.done?a(R.value):Promise.resolve(R.value).then(l,g);p((i=i.apply(t,e)).next())});var ze={};ke(ze,{Event:()=>M,initialize:()=>Xe});function Y(t){this.message=t}Y.prototype=new Error,Y.prototype.name="InvalidCharacterError";var de=typeof window!="undefined"&&window.atob&&window.atob.bind(window)||function(t){var e=String(t).replace(/=+$/,"");if(e.length%4==1)throw new Y("'atob' failed: The string to be decoded is not correctly encoded.");for(var i,a,o=0,l=0,g="";a=e.charAt(l++);~a&&(i=o%4?64*i+a:a,o++%4)?g+=String.fromCharCode(255&i>>(-2*o&6)):0)a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(a);return g};function He(t){var e=t.replace(/-/g,"+").replace(/_/g,"/");switch(e.length%4){case 0:break;case 2:e+="==";break;case 3:e+="=";break;default:throw"Illegal base64url string!"}try{return function(i){return decodeURIComponent(de(i).replace(/(.)/g,function(a,o){var l=o.charCodeAt(0).toString(16).toUpperCase();return l.length<2&&(l="0"+l),"%"+l}))}(e)}catch(i){return de(e)}}function _(t){this.message=t}function $e(t,e){if(typeof t!="string")throw new _("Invalid token specified");var i=(e=e||{}).header===!0?0:1;try{return JSON.parse(He(t.split(".")[i]))}catch(a){throw new _("Invalid token specified: "+a.message)}}_.prototype=new Error,_.prototype.name="InvalidTokenError";var ge=$e;function fe(t){return{all:t=t||new Map,on:function(e,i){var a=t.get(e);a&&a.push(i)||t.set(e,[i])},off:function(e,i){var a=t.get(e);a&&a.splice(a.indexOf(i)>>>0,1)},emit:function(e,i){(t.get(e)||[]).slice().map(function(a){a(i)}),(t.get("*")||[]).slice().map(function(a){a(e,i)})}}}var M=(c=>(c.READY="ready",c.CONNECTED="connected",c.DISCONNECTED="disconnected",c.STOPPED="stopped",c.POLLING="polling",c.POLLING_STOPPED="polling stopped",c.FLAGS_LOADED="flags loaded",c.CACHE_LOADED="cache loaded",c.CHANGED="changed",c.ERROR="error",c.ERROR_CACHE="cache error",c.ERROR_METRICS="metrics error",c.ERROR_AUTH="auth error",c.ERROR_FETCH_FLAGS="fetch flags error",c.ERROR_FETCH_FLAG="fetch flag error",c.ERROR_STREAM="stream error",c.ERROR_DEFAULT_VARIATION_RETURNED="default variation returned",c))(M||{});var qe={debug:!1,baseUrl:"https://config.ff.harness.io/api/1.0",eventUrl:"https://events.ff.harness.io/api/1.0",eventsSyncInterval:6e4,pollingInterval:6e4,enableAnalytics:!0,streamEnabled:!0,cache:!1,authRequestReadTimeout:0,maxStreamRetries:1/0},he=t=>{let e=I(I({},qe),t);return e.pollingEnabled===void 0&&(e.pollingEnabled=e.streamEnabled),e.eventsSyncInterval<6e4&&(e.eventsSyncInterval=6e4),e.pollingInterval<6e4&&(e.pollingInterval=6e4),(!e.logger||!e.logger.debug||!e.logger.error||!e.logger.info||!e.logger.warn)&&(e.logger=console),e},X=(t,e=!0)=>{e?setTimeout(t,0):t()},L=(t,e)=>Math.round(Math.random()*(e-t)+t),me=t=>{let e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",i="",a=0,o=Ge(JSON.stringify(t));for(;a<o.length;){let l=o.charCodeAt(a++),g=o.charCodeAt(a++),p=o.charCodeAt(a++),R=l>>2,d=(l&3)<<4|g>>4,b=(g&15)<<2|p>>6,O=p&63;isNaN(g)?b=O=64:isNaN(p)&&(O=64),i+=e.charAt(R)+e.charAt(d)+e.charAt(b)+e.charAt(O)}return i},Ge=t=>t.replace(/\r\n/g,` `).split("").map(e=>{let i=e.charCodeAt(0);return i<128?String.fromCharCode(i):i>127&&i<2048?String.fromCharCode(i>>6|192)+String.fromCharCode(i&63|128):String.fromCharCode(i>>12|224)+String.fromCharCode(i>>6&63|128)+String.fromCharCode(i&63|128)}).join("");function H(t){return[...t].sort(({flag:e},{flag:i})=>e<i?-1:1)}function z(t){return function(...i){let[a,o]=t(i);return fetch(a,o)}}var ve=3e4,$=class{constructor(e,i,a,o,l,g,p,R,d,b,O){this.eventBus=e;this.configurations=i;this.url=a;this.apiKey=o;this.standardHeaders=l;this.fallbackPoller=g;this.logDebug=p;this.logError=R;this.eventCallback=d;this.maxRetries=b;this.middleware=O;this.closed=!1;this.connectionOpened=!1;this.disconnectEventEmitted=!1;this.reconnectAttempts=0;this.retriesExhausted=!1}registerAPIRequestMiddleware(e){this.middleware=e}start(){let e=d=>{d.toString().split(/\r?\n/).forEach(i)},i=d=>{if(d.startsWith("data:")){let b=JSON.parse(d.substring(5));this.logDebugMessage("Received event from stream: ",b),this.eventCallback(b)}},a=()=>{this.logDebugMessage("Stream connected"),this.eventBus.emit("connected"),this.reconnectAttempts=0},o=()=>{clearInterval(this.readTimeoutCheckerId);let d=L(1e3,3e4);if(this.reconnectAttempts++,this.logDebugMessage("Stream disconnected, will reconnect in "+d+"ms"),this.disconnectEventEmitted||(this.eventBus.emit("disconnected"),this.disconnectEventEmitted=!0),this.reconnectAttempts>=5&&this.reconnectAttempts%5===0&&this.logErrorMessage(`Reconnection failed after ${this.reconnectAttempts} attempts; attempting further reconnections.`),this.reconnectAttempts>=this.maxRetries){this.retriesExhausted=!0,this.configurations.pollingEnabled?this.logErrorMessage("Max streaming retries reached. Staying in polling mode."):this.logErrorMessage("Max streaming retries reached. Polling mode is disabled and will receive no further flag updates until SDK client is restarted.");return}setTimeout(()=>this.start(),d)},l=d=>{this.retriesExhausted||(d&&this.logDebugMessage("Stream has issue",d),this.fallBackToPolling(),this.eventBus.emit("stream error",d),this.eventBus.emit("error",d),o())},g=I({"Cache-Control":"no-cache",Accept:"text/event-stream","API-Key":this.apiKey},this.standardHeaders);if(this.middleware){let[d,b]=this.middleware([this.url,{headers:g}]);this.url=d,g=(b==null?void 0:b.headers)||{}}this.logDebugMessage("SSE HTTP start request",this.url),this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url);for(let[d,b]of Object.entries(g))this.xhr.setRequestHeader(d,b);this.xhr.timeout=24*60*60*1e3,this.xhr.onerror=()=>{this.connectionOpened=!1,l("XMLHttpRequest error on SSE stream")},this.xhr.onabort=()=>{this.connectionOpened=!1,this.logDebugMessage("SSE aborted"),this.closed||l(null)},this.xhr.ontimeout=()=>{this.connectionOpened=!1,l("SSE timeout")},this.xhr.onload=()=>{l(`Received XMLHttpRequest onLoad event: ${this.xhr.status}`)};let p=0,R=Date.now();this.xhr.onprogress=()=>{this.connectionOpened||(a(),this.connectionOpened=!0,this.disconnectEventEmitted=!1),this.stopFallBackPolling(),R=Date.now();let d=this.xhr.responseText.slice(p);p+=d.length,this.logDebugMessage("SSE GOT: "+d),e(d)},this.readTimeoutCheckerId=setInterval(()=>{R<Date.now()-ve&&(this.logDebugMessage("SSE read timeout"),this.xhr.abort())},ve),this.xhr.send()}close(){this.connectionOpened=!1,this.closed=!0,this.xhr&&this.xhr.abort(),clearInterval(this.readTimeoutCheckerId),this.eventBus.emit("stopped"),this.stopFallBackPolling()}fallBackToPolling(){!this.fallbackPoller.isPolling()&&this.configurations.pollingEnabled&&(this.logDebugMessage("Falling back to polling mode while stream recovers"),this.fallbackPoller.start())}stopFallBackPolling(){this.fallbackPoller.isPolling()&&(this.logDebugMessage("Stopping fallback polling mode"),this.fallbackPoller.stop())}logDebugMessage(e,...i){this.configurations.debug&&this.logDebug(`Streaming: ${e}`,...i)}logErrorMessage(e,...i){this.logError(`Streaming: ${e}`,...i)}};function pe(t,e,i,a,o,l){let g=t in i,p=g?i[t]:e;if(g)a(t,p);else{let R={flag:t,defaultVariation:e};o.emit("default variation returned",R)}return l?{value:p,isDefaultValue:!g}:p}var N=class{constructor(e,i,a,o,l){this.fetchFlagsFn=e;this.configurations=i;this.eventBus=a;this.logDebug=o;this.logError=l;this.maxAttempts=5}start(){if(this.isPolling()){this.logDebugMessage("Already polling.");return}this.isRunning=!0,this.eventBus.emit("polling"),this.logDebugMessage(`Starting poller, first poll will be in ${this.configurations.pollingInterval}ms`),this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)}poll(){this.isRunning&&this.attemptFetch().finally(()=>{this.isRunning&&(this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval))})}attemptFetch(){return E(this,null,function*(){for(let e=1;e<=this.maxAttempts;e++){let i=yield this.fetchFlagsFn();if(i.type==="success"){this.logDebugMessage(`Successfully polled for flag updates, next poll in ${this.configurations.pollingInterval}ms. `);return}if(this.logErrorMessage("Error when polling for flag updates",i.error),e>=this.maxAttempts){this.logDebugMessage(`Maximum attempts reached for polling for flags. Next poll in ${this.configurations.pollingInterval}ms.`);return}this.logDebugMessage(`Polling for flags attempt #${e} failed. Remaining attempts: ${this.maxAttempts-e}`,i.error);let a=L(1e3,1e4);yield new Promise(o=>setTimeout(o,a))}})}stop(){this.timeoutId&&(this.isRunning=!1,clearTimeout(this.timeoutId),this.timeoutId=void 0,this.eventBus.emit("polling stopped"),this.logDebugMessage("Polling stopped"))}isPolling(){return this.isRunning}logDebugMessage(e,...i){this.configurations.debug&&this.logDebug(`Poller: ${e}`,...i)}logErrorMessage(e,...i){this.logError(`Poller: ${e}`,...i)}};function Ee(i){return E(this,arguments,function*(t,e={}){let a=yield je(t),o=Je(e);return{loadFromCache:()=>Q(a,o,e),saveToCache:l=>Z(a,o,l),updateCachedEvaluation:l=>Ue(a,o,l),removeCachedEvaluation:l=>Ke(a,o,l)}})}function Q(a,o){return E(this,arguments,function*(t,e,i={}){let l=parseInt(yield e.getItem(t+".ts"));if(i!=null&&i.ttl&&!isNaN(l)&&l+i.ttl<Date.now())return yield Be(t,e),[];let g=yield e.getItem(t);if(g)try{return JSON.parse(g)}catch(p){}return[]})}function Be(t,e){return E(this,null,function*(){yield e.removeItem(t),yield e.removeItem(t+".ts")})}function Z(t,e,i){return E(this,null,function*(){yield e.setItem(t,JSON.stringify(H(i))),yield e.setItem(t+".ts",Date.now().toString())})}function Ue(t,e,i){return E(this,null,function*(){let a=yield Q(t,e),o=a.find(({flag:l})=>l===i.flag);o?Object.assign(o,i):a.push(i),yield Z(t,e,a)})}function Ke(t,e,i){return E(this,null,function*(){let a=yield Q(t,e),o=a.findIndex(({flag:l})=>l===i);o>-1&&(a.splice(o,1),yield Z(t,e,a))})}function Re(t,e,i={}){return i.deriveKeyFromTargetAttributes?JSON.stringify(Object.keys(t.attributes||{}).sort().filter(a=>!Array.isArray(i.deriveKeyFromTargetAttributes)||i.deriveKeyFromTargetAttributes.includes(a)).reduce((a,o)=>F(I({},a),{[o]:t.attributes[o]}),{}))+t.identifier+e:t.identifier+e}function je(t){return E(this,null,function*(){var i,a;let e=t;if(globalThis!=null&&globalThis.TextEncoder&&((a=(i=globalThis==null?void 0:globalThis.crypto)==null?void 0:i.subtle)!=null&&a.digest)){let l=new TextEncoder().encode(t),g=yield crypto.subtle.digest("SHA-256",l);e=Array.from(new Uint8Array(g)).map(R=>R.toString(16).padStart(2,"0")).join("")}else globalThis.btoa&&(e=btoa(t));return"HARNESS_FF_CACHE_"+e})}function Je(t){let e;return!t.storage||typeof t.storage!="object"||!("getItem"in t.storage)||!("setItem"in t.storage)||!("removeItem"in t.storage)?globalThis.localStorage?e=globalThis.localStorage:globalThis.sessionStorage?e=globalThis.sessionStorage:e=We:e=t.storage,{getItem(a){return E(this,null,function*(){let o=e.getItem(a);return o instanceof Promise?yield o:o})},setItem(a,o){return E(this,null,function*(){let l=e.setItem(a,o);l instanceof Promise&&(yield l)})},removeItem(a){return E(this,null,function*(){let o=e.removeItem(a);o instanceof Promise&&(yield o)})}}}var We={getItem:()=>null,setItem:()=>{},removeItem:()=>{}};var ye="1.32.0",be=`Javascript ${ye} Client`,Ye=500,ee=!!globalThis.Proxy,Xe=(t,e,i)=>{let a=!1,o,l,g,p,R,d,b={},O=n=>n,x=z(O),te=0,ie=!1,q=!1,w=[],c=he(i),Ie=c.enableAnalytics,h=fe(),G=()=>{q=!0},B=()=>{q=!1},D=()=>Ie&&!q,y=(n,...r)=>{c.debug&&c.logger.debug(`[FF-SDK] ${n}`,...r)},A=(n,...r)=>{c.logger.error(`[FF-SDK] ${n}`,...r)},Se=(n,...r)=>{c.logger.warn(`[FF-SDK] ${n}`,...r)},U=n=>{let{value:r}=n;try{switch(n.kind.toLowerCase()){case"int":case"number":r=Number(r);break;case"boolean":r=r.toString().toLowerCase()==="true";break;case"json":r=JSON.parse(r);break}}catch(u){A(u)}return r},K=n=>{if(D()){let r=Date.now();r-n.lastAccessed>Ye&&(n.count++,n.lastAccessed=r)}},we=()=>E(void 0,null,function*(){if(c.cache){y("initializing cache");try{let n=!0,r=typeof c.cache=="boolean"?{}:c.cache,u=yield Ee(Re(e,t,r),r),m=yield u.loadFromCache();m!=null&&m.length&&X(()=>{y("loading from cache",m),oe(m,!1),h.emit("cache loaded",m)}),W("flags loaded",v=>E(void 0,null,function*(){yield u.saveToCache(v),n=!1})),W("changed",v=>E(void 0,null,function*(){n||(v.deleted?yield u.removeCachedEvaluation(v.flag):yield u.updateCachedEvaluation(v))}))}catch(n){A("Cache error: ",n),h.emit("cache error",n),h.emit("error",n)}}}),Ae=(n,r)=>E(void 0,null,function*(){let u=`${r.baseUrl}/client/auth`,m={method:"POST",headers:{"Content-Type":"application/json","Harness-SDK-Info":be},body:JSON.stringify({apiKey:n,target:F(I({},e),{identifier:String(e.identifier)})})},v,s;window.AbortController&&c.authRequestReadTimeout>0?(s=new AbortController,m.signal=s.signal,v=window.setTimeout(()=>s.abort(),r.authRequestReadTimeout)):r.authRequestReadTimeout>0&&Se("AbortController is not available, auth request will not timeout");try{let f=yield x(u,m);if(!f.ok)throw new Error(`${f.status}: ${f.statusText}`);return(yield f.json()).authToken}catch(f){if(s&&s.signal.aborted)throw new Error(`Request to ${u} failed: Request timeout via configured authRequestTimeout of ${c.authRequestReadTimeout}`);let T=f instanceof Error?f.message:String(f);throw new Error(`Request to ${u} failed: ${T}`)}finally{v&&clearTimeout(v)}}),j=0,J=()=>{if(D())if(w.length){y("Sending metrics...",{metrics:w,evaluations:S});let n={metricsData:w.map(r=>({timestamp:Date.now(),count:r.count,metricsType:"FFMETRICS",attributes:[{key:"featureIdentifier",value:r.featureIdentifier},{key:"featureName",value:r.featureIdentifier},{key:"variationIdentifier",value:r.variationIdentifier},{key:"target",value:e.identifier},{key:"SDK_NAME",value:"JavaScript"},{key:"SDK_LANGUAGE",value:"JavaScript"},{key:"SDK_TYPE",value:"client"},{key:"SDK_VERSION",value:ye}]}))};x(`${c.eventUrl}/metrics/${o}?cluster=${l}`,{method:"POST",headers:I({"Content-Type":"application/json"},b),body:JSON.stringify(n)}).then(()=>{w=[],j=0}).catch(r=>{j++&&(w=[],j=0),y(r),h.emit("metrics error",r)}).finally(()=>{d=window.setTimeout(J,c.eventsSyncInterval)})}else d=window.setTimeout(J,c.eventsSyncInterval)},S={},Ce=n=>{y("Sending event for",n.flag),ee?h.emit("changed",new Proxy(n,{get(r,u){var m;if(D()&&r.hasOwnProperty(u)&&u==="value"){let v=r.flag,s=n.value,f=w.find(T=>T.featureIdentifier===v&&T.featureValue===s);f?(K(f),f.variationIdentifier=((m=S[v])==null?void 0:m.identifier)||""):w.push({featureIdentifier:v,featureValue:String(s),variationIdentifier:S[v].identifier||"",count:1,lastAccessed:Date.now()}),y("Metrics event: Flag",u,"has been read with value via stream update",s)}return u==="value"?U(n):n[u]}})):h.emit("changed",{deleted:n.deleted,flag:n.flag,value:U(n)})},ne=function(){return ee?new Proxy({},{get(n,r){var m,v,s;let u=n[r];if(D()&&n.hasOwnProperty(r)){let f=n[r],T=w.find(se=>se.featureIdentifier===r&&f===se.featureValue);T?(T.variationIdentifier=((m=S[r])==null?void 0:m.identifier)||"",K(T)):w.push({featureIdentifier:r,featureValue:f,variationIdentifier:((v=S[r])==null?void 0:v.identifier)||"",count:1,lastAccessed:Date.now()}),y("Metrics event: Flag:",r,"has been read with value:",f,"variationIdentifier:",(s=S[r])==null?void 0:s.identifier)}return u}}):{}},C=ne();we().then(()=>Ae(t,c).then(n=>E(void 0,null,function*(){if(a)return;R=n;let r=ge(n);b={Authorization:`Bearer ${R}`,"Harness-AccountID":r.accountID,"Harness-EnvironmentID":r.environmentIdentifier,"Harness-SDK-Info":be};let u=me(e);u.length<262144&&(b["Harness-Target"]=u),y("Authenticated",r),D()&&(d=window.setTimeout(J,c.eventsSyncInterval)),o=r.environment,l=r.clusterIdentifier;let m=!!Object.keys(S).length;if((yield V()).type==="success"&&y("Fetch all flags ok",C),!a){if(c.streamEnabled?(y("Streaming mode enabled"),Te()):c.pollingEnabled?(y("Polling mode enabled"),Oe()):y("Streaming and polling mode disabled"),!m){G();let s=I({},C);B(),h.emit("ready",s)}ie=!0}})).catch(n=>{A("Authentication error: ",n),h.emit("auth error",n),h.emit("error",n)}));let V=()=>E(void 0,null,function*(){try{let n=yield x(`${c.baseUrl}/client/env/${o}/target/${e.identifier}/evaluations?cluster=${l}`,{headers:b});if(n.ok){let r=H(yield n.json());return r.forEach(P),h.emit("flags loaded",r),{type:"success",data:r}}else return A("Features fetch operation error: ",n),h.emit("fetch flags error",n),h.emit("error",n),{type:"error",error:n}}catch(n){return A("Features fetch operation error: ",n),h.emit("fetch flags error",n),h.emit("error",n),{type:"error",error:n}}}),re=n=>E(void 0,null,function*(){try{let r=yield x(`${c.baseUrl}/client/env/${o}/target/${e.identifier}/evaluations/${n}?cluster=${l}`,{headers:b});if(r.ok){let u=yield r.json();P(u)}else A("Feature fetch operation error: ",r),h.emit("fetch flag error",r),h.emit("error",r)}catch(r){A("Feature fetch operation error: ",r),h.emit("fetch flag error",r),h.emit("error",r)}}),P=n=>{G();let r=U(n);r!==C[n.flag]&&(y("Flag variation has changed for ",n.identifier),C[n.flag]=r,S[n.flag]=F(I({},n),{value:r}),Ce(n)),B()};p=new N(V,c,h,y,A);let Te=()=>{let n=s=>{switch(s.event){case"create":u(s.evaluations)?s.evaluations.forEach(f=>{P(f)}):setTimeout(()=>re(s.identifier),1e3);break;case"patch":u(s.evaluations)?s.evaluations.forEach(f=>{P(f)}):re(s.identifier);break;case"delete":delete C[s.identifier],h.emit("changed",{flag:s.identifier,value:void 0,deleted:!0}),y("Evaluation deleted",{message:s,storage:C});break}},r=s=>!(!s||!s.flag||!s.identifier||!s.kind||!s.value),u=s=>!(!s||s.length==0||!s.every(f=>r(f))),m=s=>{s.event==="patch"&&(u(s.evaluations)?s.evaluations.forEach(f=>{P(f)}):V())},v=`${c.baseUrl}/stream?cluster=${l}`;g=new $(h,c,v,t,b,p,y,A,s=>{s.domain==="flag"?n(s):s.domain==="target-segment"&&m(s)},c.maxStreamRetries,O),g.start()},Oe=()=>{p.start()},W=(n,r)=>h.on(n,r),De=(n,r)=>{n?h.off(n,r):ae()},Pe=(n,r)=>{var s;if(!D()||ee||r===void 0)return;let u=r,m=n,v=w.find(f=>f.featureIdentifier===m&&f.featureValue===u);v?(K(v),v.variationIdentifier=((s=S[m])==null?void 0:s.identifier)||""):w.push({featureIdentifier:m,featureValue:u,count:1,variationIdentifier:S[m].identifier||"",lastAccessed:Date.now()})},ae=()=>{a=!0,c.streamEnabled&&(y("Closing event stream"),typeof(g==null?void 0:g.close)=="function"&&g.close(),h.all.clear()),c.pollingEnabled&&p.isPolling()&&(y("Closing Poller"),p.stop()),C=ne(),S={},clearTimeout(d)},oe=(n,r=!0)=>{n.length&&X(()=>{let u=!!Object.keys(S).length;if(n.forEach(P),!u){G();let m=I({},C);B(),h.emit("ready",m)}},r)};return{on:W,off:De,close:ae,setEvaluations:oe,registerAPIRequestMiddleware:n=>{O=n,x=z(n),g&&g.registerAPIRequestMiddleware(n)},refreshEvaluations:()=>{ie&&!a&&Date.now()-te>=6e4&&(V(),te=Date.now())},variation:(n,r,u=!1)=>pe(n,r,C,Pe,h,u)}};return Le(ze);})();