librelinkup-api-client
Version:
An unofficial API for Libre Link Up (glucose monitoring system/CGM)
5 lines (3 loc) • 40.8 kB
JavaScript
var O=[0,1,2,3,4,5],H=["NotComputable","SingleDown","FortyFiveDown","Flat","FortyFiveUp","SingleUp"];var B=(F)=>({...F,created:j(F.created),lastLogin:j(F.lastLogin),dateOfBirth:j(F.dateOfBirth)}),j=(F)=>new Date(F*1000),N=(F,x)=>{let z=F.ValueInMgPerDl,Q=x.targetHigh<z,V=x.targetLow>z;return Object.freeze({timestamp:new Date(F.Timestamp),value:z,measurementColor:F.MeasurementColor,isHigh:Q,isLow:V,trend:S(F.TrendArrow)})};var S=(F,x=3)=>F??x;var Y=(F)=>{let x=new TextEncoder().encode(F);return crypto.subtle.digest("SHA-256",x).then((z)=>{return Array.from(new Uint8Array(z)).map((V)=>V.toString(16).padStart(2,"0")).join("")})};var P=Object.freeze({targetHigh:150,targetLow:70});class W{_raw;_options;timestamp;value;measurementColor;isHigh;isLow;trend;constructor(F,x=P){this._raw=F;this._options=x;let z=N(F,x);this.value=z.value,this.timestamp=z.timestamp,this.measurementColor=z.measurementColor,this.isHigh=z.isHigh,this.isLow=z.isLow,this.trend=z.trend}get mmol(){return(this.value/18).toFixed(1)}get mgDl(){return this.value}get trendType(){return H[this.trend]}}class D{apiUrl;accessToken=null;patientId=null;lluVersion;credentials;options;cache=new Map;constructor(F){if(!F?.email||!F?.password)throw Error("Email and password are required to create a LibreLinkClient instance.");this.credentials={email:F.email,password:F.password},this.apiUrl=F.apiUrl??q.apiUrl,this.patientId=F.patientId??null,this.lluVersion=F.lluVersion??q.lluVersion,this.options={...q,...F}}get me(){if(!this.cache.has("user"))return null;return this.cache.get("user")}async login(){let{email:F,password:x}=this.credentials;try{let z=await this._fetcher("llu/auth/login",{method:"POST",body:JSON.stringify({email:F,password:x})});if(z.status===2)throw Error("Invalid credentials. Please ensure that the email and password work with the LibreLinkUp app.");if(!z.data)throw Error("No data returned from Libre Link Up API.");if("redirect"in z.data){let Q=await this.findRegion(z.data.region);return this.apiUrl=Q,await this.login()}if(this.accessToken=z.data.authTicket?.token,z.data.user)this.setCache("user",B(z.data.user));return z}catch(z){throw Error(`Error logging into Libre Link Up API. ${z.message}`)}}async read(){try{let F=await this.fetchReading();return new W(F.data?.connection.glucoseItem,F.data.connection)}catch(F){throw Error(`Error reading data from Libre Link Up API. ${F.message}`)}}async history(){try{let F=await this.fetchReading();return F.data.graphData.map((z)=>new W(z,F.data.connection))}catch(F){throw Error(`Error reading data from Libre Link Up API. ${F.message}`)}}async logbook(){try{return(await this.fetchLogbook()).data.map((z)=>new W(z))}catch(F){throw Error(`Error reading data from Libre Link Up API. ${F.message}`)}}async*stream(F=90000){while(!0)try{yield await this.read(),await new Promise((z)=>setTimeout(z,F))}catch(x){throw x}}async fetchReading(){try{let F=await this.getPatientId(),x={"Account-Id":this.me?.id?await Y(this.me.id):""};return await this._fetcher(`${"llu/connections"}/${F}/graph`,{headers:x})}catch(F){throw Error(`Error fetching reading from Libre Link Up API. ${F.message}`)}}async fetchLogbook(){try{let F=await this.getPatientId(),x={"Account-Id":this.me?.id?await Y(this.me.id):""};return await this._fetcher(`${"llu/connections"}/${F}/logbook`,{headers:x})}catch(F){throw Error(`Error fetching reading from Libre Link Up API. ${F.message}`)}}async fetchConnections(){try{if(this.cache.has("connections"))return this.cache.get("connections");let F={"Account-Id":this.me?.id?await Y(this.me.id):""},x=await this._fetcher("llu/connections",{headers:F});if(x?.data?.length)this.setCache("connections",x);return x}catch(F){throw Error(`Error fetching connections from Libre Link Up API. ${F.message}`)}}async getPatientId(){let F=await this.fetchConnections();if(!F.data?.length)throw Error("No connections found. Please ensure that you have a connection with the LibreLinkUp app.");let x=F.data[0].patientId;if(this.patientId)F.data.find((z)=>z.patientId===this.patientId)?.patientId;if(!x)throw Error(`Patient ID not found in connections. (${this.patientId})`);return x}async findRegion(F){try{let z=(await this._fetcher("llu/config/country?country=DE")).data?.regionalMap[F]?.lslApi;if(!z)throw Error("Region not found in Libre Link Up API.");return z}catch(x){throw Error(`Error finding region in Libre Link Up API. ${x.message}`)}}async _fetcher(F,x={headers:{}},z=!1){let Q={...x.headers,Authorization:this.accessToken?`Bearer ${this.accessToken}`:"",product:"llu.android",version:this.lluVersion,"accept-encoding":"gzip","cache-control":"no-cache",connection:"Keep-Alive","content-type":"application/json"},V=Object.freeze({...x,headers:Q});try{let J=await fetch(`${this.apiUrl}/${F}`,V);if(!J.ok){let X=await J.json(),$=X?.message??JSON.stringify(X,null,2);if(J.status===429)throw Error(`Too many requests. Please wait before trying again. ${$}`);if(!z&&this.isTokenExpiredError(J.status,$))try{return this.accessToken=null,this.cache.delete("user"),await this.login(),await this._fetcher(F,x,!0)}catch(G){throw Error(`Token expired and automatic login failed: ${G.message}`)}throw Error(`Error fetching data from Libre Link Up API with status ${J.status}. ${$}`)}return await J.json()}catch(J){let Z=J;if(!z&&this.isTokenExpiredError(0,Z.message))try{return this.accessToken=null,this.cache.delete("user"),await this.login(),await this._fetcher(F,x,!0)}catch(X){throw Error(`Token expired and automatic login failed: ${X.message}`)}throw Error(`Error processing request to Libre Link Up API. ${Z.message}`)}}isTokenExpiredError(F,x){let Q=["token","jwt","unauthorized","authentication","expired","invalid token","access denied","malformed jwt","missing jwt"].some((J)=>x.toLowerCase().includes(J.toLowerCase()));return Q||(F===401||F===403||F===400&&Q)}setCache(F,x){if(!this.options.cache)return;this.cache.set(F,x)}clearCache(){this.cache.clear()}getAuthStatus(){return{hasToken:!!this.accessToken,tokenLength:this.accessToken?.length||0,hasUser:!!this.me,userId:this.me?.id||null}}}var q={apiUrl:"https://api-us.libreview.io",cache:!0,lluVersion:"4.7.0"};export{D as LibreLinkClient,W as GlucoseReading};
//# debugId=0FA2C081D4E7198164756E2164756E21
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2NvbnN0YW50cy50cyIsICIuLi9zcmMvdXRpbHMudHMiLCAiLi4vc3JjL3JlYWRpbmcudHMiLCAiLi4vc3JjL2NsaWVudC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsKICAgICJpbXBvcnQgeyBUcmVuZCwgVHJlbmRUeXBlIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuZXhwb3J0IGNvbnN0IFRSRU5EX01BUDogVHJlbmRbXSA9IFtcbiAgICBUcmVuZC5Ob3RDb21wdXRhYmxlLFxuICAgIFRyZW5kLlNpbmdsZURvd24sXG4gICAgVHJlbmQuRm9ydHlGaXZlRG93bixcbiAgICBUcmVuZC5GbGF0LFxuICAgIFRyZW5kLkZvcnR5Rml2ZVVwLFxuICAgIFRyZW5kLlNpbmdsZVVwLFxuXTtcblxuZXhwb3J0IGNvbnN0IFRSRU5EX1RZUEVfTUFQOiBUcmVuZFR5cGVbXSA9IFtcbiAgICBcIk5vdENvbXB1dGFibGVcIixcbiAgICBcIlNpbmdsZURvd25cIixcbiAgICBcIkZvcnR5Rml2ZURvd25cIixcbiAgICBcIkZsYXRcIixcbiAgICBcIkZvcnR5Rml2ZVVwXCIsXG4gICAgXCJTaW5nbGVVcFwiLFxuXTsiLAogICAgImltcG9ydCB7IEdsdWNvc2VSZWFkaW5nIH0gZnJvbSBcIi4vcmVhZGluZ1wiO1xuaW1wb3J0IHsgUmF3R2x1Y29zZVJlYWRpbmcsIExpYnJlVXNlciwgTWVhc3VyZW1lbnRDb2xvciwgVHJlbmQgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIFBhcnNlIGEgTGlicmUgVXNlciBvYmplY3QuXG4gKiBAcGFyYW0gdXNlciBUaGUgdXNlciBvYmplY3QgdG8gcGFyc2UuXG4gKiBAcmV0dXJucyBUaGUgcGFyc2VkIHVzZXIgb2JqZWN0LlxuICovXG5leHBvcnQgY29uc3QgcGFyc2VVc2VyID0gKHVzZXI6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBMaWJyZVVzZXIgPT4gKHtcbiAgICAuLi4odXNlciBhcyBMaWJyZVVzZXIpLFxuICAgIGNyZWF0ZWQ6IHBhcnNlVW5peFRpbWVzdGFtcCh1c2VyLmNyZWF0ZWQgYXMgdW5rbm93biBhcyBudW1iZXIpLFxuICAgIGxhc3RMb2dpbjogcGFyc2VVbml4VGltZXN0YW1wKHVzZXIubGFzdExvZ2luIGFzIHVua25vd24gYXMgbnVtYmVyKSxcbiAgICBkYXRlT2ZCaXJ0aDogcGFyc2VVbml4VGltZXN0YW1wKHVzZXIuZGF0ZU9mQmlydGggYXMgdW5rbm93biBhcyBudW1iZXIpLFxufSk7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFBhcnNlIHVuaXggdGltZXN0YW1wcyB0byBEYXRlIG9iamVjdHMuXG4gKiBAcGFyYW0gdGltZXN0YW1wIFRoZSB1bml4IHRpbWVzdGFtcCB0byBwYXJzZS5cbiAqIEByZXR1cm5zIFRoZSBwYXJzZWQgZGF0ZS5cbiAqL1xuZXhwb3J0IGNvbnN0IHBhcnNlVW5peFRpbWVzdGFtcCA9ICh0aW1lc3RhbXA6IG51bWJlcikgPT4gbmV3IERhdGUodGltZXN0YW1wICogMTAwMCk7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFBhcnNlIGEgZ2x1Y29zZSByZWFkaW5nLlxuICogQHBhcmFtIHJhd1JlYWRpbmcgVGhlIHJhdyBnbHVjb3NlIHJlYWRpbmcgY29taW5nIGZyb20gdGhlIHNlcnZlciB0byBwYXJzZS5cbiAqIEBwYXJhbSBjb25uZWN0aW9uIFRoZSBjb25uZWN0aW9uIG9iamVjdCB0byB1c2UgZm9yIHBhcnNpbmcuIFVzZWQgZm9yIGNhbGN1bGF0aW5nIGlzSGlnaCBhbmQgaXNMb3cuXG4gKiBAcmV0dXJucyBUaGUgcGFyc2VkIGdsdWNvc2UgcmVhZGluZy5cbiAqL1xuZXhwb3J0IGNvbnN0IHBhcnNlR2x1Y29zZVJlYWRpbmcgPSAocmF3UmVhZGluZzogUmF3R2x1Y29zZVJlYWRpbmcsIG9wdGlvbnM6IHsgdGFyZ2V0SGlnaDogbnVtYmVyLCB0YXJnZXRMb3c6IG51bWJlciB9KSA9PiB7XG4gICAgY29uc3QgdmFsdWUgPSByYXdSZWFkaW5nLlZhbHVlSW5NZ1BlckRsO1xuXG4gICAgLy8gISBDYWxjdWxhdGVzIHRoZSBpc0hpZ2ggYW5kIGlzTG93IHByb3BlcnRpZXMgYmFzZWQgb24gdGhlIHRhcmdldEhpZ2ggYW5kIHRhcmdldExvdyB2YWx1ZXMuIFRoZSB0d28gdmFsdWVzIGNvbWluZyBmcm9tIExpYnJlIExpbmsgVXAgc2VlbXMgdG8gYmUgaW5jb3JyZWN0LlxuICAgIGNvbnN0IGlzSGlnaCA9IG9wdGlvbnMudGFyZ2V0SGlnaCA8IHZhbHVlO1xuICAgIGNvbnN0IGlzTG93ID0gb3B0aW9ucy50YXJnZXRMb3cgPiB2YWx1ZTtcbiAgIFxuICAgIGNvbnN0IHBhcnNlZFJlYWRpbmcgPSBPYmplY3QuZnJlZXplKHtcbiAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZShyYXdSZWFkaW5nLlRpbWVzdGFtcCksXG4gICAgICAgIHZhbHVlLFxuICAgICAgICBtZWFzdXJlbWVudENvbG9yOiByYXdSZWFkaW5nLk1lYXN1cmVtZW50Q29sb3IgYXMgTWVhc3VyZW1lbnRDb2xvcixcbiAgICAgICAgaXNIaWdoLFxuICAgICAgICBpc0xvdyxcbiAgICAgICAgdHJlbmQ6IHBhcnNlVHJlbmQocmF3UmVhZGluZy5UcmVuZEFycm93KVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHBhcnNlZFJlYWRpbmc7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFNvcnQgYnkgdGltZXN0YW1wLlxuICogQHBhcmFtIGEgVGhlIGZpcnN0IGl0ZW0gdG8gY29tcGFyZS5cbiAqIEBwYXJhbSBiIFRoZSBzZWNvbmQgaXRlbSB0byBjb21wYXJlLlxuICogQHJldHVybnMgVGhlIGNvbXBhcmlzb24gcmVzdWx0LlxuICogXG4gKiBAZXhhbXBsZSBcbiAqIC5zb3J0KHNvcnRCeVRpbWVzdGFtcClcbiAqL1xuZXhwb3J0IGNvbnN0IHNvcnRCeVRpbWVzdGFtcCA9IChhOiBHbHVjb3NlUmVhZGluZywgYjogR2x1Y29zZVJlYWRpbmcpID0+IGEudGltZXN0YW1wLmdldFRpbWUoKSAtIGIudGltZXN0YW1wLmdldFRpbWUoKTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUGFyc2UgdGhlIHRyZW5kIG9mIGdsdWNvc2UgcmVhZGluZy5cbiAqIEBwYXJhbSB0cmVuZCBUaGUgY3VycmVudCB0cmVuZC5cbiAqIEBwYXJhbSBkZWZhdWx0VHJlbmQgVGhlIGRlZmF1bHQgdHJlbmQgdG8gdXNlIGlmIHRyZW5kIGlzIHVuZGVmaW5lZC5cbiAqIEByZXR1cm5zIFRoZSBwYXJzZWQgdHJlbmQuXG4gKi9cbmV4cG9ydCBjb25zdCBwYXJzZVRyZW5kID0gKHRyZW5kOiBudW1iZXIgfCB1bmRlZmluZWQsIGRlZmF1bHRUcmVuZDogVHJlbmQgPSBUcmVuZC5GbGF0KSA9PiB0cmVuZCBhcyBUcmVuZCA/PyBkZWZhdWx0VHJlbmQ7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEdldCB0aGUgdHJlbmQgdHlwZSBvZiBnbHVjb3NlIHJlYWRpbmcuXG4gKiBAcGFyYW0gdHJlbmQgVGhlIGN1cnJlbnQgdHJlbmQuXG4gKiBAcGFyYW0gZGVmYXVsdFRyZW5kIFRoZSBkZWZhdWx0IHRyZW5kIHRvIHVzZSBpZiB0cmVuZCBpcyB1bmRlZmluZWQuXG4gKiBAcmV0dXJucyBUaGUgdHJlbmQgdHlwZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGdldFRyZW5kVHlwZSA9ICh0cmVuZDogbnVtYmVyIHwgdW5kZWZpbmVkLCBkZWZhdWx0VHJlbmQ6IFRyZW5kID0gVHJlbmQuRmxhdCkgPT4gVHJlbmRbcGFyc2VUcmVuZCh0cmVuZCwgZGVmYXVsdFRyZW5kKV07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVuY3J5cHQgbWVzc2FnZSBpbiBzaGEyNTYuXG4gKiBAcGFyYW0gbWVzc2FnZSBUaGUgbWVzc2FnZSB0byBiZSBlbmNyeXB0ZWQuXG4gKiBAcmV0dXJucyBUaGUgZW5jcnlwdGVkIG1lc3NhZ2UuXG4gKi9cbmV4cG9ydCBjb25zdCBlbmNyeXB0U2hhMjU2ID0gKG1lc3NhZ2U6IHN0cmluZykgPT4ge1xuICBjb25zdCBidWZmZXIgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUobWVzc2FnZSk7XG5cbiAgcmV0dXJuIGNyeXB0by5zdWJ0bGUuZGlnZXN0KCdTSEEtMjU2JywgYnVmZmVyKS50aGVuKGhhc2hCdWZmZXIgPT4ge1xuICAgIGNvbnN0IGhhc2hBcnJheSA9IEFycmF5LmZyb20obmV3IFVpbnQ4QXJyYXkoaGFzaEJ1ZmZlcikpO1xuICAgIHJldHVybiBoYXNoQXJyYXkubWFwKGIgPT4gYi50b1N0cmluZygxNikucGFkU3RhcnQoMiwgJzAnKSkuam9pbignJyk7XG4gIH0pO1xufSIsCiAgICAiaW1wb3J0IHsgVFJFTkRfVFlQRV9NQVAgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IE1lYXN1cmVtZW50Q29sb3IsIFJhd0dsdWNvc2VSZWFkaW5nLCBUcmVuZCwgVHJlbmRUeXBlIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IHBhcnNlR2x1Y29zZVJlYWRpbmcgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5jb25zdCBERUZBVUxUX09QVElPTlMgPSBPYmplY3QuZnJlZXplKHtcbiAgICB0YXJnZXRIaWdoOiAxNTAsXG4gICAgdGFyZ2V0TG93OiA3MFxufSk7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgZ2x1Y29zZSByZWFkaW5nIGNsYXNzLlxuICovXG5leHBvcnQgY2xhc3MgR2x1Y29zZVJlYWRpbmcge1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBUaGUgdGltZXN0YW1wIG9mIHRoZSBnbHVjb3NlIHJlYWRpbmcuXG4gICAgICovXG4gICAgcHVibGljIHRpbWVzdGFtcDogRGF0ZTtcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gVGhlIHZhbHVlIG9mIHRoZSBnbHVjb3NlIHJlYWRpbmcgaW4gbWcvZEwuXG4gICAgICovXG4gICAgcHVibGljIHZhbHVlOiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFRoZSBtZWFzdXJlbWVudCBjb2xvciBvZiB0aGUgZ2x1Y29zZSByZWFkaW5nLiBTZWUge0BsaW5rIE1lYXN1cmVtZW50Q29sb3J9LlxuICAgICAqL1xuICAgIHB1YmxpYyBtZWFzdXJlbWVudENvbG9yOiBNZWFzdXJlbWVudENvbG9yO1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRoZSBnbHVjb3NlIHJlYWRpbmcgaXMgaGlnaCwgYmFzZWQgb24gdGhlIHBhdGllbnQncyBzZXR0aW5ncy4gQ2FsY3VsYXRlZCBieSB0aGUgbGlicmFyeS5cbiAgICAgKi9cbiAgICBwdWJsaWMgaXNIaWdoOiBib29sZWFuO1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRoZSBnbHVjb3NlIHJlYWRpbmcgaXMgbG93LCBiYXNlZCBvbiB0aGUgcGF0aWVudCdzIHNldHRpbmdzLiBDYWxjdWxhdGVkIGJ5IHRoZSBsaWJyYXJ5LlxuICAgICAqL1xuICAgIHB1YmxpYyBpc0xvdzogYm9vbGVhbjtcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gVGhlIHRyZW5kIG9mIHRoZSBnbHVjb3NlIHJlYWRpbmcuIFNlZSB7QGxpbmsgVHJlbmR9LlxuICAgICAqL1xuICAgIHB1YmxpYyB0cmVuZDogVHJlbmQ7XG5cbiAgICBjb25zdHJ1Y3RvcihwdWJsaWMgX3JhdzogUmF3R2x1Y29zZVJlYWRpbmcsIHB1YmxpYyBfb3B0aW9uczogeyB0YXJnZXRIaWdoOiBudW1iZXIsIHRhcmdldExvdzogbnVtYmVyIH0gPSBERUZBVUxUX09QVElPTlMpIHtcbiAgICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VHbHVjb3NlUmVhZGluZyhfcmF3LCBfb3B0aW9ucyk7XG5cbiAgICAgICAgdGhpcy52YWx1ZSA9IHBhcnNlZC52YWx1ZTtcbiAgICAgICAgdGhpcy50aW1lc3RhbXAgPSBwYXJzZWQudGltZXN0YW1wO1xuICAgICAgICB0aGlzLm1lYXN1cmVtZW50Q29sb3IgPSBwYXJzZWQubWVhc3VyZW1lbnRDb2xvcjtcbiAgICAgICAgdGhpcy5pc0hpZ2ggPSBwYXJzZWQuaXNIaWdoO1xuICAgICAgICB0aGlzLmlzTG93ID0gcGFyc2VkLmlzTG93O1xuICAgICAgICB0aGlzLnRyZW5kID0gcGFyc2VkLnRyZW5kO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBUaGUgbW1vbCB2YWx1ZSBvZiB0aGUgZ2x1Y29zZSByZWFkaW5nLlxuICAgICAqL1xuICAgIGdldCBtbW9sKCkge1xuICAgICAgICByZXR1cm4gKHRoaXMudmFsdWUgLyAxOCkudG9GaXhlZCgxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gVGhlIG1nL2RMIHZhbHVlIG9mIHRoZSBnbHVjb3NlIHJlYWRpbmcuXG4gICAgICovXG4gICAgZ2V0IG1nRGwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBUaGUgdHlwZSBvZiB0aGUgdHJlbmQuIHsgQHNlZSBUcmVuZFR5cGUgfVxuICAgICAqL1xuICAgIGdldCB0cmVuZFR5cGUoKTogVHJlbmRUeXBlIHtcbiAgICAgICAgcmV0dXJuIFRSRU5EX1RZUEVfTUFQW3RoaXMudHJlbmRdO1xuICAgIH1cbn0iLAogICAgImltcG9ydCB7IEdsdWNvc2VSZWFkaW5nIH0gZnJvbSBcIi4vcmVhZGluZ1wiO1xuaW1wb3J0IHsgTGlicmVMaW5rVXBFbmRwb2ludHMsIExpYnJlTG9naW5SZXNwb25zZSwgTGlicmVSZXNwb25zZSwgTGlicmVSZWRpcmVjdFJlc3BvbnNlLCBMaWJyZVVzZXIsIExpYnJlQ29ubmVjdGlvbiwgTGlicmVDb25uZWN0aW9uUmVzcG9uc2UsIExpYnJlTG9nYm9va1Jlc3BvbnNlLCBSYXdHbHVjb3NlUmVhZGluZyB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBlbmNyeXB0U2hhMjU2LCBwYXJzZVVzZXIgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG4vKipcbiAqIEEgY2xhc3MgZm9yIGludGVyYWN0aW5nIHdpdGggdGhlIExpYnJlIExpbmsgVXAgQVBJLlxuICovXG5leHBvcnQgY2xhc3MgTGlicmVMaW5rQ2xpZW50IHtcbiAgcHJpdmF0ZSBhcGlVcmw6IHN0cmluZztcbiAgcHJpdmF0ZSBhY2Nlc3NUb2tlbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcGF0aWVudElkOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBsbHVWZXJzaW9uOiBzdHJpbmc7XG4gIHByaXZhdGUgY3JlZGVudGlhbHM6IHsgZW1haWw6IHN0cmluZzsgcGFzc3dvcmQ6IHN0cmluZyB9O1xuICBwcml2YXRlIG9wdGlvbnM6IExpYnJlTGlua0NsaWVudE9wdGlvbnM7XG5cbiAgLy8gQSBjYWNoZSBmb3Igc3RvcmluZyBmZXRjaGVkIGRhdGEuXG4gIHByaXZhdGUgY2FjaGUgPSBuZXcgTWFwPHN0cmluZywgYW55PigpO1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IExpYnJlTGlua0NsaWVudE9wdGlvbnMpIHtcbiAgICBpZiAoIW9wdGlvbnM/LmVtYWlsIHx8ICFvcHRpb25zPy5wYXNzd29yZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRW1haWwgYW5kIHBhc3N3b3JkIGFyZSByZXF1aXJlZCB0byBjcmVhdGUgYSBMaWJyZUxpbmtDbGllbnQgaW5zdGFuY2UuXCIpO1xuICAgIH1cblxuICAgIHRoaXMuY3JlZGVudGlhbHMgPSB7XG4gICAgICBlbWFpbDogb3B0aW9ucy5lbWFpbCxcbiAgICAgIHBhc3N3b3JkOiBvcHRpb25zLnBhc3N3b3JkXG4gICAgfTtcblxuICAgIHRoaXMuYXBpVXJsID0gb3B0aW9ucy5hcGlVcmwgPz8gREVGQVVMVF9PUFRJT05TLmFwaVVybCE7XG4gICAgdGhpcy5wYXRpZW50SWQgPSBvcHRpb25zLnBhdGllbnRJZCA/PyBudWxsO1xuICAgIHRoaXMubGx1VmVyc2lvbiA9IG9wdGlvbnMubGx1VmVyc2lvbiA/PyBERUZBVUxUX09QVElPTlMubGx1VmVyc2lvbiE7XG5cbiAgICAvLyBNZXJnZSB0aGUgb3B0aW9ucyB3aXRoIHRoZSBkZWZhdWx0IG9wdGlvbnMuXG4gICAgdGhpcy5vcHRpb25zID0geyAuLi5ERUZBVUxUX09QVElPTlMsIC4uLm9wdGlvbnMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0IHRoZSB1c2VyIGRhdGEuIE9ubHkgYXZhaWxhYmxlIGFmdGVyIGxvZ2dpbmcgaW4uXG4gICAqL1xuICBwdWJsaWMgZ2V0IG1lKCk6IExpYnJlVXNlciB8IG51bGwge1xuICAgIGlmICghdGhpcy5jYWNoZS5oYXMoXCJ1c2VyXCIpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXQoXCJ1c2VyXCIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMb2cgaW50byB0aGUgTGlicmUgTGluayBVcCBBUEkgdXNpbmcgdGhlIHByb3ZpZGVkIGNyZWRlbnRpYWxzLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGxvZ2luKCk6IFByb21pc2U8TGlicmVMb2dpblJlc3BvbnNlPiB7XG4gICAgY29uc3QgeyBlbWFpbCwgcGFzc3dvcmQgfSA9IHRoaXMuY3JlZGVudGlhbHM7XG5cbiAgICB0cnkge1xuICAgICAgdHlwZSBMb2dpblJlc3BvbnNlID0gTGlicmVMb2dpblJlc3BvbnNlIHwgTGlicmVSZWRpcmVjdFJlc3BvbnNlO1xuXG4gICAgICAvLyBBdHRlbXB0IHRvIGxvZ2luIHRvIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS5cbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fZmV0Y2hlcjxMb2dpblJlc3BvbnNlPihMaWJyZUxpbmtVcEVuZHBvaW50cy5Mb2dpbiwge1xuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgZW1haWwsXG4gICAgICAgICAgcGFzc3dvcmRcbiAgICAgICAgfSksXG4gICAgICB9KTtcblxuICAgICAgLy8gSWYgdGhlIHN0YXR1cyBpcyAyLCBtZWFucyB0aGUgY3JlZGVudGlhbHMgYXJlIGludmFsaWQuXG4gICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSAyKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIGNyZWRlbnRpYWxzLiBQbGVhc2UgZW5zdXJlIHRoYXQgdGhlIGVtYWlsIGFuZCBwYXNzd29yZCB3b3JrIHdpdGggdGhlIExpYnJlTGlua1VwIGFwcC5cIik7XG5cbiAgICAgIGlmICghcmVzcG9uc2UuZGF0YSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gZGF0YSByZXR1cm5lZCBmcm9tIExpYnJlIExpbmsgVXAgQVBJLlwiKTtcblxuICAgICAgLy8gSWYgdGhlIHJlc3BvbnNlIGNvbnRhaW5zIGEgcmVkaXJlY3QsIHVwZGF0ZSB0aGUgcmVnaW9uIGFuZCB0cnkgYWdhaW4uXG4gICAgICBpZiAoXCJyZWRpcmVjdFwiIGluIHJlc3BvbnNlLmRhdGEpIHtcbiAgICAgICAgY29uc3QgcmVnaW9uVXJsID0gYXdhaXQgdGhpcy5maW5kUmVnaW9uKHJlc3BvbnNlLmRhdGEucmVnaW9uKTtcbiAgICAgICAgLy8gVXBkYXRlIHRoZSBBUEkgVVJMIHdpdGggdGhlIHJlZ2lvbiB1cmwuXG4gICAgICAgIHRoaXMuYXBpVXJsID0gcmVnaW9uVXJsO1xuXG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmxvZ2luKCk7XG4gICAgICB9XG5cbiAgICAgIC8vIFNldCB0aGUgYWNjZXNzIHRva2VuIGZvciBmdXR1cmUgcmVxdWVzdHMuXG4gICAgICB0aGlzLmFjY2Vzc1Rva2VuID0gcmVzcG9uc2UuZGF0YS5hdXRoVGlja2V0Py50b2tlbjtcblxuICAgICAgLy8gQ2FjaGUgdGhlIHVzZXIgZGF0YSBmb3IgZnV0dXJlIHVzZS4gTG9nIGluIGFnYWluIHRvIHJlZnJlc2ggdGhlIHVzZXIgZGF0YS5cbiAgICAgIGlmIChyZXNwb25zZS5kYXRhLnVzZXIpIHtcbiAgICAgICAgdGhpcy5zZXRDYWNoZShcInVzZXJcIiwgcGFyc2VVc2VyKHJlc3BvbnNlLmRhdGEudXNlcikpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzcG9uc2UgYXMgTGlicmVMb2dpblJlc3BvbnNlO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc3QgZXJyb3IgPSBlcnIgYXMgRXJyb3I7XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgbG9nZ2luZyBpbnRvIExpYnJlIExpbmsgVXAgQVBJLiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWFkIHRoZSBkYXRhIGZyb20gdGhlIExpYnJlIExpbmsgVXAgQVBJLlxuICAgKiBAcmV0dXJucyBUaGUgbGF0ZXN0IGdsdWNvc2UgbWVhc3VyZW1lbnQgZnJvbSB0aGUgTGlicmUgTGluayBVcCBBUEkuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVhZCgpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmZldGNoUmVhZGluZygpO1xuXG4gICAgICAvLyBQYXJzZSBhbmQgcmV0dXJuIHRoZSBsYXRlc3QgZ2x1Y29zZSBpdGVtIGZyb20gdGhlIHJlc3BvbnNlLlxuICAgICAgcmV0dXJuIG5ldyBHbHVjb3NlUmVhZGluZyhyZXNwb25zZS5kYXRhPy5jb25uZWN0aW9uLmdsdWNvc2VJdGVtLCByZXNwb25zZS5kYXRhLmNvbm5lY3Rpb24pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc3QgZXJyb3IgPSBlcnIgYXMgRXJyb3I7XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgcmVhZGluZyBkYXRhIGZyb20gTGlicmUgTGluayBVcCBBUEkuICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlYWQgdGhlIGhpc3RvcnkgZGF0YSBmcm9tIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBoaXN0b3J5KCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZmV0Y2hSZWFkaW5nKCk7XG5cbiAgICAgIGNvbnN0IGxpc3QgPSByZXNwb25zZS5kYXRhLmdyYXBoRGF0YS5tYXAoKGl0ZW06IFJhd0dsdWNvc2VSZWFkaW5nKSA9PiBuZXcgR2x1Y29zZVJlYWRpbmcoaXRlbSwgcmVzcG9uc2UuZGF0YS5jb25uZWN0aW9uKSk7XG5cbiAgICAgIHJldHVybiBsaXN0O1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc3QgZXJyb3IgPSBlcnIgYXMgRXJyb3I7XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgcmVhZGluZyBkYXRhIGZyb20gTGlicmUgTGluayBVcCBBUEkuICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlYWQgdGhlIGxvZ2Jvb2sgZGF0YSBmcm9tIG1hbnVhbCBzY2FucyBmcm9tIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBsb2dib29rKCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZmV0Y2hMb2dib29rKCk7XG5cbiAgICAgIGNvbnN0IGxpc3QgPSByZXNwb25zZS5kYXRhLm1hcCgoaXRlbTogUmF3R2x1Y29zZVJlYWRpbmcpID0+IG5ldyBHbHVjb3NlUmVhZGluZyhpdGVtKSk7XG5cbiAgICAgIHJldHVybiBsaXN0O1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc3QgZXJyb3IgPSBlcnIgYXMgRXJyb3I7XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgcmVhZGluZyBkYXRhIGZyb20gTGlicmUgTGluayBVcCBBUEkuICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gU3RyZWFtIHRoZSByZWFkaW5ncyBmcm9tIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS5cbiAgICAgKiBAcGFyYW0gaW50ZXJ2YWxNcyBUaGUgaW50ZXJ2YWwgYmV0d2VlbiBlYWNoIHJlYWRpbmcuIERlZmF1bHQgaXMgOTAgc2Vjb25kcy5cbiAgICAgKi9cbiAgcHVibGljIGFzeW5jICpzdHJlYW0oaW50ZXJ2YWxNcyA9IDEwMDAgKiA5MCkge1xuICAgIHdoaWxlICh0cnVlKSB7IC8vIEtlZXAgc3RyZWFtaW5nIHVudGlsIG1hbnVhbGx5IHN0b3BwZWRcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlYWRpbmcgPSBhd2FpdCB0aGlzLnJlYWQoKTtcbiAgICAgICAgeWllbGQgcmVhZGluZztcbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIGludGVydmFsTXMpKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRmV0Y2ggdGhlIHJlYWRpbmcgZnJvbSB0aGUgTGlicmUgTGluayBVcCBBUEkuIFVzZSB0byBvYnRhaW4gdGhlIHJhdyByZWFkaW5nIGFuZCBtb3JlLlxuICAgKiBAcmV0dXJucyBUaGUgcmVzcG9uc2UgZnJvbSB0aGUgTGlicmUgTGluayBVcCBBUEkuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZmV0Y2hSZWFkaW5nKCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYXRpZW50SWQgPSBhd2FpdCB0aGlzLmdldFBhdGllbnRJZCgpO1xuXG4gICAgICBjb25zdCBoZWFkZXJzID0ge1xuICAgICAgICBcIkFjY291bnQtSWRcIjogdGhpcy5tZT8uaWQgPyBhd2FpdCBlbmNyeXB0U2hhMjU2KHRoaXMubWUuaWQpIDogXCJcIixcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fZmV0Y2hlcjxMaWJyZUNvbm5lY3Rpb25SZXNwb25zZT4oYCR7TGlicmVMaW5rVXBFbmRwb2ludHMuQ29ubmVjdGlvbnN9LyR7cGF0aWVudElkfS9ncmFwaGAsIHsgaGVhZGVycyB9KTtcblxuICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc3QgZXJyb3IgPSBlcnIgYXMgRXJyb3I7XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZmV0Y2hpbmcgcmVhZGluZyBmcm9tIExpYnJlIExpbmsgVXAgQVBJLiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBGZXRjaCB0aGUgbG9nYm9vayBmcm9tIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS4gVXNlIHRvIG9idGFpbiB0aGUgbGlzdCBvZiBtYW51YWwgc2Nhbm5lZCByZWFkaW5ncy5cbiAgICogQHJldHVybnMgVGhlIHJlc3BvbnNlIGZyb20gdGhlIExpYnJlIExpbmsgVXAgQVBJLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGZldGNoTG9nYm9vaygpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcGF0aWVudElkID0gYXdhaXQgdGhpcy5nZXRQYXRpZW50SWQoKTtcblxuICAgICAgY29uc3QgaGVhZGVycyA9IHtcbiAgICAgICAgXCJBY2NvdW50LUlkXCI6IHRoaXMubWU/LmlkID8gYXdhaXQgZW5jcnlwdFNoYTI1Nih0aGlzLm1lLmlkKSA6IFwiXCIsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX2ZldGNoZXI8TGlicmVMb2dib29rUmVzcG9uc2U+KGAke0xpYnJlTGlua1VwRW5kcG9pbnRzLkNvbm5lY3Rpb25zfS8ke3BhdGllbnRJZH0vbG9nYm9va2AsIHsgaGVhZGVycyB9KTtcblxuICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc3QgZXJyb3IgPSBlcnIgYXMgRXJyb3I7XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZmV0Y2hpbmcgcmVhZGluZyBmcm9tIExpYnJlIExpbmsgVXAgQVBJLiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIGNvbm5lY3Rpb25zIGZyb20gdGhlIExpYnJlIExpbmsgVXAgQVBJLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGZldGNoQ29ubmVjdGlvbnMoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICh0aGlzLmNhY2hlLmhhcyhcImNvbm5lY3Rpb25zXCIpKVxuICAgICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXQoXCJjb25uZWN0aW9uc1wiKTtcblxuICAgICAgY29uc3QgaGVhZGVycyA9IHtcbiAgICAgICAgXCJBY2NvdW50LUlkXCI6IHRoaXMubWU/LmlkID8gYXdhaXQgZW5jcnlwdFNoYTI1Nih0aGlzLm1lLmlkKSA6IFwiXCIsXG4gICAgICB9O1xuXG4gICAgICAvLyBGZXRjaCB0aGUgY29ubmVjdGlvbnMgZnJvbSB0aGUgTGlicmUgTGluayBVcCBBUEkuXG4gICAgICBjb25zdCBjb25uZWN0aW9ucyA9IGF3YWl0IHRoaXMuX2ZldGNoZXIoTGlicmVMaW5rVXBFbmRwb2ludHMuQ29ubmVjdGlvbnMsIHsgaGVhZGVycyB9KTtcblxuICAgICAgaWYgKCEhY29ubmVjdGlvbnM/LmRhdGE/Lmxlbmd0aClcbiAgICAgICAgLy8gQ2FjaGUgdGhlIGNvbm5lY3Rpb25zIGZvciBmdXR1cmUgdXNlLlxuICAgICAgICB0aGlzLnNldENhY2hlKFwiY29ubmVjdGlvbnNcIiwgY29ubmVjdGlvbnMpO1xuXG4gICAgICByZXR1cm4gY29ubmVjdGlvbnM7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zdCBlcnJvciA9IGVyciBhcyBFcnJvcjtcblxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBmZXRjaGluZyBjb25uZWN0aW9ucyBmcm9tIExpYnJlIExpbmsgVXAgQVBJLiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIHBhdGllbnQgSUQgZnJvbSB0aGUgY29ubmVjdGlvbnMuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGdldFBhdGllbnRJZCgpIHtcbiAgICBjb25zdCBjb25uZWN0aW9ucyA9IGF3YWl0IHRoaXMuZmV0Y2hDb25uZWN0aW9ucygpO1xuXG4gICAgLy8gSWYgdGhlcmUgYXJlIG5vIGNvbm5lY3Rpb25zLCB0aHJvdyBhbiBlcnJvci5cbiAgICBpZiAoIWNvbm5lY3Rpb25zLmRhdGE/Lmxlbmd0aClcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGNvbm5lY3Rpb25zIGZvdW5kLiBQbGVhc2UgZW5zdXJlIHRoYXQgeW91IGhhdmUgYSBjb25uZWN0aW9uIHdpdGggdGhlIExpYnJlTGlua1VwIGFwcC5cIik7XG5cbiAgICAvLyBHZXQgdGhlIHBhdGllbnQgSUQgZnJvbSB0aGUgY29ubmVjdGlvbnMsIG9yIGZhbGxiYWNrIHRvIHRoZSBmaXJzdCBjb25uZWN0aW9uLlxuXG4gICAgbGV0IHBhdGllbnRJZCA9IGNvbm5lY3Rpb25zLmRhdGFbMF0ucGF0aWVudElkO1xuXG4gICAgaWYgKHRoaXMucGF0aWVudElkKVxuICAgICAgY29ubmVjdGlvbnMuZGF0YS5maW5kKFxuICAgICAgICAoY29ubmVjdGlvbjogTGlicmVDb25uZWN0aW9uKSA9PiBjb25uZWN0aW9uLnBhdGllbnRJZCA9PT0gdGhpcy5wYXRpZW50SWRcbiAgICAgICk/LnBhdGllbnRJZDtcblxuICAgIGlmICghcGF0aWVudElkKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBQYXRpZW50IElEIG5vdCBmb3VuZCBpbiBjb25uZWN0aW9ucy4gKCR7dGhpcy5wYXRpZW50SWR9KWApO1xuXG4gICAgcmV0dXJuIHBhdGllbnRJZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRmluZCB0aGUgcmVnaW9uIGluIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS4gVGhpcyBpcyB1c2VkIHdoZW4gdGhlIEFQSSByZXR1cm5zIGEgcmVkaXJlY3QuXG4gICAqIEBwYXJhbSByZWdpb24gVGhlIHJlZ2lvbiB0byBmaW5kLlxuICAgKiBAcmV0dXJucyBUaGUgc2VydmVyIFVSTCBmb3IgdGhlIHJlZ2lvbi5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZmluZFJlZ2lvbihyZWdpb246IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX2ZldGNoZXIoTGlicmVMaW5rVXBFbmRwb2ludHMuQ291bnRyeSk7XG5cbiAgICAgIC8vIEZpbmQgdGhlIHJlZ2lvbiBpbiB0aGUgcmVzcG9uc2UuXG4gICAgICBjb25zdCBsc2xBcGkgPSByZXNwb25zZS5kYXRhPy5yZWdpb25hbE1hcFtyZWdpb25dPy5sc2xBcGk7XG5cbiAgICAgIGlmICghbHNsQXBpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZWdpb24gbm90IGZvdW5kIGluIExpYnJlIExpbmsgVXAgQVBJLlwiKTtcblxuICAgICAgcmV0dXJuIGxzbEFwaTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnN0IGVycm9yID0gZXJyIGFzIEVycm9yO1xuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGZpbmRpbmcgcmVnaW9uIGluIExpYnJlIExpbmsgVXAgQVBJLiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBIGdlbmVyaWMgZmV0Y2hlciBmb3IgdGhlIExpYnJlIExpbmsgVXAgQVBJLlxuICAgKiBAcGFyYW0gZW5kcG9pbnRcbiAgICogQHBhcmFtIG9wdGlvbnNcbiAgICogQHBhcmFtIGlzUmV0cnkgSW50ZXJuYWwgZmxhZyB0byBwcmV2ZW50IGluZmluaXRlIHJldHJ5IGxvb3BzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIF9mZXRjaGVyPFQgPSBMaWJyZVJlc3BvbnNlPihlbmRwb2ludDogc3RyaW5nLCBvcHRpb25zOiBhbnkgPSB7IGhlYWRlcnM6IHt9IH0sIGlzUmV0cnkgPSBmYWxzZSk6IFByb21pc2U8VD4ge1xuICAgIGNvbnN0IGhlYWRlcnMgPSB7XG4gICAgICAuLi5vcHRpb25zLmhlYWRlcnMsXG4gICAgICBBdXRob3JpemF0aW9uOiB0aGlzLmFjY2Vzc1Rva2VuID8gYEJlYXJlciAke3RoaXMuYWNjZXNzVG9rZW59YCA6IFwiXCIsXG5cbiAgICAgIC8vIExpYnJlIExpbmsgVXAgQVBJIGhlYWRlcnNcbiAgICAgIHByb2R1Y3Q6ICdsbHUuYW5kcm9pZCcsXG4gICAgICB2ZXJzaW9uOiB0aGlzLmxsdVZlcnNpb24sXG5cbiAgICAgICdhY2NlcHQtZW5jb2RpbmcnOiAnZ3ppcCcsXG4gICAgICAnY2FjaGUtY29udHJvbCc6ICduby1jYWNoZScsXG4gICAgICBjb25uZWN0aW9uOiAnS2VlcC1BbGl2ZScsXG4gICAgICAnY29udGVudC10eXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgIH07XG5cbiAgICBjb25zdCByZXF1ZXN0T3B0aW9ucyA9IE9iamVjdC5mcmVlemUoe1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIGhlYWRlcnNcbiAgICB9KTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKFxuICAgICAgICBgJHt0aGlzLmFwaVVybH0vJHtlbmRwb2ludH1gLFxuICAgICAgICByZXF1ZXN0T3B0aW9uc1xuICAgICAgKTtcblxuICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICBjb25zdCBlcnJvclBheWxvYWQgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yUGF5bG9hZD8ubWVzc2FnZSA/PyBKU09OLnN0cmluZ2lmeShlcnJvclBheWxvYWQsIG51bGwsIDIpXG5cbiAgICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gNDI5KVxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVG9vIG1hbnkgcmVxdWVzdHMuIFBsZWFzZSB3YWl0IGJlZm9yZSB0cnlpbmcgYWdhaW4uICR7ZXJyb3JNZXNzYWdlfWApO1xuXG4gICAgICAgIC8vIENoZWNrIGlmIHRoZSBlcnJvciBpcyByZWxhdGVkIHRvIHRva2VuIGV4cGlyYXRpb25cbiAgICAgICAgaWYgKCFpc1JldHJ5ICYmIHRoaXMuaXNUb2tlbkV4cGlyZWRFcnJvcihyZXNwb25zZS5zdGF0dXMsIGVycm9yTWVzc2FnZSkpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gQ2xlYXIgdGhlIGV4cGlyZWQgdG9rZW4gYW5kIHVzZXIgY2FjaGVcbiAgICAgICAgICAgIHRoaXMuYWNjZXNzVG9rZW4gPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5jYWNoZS5kZWxldGUoXCJ1c2VyXCIpO1xuXG4gICAgICAgICAgICAvLyBBdHRlbXB0IHRvIGxvZ2luIGFnYWluIHRvIHJlZnJlc2ggdGhlIHRva2VuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmxvZ2luKCk7XG5cbiAgICAgICAgICAgIC8vIFJldHJ5IHRoZSBvcmlnaW5hbCByZXF1ZXN0IHdpdGggdGhlIG5ldyB0b2tlblxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2ZldGNoZXI8VD4oZW5kcG9pbnQsIG9wdGlvbnMsIHRydWUpO1xuICAgICAgICAgIH0gY2F0Y2ggKGxvZ2luRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVG9rZW4gZXhwaXJlZCBhbmQgYXV0b21hdGljIGxvZ2luIGZhaWxlZDogJHsobG9naW5FcnJvciBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEVycm9yIGZldGNoaW5nIGRhdGEgZnJvbSBMaWJyZSBMaW5rIFVwIEFQSSB3aXRoIHN0YXR1cyAke3Jlc3BvbnNlLnN0YXR1c30uICR7ZXJyb3JNZXNzYWdlfWBcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGF0YSA9IChhd2FpdCByZXNwb25zZS5qc29uKCkpIGFzIFQ7XG5cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc3QgZXJyb3IgPSBlcnIgYXMgRXJyb3I7XG5cbiAgICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYSBuZXR3b3JrIGVycm9yIHRoYXQgbWlnaHQgaW5kaWNhdGUgdG9rZW4gZXhwaXJhdGlvblxuICAgICAgaWYgKCFpc1JldHJ5ICYmIHRoaXMuaXNUb2tlbkV4cGlyZWRFcnJvcigwLCBlcnJvci5tZXNzYWdlKSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIENsZWFyIHRoZSBleHBpcmVkIHRva2VuIGFuZCB1c2VyIGNhY2hlXG4gICAgICAgICAgdGhpcy5hY2Nlc3NUb2tlbiA9IG51bGw7XG4gICAgICAgICAgdGhpcy5jYWNoZS5kZWxldGUoXCJ1c2VyXCIpO1xuXG4gICAgICAgICAgLy8gQXR0ZW1wdCB0byBsb2dpbiBhZ2FpbiB0byByZWZyZXNoIHRoZSB0b2tlblxuICAgICAgICAgIGF3YWl0IHRoaXMubG9naW4oKTtcblxuICAgICAgICAgIC8vIFJldHJ5IHRoZSBvcmlnaW5hbCByZXF1ZXN0IHdpdGggdGhlIG5ldyB0b2tlblxuICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLl9mZXRjaGVyPFQ+KGVuZHBvaW50LCBvcHRpb25zLCB0cnVlKTtcbiAgICAgICAgfSBjYXRjaCAobG9naW5FcnJvcikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVG9rZW4gZXhwaXJlZCBhbmQgYXV0b21hdGljIGxvZ2luIGZhaWxlZDogJHsobG9naW5FcnJvciBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHByb2Nlc3NpbmcgcmVxdWVzdCB0byBMaWJyZSBMaW5rIFVwIEFQSS4gJHtlcnJvci5tZXNzYWdlfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ2hlY2sgaWYgYW4gZXJyb3IgaW5kaWNhdGVzIHRoYXQgdGhlIGF1dGhlbnRpY2F0aW9uIHRva2VuIGhhcyBleHBpcmVkLlxuICAgKiBAcGFyYW0gc3RhdHVzQ29kZSBUaGUgSFRUUCBzdGF0dXMgY29kZSBmcm9tIHRoZSByZXNwb25zZVxuICAgKiBAcGFyYW0gZXJyb3JNZXNzYWdlIFRoZSBlcnJvciBtZXNzYWdlIGZyb20gdGhlIHJlc3BvbnNlXG4gICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGVycm9yIGluZGljYXRlcyB0b2tlbiBleHBpcmF0aW9uXG4gICAqL1xuICBwcml2YXRlIGlzVG9rZW5FeHBpcmVkRXJyb3Ioc3RhdHVzQ29kZTogbnVtYmVyLCBlcnJvck1lc3NhZ2U6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIC8vIENoZWNrIGZvciBjb21tb24gdG9rZW4gZXhwaXJhdGlvbiBpbmRpY2F0b3JzXG4gICAgY29uc3QgdG9rZW5FcnJvckluZGljYXRvcnMgPSBbXG4gICAgICAndG9rZW4nLFxuICAgICAgJ2p3dCcsXG4gICAgICAndW5hdXRob3JpemVkJyxcbiAgICAgICdhdXRoZW50aWNhdGlvbicsXG4gICAgICAnZXhwaXJlZCcsXG4gICAgICAnaW52YWxpZCB0b2tlbicsXG4gICAgICAnYWNjZXNzIGRlbmllZCcsXG4gICAgICAnbWFsZm9ybWVkIGp3dCcsXG4gICAgICAnbWlzc2luZyBqd3QnXG4gICAgXTtcblxuICAgIGNvbnN0IG1lc3NhZ2VDb250YWluc1Rva2VuRXJyb3IgPSB0b2tlbkVycm9ySW5kaWNhdG9ycy5zb21lKGluZGljYXRvciA9PlxuICAgICAgZXJyb3JNZXNzYWdlLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoaW5kaWNhdG9yLnRvTG93ZXJDYXNlKCkpXG4gICAgKTtcblxuICAgIC8vIEhUVFAgNDAxIChVbmF1dGhvcml6ZWQpLCA0MDMgKEZvcmJpZGRlbiksIG9yIDQwMCAoQmFkIFJlcXVlc3Qgd2l0aCBKV1QgZXJyb3JzKSBvZnRlbiBpbmRpY2F0ZSB0b2tlbiBpc3N1ZXNcbiAgICBjb25zdCBpc0F1dGhTdGF0dXNDb2RlID0gc3RhdHVzQ29kZSA9PT0gNDAxIHx8IHN0YXR1c0NvZGUgPT09IDQwMyB8fCAoc3RhdHVzQ29kZSA9PT0gNDAwICYmIG1lc3NhZ2VDb250YWluc1Rva2VuRXJyb3IpO1xuXG4gICAgcmV0dXJuIG1lc3NhZ2VDb250YWluc1Rva2VuRXJyb3IgfHwgaXNBdXRoU3RhdHVzQ29kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ2FjaGUgYSB2YWx1ZSwgaWYgY2FjaGluZyBpcyBlbmFibGVkLlxuICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgdG8gY2FjaGUgdGhlIHZhbHVlIHVuZGVyLlxuICAgKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlIHRvIGNhY2hlLlxuICAgKi9cbiAgcHJpdmF0ZSBzZXRDYWNoZShrZXk6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIGlmICghdGhpcy5vcHRpb25zLmNhY2hlKSByZXR1cm47XG5cbiAgICB0aGlzLmNhY2hlLnNldChrZXksIHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ2xlYXIgdGhlIGNhY2hlLlxuICAgKi9cbiAgcHVibGljIGNsZWFyQ2FjaGUoKSB7XG4gICAgdGhpcy5jYWNoZS5jbGVhcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEZWJ1ZyBtZXRob2QgdG8gY2hlY2sgaWYgdGhlIGNsaWVudCBoYXMgYSB2YWxpZCBhY2Nlc3MgdG9rZW5cbiAgICogQHJldHVybnMgSW5mb3JtYXRpb24gYWJvdXQgdGhlIGN1cnJlbnQgYXV0aGVudGljYXRpb24gc3RhdGVcbiAgICovXG4gIHB1YmxpYyBnZXRBdXRoU3RhdHVzKCkge1xuICAgIHJldHVybiB7XG4gICAgICBoYXNUb2tlbjogISF0aGlzLmFjY2Vzc1Rva2VuLFxuICAgICAgdG9rZW5MZW5ndGg6IHRoaXMuYWNjZXNzVG9rZW4/Lmxlbmd0aCB8fCAwLFxuICAgICAgaGFzVXNlcjogISF0aGlzLm1lLFxuICAgICAgdXNlcklkOiB0aGlzLm1lPy5pZCB8fCBudWxsXG4gICAgfTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIExpYnJlTGlua0NsaWVudE9wdGlvbnMge1xuICBlbWFpbDogc3RyaW5nO1xuICBwYXNzd29yZDogc3RyaW5nO1xuICBhcGlVcmw/OiBzdHJpbmc7XG4gIHBhdGllbnRJZD86IHN0cmluZztcbiAgY2FjaGU/OiBib29sZWFuO1xuICBsbHVWZXJzaW9uPzogc3RyaW5nO1xufVxuXG5jb25zdCBERUZBVUxUX09QVElPTlM6IFBhcnRpYWw8TGlicmVMaW5rQ2xpZW50T3B0aW9ucz4gPSB7XG4gIGFwaVVybDogXCJodHRwczovL2FwaS11cy5saWJyZXZpZXcuaW9cIixcbiAgY2FjaGU6IHRydWUsXG4gIGxsdVZlcnNpb246IFwiNC43LjBcIlxufTsiCiAgXSwKICAibWFwcGluZ3MiOiAiQUFFTyxJQUFNLEVBQXFCLFlBT2xDLEVBRWEsRUFBOEIsQ0FDdkMsZ0JBQ0EsYUFDQSxnQkFDQSxPQUNBLGNBQ0EsVUFDSixFQ1ZPLElBQU0sRUFBWSxDQUFDLEtBQTBDLElBQzVELEVBQ0osUUFBUyxFQUFtQixFQUFLLE9BQTRCLEVBQzdELFVBQVcsRUFBbUIsRUFBSyxTQUE4QixFQUNqRSxZQUFhLEVBQW1CLEVBQUssV0FBZ0MsQ0FDekUsR0FPYSxFQUFxQixDQUFDLElBQXNCLElBQUksS0FBSyxFQUFZLElBQUksRUFRckUsRUFBc0IsQ0FBQyxFQUErQixJQUF1RCxDQUN0SCxJQUFNLEVBQVEsRUFBVyxlQUduQixFQUFTLEVBQVEsV0FBYSxFQUM5QixFQUFRLEVBQVEsVUFBWSxFQVdsQyxPQVRzQixPQUFPLE9BQU8sQ0FDaEMsVUFBVyxJQUFJLEtBQUssRUFBVyxTQUFT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QUFTLEVBQUksRUFDckQsTUFBTyxFQUFZLENBQ25CLE1BQVUsTUFBTSw2Q0FBOEMsRUFBcUIsU0FBUyxFQUloRyxNQUFVLE1BQU0sa0RBQWtELEVBQU0sU0FBUyxHQVU3RSxtQkFBbUIsQ0FBQyxFQUFvQixFQUErQixDQWM3RSxJQUFNLEVBWnVCLENBQzNCLFFBQ0EsTUFDQSxlQUNBLGlCQUNBLFVBQ0EsZ0JBQ0EsZ0JBQ0EsZ0JBQ0EsYUFDRixFQUV1RCxLQUFLLEtBQzFELEVBQWEsWUFBWSxFQUFFLFNBQVMsRUFBVSxZQUFZLENBQUMsQ0FDN0QsRUFLQSxPQUFPLElBRmtCLElBQWUsS0FBTyxJQUFlLEtBQVEsSUFBZSxLQUFPLEdBVXRGLFFBQVEsQ0FBQyxFQUFhLEVBQVksQ0FDeEMsR0FBSSxDQUFDLEtBQUssUUFBUSxNQUFPLE9BRXpCLEtBQUssTUFBTSxJQUFJLEVBQUssQ0FBSyxFQU1wQixVQUFVLEVBQUcsQ0FDbEIsS0FBSyxNQUFNLE1BQU0sRUFPWixhQUFhLEVBQUcsQ0FDckIsTUFBTyxDQUNMLFNBQVUsQ0FBQyxDQUFDLEtBQUssWUFDakIsWUFBYSxLQUFLLGFBQWEsUUFBVSxFQUN6QyxRQUFTLENBQUMsQ0FBQyxLQUFLLEdBQ2hCLE9BQVEsS0FBSyxJQUFJLElBQU0sSUFDekIsRUFFSixDQVdBLElBQU0sRUFBbUQsQ0FDdkQsT0FBUSw4QkFDUixNQUFPLEdBQ1AsV0FBWSxPQUNkIiwKICAiZGVidWdJZCI6ICIwRkEyQzA4MUQ0RTcxOTgxNjQ3NTZFMjE2NDc1NkUyMSIsCiAgIm5hbWVzIjogW10KfQ==