@harnessio/ff-javascript-client-sdk
Advanced tools
Comparing version 1.25.0-rc.0 to 1.25.0
@@ -1,1 +0,1 @@ | ||
var Ie=Object.create;var F=Object.defineProperty,Ce=Object.defineProperties,Oe=Object.getOwnPropertyDescriptor,Te=Object.getOwnPropertyDescriptors,we=Object.getOwnPropertyNames,ne=Object.getOwnPropertySymbols,Ae=Object.getPrototypeOf,re=Object.prototype.hasOwnProperty,De=Object.prototype.propertyIsEnumerable;var ae=(t,e,a)=>e in t?F(t,e,{enumerable:!0,configurable:!0,writable:!0,value:a}):t[e]=a,T=(t,e)=>{for(var a in e||(e={}))re.call(e,a)&&ae(t,a,e[a]);if(ne)for(var a of ne(e))De.call(e,a)&&ae(t,a,e[a]);return t},K=(t,e)=>Ce(t,Te(e));var Pe=(t,e)=>{for(var a in e)F(t,a,{get:e[a],enumerable:!0})},oe=(t,e,a,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of we(e))!re.call(t,r)&&r!==a&&F(t,r,{get:()=>e[r],enumerable:!(o=Oe(e,r))||o.enumerable});return t};var se=(t,e,a)=>(a=t!=null?Ie(Ae(t)):{},oe(e||!t||!t.__esModule?F(a,"default",{value:t,enumerable:!0}):a,t)),Fe=t=>oe(F({},"__esModule",{value:!0}),t);var h=(t,e,a)=>new Promise((o,r)=>{var l=R=>{try{b(a.next(R))}catch(d){r(d)}},g=R=>{try{b(a.throw(R))}catch(d){r(d)}},b=R=>R.done?o(R.value):Promise.resolve(R.value).then(l,g);b((a=a.apply(t,e)).next())});var $e={};Pe($e,{Event:()=>x,initialize:()=>Be});module.exports=Fe($e);var ge=se(require("jwt-decode")),he=se(require("mitt"));var x=(m=>(m.READY="ready",m.CONNECTED="connected",m.DISCONNECTED="disconnected",m.STOPPED="stopped",m.POLLING="polling",m.POLLING_STOPPED="polling stopped",m.FLAGS_LOADED="flags loaded",m.CACHE_LOADED="cache loaded",m.CHANGED="changed",m.ERROR="error",m.ERROR_CACHE="cache error",m.ERROR_METRICS="metrics error",m.ERROR_AUTH="auth error",m.ERROR_FETCH_FLAGS="fetch flags error",m.ERROR_FETCH_FLAG="fetch flag error",m.ERROR_STREAM="stream error",m))(x||{});var xe={debug:!1,baseUrl:"https://config.ff.harness.io/api/1.0",eventUrl:"https://events.ff.harness.io/api/1.0",eventsSyncInterval:6e4,pollingInterval:6e4,streamEnabled:!0,cache:!1},le=t=>{let e=T(T({},xe),t);if(e.pollingEnabled===void 0&&(e.pollingEnabled=e.streamEnabled),e.eventsSyncInterval<6e4&&(e.eventsSyncInterval=6e4),e.pollingInterval<6e4&&(e.pollingInterval=6e4),e.streamEnabled)try{let{Platform:a}=require("react-native");a.OS==="android"&&(console.info("SDKCODE:1007 Android React Native detected - streaming will be disabled and polling enabled"),e.pollingEnabled=!0,e.streamEnabled=!1)}catch(a){}return e},S=(t,...e)=>console.error(`[FF-SDK] ${t}`,...e),j=(t,e=!0)=>{e?setTimeout(t,0):t()},_=(t,e)=>Math.round(Math.random()*(e-t)+t);function q(t){return function(...a){let[o,r]=t(a);return fetch(o,r)}}var ce=3e4,L=class{constructor(e,a,o,r,l,g,b){this.closed=!1;this.connectionOpened=!1;this.disconnectEventEmitted=!1;this.eventBus=e,this.configurations=a,this.url=o,this.apiKey=r,this.standardHeaders=l,this.eventCallback=b,this.fallbackPoller=g}start(){let e=d=>{d.toString().split(/\r?\n/).forEach(a)},a=d=>{if(d.startsWith("data:")){let C=JSON.parse(d.substring(5));this.logDebug("Received event from stream: ",C),this.eventCallback(C)}},o=()=>{this.logDebug("Stream connected"),this.eventBus.emit("connected")},r=()=>{clearInterval(this.readTimeoutCheckerId);let d=_(1e3,1e4);this.logDebug("Stream disconnected, will reconnect in "+d+"ms"),this.disconnectEventEmitted||(this.eventBus.emit("disconnected"),this.disconnectEventEmitted=!0),setTimeout(()=>this.start(),d)},l=d=>{d&&S("Stream has issue",d),this.fallBackToPolling(),this.eventBus.emit("stream error",d),this.eventBus.emit("error",d),r()},g=T({"Cache-Control":"no-cache",Accept:"text/event-stream","API-Key":this.apiKey},this.standardHeaders);this.logDebug("SSE HTTP start request",this.url),this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url);for(let[d,C]of Object.entries(g))this.xhr.setRequestHeader(d,C);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.logDebug("SSE aborted"),this.closed||l(null)},this.xhr.ontimeout=()=>{this.connectionOpened=!1,l("SSE timeout")},this.xhr.onload=()=>{if(this.xhr.status>=400&&this.xhr.status<=599){l(`HTTP code ${this.xhr.status}`);return}this.connectionOpened||(o(),this.connectionOpened=!0,this.disconnectEventEmitted=!1)};let b=0,R=Date.now();this.xhr.onprogress=()=>{this.connectionOpened||(o(),this.connectionOpened=!0,this.disconnectEventEmitted=!1),this.stopFallBackPolling(),R=Date.now();let d=this.xhr.responseText.slice(b);b+=d.length,this.logDebug("SSE GOT: "+d),e(d)},this.readTimeoutCheckerId=setInterval(()=>{R<Date.now()-ce&&(S("SSE read timeout"),this.xhr.abort())},ce),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.logDebug("Falling back to polling mode while stream recovers"),this.fallbackPoller.start())}stopFallBackPolling(){this.fallbackPoller.isPolling()&&(this.logDebug("Stopping fallback polling mode"),this.fallbackPoller.stop())}logDebug(e,...a){this.configurations.debug&&console.debug(`[FF-SDK] Streaming: ${e}`,...a)}};function de(t,e,a,o,r){let l=t in a,g=l?a[t]:e;return l&&o(t,g),r?{value:g,isDefaultValue:!l}:g}var N=class{constructor(e,a,o){this.fetchFlagsFn=e;this.configurations=a;this.eventBus=o;this.maxAttempts=5}start(){if(this.isPolling()){this.logDebug("Already polling.");return}this.isRunning=!0,this.eventBus.emit("polling"),this.logDebug(`Starting poller, first poll will be in ${this.configurations.pollingInterval}ms`),this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)}poll(){this.attemptFetch().finally(()=>{this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)})}attemptFetch(){return h(this,null,function*(){for(let e=1;e<=this.maxAttempts;e++){let a=yield this.fetchFlagsFn();if(a.type==="success"){this.logDebug(`Successfully polled for flag updates, next poll in ${this.configurations.pollingInterval}ms. `);return}if(S("Error when polling for flag updates",a.error),e>=this.maxAttempts){this.logDebug(`Maximum attempts reached for polling for flags. Next poll in ${this.configurations.pollingInterval}ms.`);return}this.logDebug(`Polling for flags attempt #${e} failed. Remaining attempts: ${this.maxAttempts-e}`,a.error);let o=_(1e3,1e4);yield new Promise(r=>setTimeout(r,o))}})}stop(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=void 0,this.isRunning=!1,this.eventBus.emit("polling stopped"),this.logDebug("Polling stopped"))}isPolling(){return this.isRunning}logDebug(e,...a){this.configurations.debug&&console.debug(`[FF-SDK] Poller: ${e}`,...a)}};function ue(a){return h(this,arguments,function*(t,e={}){let o=yield _e(t),r=Le(e);return{loadFromCache:()=>U(o,r,e),saveToCache:l=>W(o,r,l),updateCachedEvaluation:l=>ke(o,r,l),removeCachedEvaluation:l=>Ve(o,r,l)}})}function U(o,r){return h(this,arguments,function*(t,e,a={}){let l=parseInt(yield e.getItem(t+".ts"));if(a!=null&&a.ttl&&!isNaN(l)&&l+a.ttl<Date.now())return yield Ne(t,e),[];let g=yield e.getItem(t);if(g)try{return JSON.parse(g)}catch(b){}return[]})}function Ne(t,e){return h(this,null,function*(){yield e.removeItem(t),yield e.removeItem(t+".ts")})}function W(t,e,a){return h(this,null,function*(){yield e.setItem(t,JSON.stringify(a)),yield e.setItem(t+".ts",Date.now().toString())})}function ke(t,e,a){return h(this,null,function*(){let o=yield U(t,e),r=o.find(({flag:l})=>l===a.flag);r?Object.assign(r,a):o.push(a),yield W(t,e,o)})}function Ve(t,e,a){return h(this,null,function*(){let o=yield U(t,e),r=o.findIndex(({flag:l})=>l===a);r>-1&&(o.splice(r,1),yield W(t,e,o))})}function _e(t){return h(this,null,function*(){var a,o;let e=t;if(globalThis!=null&&globalThis.TextEncoder&&((o=(a=globalThis==null?void 0:globalThis.crypto)==null?void 0:a.subtle)!=null&&o.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 Le(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=Me:e=t.storage,{getItem(o){return h(this,null,function*(){let r=e.getItem(o);return r instanceof Promise?yield r:r})},setItem(o,r){return h(this,null,function*(){let l=e.setItem(o,r);l instanceof Promise&&(yield l)})},removeItem(o){return h(this,null,function*(){let r=e.removeItem(o);r instanceof Promise&&(yield r)})}}}var Me={getItem:()=>null,setItem:()=>{},removeItem:()=>{}};var me="1.25.0",fe=`Javascript ${me} Client`,He=500,Ge=globalThis.fetch,J=!!globalThis.Proxy,Y=t=>{let{value:e}=t;try{switch(t.kind.toLowerCase()){case"int":case"number":e=Number(e);break;case"boolean":e=e.toString().toLowerCase()==="true";break;case"json":e=JSON.parse(e);break}}catch(a){S(a)}return e},Be=(t,e,a)=>{let o=!1,r,l,g,b,R,d,C=!0,A={},k=q(i=>i),X=0,z=!1,M=()=>{C=!1},m=()=>{C=!0},O=[],u=(0,he.default)(),v=le(a),y=(i,...n)=>{v.debug&&console.debug(`[FF-SDK] ${i}`,...n)},H=i=>{if(C){let n=Date.now();n-i.lastAccessed>He&&(i.count++,i.lastAccessed=n)}},ve=()=>h(void 0,null,function*(){if(v.cache)try{let i=!0,n=yield ue(e.identifier+t,typeof v.cache=="boolean"?{}:v.cache),c=yield n.loadFromCache();c!=null&&c.length&&j(()=>{y("loading from cache",c),te(c,!1),u.emit("cache loaded",c)}),$("flags loaded",f=>h(void 0,null,function*(){yield n.saveToCache(f),i=!1})),$("changed",f=>h(void 0,null,function*(){i||(f.deleted?yield n.removeCachedEvaluation(f.flag):yield n.updateCachedEvaluation(f))}))}catch(i){S("Cache error: ",i),u.emit("cache error",i),u.emit("error",i)}}),pe=(i,n)=>h(void 0,null,function*(){return(yield(yield Ge(`${n.baseUrl}/client/auth`,{method:"POST",headers:{"Content-Type":"application/json","Harness-SDK-Info":fe},body:JSON.stringify({apiKey:i,target:K(T({},e),{identifier:String(e.identifier)})})})).json()).authToken}),G=0,B=()=>{if(O.length){y("Sending metrics...",{metrics:O,evaluations:I});let i={metricsData:O.map(n=>({timestamp:Date.now(),count:n.count,metricsType:"FFMETRICS",attributes:[{key:"featureIdentifier",value:n.featureIdentifier},{key:"featureName",value:n.featureIdentifier},{key:"variationIdentifier",value:n.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:me}]}))};k(`${v.eventUrl}/metrics/${r}?cluster=${l}`,{method:"POST",headers:T({"Content-Type":"application/json"},A),body:JSON.stringify(i)}).then(()=>{O=[],G=0}).catch(n=>{G++&&(O=[],G=0),y(n),u.emit("metrics error",n)}).finally(()=>{d=window.setTimeout(B,v.eventsSyncInterval)})}else d=window.setTimeout(B,v.eventsSyncInterval)},I={},Ee=i=>{y("Sending event for",i.flag),J?u.emit("changed",new Proxy(i,{get(n,c){var f;if(C&&n.hasOwnProperty(c)&&c==="value"){let p=n.flag,s=i.value,E=O.find(P=>P.featureIdentifier===p&&P.featureValue===s);E?(H(E),E.variationIdentifier=((f=I[p])==null?void 0:f.identifier)||""):O.push({featureIdentifier:p,featureValue:String(s),variationIdentifier:I[p].identifier||"",count:1,lastAccessed:Date.now()}),y("Metrics event: Flag",c,"has been read with value via stream update",s)}return c==="value"?Y(i):i[c]}})):u.emit("changed",{deleted:i.deleted,flag:i.flag,value:Y(i)})},Q=function(){return J?new Proxy({},{get(i,n){var f,p,s;let c=i[n];if(C&&i.hasOwnProperty(n)){let E=i[n],P=O.find(ie=>ie.featureIdentifier===n&&E===ie.featureValue);P?(P.variationIdentifier=((f=I[n])==null?void 0:f.identifier)||"",H(P)):O.push({featureIdentifier:n,featureValue:E,variationIdentifier:((p=I[n])==null?void 0:p.identifier)||"",count:1,lastAccessed:Date.now()}),y("Metrics event: Flag:",n,"has been read with value:",E,"variationIdentifier:",(s=I[n])==null?void 0:s.identifier)}return c}}):{}},w=Q();ve().then(()=>pe(t,v).then(i=>h(void 0,null,function*(){if(o)return;R=i;let n=(0,ge.default)(i);if(A={Authorization:`Bearer ${R}`,"Harness-AccountID":n.accountID,"Harness-EnvironmentID":n.environmentIdentifier,"Harness-SDK-Info":fe},globalThis.btoa){let p=globalThis.btoa(JSON.stringify(e));p.length<262144&&(A["Harness-Target"]=p)}y("Authenticated",n),d=window.setTimeout(B,v.eventsSyncInterval),r=n.environment,l=n.clusterIdentifier;let c=!!Object.keys(I).length;if((yield V()).type==="success"&&y("Fetch all flags ok",w),!o){if(v.streamEnabled?(y("Streaming mode enabled"),be()):v.pollingEnabled?(y("Polling mode enabled"),Re()):y("Streaming and polling mode disabled"),!c){M();let p=T({},w);m(),u.emit("ready",p)}z=!0}})).catch(i=>{S("Authentication error: ",i),u.emit("auth error",i),u.emit("error",i)}));let V=()=>h(void 0,null,function*(){try{let i=yield k(`${v.baseUrl}/client/env/${r}/target/${e.identifier}/evaluations?cluster=${l}`,{headers:A});if(i.ok){let n=yield i.json();return n.forEach(D),u.emit("flags loaded",n),{type:"success",data:n}}else return S("Features fetch operation error: ",i),u.emit("fetch flags error",i),u.emit("error",i),{type:"error",error:i}}catch(i){return S("Features fetch operation error: ",i),u.emit("fetch flags error",i),u.emit("error",i),{type:"error",error:i}}}),Z=i=>h(void 0,null,function*(){try{let n=yield k(`${v.baseUrl}/client/env/${r}/target/${e.identifier}/evaluations/${i}?cluster=${l}`,{headers:A});if(n.ok){let c=yield n.json();D(c)}else S("Feature fetch operation error: ",n),u.emit("fetch flag error",n),u.emit("error",n)}catch(n){S("Feature fetch operation error: ",n),u.emit("fetch flag error",n),u.emit("error",n)}}),D=i=>{M();let n=Y(i);n!==w[i.flag]&&(y("Flag variation has changed for ",i.identifier),w[i.flag]=n,I[i.flag]=K(T({},i),{value:n}),Ee(i)),m()};b=new N(V,v,u);let be=()=>{let i=s=>{switch(s.event){case"create":c(s.evaluations)?s.evaluations.forEach(E=>{D(E)}):setTimeout(()=>Z(s.identifier),1e3);break;case"patch":c(s.evaluations)?s.evaluations.forEach(E=>{D(E)}):Z(s.identifier);break;case"delete":delete w[s.identifier],u.emit("changed",{flag:s.identifier,value:void 0,deleted:!0}),y("Evaluation deleted",{message:s,storage:w});break}},n=s=>!(!s||!s.flag||!s.identifier||!s.kind||!s.value),c=s=>!(!s||s.length==0||!s.every(E=>n(E))),f=s=>{s.event==="patch"&&(c(s.evaluations)?s.evaluations.forEach(E=>{D(E)}):V())},p=`${v.baseUrl}/stream?cluster=${l}`;g=new L(u,v,p,t,A,b,s=>{s.domain==="flag"?i(s):s.domain==="target-segment"&&f(s)}),g.start()},Re=()=>{b.start()},$=(i,n)=>u.on(i,n),ye=(i,n)=>{i?u.off(i,n):ee()},Se=(i,n)=>{var s;if(!C||J||n===void 0)return;let c=n,f=i,p=O.find(E=>E.featureIdentifier===f&&E.featureValue===c);p?(H(p),p.variationIdentifier=((s=I[f])==null?void 0:s.identifier)||""):O.push({featureIdentifier:f,featureValue:c,count:1,variationIdentifier:I[f].identifier||"",lastAccessed:Date.now()})},ee=()=>{o=!0,v.streamEnabled&&(y("Closing event stream"),typeof(g==null?void 0:g.close)=="function"&&g.close(),u.all.clear()),v.pollingEnabled&&b.isPolling()&&(y("Closing Poller"),b.stop()),w=Q(),I={},clearTimeout(d)},te=(i,n=!0)=>{i.length&&j(()=>{let c=!!Object.keys(I).length;if(i.forEach(D),!c){M();let f=T({},w);m(),u.emit("ready",f)}},n)};return{on:$,off:ye,close:ee,setEvaluations:te,registerAPIRequestMiddleware:i=>{k=q(i)},refreshEvaluations:()=>{z&&!o&&Date.now()-X>=6e4&&(V(),X=Date.now())},variation:(i,n,c=!1)=>de(i,n,w,Se,c)}};0&&(module.exports={Event,initialize}); | ||
var Se=Object.create;var F=Object.defineProperty,Ce=Object.defineProperties,Te=Object.getOwnPropertyDescriptor,Oe=Object.getOwnPropertyDescriptors,we=Object.getOwnPropertyNames,ne=Object.getOwnPropertySymbols,Ae=Object.getPrototypeOf,re=Object.prototype.hasOwnProperty,De=Object.prototype.propertyIsEnumerable;var ae=(t,e,a)=>e in t?F(t,e,{enumerable:!0,configurable:!0,writable:!0,value:a}):t[e]=a,O=(t,e)=>{for(var a in e||(e={}))re.call(e,a)&&ae(t,a,e[a]);if(ne)for(var a of ne(e))De.call(e,a)&&ae(t,a,e[a]);return t},K=(t,e)=>Ce(t,Oe(e));var Pe=(t,e)=>{for(var a in e)F(t,a,{get:e[a],enumerable:!0})},oe=(t,e,a,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of we(e))!re.call(t,r)&&r!==a&&F(t,r,{get:()=>e[r],enumerable:!(o=Te(e,r))||o.enumerable});return t};var se=(t,e,a)=>(a=t!=null?Se(Ae(t)):{},oe(e||!t||!t.__esModule?F(a,"default",{value:t,enumerable:!0}):a,t)),Fe=t=>oe(F({},"__esModule",{value:!0}),t);var h=(t,e,a)=>new Promise((o,r)=>{var l=y=>{try{R(a.next(y))}catch(u){r(u)}},g=y=>{try{R(a.throw(y))}catch(u){r(u)}},R=y=>y.done?o(y.value):Promise.resolve(y.value).then(l,g);R((a=a.apply(t,e)).next())});var $e={};Pe($e,{Event:()=>x,initialize:()=>Be});module.exports=Fe($e);var ge=se(require("jwt-decode")),he=se(require("mitt"));var x=(m=>(m.READY="ready",m.CONNECTED="connected",m.DISCONNECTED="disconnected",m.STOPPED="stopped",m.POLLING="polling",m.POLLING_STOPPED="polling stopped",m.FLAGS_LOADED="flags loaded",m.CACHE_LOADED="cache loaded",m.CHANGED="changed",m.ERROR="error",m.ERROR_CACHE="cache error",m.ERROR_METRICS="metrics error",m.ERROR_AUTH="auth error",m.ERROR_FETCH_FLAGS="fetch flags error",m.ERROR_FETCH_FLAG="fetch flag error",m.ERROR_STREAM="stream error",m))(x||{});var xe={debug:!1,baseUrl:"https://config.ff.harness.io/api/1.0",eventUrl:"https://events.ff.harness.io/api/1.0",eventsSyncInterval:6e4,pollingInterval:6e4,streamEnabled:!0,cache:!1},le=t=>{let e=O(O({},xe),t);return e.pollingEnabled===void 0&&(e.pollingEnabled=e.streamEnabled),e.eventsSyncInterval<6e4&&(e.eventsSyncInterval=6e4),e.pollingInterval<6e4&&(e.pollingInterval=6e4),e},I=(t,...e)=>console.error(`[FF-SDK] ${t}`,...e),j=(t,e=!0)=>{e?setTimeout(t,0):t()},_=(t,e)=>Math.round(Math.random()*(e-t)+t);function U(t){return function(...a){let[o,r]=t(a);return fetch(o,r)}}var ce=3e4,L=class{constructor(e,a,o,r,l,g,R){this.closed=!1;this.connectionOpened=!1;this.disconnectEventEmitted=!1;this.eventBus=e,this.configurations=a,this.url=o,this.apiKey=r,this.standardHeaders=l,this.eventCallback=R,this.fallbackPoller=g}start(){let e=u=>{u.toString().split(/\r?\n/).forEach(a)},a=u=>{if(u.startsWith("data:")){let C=JSON.parse(u.substring(5));this.logDebug("Received event from stream: ",C),this.eventCallback(C)}},o=()=>{this.logDebug("Stream connected"),this.eventBus.emit("connected")},r=()=>{clearInterval(this.readTimeoutCheckerId);let u=_(1e3,1e4);this.logDebug("Stream disconnected, will reconnect in "+u+"ms"),this.disconnectEventEmitted||(this.eventBus.emit("disconnected"),this.disconnectEventEmitted=!0),setTimeout(()=>this.start(),u)},l=u=>{u&&I("Stream has issue",u),this.fallBackToPolling(),this.eventBus.emit("stream error",u),this.eventBus.emit("error",u),r()},g=O({"Cache-Control":"no-cache",Accept:"text/event-stream","API-Key":this.apiKey},this.standardHeaders);this.logDebug("SSE HTTP start request",this.url),this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url);for(let[u,C]of Object.entries(g))this.xhr.setRequestHeader(u,C);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.logDebug("SSE aborted"),this.closed||l(null)},this.xhr.ontimeout=()=>{this.connectionOpened=!1,l("SSE timeout")},this.xhr.onload=()=>{if(this.xhr.status>=400&&this.xhr.status<=599){l(`HTTP code ${this.xhr.status}`);return}this.connectionOpened||(o(),this.connectionOpened=!0,this.disconnectEventEmitted=!1)};let R=0,y=Date.now();this.xhr.onprogress=()=>{this.connectionOpened||(o(),this.connectionOpened=!0,this.disconnectEventEmitted=!1),this.stopFallBackPolling(),y=Date.now();let u=this.xhr.responseText.slice(R);R+=u.length,this.logDebug("SSE GOT: "+u),e(u)},this.readTimeoutCheckerId=setInterval(()=>{y<Date.now()-ce&&(I("SSE read timeout"),this.xhr.abort())},ce),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.logDebug("Falling back to polling mode while stream recovers"),this.fallbackPoller.start())}stopFallBackPolling(){this.fallbackPoller.isPolling()&&(this.logDebug("Stopping fallback polling mode"),this.fallbackPoller.stop())}logDebug(e,...a){this.configurations.debug&&console.debug(`[FF-SDK] Streaming: ${e}`,...a)}};function ue(t,e,a,o,r){let l=t in a,g=l?a[t]:e;return l&&o(t,g),r?{value:g,isDefaultValue:!l}:g}var N=class{constructor(e,a,o){this.fetchFlagsFn=e;this.configurations=a;this.eventBus=o;this.maxAttempts=5}start(){if(this.isPolling()){this.logDebug("Already polling.");return}this.isRunning=!0,this.eventBus.emit("polling"),this.logDebug(`Starting poller, first poll will be in ${this.configurations.pollingInterval}ms`),this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)}poll(){this.attemptFetch().finally(()=>{this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)})}attemptFetch(){return h(this,null,function*(){for(let e=1;e<=this.maxAttempts;e++){let a=yield this.fetchFlagsFn();if(a.type==="success"){this.logDebug(`Successfully polled for flag updates, next poll in ${this.configurations.pollingInterval}ms. `);return}if(I("Error when polling for flag updates",a.error),e>=this.maxAttempts){this.logDebug(`Maximum attempts reached for polling for flags. Next poll in ${this.configurations.pollingInterval}ms.`);return}this.logDebug(`Polling for flags attempt #${e} failed. Remaining attempts: ${this.maxAttempts-e}`,a.error);let o=_(1e3,1e4);yield new Promise(r=>setTimeout(r,o))}})}stop(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=void 0,this.isRunning=!1,this.eventBus.emit("polling stopped"),this.logDebug("Polling stopped"))}isPolling(){return this.isRunning}logDebug(e,...a){this.configurations.debug&&console.debug(`[FF-SDK] Poller: ${e}`,...a)}};function de(a){return h(this,arguments,function*(t,e={}){let o=yield _e(t),r=Le(e);return{loadFromCache:()=>q(o,r,e),saveToCache:l=>W(o,r,l),updateCachedEvaluation:l=>ke(o,r,l),removeCachedEvaluation:l=>Ve(o,r,l)}})}function q(o,r){return h(this,arguments,function*(t,e,a={}){let l=parseInt(yield e.getItem(t+".ts"));if(a!=null&&a.ttl&&!isNaN(l)&&l+a.ttl<Date.now())return yield Ne(t,e),[];let g=yield e.getItem(t);if(g)try{return JSON.parse(g)}catch(R){}return[]})}function Ne(t,e){return h(this,null,function*(){yield e.removeItem(t),yield e.removeItem(t+".ts")})}function W(t,e,a){return h(this,null,function*(){yield e.setItem(t,JSON.stringify(a)),yield e.setItem(t+".ts",Date.now().toString())})}function ke(t,e,a){return h(this,null,function*(){let o=yield q(t,e),r=o.find(({flag:l})=>l===a.flag);r?Object.assign(r,a):o.push(a),yield W(t,e,o)})}function Ve(t,e,a){return h(this,null,function*(){let o=yield q(t,e),r=o.findIndex(({flag:l})=>l===a);r>-1&&(o.splice(r,1),yield W(t,e,o))})}function _e(t){return h(this,null,function*(){var a,o;let e=t;if(globalThis!=null&&globalThis.TextEncoder&&((o=(a=globalThis==null?void 0:globalThis.crypto)==null?void 0:a.subtle)!=null&&o.digest)){let l=new TextEncoder().encode(t),g=yield crypto.subtle.digest("SHA-256",l);e=Array.from(new Uint8Array(g)).map(y=>y.toString(16).padStart(2,"0")).join("")}else globalThis.btoa&&(e=btoa(t));return"HARNESS_FF_CACHE_"+e})}function Le(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=Me:e=t.storage,{getItem(o){return h(this,null,function*(){let r=e.getItem(o);return r instanceof Promise?yield r:r})},setItem(o,r){return h(this,null,function*(){let l=e.setItem(o,r);l instanceof Promise&&(yield l)})},removeItem(o){return h(this,null,function*(){let r=e.removeItem(o);r instanceof Promise&&(yield r)})}}}var Me={getItem:()=>null,setItem:()=>{},removeItem:()=>{}};var me="1.25.0",fe=`Javascript ${me} Client`,He=500,Ge=globalThis.fetch,J=!!globalThis.Proxy,Y=t=>{let{value:e}=t;try{switch(t.kind.toLowerCase()){case"int":case"number":e=Number(e);break;case"boolean":e=e.toString().toLowerCase()==="true";break;case"json":e=JSON.parse(e);break}}catch(a){I(a)}return e},Be=(t,e,a)=>{let o=!1,r,l,g,R,y,u,C=!0,A={},k=U(i=>i),z=0,X=!1,M=()=>{C=!1},m=()=>{C=!0},T=[],d=(0,he.default)(),v=le(a),b=(i,...n)=>{v.debug&&console.debug(`[FF-SDK] ${i}`,...n)},H=i=>{if(C){let n=Date.now();n-i.lastAccessed>He&&(i.count++,i.lastAccessed=n)}},ve=()=>h(void 0,null,function*(){if(v.cache){b("initializing cache");try{let i=!0,n=yield de(e.identifier+t,typeof v.cache=="boolean"?{}:v.cache),c=yield n.loadFromCache();c!=null&&c.length&&j(()=>{b("loading from cache",c),te(c,!1),d.emit("cache loaded",c)}),$("flags loaded",f=>h(void 0,null,function*(){yield n.saveToCache(f),i=!1})),$("changed",f=>h(void 0,null,function*(){i||(f.deleted?yield n.removeCachedEvaluation(f.flag):yield n.updateCachedEvaluation(f))}))}catch(i){I("Cache error: ",i),d.emit("cache error",i),d.emit("error",i)}}}),pe=(i,n)=>h(void 0,null,function*(){return(yield(yield Ge(`${n.baseUrl}/client/auth`,{method:"POST",headers:{"Content-Type":"application/json","Harness-SDK-Info":fe},body:JSON.stringify({apiKey:i,target:K(O({},e),{identifier:String(e.identifier)})})})).json()).authToken}),G=0,B=()=>{if(T.length){b("Sending metrics...",{metrics:T,evaluations:S});let i={metricsData:T.map(n=>({timestamp:Date.now(),count:n.count,metricsType:"FFMETRICS",attributes:[{key:"featureIdentifier",value:n.featureIdentifier},{key:"featureName",value:n.featureIdentifier},{key:"variationIdentifier",value:n.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:me}]}))};k(`${v.eventUrl}/metrics/${r}?cluster=${l}`,{method:"POST",headers:O({"Content-Type":"application/json"},A),body:JSON.stringify(i)}).then(()=>{T=[],G=0}).catch(n=>{G++&&(T=[],G=0),b(n),d.emit("metrics error",n)}).finally(()=>{u=window.setTimeout(B,v.eventsSyncInterval)})}else u=window.setTimeout(B,v.eventsSyncInterval)},S={},Ee=i=>{b("Sending event for",i.flag),J?d.emit("changed",new Proxy(i,{get(n,c){var f;if(C&&n.hasOwnProperty(c)&&c==="value"){let p=n.flag,s=i.value,E=T.find(P=>P.featureIdentifier===p&&P.featureValue===s);E?(H(E),E.variationIdentifier=((f=S[p])==null?void 0:f.identifier)||""):T.push({featureIdentifier:p,featureValue:String(s),variationIdentifier:S[p].identifier||"",count:1,lastAccessed:Date.now()}),b("Metrics event: Flag",c,"has been read with value via stream update",s)}return c==="value"?Y(i):i[c]}})):d.emit("changed",{deleted:i.deleted,flag:i.flag,value:Y(i)})},Q=function(){return J?new Proxy({},{get(i,n){var f,p,s;let c=i[n];if(C&&i.hasOwnProperty(n)){let E=i[n],P=T.find(ie=>ie.featureIdentifier===n&&E===ie.featureValue);P?(P.variationIdentifier=((f=S[n])==null?void 0:f.identifier)||"",H(P)):T.push({featureIdentifier:n,featureValue:E,variationIdentifier:((p=S[n])==null?void 0:p.identifier)||"",count:1,lastAccessed:Date.now()}),b("Metrics event: Flag:",n,"has been read with value:",E,"variationIdentifier:",(s=S[n])==null?void 0:s.identifier)}return c}}):{}},w=Q();ve().then(()=>pe(t,v).then(i=>h(void 0,null,function*(){if(o)return;y=i;let n=(0,ge.default)(i);if(A={Authorization:`Bearer ${y}`,"Harness-AccountID":n.accountID,"Harness-EnvironmentID":n.environmentIdentifier,"Harness-SDK-Info":fe},globalThis.btoa){let p=globalThis.btoa(JSON.stringify(e));p.length<262144&&(A["Harness-Target"]=p)}b("Authenticated",n),u=window.setTimeout(B,v.eventsSyncInterval),r=n.environment,l=n.clusterIdentifier;let c=!!Object.keys(S).length;if((yield V()).type==="success"&&b("Fetch all flags ok",w),!o){if(v.streamEnabled?(b("Streaming mode enabled"),Re()):v.pollingEnabled?(b("Polling mode enabled"),be()):b("Streaming and polling mode disabled"),!c){M();let p=O({},w);m(),d.emit("ready",p)}X=!0}})).catch(i=>{I("Authentication error: ",i),d.emit("auth error",i),d.emit("error",i)}));let V=()=>h(void 0,null,function*(){try{let i=yield k(`${v.baseUrl}/client/env/${r}/target/${e.identifier}/evaluations?cluster=${l}`,{headers:A});if(i.ok){let n=yield i.json();return n.forEach(D),d.emit("flags loaded",n),{type:"success",data:n}}else return I("Features fetch operation error: ",i),d.emit("fetch flags error",i),d.emit("error",i),{type:"error",error:i}}catch(i){return I("Features fetch operation error: ",i),d.emit("fetch flags error",i),d.emit("error",i),{type:"error",error:i}}}),Z=i=>h(void 0,null,function*(){try{let n=yield k(`${v.baseUrl}/client/env/${r}/target/${e.identifier}/evaluations/${i}?cluster=${l}`,{headers:A});if(n.ok){let c=yield n.json();D(c)}else I("Feature fetch operation error: ",n),d.emit("fetch flag error",n),d.emit("error",n)}catch(n){I("Feature fetch operation error: ",n),d.emit("fetch flag error",n),d.emit("error",n)}}),D=i=>{M();let n=Y(i);n!==w[i.flag]&&(b("Flag variation has changed for ",i.identifier),w[i.flag]=n,S[i.flag]=K(O({},i),{value:n}),Ee(i)),m()};R=new N(V,v,d);let Re=()=>{let i=s=>{switch(s.event){case"create":c(s.evaluations)?s.evaluations.forEach(E=>{D(E)}):setTimeout(()=>Z(s.identifier),1e3);break;case"patch":c(s.evaluations)?s.evaluations.forEach(E=>{D(E)}):Z(s.identifier);break;case"delete":delete w[s.identifier],d.emit("changed",{flag:s.identifier,value:void 0,deleted:!0}),b("Evaluation deleted",{message:s,storage:w});break}},n=s=>!(!s||!s.flag||!s.identifier||!s.kind||!s.value),c=s=>!(!s||s.length==0||!s.every(E=>n(E))),f=s=>{s.event==="patch"&&(c(s.evaluations)?s.evaluations.forEach(E=>{D(E)}):V())},p=`${v.baseUrl}/stream?cluster=${l}`;g=new L(d,v,p,t,A,R,s=>{s.domain==="flag"?i(s):s.domain==="target-segment"&&f(s)}),g.start()},be=()=>{R.start()},$=(i,n)=>d.on(i,n),ye=(i,n)=>{i?d.off(i,n):ee()},Ie=(i,n)=>{var s;if(!C||J||n===void 0)return;let c=n,f=i,p=T.find(E=>E.featureIdentifier===f&&E.featureValue===c);p?(H(p),p.variationIdentifier=((s=S[f])==null?void 0:s.identifier)||""):T.push({featureIdentifier:f,featureValue:c,count:1,variationIdentifier:S[f].identifier||"",lastAccessed:Date.now()})},ee=()=>{o=!0,v.streamEnabled&&(b("Closing event stream"),typeof(g==null?void 0:g.close)=="function"&&g.close(),d.all.clear()),v.pollingEnabled&&R.isPolling()&&(b("Closing Poller"),R.stop()),w=Q(),S={},clearTimeout(u)},te=(i,n=!0)=>{i.length&&j(()=>{let c=!!Object.keys(S).length;if(i.forEach(D),!c){M();let f=O({},w);m(),d.emit("ready",f)}},n)};return{on:$,off:ye,close:ee,setEvaluations:te,registerAPIRequestMiddleware:i=>{k=U(i)},refreshEvaluations:()=>{X&&!o&&Date.now()-z>=6e4&&(V(),z=Date.now())},variation:(i,n,c=!1)=>ue(i,n,w,Ie,c)}};0&&(module.exports={Event,initialize}); |
@@ -1,1 +0,1 @@ | ||
var HarnessFFSDK=(()=>{var V=Object.defineProperty,we=Object.defineProperties,Ce=Object.getOwnPropertyDescriptor,Oe=Object.getOwnPropertyDescriptors,Te=Object.getOwnPropertyNames,re=Object.getOwnPropertySymbols;var se=Object.prototype.hasOwnProperty,Ae=Object.prototype.propertyIsEnumerable;var oe=(t,e,i)=>e in t?V(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[e]=i,O=(t,e)=>{for(var i in e||(e={}))se.call(e,i)&&oe(t,i,e[i]);if(re)for(var i of re(e))Ae.call(e,i)&&oe(t,i,e[i]);return t},U=(t,e)=>we(t,Oe(e));var De=(t=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(t,{get:(e,i)=>(typeof require!="undefined"?require:e)[i]}):t)(function(t){if(typeof require!="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var Pe=(t,e)=>{for(var i in e)V(t,i,{get:e[i],enumerable:!0})},Fe=(t,e,i,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Te(e))!se.call(t,o)&&o!==i&&V(t,o,{get:()=>e[o],enumerable:!(r=Ce(e,o))||r.enumerable});return t};var xe=t=>Fe(V({},"__esModule",{value:!0}),t);var h=(t,e,i)=>new Promise((r,o)=>{var s=y=>{try{b(i.next(y))}catch(d){o(d)}},f=y=>{try{b(i.throw(y))}catch(d){o(d)}},b=y=>y.done?r(y.value):Promise.resolve(y.value).then(s,f);b((i=i.apply(t,e)).next())});var je={};Pe(je,{Event:()=>F,initialize:()=>Ue});function j(t){this.message=t}j.prototype=new Error,j.prototype.name="InvalidCharacterError";var le=typeof window!="undefined"&&window.atob&&window.atob.bind(window)||function(t){var e=String(t).replace(/=+$/,"");if(e.length%4==1)throw new j("'atob' failed: The string to be decoded is not correctly encoded.");for(var i,r,o=0,s=0,f="";r=e.charAt(s++);~r&&(i=o%4?64*i+r:r,o++%4)?f+=String.fromCharCode(255&i>>(-2*o&6)):0)r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(r);return f};function ke(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(le(i).replace(/(.)/g,function(r,o){var s=o.charCodeAt(0).toString(16).toUpperCase();return s.length<2&&(s="0"+s),"%"+s}))}(e)}catch(i){return le(e)}}function _(t){this.message=t}function Ne(t,e){if(typeof t!="string")throw new _("Invalid token specified");var i=(e=e||{}).header===!0?0:1;try{return JSON.parse(ke(t.split(".")[i]))}catch(r){throw new _("Invalid token specified: "+r.message)}}_.prototype=new Error,_.prototype.name="InvalidTokenError";var ce=Ne;function de(t){return{all:t=t||new Map,on:function(e,i){var r=t.get(e);r&&r.push(i)||t.set(e,[i])},off:function(e,i){var r=t.get(e);r&&r.splice(r.indexOf(i)>>>0,1)},emit:function(e,i){(t.get(e)||[]).slice().map(function(r){r(i)}),(t.get("*")||[]).slice().map(function(r){r(e,i)})}}}var F=(m=>(m.READY="ready",m.CONNECTED="connected",m.DISCONNECTED="disconnected",m.STOPPED="stopped",m.POLLING="polling",m.POLLING_STOPPED="polling stopped",m.FLAGS_LOADED="flags loaded",m.CACHE_LOADED="cache loaded",m.CHANGED="changed",m.ERROR="error",m.ERROR_CACHE="cache error",m.ERROR_METRICS="metrics error",m.ERROR_AUTH="auth error",m.ERROR_FETCH_FLAGS="fetch flags error",m.ERROR_FETCH_FLAG="fetch flag error",m.ERROR_STREAM="stream error",m))(F||{});var Ve={debug:!1,baseUrl:"https://config.ff.harness.io/api/1.0",eventUrl:"https://events.ff.harness.io/api/1.0",eventsSyncInterval:6e4,pollingInterval:6e4,streamEnabled:!0,cache:!1},ue=t=>{let e=O(O({},Ve),t);if(e.pollingEnabled===void 0&&(e.pollingEnabled=e.streamEnabled),e.eventsSyncInterval<6e4&&(e.eventsSyncInterval=6e4),e.pollingInterval<6e4&&(e.pollingInterval=6e4),e.streamEnabled)try{let{Platform:i}=De("react-native");i.OS==="android"&&(console.info("SDKCODE:1007 Android React Native detected - streaming will be disabled and polling enabled"),e.pollingEnabled=!0,e.streamEnabled=!1)}catch(i){}return e},I=(t,...e)=>console.error(`[FF-SDK] ${t}`,...e),q=(t,e=!0)=>{e?setTimeout(t,0):t()},L=(t,e)=>Math.round(Math.random()*(e-t)+t);function J(t){return function(...i){let[r,o]=t(i);return fetch(r,o)}}var fe=3e4,M=class{constructor(e,i,r,o,s,f,b){this.closed=!1;this.connectionOpened=!1;this.disconnectEventEmitted=!1;this.eventBus=e,this.configurations=i,this.url=r,this.apiKey=o,this.standardHeaders=s,this.eventCallback=b,this.fallbackPoller=f}start(){let e=d=>{d.toString().split(/\r?\n/).forEach(i)},i=d=>{if(d.startsWith("data:")){let w=JSON.parse(d.substring(5));this.logDebug("Received event from stream: ",w),this.eventCallback(w)}},r=()=>{this.logDebug("Stream connected"),this.eventBus.emit("connected")},o=()=>{clearInterval(this.readTimeoutCheckerId);let d=L(1e3,1e4);this.logDebug("Stream disconnected, will reconnect in "+d+"ms"),this.disconnectEventEmitted||(this.eventBus.emit("disconnected"),this.disconnectEventEmitted=!0),setTimeout(()=>this.start(),d)},s=d=>{d&&I("Stream has issue",d),this.fallBackToPolling(),this.eventBus.emit("stream error",d),this.eventBus.emit("error",d),o()},f=O({"Cache-Control":"no-cache",Accept:"text/event-stream","API-Key":this.apiKey},this.standardHeaders);this.logDebug("SSE HTTP start request",this.url),this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url);for(let[d,w]of Object.entries(f))this.xhr.setRequestHeader(d,w);this.xhr.timeout=24*60*60*1e3,this.xhr.onerror=()=>{this.connectionOpened=!1,s("XMLHttpRequest error on SSE stream")},this.xhr.onabort=()=>{this.connectionOpened=!1,this.logDebug("SSE aborted"),this.closed||s(null)},this.xhr.ontimeout=()=>{this.connectionOpened=!1,s("SSE timeout")},this.xhr.onload=()=>{if(this.xhr.status>=400&&this.xhr.status<=599){s(`HTTP code ${this.xhr.status}`);return}this.connectionOpened||(r(),this.connectionOpened=!0,this.disconnectEventEmitted=!1)};let b=0,y=Date.now();this.xhr.onprogress=()=>{this.connectionOpened||(r(),this.connectionOpened=!0,this.disconnectEventEmitted=!1),this.stopFallBackPolling(),y=Date.now();let d=this.xhr.responseText.slice(b);b+=d.length,this.logDebug("SSE GOT: "+d),e(d)},this.readTimeoutCheckerId=setInterval(()=>{y<Date.now()-fe&&(I("SSE read timeout"),this.xhr.abort())},fe),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.logDebug("Falling back to polling mode while stream recovers"),this.fallbackPoller.start())}stopFallBackPolling(){this.fallbackPoller.isPolling()&&(this.logDebug("Stopping fallback polling mode"),this.fallbackPoller.stop())}logDebug(e,...i){this.configurations.debug&&console.debug(`[FF-SDK] Streaming: ${e}`,...i)}};function ge(t,e,i,r,o){let s=t in i,f=s?i[t]:e;return s&&r(t,f),o?{value:f,isDefaultValue:!s}:f}var x=class{constructor(e,i,r){this.fetchFlagsFn=e;this.configurations=i;this.eventBus=r;this.maxAttempts=5}start(){if(this.isPolling()){this.logDebug("Already polling.");return}this.isRunning=!0,this.eventBus.emit("polling"),this.logDebug(`Starting poller, first poll will be in ${this.configurations.pollingInterval}ms`),this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)}poll(){this.attemptFetch().finally(()=>{this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)})}attemptFetch(){return h(this,null,function*(){for(let e=1;e<=this.maxAttempts;e++){let i=yield this.fetchFlagsFn();if(i.type==="success"){this.logDebug(`Successfully polled for flag updates, next poll in ${this.configurations.pollingInterval}ms. `);return}if(I("Error when polling for flag updates",i.error),e>=this.maxAttempts){this.logDebug(`Maximum attempts reached for polling for flags. Next poll in ${this.configurations.pollingInterval}ms.`);return}this.logDebug(`Polling for flags attempt #${e} failed. Remaining attempts: ${this.maxAttempts-e}`,i.error);let r=L(1e3,1e4);yield new Promise(o=>setTimeout(o,r))}})}stop(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=void 0,this.isRunning=!1,this.eventBus.emit("polling stopped"),this.logDebug("Polling stopped"))}isPolling(){return this.isRunning}logDebug(e,...i){this.configurations.debug&&console.debug(`[FF-SDK] Poller: ${e}`,...i)}};function he(i){return h(this,arguments,function*(t,e={}){let r=yield He(t),o=Ge(e);return{loadFromCache:()=>W(r,o,e),saveToCache:s=>Y(r,o,s),updateCachedEvaluation:s=>Le(r,o,s),removeCachedEvaluation:s=>Me(r,o,s)}})}function W(r,o){return h(this,arguments,function*(t,e,i={}){let s=parseInt(yield e.getItem(t+".ts"));if(i!=null&&i.ttl&&!isNaN(s)&&s+i.ttl<Date.now())return yield _e(t,e),[];let f=yield e.getItem(t);if(f)try{return JSON.parse(f)}catch(b){}return[]})}function _e(t,e){return h(this,null,function*(){yield e.removeItem(t),yield e.removeItem(t+".ts")})}function Y(t,e,i){return h(this,null,function*(){yield e.setItem(t,JSON.stringify(i)),yield e.setItem(t+".ts",Date.now().toString())})}function Le(t,e,i){return h(this,null,function*(){let r=yield W(t,e),o=r.find(({flag:s})=>s===i.flag);o?Object.assign(o,i):r.push(i),yield Y(t,e,r)})}function Me(t,e,i){return h(this,null,function*(){let r=yield W(t,e),o=r.findIndex(({flag:s})=>s===i);o>-1&&(r.splice(o,1),yield Y(t,e,r))})}function He(t){return h(this,null,function*(){var i,r;let e=t;if(globalThis!=null&&globalThis.TextEncoder&&((r=(i=globalThis==null?void 0:globalThis.crypto)==null?void 0:i.subtle)!=null&&r.digest)){let s=new TextEncoder().encode(t),f=yield crypto.subtle.digest("SHA-256",s);e=Array.from(new Uint8Array(f)).map(y=>y.toString(16).padStart(2,"0")).join("")}else globalThis.btoa&&(e=btoa(t));return"HARNESS_FF_CACHE_"+e})}function Ge(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=Be:e=t.storage,{getItem(r){return h(this,null,function*(){let o=e.getItem(r);return o instanceof Promise?yield o:o})},setItem(r,o){return h(this,null,function*(){let s=e.setItem(r,o);s instanceof Promise&&(yield s)})},removeItem(r){return h(this,null,function*(){let o=e.removeItem(r);o instanceof Promise&&(yield o)})}}}var Be={getItem:()=>null,setItem:()=>{},removeItem:()=>{}};var ve="1.25.0",me=`Javascript ${ve} Client`,$e=500,Ke=globalThis.fetch,X=!!globalThis.Proxy,z=t=>{let{value:e}=t;try{switch(t.kind.toLowerCase()){case"int":case"number":e=Number(e);break;case"boolean":e=e.toString().toLowerCase()==="true";break;case"json":e=JSON.parse(e);break}}catch(i){I(i)}return e},Ue=(t,e,i)=>{let r=!1,o,s,f,b,y,d,w=!0,A={},k=J(n=>n),Q=0,Z=!1,H=()=>{w=!1},m=()=>{w=!0},C=[],u=de(),v=ue(i),R=(n,...a)=>{v.debug&&console.debug(`[FF-SDK] ${n}`,...a)},G=n=>{if(w){let a=Date.now();a-n.lastAccessed>$e&&(n.count++,n.lastAccessed=a)}},pe=()=>h(void 0,null,function*(){if(v.cache)try{let n=!0,a=yield he(e.identifier+t,typeof v.cache=="boolean"?{}:v.cache),c=yield a.loadFromCache();c!=null&&c.length&&q(()=>{R("loading from cache",c),ne(c,!1),u.emit("cache loaded",c)}),K("flags loaded",g=>h(void 0,null,function*(){yield a.saveToCache(g),n=!1})),K("changed",g=>h(void 0,null,function*(){n||(g.deleted?yield a.removeCachedEvaluation(g.flag):yield a.updateCachedEvaluation(g))}))}catch(n){I("Cache error: ",n),u.emit("cache error",n),u.emit("error",n)}}),Ee=(n,a)=>h(void 0,null,function*(){return(yield(yield Ke(`${a.baseUrl}/client/auth`,{method:"POST",headers:{"Content-Type":"application/json","Harness-SDK-Info":me},body:JSON.stringify({apiKey:n,target:U(O({},e),{identifier:String(e.identifier)})})})).json()).authToken}),B=0,$=()=>{if(C.length){R("Sending metrics...",{metrics:C,evaluations:S});let n={metricsData:C.map(a=>({timestamp:Date.now(),count:a.count,metricsType:"FFMETRICS",attributes:[{key:"featureIdentifier",value:a.featureIdentifier},{key:"featureName",value:a.featureIdentifier},{key:"variationIdentifier",value:a.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:ve}]}))};k(`${v.eventUrl}/metrics/${o}?cluster=${s}`,{method:"POST",headers:O({"Content-Type":"application/json"},A),body:JSON.stringify(n)}).then(()=>{C=[],B=0}).catch(a=>{B++&&(C=[],B=0),R(a),u.emit("metrics error",a)}).finally(()=>{d=window.setTimeout($,v.eventsSyncInterval)})}else d=window.setTimeout($,v.eventsSyncInterval)},S={},be=n=>{R("Sending event for",n.flag),X?u.emit("changed",new Proxy(n,{get(a,c){var g;if(w&&a.hasOwnProperty(c)&&c==="value"){let p=a.flag,l=n.value,E=C.find(P=>P.featureIdentifier===p&&P.featureValue===l);E?(G(E),E.variationIdentifier=((g=S[p])==null?void 0:g.identifier)||""):C.push({featureIdentifier:p,featureValue:String(l),variationIdentifier:S[p].identifier||"",count:1,lastAccessed:Date.now()}),R("Metrics event: Flag",c,"has been read with value via stream update",l)}return c==="value"?z(n):n[c]}})):u.emit("changed",{deleted:n.deleted,flag:n.flag,value:z(n)})},ee=function(){return X?new Proxy({},{get(n,a){var g,p,l;let c=n[a];if(w&&n.hasOwnProperty(a)){let E=n[a],P=C.find(ae=>ae.featureIdentifier===a&&E===ae.featureValue);P?(P.variationIdentifier=((g=S[a])==null?void 0:g.identifier)||"",G(P)):C.push({featureIdentifier:a,featureValue:E,variationIdentifier:((p=S[a])==null?void 0:p.identifier)||"",count:1,lastAccessed:Date.now()}),R("Metrics event: Flag:",a,"has been read with value:",E,"variationIdentifier:",(l=S[a])==null?void 0:l.identifier)}return c}}):{}},T=ee();pe().then(()=>Ee(t,v).then(n=>h(void 0,null,function*(){if(r)return;y=n;let a=ce(n);if(A={Authorization:`Bearer ${y}`,"Harness-AccountID":a.accountID,"Harness-EnvironmentID":a.environmentIdentifier,"Harness-SDK-Info":me},globalThis.btoa){let p=globalThis.btoa(JSON.stringify(e));p.length<262144&&(A["Harness-Target"]=p)}R("Authenticated",a),d=window.setTimeout($,v.eventsSyncInterval),o=a.environment,s=a.clusterIdentifier;let c=!!Object.keys(S).length;if((yield N()).type==="success"&&R("Fetch all flags ok",T),!r){if(v.streamEnabled?(R("Streaming mode enabled"),ye()):v.pollingEnabled?(R("Polling mode enabled"),Re()):R("Streaming and polling mode disabled"),!c){H();let p=O({},T);m(),u.emit("ready",p)}Z=!0}})).catch(n=>{I("Authentication error: ",n),u.emit("auth error",n),u.emit("error",n)}));let N=()=>h(void 0,null,function*(){try{let n=yield k(`${v.baseUrl}/client/env/${o}/target/${e.identifier}/evaluations?cluster=${s}`,{headers:A});if(n.ok){let a=yield n.json();return a.forEach(D),u.emit("flags loaded",a),{type:"success",data:a}}else return I("Features fetch operation error: ",n),u.emit("fetch flags error",n),u.emit("error",n),{type:"error",error:n}}catch(n){return I("Features fetch operation error: ",n),u.emit("fetch flags error",n),u.emit("error",n),{type:"error",error:n}}}),te=n=>h(void 0,null,function*(){try{let a=yield k(`${v.baseUrl}/client/env/${o}/target/${e.identifier}/evaluations/${n}?cluster=${s}`,{headers:A});if(a.ok){let c=yield a.json();D(c)}else I("Feature fetch operation error: ",a),u.emit("fetch flag error",a),u.emit("error",a)}catch(a){I("Feature fetch operation error: ",a),u.emit("fetch flag error",a),u.emit("error",a)}}),D=n=>{H();let a=z(n);a!==T[n.flag]&&(R("Flag variation has changed for ",n.identifier),T[n.flag]=a,S[n.flag]=U(O({},n),{value:a}),be(n)),m()};b=new x(N,v,u);let ye=()=>{let n=l=>{switch(l.event){case"create":c(l.evaluations)?l.evaluations.forEach(E=>{D(E)}):setTimeout(()=>te(l.identifier),1e3);break;case"patch":c(l.evaluations)?l.evaluations.forEach(E=>{D(E)}):te(l.identifier);break;case"delete":delete T[l.identifier],u.emit("changed",{flag:l.identifier,value:void 0,deleted:!0}),R("Evaluation deleted",{message:l,storage:T});break}},a=l=>!(!l||!l.flag||!l.identifier||!l.kind||!l.value),c=l=>!(!l||l.length==0||!l.every(E=>a(E))),g=l=>{l.event==="patch"&&(c(l.evaluations)?l.evaluations.forEach(E=>{D(E)}):N())},p=`${v.baseUrl}/stream?cluster=${s}`;f=new M(u,v,p,t,A,b,l=>{l.domain==="flag"?n(l):l.domain==="target-segment"&&g(l)}),f.start()},Re=()=>{b.start()},K=(n,a)=>u.on(n,a),Ie=(n,a)=>{n?u.off(n,a):ie()},Se=(n,a)=>{var l;if(!w||X||a===void 0)return;let c=a,g=n,p=C.find(E=>E.featureIdentifier===g&&E.featureValue===c);p?(G(p),p.variationIdentifier=((l=S[g])==null?void 0:l.identifier)||""):C.push({featureIdentifier:g,featureValue:c,count:1,variationIdentifier:S[g].identifier||"",lastAccessed:Date.now()})},ie=()=>{r=!0,v.streamEnabled&&(R("Closing event stream"),typeof(f==null?void 0:f.close)=="function"&&f.close(),u.all.clear()),v.pollingEnabled&&b.isPolling()&&(R("Closing Poller"),b.stop()),T=ee(),S={},clearTimeout(d)},ne=(n,a=!0)=>{n.length&&q(()=>{let c=!!Object.keys(S).length;if(n.forEach(D),!c){H();let g=O({},T);m(),u.emit("ready",g)}},a)};return{on:K,off:Ie,close:ie,setEvaluations:ne,registerAPIRequestMiddleware:n=>{k=J(n)},refreshEvaluations:()=>{Z&&!r&&Date.now()-Q>=6e4&&(N(),Q=Date.now())},variation:(n,a,c=!1)=>ge(n,a,T,Se,c)}};return xe(je);})(); | ||
var HarnessFFSDK=(()=>{var V=Object.defineProperty,we=Object.defineProperties,Ce=Object.getOwnPropertyDescriptor,Te=Object.getOwnPropertyDescriptors,Oe=Object.getOwnPropertyNames,re=Object.getOwnPropertySymbols;var se=Object.prototype.hasOwnProperty,Ae=Object.prototype.propertyIsEnumerable;var oe=(t,e,n)=>e in t?V(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,T=(t,e)=>{for(var n in e||(e={}))se.call(e,n)&&oe(t,n,e[n]);if(re)for(var n of re(e))Ae.call(e,n)&&oe(t,n,e[n]);return t},U=(t,e)=>we(t,Te(e));var De=(t,e)=>{for(var n in e)V(t,n,{get:e[n],enumerable:!0})},Pe=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Oe(e))!se.call(t,o)&&o!==n&&V(t,o,{get:()=>e[o],enumerable:!(r=Ce(e,o))||r.enumerable});return t};var Fe=t=>Pe(V({},"__esModule",{value:!0}),t);var h=(t,e,n)=>new Promise((r,o)=>{var s=R=>{try{b(n.next(R))}catch(u){o(u)}},f=R=>{try{b(n.throw(R))}catch(u){o(u)}},b=R=>R.done?r(R.value):Promise.resolve(R.value).then(s,f);b((n=n.apply(t,e)).next())});var Ue={};De(Ue,{Event:()=>F,initialize:()=>Ke});function j(t){this.message=t}j.prototype=new Error,j.prototype.name="InvalidCharacterError";var le=typeof window!="undefined"&&window.atob&&window.atob.bind(window)||function(t){var e=String(t).replace(/=+$/,"");if(e.length%4==1)throw new j("'atob' failed: The string to be decoded is not correctly encoded.");for(var n,r,o=0,s=0,f="";r=e.charAt(s++);~r&&(n=o%4?64*n+r:r,o++%4)?f+=String.fromCharCode(255&n>>(-2*o&6)):0)r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(r);return f};function xe(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(n){return decodeURIComponent(le(n).replace(/(.)/g,function(r,o){var s=o.charCodeAt(0).toString(16).toUpperCase();return s.length<2&&(s="0"+s),"%"+s}))}(e)}catch(n){return le(e)}}function _(t){this.message=t}function ke(t,e){if(typeof t!="string")throw new _("Invalid token specified");var n=(e=e||{}).header===!0?0:1;try{return JSON.parse(xe(t.split(".")[n]))}catch(r){throw new _("Invalid token specified: "+r.message)}}_.prototype=new Error,_.prototype.name="InvalidTokenError";var ce=ke;function ue(t){return{all:t=t||new Map,on:function(e,n){var r=t.get(e);r&&r.push(n)||t.set(e,[n])},off:function(e,n){var r=t.get(e);r&&r.splice(r.indexOf(n)>>>0,1)},emit:function(e,n){(t.get(e)||[]).slice().map(function(r){r(n)}),(t.get("*")||[]).slice().map(function(r){r(e,n)})}}}var F=(m=>(m.READY="ready",m.CONNECTED="connected",m.DISCONNECTED="disconnected",m.STOPPED="stopped",m.POLLING="polling",m.POLLING_STOPPED="polling stopped",m.FLAGS_LOADED="flags loaded",m.CACHE_LOADED="cache loaded",m.CHANGED="changed",m.ERROR="error",m.ERROR_CACHE="cache error",m.ERROR_METRICS="metrics error",m.ERROR_AUTH="auth error",m.ERROR_FETCH_FLAGS="fetch flags error",m.ERROR_FETCH_FLAG="fetch flag error",m.ERROR_STREAM="stream error",m))(F||{});var Ne={debug:!1,baseUrl:"https://config.ff.harness.io/api/1.0",eventUrl:"https://events.ff.harness.io/api/1.0",eventsSyncInterval:6e4,pollingInterval:6e4,streamEnabled:!0,cache:!1},de=t=>{let e=T(T({},Ne),t);return e.pollingEnabled===void 0&&(e.pollingEnabled=e.streamEnabled),e.eventsSyncInterval<6e4&&(e.eventsSyncInterval=6e4),e.pollingInterval<6e4&&(e.pollingInterval=6e4),e},I=(t,...e)=>console.error(`[FF-SDK] ${t}`,...e),q=(t,e=!0)=>{e?setTimeout(t,0):t()},L=(t,e)=>Math.round(Math.random()*(e-t)+t);function J(t){return function(...n){let[r,o]=t(n);return fetch(r,o)}}var fe=3e4,M=class{constructor(e,n,r,o,s,f,b){this.closed=!1;this.connectionOpened=!1;this.disconnectEventEmitted=!1;this.eventBus=e,this.configurations=n,this.url=r,this.apiKey=o,this.standardHeaders=s,this.eventCallback=b,this.fallbackPoller=f}start(){let e=u=>{u.toString().split(/\r?\n/).forEach(n)},n=u=>{if(u.startsWith("data:")){let w=JSON.parse(u.substring(5));this.logDebug("Received event from stream: ",w),this.eventCallback(w)}},r=()=>{this.logDebug("Stream connected"),this.eventBus.emit("connected")},o=()=>{clearInterval(this.readTimeoutCheckerId);let u=L(1e3,1e4);this.logDebug("Stream disconnected, will reconnect in "+u+"ms"),this.disconnectEventEmitted||(this.eventBus.emit("disconnected"),this.disconnectEventEmitted=!0),setTimeout(()=>this.start(),u)},s=u=>{u&&I("Stream has issue",u),this.fallBackToPolling(),this.eventBus.emit("stream error",u),this.eventBus.emit("error",u),o()},f=T({"Cache-Control":"no-cache",Accept:"text/event-stream","API-Key":this.apiKey},this.standardHeaders);this.logDebug("SSE HTTP start request",this.url),this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url);for(let[u,w]of Object.entries(f))this.xhr.setRequestHeader(u,w);this.xhr.timeout=24*60*60*1e3,this.xhr.onerror=()=>{this.connectionOpened=!1,s("XMLHttpRequest error on SSE stream")},this.xhr.onabort=()=>{this.connectionOpened=!1,this.logDebug("SSE aborted"),this.closed||s(null)},this.xhr.ontimeout=()=>{this.connectionOpened=!1,s("SSE timeout")},this.xhr.onload=()=>{if(this.xhr.status>=400&&this.xhr.status<=599){s(`HTTP code ${this.xhr.status}`);return}this.connectionOpened||(r(),this.connectionOpened=!0,this.disconnectEventEmitted=!1)};let b=0,R=Date.now();this.xhr.onprogress=()=>{this.connectionOpened||(r(),this.connectionOpened=!0,this.disconnectEventEmitted=!1),this.stopFallBackPolling(),R=Date.now();let u=this.xhr.responseText.slice(b);b+=u.length,this.logDebug("SSE GOT: "+u),e(u)},this.readTimeoutCheckerId=setInterval(()=>{R<Date.now()-fe&&(I("SSE read timeout"),this.xhr.abort())},fe),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.logDebug("Falling back to polling mode while stream recovers"),this.fallbackPoller.start())}stopFallBackPolling(){this.fallbackPoller.isPolling()&&(this.logDebug("Stopping fallback polling mode"),this.fallbackPoller.stop())}logDebug(e,...n){this.configurations.debug&&console.debug(`[FF-SDK] Streaming: ${e}`,...n)}};function ge(t,e,n,r,o){let s=t in n,f=s?n[t]:e;return s&&r(t,f),o?{value:f,isDefaultValue:!s}:f}var x=class{constructor(e,n,r){this.fetchFlagsFn=e;this.configurations=n;this.eventBus=r;this.maxAttempts=5}start(){if(this.isPolling()){this.logDebug("Already polling.");return}this.isRunning=!0,this.eventBus.emit("polling"),this.logDebug(`Starting poller, first poll will be in ${this.configurations.pollingInterval}ms`),this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)}poll(){this.attemptFetch().finally(()=>{this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)})}attemptFetch(){return h(this,null,function*(){for(let e=1;e<=this.maxAttempts;e++){let n=yield this.fetchFlagsFn();if(n.type==="success"){this.logDebug(`Successfully polled for flag updates, next poll in ${this.configurations.pollingInterval}ms. `);return}if(I("Error when polling for flag updates",n.error),e>=this.maxAttempts){this.logDebug(`Maximum attempts reached for polling for flags. Next poll in ${this.configurations.pollingInterval}ms.`);return}this.logDebug(`Polling for flags attempt #${e} failed. Remaining attempts: ${this.maxAttempts-e}`,n.error);let r=L(1e3,1e4);yield new Promise(o=>setTimeout(o,r))}})}stop(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=void 0,this.isRunning=!1,this.eventBus.emit("polling stopped"),this.logDebug("Polling stopped"))}isPolling(){return this.isRunning}logDebug(e,...n){this.configurations.debug&&console.debug(`[FF-SDK] Poller: ${e}`,...n)}};function he(n){return h(this,arguments,function*(t,e={}){let r=yield Me(t),o=He(e);return{loadFromCache:()=>W(r,o,e),saveToCache:s=>Y(r,o,s),updateCachedEvaluation:s=>_e(r,o,s),removeCachedEvaluation:s=>Le(r,o,s)}})}function W(r,o){return h(this,arguments,function*(t,e,n={}){let s=parseInt(yield e.getItem(t+".ts"));if(n!=null&&n.ttl&&!isNaN(s)&&s+n.ttl<Date.now())return yield Ve(t,e),[];let f=yield e.getItem(t);if(f)try{return JSON.parse(f)}catch(b){}return[]})}function Ve(t,e){return h(this,null,function*(){yield e.removeItem(t),yield e.removeItem(t+".ts")})}function Y(t,e,n){return h(this,null,function*(){yield e.setItem(t,JSON.stringify(n)),yield e.setItem(t+".ts",Date.now().toString())})}function _e(t,e,n){return h(this,null,function*(){let r=yield W(t,e),o=r.find(({flag:s})=>s===n.flag);o?Object.assign(o,n):r.push(n),yield Y(t,e,r)})}function Le(t,e,n){return h(this,null,function*(){let r=yield W(t,e),o=r.findIndex(({flag:s})=>s===n);o>-1&&(r.splice(o,1),yield Y(t,e,r))})}function Me(t){return h(this,null,function*(){var n,r;let e=t;if(globalThis!=null&&globalThis.TextEncoder&&((r=(n=globalThis==null?void 0:globalThis.crypto)==null?void 0:n.subtle)!=null&&r.digest)){let s=new TextEncoder().encode(t),f=yield crypto.subtle.digest("SHA-256",s);e=Array.from(new Uint8Array(f)).map(R=>R.toString(16).padStart(2,"0")).join("")}else globalThis.btoa&&(e=btoa(t));return"HARNESS_FF_CACHE_"+e})}function He(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=Ge:e=t.storage,{getItem(r){return h(this,null,function*(){let o=e.getItem(r);return o instanceof Promise?yield o:o})},setItem(r,o){return h(this,null,function*(){let s=e.setItem(r,o);s instanceof Promise&&(yield s)})},removeItem(r){return h(this,null,function*(){let o=e.removeItem(r);o instanceof Promise&&(yield o)})}}}var Ge={getItem:()=>null,setItem:()=>{},removeItem:()=>{}};var ve="1.25.0",me=`Javascript ${ve} Client`,Be=500,$e=globalThis.fetch,z=!!globalThis.Proxy,X=t=>{let{value:e}=t;try{switch(t.kind.toLowerCase()){case"int":case"number":e=Number(e);break;case"boolean":e=e.toString().toLowerCase()==="true";break;case"json":e=JSON.parse(e);break}}catch(n){I(n)}return e},Ke=(t,e,n)=>{let r=!1,o,s,f,b,R,u,w=!0,A={},k=J(i=>i),Q=0,Z=!1,H=()=>{w=!1},m=()=>{w=!0},C=[],d=ue(),v=de(n),y=(i,...a)=>{v.debug&&console.debug(`[FF-SDK] ${i}`,...a)},G=i=>{if(w){let a=Date.now();a-i.lastAccessed>Be&&(i.count++,i.lastAccessed=a)}},pe=()=>h(void 0,null,function*(){if(v.cache){y("initializing cache");try{let i=!0,a=yield he(e.identifier+t,typeof v.cache=="boolean"?{}:v.cache),c=yield a.loadFromCache();c!=null&&c.length&&q(()=>{y("loading from cache",c),ne(c,!1),d.emit("cache loaded",c)}),K("flags loaded",g=>h(void 0,null,function*(){yield a.saveToCache(g),i=!1})),K("changed",g=>h(void 0,null,function*(){i||(g.deleted?yield a.removeCachedEvaluation(g.flag):yield a.updateCachedEvaluation(g))}))}catch(i){I("Cache error: ",i),d.emit("cache error",i),d.emit("error",i)}}}),Ee=(i,a)=>h(void 0,null,function*(){return(yield(yield $e(`${a.baseUrl}/client/auth`,{method:"POST",headers:{"Content-Type":"application/json","Harness-SDK-Info":me},body:JSON.stringify({apiKey:i,target:U(T({},e),{identifier:String(e.identifier)})})})).json()).authToken}),B=0,$=()=>{if(C.length){y("Sending metrics...",{metrics:C,evaluations:S});let i={metricsData:C.map(a=>({timestamp:Date.now(),count:a.count,metricsType:"FFMETRICS",attributes:[{key:"featureIdentifier",value:a.featureIdentifier},{key:"featureName",value:a.featureIdentifier},{key:"variationIdentifier",value:a.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:ve}]}))};k(`${v.eventUrl}/metrics/${o}?cluster=${s}`,{method:"POST",headers:T({"Content-Type":"application/json"},A),body:JSON.stringify(i)}).then(()=>{C=[],B=0}).catch(a=>{B++&&(C=[],B=0),y(a),d.emit("metrics error",a)}).finally(()=>{u=window.setTimeout($,v.eventsSyncInterval)})}else u=window.setTimeout($,v.eventsSyncInterval)},S={},be=i=>{y("Sending event for",i.flag),z?d.emit("changed",new Proxy(i,{get(a,c){var g;if(w&&a.hasOwnProperty(c)&&c==="value"){let p=a.flag,l=i.value,E=C.find(P=>P.featureIdentifier===p&&P.featureValue===l);E?(G(E),E.variationIdentifier=((g=S[p])==null?void 0:g.identifier)||""):C.push({featureIdentifier:p,featureValue:String(l),variationIdentifier:S[p].identifier||"",count:1,lastAccessed:Date.now()}),y("Metrics event: Flag",c,"has been read with value via stream update",l)}return c==="value"?X(i):i[c]}})):d.emit("changed",{deleted:i.deleted,flag:i.flag,value:X(i)})},ee=function(){return z?new Proxy({},{get(i,a){var g,p,l;let c=i[a];if(w&&i.hasOwnProperty(a)){let E=i[a],P=C.find(ae=>ae.featureIdentifier===a&&E===ae.featureValue);P?(P.variationIdentifier=((g=S[a])==null?void 0:g.identifier)||"",G(P)):C.push({featureIdentifier:a,featureValue:E,variationIdentifier:((p=S[a])==null?void 0:p.identifier)||"",count:1,lastAccessed:Date.now()}),y("Metrics event: Flag:",a,"has been read with value:",E,"variationIdentifier:",(l=S[a])==null?void 0:l.identifier)}return c}}):{}},O=ee();pe().then(()=>Ee(t,v).then(i=>h(void 0,null,function*(){if(r)return;R=i;let a=ce(i);if(A={Authorization:`Bearer ${R}`,"Harness-AccountID":a.accountID,"Harness-EnvironmentID":a.environmentIdentifier,"Harness-SDK-Info":me},globalThis.btoa){let p=globalThis.btoa(JSON.stringify(e));p.length<262144&&(A["Harness-Target"]=p)}y("Authenticated",a),u=window.setTimeout($,v.eventsSyncInterval),o=a.environment,s=a.clusterIdentifier;let c=!!Object.keys(S).length;if((yield N()).type==="success"&&y("Fetch all flags ok",O),!r){if(v.streamEnabled?(y("Streaming mode enabled"),ye()):v.pollingEnabled?(y("Polling mode enabled"),Re()):y("Streaming and polling mode disabled"),!c){H();let p=T({},O);m(),d.emit("ready",p)}Z=!0}})).catch(i=>{I("Authentication error: ",i),d.emit("auth error",i),d.emit("error",i)}));let N=()=>h(void 0,null,function*(){try{let i=yield k(`${v.baseUrl}/client/env/${o}/target/${e.identifier}/evaluations?cluster=${s}`,{headers:A});if(i.ok){let a=yield i.json();return a.forEach(D),d.emit("flags loaded",a),{type:"success",data:a}}else return I("Features fetch operation error: ",i),d.emit("fetch flags error",i),d.emit("error",i),{type:"error",error:i}}catch(i){return I("Features fetch operation error: ",i),d.emit("fetch flags error",i),d.emit("error",i),{type:"error",error:i}}}),te=i=>h(void 0,null,function*(){try{let a=yield k(`${v.baseUrl}/client/env/${o}/target/${e.identifier}/evaluations/${i}?cluster=${s}`,{headers:A});if(a.ok){let c=yield a.json();D(c)}else I("Feature fetch operation error: ",a),d.emit("fetch flag error",a),d.emit("error",a)}catch(a){I("Feature fetch operation error: ",a),d.emit("fetch flag error",a),d.emit("error",a)}}),D=i=>{H();let a=X(i);a!==O[i.flag]&&(y("Flag variation has changed for ",i.identifier),O[i.flag]=a,S[i.flag]=U(T({},i),{value:a}),be(i)),m()};b=new x(N,v,d);let ye=()=>{let i=l=>{switch(l.event){case"create":c(l.evaluations)?l.evaluations.forEach(E=>{D(E)}):setTimeout(()=>te(l.identifier),1e3);break;case"patch":c(l.evaluations)?l.evaluations.forEach(E=>{D(E)}):te(l.identifier);break;case"delete":delete O[l.identifier],d.emit("changed",{flag:l.identifier,value:void 0,deleted:!0}),y("Evaluation deleted",{message:l,storage:O});break}},a=l=>!(!l||!l.flag||!l.identifier||!l.kind||!l.value),c=l=>!(!l||l.length==0||!l.every(E=>a(E))),g=l=>{l.event==="patch"&&(c(l.evaluations)?l.evaluations.forEach(E=>{D(E)}):N())},p=`${v.baseUrl}/stream?cluster=${s}`;f=new M(d,v,p,t,A,b,l=>{l.domain==="flag"?i(l):l.domain==="target-segment"&&g(l)}),f.start()},Re=()=>{b.start()},K=(i,a)=>d.on(i,a),Ie=(i,a)=>{i?d.off(i,a):ie()},Se=(i,a)=>{var l;if(!w||z||a===void 0)return;let c=a,g=i,p=C.find(E=>E.featureIdentifier===g&&E.featureValue===c);p?(G(p),p.variationIdentifier=((l=S[g])==null?void 0:l.identifier)||""):C.push({featureIdentifier:g,featureValue:c,count:1,variationIdentifier:S[g].identifier||"",lastAccessed:Date.now()})},ie=()=>{r=!0,v.streamEnabled&&(y("Closing event stream"),typeof(f==null?void 0:f.close)=="function"&&f.close(),d.all.clear()),v.pollingEnabled&&b.isPolling()&&(y("Closing Poller"),b.stop()),O=ee(),S={},clearTimeout(u)},ne=(i,a=!0)=>{i.length&&q(()=>{let c=!!Object.keys(S).length;if(i.forEach(D),!c){H();let g=T({},O);m(),d.emit("ready",g)}},a)};return{on:K,off:Ie,close:ie,setEvaluations:ne,registerAPIRequestMiddleware:i=>{k=J(i)},refreshEvaluations:()=>{Z&&!r&&Date.now()-Q>=6e4&&(N(),Q=Date.now())},variation:(i,a,c=!1)=>ge(i,a,O,Se,c)}};return Fe(Ue);})(); |
@@ -1,1 +0,1 @@ | ||
var Ie=Object.defineProperty,Se=Object.defineProperties;var we=Object.getOwnPropertyDescriptors;var ae=Object.getOwnPropertySymbols;var Ce=Object.prototype.hasOwnProperty,Oe=Object.prototype.propertyIsEnumerable;var re=(t,e,n)=>e in t?Ie(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,O=(t,e)=>{for(var n in e||(e={}))Ce.call(e,n)&&re(t,n,e[n]);if(ae)for(var n of ae(e))Oe.call(e,n)&&re(t,n,e[n]);return t},K=(t,e)=>Se(t,we(e));var Te=(t=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(t,{get:(e,n)=>(typeof require!="undefined"?require:e)[n]}):t)(function(t){if(typeof require!="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var h=(t,e,n)=>new Promise((r,o)=>{var s=y=>{try{b(n.next(y))}catch(d){o(d)}},f=y=>{try{b(n.throw(y))}catch(d){o(d)}},b=y=>y.done?r(y.value):Promise.resolve(y.value).then(s,f);b((n=n.apply(t,e)).next())});function U(t){this.message=t}U.prototype=new Error,U.prototype.name="InvalidCharacterError";var oe=typeof window!="undefined"&&window.atob&&window.atob.bind(window)||function(t){var e=String(t).replace(/=+$/,"");if(e.length%4==1)throw new U("'atob' failed: The string to be decoded is not correctly encoded.");for(var n,r,o=0,s=0,f="";r=e.charAt(s++);~r&&(n=o%4?64*n+r:r,o++%4)?f+=String.fromCharCode(255&n>>(-2*o&6)):0)r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(r);return f};function Ae(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(n){return decodeURIComponent(oe(n).replace(/(.)/g,function(r,o){var s=o.charCodeAt(0).toString(16).toUpperCase();return s.length<2&&(s="0"+s),"%"+s}))}(e)}catch(n){return oe(e)}}function N(t){this.message=t}function De(t,e){if(typeof t!="string")throw new N("Invalid token specified");var n=(e=e||{}).header===!0?0:1;try{return JSON.parse(Ae(t.split(".")[n]))}catch(r){throw new N("Invalid token specified: "+r.message)}}N.prototype=new Error,N.prototype.name="InvalidTokenError";var se=De;function le(t){return{all:t=t||new Map,on:function(e,n){var r=t.get(e);r&&r.push(n)||t.set(e,[n])},off:function(e,n){var r=t.get(e);r&&r.splice(r.indexOf(n)>>>0,1)},emit:function(e,n){(t.get(e)||[]).slice().map(function(r){r(n)}),(t.get("*")||[]).slice().map(function(r){r(e,n)})}}}var V=(m=>(m.READY="ready",m.CONNECTED="connected",m.DISCONNECTED="disconnected",m.STOPPED="stopped",m.POLLING="polling",m.POLLING_STOPPED="polling stopped",m.FLAGS_LOADED="flags loaded",m.CACHE_LOADED="cache loaded",m.CHANGED="changed",m.ERROR="error",m.ERROR_CACHE="cache error",m.ERROR_METRICS="metrics error",m.ERROR_AUTH="auth error",m.ERROR_FETCH_FLAGS="fetch flags error",m.ERROR_FETCH_FLAG="fetch flag error",m.ERROR_STREAM="stream error",m))(V||{});var Pe={debug:!1,baseUrl:"https://config.ff.harness.io/api/1.0",eventUrl:"https://events.ff.harness.io/api/1.0",eventsSyncInterval:6e4,pollingInterval:6e4,streamEnabled:!0,cache:!1},ce=t=>{let e=O(O({},Pe),t);if(e.pollingEnabled===void 0&&(e.pollingEnabled=e.streamEnabled),e.eventsSyncInterval<6e4&&(e.eventsSyncInterval=6e4),e.pollingInterval<6e4&&(e.pollingInterval=6e4),e.streamEnabled)try{let{Platform:n}=Te("react-native");n.OS==="android"&&(console.info("SDKCODE:1007 Android React Native detected - streaming will be disabled and polling enabled"),e.pollingEnabled=!0,e.streamEnabled=!1)}catch(n){}return e},I=(t,...e)=>console.error(`[FF-SDK] ${t}`,...e),j=(t,e=!0)=>{e?setTimeout(t,0):t()},_=(t,e)=>Math.round(Math.random()*(e-t)+t);function q(t){return function(...n){let[r,o]=t(n);return fetch(r,o)}}var de=3e4,L=class{constructor(e,n,r,o,s,f,b){this.closed=!1;this.connectionOpened=!1;this.disconnectEventEmitted=!1;this.eventBus=e,this.configurations=n,this.url=r,this.apiKey=o,this.standardHeaders=s,this.eventCallback=b,this.fallbackPoller=f}start(){let e=d=>{d.toString().split(/\r?\n/).forEach(n)},n=d=>{if(d.startsWith("data:")){let w=JSON.parse(d.substring(5));this.logDebug("Received event from stream: ",w),this.eventCallback(w)}},r=()=>{this.logDebug("Stream connected"),this.eventBus.emit("connected")},o=()=>{clearInterval(this.readTimeoutCheckerId);let d=_(1e3,1e4);this.logDebug("Stream disconnected, will reconnect in "+d+"ms"),this.disconnectEventEmitted||(this.eventBus.emit("disconnected"),this.disconnectEventEmitted=!0),setTimeout(()=>this.start(),d)},s=d=>{d&&I("Stream has issue",d),this.fallBackToPolling(),this.eventBus.emit("stream error",d),this.eventBus.emit("error",d),o()},f=O({"Cache-Control":"no-cache",Accept:"text/event-stream","API-Key":this.apiKey},this.standardHeaders);this.logDebug("SSE HTTP start request",this.url),this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url);for(let[d,w]of Object.entries(f))this.xhr.setRequestHeader(d,w);this.xhr.timeout=24*60*60*1e3,this.xhr.onerror=()=>{this.connectionOpened=!1,s("XMLHttpRequest error on SSE stream")},this.xhr.onabort=()=>{this.connectionOpened=!1,this.logDebug("SSE aborted"),this.closed||s(null)},this.xhr.ontimeout=()=>{this.connectionOpened=!1,s("SSE timeout")},this.xhr.onload=()=>{if(this.xhr.status>=400&&this.xhr.status<=599){s(`HTTP code ${this.xhr.status}`);return}this.connectionOpened||(r(),this.connectionOpened=!0,this.disconnectEventEmitted=!1)};let b=0,y=Date.now();this.xhr.onprogress=()=>{this.connectionOpened||(r(),this.connectionOpened=!0,this.disconnectEventEmitted=!1),this.stopFallBackPolling(),y=Date.now();let d=this.xhr.responseText.slice(b);b+=d.length,this.logDebug("SSE GOT: "+d),e(d)},this.readTimeoutCheckerId=setInterval(()=>{y<Date.now()-de&&(I("SSE read timeout"),this.xhr.abort())},de),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.logDebug("Falling back to polling mode while stream recovers"),this.fallbackPoller.start())}stopFallBackPolling(){this.fallbackPoller.isPolling()&&(this.logDebug("Stopping fallback polling mode"),this.fallbackPoller.stop())}logDebug(e,...n){this.configurations.debug&&console.debug(`[FF-SDK] Streaming: ${e}`,...n)}};function ue(t,e,n,r,o){let s=t in n,f=s?n[t]:e;return s&&r(t,f),o?{value:f,isDefaultValue:!s}:f}var F=class{constructor(e,n,r){this.fetchFlagsFn=e;this.configurations=n;this.eventBus=r;this.maxAttempts=5}start(){if(this.isPolling()){this.logDebug("Already polling.");return}this.isRunning=!0,this.eventBus.emit("polling"),this.logDebug(`Starting poller, first poll will be in ${this.configurations.pollingInterval}ms`),this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)}poll(){this.attemptFetch().finally(()=>{this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)})}attemptFetch(){return h(this,null,function*(){for(let e=1;e<=this.maxAttempts;e++){let n=yield this.fetchFlagsFn();if(n.type==="success"){this.logDebug(`Successfully polled for flag updates, next poll in ${this.configurations.pollingInterval}ms. `);return}if(I("Error when polling for flag updates",n.error),e>=this.maxAttempts){this.logDebug(`Maximum attempts reached for polling for flags. Next poll in ${this.configurations.pollingInterval}ms.`);return}this.logDebug(`Polling for flags attempt #${e} failed. Remaining attempts: ${this.maxAttempts-e}`,n.error);let r=_(1e3,1e4);yield new Promise(o=>setTimeout(o,r))}})}stop(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=void 0,this.isRunning=!1,this.eventBus.emit("polling stopped"),this.logDebug("Polling stopped"))}isPolling(){return this.isRunning}logDebug(e,...n){this.configurations.debug&&console.debug(`[FF-SDK] Poller: ${e}`,...n)}};function fe(n){return h(this,arguments,function*(t,e={}){let r=yield Ne(t),o=Ve(e);return{loadFromCache:()=>J(r,o,e),saveToCache:s=>W(r,o,s),updateCachedEvaluation:s=>xe(r,o,s),removeCachedEvaluation:s=>ke(r,o,s)}})}function J(r,o){return h(this,arguments,function*(t,e,n={}){let s=parseInt(yield e.getItem(t+".ts"));if(n!=null&&n.ttl&&!isNaN(s)&&s+n.ttl<Date.now())return yield Fe(t,e),[];let f=yield e.getItem(t);if(f)try{return JSON.parse(f)}catch(b){}return[]})}function Fe(t,e){return h(this,null,function*(){yield e.removeItem(t),yield e.removeItem(t+".ts")})}function W(t,e,n){return h(this,null,function*(){yield e.setItem(t,JSON.stringify(n)),yield e.setItem(t+".ts",Date.now().toString())})}function xe(t,e,n){return h(this,null,function*(){let r=yield J(t,e),o=r.find(({flag:s})=>s===n.flag);o?Object.assign(o,n):r.push(n),yield W(t,e,r)})}function ke(t,e,n){return h(this,null,function*(){let r=yield J(t,e),o=r.findIndex(({flag:s})=>s===n);o>-1&&(r.splice(o,1),yield W(t,e,r))})}function Ne(t){return h(this,null,function*(){var n,r;let e=t;if(globalThis!=null&&globalThis.TextEncoder&&((r=(n=globalThis==null?void 0:globalThis.crypto)==null?void 0:n.subtle)!=null&&r.digest)){let s=new TextEncoder().encode(t),f=yield crypto.subtle.digest("SHA-256",s);e=Array.from(new Uint8Array(f)).map(y=>y.toString(16).padStart(2,"0")).join("")}else globalThis.btoa&&(e=btoa(t));return"HARNESS_FF_CACHE_"+e})}function Ve(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=_e:e=t.storage,{getItem(r){return h(this,null,function*(){let o=e.getItem(r);return o instanceof Promise?yield o:o})},setItem(r,o){return h(this,null,function*(){let s=e.setItem(r,o);s instanceof Promise&&(yield s)})},removeItem(r){return h(this,null,function*(){let o=e.removeItem(r);o instanceof Promise&&(yield o)})}}}var _e={getItem:()=>null,setItem:()=>{},removeItem:()=>{}};var he="1.25.0",ge=`Javascript ${he} Client`,Le=500,Me=globalThis.fetch,Y=!!globalThis.Proxy,X=t=>{let{value:e}=t;try{switch(t.kind.toLowerCase()){case"int":case"number":e=Number(e);break;case"boolean":e=e.toString().toLowerCase()==="true";break;case"json":e=JSON.parse(e);break}}catch(n){I(n)}return e},bt=(t,e,n)=>{let r=!1,o,s,f,b,y,d,w=!0,A={},x=q(i=>i),z=0,Q=!1,M=()=>{w=!1},m=()=>{w=!0},C=[],u=le(),v=ce(n),R=(i,...a)=>{v.debug&&console.debug(`[FF-SDK] ${i}`,...a)},H=i=>{if(w){let a=Date.now();a-i.lastAccessed>Le&&(i.count++,i.lastAccessed=a)}},me=()=>h(void 0,null,function*(){if(v.cache)try{let i=!0,a=yield fe(e.identifier+t,typeof v.cache=="boolean"?{}:v.cache),c=yield a.loadFromCache();c!=null&&c.length&&j(()=>{R("loading from cache",c),ie(c,!1),u.emit("cache loaded",c)}),$("flags loaded",g=>h(void 0,null,function*(){yield a.saveToCache(g),i=!1})),$("changed",g=>h(void 0,null,function*(){i||(g.deleted?yield a.removeCachedEvaluation(g.flag):yield a.updateCachedEvaluation(g))}))}catch(i){I("Cache error: ",i),u.emit("cache error",i),u.emit("error",i)}}),ve=(i,a)=>h(void 0,null,function*(){return(yield(yield Me(`${a.baseUrl}/client/auth`,{method:"POST",headers:{"Content-Type":"application/json","Harness-SDK-Info":ge},body:JSON.stringify({apiKey:i,target:K(O({},e),{identifier:String(e.identifier)})})})).json()).authToken}),G=0,B=()=>{if(C.length){R("Sending metrics...",{metrics:C,evaluations:S});let i={metricsData:C.map(a=>({timestamp:Date.now(),count:a.count,metricsType:"FFMETRICS",attributes:[{key:"featureIdentifier",value:a.featureIdentifier},{key:"featureName",value:a.featureIdentifier},{key:"variationIdentifier",value:a.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:he}]}))};x(`${v.eventUrl}/metrics/${o}?cluster=${s}`,{method:"POST",headers:O({"Content-Type":"application/json"},A),body:JSON.stringify(i)}).then(()=>{C=[],G=0}).catch(a=>{G++&&(C=[],G=0),R(a),u.emit("metrics error",a)}).finally(()=>{d=window.setTimeout(B,v.eventsSyncInterval)})}else d=window.setTimeout(B,v.eventsSyncInterval)},S={},pe=i=>{R("Sending event for",i.flag),Y?u.emit("changed",new Proxy(i,{get(a,c){var g;if(w&&a.hasOwnProperty(c)&&c==="value"){let p=a.flag,l=i.value,E=C.find(P=>P.featureIdentifier===p&&P.featureValue===l);E?(H(E),E.variationIdentifier=((g=S[p])==null?void 0:g.identifier)||""):C.push({featureIdentifier:p,featureValue:String(l),variationIdentifier:S[p].identifier||"",count:1,lastAccessed:Date.now()}),R("Metrics event: Flag",c,"has been read with value via stream update",l)}return c==="value"?X(i):i[c]}})):u.emit("changed",{deleted:i.deleted,flag:i.flag,value:X(i)})},Z=function(){return Y?new Proxy({},{get(i,a){var g,p,l;let c=i[a];if(w&&i.hasOwnProperty(a)){let E=i[a],P=C.find(ne=>ne.featureIdentifier===a&&E===ne.featureValue);P?(P.variationIdentifier=((g=S[a])==null?void 0:g.identifier)||"",H(P)):C.push({featureIdentifier:a,featureValue:E,variationIdentifier:((p=S[a])==null?void 0:p.identifier)||"",count:1,lastAccessed:Date.now()}),R("Metrics event: Flag:",a,"has been read with value:",E,"variationIdentifier:",(l=S[a])==null?void 0:l.identifier)}return c}}):{}},T=Z();me().then(()=>ve(t,v).then(i=>h(void 0,null,function*(){if(r)return;y=i;let a=se(i);if(A={Authorization:`Bearer ${y}`,"Harness-AccountID":a.accountID,"Harness-EnvironmentID":a.environmentIdentifier,"Harness-SDK-Info":ge},globalThis.btoa){let p=globalThis.btoa(JSON.stringify(e));p.length<262144&&(A["Harness-Target"]=p)}R("Authenticated",a),d=window.setTimeout(B,v.eventsSyncInterval),o=a.environment,s=a.clusterIdentifier;let c=!!Object.keys(S).length;if((yield k()).type==="success"&&R("Fetch all flags ok",T),!r){if(v.streamEnabled?(R("Streaming mode enabled"),Ee()):v.pollingEnabled?(R("Polling mode enabled"),be()):R("Streaming and polling mode disabled"),!c){M();let p=O({},T);m(),u.emit("ready",p)}Q=!0}})).catch(i=>{I("Authentication error: ",i),u.emit("auth error",i),u.emit("error",i)}));let k=()=>h(void 0,null,function*(){try{let i=yield x(`${v.baseUrl}/client/env/${o}/target/${e.identifier}/evaluations?cluster=${s}`,{headers:A});if(i.ok){let a=yield i.json();return a.forEach(D),u.emit("flags loaded",a),{type:"success",data:a}}else return I("Features fetch operation error: ",i),u.emit("fetch flags error",i),u.emit("error",i),{type:"error",error:i}}catch(i){return I("Features fetch operation error: ",i),u.emit("fetch flags error",i),u.emit("error",i),{type:"error",error:i}}}),ee=i=>h(void 0,null,function*(){try{let a=yield x(`${v.baseUrl}/client/env/${o}/target/${e.identifier}/evaluations/${i}?cluster=${s}`,{headers:A});if(a.ok){let c=yield a.json();D(c)}else I("Feature fetch operation error: ",a),u.emit("fetch flag error",a),u.emit("error",a)}catch(a){I("Feature fetch operation error: ",a),u.emit("fetch flag error",a),u.emit("error",a)}}),D=i=>{M();let a=X(i);a!==T[i.flag]&&(R("Flag variation has changed for ",i.identifier),T[i.flag]=a,S[i.flag]=K(O({},i),{value:a}),pe(i)),m()};b=new F(k,v,u);let Ee=()=>{let i=l=>{switch(l.event){case"create":c(l.evaluations)?l.evaluations.forEach(E=>{D(E)}):setTimeout(()=>ee(l.identifier),1e3);break;case"patch":c(l.evaluations)?l.evaluations.forEach(E=>{D(E)}):ee(l.identifier);break;case"delete":delete T[l.identifier],u.emit("changed",{flag:l.identifier,value:void 0,deleted:!0}),R("Evaluation deleted",{message:l,storage:T});break}},a=l=>!(!l||!l.flag||!l.identifier||!l.kind||!l.value),c=l=>!(!l||l.length==0||!l.every(E=>a(E))),g=l=>{l.event==="patch"&&(c(l.evaluations)?l.evaluations.forEach(E=>{D(E)}):k())},p=`${v.baseUrl}/stream?cluster=${s}`;f=new L(u,v,p,t,A,b,l=>{l.domain==="flag"?i(l):l.domain==="target-segment"&&g(l)}),f.start()},be=()=>{b.start()},$=(i,a)=>u.on(i,a),ye=(i,a)=>{i?u.off(i,a):te()},Re=(i,a)=>{var l;if(!w||Y||a===void 0)return;let c=a,g=i,p=C.find(E=>E.featureIdentifier===g&&E.featureValue===c);p?(H(p),p.variationIdentifier=((l=S[g])==null?void 0:l.identifier)||""):C.push({featureIdentifier:g,featureValue:c,count:1,variationIdentifier:S[g].identifier||"",lastAccessed:Date.now()})},te=()=>{r=!0,v.streamEnabled&&(R("Closing event stream"),typeof(f==null?void 0:f.close)=="function"&&f.close(),u.all.clear()),v.pollingEnabled&&b.isPolling()&&(R("Closing Poller"),b.stop()),T=Z(),S={},clearTimeout(d)},ie=(i,a=!0)=>{i.length&&j(()=>{let c=!!Object.keys(S).length;if(i.forEach(D),!c){M();let g=O({},T);m(),u.emit("ready",g)}},a)};return{on:$,off:ye,close:te,setEvaluations:ie,registerAPIRequestMiddleware:i=>{x=q(i)},refreshEvaluations:()=>{Q&&!r&&Date.now()-z>=6e4&&(k(),z=Date.now())},variation:(i,a,c=!1)=>ue(i,a,T,Re,c)}};export{V as Event,bt as initialize}; | ||
var Ie=Object.defineProperty,Se=Object.defineProperties;var we=Object.getOwnPropertyDescriptors;var ae=Object.getOwnPropertySymbols;var Ce=Object.prototype.hasOwnProperty,Te=Object.prototype.propertyIsEnumerable;var re=(t,e,n)=>e in t?Ie(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,T=(t,e)=>{for(var n in e||(e={}))Ce.call(e,n)&&re(t,n,e[n]);if(ae)for(var n of ae(e))Te.call(e,n)&&re(t,n,e[n]);return t},K=(t,e)=>Se(t,we(e));var h=(t,e,n)=>new Promise((r,o)=>{var s=R=>{try{b(n.next(R))}catch(u){o(u)}},f=R=>{try{b(n.throw(R))}catch(u){o(u)}},b=R=>R.done?r(R.value):Promise.resolve(R.value).then(s,f);b((n=n.apply(t,e)).next())});function U(t){this.message=t}U.prototype=new Error,U.prototype.name="InvalidCharacterError";var oe=typeof window!="undefined"&&window.atob&&window.atob.bind(window)||function(t){var e=String(t).replace(/=+$/,"");if(e.length%4==1)throw new U("'atob' failed: The string to be decoded is not correctly encoded.");for(var n,r,o=0,s=0,f="";r=e.charAt(s++);~r&&(n=o%4?64*n+r:r,o++%4)?f+=String.fromCharCode(255&n>>(-2*o&6)):0)r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(r);return f};function Oe(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(n){return decodeURIComponent(oe(n).replace(/(.)/g,function(r,o){var s=o.charCodeAt(0).toString(16).toUpperCase();return s.length<2&&(s="0"+s),"%"+s}))}(e)}catch(n){return oe(e)}}function N(t){this.message=t}function Ae(t,e){if(typeof t!="string")throw new N("Invalid token specified");var n=(e=e||{}).header===!0?0:1;try{return JSON.parse(Oe(t.split(".")[n]))}catch(r){throw new N("Invalid token specified: "+r.message)}}N.prototype=new Error,N.prototype.name="InvalidTokenError";var se=Ae;function le(t){return{all:t=t||new Map,on:function(e,n){var r=t.get(e);r&&r.push(n)||t.set(e,[n])},off:function(e,n){var r=t.get(e);r&&r.splice(r.indexOf(n)>>>0,1)},emit:function(e,n){(t.get(e)||[]).slice().map(function(r){r(n)}),(t.get("*")||[]).slice().map(function(r){r(e,n)})}}}var V=(m=>(m.READY="ready",m.CONNECTED="connected",m.DISCONNECTED="disconnected",m.STOPPED="stopped",m.POLLING="polling",m.POLLING_STOPPED="polling stopped",m.FLAGS_LOADED="flags loaded",m.CACHE_LOADED="cache loaded",m.CHANGED="changed",m.ERROR="error",m.ERROR_CACHE="cache error",m.ERROR_METRICS="metrics error",m.ERROR_AUTH="auth error",m.ERROR_FETCH_FLAGS="fetch flags error",m.ERROR_FETCH_FLAG="fetch flag error",m.ERROR_STREAM="stream error",m))(V||{});var De={debug:!1,baseUrl:"https://config.ff.harness.io/api/1.0",eventUrl:"https://events.ff.harness.io/api/1.0",eventsSyncInterval:6e4,pollingInterval:6e4,streamEnabled:!0,cache:!1},ce=t=>{let e=T(T({},De),t);return e.pollingEnabled===void 0&&(e.pollingEnabled=e.streamEnabled),e.eventsSyncInterval<6e4&&(e.eventsSyncInterval=6e4),e.pollingInterval<6e4&&(e.pollingInterval=6e4),e},I=(t,...e)=>console.error(`[FF-SDK] ${t}`,...e),j=(t,e=!0)=>{e?setTimeout(t,0):t()},_=(t,e)=>Math.round(Math.random()*(e-t)+t);function q(t){return function(...n){let[r,o]=t(n);return fetch(r,o)}}var ue=3e4,L=class{constructor(e,n,r,o,s,f,b){this.closed=!1;this.connectionOpened=!1;this.disconnectEventEmitted=!1;this.eventBus=e,this.configurations=n,this.url=r,this.apiKey=o,this.standardHeaders=s,this.eventCallback=b,this.fallbackPoller=f}start(){let e=u=>{u.toString().split(/\r?\n/).forEach(n)},n=u=>{if(u.startsWith("data:")){let w=JSON.parse(u.substring(5));this.logDebug("Received event from stream: ",w),this.eventCallback(w)}},r=()=>{this.logDebug("Stream connected"),this.eventBus.emit("connected")},o=()=>{clearInterval(this.readTimeoutCheckerId);let u=_(1e3,1e4);this.logDebug("Stream disconnected, will reconnect in "+u+"ms"),this.disconnectEventEmitted||(this.eventBus.emit("disconnected"),this.disconnectEventEmitted=!0),setTimeout(()=>this.start(),u)},s=u=>{u&&I("Stream has issue",u),this.fallBackToPolling(),this.eventBus.emit("stream error",u),this.eventBus.emit("error",u),o()},f=T({"Cache-Control":"no-cache",Accept:"text/event-stream","API-Key":this.apiKey},this.standardHeaders);this.logDebug("SSE HTTP start request",this.url),this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url);for(let[u,w]of Object.entries(f))this.xhr.setRequestHeader(u,w);this.xhr.timeout=24*60*60*1e3,this.xhr.onerror=()=>{this.connectionOpened=!1,s("XMLHttpRequest error on SSE stream")},this.xhr.onabort=()=>{this.connectionOpened=!1,this.logDebug("SSE aborted"),this.closed||s(null)},this.xhr.ontimeout=()=>{this.connectionOpened=!1,s("SSE timeout")},this.xhr.onload=()=>{if(this.xhr.status>=400&&this.xhr.status<=599){s(`HTTP code ${this.xhr.status}`);return}this.connectionOpened||(r(),this.connectionOpened=!0,this.disconnectEventEmitted=!1)};let b=0,R=Date.now();this.xhr.onprogress=()=>{this.connectionOpened||(r(),this.connectionOpened=!0,this.disconnectEventEmitted=!1),this.stopFallBackPolling(),R=Date.now();let u=this.xhr.responseText.slice(b);b+=u.length,this.logDebug("SSE GOT: "+u),e(u)},this.readTimeoutCheckerId=setInterval(()=>{R<Date.now()-ue&&(I("SSE read timeout"),this.xhr.abort())},ue),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.logDebug("Falling back to polling mode while stream recovers"),this.fallbackPoller.start())}stopFallBackPolling(){this.fallbackPoller.isPolling()&&(this.logDebug("Stopping fallback polling mode"),this.fallbackPoller.stop())}logDebug(e,...n){this.configurations.debug&&console.debug(`[FF-SDK] Streaming: ${e}`,...n)}};function de(t,e,n,r,o){let s=t in n,f=s?n[t]:e;return s&&r(t,f),o?{value:f,isDefaultValue:!s}:f}var F=class{constructor(e,n,r){this.fetchFlagsFn=e;this.configurations=n;this.eventBus=r;this.maxAttempts=5}start(){if(this.isPolling()){this.logDebug("Already polling.");return}this.isRunning=!0,this.eventBus.emit("polling"),this.logDebug(`Starting poller, first poll will be in ${this.configurations.pollingInterval}ms`),this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)}poll(){this.attemptFetch().finally(()=>{this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)})}attemptFetch(){return h(this,null,function*(){for(let e=1;e<=this.maxAttempts;e++){let n=yield this.fetchFlagsFn();if(n.type==="success"){this.logDebug(`Successfully polled for flag updates, next poll in ${this.configurations.pollingInterval}ms. `);return}if(I("Error when polling for flag updates",n.error),e>=this.maxAttempts){this.logDebug(`Maximum attempts reached for polling for flags. Next poll in ${this.configurations.pollingInterval}ms.`);return}this.logDebug(`Polling for flags attempt #${e} failed. Remaining attempts: ${this.maxAttempts-e}`,n.error);let r=_(1e3,1e4);yield new Promise(o=>setTimeout(o,r))}})}stop(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=void 0,this.isRunning=!1,this.eventBus.emit("polling stopped"),this.logDebug("Polling stopped"))}isPolling(){return this.isRunning}logDebug(e,...n){this.configurations.debug&&console.debug(`[FF-SDK] Poller: ${e}`,...n)}};function fe(n){return h(this,arguments,function*(t,e={}){let r=yield ke(t),o=Ne(e);return{loadFromCache:()=>J(r,o,e),saveToCache:s=>W(r,o,s),updateCachedEvaluation:s=>Fe(r,o,s),removeCachedEvaluation:s=>xe(r,o,s)}})}function J(r,o){return h(this,arguments,function*(t,e,n={}){let s=parseInt(yield e.getItem(t+".ts"));if(n!=null&&n.ttl&&!isNaN(s)&&s+n.ttl<Date.now())return yield Pe(t,e),[];let f=yield e.getItem(t);if(f)try{return JSON.parse(f)}catch(b){}return[]})}function Pe(t,e){return h(this,null,function*(){yield e.removeItem(t),yield e.removeItem(t+".ts")})}function W(t,e,n){return h(this,null,function*(){yield e.setItem(t,JSON.stringify(n)),yield e.setItem(t+".ts",Date.now().toString())})}function Fe(t,e,n){return h(this,null,function*(){let r=yield J(t,e),o=r.find(({flag:s})=>s===n.flag);o?Object.assign(o,n):r.push(n),yield W(t,e,r)})}function xe(t,e,n){return h(this,null,function*(){let r=yield J(t,e),o=r.findIndex(({flag:s})=>s===n);o>-1&&(r.splice(o,1),yield W(t,e,r))})}function ke(t){return h(this,null,function*(){var n,r;let e=t;if(globalThis!=null&&globalThis.TextEncoder&&((r=(n=globalThis==null?void 0:globalThis.crypto)==null?void 0:n.subtle)!=null&&r.digest)){let s=new TextEncoder().encode(t),f=yield crypto.subtle.digest("SHA-256",s);e=Array.from(new Uint8Array(f)).map(R=>R.toString(16).padStart(2,"0")).join("")}else globalThis.btoa&&(e=btoa(t));return"HARNESS_FF_CACHE_"+e})}function Ne(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=Ve:e=t.storage,{getItem(r){return h(this,null,function*(){let o=e.getItem(r);return o instanceof Promise?yield o:o})},setItem(r,o){return h(this,null,function*(){let s=e.setItem(r,o);s instanceof Promise&&(yield s)})},removeItem(r){return h(this,null,function*(){let o=e.removeItem(r);o instanceof Promise&&(yield o)})}}}var Ve={getItem:()=>null,setItem:()=>{},removeItem:()=>{}};var he="1.25.0",ge=`Javascript ${he} Client`,_e=500,Le=globalThis.fetch,Y=!!globalThis.Proxy,z=t=>{let{value:e}=t;try{switch(t.kind.toLowerCase()){case"int":case"number":e=Number(e);break;case"boolean":e=e.toString().toLowerCase()==="true";break;case"json":e=JSON.parse(e);break}}catch(n){I(n)}return e},Et=(t,e,n)=>{let r=!1,o,s,f,b,R,u,w=!0,A={},x=q(i=>i),X=0,Q=!1,M=()=>{w=!1},m=()=>{w=!0},C=[],d=le(),v=ce(n),y=(i,...a)=>{v.debug&&console.debug(`[FF-SDK] ${i}`,...a)},H=i=>{if(w){let a=Date.now();a-i.lastAccessed>_e&&(i.count++,i.lastAccessed=a)}},me=()=>h(void 0,null,function*(){if(v.cache){y("initializing cache");try{let i=!0,a=yield fe(e.identifier+t,typeof v.cache=="boolean"?{}:v.cache),c=yield a.loadFromCache();c!=null&&c.length&&j(()=>{y("loading from cache",c),ie(c,!1),d.emit("cache loaded",c)}),$("flags loaded",g=>h(void 0,null,function*(){yield a.saveToCache(g),i=!1})),$("changed",g=>h(void 0,null,function*(){i||(g.deleted?yield a.removeCachedEvaluation(g.flag):yield a.updateCachedEvaluation(g))}))}catch(i){I("Cache error: ",i),d.emit("cache error",i),d.emit("error",i)}}}),ve=(i,a)=>h(void 0,null,function*(){return(yield(yield Le(`${a.baseUrl}/client/auth`,{method:"POST",headers:{"Content-Type":"application/json","Harness-SDK-Info":ge},body:JSON.stringify({apiKey:i,target:K(T({},e),{identifier:String(e.identifier)})})})).json()).authToken}),G=0,B=()=>{if(C.length){y("Sending metrics...",{metrics:C,evaluations:S});let i={metricsData:C.map(a=>({timestamp:Date.now(),count:a.count,metricsType:"FFMETRICS",attributes:[{key:"featureIdentifier",value:a.featureIdentifier},{key:"featureName",value:a.featureIdentifier},{key:"variationIdentifier",value:a.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:he}]}))};x(`${v.eventUrl}/metrics/${o}?cluster=${s}`,{method:"POST",headers:T({"Content-Type":"application/json"},A),body:JSON.stringify(i)}).then(()=>{C=[],G=0}).catch(a=>{G++&&(C=[],G=0),y(a),d.emit("metrics error",a)}).finally(()=>{u=window.setTimeout(B,v.eventsSyncInterval)})}else u=window.setTimeout(B,v.eventsSyncInterval)},S={},pe=i=>{y("Sending event for",i.flag),Y?d.emit("changed",new Proxy(i,{get(a,c){var g;if(w&&a.hasOwnProperty(c)&&c==="value"){let p=a.flag,l=i.value,E=C.find(P=>P.featureIdentifier===p&&P.featureValue===l);E?(H(E),E.variationIdentifier=((g=S[p])==null?void 0:g.identifier)||""):C.push({featureIdentifier:p,featureValue:String(l),variationIdentifier:S[p].identifier||"",count:1,lastAccessed:Date.now()}),y("Metrics event: Flag",c,"has been read with value via stream update",l)}return c==="value"?z(i):i[c]}})):d.emit("changed",{deleted:i.deleted,flag:i.flag,value:z(i)})},Z=function(){return Y?new Proxy({},{get(i,a){var g,p,l;let c=i[a];if(w&&i.hasOwnProperty(a)){let E=i[a],P=C.find(ne=>ne.featureIdentifier===a&&E===ne.featureValue);P?(P.variationIdentifier=((g=S[a])==null?void 0:g.identifier)||"",H(P)):C.push({featureIdentifier:a,featureValue:E,variationIdentifier:((p=S[a])==null?void 0:p.identifier)||"",count:1,lastAccessed:Date.now()}),y("Metrics event: Flag:",a,"has been read with value:",E,"variationIdentifier:",(l=S[a])==null?void 0:l.identifier)}return c}}):{}},O=Z();me().then(()=>ve(t,v).then(i=>h(void 0,null,function*(){if(r)return;R=i;let a=se(i);if(A={Authorization:`Bearer ${R}`,"Harness-AccountID":a.accountID,"Harness-EnvironmentID":a.environmentIdentifier,"Harness-SDK-Info":ge},globalThis.btoa){let p=globalThis.btoa(JSON.stringify(e));p.length<262144&&(A["Harness-Target"]=p)}y("Authenticated",a),u=window.setTimeout(B,v.eventsSyncInterval),o=a.environment,s=a.clusterIdentifier;let c=!!Object.keys(S).length;if((yield k()).type==="success"&&y("Fetch all flags ok",O),!r){if(v.streamEnabled?(y("Streaming mode enabled"),Ee()):v.pollingEnabled?(y("Polling mode enabled"),be()):y("Streaming and polling mode disabled"),!c){M();let p=T({},O);m(),d.emit("ready",p)}Q=!0}})).catch(i=>{I("Authentication error: ",i),d.emit("auth error",i),d.emit("error",i)}));let k=()=>h(void 0,null,function*(){try{let i=yield x(`${v.baseUrl}/client/env/${o}/target/${e.identifier}/evaluations?cluster=${s}`,{headers:A});if(i.ok){let a=yield i.json();return a.forEach(D),d.emit("flags loaded",a),{type:"success",data:a}}else return I("Features fetch operation error: ",i),d.emit("fetch flags error",i),d.emit("error",i),{type:"error",error:i}}catch(i){return I("Features fetch operation error: ",i),d.emit("fetch flags error",i),d.emit("error",i),{type:"error",error:i}}}),ee=i=>h(void 0,null,function*(){try{let a=yield x(`${v.baseUrl}/client/env/${o}/target/${e.identifier}/evaluations/${i}?cluster=${s}`,{headers:A});if(a.ok){let c=yield a.json();D(c)}else I("Feature fetch operation error: ",a),d.emit("fetch flag error",a),d.emit("error",a)}catch(a){I("Feature fetch operation error: ",a),d.emit("fetch flag error",a),d.emit("error",a)}}),D=i=>{M();let a=z(i);a!==O[i.flag]&&(y("Flag variation has changed for ",i.identifier),O[i.flag]=a,S[i.flag]=K(T({},i),{value:a}),pe(i)),m()};b=new F(k,v,d);let Ee=()=>{let i=l=>{switch(l.event){case"create":c(l.evaluations)?l.evaluations.forEach(E=>{D(E)}):setTimeout(()=>ee(l.identifier),1e3);break;case"patch":c(l.evaluations)?l.evaluations.forEach(E=>{D(E)}):ee(l.identifier);break;case"delete":delete O[l.identifier],d.emit("changed",{flag:l.identifier,value:void 0,deleted:!0}),y("Evaluation deleted",{message:l,storage:O});break}},a=l=>!(!l||!l.flag||!l.identifier||!l.kind||!l.value),c=l=>!(!l||l.length==0||!l.every(E=>a(E))),g=l=>{l.event==="patch"&&(c(l.evaluations)?l.evaluations.forEach(E=>{D(E)}):k())},p=`${v.baseUrl}/stream?cluster=${s}`;f=new L(d,v,p,t,A,b,l=>{l.domain==="flag"?i(l):l.domain==="target-segment"&&g(l)}),f.start()},be=()=>{b.start()},$=(i,a)=>d.on(i,a),ye=(i,a)=>{i?d.off(i,a):te()},Re=(i,a)=>{var l;if(!w||Y||a===void 0)return;let c=a,g=i,p=C.find(E=>E.featureIdentifier===g&&E.featureValue===c);p?(H(p),p.variationIdentifier=((l=S[g])==null?void 0:l.identifier)||""):C.push({featureIdentifier:g,featureValue:c,count:1,variationIdentifier:S[g].identifier||"",lastAccessed:Date.now()})},te=()=>{r=!0,v.streamEnabled&&(y("Closing event stream"),typeof(f==null?void 0:f.close)=="function"&&f.close(),d.all.clear()),v.pollingEnabled&&b.isPolling()&&(y("Closing Poller"),b.stop()),O=Z(),S={},clearTimeout(u)},ie=(i,a=!0)=>{i.length&&j(()=>{let c=!!Object.keys(S).length;if(i.forEach(D),!c){M();let g=T({},O);m(),d.emit("ready",g)}},a)};return{on:$,off:ye,close:te,setEvaluations:ie,registerAPIRequestMiddleware:i=>{x=q(i)},refreshEvaluations:()=>{Q&&!r&&Date.now()-X>=6e4&&(k(),X=Date.now())},variation:(i,a,c=!1)=>de(i,a,O,Re,c)}};export{V as Event,Et as initialize}; |
@@ -1,1 +0,1 @@ | ||
var pe=Object.defineProperty,Ee=Object.defineProperties;var be=Object.getOwnPropertyDescriptors;var ie=Object.getOwnPropertySymbols;var Re=Object.prototype.hasOwnProperty,ye=Object.prototype.propertyIsEnumerable;var ne=(i,e,a)=>e in i?pe(i,e,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[e]=a,T=(i,e)=>{for(var a in e||(e={}))Re.call(e,a)&&ne(i,a,e[a]);if(ie)for(var a of ie(e))ye.call(e,a)&&ne(i,a,e[a]);return i},$=(i,e)=>Ee(i,be(e));var Se=(i=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(i,{get:(e,a)=>(typeof require!="undefined"?require:e)[a]}):i)(function(i){if(typeof require!="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+i+'" is not supported')});var h=(i,e,a)=>new Promise((r,s)=>{var l=R=>{try{b(a.next(R))}catch(d){s(d)}},g=R=>{try{b(a.throw(R))}catch(d){s(d)}},b=R=>R.done?r(R.value):Promise.resolve(R.value).then(l,g);b((a=a.apply(i,e)).next())});import Pe from"jwt-decode";import Fe from"mitt";var k=(m=>(m.READY="ready",m.CONNECTED="connected",m.DISCONNECTED="disconnected",m.STOPPED="stopped",m.POLLING="polling",m.POLLING_STOPPED="polling stopped",m.FLAGS_LOADED="flags loaded",m.CACHE_LOADED="cache loaded",m.CHANGED="changed",m.ERROR="error",m.ERROR_CACHE="cache error",m.ERROR_METRICS="metrics error",m.ERROR_AUTH="auth error",m.ERROR_FETCH_FLAGS="fetch flags error",m.ERROR_FETCH_FLAG="fetch flag error",m.ERROR_STREAM="stream error",m))(k||{});var Ie={debug:!1,baseUrl:"https://config.ff.harness.io/api/1.0",eventUrl:"https://events.ff.harness.io/api/1.0",eventsSyncInterval:6e4,pollingInterval:6e4,streamEnabled:!0,cache:!1},ae=i=>{let e=T(T({},Ie),i);if(e.pollingEnabled===void 0&&(e.pollingEnabled=e.streamEnabled),e.eventsSyncInterval<6e4&&(e.eventsSyncInterval=6e4),e.pollingInterval<6e4&&(e.pollingInterval=6e4),e.streamEnabled)try{let{Platform:a}=Se("react-native");a.OS==="android"&&(console.info("SDKCODE:1007 Android React Native detected - streaming will be disabled and polling enabled"),e.pollingEnabled=!0,e.streamEnabled=!1)}catch(a){}return e},S=(i,...e)=>console.error(`[FF-SDK] ${i}`,...e),K=(i,e=!0)=>{e?setTimeout(i,0):i()},V=(i,e)=>Math.round(Math.random()*(e-i)+i);function j(i){return function(...a){let[r,s]=i(a);return fetch(r,s)}}var re=3e4,_=class{constructor(e,a,r,s,l,g,b){this.closed=!1;this.connectionOpened=!1;this.disconnectEventEmitted=!1;this.eventBus=e,this.configurations=a,this.url=r,this.apiKey=s,this.standardHeaders=l,this.eventCallback=b,this.fallbackPoller=g}start(){let e=d=>{d.toString().split(/\r?\n/).forEach(a)},a=d=>{if(d.startsWith("data:")){let C=JSON.parse(d.substring(5));this.logDebug("Received event from stream: ",C),this.eventCallback(C)}},r=()=>{this.logDebug("Stream connected"),this.eventBus.emit("connected")},s=()=>{clearInterval(this.readTimeoutCheckerId);let d=V(1e3,1e4);this.logDebug("Stream disconnected, will reconnect in "+d+"ms"),this.disconnectEventEmitted||(this.eventBus.emit("disconnected"),this.disconnectEventEmitted=!0),setTimeout(()=>this.start(),d)},l=d=>{d&&S("Stream has issue",d),this.fallBackToPolling(),this.eventBus.emit("stream error",d),this.eventBus.emit("error",d),s()},g=T({"Cache-Control":"no-cache",Accept:"text/event-stream","API-Key":this.apiKey},this.standardHeaders);this.logDebug("SSE HTTP start request",this.url),this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url);for(let[d,C]of Object.entries(g))this.xhr.setRequestHeader(d,C);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.logDebug("SSE aborted"),this.closed||l(null)},this.xhr.ontimeout=()=>{this.connectionOpened=!1,l("SSE timeout")},this.xhr.onload=()=>{if(this.xhr.status>=400&&this.xhr.status<=599){l(`HTTP code ${this.xhr.status}`);return}this.connectionOpened||(r(),this.connectionOpened=!0,this.disconnectEventEmitted=!1)};let b=0,R=Date.now();this.xhr.onprogress=()=>{this.connectionOpened||(r(),this.connectionOpened=!0,this.disconnectEventEmitted=!1),this.stopFallBackPolling(),R=Date.now();let d=this.xhr.responseText.slice(b);b+=d.length,this.logDebug("SSE GOT: "+d),e(d)},this.readTimeoutCheckerId=setInterval(()=>{R<Date.now()-re&&(S("SSE read timeout"),this.xhr.abort())},re),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.logDebug("Falling back to polling mode while stream recovers"),this.fallbackPoller.start())}stopFallBackPolling(){this.fallbackPoller.isPolling()&&(this.logDebug("Stopping fallback polling mode"),this.fallbackPoller.stop())}logDebug(e,...a){this.configurations.debug&&console.debug(`[FF-SDK] Streaming: ${e}`,...a)}};function oe(i,e,a,r,s){let l=i in a,g=l?a[i]:e;return l&&r(i,g),s?{value:g,isDefaultValue:!l}:g}var F=class{constructor(e,a,r){this.fetchFlagsFn=e;this.configurations=a;this.eventBus=r;this.maxAttempts=5}start(){if(this.isPolling()){this.logDebug("Already polling.");return}this.isRunning=!0,this.eventBus.emit("polling"),this.logDebug(`Starting poller, first poll will be in ${this.configurations.pollingInterval}ms`),this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)}poll(){this.attemptFetch().finally(()=>{this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)})}attemptFetch(){return h(this,null,function*(){for(let e=1;e<=this.maxAttempts;e++){let a=yield this.fetchFlagsFn();if(a.type==="success"){this.logDebug(`Successfully polled for flag updates, next poll in ${this.configurations.pollingInterval}ms. `);return}if(S("Error when polling for flag updates",a.error),e>=this.maxAttempts){this.logDebug(`Maximum attempts reached for polling for flags. Next poll in ${this.configurations.pollingInterval}ms.`);return}this.logDebug(`Polling for flags attempt #${e} failed. Remaining attempts: ${this.maxAttempts-e}`,a.error);let r=V(1e3,1e4);yield new Promise(s=>setTimeout(s,r))}})}stop(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=void 0,this.isRunning=!1,this.eventBus.emit("polling stopped"),this.logDebug("Polling stopped"))}isPolling(){return this.isRunning}logDebug(e,...a){this.configurations.debug&&console.debug(`[FF-SDK] Poller: ${e}`,...a)}};function se(a){return h(this,arguments,function*(i,e={}){let r=yield we(i),s=Ae(e);return{loadFromCache:()=>q(r,s,e),saveToCache:l=>U(r,s,l),updateCachedEvaluation:l=>Oe(r,s,l),removeCachedEvaluation:l=>Te(r,s,l)}})}function q(r,s){return h(this,arguments,function*(i,e,a={}){let l=parseInt(yield e.getItem(i+".ts"));if(a!=null&&a.ttl&&!isNaN(l)&&l+a.ttl<Date.now())return yield Ce(i,e),[];let g=yield e.getItem(i);if(g)try{return JSON.parse(g)}catch(b){}return[]})}function Ce(i,e){return h(this,null,function*(){yield e.removeItem(i),yield e.removeItem(i+".ts")})}function U(i,e,a){return h(this,null,function*(){yield e.setItem(i,JSON.stringify(a)),yield e.setItem(i+".ts",Date.now().toString())})}function Oe(i,e,a){return h(this,null,function*(){let r=yield q(i,e),s=r.find(({flag:l})=>l===a.flag);s?Object.assign(s,a):r.push(a),yield U(i,e,r)})}function Te(i,e,a){return h(this,null,function*(){let r=yield q(i,e),s=r.findIndex(({flag:l})=>l===a);s>-1&&(r.splice(s,1),yield U(i,e,r))})}function we(i){return h(this,null,function*(){var a,r;let e=i;if(globalThis!=null&&globalThis.TextEncoder&&((r=(a=globalThis==null?void 0:globalThis.crypto)==null?void 0:a.subtle)!=null&&r.digest)){let l=new TextEncoder().encode(i),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(i));return"HARNESS_FF_CACHE_"+e})}function Ae(i){let e;return!i.storage||typeof i.storage!="object"||!("getItem"in i.storage)||!("setItem"in i.storage)||!("removeItem"in i.storage)?globalThis.localStorage?e=globalThis.localStorage:globalThis.sessionStorage?e=globalThis.sessionStorage:e=De:e=i.storage,{getItem(r){return h(this,null,function*(){let s=e.getItem(r);return s instanceof Promise?yield s:s})},setItem(r,s){return h(this,null,function*(){let l=e.setItem(r,s);l instanceof Promise&&(yield l)})},removeItem(r){return h(this,null,function*(){let s=e.removeItem(r);s instanceof Promise&&(yield s)})}}}var De={getItem:()=>null,setItem:()=>{},removeItem:()=>{}};var ce="1.25.0",le=`Javascript ${ce} Client`,xe=500,Ne=globalThis.fetch,W=!!globalThis.Proxy,J=i=>{let{value:e}=i;try{switch(i.kind.toLowerCase()){case"int":case"number":e=Number(e);break;case"boolean":e=e.toString().toLowerCase()==="true";break;case"json":e=JSON.parse(e);break}}catch(a){S(a)}return e},ft=(i,e,a)=>{let r=!1,s,l,g,b,R,d,C=!0,A={},x=j(t=>t),Y=0,X=!1,L=()=>{C=!1},m=()=>{C=!0},O=[],u=Fe(),v=ae(a),y=(t,...n)=>{v.debug&&console.debug(`[FF-SDK] ${t}`,...n)},M=t=>{if(C){let n=Date.now();n-t.lastAccessed>xe&&(t.count++,t.lastAccessed=n)}},de=()=>h(void 0,null,function*(){if(v.cache)try{let t=!0,n=yield se(e.identifier+i,typeof v.cache=="boolean"?{}:v.cache),c=yield n.loadFromCache();c!=null&&c.length&&K(()=>{y("loading from cache",c),ee(c,!1),u.emit("cache loaded",c)}),B("flags loaded",f=>h(void 0,null,function*(){yield n.saveToCache(f),t=!1})),B("changed",f=>h(void 0,null,function*(){t||(f.deleted?yield n.removeCachedEvaluation(f.flag):yield n.updateCachedEvaluation(f))}))}catch(t){S("Cache error: ",t),u.emit("cache error",t),u.emit("error",t)}}),ue=(t,n)=>h(void 0,null,function*(){return(yield(yield Ne(`${n.baseUrl}/client/auth`,{method:"POST",headers:{"Content-Type":"application/json","Harness-SDK-Info":le},body:JSON.stringify({apiKey:t,target:$(T({},e),{identifier:String(e.identifier)})})})).json()).authToken}),H=0,G=()=>{if(O.length){y("Sending metrics...",{metrics:O,evaluations:I});let t={metricsData:O.map(n=>({timestamp:Date.now(),count:n.count,metricsType:"FFMETRICS",attributes:[{key:"featureIdentifier",value:n.featureIdentifier},{key:"featureName",value:n.featureIdentifier},{key:"variationIdentifier",value:n.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:ce}]}))};x(`${v.eventUrl}/metrics/${s}?cluster=${l}`,{method:"POST",headers:T({"Content-Type":"application/json"},A),body:JSON.stringify(t)}).then(()=>{O=[],H=0}).catch(n=>{H++&&(O=[],H=0),y(n),u.emit("metrics error",n)}).finally(()=>{d=window.setTimeout(G,v.eventsSyncInterval)})}else d=window.setTimeout(G,v.eventsSyncInterval)},I={},fe=t=>{y("Sending event for",t.flag),W?u.emit("changed",new Proxy(t,{get(n,c){var f;if(C&&n.hasOwnProperty(c)&&c==="value"){let p=n.flag,o=t.value,E=O.find(P=>P.featureIdentifier===p&&P.featureValue===o);E?(M(E),E.variationIdentifier=((f=I[p])==null?void 0:f.identifier)||""):O.push({featureIdentifier:p,featureValue:String(o),variationIdentifier:I[p].identifier||"",count:1,lastAccessed:Date.now()}),y("Metrics event: Flag",c,"has been read with value via stream update",o)}return c==="value"?J(t):t[c]}})):u.emit("changed",{deleted:t.deleted,flag:t.flag,value:J(t)})},z=function(){return W?new Proxy({},{get(t,n){var f,p,o;let c=t[n];if(C&&t.hasOwnProperty(n)){let E=t[n],P=O.find(te=>te.featureIdentifier===n&&E===te.featureValue);P?(P.variationIdentifier=((f=I[n])==null?void 0:f.identifier)||"",M(P)):O.push({featureIdentifier:n,featureValue:E,variationIdentifier:((p=I[n])==null?void 0:p.identifier)||"",count:1,lastAccessed:Date.now()}),y("Metrics event: Flag:",n,"has been read with value:",E,"variationIdentifier:",(o=I[n])==null?void 0:o.identifier)}return c}}):{}},w=z();de().then(()=>ue(i,v).then(t=>h(void 0,null,function*(){if(r)return;R=t;let n=Pe(t);if(A={Authorization:`Bearer ${R}`,"Harness-AccountID":n.accountID,"Harness-EnvironmentID":n.environmentIdentifier,"Harness-SDK-Info":le},globalThis.btoa){let p=globalThis.btoa(JSON.stringify(e));p.length<262144&&(A["Harness-Target"]=p)}y("Authenticated",n),d=window.setTimeout(G,v.eventsSyncInterval),s=n.environment,l=n.clusterIdentifier;let c=!!Object.keys(I).length;if((yield N()).type==="success"&&y("Fetch all flags ok",w),!r){if(v.streamEnabled?(y("Streaming mode enabled"),ge()):v.pollingEnabled?(y("Polling mode enabled"),he()):y("Streaming and polling mode disabled"),!c){L();let p=T({},w);m(),u.emit("ready",p)}X=!0}})).catch(t=>{S("Authentication error: ",t),u.emit("auth error",t),u.emit("error",t)}));let N=()=>h(void 0,null,function*(){try{let t=yield x(`${v.baseUrl}/client/env/${s}/target/${e.identifier}/evaluations?cluster=${l}`,{headers:A});if(t.ok){let n=yield t.json();return n.forEach(D),u.emit("flags loaded",n),{type:"success",data:n}}else return S("Features fetch operation error: ",t),u.emit("fetch flags error",t),u.emit("error",t),{type:"error",error:t}}catch(t){return S("Features fetch operation error: ",t),u.emit("fetch flags error",t),u.emit("error",t),{type:"error",error:t}}}),Q=t=>h(void 0,null,function*(){try{let n=yield x(`${v.baseUrl}/client/env/${s}/target/${e.identifier}/evaluations/${t}?cluster=${l}`,{headers:A});if(n.ok){let c=yield n.json();D(c)}else S("Feature fetch operation error: ",n),u.emit("fetch flag error",n),u.emit("error",n)}catch(n){S("Feature fetch operation error: ",n),u.emit("fetch flag error",n),u.emit("error",n)}}),D=t=>{L();let n=J(t);n!==w[t.flag]&&(y("Flag variation has changed for ",t.identifier),w[t.flag]=n,I[t.flag]=$(T({},t),{value:n}),fe(t)),m()};b=new F(N,v,u);let ge=()=>{let t=o=>{switch(o.event){case"create":c(o.evaluations)?o.evaluations.forEach(E=>{D(E)}):setTimeout(()=>Q(o.identifier),1e3);break;case"patch":c(o.evaluations)?o.evaluations.forEach(E=>{D(E)}):Q(o.identifier);break;case"delete":delete w[o.identifier],u.emit("changed",{flag:o.identifier,value:void 0,deleted:!0}),y("Evaluation deleted",{message:o,storage:w});break}},n=o=>!(!o||!o.flag||!o.identifier||!o.kind||!o.value),c=o=>!(!o||o.length==0||!o.every(E=>n(E))),f=o=>{o.event==="patch"&&(c(o.evaluations)?o.evaluations.forEach(E=>{D(E)}):N())},p=`${v.baseUrl}/stream?cluster=${l}`;g=new _(u,v,p,i,A,b,o=>{o.domain==="flag"?t(o):o.domain==="target-segment"&&f(o)}),g.start()},he=()=>{b.start()},B=(t,n)=>u.on(t,n),me=(t,n)=>{t?u.off(t,n):Z()},ve=(t,n)=>{var o;if(!C||W||n===void 0)return;let c=n,f=t,p=O.find(E=>E.featureIdentifier===f&&E.featureValue===c);p?(M(p),p.variationIdentifier=((o=I[f])==null?void 0:o.identifier)||""):O.push({featureIdentifier:f,featureValue:c,count:1,variationIdentifier:I[f].identifier||"",lastAccessed:Date.now()})},Z=()=>{r=!0,v.streamEnabled&&(y("Closing event stream"),typeof(g==null?void 0:g.close)=="function"&&g.close(),u.all.clear()),v.pollingEnabled&&b.isPolling()&&(y("Closing Poller"),b.stop()),w=z(),I={},clearTimeout(d)},ee=(t,n=!0)=>{t.length&&K(()=>{let c=!!Object.keys(I).length;if(t.forEach(D),!c){L();let f=T({},w);m(),u.emit("ready",f)}},n)};return{on:B,off:me,close:Z,setEvaluations:ee,registerAPIRequestMiddleware:t=>{x=j(t)},refreshEvaluations:()=>{X&&!r&&Date.now()-Y>=6e4&&(N(),Y=Date.now())},variation:(t,n,c=!1)=>oe(t,n,w,ve,c)}};export{k as Event,ft as initialize}; | ||
var pe=Object.defineProperty,Ee=Object.defineProperties;var Re=Object.getOwnPropertyDescriptors;var ie=Object.getOwnPropertySymbols;var be=Object.prototype.hasOwnProperty,ye=Object.prototype.propertyIsEnumerable;var ne=(n,e,a)=>e in n?pe(n,e,{enumerable:!0,configurable:!0,writable:!0,value:a}):n[e]=a,O=(n,e)=>{for(var a in e||(e={}))be.call(e,a)&&ne(n,a,e[a]);if(ie)for(var a of ie(e))ye.call(e,a)&&ne(n,a,e[a]);return n},$=(n,e)=>Ee(n,Re(e));var h=(n,e,a)=>new Promise((r,s)=>{var l=y=>{try{R(a.next(y))}catch(u){s(u)}},g=y=>{try{R(a.throw(y))}catch(u){s(u)}},R=y=>y.done?r(y.value):Promise.resolve(y.value).then(l,g);R((a=a.apply(n,e)).next())});import De from"jwt-decode";import Pe from"mitt";var k=(m=>(m.READY="ready",m.CONNECTED="connected",m.DISCONNECTED="disconnected",m.STOPPED="stopped",m.POLLING="polling",m.POLLING_STOPPED="polling stopped",m.FLAGS_LOADED="flags loaded",m.CACHE_LOADED="cache loaded",m.CHANGED="changed",m.ERROR="error",m.ERROR_CACHE="cache error",m.ERROR_METRICS="metrics error",m.ERROR_AUTH="auth error",m.ERROR_FETCH_FLAGS="fetch flags error",m.ERROR_FETCH_FLAG="fetch flag error",m.ERROR_STREAM="stream error",m))(k||{});var Ie={debug:!1,baseUrl:"https://config.ff.harness.io/api/1.0",eventUrl:"https://events.ff.harness.io/api/1.0",eventsSyncInterval:6e4,pollingInterval:6e4,streamEnabled:!0,cache:!1},ae=n=>{let e=O(O({},Ie),n);return e.pollingEnabled===void 0&&(e.pollingEnabled=e.streamEnabled),e.eventsSyncInterval<6e4&&(e.eventsSyncInterval=6e4),e.pollingInterval<6e4&&(e.pollingInterval=6e4),e},I=(n,...e)=>console.error(`[FF-SDK] ${n}`,...e),K=(n,e=!0)=>{e?setTimeout(n,0):n()},V=(n,e)=>Math.round(Math.random()*(e-n)+n);function j(n){return function(...a){let[r,s]=n(a);return fetch(r,s)}}var re=3e4,_=class{constructor(e,a,r,s,l,g,R){this.closed=!1;this.connectionOpened=!1;this.disconnectEventEmitted=!1;this.eventBus=e,this.configurations=a,this.url=r,this.apiKey=s,this.standardHeaders=l,this.eventCallback=R,this.fallbackPoller=g}start(){let e=u=>{u.toString().split(/\r?\n/).forEach(a)},a=u=>{if(u.startsWith("data:")){let C=JSON.parse(u.substring(5));this.logDebug("Received event from stream: ",C),this.eventCallback(C)}},r=()=>{this.logDebug("Stream connected"),this.eventBus.emit("connected")},s=()=>{clearInterval(this.readTimeoutCheckerId);let u=V(1e3,1e4);this.logDebug("Stream disconnected, will reconnect in "+u+"ms"),this.disconnectEventEmitted||(this.eventBus.emit("disconnected"),this.disconnectEventEmitted=!0),setTimeout(()=>this.start(),u)},l=u=>{u&&I("Stream has issue",u),this.fallBackToPolling(),this.eventBus.emit("stream error",u),this.eventBus.emit("error",u),s()},g=O({"Cache-Control":"no-cache",Accept:"text/event-stream","API-Key":this.apiKey},this.standardHeaders);this.logDebug("SSE HTTP start request",this.url),this.xhr=new XMLHttpRequest,this.xhr.open("GET",this.url);for(let[u,C]of Object.entries(g))this.xhr.setRequestHeader(u,C);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.logDebug("SSE aborted"),this.closed||l(null)},this.xhr.ontimeout=()=>{this.connectionOpened=!1,l("SSE timeout")},this.xhr.onload=()=>{if(this.xhr.status>=400&&this.xhr.status<=599){l(`HTTP code ${this.xhr.status}`);return}this.connectionOpened||(r(),this.connectionOpened=!0,this.disconnectEventEmitted=!1)};let R=0,y=Date.now();this.xhr.onprogress=()=>{this.connectionOpened||(r(),this.connectionOpened=!0,this.disconnectEventEmitted=!1),this.stopFallBackPolling(),y=Date.now();let u=this.xhr.responseText.slice(R);R+=u.length,this.logDebug("SSE GOT: "+u),e(u)},this.readTimeoutCheckerId=setInterval(()=>{y<Date.now()-re&&(I("SSE read timeout"),this.xhr.abort())},re),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.logDebug("Falling back to polling mode while stream recovers"),this.fallbackPoller.start())}stopFallBackPolling(){this.fallbackPoller.isPolling()&&(this.logDebug("Stopping fallback polling mode"),this.fallbackPoller.stop())}logDebug(e,...a){this.configurations.debug&&console.debug(`[FF-SDK] Streaming: ${e}`,...a)}};function oe(n,e,a,r,s){let l=n in a,g=l?a[n]:e;return l&&r(n,g),s?{value:g,isDefaultValue:!l}:g}var F=class{constructor(e,a,r){this.fetchFlagsFn=e;this.configurations=a;this.eventBus=r;this.maxAttempts=5}start(){if(this.isPolling()){this.logDebug("Already polling.");return}this.isRunning=!0,this.eventBus.emit("polling"),this.logDebug(`Starting poller, first poll will be in ${this.configurations.pollingInterval}ms`),this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)}poll(){this.attemptFetch().finally(()=>{this.timeoutId=setTimeout(()=>this.poll(),this.configurations.pollingInterval)})}attemptFetch(){return h(this,null,function*(){for(let e=1;e<=this.maxAttempts;e++){let a=yield this.fetchFlagsFn();if(a.type==="success"){this.logDebug(`Successfully polled for flag updates, next poll in ${this.configurations.pollingInterval}ms. `);return}if(I("Error when polling for flag updates",a.error),e>=this.maxAttempts){this.logDebug(`Maximum attempts reached for polling for flags. Next poll in ${this.configurations.pollingInterval}ms.`);return}this.logDebug(`Polling for flags attempt #${e} failed. Remaining attempts: ${this.maxAttempts-e}`,a.error);let r=V(1e3,1e4);yield new Promise(s=>setTimeout(s,r))}})}stop(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=void 0,this.isRunning=!1,this.eventBus.emit("polling stopped"),this.logDebug("Polling stopped"))}isPolling(){return this.isRunning}logDebug(e,...a){this.configurations.debug&&console.debug(`[FF-SDK] Poller: ${e}`,...a)}};function se(a){return h(this,arguments,function*(n,e={}){let r=yield Oe(n),s=we(e);return{loadFromCache:()=>U(r,s,e),saveToCache:l=>q(r,s,l),updateCachedEvaluation:l=>Ce(r,s,l),removeCachedEvaluation:l=>Te(r,s,l)}})}function U(r,s){return h(this,arguments,function*(n,e,a={}){let l=parseInt(yield e.getItem(n+".ts"));if(a!=null&&a.ttl&&!isNaN(l)&&l+a.ttl<Date.now())return yield Se(n,e),[];let g=yield e.getItem(n);if(g)try{return JSON.parse(g)}catch(R){}return[]})}function Se(n,e){return h(this,null,function*(){yield e.removeItem(n),yield e.removeItem(n+".ts")})}function q(n,e,a){return h(this,null,function*(){yield e.setItem(n,JSON.stringify(a)),yield e.setItem(n+".ts",Date.now().toString())})}function Ce(n,e,a){return h(this,null,function*(){let r=yield U(n,e),s=r.find(({flag:l})=>l===a.flag);s?Object.assign(s,a):r.push(a),yield q(n,e,r)})}function Te(n,e,a){return h(this,null,function*(){let r=yield U(n,e),s=r.findIndex(({flag:l})=>l===a);s>-1&&(r.splice(s,1),yield q(n,e,r))})}function Oe(n){return h(this,null,function*(){var a,r;let e=n;if(globalThis!=null&&globalThis.TextEncoder&&((r=(a=globalThis==null?void 0:globalThis.crypto)==null?void 0:a.subtle)!=null&&r.digest)){let l=new TextEncoder().encode(n),g=yield crypto.subtle.digest("SHA-256",l);e=Array.from(new Uint8Array(g)).map(y=>y.toString(16).padStart(2,"0")).join("")}else globalThis.btoa&&(e=btoa(n));return"HARNESS_FF_CACHE_"+e})}function we(n){let e;return!n.storage||typeof n.storage!="object"||!("getItem"in n.storage)||!("setItem"in n.storage)||!("removeItem"in n.storage)?globalThis.localStorage?e=globalThis.localStorage:globalThis.sessionStorage?e=globalThis.sessionStorage:e=Ae:e=n.storage,{getItem(r){return h(this,null,function*(){let s=e.getItem(r);return s instanceof Promise?yield s:s})},setItem(r,s){return h(this,null,function*(){let l=e.setItem(r,s);l instanceof Promise&&(yield l)})},removeItem(r){return h(this,null,function*(){let s=e.removeItem(r);s instanceof Promise&&(yield s)})}}}var Ae={getItem:()=>null,setItem:()=>{},removeItem:()=>{}};var ce="1.25.0",le=`Javascript ${ce} Client`,Fe=500,xe=globalThis.fetch,W=!!globalThis.Proxy,J=n=>{let{value:e}=n;try{switch(n.kind.toLowerCase()){case"int":case"number":e=Number(e);break;case"boolean":e=e.toString().toLowerCase()==="true";break;case"json":e=JSON.parse(e);break}}catch(a){I(a)}return e},dt=(n,e,a)=>{let r=!1,s,l,g,R,y,u,C=!0,A={},x=j(t=>t),Y=0,z=!1,L=()=>{C=!1},m=()=>{C=!0},T=[],d=Pe(),v=ae(a),b=(t,...i)=>{v.debug&&console.debug(`[FF-SDK] ${t}`,...i)},M=t=>{if(C){let i=Date.now();i-t.lastAccessed>Fe&&(t.count++,t.lastAccessed=i)}},ue=()=>h(void 0,null,function*(){if(v.cache){b("initializing cache");try{let t=!0,i=yield se(e.identifier+n,typeof v.cache=="boolean"?{}:v.cache),c=yield i.loadFromCache();c!=null&&c.length&&K(()=>{b("loading from cache",c),ee(c,!1),d.emit("cache loaded",c)}),B("flags loaded",f=>h(void 0,null,function*(){yield i.saveToCache(f),t=!1})),B("changed",f=>h(void 0,null,function*(){t||(f.deleted?yield i.removeCachedEvaluation(f.flag):yield i.updateCachedEvaluation(f))}))}catch(t){I("Cache error: ",t),d.emit("cache error",t),d.emit("error",t)}}}),de=(t,i)=>h(void 0,null,function*(){return(yield(yield xe(`${i.baseUrl}/client/auth`,{method:"POST",headers:{"Content-Type":"application/json","Harness-SDK-Info":le},body:JSON.stringify({apiKey:t,target:$(O({},e),{identifier:String(e.identifier)})})})).json()).authToken}),H=0,G=()=>{if(T.length){b("Sending metrics...",{metrics:T,evaluations:S});let t={metricsData:T.map(i=>({timestamp:Date.now(),count:i.count,metricsType:"FFMETRICS",attributes:[{key:"featureIdentifier",value:i.featureIdentifier},{key:"featureName",value:i.featureIdentifier},{key:"variationIdentifier",value:i.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:ce}]}))};x(`${v.eventUrl}/metrics/${s}?cluster=${l}`,{method:"POST",headers:O({"Content-Type":"application/json"},A),body:JSON.stringify(t)}).then(()=>{T=[],H=0}).catch(i=>{H++&&(T=[],H=0),b(i),d.emit("metrics error",i)}).finally(()=>{u=window.setTimeout(G,v.eventsSyncInterval)})}else u=window.setTimeout(G,v.eventsSyncInterval)},S={},fe=t=>{b("Sending event for",t.flag),W?d.emit("changed",new Proxy(t,{get(i,c){var f;if(C&&i.hasOwnProperty(c)&&c==="value"){let p=i.flag,o=t.value,E=T.find(P=>P.featureIdentifier===p&&P.featureValue===o);E?(M(E),E.variationIdentifier=((f=S[p])==null?void 0:f.identifier)||""):T.push({featureIdentifier:p,featureValue:String(o),variationIdentifier:S[p].identifier||"",count:1,lastAccessed:Date.now()}),b("Metrics event: Flag",c,"has been read with value via stream update",o)}return c==="value"?J(t):t[c]}})):d.emit("changed",{deleted:t.deleted,flag:t.flag,value:J(t)})},X=function(){return W?new Proxy({},{get(t,i){var f,p,o;let c=t[i];if(C&&t.hasOwnProperty(i)){let E=t[i],P=T.find(te=>te.featureIdentifier===i&&E===te.featureValue);P?(P.variationIdentifier=((f=S[i])==null?void 0:f.identifier)||"",M(P)):T.push({featureIdentifier:i,featureValue:E,variationIdentifier:((p=S[i])==null?void 0:p.identifier)||"",count:1,lastAccessed:Date.now()}),b("Metrics event: Flag:",i,"has been read with value:",E,"variationIdentifier:",(o=S[i])==null?void 0:o.identifier)}return c}}):{}},w=X();ue().then(()=>de(n,v).then(t=>h(void 0,null,function*(){if(r)return;y=t;let i=De(t);if(A={Authorization:`Bearer ${y}`,"Harness-AccountID":i.accountID,"Harness-EnvironmentID":i.environmentIdentifier,"Harness-SDK-Info":le},globalThis.btoa){let p=globalThis.btoa(JSON.stringify(e));p.length<262144&&(A["Harness-Target"]=p)}b("Authenticated",i),u=window.setTimeout(G,v.eventsSyncInterval),s=i.environment,l=i.clusterIdentifier;let c=!!Object.keys(S).length;if((yield N()).type==="success"&&b("Fetch all flags ok",w),!r){if(v.streamEnabled?(b("Streaming mode enabled"),ge()):v.pollingEnabled?(b("Polling mode enabled"),he()):b("Streaming and polling mode disabled"),!c){L();let p=O({},w);m(),d.emit("ready",p)}z=!0}})).catch(t=>{I("Authentication error: ",t),d.emit("auth error",t),d.emit("error",t)}));let N=()=>h(void 0,null,function*(){try{let t=yield x(`${v.baseUrl}/client/env/${s}/target/${e.identifier}/evaluations?cluster=${l}`,{headers:A});if(t.ok){let i=yield t.json();return i.forEach(D),d.emit("flags loaded",i),{type:"success",data:i}}else return I("Features fetch operation error: ",t),d.emit("fetch flags error",t),d.emit("error",t),{type:"error",error:t}}catch(t){return I("Features fetch operation error: ",t),d.emit("fetch flags error",t),d.emit("error",t),{type:"error",error:t}}}),Q=t=>h(void 0,null,function*(){try{let i=yield x(`${v.baseUrl}/client/env/${s}/target/${e.identifier}/evaluations/${t}?cluster=${l}`,{headers:A});if(i.ok){let c=yield i.json();D(c)}else I("Feature fetch operation error: ",i),d.emit("fetch flag error",i),d.emit("error",i)}catch(i){I("Feature fetch operation error: ",i),d.emit("fetch flag error",i),d.emit("error",i)}}),D=t=>{L();let i=J(t);i!==w[t.flag]&&(b("Flag variation has changed for ",t.identifier),w[t.flag]=i,S[t.flag]=$(O({},t),{value:i}),fe(t)),m()};R=new F(N,v,d);let ge=()=>{let t=o=>{switch(o.event){case"create":c(o.evaluations)?o.evaluations.forEach(E=>{D(E)}):setTimeout(()=>Q(o.identifier),1e3);break;case"patch":c(o.evaluations)?o.evaluations.forEach(E=>{D(E)}):Q(o.identifier);break;case"delete":delete w[o.identifier],d.emit("changed",{flag:o.identifier,value:void 0,deleted:!0}),b("Evaluation deleted",{message:o,storage:w});break}},i=o=>!(!o||!o.flag||!o.identifier||!o.kind||!o.value),c=o=>!(!o||o.length==0||!o.every(E=>i(E))),f=o=>{o.event==="patch"&&(c(o.evaluations)?o.evaluations.forEach(E=>{D(E)}):N())},p=`${v.baseUrl}/stream?cluster=${l}`;g=new _(d,v,p,n,A,R,o=>{o.domain==="flag"?t(o):o.domain==="target-segment"&&f(o)}),g.start()},he=()=>{R.start()},B=(t,i)=>d.on(t,i),me=(t,i)=>{t?d.off(t,i):Z()},ve=(t,i)=>{var o;if(!C||W||i===void 0)return;let c=i,f=t,p=T.find(E=>E.featureIdentifier===f&&E.featureValue===c);p?(M(p),p.variationIdentifier=((o=S[f])==null?void 0:o.identifier)||""):T.push({featureIdentifier:f,featureValue:c,count:1,variationIdentifier:S[f].identifier||"",lastAccessed:Date.now()})},Z=()=>{r=!0,v.streamEnabled&&(b("Closing event stream"),typeof(g==null?void 0:g.close)=="function"&&g.close(),d.all.clear()),v.pollingEnabled&&R.isPolling()&&(b("Closing Poller"),R.stop()),w=X(),S={},clearTimeout(u)},ee=(t,i=!0)=>{t.length&&K(()=>{let c=!!Object.keys(S).length;if(t.forEach(D),!c){L();let f=O({},w);m(),d.emit("ready",f)}},i)};return{on:B,off:me,close:Z,setEvaluations:ee,registerAPIRequestMiddleware:t=>{x=j(t)},refreshEvaluations:()=>{z&&!r&&Date.now()-Y>=6e4&&(N(),Y=Date.now())},variation:(t,i,c=!1)=>oe(t,i,w,ve,c)}};export{k as Event,dt as initialize}; |
{ | ||
"name": "@harnessio/ff-javascript-client-sdk", | ||
"version": "1.25.0-rc.0", | ||
"version": "1.25.0", | ||
"author": "Harness", | ||
@@ -5,0 +5,0 @@ "license": "Apache-2.0", |
@@ -58,5 +58,4 @@ # Before you Begin | ||
streamEnabled?: boolean | ||
allAttributesPrivate?: boolean | ||
privateAttributeNames?: string[] | ||
debug?: boolean | ||
debug?: boolean, | ||
cache?: boolean | CacheOptions | ||
} | ||
@@ -164,2 +163,6 @@ ``` | ||
client.on(Event.ERROR_CACHE, error => { | ||
// Event happens when an error occurs when accessing the cache | ||
}) | ||
client.on(Event.ERROR_AUTH, error => { | ||
@@ -267,3 +270,7 @@ // Event happens when unable to authenticate | ||
interface CacheOptions { | ||
ttl?: number // maximum age of stored cache, in ms, before it is considered stale | ||
// maximum age of stored cache, in ms, before it is considered stale | ||
ttl?: number | ||
// storage mechanism to use, conforming to the Web Storage API standard, can be either synchronous or asynchronous | ||
// defaults to localStorage | ||
storage?: AsyncStorage | SyncStorage | ||
} | ||
@@ -270,0 +277,0 @@ ``` |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1
333
0
94901
462