@configdirector/react-web-sdk 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`react`);c=s(c);let l=require(`react/jsx-runtime`);var u=class{constructor(){this.handlerMap=new Map}on(e,t){let n=this.handlerMap.get(e);n?n.push(t):this.handlerMap.set(e,[t])}once(e,t){let n=this;function r(i){n.off(e,r),t.apply(n,i)}this.on(e,r)}off(e,t){let n=this.handlerMap.get(e);if(n)if(t){let e=n.indexOf(t);e>=0&&n.splice(e,1)}else this.handlerMap.set(e,[])}clear(){this.handlerMap.clear()}emit(e,t){let n=this.handlerMap.get(e);n&&n.slice().map(e=>e(t))}},d=class e extends Error{constructor(t,n){super(t),this.name=`ConfigDirectorConnectionError`,this.status=n,Object.setPrototypeOf(this,e.prototype)}},f=class e extends Error{constructor(t){super(t),this.name=`ConfigDirectorValidationError`,Object.setPrototypeOf(this,e.prototype)}};const p=e=>{if(e instanceof DOMException){if(e.name===`NotAllowedError`)return!0}else if(e instanceof TypeError)return!0;return!1};var m=class e extends Error{constructor(t){super(t),this.name=`StreamClosedError`,Object.setPrototypeOf(this,e.prototype)}},h=class e extends Error{constructor(t){super(t),this.name=`MissingResponseBodyError`,Object.setPrototypeOf(this,e.prototype)}},g=class e extends Error{constructor(t){super(t),this.name=`InvalidOptionError`,Object.setPrototypeOf(this,e.prototype)}},_=class e extends Error{constructor(t){super(t),this.name=`ValueOutOfRangeError`,Object.setPrototypeOf(this,e.prototype)}},v=class{constructor(e){this.isFirstChunk=!0,this.previousIncompleteLine=``,this.currentEvent={data:``},this.onEvent=e.onEvent??(()=>{}),this.onRetry=e.onRetry,this.onComment=e.onComment}parse(e){let t=this.prepareChunk(e),n=this.splitLines(t);for(let e of n)this.parseAndProcessLine(e)}finish(){this.previousIncompleteLine!==``&&this.parseAndProcessLine(this.previousIncompleteLine)}parseAndProcessLine(e){if(e.startsWith(`:`)){this.onComment?.(this.getValueFromLine(0,e));return}if(e===``){this.publishEvent();return}let t=this.parseContentLine(e);this.processContent(t)}publishEvent(){let e=this.currentEvent.data.endsWith(`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`react`);c=s(c);let l=require(`react/jsx-runtime`);var u=class{constructor(){this.handlerMap=new Map}on(e,t){let n=this.handlerMap.get(e);n?n.push(t):this.handlerMap.set(e,[t])}once(e,t){let n=this;function r(i){n.off(e,r),t.apply(n,i)}this.on(e,r)}off(e,t){let n=this.handlerMap.get(e);if(n)if(t){let e=n.indexOf(t);e>=0&&n.splice(e,1)}else this.handlerMap.set(e,[])}clear(){this.handlerMap.clear()}emit(e,t){let n=this.handlerMap.get(e);n&&n.slice().map(e=>e(t))}},d=class e extends Error{constructor(t,n){super(t),this.name=`ConfigDirectorConnectionError`,this.status=n,Object.setPrototypeOf(this,e.prototype)}},f=class e extends Error{constructor(t){super(t),this.name=`ConfigDirectorValidationError`,Object.setPrototypeOf(this,e.prototype)}};const p=e=>e?.name===`NotAllowedError`?!0:e instanceof TypeError;var m=class e extends Error{constructor(t){super(t),this.name=`StreamClosedError`,Object.setPrototypeOf(this,e.prototype)}},h=class e extends Error{constructor(t){super(t),this.name=`MissingResponseBodyError`,Object.setPrototypeOf(this,e.prototype)}},g=class e extends Error{constructor(t){super(t),this.name=`InvalidOptionError`,Object.setPrototypeOf(this,e.prototype)}},_=class e extends Error{constructor(t){super(t),this.name=`ValueOutOfRangeError`,Object.setPrototypeOf(this,e.prototype)}},v=class{constructor(e){this.isFirstChunk=!0,this.previousIncompleteLine=``,this.currentEvent={data:``},this.onEvent=e.onEvent??(()=>{}),this.onRetry=e.onRetry,this.onComment=e.onComment}parse(e){let t=this.prepareChunk(e),n=this.splitLines(t);for(let e of n)this.parseAndProcessLine(e)}finish(){this.previousIncompleteLine!==``&&this.parseAndProcessLine(this.previousIncompleteLine)}parseAndProcessLine(e){if(e.startsWith(`:`)){this.onComment?.(this.getValueFromLine(0,e));return}if(e===``){this.publishEvent();return}let t=this.parseContentLine(e);this.processContent(t)}publishEvent(){let e=this.currentEvent.data.endsWith(`
2
2
  `)?this.currentEvent.data.slice(0,-1):this.currentEvent.data;e&&this.onEvent({...this.currentEvent,id:this.lastEventId,data:e}),this.currentEvent={data:``}}processContent(e){switch(e.field){case`event`:this.currentEvent.type=e.value;break;case`data`:this.currentEvent.data+=e.value+`
3
- `;break;case`id`:e.value.includes(`\0`)||(this.lastEventId=e.value);break;case`retry`:/^\d+$/.test(e.value)&&this.onRetry?.(Number.parseInt(e.value,10));break;default:break}}parseContentLine(e){let t=e.indexOf(`:`);return t===-1?{field:e,value:``}:{field:e.slice(0,t),value:this.getValueFromLine(t,e)}}splitLines(e){let t=e.split(/\r\n|\r|\n/);return this.previousIncompleteLine=t.pop()??``,t}getValueFromLine(e,t){if(e===-1)return``;let n=t[e+1]===` `?e+2:e+1;return t.slice(n)}prepareChunk(e){return this.isFirstChunk?(this.isFirstChunk=!1,this.previousIncompleteLine+e.replace(/^\xEF\xBB\xBF/,``).replace(/^\uFEFF/,``)):this.previousIncompleteLine+e}};let y=function(e){return e.OPEN=`open`,e.CLOSED=`closed`,e.CONNECTING=`connecting`,e}({});var b=class{constructor(e){this.DEFAULT_SHOULD_RECONNECT=()=>!0,this.DEFAULT_CALCULATE_RECONNECT_DELAY=()=>this.serverReconnectionTime,this.reconnectAttempt=0,this.abortController=new AbortController,this._readyState=y.CLOSED,this.serverReconnectionTime=2e3,this.url=new URL(e.url),this.lastEventId=e.lastEventId,this.headers={Accept:`text/event-stream`,...e.headers},this.requestOptions={body:e.body,method:e.method??`GET`,mode:e.mode,credentials:e.credentials,redirect:e.redirect,referrer:e.referrer,referrerPolicy:e.referrerPolicy},this._onError=this.getValidatedFunctionOrNoOp(e.onError,`onError`),this._onConnect=this.getValidatedFunctionOrNoOp(e.onConnect,`onConnect`),this._onDisconnect=this.getValidatedFunctionOrNoOp(e.onDisconnect,`onDisconnect`),this._onMessage=this.getValidatedFunctionOrNoOp(e.onMessage,`onMessage`),this._onComment=this.getValidatedFunctionOrNoOp(e.onComment,`onComment`),this._shouldReconnect=this.getValidatedFunctionOr(e.shouldReconnect,this.DEFAULT_SHOULD_RECONNECT,`shouldReconnect`),this._calculateReconnectDelay=this.getValidatedFunctionOr(e.calculateReconnectDelay,this.DEFAULT_CALCULATE_RECONNECT_DELAY,`calculateReconnectDelay`)}set onError(e){this._onError=this.getValidatedFunctionOrNoOp(e,`onError`)}set onMessage(e){this._onMessage=this.getValidatedFunctionOrNoOp(e,`onMessage`)}set onComment(e){this._onComment=this.getValidatedFunctionOrNoOp(e,`onComment`)}set onConnect(e){this._onConnect=this.getValidatedFunctionOrNoOp(e,`onConnect`)}set onDisconnect(e){this._onDisconnect=this.getValidatedFunctionOrNoOp(e,`onDisconnect`)}set shouldReconnect(e){this._shouldReconnect=this.getValidatedFunctionOr(e,this.DEFAULT_SHOULD_RECONNECT,`shouldReconnect`)}set calculateReconnectDelay(e){this._calculateReconnectDelay=this.getValidatedFunctionOr(e,this.DEFAULT_CALCULATE_RECONNECT_DELAY,`shouldReconnect`)}get readyState(){return this._readyState}connect(){this._readyState===y.CLOSED&&(this.reconnectAttempt=0,this.initiateConnection())}initiateConnection(){this.abortController=new AbortController,this._readyState=y.CONNECTING,fetch(this.url,{...this.requestOptions,headers:this.buildHeaders(),signal:this.abortController.signal,cache:`no-store`}).then(this.handleFetchResponse.bind(this)).catch(e=>{if(e.name===`AbortError`||this.abortController.signal.aborted){this.close();return}this._onError(e),this.scheduleReconnect({error:e})})}close(){clearTimeout(this.reconnectTimeout),this._readyState=y.CLOSED,this.abortController.abort()}disconnected(){clearTimeout(this.reconnectTimeout),this._readyState=y.CLOSED,this._onDisconnect()}buildHeaders(){let e=this.lastEventId?{"Last-Event-ID":this.lastEventId}:void 0;return{...this.headers,...e}}async handleFetchResponse(e){let{body:t,status:n}=e;if(n===204){this.disconnected();return}if(n>=400){this.scheduleReconnect({status:n});return}if(!t)throw new h(`The server response did not have a body`);this._readyState=y.OPEN,this._onConnect(),this.reconnectAttempt=0;let r=(t?.pipeThrough(new TextDecoderStream)).getReader(),i=new v({onEvent:e=>{typeof e.id==`string`&&(this.lastEventId=e.id),this._onMessage(e)},onComment:e=>this._onComment(e),onRetry:e=>this.serverReconnectionTime=e}),a=!1;for(;!a;){let{done:e,value:t}=await r.read();t&&i.parse(t),a=e}i.finish(),this.scheduleReconnect({status:n,error:new m(`The server response stream was closed`)})}scheduleReconnect(e){if(this.abortController.signal.aborted)return;clearTimeout(this.reconnectTimeout),this.reconnectAttempt+=1;let t={attempt:this.reconnectAttempt,status:e.status,error:e.error,serverReconnectionTime:this.serverReconnectionTime};if(this._shouldReconnect(t)){this._readyState=y.CONNECTING;let e=this._calculateReconnectDelay(t);(!Number.isFinite(e)||e<1||e>1e3*60*60)&&(this._onError(new _(`The calculated reconnect delay is out of range: ${e}. Defaulting to ${this.serverReconnectionTime}`)),e=this.serverReconnectionTime),this.reconnectTimeout=setTimeout(()=>this.initiateConnection(),e)}else{this.disconnected();return}}getValidatedFunctionOrNoOp(e,t){return this.getValidatedFunctionOr(e,()=>{},t)}getValidatedFunctionOr(e,t,n){if(e==null)return t;if(typeof e==`function`)return e;throw new g(`${n} must be a function`)}};const x=e=>new b(e);var S=class{constructor(e){this.options=e,this.eventEmitter=new u,this.options=e,this.logger=e.logger,this.url=new URL(`client/sse/v1`,e.baseUrl)}async connect(e,t){this.eventSource&&this.close();let n=new Promise((t,n)=>{this.eventSource=x({url:this.url,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({givenContext:e,metaContext:this.options.metaContext,clientSdkKey:this.options.clientSdkKey}),onMessage:({data:e})=>{this.dispatchMessage(e)},onConnect:()=>{this.logger.debug(`[EventSourceTransport] Connected`),t(this)},shouldReconnect:e=>{let t=!this.isStatusFatal(e.status);return t||n(this.prepareFatalError(e.status,e.error)),t},calculateReconnectDelay:e=>{let t=2e3*e.attempt;return this.logger.warn(`[EventSourceTransport] Scheduling reconnect in ${t}ms.`),t},onDisconnect:()=>{this.logger.debug(`[EventSourceTransport] Disconnected`)}}),this.eventSource.connect()});return Promise.race([n,new Promise(e=>{setTimeout(()=>e(this),t)})])}dispatchMessage(e){try{let t=JSON.parse(e);this.eventEmitter.emit(`configSetReceived`,t)}catch(e){this.logger.error(`[EventSourceTransport] Error parsing and dispatching config data update: `,e)}}prepareFatalError(e,t){let n=e??0;return new d(`${`Connection failed with status: ${e??`unknown`}.`}${t?` Error: ${t}`:``}. This is an unrecoverable error, will not attempt to reconnect.`,n)}isStatusFatal(e){return!!e&&e>=400&&e<500}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.eventEmitter.clear()}close(){this.eventSource?.close()}dispose(){this.close(),this.clear()}};const C=e=>{let t=typeof e;if(t===`object`)try{return e.constructor?.name??t}catch{return t}else if(t===`function`)try{let n=e.name;return n?`function: ${n}`:t}catch{return t}return t},w=e=>e===`number`||e===`bigint`,T=(e,t)=>{let n=e.value,r=C(t);if(!n)return{parsedValue:t,requestedType:r,usedDefault:!0,reason:`value-missing`};if(typeof t==`string`)return{parsedValue:n,requestedType:r,usedDefault:!1,reason:`found-match`};if(typeof t==`boolean`&&e.type===`boolean`){let e=E(n),i=typeof e==`boolean`;return{parsedValue:i?e:t,requestedType:r,usedDefault:!i,reason:i?`found-match`:`invalid-boolean`}}if(w(typeof t)&&e.type===`integer`){let e=D(n),i=typeof e==`number`;return{parsedValue:i?e:t,requestedType:r,usedDefault:!i,reason:i?`found-match`:`invalid-number`}}if(w(typeof t)&&(e.type===`float`||e.type===`enum`)){let e=O(n),i=typeof e==`number`;return{parsedValue:i?e:t,requestedType:r,usedDefault:!i,reason:i?`found-match`:`invalid-number`}}return{parsedValue:n,requestedType:r,usedDefault:!1,reason:`found-match`}},E=e=>{if(!e)return;let t=e.toLowerCase();if(!(t!=`true`&&t!=`false`))return t===`true`},D=e=>{if(!e)return;let t=Number.parseInt(e);if(!(isNaN(t)||!isFinite(t)))return t},O=e=>{if(!e)return;let t=Number.parseFloat(e);if(!(isNaN(t)||!isFinite(t)))return t},k={off:-1,error:0,warn:1,info:2,debug:3},A=()=>{let e={year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,timeZoneName:`short`};try{return new Intl.DateTimeFormat(void 0,{...e,fractionalSecondDigits:3})}catch{return new Intl.DateTimeFormat(void 0,e)}};var j=class{constructor(e,t){this.level=e,this.decorator=t,this.level=e,this.decorator=t,this.dateFormatter=A()}debug(e,...t){this.log(console.debug,`debug`,e,...t)}info(e,...t){this.log(console.info,`info`,e,...t)}warn(e,...t){this.log(console.warn,`warn`,e,...t)}error(e,...t){this.log(console.error,`error`,e,...t)}log(e,t,n,...r){k[this.level]>=k[t]&&e(`[${this.dateFormatter.format(new Date)}] ${this.decorator?.decorateMessage(n)}`,...r)}},M=class{decorateMessage(e){return`[ConfigDirector:js-client-sdk] ${e}`}};const N=(e,t)=>new j(e??`warn`,t??new M),P=async(e,t,n,r)=>{let i=new AbortController,a=setTimeout(()=>{r.debug(`[fetchWithTimeout] Reached timeout, aborting request`),i.abort()},e);try{let e=await fetch(t,{...n,signal:i.signal});return clearTimeout(a),e}catch(e){throw r.warn(`[fetchWithTimeout] Fetch error: `,e),clearTimeout(a),e}};var F=class{constructor(e){this.options=e,this.eventEmitter=new u,this.fatalError=!1,this.options=e,this.logger=e.logger,this.url=new URL(`client/pull/v1`,e.baseUrl)}async connect(e,t){if(this.fatalError)return this.logger.warn(`[PullTransport] There was a prior unrecoverable error. Ignoring attempt to reconnect.`),this;try{let n=await P(t,this.url,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({givenContext:e,metaContext:this.options.metaContext,clientSdkKey:this.options.clientSdkKey})},this.logger);if(!n.ok)throw this.isStatusFatal(n.status)?(this.fatalError=!0,this.prepareFatalResponseStatusError(n.status,await n.text())):new d(`Connection failed with status: ${n.status}`,n.status);let r=JSON.parse(await n.text());return this.eventEmitter.emit(`configSetReceived`,r),this}catch(e){throw p(e)?(this.fatalError=!0,new d(`Connection failed with fatal error: ${e}. This is an unrecoverable error, retry attempts will be ignored.`)):e instanceof SyntaxError?new d(`Failed to parse the response from the server: ${e}`):new d(`Connection failed with error: ${e}.`)}}prepareFatalResponseStatusError(e,t){let n=e??0;return new d(`${`Connection failed with status: ${e??`unknown`}`}${(t?.trim()?.length??0)>0?` (${t})`:``}. This is an unrecoverable error, retry attempts will be ignored.`,n)}isStatusFatal(e){return!!e&&e>=400&&e<500}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.eventEmitter.clear()}close(){}dispose(){this.close(),this.clear()}};const I=(e,t)=>{if(t===`json`)try{return L(JSON.stringify(e))}catch{return e.toString().slice(0,500)}return e.toString().slice(0,500)},L=e=>R(new TextEncoder().encode(e)).toString(16).padStart(8,`0`),R=e=>{let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e[n],t>>>=0;return t};var z=class{constructor(e){this.logger=e.logger;let t={type:`Initialize`,payload:{sdkKey:e.sdkKey,baseUrl:e.baseUrl.toString(),evaluationQueueLimit:e.evaluationQueueLimit??1e3,initialFlushIntervalDelay:e.initialFlushIntervalDelay??5e3,flushIntervalDelay:e.flushIntervalDelay??3e4}};this.worker=new Worker(URL.createObjectURL(new Blob(["(function(){let e=(e,n)=>{if(n===`json`)try{return t(JSON.stringify(e))}catch{return e.toString().slice(0,500)}return e.toString().slice(0,500)},t=e=>n(new TextEncoder().encode(e)).toString(16).padStart(8,`0`),n=e=>{let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e[n],t>>>=0;return t},r=e=>{let t=Object.keys(e);if(t.length==0)return!0;for(let n of t)if((e[n]?.length??0)>0)return!1;return!0},i=e=>{if(!e)return!0;let t=Object.keys(e);if(t.length==0)return!0;for(let n of t)if((e[n]??0)>0)return!1;return!0},a=async(e,t,n,r)=>{let i=new AbortController,a=setTimeout(()=>{r.debug(`[fetchWithTimeout] Reached timeout, aborting request`),i.abort()},e);try{let e=await fetch(t,{...n,signal:i.signal});return clearTimeout(a),e}catch(e){throw r.warn(`[fetchWithTimeout] Fetch error: `,e),clearTimeout(a),e}},o=e=>{if(e instanceof DOMException){if(e.name===`NotAllowedError`)return!0}else if(e instanceof TypeError)return!0;return!1};var s=class{constructor(e){this.executeRequests=!0,this.sdkKey=e.sdkKey,this.logger=e.logger,this.url=new URL(`client/telemetry/v1`,e.baseUrl)}async report({context:e,discreteEvents:t,aggregatedEvents:n,droppedEvents:r}){if(!this.executeRequests)return{success:!1,fatalError:!0};let i={clientSdkKey:this.sdkKey,context:e,discreteEvents:t,aggregatedEvents:n,droppedEvents:r};if(this.isReportEmpty(i))return{success:!0,fatalError:!1};let a=await this.sendReport(i);return a.fatalError&&(this.executeRequests=!1),a}isReportEmpty(e){return r(e.discreteEvents)&&r(e.aggregatedEvents)&&i(e.droppedEvents)}async sendReport(e){try{let t=await a(5e3,this.url,{method:`POST`,body:JSON.stringify(e),keepalive:!0},this.logger),n=this.isStatusFatal(t.status);return n&&this.logger.warn(`[EventReporter] Received a fatal status response (${t.status}) from the telemetry endpoint. No more telemetry data will be sent.`),{success:t.ok,fatalError:n}}catch(e){let t=o(e);return this.logger.warn(`[EventReporter] Error attempting to send telemetry data: ${e}`,{error:e}),{success:!1,fatalError:t}}}isStatusFatal(e){return!!e&&e>=400&&e<500}},c=class{aggregate(e){if(e.events.length==0)return[];let t=new Map;for(let n of e.events){let e=JSON.stringify(n),r=t.get(e)?.count||0;t.set(e,{event:n,count:r+1})}return Array.from(t).map(([,t])=>({startTime:e.startTime,endTime:e.endTime,count:t.count,event:t.event}))}},l=class{constructor(e){this._events=[],this._droppedEventCount=0,this.limit=e??1e3}get events(){return this._events}get reachedLimit(){return this._events.length>=this.limit}get droppedEventCount(){return this._droppedEventCount}push(...e){this.startTime||=new Date;let t=Math.max(0,e.length-this.limit),n=e.slice(t,e.length);if(this._droppedEventCount+=t,this._events.length+n.length>this.limit){let e=this._events.length+n.length-this.limit;this._events.splice(0,e),this._droppedEventCount+=e}return this._events.push(...n)}takeSnapshot(){let e=new Date,t=this.startTime??e,n=this._events.splice(0),r=this._droppedEventCount;return this.startTime=void 0,this._droppedEventCount=0,{startTime:t,endTime:e,events:n,droppedCount:r}}clear(){this._events=[],this.startTime=void 0,this._droppedEventCount=0}},u=class{constructor(e){this.aggregator=new c,this.collectEvents=!0,this.logger=e.logger,this.evaluationEventQueue=new l(e.evaluationQueueLimit??1e3),this.flushIntervalDelay=e.flushIntervalDelay??3e4;let t=e.initialFlushIntervalDelay??5e3;this.flushTimeout=setTimeout(()=>this.flushAndScheduleNext(),t)}sanitizeValue(t,n){return e(t,n)}async flushAndScheduleNext(){(await this.flush()).fatalError?(this.collectEvents=!1,this.close(),this.logger.warn(`[TelemetryEventCollector] Received a fatal error from telemetry collection. No longer collecting events.`)):this.flushTimeout=setTimeout(()=>this.flushAndScheduleNext(),this.flushIntervalDelay)}async flush(){if(!this.reporter)return{success:!1,fatalError:!1};let e=this.evaluationEventQueue.takeSnapshot();return await this.reporter?.report({context:this._context,discreteEvents:{},aggregatedEvents:{evaluatedConfig:this.aggregator.aggregate(e)},droppedEvents:{evaluatedConfig:e.droppedCount}})}cancelScheduledFlush(){clearTimeout(this.flushTimeout)}async close(){this.collectEvents=!1,clearTimeout(this.flushTimeout),await this.flush(),this.evaluationEventQueue.clear()}dispose(){this.close()}},d=class extends u{constructor(e){super(e),this.reporter=new s(e)}async updateContext(e){this.cancelScheduledFlush(),await this.flush(),this._context=e,await this.flushAndScheduleNext()}evaluatedConfig(e){this.collectEvents&&this.evaluationEventQueue.push(e)}async forceFlush(){this.cancelScheduledFlush(),await this.flushAndScheduleNext()}};let f,p=(e,t,...n)=>({type:`Log`,payload:{level:e,message:t,args:n}}),m=e=>{try{self.postMessage(e)}catch{self.postMessage(p(e.payload.level,e.payload.message))}},h={debug:function(e,...t){m(p(`debug`,e,t))},info:function(e,...t){m(p(`info`,e,t))},warn:function(e,...t){m(p(`warn`,e,t))},error:function(e,...t){m(p(`error`,e,t))}};addEventListener(`message`,e=>{let t=e.data;if(t.type!=`Initialize`&&!f){h.info(`[TelemetryWorker] Ignoring ${t.type} because no collector is configured`);return}switch(h.debug(`[TelemetryWorker] Received '${t.type}' event:`,t),t.type){case`Initialize`:f=new d({...t.payload,baseUrl:new URL(t.payload.baseUrl),logger:h});break;case`EvaluatedConfigEvent`:f?.evaluatedConfig(t.payload);break;case`UpdateContext`:f?.updateContext(t.payload.context);break;case`Flush`:f?.forceFlush();break;case`Close`:(f?.close()??Promise.resolve()).then(()=>{self.postMessage({type:`Closed`}),self.close()});break}})})();"],{type:`application/javascript`}))),this.worker.onmessage=e=>{this.handleWorkerEvent(e.data)},this.worker.postMessage(t),this.visibilityHandler=()=>{document.visibilityState===`hidden`&&this.flush()};try{document.addEventListener(`visibilitychange`,this.visibilityHandler)}catch(e){this.logger.warn(`[TelemetryEventCollector] Could not configure 'visibilitychange' listener: `,e)}}async updateContext(e){let t={type:`UpdateContext`,payload:{context:e}};this.worker.postMessage(t)}evaluatedConfig(e){let t={type:`EvaluatedConfigEvent`,payload:this.sanitizeEvaluatedConfigEvent(e)};this.worker.postMessage(t)}sanitizeEvaluatedConfigEvent(e){return{...e,defaultValue:I(e.defaultValue,e.type),evaluatedValue:I(e.evaluatedValue,e.type)}}handleWorkerEvent(e){if(e.type===`Closed`){this.closeResolve?.();return}if(!e.payload?.level||!e.payload?.message)return;let{level:t,message:n,args:r}=e.payload;switch(t){case`debug`:this.logger.debug(n,...r);break;case`info`:this.logger.info(n,...r);break;case`warn`:this.logger.warn(n,...r);break;case`error`:this.logger.warn(n,...r);break}}flush(){this.worker.postMessage({type:`Flush`})}close(){return this.closePromise?this.closePromise:this.performClose()}performClose(){return document.removeEventListener(`visibilitychange`,this.visibilityHandler),this.closePromise=new Promise(e=>{this.closeResolve=e,this.worker.postMessage({type:`Close`})}),this.closePromise}};const B=new URL(`https://client-sdk-api.configdirector.com`);var V=class{constructor(e,t,n){this.handlersMap=new Map,this.eventEmitter=new u,this.ready=!1,this.logger=n?.logger??N(),this.timeout=n?.connection?.timeout??3e3;let r=this.parseUrl(n?.connection?.url)??B;this.streaming=n?.connection?.streaming!==!1;let i=this.streaming?S:F;this.usageEventCollector=new z({sdkKey:e,logger:this.logger,baseUrl:r}),this.transport=new i({clientSdkKey:e,baseUrl:r,metaContext:{...n?.metadata,sdkName:t.sdkName,sdkVersion:t.sdkVersion,userAgent:navigator?.userAgent},logger:this.logger}),this.transport.on(`configSetReceived`,e=>{this.readyResolve?.();let t=Object.keys(e.configs);!this.configSet||e.kind==`full`?(this.configSet=e,this.eventEmitter.emit(`configsUpdated`,{keys:t}),this.updateWatchers(e.configs)):(this.configSet.configs={...this.configSet.configs,...e.configs},this.eventEmitter.emit(`configsUpdated`,{keys:t}),this.updateWatchers(e.configs)),this.logger.debug(`[ConfigDirectorClient] ConfigSet updated from server:`,{keys:t})})}async initialize(e){await this.connectToTransport(e,`initialization`)}async updateContext(e){await this.connectToTransport(e,`context update`)}async connectToTransport(e,t){try{this.ready=!1,this.readyPromise=new Promise(e=>{this.readyResolve=e}).then(()=>{this.ready=!0,this.eventEmitter.emit(`clientReady`,{action:t}),this.logger.debug(`[ConfigDirectorClient] Received initial payload from the server, client is ready`)});let n=new Date().getTime();await this.transport.connect(e??{},this.timeout),this.currentContext=e,this.usageEventCollector.updateContext(e);let r=new Date().getTime()-n,i=this.timeout-r;if(i>0&&await Promise.race([this.readyPromise,new Promise(e=>{setTimeout(()=>e(),i)})]),!this.ready){let e=this.streaming?`The client will continue to retry since there were no fatal errors detected. Configs will return the default value until the connection succeeds.`:`Since the client was configured without streaming, configs may not update and always return the default value.`;this.logger.warn(`[ConfigDirectorClient] Timed out waiting for ${t} after ${this.timeout}ms. ${e}`)}}catch(e){this.logger.error(`[ConfigDirectorClient] An error occurred during ${t}: `,e)}}updateWatchers(e){Object.values(e).forEach(e=>this.updateWatchersForConfig(e))}updateWatchersForConfig(e){this.handlersMap.get(e.key)?.forEach(t=>{let n=this.getValueFromConfigState(e.key,e,t.defaultValue);t.handler(n)})}watch(e,t,n){this.validateDefaultValue(t);let r=this.handlersMap.get(e),i={handler:n,defaultValue:t,requestedType:typeof t};return r?r.push(i):this.handlersMap.set(e,[i]),()=>this.unwatch(e,n)}unwatch(e,t){let n=this.handlersMap.get(e);if(n)if(t){let e=n.findIndex(e=>e.handler==t);e>=0&&n?.splice(e,1)}else n.splice(0)}getValue(e,t){this.validateDefaultValue(t);let n=this.configSet?.configs[e];return this.getValueFromConfigState(e,n,t)}getValueFromConfigState(e,t,n){if(!t)return this.logger.debug(`[ConfigDirectorClient] No config state found for '${e}', returning default value '${n}'`),this.usageEventCollector.evaluatedConfig({contextId:this.currentContext?.id,key:e,defaultValue:n,requestedType:C(n),evaluatedValue:n,usedDefault:!0,evaluationReason:`config-state-missing`}),n;let r=T(t,n);return this.usageEventCollector.evaluatedConfig({contextId:this.currentContext?.id,key:e,defaultValue:n,requestedType:r.requestedType,evaluatedValue:r.parsedValue,usedDefault:r.usedDefault,evaluationReason:r.reason}),this.logger.debug(`[ConfigDirectorClient] Evaluated '${e}' to '${r.parsedValue}'`),r.parsedValue}parseUrl(e){if(e)try{return new URL(e)}catch(t){throw new f(`Invalid base URL '${e}'. Parsing failed: ${t}`)}}validateDefaultValue(e){if(e==null)throw new f(`Invalid default value. The default value for a config must be defined and non-null.`);if(typeof e==`function`)throw new f(`Invalid default value. The default value for a config cannot be a function.`)}get isReady(){return this.ready}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.logger.debug(`[ConfigDirectorClient] clear() has been called, removing all observers`),this.eventEmitter.clear(),this.handlersMap.clear()}unwatchAll(){this.handlersMap.clear()}close(){this.logger.debug(`[ConfigDirectorClient] close() has been called, closing connection to server`),this.transport.close(),this.ready=!1}dispose(){this.clear(),this.close()}};const H=(e,t)=>new V(e,{sdkName:`react-web-sdk`,sdkVersion:`0.3.0`},t),U=c.default.createContext({status:`loading`});var W=class{decorateMessage(e){return`[ConfigDirector:react-web-sdk] ${e}`}};const G=e=>N(e,new W),K=async e=>{let t=e.logger??G(`debug`),n=H(e.sdkKey,{connection:{url:e.url,timeout:e.timeout},metadata:{appName:e.appName,appVersion:e.appVersion},logger:t});return await n.initialize(e.context),({children:e})=>{let[t,r]=(0,c.useState)(()=>({client:n,status:n.isReady?`ready`:`default`}));return(0,c.useEffect)(()=>{n.on(`configsUpdated`,()=>{r(e=>({...e,updatedAt:new Date}))}),n.on(`clientReady`,()=>{r(e=>({...e,status:`ready`}))})}),(0,l.jsx)(U.Provider,{value:t,children:e})}};var q=class extends c.Component{constructor(e){super(e),this.state={client:H(e.sdkKey,{connection:{url:e.url,timeout:e.timeout},metadata:{appName:e.appName,appVersion:e.appVersion},logger:e.logger??G(`warn`)}),status:`loading`}}async componentDidMount(){this.state.client?.on(`configsUpdated`,()=>{this.setState({updatedAt:new Date})}),this.state.client?.on(`clientReady`,()=>{this.setState({status:`ready`})}),await this.state.client?.initialize(this.props.context),this.state.client?.isReady||this.setState({status:`default`})}componentWillUnmount(){this.state.client?.dispose()}render(){return(0,l.jsx)(U.Provider,{value:this.state,children:this.props.children})}},J=class e extends Error{constructor(t){super(t),this.name=`ConfigDirectorReactContextError`,Object.setPrototypeOf(this,e.prototype)}};const Y=()=>new J(`The ConfigDirector client was not found in the React context. Please make sure the component using this hook is inside the context of a ConfigDirectorProvider.`),X=(e,t)=>{let n=(0,c.useContext)(U);if(!n?.client)throw Y();return{value:n.client.getValue(e,t),readyStatus:n.status,loading:n.status===`loading`}},Z=()=>{let e=(0,c.useContext)(U);if(!e?.client)throw Y();return{updateContext:async t=>{await e.client?.updateContext(t)}}},Q=()=>{let e=(0,c.useContext)(U);if(!e?.client)throw Y();return{client:e.client}};exports.ConfigDirectorProvider=q,exports.createConsoleLogger=G,exports.useConfigDirectorClient=Q,exports.useConfigDirectorContext=Z,exports.useConfigValue=X,exports.withProvider=K;
3
+ `;break;case`id`:e.value.includes(`\0`)||(this.lastEventId=e.value);break;case`retry`:/^\d+$/.test(e.value)&&this.onRetry?.(Number.parseInt(e.value,10));break;default:break}}parseContentLine(e){let t=e.indexOf(`:`);return t===-1?{field:e,value:``}:{field:e.slice(0,t),value:this.getValueFromLine(t,e)}}splitLines(e){let t=e.split(/\r\n|\r|\n/);return this.previousIncompleteLine=t.pop()??``,t}getValueFromLine(e,t){if(e===-1)return``;let n=t[e+1]===` `?e+2:e+1;return t.slice(n)}prepareChunk(e){return this.isFirstChunk?(this.isFirstChunk=!1,this.previousIncompleteLine+e.replace(/^\xEF\xBB\xBF/,``).replace(/^\uFEFF/,``)):this.previousIncompleteLine+e}};let y=function(e){return e.OPEN=`open`,e.CLOSED=`closed`,e.CONNECTING=`connecting`,e}({});var b=class{constructor(e){this.DEFAULT_SHOULD_RECONNECT=()=>!0,this.DEFAULT_CALCULATE_RECONNECT_DELAY=()=>this.serverReconnectionTime,this.reconnectAttempt=0,this.abortController=new AbortController,this._readyState=y.CLOSED,this.serverReconnectionTime=2e3,this.url=e.url.toString(),this.lastEventId=e.lastEventId,this.headers={Accept:`text/event-stream`,...e.headers},this.requestOptions={body:e.body,method:e.method??`GET`,mode:e.mode,credentials:e.credentials,redirect:e.redirect,referrer:e.referrer,referrerPolicy:e.referrerPolicy},this._fetch=e.fetch??((e,t)=>fetch(e,t)),this._onError=this.getValidatedFunctionOrNoOp(e.onError,`onError`),this._onConnect=this.getValidatedFunctionOrNoOp(e.onConnect,`onConnect`),this._onDisconnect=this.getValidatedFunctionOrNoOp(e.onDisconnect,`onDisconnect`),this._onMessage=this.getValidatedFunctionOrNoOp(e.onMessage,`onMessage`),this._onComment=this.getValidatedFunctionOrNoOp(e.onComment,`onComment`),this._shouldReconnect=this.getValidatedFunctionOr(e.shouldReconnect,this.DEFAULT_SHOULD_RECONNECT,`shouldReconnect`),this._calculateReconnectDelay=this.getValidatedFunctionOr(e.calculateReconnectDelay,this.DEFAULT_CALCULATE_RECONNECT_DELAY,`calculateReconnectDelay`)}set onError(e){this._onError=this.getValidatedFunctionOrNoOp(e,`onError`)}set onMessage(e){this._onMessage=this.getValidatedFunctionOrNoOp(e,`onMessage`)}set onComment(e){this._onComment=this.getValidatedFunctionOrNoOp(e,`onComment`)}set onConnect(e){this._onConnect=this.getValidatedFunctionOrNoOp(e,`onConnect`)}set onDisconnect(e){this._onDisconnect=this.getValidatedFunctionOrNoOp(e,`onDisconnect`)}set shouldReconnect(e){this._shouldReconnect=this.getValidatedFunctionOr(e,this.DEFAULT_SHOULD_RECONNECT,`shouldReconnect`)}set calculateReconnectDelay(e){this._calculateReconnectDelay=this.getValidatedFunctionOr(e,this.DEFAULT_CALCULATE_RECONNECT_DELAY,`shouldReconnect`)}get readyState(){return this._readyState}connect(){this._readyState===y.CLOSED&&(this.reconnectAttempt=0,this.initiateConnection())}initiateConnection(){this.abortController=new AbortController,this._readyState=y.CONNECTING,this._fetch(this.url,{...this.requestOptions,headers:this.buildHeaders(),signal:this.abortController.signal,cache:`no-store`}).then(this.handleFetchResponse.bind(this)).catch(e=>{if(e.name===`AbortError`||this.abortController.signal.aborted){this.close();return}this._onError(e),this.scheduleReconnect({error:e})})}close(){clearTimeout(this.reconnectTimeout),this._readyState=y.CLOSED,this.abortController.abort()}disconnected(){clearTimeout(this.reconnectTimeout),this._readyState=y.CLOSED,this._onDisconnect()}buildHeaders(){let e=this.lastEventId?{"Last-Event-ID":this.lastEventId}:void 0;return{...this.headers,...e}}async handleFetchResponse(e){let{body:t,status:n}=e;if(n===204){this.disconnected();return}if(n>=400){this.scheduleReconnect({status:n});return}if(!t)throw new h(`The server response did not have a body`);this._readyState=y.OPEN,this._onConnect(),this.reconnectAttempt=0;let r=t.getReader(),i=new TextDecoder,a=new v({onEvent:e=>{typeof e.id==`string`&&(this.lastEventId=e.id),this._onMessage(e)},onComment:e=>this._onComment(e),onRetry:e=>this.serverReconnectionTime=e}),o=!1;for(;!o;){let{done:e,value:t}=await r.read();t&&a.parse(i.decode(t,{stream:!0})),o=e}a.finish(),this.scheduleReconnect({status:n,error:new m(`The server response stream was closed`)})}scheduleReconnect(e){if(this.abortController.signal.aborted)return;clearTimeout(this.reconnectTimeout),this.reconnectAttempt+=1;let t={attempt:this.reconnectAttempt,status:e.status,error:e.error,serverReconnectionTime:this.serverReconnectionTime};if(this._shouldReconnect(t)){this._readyState=y.CONNECTING;let e=this._calculateReconnectDelay(t);(!Number.isFinite(e)||e<1||e>1e3*60*60)&&(this._onError(new _(`The calculated reconnect delay is out of range: ${e}. Defaulting to ${this.serverReconnectionTime}`)),e=this.serverReconnectionTime),this.reconnectTimeout=setTimeout(()=>this.initiateConnection(),e)}else{this.disconnected();return}}getValidatedFunctionOrNoOp(e,t){return this.getValidatedFunctionOr(e,()=>{},t)}getValidatedFunctionOr(e,t,n){if(e==null)return t;if(typeof e==`function`)return e;throw new g(`${n} must be a function`)}};const x=e=>new b(e);var S=class{constructor(e){this.options=e,this.eventEmitter=new u,this.options=e,this.logger=e.logger,this.url=e.resolveUrl(`client/sse/v1`,e.baseUrl)}async connect(e,t){this.eventSource&&this.close();let n=new Promise((t,n)=>{this.eventSource=x({url:this.url,method:`POST`,headers:{"Content-Type":`application/json`},fetch:this.options.fetch,body:JSON.stringify({givenContext:e,metaContext:this.options.metaContext,clientSdkKey:this.options.clientSdkKey}),onMessage:({data:e})=>{this.dispatchMessage(e)},onConnect:()=>{this.logger.debug(`[EventSourceTransport] Connected`),t(this)},shouldReconnect:e=>{let t=!this.isStatusFatal(e.status);return t||n(this.prepareFatalError(e.status,e.error)),t},calculateReconnectDelay:e=>{let t=this.options.connectionRetryDelay(e.attempt);return this.logger.warn(`[EventSourceTransport] Scheduling reconnect in ${t}ms.`),t},onError:e=>{this.logger.debug(`[EventSourceTransport] Error: `,e)},onDisconnect:()=>{this.logger.debug(`[EventSourceTransport] Disconnected`)}}),this.eventSource.connect()});return clearTimeout(this.timeoutTimer),this.timeoutTimer=void 0,Promise.race([n,new Promise(e=>{this.timeoutTimer=setTimeout(()=>e(this),t)})]).finally(()=>clearTimeout(this.timeoutTimer))}dispatchMessage(e){try{let t=JSON.parse(e);this.eventEmitter.emit(`configSetReceived`,t)}catch(e){this.logger.error(`[EventSourceTransport] Error parsing and dispatching config data update: `,e)}}prepareFatalError(e,t){let n=e??0;return new d(`${`Connection failed with status: ${e??`unknown`}.`}${t?` Error: ${t}`:``}. This is an unrecoverable error, will not attempt to reconnect.`,n)}isStatusFatal(e){return!!e&&e>=400&&e<500}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.eventEmitter.clear()}close(){this.eventSource?.close(),clearTimeout(this.timeoutTimer)}dispose(){this.close(),this.clear()}};const C=e=>{let t=typeof e;if(t===`object`)try{return e.constructor?.name??t}catch{return t}else if(t===`function`)try{let n=e.name;return n?`function: ${n}`:t}catch{return t}return t},w=e=>e===`number`||e===`bigint`,T=(e,t)=>{let n=e.value,r=C(t);if(!n)return{parsedValue:t,requestedType:r,usedDefault:!0,reason:`value-missing`};if(typeof t==`string`)return{parsedValue:n,requestedType:r,usedDefault:!1,reason:`found-match`};if(typeof t==`boolean`&&e.type===`boolean`){let e=E(n),i=typeof e==`boolean`;return{parsedValue:i?e:t,requestedType:r,usedDefault:!i,reason:i?`found-match`:`invalid-boolean`}}if(w(typeof t)&&e.type===`integer`){let e=D(n),i=typeof e==`number`;return{parsedValue:i?e:t,requestedType:r,usedDefault:!i,reason:i?`found-match`:`invalid-number`}}if(w(typeof t)&&(e.type===`float`||e.type===`enum`)){let e=O(n),i=typeof e==`number`;return{parsedValue:i?e:t,requestedType:r,usedDefault:!i,reason:i?`found-match`:`invalid-number`}}return{parsedValue:n,requestedType:r,usedDefault:!1,reason:`found-match`}},E=e=>{if(!e)return;let t=e.toLowerCase();if(!(t!=`true`&&t!=`false`))return t===`true`},D=e=>{if(!e)return;let t=Number.parseInt(e);if(!(isNaN(t)||!isFinite(t)))return t},O=e=>{if(!e)return;let t=Number.parseFloat(e);if(!(isNaN(t)||!isFinite(t)))return t},k={off:-1,error:0,warn:1,info:2,debug:3},A=()=>{let e={year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,timeZoneName:`short`};try{return new Intl.DateTimeFormat(void 0,{...e,fractionalSecondDigits:3})}catch{return new Intl.DateTimeFormat(void 0,e)}};var j=class{constructor(e,t){this.level=e,this.decorator=t,this.level=e,this.decorator=t,this.dateFormatter=A()}debug(e,...t){this.log(console.debug,`debug`,e,...t)}info(e,...t){this.log(console.info,`info`,e,...t)}warn(e,...t){this.log(console.warn,`warn`,e,...t)}error(e,...t){this.log(console.error,`error`,e,...t)}log(e,t,n,...r){k[this.level]>=k[t]&&e(`[${this.dateFormatter.format(new Date)}] ${this.decorator?.decorateMessage(n)}`,...r)}},M=class{decorateMessage(e){return`[ConfigDirector:js-client-sdk] ${e}`}};const N=(e,t)=>new j(e??`warn`,t??new M),P=async(e,t,n,r)=>{let i=new AbortController,a=setTimeout(()=>{r.debug(`[fetchWithTimeout] Reached timeout, aborting request`),i.abort()},e);try{let e=await fetch(typeof t==`string`||t instanceof Request?t:t.toString(),{...n,signal:i.signal});return clearTimeout(a),e}catch(e){throw r.warn(`[fetchWithTimeout] Fetch error: `,e),clearTimeout(a),e}};var F=class{constructor(e){this.options=e,this.eventEmitter=new u,this.fatalError=!1,this.options=e,this.logger=e.logger,this.url=e.resolveUrl(`client/pull/v1`,e.baseUrl)}async connect(e,t){if(this.fatalError)return this.logger.warn(`[PullTransport] There was a prior unrecoverable error. Ignoring attempt to reconnect.`),this;try{let n=await P(t,this.url,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({givenContext:e,metaContext:this.options.metaContext,clientSdkKey:this.options.clientSdkKey})},this.logger);if(!n.ok)throw this.isStatusFatal(n.status)?(this.fatalError=!0,this.prepareFatalResponseStatusError(n.status,await n.text())):new d(`Connection failed with status: ${n.status}`,n.status);let r=JSON.parse(await n.text());return this.eventEmitter.emit(`configSetReceived`,r),this}catch(e){throw p(e)?(this.fatalError=!0,new d(`Connection failed with fatal error: ${e}. This is an unrecoverable error, retry attempts will be ignored.`)):e instanceof SyntaxError?new d(`Failed to parse the response from the server: ${e}`):new d(`Connection failed with error: ${e}.`)}}prepareFatalResponseStatusError(e,t){let n=e??0;return new d(`${`Connection failed with status: ${e??`unknown`}`}${(t?.trim()?.length??0)>0?` (${t})`:``}. This is an unrecoverable error, retry attempts will be ignored.`,n)}isStatusFatal(e){return!!e&&e>=400&&e<500}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.eventEmitter.clear()}close(){}dispose(){this.close(),this.clear()}};const I=(e,t)=>new URL(e,t?.toString()),L=e=>{if(e)try{return new URL(e)}catch(t){throw new f(`Invalid URL '${e}'. Parsing failed: ${t}`)}};var R=class{constructor(e,t,n,r,i){this.handlersMap=new Map,this.eventEmitter=new u,this.ready=!1,this.logger=r?.logger??N(),this.timeout=r?.connection?.timeout??3e3;let a=i?.urlFactory??I,o=this.parseUrl(r?.connection?.url,a)??`https://client-sdk-api.configdirector.com`;this.streaming=r?.connection?.streaming!==!1;let s=this.streaming?S:F;this.telemetryClient=e,this.transport=new s({clientSdkKey:t,baseUrl:o,resolveUrl:a,metaContext:{...r?.metadata,sdkName:n.sdkName,sdkVersion:n.sdkVersion,userAgent:navigator?.userAgent},logger:this.logger,fetch:i?.fetch,connectionRetryDelay:i?.connectionRetryDelay??(e=>2**Math.min(e,9)*1e3)}),this.transport.on(`configSetReceived`,e=>{this.readyResolve?.();let t=Object.keys(e.configs);!this.configSet||e.kind==`full`?(this.configSet=e,this.eventEmitter.emit(`configsUpdated`,{keys:t}),this.updateWatchers(e.configs)):(this.configSet.configs={...this.configSet.configs,...e.configs},this.eventEmitter.emit(`configsUpdated`,{keys:t}),this.updateWatchers(e.configs)),this.logger.debug(`[ConfigDirectorClient] ConfigSet updated from server:`,{keys:t})})}async initialize(e){await this.connectToTransport(e,`initialization`)}async updateContext(e){await this.connectToTransport(e,`context update`)}async connectToTransport(e,t){try{this.ready=!1,this.readyPromise=new Promise(e=>{this.readyResolve=e}).then(()=>{this.ready=!0,this.eventEmitter.emit(`clientReady`,{action:t}),this.logger.debug(`[ConfigDirectorClient] Received initial payload from the server, client is ready`)});let n=new Date().getTime();await this.transport.connect(e??{},this.timeout),this.currentContext=e,this.telemetryClient.updateContext(e);let r=new Date().getTime()-n,i=this.timeout-r;if(clearTimeout(this.timeoutTimer),this.timeoutTimer=void 0,i>0&&await Promise.race([this.readyPromise,new Promise(e=>{this.timeoutTimer=setTimeout(()=>e(),i)})]).finally(()=>clearTimeout(this.timeoutTimer)),!this.ready){let e=this.streaming?`The client will continue to retry since there were no fatal errors detected. Configs will return the default value until the connection succeeds.`:`Since the client was configured without streaming, configs may not update and always return the default value.`;this.logger.warn(`[ConfigDirectorClient] Timed out waiting for ${t} after ${this.timeout}ms. ${e}`)}}catch(e){this.logger.error(`[ConfigDirectorClient] An error occurred during ${t}: `,e)}}updateWatchers(e){Object.values(e).forEach(e=>this.updateWatchersForConfig(e))}updateWatchersForConfig(e){this.handlersMap.get(e.key)?.forEach(t=>{let n=this.getValueFromConfigState(e.key,e,t.defaultValue);t.handler(n)})}watch(e,t,n){this.validateDefaultValue(t);let r=this.handlersMap.get(e),i={handler:n,defaultValue:t,requestedType:typeof t};return r?r.push(i):this.handlersMap.set(e,[i]),()=>this.unwatch(e,n)}unwatch(e,t){let n=this.handlersMap.get(e);if(n)if(t){let e=n.findIndex(e=>e.handler==t);e>=0&&n?.splice(e,1)}else n.splice(0)}getValue(e,t){this.validateDefaultValue(t);let n=this.configSet?.configs[e];return this.getValueFromConfigState(e,n,t)}getValueFromConfigState(e,t,n){if(!t)return this.logger.debug(`[ConfigDirectorClient] No config state found for '${e}', returning default value '${n}'`),this.telemetryClient.evaluatedConfig({contextId:this.currentContext?.id,key:e,defaultValue:n,requestedType:C(n),evaluatedValue:n,usedDefault:!0,evaluationReason:`config-state-missing`}),n;let r=T(t,n);return this.telemetryClient.evaluatedConfig({contextId:this.currentContext?.id,key:e,defaultValue:n,requestedType:r.requestedType,evaluatedValue:r.parsedValue,usedDefault:r.usedDefault,evaluationReason:r.reason}),this.logger.debug(`[ConfigDirectorClient] Evaluated '${e}' to '${r.parsedValue}'`),r.parsedValue}parseUrl(e,t){if(e)try{return t(e)}catch(t){throw new f(`Invalid base URL '${e}'. Parsing failed: ${t}`)}}validateDefaultValue(e){if(e==null)throw new f(`Invalid default value. The default value for a config must be defined and non-null.`);if(typeof e==`function`)throw new f(`Invalid default value. The default value for a config cannot be a function.`)}get isReady(){return this.ready}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.logger.debug(`[ConfigDirectorClient] clear() has been called, removing all observers`),this.eventEmitter.clear(),this.handlersMap.clear()}unwatchAll(){this.handlersMap.clear()}pauseNetwork(){this.logger.debug(`[ConfigDirectorClient] pauseNetwork() called, pausing transport connection`),clearTimeout(this.timeoutTimer),this.timeoutTimer=void 0,this.transport.close(),this.ready=!1}async resumeNetwork(){await this.connectToTransport(this.currentContext,`network resume`)}async close(){this.logger.debug(`[ConfigDirectorClient] close() has been called, closing connection to server`),clearTimeout(this.timeoutTimer),this.readyResolve?.(),this.telemetryClient.close(),this.transport.close(),this.ready=!1}dispose(){this.clear(),this.close()}};const z=(e,t)=>{if(t===`json`)try{return B(JSON.stringify(e))}catch{return e.toString().slice(0,500)}return e.toString().slice(0,500)},B=e=>V(new TextEncoder().encode(e)).toString(16).padStart(8,`0`),V=e=>{let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+(e[n]??0),t>>>=0;return t};var H=class{constructor(e){this.logger=e.logger;let t={type:`Initialize`,payload:{sdkKey:e.sdkKey,baseUrl:e.baseUrl.toString(),evaluationQueueLimit:e.evaluationQueueLimit??1e3,initialFlushIntervalDelay:e.initialFlushIntervalDelay??5e3,flushIntervalDelay:e.flushIntervalDelay??3e4}};this.worker=new Worker(URL.createObjectURL(new Blob(["(function(){let e=(e,n)=>{if(n===`json`)try{return t(JSON.stringify(e))}catch{return e.toString().slice(0,500)}return e.toString().slice(0,500)},t=e=>n(new TextEncoder().encode(e)).toString(16).padStart(8,`0`),n=e=>{let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+(e[n]??0),t>>>=0;return t},r=e=>{let t=Object.keys(e);if(t.length==0)return!0;for(let n of t)if((e[n]?.length??0)>0)return!1;return!0},i=e=>{if(!e)return!0;let t=Object.keys(e);if(t.length==0)return!0;for(let n of t)if((e[n]??0)>0)return!1;return!0},a=async(e,t,n,r)=>{let i=new AbortController,a=setTimeout(()=>{r.debug(`[fetchWithTimeout] Reached timeout, aborting request`),i.abort()},e);try{let e=await fetch(typeof t==`string`||t instanceof Request?t:t.toString(),{...n,signal:i.signal});return clearTimeout(a),e}catch(e){throw r.warn(`[fetchWithTimeout] Fetch error: `,e),clearTimeout(a),e}},o=e=>e?.name===`NotAllowedError`?!0:e instanceof TypeError;var s=class{constructor(e){this.executeRequests=!0,this.sdkKey=e.sdkKey,this.logger=e.logger,this.url=e.urlFactory(`client/telemetry/v1`,e.baseUrl)}async report({context:e,discreteEvents:t,aggregatedEvents:n,droppedEvents:r}){if(!this.executeRequests)return{success:!1,fatalError:!0};let i={clientSdkKey:this.sdkKey,context:e,discreteEvents:t,aggregatedEvents:n,droppedEvents:r};if(this.isReportEmpty(i))return{success:!0,fatalError:!1};let a=await this.sendReport(i);return a.fatalError&&(this.executeRequests=!1),a}isReportEmpty(e){return r(e.discreteEvents)&&r(e.aggregatedEvents)&&i(e.droppedEvents)}async sendReport(e){try{let t=await a(5e3,this.url,{method:`POST`,body:JSON.stringify(e),keepalive:!0},this.logger),n=this.isStatusFatal(t.status);return n&&this.logger.warn(`[EventReporter] Received a fatal status response (${t.status}) from the telemetry endpoint. No more telemetry data will be sent.`),{success:t.ok,fatalError:n}}catch(e){let t=o(e);return this.logger.warn(`[EventReporter] Error attempting to send telemetry data: ${e}`,{error:e}),{success:!1,fatalError:t}}}isStatusFatal(e){return!!e&&e>=400&&e<500}},c=class{aggregate(e){if(e.events.length==0)return[];let t=new Map;for(let n of e.events){let e=JSON.stringify(n),r=t.get(e)?.count||0;t.set(e,{event:n,count:r+1})}return Array.from(t).map(([,t])=>({startTime:e.startTime,endTime:e.endTime,count:t.count,event:t.event}))}},l=class{constructor(e){this._events=[],this._droppedEventCount=0,this.limit=e??1e3}get events(){return this._events}get reachedLimit(){return this._events.length>=this.limit}get droppedEventCount(){return this._droppedEventCount}push(...e){this.startTime||=new Date;let t=Math.max(0,e.length-this.limit),n=e.slice(t,e.length);if(this._droppedEventCount+=t,this._events.length+n.length>this.limit){let e=this._events.length+n.length-this.limit;this._events.splice(0,e),this._droppedEventCount+=e}return this._events.push(...n)}takeSnapshot(){let e=new Date,t=this.startTime??e,n=this._events.splice(0),r=this._droppedEventCount;return this.startTime=void 0,this._droppedEventCount=0,{startTime:t,endTime:e,events:n,droppedCount:r}}clear(){this._events=[],this.startTime=void 0,this._droppedEventCount=0}},u=class{constructor(e){this.aggregator=new c,this.collectEvents=!0,this.logger=e.logger,this.evaluationEventQueue=new l(e.evaluationQueueLimit??1e3),this.flushIntervalDelay=e.flushIntervalDelay??3e4;let t=e.initialFlushIntervalDelay??5e3;this.flushTimeout=setTimeout(()=>this.flushAndScheduleNext(),t)}sanitizeValue(t,n){return e(t,n)}async flushAndScheduleNext(){(await this.flush()).fatalError?(this.collectEvents=!1,this.close(),this.logger.warn(`[TelemetryEventCollector] Received a fatal error from telemetry collection. No longer collecting events.`)):this.flushTimeout=setTimeout(()=>this.flushAndScheduleNext(),this.flushIntervalDelay)}async flush(){if(!this.reporter)return{success:!1,fatalError:!1};let e=this.evaluationEventQueue.takeSnapshot();return await this.reporter?.report({context:this._context,discreteEvents:{},aggregatedEvents:{evaluatedConfig:this.aggregator.aggregate(e)},droppedEvents:{evaluatedConfig:e.droppedCount}})}cancelScheduledFlush(){clearTimeout(this.flushTimeout)}async close(){this.collectEvents=!1,clearTimeout(this.flushTimeout),await this.flush(),this.evaluationEventQueue.clear()}dispose(){this.close()}},d=class extends u{constructor(e){super(e),this.reporter=new s(e)}async updateContext(e){this.cancelScheduledFlush(),await this.flush(),this._context=e,await this.flushAndScheduleNext()}evaluatedConfig(e){this.collectEvents&&this.evaluationEventQueue.push(e)}async forceFlush(){this.cancelScheduledFlush(),await this.flushAndScheduleNext()}};let f=(e,t)=>new URL(e,t?.toString()),p,m=(e,t,...n)=>({type:`Log`,payload:{level:e,message:t,args:n}}),h=e=>{try{self.postMessage(e)}catch{self.postMessage(m(e.payload.level,e.payload.message))}},g={debug:function(e,...t){h(m(`debug`,e,t))},info:function(e,...t){h(m(`info`,e,t))},warn:function(e,...t){h(m(`warn`,e,t))},error:function(e,...t){h(m(`error`,e,t))}};addEventListener(`message`,e=>{let t=e.data;if(t.type!=`Initialize`&&!p){g.info(`[TelemetryWorker] Ignoring ${t.type} because no collector is configured`);return}switch(g.debug(`[TelemetryWorker] Received '${t.type}' event:`,t),t.type){case`Initialize`:p=new d({...t.payload,baseUrl:f(t.payload.baseUrl),urlFactory:f,logger:g});break;case`EvaluatedConfigEvent`:p?.evaluatedConfig(t.payload);break;case`UpdateContext`:p?.updateContext(t.payload.context);break;case`Flush`:p?.forceFlush();break;case`Close`:(p?.close()??Promise.resolve()).then(()=>{self.postMessage({type:`Closed`}),self.close()});break}})})();"],{type:`application/javascript`}))),this.worker.onmessage=e=>{this.handleWorkerEvent(e.data)},this.worker.postMessage(t),this.visibilityHandler=()=>{document.visibilityState===`hidden`&&this.flush()};try{document.addEventListener(`visibilitychange`,this.visibilityHandler)}catch(e){this.logger.warn(`[TelemetryEventCollector] Could not configure 'visibilitychange' listener: `,e)}}async updateContext(e){let t={type:`UpdateContext`,payload:{context:e}};this.worker.postMessage(t)}evaluatedConfig(e){let t={type:`EvaluatedConfigEvent`,payload:this.sanitizeEvaluatedConfigEvent(e)};this.worker.postMessage(t)}sanitizeEvaluatedConfigEvent(e){return{...e,defaultValue:z(e.defaultValue,e.type),evaluatedValue:z(e.evaluatedValue,e.type)}}handleWorkerEvent(e){if(e.type===`Closed`){this.closeResolve?.();return}if(!e.payload?.level||!e.payload?.message)return;let{level:t,message:n,args:r}=e.payload;switch(t){case`debug`:this.logger.debug(n,...r);break;case`info`:this.logger.info(n,...r);break;case`warn`:this.logger.warn(n,...r);break;case`error`:this.logger.warn(n,...r);break}}flush(){this.worker.postMessage({type:`Flush`})}close(){return this.closePromise?this.closePromise:this.performClose()}performClose(){return document.removeEventListener(`visibilitychange`,this.visibilityHandler),this.closePromise=new Promise(e=>{this.closeResolve=e,this.worker.postMessage({type:`Close`})}),this.closePromise}};const U=(e,t,n)=>{let r=n?.logger??N();return new R(new H({sdkKey:e,logger:r,baseUrl:L(n?.connection?.url)??`https://client-sdk-api.configdirector.com`,urlFactory:I}),e,t,{...n,logger:r})},W=(e,t)=>U(e,{sdkName:`react-web-sdk`,sdkVersion:`0.3.1`},t),G=c.default.createContext({status:`loading`});var K=class{decorateMessage(e){return`[ConfigDirector:react-web-sdk] ${e}`}};const q=e=>N(e,new K),J=async e=>{let t=e.logger??q(`debug`),n=W(e.sdkKey,{connection:{url:e.url,timeout:e.timeout},metadata:{appName:e.appName,appVersion:e.appVersion},logger:t});return await n.initialize(e.context),({children:e})=>{let[t,r]=(0,c.useState)(()=>({client:n,status:n.isReady?`ready`:`default`}));return(0,c.useEffect)(()=>{n.on(`configsUpdated`,()=>{r(e=>({...e,updatedAt:new Date}))}),n.on(`clientReady`,()=>{r(e=>({...e,status:`ready`}))})}),(0,l.jsx)(G.Provider,{value:t,children:e})}};var Y=class extends c.Component{constructor(e){super(e),this.state={client:W(e.sdkKey,{connection:{url:e.url,timeout:e.timeout},metadata:{appName:e.appName,appVersion:e.appVersion},logger:e.logger??q(`warn`)}),status:`loading`}}async componentDidMount(){this.state.client?.on(`configsUpdated`,()=>{this.setState({updatedAt:new Date})}),this.state.client?.on(`clientReady`,()=>{this.setState({status:`ready`})}),await this.state.client?.initialize(this.props.context),this.state.client?.isReady||this.setState({status:`default`})}async componentDidUpdate(e){e.context!==this.props.context&&(this.setState({status:`loading`}),await this.state.client?.updateContext(this.props.context??{}),this.state.client?.isReady||this.setState({status:`default`}))}componentWillUnmount(){this.state.client?.dispose()}render(){return(0,l.jsx)(G.Provider,{value:this.state,children:this.props.children})}},X=class e extends Error{constructor(t){super(t),this.name=`ConfigDirectorReactContextError`,Object.setPrototypeOf(this,e.prototype)}};const Z=()=>new X(`The ConfigDirector client was not found in the React context. Please make sure the component using this hook is inside the context of a ConfigDirectorProvider.`),Q=(e,t)=>{let n=(0,c.useContext)(G);if(!n?.client)throw Z();return{value:n.client.getValue(e,t),readyStatus:n.status,loading:n.status===`loading`}},$=()=>{let e=(0,c.useContext)(G);if(!e?.client)throw Z();return{updateContext:async t=>{await e.client?.updateContext(t)}}},ee=()=>{let e=(0,c.useContext)(G);if(!e?.client)throw Z();return{client:e.client}};exports.ConfigDirectorProvider=Y,exports.createConsoleLogger=q,exports.useConfigDirectorClient=ee,exports.useConfigDirectorContext=$,exports.useConfigValue=Q,exports.withProvider=J;
@@ -52,7 +52,7 @@ type ConfigDirectorContext = {
52
52
  };
53
53
  //#endregion
54
54
  //#region ../js-client-core/src/types.d.ts
55
- type ClientConnectAction = "initialization" | "context update";
55
+ type ClientConnectAction = "initialization" | "context update" | "network resume";
56
56
  type ClientEvents = {
57
57
  configsUpdated: {
58
58
  keys: string[];
@@ -134,6 +134,19 @@ interface ConfigDirectorClient extends EventProvider<ClientEvents> {
134
134
  * Removes all subscribers from all config keys
135
135
  */
136
136
  unwatchAll(): void;
137
+ /**
138
+ * Pauses the network connection without clearing event handlers, watch handlers, or config
139
+ * state. Intended for mobile environments where the OS may kill background connections (e.g.
140
+ * when the app is backgrounded on iOS/Android).
141
+ *
142
+ * Call {@link resumeNetwork} to re-establish the connection.
143
+ */
144
+ pauseNetwork(): void;
145
+ /**
146
+ * Resumes a connection that was paused via {@link pauseNetwork}, using the last context that
147
+ * was provided to {@link initialize} or {@link updateContext}.
148
+ */
149
+ resumeNetwork(): Promise<void>;
137
150
  /**
138
151
  * Disposes of the client. All connections are closed, and all event and config key subscribers
139
152
  * are removed.
@@ -143,15 +156,6 @@ interface ConfigDirectorClient extends EventProvider<ClientEvents> {
143
156
  dispose(): void;
144
157
  }
145
158
  //#endregion
146
- //#region ../js-client-core/src/telemetry/types.d.ts
147
- declare global {
148
- interface Window {
149
- ConfigDirector: {
150
- logger: ConfigDirectorLogger;
151
- };
152
- }
153
- }
154
- //#endregion
155
159
  //#region src/types.d.ts
156
160
  type ClientStatus = "loading" | "ready" | "default";
157
161
  interface ConfigDirectorContextData {
@@ -181,6 +185,7 @@ declare const withProvider: (options: ConfigDirectorProviderOptions) => Promise<
181
185
  declare class ConfigDirectorProvider extends Component<PropsWithChildren<ConfigDirectorProviderOptions>, ConfigDirectorProviderState> {
182
186
  constructor(props: ConfigDirectorProviderOptions);
183
187
  componentDidMount(): Promise<void>;
188
+ componentDidUpdate(prevProps: PropsWithChildren<ConfigDirectorProviderOptions>): Promise<void>;
184
189
  componentWillUnmount(): void;
185
190
  render(): _$react_jsx_runtime0.JSX.Element;
186
191
  }
@@ -1 +1 @@
1
- {"version":3,"file":"configdirector-react-client.d.cts","names":[],"sources":["../../js-client-core/src/Emitter.ts","../../shared/src/types.ts","../../js-client-core/src/types.ts","../../js-client-core/src/telemetry/types.ts","../src/types.ts","../src/withProvider.tsx","../src/provider.tsx","../src/hooks.tsx","../src/logger.ts"],"mappings":"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"}
1
+ {"version":3,"file":"configdirector-react-client.d.cts","names":[],"sources":["../../js-client-core/src/Emitter.ts","../../shared/src/types.ts","../../js-client-core/src/types.ts","../src/types.ts","../src/withProvider.tsx","../src/provider.tsx","../src/hooks.tsx","../src/logger.ts"],"mappings":"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"}
@@ -52,7 +52,7 @@ type ConfigDirectorContext = {
52
52
  };
53
53
  //#endregion
54
54
  //#region ../js-client-core/src/types.d.ts
55
- type ClientConnectAction = "initialization" | "context update";
55
+ type ClientConnectAction = "initialization" | "context update" | "network resume";
56
56
  type ClientEvents = {
57
57
  configsUpdated: {
58
58
  keys: string[];
@@ -134,6 +134,19 @@ interface ConfigDirectorClient extends EventProvider<ClientEvents> {
134
134
  * Removes all subscribers from all config keys
135
135
  */
136
136
  unwatchAll(): void;
137
+ /**
138
+ * Pauses the network connection without clearing event handlers, watch handlers, or config
139
+ * state. Intended for mobile environments where the OS may kill background connections (e.g.
140
+ * when the app is backgrounded on iOS/Android).
141
+ *
142
+ * Call {@link resumeNetwork} to re-establish the connection.
143
+ */
144
+ pauseNetwork(): void;
145
+ /**
146
+ * Resumes a connection that was paused via {@link pauseNetwork}, using the last context that
147
+ * was provided to {@link initialize} or {@link updateContext}.
148
+ */
149
+ resumeNetwork(): Promise<void>;
137
150
  /**
138
151
  * Disposes of the client. All connections are closed, and all event and config key subscribers
139
152
  * are removed.
@@ -143,15 +156,6 @@ interface ConfigDirectorClient extends EventProvider<ClientEvents> {
143
156
  dispose(): void;
144
157
  }
145
158
  //#endregion
146
- //#region ../js-client-core/src/telemetry/types.d.ts
147
- declare global {
148
- interface Window {
149
- ConfigDirector: {
150
- logger: ConfigDirectorLogger;
151
- };
152
- }
153
- }
154
- //#endregion
155
159
  //#region src/types.d.ts
156
160
  type ClientStatus = "loading" | "ready" | "default";
157
161
  interface ConfigDirectorContextData {
@@ -181,6 +185,7 @@ declare const withProvider: (options: ConfigDirectorProviderOptions) => Promise<
181
185
  declare class ConfigDirectorProvider extends Component<PropsWithChildren<ConfigDirectorProviderOptions>, ConfigDirectorProviderState> {
182
186
  constructor(props: ConfigDirectorProviderOptions);
183
187
  componentDidMount(): Promise<void>;
188
+ componentDidUpdate(prevProps: PropsWithChildren<ConfigDirectorProviderOptions>): Promise<void>;
184
189
  componentWillUnmount(): void;
185
190
  render(): _$react_jsx_runtime0.JSX.Element;
186
191
  }
@@ -1 +1 @@
1
- {"version":3,"file":"configdirector-react-client.d.mts","names":[],"sources":["../../js-client-core/src/Emitter.ts","../../shared/src/types.ts","../../js-client-core/src/types.ts","../../js-client-core/src/telemetry/types.ts","../src/types.ts","../src/withProvider.tsx","../src/provider.tsx","../src/hooks.tsx","../src/logger.ts"],"mappings":"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"}
1
+ {"version":3,"file":"configdirector-react-client.d.mts","names":[],"sources":["../../js-client-core/src/Emitter.ts","../../shared/src/types.ts","../../js-client-core/src/types.ts","../src/types.ts","../src/withProvider.tsx","../src/provider.tsx","../src/hooks.tsx","../src/logger.ts"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import e,{Component as t,useContext as n,useEffect as r,useState as i}from"react";import{jsx as a}from"react/jsx-runtime";var o=class{constructor(){this.handlerMap=new Map}on(e,t){let n=this.handlerMap.get(e);n?n.push(t):this.handlerMap.set(e,[t])}once(e,t){let n=this;function r(i){n.off(e,r),t.apply(n,i)}this.on(e,r)}off(e,t){let n=this.handlerMap.get(e);if(n)if(t){let e=n.indexOf(t);e>=0&&n.splice(e,1)}else this.handlerMap.set(e,[])}clear(){this.handlerMap.clear()}emit(e,t){let n=this.handlerMap.get(e);n&&n.slice().map(e=>e(t))}},s=class e extends Error{constructor(t,n){super(t),this.name=`ConfigDirectorConnectionError`,this.status=n,Object.setPrototypeOf(this,e.prototype)}},c=class e extends Error{constructor(t){super(t),this.name=`ConfigDirectorValidationError`,Object.setPrototypeOf(this,e.prototype)}};const l=e=>{if(e instanceof DOMException){if(e.name===`NotAllowedError`)return!0}else if(e instanceof TypeError)return!0;return!1};var u=class e extends Error{constructor(t){super(t),this.name=`StreamClosedError`,Object.setPrototypeOf(this,e.prototype)}},d=class e extends Error{constructor(t){super(t),this.name=`MissingResponseBodyError`,Object.setPrototypeOf(this,e.prototype)}},f=class e extends Error{constructor(t){super(t),this.name=`InvalidOptionError`,Object.setPrototypeOf(this,e.prototype)}},p=class e extends Error{constructor(t){super(t),this.name=`ValueOutOfRangeError`,Object.setPrototypeOf(this,e.prototype)}};function m(e){"@babel/helpers - typeof";return m=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},m(e)}function h(e,t){if(m(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(m(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function g(e){var t=h(e,`string`);return m(t)==`symbol`?t:t+``}function _(e,t,n){return(t=g(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function v(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function y(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?v(Object(n),!0).forEach(function(t){_(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):v(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}var b=class{constructor(e){var t;this.isFirstChunk=!0,this.previousIncompleteLine=``,this.currentEvent={data:``},this.onEvent=(t=e.onEvent)==null?(()=>{}):t,this.onRetry=e.onRetry,this.onComment=e.onComment}parse(e){let t=this.prepareChunk(e),n=this.splitLines(t);for(let e of n)this.parseAndProcessLine(e)}finish(){this.previousIncompleteLine!==``&&this.parseAndProcessLine(this.previousIncompleteLine)}parseAndProcessLine(e){if(e.startsWith(`:`)){var t;(t=this.onComment)==null||t.call(this,this.getValueFromLine(0,e));return}if(e===``){this.publishEvent();return}let n=this.parseContentLine(e);this.processContent(n)}publishEvent(){let e=this.currentEvent.data.endsWith(`
1
+ import e,{Component as t,useContext as n,useEffect as r,useState as i}from"react";import{jsx as a}from"react/jsx-runtime";var o=class{constructor(){this.handlerMap=new Map}on(e,t){let n=this.handlerMap.get(e);n?n.push(t):this.handlerMap.set(e,[t])}once(e,t){let n=this;function r(i){n.off(e,r),t.apply(n,i)}this.on(e,r)}off(e,t){let n=this.handlerMap.get(e);if(n)if(t){let e=n.indexOf(t);e>=0&&n.splice(e,1)}else this.handlerMap.set(e,[])}clear(){this.handlerMap.clear()}emit(e,t){let n=this.handlerMap.get(e);n&&n.slice().map(e=>e(t))}},s=class e extends Error{constructor(t,n){super(t),this.name=`ConfigDirectorConnectionError`,this.status=n,Object.setPrototypeOf(this,e.prototype)}},c=class e extends Error{constructor(t){super(t),this.name=`ConfigDirectorValidationError`,Object.setPrototypeOf(this,e.prototype)}};const l=e=>(e==null?void 0:e.name)===`NotAllowedError`?!0:e instanceof TypeError;var u=class e extends Error{constructor(t){super(t),this.name=`StreamClosedError`,Object.setPrototypeOf(this,e.prototype)}},d=class e extends Error{constructor(t){super(t),this.name=`MissingResponseBodyError`,Object.setPrototypeOf(this,e.prototype)}},f=class e extends Error{constructor(t){super(t),this.name=`InvalidOptionError`,Object.setPrototypeOf(this,e.prototype)}},p=class e extends Error{constructor(t){super(t),this.name=`ValueOutOfRangeError`,Object.setPrototypeOf(this,e.prototype)}};function m(e){"@babel/helpers - typeof";return m=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},m(e)}function h(e,t){if(m(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(m(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function g(e){var t=h(e,`string`);return m(t)==`symbol`?t:t+``}function _(e,t,n){return(t=g(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function v(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function y(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?v(Object(n),!0).forEach(function(t){_(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):v(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}var b=class{constructor(e){var t;this.isFirstChunk=!0,this.previousIncompleteLine=``,this.currentEvent={data:``},this.onEvent=(t=e.onEvent)==null?(()=>{}):t,this.onRetry=e.onRetry,this.onComment=e.onComment}parse(e){let t=this.prepareChunk(e),n=this.splitLines(t);for(let e of n)this.parseAndProcessLine(e)}finish(){this.previousIncompleteLine!==``&&this.parseAndProcessLine(this.previousIncompleteLine)}parseAndProcessLine(e){if(e.startsWith(`:`)){var t;(t=this.onComment)==null||t.call(this,this.getValueFromLine(0,e));return}if(e===``){this.publishEvent();return}let n=this.parseContentLine(e);this.processContent(n)}publishEvent(){let e=this.currentEvent.data.endsWith(`
2
2
  `)?this.currentEvent.data.slice(0,-1):this.currentEvent.data;e&&this.onEvent(y(y({},this.currentEvent),{},{id:this.lastEventId,data:e})),this.currentEvent={data:``}}processContent(e){switch(e.field){case`event`:this.currentEvent.type=e.value;break;case`data`:this.currentEvent.data+=e.value+`
3
- `;break;case`id`:e.value.includes(`\0`)||(this.lastEventId=e.value);break;case`retry`:if(/^\d+$/.test(e.value)){var t;(t=this.onRetry)==null||t.call(this,Number.parseInt(e.value,10))}break;default:break}}parseContentLine(e){let t=e.indexOf(`:`);return t===-1?{field:e,value:``}:{field:e.slice(0,t),value:this.getValueFromLine(t,e)}}splitLines(e){var t;let n=e.split(/\r\n|\r|\n/);return this.previousIncompleteLine=(t=n.pop())==null?``:t,n}getValueFromLine(e,t){if(e===-1)return``;let n=t[e+1]===` `?e+2:e+1;return t.slice(n)}prepareChunk(e){return this.isFirstChunk?(this.isFirstChunk=!1,this.previousIncompleteLine+e.replace(/^\xEF\xBB\xBF/,``).replace(/^\uFEFF/,``)):this.previousIncompleteLine+e}};let x=function(e){return e.OPEN=`open`,e.CLOSED=`closed`,e.CONNECTING=`connecting`,e}({});var S=class{constructor(e){var t;this.DEFAULT_SHOULD_RECONNECT=()=>!0,this.DEFAULT_CALCULATE_RECONNECT_DELAY=()=>this.serverReconnectionTime,this.reconnectAttempt=0,this.abortController=new AbortController,this._readyState=x.CLOSED,this.serverReconnectionTime=2e3,this.url=new URL(e.url),this.lastEventId=e.lastEventId,this.headers=y({Accept:`text/event-stream`},e.headers),this.requestOptions={body:e.body,method:(t=e.method)==null?`GET`:t,mode:e.mode,credentials:e.credentials,redirect:e.redirect,referrer:e.referrer,referrerPolicy:e.referrerPolicy},this._onError=this.getValidatedFunctionOrNoOp(e.onError,`onError`),this._onConnect=this.getValidatedFunctionOrNoOp(e.onConnect,`onConnect`),this._onDisconnect=this.getValidatedFunctionOrNoOp(e.onDisconnect,`onDisconnect`),this._onMessage=this.getValidatedFunctionOrNoOp(e.onMessage,`onMessage`),this._onComment=this.getValidatedFunctionOrNoOp(e.onComment,`onComment`),this._shouldReconnect=this.getValidatedFunctionOr(e.shouldReconnect,this.DEFAULT_SHOULD_RECONNECT,`shouldReconnect`),this._calculateReconnectDelay=this.getValidatedFunctionOr(e.calculateReconnectDelay,this.DEFAULT_CALCULATE_RECONNECT_DELAY,`calculateReconnectDelay`)}set onError(e){this._onError=this.getValidatedFunctionOrNoOp(e,`onError`)}set onMessage(e){this._onMessage=this.getValidatedFunctionOrNoOp(e,`onMessage`)}set onComment(e){this._onComment=this.getValidatedFunctionOrNoOp(e,`onComment`)}set onConnect(e){this._onConnect=this.getValidatedFunctionOrNoOp(e,`onConnect`)}set onDisconnect(e){this._onDisconnect=this.getValidatedFunctionOrNoOp(e,`onDisconnect`)}set shouldReconnect(e){this._shouldReconnect=this.getValidatedFunctionOr(e,this.DEFAULT_SHOULD_RECONNECT,`shouldReconnect`)}set calculateReconnectDelay(e){this._calculateReconnectDelay=this.getValidatedFunctionOr(e,this.DEFAULT_CALCULATE_RECONNECT_DELAY,`shouldReconnect`)}get readyState(){return this._readyState}connect(){this._readyState===x.CLOSED&&(this.reconnectAttempt=0,this.initiateConnection())}initiateConnection(){this.abortController=new AbortController,this._readyState=x.CONNECTING,fetch(this.url,y(y({},this.requestOptions),{},{headers:this.buildHeaders(),signal:this.abortController.signal,cache:`no-store`})).then(this.handleFetchResponse.bind(this)).catch(e=>{if(e.name===`AbortError`||this.abortController.signal.aborted){this.close();return}this._onError(e),this.scheduleReconnect({error:e})})}close(){clearTimeout(this.reconnectTimeout),this._readyState=x.CLOSED,this.abortController.abort()}disconnected(){clearTimeout(this.reconnectTimeout),this._readyState=x.CLOSED,this._onDisconnect()}buildHeaders(){let e=this.lastEventId?{"Last-Event-ID":this.lastEventId}:void 0;return y(y({},this.headers),e)}async handleFetchResponse(e){var t=this;let{body:n,status:r}=e;if(r===204){t.disconnected();return}if(r>=400){t.scheduleReconnect({status:r});return}if(!n)throw new d(`The server response did not have a body`);t._readyState=x.OPEN,t._onConnect(),t.reconnectAttempt=0;let i=(n==null?void 0:n.pipeThrough(new TextDecoderStream)).getReader(),a=new b({onEvent:e=>{typeof e.id==`string`&&(t.lastEventId=e.id),t._onMessage(e)},onComment:e=>t._onComment(e),onRetry:e=>t.serverReconnectionTime=e}),o=!1;for(;!o;){let{done:e,value:t}=await i.read();t&&a.parse(t),o=e}a.finish(),t.scheduleReconnect({status:r,error:new u(`The server response stream was closed`)})}scheduleReconnect(e){if(this.abortController.signal.aborted)return;clearTimeout(this.reconnectTimeout),this.reconnectAttempt+=1;let t={attempt:this.reconnectAttempt,status:e.status,error:e.error,serverReconnectionTime:this.serverReconnectionTime};if(this._shouldReconnect(t)){this._readyState=x.CONNECTING;let e=this._calculateReconnectDelay(t);(!Number.isFinite(e)||e<1||e>1e3*60*60)&&(this._onError(new p(`The calculated reconnect delay is out of range: ${e}. Defaulting to ${this.serverReconnectionTime}`)),e=this.serverReconnectionTime),this.reconnectTimeout=setTimeout(()=>this.initiateConnection(),e)}else{this.disconnected();return}}getValidatedFunctionOrNoOp(e,t){return this.getValidatedFunctionOr(e,()=>{},t)}getValidatedFunctionOr(e,t,n){if(e==null)return t;if(typeof e==`function`)return e;throw new f(`${n} must be a function`)}};const C=e=>new S(e);var w=class{constructor(e){this.options=e,this.eventEmitter=new o,this.options=e,this.logger=e.logger,this.url=new URL(`client/sse/v1`,e.baseUrl)}async connect(e,t){var n=this;n.eventSource&&n.close();let r=new Promise((t,r)=>{n.eventSource=C({url:n.url,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({givenContext:e,metaContext:n.options.metaContext,clientSdkKey:n.options.clientSdkKey}),onMessage:({data:e})=>{n.dispatchMessage(e)},onConnect:()=>{n.logger.debug(`[EventSourceTransport] Connected`),t(n)},shouldReconnect:e=>{let t=!n.isStatusFatal(e.status);return t||r(n.prepareFatalError(e.status,e.error)),t},calculateReconnectDelay:e=>{let t=2e3*e.attempt;return n.logger.warn(`[EventSourceTransport] Scheduling reconnect in ${t}ms.`),t},onDisconnect:()=>{n.logger.debug(`[EventSourceTransport] Disconnected`)}}),n.eventSource.connect()});return Promise.race([r,new Promise(e=>{setTimeout(()=>e(n),t)})])}dispatchMessage(e){try{let t=JSON.parse(e);this.eventEmitter.emit(`configSetReceived`,t)}catch(e){this.logger.error(`[EventSourceTransport] Error parsing and dispatching config data update: `,e)}}prepareFatalError(e,t){let n=e==null?0:e;return new s(`${`Connection failed with status: ${e==null?`unknown`:e}.`}${t?` Error: ${t}`:``}. This is an unrecoverable error, will not attempt to reconnect.`,n)}isStatusFatal(e){return!!e&&e>=400&&e<500}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.eventEmitter.clear()}close(){var e;(e=this.eventSource)==null||e.close()}dispose(){this.close(),this.clear()}};const T=e=>{let t=typeof e;if(t===`object`)try{var n,r;return(n=(r=e.constructor)==null?void 0:r.name)==null?t:n}catch(e){return t}else if(t===`function`)try{let n=e.name;return n?`function: ${n}`:t}catch(e){return t}return t},E=e=>e===`number`||e===`bigint`,D=(e,t)=>{let n=e.value,r=T(t);if(!n)return{parsedValue:t,requestedType:r,usedDefault:!0,reason:`value-missing`};if(typeof t==`string`)return{parsedValue:n,requestedType:r,usedDefault:!1,reason:`found-match`};if(typeof t==`boolean`&&e.type===`boolean`){let e=O(n),i=typeof e==`boolean`;return{parsedValue:i?e:t,requestedType:r,usedDefault:!i,reason:i?`found-match`:`invalid-boolean`}}if(E(typeof t)&&e.type===`integer`){let e=k(n),i=typeof e==`number`;return{parsedValue:i?e:t,requestedType:r,usedDefault:!i,reason:i?`found-match`:`invalid-number`}}if(E(typeof t)&&(e.type===`float`||e.type===`enum`)){let e=A(n),i=typeof e==`number`;return{parsedValue:i?e:t,requestedType:r,usedDefault:!i,reason:i?`found-match`:`invalid-number`}}return{parsedValue:n,requestedType:r,usedDefault:!1,reason:`found-match`}},O=e=>{if(!e)return;let t=e.toLowerCase();if(!(t!=`true`&&t!=`false`))return t===`true`},k=e=>{if(!e)return;let t=Number.parseInt(e);if(!(isNaN(t)||!isFinite(t)))return t},A=e=>{if(!e)return;let t=Number.parseFloat(e);if(!(isNaN(t)||!isFinite(t)))return t},j={off:-1,error:0,warn:1,info:2,debug:3},M=()=>{let e={year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,timeZoneName:`short`};try{return new Intl.DateTimeFormat(void 0,y(y({},e),{},{fractionalSecondDigits:3}))}catch(t){return new Intl.DateTimeFormat(void 0,e)}};var N=class{constructor(e,t){this.level=e,this.decorator=t,this.level=e,this.decorator=t,this.dateFormatter=M()}debug(e,...t){this.log(console.debug,`debug`,e,...t)}info(e,...t){this.log(console.info,`info`,e,...t)}warn(e,...t){this.log(console.warn,`warn`,e,...t)}error(e,...t){this.log(console.error,`error`,e,...t)}log(e,t,n,...r){if(j[this.level]>=j[t]){var i;e(`[${this.dateFormatter.format(new Date)}] ${(i=this.decorator)==null?void 0:i.decorateMessage(n)}`,...r)}}},P=class{decorateMessage(e){return`[ConfigDirector:js-client-sdk] ${e}`}};const F=(e,t)=>new N(e==null?`warn`:e,t==null?new P:t),I=async(e,t,n,r)=>{let i=new AbortController,a=setTimeout(()=>{r.debug(`[fetchWithTimeout] Reached timeout, aborting request`),i.abort()},e);try{let e=await fetch(t,y(y({},n),{},{signal:i.signal}));return clearTimeout(a),e}catch(e){throw r.warn(`[fetchWithTimeout] Fetch error: `,e),clearTimeout(a),e}};var L=class{constructor(e){this.options=e,this.eventEmitter=new o,this.fatalError=!1,this.options=e,this.logger=e.logger,this.url=new URL(`client/pull/v1`,e.baseUrl)}async connect(e,t){var n=this;if(n.fatalError)return n.logger.warn(`[PullTransport] There was a prior unrecoverable error. Ignoring attempt to reconnect.`),n;try{let r=await I(t,n.url,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({givenContext:e,metaContext:n.options.metaContext,clientSdkKey:n.options.clientSdkKey})},n.logger);if(!r.ok)throw n.isStatusFatal(r.status)?(n.fatalError=!0,n.prepareFatalResponseStatusError(r.status,await r.text())):new s(`Connection failed with status: ${r.status}`,r.status);let i=JSON.parse(await r.text());return n.eventEmitter.emit(`configSetReceived`,i),n}catch(e){throw l(e)?(n.fatalError=!0,new s(`Connection failed with fatal error: ${e}. This is an unrecoverable error, retry attempts will be ignored.`)):e instanceof SyntaxError?new s(`Failed to parse the response from the server: ${e}`):new s(`Connection failed with error: ${e}.`)}}prepareFatalResponseStatusError(e,t){var n,r;let i=e==null?0:e;return new s(`${`Connection failed with status: ${e==null?`unknown`:e}`}${((n=t==null||(r=t.trim())==null?void 0:r.length)==null?0:n)>0?` (${t})`:``}. This is an unrecoverable error, retry attempts will be ignored.`,i)}isStatusFatal(e){return!!e&&e>=400&&e<500}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.eventEmitter.clear()}close(){}dispose(){this.close(),this.clear()}};const R=(e,t)=>{if(t===`json`)try{return z(JSON.stringify(e))}catch(t){return e.toString().slice(0,500)}return e.toString().slice(0,500)},z=e=>B(new TextEncoder().encode(e)).toString(16).padStart(8,`0`),B=e=>{let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e[n],t>>>=0;return t};var V=class{constructor(e){var t,n,r;this.logger=e.logger;let i={type:`Initialize`,payload:{sdkKey:e.sdkKey,baseUrl:e.baseUrl.toString(),evaluationQueueLimit:(t=e.evaluationQueueLimit)==null?1e3:t,initialFlushIntervalDelay:(n=e.initialFlushIntervalDelay)==null?5e3:n,flushIntervalDelay:(r=e.flushIntervalDelay)==null?3e4:r}};this.worker=new Worker(URL.createObjectURL(new Blob(["(function(){let e=(e,n)=>{if(n===`json`)try{return t(JSON.stringify(e))}catch{return e.toString().slice(0,500)}return e.toString().slice(0,500)},t=e=>n(new TextEncoder().encode(e)).toString(16).padStart(8,`0`),n=e=>{let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e[n],t>>>=0;return t},r=e=>{let t=Object.keys(e);if(t.length==0)return!0;for(let n of t)if((e[n]?.length??0)>0)return!1;return!0},i=e=>{if(!e)return!0;let t=Object.keys(e);if(t.length==0)return!0;for(let n of t)if((e[n]??0)>0)return!1;return!0},a=async(e,t,n,r)=>{let i=new AbortController,a=setTimeout(()=>{r.debug(`[fetchWithTimeout] Reached timeout, aborting request`),i.abort()},e);try{let e=await fetch(t,{...n,signal:i.signal});return clearTimeout(a),e}catch(e){throw r.warn(`[fetchWithTimeout] Fetch error: `,e),clearTimeout(a),e}},o=e=>{if(e instanceof DOMException){if(e.name===`NotAllowedError`)return!0}else if(e instanceof TypeError)return!0;return!1};var s=class{constructor(e){this.executeRequests=!0,this.sdkKey=e.sdkKey,this.logger=e.logger,this.url=new URL(`client/telemetry/v1`,e.baseUrl)}async report({context:e,discreteEvents:t,aggregatedEvents:n,droppedEvents:r}){if(!this.executeRequests)return{success:!1,fatalError:!0};let i={clientSdkKey:this.sdkKey,context:e,discreteEvents:t,aggregatedEvents:n,droppedEvents:r};if(this.isReportEmpty(i))return{success:!0,fatalError:!1};let a=await this.sendReport(i);return a.fatalError&&(this.executeRequests=!1),a}isReportEmpty(e){return r(e.discreteEvents)&&r(e.aggregatedEvents)&&i(e.droppedEvents)}async sendReport(e){try{let t=await a(5e3,this.url,{method:`POST`,body:JSON.stringify(e),keepalive:!0},this.logger),n=this.isStatusFatal(t.status);return n&&this.logger.warn(`[EventReporter] Received a fatal status response (${t.status}) from the telemetry endpoint. No more telemetry data will be sent.`),{success:t.ok,fatalError:n}}catch(e){let t=o(e);return this.logger.warn(`[EventReporter] Error attempting to send telemetry data: ${e}`,{error:e}),{success:!1,fatalError:t}}}isStatusFatal(e){return!!e&&e>=400&&e<500}},c=class{aggregate(e){if(e.events.length==0)return[];let t=new Map;for(let n of e.events){let e=JSON.stringify(n),r=t.get(e)?.count||0;t.set(e,{event:n,count:r+1})}return Array.from(t).map(([,t])=>({startTime:e.startTime,endTime:e.endTime,count:t.count,event:t.event}))}},l=class{constructor(e){this._events=[],this._droppedEventCount=0,this.limit=e??1e3}get events(){return this._events}get reachedLimit(){return this._events.length>=this.limit}get droppedEventCount(){return this._droppedEventCount}push(...e){this.startTime||=new Date;let t=Math.max(0,e.length-this.limit),n=e.slice(t,e.length);if(this._droppedEventCount+=t,this._events.length+n.length>this.limit){let e=this._events.length+n.length-this.limit;this._events.splice(0,e),this._droppedEventCount+=e}return this._events.push(...n)}takeSnapshot(){let e=new Date,t=this.startTime??e,n=this._events.splice(0),r=this._droppedEventCount;return this.startTime=void 0,this._droppedEventCount=0,{startTime:t,endTime:e,events:n,droppedCount:r}}clear(){this._events=[],this.startTime=void 0,this._droppedEventCount=0}},u=class{constructor(e){this.aggregator=new c,this.collectEvents=!0,this.logger=e.logger,this.evaluationEventQueue=new l(e.evaluationQueueLimit??1e3),this.flushIntervalDelay=e.flushIntervalDelay??3e4;let t=e.initialFlushIntervalDelay??5e3;this.flushTimeout=setTimeout(()=>this.flushAndScheduleNext(),t)}sanitizeValue(t,n){return e(t,n)}async flushAndScheduleNext(){(await this.flush()).fatalError?(this.collectEvents=!1,this.close(),this.logger.warn(`[TelemetryEventCollector] Received a fatal error from telemetry collection. No longer collecting events.`)):this.flushTimeout=setTimeout(()=>this.flushAndScheduleNext(),this.flushIntervalDelay)}async flush(){if(!this.reporter)return{success:!1,fatalError:!1};let e=this.evaluationEventQueue.takeSnapshot();return await this.reporter?.report({context:this._context,discreteEvents:{},aggregatedEvents:{evaluatedConfig:this.aggregator.aggregate(e)},droppedEvents:{evaluatedConfig:e.droppedCount}})}cancelScheduledFlush(){clearTimeout(this.flushTimeout)}async close(){this.collectEvents=!1,clearTimeout(this.flushTimeout),await this.flush(),this.evaluationEventQueue.clear()}dispose(){this.close()}},d=class extends u{constructor(e){super(e),this.reporter=new s(e)}async updateContext(e){this.cancelScheduledFlush(),await this.flush(),this._context=e,await this.flushAndScheduleNext()}evaluatedConfig(e){this.collectEvents&&this.evaluationEventQueue.push(e)}async forceFlush(){this.cancelScheduledFlush(),await this.flushAndScheduleNext()}};let f,p=(e,t,...n)=>({type:`Log`,payload:{level:e,message:t,args:n}}),m=e=>{try{self.postMessage(e)}catch{self.postMessage(p(e.payload.level,e.payload.message))}},h={debug:function(e,...t){m(p(`debug`,e,t))},info:function(e,...t){m(p(`info`,e,t))},warn:function(e,...t){m(p(`warn`,e,t))},error:function(e,...t){m(p(`error`,e,t))}};addEventListener(`message`,e=>{let t=e.data;if(t.type!=`Initialize`&&!f){h.info(`[TelemetryWorker] Ignoring ${t.type} because no collector is configured`);return}switch(h.debug(`[TelemetryWorker] Received '${t.type}' event:`,t),t.type){case`Initialize`:f=new d({...t.payload,baseUrl:new URL(t.payload.baseUrl),logger:h});break;case`EvaluatedConfigEvent`:f?.evaluatedConfig(t.payload);break;case`UpdateContext`:f?.updateContext(t.payload.context);break;case`Flush`:f?.forceFlush();break;case`Close`:(f?.close()??Promise.resolve()).then(()=>{self.postMessage({type:`Closed`}),self.close()});break}})})();"],{type:`application/javascript`}))),this.worker.onmessage=e=>{this.handleWorkerEvent(e.data)},this.worker.postMessage(i),this.visibilityHandler=()=>{document.visibilityState===`hidden`&&this.flush()};try{document.addEventListener(`visibilitychange`,this.visibilityHandler)}catch(e){this.logger.warn(`[TelemetryEventCollector] Could not configure 'visibilitychange' listener: `,e)}}async updateContext(e){var t=this;let n={type:`UpdateContext`,payload:{context:e}};t.worker.postMessage(n)}evaluatedConfig(e){let t={type:`EvaluatedConfigEvent`,payload:this.sanitizeEvaluatedConfigEvent(e)};this.worker.postMessage(t)}sanitizeEvaluatedConfigEvent(e){return y(y({},e),{},{defaultValue:R(e.defaultValue,e.type),evaluatedValue:R(e.evaluatedValue,e.type)})}handleWorkerEvent(e){var t,n;if(e.type===`Closed`){var r;(r=this.closeResolve)==null||r.call(this);return}if(!((t=e.payload)!=null&&t.level)||!((n=e.payload)!=null&&n.message))return;let{level:i,message:a,args:o}=e.payload;switch(i){case`debug`:this.logger.debug(a,...o);break;case`info`:this.logger.info(a,...o);break;case`warn`:this.logger.warn(a,...o);break;case`error`:this.logger.warn(a,...o);break}}flush(){this.worker.postMessage({type:`Flush`})}close(){return this.closePromise?this.closePromise:this.performClose()}performClose(){return document.removeEventListener(`visibilitychange`,this.visibilityHandler),this.closePromise=new Promise(e=>{this.closeResolve=e,this.worker.postMessage({type:`Close`})}),this.closePromise}};const H=new URL(`https://client-sdk-api.configdirector.com`);var U=class{constructor(e,t,n){var r,i,a,s,c,l,u;this.handlersMap=new Map,this.eventEmitter=new o,this.ready=!1,this.logger=(r=n==null?void 0:n.logger)==null?F():r,this.timeout=(i=n==null||(a=n.connection)==null?void 0:a.timeout)==null?3e3:i;let d=(s=this.parseUrl(n==null||(c=n.connection)==null?void 0:c.url))==null?H:s;this.streaming=(n==null||(l=n.connection)==null?void 0:l.streaming)!==!1;let f=this.streaming?w:L;this.usageEventCollector=new V({sdkKey:e,logger:this.logger,baseUrl:d}),this.transport=new f({clientSdkKey:e,baseUrl:d,metaContext:y(y({},n==null?void 0:n.metadata),{},{sdkName:t.sdkName,sdkVersion:t.sdkVersion,userAgent:(u=navigator)==null?void 0:u.userAgent}),logger:this.logger}),this.transport.on(`configSetReceived`,e=>{var t;(t=this.readyResolve)==null||t.call(this);let n=Object.keys(e.configs);!this.configSet||e.kind==`full`?(this.configSet=e,this.eventEmitter.emit(`configsUpdated`,{keys:n}),this.updateWatchers(e.configs)):(this.configSet.configs=y(y({},this.configSet.configs),e.configs),this.eventEmitter.emit(`configsUpdated`,{keys:n}),this.updateWatchers(e.configs)),this.logger.debug(`[ConfigDirectorClient] ConfigSet updated from server:`,{keys:n})})}async initialize(e){await this.connectToTransport(e,`initialization`)}async updateContext(e){await this.connectToTransport(e,`context update`)}async connectToTransport(e,t){var n=this;try{n.ready=!1,n.readyPromise=new Promise(e=>{n.readyResolve=e}).then(()=>{n.ready=!0,n.eventEmitter.emit(`clientReady`,{action:t}),n.logger.debug(`[ConfigDirectorClient] Received initial payload from the server, client is ready`)});let r=new Date().getTime();await n.transport.connect(e==null?{}:e,n.timeout),n.currentContext=e,n.usageEventCollector.updateContext(e);let i=new Date().getTime()-r,a=n.timeout-i;if(a>0&&await Promise.race([n.readyPromise,new Promise(e=>{setTimeout(()=>e(),a)})]),!n.ready){let e=n.streaming?`The client will continue to retry since there were no fatal errors detected. Configs will return the default value until the connection succeeds.`:`Since the client was configured without streaming, configs may not update and always return the default value.`;n.logger.warn(`[ConfigDirectorClient] Timed out waiting for ${t} after ${n.timeout}ms. ${e}`)}}catch(e){n.logger.error(`[ConfigDirectorClient] An error occurred during ${t}: `,e)}}updateWatchers(e){Object.values(e).forEach(e=>this.updateWatchersForConfig(e))}updateWatchersForConfig(e){var t;(t=this.handlersMap.get(e.key))==null||t.forEach(t=>{let n=this.getValueFromConfigState(e.key,e,t.defaultValue);t.handler(n)})}watch(e,t,n){this.validateDefaultValue(t);let r=this.handlersMap.get(e),i={handler:n,defaultValue:t,requestedType:typeof t};return r?r.push(i):this.handlersMap.set(e,[i]),()=>this.unwatch(e,n)}unwatch(e,t){let n=this.handlersMap.get(e);if(n)if(t){let e=n.findIndex(e=>e.handler==t);e>=0&&(n==null||n.splice(e,1))}else n.splice(0)}getValue(e,t){var n;this.validateDefaultValue(t);let r=(n=this.configSet)==null?void 0:n.configs[e];return this.getValueFromConfigState(e,r,t)}getValueFromConfigState(e,t,n){var r;if(!t){var i;return this.logger.debug(`[ConfigDirectorClient] No config state found for '${e}', returning default value '${n}'`),this.usageEventCollector.evaluatedConfig({contextId:(i=this.currentContext)==null?void 0:i.id,key:e,defaultValue:n,requestedType:T(n),evaluatedValue:n,usedDefault:!0,evaluationReason:`config-state-missing`}),n}let a=D(t,n);return this.usageEventCollector.evaluatedConfig({contextId:(r=this.currentContext)==null?void 0:r.id,key:e,defaultValue:n,requestedType:a.requestedType,evaluatedValue:a.parsedValue,usedDefault:a.usedDefault,evaluationReason:a.reason}),this.logger.debug(`[ConfigDirectorClient] Evaluated '${e}' to '${a.parsedValue}'`),a.parsedValue}parseUrl(e){if(e)try{return new URL(e)}catch(t){throw new c(`Invalid base URL '${e}'. Parsing failed: ${t}`)}}validateDefaultValue(e){if(e==null)throw new c(`Invalid default value. The default value for a config must be defined and non-null.`);if(typeof e==`function`)throw new c(`Invalid default value. The default value for a config cannot be a function.`)}get isReady(){return this.ready}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.logger.debug(`[ConfigDirectorClient] clear() has been called, removing all observers`),this.eventEmitter.clear(),this.handlersMap.clear()}unwatchAll(){this.handlersMap.clear()}close(){this.logger.debug(`[ConfigDirectorClient] close() has been called, closing connection to server`),this.transport.close(),this.ready=!1}dispose(){this.clear(),this.close()}};const W=(e,t)=>new U(e,{sdkName:`react-web-sdk`,sdkVersion:`0.3.0`},t),G=e.createContext({status:`loading`});var K=class{decorateMessage(e){return`[ConfigDirector:react-web-sdk] ${e}`}};const q=e=>F(e,new K),J=async e=>{var t;let n=(t=e.logger)==null?q(`debug`):t,o=W(e.sdkKey,{connection:{url:e.url,timeout:e.timeout},metadata:{appName:e.appName,appVersion:e.appVersion},logger:n});return await o.initialize(e.context),({children:e})=>{let[t,n]=i(()=>({client:o,status:o.isReady?`ready`:`default`}));return r(()=>{o.on(`configsUpdated`,()=>{n(e=>y(y({},e),{},{updatedAt:new Date}))}),o.on(`clientReady`,()=>{n(e=>y(y({},e),{},{status:`ready`}))})}),a(G.Provider,{value:t,children:e})}};var Y=class extends t{constructor(e){var t;super(e),this.state={client:W(e.sdkKey,{connection:{url:e.url,timeout:e.timeout},metadata:{appName:e.appName,appVersion:e.appVersion},logger:(t=e.logger)==null?q(`warn`):t}),status:`loading`}}async componentDidMount(){var e=this,t,n,r,i;(t=e.state.client)==null||t.on(`configsUpdated`,()=>{e.setState({updatedAt:new Date})}),(n=e.state.client)==null||n.on(`clientReady`,()=>{e.setState({status:`ready`})}),await((r=e.state.client)==null?void 0:r.initialize(e.props.context)),(i=e.state.client)!=null&&i.isReady||e.setState({status:`default`})}componentWillUnmount(){var e;(e=this.state.client)==null||e.dispose()}render(){return a(G.Provider,{value:this.state,children:this.props.children})}},X=class e extends Error{constructor(t){super(t),this.name=`ConfigDirectorReactContextError`,Object.setPrototypeOf(this,e.prototype)}};const Z=()=>new X(`The ConfigDirector client was not found in the React context. Please make sure the component using this hook is inside the context of a ConfigDirectorProvider.`),Q=(e,t)=>{let r=n(G);if(!(r!=null&&r.client))throw Z();return{value:r.client.getValue(e,t),readyStatus:r.status,loading:r.status===`loading`}},$=()=>{let e=n(G);if(!(e!=null&&e.client))throw Z();return{updateContext:async t=>{var n;await((n=e.client)==null?void 0:n.updateContext(t))}}},ee=()=>{let e=n(G);if(!(e!=null&&e.client))throw Z();return{client:e.client}};export{Y as ConfigDirectorProvider,q as createConsoleLogger,ee as useConfigDirectorClient,$ as useConfigDirectorContext,Q as useConfigValue,J as withProvider};
3
+ `;break;case`id`:e.value.includes(`\0`)||(this.lastEventId=e.value);break;case`retry`:if(/^\d+$/.test(e.value)){var t;(t=this.onRetry)==null||t.call(this,Number.parseInt(e.value,10))}break;default:break}}parseContentLine(e){let t=e.indexOf(`:`);return t===-1?{field:e,value:``}:{field:e.slice(0,t),value:this.getValueFromLine(t,e)}}splitLines(e){var t;let n=e.split(/\r\n|\r|\n/);return this.previousIncompleteLine=(t=n.pop())==null?``:t,n}getValueFromLine(e,t){if(e===-1)return``;let n=t[e+1]===` `?e+2:e+1;return t.slice(n)}prepareChunk(e){return this.isFirstChunk?(this.isFirstChunk=!1,this.previousIncompleteLine+e.replace(/^\xEF\xBB\xBF/,``).replace(/^\uFEFF/,``)):this.previousIncompleteLine+e}};let x=function(e){return e.OPEN=`open`,e.CLOSED=`closed`,e.CONNECTING=`connecting`,e}({});var S=class{constructor(e){var t,n;this.DEFAULT_SHOULD_RECONNECT=()=>!0,this.DEFAULT_CALCULATE_RECONNECT_DELAY=()=>this.serverReconnectionTime,this.reconnectAttempt=0,this.abortController=new AbortController,this._readyState=x.CLOSED,this.serverReconnectionTime=2e3,this.url=e.url.toString(),this.lastEventId=e.lastEventId,this.headers=y({Accept:`text/event-stream`},e.headers),this.requestOptions={body:e.body,method:(t=e.method)==null?`GET`:t,mode:e.mode,credentials:e.credentials,redirect:e.redirect,referrer:e.referrer,referrerPolicy:e.referrerPolicy},this._fetch=(n=e.fetch)==null?((e,t)=>fetch(e,t)):n,this._onError=this.getValidatedFunctionOrNoOp(e.onError,`onError`),this._onConnect=this.getValidatedFunctionOrNoOp(e.onConnect,`onConnect`),this._onDisconnect=this.getValidatedFunctionOrNoOp(e.onDisconnect,`onDisconnect`),this._onMessage=this.getValidatedFunctionOrNoOp(e.onMessage,`onMessage`),this._onComment=this.getValidatedFunctionOrNoOp(e.onComment,`onComment`),this._shouldReconnect=this.getValidatedFunctionOr(e.shouldReconnect,this.DEFAULT_SHOULD_RECONNECT,`shouldReconnect`),this._calculateReconnectDelay=this.getValidatedFunctionOr(e.calculateReconnectDelay,this.DEFAULT_CALCULATE_RECONNECT_DELAY,`calculateReconnectDelay`)}set onError(e){this._onError=this.getValidatedFunctionOrNoOp(e,`onError`)}set onMessage(e){this._onMessage=this.getValidatedFunctionOrNoOp(e,`onMessage`)}set onComment(e){this._onComment=this.getValidatedFunctionOrNoOp(e,`onComment`)}set onConnect(e){this._onConnect=this.getValidatedFunctionOrNoOp(e,`onConnect`)}set onDisconnect(e){this._onDisconnect=this.getValidatedFunctionOrNoOp(e,`onDisconnect`)}set shouldReconnect(e){this._shouldReconnect=this.getValidatedFunctionOr(e,this.DEFAULT_SHOULD_RECONNECT,`shouldReconnect`)}set calculateReconnectDelay(e){this._calculateReconnectDelay=this.getValidatedFunctionOr(e,this.DEFAULT_CALCULATE_RECONNECT_DELAY,`shouldReconnect`)}get readyState(){return this._readyState}connect(){this._readyState===x.CLOSED&&(this.reconnectAttempt=0,this.initiateConnection())}initiateConnection(){this.abortController=new AbortController,this._readyState=x.CONNECTING,this._fetch(this.url,y(y({},this.requestOptions),{},{headers:this.buildHeaders(),signal:this.abortController.signal,cache:`no-store`})).then(this.handleFetchResponse.bind(this)).catch(e=>{if(e.name===`AbortError`||this.abortController.signal.aborted){this.close();return}this._onError(e),this.scheduleReconnect({error:e})})}close(){clearTimeout(this.reconnectTimeout),this._readyState=x.CLOSED,this.abortController.abort()}disconnected(){clearTimeout(this.reconnectTimeout),this._readyState=x.CLOSED,this._onDisconnect()}buildHeaders(){let e=this.lastEventId?{"Last-Event-ID":this.lastEventId}:void 0;return y(y({},this.headers),e)}async handleFetchResponse(e){var t=this;let{body:n,status:r}=e;if(r===204){t.disconnected();return}if(r>=400){t.scheduleReconnect({status:r});return}if(!n)throw new d(`The server response did not have a body`);t._readyState=x.OPEN,t._onConnect(),t.reconnectAttempt=0;let i=n.getReader(),a=new TextDecoder,o=new b({onEvent:e=>{typeof e.id==`string`&&(t.lastEventId=e.id),t._onMessage(e)},onComment:e=>t._onComment(e),onRetry:e=>t.serverReconnectionTime=e}),s=!1;for(;!s;){let{done:e,value:t}=await i.read();t&&o.parse(a.decode(t,{stream:!0})),s=e}o.finish(),t.scheduleReconnect({status:r,error:new u(`The server response stream was closed`)})}scheduleReconnect(e){if(this.abortController.signal.aborted)return;clearTimeout(this.reconnectTimeout),this.reconnectAttempt+=1;let t={attempt:this.reconnectAttempt,status:e.status,error:e.error,serverReconnectionTime:this.serverReconnectionTime};if(this._shouldReconnect(t)){this._readyState=x.CONNECTING;let e=this._calculateReconnectDelay(t);(!Number.isFinite(e)||e<1||e>1e3*60*60)&&(this._onError(new p(`The calculated reconnect delay is out of range: ${e}. Defaulting to ${this.serverReconnectionTime}`)),e=this.serverReconnectionTime),this.reconnectTimeout=setTimeout(()=>this.initiateConnection(),e)}else{this.disconnected();return}}getValidatedFunctionOrNoOp(e,t){return this.getValidatedFunctionOr(e,()=>{},t)}getValidatedFunctionOr(e,t,n){if(e==null)return t;if(typeof e==`function`)return e;throw new f(`${n} must be a function`)}};const C=e=>new S(e);var w=class{constructor(e){this.options=e,this.eventEmitter=new o,this.options=e,this.logger=e.logger,this.url=e.resolveUrl(`client/sse/v1`,e.baseUrl)}async connect(e,t){var n=this;n.eventSource&&n.close();let r=new Promise((t,r)=>{n.eventSource=C({url:n.url,method:`POST`,headers:{"Content-Type":`application/json`},fetch:n.options.fetch,body:JSON.stringify({givenContext:e,metaContext:n.options.metaContext,clientSdkKey:n.options.clientSdkKey}),onMessage:({data:e})=>{n.dispatchMessage(e)},onConnect:()=>{n.logger.debug(`[EventSourceTransport] Connected`),t(n)},shouldReconnect:e=>{let t=!n.isStatusFatal(e.status);return t||r(n.prepareFatalError(e.status,e.error)),t},calculateReconnectDelay:e=>{let t=n.options.connectionRetryDelay(e.attempt);return n.logger.warn(`[EventSourceTransport] Scheduling reconnect in ${t}ms.`),t},onError:e=>{n.logger.debug(`[EventSourceTransport] Error: `,e)},onDisconnect:()=>{n.logger.debug(`[EventSourceTransport] Disconnected`)}}),n.eventSource.connect()});return clearTimeout(n.timeoutTimer),n.timeoutTimer=void 0,Promise.race([r,new Promise(e=>{n.timeoutTimer=setTimeout(()=>e(n),t)})]).finally(()=>clearTimeout(n.timeoutTimer))}dispatchMessage(e){try{let t=JSON.parse(e);this.eventEmitter.emit(`configSetReceived`,t)}catch(e){this.logger.error(`[EventSourceTransport] Error parsing and dispatching config data update: `,e)}}prepareFatalError(e,t){let n=e==null?0:e;return new s(`${`Connection failed with status: ${e==null?`unknown`:e}.`}${t?` Error: ${t}`:``}. This is an unrecoverable error, will not attempt to reconnect.`,n)}isStatusFatal(e){return!!e&&e>=400&&e<500}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.eventEmitter.clear()}close(){var e;(e=this.eventSource)==null||e.close(),clearTimeout(this.timeoutTimer)}dispose(){this.close(),this.clear()}};const T=e=>{let t=typeof e;if(t===`object`)try{var n,r;return(n=(r=e.constructor)==null?void 0:r.name)==null?t:n}catch(e){return t}else if(t===`function`)try{let n=e.name;return n?`function: ${n}`:t}catch(e){return t}return t},E=e=>e===`number`||e===`bigint`,D=(e,t)=>{let n=e.value,r=T(t);if(!n)return{parsedValue:t,requestedType:r,usedDefault:!0,reason:`value-missing`};if(typeof t==`string`)return{parsedValue:n,requestedType:r,usedDefault:!1,reason:`found-match`};if(typeof t==`boolean`&&e.type===`boolean`){let e=O(n),i=typeof e==`boolean`;return{parsedValue:i?e:t,requestedType:r,usedDefault:!i,reason:i?`found-match`:`invalid-boolean`}}if(E(typeof t)&&e.type===`integer`){let e=k(n),i=typeof e==`number`;return{parsedValue:i?e:t,requestedType:r,usedDefault:!i,reason:i?`found-match`:`invalid-number`}}if(E(typeof t)&&(e.type===`float`||e.type===`enum`)){let e=A(n),i=typeof e==`number`;return{parsedValue:i?e:t,requestedType:r,usedDefault:!i,reason:i?`found-match`:`invalid-number`}}return{parsedValue:n,requestedType:r,usedDefault:!1,reason:`found-match`}},O=e=>{if(!e)return;let t=e.toLowerCase();if(!(t!=`true`&&t!=`false`))return t===`true`},k=e=>{if(!e)return;let t=Number.parseInt(e);if(!(isNaN(t)||!isFinite(t)))return t},A=e=>{if(!e)return;let t=Number.parseFloat(e);if(!(isNaN(t)||!isFinite(t)))return t},j={off:-1,error:0,warn:1,info:2,debug:3},ee=()=>{let e={year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,timeZoneName:`short`};try{return new Intl.DateTimeFormat(void 0,y(y({},e),{},{fractionalSecondDigits:3}))}catch(t){return new Intl.DateTimeFormat(void 0,e)}};var M=class{constructor(e,t){this.level=e,this.decorator=t,this.level=e,this.decorator=t,this.dateFormatter=ee()}debug(e,...t){this.log(console.debug,`debug`,e,...t)}info(e,...t){this.log(console.info,`info`,e,...t)}warn(e,...t){this.log(console.warn,`warn`,e,...t)}error(e,...t){this.log(console.error,`error`,e,...t)}log(e,t,n,...r){if(j[this.level]>=j[t]){var i;e(`[${this.dateFormatter.format(new Date)}] ${(i=this.decorator)==null?void 0:i.decorateMessage(n)}`,...r)}}},N=class{decorateMessage(e){return`[ConfigDirector:js-client-sdk] ${e}`}};const P=(e,t)=>new M(e==null?`warn`:e,t==null?new N:t),F=async(e,t,n,r)=>{let i=new AbortController,a=setTimeout(()=>{r.debug(`[fetchWithTimeout] Reached timeout, aborting request`),i.abort()},e);try{let e=await fetch(typeof t==`string`||t instanceof Request?t:t.toString(),y(y({},n),{},{signal:i.signal}));return clearTimeout(a),e}catch(e){throw r.warn(`[fetchWithTimeout] Fetch error: `,e),clearTimeout(a),e}};var I=class{constructor(e){this.options=e,this.eventEmitter=new o,this.fatalError=!1,this.options=e,this.logger=e.logger,this.url=e.resolveUrl(`client/pull/v1`,e.baseUrl)}async connect(e,t){var n=this;if(n.fatalError)return n.logger.warn(`[PullTransport] There was a prior unrecoverable error. Ignoring attempt to reconnect.`),n;try{let r=await F(t,n.url,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({givenContext:e,metaContext:n.options.metaContext,clientSdkKey:n.options.clientSdkKey})},n.logger);if(!r.ok)throw n.isStatusFatal(r.status)?(n.fatalError=!0,n.prepareFatalResponseStatusError(r.status,await r.text())):new s(`Connection failed with status: ${r.status}`,r.status);let i=JSON.parse(await r.text());return n.eventEmitter.emit(`configSetReceived`,i),n}catch(e){throw l(e)?(n.fatalError=!0,new s(`Connection failed with fatal error: ${e}. This is an unrecoverable error, retry attempts will be ignored.`)):e instanceof SyntaxError?new s(`Failed to parse the response from the server: ${e}`):new s(`Connection failed with error: ${e}.`)}}prepareFatalResponseStatusError(e,t){var n,r;let i=e==null?0:e;return new s(`${`Connection failed with status: ${e==null?`unknown`:e}`}${((n=t==null||(r=t.trim())==null?void 0:r.length)==null?0:n)>0?` (${t})`:``}. This is an unrecoverable error, retry attempts will be ignored.`,i)}isStatusFatal(e){return!!e&&e>=400&&e<500}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.eventEmitter.clear()}close(){}dispose(){this.close(),this.clear()}};const L=(e,t)=>new URL(e,t==null?void 0:t.toString()),R=e=>{if(e)try{return new URL(e)}catch(t){throw new c(`Invalid URL '${e}'. Parsing failed: ${t}`)}},z=`https://client-sdk-api.configdirector.com`;var B=class{constructor(e,t,n,r,i){var a,s,c,l,u,d,f,p,m;this.handlersMap=new Map,this.eventEmitter=new o,this.ready=!1,this.logger=(a=r==null?void 0:r.logger)==null?P():a,this.timeout=(s=r==null||(c=r.connection)==null?void 0:c.timeout)==null?3e3:s;let h=(l=i==null?void 0:i.urlFactory)==null?L:l,g=(u=this.parseUrl(r==null||(d=r.connection)==null?void 0:d.url,h))==null?z:u;this.streaming=(r==null||(f=r.connection)==null?void 0:f.streaming)!==!1;let _=this.streaming?w:I;this.telemetryClient=e,this.transport=new _({clientSdkKey:t,baseUrl:g,resolveUrl:h,metaContext:y(y({},r==null?void 0:r.metadata),{},{sdkName:n.sdkName,sdkVersion:n.sdkVersion,userAgent:(p=navigator)==null?void 0:p.userAgent}),logger:this.logger,fetch:i==null?void 0:i.fetch,connectionRetryDelay:(m=i==null?void 0:i.connectionRetryDelay)==null?(e=>2**Math.min(e,9)*1e3):m}),this.transport.on(`configSetReceived`,e=>{var t;(t=this.readyResolve)==null||t.call(this);let n=Object.keys(e.configs);!this.configSet||e.kind==`full`?(this.configSet=e,this.eventEmitter.emit(`configsUpdated`,{keys:n}),this.updateWatchers(e.configs)):(this.configSet.configs=y(y({},this.configSet.configs),e.configs),this.eventEmitter.emit(`configsUpdated`,{keys:n}),this.updateWatchers(e.configs)),this.logger.debug(`[ConfigDirectorClient] ConfigSet updated from server:`,{keys:n})})}async initialize(e){await this.connectToTransport(e,`initialization`)}async updateContext(e){await this.connectToTransport(e,`context update`)}async connectToTransport(e,t){var n=this;try{n.ready=!1,n.readyPromise=new Promise(e=>{n.readyResolve=e}).then(()=>{n.ready=!0,n.eventEmitter.emit(`clientReady`,{action:t}),n.logger.debug(`[ConfigDirectorClient] Received initial payload from the server, client is ready`)});let r=new Date().getTime();await n.transport.connect(e==null?{}:e,n.timeout),n.currentContext=e,n.telemetryClient.updateContext(e);let i=new Date().getTime()-r,a=n.timeout-i;if(clearTimeout(n.timeoutTimer),n.timeoutTimer=void 0,a>0&&await Promise.race([n.readyPromise,new Promise(e=>{n.timeoutTimer=setTimeout(()=>e(),a)})]).finally(()=>clearTimeout(n.timeoutTimer)),!n.ready){let e=n.streaming?`The client will continue to retry since there were no fatal errors detected. Configs will return the default value until the connection succeeds.`:`Since the client was configured without streaming, configs may not update and always return the default value.`;n.logger.warn(`[ConfigDirectorClient] Timed out waiting for ${t} after ${n.timeout}ms. ${e}`)}}catch(e){n.logger.error(`[ConfigDirectorClient] An error occurred during ${t}: `,e)}}updateWatchers(e){Object.values(e).forEach(e=>this.updateWatchersForConfig(e))}updateWatchersForConfig(e){var t;(t=this.handlersMap.get(e.key))==null||t.forEach(t=>{let n=this.getValueFromConfigState(e.key,e,t.defaultValue);t.handler(n)})}watch(e,t,n){this.validateDefaultValue(t);let r=this.handlersMap.get(e),i={handler:n,defaultValue:t,requestedType:typeof t};return r?r.push(i):this.handlersMap.set(e,[i]),()=>this.unwatch(e,n)}unwatch(e,t){let n=this.handlersMap.get(e);if(n)if(t){let e=n.findIndex(e=>e.handler==t);e>=0&&(n==null||n.splice(e,1))}else n.splice(0)}getValue(e,t){var n;this.validateDefaultValue(t);let r=(n=this.configSet)==null?void 0:n.configs[e];return this.getValueFromConfigState(e,r,t)}getValueFromConfigState(e,t,n){var r;if(!t){var i;return this.logger.debug(`[ConfigDirectorClient] No config state found for '${e}', returning default value '${n}'`),this.telemetryClient.evaluatedConfig({contextId:(i=this.currentContext)==null?void 0:i.id,key:e,defaultValue:n,requestedType:T(n),evaluatedValue:n,usedDefault:!0,evaluationReason:`config-state-missing`}),n}let a=D(t,n);return this.telemetryClient.evaluatedConfig({contextId:(r=this.currentContext)==null?void 0:r.id,key:e,defaultValue:n,requestedType:a.requestedType,evaluatedValue:a.parsedValue,usedDefault:a.usedDefault,evaluationReason:a.reason}),this.logger.debug(`[ConfigDirectorClient] Evaluated '${e}' to '${a.parsedValue}'`),a.parsedValue}parseUrl(e,t){if(e)try{return t(e)}catch(t){throw new c(`Invalid base URL '${e}'. Parsing failed: ${t}`)}}validateDefaultValue(e){if(e==null)throw new c(`Invalid default value. The default value for a config must be defined and non-null.`);if(typeof e==`function`)throw new c(`Invalid default value. The default value for a config cannot be a function.`)}get isReady(){return this.ready}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.logger.debug(`[ConfigDirectorClient] clear() has been called, removing all observers`),this.eventEmitter.clear(),this.handlersMap.clear()}unwatchAll(){this.handlersMap.clear()}pauseNetwork(){this.logger.debug(`[ConfigDirectorClient] pauseNetwork() called, pausing transport connection`),clearTimeout(this.timeoutTimer),this.timeoutTimer=void 0,this.transport.close(),this.ready=!1}async resumeNetwork(){var e=this;await e.connectToTransport(e.currentContext,`network resume`)}async close(){var e=this,t;e.logger.debug(`[ConfigDirectorClient] close() has been called, closing connection to server`),clearTimeout(e.timeoutTimer),(t=e.readyResolve)==null||t.call(e),e.telemetryClient.close(),e.transport.close(),e.ready=!1}dispose(){this.clear(),this.close()}};const V=(e,t)=>{if(t===`json`)try{return H(JSON.stringify(e))}catch(t){return e.toString().slice(0,500)}return e.toString().slice(0,500)},H=e=>U(new TextEncoder().encode(e)).toString(16).padStart(8,`0`),U=e=>{let t=5381;for(let r=0;r<e.length;r++){var n;t=(t<<5)+t+((n=e[r])==null?0:n),t>>>=0}return t};var W=class{constructor(e){var t,n,r;this.logger=e.logger;let i={type:`Initialize`,payload:{sdkKey:e.sdkKey,baseUrl:e.baseUrl.toString(),evaluationQueueLimit:(t=e.evaluationQueueLimit)==null?1e3:t,initialFlushIntervalDelay:(n=e.initialFlushIntervalDelay)==null?5e3:n,flushIntervalDelay:(r=e.flushIntervalDelay)==null?3e4:r}};this.worker=new Worker(URL.createObjectURL(new Blob(["(function(){let e=(e,n)=>{if(n===`json`)try{return t(JSON.stringify(e))}catch{return e.toString().slice(0,500)}return e.toString().slice(0,500)},t=e=>n(new TextEncoder().encode(e)).toString(16).padStart(8,`0`),n=e=>{let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+(e[n]??0),t>>>=0;return t},r=e=>{let t=Object.keys(e);if(t.length==0)return!0;for(let n of t)if((e[n]?.length??0)>0)return!1;return!0},i=e=>{if(!e)return!0;let t=Object.keys(e);if(t.length==0)return!0;for(let n of t)if((e[n]??0)>0)return!1;return!0},a=async(e,t,n,r)=>{let i=new AbortController,a=setTimeout(()=>{r.debug(`[fetchWithTimeout] Reached timeout, aborting request`),i.abort()},e);try{let e=await fetch(typeof t==`string`||t instanceof Request?t:t.toString(),{...n,signal:i.signal});return clearTimeout(a),e}catch(e){throw r.warn(`[fetchWithTimeout] Fetch error: `,e),clearTimeout(a),e}},o=e=>e?.name===`NotAllowedError`?!0:e instanceof TypeError;var s=class{constructor(e){this.executeRequests=!0,this.sdkKey=e.sdkKey,this.logger=e.logger,this.url=e.urlFactory(`client/telemetry/v1`,e.baseUrl)}async report({context:e,discreteEvents:t,aggregatedEvents:n,droppedEvents:r}){if(!this.executeRequests)return{success:!1,fatalError:!0};let i={clientSdkKey:this.sdkKey,context:e,discreteEvents:t,aggregatedEvents:n,droppedEvents:r};if(this.isReportEmpty(i))return{success:!0,fatalError:!1};let a=await this.sendReport(i);return a.fatalError&&(this.executeRequests=!1),a}isReportEmpty(e){return r(e.discreteEvents)&&r(e.aggregatedEvents)&&i(e.droppedEvents)}async sendReport(e){try{let t=await a(5e3,this.url,{method:`POST`,body:JSON.stringify(e),keepalive:!0},this.logger),n=this.isStatusFatal(t.status);return n&&this.logger.warn(`[EventReporter] Received a fatal status response (${t.status}) from the telemetry endpoint. No more telemetry data will be sent.`),{success:t.ok,fatalError:n}}catch(e){let t=o(e);return this.logger.warn(`[EventReporter] Error attempting to send telemetry data: ${e}`,{error:e}),{success:!1,fatalError:t}}}isStatusFatal(e){return!!e&&e>=400&&e<500}},c=class{aggregate(e){if(e.events.length==0)return[];let t=new Map;for(let n of e.events){let e=JSON.stringify(n),r=t.get(e)?.count||0;t.set(e,{event:n,count:r+1})}return Array.from(t).map(([,t])=>({startTime:e.startTime,endTime:e.endTime,count:t.count,event:t.event}))}},l=class{constructor(e){this._events=[],this._droppedEventCount=0,this.limit=e??1e3}get events(){return this._events}get reachedLimit(){return this._events.length>=this.limit}get droppedEventCount(){return this._droppedEventCount}push(...e){this.startTime||=new Date;let t=Math.max(0,e.length-this.limit),n=e.slice(t,e.length);if(this._droppedEventCount+=t,this._events.length+n.length>this.limit){let e=this._events.length+n.length-this.limit;this._events.splice(0,e),this._droppedEventCount+=e}return this._events.push(...n)}takeSnapshot(){let e=new Date,t=this.startTime??e,n=this._events.splice(0),r=this._droppedEventCount;return this.startTime=void 0,this._droppedEventCount=0,{startTime:t,endTime:e,events:n,droppedCount:r}}clear(){this._events=[],this.startTime=void 0,this._droppedEventCount=0}},u=class{constructor(e){this.aggregator=new c,this.collectEvents=!0,this.logger=e.logger,this.evaluationEventQueue=new l(e.evaluationQueueLimit??1e3),this.flushIntervalDelay=e.flushIntervalDelay??3e4;let t=e.initialFlushIntervalDelay??5e3;this.flushTimeout=setTimeout(()=>this.flushAndScheduleNext(),t)}sanitizeValue(t,n){return e(t,n)}async flushAndScheduleNext(){(await this.flush()).fatalError?(this.collectEvents=!1,this.close(),this.logger.warn(`[TelemetryEventCollector] Received a fatal error from telemetry collection. No longer collecting events.`)):this.flushTimeout=setTimeout(()=>this.flushAndScheduleNext(),this.flushIntervalDelay)}async flush(){if(!this.reporter)return{success:!1,fatalError:!1};let e=this.evaluationEventQueue.takeSnapshot();return await this.reporter?.report({context:this._context,discreteEvents:{},aggregatedEvents:{evaluatedConfig:this.aggregator.aggregate(e)},droppedEvents:{evaluatedConfig:e.droppedCount}})}cancelScheduledFlush(){clearTimeout(this.flushTimeout)}async close(){this.collectEvents=!1,clearTimeout(this.flushTimeout),await this.flush(),this.evaluationEventQueue.clear()}dispose(){this.close()}},d=class extends u{constructor(e){super(e),this.reporter=new s(e)}async updateContext(e){this.cancelScheduledFlush(),await this.flush(),this._context=e,await this.flushAndScheduleNext()}evaluatedConfig(e){this.collectEvents&&this.evaluationEventQueue.push(e)}async forceFlush(){this.cancelScheduledFlush(),await this.flushAndScheduleNext()}};let f=(e,t)=>new URL(e,t?.toString()),p,m=(e,t,...n)=>({type:`Log`,payload:{level:e,message:t,args:n}}),h=e=>{try{self.postMessage(e)}catch{self.postMessage(m(e.payload.level,e.payload.message))}},g={debug:function(e,...t){h(m(`debug`,e,t))},info:function(e,...t){h(m(`info`,e,t))},warn:function(e,...t){h(m(`warn`,e,t))},error:function(e,...t){h(m(`error`,e,t))}};addEventListener(`message`,e=>{let t=e.data;if(t.type!=`Initialize`&&!p){g.info(`[TelemetryWorker] Ignoring ${t.type} because no collector is configured`);return}switch(g.debug(`[TelemetryWorker] Received '${t.type}' event:`,t),t.type){case`Initialize`:p=new d({...t.payload,baseUrl:f(t.payload.baseUrl),urlFactory:f,logger:g});break;case`EvaluatedConfigEvent`:p?.evaluatedConfig(t.payload);break;case`UpdateContext`:p?.updateContext(t.payload.context);break;case`Flush`:p?.forceFlush();break;case`Close`:(p?.close()??Promise.resolve()).then(()=>{self.postMessage({type:`Closed`}),self.close()});break}})})();"],{type:`application/javascript`}))),this.worker.onmessage=e=>{this.handleWorkerEvent(e.data)},this.worker.postMessage(i),this.visibilityHandler=()=>{document.visibilityState===`hidden`&&this.flush()};try{document.addEventListener(`visibilitychange`,this.visibilityHandler)}catch(e){this.logger.warn(`[TelemetryEventCollector] Could not configure 'visibilitychange' listener: `,e)}}async updateContext(e){var t=this;let n={type:`UpdateContext`,payload:{context:e}};t.worker.postMessage(n)}evaluatedConfig(e){let t={type:`EvaluatedConfigEvent`,payload:this.sanitizeEvaluatedConfigEvent(e)};this.worker.postMessage(t)}sanitizeEvaluatedConfigEvent(e){return y(y({},e),{},{defaultValue:V(e.defaultValue,e.type),evaluatedValue:V(e.evaluatedValue,e.type)})}handleWorkerEvent(e){var t,n;if(e.type===`Closed`){var r;(r=this.closeResolve)==null||r.call(this);return}if(!((t=e.payload)!=null&&t.level)||!((n=e.payload)!=null&&n.message))return;let{level:i,message:a,args:o}=e.payload;switch(i){case`debug`:this.logger.debug(a,...o);break;case`info`:this.logger.info(a,...o);break;case`warn`:this.logger.warn(a,...o);break;case`error`:this.logger.warn(a,...o);break}}flush(){this.worker.postMessage({type:`Flush`})}close(){return this.closePromise?this.closePromise:this.performClose()}performClose(){return document.removeEventListener(`visibilitychange`,this.visibilityHandler),this.closePromise=new Promise(e=>{this.closeResolve=e,this.worker.postMessage({type:`Close`})}),this.closePromise}};const G=(e,t,n)=>{var r,i,a;let o=(r=n==null?void 0:n.logger)==null?P():r;return new B(new W({sdkKey:e,logger:o,baseUrl:(i=R(n==null||(a=n.connection)==null?void 0:a.url))==null?z:i,urlFactory:L}),e,t,y(y({},n),{},{logger:o}))},K=(e,t)=>G(e,{sdkName:`react-web-sdk`,sdkVersion:`0.3.1`},t),q=e.createContext({status:`loading`});var J=class{decorateMessage(e){return`[ConfigDirector:react-web-sdk] ${e}`}};const Y=e=>P(e,new J),X=async e=>{var t;let n=(t=e.logger)==null?Y(`debug`):t,o=K(e.sdkKey,{connection:{url:e.url,timeout:e.timeout},metadata:{appName:e.appName,appVersion:e.appVersion},logger:n});return await o.initialize(e.context),({children:e})=>{let[t,n]=i(()=>({client:o,status:o.isReady?`ready`:`default`}));return r(()=>{o.on(`configsUpdated`,()=>{n(e=>y(y({},e),{},{updatedAt:new Date}))}),o.on(`clientReady`,()=>{n(e=>y(y({},e),{},{status:`ready`}))})}),a(q.Provider,{value:t,children:e})}};var Z=class extends t{constructor(e){var t;super(e),this.state={client:K(e.sdkKey,{connection:{url:e.url,timeout:e.timeout},metadata:{appName:e.appName,appVersion:e.appVersion},logger:(t=e.logger)==null?Y(`warn`):t}),status:`loading`}}async componentDidMount(){var e=this,t,n,r,i;(t=e.state.client)==null||t.on(`configsUpdated`,()=>{e.setState({updatedAt:new Date})}),(n=e.state.client)==null||n.on(`clientReady`,()=>{e.setState({status:`ready`})}),await((r=e.state.client)==null?void 0:r.initialize(e.props.context)),(i=e.state.client)!=null&&i.isReady||e.setState({status:`default`})}async componentDidUpdate(e){var t=this;if(e.context!==t.props.context){var n,r,i;t.setState({status:`loading`}),await((n=t.state.client)==null?void 0:n.updateContext((r=t.props.context)==null?{}:r)),(i=t.state.client)!=null&&i.isReady||t.setState({status:`default`})}}componentWillUnmount(){var e;(e=this.state.client)==null||e.dispose()}render(){return a(q.Provider,{value:this.state,children:this.props.children})}},Q=class e extends Error{constructor(t){super(t),this.name=`ConfigDirectorReactContextError`,Object.setPrototypeOf(this,e.prototype)}};const $=()=>new Q(`The ConfigDirector client was not found in the React context. Please make sure the component using this hook is inside the context of a ConfigDirectorProvider.`),te=(e,t)=>{let r=n(q);if(!(r!=null&&r.client))throw $();return{value:r.client.getValue(e,t),readyStatus:r.status,loading:r.status===`loading`}},ne=()=>{let e=n(q);if(!(e!=null&&e.client))throw $();return{updateContext:async t=>{var n;await((n=e.client)==null?void 0:n.updateContext(t))}}},re=()=>{let e=n(q);if(!(e!=null&&e.client))throw $();return{client:e.client}};export{Z as ConfigDirectorProvider,Y as createConsoleLogger,re as useConfigDirectorClient,ne as useConfigDirectorContext,te as useConfigValue,X as withProvider};
4
4
  //# sourceMappingURL=configdirector-react-client.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"configdirector-react-client.mjs","names":["this","this","this","this","createJsSdkLogger","this"],"sources":["../../js-client-core/src/Emitter.ts","../../shared/src/errors.ts","../../js-client-core/src/errors.ts","../../eventsource/src/errors.ts","../../eventsource/src/EventSourceParser.ts","../../eventsource/src/types.ts","../../eventsource/src/EventSourceClient.ts","../../eventsource/src/index.ts","../../js-client-core/src/StreamingTransport.ts","../../shared/src/value-parser.ts","../../shared/src/logger.ts","../../js-client-core/src/logger.ts","../../shared/src/fetchWithTimeout.ts","../../js-client-core/src/PullTransport.ts","../../shared/src/telemetry/utils.ts","../../js-client-core/src/telemetry/TelemetryClient.ts","../../js-client-core/src/DefaultConfigDirectorClient.ts","../src/client.ts","../src/context.tsx","../src/logger.ts","../src/withProvider.tsx","../src/provider.tsx","../src/errors.ts","../src/hooks.tsx"],"sourcesContent":["type EventType = string | symbol;\ntype EventsRecord = Record<EventType, any>;\n\ntype Handler<TEventsRecord extends EventsRecord, TKey extends keyof TEventsRecord> = (\n payload: TEventsRecord[TKey],\n) => void;\n\nexport interface EventProvider<TEventsRecord extends EventsRecord> {\n on<TName extends keyof TEventsRecord>(name: TName, handler: Handler<TEventsRecord, TName>): void;\n off<TName extends keyof TEventsRecord>(name: TName, handler?: Handler<TEventsRecord, TName>): void;\n clear(): void;\n}\n\nexport class Emitter<TEventsRecord extends EventsRecord> implements EventProvider<TEventsRecord> {\n private handlerMap: Map<keyof TEventsRecord, Array<(payload: any) => void>> = new Map();\n\n on<TName extends keyof TEventsRecord>(name: TName, handler: Handler<TEventsRecord, TName>) {\n const handlers = this.handlerMap.get(name);\n if (handlers) {\n handlers.push(handler);\n } else {\n this.handlerMap.set(name, [handler]);\n }\n }\n\n once<TName extends keyof TEventsRecord>(name: TName, handler: Handler<TEventsRecord, TName>) {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n function onceHandler(payload: TEventsRecord[keyof TEventsRecord]) {\n self.off(name, onceHandler);\n handler.apply(self, payload);\n }\n this.on(name, onceHandler);\n }\n\n off<TName extends keyof TEventsRecord>(name: TName, handler?: Handler<TEventsRecord, TName>) {\n const handlers = this.handlerMap.get(name);\n if (!handlers) {\n return;\n }\n\n if (handler) {\n const listenerIndex = handlers.indexOf(handler);\n if (listenerIndex >= 0) {\n handlers.splice(listenerIndex, 1);\n }\n } else {\n this.handlerMap.set(name, []);\n }\n }\n\n clear() {\n this.handlerMap.clear();\n }\n\n emit<TName extends keyof TEventsRecord>(name: TName, payload: TEventsRecord[TName]) {\n const handlers = this.handlerMap.get(name);\n if (!handlers) {\n return;\n }\n\n handlers.slice().map((h) => h(payload));\n }\n}\n","export class ConfigDirectorConnectionError extends Error {\n public override readonly name: string = \"ConfigDirectorConnectionError\";\n public readonly status?: number;\n\n constructor(message: string, status?: number) {\n super(message);\n this.status = status;\n\n Object.setPrototypeOf(this, ConfigDirectorConnectionError.prototype);\n }\n}\n\nexport class ConfigDirectorValidationError extends Error {\n public override readonly name: string = \"ConfigDirectorValidationError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, ConfigDirectorValidationError.prototype);\n }\n}\n","export { ConfigDirectorConnectionError, ConfigDirectorValidationError } from \"../../shared/src/errors\";\n\nexport const isFetchErrorFatal = (fetchError: any): boolean => {\n if (fetchError instanceof DOMException) {\n const domError = fetchError as DOMException;\n if (domError.name === \"NotAllowedError\") {\n return true;\n }\n } else if (fetchError instanceof TypeError) {\n return true;\n }\n\n return false;\n};\n","export class StreamClosedError extends Error {\n public override readonly name: string = \"StreamClosedError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, StreamClosedError.prototype);\n }\n}\n\nexport class MissingResponseBodyError extends Error {\n public override readonly name: string = \"MissingResponseBodyError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, MissingResponseBodyError.prototype);\n }\n}\n\nexport class InvalidOptionError extends Error {\n public override readonly name: string = \"InvalidOptionError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, InvalidOptionError.prototype);\n }\n}\n\nexport class ValueOutOfRangeError extends Error {\n public override readonly name: string = \"ValueOutOfRangeError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, ValueOutOfRangeError.prototype);\n }\n}\n","import {\n EventSourceParserOptions,\n EventSourceMessageHandler,\n EventSourceCommentHandler,\n EventParserRetryCallback,\n} from \"./types\";\n\ntype LineContent = {\n field: string;\n value: string;\n};\n\nexport class EventSourceParser {\n private isFirstChunk = true;\n private previousIncompleteLine = \"\";\n private currentEvent: { type?: string | undefined; data: string };\n private lastEventId: string | undefined;\n private onEvent: EventSourceMessageHandler;\n private onRetry: EventParserRetryCallback | undefined;\n private onComment: EventSourceCommentHandler | undefined;\n\n constructor(options: EventSourceParserOptions) {\n this.currentEvent = {\n data: \"\",\n };\n this.onEvent = options.onEvent ?? (() => {});\n this.onRetry = options.onRetry;\n this.onComment = options.onComment;\n }\n\n public parse(input: string) {\n const chunk = this.prepareChunk(input);\n const lines = this.splitLines(chunk);\n for (const line of lines) {\n this.parseAndProcessLine(line);\n }\n }\n\n public finish() {\n if (this.previousIncompleteLine !== \"\") {\n this.parseAndProcessLine(this.previousIncompleteLine);\n }\n }\n\n private parseAndProcessLine(line: string) {\n if (line.startsWith(\":\")) {\n this.onComment?.(this.getValueFromLine(0, line));\n return;\n }\n\n if (line === \"\") {\n this.publishEvent();\n return;\n }\n\n const content = this.parseContentLine(line);\n this.processContent(content);\n }\n\n private publishEvent() {\n const data = this.currentEvent.data.endsWith(\"\\n\")\n ? this.currentEvent.data.slice(0, -1)\n : this.currentEvent.data;\n\n if (data) {\n this.onEvent({\n ...this.currentEvent,\n id: this.lastEventId,\n data,\n });\n }\n this.currentEvent = {\n data: \"\",\n };\n }\n\n private processContent(content: LineContent) {\n switch (content.field) {\n case \"event\":\n this.currentEvent.type = content.value;\n break;\n case \"data\":\n this.currentEvent.data += content.value + \"\\n\";\n break;\n case \"id\":\n if (!content.value.includes(\"\\0\")) {\n this.lastEventId = content.value;\n }\n break;\n case \"retry\":\n if (/^\\d+$/.test(content.value)) {\n this.onRetry?.(Number.parseInt(content.value, 10));\n }\n break;\n\n default:\n break;\n }\n }\n\n private parseContentLine(line: string): LineContent {\n const delimiterIndex = line.indexOf(\":\");\n if (delimiterIndex === -1) {\n return { field: line, value: \"\" };\n }\n\n return { field: line.slice(0, delimiterIndex), value: this.getValueFromLine(delimiterIndex, line) };\n }\n\n private splitLines(chunk: string) {\n const lines = chunk.split(/\\r\\n|\\r|\\n/);\n this.previousIncompleteLine = lines.pop() ?? \"\";\n return lines;\n }\n\n private getValueFromLine(delimiterIndex: number, line: string): string {\n if (delimiterIndex === -1) {\n return \"\";\n }\n\n const valueStartIndex = line[delimiterIndex + 1] === \" \" ? delimiterIndex + 2 : delimiterIndex + 1;\n return line.slice(valueStartIndex);\n }\n\n private prepareChunk(chunk: string) {\n if (this.isFirstChunk) {\n this.isFirstChunk = false;\n return this.previousIncompleteLine + chunk.replace(/^\\xEF\\xBB\\xBF/, \"\").replace(/^\\uFEFF/, \"\");\n } else {\n return this.previousIncompleteLine + chunk;\n }\n }\n}\n","export type ReconnectionState = {\n attempt: number;\n serverReconnectionTime: number;\n status?: number | undefined;\n error?: Error | undefined;\n};\n\nexport enum ReadyState {\n OPEN = \"open\",\n CLOSED = \"closed\",\n CONNECTING = \"connecting\",\n}\n\nexport type EventSourceClientOptions = {\n url: URL | string;\n method?: string;\n headers?: Record<string, string>;\n body?: any;\n mode?: \"cors\" | \"no-cors\" | \"same-origin\";\n credentials?: \"include\" | \"omit\" | \"same-origin\";\n redirect?: \"error\" | \"follow\";\n referrer?: string;\n referrerPolicy?: ReferrerPolicy;\n lastEventId?: string;\n onError?: (error: Error) => void;\n onConnect?: () => void;\n onDisconnect?: () => void;\n onMessage?: EventSourceMessageHandler;\n onComment?: EventSourceCommentHandler;\n shouldReconnect?: (state: ReconnectionState) => boolean;\n calculateReconnectDelay?: (state: ReconnectionState) => number;\n};\n\nexport type EventSourceMessage = {\n id?: string | undefined;\n type?: string;\n data: string;\n};\n\nexport type EventSourceMessageHandler = (message: EventSourceMessage) => void;\nexport type EventSourceCommentHandler = (comment: string) => void;\n\nexport type EventParserRetryCallback = (retry: number) => void;\n\nexport type EventSourceParserOptions = {\n onEvent?: EventSourceMessageHandler;\n onRetry?: EventParserRetryCallback;\n onComment?: EventSourceCommentHandler;\n};\n","import {\n InvalidOptionError,\n MissingResponseBodyError,\n StreamClosedError,\n ValueOutOfRangeError,\n} from \"./errors\";\nimport { EventSourceParser } from \"./EventSourceParser\";\nimport {\n EventSourceClientOptions,\n EventSourceCommentHandler,\n EventSourceMessageHandler,\n ReconnectionState,\n ReadyState,\n} from \"./types\";\n\nexport class EventSourceClient {\n private readonly DEFAULT_SHOULD_RECONNECT = () => true;\n private readonly DEFAULT_CALCULATE_RECONNECT_DELAY = () => this.serverReconnectionTime;\n private readonly url: URL;\n private readonly headers?: Record<string, string>;\n private readonly requestOptions;\n private lastEventId?: string;\n private reconnectAttempt: number = 0;\n private abortController: AbortController = new AbortController();\n private reconnectTimeout: ReturnType<typeof setTimeout> | undefined;\n private _readyState: ReadyState = ReadyState.CLOSED;\n private serverReconnectionTime: number = 2_000;\n private _onError: (error: Error) => void;\n private _onMessage: EventSourceMessageHandler;\n private _onComment: EventSourceCommentHandler;\n private _onConnect: () => void;\n private _onDisconnect: () => void;\n private _shouldReconnect: (state: ReconnectionState) => boolean;\n private _calculateReconnectDelay: (state: ReconnectionState) => number;\n\n constructor(options: EventSourceClientOptions) {\n this.url = new URL(options.url);\n this.lastEventId = options.lastEventId;\n this.headers = {\n Accept: \"text/event-stream\",\n ...options.headers,\n };\n this.requestOptions = {\n body: options.body,\n method: options.method ?? \"GET\",\n mode: options.mode,\n credentials: options.credentials,\n redirect: options.redirect,\n referrer: options.referrer,\n referrerPolicy: options.referrerPolicy,\n };\n this._onError = this.getValidatedFunctionOrNoOp(options.onError, \"onError\");\n this._onConnect = this.getValidatedFunctionOrNoOp(options.onConnect, \"onConnect\");\n this._onDisconnect = this.getValidatedFunctionOrNoOp(options.onDisconnect, \"onDisconnect\");\n this._onMessage = this.getValidatedFunctionOrNoOp(options.onMessage, \"onMessage\");\n this._onComment = this.getValidatedFunctionOrNoOp(options.onComment, \"onComment\");\n this._shouldReconnect = this.getValidatedFunctionOr(\n options.shouldReconnect,\n this.DEFAULT_SHOULD_RECONNECT,\n \"shouldReconnect\",\n );\n this._calculateReconnectDelay = this.getValidatedFunctionOr(\n options.calculateReconnectDelay,\n this.DEFAULT_CALCULATE_RECONNECT_DELAY,\n \"calculateReconnectDelay\",\n );\n }\n\n public set onError(value: (error: Error) => void) {\n this._onError = this.getValidatedFunctionOrNoOp(value, \"onError\");\n }\n\n public set onMessage(value: EventSourceMessageHandler) {\n this._onMessage = this.getValidatedFunctionOrNoOp(value, \"onMessage\");\n }\n\n public set onComment(value: EventSourceCommentHandler) {\n this._onComment = this.getValidatedFunctionOrNoOp(value, \"onComment\");\n }\n\n public set onConnect(value: () => void) {\n this._onConnect = this.getValidatedFunctionOrNoOp(value, \"onConnect\");\n }\n\n public set onDisconnect(value: () => void) {\n this._onDisconnect = this.getValidatedFunctionOrNoOp(value, \"onDisconnect\");\n }\n\n public set shouldReconnect(value: (state: ReconnectionState) => boolean) {\n this._shouldReconnect = this.getValidatedFunctionOr(\n value,\n this.DEFAULT_SHOULD_RECONNECT,\n \"shouldReconnect\",\n );\n }\n\n public set calculateReconnectDelay(value: (state: ReconnectionState) => number) {\n this._calculateReconnectDelay = this.getValidatedFunctionOr(\n value,\n this.DEFAULT_CALCULATE_RECONNECT_DELAY,\n \"shouldReconnect\",\n );\n }\n\n public get readyState(): ReadyState {\n return this._readyState;\n }\n\n public connect() {\n if (this._readyState !== ReadyState.CLOSED) {\n return;\n }\n\n this.reconnectAttempt = 0;\n this.initiateConnection();\n }\n\n private initiateConnection() {\n this.abortController = new AbortController();\n this._readyState = ReadyState.CONNECTING;\n fetch(this.url, {\n ...this.requestOptions,\n headers: this.buildHeaders(),\n signal: this.abortController.signal,\n cache: \"no-store\",\n })\n .then(this.handleFetchResponse.bind(this))\n .catch((error: Error) => {\n if (error.name === \"AbortError\" || this.abortController.signal.aborted) {\n this.close();\n return;\n }\n\n this._onError(error);\n this.scheduleReconnect({ error });\n });\n }\n\n public close() {\n clearTimeout(this.reconnectTimeout);\n this._readyState = ReadyState.CLOSED;\n this.abortController.abort();\n }\n\n private disconnected() {\n clearTimeout(this.reconnectTimeout);\n this._readyState = ReadyState.CLOSED;\n this._onDisconnect();\n }\n\n private buildHeaders(): Record<string, string> {\n const lastEventIdHeader = this.lastEventId ? { \"Last-Event-ID\": this.lastEventId } : undefined;\n return {\n ...this.headers,\n ...lastEventIdHeader,\n };\n }\n\n private async handleFetchResponse(response: Response) {\n const { body, status } = response;\n\n if (status === 204) {\n this.disconnected();\n return;\n }\n\n if (status >= 400) {\n this.scheduleReconnect({ status });\n return;\n }\n\n if (!body) {\n throw new MissingResponseBodyError(\"The server response did not have a body\");\n }\n\n this._readyState = ReadyState.OPEN;\n this._onConnect();\n this.reconnectAttempt = 0;\n\n const stream = body?.pipeThrough(new TextDecoderStream());\n const reader = stream.getReader();\n const parser = new EventSourceParser({\n onEvent: (event) => {\n if (typeof event.id === \"string\") {\n this.lastEventId = event.id;\n }\n this._onMessage(event);\n },\n onComment: (comment) => this._onComment(comment),\n onRetry: (retryDelay) => (this.serverReconnectionTime = retryDelay),\n });\n\n let done = false;\n while (!done) {\n const { done: readerDone, value } = await reader.read();\n if (value) {\n parser.parse(value);\n }\n\n done = readerDone;\n }\n\n parser.finish();\n this.scheduleReconnect({ status, error: new StreamClosedError(\"The server response stream was closed\") });\n }\n\n private scheduleReconnect(state: { status?: number; error?: Error }) {\n if (this.abortController.signal.aborted) {\n return;\n }\n\n clearTimeout(this.reconnectTimeout);\n this.reconnectAttempt += 1;\n const reconnectionState = {\n attempt: this.reconnectAttempt,\n status: state.status,\n error: state.error,\n serverReconnectionTime: this.serverReconnectionTime,\n };\n if (this._shouldReconnect(reconnectionState)) {\n this._readyState = ReadyState.CONNECTING;\n let delay = this._calculateReconnectDelay(reconnectionState);\n if (!Number.isFinite(delay) || delay < 1 || delay > 1_000 * 60 * 60) {\n this._onError(\n new ValueOutOfRangeError(\n `The calculated reconnect delay is out of range: ${delay}. Defaulting to ${this.serverReconnectionTime}`,\n ),\n );\n delay = this.serverReconnectionTime;\n }\n this.reconnectTimeout = setTimeout(() => this.initiateConnection(), delay);\n } else {\n this.disconnected();\n return;\n }\n }\n\n private getValidatedFunctionOrNoOp(func: any, name: string): (...args: any) => any {\n return this.getValidatedFunctionOr(func, () => {}, name);\n }\n\n private getValidatedFunctionOr(\n func: any,\n defaultFunc: (...args: any) => any,\n name: string,\n ): (...args: any) => any {\n if (func == null) {\n return defaultFunc;\n } else if (typeof func === \"function\") {\n return func;\n } else {\n throw new InvalidOptionError(`${name} must be a function`);\n }\n }\n}\n","import { EventSourceClient } from \"./EventSourceClient\";\nimport { EventSourceClientOptions } from \"./types\";\n\nexport const createEventSourceClient = (options: EventSourceClientOptions) => {\n return new EventSourceClient(options);\n};\n","import type {\n ConfigDirectorContext,\n ConfigDirectorLogger,\n Transport,\n TransportEvents,\n TransportOptions,\n} from \"./types\";\nimport { Emitter } from \"./Emitter\";\nimport { ConfigDirectorConnectionError } from \"./errors\";\nimport { createEventSourceClient } from \"@eventsource/index\";\nimport { EventSourceClient } from \"@eventsource/EventSourceClient\";\n\nexport class StreamingTransport implements Transport {\n private logger: ConfigDirectorLogger;\n private eventSource: EventSourceClient | undefined;\n private eventEmitter = new Emitter<TransportEvents>();\n private url: URL;\n\n constructor(private readonly options: TransportOptions) {\n this.options = options;\n this.logger = options.logger;\n this.url = new URL(\"client/sse/v1\", options.baseUrl);\n }\n\n public async connect(context: ConfigDirectorContext, timeout: number): Promise<this> {\n if (this.eventSource) {\n this.close();\n }\n\n const eventSourcePromise = new Promise<this>((resolve, reject) => {\n this.eventSource = createEventSourceClient({\n url: this.url,\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n givenContext: context,\n metaContext: this.options.metaContext,\n clientSdkKey: this.options.clientSdkKey,\n }),\n\n onMessage: ({ data }) => {\n this.dispatchMessage(data);\n },\n onConnect: () => {\n this.logger.debug(\"[EventSourceTransport] Connected\");\n resolve(this);\n },\n shouldReconnect: (state) => {\n const reconnect = !this.isStatusFatal(state.status);\n if (!reconnect) {\n reject(this.prepareFatalError(state.status, state.error));\n }\n return reconnect;\n },\n calculateReconnectDelay: (state) => {\n const delay = 2_000 * state.attempt;\n this.logger.warn(`[EventSourceTransport] Scheduling reconnect in ${delay}ms.`);\n return delay;\n },\n onDisconnect: () => {\n this.logger.debug(\"[EventSourceTransport] Disconnected\");\n },\n });\n this.eventSource.connect();\n });\n return Promise.race([\n eventSourcePromise,\n new Promise<this>((resolve) => {\n setTimeout(() => resolve(this), timeout);\n }),\n ]);\n }\n\n private dispatchMessage(data: string) {\n try {\n const json = JSON.parse(data);\n this.eventEmitter.emit(\"configSetReceived\", json);\n } catch (error) {\n this.logger.error(\"[EventSourceTransport] Error parsing and dispatching config data update: \", error);\n }\n }\n\n private prepareFatalError(\n responseStatus: number | undefined,\n error: Error | undefined,\n ): ConfigDirectorConnectionError {\n const status = responseStatus ?? 0;\n const headline = `Connection failed with status: ${responseStatus ?? \"unknown\"}.`;\n const errorLine = error ? ` Error: ${error}` : \"\";\n const message = `${headline}${errorLine}. This is an unrecoverable error, will not attempt to reconnect.`;\n return new ConfigDirectorConnectionError(message, status);\n }\n\n private isStatusFatal(status: number | undefined): boolean {\n return !!status && status >= 400 && status < 500;\n }\n\n public on<TName extends keyof TransportEvents>(\n name: TName,\n handler: (payload: TransportEvents[TName]) => void,\n ): void {\n this.eventEmitter.on(name, handler);\n }\n\n public off<TName extends keyof TransportEvents>(\n name: TName,\n handler?: ((payload: TransportEvents[TName]) => void) | undefined,\n ): void {\n this.eventEmitter.off(name, handler);\n }\n\n public clear(): void {\n this.eventEmitter.clear();\n }\n\n public close() {\n this.eventSource?.close();\n }\n\n public dispose(): void {\n this.close();\n this.clear();\n }\n}\n","import type { ConfigState, ConfigValueType, EvaluationReason } from \"./types\";\n\ntype NativeType =\n | \"string\"\n | \"number\"\n | \"bigint\"\n | \"boolean\"\n | \"symbol\"\n | \"undefined\"\n | \"object\"\n | \"function\";\n\ntype ParseResult<T extends ConfigValueType> = {\n parsedValue: T;\n requestedType: NativeType | string;\n usedDefault: boolean;\n reason: EvaluationReason;\n};\n\nexport const getRequestedType = <T extends ConfigValueType>(defaultValue: T): string => {\n const baseType = typeof defaultValue;\n if (baseType === \"object\") {\n try {\n return (defaultValue as object).constructor?.name ?? baseType;\n } catch {\n return baseType;\n }\n } else if (baseType === \"function\") {\n try {\n const functionName = (defaultValue as any).name;\n return functionName ? `function: ${functionName}` : baseType;\n } catch {\n return baseType;\n }\n }\n return baseType;\n};\n\nconst isNumericNativeType = (requestedType: NativeType): boolean => {\n return requestedType === \"number\" || requestedType === \"bigint\";\n};\n\nexport const parseConfigValue = <T extends ConfigValueType>(\n configState: ConfigState,\n defaultValue: T,\n): ParseResult<T> => {\n const value = configState.value;\n const requestedType = getRequestedType(defaultValue);\n\n if (!value) {\n return {\n parsedValue: defaultValue as T,\n requestedType,\n usedDefault: true,\n reason: \"value-missing\",\n };\n }\n\n if (typeof defaultValue === \"string\") {\n return {\n parsedValue: value as T,\n requestedType,\n usedDefault: false,\n reason: \"found-match\",\n };\n }\n\n if (typeof defaultValue === \"boolean\" && configState.type === \"boolean\") {\n const boolValue = parseConfigBoolean(value);\n const hasBoolean = typeof boolValue === \"boolean\";\n return {\n parsedValue: (hasBoolean ? boolValue : defaultValue) as T,\n requestedType,\n usedDefault: !hasBoolean,\n reason: hasBoolean ? \"found-match\" : \"invalid-boolean\",\n };\n }\n\n if (isNumericNativeType(typeof defaultValue) && configState.type === \"integer\") {\n const numValue = parseConfigInteger(value);\n const hasNumber = typeof numValue === \"number\";\n return {\n parsedValue: (hasNumber ? numValue : defaultValue) as T,\n requestedType,\n usedDefault: !hasNumber,\n reason: hasNumber ? \"found-match\" : \"invalid-number\",\n };\n }\n if (isNumericNativeType(typeof defaultValue) && (configState.type === \"float\" || configState.type === \"enum\" )) {\n const numValue = parseConfigFloat(value);\n const hasNumber = typeof numValue === \"number\";\n return {\n parsedValue: (hasNumber ? numValue : defaultValue) as T,\n requestedType,\n usedDefault: !hasNumber,\n reason: hasNumber ? \"found-match\" : \"invalid-number\",\n };\n }\n\n return {\n parsedValue: value as T,\n requestedType,\n usedDefault: false,\n reason: \"found-match\",\n };\n};\n\nconst parseConfigBoolean = (value: string): boolean | undefined => {\n if (!value) {\n return;\n }\n const lowerValue = value.toLowerCase();\n if (lowerValue != \"true\" && lowerValue != \"false\") {\n return;\n }\n return lowerValue === \"true\";\n};\n\nconst parseConfigInteger = (value: string): number | undefined => {\n if (!value) {\n return;\n }\n const num = Number.parseInt(value);\n if (isNaN(num) || !isFinite(num)) {\n return;\n }\n return num;\n};\n\nconst parseConfigFloat = (value: string): number | undefined => {\n if (!value) {\n return;\n }\n const num = Number.parseFloat(value);\n if (isNaN(num) || !isFinite(num)) {\n return;\n }\n return num;\n};\n","import { ConfigDirectorLogger, ConfigDirectorLogMessageDecorator, ConfigDirectorLoggingLevel } from \"./types\";\n\nconst LEVELS: Record<ConfigDirectorLoggingLevel, number> = {\n off: -1,\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\nconst buildDateFormatter = () => {\n const baseOptions: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n timeZoneName: \"short\",\n };\n\n try {\n return new Intl.DateTimeFormat(\n undefined,\n { ...baseOptions, fractionalSecondDigits: 3 } as Intl.DateTimeFormatOptions,\n );\n } catch {\n return new Intl.DateTimeFormat(undefined, baseOptions);\n }\n};\n\nexport class DefaultConsoleLogger implements ConfigDirectorLogger {\n private readonly dateFormatter;\n\n constructor(private readonly level: ConfigDirectorLoggingLevel, private readonly decorator: ConfigDirectorLogMessageDecorator) {\n this.level = level;\n this.decorator = decorator;\n this.dateFormatter = buildDateFormatter();\n }\n\n debug(message: string, ...args: any): void {\n this.log(console.debug, \"debug\", message, ...args);\n }\n\n info(message: string, ...args: any): void {\n this.log(console.info, \"info\", message, ...args);\n }\n\n warn(message: string, ...args: any): void {\n this.log(console.warn, \"warn\", message, ...args);\n }\n\n error(message: string, ...args: any): void {\n this.log(console.error, \"error\", message, ...args);\n }\n\n private log(loggerFunction: (...args: any) => void, level: ConfigDirectorLoggingLevel, message: string, ...args: any) {\n if (LEVELS[this.level] >= LEVELS[level]) {\n loggerFunction(`[${this.dateFormatter.format(new Date())}] ${this.decorator?.decorateMessage(message)}`, ...args);\n }\n }\n}\n","import { ConfigDirectorLogMessageDecorator, ConfigDirectorLoggingLevel } from \"./types\";\nimport { DefaultConsoleLogger } from \"../../shared/src/logger\";\nexport { DefaultConsoleLogger } from \"../../shared/src/logger\";\n\nclass LogMessageDecorator implements ConfigDirectorLogMessageDecorator {\n decorateMessage(message: string): string {\n return `[ConfigDirector:js-client-sdk] ${message}`;\n }\n}\n\nexport const createDefaultLogger = (\n level?: ConfigDirectorLoggingLevel,\n messageDecorator?: ConfigDirectorLogMessageDecorator,\n) => {\n return new DefaultConsoleLogger(level ?? \"warn\", messageDecorator ?? new LogMessageDecorator());\n};\n","import { ConfigDirectorLogger } from \"./types\";\n\nexport const fetchWithTimeout = async (\n timeout: number,\n resource: string | URL | Request,\n options: RequestInit | undefined,\n logger: ConfigDirectorLogger,\n) => {\n const abortController = new AbortController();\n const abortTimeoutId = setTimeout(() => {\n logger.debug(\"[fetchWithTimeout] Reached timeout, aborting request\");\n abortController.abort();\n }, timeout);\n\n try {\n const response = await fetch(resource, {\n ...options,\n signal: abortController.signal,\n });\n clearTimeout(abortTimeoutId);\n return response;\n } catch (error) {\n logger.warn(\"[fetchWithTimeout] Fetch error: \", error);\n clearTimeout(abortTimeoutId);\n throw error;\n }\n};\n","import type {\n ConfigDirectorContext,\n ConfigDirectorLogger,\n Transport,\n TransportEvents,\n TransportOptions,\n} from \"./types\";\nimport { Emitter } from \"./Emitter\";\nimport { ConfigDirectorConnectionError, isFetchErrorFatal } from \"./errors\";\nimport { fetchWithTimeout } from \"@shared/fetchWithTimeout\";\n\nexport class PullTransport implements Transport {\n private logger: ConfigDirectorLogger;\n private eventEmitter = new Emitter<TransportEvents>();\n private url: URL;\n private fatalError = false;\n\n constructor(private readonly options: TransportOptions) {\n this.options = options;\n this.logger = options.logger;\n this.url = new URL(\"client/pull/v1\", options.baseUrl);\n }\n\n public async connect(context: ConfigDirectorContext, timeout: number): Promise<this> {\n if (this.fatalError) {\n this.logger.warn(\n \"[PullTransport] There was a prior unrecoverable error. Ignoring attempt to reconnect.\",\n );\n return this;\n }\n\n try {\n const response = await fetchWithTimeout(timeout, this.url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n givenContext: context,\n metaContext: this.options.metaContext,\n clientSdkKey: this.options.clientSdkKey,\n }),\n }, this.logger);\n\n if (!response.ok) {\n if (this.isStatusFatal(response.status)) {\n this.fatalError = true;\n throw this.prepareFatalResponseStatusError(response.status, await response.text());\n } else {\n throw new ConfigDirectorConnectionError(\n `Connection failed with status: ${response.status}`,\n response.status,\n );\n }\n }\n\n const json = JSON.parse(await response.text());\n this.eventEmitter.emit(\"configSetReceived\", json);\n return this;\n } catch (fetchError) {\n if (isFetchErrorFatal(fetchError)) {\n this.fatalError = true;\n throw new ConfigDirectorConnectionError(\n `Connection failed with fatal error: ${fetchError}. This is an unrecoverable error, retry attempts will be ignored.`,\n );\n } else if (fetchError instanceof SyntaxError) {\n throw new ConfigDirectorConnectionError(\n `Failed to parse the response from the server: ${fetchError}`,\n );\n } else {\n throw new ConfigDirectorConnectionError(`Connection failed with error: ${fetchError}.`);\n }\n }\n }\n\n private prepareFatalResponseStatusError(\n responseStatus: number,\n errorBody: string | undefined,\n ): ConfigDirectorConnectionError {\n const status = responseStatus ?? 0;\n const headline = `Connection failed with status: ${responseStatus ?? \"unknown\"}`;\n const serverBody = (errorBody?.trim()?.length ?? 0) > 0 ? ` (${errorBody})` : \"\";\n const message = `${headline}${serverBody}. This is an unrecoverable error, retry attempts will be ignored.`;\n return new ConfigDirectorConnectionError(message, status);\n }\n\n private isStatusFatal(status: number | undefined): boolean {\n return !!status && status >= 400 && status < 500;\n }\n\n public on<TName extends keyof TransportEvents>(\n name: TName,\n handler: (payload: TransportEvents[TName]) => void,\n ): void {\n this.eventEmitter.on(name, handler);\n }\n\n public off<TName extends keyof TransportEvents>(\n name: TName,\n handler?: ((payload: TransportEvents[TName]) => void) | undefined,\n ): void {\n this.eventEmitter.off(name, handler);\n }\n\n public clear(): void {\n this.eventEmitter.clear();\n }\n\n public close() {}\n\n public dispose(): void {\n this.close();\n this.clear();\n }\n}\n","import { ConfigType, ConfigValueType } from \"../types\";\nimport { DroppedEvents } from \"./types\";\n\nconst CONFIG_VALUE_MAX_LENGTH = 500;\n\nexport const sanitizeValue = <TV extends ConfigValueType>(value: TV, type?: ConfigType): string => {\n if (type === \"json\") {\n try {\n const json = JSON.stringify(value);\n return djb2Hash(json);\n } catch {\n return value.toString().slice(0, CONFIG_VALUE_MAX_LENGTH);\n }\n }\n\n return value.toString().slice(0, CONFIG_VALUE_MAX_LENGTH);\n};\n\nexport const djb2Hash = (data: string): string => {\n const hash = djb2(new TextEncoder().encode(data));\n return hash.toString(16).padStart(8, \"0\");\n};\n\nconst djb2 = (bytes: Uint8Array): number => {\n let hash = 5381;\n for (let i = 0; i < bytes.length; i++) {\n hash = (hash << 5) + hash + bytes[i];\n hash = hash >>> 0;\n }\n return hash;\n};\n\nexport const isEventListEmpty = <T extends Record<string | symbol, any[]>>(eventList: T): boolean => {\n const keys = Object.keys(eventList);\n if (keys.length == 0) {\n return true;\n }\n\n for (const key of keys) {\n if ((eventList[key]?.length ?? 0) > 0) {\n return false;\n }\n }\n\n return true;\n};\n\nexport const isDroppedEventsEmpty = (droppedEvents?: DroppedEvents): boolean => {\n if (!droppedEvents) {\n return true;\n }\n const keys = Object.keys(droppedEvents);\n if (keys.length == 0) {\n return true;\n }\n\n for (const key of keys) {\n if ((droppedEvents[key] ?? 0) > 0) {\n return false;\n }\n }\n\n return true;\n};\n","import { TelemetryEventCollectorOptions } from \"@shared/telemetry/TelemetryEventCollector\";\nimport { ConfigDirectorContext, ConfigDirectorLogger, ConfigValueType } from \"../types\";\nimport { EvaluatedConfigEvent } from \"./telemetry-events\";\nimport {\n TelemetryCloseEvent,\n TelemetryEvaluatedConfigEvent,\n TelemetryFlushEvent,\n TelemetryInitializeEvent,\n TelemetryUpdateContextEvent,\n TelemetryWorkerResponseEvent,\n} from \"./types\";\nimport { sanitizeValue } from \"@shared/telemetry/utils\";\n\nexport class TelemetryClient {\n private readonly logger: ConfigDirectorLogger;\n private worker: Worker;\n private closePromise: Promise<void> | undefined;\n private closeResolve: (() => void) | undefined;\n private readonly visibilityHandler: () => void;\n\n constructor(options: TelemetryEventCollectorOptions) {\n this.logger = options.logger;\n\n const initializeMessage: TelemetryInitializeEvent = {\n type: \"Initialize\",\n payload: {\n sdkKey: options.sdkKey,\n baseUrl: options.baseUrl.toString(),\n evaluationQueueLimit: options.evaluationQueueLimit ?? 1_000,\n initialFlushIntervalDelay: options.initialFlushIntervalDelay ?? 5_000,\n flushIntervalDelay: options.flushIntervalDelay ?? 30_000,\n },\n };\n this.worker = new Worker(new URL(\"./worker.ts\", import.meta.url), { type: \"module\" });\n this.worker.onmessage = (message: MessageEvent<TelemetryWorkerResponseEvent>) => {\n this.handleWorkerEvent(message.data);\n };\n this.worker.postMessage(initializeMessage);\n\n this.visibilityHandler = () => {\n if (document.visibilityState === \"hidden\") {\n this.flush();\n }\n };\n try {\n document.addEventListener(\"visibilitychange\", this.visibilityHandler);\n } catch (error) {\n this.logger.warn(\"[TelemetryEventCollector] Could not configure 'visibilitychange' listener: \", error);\n }\n }\n\n public async updateContext(value: ConfigDirectorContext | undefined) {\n const updateContextMessage: TelemetryUpdateContextEvent = {\n type: \"UpdateContext\",\n payload: {\n context: value,\n },\n };\n this.worker.postMessage(updateContextMessage);\n }\n\n public evaluatedConfig<T extends ConfigValueType>(event: EvaluatedConfigEvent<T>): void {\n const evaluatedConfigMessage: TelemetryEvaluatedConfigEvent = {\n type: \"EvaluatedConfigEvent\",\n payload: this.sanitizeEvaluatedConfigEvent(event),\n };\n this.worker.postMessage(evaluatedConfigMessage);\n }\n\n private sanitizeEvaluatedConfigEvent<T extends ConfigValueType>(\n event: EvaluatedConfigEvent<T>,\n ): EvaluatedConfigEvent<string> {\n return {\n ...event,\n defaultValue: sanitizeValue(event.defaultValue, event.type),\n evaluatedValue: sanitizeValue(event.evaluatedValue, event.type),\n };\n }\n\n private handleWorkerEvent(event: TelemetryWorkerResponseEvent) {\n if (event.type === \"Closed\") {\n this.closeResolve?.();\n return;\n }\n if (!event.payload?.level || !event.payload?.message) {\n return;\n }\n const { level, message, args } = event.payload;\n\n switch (level) {\n case \"debug\":\n this.logger.debug(message, ...args);\n break;\n case \"info\":\n this.logger.info(message, ...args);\n break;\n case \"warn\":\n this.logger.warn(message, ...args);\n break;\n case \"error\":\n this.logger.warn(message, ...args);\n break;\n }\n }\n\n private flush() {\n const flushMessage: TelemetryFlushEvent = {\n type: \"Flush\",\n };\n this.worker.postMessage(flushMessage);\n }\n\n public close(): Promise<void> {\n if (this.closePromise) {\n return this.closePromise;\n }\n\n return this.performClose();\n }\n\n private performClose(): Promise<void> {\n document.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n this.closePromise = new Promise<void>((resolve) => {\n this.closeResolve = resolve;\n const closeMessage: TelemetryCloseEvent = { type: \"Close\" };\n this.worker.postMessage(closeMessage);\n });\n return this.closePromise;\n }\n}\n","import { Emitter } from \"./Emitter\";\nimport { StreamingTransport } from \"./StreamingTransport\";\nimport { getRequestedType, parseConfigValue } from \"../../shared/src/value-parser\";\nimport {\n ConfigSet,\n ConfigState,\n ConfigStateMap,\n ConfigDirectorContext,\n ConfigDirectorClientOptions,\n ConfigDirectorClient,\n ClientEvents,\n WatchHandler,\n ConfigValueType,\n ConfigDirectorLogger,\n Transport,\n ClientConnectAction,\n IdentifyingSdkOptions,\n} from \"./types\";\nimport { createDefaultLogger } from \"./logger\";\nimport { ConfigDirectorValidationError } from \"./errors\";\nimport { PullTransport } from \"./PullTransport\";\nimport { TelemetryClient } from \"./telemetry/TelemetryClient\";\n\nconst defaultBaseUrl = new URL(\"https://client-sdk-api.configdirector.com\");\n\ntype WatchHandlerWithOptions<T extends ConfigValueType> = {\n handler: WatchHandler<T>;\n defaultValue: T;\n requestedType: string;\n};\n\nexport class DefaultConfigDirectorClient implements ConfigDirectorClient {\n private logger: ConfigDirectorLogger;\n private usageEventCollector: TelemetryClient;\n private configSet: ConfigSet | undefined;\n private handlersMap: Map<string, WatchHandlerWithOptions<any>[]> = new Map();\n private transport: Transport;\n private eventEmitter = new Emitter<ClientEvents>();\n private timeout: number;\n private ready = false;\n private readyPromise: Promise<void> | undefined;\n private readyResolve: (() => void) | undefined;\n private currentContext?: ConfigDirectorContext;\n private streaming: boolean;\n\n constructor(clientSdkKey: string, sdkOptions: IdentifyingSdkOptions, clientOptions?: ConfigDirectorClientOptions) {\n this.logger = clientOptions?.logger ?? createDefaultLogger();\n this.timeout = clientOptions?.connection?.timeout ?? 3_000;\n const baseUrl = this.parseUrl(clientOptions?.connection?.url) ?? defaultBaseUrl;\n this.streaming = clientOptions?.connection?.streaming === false ? false : true;\n const transportConstructor = this.streaming ? StreamingTransport : PullTransport;\n this.usageEventCollector = new TelemetryClient({\n sdkKey: clientSdkKey,\n logger: this.logger,\n baseUrl,\n });\n this.transport = new transportConstructor({\n clientSdkKey,\n baseUrl,\n metaContext: {\n ...clientOptions?.metadata,\n sdkName: sdkOptions.sdkName,\n sdkVersion: sdkOptions.sdkVersion,\n userAgent: navigator?.userAgent,\n },\n logger: this.logger,\n });\n\n this.transport.on(\"configSetReceived\", (configSet: ConfigSet) => {\n this.readyResolve?.();\n const configKeys = Object.keys(configSet.configs);\n if (!this.configSet || configSet.kind == \"full\") {\n this.configSet = configSet;\n this.eventEmitter.emit(\"configsUpdated\", { keys: configKeys });\n this.updateWatchers(configSet.configs);\n } else {\n this.configSet.configs = {\n ...this.configSet.configs,\n ...configSet.configs,\n };\n this.eventEmitter.emit(\"configsUpdated\", { keys: configKeys });\n this.updateWatchers(configSet.configs);\n }\n this.logger.debug(\"[ConfigDirectorClient] ConfigSet updated from server:\", { keys: configKeys });\n });\n }\n\n public async initialize(context?: ConfigDirectorContext) {\n await this.connectToTransport(context, \"initialization\");\n }\n\n public async updateContext(context: ConfigDirectorContext) {\n await this.connectToTransport(context, \"context update\");\n }\n\n private async connectToTransport(context: ConfigDirectorContext | undefined, caller: ClientConnectAction) {\n try {\n this.ready = false;\n this.readyPromise = new Promise<void>((resolve) => {\n this.readyResolve = resolve;\n }).then(() => {\n this.ready = true;\n this.eventEmitter.emit(\"clientReady\", { action: caller });\n this.logger.debug(\"[ConfigDirectorClient] Received initial payload from the server, client is ready\");\n });\n const startTime = new Date().getTime();\n await this.transport.connect(context ?? {}, this.timeout);\n this.currentContext = context;\n this.usageEventCollector.updateContext(context);\n const elapsedTime = (new Date().getTime() - startTime);\n const remainingTimeout = this.timeout - elapsedTime;\n if (remainingTimeout > 0) {\n await Promise.race([\n this.readyPromise,\n new Promise<void>((resolve) => {\n setTimeout(() => resolve(), remainingTimeout);\n }),\n ]);\n }\n if (!this.ready) {\n const warningDetails = this.streaming\n ? \"The client will continue to retry since there were no fatal errors detected. Configs will return the default value until the connection succeeds.\"\n : \"Since the client was configured without streaming, configs may not update and always return the default value.\";\n this.logger.warn(\n `[ConfigDirectorClient] Timed out waiting for ${caller} after ${this.timeout}ms. ${warningDetails}`,\n );\n }\n } catch (error) {\n this.logger.error(`[ConfigDirectorClient] An error occurred during ${caller}: `, error);\n }\n }\n\n private updateWatchers(configsMap: ConfigStateMap) {\n Object.values(configsMap).forEach((v) => this.updateWatchersForConfig(v));\n }\n\n private updateWatchersForConfig(configState: ConfigState) {\n this.handlersMap.get(configState.key)?.forEach((h) => {\n const value = this.getValueFromConfigState(configState.key, configState, h.defaultValue);\n h.handler(value);\n });\n }\n\n public watch<T extends ConfigValueType>(configKey: string, defaultValue: T, callback: WatchHandler<T>) {\n this.validateDefaultValue(defaultValue);\n\n const handlers = this.handlersMap.get(configKey);\n const handlerWithOptions = { handler: callback, defaultValue, requestedType: typeof defaultValue };\n if (handlers) {\n handlers.push(handlerWithOptions);\n } else {\n this.handlersMap.set(configKey, [handlerWithOptions]);\n }\n\n return () => this.unwatch(configKey, callback);\n }\n\n public unwatch<T extends ConfigValueType>(configKey: string, callback?: WatchHandler<T>) {\n const handlers = this.handlersMap.get(configKey);\n if (!handlers) {\n return;\n }\n\n if (callback) {\n const index = handlers.findIndex((h) => h.handler == callback);\n if (index >= 0) {\n handlers?.splice(index, 1);\n }\n } else {\n handlers.splice(0);\n }\n }\n\n public getValue<T extends ConfigValueType>(configKey: string, defaultValue: T): T {\n this.validateDefaultValue(defaultValue);\n\n const configState = this.configSet?.configs[configKey];\n return this.getValueFromConfigState(configKey, configState, defaultValue);\n }\n\n private getValueFromConfigState<T extends ConfigValueType>(\n configKey: string,\n configState: ConfigState | undefined,\n defaultValue: T,\n ): T {\n if (!configState) {\n this.logger.debug(\n `[ConfigDirectorClient] No config state found for '${configKey}', returning default value '${defaultValue}'`,\n );\n this.usageEventCollector.evaluatedConfig({\n contextId: this.currentContext?.id,\n key: configKey,\n defaultValue: defaultValue,\n requestedType: getRequestedType(defaultValue),\n evaluatedValue: defaultValue,\n usedDefault: true,\n evaluationReason: \"config-state-missing\",\n });\n return defaultValue;\n }\n\n const parseResult = parseConfigValue<T>(configState, defaultValue);\n this.usageEventCollector.evaluatedConfig({\n contextId: this.currentContext?.id,\n key: configKey,\n defaultValue: defaultValue,\n requestedType: parseResult.requestedType,\n evaluatedValue: parseResult.parsedValue,\n usedDefault: parseResult.usedDefault,\n evaluationReason: parseResult.reason,\n });\n this.logger.debug(`[ConfigDirectorClient] Evaluated '${configKey}' to '${parseResult.parsedValue}'`);\n return parseResult.parsedValue;\n }\n\n private parseUrl(url: string | undefined): URL | undefined {\n if (!url) {\n return;\n }\n\n try {\n return new URL(url);\n } catch (error) {\n throw new ConfigDirectorValidationError(`Invalid base URL '${url}'. Parsing failed: ${error}`);\n }\n }\n\n private validateDefaultValue<T extends ConfigValueType>(defaultValue: T) {\n if (defaultValue === undefined || defaultValue === null) {\n throw new ConfigDirectorValidationError(\n \"Invalid default value. The default value for a config must be defined and non-null.\",\n );\n }\n\n if (typeof defaultValue === \"function\") {\n throw new ConfigDirectorValidationError(\n \"Invalid default value. The default value for a config cannot be a function.\",\n );\n }\n }\n\n public get isReady(): boolean {\n return this.ready;\n }\n\n public on<T extends keyof ClientEvents>(eventName: T, handler: (event: ClientEvents[T]) => void): void {\n this.eventEmitter.on(eventName, handler);\n }\n\n public off<T extends keyof ClientEvents>(eventName: T, handler?: (payload: ClientEvents[T]) => void) {\n this.eventEmitter.off(eventName, handler);\n }\n\n public clear() {\n this.logger.debug(\"[ConfigDirectorClient] clear() has been called, removing all observers\");\n this.eventEmitter.clear();\n this.handlersMap.clear();\n }\n\n public unwatchAll() {\n this.handlersMap.clear();\n }\n\n public close() {\n this.logger.debug(\"[ConfigDirectorClient] close() has been called, closing connection to server\");\n this.transport.close();\n this.ready = false;\n }\n\n public dispose() {\n this.clear();\n this.close();\n }\n}\n","import {\n ConfigDirectorClient,\n ConfigDirectorClientOptions,\n DefaultConfigDirectorClient,\n} from \"@js-client-core/index\";\n\nexport const createClient = (\n clientSdkKey: string,\n clientOptions?: ConfigDirectorClientOptions,\n): ConfigDirectorClient => {\n return new DefaultConfigDirectorClient(\n clientSdkKey,\n { sdkName: \"react-web-sdk\", sdkVersion: \"__VERSION__\" },\n clientOptions,\n );\n};\n\n","import React from \"react\";\nimport { ConfigDirectorContextData } from \"./types\";\n\nconst createReactContext = () => React.createContext<ConfigDirectorContextData>({status: \"loading\"});\nexport const reactContext = createReactContext();\n","import {\n type ConfigDirectorLoggingLevel,\n createDefaultLogger as createJsSdkLogger,\n ConfigDirectorLogMessageDecorator,\n ConfigDirectorLogger,\n} from \"@js-client-core/index\";\n\nclass MessageDecorator implements ConfigDirectorLogMessageDecorator {\n decorateMessage(message: string): string {\n return `[ConfigDirector:react-web-sdk] ${message}`;\n }\n}\n\nexport const createConsoleLogger = (level: ConfigDirectorLoggingLevel): ConfigDirectorLogger => {\n return createJsSdkLogger(level, new MessageDecorator());\n};\n","import { createClient } from \"./client\";\nimport { useEffect, useState, type ReactNode } from \"react\";\nimport { reactContext } from \"./context\";\nimport { createConsoleLogger } from \"./logger\";\nimport { ConfigDirectorProviderOptions, ConfigDirectorProviderState } from \"./types\";\n\nexport const withProvider = async (options: ConfigDirectorProviderOptions) => {\n const logger = options.logger ?? createConsoleLogger(\"debug\");\n const client = createClient(options.sdkKey, {\n connection: { url: options.url, timeout: options.timeout },\n metadata: { appName: options.appName, appVersion: options.appVersion },\n logger: logger,\n });\n await client.initialize(options.context);\n\n const ConfigDirectorProvider = ({ children }: { children: ReactNode }) => {\n const [data, setData] = useState<ConfigDirectorProviderState>(() => ({\n client,\n status: client.isReady ? \"ready\" : \"default\",\n }));\n\n useEffect(() => {\n client.on(\"configsUpdated\", () => {\n setData((prevState) => ({ ...prevState, updatedAt: new Date() }));\n });\n client.on(\"clientReady\", () => {\n setData((prevState) => ({ ...prevState, status: \"ready\" }));\n });\n });\n\n return <reactContext.Provider value={data}>{children}</reactContext.Provider>;\n };\n\n return ConfigDirectorProvider;\n};\n","import { createClient } from \"./client\";\nimport { reactContext } from \"./context\";\nimport { createConsoleLogger } from \"./logger\";\nimport { Component, type PropsWithChildren } from \"react\";\nimport { ConfigDirectorProviderOptions, ConfigDirectorProviderState } from \"./types\";\n\nexport class ConfigDirectorProvider extends Component<\n PropsWithChildren<ConfigDirectorProviderOptions>,\n ConfigDirectorProviderState\n> {\n constructor(props: ConfigDirectorProviderOptions) {\n super(props);\n\n const client = createClient(props.sdkKey, {\n connection: { url: props.url, timeout: props.timeout },\n metadata: { appName: props.appName, appVersion: props.appVersion },\n logger: props.logger ?? createConsoleLogger(\"warn\"),\n });\n\n this.state = { client, status: \"loading\" };\n }\n\n override async componentDidMount(): Promise<void> {\n this.state.client?.on(\"configsUpdated\", () => {\n this.setState({ updatedAt: new Date() });\n });\n this.state.client?.on(\"clientReady\", () => {\n this.setState({ status: \"ready\" });\n });\n await this.state.client?.initialize(this.props.context);\n if (!this.state.client?.isReady) {\n this.setState({ status: \"default\" });\n }\n }\n\n override componentWillUnmount(): void {\n this.state.client?.dispose();\n }\n\n override render() {\n return <reactContext.Provider value={this.state}>{this.props.children}</reactContext.Provider>;\n }\n}\n","export class ConfigDirectorReactContextError extends Error {\n public override readonly name: string = \"ConfigDirectorReactContextError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, ConfigDirectorReactContextError.prototype);\n }\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { reactContext } from \"./context\";\nimport type {\n ConfigDirectorContext,\n ConfigValueType,\n} from \"@js-client-core/index\";\nimport { ConfigDirectorReactContextError } from \"./errors\";\nimport { ClientStatus } from \"./types\";\n\nconst noContextError = () => {\n return new ConfigDirectorReactContextError(\"The ConfigDirector client was not found in the React context. Please make sure the component using this hook is inside the context of a ConfigDirectorProvider.\");\n};\n\nconst useConfigValue = <T extends ConfigValueType>(\n key: string,\n defaultValue: T,\n): {\n value: T;\n readyStatus: ClientStatus;\n loading: boolean;\n} => {\n const configDirectorReactContext = useContext(reactContext);\n if (!configDirectorReactContext?.client) {\n throw noContextError();\n }\n\n const value = configDirectorReactContext.client.getValue(key, defaultValue);\n\n return { value, readyStatus: configDirectorReactContext.status, loading: configDirectorReactContext.status === \"loading\" };\n};\n\nconst useConfigDirectorContext = () => {\n const configDirectorReactContext = useContext(reactContext);\n if (!configDirectorReactContext?.client) {\n throw noContextError();\n }\n\n const updateContext = async (context: ConfigDirectorContext) => {\n await configDirectorReactContext.client?.updateContext(context);\n };\n\n return { updateContext };\n};\n\nconst useConfigDirectorClient = () => {\n const configDirectorReactContext = useContext(reactContext);\n if (!configDirectorReactContext?.client) {\n throw noContextError();\n }\n\n return { client: configDirectorReactContext.client };\n};\n\nexport { useConfigValue, useConfigDirectorContext, useConfigDirectorClient };\n"],"mappings":"0HAaA,IAAa,EAAb,KAAiG,eAC/F,KAAQ,WAAsE,IAAI,IAElF,GAAsC,EAAa,EAAwC,CACzF,IAAM,EAAW,KAAK,WAAW,IAAI,EAAK,CACtC,EACF,EAAS,KAAK,EAAQ,CAEtB,KAAK,WAAW,IAAI,EAAM,CAAC,EAAQ,CAAC,CAIxC,KAAwC,EAAa,EAAwC,CAE3F,IAAM,EAAO,KACb,SAAS,EAAY,EAA6C,CAChE,EAAK,IAAI,EAAM,EAAY,CAC3B,EAAQ,MAAM,EAAM,EAAQ,CAE9B,KAAK,GAAG,EAAM,EAAY,CAG5B,IAAuC,EAAa,EAAyC,CAC3F,IAAM,EAAW,KAAK,WAAW,IAAI,EAAK,CACrC,KAIL,GAAI,EAAS,CACX,IAAM,EAAgB,EAAS,QAAQ,EAAQ,CAC3C,GAAiB,GACnB,EAAS,OAAO,EAAe,EAAE,MAGnC,KAAK,WAAW,IAAI,EAAM,EAAE,CAAC,CAIjC,OAAQ,CACN,KAAK,WAAW,OAAO,CAGzB,KAAwC,EAAa,EAA+B,CAClF,IAAM,EAAW,KAAK,WAAW,IAAI,EAAK,CACrC,GAIL,EAAS,OAAO,CAAC,IAAK,GAAM,EAAE,EAAQ,CAAC,GC7D9B,EAAb,MAAa,UAAsC,KAAM,CAIvD,YAAY,EAAiB,EAAiB,CAC5C,MAAM,EAAQ,CAJhB,KAAyB,KAAe,gCAKtC,KAAK,OAAS,EAEd,OAAO,eAAe,KAAM,EAA8B,UAAU,GAI3D,EAAb,MAAa,UAAsC,KAAM,CAGvD,YAAY,EAAiB,CAC3B,MAAM,EAAQ,CAHhB,KAAyB,KAAe,gCAKtC,OAAO,eAAe,KAAM,EAA8B,UAAU,GChBxE,MAAa,EAAqB,GAA6B,CAC7D,GAAI,aAAsB,iBACP,EACJ,OAAS,kBACpB,MAAO,WAEA,aAAsB,UAC/B,MAAO,GAGT,MAAO,ICZT,IAAa,EAAb,MAAa,UAA0B,KAAM,CAG3C,YAAY,EAAiB,CAC3B,MAAM,EAAQ,CAHhB,KAAyB,KAAe,oBAKtC,OAAO,eAAe,KAAM,EAAkB,UAAU,GAI/C,EAAb,MAAa,UAAiC,KAAM,CAGlD,YAAY,EAAiB,CAC3B,MAAM,EAAQ,CAHhB,KAAyB,KAAe,2BAKtC,OAAO,eAAe,KAAM,EAAyB,UAAU,GAItD,EAAb,MAAa,UAA2B,KAAM,CAG5C,YAAY,EAAiB,CAC3B,MAAM,EAAQ,CAHhB,KAAyB,KAAe,qBAKtC,OAAO,eAAe,KAAM,EAAmB,UAAU,GAIhD,EAAb,MAAa,UAA6B,KAAM,CAG9C,YAAY,EAAiB,CAC3B,MAAM,EAAQ,CAHhB,KAAyB,KAAe,uBAKtC,OAAO,eAAe,KAAM,EAAqB,UAAU,gvCCxB/D,IAAa,EAAb,KAA+B,CAS7B,YAAY,EAAmC,OAR/C,KAAQ,aAAe,GACvB,KAAQ,uBAAyB,GAQ/B,KAAK,aAAe,CAClB,KAAM,GACP,CACD,KAAK,SAAA,EAAU,EAAQ,UAAA,UAAkB,IAAlB,EACvB,KAAK,QAAU,EAAQ,QACvB,KAAK,UAAY,EAAQ,UAG3B,MAAa,EAAe,CAC1B,IAAM,EAAQ,KAAK,aAAa,EAAM,CAChC,EAAQ,KAAK,WAAW,EAAM,CACpC,IAAK,IAAM,KAAQ,EACjB,KAAK,oBAAoB,EAAK,CAIlC,QAAgB,CACV,KAAK,yBAA2B,IAClC,KAAK,oBAAoB,KAAK,uBAAuB,CAIzD,oBAA4B,EAAc,CACxC,GAAI,EAAK,WAAW,IAAI,CAAE,QACxB,EAAA,KAAK,YAAA,MAAA,EAAA,KAAA,KAAY,KAAK,iBAAiB,EAAG,EAAK,CAAC,CAChD,OAGF,GAAI,IAAS,GAAI,CACf,KAAK,cAAc,CACnB,OAGF,IAAM,EAAU,KAAK,iBAAiB,EAAK,CAC3C,KAAK,eAAe,EAAQ,CAG9B,cAAuB,CACrB,IAAM,EAAO,KAAK,aAAa,KAAK,SAAS;EAAK,CAC9C,KAAK,aAAa,KAAK,MAAM,EAAG,GAAG,CACnC,KAAK,aAAa,KAElB,GACF,KAAK,QAAA,EAAA,EAAA,EAAA,CACA,KAAK,aAAA,CAAA,EAAA,CAAA,CACR,GAAI,KAAK,YACT,QACD,CAAC,CAEJ,KAAK,aAAe,CAClB,KAAM,GACP,CAGH,eAAuB,EAAsB,CAC3C,OAAQ,EAAQ,MAAhB,CACE,IAAK,QACH,KAAK,aAAa,KAAO,EAAQ,MACjC,MACF,IAAK,OACH,KAAK,aAAa,MAAQ,EAAQ,MAAQ;EAC1C,MACF,IAAK,KACE,EAAQ,MAAM,SAAS,KAAK,GAC/B,KAAK,YAAc,EAAQ,OAE7B,MACF,IAAK,QACH,GAAI,QAAQ,KAAK,EAAQ,MAAM,CAAE,QAC/B,EAAA,KAAK,UAAA,MAAA,EAAA,KAAA,KAAU,OAAO,SAAS,EAAQ,MAAO,GAAG,CAAC,CAEpD,MAEF,QACE,OAIN,iBAAyB,EAA2B,CAClD,IAAM,EAAiB,EAAK,QAAQ,IAAI,CAKxC,OAJI,IAAmB,GACd,CAAE,MAAO,EAAM,MAAO,GAAI,CAG5B,CAAE,MAAO,EAAK,MAAM,EAAG,EAAe,CAAE,MAAO,KAAK,iBAAiB,EAAgB,EAAK,CAAE,CAGrG,WAAmB,EAAe,OAChC,IAAM,EAAQ,EAAM,MAAM,aAAa,CAEvC,MADA,MAAK,wBAAA,EAAyB,EAAM,KAAK,GAAA,KAAI,GAAJ,EAClC,EAGT,iBAAyB,EAAwB,EAAsB,CACrE,GAAI,IAAmB,GACrB,MAAO,GAGT,IAAM,EAAkB,EAAK,EAAiB,KAAO,IAAM,EAAiB,EAAI,EAAiB,EACjG,OAAO,EAAK,MAAM,EAAgB,CAGpC,aAAqB,EAAe,CAKhC,OAJE,KAAK,cACP,KAAK,aAAe,GACb,KAAK,uBAAyB,EAAM,QAAQ,gBAAiB,GAAG,CAAC,QAAQ,UAAW,GAAG,EAEvF,KAAK,uBAAyB,IC1H3C,IAAY,EAAL,SAAA,EAAA,OACL,GAAA,KAAA,OACA,EAAA,OAAA,SACA,EAAA,WAAA,mBACD,CCID,IAAa,EAAb,KAA+B,CAoB7B,YAAY,EAAmC,OAnB/C,KAAiB,6BAAiC,GAClD,KAAiB,sCAA0C,KAAK,uBAKhE,KAAQ,iBAA2B,EACnC,KAAQ,gBAAmC,IAAI,gBAE/C,KAAQ,YAA0B,EAAW,OAC7C,KAAQ,uBAAiC,IAUvC,KAAK,IAAM,IAAI,IAAI,EAAQ,IAAI,CAC/B,KAAK,YAAc,EAAQ,YAC3B,KAAK,QAAA,EAAA,CACH,OAAQ,oBAAA,CACL,EAAQ,QACZ,CACD,KAAK,eAAiB,CACpB,KAAM,EAAQ,KACd,QAAA,EAAQ,EAAQ,SAAA,KAAU,MAAV,EAChB,KAAM,EAAQ,KACd,YAAa,EAAQ,YACrB,SAAU,EAAQ,SAClB,SAAU,EAAQ,SAClB,eAAgB,EAAQ,eACzB,CACD,KAAK,SAAW,KAAK,2BAA2B,EAAQ,QAAS,UAAU,CAC3E,KAAK,WAAa,KAAK,2BAA2B,EAAQ,UAAW,YAAY,CACjF,KAAK,cAAgB,KAAK,2BAA2B,EAAQ,aAAc,eAAe,CAC1F,KAAK,WAAa,KAAK,2BAA2B,EAAQ,UAAW,YAAY,CACjF,KAAK,WAAa,KAAK,2BAA2B,EAAQ,UAAW,YAAY,CACjF,KAAK,iBAAmB,KAAK,uBAC3B,EAAQ,gBACR,KAAK,yBACL,kBACD,CACD,KAAK,yBAA2B,KAAK,uBACnC,EAAQ,wBACR,KAAK,kCACL,0BACD,CAGH,IAAW,QAAQ,EAA+B,CAChD,KAAK,SAAW,KAAK,2BAA2B,EAAO,UAAU,CAGnE,IAAW,UAAU,EAAkC,CACrD,KAAK,WAAa,KAAK,2BAA2B,EAAO,YAAY,CAGvE,IAAW,UAAU,EAAkC,CACrD,KAAK,WAAa,KAAK,2BAA2B,EAAO,YAAY,CAGvE,IAAW,UAAU,EAAmB,CACtC,KAAK,WAAa,KAAK,2BAA2B,EAAO,YAAY,CAGvE,IAAW,aAAa,EAAmB,CACzC,KAAK,cAAgB,KAAK,2BAA2B,EAAO,eAAe,CAG7E,IAAW,gBAAgB,EAA8C,CACvE,KAAK,iBAAmB,KAAK,uBAC3B,EACA,KAAK,yBACL,kBACD,CAGH,IAAW,wBAAwB,EAA6C,CAC9E,KAAK,yBAA2B,KAAK,uBACnC,EACA,KAAK,kCACL,kBACD,CAGH,IAAW,YAAyB,CAClC,OAAO,KAAK,YAGd,SAAiB,CACX,KAAK,cAAgB,EAAW,SAIpC,KAAK,iBAAmB,EACxB,KAAK,oBAAoB,EAG3B,oBAA6B,CAC3B,KAAK,gBAAkB,IAAI,gBAC3B,KAAK,YAAc,EAAW,WAC9B,MAAM,KAAK,IAAA,EAAA,EAAA,EAAA,CACN,KAAK,eAAA,CAAA,EAAA,CAAA,CACR,QAAS,KAAK,cAAc,CAC5B,OAAQ,KAAK,gBAAgB,OAC7B,MAAO,YACR,CAAC,CACC,KAAK,KAAK,oBAAoB,KAAK,KAAK,CAAC,CACzC,MAAO,GAAiB,CACvB,GAAI,EAAM,OAAS,cAAgB,KAAK,gBAAgB,OAAO,QAAS,CACtE,KAAK,OAAO,CACZ,OAGF,KAAK,SAAS,EAAM,CACpB,KAAK,kBAAkB,CAAE,QAAO,CAAC,EACjC,CAGN,OAAe,CACb,aAAa,KAAK,iBAAiB,CACnC,KAAK,YAAc,EAAW,OAC9B,KAAK,gBAAgB,OAAO,CAG9B,cAAuB,CACrB,aAAa,KAAK,iBAAiB,CACnC,KAAK,YAAc,EAAW,OAC9B,KAAK,eAAe,CAGtB,cAA+C,CAC7C,IAAM,EAAoB,KAAK,YAAc,CAAE,gBAAiB,KAAK,YAAa,CAAG,IAAA,GACrF,OAAA,EAAA,EAAA,EAAA,CACK,KAAK,QAAA,CACL,EACJ,CAGH,MAAc,oBAAoB,EAAoB,YACpD,GAAM,CAAE,OAAM,UAAW,EAEzB,GAAI,IAAW,IAAK,CAClB,EAAK,cAAc,CACnB,OAGF,GAAI,GAAU,IAAK,CACjB,EAAK,kBAAkB,CAAE,SAAQ,CAAC,CAClC,OAGF,GAAI,CAAC,EACH,MAAM,IAAI,EAAyB,0CAA0C,CAG/E,EAAK,YAAc,EAAW,KAC9B,EAAK,YAAY,CACjB,EAAK,iBAAmB,EAGxB,IAAM,GAAA,GAAA,KAAA,IAAA,GADS,EAAM,YAAY,IAAI,kBAAoB,EACnC,WAAW,CAC3B,EAAS,IAAI,EAAkB,CACnC,QAAU,GAAU,CACd,OAAO,EAAM,IAAO,WACtB,EAAK,YAAc,EAAM,IAE3B,EAAK,WAAW,EAAM,EAExB,UAAY,GAAYA,EAAK,WAAW,EAAQ,CAChD,QAAU,GAAgB,EAAK,uBAAyB,EACzD,CAAC,CAEE,EAAO,GACX,KAAO,CAAC,GAAM,CACZ,GAAM,CAAE,KAAM,EAAY,SAAU,MAAM,EAAO,MAAM,CACnD,GACF,EAAO,MAAM,EAAM,CAGrB,EAAO,EAGT,EAAO,QAAQ,CACf,EAAK,kBAAkB,CAAE,SAAQ,MAAO,IAAI,EAAkB,wCAAwC,CAAE,CAAC,CAG3G,kBAA0B,EAA2C,CACnE,GAAI,KAAK,gBAAgB,OAAO,QAC9B,OAGF,aAAa,KAAK,iBAAiB,CACnC,KAAK,kBAAoB,EACzB,IAAM,EAAoB,CACxB,QAAS,KAAK,iBACd,OAAQ,EAAM,OACd,MAAO,EAAM,MACb,uBAAwB,KAAK,uBAC9B,CACD,GAAI,KAAK,iBAAiB,EAAkB,CAAE,CAC5C,KAAK,YAAc,EAAW,WAC9B,IAAI,EAAQ,KAAK,yBAAyB,EAAkB,EACxD,CAAC,OAAO,SAAS,EAAM,EAAI,EAAQ,GAAK,EAAQ,IAAQ,GAAK,MAC/D,KAAK,SACH,IAAI,EACF,mDAAmD,EAAM,kBAAkB,KAAK,yBACjF,CACF,CACD,EAAQ,KAAK,wBAEf,KAAK,iBAAmB,eAAiB,KAAK,oBAAoB,CAAE,EAAM,KACrE,CACL,KAAK,cAAc,CACnB,QAIJ,2BAAmC,EAAW,EAAqC,CACjF,OAAO,KAAK,uBAAuB,MAAY,GAAI,EAAK,CAG1D,uBACE,EACA,EACA,EACuB,CACvB,GAAI,GAAQ,KACV,OAAO,KACE,OAAO,GAAS,WACzB,OAAO,EAEP,MAAM,IAAI,EAAmB,GAAG,EAAK,qBAAqB,GCxPhE,MAAa,EAA2B,GAC/B,IAAI,EAAkB,EAAQ,CCQvC,IAAa,EAAb,KAAqD,CAMnD,YAAY,EAA4C,CAA3B,KAAA,QAAA,EAH7B,KAAQ,aAAe,IAAI,EAIzB,KAAK,QAAU,EACf,KAAK,OAAS,EAAQ,OACtB,KAAK,IAAM,IAAI,IAAI,gBAAiB,EAAQ,QAAQ,CAGtD,MAAa,QAAQ,EAAgC,EAAgC,YAC/EC,EAAK,aACP,EAAK,OAAO,CAGd,IAAM,EAAqB,IAAI,SAAe,EAAS,IAAW,CAChE,EAAK,YAAc,EAAwB,CACzC,IAAKA,EAAK,IACV,OAAQ,OACR,QAAS,CAAE,eAAgB,mBAAoB,CAC/C,KAAM,KAAK,UAAU,CACnB,aAAc,EACd,YAAaA,EAAK,QAAQ,YAC1B,aAAcA,EAAK,QAAQ,aAC5B,CAAC,CAEF,WAAY,CAAE,UAAW,CACvB,EAAK,gBAAgB,EAAK,EAE5B,cAAiB,CACf,EAAK,OAAO,MAAM,mCAAmC,CACrD,EAAQA,EAAK,EAEf,gBAAkB,GAAU,CAC1B,IAAM,EAAY,CAACA,EAAK,cAAc,EAAM,OAAO,CAInD,OAHK,GACH,EAAOA,EAAK,kBAAkB,EAAM,OAAQ,EAAM,MAAM,CAAC,CAEpD,GAET,wBAA0B,GAAU,CAClC,IAAM,EAAQ,IAAQ,EAAM,QAE5B,OADA,EAAK,OAAO,KAAK,kDAAkD,EAAM,KAAK,CACvE,GAET,iBAAoB,CAClB,EAAK,OAAO,MAAM,sCAAsC,EAE3D,CAAC,CACF,EAAK,YAAY,SAAS,EAC1B,CACF,OAAO,QAAQ,KAAK,CAClB,EACA,IAAI,QAAe,GAAY,CAC7B,eAAiB,EAAQA,EAAK,CAAE,EAAQ,EACxC,CACH,CAAC,CAGJ,gBAAwB,EAAc,CACpC,GAAI,CACF,IAAM,EAAO,KAAK,MAAM,EAAK,CAC7B,KAAK,aAAa,KAAK,oBAAqB,EAAK,OAC1C,EAAO,CACd,KAAK,OAAO,MAAM,4EAA6E,EAAM,EAIzG,kBACE,EACA,EAC+B,CAC/B,IAAM,EAAS,GAAA,KAAkB,EAAlB,EAIf,OAAO,IAAI,EADK,GAFC,kCAAkC,GAAA,KAAkB,UAAlB,EAA4B,KAC7D,EAAQ,WAAW,IAAU,GACP,kEACU,EAAO,CAG3D,cAAsB,EAAqC,CACzD,MAAO,CAAC,CAAC,GAAU,GAAU,KAAO,EAAS,IAG/C,GACE,EACA,EACM,CACN,KAAK,aAAa,GAAG,EAAM,EAAQ,CAGrC,IACE,EACA,EACM,CACN,KAAK,aAAa,IAAI,EAAM,EAAQ,CAGtC,OAAqB,CACnB,KAAK,aAAa,OAAO,CAG3B,OAAe,QACb,EAAA,KAAK,cAAA,MAAA,EAAa,OAAO,CAG3B,SAAuB,CACrB,KAAK,OAAO,CACZ,KAAK,OAAO,GCtGhB,MAAa,EAA+C,GAA4B,CACtF,IAAM,EAAW,OAAO,EACxB,GAAI,IAAa,SACf,GAAI,SACF,OAAA,GAAA,EAAQ,EAAwB,cAAA,KAAA,IAAA,GAAA,EAAa,OAAA,KAAQ,EAAR,UACvC,CACN,OAAO,UAEA,IAAa,WACtB,GAAI,CACF,IAAM,EAAgB,EAAqB,KAC3C,OAAO,EAAe,aAAa,IAAiB,UAC9C,CACN,OAAO,EAGX,OAAO,GAGH,EAAuB,GACpB,IAAkB,UAAY,IAAkB,SAG5C,GACX,EACA,IACmB,CACnB,IAAM,EAAQ,EAAY,MACpB,EAAgB,EAAiB,EAAa,CAEpD,GAAI,CAAC,EACH,MAAO,CACL,YAAa,EACb,gBACA,YAAa,GACb,OAAQ,gBACT,CAGH,GAAI,OAAO,GAAiB,SAC1B,MAAO,CACL,YAAa,EACb,gBACA,YAAa,GACb,OAAQ,cACT,CAGH,GAAI,OAAO,GAAiB,WAAa,EAAY,OAAS,UAAW,CACvE,IAAM,EAAY,EAAmB,EAAM,CACrC,EAAa,OAAO,GAAc,UACxC,MAAO,CACL,YAAc,EAAa,EAAY,EACvC,gBACA,YAAa,CAAC,EACd,OAAQ,EAAa,cAAgB,kBACtC,CAGH,GAAI,EAAoB,OAAO,EAAa,EAAI,EAAY,OAAS,UAAW,CAC9E,IAAM,EAAW,EAAmB,EAAM,CACpC,EAAY,OAAO,GAAa,SACtC,MAAO,CACL,YAAc,EAAY,EAAW,EACrC,gBACA,YAAa,CAAC,EACd,OAAQ,EAAY,cAAgB,iBACrC,CAEH,GAAI,EAAoB,OAAO,EAAa,GAAK,EAAY,OAAS,SAAW,EAAY,OAAS,QAAU,CAC9G,IAAM,EAAW,EAAiB,EAAM,CAClC,EAAY,OAAO,GAAa,SACtC,MAAO,CACL,YAAc,EAAY,EAAW,EACrC,gBACA,YAAa,CAAC,EACd,OAAQ,EAAY,cAAgB,iBACrC,CAGH,MAAO,CACL,YAAa,EACb,gBACA,YAAa,GACb,OAAQ,cACT,EAGG,EAAsB,GAAuC,CACjE,GAAI,CAAC,EACH,OAEF,IAAM,EAAa,EAAM,aAAa,CAClC,QAAc,QAAU,GAAc,SAG1C,OAAO,IAAe,QAGlB,EAAsB,GAAsC,CAChE,GAAI,CAAC,EACH,OAEF,IAAM,EAAM,OAAO,SAAS,EAAM,CAC9B,WAAM,EAAI,EAAI,CAAC,SAAS,EAAI,EAGhC,OAAO,GAGH,EAAoB,GAAsC,CAC9D,GAAI,CAAC,EACH,OAEF,IAAM,EAAM,OAAO,WAAW,EAAM,CAChC,WAAM,EAAI,EAAI,CAAC,SAAS,EAAI,EAGhC,OAAO,GCvIH,EAAqD,CACzD,IAAK,GACL,MAAO,EACP,KAAM,EACN,KAAM,EACN,MAAO,EACR,CAEK,MAA2B,CAC/B,IAAM,EAA0C,CAC9C,KAAM,UACN,MAAO,UACP,IAAK,UACL,KAAM,UACN,OAAQ,UACR,OAAQ,UACR,aAAc,QACf,CAED,GAAI,CACF,OAAO,IAAI,KAAK,eACd,IAAA,GAAA,EAAA,EAAA,EAAA,CACK,EAAA,CAAA,EAAA,CAAA,CAAa,uBAAwB,EAAA,CAAG,CAC9C,SACK,CACN,OAAO,IAAI,KAAK,eAAe,IAAA,GAAW,EAAY,GAI1D,IAAa,EAAb,KAAkE,CAGhE,YAAY,EAAoD,EAA+D,CAAlG,KAAA,MAAA,EAAoD,KAAA,UAAA,EAC/E,KAAK,MAAQ,EACb,KAAK,UAAY,EACjB,KAAK,cAAgB,GAAoB,CAG3C,MAAM,EAAiB,GAAG,EAAiB,CACzC,KAAK,IAAI,QAAQ,MAAO,QAAS,EAAS,GAAG,EAAK,CAGpD,KAAK,EAAiB,GAAG,EAAiB,CACxC,KAAK,IAAI,QAAQ,KAAM,OAAQ,EAAS,GAAG,EAAK,CAGlD,KAAK,EAAiB,GAAG,EAAiB,CACxC,KAAK,IAAI,QAAQ,KAAM,OAAQ,EAAS,GAAG,EAAK,CAGlD,MAAM,EAAiB,GAAG,EAAiB,CACzC,KAAK,IAAI,QAAQ,MAAO,QAAS,EAAS,GAAG,EAAK,CAGpD,IAAY,EAAwC,EAAmC,EAAiB,GAAG,EAAW,CACpH,GAAI,EAAO,KAAK,QAAU,EAAO,GAAQ,OACvC,EAAe,IAAI,KAAK,cAAc,OAAO,IAAI,KAAO,CAAC,KAAA,EAAI,KAAK,YAAA,KAAA,IAAA,GAAA,EAAW,gBAAgB,EAAQ,GAAI,GAAG,EAAK,ICtDjH,EAAN,KAAuE,CACrE,gBAAgB,EAAyB,CACvC,MAAO,kCAAkC,MAI7C,MAAa,GACX,EACA,IAEO,IAAI,EAAqB,GAAA,KAAS,OAAT,EAAiB,GAAA,KAAoB,IAAI,EAAxB,EAA8C,CCZpF,EAAmB,MAC9B,EACA,EACA,EACA,IACG,CACH,IAAM,EAAkB,IAAI,gBACtB,EAAiB,eAAiB,CACtC,EAAO,MAAM,uDAAuD,CACpE,EAAgB,OAAO,EACtB,EAAQ,CAEX,GAAI,CACF,IAAM,EAAW,MAAM,MAAM,EAAA,EAAA,EAAA,EAAA,CACxB,EAAA,CAAA,EAAA,CAAA,CACH,OAAQ,EAAgB,OAAA,CACzB,CAAC,CAEF,OADA,aAAa,EAAe,CACrB,QACA,EAAO,CAGd,MAFA,EAAO,KAAK,mCAAoC,EAAM,CACtD,aAAa,EAAe,CACtB,ICbV,IAAa,EAAb,KAAgD,CAM9C,YAAY,EAA4C,CAA3B,KAAA,QAAA,EAJ7B,KAAQ,aAAe,IAAI,EAE3B,KAAQ,WAAa,GAGnB,KAAK,QAAU,EACf,KAAK,OAAS,EAAQ,OACtB,KAAK,IAAM,IAAI,IAAI,iBAAkB,EAAQ,QAAQ,CAGvD,MAAa,QAAQ,EAAgC,EAAgC,YACnF,GAAIC,EAAK,WAIP,OAHA,EAAK,OAAO,KACV,wFACD,CACMA,EAGT,GAAI,CACF,IAAM,EAAW,MAAM,EAAiB,EAASA,EAAK,IAAK,CACzD,OAAQ,OACR,QAAS,CAAE,eAAgB,mBAAoB,CAC/C,KAAM,KAAK,UAAU,CACnB,aAAc,EACd,YAAaA,EAAK,QAAQ,YAC1B,aAAcA,EAAK,QAAQ,aAC5B,CAAC,CACH,CAAEA,EAAK,OAAO,CAEf,GAAI,CAAC,EAAS,GAKV,MAJEA,EAAK,cAAc,EAAS,OAAO,EACrC,EAAK,WAAa,GACZA,EAAK,gCAAgC,EAAS,OAAQ,MAAM,EAAS,MAAM,CAAC,EAE5E,IAAI,EACR,kCAAkC,EAAS,SAC3C,EAAS,OACV,CAIL,IAAM,EAAO,KAAK,MAAM,MAAM,EAAS,MAAM,CAAC,CAE9C,OADA,EAAK,aAAa,KAAK,oBAAqB,EAAK,CAC1CA,QACA,EAAY,CAWjB,MAVE,EAAkB,EAAW,EAC/B,EAAK,WAAa,GACZ,IAAI,EACR,uCAAuC,EAAW,mEACnD,EACQ,aAAsB,YACzB,IAAI,EACR,iDAAiD,IAClD,CAEK,IAAI,EAA8B,iCAAiC,EAAW,GAAG,EAK7F,gCACE,EACA,EAC+B,SAC/B,IAAM,EAAS,GAAA,KAAkB,EAAlB,EAIf,OAAO,IAAI,EADK,GAFC,kCAAkC,GAAA,KAAkB,UAAlB,QAAkB,EAAA,GAAA,OAAA,EACjD,EAAW,MAAM,GAAA,KAAA,IAAA,GAAA,EAAE,SAAA,KAAU,EAAV,GAAe,EAAI,KAAK,EAAU,GAAK,GACrC,mEACS,EAAO,CAG3D,cAAsB,EAAqC,CACzD,MAAO,CAAC,CAAC,GAAU,GAAU,KAAO,EAAS,IAG/C,GACE,EACA,EACM,CACN,KAAK,aAAa,GAAG,EAAM,EAAQ,CAGrC,IACE,EACA,EACM,CACN,KAAK,aAAa,IAAI,EAAM,EAAQ,CAGtC,OAAqB,CACnB,KAAK,aAAa,OAAO,CAG3B,OAAe,EAEf,SAAuB,CACrB,KAAK,OAAO,CACZ,KAAK,OAAO,GC3GhB,MAEa,GAA6C,EAAW,IAA8B,CACjG,GAAI,IAAS,OACX,GAAI,CAEF,OAAO,EADM,KAAK,UAAU,EAAM,CACb,SACf,CACN,OAAO,EAAM,UAAU,CAAC,MAAM,EAAG,IAAwB,CAI7D,OAAO,EAAM,UAAU,CAAC,MAAM,EAAG,IAAwB,EAG9C,EAAY,GACV,EAAK,IAAI,aAAa,CAAC,OAAO,EAAK,CAAC,CACrC,SAAS,GAAG,CAAC,SAAS,EAAG,IAAI,CAGrC,EAAQ,GAA8B,CAC1C,IAAI,EAAO,KACX,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,OAAQ,IAChC,GAAQ,GAAQ,GAAK,EAAO,EAAM,GAClC,KAAgB,EAElB,OAAO,GChBT,IAAa,EAAb,KAA6B,CAO3B,YAAY,EAAyC,WACnD,KAAK,OAAS,EAAQ,OAEtB,IAAM,EAA8C,CAClD,KAAM,aACN,QAAS,CACP,OAAQ,EAAQ,OAChB,QAAS,EAAQ,QAAQ,UAAU,CACnC,sBAAA,EAAsB,EAAQ,uBAAA,KAAwB,IAAxB,EAC9B,2BAAA,EAA2B,EAAQ,4BAAA,KAA6B,IAA7B,EACnC,oBAAA,EAAoB,EAAQ,qBAAA,KAAsB,IAAtB,EAC7B,CACF,CACD,KAAK,OAAS,IAAI,OAAO,IAAI,gBAAgB,IAAG,KAAM,CAAC,86KAA8B,CAAA,CAAA,KAAA,yBAAA,CAAA,CAAA,CAAA,CACrF,KAAK,OAAO,UAAa,GAAwD,CAC/E,KAAK,kBAAkB,EAAQ,KAAK,EAEtC,KAAK,OAAO,YAAY,EAAkB,CAE1C,KAAK,sBAA0B,CACzB,SAAS,kBAAoB,UAC/B,KAAK,OAAO,EAGhB,GAAI,CACF,SAAS,iBAAiB,mBAAoB,KAAK,kBAAkB,OAC9D,EAAO,CACd,KAAK,OAAO,KAAK,8EAA+E,EAAM,EAI1G,MAAa,cAAc,EAA0C,YACnE,IAAM,EAAoD,CACxD,KAAM,gBACN,QAAS,CACP,QAAS,EACV,CACF,CACD,EAAK,OAAO,YAAY,EAAqB,CAG/C,gBAAkD,EAAsC,CACtF,IAAM,EAAwD,CAC5D,KAAM,uBACN,QAAS,KAAK,6BAA6B,EAAM,CAClD,CACD,KAAK,OAAO,YAAY,EAAuB,CAGjD,6BACE,EAC8B,CAC9B,OAAA,EAAA,EAAA,EAAA,CACK,EAAA,CAAA,EAAA,CAAA,CACH,aAAc,EAAc,EAAM,aAAc,EAAM,KAAK,CAC3D,eAAgB,EAAc,EAAM,eAAgB,EAAM,KAAK,EAChE,CAGH,kBAA0B,EAAqC,SAC7D,GAAI,EAAM,OAAS,SAAU,QAC3B,EAAA,KAAK,eAAA,MAAA,EAAA,KAAA,KAAgB,CACrB,OAEF,GAAI,GAAA,EAAC,EAAM,UAAA,MAAA,EAAS,QAAS,GAAA,EAAC,EAAM,UAAA,MAAA,EAAS,SAC3C,OAEF,GAAM,CAAE,QAAO,UAAS,QAAS,EAAM,QAEvC,OAAQ,EAAR,CACE,IAAK,QACH,KAAK,OAAO,MAAM,EAAS,GAAG,EAAK,CACnC,MACF,IAAK,OACH,KAAK,OAAO,KAAK,EAAS,GAAG,EAAK,CAClC,MACF,IAAK,OACH,KAAK,OAAO,KAAK,EAAS,GAAG,EAAK,CAClC,MACF,IAAK,QACH,KAAK,OAAO,KAAK,EAAS,GAAG,EAAK,CAClC,OAIN,OAAgB,CAId,KAAK,OAAO,YAH8B,CACxC,KAAM,QACP,CACoC,CAGvC,OAA8B,CAK5B,OAJI,KAAK,aACA,KAAK,aAGP,KAAK,cAAc,CAG5B,cAAsC,CAOpC,OANA,SAAS,oBAAoB,mBAAoB,KAAK,kBAAkB,CACxE,KAAK,aAAe,IAAI,QAAe,GAAY,CACjD,KAAK,aAAe,EAEpB,KAAK,OAAO,YAD8B,CAAE,KAAM,QAAS,CACtB,EACrC,CACK,KAAK,eCxGhB,MAAM,EAAiB,IAAI,IAAI,4CAA4C,CAQ3E,IAAa,EAAb,KAAyE,CAcvE,YAAY,EAAsB,EAAmC,EAA6C,mBAVlH,KAAQ,YAA2D,IAAI,IAEvE,KAAQ,aAAe,IAAI,EAE3B,KAAQ,MAAQ,GAOd,KAAK,QAAA,EAAA,GAAA,KAAA,IAAA,GAAS,EAAe,SAAA,KAAU,GAAqB,CAA/B,EAC7B,KAAK,SAAA,EAAA,GAAA,OAAA,EAAU,EAAe,aAAA,KAAA,IAAA,GAAA,EAAY,UAAA,KAAW,IAAX,EAC1C,IAAM,GAAA,EAAU,KAAK,SAAA,GAAA,OAAA,EAAS,EAAe,aAAA,KAAA,IAAA,GAAA,EAAY,IAAI,GAAA,KAAI,EAAJ,EAC7D,KAAK,WAAA,GAAA,OAAA,EAAY,EAAe,aAAA,KAAA,IAAA,GAAA,EAAY,aAAc,GAC1D,IAAM,EAAuB,KAAK,UAAY,EAAqB,EACnE,KAAK,oBAAsB,IAAI,EAAgB,CAC7C,OAAQ,EACR,OAAQ,KAAK,OACb,UACD,CAAC,CACF,KAAK,UAAY,IAAI,EAAqB,CACxC,eACA,UACA,YAAA,EAAA,EAAA,EAAA,CAAA,GAAA,KAAA,IAAA,GACK,EAAe,SAAA,CAAA,EAAA,CAAA,CAClB,QAAS,EAAW,QACpB,WAAY,EAAW,WACvB,WAAA,EAAW,YAAA,KAAA,IAAA,GAAA,EAAW,WACvB,CACD,OAAQ,KAAK,OACd,CAAC,CAEF,KAAK,UAAU,GAAG,oBAAsB,GAAyB,QAC/D,EAAA,KAAK,eAAA,MAAA,EAAA,KAAA,KAAgB,CACrB,IAAM,EAAa,OAAO,KAAK,EAAU,QAAQ,CAC7C,CAAC,KAAK,WAAa,EAAU,MAAQ,QACvC,KAAK,UAAY,EACjB,KAAK,aAAa,KAAK,iBAAkB,CAAE,KAAM,EAAY,CAAC,CAC9D,KAAK,eAAe,EAAU,QAAQ,GAEtC,KAAK,UAAU,QAAA,EAAA,EAAA,EAAA,CACV,KAAK,UAAU,QAAA,CACf,EAAU,QACd,CACD,KAAK,aAAa,KAAK,iBAAkB,CAAE,KAAM,EAAY,CAAC,CAC9D,KAAK,eAAe,EAAU,QAAQ,EAExC,KAAK,OAAO,MAAM,wDAAyD,CAAE,KAAM,EAAY,CAAC,EAChG,CAGJ,MAAa,WAAW,EAAiC,CACvD,MAAA,KAAW,mBAAmB,EAAS,iBAAiB,CAG1D,MAAa,cAAc,EAAgC,CACzD,MAAA,KAAW,mBAAmB,EAAS,iBAAiB,CAG1D,MAAc,mBAAmB,EAA4C,EAA6B,YACxG,GAAI,CACF,EAAK,MAAQ,GACb,EAAK,aAAe,IAAI,QAAe,GAAY,CACjD,EAAK,aAAe,GACpB,CAAC,SAAW,CACZ,EAAK,MAAQ,GACb,EAAK,aAAa,KAAK,cAAe,CAAE,OAAQ,EAAQ,CAAC,CACzD,EAAK,OAAO,MAAM,mFAAmF,EACrG,CACF,IAAM,EAAY,IAAI,MAAM,CAAC,SAAS,CACtC,MAAMC,EAAK,UAAU,QAAQ,GAAA,KAAW,EAAE,CAAb,EAAeA,EAAK,QAAQ,CACzD,EAAK,eAAiB,EACtB,EAAK,oBAAoB,cAAc,EAAQ,CAC/C,IAAM,EAAe,IAAI,MAAM,CAAC,SAAS,CAAG,EACtC,EAAmBA,EAAK,QAAU,EASxC,GARI,EAAmB,GACrB,MAAM,QAAQ,KAAK,CACjBA,EAAK,aACL,IAAI,QAAe,GAAY,CAC7B,eAAiB,GAAS,CAAE,EAAiB,EAC7C,CACH,CAAC,CAEA,CAACA,EAAK,MAAO,CACf,IAAM,EAAiBA,EAAK,UACxB,oJACA,iHACJ,EAAK,OAAO,KACV,gDAAgD,EAAO,SAASA,EAAK,QAAQ,MAAM,IACpF,QAEI,EAAO,CACd,EAAK,OAAO,MAAM,mDAAmD,EAAO,IAAK,EAAM,EAI3F,eAAuB,EAA4B,CACjD,OAAO,OAAO,EAAW,CAAC,QAAS,GAAM,KAAK,wBAAwB,EAAE,CAAC,CAG3E,wBAAgC,EAA0B,QACxD,EAAA,KAAK,YAAY,IAAI,EAAY,IAAI,GAAA,MAAA,EAAE,QAAS,GAAM,CACpD,IAAM,EAAQ,KAAK,wBAAwB,EAAY,IAAK,EAAa,EAAE,aAAa,CACxF,EAAE,QAAQ,EAAM,EAChB,CAGJ,MAAwC,EAAmB,EAAiB,EAA2B,CACrG,KAAK,qBAAqB,EAAa,CAEvC,IAAM,EAAW,KAAK,YAAY,IAAI,EAAU,CAC1C,EAAqB,CAAE,QAAS,EAAU,eAAc,cAAe,OAAO,EAAc,CAOlG,OANI,EACF,EAAS,KAAK,EAAmB,CAEjC,KAAK,YAAY,IAAI,EAAW,CAAC,EAAmB,CAAC,KAG1C,KAAK,QAAQ,EAAW,EAAS,CAGhD,QAA0C,EAAmB,EAA4B,CACvF,IAAM,EAAW,KAAK,YAAY,IAAI,EAAU,CAC3C,KAIL,GAAI,EAAU,CACZ,IAAM,EAAQ,EAAS,UAAW,GAAM,EAAE,SAAW,EAAS,CAC1D,GAAS,IACX,GAAA,MAAA,EAAU,OAAO,EAAO,EAAE,OAG5B,EAAS,OAAO,EAAE,CAItB,SAA2C,EAAmB,EAAoB,OAChF,KAAK,qBAAqB,EAAa,CAEvC,IAAM,GAAA,EAAc,KAAK,YAAA,KAAA,IAAA,GAAA,EAAW,QAAQ,GAC5C,OAAO,KAAK,wBAAwB,EAAW,EAAa,EAAa,CAG3E,wBACE,EACA,EACA,EACG,OACH,GAAI,CAAC,EAAa,OAahB,OAZA,KAAK,OAAO,MACV,qDAAqD,EAAU,8BAA8B,EAAa,GAC3G,CACD,KAAK,oBAAoB,gBAAgB,CACvC,WAAA,EAAW,KAAK,iBAAA,KAAA,IAAA,GAAA,EAAgB,GAChC,IAAK,EACS,eACd,cAAe,EAAiB,EAAa,CAC7C,eAAgB,EAChB,YAAa,GACb,iBAAkB,uBACnB,CAAC,CACK,EAGT,IAAM,EAAc,EAAoB,EAAa,EAAa,CAWlE,OAVA,KAAK,oBAAoB,gBAAgB,CACvC,WAAA,EAAW,KAAK,iBAAA,KAAA,IAAA,GAAA,EAAgB,GAChC,IAAK,EACS,eACd,cAAe,EAAY,cAC3B,eAAgB,EAAY,YAC5B,YAAa,EAAY,YACzB,iBAAkB,EAAY,OAC/B,CAAC,CACF,KAAK,OAAO,MAAM,qCAAqC,EAAU,QAAQ,EAAY,YAAY,GAAG,CAC7F,EAAY,YAGrB,SAAiB,EAA0C,CACpD,KAIL,GAAI,CACF,OAAO,IAAI,IAAI,EAAI,OACZ,EAAO,CACd,MAAM,IAAI,EAA8B,qBAAqB,EAAI,qBAAqB,IAAQ,EAIlG,qBAAwD,EAAiB,CACvE,GAAI,GAA+C,KACjD,MAAM,IAAI,EACR,sFACD,CAGH,GAAI,OAAO,GAAiB,WAC1B,MAAM,IAAI,EACR,8EACD,CAIL,IAAW,SAAmB,CAC5B,OAAO,KAAK,MAGd,GAAwC,EAAc,EAAiD,CACrG,KAAK,aAAa,GAAG,EAAW,EAAQ,CAG1C,IAAyC,EAAc,EAA8C,CACnG,KAAK,aAAa,IAAI,EAAW,EAAQ,CAG3C,OAAe,CACb,KAAK,OAAO,MAAM,yEAAyE,CAC3F,KAAK,aAAa,OAAO,CACzB,KAAK,YAAY,OAAO,CAG1B,YAAoB,CAClB,KAAK,YAAY,OAAO,CAG1B,OAAe,CACb,KAAK,OAAO,MAAM,+EAA+E,CACjG,KAAK,UAAU,OAAO,CACtB,KAAK,MAAQ,GAGf,SAAiB,CACf,KAAK,OAAO,CACZ,KAAK,OAAO,GCzQhB,MAAa,GACX,EACA,IAEO,IAAI,EACT,EACA,CAAE,QAAS,gBAAiB,WAAY,QAAe,CACvD,EACD,CCVU,EADoB,EAAM,cAAyC,CAAC,OAAQ,UAAU,CAAC,CCIpG,IAAM,EAAN,KAAoE,CAClE,gBAAgB,EAAyB,CACvC,MAAO,kCAAkC,MAI7C,MAAa,EAAuB,GAC3BC,EAAkB,EAAO,IAAI,EAAmB,CCR5C,EAAe,KAAO,IAA2C,OAC5E,IAAM,GAAA,EAAS,EAAQ,SAAA,KAAU,EAAoB,QAAQ,CAAtC,EACjB,EAAS,EAAa,EAAQ,OAAQ,CAC1C,WAAY,CAAE,IAAK,EAAQ,IAAK,QAAS,EAAQ,QAAS,CAC1D,SAAU,CAAE,QAAS,EAAQ,QAAS,WAAY,EAAQ,WAAY,CAC9D,SACT,CAAC,CAqBF,OApBA,MAAM,EAAO,WAAW,EAAQ,QAAQ,EAER,CAAE,cAAwC,CACxE,GAAM,CAAC,EAAM,GAAW,OAA6C,CACnE,SACA,OAAQ,EAAO,QAAU,QAAU,UACpC,EAAE,CAWH,OATA,MAAgB,CACd,EAAO,GAAG,qBAAwB,CAChC,EAAS,GAAA,EAAA,EAAA,EAAA,CAAoB,EAAA,CAAA,EAAA,CAAA,CAAW,UAAW,IAAI,KAAM,CAAE,CAAE,EACjE,CACF,EAAO,GAAG,kBAAqB,CAC7B,EAAS,GAAA,EAAA,EAAA,EAAA,CAAoB,EAAA,CAAA,EAAA,CAAA,CAAW,OAAQ,QAAA,CAAS,CAAE,EAC3D,EACF,CAEK,EAAC,EAAa,SAAd,CAAuB,MAAO,EAAO,WAAiC,CAAA,GCxBjF,IAAa,EAAb,cAA4C,CAG1C,CACA,YAAY,EAAsC,OAChD,MAAM,EAAM,CAQZ,KAAK,MAAQ,CAAE,OANA,EAAa,EAAM,OAAQ,CACxC,WAAY,CAAE,IAAK,EAAM,IAAK,QAAS,EAAM,QAAS,CACtD,SAAU,CAAE,QAAS,EAAM,QAAS,WAAY,EAAM,WAAY,CAClE,QAAA,EAAQ,EAAM,SAAA,KAAU,EAAoB,OAAO,CAArC,EACf,CAAC,CAEqB,OAAQ,UAAW,CAG5C,MAAe,mBAAmC,qBAChD,EAAA,EAAK,MAAM,SAAA,MAAA,EAAQ,GAAG,qBAAwB,CAC5C,EAAK,SAAS,CAAE,UAAW,IAAI,KAAQ,CAAC,EACxC,EACF,EAAA,EAAK,MAAM,SAAA,MAAA,EAAQ,GAAG,kBAAqB,CACzC,EAAK,SAAS,CAAE,OAAQ,QAAS,CAAC,EAClC,CACF,OAAA,EAAMC,EAAK,MAAM,SAAA,KAAA,IAAA,GAAA,EAAQ,WAAWA,EAAK,MAAM,QAAQ,GACnD,EAACA,EAAK,MAAM,SAAA,MAAA,EAAQ,SACtB,EAAK,SAAS,CAAE,OAAQ,UAAW,CAAC,CAIxC,sBAAsC,QACpC,EAAA,KAAK,MAAM,SAAA,MAAA,EAAQ,SAAS,CAG9B,QAAkB,CAChB,OAAO,EAAC,EAAa,SAAd,CAAuB,MAAO,KAAK,eAAQ,KAAK,MAAM,SAAiC,CAAA,GCxCrF,EAAb,MAAa,UAAwC,KAAM,CAGzD,YAAY,EAAiB,CAC3B,MAAM,EAAQ,CAHhB,KAAyB,KAAe,kCAKtC,OAAO,eAAe,KAAM,EAAgC,UAAU,GCK1E,MAAM,MACG,IAAI,EAAgC,kKAAkK,CAGzM,GACJ,EACA,IAKG,CACH,IAAM,EAA6B,EAAW,EAAa,CAC3D,GAAI,EAAA,GAAA,MAAC,EAA4B,QAC/B,MAAM,GAAgB,CAKxB,MAAO,CAAE,MAFK,EAA2B,OAAO,SAAS,EAAK,EAAa,CAE3D,YAAa,EAA2B,OAAQ,QAAS,EAA2B,SAAW,UAAW,EAGtH,MAAiC,CACrC,IAAM,EAA6B,EAAW,EAAa,CAC3D,GAAI,EAAA,GAAA,MAAC,EAA4B,QAC/B,MAAM,GAAgB,CAOxB,MAAO,CAAE,cAJa,KAAO,IAAmC,OAC9D,OAAA,EAAM,EAA2B,SAAA,KAAA,IAAA,GAAA,EAAQ,cAAc,EAAQ,GAGzC,EAGpB,OAAgC,CACpC,IAAM,EAA6B,EAAW,EAAa,CAC3D,GAAI,EAAA,GAAA,MAAC,EAA4B,QAC/B,MAAM,GAAgB,CAGxB,MAAO,CAAE,OAAQ,EAA2B,OAAQ"}
1
+ {"version":3,"file":"configdirector-react-client.mjs","names":["this","this","this","this","createJsSdkLogger","this"],"sources":["../../js-client-core/src/Emitter.ts","../../shared/src/errors.ts","../../js-client-core/src/errors.ts","../../eventsource/src/errors.ts","../../eventsource/src/EventSourceParser.ts","../../eventsource/src/types.ts","../../eventsource/src/EventSourceClient.ts","../../eventsource/src/index.ts","../../js-client-core/src/StreamingTransport.ts","../../shared/src/value-parser.ts","../../shared/src/logger.ts","../../js-client-core/src/logger.ts","../../shared/src/fetchWithTimeout.ts","../../js-client-core/src/PullTransport.ts","../../shared/src/url.ts","../../shared/src/constants.ts","../../js-client-core/src/DefaultConfigDirectorClient.ts","../../shared/src/telemetry/utils.ts","../../js-browser-client/src/telemetry/WebWorkerTelemetryClient.ts","../../js-browser-client/src/BrowserConfigDirectorClient.ts","../src/client.ts","../src/context.tsx","../src/logger.ts","../src/withProvider.tsx","../src/provider.tsx","../src/errors.ts","../src/hooks.tsx"],"sourcesContent":["type EventType = string | symbol;\ntype EventsRecord = Record<EventType, any>;\n\ntype Handler<TEventsRecord extends EventsRecord, TKey extends keyof TEventsRecord> = (\n payload: TEventsRecord[TKey],\n) => void;\n\nexport interface EventProvider<TEventsRecord extends EventsRecord> {\n on<TName extends keyof TEventsRecord>(name: TName, handler: Handler<TEventsRecord, TName>): void;\n off<TName extends keyof TEventsRecord>(name: TName, handler?: Handler<TEventsRecord, TName>): void;\n clear(): void;\n}\n\nexport class Emitter<TEventsRecord extends EventsRecord> implements EventProvider<TEventsRecord> {\n private handlerMap: Map<keyof TEventsRecord, Array<(payload: any) => void>> = new Map();\n\n on<TName extends keyof TEventsRecord>(name: TName, handler: Handler<TEventsRecord, TName>) {\n const handlers = this.handlerMap.get(name);\n if (handlers) {\n handlers.push(handler);\n } else {\n this.handlerMap.set(name, [handler]);\n }\n }\n\n once<TName extends keyof TEventsRecord>(name: TName, handler: Handler<TEventsRecord, TName>) {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n function onceHandler(payload: TEventsRecord[keyof TEventsRecord]) {\n self.off(name, onceHandler);\n handler.apply(self, payload);\n }\n this.on(name, onceHandler);\n }\n\n off<TName extends keyof TEventsRecord>(name: TName, handler?: Handler<TEventsRecord, TName>) {\n const handlers = this.handlerMap.get(name);\n if (!handlers) {\n return;\n }\n\n if (handler) {\n const listenerIndex = handlers.indexOf(handler);\n if (listenerIndex >= 0) {\n handlers.splice(listenerIndex, 1);\n }\n } else {\n this.handlerMap.set(name, []);\n }\n }\n\n clear() {\n this.handlerMap.clear();\n }\n\n emit<TName extends keyof TEventsRecord>(name: TName, payload: TEventsRecord[TName]) {\n const handlers = this.handlerMap.get(name);\n if (!handlers) {\n return;\n }\n\n handlers.slice().map((h) => h(payload));\n }\n}\n","export class ConfigDirectorConnectionError extends Error {\n public override readonly name: string = \"ConfigDirectorConnectionError\";\n public readonly status?: number;\n\n constructor(message: string, status?: number) {\n super(message);\n this.status = status;\n\n Object.setPrototypeOf(this, ConfigDirectorConnectionError.prototype);\n }\n}\n\nexport class ConfigDirectorValidationError extends Error {\n public override readonly name: string = \"ConfigDirectorValidationError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, ConfigDirectorValidationError.prototype);\n }\n}\n","export { ConfigDirectorConnectionError, ConfigDirectorValidationError } from \"../../shared/src/errors\";\n\nexport const isFetchErrorFatal = (fetchError: any): boolean => {\n if (fetchError?.name === \"NotAllowedError\") {\n return true;\n } else if (fetchError instanceof TypeError) {\n return true;\n }\n\n return false;\n};\n","export class StreamClosedError extends Error {\n public override readonly name: string = \"StreamClosedError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, StreamClosedError.prototype);\n }\n}\n\nexport class MissingResponseBodyError extends Error {\n public override readonly name: string = \"MissingResponseBodyError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, MissingResponseBodyError.prototype);\n }\n}\n\nexport class InvalidOptionError extends Error {\n public override readonly name: string = \"InvalidOptionError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, InvalidOptionError.prototype);\n }\n}\n\nexport class ValueOutOfRangeError extends Error {\n public override readonly name: string = \"ValueOutOfRangeError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, ValueOutOfRangeError.prototype);\n }\n}\n","import {\n type EventSourceParserOptions,\n type EventSourceMessageHandler,\n type EventSourceCommentHandler,\n type EventParserRetryCallback,\n} from \"./types\";\n\ntype LineContent = {\n field: string;\n value: string;\n};\n\nexport class EventSourceParser {\n private isFirstChunk = true;\n private previousIncompleteLine = \"\";\n private currentEvent: { type?: string | undefined; data: string };\n private lastEventId: string | undefined;\n private onEvent: EventSourceMessageHandler;\n private onRetry: EventParserRetryCallback | undefined;\n private onComment: EventSourceCommentHandler | undefined;\n\n constructor(options: EventSourceParserOptions) {\n this.currentEvent = {\n data: \"\",\n };\n this.onEvent = options.onEvent ?? (() => {});\n this.onRetry = options.onRetry;\n this.onComment = options.onComment;\n }\n\n public parse(input: string) {\n const chunk = this.prepareChunk(input);\n const lines = this.splitLines(chunk);\n for (const line of lines) {\n this.parseAndProcessLine(line);\n }\n }\n\n public finish() {\n if (this.previousIncompleteLine !== \"\") {\n this.parseAndProcessLine(this.previousIncompleteLine);\n }\n }\n\n private parseAndProcessLine(line: string) {\n if (line.startsWith(\":\")) {\n this.onComment?.(this.getValueFromLine(0, line));\n return;\n }\n\n if (line === \"\") {\n this.publishEvent();\n return;\n }\n\n const content = this.parseContentLine(line);\n this.processContent(content);\n }\n\n private publishEvent() {\n const data = this.currentEvent.data.endsWith(\"\\n\")\n ? this.currentEvent.data.slice(0, -1)\n : this.currentEvent.data;\n\n if (data) {\n this.onEvent({\n ...this.currentEvent,\n id: this.lastEventId,\n data,\n });\n }\n this.currentEvent = {\n data: \"\",\n };\n }\n\n private processContent(content: LineContent) {\n switch (content.field) {\n case \"event\":\n this.currentEvent.type = content.value;\n break;\n case \"data\":\n this.currentEvent.data += content.value + \"\\n\";\n break;\n case \"id\":\n if (!content.value.includes(\"\\0\")) {\n this.lastEventId = content.value;\n }\n break;\n case \"retry\":\n if (/^\\d+$/.test(content.value)) {\n this.onRetry?.(Number.parseInt(content.value, 10));\n }\n break;\n\n default:\n break;\n }\n }\n\n private parseContentLine(line: string): LineContent {\n const delimiterIndex = line.indexOf(\":\");\n if (delimiterIndex === -1) {\n return { field: line, value: \"\" };\n }\n\n return { field: line.slice(0, delimiterIndex), value: this.getValueFromLine(delimiterIndex, line) };\n }\n\n private splitLines(chunk: string) {\n const lines = chunk.split(/\\r\\n|\\r|\\n/);\n this.previousIncompleteLine = lines.pop() ?? \"\";\n return lines;\n }\n\n private getValueFromLine(delimiterIndex: number, line: string): string {\n if (delimiterIndex === -1) {\n return \"\";\n }\n\n const valueStartIndex = line[delimiterIndex + 1] === \" \" ? delimiterIndex + 2 : delimiterIndex + 1;\n return line.slice(valueStartIndex);\n }\n\n private prepareChunk(chunk: string) {\n if (this.isFirstChunk) {\n this.isFirstChunk = false;\n return this.previousIncompleteLine + chunk.replace(/^\\xEF\\xBB\\xBF/, \"\").replace(/^\\uFEFF/, \"\");\n } else {\n return this.previousIncompleteLine + chunk;\n }\n }\n}\n","export type ReconnectionState = {\n attempt: number;\n serverReconnectionTime: number;\n status?: number | undefined;\n error?: Error | undefined;\n};\n\nexport enum ReadyState {\n OPEN = \"open\",\n CLOSED = \"closed\",\n CONNECTING = \"connecting\",\n}\n\nexport type EventSourceClientOptions = {\n url: { toString(): string } | string;\n method?: string;\n headers?: Record<string, string>;\n body?: any;\n mode?: \"cors\" | \"no-cors\" | \"same-origin\";\n credentials?: \"include\" | \"omit\" | \"same-origin\";\n redirect?: \"error\" | \"follow\";\n referrer?: string;\n referrerPolicy?: ReferrerPolicy;\n lastEventId?: string;\n fetch?: (url: string, init: RequestInit) => Promise<Response>;\n onError?: (error: Error) => void;\n onConnect?: () => void;\n onDisconnect?: () => void;\n onMessage?: EventSourceMessageHandler;\n onComment?: EventSourceCommentHandler;\n shouldReconnect?: (state: ReconnectionState) => boolean;\n calculateReconnectDelay?: (state: ReconnectionState) => number;\n};\n\nexport type EventSourceMessage = {\n id?: string | undefined;\n type?: string;\n data: string;\n};\n\nexport type EventSourceMessageHandler = (message: EventSourceMessage) => void;\nexport type EventSourceCommentHandler = (comment: string) => void;\n\nexport type EventParserRetryCallback = (retry: number) => void;\n\nexport type EventSourceParserOptions = {\n onEvent?: EventSourceMessageHandler;\n onRetry?: EventParserRetryCallback;\n onComment?: EventSourceCommentHandler;\n};\n","import {\n InvalidOptionError,\n MissingResponseBodyError,\n StreamClosedError,\n ValueOutOfRangeError,\n} from \"./errors\";\nimport { EventSourceParser } from \"./EventSourceParser\";\nimport {\n type EventSourceClientOptions,\n type EventSourceCommentHandler,\n type EventSourceMessageHandler,\n type ReconnectionState,\n ReadyState,\n} from \"./types\";\n\nexport class EventSourceClient {\n private readonly DEFAULT_SHOULD_RECONNECT = () => true;\n private readonly DEFAULT_CALCULATE_RECONNECT_DELAY = () => this.serverReconnectionTime;\n private readonly url: string;\n private readonly headers?: Record<string, string>;\n private readonly requestOptions;\n private lastEventId?: string;\n private reconnectAttempt: number = 0;\n private abortController: AbortController = new AbortController();\n private reconnectTimeout: ReturnType<typeof setTimeout> | undefined;\n private _readyState: ReadyState = ReadyState.CLOSED;\n private serverReconnectionTime: number = 2_000;\n private _fetch: (url: string, init: RequestInit) => Promise<Response>;\n private _onError: (error: Error) => void;\n private _onMessage: EventSourceMessageHandler;\n private _onComment: EventSourceCommentHandler;\n private _onConnect: () => void;\n private _onDisconnect: () => void;\n private _shouldReconnect: (state: ReconnectionState) => boolean;\n private _calculateReconnectDelay: (state: ReconnectionState) => number;\n\n constructor(options: EventSourceClientOptions) {\n this.url = options.url.toString();\n this.lastEventId = options.lastEventId;\n this.headers = {\n Accept: \"text/event-stream\",\n ...options.headers,\n };\n this.requestOptions = {\n body: options.body,\n method: options.method ?? \"GET\",\n mode: options.mode,\n credentials: options.credentials,\n redirect: options.redirect,\n referrer: options.referrer,\n referrerPolicy: options.referrerPolicy,\n };\n this._fetch = options.fetch ?? ((url, init) => fetch(url, init));\n this._onError = this.getValidatedFunctionOrNoOp(options.onError, \"onError\");\n this._onConnect = this.getValidatedFunctionOrNoOp(options.onConnect, \"onConnect\");\n this._onDisconnect = this.getValidatedFunctionOrNoOp(options.onDisconnect, \"onDisconnect\");\n this._onMessage = this.getValidatedFunctionOrNoOp(options.onMessage, \"onMessage\");\n this._onComment = this.getValidatedFunctionOrNoOp(options.onComment, \"onComment\");\n this._shouldReconnect = this.getValidatedFunctionOr(\n options.shouldReconnect,\n this.DEFAULT_SHOULD_RECONNECT,\n \"shouldReconnect\",\n );\n this._calculateReconnectDelay = this.getValidatedFunctionOr(\n options.calculateReconnectDelay,\n this.DEFAULT_CALCULATE_RECONNECT_DELAY,\n \"calculateReconnectDelay\",\n );\n }\n\n public set onError(value: (error: Error) => void) {\n this._onError = this.getValidatedFunctionOrNoOp(value, \"onError\");\n }\n\n public set onMessage(value: EventSourceMessageHandler) {\n this._onMessage = this.getValidatedFunctionOrNoOp(value, \"onMessage\");\n }\n\n public set onComment(value: EventSourceCommentHandler) {\n this._onComment = this.getValidatedFunctionOrNoOp(value, \"onComment\");\n }\n\n public set onConnect(value: () => void) {\n this._onConnect = this.getValidatedFunctionOrNoOp(value, \"onConnect\");\n }\n\n public set onDisconnect(value: () => void) {\n this._onDisconnect = this.getValidatedFunctionOrNoOp(value, \"onDisconnect\");\n }\n\n public set shouldReconnect(value: (state: ReconnectionState) => boolean) {\n this._shouldReconnect = this.getValidatedFunctionOr(\n value,\n this.DEFAULT_SHOULD_RECONNECT,\n \"shouldReconnect\",\n );\n }\n\n public set calculateReconnectDelay(value: (state: ReconnectionState) => number) {\n this._calculateReconnectDelay = this.getValidatedFunctionOr(\n value,\n this.DEFAULT_CALCULATE_RECONNECT_DELAY,\n \"shouldReconnect\",\n );\n }\n\n public get readyState(): ReadyState {\n return this._readyState;\n }\n\n public connect() {\n if (this._readyState !== ReadyState.CLOSED) {\n return;\n }\n\n this.reconnectAttempt = 0;\n this.initiateConnection();\n }\n\n private initiateConnection() {\n this.abortController = new AbortController();\n this._readyState = ReadyState.CONNECTING;\n\n this._fetch(this.url, {\n ...this.requestOptions,\n headers: this.buildHeaders(),\n signal: this.abortController.signal,\n cache: \"no-store\",\n })\n .then(this.handleFetchResponse.bind(this))\n .catch((error: Error) => {\n if (error.name === \"AbortError\" || this.abortController.signal.aborted) {\n this.close();\n return;\n }\n\n this._onError(error);\n this.scheduleReconnect({ error });\n });\n }\n\n public close() {\n clearTimeout(this.reconnectTimeout);\n this._readyState = ReadyState.CLOSED;\n this.abortController.abort();\n }\n\n private disconnected() {\n clearTimeout(this.reconnectTimeout);\n this._readyState = ReadyState.CLOSED;\n this._onDisconnect();\n }\n\n private buildHeaders(): Record<string, string> {\n const lastEventIdHeader = this.lastEventId ? { \"Last-Event-ID\": this.lastEventId } : undefined;\n return {\n ...this.headers,\n ...lastEventIdHeader,\n };\n }\n\n private async handleFetchResponse(response: Response) {\n const { body, status } = response;\n\n if (status === 204) {\n this.disconnected();\n return;\n }\n\n if (status >= 400) {\n this.scheduleReconnect({ status });\n return;\n }\n\n if (!body) {\n throw new MissingResponseBodyError(\"The server response did not have a body\");\n }\n\n this._readyState = ReadyState.OPEN;\n this._onConnect();\n this.reconnectAttempt = 0;\n\n const reader = body.getReader();\n const decoder = new TextDecoder();\n const parser = new EventSourceParser({\n onEvent: (event) => {\n if (typeof event.id === \"string\") {\n this.lastEventId = event.id;\n }\n this._onMessage(event);\n },\n onComment: (comment) => this._onComment(comment),\n onRetry: (retryDelay) => (this.serverReconnectionTime = retryDelay),\n });\n\n let done = false;\n while (!done) {\n const { done: readerDone, value } = await reader.read();\n if (value) {\n parser.parse(decoder.decode(value, { stream: true }));\n }\n\n done = readerDone;\n }\n\n parser.finish();\n this.scheduleReconnect({ status, error: new StreamClosedError(\"The server response stream was closed\") });\n }\n\n private scheduleReconnect(state: { status?: number; error?: Error }) {\n if (this.abortController.signal.aborted) {\n return;\n }\n\n clearTimeout(this.reconnectTimeout);\n this.reconnectAttempt += 1;\n const reconnectionState = {\n attempt: this.reconnectAttempt,\n status: state.status,\n error: state.error,\n serverReconnectionTime: this.serverReconnectionTime,\n };\n if (this._shouldReconnect(reconnectionState)) {\n this._readyState = ReadyState.CONNECTING;\n let delay = this._calculateReconnectDelay(reconnectionState);\n if (!Number.isFinite(delay) || delay < 1 || delay > 1_000 * 60 * 60) {\n this._onError(\n new ValueOutOfRangeError(\n `The calculated reconnect delay is out of range: ${delay}. Defaulting to ${this.serverReconnectionTime}`,\n ),\n );\n delay = this.serverReconnectionTime;\n }\n this.reconnectTimeout = setTimeout(() => this.initiateConnection(), delay);\n } else {\n this.disconnected();\n return;\n }\n }\n\n private getValidatedFunctionOrNoOp(func: any, name: string): (...args: any) => any {\n return this.getValidatedFunctionOr(func, () => {}, name);\n }\n\n private getValidatedFunctionOr(\n func: any,\n defaultFunc: (...args: any) => any,\n name: string,\n ): (...args: any) => any {\n if (func == null) {\n return defaultFunc;\n } else if (typeof func === \"function\") {\n return func;\n } else {\n throw new InvalidOptionError(`${name} must be a function`);\n }\n }\n}\n","import { EventSourceClient } from \"./EventSourceClient\";\nimport { type EventSourceClientOptions } from \"./types\";\n\nexport const createEventSourceClient = (options: EventSourceClientOptions) => {\n return new EventSourceClient(options);\n};\n","import type {\n ConfigDirectorContext,\n ConfigDirectorLogger,\n Transport,\n TransportEvents,\n TransportOptions,\n} from \"./types\";\nimport { Emitter } from \"./Emitter\";\nimport { ConfigDirectorConnectionError } from \"./errors\";\nimport { createEventSourceClient } from \"@eventsource/index\";\nimport type { EventSourceClient } from \"@eventsource/EventSourceClient\";\nimport type { UrlLike } from \"@shared/url\";\n\nexport class StreamingTransport implements Transport {\n private logger: ConfigDirectorLogger;\n private eventSource: EventSourceClient | undefined;\n private eventEmitter = new Emitter<TransportEvents>();\n private url: UrlLike;\n private timeoutTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(private readonly options: TransportOptions) {\n this.options = options;\n this.logger = options.logger;\n this.url = options.resolveUrl(\"client/sse/v1\", options.baseUrl);\n }\n\n public async connect(context: ConfigDirectorContext, timeout: number): Promise<this> {\n if (this.eventSource) {\n this.close();\n }\n\n const eventSourcePromise = new Promise<this>((resolve, reject) => {\n this.eventSource = createEventSourceClient({\n url: this.url,\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n fetch: this.options.fetch,\n body: JSON.stringify({\n givenContext: context,\n metaContext: this.options.metaContext,\n clientSdkKey: this.options.clientSdkKey,\n }),\n\n onMessage: ({ data }) => {\n this.dispatchMessage(data);\n },\n onConnect: () => {\n this.logger.debug(\"[EventSourceTransport] Connected\");\n resolve(this);\n },\n shouldReconnect: (state) => {\n const reconnect = !this.isStatusFatal(state.status);\n if (!reconnect) {\n reject(this.prepareFatalError(state.status, state.error));\n }\n return reconnect;\n },\n calculateReconnectDelay: (state) => {\n const delay = this.options.connectionRetryDelay(state.attempt);\n this.logger.warn(`[EventSourceTransport] Scheduling reconnect in ${delay}ms.`);\n return delay;\n },\n onError: (error) => {\n this.logger.debug(\"[EventSourceTransport] Error: \", error);\n },\n onDisconnect: () => {\n this.logger.debug(\"[EventSourceTransport] Disconnected\");\n },\n });\n this.eventSource.connect();\n });\n\n clearTimeout(this.timeoutTimer);\n this.timeoutTimer = undefined;\n return Promise.race([\n eventSourcePromise,\n new Promise<this>((resolve) => {\n this.timeoutTimer = setTimeout(() => resolve(this), timeout);\n }),\n ]).finally(() => clearTimeout(this.timeoutTimer));\n }\n\n private dispatchMessage(data: string) {\n try {\n const json = JSON.parse(data);\n this.eventEmitter.emit(\"configSetReceived\", json);\n } catch (error) {\n this.logger.error(\"[EventSourceTransport] Error parsing and dispatching config data update: \", error);\n }\n }\n\n private prepareFatalError(\n responseStatus: number | undefined,\n error: Error | undefined,\n ): ConfigDirectorConnectionError {\n const status = responseStatus ?? 0;\n const headline = `Connection failed with status: ${responseStatus ?? \"unknown\"}.`;\n const errorLine = error ? ` Error: ${error}` : \"\";\n const message = `${headline}${errorLine}. This is an unrecoverable error, will not attempt to reconnect.`;\n return new ConfigDirectorConnectionError(message, status);\n }\n\n private isStatusFatal(status: number | undefined): boolean {\n return !!status && status >= 400 && status < 500;\n }\n\n public on<TName extends keyof TransportEvents>(\n name: TName,\n handler: (payload: TransportEvents[TName]) => void,\n ): void {\n this.eventEmitter.on(name, handler);\n }\n\n public off<TName extends keyof TransportEvents>(\n name: TName,\n handler?: ((payload: TransportEvents[TName]) => void) | undefined,\n ): void {\n this.eventEmitter.off(name, handler);\n }\n\n public clear(): void {\n this.eventEmitter.clear();\n }\n\n public close() {\n this.eventSource?.close();\n clearTimeout(this.timeoutTimer);\n }\n\n public dispose(): void {\n this.close();\n this.clear();\n }\n}\n","import type { ConfigState, ConfigValueType, EvaluationReason } from \"./types\";\n\ntype NativeType =\n | \"string\"\n | \"number\"\n | \"bigint\"\n | \"boolean\"\n | \"symbol\"\n | \"undefined\"\n | \"object\"\n | \"function\";\n\ntype ParseResult<T extends ConfigValueType> = {\n parsedValue: T;\n requestedType: NativeType | string;\n usedDefault: boolean;\n reason: EvaluationReason;\n};\n\nexport const getRequestedType = <T extends ConfigValueType>(defaultValue: T): string => {\n const baseType = typeof defaultValue;\n if (baseType === \"object\") {\n try {\n return (defaultValue as object).constructor?.name ?? baseType;\n } catch {\n return baseType;\n }\n } else if (baseType === \"function\") {\n try {\n const functionName = (defaultValue as any).name;\n return functionName ? `function: ${functionName}` : baseType;\n } catch {\n return baseType;\n }\n }\n return baseType;\n};\n\nconst isNumericNativeType = (requestedType: NativeType): boolean => {\n return requestedType === \"number\" || requestedType === \"bigint\";\n};\n\nexport const parseConfigValue = <T extends ConfigValueType>(\n configState: ConfigState,\n defaultValue: T,\n): ParseResult<T> => {\n const value = configState.value;\n const requestedType = getRequestedType(defaultValue);\n\n if (!value) {\n return {\n parsedValue: defaultValue as T,\n requestedType,\n usedDefault: true,\n reason: \"value-missing\",\n };\n }\n\n if (typeof defaultValue === \"string\") {\n return {\n parsedValue: value as T,\n requestedType,\n usedDefault: false,\n reason: \"found-match\",\n };\n }\n\n if (typeof defaultValue === \"boolean\" && configState.type === \"boolean\") {\n const boolValue = parseConfigBoolean(value);\n const hasBoolean = typeof boolValue === \"boolean\";\n return {\n parsedValue: (hasBoolean ? boolValue : defaultValue) as T,\n requestedType,\n usedDefault: !hasBoolean,\n reason: hasBoolean ? \"found-match\" : \"invalid-boolean\",\n };\n }\n\n if (isNumericNativeType(typeof defaultValue) && configState.type === \"integer\") {\n const numValue = parseConfigInteger(value);\n const hasNumber = typeof numValue === \"number\";\n return {\n parsedValue: (hasNumber ? numValue : defaultValue) as T,\n requestedType,\n usedDefault: !hasNumber,\n reason: hasNumber ? \"found-match\" : \"invalid-number\",\n };\n }\n if (isNumericNativeType(typeof defaultValue) && (configState.type === \"float\" || configState.type === \"enum\" )) {\n const numValue = parseConfigFloat(value);\n const hasNumber = typeof numValue === \"number\";\n return {\n parsedValue: (hasNumber ? numValue : defaultValue) as T,\n requestedType,\n usedDefault: !hasNumber,\n reason: hasNumber ? \"found-match\" : \"invalid-number\",\n };\n }\n\n return {\n parsedValue: value as T,\n requestedType,\n usedDefault: false,\n reason: \"found-match\",\n };\n};\n\nconst parseConfigBoolean = (value: string): boolean | undefined => {\n if (!value) {\n return;\n }\n const lowerValue = value.toLowerCase();\n if (lowerValue != \"true\" && lowerValue != \"false\") {\n return;\n }\n return lowerValue === \"true\";\n};\n\nconst parseConfigInteger = (value: string): number | undefined => {\n if (!value) {\n return;\n }\n const num = Number.parseInt(value);\n if (isNaN(num) || !isFinite(num)) {\n return;\n }\n return num;\n};\n\nconst parseConfigFloat = (value: string): number | undefined => {\n if (!value) {\n return;\n }\n const num = Number.parseFloat(value);\n if (isNaN(num) || !isFinite(num)) {\n return;\n }\n return num;\n};\n","import type { ConfigDirectorLogger, ConfigDirectorLogMessageDecorator, ConfigDirectorLoggingLevel } from \"./types\";\n\nconst LEVELS: Record<ConfigDirectorLoggingLevel, number> = {\n off: -1,\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\nconst buildDateFormatter = () => {\n const baseOptions: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n timeZoneName: \"short\",\n };\n\n try {\n return new Intl.DateTimeFormat(\n undefined,\n { ...baseOptions, fractionalSecondDigits: 3 } as Intl.DateTimeFormatOptions,\n );\n } catch {\n return new Intl.DateTimeFormat(undefined, baseOptions);\n }\n};\n\nexport class DefaultConsoleLogger implements ConfigDirectorLogger {\n private readonly dateFormatter;\n\n constructor(private readonly level: ConfigDirectorLoggingLevel, private readonly decorator: ConfigDirectorLogMessageDecorator) {\n this.level = level;\n this.decorator = decorator;\n this.dateFormatter = buildDateFormatter();\n }\n\n debug(message: string, ...args: any): void {\n this.log(console.debug, \"debug\", message, ...args);\n }\n\n info(message: string, ...args: any): void {\n this.log(console.info, \"info\", message, ...args);\n }\n\n warn(message: string, ...args: any): void {\n this.log(console.warn, \"warn\", message, ...args);\n }\n\n error(message: string, ...args: any): void {\n this.log(console.error, \"error\", message, ...args);\n }\n\n private log(loggerFunction: (...args: any) => void, level: ConfigDirectorLoggingLevel, message: string, ...args: any) {\n if (LEVELS[this.level] >= LEVELS[level]) {\n loggerFunction(`[${this.dateFormatter.format(new Date())}] ${this.decorator?.decorateMessage(message)}`, ...args);\n }\n }\n}\n","import { type ConfigDirectorLogMessageDecorator, type ConfigDirectorLoggingLevel } from \"./types\";\nimport { DefaultConsoleLogger } from \"../../shared/src/logger\";\nexport { DefaultConsoleLogger } from \"../../shared/src/logger\";\n\nclass LogMessageDecorator implements ConfigDirectorLogMessageDecorator {\n decorateMessage(message: string): string {\n return `[ConfigDirector:js-client-sdk] ${message}`;\n }\n}\n\nexport const createDefaultLogger = (\n level?: ConfigDirectorLoggingLevel,\n messageDecorator?: ConfigDirectorLogMessageDecorator,\n) => {\n return new DefaultConsoleLogger(level ?? \"warn\", messageDecorator ?? new LogMessageDecorator());\n};\n","import { type ConfigDirectorLogger } from \"./types\";\nimport type { UrlLike } from \"./url\";\n\nexport const fetchWithTimeout = async (\n timeout: number,\n resource: string | UrlLike | Request,\n options: RequestInit | undefined,\n logger: ConfigDirectorLogger,\n) => {\n const abortController = new AbortController();\n const abortTimeoutId = setTimeout(() => {\n logger.debug(\"[fetchWithTimeout] Reached timeout, aborting request\");\n abortController.abort();\n }, timeout);\n\n try {\n const response = await fetch(typeof resource === \"string\" || resource instanceof Request ? resource : resource.toString(), {\n ...options,\n signal: abortController.signal,\n });\n clearTimeout(abortTimeoutId);\n return response;\n } catch (error) {\n logger.warn(\"[fetchWithTimeout] Fetch error: \", error);\n clearTimeout(abortTimeoutId);\n throw error;\n }\n};\n","import type {\n ConfigDirectorContext,\n ConfigDirectorLogger,\n Transport,\n TransportEvents,\n TransportOptions,\n} from \"./types\";\nimport { Emitter } from \"./Emitter\";\nimport { ConfigDirectorConnectionError, isFetchErrorFatal } from \"./errors\";\nimport { fetchWithTimeout } from \"@shared/fetchWithTimeout\";\nimport type { UrlLike } from \"@shared/url\";\n\nexport class PullTransport implements Transport {\n private logger: ConfigDirectorLogger;\n private eventEmitter = new Emitter<TransportEvents>();\n private url: UrlLike;\n private fatalError = false;\n\n constructor(private readonly options: TransportOptions) {\n this.options = options;\n this.logger = options.logger;\n this.url = options.resolveUrl(\"client/pull/v1\", options.baseUrl);\n }\n\n public async connect(context: ConfigDirectorContext, timeout: number): Promise<this> {\n if (this.fatalError) {\n this.logger.warn(\n \"[PullTransport] There was a prior unrecoverable error. Ignoring attempt to reconnect.\",\n );\n return this;\n }\n\n try {\n const response = await fetchWithTimeout(timeout, this.url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n givenContext: context,\n metaContext: this.options.metaContext,\n clientSdkKey: this.options.clientSdkKey,\n }),\n }, this.logger);\n\n if (!response.ok) {\n if (this.isStatusFatal(response.status)) {\n this.fatalError = true;\n throw this.prepareFatalResponseStatusError(response.status, await response.text());\n } else {\n throw new ConfigDirectorConnectionError(\n `Connection failed with status: ${response.status}`,\n response.status,\n );\n }\n }\n\n const json = JSON.parse(await response.text());\n this.eventEmitter.emit(\"configSetReceived\", json);\n return this;\n } catch (fetchError) {\n if (isFetchErrorFatal(fetchError)) {\n this.fatalError = true;\n throw new ConfigDirectorConnectionError(\n `Connection failed with fatal error: ${fetchError}. This is an unrecoverable error, retry attempts will be ignored.`,\n );\n } else if (fetchError instanceof SyntaxError) {\n throw new ConfigDirectorConnectionError(\n `Failed to parse the response from the server: ${fetchError}`,\n );\n } else {\n throw new ConfigDirectorConnectionError(`Connection failed with error: ${fetchError}.`);\n }\n }\n }\n\n private prepareFatalResponseStatusError(\n responseStatus: number,\n errorBody: string | undefined,\n ): ConfigDirectorConnectionError {\n const status = responseStatus ?? 0;\n const headline = `Connection failed with status: ${responseStatus ?? \"unknown\"}`;\n const serverBody = (errorBody?.trim()?.length ?? 0) > 0 ? ` (${errorBody})` : \"\";\n const message = `${headline}${serverBody}. This is an unrecoverable error, retry attempts will be ignored.`;\n return new ConfigDirectorConnectionError(message, status);\n }\n\n private isStatusFatal(status: number | undefined): boolean {\n return !!status && status >= 400 && status < 500;\n }\n\n public on<TName extends keyof TransportEvents>(\n name: TName,\n handler: (payload: TransportEvents[TName]) => void,\n ): void {\n this.eventEmitter.on(name, handler);\n }\n\n public off<TName extends keyof TransportEvents>(\n name: TName,\n handler?: ((payload: TransportEvents[TName]) => void) | undefined,\n ): void {\n this.eventEmitter.off(name, handler);\n }\n\n public clear(): void {\n this.eventEmitter.clear();\n }\n\n public close() {}\n\n public dispose(): void {\n this.close();\n this.clear();\n }\n}\n","import { ConfigDirectorValidationError } from \"./errors\";\n\nexport interface UrlLike {\n toString(): string;\n}\n\nexport type UrlFactory = (input: string, base?: UrlLike) => UrlLike;\n\nexport const defaultUrlFactory: UrlFactory = (input, base) => new URL(input, base?.toString());\n\nexport const parseUrl = (url: string | undefined): URL | undefined => {\n if (!url) {\n return;\n }\n\n try {\n return new URL(url);\n } catch (error) {\n throw new ConfigDirectorValidationError(`Invalid URL '${url}'. Parsing failed: ${error}`);\n }\n};\n","export const CLIENT_BASE_URL = \"https://client-sdk-api.configdirector.com\";\n","import { Emitter } from \"./Emitter\";\nimport { StreamingTransport } from \"./StreamingTransport\";\nimport { getRequestedType, parseConfigValue } from \"../../shared/src/value-parser\";\nimport type {\n ConfigSet,\n ConfigState,\n ConfigStateMap,\n ConfigDirectorContext,\n ConfigDirectorClientOptions,\n ConfigDirectorClient,\n ClientEvents,\n WatchHandler,\n ConfigValueType,\n ConfigDirectorLogger,\n Transport,\n ClientConnectAction,\n IdentifyingSdkOptions,\n InternalClientOptions,\n} from \"./types\";\nimport { createDefaultLogger } from \"./logger\";\nimport { ConfigDirectorValidationError } from \"./errors\";\nimport { PullTransport } from \"./PullTransport\";\nimport type { TelemetryClient } from \"./telemetry\";\nimport { defaultUrlFactory } from \"@shared/url\";\nimport type { UrlFactory, UrlLike } from \"@shared/url\";\nimport { CLIENT_BASE_URL } from \"@shared/constants\";\nconst MAX_EXPONENTIAL_DELAY = 9; // 2^9 = 512 seconds, to cap it to under 10min\n\ntype WatchHandlerWithOptions<T extends ConfigValueType> = {\n handler: WatchHandler<T>;\n defaultValue: T;\n requestedType: string;\n};\n\nexport class DefaultConfigDirectorClient implements ConfigDirectorClient {\n private logger: ConfigDirectorLogger;\n private telemetryClient: TelemetryClient;\n private configSet: ConfigSet | undefined;\n private handlersMap: Map<string, WatchHandlerWithOptions<any>[]> = new Map();\n private transport: Transport;\n private eventEmitter = new Emitter<ClientEvents>();\n private timeout: number;\n private timeoutTimer: ReturnType<typeof setTimeout> | undefined;\n private ready = false;\n private readyPromise: Promise<void> | undefined;\n private readyResolve: (() => void) | undefined;\n private currentContext?: ConfigDirectorContext;\n private streaming: boolean;\n\n constructor(\n telemetryClient: TelemetryClient,\n clientSdkKey: string,\n sdkOptions: IdentifyingSdkOptions,\n clientOptions?: ConfigDirectorClientOptions,\n internalClientOptions?: InternalClientOptions,\n ) {\n this.logger = clientOptions?.logger ?? createDefaultLogger();\n this.timeout = clientOptions?.connection?.timeout ?? 3_000;\n const urlFactory: UrlFactory = internalClientOptions?.urlFactory ?? defaultUrlFactory;\n const baseUrl = this.parseUrl(clientOptions?.connection?.url, urlFactory) ?? CLIENT_BASE_URL;\n this.streaming = clientOptions?.connection?.streaming === false ? false : true;\n const transportConstructor = this.streaming ? StreamingTransport : PullTransport;\n this.telemetryClient = telemetryClient;\n this.transport = new transportConstructor({\n clientSdkKey,\n baseUrl,\n resolveUrl: urlFactory,\n metaContext: {\n ...clientOptions?.metadata,\n sdkName: sdkOptions.sdkName,\n sdkVersion: sdkOptions.sdkVersion,\n userAgent: navigator?.userAgent,\n },\n logger: this.logger,\n fetch: internalClientOptions?.fetch,\n connectionRetryDelay:\n internalClientOptions?.connectionRetryDelay ??\n ((attempt: number) => {\n const seconds = Math.pow(2, Math.min(attempt, MAX_EXPONENTIAL_DELAY));\n return seconds * 1_000;\n }),\n });\n\n this.transport.on(\"configSetReceived\", (configSet: ConfigSet) => {\n this.readyResolve?.();\n const configKeys = Object.keys(configSet.configs);\n if (!this.configSet || configSet.kind == \"full\") {\n this.configSet = configSet;\n this.eventEmitter.emit(\"configsUpdated\", { keys: configKeys });\n this.updateWatchers(configSet.configs);\n } else {\n this.configSet.configs = {\n ...this.configSet.configs,\n ...configSet.configs,\n };\n this.eventEmitter.emit(\"configsUpdated\", { keys: configKeys });\n this.updateWatchers(configSet.configs);\n }\n this.logger.debug(\"[ConfigDirectorClient] ConfigSet updated from server:\", { keys: configKeys });\n });\n }\n\n public async initialize(context?: ConfigDirectorContext) {\n await this.connectToTransport(context, \"initialization\");\n }\n\n public async updateContext(context: ConfigDirectorContext) {\n await this.connectToTransport(context, \"context update\");\n }\n\n private async connectToTransport(context: ConfigDirectorContext | undefined, caller: ClientConnectAction) {\n try {\n this.ready = false;\n this.readyPromise = new Promise<void>((resolve) => {\n this.readyResolve = resolve;\n }).then(() => {\n this.ready = true;\n this.eventEmitter.emit(\"clientReady\", { action: caller });\n this.logger.debug(\"[ConfigDirectorClient] Received initial payload from the server, client is ready\");\n });\n const startTime = new Date().getTime();\n await this.transport.connect(context ?? {}, this.timeout);\n this.currentContext = context;\n this.telemetryClient.updateContext(context);\n\n const elapsedTime = new Date().getTime() - startTime;\n const remainingTimeout = this.timeout - elapsedTime;\n clearTimeout(this.timeoutTimer);\n this.timeoutTimer = undefined;\n if (remainingTimeout > 0) {\n await Promise.race([\n this.readyPromise,\n new Promise<void>((resolve) => {\n this.timeoutTimer = setTimeout(() => resolve(), remainingTimeout);\n }),\n ]).finally(() => clearTimeout(this.timeoutTimer));\n }\n\n if (!this.ready) {\n const warningDetails = this.streaming\n ? \"The client will continue to retry since there were no fatal errors detected. Configs will return the default value until the connection succeeds.\"\n : \"Since the client was configured without streaming, configs may not update and always return the default value.\";\n this.logger.warn(\n `[ConfigDirectorClient] Timed out waiting for ${caller} after ${this.timeout}ms. ${warningDetails}`,\n );\n }\n } catch (error) {\n this.logger.error(`[ConfigDirectorClient] An error occurred during ${caller}: `, error);\n }\n }\n\n private updateWatchers(configsMap: ConfigStateMap) {\n Object.values(configsMap).forEach((v) => this.updateWatchersForConfig(v));\n }\n\n private updateWatchersForConfig(configState: ConfigState) {\n this.handlersMap.get(configState.key)?.forEach((h) => {\n const value = this.getValueFromConfigState(configState.key, configState, h.defaultValue);\n h.handler(value);\n });\n }\n\n public watch<T extends ConfigValueType>(configKey: string, defaultValue: T, callback: WatchHandler<T>) {\n this.validateDefaultValue(defaultValue);\n\n const handlers = this.handlersMap.get(configKey);\n const handlerWithOptions = { handler: callback, defaultValue, requestedType: typeof defaultValue };\n if (handlers) {\n handlers.push(handlerWithOptions);\n } else {\n this.handlersMap.set(configKey, [handlerWithOptions]);\n }\n\n return () => this.unwatch(configKey, callback);\n }\n\n public unwatch<T extends ConfigValueType>(configKey: string, callback?: WatchHandler<T>) {\n const handlers = this.handlersMap.get(configKey);\n if (!handlers) {\n return;\n }\n\n if (callback) {\n const index = handlers.findIndex((h) => h.handler == callback);\n if (index >= 0) {\n handlers?.splice(index, 1);\n }\n } else {\n handlers.splice(0);\n }\n }\n\n public getValue<T extends ConfigValueType>(configKey: string, defaultValue: T): T {\n this.validateDefaultValue(defaultValue);\n\n const configState = this.configSet?.configs[configKey];\n return this.getValueFromConfigState(configKey, configState, defaultValue);\n }\n\n private getValueFromConfigState<T extends ConfigValueType>(\n configKey: string,\n configState: ConfigState | undefined,\n defaultValue: T,\n ): T {\n if (!configState) {\n this.logger.debug(\n `[ConfigDirectorClient] No config state found for '${configKey}', returning default value '${defaultValue}'`,\n );\n this.telemetryClient.evaluatedConfig({\n contextId: this.currentContext?.id,\n key: configKey,\n defaultValue: defaultValue,\n requestedType: getRequestedType(defaultValue),\n evaluatedValue: defaultValue,\n usedDefault: true,\n evaluationReason: \"config-state-missing\",\n });\n return defaultValue;\n }\n\n const parseResult = parseConfigValue<T>(configState, defaultValue);\n this.telemetryClient.evaluatedConfig({\n contextId: this.currentContext?.id,\n key: configKey,\n defaultValue: defaultValue,\n requestedType: parseResult.requestedType,\n evaluatedValue: parseResult.parsedValue,\n usedDefault: parseResult.usedDefault,\n evaluationReason: parseResult.reason,\n });\n this.logger.debug(`[ConfigDirectorClient] Evaluated '${configKey}' to '${parseResult.parsedValue}'`);\n return parseResult.parsedValue;\n }\n\n private parseUrl(url: string | undefined, urlFactory: UrlFactory): UrlLike | undefined {\n if (!url) {\n return;\n }\n\n try {\n return urlFactory(url);\n } catch (error) {\n throw new ConfigDirectorValidationError(`Invalid base URL '${url}'. Parsing failed: ${error}`);\n }\n }\n\n private validateDefaultValue<T extends ConfigValueType>(defaultValue: T) {\n if (defaultValue === undefined || defaultValue === null) {\n throw new ConfigDirectorValidationError(\n \"Invalid default value. The default value for a config must be defined and non-null.\",\n );\n }\n\n if (typeof defaultValue === \"function\") {\n throw new ConfigDirectorValidationError(\n \"Invalid default value. The default value for a config cannot be a function.\",\n );\n }\n }\n\n public get isReady(): boolean {\n return this.ready;\n }\n\n public on<T extends keyof ClientEvents>(eventName: T, handler: (event: ClientEvents[T]) => void): void {\n this.eventEmitter.on(eventName, handler);\n }\n\n public off<T extends keyof ClientEvents>(eventName: T, handler?: (payload: ClientEvents[T]) => void) {\n this.eventEmitter.off(eventName, handler);\n }\n\n public clear() {\n this.logger.debug(\"[ConfigDirectorClient] clear() has been called, removing all observers\");\n this.eventEmitter.clear();\n this.handlersMap.clear();\n }\n\n public unwatchAll() {\n this.handlersMap.clear();\n }\n\n public pauseNetwork(): void {\n this.logger.debug(\"[ConfigDirectorClient] pauseNetwork() called, pausing transport connection\");\n clearTimeout(this.timeoutTimer);\n this.timeoutTimer = undefined;\n this.transport.close();\n this.ready = false;\n }\n\n public async resumeNetwork(): Promise<void> {\n await this.connectToTransport(this.currentContext, \"network resume\");\n }\n\n public async close() {\n this.logger.debug(\"[ConfigDirectorClient] close() has been called, closing connection to server\");\n clearTimeout(this.timeoutTimer);\n this.readyResolve?.();\n this.telemetryClient.close();\n this.transport.close();\n this.ready = false;\n }\n\n public dispose() {\n this.clear();\n this.close();\n }\n}\n","import type { ConfigType, ConfigValueType } from \"../types\";\nimport { type DroppedEvents } from \"./types\";\n\nconst CONFIG_VALUE_MAX_LENGTH = 500;\n\nexport const sanitizeValue = <TV extends ConfigValueType>(value: TV, type?: ConfigType): string => {\n if (type === \"json\") {\n try {\n const json = JSON.stringify(value);\n return djb2Hash(json);\n } catch {\n return value.toString().slice(0, CONFIG_VALUE_MAX_LENGTH);\n }\n }\n\n return value.toString().slice(0, CONFIG_VALUE_MAX_LENGTH);\n};\n\nexport const djb2Hash = (data: string): string => {\n const hash = djb2(new TextEncoder().encode(data));\n return hash.toString(16).padStart(8, \"0\");\n};\n\nconst djb2 = (bytes: Uint8Array): number => {\n let hash = 5381;\n for (let i = 0; i < bytes.length; i++) {\n hash = (hash << 5) + hash + (bytes[i] ?? 0);\n hash = hash >>> 0;\n }\n return hash;\n};\n\nexport const isEventListEmpty = <T extends Record<string | symbol, any[]>>(eventList: T): boolean => {\n const keys = Object.keys(eventList);\n if (keys.length == 0) {\n return true;\n }\n\n for (const key of keys) {\n if ((eventList[key]?.length ?? 0) > 0) {\n return false;\n }\n }\n\n return true;\n};\n\nexport const isDroppedEventsEmpty = (droppedEvents?: DroppedEvents): boolean => {\n if (!droppedEvents) {\n return true;\n }\n const keys = Object.keys(droppedEvents);\n if (keys.length == 0) {\n return true;\n }\n\n for (const key of keys) {\n if ((droppedEvents[key] ?? 0) > 0) {\n return false;\n }\n }\n\n return true;\n};\n","import { type TelemetryEventCollectorOptions } from \"@shared/telemetry/TelemetryEventCollector\";\nimport type { ConfigDirectorContext, ConfigDirectorLogger, ConfigValueType } from \"@js-client-core/types\";\nimport type { TelemetryClient, EvaluatedConfigEvent } from \"@js-client-core/telemetry\";\nimport type {\n TelemetryCloseEvent,\n TelemetryEvaluatedConfigEvent,\n TelemetryFlushEvent,\n TelemetryInitializeEvent,\n TelemetryUpdateContextEvent,\n TelemetryWorkerResponseEvent,\n} from \"./types\";\nimport { sanitizeValue } from \"@shared/telemetry/utils\";\n\nexport class WebWorkerTelemetryClient implements TelemetryClient {\n private readonly logger: ConfigDirectorLogger;\n private worker: Worker;\n private closePromise: Promise<void> | undefined;\n private closeResolve: (() => void) | undefined;\n private readonly visibilityHandler: () => void;\n\n constructor(options: TelemetryEventCollectorOptions) {\n this.logger = options.logger;\n\n const initializeMessage: TelemetryInitializeEvent = {\n type: \"Initialize\",\n payload: {\n sdkKey: options.sdkKey,\n baseUrl: options.baseUrl.toString(),\n evaluationQueueLimit: options.evaluationQueueLimit ?? 1_000,\n initialFlushIntervalDelay: options.initialFlushIntervalDelay ?? 5_000,\n flushIntervalDelay: options.flushIntervalDelay ?? 30_000,\n },\n };\n this.worker = new Worker(new URL(\"./worker.ts\", import.meta.url), { type: \"module\" });\n this.worker.onmessage = (message: MessageEvent<TelemetryWorkerResponseEvent>) => {\n this.handleWorkerEvent(message.data);\n };\n this.worker.postMessage(initializeMessage);\n\n this.visibilityHandler = () => {\n if (document.visibilityState === \"hidden\") {\n this.flush();\n }\n };\n try {\n document.addEventListener(\"visibilitychange\", this.visibilityHandler);\n } catch (error) {\n this.logger.warn(\"[TelemetryEventCollector] Could not configure 'visibilitychange' listener: \", error);\n }\n }\n\n public async updateContext(value: ConfigDirectorContext | undefined) {\n const updateContextMessage: TelemetryUpdateContextEvent = {\n type: \"UpdateContext\",\n payload: {\n context: value,\n },\n };\n this.worker.postMessage(updateContextMessage);\n }\n\n public evaluatedConfig<T extends ConfigValueType>(event: EvaluatedConfigEvent<T>): void {\n const evaluatedConfigMessage: TelemetryEvaluatedConfigEvent = {\n type: \"EvaluatedConfigEvent\",\n payload: this.sanitizeEvaluatedConfigEvent(event),\n };\n this.worker.postMessage(evaluatedConfigMessage);\n }\n\n private sanitizeEvaluatedConfigEvent<T extends ConfigValueType>(\n event: EvaluatedConfigEvent<T>,\n ): EvaluatedConfigEvent<string> {\n return {\n ...event,\n defaultValue: sanitizeValue(event.defaultValue, event.type),\n evaluatedValue: sanitizeValue(event.evaluatedValue, event.type),\n };\n }\n\n private handleWorkerEvent(event: TelemetryWorkerResponseEvent) {\n if (event.type === \"Closed\") {\n this.closeResolve?.();\n return;\n }\n if (!event.payload?.level || !event.payload?.message) {\n return;\n }\n const { level, message, args } = event.payload;\n\n switch (level) {\n case \"debug\":\n this.logger.debug(message, ...args);\n break;\n case \"info\":\n this.logger.info(message, ...args);\n break;\n case \"warn\":\n this.logger.warn(message, ...args);\n break;\n case \"error\":\n this.logger.warn(message, ...args);\n break;\n }\n }\n\n private flush() {\n const flushMessage: TelemetryFlushEvent = {\n type: \"Flush\",\n };\n this.worker.postMessage(flushMessage);\n }\n\n public close(): Promise<void> {\n if (this.closePromise) {\n return this.closePromise;\n }\n\n return this.performClose();\n }\n\n private performClose(): Promise<void> {\n document.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n this.closePromise = new Promise<void>((resolve) => {\n this.closeResolve = resolve;\n const closeMessage: TelemetryCloseEvent = { type: \"Close\" };\n this.worker.postMessage(closeMessage);\n });\n return this.closePromise;\n }\n}\n","import {\n type ConfigDirectorClientOptions,\n type ConfigDirectorClient,\n type IdentifyingSdkOptions,\n createDefaultLogger,\n} from \"@js-client-core/index\";\nimport { WebWorkerTelemetryClient } from \"./telemetry/WebWorkerTelemetryClient\";\nimport { DefaultConfigDirectorClient } from \"@js-client-core/DefaultConfigDirectorClient\";\nimport { defaultUrlFactory, parseUrl } from \"@shared/url\";\nimport { CLIENT_BASE_URL } from \"@shared/constants\";\n\nexport const createBrowserClient = (\n clientSdkKey: string,\n sdkOptions: IdentifyingSdkOptions,\n clientOptions?: ConfigDirectorClientOptions,\n): ConfigDirectorClient => {\n const logger = clientOptions?.logger ?? createDefaultLogger();\n const baseUrl = parseUrl(clientOptions?.connection?.url) ?? CLIENT_BASE_URL;\n const telemetryClient = new WebWorkerTelemetryClient({\n sdkKey: clientSdkKey,\n logger: logger,\n baseUrl,\n urlFactory: defaultUrlFactory,\n });\n\n return new DefaultConfigDirectorClient(telemetryClient, clientSdkKey, sdkOptions, {\n ...clientOptions,\n logger,\n });\n};\n","import type {\n ConfigDirectorClient,\n ConfigDirectorClientOptions} from \"@js-browser-client/index\";\nimport {\n createBrowserClient,\n} from \"@js-browser-client/index\";\n\nexport const createClient = (\n clientSdkKey: string,\n clientOptions?: ConfigDirectorClientOptions,\n): ConfigDirectorClient => {\n return createBrowserClient(\n clientSdkKey,\n { sdkName: \"react-web-sdk\", sdkVersion: \"__VERSION__\" },\n clientOptions,\n );\n};\n\n","import React from \"react\";\nimport type { ConfigDirectorContextData } from \"./types\";\n\nconst createReactContext = () => React.createContext<ConfigDirectorContextData>({status: \"loading\"});\nexport const reactContext = createReactContext();\n","import type {\n ConfigDirectorLogMessageDecorator,\n ConfigDirectorLogger} from \"@js-browser-client/index\";\nimport {\n type ConfigDirectorLoggingLevel,\n createDefaultLogger as createJsSdkLogger,\n} from \"@js-browser-client/index\";\n\nclass MessageDecorator implements ConfigDirectorLogMessageDecorator {\n decorateMessage(message: string): string {\n return `[ConfigDirector:react-web-sdk] ${message}`;\n }\n}\n\nexport const createConsoleLogger = (level: ConfigDirectorLoggingLevel): ConfigDirectorLogger => {\n return createJsSdkLogger(level, new MessageDecorator());\n};\n","import { createClient } from \"./client\";\nimport { useEffect, useState, type ReactNode } from \"react\";\nimport { reactContext } from \"./context\";\nimport { createConsoleLogger } from \"./logger\";\nimport type { ConfigDirectorProviderOptions, ConfigDirectorProviderState } from \"./types\";\n\nexport const withProvider = async (options: ConfigDirectorProviderOptions) => {\n const logger = options.logger ?? createConsoleLogger(\"debug\");\n const client = createClient(options.sdkKey, {\n connection: { url: options.url, timeout: options.timeout },\n metadata: { appName: options.appName, appVersion: options.appVersion },\n logger: logger,\n });\n await client.initialize(options.context);\n\n const ConfigDirectorProvider = ({ children }: { children: ReactNode }) => {\n const [data, setData] = useState<ConfigDirectorProviderState>(() => ({\n client,\n status: client.isReady ? \"ready\" : \"default\",\n }));\n\n useEffect(() => {\n client.on(\"configsUpdated\", () => {\n setData((prevState) => ({ ...prevState, updatedAt: new Date() }));\n });\n client.on(\"clientReady\", () => {\n setData((prevState) => ({ ...prevState, status: \"ready\" }));\n });\n });\n\n return <reactContext.Provider value={data}>{children}</reactContext.Provider>;\n };\n\n return ConfigDirectorProvider;\n};\n","import { createClient } from \"./client\";\nimport { reactContext } from \"./context\";\nimport { createConsoleLogger } from \"./logger\";\nimport { Component, type PropsWithChildren } from \"react\";\nimport type { ConfigDirectorProviderOptions, ConfigDirectorProviderState } from \"./types\";\n\nexport class ConfigDirectorProvider extends Component<\n PropsWithChildren<ConfigDirectorProviderOptions>,\n ConfigDirectorProviderState\n> {\n constructor(props: ConfigDirectorProviderOptions) {\n super(props);\n\n const client = createClient(props.sdkKey, {\n connection: { url: props.url, timeout: props.timeout },\n metadata: { appName: props.appName, appVersion: props.appVersion },\n logger: props.logger ?? createConsoleLogger(\"warn\"),\n });\n\n this.state = { client, status: \"loading\" };\n }\n\n override async componentDidMount(): Promise<void> {\n this.state.client?.on(\"configsUpdated\", () => {\n this.setState({ updatedAt: new Date() });\n });\n this.state.client?.on(\"clientReady\", () => {\n this.setState({ status: \"ready\" });\n });\n await this.state.client?.initialize(this.props.context);\n if (!this.state.client?.isReady) {\n this.setState({ status: \"default\" });\n }\n }\n\n override async componentDidUpdate(\n prevProps: PropsWithChildren<ConfigDirectorProviderOptions>,\n ): Promise<void> {\n if (prevProps.context !== this.props.context) {\n this.setState({ status: \"loading\" });\n await this.state.client?.updateContext(this.props.context ?? {});\n if (!this.state.client?.isReady) {\n this.setState({ status: \"default\" });\n }\n }\n }\n\n override componentWillUnmount(): void {\n this.state.client?.dispose();\n }\n\n override render() {\n return <reactContext.Provider value={this.state}>{this.props.children}</reactContext.Provider>;\n }\n}\n","export class ConfigDirectorReactContextError extends Error {\n public override readonly name: string = \"ConfigDirectorReactContextError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, ConfigDirectorReactContextError.prototype);\n }\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { reactContext } from \"./context\";\nimport type {\n ConfigDirectorContext,\n ConfigValueType,\n} from \"@js-browser-client/index\";\nimport { ConfigDirectorReactContextError } from \"./errors\";\nimport type { ClientStatus } from \"./types\";\n\nconst noContextError = () => {\n return new ConfigDirectorReactContextError(\"The ConfigDirector client was not found in the React context. Please make sure the component using this hook is inside the context of a ConfigDirectorProvider.\");\n};\n\nconst useConfigValue = <T extends ConfigValueType>(\n key: string,\n defaultValue: T,\n): {\n value: T;\n readyStatus: ClientStatus;\n loading: boolean;\n} => {\n const configDirectorReactContext = useContext(reactContext);\n if (!configDirectorReactContext?.client) {\n throw noContextError();\n }\n\n const value = configDirectorReactContext.client.getValue(key, defaultValue);\n\n return { value, readyStatus: configDirectorReactContext.status, loading: configDirectorReactContext.status === \"loading\" };\n};\n\nconst useConfigDirectorContext = () => {\n const configDirectorReactContext = useContext(reactContext);\n if (!configDirectorReactContext?.client) {\n throw noContextError();\n }\n\n const updateContext = async (context: ConfigDirectorContext) => {\n await configDirectorReactContext.client?.updateContext(context);\n };\n\n return { updateContext };\n};\n\nconst useConfigDirectorClient = () => {\n const configDirectorReactContext = useContext(reactContext);\n if (!configDirectorReactContext?.client) {\n throw noContextError();\n }\n\n return { client: configDirectorReactContext.client };\n};\n\nexport { useConfigValue, useConfigDirectorContext, useConfigDirectorClient };\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@configdirector/react-web-sdk",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "React web client SDK for ConfigDirector. ConfigDirector is a remote configuration and feature flag service.",
5
5
  "license": "MIT",
6
6
  "author": "ConfigDirector",
@@ -63,7 +63,7 @@
63
63
  "@types/react": "^19.2.14",
64
64
  "@vitest/browser-playwright": "^4.1.2",
65
65
  "@vitest/coverage-v8": "^4.1.2",
66
- "eslint": "^10.1.0",
66
+ "eslint": "^10.2.0",
67
67
  "globals": "^17.3.0",
68
68
  "msw": "^2.12.9",
69
69
  "playwright": "^1.59.1",