@reforge-com/javascript
Advanced tools
| "use strict";var window;(window||={}).reforgeNamespace=(()=>{var h=(e,r)=>()=>(r||e((r={exports:{}}).exports,r),r.exports);var Q=h(z=>{"use strict";Object.defineProperty(z,"__esModule",{value:!0});z.default=Ke;var C,ke=new Uint8Array(16);function Ke(){if(!C&&(C=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!C))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return C(ke)}});var oe=h(R=>{"use strict";Object.defineProperty(R,"__esModule",{value:!0});R.default=void 0;var He=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;R.default=He});var T=h(j=>{"use strict";Object.defineProperty(j,"__esModule",{value:!0});j.default=void 0;var Fe=Be(oe());function Be(e){return e&&e.__esModule?e:{default:e}}function We(e){return typeof e=="string"&&Fe.default.test(e)}var Je=We;j.default=Je});var S=h(A=>{"use strict";Object.defineProperty(A,"__esModule",{value:!0});A.default=void 0;A.unsafeStringify=ae;var Xe=ze(T());function ze(e){return e&&e.__esModule?e:{default:e}}var g=[];for(let e=0;e<256;++e)g.push((e+256).toString(16).slice(1));function ae(e,r=0){return g[e[r+0]]+g[e[r+1]]+g[e[r+2]]+g[e[r+3]]+"-"+g[e[r+4]]+g[e[r+5]]+"-"+g[e[r+6]]+g[e[r+7]]+"-"+g[e[r+8]]+g[e[r+9]]+"-"+g[e[r+10]]+g[e[r+11]]+g[e[r+12]]+g[e[r+13]]+g[e[r+14]]+g[e[r+15]]}function Qe(e,r=0){let t=ae(e,r);if(!(0,Xe.default)(t))throw TypeError("Stringified UUID is invalid");return t}var Ye=Qe;A.default=Ye});var ue=h(M=>{"use strict";Object.defineProperty(M,"__esModule",{value:!0});M.default=void 0;var Ge=et(Q()),Ze=S();function et(e){return e&&e.__esModule?e:{default:e}}var le,Y,G=0,Z=0;function tt(e,r,t){let n=r&&t||0,i=r||new Array(16);e=e||{};let s=e.node||le,o=e.clockseq!==void 0?e.clockseq:Y;if(s==null||o==null){let f=e.random||(e.rng||Ge.default)();s==null&&(s=le=[f[0]|1,f[1],f[2],f[3],f[4],f[5]]),o==null&&(o=Y=(f[6]<<8|f[7])&16383)}let l=e.msecs!==void 0?e.msecs:Date.now(),a=e.nsecs!==void 0?e.nsecs:Z+1,u=l-G+(a-Z)/1e4;if(u<0&&e.clockseq===void 0&&(o=o+1&16383),(u<0||l>G)&&e.nsecs===void 0&&(a=0),a>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");G=l,Z=a,Y=o,l+=122192928e5;let c=((l&268435455)*1e4+a)%4294967296;i[n++]=c>>>24&255,i[n++]=c>>>16&255,i[n++]=c>>>8&255,i[n++]=c&255;let y=l/4294967296*1e4&268435455;i[n++]=y>>>8&255,i[n++]=y&255,i[n++]=y>>>24&15|16,i[n++]=y>>>16&255,i[n++]=o>>>8|128,i[n++]=o&255;for(let f=0;f<6;++f)i[n+f]=s[f];return r||(0,Ze.unsafeStringify)(i)}var rt=tt;M.default=rt});var ee=h(U=>{"use strict";Object.defineProperty(U,"__esModule",{value:!0});U.default=void 0;var nt=it(T());function it(e){return e&&e.__esModule?e:{default:e}}function st(e){if(!(0,nt.default)(e))throw TypeError("Invalid UUID");let r,t=new Uint8Array(16);return t[0]=(r=parseInt(e.slice(0,8),16))>>>24,t[1]=r>>>16&255,t[2]=r>>>8&255,t[3]=r&255,t[4]=(r=parseInt(e.slice(9,13),16))>>>8,t[5]=r&255,t[6]=(r=parseInt(e.slice(14,18),16))>>>8,t[7]=r&255,t[8]=(r=parseInt(e.slice(19,23),16))>>>8,t[9]=r&255,t[10]=(r=parseInt(e.slice(24,36),16))/1099511627776&255,t[11]=r/4294967296&255,t[12]=r>>>24&255,t[13]=r>>>16&255,t[14]=r>>>8&255,t[15]=r&255,t}var ot=st;U.default=ot});var te=h(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.URL=O.DNS=void 0;O.default=ft;var at=S(),lt=ut(ee());function ut(e){return e&&e.__esModule?e:{default:e}}function ct(e){e=unescape(encodeURIComponent(e));let r=[];for(let t=0;t<e.length;++t)r.push(e.charCodeAt(t));return r}var ce="6ba7b810-9dad-11d1-80b4-00c04fd430c8";O.DNS=ce;var fe="6ba7b811-9dad-11d1-80b4-00c04fd430c8";O.URL=fe;function ft(e,r,t){function n(i,s,o,l){var a;if(typeof i=="string"&&(i=ct(i)),typeof s=="string"&&(s=(0,lt.default)(s)),((a=s)===null||a===void 0?void 0:a.length)!==16)throw TypeError("Namespace must be array-like (16 iterable integer values, 0-255)");let u=new Uint8Array(16+i.length);if(u.set(s),u.set(i,s.length),u=t(u),u[6]=u[6]&15|r,u[8]=u[8]&63|128,o){l=l||0;for(let c=0;c<16;++c)o[l+c]=u[c];return o}return(0,at.unsafeStringify)(u)}try{n.name=e}catch{}return n.DNS=ce,n.URL=fe,n}});var he=h(q=>{"use strict";Object.defineProperty(q,"__esModule",{value:!0});q.default=void 0;function dt(e){if(typeof e=="string"){let r=unescape(encodeURIComponent(e));e=new Uint8Array(r.length);for(let t=0;t<r.length;++t)e[t]=r.charCodeAt(t)}return ht(gt(pt(e),e.length*8))}function ht(e){let r=[],t=e.length*32,n="0123456789abcdef";for(let i=0;i<t;i+=8){let s=e[i>>5]>>>i%32&255,o=parseInt(n.charAt(s>>>4&15)+n.charAt(s&15),16);r.push(o)}return r}function de(e){return(e+64>>>9<<4)+14+1}function gt(e,r){e[r>>5]|=128<<r%32,e[de(r)-1]=r;let t=1732584193,n=-271733879,i=-1732584194,s=271733878;for(let o=0;o<e.length;o+=16){let l=t,a=n,u=i,c=s;t=p(t,n,i,s,e[o],7,-680876936),s=p(s,t,n,i,e[o+1],12,-389564586),i=p(i,s,t,n,e[o+2],17,606105819),n=p(n,i,s,t,e[o+3],22,-1044525330),t=p(t,n,i,s,e[o+4],7,-176418897),s=p(s,t,n,i,e[o+5],12,1200080426),i=p(i,s,t,n,e[o+6],17,-1473231341),n=p(n,i,s,t,e[o+7],22,-45705983),t=p(t,n,i,s,e[o+8],7,1770035416),s=p(s,t,n,i,e[o+9],12,-1958414417),i=p(i,s,t,n,e[o+10],17,-42063),n=p(n,i,s,t,e[o+11],22,-1990404162),t=p(t,n,i,s,e[o+12],7,1804603682),s=p(s,t,n,i,e[o+13],12,-40341101),i=p(i,s,t,n,e[o+14],17,-1502002290),n=p(n,i,s,t,e[o+15],22,1236535329),t=v(t,n,i,s,e[o+1],5,-165796510),s=v(s,t,n,i,e[o+6],9,-1069501632),i=v(i,s,t,n,e[o+11],14,643717713),n=v(n,i,s,t,e[o],20,-373897302),t=v(t,n,i,s,e[o+5],5,-701558691),s=v(s,t,n,i,e[o+10],9,38016083),i=v(i,s,t,n,e[o+15],14,-660478335),n=v(n,i,s,t,e[o+4],20,-405537848),t=v(t,n,i,s,e[o+9],5,568446438),s=v(s,t,n,i,e[o+14],9,-1019803690),i=v(i,s,t,n,e[o+3],14,-187363961),n=v(n,i,s,t,e[o+8],20,1163531501),t=v(t,n,i,s,e[o+13],5,-1444681467),s=v(s,t,n,i,e[o+2],9,-51403784),i=v(i,s,t,n,e[o+7],14,1735328473),n=v(n,i,s,t,e[o+12],20,-1926607734),t=m(t,n,i,s,e[o+5],4,-378558),s=m(s,t,n,i,e[o+8],11,-2022574463),i=m(i,s,t,n,e[o+11],16,1839030562),n=m(n,i,s,t,e[o+14],23,-35309556),t=m(t,n,i,s,e[o+1],4,-1530992060),s=m(s,t,n,i,e[o+4],11,1272893353),i=m(i,s,t,n,e[o+7],16,-155497632),n=m(n,i,s,t,e[o+10],23,-1094730640),t=m(t,n,i,s,e[o+13],4,681279174),s=m(s,t,n,i,e[o],11,-358537222),i=m(i,s,t,n,e[o+3],16,-722521979),n=m(n,i,s,t,e[o+6],23,76029189),t=m(t,n,i,s,e[o+9],4,-640364487),s=m(s,t,n,i,e[o+12],11,-421815835),i=m(i,s,t,n,e[o+15],16,530742520),n=m(n,i,s,t,e[o+2],23,-995338651),t=_(t,n,i,s,e[o],6,-198630844),s=_(s,t,n,i,e[o+7],10,1126891415),i=_(i,s,t,n,e[o+14],15,-1416354905),n=_(n,i,s,t,e[o+5],21,-57434055),t=_(t,n,i,s,e[o+12],6,1700485571),s=_(s,t,n,i,e[o+3],10,-1894986606),i=_(i,s,t,n,e[o+10],15,-1051523),n=_(n,i,s,t,e[o+1],21,-2054922799),t=_(t,n,i,s,e[o+8],6,1873313359),s=_(s,t,n,i,e[o+15],10,-30611744),i=_(i,s,t,n,e[o+6],15,-1560198380),n=_(n,i,s,t,e[o+13],21,1309151649),t=_(t,n,i,s,e[o+4],6,-145523070),s=_(s,t,n,i,e[o+11],10,-1120210379),i=_(i,s,t,n,e[o+2],15,718787259),n=_(n,i,s,t,e[o+9],21,-343485551),t=x(t,l),n=x(n,a),i=x(i,u),s=x(s,c)}return[t,n,i,s]}function pt(e){if(e.length===0)return[];let r=e.length*8,t=new Uint32Array(de(r));for(let n=0;n<r;n+=8)t[n>>5]|=(e[n/8]&255)<<n%32;return t}function x(e,r){let t=(e&65535)+(r&65535);return(e>>16)+(r>>16)+(t>>16)<<16|t&65535}function vt(e,r){return e<<r|e>>>32-r}function D(e,r,t,n,i,s){return x(vt(x(x(r,e),x(n,s)),i),t)}function p(e,r,t,n,i,s,o){return D(r&t|~r&n,e,r,i,s,o)}function v(e,r,t,n,i,s,o){return D(r&n|t&~n,e,r,i,s,o)}function m(e,r,t,n,i,s,o){return D(r^t^n,e,r,i,s,o)}function _(e,r,t,n,i,s,o){return D(t^(r|~n),e,r,i,s,o)}var mt=dt;q.default=mt});var pe=h(N=>{"use strict";Object.defineProperty(N,"__esModule",{value:!0});N.default=void 0;var _t=ge(te()),yt=ge(he());function ge(e){return e&&e.__esModule?e:{default:e}}var wt=(0,_t.default)("v3",48,yt.default),bt=wt;N.default=bt});var ve=h(L=>{"use strict";Object.defineProperty(L,"__esModule",{value:!0});L.default=void 0;var xt=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto),Ot={randomUUID:xt};L.default=Ot});var ye=h(V=>{"use strict";Object.defineProperty(V,"__esModule",{value:!0});V.default=void 0;var me=_e(ve()),Et=_e(Q()),Pt=S();function _e(e){return e&&e.__esModule?e:{default:e}}function Tt(e,r,t){if(me.default.randomUUID&&!r&&!e)return me.default.randomUUID();e=e||{};let n=e.random||(e.rng||Et.default)();if(n[6]=n[6]&15|64,n[8]=n[8]&63|128,r){t=t||0;for(let i=0;i<16;++i)r[t+i]=n[i];return r}return(0,Pt.unsafeStringify)(n)}var At=Tt;V.default=At});var we=h($=>{"use strict";Object.defineProperty($,"__esModule",{value:!0});$.default=void 0;function St(e,r,t,n){switch(e){case 0:return r&t^~r&n;case 1:return r^t^n;case 2:return r&t^r&n^t&n;case 3:return r^t^n}}function re(e,r){return e<<r|e>>>32-r}function It(e){let r=[1518500249,1859775393,2400959708,3395469782],t=[1732584193,4023233417,2562383102,271733878,3285377520];if(typeof e=="string"){let o=unescape(encodeURIComponent(e));e=[];for(let l=0;l<o.length;++l)e.push(o.charCodeAt(l))}else Array.isArray(e)||(e=Array.prototype.slice.call(e));e.push(128);let n=e.length/4+2,i=Math.ceil(n/16),s=new Array(i);for(let o=0;o<i;++o){let l=new Uint32Array(16);for(let a=0;a<16;++a)l[a]=e[o*64+a*4]<<24|e[o*64+a*4+1]<<16|e[o*64+a*4+2]<<8|e[o*64+a*4+3];s[o]=l}s[i-1][14]=(e.length-1)*8/Math.pow(2,32),s[i-1][14]=Math.floor(s[i-1][14]),s[i-1][15]=(e.length-1)*8&4294967295;for(let o=0;o<i;++o){let l=new Uint32Array(80);for(let d=0;d<16;++d)l[d]=s[o][d];for(let d=16;d<80;++d)l[d]=re(l[d-3]^l[d-8]^l[d-14]^l[d-16],1);let a=t[0],u=t[1],c=t[2],y=t[3],f=t[4];for(let d=0;d<80;++d){let P=Math.floor(d/20),I=re(a,5)+St(P,u,c,y)+f+r[P]+l[d]>>>0;f=y,y=c,c=re(u,30)>>>0,u=a,a=I}t[0]=t[0]+a>>>0,t[1]=t[1]+u>>>0,t[2]=t[2]+c>>>0,t[3]=t[3]+y>>>0,t[4]=t[4]+f>>>0}return[t[0]>>24&255,t[0]>>16&255,t[0]>>8&255,t[0]&255,t[1]>>24&255,t[1]>>16&255,t[1]>>8&255,t[1]&255,t[2]>>24&255,t[2]>>16&255,t[2]>>8&255,t[2]&255,t[3]>>24&255,t[3]>>16&255,t[3]>>8&255,t[3]&255,t[4]>>24&255,t[4]>>16&255,t[4]>>8&255,t[4]&255]}var Ct=It;$.default=Ct});var xe=h(k=>{"use strict";Object.defineProperty(k,"__esModule",{value:!0});k.default=void 0;var Rt=be(te()),jt=be(we());function be(e){return e&&e.__esModule?e:{default:e}}var Mt=(0,Rt.default)("v5",80,jt.default),Ut=Mt;k.default=Ut});var Oe=h(K=>{"use strict";Object.defineProperty(K,"__esModule",{value:!0});K.default=void 0;var Dt="00000000-0000-0000-0000-000000000000";K.default=Dt});var Ee=h(H=>{"use strict";Object.defineProperty(H,"__esModule",{value:!0});H.default=void 0;var qt=Nt(T());function Nt(e){return e&&e.__esModule?e:{default:e}}function Lt(e){if(!(0,qt.default)(e))throw TypeError("Invalid UUID");return parseInt(e.slice(14,15),16)}var Vt=Lt;H.default=Vt});var Pe=h(w=>{"use strict";Object.defineProperty(w,"__esModule",{value:!0});Object.defineProperty(w,"NIL",{enumerable:!0,get:function(){return Ft.default}});Object.defineProperty(w,"parse",{enumerable:!0,get:function(){return Xt.default}});Object.defineProperty(w,"stringify",{enumerable:!0,get:function(){return Jt.default}});Object.defineProperty(w,"v1",{enumerable:!0,get:function(){return $t.default}});Object.defineProperty(w,"v3",{enumerable:!0,get:function(){return kt.default}});Object.defineProperty(w,"v4",{enumerable:!0,get:function(){return Kt.default}});Object.defineProperty(w,"v5",{enumerable:!0,get:function(){return Ht.default}});Object.defineProperty(w,"validate",{enumerable:!0,get:function(){return Wt.default}});Object.defineProperty(w,"version",{enumerable:!0,get:function(){return Bt.default}});var $t=b(ue()),kt=b(pe()),Kt=b(ye()),Ht=b(xe()),Ft=b(Oe()),Bt=b(Ee()),Wt=b(T()),Jt=b(S()),Xt=b(ee());function b(e){return e&&e.__esModule?e:{default:e}}});var Pr=h((Hr,$e)=>{var J=Object.defineProperty,zt=Object.defineProperties,Qt=Object.getOwnPropertyDescriptor,Yt=Object.getOwnPropertyDescriptors,Ae=Object.getOwnPropertyNames,B=Object.getOwnPropertySymbols,se=Object.prototype.hasOwnProperty,Se=Object.prototype.propertyIsEnumerable,Te=(e,r,t)=>r in e?J(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t,E=(e,r)=>{for(var t in r||(r={}))se.call(r,t)&&Te(e,t,r[t]);if(B)for(var t of B(r))Se.call(r,t)&&Te(e,t,r[t]);return e},W=(e,r)=>zt(e,Yt(r)),Gt=(e,r)=>{var t={};for(var n in e)se.call(e,n)&&r.indexOf(n)<0&&(t[n]=e[n]);if(e!=null&&B)for(var n of B(e))r.indexOf(n)<0&&Se.call(e,n)&&(t[n]=e[n]);return t},Zt=(e,r)=>function(){return r||(0,e[Ae(e)[0]])((r={exports:{}}).exports,r),r.exports},er=(e,r)=>{for(var t in r)J(e,t,{get:r[t],enumerable:!0})},tr=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let i of Ae(r))!se.call(e,i)&&i!==t&&J(e,i,{get:()=>r[i],enumerable:!(n=Qt(r,i))||n.enumerable});return e},rr=e=>tr(J({},"__esModule",{value:!0}),e),F=(e,r,t)=>new Promise((n,i)=>{var s=a=>{try{l(t.next(a))}catch(u){i(u)}},o=a=>{try{l(t.throw(a))}catch(u){i(u)}},l=a=>a.done?n(a.value):Promise.resolve(a.value).then(s,o);l((t=t.apply(e,r)).next())}),Ie=Zt({"package.json"(e,r){r.exports={packageManager:"yarn@4.9.2",name:"@reforge-com/javascript",version:"0.0.2",description:"Feature Flags & Dynamic Configuration as a Service",main:"dist/index.cjs",module:"dist/index.mjs",types:"dist/index.d.ts",author:"Jeffrey Chupp",license:"ISC",devDependencies:{"@types/eslint-plugin-jsx-a11y":"^6","@types/express":"^4.17.13","@types/jest":"^28.1.6","@types/uuid":"^9.0.5","@typescript-eslint/eslint-plugin":"^5.33.0","@typescript-eslint/parser":"^5.33.0",esbuild:"^0.25.11",eslint:"^8.21.0","eslint-config-airbnb":"^19.0.4","eslint-config-airbnb-typescript":"^17.0.0","eslint-config-prettier":"^8.8.0","eslint-plugin-import":"^2.26.0","eslint-plugin-jest":"^26.8.0","eslint-plugin-jsx-a11y":"^6.10.2","eslint-plugin-react":"^7.37.5",jest:"^29.0.0","jest-fetch-mock":"^3.0.3",prettier:"^3.0.0","ts-jest":"^29.1.1","ts-node":"^10.9.1",tsup:"^8.0.2",typescript:"^5.1.6"},scripts:{build:"rm -rf dist/ && tsup",dev:"tsup --watch",bundle:"esbuild --minify --target=esnext --bundle --outfile=dist/reforge.bundle.js --global-name=window.reforgeNamespace dist/index.cjs && echo 'window.reforge = window.reforgeNamespace.reforge' >> dist/reforge.bundle.js",lint:"eslint --ext .ts,.tsx src/","lint:fix":"eslint --fix --ext .ts,.tsx src/",prettier:"prettier . -l","prettier:fix":"prettier --write .",test:"jest --verbose"},repository:{type:"git",url:"https://github.com/ReforgeHQ/sdk-javascript.git"},keywords:["feature-flags","config"],bugs:{url:"https://github.com/ReforgeHQ/sdk-javascript/issues"},homepage:"https://github.com/ReforgeHQ/sdk-javascript#readme",dependencies:{uuid:"^9.0.1"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.mjs",require:"./dist/index.cjs"}}}}}),Ce={};er(Ce,{Config:()=>X,Context:()=>ne,Reforge:()=>Ve,reforge:()=>Or,version:()=>Er});$e.exports=rr(Ce);var nr=Pe(),ir=e=>({configRowIndex:parseInt(e.configRowIndex,10),conditionalValueIndex:parseInt(e.conditionalValueIndex,10),type:e.type,configId:e.id}),Re=(e,r,t)=>{let n=e[r];switch(r){case"json":try{return JSON.parse(n)}catch(i){return console.error(`Error parsing JSON from Reforge config ${t}`,i,n),e[r]}case"duration":{let i=n;return{ms:i.millis,seconds:i.millis/1e3}}default:return n}},sr=e=>{let r={};return Object.keys(e.evaluations).forEach(t=>{let n=e.evaluations[t],i=Object.keys(n.value)[0];r[t]=new X(t,Re(n.value,i,t),i,n.value,n.configEvaluationMetadata?ir(n.configEvaluationMetadata):void 0)}),r},or=e=>{let r={};return Object.keys(e).forEach(t=>{let n=typeof e[t];r[t]=new X(t,Re({[n]:e[t]},n,t),n)}),r},X=class{constructor(e,r,t,n,i){this.key=e,this.value=r,this.type=t,this.rawValue=n,this.configEvaluationMetadata=i}static digest(e){return e===void 0&&console.trace("Config.digest called with undefined payload"),"evaluations"in e?sr(e):or(e)}},ar=e=>{if(typeof window<"u"){if(typeof TextEncoder>"u")return window.btoa(e);let r=new TextEncoder().encode(e),t=Array.from(r,n=>String.fromCodePoint(n)).join("");return btoa(t)}return Buffer.from(e).toString("base64")},je=ar,lr=(e,r)=>{let t=Object.keys(e),n=Object.keys(r);return t.length!==n.length?!1:t.every(i=>{let s=e[i],o=r[i],l=Object.keys(s),a=Object.keys(o);return l.length!==a.length?!1:l.every(u=>{let c=s[u],y=o[u];return c===y})})},ur=e=>typeof e=="string"?"string":typeof e=="number"?Number.isInteger(e)?"int":"double":"bool",ne=class{constructor(e){Object.values(e).every(r=>typeof r=="object")||console.error("Context must be an object where the value of each key is also an object"),Object.values(e).some(r=>Object.values(r).some(t=>typeof t=="object"&&t!==null))&&console.error("Nested objects are not supported in context values at this time"),this.contexts=e}equals(e){return lr(this.contexts,e.contexts)}encode(){let e=Object.keys(this.contexts).map(r=>{let t={};return Object.keys(this.contexts[r]).forEach(n=>{t[n]={[ur(this.contexts[r][n])]:this.contexts[r][n]}}),{type:r,values:t}});return encodeURIComponent(je(JSON.stringify({contexts:e})))}},cr=class{constructor(e,r=2,t=2){this.maxDelay=e,this.multiplier=t,this.delay=r}call(){let e=this.delay;return this.delay=Math.min(this.delay*this.multiplier,this.maxDelay),e*1e3}},ie="log-level",fr={TRACE:1,DEBUG:2,INFO:3,WARN:4,ERROR:5,FATAL:6},dr=({loggerName:e,desiredLevel:r,defaultLevel:t,get:n})=>{let i=`${ie}.${e}`;for(;i.length>0;){let s=n(i);if(s)return fr[s.toString().toUpperCase()]<=r;if(i.indexOf(".")===-1)break;i=i.slice(0,i.lastIndexOf("."))}return t<=r},Me=class Ue{constructor(r,t,n){this.data=new Map,this.client=r,this.name=t,this.startAt=new Date,this.startPeriodicSync(n)}stop(){clearTimeout(this.timeoutID)}sync(){if(this.data.size===0)return;this.logInternal(`${this.name} syncing ${this.data.size} items`);let r=this.startAt;this.startAt=new Date,this.flush(this.prepareData(),r)}prepareData(){let r=new Map(this.data);return this.data.clear(),r}startPeriodicSync(r){this.startAt=new Date,this.syncInterval=Ue.calculateSyncInterval(r),this.scheduleNextSync()}scheduleNextSync(){let r=this.syncInterval();this.timeoutID=setTimeout(()=>{this.sync(),this.scheduleNextSync()},r)}static calculateSyncInterval(r){if(r!==void 0)return()=>r;let t=new cr(300,8);return()=>t.call()}logInternal(r){let t=`${this.client.clientNameString}.reforge.${this.name}`;this.client.shouldLog({loggerName:t,desiredLevel:2,defaultLevel:5},!1)&&console.log(`${t}: ${r}`)}},hr=e=>e.rawValue&&(e.type==="duration"||e.type==="json")?e.type==="json"?{json:e.rawValue[e.type]}:e.rawValue[e.type]:e.type==="stringList"?{values:e.value}:e.value,gr=(e,r)=>W(E({},r),{selectedValue:{[e.type]:hr(e)},count:0}),pr=class De extends Me{constructor(r,t,n){super(r,"EvaluationSummaryAggregator",n??3e4),this.maxKeys=t}record(r){if(!(this.data.size>=this.maxKeys)&&r?.configEvaluationMetadata){let t=r.configEvaluationMetadata,{type:n}=t,i=Gt(t,["type"]),s=`${r.key},${n}`;this.data.has(s)||this.data.set(s,gr(r,i));let o=this.data.get(s);o&&(o.count+=1)}}flush(r,t){var n;let i={start:t.getTime(),end:new Date().getTime(),summaries:De.summaries(r)};(n=this.client.telemetryUploader)==null||n.post(this.events(i))}static summaries(r){return Array.from(r).map(t=>{let[n,i]=t[0].split(","),o=[t[1]];return{key:n,type:i,counters:o}})}events(r){let t={summaries:r};return{instanceHash:this.client.instanceHash,events:[t]}}},qe=(e,r)=>({Authorization:`Basic ${je(`u:${e}`)}`,"X-Reforge-SDK-Version":r}),Ne=1e4,vr=["https://primary.reforge.com/api/v2","https://secondary.reforge.com/api/v2"],mr=2e3,_r=class{constructor({sdkKey:e,context:r,endpoints:t=void 0,timeout:n,collectContextMode:i="PERIODIC_EXAMPLE",clientVersion:s=""}){this.collectContextMode="PERIODIC_EXAMPLE",this.isAborted=!1,this.sdkKey=e,this.context=r,this.endpoints=t||vr,this.timeout=n||Ne,this.collectContextMode=i,this.clientVersion=s}url(e){return`${e}/configs/eval-with-context/${this.context.encode()}?collectContextMode=${this.collectContextMode}`}loadFromEndpoint(e,r,t,n){this.abortController=new AbortController;let{signal:i}=this.abortController;this.isAborted=!1;let s=this.endpoints[e],o=this.url(s);fetch(o,E({signal:i},r)).then(a=>{if(this.clearAbortTimeout(),a.ok)return a.json();throw new Error(`${a.status} ${a.statusText}`)}).then(a=>{if(!("evaluations"in a))throw new Error(`Invalid payload:${JSON.stringify(a)}`);t(a)}).catch(a=>{this.clearAbortTimeout(),e<this.endpoints.length-1?this.loadFromEndpoint(e+1,r,t,n):n(a)});let l=e<this.endpoints.length-1?Math.min(this.timeout,mr):this.timeout;this.abortTimeoutId=setTimeout(()=>{var a;this.isAborted||(this.isAborted=!0,(a=this.abortController)==null||a.abort())},l)}load(){var e;this.isAborted||(this.isAborted=!0,(e=this.abortController)==null||e.abort());let r={headers:qe(this.sdkKey,this.clientVersion)};return new Promise((n,i)=>{this.loadFromEndpoint(0,r,n,i)})}clearAbortTimeout(){clearTimeout(this.abortTimeoutId)}},yr=class Le{constructor({sdkKey:r,apiEndpoint:t=void 0,timeout:n,clientVersion:i}){this.sdkKey=r,this.apiEndpoint=t||"https://telemetry.prefab.cloud/api/v1",this.timeout=n||Ne,this.clientVersion=i}clearAbortTimeout(){clearTimeout(this.abortTimeoutId)}static postUrl(r){return`${r}/telemetry`}postToEndpoint(r,t,n){let i=new AbortController,s=i?.signal,o=!1,l=Le.postUrl(this.apiEndpoint);fetch(l,E({signal:s},r)).then(a=>(this.clearAbortTimeout(),a.ok?a.json():(console.warn(`Reforge warning: Error uploading telemetry ${a.status} ${a.statusText}`),a.status))).then(a=>{t(a)}).catch(a=>{if(this.clearAbortTimeout(),a.name==="AbortError"){try{console.debug("Reforge telemetry request aborted")}catch{}t({status:"aborted"});return}n(a)}),this.abortTimeoutId=setTimeout(()=>{o||(o=!0,i.abort())},this.timeout)}post(r){let t={method:"POST",headers:W(E({},qe(this.sdkKey,this.clientVersion)),{"Content-Type":"application/json",Accept:"application/json"}),body:JSON.stringify(r),keepalive:!0};return new Promise((i,s)=>{this.postToEndpoint(t,i,s)})}},wr={1:"traces",2:"debugs",3:"infos",4:"warns",5:"errors",6:"fatals"},br=class extends Me{constructor(e,r,t){super(e,"LoggerAggregator",t??3e4),this.maxLoggers=r}record(e,r){if(this.data.size>=this.maxLoggers)return;this.data.has(e)||this.data.set(e,{loggerName:e,traces:0,debugs:0,infos:0,warns:0,errors:0,fatals:0});let t=this.data.get(e);if(t){let n=wr[r];t[n]+=1}}flush(e,r){var t;let n={startAt:r.getTime(),endAt:new Date().getTime(),loggers:Array.from(e.values())};(t=this.client.telemetryUploader)==null||t.post(this.events(n))}events(e){let r={loggers:e};return{instanceHash:this.client.instanceHash,events:[r]}}},{version:xr}=Ie(),Ve=class{constructor(){this._configs={},this._pollCount=0,this._pollStatus={status:"not-started"},this._pollTimeoutId=void 0,this._instanceHash=(0,nr.v4)(),this.collectEvaluationSummaries=!0,this.collectLoggerNames=!1,this.clientNameString="sdk-javascript",this.loaded=!1,this.afterEvaluationCallback=(()=>{}),this._context=new ne({})}init(e){return F(this,arguments,function*({sdkKey:r,context:t,endpoints:n=void 0,apiEndpoint:i,timeout:s=void 0,afterEvaluationCallback:o=()=>{},collectEvaluationSummaries:l=!0,collectLoggerNames:a=!1,collectContextMode:u="PERIODIC_EXAMPLE",clientNameString:c="sdk-javascript",clientVersionString:y=xr}){let f=t??this.context;if(!f)throw new Error("Context must be provided");this._context=f,this.clientNameString=c;let d=`${c}-${y}`;return this.loader=new _r({sdkKey:r,context:f,endpoints:n,timeout:s,collectContextMode:u,clientVersion:d}),this._telemetryUploader=new yr({sdkKey:r,apiEndpoint:i,timeout:s,clientVersion:d}),this.collectEvaluationSummaries=l,l&&(this.evalutionSummaryAggregator=new pr(this,1e5)),this.collectLoggerNames=a,a&&(this.loggerAggregator=new br(this,1e5)),(l||a)&&typeof window<"u"&&typeof window.addEventListener=="function"&&window.addEventListener("beforeunload",()=>{var P,I;(P=this.evalutionSummaryAggregator)==null||P.sync(),(I=this.loggerAggregator)==null||I.sync()}),this.afterEvaluationCallback=o,this.load()})}extract(){return Object.entries(this._configs).reduce((e,[r,t])=>W(E({},e),{[r]:t.value}),{})}hydrate(e){this.setConfigPrivate(e)}get context(){return this._context}get instanceHash(){return this._instanceHash}get pollTimeoutId(){return this._pollTimeoutId}get pollCount(){return this._pollCount}get pollStatus(){return this._pollStatus}get telemetryUploader(){return this._telemetryUploader}load(){return F(this,null,function*(){if(!this.loader||!this.context)throw new Error("Reforge not initialized. Call init() first.");if(globalThis&&globalThis._reforgeBootstrap){let e=globalThis._reforgeBootstrap,r=new ne(e.context);if(this.context.equals(r))return this.setConfigPrivate({evaluations:e.evaluations}),Promise.resolve()}return this.loader.context=this.context,this.loader.load().then(e=>{this.setConfigPrivate(e)}).finally(()=>{this.pollStatus.status==="running"&&(this._pollCount+=1)})})}updateContext(e,r=!1){return F(this,null,function*(){if(!this.loader)throw new Error("Reforge not initialized. Call init() first.");return this._context=e,r?Promise.resolve():this.load()})}poll(e){return F(this,arguments,function*({frequencyInMs:r}){if(!this.loader)throw new Error("Reforge not initialized. Call init() first.");return this.stopPolling(),this._pollStatus={status:"pending"},this.loader.load().finally(()=>{this.doPolling({frequencyInMs:r})})})}doPolling({frequencyInMs:e}){this._pollTimeoutId=setTimeout(()=>{this.load().finally(()=>{this.pollStatus.status==="running"&&this.doPolling({frequencyInMs:e})})},e),this._pollStatus={status:"running",frequencyInMs:e}}stopPolling(){this.pollTimeoutId&&(clearTimeout(this.pollTimeoutId),this._pollTimeoutId=void 0),this._pollStatus={status:"stopped"}}stopTelemetry(){var e,r;this.telemetryUploader&&((e=this.evalutionSummaryAggregator)==null||e.stop(),(r=this.loggerAggregator)==null||r.stop())}setConfigPrivate(e){this._configs=X.digest(e),this.loaded=!0}isEnabled(e){return this.get(e)===!0}get(e){if(!this.loaded){e.startsWith(ie)||console.warn(`Reforge warning: The client has not finished loading data yet. Unable to look up actual value for key "${e}".`);return}let r=this._configs[e],t=r?.value;return e.startsWith(ie)||(this.collectEvaluationSummaries&&setTimeout(()=>{var n;return(n=this.evalutionSummaryAggregator)==null?void 0:n.record(r)}),setTimeout(()=>this.afterEvaluationCallback(e,t,this.context))),t}getDuration(e){let r=this.get(e);if(r){if(!Object.prototype.hasOwnProperty.call(r,"seconds")||!Object.prototype.hasOwnProperty.call(r,"ms"))throw new Error(`Value for key "${e}" is not a duration`);return r}}shouldLog(e,r=!0){if(this.collectLoggerNames){let t=()=>{var n;return(n=this.loggerAggregator)==null?void 0:n.record(e.loggerName,e.desiredLevel)};r?setTimeout(t):t()}return dr(W(E({},e),{get:this.get.bind(this)}))}isCollectingEvaluationSummaries(){return this.collectEvaluationSummaries}isCollectingLoggerNames(){return this.collectLoggerNames}},Or=new Ve,{version:Er}=Ie()});return Pr();})(); | ||
| window.reforge = window.reforgeNamespace.reforge |
+4
-0
| # Changelog | ||
| ## 0.0.2 - 2025-10-30 | ||
| - fix: include the dist/reforge.bundle.js in our published NPM package | ||
| ## 0.0.1 - 2025-10-01 | ||
@@ -4,0 +8,0 @@ |
+2
-1
@@ -78,3 +78,3 @@ "use strict"; | ||
| name: "@reforge-com/javascript", | ||
| version: "0.0.1", | ||
| version: "0.0.2", | ||
| description: "Feature Flags & Dynamic Configuration as a Service", | ||
@@ -93,2 +93,3 @@ main: "dist/index.cjs", | ||
| "@typescript-eslint/parser": "^5.33.0", | ||
| esbuild: "^0.25.11", | ||
| eslint: "^8.21.0", | ||
@@ -95,0 +96,0 @@ "eslint-config-airbnb": "^19.0.4", |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../package.json","../index.ts","../src/reforge.ts","../src/config.ts","../src/base64Encode.ts","../src/context.ts","../src/exponentialBackoff.ts","../src/logger.ts","../src/periodicSync.ts","../src/evaluationSummaryAggregator.ts","../src/apiHelpers.ts","../src/loader.ts","../src/telemetryUploader.ts","../src/loggerAggregator.ts"],"sourcesContent":["{\n \"packageManager\": \"yarn@4.9.2\",\n \"name\": \"@reforge-com/javascript\",\n \"version\": \"0.0.1\",\n \"description\": \"Feature Flags & Dynamic Configuration as a Service\",\n \"main\": \"dist/index.cjs\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"author\": \"Jeffrey Chupp\",\n \"license\": \"ISC\",\n \"devDependencies\": {\n \"@types/eslint-plugin-jsx-a11y\": \"^6\",\n \"@types/express\": \"^4.17.13\",\n \"@types/jest\": \"^28.1.6\",\n \"@types/uuid\": \"^9.0.5\",\n \"@typescript-eslint/eslint-plugin\": \"^5.33.0\",\n \"@typescript-eslint/parser\": \"^5.33.0\",\n \"eslint\": \"^8.21.0\",\n \"eslint-config-airbnb\": \"^19.0.4\",\n \"eslint-config-airbnb-typescript\": \"^17.0.0\",\n \"eslint-config-prettier\": \"^8.8.0\",\n \"eslint-plugin-import\": \"^2.26.0\",\n \"eslint-plugin-jest\": \"^26.8.0\",\n \"eslint-plugin-jsx-a11y\": \"^6.10.2\",\n \"eslint-plugin-react\": \"^7.37.5\",\n \"jest\": \"^29.0.0\",\n \"jest-fetch-mock\": \"^3.0.3\",\n \"prettier\": \"^3.0.0\",\n \"ts-jest\": \"^29.1.1\",\n \"ts-node\": \"^10.9.1\",\n \"tsup\": \"^8.0.2\",\n \"typescript\": \"^5.1.6\"\n },\n \"scripts\": {\n \"build\": \"rm -rf dist/ && tsup\",\n \"dev\": \"tsup --watch\",\n \"bundle\": \"esbuild --minify --target=esnext --bundle --outfile=dist/reforge.bundle.js --global-name=window.reforgeNamespace dist/index.cjs && echo 'window.reforge = window.reforgeNamespace.reforge' >> dist/reforge.bundle.js\",\n \"lint\": \"eslint --ext .ts,.tsx src/\",\n \"lint:fix\": \"eslint --fix --ext .ts,.tsx src/\",\n \"prettier\": \"prettier . -l\",\n \"prettier:fix\": \"prettier --write .\",\n \"test\": \"jest --verbose\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/ReforgeHQ/sdk-javascript.git\"\n },\n \"keywords\": [\n \"feature-flags\",\n \"config\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/ReforgeHQ/sdk-javascript/issues\"\n },\n \"homepage\": \"https://github.com/ReforgeHQ/sdk-javascript#readme\",\n \"dependencies\": {\n \"uuid\": \"^9.0.1\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n }\n }\n}\n","import { reforge, Reforge, ReforgeInitParams, ReforgeBootstrap } from \"./src/reforge\";\nimport { Config } from \"./src/config\";\nimport Context from \"./src/context\";\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { version } = require(\"./package.json\");\n\nexport { reforge, Reforge, ReforgeInitParams, Config, Context, version };\n\nexport { ReforgeBootstrap };\n\nexport type { ConfigValue } from \"./src/config\";\nexport type {\n Duration,\n ContextValue,\n Contexts,\n TypedFrontEndConfigurationRaw,\n FrontEndConfigurationRaw,\n} from \"./src/types\";\nexport type { CollectContextModeType } from \"./src/loader\";\n","import { v4 as uuid } from \"uuid\";\n\nimport { Config, EvaluationPayload, RawConfigWithoutTypes } from \"./config\";\nimport type {\n Duration,\n TypedFrontEndConfigurationRaw,\n FrontEndConfigurationRaw,\n Contexts,\n} from \"./types\";\nimport Context from \"./context\";\nimport { EvaluationSummaryAggregator } from \"./evaluationSummaryAggregator\";\nimport Loader, { CollectContextModeType } from \"./loader\";\nimport { PREFIX as loggerPrefix, shouldLog, ShouldLogParams } from \"./logger\";\nimport TelemetryUploader from \"./telemetryUploader\";\nimport { LoggerAggregator } from \"./loggerAggregator\";\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { version } = require(\"../package.json\");\n\ntype EvaluationCallback = <K extends keyof TypedFrontEndConfigurationRaw>(\n key: K,\n value: TypedFrontEndConfigurationRaw[K],\n context: Context | undefined\n) => void;\n\nexport interface ReforgeBootstrap {\n evaluations: EvaluationPayload;\n context: Contexts;\n}\n\nexport type ReforgeInitParams = {\n sdkKey: string;\n context: Context;\n endpoints?: string[] | undefined;\n apiEndpoint?: string;\n timeout?: number;\n afterEvaluationCallback?: EvaluationCallback;\n collectEvaluationSummaries?: boolean;\n collectLoggerNames?: boolean;\n collectContextMode?: CollectContextModeType;\n clientNameString?: string;\n clientVersionString?: string;\n};\n\ntype PollStatus =\n | { status: \"not-started\" }\n | { status: \"pending\" }\n | { status: \"stopped\" }\n | { status: \"running\"; frequencyInMs: number };\n\ntype PublicShouldLogParams = Omit<ShouldLogParams, \"get\">;\n\nexport class Reforge {\n private _configs: { [key: string]: Config } = {};\n\n private _telemetryUploader: TelemetryUploader | undefined;\n\n private _pollCount = 0;\n\n private _pollStatus: PollStatus = { status: \"not-started\" };\n\n private _pollTimeoutId = undefined as ReturnType<typeof setTimeout> | undefined;\n\n private _instanceHash: string = uuid();\n\n private collectEvaluationSummaries = true;\n\n private collectLoggerNames = false;\n\n private evalutionSummaryAggregator: EvaluationSummaryAggregator | undefined;\n\n private loggerAggregator: LoggerAggregator | undefined;\n\n public clientNameString = \"sdk-javascript\";\n\n public loaded = false;\n\n public loader: Loader | undefined;\n\n public afterEvaluationCallback = (() => {}) as EvaluationCallback;\n\n private _context: Context = new Context({});\n\n async init({\n sdkKey,\n context: providedContext,\n endpoints = undefined,\n apiEndpoint,\n timeout = undefined,\n afterEvaluationCallback = () => {},\n collectEvaluationSummaries = true,\n collectLoggerNames = false,\n collectContextMode = \"PERIODIC_EXAMPLE\",\n clientNameString = \"sdk-javascript\",\n clientVersionString = version,\n }: ReforgeInitParams) {\n const context = providedContext ?? this.context;\n\n if (!context) {\n throw new Error(\"Context must be provided\");\n }\n\n this._context = context;\n\n this.clientNameString = clientNameString;\n const clientNameAndVersionString = `${clientNameString}-${clientVersionString}`;\n\n this.loader = new Loader({\n sdkKey,\n context,\n endpoints,\n timeout,\n collectContextMode,\n clientVersion: clientNameAndVersionString,\n });\n\n this._telemetryUploader = new TelemetryUploader({\n sdkKey,\n apiEndpoint,\n timeout,\n clientVersion: clientNameAndVersionString,\n });\n\n this.collectEvaluationSummaries = collectEvaluationSummaries;\n if (collectEvaluationSummaries) {\n this.evalutionSummaryAggregator = new EvaluationSummaryAggregator(this, 100000);\n }\n\n this.collectLoggerNames = collectLoggerNames;\n if (collectLoggerNames) {\n this.loggerAggregator = new LoggerAggregator(this, 100000);\n }\n\n if (\n (collectEvaluationSummaries || collectLoggerNames) &&\n typeof window !== \"undefined\" &&\n typeof window.addEventListener === \"function\"\n ) {\n window.addEventListener(\"beforeunload\", () => {\n this.evalutionSummaryAggregator?.sync();\n this.loggerAggregator?.sync();\n });\n }\n\n this.afterEvaluationCallback = afterEvaluationCallback;\n\n return this.load();\n }\n\n public extract(): Record<string, Config[\"value\"]> {\n return Object.entries(this._configs).reduce(\n (agg, [key, value]) => ({\n ...agg,\n [key]: value.value,\n }),\n {} as Record<string, Config[\"value\"]>\n );\n }\n\n public hydrate(rawValues: RawConfigWithoutTypes | EvaluationPayload): void {\n this.setConfigPrivate(rawValues);\n }\n\n get context(): Context {\n return this._context;\n }\n\n get instanceHash(): string {\n return this._instanceHash;\n }\n\n get pollTimeoutId() {\n return this._pollTimeoutId;\n }\n\n get pollCount() {\n return this._pollCount;\n }\n\n get pollStatus() {\n return this._pollStatus;\n }\n\n get telemetryUploader(): TelemetryUploader | undefined {\n return this._telemetryUploader;\n }\n\n private async load() {\n if (!this.loader || !this.context) {\n throw new Error(\"Reforge not initialized. Call init() first.\");\n }\n\n /* eslint-disable no-underscore-dangle */\n if (globalThis && (globalThis as any)._reforgeBootstrap) {\n /* eslint-disable no-underscore-dangle */\n const reforgeBootstrap = (globalThis as any)._reforgeBootstrap as ReforgeBootstrap;\n const bootstrapContext = new Context(reforgeBootstrap.context);\n\n if (this.context.equals(bootstrapContext)) {\n this.setConfigPrivate({ evaluations: reforgeBootstrap.evaluations });\n return Promise.resolve();\n }\n }\n\n // make sure we have the freshest context\n this.loader.context = this.context;\n\n return this.loader\n .load()\n .then((rawValues: any) => {\n this.setConfigPrivate(rawValues as EvaluationPayload);\n })\n .finally(() => {\n if (this.pollStatus.status === \"running\") {\n this._pollCount += 1;\n }\n });\n }\n\n async updateContext(context: Context, skipLoad = false) {\n if (!this.loader) {\n throw new Error(\"Reforge not initialized. Call init() first.\");\n }\n\n this._context = context;\n\n if (skipLoad) {\n return Promise.resolve();\n }\n\n return this.load();\n }\n\n async poll({ frequencyInMs }: { frequencyInMs: number }) {\n if (!this.loader) {\n throw new Error(\"Reforge not initialized. Call init() first.\");\n }\n\n this.stopPolling();\n\n this._pollStatus = { status: \"pending\" };\n\n return this.loader.load().finally(() => {\n this.doPolling({ frequencyInMs });\n });\n }\n\n private doPolling({ frequencyInMs }: { frequencyInMs: number }) {\n this._pollTimeoutId = setTimeout(() => {\n this.load().finally(() => {\n if (this.pollStatus.status === \"running\") {\n this.doPolling({ frequencyInMs });\n }\n });\n }, frequencyInMs);\n\n this._pollStatus = {\n status: \"running\",\n frequencyInMs,\n };\n }\n\n stopPolling() {\n if (this.pollTimeoutId) {\n clearTimeout(this.pollTimeoutId);\n this._pollTimeoutId = undefined;\n }\n\n this._pollStatus = { status: \"stopped\" };\n }\n\n stopTelemetry() {\n if (this.telemetryUploader) {\n this.evalutionSummaryAggregator?.stop();\n this.loggerAggregator?.stop();\n }\n }\n\n private setConfigPrivate(rawValues: RawConfigWithoutTypes | EvaluationPayload) {\n this._configs = Config.digest(rawValues);\n this.loaded = true;\n }\n\n isEnabled<\n // We need to calcuate these live and not store in a type to ensure dynamic evaluation\n // in upstream libraries that override the FrontEndConfigurationRaw interface\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends boolean\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(key: K): boolean {\n return this.get(key) === true;\n }\n\n get<K extends keyof TypedFrontEndConfigurationRaw>(key: K): TypedFrontEndConfigurationRaw[K] {\n if (!this.loaded) {\n if (!key.startsWith(loggerPrefix)) {\n // eslint-disable-next-line no-console\n console.warn(\n `Reforge warning: The client has not finished loading data yet. Unable to look up actual value for key \"${key}\".`\n );\n }\n\n return undefined;\n }\n\n const config = this._configs[key];\n\n const value = config?.value;\n\n if (!key.startsWith(loggerPrefix)) {\n if (this.collectEvaluationSummaries) {\n setTimeout(() => this.evalutionSummaryAggregator?.record(config));\n }\n\n setTimeout(() => this.afterEvaluationCallback(key, value, this.context));\n }\n\n return value;\n }\n\n getDuration<\n // We need to calcuate these live and not store in a type to ensure dynamic evaluation\n // in upstream libraries that override the FrontEndConfigurationRaw interface\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends Duration\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(key: K): Duration | undefined {\n const value = this.get(key);\n\n if (!value) {\n return undefined;\n }\n\n if (\n !Object.prototype.hasOwnProperty.call(value, \"seconds\") ||\n !Object.prototype.hasOwnProperty.call(value, \"ms\")\n ) {\n throw new Error(`Value for key \"${key}\" is not a duration`);\n }\n\n return value as Duration;\n }\n\n shouldLog(args: PublicShouldLogParams, async = true): boolean {\n if (this.collectLoggerNames) {\n const record = () => this.loggerAggregator?.record(args.loggerName, args.desiredLevel);\n if (async) {\n setTimeout(record);\n } else {\n record();\n }\n }\n\n return shouldLog({ ...args, get: this.get.bind(this) });\n }\n\n isCollectingEvaluationSummaries(): boolean {\n return this.collectEvaluationSummaries;\n }\n\n isCollectingLoggerNames(): boolean {\n return this.collectLoggerNames;\n }\n}\n\nexport const reforge = new Reforge();\n","import { ReforgeLogLevel } from \"./logger\";\nimport { TypedFrontEndConfigurationRaw, ConfigEvaluationMetadata } from \"./types\";\n\nexport type RawConfigWithoutTypes = Record<string, any>;\n\ntype APIKeyMetadata = {\n id: string | number;\n};\n\n// TODO: Why is this definition different from the one in ./types.ts?\ntype Duration = {\n definition: string;\n millis: number;\n};\n\nexport interface IntRange {\n /** if empty treat as Number.MIN_VALUE. Inclusive */\n start?: bigint | undefined;\n /** if empty treat as Number.MAX_VALUE. Exclusive */\n end?: bigint | undefined;\n}\n\nexport enum ProvidedSource {\n EnvVar = \"ENV_VAR\",\n}\nexport interface Provided {\n source?: ProvidedSource | undefined;\n /** eg MY_ENV_VAR */\n lookup?: string | undefined;\n}\n\nexport enum SchemaType {\n UNKNOWN = 0,\n ZOD = 1,\n JSON_SCHEMA = 2,\n}\n\nexport interface Schema {\n schema: string;\n schemaType: SchemaType;\n}\n\nexport interface WeightedValue {\n /** out of 1000 */\n weight: number;\n // eslint-disable-next-line no-use-before-define\n value: ConfigValue | undefined;\n}\n\nexport enum LimitResponse_LimitPolicyNames {\n SecondlyRolling = 1,\n MinutelyRolling = 3,\n HourlyRolling = 5,\n DailyRolling = 7,\n MonthlyRolling = 8,\n Infinite = 9,\n YearlyRolling = 10,\n}\n\nexport enum LimitDefinition_SafetyLevel {\n L4_BEST_EFFORT = 4,\n L5_BOMBPROOF = 5,\n}\n\nexport interface LimitDefinition {\n policyName: LimitResponse_LimitPolicyNames;\n limit: number;\n burst: number;\n accountId: number;\n lastModified: number;\n returnable: boolean;\n /** [default = L4_BEST_EFFORT]; // Overridable by request */\n safetyLevel: LimitDefinition_SafetyLevel;\n}\nexport interface WeightedValues {\n weightedValues: WeightedValue[];\n hashByPropertyName?: string | undefined;\n}\n\nexport type ConfigValue =\n | {\n int: number | undefined;\n }\n | {\n string: string | undefined;\n }\n | {\n bytes: Buffer | undefined;\n }\n | {\n double: number | undefined;\n }\n | {\n bool: boolean | undefined;\n }\n | {\n weightedValues?: WeightedValues | undefined;\n }\n | {\n limitDefinition?: LimitDefinition | undefined;\n }\n | {\n logLevel: ReforgeLogLevel | undefined;\n }\n | {\n stringList: string[] | undefined;\n }\n | {\n intRange: IntRange | undefined;\n }\n | {\n provided: Provided | undefined;\n }\n | {\n duration: Duration | undefined;\n }\n | {\n json: string | undefined;\n }\n | {\n schema: Schema | undefined;\n }\n | {\n /** don't log or telemetry this value */\n confidential: boolean | undefined;\n }\n | {\n /** key name to decrypt with */\n decryptWith: string | undefined;\n };\n\ntype Evaluation = {\n value: ConfigValue;\n configEvaluationMetadata: {\n configRowIndex: string | number;\n conditionalValueIndex: string | number;\n weightedValueIndex?: string | number;\n type: string;\n valueType: string;\n id: string;\n };\n};\n\nexport type EvaluationPayload = {\n evaluations: { [key: string]: Evaluation };\n apikeyMetadata: APIKeyMetadata;\n};\n\nconst parseRawMetadata = (metadata: any) => ({\n configRowIndex: parseInt(metadata.configRowIndex, 10),\n conditionalValueIndex: parseInt(metadata.conditionalValueIndex, 10),\n type: metadata.type,\n configId: metadata.id,\n});\n\nconst valueFor = <K extends keyof TypedFrontEndConfigurationRaw>(\n value: ConfigValue,\n type: keyof ConfigValue,\n key: K\n): TypedFrontEndConfigurationRaw[K] => {\n const rawValue = value[type];\n\n switch (type) {\n case \"json\":\n try {\n return JSON.parse(rawValue as string);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(`Error parsing JSON from Reforge config ${key}`, e, rawValue);\n return value[type];\n }\n case \"duration\": {\n const duration = rawValue as Duration;\n return {\n ms: duration.millis,\n seconds: duration.millis / 1000,\n };\n }\n default:\n return rawValue;\n }\n};\n\nexport const parseEvaluationPayload = (payload: EvaluationPayload) => {\n // eslint-disable-next-line no-use-before-define\n const configs = {} as { [key: string]: Config };\n Object.keys(payload.evaluations).forEach((key) => {\n const evaluation = payload.evaluations[key];\n\n const type = Object.keys(evaluation.value)[0] as keyof ConfigValue;\n\n // eslint-disable-next-line no-use-before-define\n configs[key] = new Config(\n key,\n valueFor(evaluation.value, type, key),\n type,\n evaluation.value,\n evaluation.configEvaluationMetadata\n ? parseRawMetadata(evaluation.configEvaluationMetadata)\n : undefined\n );\n });\n\n return configs;\n};\n\nconst parseRawConfigWithoutTypes = (payload: RawConfigWithoutTypes) => {\n // eslint-disable-next-line no-use-before-define\n const configs = {} as { [key: string]: Config };\n Object.keys(payload).forEach((key) => {\n const type = typeof payload[key] as keyof ConfigValue;\n // eslint-disable-next-line no-use-before-define\n configs[key] = new Config(key, valueFor({ [type]: payload[key] }, type, key), type);\n });\n\n return configs;\n};\n\nexport class Config<\n K extends keyof TypedFrontEndConfigurationRaw = keyof TypedFrontEndConfigurationRaw,\n> {\n key: K;\n\n value: TypedFrontEndConfigurationRaw[K];\n\n rawValue: ConfigValue | undefined;\n\n type: keyof ConfigValue;\n\n configEvaluationMetadata: ConfigEvaluationMetadata | undefined;\n\n constructor(\n key: K,\n value: TypedFrontEndConfigurationRaw[K],\n type: keyof ConfigValue,\n rawValue?: ConfigValue,\n metadata?: ConfigEvaluationMetadata\n ) {\n this.key = key;\n this.value = value;\n this.type = type;\n this.rawValue = rawValue;\n this.configEvaluationMetadata = metadata;\n }\n\n static digest(payload: EvaluationPayload | RawConfigWithoutTypes) {\n if (payload === undefined) {\n // eslint-disable-next-line no-console\n console.trace(\"Config.digest called with undefined payload\");\n }\n\n if (\"evaluations\" in payload) {\n return parseEvaluationPayload(payload as EvaluationPayload);\n }\n\n return parseRawConfigWithoutTypes(payload as RawConfigWithoutTypes);\n }\n}\n","const base64Encode = (obj: string) => {\n if (typeof window !== \"undefined\") {\n if (typeof TextEncoder === \"undefined\") {\n return window.btoa(obj);\n }\n\n const bytes = new TextEncoder().encode(obj);\n const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join(\"\");\n return btoa(binString);\n }\n\n return Buffer.from(obj).toString(\"base64\");\n};\n\nexport default base64Encode;\n","import { Contexts, ContextValue } from \"./types\";\nimport base64Encode from \"./base64Encode\";\n\nconst isEqual = (a: Contexts, b: Contexts) => {\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n return aKeys.every((key) => {\n const aValues = a[key];\n const bValues = b[key];\n\n const aValuesKeys = Object.keys(aValues);\n const bValuesKeys = Object.keys(bValues);\n\n if (aValuesKeys.length !== bValuesKeys.length) {\n return false;\n }\n\n return aValuesKeys.every((ckey) => {\n const aValue = aValues[ckey];\n const bValue = bValues[ckey];\n\n return aValue === bValue;\n });\n });\n};\n\nconst getType = (value: ContextValue) => {\n if (typeof value === \"string\") {\n return \"string\";\n }\n\n if (typeof value === \"number\") {\n if (Number.isInteger(value)) {\n return \"int\";\n }\n\n return \"double\";\n }\n\n return \"bool\";\n};\n\nexport default class Context {\n contexts: Contexts;\n\n constructor(contexts: Contexts) {\n if (!Object.values(contexts).every((item: any) => typeof item === \"object\")) {\n // eslint-disable-next-line no-console\n console.error(\"Context must be an object where the value of each key is also an object\");\n }\n\n if (\n Object.values(contexts).some((item: any) =>\n Object.values(item).some((value: any) => typeof value === \"object\" && value !== null)\n )\n ) {\n // we decided to allow null values, which requres an extra check since typeof null is object\n // eslint-disable-next-line no-console\n console.error(\"Nested objects are not supported in context values at this time\");\n }\n\n this.contexts = contexts;\n }\n\n equals(other: Context) {\n return isEqual(this.contexts, other.contexts);\n }\n\n encode() {\n const formatted = Object.keys(this.contexts).map((key) => {\n const values: Record<string, Record<string, ContextValue>> = {};\n\n Object.keys(this.contexts[key]).forEach((ckey) => {\n values[ckey] = {\n [getType(this.contexts[key][ckey])]: this.contexts[key][ckey],\n };\n });\n\n return {\n type: key,\n values,\n };\n });\n\n return encodeURIComponent(base64Encode(JSON.stringify({ contexts: formatted })));\n }\n}\n","export class ExponentialBackoff {\n private maxDelay: number;\n\n private multiplier: number;\n\n private delay: number;\n\n // arguments are in seconds\n constructor(maxDelay: number, initialDelay = 2, multiplier = 2) {\n this.maxDelay = maxDelay;\n this.multiplier = multiplier;\n this.delay = initialDelay;\n }\n\n call(): number {\n const delayValue = this.delay;\n this.delay = Math.min(this.delay * this.multiplier, this.maxDelay);\n return delayValue * 1000;\n }\n}\n","import { TypedFrontEndConfigurationRaw } from \"./types\";\n\nexport const PREFIX = \"log-level\";\nexport enum ReforgeLogLevel {\n Trace = 1,\n Debug = 2,\n Info = 3,\n Warn = 4,\n Error = 5,\n Fatal = 6,\n}\n\nexport type LogLevelWord = Uppercase<keyof typeof ReforgeLogLevel>;\n\nconst WORD_LEVEL_LOOKUP: Readonly<Record<LogLevelWord, ReforgeLogLevel>> = {\n TRACE: ReforgeLogLevel.Trace,\n DEBUG: ReforgeLogLevel.Debug,\n INFO: ReforgeLogLevel.Info,\n WARN: ReforgeLogLevel.Warn,\n ERROR: ReforgeLogLevel.Error,\n FATAL: ReforgeLogLevel.Fatal,\n};\n\nexport const isValidLogLevel = (possibleLogLevel: string) =>\n Object.keys(WORD_LEVEL_LOOKUP).includes(possibleLogLevel.toUpperCase());\n\nexport interface ShouldLogParams {\n loggerName: string;\n desiredLevel: ReforgeLogLevel;\n defaultLevel: ReforgeLogLevel;\n get: <K extends keyof TypedFrontEndConfigurationRaw>(key: K) => TypedFrontEndConfigurationRaw[K];\n}\n\nexport const shouldLog = ({\n loggerName,\n desiredLevel,\n defaultLevel,\n get,\n}: ShouldLogParams): boolean => {\n let loggerNameWithPrefix = `${PREFIX}.${loggerName}`;\n\n while (loggerNameWithPrefix.length > 0) {\n const resolvedLevel = get(loggerNameWithPrefix);\n\n if (resolvedLevel) {\n return (\n WORD_LEVEL_LOOKUP[resolvedLevel.toString().toUpperCase() as LogLevelWord] <= desiredLevel\n );\n }\n\n if (loggerNameWithPrefix.indexOf(\".\") === -1) {\n break;\n }\n\n loggerNameWithPrefix = loggerNameWithPrefix.slice(0, loggerNameWithPrefix.lastIndexOf(\".\"));\n }\n\n return defaultLevel <= desiredLevel;\n};\n","import { ExponentialBackoff } from \"./exponentialBackoff\";\nimport { ReforgeLogLevel } from \"./logger\";\nimport { type reforge } from \"./reforge\";\n\nabstract class PeriodicSync<T> {\n protected data: Map<string, T> = new Map();\n\n private startAt: Date;\n\n private syncInterval: any;\n\n protected client: typeof reforge;\n\n private name: string;\n\n private timeoutID: ReturnType<typeof setTimeout> | undefined;\n\n constructor(client: typeof reforge, name: string, syncInterval?: number) {\n this.client = client;\n this.name = name;\n\n this.startAt = new Date();\n\n this.startPeriodicSync(syncInterval);\n }\n\n stop(): void {\n clearTimeout(this.timeoutID);\n }\n\n sync(): void {\n if (this.data.size === 0) return;\n\n this.logInternal(`${this.name} syncing ${this.data.size} items`);\n\n const startAtWas = this.startAt;\n this.startAt = new Date();\n\n this.flush(this.prepareData(), startAtWas);\n }\n\n protected abstract flush(toShip: Map<string, T>, startAtWas: Date): void;\n\n private prepareData(): Map<string, T> {\n const toShip = new Map(this.data);\n this.data.clear();\n\n return toShip;\n }\n\n private startPeriodicSync(syncInterval?: number): void {\n this.startAt = new Date();\n this.syncInterval = PeriodicSync.calculateSyncInterval(syncInterval);\n\n this.scheduleNextSync();\n }\n\n private scheduleNextSync() {\n const interval = this.syncInterval();\n this.timeoutID = setTimeout(() => {\n this.sync();\n this.scheduleNextSync(); // Schedule the next sync after the current one completes\n }, interval);\n }\n\n private static calculateSyncInterval(syncInterval?: number): any {\n if (syncInterval !== undefined) {\n return () => syncInterval;\n }\n\n const backoff = new ExponentialBackoff(60 * 5, 8);\n return () => backoff.call();\n }\n\n protected logInternal(message: string): void {\n const loggerName = `${this.client.clientNameString}.reforge.${this.name}`;\n\n if (\n this.client.shouldLog(\n {\n loggerName,\n desiredLevel: ReforgeLogLevel.Debug,\n defaultLevel: ReforgeLogLevel.Error,\n },\n false // synchronous so that this log ends up in the current batch\n )\n ) {\n // eslint-disable-next-line no-console\n console.log(`${loggerName}: ${message}`);\n }\n }\n}\n\nexport { PeriodicSync };\n","// TODO: should we retry the data chunk if a flush fails?\n\n// TODO: pause when offline?\n\n// TODO: flush when we receive a config update (or as a result of a context update...but that should trigger a config update anyway)\n\nimport { PeriodicSync } from \"./periodicSync\";\nimport { Config } from \"./config\";\nimport { type reforge } from \"./reforge\";\nimport {\n ConfigEvaluationCounter,\n ConfigEvaluationSummaries,\n ConfigEvaluationSummary,\n TelemetryEvents,\n ConfigEvaluationMetadata,\n} from \"./types\";\n\nexport const massageSelectedValue = (config: Config): any => {\n if (config.rawValue && (config.type === \"duration\" || config.type === \"json\")) {\n if (config.type === \"json\") {\n return { json: config.rawValue[config.type] };\n }\n\n return config.rawValue[config.type];\n }\n\n return config.type === \"stringList\" ? { values: config.value } : config.value;\n};\n\nexport const massageConfigForTelemetry = (\n config: Config,\n metadata: Omit<ConfigEvaluationMetadata, \"type\">\n) => ({\n ...metadata,\n selectedValue: {\n [config.type]: massageSelectedValue(config),\n },\n count: 0,\n});\n\nclass EvaluationSummaryAggregator extends PeriodicSync<ConfigEvaluationCounter> {\n private maxKeys: number;\n\n constructor(client: typeof reforge, maxKeys: number, syncInterval?: number) {\n super(client, \"EvaluationSummaryAggregator\", syncInterval ?? 30000);\n\n this.maxKeys = maxKeys;\n }\n\n record(config: Config): void {\n if (this.data.size >= this.maxKeys) return;\n\n if (config?.configEvaluationMetadata) {\n const { type, ...metadata } = config.configEvaluationMetadata;\n const key = `${config.key},${type}`;\n\n // create counter entry if it doesn't exist\n if (!this.data.has(key)) {\n this.data.set(key, massageConfigForTelemetry(config, metadata));\n }\n\n // increment count\n const counter = this.data.get(key);\n if (counter) {\n counter.count += 1;\n }\n }\n }\n\n protected flush(toShip: Map<string, ConfigEvaluationCounter>, startAtWas: Date): void {\n const summaries = {\n start: startAtWas.getTime(),\n end: new Date().getTime(),\n summaries: EvaluationSummaryAggregator.summaries(toShip),\n };\n\n this.client.telemetryUploader?.post(this.events(summaries));\n }\n\n private static summaries(data: Map<string, ConfigEvaluationCounter>): ConfigEvaluationSummary[] {\n return Array.from(data).map((entry: [string, ConfigEvaluationCounter]) => {\n const [configKey, configType] = entry[0].split(\",\");\n const counter = entry[1];\n const counters = [counter]; // this client only ever has one set of counter info per key\n\n return {\n key: configKey,\n type: configType,\n counters,\n };\n });\n }\n\n private events(summaries: ConfigEvaluationSummaries): TelemetryEvents {\n const event = { summaries };\n\n return {\n instanceHash: this.client.instanceHash,\n events: [event],\n };\n }\n}\n\nexport { EvaluationSummaryAggregator };\n","import base64Encode from \"./base64Encode\";\n\nexport const headers = (sdkKey: string, clientVersion: string) => ({\n Authorization: `Basic ${base64Encode(`u:${sdkKey}`)}`,\n \"X-Reforge-SDK-Version\": clientVersion,\n});\n\nexport const DEFAULT_TIMEOUT = 10000;\n","import { DEFAULT_TIMEOUT, headers } from \"./apiHelpers\";\nimport { EvaluationPayload } from \"./config\";\nimport Context from \"./context\";\n\nexport type CollectContextModeType = \"NONE\" | \"SHAPE_ONLY\" | \"PERIODIC_EXAMPLE\";\n\nexport type LoaderParams = {\n sdkKey: string;\n context: Context;\n endpoints?: string[] | undefined;\n timeout?: number;\n collectContextMode?: CollectContextModeType;\n clientVersion?: string;\n};\n\nexport type Headers = {\n [key: string]: string;\n};\n\nexport type FetchOptions = {\n headers: Headers;\n};\n\nconst defaultEndpoints = [\n \"https://primary.reforge.com/api/v2\",\n \"https://secondary.reforge.com/api/v2\",\n];\n\nconst EARLY_TIMEOUT = 2000;\n\nexport default class Loader {\n sdkKey: string;\n\n context: Context;\n\n endpoints: string[];\n\n timeout: number;\n\n abortTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n collectContextMode: CollectContextModeType = \"PERIODIC_EXAMPLE\";\n\n clientVersion: string;\n\n abortController: AbortController | undefined;\n\n isAborted = false;\n\n constructor({\n sdkKey,\n context,\n endpoints = undefined,\n timeout,\n collectContextMode = \"PERIODIC_EXAMPLE\",\n clientVersion = \"\",\n }: LoaderParams) {\n this.sdkKey = sdkKey;\n this.context = context;\n this.endpoints = endpoints || defaultEndpoints;\n this.timeout = timeout || DEFAULT_TIMEOUT;\n this.collectContextMode = collectContextMode;\n this.clientVersion = clientVersion;\n }\n\n url(root: string) {\n return `${root}/configs/eval-with-context/${this.context.encode()}?collectContextMode=${\n this.collectContextMode\n }`;\n }\n\n loadFromEndpoint(\n index: number,\n options: FetchOptions,\n resolve: (value: any) => void,\n reject: (value: any) => void\n ) {\n this.abortController = new AbortController() as AbortController;\n const { signal } = this.abortController;\n this.isAborted = false;\n\n const endpoint = this.endpoints[index];\n const url = this.url(endpoint);\n\n fetch(url, { signal, ...options })\n .then((response) => {\n this.clearAbortTimeout();\n\n if (response.ok) {\n return response.json();\n }\n throw new Error(`${response.status} ${response.statusText}`);\n })\n .then((data) => {\n if (!(\"evaluations\" in data)) {\n throw new Error(`Invalid payload:${JSON.stringify(data)}`);\n }\n\n resolve(data as EvaluationPayload);\n })\n .catch((error) => {\n this.clearAbortTimeout();\n\n if (index < this.endpoints.length - 1) {\n this.loadFromEndpoint(index + 1, options, resolve, reject);\n } else {\n reject(error);\n }\n });\n\n // Use an early timeout if we're not on the last endpoint. But if the user-provided timeout is less than EARLY_TIMEOUT, use that\n const timeout =\n index < this.endpoints.length - 1 ? Math.min(this.timeout, EARLY_TIMEOUT) : this.timeout;\n\n this.abortTimeoutId = setTimeout(() => {\n if (!this.isAborted) {\n this.isAborted = true;\n this.abortController?.abort();\n }\n }, timeout);\n }\n\n load() {\n if (!this.isAborted) {\n this.isAborted = true;\n this.abortController?.abort();\n }\n\n const options = {\n headers: headers(this.sdkKey, this.clientVersion),\n };\n\n const promise = new Promise((resolve, reject) => {\n this.loadFromEndpoint(0, options, resolve, reject);\n });\n\n return promise;\n }\n\n clearAbortTimeout() {\n clearTimeout(this.abortTimeoutId);\n }\n}\n","import { DEFAULT_TIMEOUT, headers } from \"./apiHelpers\";\nimport { TelemetryEvents } from \"./types\";\n\nexport type TelemetryUploaderParams = {\n sdkKey: string;\n apiEndpoint?: string;\n timeout?: number;\n clientVersion: string;\n};\n\nexport default class TelemetryUploader {\n sdkKey: Required<TelemetryUploaderParams>[\"sdkKey\"];\n\n apiEndpoint: Required<TelemetryUploaderParams>[\"apiEndpoint\"];\n\n timeout: Required<TelemetryUploaderParams>[\"timeout\"];\n\n clientVersion: Required<TelemetryUploaderParams>[\"clientVersion\"];\n\n abortTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n constructor({\n sdkKey,\n apiEndpoint = undefined,\n timeout,\n clientVersion,\n }: TelemetryUploaderParams) {\n this.sdkKey = sdkKey;\n this.apiEndpoint = apiEndpoint || \"https://telemetry.prefab.cloud/api/v1\";\n this.timeout = timeout || DEFAULT_TIMEOUT;\n this.clientVersion = clientVersion;\n }\n\n clearAbortTimeout() {\n clearTimeout(this.abortTimeoutId);\n }\n\n static postUrl(root: string) {\n return `${root}/telemetry`;\n }\n\n postToEndpoint(\n options: RequestInit,\n resolve: (value: unknown) => void,\n reject: (value: unknown) => void\n ) {\n const controller = new AbortController() as AbortController;\n const signal = controller?.signal;\n let isAborted = false;\n\n const url = TelemetryUploader.postUrl(this.apiEndpoint);\n\n fetch(url, { signal, ...options })\n .then((response) => {\n this.clearAbortTimeout();\n\n if (response.ok) {\n return response.json();\n }\n\n // eslint-disable-next-line no-console\n console.warn(\n `Reforge warning: Error uploading telemetry ${response.status} ${response.statusText}`\n );\n\n return response.status;\n })\n .then((response) => {\n resolve(response);\n })\n .catch((error) => {\n this.clearAbortTimeout();\n\n // Silently handle AbortErrors (from timeouts or page navigations)\n if (error.name === \"AbortError\") {\n try {\n // eslint-disable-next-line no-console\n console.debug(\"Reforge telemetry request aborted\");\n } catch (e) {\n // no-op\n }\n resolve({ status: \"aborted\" });\n return;\n }\n\n reject(error);\n });\n\n this.abortTimeoutId = setTimeout(() => {\n if (!isAborted) {\n isAborted = true;\n controller.abort();\n }\n }, this.timeout);\n }\n\n post(data: TelemetryEvents) {\n const options = {\n method: \"POST\",\n headers: {\n ...headers(this.sdkKey, this.clientVersion),\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify(data),\n keepalive: true, // needed for flushing when the window is closed\n };\n\n const promise = new Promise((resolve, reject) => {\n this.postToEndpoint(options, resolve, reject);\n });\n\n return promise;\n }\n}\n","// TODO: should we retry the data chunk if a flush fails?\n\n// TODO: pause when offline?\n\nimport { ReforgeLogLevel } from \"./logger\";\nimport { PeriodicSync } from \"./periodicSync\";\nimport { type reforge } from \"./reforge\";\nimport { LoggerCounter, LoggersTelemetryEvent, TelemetryEvents } from \"./types\";\n\nconst SEVERITY_KEY: { [key in ReforgeLogLevel]: Omit<keyof LoggerCounter, \"loggerName\"> } = {\n [ReforgeLogLevel.Trace]: \"traces\",\n [ReforgeLogLevel.Debug]: \"debugs\",\n [ReforgeLogLevel.Info]: \"infos\",\n [ReforgeLogLevel.Warn]: \"warns\",\n [ReforgeLogLevel.Error]: \"errors\",\n [ReforgeLogLevel.Fatal]: \"fatals\",\n};\n\nclass LoggerAggregator extends PeriodicSync<LoggerCounter> {\n private maxLoggers: number;\n\n constructor(client: typeof reforge, maxLoggers: number, syncInterval?: number) {\n super(client, \"LoggerAggregator\", syncInterval ?? 30000);\n\n this.maxLoggers = maxLoggers;\n }\n\n record(logger: string, level: ReforgeLogLevel): void {\n if (this.data.size >= this.maxLoggers) return;\n\n // create counter entry if it doesn't exist\n if (!this.data.has(logger)) {\n this.data.set(logger, {\n loggerName: logger,\n traces: 0,\n debugs: 0,\n infos: 0,\n warns: 0,\n errors: 0,\n fatals: 0,\n });\n }\n\n // increment count\n const counter = this.data.get(logger);\n if (counter) {\n const severityKey = SEVERITY_KEY[level] as keyof LoggerCounter;\n (counter[severityKey] as number) += 1;\n }\n }\n\n protected flush(toShip: Map<string, LoggerCounter>, startAtWas: Date): void {\n const loggers = {\n startAt: startAtWas.getTime(),\n endAt: new Date().getTime(),\n loggers: Array.from(toShip.values()),\n };\n\n this.client.telemetryUploader?.post(this.events(loggers));\n }\n\n private events(loggers: LoggersTelemetryEvent): TelemetryEvents {\n const event = { loggers };\n\n return {\n instanceHash: this.client.instanceHash,\n events: [event],\n };\n }\n}\n\nexport { LoggerAggregator };\n"],"mappings":"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","names":["exports","module","version","uuid","version"]} | ||
| {"version":3,"sources":["../package.json","../index.ts","../src/reforge.ts","../src/config.ts","../src/base64Encode.ts","../src/context.ts","../src/exponentialBackoff.ts","../src/logger.ts","../src/periodicSync.ts","../src/evaluationSummaryAggregator.ts","../src/apiHelpers.ts","../src/loader.ts","../src/telemetryUploader.ts","../src/loggerAggregator.ts"],"sourcesContent":["{\n \"packageManager\": \"yarn@4.9.2\",\n \"name\": \"@reforge-com/javascript\",\n \"version\": \"0.0.2\",\n \"description\": \"Feature Flags & Dynamic Configuration as a Service\",\n \"main\": \"dist/index.cjs\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"author\": \"Jeffrey Chupp\",\n \"license\": \"ISC\",\n \"devDependencies\": {\n \"@types/eslint-plugin-jsx-a11y\": \"^6\",\n \"@types/express\": \"^4.17.13\",\n \"@types/jest\": \"^28.1.6\",\n \"@types/uuid\": \"^9.0.5\",\n \"@typescript-eslint/eslint-plugin\": \"^5.33.0\",\n \"@typescript-eslint/parser\": \"^5.33.0\",\n \"esbuild\": \"^0.25.11\",\n \"eslint\": \"^8.21.0\",\n \"eslint-config-airbnb\": \"^19.0.4\",\n \"eslint-config-airbnb-typescript\": \"^17.0.0\",\n \"eslint-config-prettier\": \"^8.8.0\",\n \"eslint-plugin-import\": \"^2.26.0\",\n \"eslint-plugin-jest\": \"^26.8.0\",\n \"eslint-plugin-jsx-a11y\": \"^6.10.2\",\n \"eslint-plugin-react\": \"^7.37.5\",\n \"jest\": \"^29.0.0\",\n \"jest-fetch-mock\": \"^3.0.3\",\n \"prettier\": \"^3.0.0\",\n \"ts-jest\": \"^29.1.1\",\n \"ts-node\": \"^10.9.1\",\n \"tsup\": \"^8.0.2\",\n \"typescript\": \"^5.1.6\"\n },\n \"scripts\": {\n \"build\": \"rm -rf dist/ && tsup\",\n \"dev\": \"tsup --watch\",\n \"bundle\": \"esbuild --minify --target=esnext --bundle --outfile=dist/reforge.bundle.js --global-name=window.reforgeNamespace dist/index.cjs && echo 'window.reforge = window.reforgeNamespace.reforge' >> dist/reforge.bundle.js\",\n \"lint\": \"eslint --ext .ts,.tsx src/\",\n \"lint:fix\": \"eslint --fix --ext .ts,.tsx src/\",\n \"prettier\": \"prettier . -l\",\n \"prettier:fix\": \"prettier --write .\",\n \"test\": \"jest --verbose\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/ReforgeHQ/sdk-javascript.git\"\n },\n \"keywords\": [\n \"feature-flags\",\n \"config\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/ReforgeHQ/sdk-javascript/issues\"\n },\n \"homepage\": \"https://github.com/ReforgeHQ/sdk-javascript#readme\",\n \"dependencies\": {\n \"uuid\": \"^9.0.1\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n }\n }\n}\n","import { reforge, Reforge, ReforgeInitParams, ReforgeBootstrap } from \"./src/reforge\";\nimport { Config } from \"./src/config\";\nimport Context from \"./src/context\";\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { version } = require(\"./package.json\");\n\nexport { reforge, Reforge, ReforgeInitParams, Config, Context, version };\n\nexport { ReforgeBootstrap };\n\nexport type { ConfigValue } from \"./src/config\";\nexport type {\n Duration,\n ContextValue,\n Contexts,\n TypedFrontEndConfigurationRaw,\n FrontEndConfigurationRaw,\n} from \"./src/types\";\nexport type { CollectContextModeType } from \"./src/loader\";\n","import { v4 as uuid } from \"uuid\";\n\nimport { Config, EvaluationPayload, RawConfigWithoutTypes } from \"./config\";\nimport type {\n Duration,\n TypedFrontEndConfigurationRaw,\n FrontEndConfigurationRaw,\n Contexts,\n} from \"./types\";\nimport Context from \"./context\";\nimport { EvaluationSummaryAggregator } from \"./evaluationSummaryAggregator\";\nimport Loader, { CollectContextModeType } from \"./loader\";\nimport { PREFIX as loggerPrefix, shouldLog, ShouldLogParams } from \"./logger\";\nimport TelemetryUploader from \"./telemetryUploader\";\nimport { LoggerAggregator } from \"./loggerAggregator\";\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { version } = require(\"../package.json\");\n\ntype EvaluationCallback = <K extends keyof TypedFrontEndConfigurationRaw>(\n key: K,\n value: TypedFrontEndConfigurationRaw[K],\n context: Context | undefined\n) => void;\n\nexport interface ReforgeBootstrap {\n evaluations: EvaluationPayload;\n context: Contexts;\n}\n\nexport type ReforgeInitParams = {\n sdkKey: string;\n context: Context;\n endpoints?: string[] | undefined;\n apiEndpoint?: string;\n timeout?: number;\n afterEvaluationCallback?: EvaluationCallback;\n collectEvaluationSummaries?: boolean;\n collectLoggerNames?: boolean;\n collectContextMode?: CollectContextModeType;\n clientNameString?: string;\n clientVersionString?: string;\n};\n\ntype PollStatus =\n | { status: \"not-started\" }\n | { status: \"pending\" }\n | { status: \"stopped\" }\n | { status: \"running\"; frequencyInMs: number };\n\ntype PublicShouldLogParams = Omit<ShouldLogParams, \"get\">;\n\nexport class Reforge {\n private _configs: { [key: string]: Config } = {};\n\n private _telemetryUploader: TelemetryUploader | undefined;\n\n private _pollCount = 0;\n\n private _pollStatus: PollStatus = { status: \"not-started\" };\n\n private _pollTimeoutId = undefined as ReturnType<typeof setTimeout> | undefined;\n\n private _instanceHash: string = uuid();\n\n private collectEvaluationSummaries = true;\n\n private collectLoggerNames = false;\n\n private evalutionSummaryAggregator: EvaluationSummaryAggregator | undefined;\n\n private loggerAggregator: LoggerAggregator | undefined;\n\n public clientNameString = \"sdk-javascript\";\n\n public loaded = false;\n\n public loader: Loader | undefined;\n\n public afterEvaluationCallback = (() => {}) as EvaluationCallback;\n\n private _context: Context = new Context({});\n\n async init({\n sdkKey,\n context: providedContext,\n endpoints = undefined,\n apiEndpoint,\n timeout = undefined,\n afterEvaluationCallback = () => {},\n collectEvaluationSummaries = true,\n collectLoggerNames = false,\n collectContextMode = \"PERIODIC_EXAMPLE\",\n clientNameString = \"sdk-javascript\",\n clientVersionString = version,\n }: ReforgeInitParams) {\n const context = providedContext ?? this.context;\n\n if (!context) {\n throw new Error(\"Context must be provided\");\n }\n\n this._context = context;\n\n this.clientNameString = clientNameString;\n const clientNameAndVersionString = `${clientNameString}-${clientVersionString}`;\n\n this.loader = new Loader({\n sdkKey,\n context,\n endpoints,\n timeout,\n collectContextMode,\n clientVersion: clientNameAndVersionString,\n });\n\n this._telemetryUploader = new TelemetryUploader({\n sdkKey,\n apiEndpoint,\n timeout,\n clientVersion: clientNameAndVersionString,\n });\n\n this.collectEvaluationSummaries = collectEvaluationSummaries;\n if (collectEvaluationSummaries) {\n this.evalutionSummaryAggregator = new EvaluationSummaryAggregator(this, 100000);\n }\n\n this.collectLoggerNames = collectLoggerNames;\n if (collectLoggerNames) {\n this.loggerAggregator = new LoggerAggregator(this, 100000);\n }\n\n if (\n (collectEvaluationSummaries || collectLoggerNames) &&\n typeof window !== \"undefined\" &&\n typeof window.addEventListener === \"function\"\n ) {\n window.addEventListener(\"beforeunload\", () => {\n this.evalutionSummaryAggregator?.sync();\n this.loggerAggregator?.sync();\n });\n }\n\n this.afterEvaluationCallback = afterEvaluationCallback;\n\n return this.load();\n }\n\n public extract(): Record<string, Config[\"value\"]> {\n return Object.entries(this._configs).reduce(\n (agg, [key, value]) => ({\n ...agg,\n [key]: value.value,\n }),\n {} as Record<string, Config[\"value\"]>\n );\n }\n\n public hydrate(rawValues: RawConfigWithoutTypes | EvaluationPayload): void {\n this.setConfigPrivate(rawValues);\n }\n\n get context(): Context {\n return this._context;\n }\n\n get instanceHash(): string {\n return this._instanceHash;\n }\n\n get pollTimeoutId() {\n return this._pollTimeoutId;\n }\n\n get pollCount() {\n return this._pollCount;\n }\n\n get pollStatus() {\n return this._pollStatus;\n }\n\n get telemetryUploader(): TelemetryUploader | undefined {\n return this._telemetryUploader;\n }\n\n private async load() {\n if (!this.loader || !this.context) {\n throw new Error(\"Reforge not initialized. Call init() first.\");\n }\n\n /* eslint-disable no-underscore-dangle */\n if (globalThis && (globalThis as any)._reforgeBootstrap) {\n /* eslint-disable no-underscore-dangle */\n const reforgeBootstrap = (globalThis as any)._reforgeBootstrap as ReforgeBootstrap;\n const bootstrapContext = new Context(reforgeBootstrap.context);\n\n if (this.context.equals(bootstrapContext)) {\n this.setConfigPrivate({ evaluations: reforgeBootstrap.evaluations });\n return Promise.resolve();\n }\n }\n\n // make sure we have the freshest context\n this.loader.context = this.context;\n\n return this.loader\n .load()\n .then((rawValues: any) => {\n this.setConfigPrivate(rawValues as EvaluationPayload);\n })\n .finally(() => {\n if (this.pollStatus.status === \"running\") {\n this._pollCount += 1;\n }\n });\n }\n\n async updateContext(context: Context, skipLoad = false) {\n if (!this.loader) {\n throw new Error(\"Reforge not initialized. Call init() first.\");\n }\n\n this._context = context;\n\n if (skipLoad) {\n return Promise.resolve();\n }\n\n return this.load();\n }\n\n async poll({ frequencyInMs }: { frequencyInMs: number }) {\n if (!this.loader) {\n throw new Error(\"Reforge not initialized. Call init() first.\");\n }\n\n this.stopPolling();\n\n this._pollStatus = { status: \"pending\" };\n\n return this.loader.load().finally(() => {\n this.doPolling({ frequencyInMs });\n });\n }\n\n private doPolling({ frequencyInMs }: { frequencyInMs: number }) {\n this._pollTimeoutId = setTimeout(() => {\n this.load().finally(() => {\n if (this.pollStatus.status === \"running\") {\n this.doPolling({ frequencyInMs });\n }\n });\n }, frequencyInMs);\n\n this._pollStatus = {\n status: \"running\",\n frequencyInMs,\n };\n }\n\n stopPolling() {\n if (this.pollTimeoutId) {\n clearTimeout(this.pollTimeoutId);\n this._pollTimeoutId = undefined;\n }\n\n this._pollStatus = { status: \"stopped\" };\n }\n\n stopTelemetry() {\n if (this.telemetryUploader) {\n this.evalutionSummaryAggregator?.stop();\n this.loggerAggregator?.stop();\n }\n }\n\n private setConfigPrivate(rawValues: RawConfigWithoutTypes | EvaluationPayload) {\n this._configs = Config.digest(rawValues);\n this.loaded = true;\n }\n\n isEnabled<\n // We need to calcuate these live and not store in a type to ensure dynamic evaluation\n // in upstream libraries that override the FrontEndConfigurationRaw interface\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends boolean\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(key: K): boolean {\n return this.get(key) === true;\n }\n\n get<K extends keyof TypedFrontEndConfigurationRaw>(key: K): TypedFrontEndConfigurationRaw[K] {\n if (!this.loaded) {\n if (!key.startsWith(loggerPrefix)) {\n // eslint-disable-next-line no-console\n console.warn(\n `Reforge warning: The client has not finished loading data yet. Unable to look up actual value for key \"${key}\".`\n );\n }\n\n return undefined;\n }\n\n const config = this._configs[key];\n\n const value = config?.value;\n\n if (!key.startsWith(loggerPrefix)) {\n if (this.collectEvaluationSummaries) {\n setTimeout(() => this.evalutionSummaryAggregator?.record(config));\n }\n\n setTimeout(() => this.afterEvaluationCallback(key, value, this.context));\n }\n\n return value;\n }\n\n getDuration<\n // We need to calcuate these live and not store in a type to ensure dynamic evaluation\n // in upstream libraries that override the FrontEndConfigurationRaw interface\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends Duration\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(key: K): Duration | undefined {\n const value = this.get(key);\n\n if (!value) {\n return undefined;\n }\n\n if (\n !Object.prototype.hasOwnProperty.call(value, \"seconds\") ||\n !Object.prototype.hasOwnProperty.call(value, \"ms\")\n ) {\n throw new Error(`Value for key \"${key}\" is not a duration`);\n }\n\n return value as Duration;\n }\n\n shouldLog(args: PublicShouldLogParams, async = true): boolean {\n if (this.collectLoggerNames) {\n const record = () => this.loggerAggregator?.record(args.loggerName, args.desiredLevel);\n if (async) {\n setTimeout(record);\n } else {\n record();\n }\n }\n\n return shouldLog({ ...args, get: this.get.bind(this) });\n }\n\n isCollectingEvaluationSummaries(): boolean {\n return this.collectEvaluationSummaries;\n }\n\n isCollectingLoggerNames(): boolean {\n return this.collectLoggerNames;\n }\n}\n\nexport const reforge = new Reforge();\n","import { ReforgeLogLevel } from \"./logger\";\nimport { TypedFrontEndConfigurationRaw, ConfigEvaluationMetadata } from \"./types\";\n\nexport type RawConfigWithoutTypes = Record<string, any>;\n\ntype APIKeyMetadata = {\n id: string | number;\n};\n\n// TODO: Why is this definition different from the one in ./types.ts?\ntype Duration = {\n definition: string;\n millis: number;\n};\n\nexport interface IntRange {\n /** if empty treat as Number.MIN_VALUE. Inclusive */\n start?: bigint | undefined;\n /** if empty treat as Number.MAX_VALUE. Exclusive */\n end?: bigint | undefined;\n}\n\nexport enum ProvidedSource {\n EnvVar = \"ENV_VAR\",\n}\nexport interface Provided {\n source?: ProvidedSource | undefined;\n /** eg MY_ENV_VAR */\n lookup?: string | undefined;\n}\n\nexport enum SchemaType {\n UNKNOWN = 0,\n ZOD = 1,\n JSON_SCHEMA = 2,\n}\n\nexport interface Schema {\n schema: string;\n schemaType: SchemaType;\n}\n\nexport interface WeightedValue {\n /** out of 1000 */\n weight: number;\n // eslint-disable-next-line no-use-before-define\n value: ConfigValue | undefined;\n}\n\nexport enum LimitResponse_LimitPolicyNames {\n SecondlyRolling = 1,\n MinutelyRolling = 3,\n HourlyRolling = 5,\n DailyRolling = 7,\n MonthlyRolling = 8,\n Infinite = 9,\n YearlyRolling = 10,\n}\n\nexport enum LimitDefinition_SafetyLevel {\n L4_BEST_EFFORT = 4,\n L5_BOMBPROOF = 5,\n}\n\nexport interface LimitDefinition {\n policyName: LimitResponse_LimitPolicyNames;\n limit: number;\n burst: number;\n accountId: number;\n lastModified: number;\n returnable: boolean;\n /** [default = L4_BEST_EFFORT]; // Overridable by request */\n safetyLevel: LimitDefinition_SafetyLevel;\n}\nexport interface WeightedValues {\n weightedValues: WeightedValue[];\n hashByPropertyName?: string | undefined;\n}\n\nexport type ConfigValue =\n | {\n int: number | undefined;\n }\n | {\n string: string | undefined;\n }\n | {\n bytes: Buffer | undefined;\n }\n | {\n double: number | undefined;\n }\n | {\n bool: boolean | undefined;\n }\n | {\n weightedValues?: WeightedValues | undefined;\n }\n | {\n limitDefinition?: LimitDefinition | undefined;\n }\n | {\n logLevel: ReforgeLogLevel | undefined;\n }\n | {\n stringList: string[] | undefined;\n }\n | {\n intRange: IntRange | undefined;\n }\n | {\n provided: Provided | undefined;\n }\n | {\n duration: Duration | undefined;\n }\n | {\n json: string | undefined;\n }\n | {\n schema: Schema | undefined;\n }\n | {\n /** don't log or telemetry this value */\n confidential: boolean | undefined;\n }\n | {\n /** key name to decrypt with */\n decryptWith: string | undefined;\n };\n\ntype Evaluation = {\n value: ConfigValue;\n configEvaluationMetadata: {\n configRowIndex: string | number;\n conditionalValueIndex: string | number;\n weightedValueIndex?: string | number;\n type: string;\n valueType: string;\n id: string;\n };\n};\n\nexport type EvaluationPayload = {\n evaluations: { [key: string]: Evaluation };\n apikeyMetadata: APIKeyMetadata;\n};\n\nconst parseRawMetadata = (metadata: any) => ({\n configRowIndex: parseInt(metadata.configRowIndex, 10),\n conditionalValueIndex: parseInt(metadata.conditionalValueIndex, 10),\n type: metadata.type,\n configId: metadata.id,\n});\n\nconst valueFor = <K extends keyof TypedFrontEndConfigurationRaw>(\n value: ConfigValue,\n type: keyof ConfigValue,\n key: K\n): TypedFrontEndConfigurationRaw[K] => {\n const rawValue = value[type];\n\n switch (type) {\n case \"json\":\n try {\n return JSON.parse(rawValue as string);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(`Error parsing JSON from Reforge config ${key}`, e, rawValue);\n return value[type];\n }\n case \"duration\": {\n const duration = rawValue as Duration;\n return {\n ms: duration.millis,\n seconds: duration.millis / 1000,\n };\n }\n default:\n return rawValue;\n }\n};\n\nexport const parseEvaluationPayload = (payload: EvaluationPayload) => {\n // eslint-disable-next-line no-use-before-define\n const configs = {} as { [key: string]: Config };\n Object.keys(payload.evaluations).forEach((key) => {\n const evaluation = payload.evaluations[key];\n\n const type = Object.keys(evaluation.value)[0] as keyof ConfigValue;\n\n // eslint-disable-next-line no-use-before-define\n configs[key] = new Config(\n key,\n valueFor(evaluation.value, type, key),\n type,\n evaluation.value,\n evaluation.configEvaluationMetadata\n ? parseRawMetadata(evaluation.configEvaluationMetadata)\n : undefined\n );\n });\n\n return configs;\n};\n\nconst parseRawConfigWithoutTypes = (payload: RawConfigWithoutTypes) => {\n // eslint-disable-next-line no-use-before-define\n const configs = {} as { [key: string]: Config };\n Object.keys(payload).forEach((key) => {\n const type = typeof payload[key] as keyof ConfigValue;\n // eslint-disable-next-line no-use-before-define\n configs[key] = new Config(key, valueFor({ [type]: payload[key] }, type, key), type);\n });\n\n return configs;\n};\n\nexport class Config<\n K extends keyof TypedFrontEndConfigurationRaw = keyof TypedFrontEndConfigurationRaw,\n> {\n key: K;\n\n value: TypedFrontEndConfigurationRaw[K];\n\n rawValue: ConfigValue | undefined;\n\n type: keyof ConfigValue;\n\n configEvaluationMetadata: ConfigEvaluationMetadata | undefined;\n\n constructor(\n key: K,\n value: TypedFrontEndConfigurationRaw[K],\n type: keyof ConfigValue,\n rawValue?: ConfigValue,\n metadata?: ConfigEvaluationMetadata\n ) {\n this.key = key;\n this.value = value;\n this.type = type;\n this.rawValue = rawValue;\n this.configEvaluationMetadata = metadata;\n }\n\n static digest(payload: EvaluationPayload | RawConfigWithoutTypes) {\n if (payload === undefined) {\n // eslint-disable-next-line no-console\n console.trace(\"Config.digest called with undefined payload\");\n }\n\n if (\"evaluations\" in payload) {\n return parseEvaluationPayload(payload as EvaluationPayload);\n }\n\n return parseRawConfigWithoutTypes(payload as RawConfigWithoutTypes);\n }\n}\n","const base64Encode = (obj: string) => {\n if (typeof window !== \"undefined\") {\n if (typeof TextEncoder === \"undefined\") {\n return window.btoa(obj);\n }\n\n const bytes = new TextEncoder().encode(obj);\n const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join(\"\");\n return btoa(binString);\n }\n\n return Buffer.from(obj).toString(\"base64\");\n};\n\nexport default base64Encode;\n","import { Contexts, ContextValue } from \"./types\";\nimport base64Encode from \"./base64Encode\";\n\nconst isEqual = (a: Contexts, b: Contexts) => {\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n return aKeys.every((key) => {\n const aValues = a[key];\n const bValues = b[key];\n\n const aValuesKeys = Object.keys(aValues);\n const bValuesKeys = Object.keys(bValues);\n\n if (aValuesKeys.length !== bValuesKeys.length) {\n return false;\n }\n\n return aValuesKeys.every((ckey) => {\n const aValue = aValues[ckey];\n const bValue = bValues[ckey];\n\n return aValue === bValue;\n });\n });\n};\n\nconst getType = (value: ContextValue) => {\n if (typeof value === \"string\") {\n return \"string\";\n }\n\n if (typeof value === \"number\") {\n if (Number.isInteger(value)) {\n return \"int\";\n }\n\n return \"double\";\n }\n\n return \"bool\";\n};\n\nexport default class Context {\n contexts: Contexts;\n\n constructor(contexts: Contexts) {\n if (!Object.values(contexts).every((item: any) => typeof item === \"object\")) {\n // eslint-disable-next-line no-console\n console.error(\"Context must be an object where the value of each key is also an object\");\n }\n\n if (\n Object.values(contexts).some((item: any) =>\n Object.values(item).some((value: any) => typeof value === \"object\" && value !== null)\n )\n ) {\n // we decided to allow null values, which requres an extra check since typeof null is object\n // eslint-disable-next-line no-console\n console.error(\"Nested objects are not supported in context values at this time\");\n }\n\n this.contexts = contexts;\n }\n\n equals(other: Context) {\n return isEqual(this.contexts, other.contexts);\n }\n\n encode() {\n const formatted = Object.keys(this.contexts).map((key) => {\n const values: Record<string, Record<string, ContextValue>> = {};\n\n Object.keys(this.contexts[key]).forEach((ckey) => {\n values[ckey] = {\n [getType(this.contexts[key][ckey])]: this.contexts[key][ckey],\n };\n });\n\n return {\n type: key,\n values,\n };\n });\n\n return encodeURIComponent(base64Encode(JSON.stringify({ contexts: formatted })));\n }\n}\n","export class ExponentialBackoff {\n private maxDelay: number;\n\n private multiplier: number;\n\n private delay: number;\n\n // arguments are in seconds\n constructor(maxDelay: number, initialDelay = 2, multiplier = 2) {\n this.maxDelay = maxDelay;\n this.multiplier = multiplier;\n this.delay = initialDelay;\n }\n\n call(): number {\n const delayValue = this.delay;\n this.delay = Math.min(this.delay * this.multiplier, this.maxDelay);\n return delayValue * 1000;\n }\n}\n","import { TypedFrontEndConfigurationRaw } from \"./types\";\n\nexport const PREFIX = \"log-level\";\nexport enum ReforgeLogLevel {\n Trace = 1,\n Debug = 2,\n Info = 3,\n Warn = 4,\n Error = 5,\n Fatal = 6,\n}\n\nexport type LogLevelWord = Uppercase<keyof typeof ReforgeLogLevel>;\n\nconst WORD_LEVEL_LOOKUP: Readonly<Record<LogLevelWord, ReforgeLogLevel>> = {\n TRACE: ReforgeLogLevel.Trace,\n DEBUG: ReforgeLogLevel.Debug,\n INFO: ReforgeLogLevel.Info,\n WARN: ReforgeLogLevel.Warn,\n ERROR: ReforgeLogLevel.Error,\n FATAL: ReforgeLogLevel.Fatal,\n};\n\nexport const isValidLogLevel = (possibleLogLevel: string) =>\n Object.keys(WORD_LEVEL_LOOKUP).includes(possibleLogLevel.toUpperCase());\n\nexport interface ShouldLogParams {\n loggerName: string;\n desiredLevel: ReforgeLogLevel;\n defaultLevel: ReforgeLogLevel;\n get: <K extends keyof TypedFrontEndConfigurationRaw>(key: K) => TypedFrontEndConfigurationRaw[K];\n}\n\nexport const shouldLog = ({\n loggerName,\n desiredLevel,\n defaultLevel,\n get,\n}: ShouldLogParams): boolean => {\n let loggerNameWithPrefix = `${PREFIX}.${loggerName}`;\n\n while (loggerNameWithPrefix.length > 0) {\n const resolvedLevel = get(loggerNameWithPrefix);\n\n if (resolvedLevel) {\n return (\n WORD_LEVEL_LOOKUP[resolvedLevel.toString().toUpperCase() as LogLevelWord] <= desiredLevel\n );\n }\n\n if (loggerNameWithPrefix.indexOf(\".\") === -1) {\n break;\n }\n\n loggerNameWithPrefix = loggerNameWithPrefix.slice(0, loggerNameWithPrefix.lastIndexOf(\".\"));\n }\n\n return defaultLevel <= desiredLevel;\n};\n","import { ExponentialBackoff } from \"./exponentialBackoff\";\nimport { ReforgeLogLevel } from \"./logger\";\nimport { type reforge } from \"./reforge\";\n\nabstract class PeriodicSync<T> {\n protected data: Map<string, T> = new Map();\n\n private startAt: Date;\n\n private syncInterval: any;\n\n protected client: typeof reforge;\n\n private name: string;\n\n private timeoutID: ReturnType<typeof setTimeout> | undefined;\n\n constructor(client: typeof reforge, name: string, syncInterval?: number) {\n this.client = client;\n this.name = name;\n\n this.startAt = new Date();\n\n this.startPeriodicSync(syncInterval);\n }\n\n stop(): void {\n clearTimeout(this.timeoutID);\n }\n\n sync(): void {\n if (this.data.size === 0) return;\n\n this.logInternal(`${this.name} syncing ${this.data.size} items`);\n\n const startAtWas = this.startAt;\n this.startAt = new Date();\n\n this.flush(this.prepareData(), startAtWas);\n }\n\n protected abstract flush(toShip: Map<string, T>, startAtWas: Date): void;\n\n private prepareData(): Map<string, T> {\n const toShip = new Map(this.data);\n this.data.clear();\n\n return toShip;\n }\n\n private startPeriodicSync(syncInterval?: number): void {\n this.startAt = new Date();\n this.syncInterval = PeriodicSync.calculateSyncInterval(syncInterval);\n\n this.scheduleNextSync();\n }\n\n private scheduleNextSync() {\n const interval = this.syncInterval();\n this.timeoutID = setTimeout(() => {\n this.sync();\n this.scheduleNextSync(); // Schedule the next sync after the current one completes\n }, interval);\n }\n\n private static calculateSyncInterval(syncInterval?: number): any {\n if (syncInterval !== undefined) {\n return () => syncInterval;\n }\n\n const backoff = new ExponentialBackoff(60 * 5, 8);\n return () => backoff.call();\n }\n\n protected logInternal(message: string): void {\n const loggerName = `${this.client.clientNameString}.reforge.${this.name}`;\n\n if (\n this.client.shouldLog(\n {\n loggerName,\n desiredLevel: ReforgeLogLevel.Debug,\n defaultLevel: ReforgeLogLevel.Error,\n },\n false // synchronous so that this log ends up in the current batch\n )\n ) {\n // eslint-disable-next-line no-console\n console.log(`${loggerName}: ${message}`);\n }\n }\n}\n\nexport { PeriodicSync };\n","// TODO: should we retry the data chunk if a flush fails?\n\n// TODO: pause when offline?\n\n// TODO: flush when we receive a config update (or as a result of a context update...but that should trigger a config update anyway)\n\nimport { PeriodicSync } from \"./periodicSync\";\nimport { Config } from \"./config\";\nimport { type reforge } from \"./reforge\";\nimport {\n ConfigEvaluationCounter,\n ConfigEvaluationSummaries,\n ConfigEvaluationSummary,\n TelemetryEvents,\n ConfigEvaluationMetadata,\n} from \"./types\";\n\nexport const massageSelectedValue = (config: Config): any => {\n if (config.rawValue && (config.type === \"duration\" || config.type === \"json\")) {\n if (config.type === \"json\") {\n return { json: config.rawValue[config.type] };\n }\n\n return config.rawValue[config.type];\n }\n\n return config.type === \"stringList\" ? { values: config.value } : config.value;\n};\n\nexport const massageConfigForTelemetry = (\n config: Config,\n metadata: Omit<ConfigEvaluationMetadata, \"type\">\n) => ({\n ...metadata,\n selectedValue: {\n [config.type]: massageSelectedValue(config),\n },\n count: 0,\n});\n\nclass EvaluationSummaryAggregator extends PeriodicSync<ConfigEvaluationCounter> {\n private maxKeys: number;\n\n constructor(client: typeof reforge, maxKeys: number, syncInterval?: number) {\n super(client, \"EvaluationSummaryAggregator\", syncInterval ?? 30000);\n\n this.maxKeys = maxKeys;\n }\n\n record(config: Config): void {\n if (this.data.size >= this.maxKeys) return;\n\n if (config?.configEvaluationMetadata) {\n const { type, ...metadata } = config.configEvaluationMetadata;\n const key = `${config.key},${type}`;\n\n // create counter entry if it doesn't exist\n if (!this.data.has(key)) {\n this.data.set(key, massageConfigForTelemetry(config, metadata));\n }\n\n // increment count\n const counter = this.data.get(key);\n if (counter) {\n counter.count += 1;\n }\n }\n }\n\n protected flush(toShip: Map<string, ConfigEvaluationCounter>, startAtWas: Date): void {\n const summaries = {\n start: startAtWas.getTime(),\n end: new Date().getTime(),\n summaries: EvaluationSummaryAggregator.summaries(toShip),\n };\n\n this.client.telemetryUploader?.post(this.events(summaries));\n }\n\n private static summaries(data: Map<string, ConfigEvaluationCounter>): ConfigEvaluationSummary[] {\n return Array.from(data).map((entry: [string, ConfigEvaluationCounter]) => {\n const [configKey, configType] = entry[0].split(\",\");\n const counter = entry[1];\n const counters = [counter]; // this client only ever has one set of counter info per key\n\n return {\n key: configKey,\n type: configType,\n counters,\n };\n });\n }\n\n private events(summaries: ConfigEvaluationSummaries): TelemetryEvents {\n const event = { summaries };\n\n return {\n instanceHash: this.client.instanceHash,\n events: [event],\n };\n }\n}\n\nexport { EvaluationSummaryAggregator };\n","import base64Encode from \"./base64Encode\";\n\nexport const headers = (sdkKey: string, clientVersion: string) => ({\n Authorization: `Basic ${base64Encode(`u:${sdkKey}`)}`,\n \"X-Reforge-SDK-Version\": clientVersion,\n});\n\nexport const DEFAULT_TIMEOUT = 10000;\n","import { DEFAULT_TIMEOUT, headers } from \"./apiHelpers\";\nimport { EvaluationPayload } from \"./config\";\nimport Context from \"./context\";\n\nexport type CollectContextModeType = \"NONE\" | \"SHAPE_ONLY\" | \"PERIODIC_EXAMPLE\";\n\nexport type LoaderParams = {\n sdkKey: string;\n context: Context;\n endpoints?: string[] | undefined;\n timeout?: number;\n collectContextMode?: CollectContextModeType;\n clientVersion?: string;\n};\n\nexport type Headers = {\n [key: string]: string;\n};\n\nexport type FetchOptions = {\n headers: Headers;\n};\n\nconst defaultEndpoints = [\n \"https://primary.reforge.com/api/v2\",\n \"https://secondary.reforge.com/api/v2\",\n];\n\nconst EARLY_TIMEOUT = 2000;\n\nexport default class Loader {\n sdkKey: string;\n\n context: Context;\n\n endpoints: string[];\n\n timeout: number;\n\n abortTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n collectContextMode: CollectContextModeType = \"PERIODIC_EXAMPLE\";\n\n clientVersion: string;\n\n abortController: AbortController | undefined;\n\n isAborted = false;\n\n constructor({\n sdkKey,\n context,\n endpoints = undefined,\n timeout,\n collectContextMode = \"PERIODIC_EXAMPLE\",\n clientVersion = \"\",\n }: LoaderParams) {\n this.sdkKey = sdkKey;\n this.context = context;\n this.endpoints = endpoints || defaultEndpoints;\n this.timeout = timeout || DEFAULT_TIMEOUT;\n this.collectContextMode = collectContextMode;\n this.clientVersion = clientVersion;\n }\n\n url(root: string) {\n return `${root}/configs/eval-with-context/${this.context.encode()}?collectContextMode=${\n this.collectContextMode\n }`;\n }\n\n loadFromEndpoint(\n index: number,\n options: FetchOptions,\n resolve: (value: any) => void,\n reject: (value: any) => void\n ) {\n this.abortController = new AbortController() as AbortController;\n const { signal } = this.abortController;\n this.isAborted = false;\n\n const endpoint = this.endpoints[index];\n const url = this.url(endpoint);\n\n fetch(url, { signal, ...options })\n .then((response) => {\n this.clearAbortTimeout();\n\n if (response.ok) {\n return response.json();\n }\n throw new Error(`${response.status} ${response.statusText}`);\n })\n .then((data) => {\n if (!(\"evaluations\" in data)) {\n throw new Error(`Invalid payload:${JSON.stringify(data)}`);\n }\n\n resolve(data as EvaluationPayload);\n })\n .catch((error) => {\n this.clearAbortTimeout();\n\n if (index < this.endpoints.length - 1) {\n this.loadFromEndpoint(index + 1, options, resolve, reject);\n } else {\n reject(error);\n }\n });\n\n // Use an early timeout if we're not on the last endpoint. But if the user-provided timeout is less than EARLY_TIMEOUT, use that\n const timeout =\n index < this.endpoints.length - 1 ? Math.min(this.timeout, EARLY_TIMEOUT) : this.timeout;\n\n this.abortTimeoutId = setTimeout(() => {\n if (!this.isAborted) {\n this.isAborted = true;\n this.abortController?.abort();\n }\n }, timeout);\n }\n\n load() {\n if (!this.isAborted) {\n this.isAborted = true;\n this.abortController?.abort();\n }\n\n const options = {\n headers: headers(this.sdkKey, this.clientVersion),\n };\n\n const promise = new Promise((resolve, reject) => {\n this.loadFromEndpoint(0, options, resolve, reject);\n });\n\n return promise;\n }\n\n clearAbortTimeout() {\n clearTimeout(this.abortTimeoutId);\n }\n}\n","import { DEFAULT_TIMEOUT, headers } from \"./apiHelpers\";\nimport { TelemetryEvents } from \"./types\";\n\nexport type TelemetryUploaderParams = {\n sdkKey: string;\n apiEndpoint?: string;\n timeout?: number;\n clientVersion: string;\n};\n\nexport default class TelemetryUploader {\n sdkKey: Required<TelemetryUploaderParams>[\"sdkKey\"];\n\n apiEndpoint: Required<TelemetryUploaderParams>[\"apiEndpoint\"];\n\n timeout: Required<TelemetryUploaderParams>[\"timeout\"];\n\n clientVersion: Required<TelemetryUploaderParams>[\"clientVersion\"];\n\n abortTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n constructor({\n sdkKey,\n apiEndpoint = undefined,\n timeout,\n clientVersion,\n }: TelemetryUploaderParams) {\n this.sdkKey = sdkKey;\n this.apiEndpoint = apiEndpoint || \"https://telemetry.prefab.cloud/api/v1\";\n this.timeout = timeout || DEFAULT_TIMEOUT;\n this.clientVersion = clientVersion;\n }\n\n clearAbortTimeout() {\n clearTimeout(this.abortTimeoutId);\n }\n\n static postUrl(root: string) {\n return `${root}/telemetry`;\n }\n\n postToEndpoint(\n options: RequestInit,\n resolve: (value: unknown) => void,\n reject: (value: unknown) => void\n ) {\n const controller = new AbortController() as AbortController;\n const signal = controller?.signal;\n let isAborted = false;\n\n const url = TelemetryUploader.postUrl(this.apiEndpoint);\n\n fetch(url, { signal, ...options })\n .then((response) => {\n this.clearAbortTimeout();\n\n if (response.ok) {\n return response.json();\n }\n\n // eslint-disable-next-line no-console\n console.warn(\n `Reforge warning: Error uploading telemetry ${response.status} ${response.statusText}`\n );\n\n return response.status;\n })\n .then((response) => {\n resolve(response);\n })\n .catch((error) => {\n this.clearAbortTimeout();\n\n // Silently handle AbortErrors (from timeouts or page navigations)\n if (error.name === \"AbortError\") {\n try {\n // eslint-disable-next-line no-console\n console.debug(\"Reforge telemetry request aborted\");\n } catch (e) {\n // no-op\n }\n resolve({ status: \"aborted\" });\n return;\n }\n\n reject(error);\n });\n\n this.abortTimeoutId = setTimeout(() => {\n if (!isAborted) {\n isAborted = true;\n controller.abort();\n }\n }, this.timeout);\n }\n\n post(data: TelemetryEvents) {\n const options = {\n method: \"POST\",\n headers: {\n ...headers(this.sdkKey, this.clientVersion),\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify(data),\n keepalive: true, // needed for flushing when the window is closed\n };\n\n const promise = new Promise((resolve, reject) => {\n this.postToEndpoint(options, resolve, reject);\n });\n\n return promise;\n }\n}\n","// TODO: should we retry the data chunk if a flush fails?\n\n// TODO: pause when offline?\n\nimport { ReforgeLogLevel } from \"./logger\";\nimport { PeriodicSync } from \"./periodicSync\";\nimport { type reforge } from \"./reforge\";\nimport { LoggerCounter, LoggersTelemetryEvent, TelemetryEvents } from \"./types\";\n\nconst SEVERITY_KEY: { [key in ReforgeLogLevel]: Omit<keyof LoggerCounter, \"loggerName\"> } = {\n [ReforgeLogLevel.Trace]: \"traces\",\n [ReforgeLogLevel.Debug]: \"debugs\",\n [ReforgeLogLevel.Info]: \"infos\",\n [ReforgeLogLevel.Warn]: \"warns\",\n [ReforgeLogLevel.Error]: \"errors\",\n [ReforgeLogLevel.Fatal]: \"fatals\",\n};\n\nclass LoggerAggregator extends PeriodicSync<LoggerCounter> {\n private maxLoggers: number;\n\n constructor(client: typeof reforge, maxLoggers: number, syncInterval?: number) {\n super(client, \"LoggerAggregator\", syncInterval ?? 30000);\n\n this.maxLoggers = maxLoggers;\n }\n\n record(logger: string, level: ReforgeLogLevel): void {\n if (this.data.size >= this.maxLoggers) return;\n\n // create counter entry if it doesn't exist\n if (!this.data.has(logger)) {\n this.data.set(logger, {\n loggerName: logger,\n traces: 0,\n debugs: 0,\n infos: 0,\n warns: 0,\n errors: 0,\n fatals: 0,\n });\n }\n\n // increment count\n const counter = this.data.get(logger);\n if (counter) {\n const severityKey = SEVERITY_KEY[level] as keyof LoggerCounter;\n (counter[severityKey] as number) += 1;\n }\n }\n\n protected flush(toShip: Map<string, LoggerCounter>, startAtWas: Date): void {\n const loggers = {\n startAt: startAtWas.getTime(),\n endAt: new Date().getTime(),\n loggers: Array.from(toShip.values()),\n };\n\n this.client.telemetryUploader?.post(this.events(loggers));\n }\n\n private events(loggers: LoggersTelemetryEvent): TelemetryEvents {\n const event = { loggers };\n\n return {\n instanceHash: this.client.instanceHash,\n events: [event],\n };\n }\n}\n\nexport { LoggerAggregator };\n"],"mappings":"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","names":["exports","module","version","uuid","version"]} |
+2
-1
@@ -63,3 +63,3 @@ var __defProp = Object.defineProperty; | ||
| name: "@reforge-com/javascript", | ||
| version: "0.0.1", | ||
| version: "0.0.2", | ||
| description: "Feature Flags & Dynamic Configuration as a Service", | ||
@@ -78,2 +78,3 @@ main: "dist/index.cjs", | ||
| "@typescript-eslint/parser": "^5.33.0", | ||
| esbuild: "^0.25.11", | ||
| eslint: "^8.21.0", | ||
@@ -80,0 +81,0 @@ "eslint-config-airbnb": "^19.0.4", |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../package.json","../src/reforge.ts","../src/config.ts","../src/base64Encode.ts","../src/context.ts","../src/exponentialBackoff.ts","../src/logger.ts","../src/periodicSync.ts","../src/evaluationSummaryAggregator.ts","../src/apiHelpers.ts","../src/loader.ts","../src/telemetryUploader.ts","../src/loggerAggregator.ts","../index.ts"],"sourcesContent":["{\n \"packageManager\": \"yarn@4.9.2\",\n \"name\": \"@reforge-com/javascript\",\n \"version\": \"0.0.1\",\n \"description\": \"Feature Flags & Dynamic Configuration as a Service\",\n \"main\": \"dist/index.cjs\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"author\": \"Jeffrey Chupp\",\n \"license\": \"ISC\",\n \"devDependencies\": {\n \"@types/eslint-plugin-jsx-a11y\": \"^6\",\n \"@types/express\": \"^4.17.13\",\n \"@types/jest\": \"^28.1.6\",\n \"@types/uuid\": \"^9.0.5\",\n \"@typescript-eslint/eslint-plugin\": \"^5.33.0\",\n \"@typescript-eslint/parser\": \"^5.33.0\",\n \"eslint\": \"^8.21.0\",\n \"eslint-config-airbnb\": \"^19.0.4\",\n \"eslint-config-airbnb-typescript\": \"^17.0.0\",\n \"eslint-config-prettier\": \"^8.8.0\",\n \"eslint-plugin-import\": \"^2.26.0\",\n \"eslint-plugin-jest\": \"^26.8.0\",\n \"eslint-plugin-jsx-a11y\": \"^6.10.2\",\n \"eslint-plugin-react\": \"^7.37.5\",\n \"jest\": \"^29.0.0\",\n \"jest-fetch-mock\": \"^3.0.3\",\n \"prettier\": \"^3.0.0\",\n \"ts-jest\": \"^29.1.1\",\n \"ts-node\": \"^10.9.1\",\n \"tsup\": \"^8.0.2\",\n \"typescript\": \"^5.1.6\"\n },\n \"scripts\": {\n \"build\": \"rm -rf dist/ && tsup\",\n \"dev\": \"tsup --watch\",\n \"bundle\": \"esbuild --minify --target=esnext --bundle --outfile=dist/reforge.bundle.js --global-name=window.reforgeNamespace dist/index.cjs && echo 'window.reforge = window.reforgeNamespace.reforge' >> dist/reforge.bundle.js\",\n \"lint\": \"eslint --ext .ts,.tsx src/\",\n \"lint:fix\": \"eslint --fix --ext .ts,.tsx src/\",\n \"prettier\": \"prettier . -l\",\n \"prettier:fix\": \"prettier --write .\",\n \"test\": \"jest --verbose\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/ReforgeHQ/sdk-javascript.git\"\n },\n \"keywords\": [\n \"feature-flags\",\n \"config\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/ReforgeHQ/sdk-javascript/issues\"\n },\n \"homepage\": \"https://github.com/ReforgeHQ/sdk-javascript#readme\",\n \"dependencies\": {\n \"uuid\": \"^9.0.1\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n }\n }\n}\n","import { v4 as uuid } from \"uuid\";\n\nimport { Config, EvaluationPayload, RawConfigWithoutTypes } from \"./config\";\nimport type {\n Duration,\n TypedFrontEndConfigurationRaw,\n FrontEndConfigurationRaw,\n Contexts,\n} from \"./types\";\nimport Context from \"./context\";\nimport { EvaluationSummaryAggregator } from \"./evaluationSummaryAggregator\";\nimport Loader, { CollectContextModeType } from \"./loader\";\nimport { PREFIX as loggerPrefix, shouldLog, ShouldLogParams } from \"./logger\";\nimport TelemetryUploader from \"./telemetryUploader\";\nimport { LoggerAggregator } from \"./loggerAggregator\";\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { version } = require(\"../package.json\");\n\ntype EvaluationCallback = <K extends keyof TypedFrontEndConfigurationRaw>(\n key: K,\n value: TypedFrontEndConfigurationRaw[K],\n context: Context | undefined\n) => void;\n\nexport interface ReforgeBootstrap {\n evaluations: EvaluationPayload;\n context: Contexts;\n}\n\nexport type ReforgeInitParams = {\n sdkKey: string;\n context: Context;\n endpoints?: string[] | undefined;\n apiEndpoint?: string;\n timeout?: number;\n afterEvaluationCallback?: EvaluationCallback;\n collectEvaluationSummaries?: boolean;\n collectLoggerNames?: boolean;\n collectContextMode?: CollectContextModeType;\n clientNameString?: string;\n clientVersionString?: string;\n};\n\ntype PollStatus =\n | { status: \"not-started\" }\n | { status: \"pending\" }\n | { status: \"stopped\" }\n | { status: \"running\"; frequencyInMs: number };\n\ntype PublicShouldLogParams = Omit<ShouldLogParams, \"get\">;\n\nexport class Reforge {\n private _configs: { [key: string]: Config } = {};\n\n private _telemetryUploader: TelemetryUploader | undefined;\n\n private _pollCount = 0;\n\n private _pollStatus: PollStatus = { status: \"not-started\" };\n\n private _pollTimeoutId = undefined as ReturnType<typeof setTimeout> | undefined;\n\n private _instanceHash: string = uuid();\n\n private collectEvaluationSummaries = true;\n\n private collectLoggerNames = false;\n\n private evalutionSummaryAggregator: EvaluationSummaryAggregator | undefined;\n\n private loggerAggregator: LoggerAggregator | undefined;\n\n public clientNameString = \"sdk-javascript\";\n\n public loaded = false;\n\n public loader: Loader | undefined;\n\n public afterEvaluationCallback = (() => {}) as EvaluationCallback;\n\n private _context: Context = new Context({});\n\n async init({\n sdkKey,\n context: providedContext,\n endpoints = undefined,\n apiEndpoint,\n timeout = undefined,\n afterEvaluationCallback = () => {},\n collectEvaluationSummaries = true,\n collectLoggerNames = false,\n collectContextMode = \"PERIODIC_EXAMPLE\",\n clientNameString = \"sdk-javascript\",\n clientVersionString = version,\n }: ReforgeInitParams) {\n const context = providedContext ?? this.context;\n\n if (!context) {\n throw new Error(\"Context must be provided\");\n }\n\n this._context = context;\n\n this.clientNameString = clientNameString;\n const clientNameAndVersionString = `${clientNameString}-${clientVersionString}`;\n\n this.loader = new Loader({\n sdkKey,\n context,\n endpoints,\n timeout,\n collectContextMode,\n clientVersion: clientNameAndVersionString,\n });\n\n this._telemetryUploader = new TelemetryUploader({\n sdkKey,\n apiEndpoint,\n timeout,\n clientVersion: clientNameAndVersionString,\n });\n\n this.collectEvaluationSummaries = collectEvaluationSummaries;\n if (collectEvaluationSummaries) {\n this.evalutionSummaryAggregator = new EvaluationSummaryAggregator(this, 100000);\n }\n\n this.collectLoggerNames = collectLoggerNames;\n if (collectLoggerNames) {\n this.loggerAggregator = new LoggerAggregator(this, 100000);\n }\n\n if (\n (collectEvaluationSummaries || collectLoggerNames) &&\n typeof window !== \"undefined\" &&\n typeof window.addEventListener === \"function\"\n ) {\n window.addEventListener(\"beforeunload\", () => {\n this.evalutionSummaryAggregator?.sync();\n this.loggerAggregator?.sync();\n });\n }\n\n this.afterEvaluationCallback = afterEvaluationCallback;\n\n return this.load();\n }\n\n public extract(): Record<string, Config[\"value\"]> {\n return Object.entries(this._configs).reduce(\n (agg, [key, value]) => ({\n ...agg,\n [key]: value.value,\n }),\n {} as Record<string, Config[\"value\"]>\n );\n }\n\n public hydrate(rawValues: RawConfigWithoutTypes | EvaluationPayload): void {\n this.setConfigPrivate(rawValues);\n }\n\n get context(): Context {\n return this._context;\n }\n\n get instanceHash(): string {\n return this._instanceHash;\n }\n\n get pollTimeoutId() {\n return this._pollTimeoutId;\n }\n\n get pollCount() {\n return this._pollCount;\n }\n\n get pollStatus() {\n return this._pollStatus;\n }\n\n get telemetryUploader(): TelemetryUploader | undefined {\n return this._telemetryUploader;\n }\n\n private async load() {\n if (!this.loader || !this.context) {\n throw new Error(\"Reforge not initialized. Call init() first.\");\n }\n\n /* eslint-disable no-underscore-dangle */\n if (globalThis && (globalThis as any)._reforgeBootstrap) {\n /* eslint-disable no-underscore-dangle */\n const reforgeBootstrap = (globalThis as any)._reforgeBootstrap as ReforgeBootstrap;\n const bootstrapContext = new Context(reforgeBootstrap.context);\n\n if (this.context.equals(bootstrapContext)) {\n this.setConfigPrivate({ evaluations: reforgeBootstrap.evaluations });\n return Promise.resolve();\n }\n }\n\n // make sure we have the freshest context\n this.loader.context = this.context;\n\n return this.loader\n .load()\n .then((rawValues: any) => {\n this.setConfigPrivate(rawValues as EvaluationPayload);\n })\n .finally(() => {\n if (this.pollStatus.status === \"running\") {\n this._pollCount += 1;\n }\n });\n }\n\n async updateContext(context: Context, skipLoad = false) {\n if (!this.loader) {\n throw new Error(\"Reforge not initialized. Call init() first.\");\n }\n\n this._context = context;\n\n if (skipLoad) {\n return Promise.resolve();\n }\n\n return this.load();\n }\n\n async poll({ frequencyInMs }: { frequencyInMs: number }) {\n if (!this.loader) {\n throw new Error(\"Reforge not initialized. Call init() first.\");\n }\n\n this.stopPolling();\n\n this._pollStatus = { status: \"pending\" };\n\n return this.loader.load().finally(() => {\n this.doPolling({ frequencyInMs });\n });\n }\n\n private doPolling({ frequencyInMs }: { frequencyInMs: number }) {\n this._pollTimeoutId = setTimeout(() => {\n this.load().finally(() => {\n if (this.pollStatus.status === \"running\") {\n this.doPolling({ frequencyInMs });\n }\n });\n }, frequencyInMs);\n\n this._pollStatus = {\n status: \"running\",\n frequencyInMs,\n };\n }\n\n stopPolling() {\n if (this.pollTimeoutId) {\n clearTimeout(this.pollTimeoutId);\n this._pollTimeoutId = undefined;\n }\n\n this._pollStatus = { status: \"stopped\" };\n }\n\n stopTelemetry() {\n if (this.telemetryUploader) {\n this.evalutionSummaryAggregator?.stop();\n this.loggerAggregator?.stop();\n }\n }\n\n private setConfigPrivate(rawValues: RawConfigWithoutTypes | EvaluationPayload) {\n this._configs = Config.digest(rawValues);\n this.loaded = true;\n }\n\n isEnabled<\n // We need to calcuate these live and not store in a type to ensure dynamic evaluation\n // in upstream libraries that override the FrontEndConfigurationRaw interface\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends boolean\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(key: K): boolean {\n return this.get(key) === true;\n }\n\n get<K extends keyof TypedFrontEndConfigurationRaw>(key: K): TypedFrontEndConfigurationRaw[K] {\n if (!this.loaded) {\n if (!key.startsWith(loggerPrefix)) {\n // eslint-disable-next-line no-console\n console.warn(\n `Reforge warning: The client has not finished loading data yet. Unable to look up actual value for key \"${key}\".`\n );\n }\n\n return undefined;\n }\n\n const config = this._configs[key];\n\n const value = config?.value;\n\n if (!key.startsWith(loggerPrefix)) {\n if (this.collectEvaluationSummaries) {\n setTimeout(() => this.evalutionSummaryAggregator?.record(config));\n }\n\n setTimeout(() => this.afterEvaluationCallback(key, value, this.context));\n }\n\n return value;\n }\n\n getDuration<\n // We need to calcuate these live and not store in a type to ensure dynamic evaluation\n // in upstream libraries that override the FrontEndConfigurationRaw interface\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends Duration\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(key: K): Duration | undefined {\n const value = this.get(key);\n\n if (!value) {\n return undefined;\n }\n\n if (\n !Object.prototype.hasOwnProperty.call(value, \"seconds\") ||\n !Object.prototype.hasOwnProperty.call(value, \"ms\")\n ) {\n throw new Error(`Value for key \"${key}\" is not a duration`);\n }\n\n return value as Duration;\n }\n\n shouldLog(args: PublicShouldLogParams, async = true): boolean {\n if (this.collectLoggerNames) {\n const record = () => this.loggerAggregator?.record(args.loggerName, args.desiredLevel);\n if (async) {\n setTimeout(record);\n } else {\n record();\n }\n }\n\n return shouldLog({ ...args, get: this.get.bind(this) });\n }\n\n isCollectingEvaluationSummaries(): boolean {\n return this.collectEvaluationSummaries;\n }\n\n isCollectingLoggerNames(): boolean {\n return this.collectLoggerNames;\n }\n}\n\nexport const reforge = new Reforge();\n","import { ReforgeLogLevel } from \"./logger\";\nimport { TypedFrontEndConfigurationRaw, ConfigEvaluationMetadata } from \"./types\";\n\nexport type RawConfigWithoutTypes = Record<string, any>;\n\ntype APIKeyMetadata = {\n id: string | number;\n};\n\n// TODO: Why is this definition different from the one in ./types.ts?\ntype Duration = {\n definition: string;\n millis: number;\n};\n\nexport interface IntRange {\n /** if empty treat as Number.MIN_VALUE. Inclusive */\n start?: bigint | undefined;\n /** if empty treat as Number.MAX_VALUE. Exclusive */\n end?: bigint | undefined;\n}\n\nexport enum ProvidedSource {\n EnvVar = \"ENV_VAR\",\n}\nexport interface Provided {\n source?: ProvidedSource | undefined;\n /** eg MY_ENV_VAR */\n lookup?: string | undefined;\n}\n\nexport enum SchemaType {\n UNKNOWN = 0,\n ZOD = 1,\n JSON_SCHEMA = 2,\n}\n\nexport interface Schema {\n schema: string;\n schemaType: SchemaType;\n}\n\nexport interface WeightedValue {\n /** out of 1000 */\n weight: number;\n // eslint-disable-next-line no-use-before-define\n value: ConfigValue | undefined;\n}\n\nexport enum LimitResponse_LimitPolicyNames {\n SecondlyRolling = 1,\n MinutelyRolling = 3,\n HourlyRolling = 5,\n DailyRolling = 7,\n MonthlyRolling = 8,\n Infinite = 9,\n YearlyRolling = 10,\n}\n\nexport enum LimitDefinition_SafetyLevel {\n L4_BEST_EFFORT = 4,\n L5_BOMBPROOF = 5,\n}\n\nexport interface LimitDefinition {\n policyName: LimitResponse_LimitPolicyNames;\n limit: number;\n burst: number;\n accountId: number;\n lastModified: number;\n returnable: boolean;\n /** [default = L4_BEST_EFFORT]; // Overridable by request */\n safetyLevel: LimitDefinition_SafetyLevel;\n}\nexport interface WeightedValues {\n weightedValues: WeightedValue[];\n hashByPropertyName?: string | undefined;\n}\n\nexport type ConfigValue =\n | {\n int: number | undefined;\n }\n | {\n string: string | undefined;\n }\n | {\n bytes: Buffer | undefined;\n }\n | {\n double: number | undefined;\n }\n | {\n bool: boolean | undefined;\n }\n | {\n weightedValues?: WeightedValues | undefined;\n }\n | {\n limitDefinition?: LimitDefinition | undefined;\n }\n | {\n logLevel: ReforgeLogLevel | undefined;\n }\n | {\n stringList: string[] | undefined;\n }\n | {\n intRange: IntRange | undefined;\n }\n | {\n provided: Provided | undefined;\n }\n | {\n duration: Duration | undefined;\n }\n | {\n json: string | undefined;\n }\n | {\n schema: Schema | undefined;\n }\n | {\n /** don't log or telemetry this value */\n confidential: boolean | undefined;\n }\n | {\n /** key name to decrypt with */\n decryptWith: string | undefined;\n };\n\ntype Evaluation = {\n value: ConfigValue;\n configEvaluationMetadata: {\n configRowIndex: string | number;\n conditionalValueIndex: string | number;\n weightedValueIndex?: string | number;\n type: string;\n valueType: string;\n id: string;\n };\n};\n\nexport type EvaluationPayload = {\n evaluations: { [key: string]: Evaluation };\n apikeyMetadata: APIKeyMetadata;\n};\n\nconst parseRawMetadata = (metadata: any) => ({\n configRowIndex: parseInt(metadata.configRowIndex, 10),\n conditionalValueIndex: parseInt(metadata.conditionalValueIndex, 10),\n type: metadata.type,\n configId: metadata.id,\n});\n\nconst valueFor = <K extends keyof TypedFrontEndConfigurationRaw>(\n value: ConfigValue,\n type: keyof ConfigValue,\n key: K\n): TypedFrontEndConfigurationRaw[K] => {\n const rawValue = value[type];\n\n switch (type) {\n case \"json\":\n try {\n return JSON.parse(rawValue as string);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(`Error parsing JSON from Reforge config ${key}`, e, rawValue);\n return value[type];\n }\n case \"duration\": {\n const duration = rawValue as Duration;\n return {\n ms: duration.millis,\n seconds: duration.millis / 1000,\n };\n }\n default:\n return rawValue;\n }\n};\n\nexport const parseEvaluationPayload = (payload: EvaluationPayload) => {\n // eslint-disable-next-line no-use-before-define\n const configs = {} as { [key: string]: Config };\n Object.keys(payload.evaluations).forEach((key) => {\n const evaluation = payload.evaluations[key];\n\n const type = Object.keys(evaluation.value)[0] as keyof ConfigValue;\n\n // eslint-disable-next-line no-use-before-define\n configs[key] = new Config(\n key,\n valueFor(evaluation.value, type, key),\n type,\n evaluation.value,\n evaluation.configEvaluationMetadata\n ? parseRawMetadata(evaluation.configEvaluationMetadata)\n : undefined\n );\n });\n\n return configs;\n};\n\nconst parseRawConfigWithoutTypes = (payload: RawConfigWithoutTypes) => {\n // eslint-disable-next-line no-use-before-define\n const configs = {} as { [key: string]: Config };\n Object.keys(payload).forEach((key) => {\n const type = typeof payload[key] as keyof ConfigValue;\n // eslint-disable-next-line no-use-before-define\n configs[key] = new Config(key, valueFor({ [type]: payload[key] }, type, key), type);\n });\n\n return configs;\n};\n\nexport class Config<\n K extends keyof TypedFrontEndConfigurationRaw = keyof TypedFrontEndConfigurationRaw,\n> {\n key: K;\n\n value: TypedFrontEndConfigurationRaw[K];\n\n rawValue: ConfigValue | undefined;\n\n type: keyof ConfigValue;\n\n configEvaluationMetadata: ConfigEvaluationMetadata | undefined;\n\n constructor(\n key: K,\n value: TypedFrontEndConfigurationRaw[K],\n type: keyof ConfigValue,\n rawValue?: ConfigValue,\n metadata?: ConfigEvaluationMetadata\n ) {\n this.key = key;\n this.value = value;\n this.type = type;\n this.rawValue = rawValue;\n this.configEvaluationMetadata = metadata;\n }\n\n static digest(payload: EvaluationPayload | RawConfigWithoutTypes) {\n if (payload === undefined) {\n // eslint-disable-next-line no-console\n console.trace(\"Config.digest called with undefined payload\");\n }\n\n if (\"evaluations\" in payload) {\n return parseEvaluationPayload(payload as EvaluationPayload);\n }\n\n return parseRawConfigWithoutTypes(payload as RawConfigWithoutTypes);\n }\n}\n","const base64Encode = (obj: string) => {\n if (typeof window !== \"undefined\") {\n if (typeof TextEncoder === \"undefined\") {\n return window.btoa(obj);\n }\n\n const bytes = new TextEncoder().encode(obj);\n const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join(\"\");\n return btoa(binString);\n }\n\n return Buffer.from(obj).toString(\"base64\");\n};\n\nexport default base64Encode;\n","import { Contexts, ContextValue } from \"./types\";\nimport base64Encode from \"./base64Encode\";\n\nconst isEqual = (a: Contexts, b: Contexts) => {\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n return aKeys.every((key) => {\n const aValues = a[key];\n const bValues = b[key];\n\n const aValuesKeys = Object.keys(aValues);\n const bValuesKeys = Object.keys(bValues);\n\n if (aValuesKeys.length !== bValuesKeys.length) {\n return false;\n }\n\n return aValuesKeys.every((ckey) => {\n const aValue = aValues[ckey];\n const bValue = bValues[ckey];\n\n return aValue === bValue;\n });\n });\n};\n\nconst getType = (value: ContextValue) => {\n if (typeof value === \"string\") {\n return \"string\";\n }\n\n if (typeof value === \"number\") {\n if (Number.isInteger(value)) {\n return \"int\";\n }\n\n return \"double\";\n }\n\n return \"bool\";\n};\n\nexport default class Context {\n contexts: Contexts;\n\n constructor(contexts: Contexts) {\n if (!Object.values(contexts).every((item: any) => typeof item === \"object\")) {\n // eslint-disable-next-line no-console\n console.error(\"Context must be an object where the value of each key is also an object\");\n }\n\n if (\n Object.values(contexts).some((item: any) =>\n Object.values(item).some((value: any) => typeof value === \"object\" && value !== null)\n )\n ) {\n // we decided to allow null values, which requres an extra check since typeof null is object\n // eslint-disable-next-line no-console\n console.error(\"Nested objects are not supported in context values at this time\");\n }\n\n this.contexts = contexts;\n }\n\n equals(other: Context) {\n return isEqual(this.contexts, other.contexts);\n }\n\n encode() {\n const formatted = Object.keys(this.contexts).map((key) => {\n const values: Record<string, Record<string, ContextValue>> = {};\n\n Object.keys(this.contexts[key]).forEach((ckey) => {\n values[ckey] = {\n [getType(this.contexts[key][ckey])]: this.contexts[key][ckey],\n };\n });\n\n return {\n type: key,\n values,\n };\n });\n\n return encodeURIComponent(base64Encode(JSON.stringify({ contexts: formatted })));\n }\n}\n","export class ExponentialBackoff {\n private maxDelay: number;\n\n private multiplier: number;\n\n private delay: number;\n\n // arguments are in seconds\n constructor(maxDelay: number, initialDelay = 2, multiplier = 2) {\n this.maxDelay = maxDelay;\n this.multiplier = multiplier;\n this.delay = initialDelay;\n }\n\n call(): number {\n const delayValue = this.delay;\n this.delay = Math.min(this.delay * this.multiplier, this.maxDelay);\n return delayValue * 1000;\n }\n}\n","import { TypedFrontEndConfigurationRaw } from \"./types\";\n\nexport const PREFIX = \"log-level\";\nexport enum ReforgeLogLevel {\n Trace = 1,\n Debug = 2,\n Info = 3,\n Warn = 4,\n Error = 5,\n Fatal = 6,\n}\n\nexport type LogLevelWord = Uppercase<keyof typeof ReforgeLogLevel>;\n\nconst WORD_LEVEL_LOOKUP: Readonly<Record<LogLevelWord, ReforgeLogLevel>> = {\n TRACE: ReforgeLogLevel.Trace,\n DEBUG: ReforgeLogLevel.Debug,\n INFO: ReforgeLogLevel.Info,\n WARN: ReforgeLogLevel.Warn,\n ERROR: ReforgeLogLevel.Error,\n FATAL: ReforgeLogLevel.Fatal,\n};\n\nexport const isValidLogLevel = (possibleLogLevel: string) =>\n Object.keys(WORD_LEVEL_LOOKUP).includes(possibleLogLevel.toUpperCase());\n\nexport interface ShouldLogParams {\n loggerName: string;\n desiredLevel: ReforgeLogLevel;\n defaultLevel: ReforgeLogLevel;\n get: <K extends keyof TypedFrontEndConfigurationRaw>(key: K) => TypedFrontEndConfigurationRaw[K];\n}\n\nexport const shouldLog = ({\n loggerName,\n desiredLevel,\n defaultLevel,\n get,\n}: ShouldLogParams): boolean => {\n let loggerNameWithPrefix = `${PREFIX}.${loggerName}`;\n\n while (loggerNameWithPrefix.length > 0) {\n const resolvedLevel = get(loggerNameWithPrefix);\n\n if (resolvedLevel) {\n return (\n WORD_LEVEL_LOOKUP[resolvedLevel.toString().toUpperCase() as LogLevelWord] <= desiredLevel\n );\n }\n\n if (loggerNameWithPrefix.indexOf(\".\") === -1) {\n break;\n }\n\n loggerNameWithPrefix = loggerNameWithPrefix.slice(0, loggerNameWithPrefix.lastIndexOf(\".\"));\n }\n\n return defaultLevel <= desiredLevel;\n};\n","import { ExponentialBackoff } from \"./exponentialBackoff\";\nimport { ReforgeLogLevel } from \"./logger\";\nimport { type reforge } from \"./reforge\";\n\nabstract class PeriodicSync<T> {\n protected data: Map<string, T> = new Map();\n\n private startAt: Date;\n\n private syncInterval: any;\n\n protected client: typeof reforge;\n\n private name: string;\n\n private timeoutID: ReturnType<typeof setTimeout> | undefined;\n\n constructor(client: typeof reforge, name: string, syncInterval?: number) {\n this.client = client;\n this.name = name;\n\n this.startAt = new Date();\n\n this.startPeriodicSync(syncInterval);\n }\n\n stop(): void {\n clearTimeout(this.timeoutID);\n }\n\n sync(): void {\n if (this.data.size === 0) return;\n\n this.logInternal(`${this.name} syncing ${this.data.size} items`);\n\n const startAtWas = this.startAt;\n this.startAt = new Date();\n\n this.flush(this.prepareData(), startAtWas);\n }\n\n protected abstract flush(toShip: Map<string, T>, startAtWas: Date): void;\n\n private prepareData(): Map<string, T> {\n const toShip = new Map(this.data);\n this.data.clear();\n\n return toShip;\n }\n\n private startPeriodicSync(syncInterval?: number): void {\n this.startAt = new Date();\n this.syncInterval = PeriodicSync.calculateSyncInterval(syncInterval);\n\n this.scheduleNextSync();\n }\n\n private scheduleNextSync() {\n const interval = this.syncInterval();\n this.timeoutID = setTimeout(() => {\n this.sync();\n this.scheduleNextSync(); // Schedule the next sync after the current one completes\n }, interval);\n }\n\n private static calculateSyncInterval(syncInterval?: number): any {\n if (syncInterval !== undefined) {\n return () => syncInterval;\n }\n\n const backoff = new ExponentialBackoff(60 * 5, 8);\n return () => backoff.call();\n }\n\n protected logInternal(message: string): void {\n const loggerName = `${this.client.clientNameString}.reforge.${this.name}`;\n\n if (\n this.client.shouldLog(\n {\n loggerName,\n desiredLevel: ReforgeLogLevel.Debug,\n defaultLevel: ReforgeLogLevel.Error,\n },\n false // synchronous so that this log ends up in the current batch\n )\n ) {\n // eslint-disable-next-line no-console\n console.log(`${loggerName}: ${message}`);\n }\n }\n}\n\nexport { PeriodicSync };\n","// TODO: should we retry the data chunk if a flush fails?\n\n// TODO: pause when offline?\n\n// TODO: flush when we receive a config update (or as a result of a context update...but that should trigger a config update anyway)\n\nimport { PeriodicSync } from \"./periodicSync\";\nimport { Config } from \"./config\";\nimport { type reforge } from \"./reforge\";\nimport {\n ConfigEvaluationCounter,\n ConfigEvaluationSummaries,\n ConfigEvaluationSummary,\n TelemetryEvents,\n ConfigEvaluationMetadata,\n} from \"./types\";\n\nexport const massageSelectedValue = (config: Config): any => {\n if (config.rawValue && (config.type === \"duration\" || config.type === \"json\")) {\n if (config.type === \"json\") {\n return { json: config.rawValue[config.type] };\n }\n\n return config.rawValue[config.type];\n }\n\n return config.type === \"stringList\" ? { values: config.value } : config.value;\n};\n\nexport const massageConfigForTelemetry = (\n config: Config,\n metadata: Omit<ConfigEvaluationMetadata, \"type\">\n) => ({\n ...metadata,\n selectedValue: {\n [config.type]: massageSelectedValue(config),\n },\n count: 0,\n});\n\nclass EvaluationSummaryAggregator extends PeriodicSync<ConfigEvaluationCounter> {\n private maxKeys: number;\n\n constructor(client: typeof reforge, maxKeys: number, syncInterval?: number) {\n super(client, \"EvaluationSummaryAggregator\", syncInterval ?? 30000);\n\n this.maxKeys = maxKeys;\n }\n\n record(config: Config): void {\n if (this.data.size >= this.maxKeys) return;\n\n if (config?.configEvaluationMetadata) {\n const { type, ...metadata } = config.configEvaluationMetadata;\n const key = `${config.key},${type}`;\n\n // create counter entry if it doesn't exist\n if (!this.data.has(key)) {\n this.data.set(key, massageConfigForTelemetry(config, metadata));\n }\n\n // increment count\n const counter = this.data.get(key);\n if (counter) {\n counter.count += 1;\n }\n }\n }\n\n protected flush(toShip: Map<string, ConfigEvaluationCounter>, startAtWas: Date): void {\n const summaries = {\n start: startAtWas.getTime(),\n end: new Date().getTime(),\n summaries: EvaluationSummaryAggregator.summaries(toShip),\n };\n\n this.client.telemetryUploader?.post(this.events(summaries));\n }\n\n private static summaries(data: Map<string, ConfigEvaluationCounter>): ConfigEvaluationSummary[] {\n return Array.from(data).map((entry: [string, ConfigEvaluationCounter]) => {\n const [configKey, configType] = entry[0].split(\",\");\n const counter = entry[1];\n const counters = [counter]; // this client only ever has one set of counter info per key\n\n return {\n key: configKey,\n type: configType,\n counters,\n };\n });\n }\n\n private events(summaries: ConfigEvaluationSummaries): TelemetryEvents {\n const event = { summaries };\n\n return {\n instanceHash: this.client.instanceHash,\n events: [event],\n };\n }\n}\n\nexport { EvaluationSummaryAggregator };\n","import base64Encode from \"./base64Encode\";\n\nexport const headers = (sdkKey: string, clientVersion: string) => ({\n Authorization: `Basic ${base64Encode(`u:${sdkKey}`)}`,\n \"X-Reforge-SDK-Version\": clientVersion,\n});\n\nexport const DEFAULT_TIMEOUT = 10000;\n","import { DEFAULT_TIMEOUT, headers } from \"./apiHelpers\";\nimport { EvaluationPayload } from \"./config\";\nimport Context from \"./context\";\n\nexport type CollectContextModeType = \"NONE\" | \"SHAPE_ONLY\" | \"PERIODIC_EXAMPLE\";\n\nexport type LoaderParams = {\n sdkKey: string;\n context: Context;\n endpoints?: string[] | undefined;\n timeout?: number;\n collectContextMode?: CollectContextModeType;\n clientVersion?: string;\n};\n\nexport type Headers = {\n [key: string]: string;\n};\n\nexport type FetchOptions = {\n headers: Headers;\n};\n\nconst defaultEndpoints = [\n \"https://primary.reforge.com/api/v2\",\n \"https://secondary.reforge.com/api/v2\",\n];\n\nconst EARLY_TIMEOUT = 2000;\n\nexport default class Loader {\n sdkKey: string;\n\n context: Context;\n\n endpoints: string[];\n\n timeout: number;\n\n abortTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n collectContextMode: CollectContextModeType = \"PERIODIC_EXAMPLE\";\n\n clientVersion: string;\n\n abortController: AbortController | undefined;\n\n isAborted = false;\n\n constructor({\n sdkKey,\n context,\n endpoints = undefined,\n timeout,\n collectContextMode = \"PERIODIC_EXAMPLE\",\n clientVersion = \"\",\n }: LoaderParams) {\n this.sdkKey = sdkKey;\n this.context = context;\n this.endpoints = endpoints || defaultEndpoints;\n this.timeout = timeout || DEFAULT_TIMEOUT;\n this.collectContextMode = collectContextMode;\n this.clientVersion = clientVersion;\n }\n\n url(root: string) {\n return `${root}/configs/eval-with-context/${this.context.encode()}?collectContextMode=${\n this.collectContextMode\n }`;\n }\n\n loadFromEndpoint(\n index: number,\n options: FetchOptions,\n resolve: (value: any) => void,\n reject: (value: any) => void\n ) {\n this.abortController = new AbortController() as AbortController;\n const { signal } = this.abortController;\n this.isAborted = false;\n\n const endpoint = this.endpoints[index];\n const url = this.url(endpoint);\n\n fetch(url, { signal, ...options })\n .then((response) => {\n this.clearAbortTimeout();\n\n if (response.ok) {\n return response.json();\n }\n throw new Error(`${response.status} ${response.statusText}`);\n })\n .then((data) => {\n if (!(\"evaluations\" in data)) {\n throw new Error(`Invalid payload:${JSON.stringify(data)}`);\n }\n\n resolve(data as EvaluationPayload);\n })\n .catch((error) => {\n this.clearAbortTimeout();\n\n if (index < this.endpoints.length - 1) {\n this.loadFromEndpoint(index + 1, options, resolve, reject);\n } else {\n reject(error);\n }\n });\n\n // Use an early timeout if we're not on the last endpoint. But if the user-provided timeout is less than EARLY_TIMEOUT, use that\n const timeout =\n index < this.endpoints.length - 1 ? Math.min(this.timeout, EARLY_TIMEOUT) : this.timeout;\n\n this.abortTimeoutId = setTimeout(() => {\n if (!this.isAborted) {\n this.isAborted = true;\n this.abortController?.abort();\n }\n }, timeout);\n }\n\n load() {\n if (!this.isAborted) {\n this.isAborted = true;\n this.abortController?.abort();\n }\n\n const options = {\n headers: headers(this.sdkKey, this.clientVersion),\n };\n\n const promise = new Promise((resolve, reject) => {\n this.loadFromEndpoint(0, options, resolve, reject);\n });\n\n return promise;\n }\n\n clearAbortTimeout() {\n clearTimeout(this.abortTimeoutId);\n }\n}\n","import { DEFAULT_TIMEOUT, headers } from \"./apiHelpers\";\nimport { TelemetryEvents } from \"./types\";\n\nexport type TelemetryUploaderParams = {\n sdkKey: string;\n apiEndpoint?: string;\n timeout?: number;\n clientVersion: string;\n};\n\nexport default class TelemetryUploader {\n sdkKey: Required<TelemetryUploaderParams>[\"sdkKey\"];\n\n apiEndpoint: Required<TelemetryUploaderParams>[\"apiEndpoint\"];\n\n timeout: Required<TelemetryUploaderParams>[\"timeout\"];\n\n clientVersion: Required<TelemetryUploaderParams>[\"clientVersion\"];\n\n abortTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n constructor({\n sdkKey,\n apiEndpoint = undefined,\n timeout,\n clientVersion,\n }: TelemetryUploaderParams) {\n this.sdkKey = sdkKey;\n this.apiEndpoint = apiEndpoint || \"https://telemetry.prefab.cloud/api/v1\";\n this.timeout = timeout || DEFAULT_TIMEOUT;\n this.clientVersion = clientVersion;\n }\n\n clearAbortTimeout() {\n clearTimeout(this.abortTimeoutId);\n }\n\n static postUrl(root: string) {\n return `${root}/telemetry`;\n }\n\n postToEndpoint(\n options: RequestInit,\n resolve: (value: unknown) => void,\n reject: (value: unknown) => void\n ) {\n const controller = new AbortController() as AbortController;\n const signal = controller?.signal;\n let isAborted = false;\n\n const url = TelemetryUploader.postUrl(this.apiEndpoint);\n\n fetch(url, { signal, ...options })\n .then((response) => {\n this.clearAbortTimeout();\n\n if (response.ok) {\n return response.json();\n }\n\n // eslint-disable-next-line no-console\n console.warn(\n `Reforge warning: Error uploading telemetry ${response.status} ${response.statusText}`\n );\n\n return response.status;\n })\n .then((response) => {\n resolve(response);\n })\n .catch((error) => {\n this.clearAbortTimeout();\n\n // Silently handle AbortErrors (from timeouts or page navigations)\n if (error.name === \"AbortError\") {\n try {\n // eslint-disable-next-line no-console\n console.debug(\"Reforge telemetry request aborted\");\n } catch (e) {\n // no-op\n }\n resolve({ status: \"aborted\" });\n return;\n }\n\n reject(error);\n });\n\n this.abortTimeoutId = setTimeout(() => {\n if (!isAborted) {\n isAborted = true;\n controller.abort();\n }\n }, this.timeout);\n }\n\n post(data: TelemetryEvents) {\n const options = {\n method: \"POST\",\n headers: {\n ...headers(this.sdkKey, this.clientVersion),\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify(data),\n keepalive: true, // needed for flushing when the window is closed\n };\n\n const promise = new Promise((resolve, reject) => {\n this.postToEndpoint(options, resolve, reject);\n });\n\n return promise;\n }\n}\n","// TODO: should we retry the data chunk if a flush fails?\n\n// TODO: pause when offline?\n\nimport { ReforgeLogLevel } from \"./logger\";\nimport { PeriodicSync } from \"./periodicSync\";\nimport { type reforge } from \"./reforge\";\nimport { LoggerCounter, LoggersTelemetryEvent, TelemetryEvents } from \"./types\";\n\nconst SEVERITY_KEY: { [key in ReforgeLogLevel]: Omit<keyof LoggerCounter, \"loggerName\"> } = {\n [ReforgeLogLevel.Trace]: \"traces\",\n [ReforgeLogLevel.Debug]: \"debugs\",\n [ReforgeLogLevel.Info]: \"infos\",\n [ReforgeLogLevel.Warn]: \"warns\",\n [ReforgeLogLevel.Error]: \"errors\",\n [ReforgeLogLevel.Fatal]: \"fatals\",\n};\n\nclass LoggerAggregator extends PeriodicSync<LoggerCounter> {\n private maxLoggers: number;\n\n constructor(client: typeof reforge, maxLoggers: number, syncInterval?: number) {\n super(client, \"LoggerAggregator\", syncInterval ?? 30000);\n\n this.maxLoggers = maxLoggers;\n }\n\n record(logger: string, level: ReforgeLogLevel): void {\n if (this.data.size >= this.maxLoggers) return;\n\n // create counter entry if it doesn't exist\n if (!this.data.has(logger)) {\n this.data.set(logger, {\n loggerName: logger,\n traces: 0,\n debugs: 0,\n infos: 0,\n warns: 0,\n errors: 0,\n fatals: 0,\n });\n }\n\n // increment count\n const counter = this.data.get(logger);\n if (counter) {\n const severityKey = SEVERITY_KEY[level] as keyof LoggerCounter;\n (counter[severityKey] as number) += 1;\n }\n }\n\n protected flush(toShip: Map<string, LoggerCounter>, startAtWas: Date): void {\n const loggers = {\n startAt: startAtWas.getTime(),\n endAt: new Date().getTime(),\n loggers: Array.from(toShip.values()),\n };\n\n this.client.telemetryUploader?.post(this.events(loggers));\n }\n\n private events(loggers: LoggersTelemetryEvent): TelemetryEvents {\n const event = { loggers };\n\n return {\n instanceHash: this.client.instanceHash,\n events: [event],\n };\n }\n}\n\nexport { LoggerAggregator };\n","import { reforge, Reforge, ReforgeInitParams, ReforgeBootstrap } from \"./src/reforge\";\nimport { Config } from \"./src/config\";\nimport Context from \"./src/context\";\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { version } = require(\"./package.json\");\n\nexport { reforge, Reforge, ReforgeInitParams, Config, Context, version };\n\nexport { ReforgeBootstrap };\n\nexport type { ConfigValue } from \"./src/config\";\nexport type {\n Duration,\n ContextValue,\n Contexts,\n TypedFrontEndConfigurationRaw,\n FrontEndConfigurationRaw,\n} from \"./src/types\";\nexport type { CollectContextModeType } from \"./src/loader\";\n"],"mappings":"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","names":["version"]} | ||
| {"version":3,"sources":["../package.json","../src/reforge.ts","../src/config.ts","../src/base64Encode.ts","../src/context.ts","../src/exponentialBackoff.ts","../src/logger.ts","../src/periodicSync.ts","../src/evaluationSummaryAggregator.ts","../src/apiHelpers.ts","../src/loader.ts","../src/telemetryUploader.ts","../src/loggerAggregator.ts","../index.ts"],"sourcesContent":["{\n \"packageManager\": \"yarn@4.9.2\",\n \"name\": \"@reforge-com/javascript\",\n \"version\": \"0.0.2\",\n \"description\": \"Feature Flags & Dynamic Configuration as a Service\",\n \"main\": \"dist/index.cjs\",\n \"module\": \"dist/index.mjs\",\n \"types\": \"dist/index.d.ts\",\n \"author\": \"Jeffrey Chupp\",\n \"license\": \"ISC\",\n \"devDependencies\": {\n \"@types/eslint-plugin-jsx-a11y\": \"^6\",\n \"@types/express\": \"^4.17.13\",\n \"@types/jest\": \"^28.1.6\",\n \"@types/uuid\": \"^9.0.5\",\n \"@typescript-eslint/eslint-plugin\": \"^5.33.0\",\n \"@typescript-eslint/parser\": \"^5.33.0\",\n \"esbuild\": \"^0.25.11\",\n \"eslint\": \"^8.21.0\",\n \"eslint-config-airbnb\": \"^19.0.4\",\n \"eslint-config-airbnb-typescript\": \"^17.0.0\",\n \"eslint-config-prettier\": \"^8.8.0\",\n \"eslint-plugin-import\": \"^2.26.0\",\n \"eslint-plugin-jest\": \"^26.8.0\",\n \"eslint-plugin-jsx-a11y\": \"^6.10.2\",\n \"eslint-plugin-react\": \"^7.37.5\",\n \"jest\": \"^29.0.0\",\n \"jest-fetch-mock\": \"^3.0.3\",\n \"prettier\": \"^3.0.0\",\n \"ts-jest\": \"^29.1.1\",\n \"ts-node\": \"^10.9.1\",\n \"tsup\": \"^8.0.2\",\n \"typescript\": \"^5.1.6\"\n },\n \"scripts\": {\n \"build\": \"rm -rf dist/ && tsup\",\n \"dev\": \"tsup --watch\",\n \"bundle\": \"esbuild --minify --target=esnext --bundle --outfile=dist/reforge.bundle.js --global-name=window.reforgeNamespace dist/index.cjs && echo 'window.reforge = window.reforgeNamespace.reforge' >> dist/reforge.bundle.js\",\n \"lint\": \"eslint --ext .ts,.tsx src/\",\n \"lint:fix\": \"eslint --fix --ext .ts,.tsx src/\",\n \"prettier\": \"prettier . -l\",\n \"prettier:fix\": \"prettier --write .\",\n \"test\": \"jest --verbose\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/ReforgeHQ/sdk-javascript.git\"\n },\n \"keywords\": [\n \"feature-flags\",\n \"config\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/ReforgeHQ/sdk-javascript/issues\"\n },\n \"homepage\": \"https://github.com/ReforgeHQ/sdk-javascript#readme\",\n \"dependencies\": {\n \"uuid\": \"^9.0.1\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n }\n }\n}\n","import { v4 as uuid } from \"uuid\";\n\nimport { Config, EvaluationPayload, RawConfigWithoutTypes } from \"./config\";\nimport type {\n Duration,\n TypedFrontEndConfigurationRaw,\n FrontEndConfigurationRaw,\n Contexts,\n} from \"./types\";\nimport Context from \"./context\";\nimport { EvaluationSummaryAggregator } from \"./evaluationSummaryAggregator\";\nimport Loader, { CollectContextModeType } from \"./loader\";\nimport { PREFIX as loggerPrefix, shouldLog, ShouldLogParams } from \"./logger\";\nimport TelemetryUploader from \"./telemetryUploader\";\nimport { LoggerAggregator } from \"./loggerAggregator\";\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { version } = require(\"../package.json\");\n\ntype EvaluationCallback = <K extends keyof TypedFrontEndConfigurationRaw>(\n key: K,\n value: TypedFrontEndConfigurationRaw[K],\n context: Context | undefined\n) => void;\n\nexport interface ReforgeBootstrap {\n evaluations: EvaluationPayload;\n context: Contexts;\n}\n\nexport type ReforgeInitParams = {\n sdkKey: string;\n context: Context;\n endpoints?: string[] | undefined;\n apiEndpoint?: string;\n timeout?: number;\n afterEvaluationCallback?: EvaluationCallback;\n collectEvaluationSummaries?: boolean;\n collectLoggerNames?: boolean;\n collectContextMode?: CollectContextModeType;\n clientNameString?: string;\n clientVersionString?: string;\n};\n\ntype PollStatus =\n | { status: \"not-started\" }\n | { status: \"pending\" }\n | { status: \"stopped\" }\n | { status: \"running\"; frequencyInMs: number };\n\ntype PublicShouldLogParams = Omit<ShouldLogParams, \"get\">;\n\nexport class Reforge {\n private _configs: { [key: string]: Config } = {};\n\n private _telemetryUploader: TelemetryUploader | undefined;\n\n private _pollCount = 0;\n\n private _pollStatus: PollStatus = { status: \"not-started\" };\n\n private _pollTimeoutId = undefined as ReturnType<typeof setTimeout> | undefined;\n\n private _instanceHash: string = uuid();\n\n private collectEvaluationSummaries = true;\n\n private collectLoggerNames = false;\n\n private evalutionSummaryAggregator: EvaluationSummaryAggregator | undefined;\n\n private loggerAggregator: LoggerAggregator | undefined;\n\n public clientNameString = \"sdk-javascript\";\n\n public loaded = false;\n\n public loader: Loader | undefined;\n\n public afterEvaluationCallback = (() => {}) as EvaluationCallback;\n\n private _context: Context = new Context({});\n\n async init({\n sdkKey,\n context: providedContext,\n endpoints = undefined,\n apiEndpoint,\n timeout = undefined,\n afterEvaluationCallback = () => {},\n collectEvaluationSummaries = true,\n collectLoggerNames = false,\n collectContextMode = \"PERIODIC_EXAMPLE\",\n clientNameString = \"sdk-javascript\",\n clientVersionString = version,\n }: ReforgeInitParams) {\n const context = providedContext ?? this.context;\n\n if (!context) {\n throw new Error(\"Context must be provided\");\n }\n\n this._context = context;\n\n this.clientNameString = clientNameString;\n const clientNameAndVersionString = `${clientNameString}-${clientVersionString}`;\n\n this.loader = new Loader({\n sdkKey,\n context,\n endpoints,\n timeout,\n collectContextMode,\n clientVersion: clientNameAndVersionString,\n });\n\n this._telemetryUploader = new TelemetryUploader({\n sdkKey,\n apiEndpoint,\n timeout,\n clientVersion: clientNameAndVersionString,\n });\n\n this.collectEvaluationSummaries = collectEvaluationSummaries;\n if (collectEvaluationSummaries) {\n this.evalutionSummaryAggregator = new EvaluationSummaryAggregator(this, 100000);\n }\n\n this.collectLoggerNames = collectLoggerNames;\n if (collectLoggerNames) {\n this.loggerAggregator = new LoggerAggregator(this, 100000);\n }\n\n if (\n (collectEvaluationSummaries || collectLoggerNames) &&\n typeof window !== \"undefined\" &&\n typeof window.addEventListener === \"function\"\n ) {\n window.addEventListener(\"beforeunload\", () => {\n this.evalutionSummaryAggregator?.sync();\n this.loggerAggregator?.sync();\n });\n }\n\n this.afterEvaluationCallback = afterEvaluationCallback;\n\n return this.load();\n }\n\n public extract(): Record<string, Config[\"value\"]> {\n return Object.entries(this._configs).reduce(\n (agg, [key, value]) => ({\n ...agg,\n [key]: value.value,\n }),\n {} as Record<string, Config[\"value\"]>\n );\n }\n\n public hydrate(rawValues: RawConfigWithoutTypes | EvaluationPayload): void {\n this.setConfigPrivate(rawValues);\n }\n\n get context(): Context {\n return this._context;\n }\n\n get instanceHash(): string {\n return this._instanceHash;\n }\n\n get pollTimeoutId() {\n return this._pollTimeoutId;\n }\n\n get pollCount() {\n return this._pollCount;\n }\n\n get pollStatus() {\n return this._pollStatus;\n }\n\n get telemetryUploader(): TelemetryUploader | undefined {\n return this._telemetryUploader;\n }\n\n private async load() {\n if (!this.loader || !this.context) {\n throw new Error(\"Reforge not initialized. Call init() first.\");\n }\n\n /* eslint-disable no-underscore-dangle */\n if (globalThis && (globalThis as any)._reforgeBootstrap) {\n /* eslint-disable no-underscore-dangle */\n const reforgeBootstrap = (globalThis as any)._reforgeBootstrap as ReforgeBootstrap;\n const bootstrapContext = new Context(reforgeBootstrap.context);\n\n if (this.context.equals(bootstrapContext)) {\n this.setConfigPrivate({ evaluations: reforgeBootstrap.evaluations });\n return Promise.resolve();\n }\n }\n\n // make sure we have the freshest context\n this.loader.context = this.context;\n\n return this.loader\n .load()\n .then((rawValues: any) => {\n this.setConfigPrivate(rawValues as EvaluationPayload);\n })\n .finally(() => {\n if (this.pollStatus.status === \"running\") {\n this._pollCount += 1;\n }\n });\n }\n\n async updateContext(context: Context, skipLoad = false) {\n if (!this.loader) {\n throw new Error(\"Reforge not initialized. Call init() first.\");\n }\n\n this._context = context;\n\n if (skipLoad) {\n return Promise.resolve();\n }\n\n return this.load();\n }\n\n async poll({ frequencyInMs }: { frequencyInMs: number }) {\n if (!this.loader) {\n throw new Error(\"Reforge not initialized. Call init() first.\");\n }\n\n this.stopPolling();\n\n this._pollStatus = { status: \"pending\" };\n\n return this.loader.load().finally(() => {\n this.doPolling({ frequencyInMs });\n });\n }\n\n private doPolling({ frequencyInMs }: { frequencyInMs: number }) {\n this._pollTimeoutId = setTimeout(() => {\n this.load().finally(() => {\n if (this.pollStatus.status === \"running\") {\n this.doPolling({ frequencyInMs });\n }\n });\n }, frequencyInMs);\n\n this._pollStatus = {\n status: \"running\",\n frequencyInMs,\n };\n }\n\n stopPolling() {\n if (this.pollTimeoutId) {\n clearTimeout(this.pollTimeoutId);\n this._pollTimeoutId = undefined;\n }\n\n this._pollStatus = { status: \"stopped\" };\n }\n\n stopTelemetry() {\n if (this.telemetryUploader) {\n this.evalutionSummaryAggregator?.stop();\n this.loggerAggregator?.stop();\n }\n }\n\n private setConfigPrivate(rawValues: RawConfigWithoutTypes | EvaluationPayload) {\n this._configs = Config.digest(rawValues);\n this.loaded = true;\n }\n\n isEnabled<\n // We need to calcuate these live and not store in a type to ensure dynamic evaluation\n // in upstream libraries that override the FrontEndConfigurationRaw interface\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends boolean\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(key: K): boolean {\n return this.get(key) === true;\n }\n\n get<K extends keyof TypedFrontEndConfigurationRaw>(key: K): TypedFrontEndConfigurationRaw[K] {\n if (!this.loaded) {\n if (!key.startsWith(loggerPrefix)) {\n // eslint-disable-next-line no-console\n console.warn(\n `Reforge warning: The client has not finished loading data yet. Unable to look up actual value for key \"${key}\".`\n );\n }\n\n return undefined;\n }\n\n const config = this._configs[key];\n\n const value = config?.value;\n\n if (!key.startsWith(loggerPrefix)) {\n if (this.collectEvaluationSummaries) {\n setTimeout(() => this.evalutionSummaryAggregator?.record(config));\n }\n\n setTimeout(() => this.afterEvaluationCallback(key, value, this.context));\n }\n\n return value;\n }\n\n getDuration<\n // We need to calcuate these live and not store in a type to ensure dynamic evaluation\n // in upstream libraries that override the FrontEndConfigurationRaw interface\n K extends keyof FrontEndConfigurationRaw extends never\n ? string\n : {\n [IK in keyof TypedFrontEndConfigurationRaw]: TypedFrontEndConfigurationRaw[IK] extends Duration\n ? IK\n : never;\n }[keyof TypedFrontEndConfigurationRaw],\n >(key: K): Duration | undefined {\n const value = this.get(key);\n\n if (!value) {\n return undefined;\n }\n\n if (\n !Object.prototype.hasOwnProperty.call(value, \"seconds\") ||\n !Object.prototype.hasOwnProperty.call(value, \"ms\")\n ) {\n throw new Error(`Value for key \"${key}\" is not a duration`);\n }\n\n return value as Duration;\n }\n\n shouldLog(args: PublicShouldLogParams, async = true): boolean {\n if (this.collectLoggerNames) {\n const record = () => this.loggerAggregator?.record(args.loggerName, args.desiredLevel);\n if (async) {\n setTimeout(record);\n } else {\n record();\n }\n }\n\n return shouldLog({ ...args, get: this.get.bind(this) });\n }\n\n isCollectingEvaluationSummaries(): boolean {\n return this.collectEvaluationSummaries;\n }\n\n isCollectingLoggerNames(): boolean {\n return this.collectLoggerNames;\n }\n}\n\nexport const reforge = new Reforge();\n","import { ReforgeLogLevel } from \"./logger\";\nimport { TypedFrontEndConfigurationRaw, ConfigEvaluationMetadata } from \"./types\";\n\nexport type RawConfigWithoutTypes = Record<string, any>;\n\ntype APIKeyMetadata = {\n id: string | number;\n};\n\n// TODO: Why is this definition different from the one in ./types.ts?\ntype Duration = {\n definition: string;\n millis: number;\n};\n\nexport interface IntRange {\n /** if empty treat as Number.MIN_VALUE. Inclusive */\n start?: bigint | undefined;\n /** if empty treat as Number.MAX_VALUE. Exclusive */\n end?: bigint | undefined;\n}\n\nexport enum ProvidedSource {\n EnvVar = \"ENV_VAR\",\n}\nexport interface Provided {\n source?: ProvidedSource | undefined;\n /** eg MY_ENV_VAR */\n lookup?: string | undefined;\n}\n\nexport enum SchemaType {\n UNKNOWN = 0,\n ZOD = 1,\n JSON_SCHEMA = 2,\n}\n\nexport interface Schema {\n schema: string;\n schemaType: SchemaType;\n}\n\nexport interface WeightedValue {\n /** out of 1000 */\n weight: number;\n // eslint-disable-next-line no-use-before-define\n value: ConfigValue | undefined;\n}\n\nexport enum LimitResponse_LimitPolicyNames {\n SecondlyRolling = 1,\n MinutelyRolling = 3,\n HourlyRolling = 5,\n DailyRolling = 7,\n MonthlyRolling = 8,\n Infinite = 9,\n YearlyRolling = 10,\n}\n\nexport enum LimitDefinition_SafetyLevel {\n L4_BEST_EFFORT = 4,\n L5_BOMBPROOF = 5,\n}\n\nexport interface LimitDefinition {\n policyName: LimitResponse_LimitPolicyNames;\n limit: number;\n burst: number;\n accountId: number;\n lastModified: number;\n returnable: boolean;\n /** [default = L4_BEST_EFFORT]; // Overridable by request */\n safetyLevel: LimitDefinition_SafetyLevel;\n}\nexport interface WeightedValues {\n weightedValues: WeightedValue[];\n hashByPropertyName?: string | undefined;\n}\n\nexport type ConfigValue =\n | {\n int: number | undefined;\n }\n | {\n string: string | undefined;\n }\n | {\n bytes: Buffer | undefined;\n }\n | {\n double: number | undefined;\n }\n | {\n bool: boolean | undefined;\n }\n | {\n weightedValues?: WeightedValues | undefined;\n }\n | {\n limitDefinition?: LimitDefinition | undefined;\n }\n | {\n logLevel: ReforgeLogLevel | undefined;\n }\n | {\n stringList: string[] | undefined;\n }\n | {\n intRange: IntRange | undefined;\n }\n | {\n provided: Provided | undefined;\n }\n | {\n duration: Duration | undefined;\n }\n | {\n json: string | undefined;\n }\n | {\n schema: Schema | undefined;\n }\n | {\n /** don't log or telemetry this value */\n confidential: boolean | undefined;\n }\n | {\n /** key name to decrypt with */\n decryptWith: string | undefined;\n };\n\ntype Evaluation = {\n value: ConfigValue;\n configEvaluationMetadata: {\n configRowIndex: string | number;\n conditionalValueIndex: string | number;\n weightedValueIndex?: string | number;\n type: string;\n valueType: string;\n id: string;\n };\n};\n\nexport type EvaluationPayload = {\n evaluations: { [key: string]: Evaluation };\n apikeyMetadata: APIKeyMetadata;\n};\n\nconst parseRawMetadata = (metadata: any) => ({\n configRowIndex: parseInt(metadata.configRowIndex, 10),\n conditionalValueIndex: parseInt(metadata.conditionalValueIndex, 10),\n type: metadata.type,\n configId: metadata.id,\n});\n\nconst valueFor = <K extends keyof TypedFrontEndConfigurationRaw>(\n value: ConfigValue,\n type: keyof ConfigValue,\n key: K\n): TypedFrontEndConfigurationRaw[K] => {\n const rawValue = value[type];\n\n switch (type) {\n case \"json\":\n try {\n return JSON.parse(rawValue as string);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(`Error parsing JSON from Reforge config ${key}`, e, rawValue);\n return value[type];\n }\n case \"duration\": {\n const duration = rawValue as Duration;\n return {\n ms: duration.millis,\n seconds: duration.millis / 1000,\n };\n }\n default:\n return rawValue;\n }\n};\n\nexport const parseEvaluationPayload = (payload: EvaluationPayload) => {\n // eslint-disable-next-line no-use-before-define\n const configs = {} as { [key: string]: Config };\n Object.keys(payload.evaluations).forEach((key) => {\n const evaluation = payload.evaluations[key];\n\n const type = Object.keys(evaluation.value)[0] as keyof ConfigValue;\n\n // eslint-disable-next-line no-use-before-define\n configs[key] = new Config(\n key,\n valueFor(evaluation.value, type, key),\n type,\n evaluation.value,\n evaluation.configEvaluationMetadata\n ? parseRawMetadata(evaluation.configEvaluationMetadata)\n : undefined\n );\n });\n\n return configs;\n};\n\nconst parseRawConfigWithoutTypes = (payload: RawConfigWithoutTypes) => {\n // eslint-disable-next-line no-use-before-define\n const configs = {} as { [key: string]: Config };\n Object.keys(payload).forEach((key) => {\n const type = typeof payload[key] as keyof ConfigValue;\n // eslint-disable-next-line no-use-before-define\n configs[key] = new Config(key, valueFor({ [type]: payload[key] }, type, key), type);\n });\n\n return configs;\n};\n\nexport class Config<\n K extends keyof TypedFrontEndConfigurationRaw = keyof TypedFrontEndConfigurationRaw,\n> {\n key: K;\n\n value: TypedFrontEndConfigurationRaw[K];\n\n rawValue: ConfigValue | undefined;\n\n type: keyof ConfigValue;\n\n configEvaluationMetadata: ConfigEvaluationMetadata | undefined;\n\n constructor(\n key: K,\n value: TypedFrontEndConfigurationRaw[K],\n type: keyof ConfigValue,\n rawValue?: ConfigValue,\n metadata?: ConfigEvaluationMetadata\n ) {\n this.key = key;\n this.value = value;\n this.type = type;\n this.rawValue = rawValue;\n this.configEvaluationMetadata = metadata;\n }\n\n static digest(payload: EvaluationPayload | RawConfigWithoutTypes) {\n if (payload === undefined) {\n // eslint-disable-next-line no-console\n console.trace(\"Config.digest called with undefined payload\");\n }\n\n if (\"evaluations\" in payload) {\n return parseEvaluationPayload(payload as EvaluationPayload);\n }\n\n return parseRawConfigWithoutTypes(payload as RawConfigWithoutTypes);\n }\n}\n","const base64Encode = (obj: string) => {\n if (typeof window !== \"undefined\") {\n if (typeof TextEncoder === \"undefined\") {\n return window.btoa(obj);\n }\n\n const bytes = new TextEncoder().encode(obj);\n const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join(\"\");\n return btoa(binString);\n }\n\n return Buffer.from(obj).toString(\"base64\");\n};\n\nexport default base64Encode;\n","import { Contexts, ContextValue } from \"./types\";\nimport base64Encode from \"./base64Encode\";\n\nconst isEqual = (a: Contexts, b: Contexts) => {\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n return aKeys.every((key) => {\n const aValues = a[key];\n const bValues = b[key];\n\n const aValuesKeys = Object.keys(aValues);\n const bValuesKeys = Object.keys(bValues);\n\n if (aValuesKeys.length !== bValuesKeys.length) {\n return false;\n }\n\n return aValuesKeys.every((ckey) => {\n const aValue = aValues[ckey];\n const bValue = bValues[ckey];\n\n return aValue === bValue;\n });\n });\n};\n\nconst getType = (value: ContextValue) => {\n if (typeof value === \"string\") {\n return \"string\";\n }\n\n if (typeof value === \"number\") {\n if (Number.isInteger(value)) {\n return \"int\";\n }\n\n return \"double\";\n }\n\n return \"bool\";\n};\n\nexport default class Context {\n contexts: Contexts;\n\n constructor(contexts: Contexts) {\n if (!Object.values(contexts).every((item: any) => typeof item === \"object\")) {\n // eslint-disable-next-line no-console\n console.error(\"Context must be an object where the value of each key is also an object\");\n }\n\n if (\n Object.values(contexts).some((item: any) =>\n Object.values(item).some((value: any) => typeof value === \"object\" && value !== null)\n )\n ) {\n // we decided to allow null values, which requres an extra check since typeof null is object\n // eslint-disable-next-line no-console\n console.error(\"Nested objects are not supported in context values at this time\");\n }\n\n this.contexts = contexts;\n }\n\n equals(other: Context) {\n return isEqual(this.contexts, other.contexts);\n }\n\n encode() {\n const formatted = Object.keys(this.contexts).map((key) => {\n const values: Record<string, Record<string, ContextValue>> = {};\n\n Object.keys(this.contexts[key]).forEach((ckey) => {\n values[ckey] = {\n [getType(this.contexts[key][ckey])]: this.contexts[key][ckey],\n };\n });\n\n return {\n type: key,\n values,\n };\n });\n\n return encodeURIComponent(base64Encode(JSON.stringify({ contexts: formatted })));\n }\n}\n","export class ExponentialBackoff {\n private maxDelay: number;\n\n private multiplier: number;\n\n private delay: number;\n\n // arguments are in seconds\n constructor(maxDelay: number, initialDelay = 2, multiplier = 2) {\n this.maxDelay = maxDelay;\n this.multiplier = multiplier;\n this.delay = initialDelay;\n }\n\n call(): number {\n const delayValue = this.delay;\n this.delay = Math.min(this.delay * this.multiplier, this.maxDelay);\n return delayValue * 1000;\n }\n}\n","import { TypedFrontEndConfigurationRaw } from \"./types\";\n\nexport const PREFIX = \"log-level\";\nexport enum ReforgeLogLevel {\n Trace = 1,\n Debug = 2,\n Info = 3,\n Warn = 4,\n Error = 5,\n Fatal = 6,\n}\n\nexport type LogLevelWord = Uppercase<keyof typeof ReforgeLogLevel>;\n\nconst WORD_LEVEL_LOOKUP: Readonly<Record<LogLevelWord, ReforgeLogLevel>> = {\n TRACE: ReforgeLogLevel.Trace,\n DEBUG: ReforgeLogLevel.Debug,\n INFO: ReforgeLogLevel.Info,\n WARN: ReforgeLogLevel.Warn,\n ERROR: ReforgeLogLevel.Error,\n FATAL: ReforgeLogLevel.Fatal,\n};\n\nexport const isValidLogLevel = (possibleLogLevel: string) =>\n Object.keys(WORD_LEVEL_LOOKUP).includes(possibleLogLevel.toUpperCase());\n\nexport interface ShouldLogParams {\n loggerName: string;\n desiredLevel: ReforgeLogLevel;\n defaultLevel: ReforgeLogLevel;\n get: <K extends keyof TypedFrontEndConfigurationRaw>(key: K) => TypedFrontEndConfigurationRaw[K];\n}\n\nexport const shouldLog = ({\n loggerName,\n desiredLevel,\n defaultLevel,\n get,\n}: ShouldLogParams): boolean => {\n let loggerNameWithPrefix = `${PREFIX}.${loggerName}`;\n\n while (loggerNameWithPrefix.length > 0) {\n const resolvedLevel = get(loggerNameWithPrefix);\n\n if (resolvedLevel) {\n return (\n WORD_LEVEL_LOOKUP[resolvedLevel.toString().toUpperCase() as LogLevelWord] <= desiredLevel\n );\n }\n\n if (loggerNameWithPrefix.indexOf(\".\") === -1) {\n break;\n }\n\n loggerNameWithPrefix = loggerNameWithPrefix.slice(0, loggerNameWithPrefix.lastIndexOf(\".\"));\n }\n\n return defaultLevel <= desiredLevel;\n};\n","import { ExponentialBackoff } from \"./exponentialBackoff\";\nimport { ReforgeLogLevel } from \"./logger\";\nimport { type reforge } from \"./reforge\";\n\nabstract class PeriodicSync<T> {\n protected data: Map<string, T> = new Map();\n\n private startAt: Date;\n\n private syncInterval: any;\n\n protected client: typeof reforge;\n\n private name: string;\n\n private timeoutID: ReturnType<typeof setTimeout> | undefined;\n\n constructor(client: typeof reforge, name: string, syncInterval?: number) {\n this.client = client;\n this.name = name;\n\n this.startAt = new Date();\n\n this.startPeriodicSync(syncInterval);\n }\n\n stop(): void {\n clearTimeout(this.timeoutID);\n }\n\n sync(): void {\n if (this.data.size === 0) return;\n\n this.logInternal(`${this.name} syncing ${this.data.size} items`);\n\n const startAtWas = this.startAt;\n this.startAt = new Date();\n\n this.flush(this.prepareData(), startAtWas);\n }\n\n protected abstract flush(toShip: Map<string, T>, startAtWas: Date): void;\n\n private prepareData(): Map<string, T> {\n const toShip = new Map(this.data);\n this.data.clear();\n\n return toShip;\n }\n\n private startPeriodicSync(syncInterval?: number): void {\n this.startAt = new Date();\n this.syncInterval = PeriodicSync.calculateSyncInterval(syncInterval);\n\n this.scheduleNextSync();\n }\n\n private scheduleNextSync() {\n const interval = this.syncInterval();\n this.timeoutID = setTimeout(() => {\n this.sync();\n this.scheduleNextSync(); // Schedule the next sync after the current one completes\n }, interval);\n }\n\n private static calculateSyncInterval(syncInterval?: number): any {\n if (syncInterval !== undefined) {\n return () => syncInterval;\n }\n\n const backoff = new ExponentialBackoff(60 * 5, 8);\n return () => backoff.call();\n }\n\n protected logInternal(message: string): void {\n const loggerName = `${this.client.clientNameString}.reforge.${this.name}`;\n\n if (\n this.client.shouldLog(\n {\n loggerName,\n desiredLevel: ReforgeLogLevel.Debug,\n defaultLevel: ReforgeLogLevel.Error,\n },\n false // synchronous so that this log ends up in the current batch\n )\n ) {\n // eslint-disable-next-line no-console\n console.log(`${loggerName}: ${message}`);\n }\n }\n}\n\nexport { PeriodicSync };\n","// TODO: should we retry the data chunk if a flush fails?\n\n// TODO: pause when offline?\n\n// TODO: flush when we receive a config update (or as a result of a context update...but that should trigger a config update anyway)\n\nimport { PeriodicSync } from \"./periodicSync\";\nimport { Config } from \"./config\";\nimport { type reforge } from \"./reforge\";\nimport {\n ConfigEvaluationCounter,\n ConfigEvaluationSummaries,\n ConfigEvaluationSummary,\n TelemetryEvents,\n ConfigEvaluationMetadata,\n} from \"./types\";\n\nexport const massageSelectedValue = (config: Config): any => {\n if (config.rawValue && (config.type === \"duration\" || config.type === \"json\")) {\n if (config.type === \"json\") {\n return { json: config.rawValue[config.type] };\n }\n\n return config.rawValue[config.type];\n }\n\n return config.type === \"stringList\" ? { values: config.value } : config.value;\n};\n\nexport const massageConfigForTelemetry = (\n config: Config,\n metadata: Omit<ConfigEvaluationMetadata, \"type\">\n) => ({\n ...metadata,\n selectedValue: {\n [config.type]: massageSelectedValue(config),\n },\n count: 0,\n});\n\nclass EvaluationSummaryAggregator extends PeriodicSync<ConfigEvaluationCounter> {\n private maxKeys: number;\n\n constructor(client: typeof reforge, maxKeys: number, syncInterval?: number) {\n super(client, \"EvaluationSummaryAggregator\", syncInterval ?? 30000);\n\n this.maxKeys = maxKeys;\n }\n\n record(config: Config): void {\n if (this.data.size >= this.maxKeys) return;\n\n if (config?.configEvaluationMetadata) {\n const { type, ...metadata } = config.configEvaluationMetadata;\n const key = `${config.key},${type}`;\n\n // create counter entry if it doesn't exist\n if (!this.data.has(key)) {\n this.data.set(key, massageConfigForTelemetry(config, metadata));\n }\n\n // increment count\n const counter = this.data.get(key);\n if (counter) {\n counter.count += 1;\n }\n }\n }\n\n protected flush(toShip: Map<string, ConfigEvaluationCounter>, startAtWas: Date): void {\n const summaries = {\n start: startAtWas.getTime(),\n end: new Date().getTime(),\n summaries: EvaluationSummaryAggregator.summaries(toShip),\n };\n\n this.client.telemetryUploader?.post(this.events(summaries));\n }\n\n private static summaries(data: Map<string, ConfigEvaluationCounter>): ConfigEvaluationSummary[] {\n return Array.from(data).map((entry: [string, ConfigEvaluationCounter]) => {\n const [configKey, configType] = entry[0].split(\",\");\n const counter = entry[1];\n const counters = [counter]; // this client only ever has one set of counter info per key\n\n return {\n key: configKey,\n type: configType,\n counters,\n };\n });\n }\n\n private events(summaries: ConfigEvaluationSummaries): TelemetryEvents {\n const event = { summaries };\n\n return {\n instanceHash: this.client.instanceHash,\n events: [event],\n };\n }\n}\n\nexport { EvaluationSummaryAggregator };\n","import base64Encode from \"./base64Encode\";\n\nexport const headers = (sdkKey: string, clientVersion: string) => ({\n Authorization: `Basic ${base64Encode(`u:${sdkKey}`)}`,\n \"X-Reforge-SDK-Version\": clientVersion,\n});\n\nexport const DEFAULT_TIMEOUT = 10000;\n","import { DEFAULT_TIMEOUT, headers } from \"./apiHelpers\";\nimport { EvaluationPayload } from \"./config\";\nimport Context from \"./context\";\n\nexport type CollectContextModeType = \"NONE\" | \"SHAPE_ONLY\" | \"PERIODIC_EXAMPLE\";\n\nexport type LoaderParams = {\n sdkKey: string;\n context: Context;\n endpoints?: string[] | undefined;\n timeout?: number;\n collectContextMode?: CollectContextModeType;\n clientVersion?: string;\n};\n\nexport type Headers = {\n [key: string]: string;\n};\n\nexport type FetchOptions = {\n headers: Headers;\n};\n\nconst defaultEndpoints = [\n \"https://primary.reforge.com/api/v2\",\n \"https://secondary.reforge.com/api/v2\",\n];\n\nconst EARLY_TIMEOUT = 2000;\n\nexport default class Loader {\n sdkKey: string;\n\n context: Context;\n\n endpoints: string[];\n\n timeout: number;\n\n abortTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n collectContextMode: CollectContextModeType = \"PERIODIC_EXAMPLE\";\n\n clientVersion: string;\n\n abortController: AbortController | undefined;\n\n isAborted = false;\n\n constructor({\n sdkKey,\n context,\n endpoints = undefined,\n timeout,\n collectContextMode = \"PERIODIC_EXAMPLE\",\n clientVersion = \"\",\n }: LoaderParams) {\n this.sdkKey = sdkKey;\n this.context = context;\n this.endpoints = endpoints || defaultEndpoints;\n this.timeout = timeout || DEFAULT_TIMEOUT;\n this.collectContextMode = collectContextMode;\n this.clientVersion = clientVersion;\n }\n\n url(root: string) {\n return `${root}/configs/eval-with-context/${this.context.encode()}?collectContextMode=${\n this.collectContextMode\n }`;\n }\n\n loadFromEndpoint(\n index: number,\n options: FetchOptions,\n resolve: (value: any) => void,\n reject: (value: any) => void\n ) {\n this.abortController = new AbortController() as AbortController;\n const { signal } = this.abortController;\n this.isAborted = false;\n\n const endpoint = this.endpoints[index];\n const url = this.url(endpoint);\n\n fetch(url, { signal, ...options })\n .then((response) => {\n this.clearAbortTimeout();\n\n if (response.ok) {\n return response.json();\n }\n throw new Error(`${response.status} ${response.statusText}`);\n })\n .then((data) => {\n if (!(\"evaluations\" in data)) {\n throw new Error(`Invalid payload:${JSON.stringify(data)}`);\n }\n\n resolve(data as EvaluationPayload);\n })\n .catch((error) => {\n this.clearAbortTimeout();\n\n if (index < this.endpoints.length - 1) {\n this.loadFromEndpoint(index + 1, options, resolve, reject);\n } else {\n reject(error);\n }\n });\n\n // Use an early timeout if we're not on the last endpoint. But if the user-provided timeout is less than EARLY_TIMEOUT, use that\n const timeout =\n index < this.endpoints.length - 1 ? Math.min(this.timeout, EARLY_TIMEOUT) : this.timeout;\n\n this.abortTimeoutId = setTimeout(() => {\n if (!this.isAborted) {\n this.isAborted = true;\n this.abortController?.abort();\n }\n }, timeout);\n }\n\n load() {\n if (!this.isAborted) {\n this.isAborted = true;\n this.abortController?.abort();\n }\n\n const options = {\n headers: headers(this.sdkKey, this.clientVersion),\n };\n\n const promise = new Promise((resolve, reject) => {\n this.loadFromEndpoint(0, options, resolve, reject);\n });\n\n return promise;\n }\n\n clearAbortTimeout() {\n clearTimeout(this.abortTimeoutId);\n }\n}\n","import { DEFAULT_TIMEOUT, headers } from \"./apiHelpers\";\nimport { TelemetryEvents } from \"./types\";\n\nexport type TelemetryUploaderParams = {\n sdkKey: string;\n apiEndpoint?: string;\n timeout?: number;\n clientVersion: string;\n};\n\nexport default class TelemetryUploader {\n sdkKey: Required<TelemetryUploaderParams>[\"sdkKey\"];\n\n apiEndpoint: Required<TelemetryUploaderParams>[\"apiEndpoint\"];\n\n timeout: Required<TelemetryUploaderParams>[\"timeout\"];\n\n clientVersion: Required<TelemetryUploaderParams>[\"clientVersion\"];\n\n abortTimeoutId: ReturnType<typeof setTimeout> | undefined;\n\n constructor({\n sdkKey,\n apiEndpoint = undefined,\n timeout,\n clientVersion,\n }: TelemetryUploaderParams) {\n this.sdkKey = sdkKey;\n this.apiEndpoint = apiEndpoint || \"https://telemetry.prefab.cloud/api/v1\";\n this.timeout = timeout || DEFAULT_TIMEOUT;\n this.clientVersion = clientVersion;\n }\n\n clearAbortTimeout() {\n clearTimeout(this.abortTimeoutId);\n }\n\n static postUrl(root: string) {\n return `${root}/telemetry`;\n }\n\n postToEndpoint(\n options: RequestInit,\n resolve: (value: unknown) => void,\n reject: (value: unknown) => void\n ) {\n const controller = new AbortController() as AbortController;\n const signal = controller?.signal;\n let isAborted = false;\n\n const url = TelemetryUploader.postUrl(this.apiEndpoint);\n\n fetch(url, { signal, ...options })\n .then((response) => {\n this.clearAbortTimeout();\n\n if (response.ok) {\n return response.json();\n }\n\n // eslint-disable-next-line no-console\n console.warn(\n `Reforge warning: Error uploading telemetry ${response.status} ${response.statusText}`\n );\n\n return response.status;\n })\n .then((response) => {\n resolve(response);\n })\n .catch((error) => {\n this.clearAbortTimeout();\n\n // Silently handle AbortErrors (from timeouts or page navigations)\n if (error.name === \"AbortError\") {\n try {\n // eslint-disable-next-line no-console\n console.debug(\"Reforge telemetry request aborted\");\n } catch (e) {\n // no-op\n }\n resolve({ status: \"aborted\" });\n return;\n }\n\n reject(error);\n });\n\n this.abortTimeoutId = setTimeout(() => {\n if (!isAborted) {\n isAborted = true;\n controller.abort();\n }\n }, this.timeout);\n }\n\n post(data: TelemetryEvents) {\n const options = {\n method: \"POST\",\n headers: {\n ...headers(this.sdkKey, this.clientVersion),\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify(data),\n keepalive: true, // needed for flushing when the window is closed\n };\n\n const promise = new Promise((resolve, reject) => {\n this.postToEndpoint(options, resolve, reject);\n });\n\n return promise;\n }\n}\n","// TODO: should we retry the data chunk if a flush fails?\n\n// TODO: pause when offline?\n\nimport { ReforgeLogLevel } from \"./logger\";\nimport { PeriodicSync } from \"./periodicSync\";\nimport { type reforge } from \"./reforge\";\nimport { LoggerCounter, LoggersTelemetryEvent, TelemetryEvents } from \"./types\";\n\nconst SEVERITY_KEY: { [key in ReforgeLogLevel]: Omit<keyof LoggerCounter, \"loggerName\"> } = {\n [ReforgeLogLevel.Trace]: \"traces\",\n [ReforgeLogLevel.Debug]: \"debugs\",\n [ReforgeLogLevel.Info]: \"infos\",\n [ReforgeLogLevel.Warn]: \"warns\",\n [ReforgeLogLevel.Error]: \"errors\",\n [ReforgeLogLevel.Fatal]: \"fatals\",\n};\n\nclass LoggerAggregator extends PeriodicSync<LoggerCounter> {\n private maxLoggers: number;\n\n constructor(client: typeof reforge, maxLoggers: number, syncInterval?: number) {\n super(client, \"LoggerAggregator\", syncInterval ?? 30000);\n\n this.maxLoggers = maxLoggers;\n }\n\n record(logger: string, level: ReforgeLogLevel): void {\n if (this.data.size >= this.maxLoggers) return;\n\n // create counter entry if it doesn't exist\n if (!this.data.has(logger)) {\n this.data.set(logger, {\n loggerName: logger,\n traces: 0,\n debugs: 0,\n infos: 0,\n warns: 0,\n errors: 0,\n fatals: 0,\n });\n }\n\n // increment count\n const counter = this.data.get(logger);\n if (counter) {\n const severityKey = SEVERITY_KEY[level] as keyof LoggerCounter;\n (counter[severityKey] as number) += 1;\n }\n }\n\n protected flush(toShip: Map<string, LoggerCounter>, startAtWas: Date): void {\n const loggers = {\n startAt: startAtWas.getTime(),\n endAt: new Date().getTime(),\n loggers: Array.from(toShip.values()),\n };\n\n this.client.telemetryUploader?.post(this.events(loggers));\n }\n\n private events(loggers: LoggersTelemetryEvent): TelemetryEvents {\n const event = { loggers };\n\n return {\n instanceHash: this.client.instanceHash,\n events: [event],\n };\n }\n}\n\nexport { LoggerAggregator };\n","import { reforge, Reforge, ReforgeInitParams, ReforgeBootstrap } from \"./src/reforge\";\nimport { Config } from \"./src/config\";\nimport Context from \"./src/context\";\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { version } = require(\"./package.json\");\n\nexport { reforge, Reforge, ReforgeInitParams, Config, Context, version };\n\nexport { ReforgeBootstrap };\n\nexport type { ConfigValue } from \"./src/config\";\nexport type {\n Duration,\n ContextValue,\n Contexts,\n TypedFrontEndConfigurationRaw,\n FrontEndConfigurationRaw,\n} from \"./src/types\";\nexport type { CollectContextModeType } from \"./src/loader\";\n"],"mappings":"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","names":["version"]} |
+2
-1
| { | ||
| "packageManager": "yarn@4.9.2", | ||
| "name": "@reforge-com/javascript", | ||
| "version": "0.0.1", | ||
| "version": "0.0.2", | ||
| "description": "Feature Flags & Dynamic Configuration as a Service", | ||
@@ -18,2 +18,3 @@ "main": "dist/index.cjs", | ||
| "@typescript-eslint/parser": "^5.33.0", | ||
| "esbuild": "^0.25.11", | ||
| "eslint": "^8.21.0", | ||
@@ -20,0 +21,0 @@ "eslint-config-airbnb": "^19.0.4", |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
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
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
232823
13.14%12
9.09%2242
4.96%22
4.76%2
100%2
100%9
50%