UNPKG

librelinkup-api-client

Version:

An unofficial API for Libre Link Up (glucose monitoring system/CGM)

5 lines (3 loc) 42.4 kB
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 new 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 new Error("Invalid credentials. Please ensure that the email and password work with the LibreLinkUp app.");if(!z.data)throw new 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()}return this.accessToken=z.data.authTicket?.token,this.setCache("user",B(z.data.user)),z}catch(z){throw new 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 new 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 new 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 new 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 new 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 new 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 new Error(`Error fetching connections from Libre Link Up API. ${F.message}`)}}async getPatientId(){let F=await this.fetchConnections();if(!F.data?.length)throw new 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 new 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 new Error("Region not found in Libre Link Up API.");return z}catch(x){throw new 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 new 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 new Error(`Token expired and automatic login failed: ${G.message}`)}throw new 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 new Error(`Token expired and automatic login failed: ${X.message}`)}throw new 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=73097D2D8454B32464756E2164756E21 //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi5cXHNyY1xcY29uc3RhbnRzLnRzIiwgIi4uXFxzcmNcXHV0aWxzLnRzIiwgIi4uXFxzcmNcXHJlYWRpbmcudHMiLCAiLi5cXHNyY1xcY2xpZW50LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWwogICAgImltcG9ydCB7IFRyZW5kLCBUcmVuZFR5cGUgfSBmcm9tIFwiLi90eXBlc1wiO1xyXG5cclxuZXhwb3J0IGNvbnN0IFRSRU5EX01BUDogVHJlbmRbXSA9IFtcclxuICAgIFRyZW5kLk5vdENvbXB1dGFibGUsXHJcbiAgICBUcmVuZC5TaW5nbGVEb3duLFxyXG4gICAgVHJlbmQuRm9ydHlGaXZlRG93bixcclxuICAgIFRyZW5kLkZsYXQsXHJcbiAgICBUcmVuZC5Gb3J0eUZpdmVVcCxcclxuICAgIFRyZW5kLlNpbmdsZVVwLFxyXG5dO1xyXG5cclxuZXhwb3J0IGNvbnN0IFRSRU5EX1RZUEVfTUFQOiBUcmVuZFR5cGVbXSA9IFtcclxuICAgIFwiTm90Q29tcHV0YWJsZVwiLFxyXG4gICAgXCJTaW5nbGVEb3duXCIsXHJcbiAgICBcIkZvcnR5Rml2ZURvd25cIixcclxuICAgIFwiRmxhdFwiLFxyXG4gICAgXCJGb3J0eUZpdmVVcFwiLFxyXG4gICAgXCJTaW5nbGVVcFwiLFxyXG5dOyIsCiAgICAiaW1wb3J0IHsgR2x1Y29zZVJlYWRpbmcgfSBmcm9tIFwiLi9yZWFkaW5nXCI7XHJcbmltcG9ydCB7IFJhd0dsdWNvc2VSZWFkaW5nLCBMaWJyZVVzZXIsIE1lYXN1cmVtZW50Q29sb3IsIFRyZW5kIH0gZnJvbSBcIi4vdHlwZXNcIjtcclxuXHJcbi8qKlxyXG4gKiBQYXJzZSBhIExpYnJlIFVzZXIgb2JqZWN0LlxyXG4gKiBAcGFyYW0gdXNlciBUaGUgdXNlciBvYmplY3QgdG8gcGFyc2UuXHJcbiAqIEByZXR1cm5zIFRoZSBwYXJzZWQgdXNlciBvYmplY3QuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgcGFyc2VVc2VyID0gKHVzZXI6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBMaWJyZVVzZXIgPT4gKHtcclxuICAgIC4uLih1c2VyIGFzIExpYnJlVXNlciksXHJcbiAgICBjcmVhdGVkOiBwYXJzZVVuaXhUaW1lc3RhbXAodXNlci5jcmVhdGVkIGFzIHVua25vd24gYXMgbnVtYmVyKSxcclxuICAgIGxhc3RMb2dpbjogcGFyc2VVbml4VGltZXN0YW1wKHVzZXIubGFzdExvZ2luIGFzIHVua25vd24gYXMgbnVtYmVyKSxcclxuICAgIGRhdGVPZkJpcnRoOiBwYXJzZVVuaXhUaW1lc3RhbXAodXNlci5kYXRlT2ZCaXJ0aCBhcyB1bmtub3duIGFzIG51bWJlciksXHJcbn0pO1xyXG5cclxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBQYXJzZSB1bml4IHRpbWVzdGFtcHMgdG8gRGF0ZSBvYmplY3RzLlxyXG4gKiBAcGFyYW0gdGltZXN0YW1wIFRoZSB1bml4IHRpbWVzdGFtcCB0byBwYXJzZS5cclxuICogQHJldHVybnMgVGhlIHBhcnNlZCBkYXRlLlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IHBhcnNlVW5peFRpbWVzdGFtcCA9ICh0aW1lc3RhbXA6IG51bWJlcikgPT4gbmV3IERhdGUodGltZXN0YW1wICogMTAwMCk7XHJcblxyXG4vKipcclxuICogQGRlc2NyaXB0aW9uIFBhcnNlIGEgZ2x1Y29zZSByZWFkaW5nLlxyXG4gKiBAcGFyYW0gcmF3UmVhZGluZyBUaGUgcmF3IGdsdWNvc2UgcmVhZGluZyBjb21pbmcgZnJvbSB0aGUgc2VydmVyIHRvIHBhcnNlLlxyXG4gKiBAcGFyYW0gY29ubmVjdGlvbiBUaGUgY29ubmVjdGlvbiBvYmplY3QgdG8gdXNlIGZvciBwYXJzaW5nLiBVc2VkIGZvciBjYWxjdWxhdGluZyBpc0hpZ2ggYW5kIGlzTG93LlxyXG4gKiBAcmV0dXJucyBUaGUgcGFyc2VkIGdsdWNvc2UgcmVhZGluZy5cclxuICovXHJcbmV4cG9ydCBjb25zdCBwYXJzZUdsdWNvc2VSZWFkaW5nID0gKHJhd1JlYWRpbmc6IFJhd0dsdWNvc2VSZWFkaW5nLCBvcHRpb25zOiB7IHRhcmdldEhpZ2g6IG51bWJlciwgdGFyZ2V0TG93OiBudW1iZXIgfSkgPT4ge1xyXG4gICAgY29uc3QgdmFsdWUgPSByYXdSZWFkaW5nLlZhbHVlSW5NZ1BlckRsO1xyXG5cclxuICAgIC8vICEgQ2FsY3VsYXRlcyB0aGUgaXNIaWdoIGFuZCBpc0xvdyBwcm9wZXJ0aWVzIGJhc2VkIG9uIHRoZSB0YXJnZXRIaWdoIGFuZCB0YXJnZXRMb3cgdmFsdWVzLiBUaGUgdHdvIHZhbHVlcyBjb21pbmcgZnJvbSBMaWJyZSBMaW5rIFVwIHNlZW1zIHRvIGJlIGluY29ycmVjdC5cclxuICAgIGNvbnN0IGlzSGlnaCA9IG9wdGlvbnMudGFyZ2V0SGlnaCA8IHZhbHVlO1xyXG4gICAgY29uc3QgaXNMb3cgPSBvcHRpb25zLnRhcmdldExvdyA+IHZhbHVlO1xyXG4gICBcclxuICAgIGNvbnN0IHBhcnNlZFJlYWRpbmcgPSBPYmplY3QuZnJlZXplKHtcclxuICAgICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKHJhd1JlYWRpbmcuVGltZXN0YW1wKSxcclxuICAgICAgICB2YWx1ZSxcclxuICAgICAgICBtZWFzdXJlbWVudENvbG9yOiByYXdSZWFkaW5nLk1lYXN1cmVtZW50Q29sb3IgYXMgTWVhc3VyZW1lbnRDb2xvcixcclxuICAgICAgICBpc0hpZ2gsXHJcbiAgICAgICAgaXNMb3csXHJcbiAgICAgICAgdHJlbmQ6IHBhcnNlVHJlbmQocmF3UmVhZGluZy5UcmVuZEFycm93KVxyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIHBhcnNlZFJlYWRpbmc7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gU29ydCBieSB0aW1lc3RhbXAuXHJcbiAqIEBwYXJhbSBhIFRoZSBmaXJzdCBpdGVtIHRvIGNvbXBhcmUuXHJcbiAqIEBwYXJhbSBiIFRoZSBzZWNvbmQgaXRlbSB0byBjb21wYXJlLlxyXG4gKiBAcmV0dXJucyBUaGUgY29tcGFyaXNvbiByZXN1bHQuXHJcbiAqIFxyXG4gKiBAZXhhbXBsZSBcclxuICogLnNvcnQoc29ydEJ5VGltZXN0YW1wKVxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IHNvcnRCeVRpbWVzdGFtcCA9IChhOiBHbHVjb3NlUmVhZGluZywgYjogR2x1Y29zZVJlYWRpbmcpID0+IGEudGltZXN0YW1wLmdldFRpbWUoKSAtIGIudGltZXN0YW1wLmdldFRpbWUoKTtcclxuXHJcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gUGFyc2UgdGhlIHRyZW5kIG9mIGdsdWNvc2UgcmVhZGluZy5cclxuICogQHBhcmFtIHRyZW5kIFRoZSBjdXJyZW50IHRyZW5kLlxyXG4gKiBAcGFyYW0gZGVmYXVsdFRyZW5kIFRoZSBkZWZhdWx0IHRyZW5kIHRvIHVzZSBpZiB0cmVuZCBpcyB1bmRlZmluZWQuXHJcbiAqIEByZXR1cm5zIFRoZSBwYXJzZWQgdHJlbmQuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgcGFyc2VUcmVuZCA9ICh0cmVuZDogbnVtYmVyIHwgdW5kZWZpbmVkLCBkZWZhdWx0VHJlbmQ6IFRyZW5kID0gVHJlbmQuRmxhdCkgPT4gdHJlbmQgYXMgVHJlbmQgPz8gZGVmYXVsdFRyZW5kO1xyXG5cclxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIHRyZW5kIHR5cGUgb2YgZ2x1Y29zZSByZWFkaW5nLlxyXG4gKiBAcGFyYW0gdHJlbmQgVGhlIGN1cnJlbnQgdHJlbmQuXHJcbiAqIEBwYXJhbSBkZWZhdWx0VHJlbmQgVGhlIGRlZmF1bHQgdHJlbmQgdG8gdXNlIGlmIHRyZW5kIGlzIHVuZGVmaW5lZC5cclxuICogQHJldHVybnMgVGhlIHRyZW5kIHR5cGUuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgZ2V0VHJlbmRUeXBlID0gKHRyZW5kOiBudW1iZXIgfCB1bmRlZmluZWQsIGRlZmF1bHRUcmVuZDogVHJlbmQgPSBUcmVuZC5GbGF0KSA9PiBUcmVuZFtwYXJzZVRyZW5kKHRyZW5kLCBkZWZhdWx0VHJlbmQpXTtcclxuXHJcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gRW5jcnlwdCBtZXNzYWdlIGluIHNoYTI1Ni5cclxuICogQHBhcmFtIG1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gYmUgZW5jcnlwdGVkLlxyXG4gKiBAcmV0dXJucyBUaGUgZW5jcnlwdGVkIG1lc3NhZ2UuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgZW5jcnlwdFNoYTI1NiA9IChtZXNzYWdlOiBzdHJpbmcpID0+IHtcclxuICBjb25zdCBidWZmZXIgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUobWVzc2FnZSk7XHJcblxyXG4gIHJldHVybiBjcnlwdG8uc3VidGxlLmRpZ2VzdCgnU0hBLTI1NicsIGJ1ZmZlcikudGhlbihoYXNoQnVmZmVyID0+IHtcclxuICAgIGNvbnN0IGhhc2hBcnJheSA9IEFycmF5LmZyb20obmV3IFVpbnQ4QXJyYXkoaGFzaEJ1ZmZlcikpO1xyXG4gICAgcmV0dXJuIGhhc2hBcnJheS5tYXAoYiA9PiBiLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAnMCcpKS5qb2luKCcnKTtcclxuICB9KTtcclxufSIsCiAgICAiaW1wb3J0IHsgVFJFTkRfVFlQRV9NQVAgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcclxuaW1wb3J0IHsgTWVhc3VyZW1lbnRDb2xvciwgUmF3R2x1Y29zZVJlYWRpbmcsIFRyZW5kLCBUcmVuZFR5cGUgfSBmcm9tIFwiLi90eXBlc1wiO1xyXG5pbXBvcnQgeyBwYXJzZUdsdWNvc2VSZWFkaW5nIH0gZnJvbSBcIi4vdXRpbHNcIjtcclxuXHJcbmNvbnN0IERFRkFVTFRfT1BUSU9OUyA9IE9iamVjdC5mcmVlemUoe1xyXG4gICAgdGFyZ2V0SGlnaDogMTUwLFxyXG4gICAgdGFyZ2V0TG93OiA3MFxyXG59KTtcclxuXHJcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gQSBnbHVjb3NlIHJlYWRpbmcgY2xhc3MuXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgR2x1Y29zZVJlYWRpbmcge1xyXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gVGhlIHRpbWVzdGFtcCBvZiB0aGUgZ2x1Y29zZSByZWFkaW5nLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdGltZXN0YW1wOiBEYXRlO1xyXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gVGhlIHZhbHVlIG9mIHRoZSBnbHVjb3NlIHJlYWRpbmcgaW4gbWcvZEwuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyB2YWx1ZTogbnVtYmVyO1xyXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gVGhlIG1lYXN1cmVtZW50IGNvbG9yIG9mIHRoZSBnbHVjb3NlIHJlYWRpbmcuIFNlZSB7QGxpbmsgTWVhc3VyZW1lbnRDb2xvcn0uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBtZWFzdXJlbWVudENvbG9yOiBNZWFzdXJlbWVudENvbG9yO1xyXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0aGUgZ2x1Y29zZSByZWFkaW5nIGlzIGhpZ2gsIGJhc2VkIG9uIHRoZSBwYXRpZW50J3Mgc2V0dGluZ3MuIENhbGN1bGF0ZWQgYnkgdGhlIGxpYnJhcnkuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBpc0hpZ2g6IGJvb2xlYW47XHJcbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRoZSBnbHVjb3NlIHJlYWRpbmcgaXMgbG93LCBiYXNlZCBvbiB0aGUgcGF0aWVudCdzIHNldHRpbmdzLiBDYWxjdWxhdGVkIGJ5IHRoZSBsaWJyYXJ5LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaXNMb3c6IGJvb2xlYW47XHJcbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBUaGUgdHJlbmQgb2YgdGhlIGdsdWNvc2UgcmVhZGluZy4gU2VlIHtAbGluayBUcmVuZH0uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyB0cmVuZDogVHJlbmQ7XHJcblxyXG4gICAgY29uc3RydWN0b3IocHVibGljIF9yYXc6IFJhd0dsdWNvc2VSZWFkaW5nLCBwdWJsaWMgX29wdGlvbnM6IHsgdGFyZ2V0SGlnaDogbnVtYmVyLCB0YXJnZXRMb3c6IG51bWJlciB9ID0gREVGQVVMVF9PUFRJT05TKSB7XHJcbiAgICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VHbHVjb3NlUmVhZGluZyhfcmF3LCBfb3B0aW9ucyk7XHJcblxyXG4gICAgICAgIHRoaXMudmFsdWUgPSBwYXJzZWQudmFsdWU7XHJcbiAgICAgICAgdGhpcy50aW1lc3RhbXAgPSBwYXJzZWQudGltZXN0YW1wO1xyXG4gICAgICAgIHRoaXMubWVhc3VyZW1lbnRDb2xvciA9IHBhcnNlZC5tZWFzdXJlbWVudENvbG9yO1xyXG4gICAgICAgIHRoaXMuaXNIaWdoID0gcGFyc2VkLmlzSGlnaDtcclxuICAgICAgICB0aGlzLmlzTG93ID0gcGFyc2VkLmlzTG93O1xyXG4gICAgICAgIHRoaXMudHJlbmQgPSBwYXJzZWQudHJlbmQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gVGhlIG1tb2wgdmFsdWUgb2YgdGhlIGdsdWNvc2UgcmVhZGluZy5cclxuICAgICAqL1xyXG4gICAgZ2V0IG1tb2woKSB7XHJcbiAgICAgICAgcmV0dXJuICh0aGlzLnZhbHVlIC8gMTgpLnRvRml4ZWQoMSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gVGhlIG1nL2RMIHZhbHVlIG9mIHRoZSBnbHVjb3NlIHJlYWRpbmcuXHJcbiAgICAgKi9cclxuICAgIGdldCBtZ0RsKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIFRoZSB0eXBlIG9mIHRoZSB0cmVuZC4geyBAc2VlIFRyZW5kVHlwZSB9XHJcbiAgICAgKi9cclxuICAgIGdldCB0cmVuZFR5cGUoKTogVHJlbmRUeXBlIHtcclxuICAgICAgICByZXR1cm4gVFJFTkRfVFlQRV9NQVBbdGhpcy50cmVuZF07XHJcbiAgICB9XHJcbn0iLAogICAgImltcG9ydCB7IEdsdWNvc2VSZWFkaW5nIH0gZnJvbSBcIi4vcmVhZGluZ1wiO1xyXG5pbXBvcnQgeyBMaWJyZUxpbmtVcEVuZHBvaW50cywgTGlicmVMb2dpblJlc3BvbnNlLCBMaWJyZVJlc3BvbnNlLCBMaWJyZVJlZGlyZWN0UmVzcG9uc2UsIExpYnJlVXNlciwgTGlicmVDb25uZWN0aW9uLCBMaWJyZUNvbm5lY3Rpb25SZXNwb25zZSwgTGlicmVMb2dib29rUmVzcG9uc2UsIFJhd0dsdWNvc2VSZWFkaW5nIH0gZnJvbSBcIi4vdHlwZXNcIjtcclxuaW1wb3J0IHsgZW5jcnlwdFNoYTI1NiwgcGFyc2VVc2VyIH0gZnJvbSBcIi4vdXRpbHNcIjtcclxuXHJcbi8qKlxyXG4gKiBBIGNsYXNzIGZvciBpbnRlcmFjdGluZyB3aXRoIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBMaWJyZUxpbmtDbGllbnQge1xyXG4gIHByaXZhdGUgYXBpVXJsOiBzdHJpbmc7XHJcbiAgcHJpdmF0ZSBhY2Nlc3NUb2tlbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XHJcbiAgcHJpdmF0ZSBwYXRpZW50SWQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgbGx1VmVyc2lvbjogc3RyaW5nO1xyXG4gIHByaXZhdGUgY3JlZGVudGlhbHM6IHsgZW1haWw6IHN0cmluZzsgcGFzc3dvcmQ6IHN0cmluZyB9O1xyXG4gIHByaXZhdGUgb3B0aW9uczogTGlicmVMaW5rQ2xpZW50T3B0aW9ucztcclxuXHJcbiAgLy8gQSBjYWNoZSBmb3Igc3RvcmluZyBmZXRjaGVkIGRhdGEuXHJcbiAgcHJpdmF0ZSBjYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBhbnk+KCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IExpYnJlTGlua0NsaWVudE9wdGlvbnMpIHtcclxuICAgIGlmICghb3B0aW9ucz8uZW1haWwgfHwgIW9wdGlvbnM/LnBhc3N3b3JkKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkVtYWlsIGFuZCBwYXNzd29yZCBhcmUgcmVxdWlyZWQgdG8gY3JlYXRlIGEgTGlicmVMaW5rQ2xpZW50IGluc3RhbmNlLlwiKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmNyZWRlbnRpYWxzID0ge1xyXG4gICAgICBlbWFpbDogb3B0aW9ucy5lbWFpbCxcclxuICAgICAgcGFzc3dvcmQ6IG9wdGlvbnMucGFzc3dvcmRcclxuICAgIH07XHJcblxyXG4gICAgdGhpcy5hcGlVcmwgPSBvcHRpb25zLmFwaVVybCA/PyBERUZBVUxUX09QVElPTlMuYXBpVXJsITtcclxuICAgIHRoaXMucGF0aWVudElkID0gb3B0aW9ucy5wYXRpZW50SWQgPz8gbnVsbDtcclxuICAgIHRoaXMubGx1VmVyc2lvbiA9IG9wdGlvbnMubGx1VmVyc2lvbiA/PyBERUZBVUxUX09QVElPTlMubGx1VmVyc2lvbiE7XHJcblxyXG4gICAgLy8gTWVyZ2UgdGhlIG9wdGlvbnMgd2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zLlxyXG4gICAgdGhpcy5vcHRpb25zID0geyAuLi5ERUZBVUxUX09QVElPTlMsIC4uLm9wdGlvbnMgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIHVzZXIgZGF0YS4gT25seSBhdmFpbGFibGUgYWZ0ZXIgbG9nZ2luZyBpbi5cclxuICAgKi9cclxuICBwdWJsaWMgZ2V0IG1lKCk6IExpYnJlVXNlciB8IG51bGwge1xyXG4gICAgaWYgKCF0aGlzLmNhY2hlLmhhcyhcInVzZXJcIikpIHtcclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0KFwidXNlclwiKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiBMb2cgaW50byB0aGUgTGlicmUgTGluayBVcCBBUEkgdXNpbmcgdGhlIHByb3ZpZGVkIGNyZWRlbnRpYWxzLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBsb2dpbigpOiBQcm9taXNlPExpYnJlTG9naW5SZXNwb25zZT4ge1xyXG4gICAgY29uc3QgeyBlbWFpbCwgcGFzc3dvcmQgfSA9IHRoaXMuY3JlZGVudGlhbHM7XHJcblxyXG4gICAgdHJ5IHtcclxuICAgICAgdHlwZSBMb2dpblJlc3BvbnNlID0gTGlicmVMb2dpblJlc3BvbnNlIHwgTGlicmVSZWRpcmVjdFJlc3BvbnNlO1xyXG5cclxuICAgICAgLy8gQXR0ZW1wdCB0byBsb2dpbiB0byB0aGUgTGlicmUgTGluayBVcCBBUEkuXHJcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fZmV0Y2hlcjxMb2dpblJlc3BvbnNlPihMaWJyZUxpbmtVcEVuZHBvaW50cy5Mb2dpbiwge1xyXG4gICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXHJcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xyXG4gICAgICAgICAgZW1haWwsXHJcbiAgICAgICAgICBwYXNzd29yZFxyXG4gICAgICAgIH0pLFxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIC8vIElmIHRoZSBzdGF0dXMgaXMgMiwgbWVhbnMgdGhlIGNyZWRlbnRpYWxzIGFyZSBpbnZhbGlkLlxyXG4gICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSAyKVxyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgY3JlZGVudGlhbHMuIFBsZWFzZSBlbnN1cmUgdGhhdCB0aGUgZW1haWwgYW5kIHBhc3N3b3JkIHdvcmsgd2l0aCB0aGUgTGlicmVMaW5rVXAgYXBwLlwiKTtcclxuXHJcbiAgICAgIGlmICghcmVzcG9uc2UuZGF0YSlcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBkYXRhIHJldHVybmVkIGZyb20gTGlicmUgTGluayBVcCBBUEkuXCIpO1xyXG5cclxuICAgICAgLy8gSWYgdGhlIHJlc3BvbnNlIGNvbnRhaW5zIGEgcmVkaXJlY3QsIHVwZGF0ZSB0aGUgcmVnaW9uIGFuZCB0cnkgYWdhaW4uXHJcbiAgICAgIGlmIChcInJlZGlyZWN0XCIgaW4gcmVzcG9uc2UuZGF0YSkge1xyXG4gICAgICAgIGNvbnN0IHJlZ2lvblVybCA9IGF3YWl0IHRoaXMuZmluZFJlZ2lvbihyZXNwb25zZS5kYXRhLnJlZ2lvbik7XHJcbiAgICAgICAgLy8gVXBkYXRlIHRoZSBBUEkgVVJMIHdpdGggdGhlIHJlZ2lvbiB1cmwuXHJcbiAgICAgICAgdGhpcy5hcGlVcmwgPSByZWdpb25Vcmw7XHJcblxyXG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmxvZ2luKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIFNldCB0aGUgYWNjZXNzIHRva2VuIGZvciBmdXR1cmUgcmVxdWVzdHMuXHJcbiAgICAgIHRoaXMuYWNjZXNzVG9rZW4gPSByZXNwb25zZS5kYXRhLmF1dGhUaWNrZXQ/LnRva2VuO1xyXG5cclxuICAgICAgLy8gQ2FjaGUgdGhlIHVzZXIgZGF0YSBmb3IgZnV0dXJlIHVzZS4gTG9nIGluIGFnYWluIHRvIHJlZnJlc2ggdGhlIHVzZXIgZGF0YS5cclxuICAgICAgdGhpcy5zZXRDYWNoZShcInVzZXJcIiwgcGFyc2VVc2VyKHJlc3BvbnNlLmRhdGEudXNlcikpO1xyXG5cclxuICAgICAgcmV0dXJuIHJlc3BvbnNlIGFzIExpYnJlTG9naW5SZXNwb25zZTtcclxuICAgIH0gY2F0Y2ggKGVycikge1xyXG4gICAgICBjb25zdCBlcnJvciA9IGVyciBhcyBFcnJvcjtcclxuXHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgbG9nZ2luZyBpbnRvIExpYnJlIExpbmsgVXAgQVBJLiAke2Vycm9yLm1lc3NhZ2V9YCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gUmVhZCB0aGUgZGF0YSBmcm9tIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS5cclxuICAgKiBAcmV0dXJucyBUaGUgbGF0ZXN0IGdsdWNvc2UgbWVhc3VyZW1lbnQgZnJvbSB0aGUgTGlicmUgTGluayBVcCBBUEkuXHJcbiAgICovXHJcbiAgcHVibGljIGFzeW5jIHJlYWQoKSB7XHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZmV0Y2hSZWFkaW5nKCk7XHJcblxyXG4gICAgICAvLyBQYXJzZSBhbmQgcmV0dXJuIHRoZSBsYXRlc3QgZ2x1Y29zZSBpdGVtIGZyb20gdGhlIHJlc3BvbnNlLlxyXG4gICAgICByZXR1cm4gbmV3IEdsdWNvc2VSZWFkaW5nKHJlc3BvbnNlLmRhdGE/LmNvbm5lY3Rpb24uZ2x1Y29zZUl0ZW0sIHJlc3BvbnNlLmRhdGEuY29ubmVjdGlvbik7XHJcbiAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgY29uc3QgZXJyb3IgPSBlcnIgYXMgRXJyb3I7XHJcblxyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHJlYWRpbmcgZGF0YSBmcm9tIExpYnJlIExpbmsgVXAgQVBJLiAke2Vycm9yLm1lc3NhZ2V9YCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gUmVhZCB0aGUgaGlzdG9yeSBkYXRhIGZyb20gdGhlIExpYnJlIExpbmsgVXAgQVBJLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBhc3luYyBoaXN0b3J5KCkge1xyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmZldGNoUmVhZGluZygpO1xyXG5cclxuICAgICAgY29uc3QgbGlzdCA9IHJlc3BvbnNlLmRhdGEuZ3JhcGhEYXRhLm1hcCgoaXRlbTogUmF3R2x1Y29zZVJlYWRpbmcpID0+IG5ldyBHbHVjb3NlUmVhZGluZyhpdGVtLCByZXNwb25zZS5kYXRhLmNvbm5lY3Rpb24pKTtcclxuXHJcbiAgICAgIHJldHVybiBsaXN0O1xyXG4gICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgIGNvbnN0IGVycm9yID0gZXJyIGFzIEVycm9yO1xyXG5cclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciByZWFkaW5nIGRhdGEgZnJvbSBMaWJyZSBMaW5rIFVwIEFQSS4gJHtlcnJvci5tZXNzYWdlfWApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIFJlYWQgdGhlIGxvZ2Jvb2sgZGF0YSBmcm9tIG1hbnVhbCBzY2FucyBmcm9tIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS5cclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgbG9nYm9vaygpIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5mZXRjaExvZ2Jvb2soKTtcclxuXHJcbiAgICAgIGNvbnN0IGxpc3QgPSByZXNwb25zZS5kYXRhLm1hcCgoaXRlbTogUmF3R2x1Y29zZVJlYWRpbmcpID0+IG5ldyBHbHVjb3NlUmVhZGluZyhpdGVtKSk7XHJcblxyXG4gICAgICByZXR1cm4gbGlzdDtcclxuICAgIH0gY2F0Y2ggKGVycikge1xyXG4gICAgICBjb25zdCBlcnJvciA9IGVyciBhcyBFcnJvcjtcclxuXHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgcmVhZGluZyBkYXRhIGZyb20gTGlicmUgTGluayBVcCBBUEkuICR7ZXJyb3IubWVzc2FnZX1gKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIFN0cmVhbSB0aGUgcmVhZGluZ3MgZnJvbSB0aGUgTGlicmUgTGluayBVcCBBUEkuXHJcbiAgICAgKiBAcGFyYW0gaW50ZXJ2YWxNcyBUaGUgaW50ZXJ2YWwgYmV0d2VlbiBlYWNoIHJlYWRpbmcuIERlZmF1bHQgaXMgOTAgc2Vjb25kcy5cclxuICAgICAqL1xyXG4gIHB1YmxpYyBhc3luYyAqc3RyZWFtKGludGVydmFsTXMgPSAxMDAwICogOTApIHtcclxuICAgIHdoaWxlICh0cnVlKSB7IC8vIEtlZXAgc3RyZWFtaW5nIHVudGlsIG1hbnVhbGx5IHN0b3BwZWRcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBjb25zdCByZWFkaW5nID0gYXdhaXQgdGhpcy5yZWFkKCk7XHJcbiAgICAgICAgeWllbGQgcmVhZGluZztcclxuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgaW50ZXJ2YWxNcykpO1xyXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgIHRocm93IGVycm9yO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gRmV0Y2ggdGhlIHJlYWRpbmcgZnJvbSB0aGUgTGlicmUgTGluayBVcCBBUEkuIFVzZSB0byBvYnRhaW4gdGhlIHJhdyByZWFkaW5nIGFuZCBtb3JlLlxyXG4gICAqIEByZXR1cm5zIFRoZSByZXNwb25zZSBmcm9tIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS5cclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgZmV0Y2hSZWFkaW5nKCkge1xyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgcGF0aWVudElkID0gYXdhaXQgdGhpcy5nZXRQYXRpZW50SWQoKTtcclxuXHJcbiAgICAgIGNvbnN0IGhlYWRlcnMgPSB7XHJcbiAgICAgICAgXCJBY2NvdW50LUlkXCI6IHRoaXMubWU/LmlkID8gYXdhaXQgZW5jcnlwdFNoYTI1Nih0aGlzLm1lLmlkKSA6IFwiXCIsXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX2ZldGNoZXI8TGlicmVDb25uZWN0aW9uUmVzcG9uc2U+KGAke0xpYnJlTGlua1VwRW5kcG9pbnRzLkNvbm5lY3Rpb25zfS8ke3BhdGllbnRJZH0vZ3JhcGhgLCB7IGhlYWRlcnMgfSk7XHJcblxyXG4gICAgICByZXR1cm4gcmVzcG9uc2U7XHJcbiAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgY29uc3QgZXJyb3IgPSBlcnIgYXMgRXJyb3I7XHJcblxyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGZldGNoaW5nIHJlYWRpbmcgZnJvbSBMaWJyZSBMaW5rIFVwIEFQSS4gJHtlcnJvci5tZXNzYWdlfWApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIEZldGNoIHRoZSBsb2dib29rIGZyb20gdGhlIExpYnJlIExpbmsgVXAgQVBJLiBVc2UgdG8gb2J0YWluIHRoZSBsaXN0IG9mIG1hbnVhbCBzY2FubmVkIHJlYWRpbmdzLlxyXG4gICAqIEByZXR1cm5zIFRoZSByZXNwb25zZSBmcm9tIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS5cclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgZmV0Y2hMb2dib29rKCkge1xyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgcGF0aWVudElkID0gYXdhaXQgdGhpcy5nZXRQYXRpZW50SWQoKTtcclxuXHJcbiAgICAgIGNvbnN0IGhlYWRlcnMgPSB7XHJcbiAgICAgICAgXCJBY2NvdW50LUlkXCI6IHRoaXMubWU/LmlkID8gYXdhaXQgZW5jcnlwdFNoYTI1Nih0aGlzLm1lLmlkKSA6IFwiXCIsXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX2ZldGNoZXI8TGlicmVMb2dib29rUmVzcG9uc2U+KGAke0xpYnJlTGlua1VwRW5kcG9pbnRzLkNvbm5lY3Rpb25zfS8ke3BhdGllbnRJZH0vbG9nYm9va2AsIHsgaGVhZGVycyB9KTtcclxuXHJcbiAgICAgIHJldHVybiByZXNwb25zZTtcclxuICAgIH0gY2F0Y2ggKGVycikge1xyXG4gICAgICBjb25zdCBlcnJvciA9IGVyciBhcyBFcnJvcjtcclxuXHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZmV0Y2hpbmcgcmVhZGluZyBmcm9tIExpYnJlIExpbmsgVXAgQVBJLiAke2Vycm9yLm1lc3NhZ2V9YCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gR2V0IHRoZSBjb25uZWN0aW9ucyBmcm9tIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS5cclxuICAgKi9cclxuICBwdWJsaWMgYXN5bmMgZmV0Y2hDb25uZWN0aW9ucygpIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGlmICh0aGlzLmNhY2hlLmhhcyhcImNvbm5lY3Rpb25zXCIpKVxyXG4gICAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldChcImNvbm5lY3Rpb25zXCIpO1xyXG5cclxuICAgICAgY29uc3QgaGVhZGVycyA9IHtcclxuICAgICAgICBcIkFjY291bnQtSWRcIjogdGhpcy5tZT8uaWQgPyBhd2FpdCBlbmNyeXB0U2hhMjU2KHRoaXMubWUuaWQpIDogXCJcIixcclxuICAgICAgfTtcclxuXHJcbiAgICAgIC8vIEZldGNoIHRoZSBjb25uZWN0aW9ucyBmcm9tIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS5cclxuICAgICAgY29uc3QgY29ubmVjdGlvbnMgPSBhd2FpdCB0aGlzLl9mZXRjaGVyKExpYnJlTGlua1VwRW5kcG9pbnRzLkNvbm5lY3Rpb25zLCB7IGhlYWRlcnMgfSk7XHJcblxyXG4gICAgICBpZiAoISFjb25uZWN0aW9ucz8uZGF0YT8ubGVuZ3RoKVxyXG4gICAgICAgIC8vIENhY2hlIHRoZSBjb25uZWN0aW9ucyBmb3IgZnV0dXJlIHVzZS5cclxuICAgICAgICB0aGlzLnNldENhY2hlKFwiY29ubmVjdGlvbnNcIiwgY29ubmVjdGlvbnMpO1xyXG5cclxuICAgICAgcmV0dXJuIGNvbm5lY3Rpb25zO1xyXG4gICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgIGNvbnN0IGVycm9yID0gZXJyIGFzIEVycm9yO1xyXG5cclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBmZXRjaGluZyBjb25uZWN0aW9ucyBmcm9tIExpYnJlIExpbmsgVXAgQVBJLiAke2Vycm9yLm1lc3NhZ2V9YCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gR2V0IHRoZSBwYXRpZW50IElEIGZyb20gdGhlIGNvbm5lY3Rpb25zLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgYXN5bmMgZ2V0UGF0aWVudElkKCkge1xyXG4gICAgY29uc3QgY29ubmVjdGlvbnMgPSBhd2FpdCB0aGlzLmZldGNoQ29ubmVjdGlvbnMoKTtcclxuXHJcbiAgICAvLyBJZiB0aGVyZSBhcmUgbm8gY29ubmVjdGlvbnMsIHRocm93IGFuIGVycm9yLlxyXG4gICAgaWYgKCFjb25uZWN0aW9ucy5kYXRhPy5sZW5ndGgpXHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGNvbm5lY3Rpb25zIGZvdW5kLiBQbGVhc2UgZW5zdXJlIHRoYXQgeW91IGhhdmUgYSBjb25uZWN0aW9uIHdpdGggdGhlIExpYnJlTGlua1VwIGFwcC5cIik7XHJcblxyXG4gICAgLy8gR2V0IHRoZSBwYXRpZW50IElEIGZyb20gdGhlIGNvbm5lY3Rpb25zLCBvciBmYWxsYmFjayB0byB0aGUgZmlyc3QgY29ubmVjdGlvbi5cclxuXHJcbiAgICBsZXQgcGF0aWVudElkID0gY29ubmVjdGlvbnMuZGF0YVswXS5wYXRpZW50SWQ7XHJcblxyXG4gICAgaWYgKHRoaXMucGF0aWVudElkKVxyXG4gICAgICBjb25uZWN0aW9ucy5kYXRhLmZpbmQoXHJcbiAgICAgICAgKGNvbm5lY3Rpb246IExpYnJlQ29ubmVjdGlvbikgPT4gY29ubmVjdGlvbi5wYXRpZW50SWQgPT09IHRoaXMucGF0aWVudElkXHJcbiAgICAgICk/LnBhdGllbnRJZDtcclxuXHJcbiAgICBpZiAoIXBhdGllbnRJZClcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBQYXRpZW50IElEIG5vdCBmb3VuZCBpbiBjb25uZWN0aW9ucy4gKCR7dGhpcy5wYXRpZW50SWR9KWApO1xyXG5cclxuICAgIHJldHVybiBwYXRpZW50SWQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gRmluZCB0aGUgcmVnaW9uIGluIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS4gVGhpcyBpcyB1c2VkIHdoZW4gdGhlIEFQSSByZXR1cm5zIGEgcmVkaXJlY3QuXHJcbiAgICogQHBhcmFtIHJlZ2lvbiBUaGUgcmVnaW9uIHRvIGZpbmQuXHJcbiAgICogQHJldHVybnMgVGhlIHNlcnZlciBVUkwgZm9yIHRoZSByZWdpb24uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhc3luYyBmaW5kUmVnaW9uKHJlZ2lvbjogc3RyaW5nKSB7XHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX2ZldGNoZXIoTGlicmVMaW5rVXBFbmRwb2ludHMuQ291bnRyeSk7XHJcblxyXG4gICAgICAvLyBGaW5kIHRoZSByZWdpb24gaW4gdGhlIHJlc3BvbnNlLlxyXG4gICAgICBjb25zdCBsc2xBcGkgPSByZXNwb25zZS5kYXRhPy5yZWdpb25hbE1hcFtyZWdpb25dPy5sc2xBcGk7XHJcblxyXG4gICAgICBpZiAoIWxzbEFwaSlcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZWdpb24gbm90IGZvdW5kIGluIExpYnJlIExpbmsgVXAgQVBJLlwiKTtcclxuXHJcbiAgICAgIHJldHVybiBsc2xBcGk7XHJcbiAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgY29uc3QgZXJyb3IgPSBlcnIgYXMgRXJyb3I7XHJcblxyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGZpbmRpbmcgcmVnaW9uIGluIExpYnJlIExpbmsgVXAgQVBJLiAke2Vycm9yLm1lc3NhZ2V9YCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gQSBnZW5lcmljIGZldGNoZXIgZm9yIHRoZSBMaWJyZSBMaW5rIFVwIEFQSS5cclxuICAgKiBAcGFyYW0gZW5kcG9pbnRcclxuICAgKiBAcGFyYW0gb3B0aW9uc1xyXG4gICAqIEBwYXJhbSBpc1JldHJ5IEludGVybmFsIGZsYWcgdG8gcHJldmVudCBpbmZpbml0ZSByZXRyeSBsb29wc1xyXG4gICAqL1xyXG4gIHByaXZhdGUgYXN5bmMgX2ZldGNoZXI8VCA9IExpYnJlUmVzcG9uc2U+KGVuZHBvaW50OiBzdHJpbmcsIG9wdGlvbnM6IGFueSA9IHsgaGVhZGVyczoge30gfSwgaXNSZXRyeSA9IGZhbHNlKTogUHJvbWlzZTxUPiB7XHJcbiAgICBjb25zdCBoZWFkZXJzID0ge1xyXG4gICAgICAuLi5vcHRpb25zLmhlYWRlcnMsXHJcbiAgICAgIEF1dGhvcml6YXRpb246IHRoaXMuYWNjZXNzVG9rZW4gPyBgQmVhcmVyICR7dGhpcy5hY2Nlc3NUb2tlbn1gIDogXCJcIixcclxuXHJcbiAgICAgIC8vIExpYnJlIExpbmsgVXAgQVBJIGhlYWRlcnNcclxuICAgICAgcHJvZHVjdDogJ2xsdS5hbmRyb2lkJyxcclxuICAgICAgdmVyc2lvbjogdGhpcy5sbHVWZXJzaW9uLFxyXG5cclxuICAgICAgJ2FjY2VwdC1lbmNvZGluZyc6ICdnemlwJyxcclxuICAgICAgJ2NhY2hlLWNvbnRyb2wnOiAnbm8tY2FjaGUnLFxyXG4gICAgICBjb25uZWN0aW9uOiAnS2VlcC1BbGl2ZScsXHJcbiAgICAgICdjb250ZW50LXR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXHJcbiAgICB9O1xyXG5cclxuICAgIGNvbnN0IHJlcXVlc3RPcHRpb25zID0gT2JqZWN0LmZyZWV6ZSh7XHJcbiAgICAgIC4uLm9wdGlvbnMsXHJcbiAgICAgIGhlYWRlcnNcclxuICAgIH0pO1xyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goXHJcbiAgICAgICAgYCR7dGhpcy5hcGlVcmx9LyR7ZW5kcG9pbnR9YCxcclxuICAgICAgICByZXF1ZXN0T3B0aW9uc1xyXG4gICAgICApO1xyXG5cclxuICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xyXG4gICAgICAgIGNvbnN0IGVycm9yUGF5bG9hZCA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcclxuICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBlcnJvclBheWxvYWQ/Lm1lc3NhZ2UgPz8gSlNPTi5zdHJpbmdpZnkoZXJyb3JQYXlsb2FkLCBudWxsLCAyKVxyXG5cclxuICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSA0MjkpXHJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRvbyBtYW55IHJlcXVlc3RzLiBQbGVhc2Ugd2FpdCBiZWZvcmUgdHJ5aW5nIGFnYWluLiAke2Vycm9yTWVzc2FnZX1gKTtcclxuXHJcbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGVycm9yIGlzIHJlbGF0ZWQgdG8gdG9rZW4gZXhwaXJhdGlvblxyXG4gICAgICAgIGlmICghaXNSZXRyeSAmJiB0aGlzLmlzVG9rZW5FeHBpcmVkRXJyb3IocmVzcG9uc2Uuc3RhdHVzLCBlcnJvck1lc3NhZ2UpKSB7XHJcbiAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAvLyBDbGVhciB0aGUgZXhwaXJlZCB0b2tlbiBhbmQgdXNlciBjYWNoZVxyXG4gICAgICAgICAgICB0aGlzLmFjY2Vzc1Rva2VuID0gbnVsbDtcclxuICAgICAgICAgICAgdGhpcy5jYWNoZS5kZWxldGUoXCJ1c2VyXCIpO1xyXG5cclxuICAgICAgICAgICAgLy8gQXR0ZW1wdCB0byBsb2dpbiBhZ2FpbiB0byByZWZyZXNoIHRoZSB0b2tlblxyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmxvZ2luKCk7XHJcblxyXG4gICAgICAgICAgICAvLyBSZXRyeSB0aGUgb3JpZ2luYWwgcmVxdWVzdCB3aXRoIHRoZSBuZXcgdG9rZW5cclxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2ZldGNoZXI8VD4oZW5kcG9pbnQsIG9wdGlvbnMsIHRydWUpO1xyXG4gICAgICAgICAgfSBjYXRjaCAobG9naW5FcnJvcikge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRva2VuIGV4cGlyZWQgYW5kIGF1dG9tYXRpYyBsb2dpbiBmYWlsZWQ6ICR7KGxvZ2luRXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9YCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXHJcbiAgICAgICAgICBgRXJyb3IgZmV0Y2hpbmcgZGF0YSBmcm9tIExpYnJlIExpbmsgVXAgQVBJIHdpdGggc3RhdHVzICR7cmVzcG9uc2Uuc3RhdHVzfS4gJHtlcnJvck1lc3NhZ2V9YFxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IGRhdGEgPSAoYXdhaXQgcmVzcG9uc2UuanNvbigpKSBhcyBUO1xyXG5cclxuICAgICAgcmV0dXJuIGRhdGE7XHJcbiAgICB9IGNhdGNoIChlcnIpIHtcclxuICAgICAgY29uc3QgZXJyb3IgPSBlcnIgYXMgRXJyb3I7XHJcblxyXG4gICAgICAvLyBDaGVjayBpZiB0aGlzIGlzIGEgbmV0d29yayBlcnJvciB0aGF0IG1pZ2h0IGluZGljYXRlIHRva2VuIGV4cGlyYXRpb25cclxuICAgICAgaWYgKCFpc1JldHJ5ICYmIHRoaXMuaXNUb2tlbkV4cGlyZWRFcnJvcigwLCBlcnJvci5tZXNzYWdlKSkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAvLyBDbGVhciB0aGUgZXhwaXJlZCB0b2tlbiBhbmQgdXNlciBjYWNoZVxyXG4gICAgICAgICAgdGhpcy5hY2Nlc3NUb2tlbiA9IG51bGw7XHJcbiAgICAgICAgICB0aGlzLmNhY2hlLmRlbGV0ZShcInVzZXJcIik7XHJcblxyXG4gICAgICAgICAgLy8gQXR0ZW1wdCB0byBsb2dpbiBhZ2FpbiB0byByZWZyZXNoIHRoZSB0b2tlblxyXG4gICAgICAgICAgYXdhaXQgdGhpcy5sb2dpbigpO1xyXG5cclxuICAgICAgICAgIC8vIFJldHJ5IHRoZSBvcmlnaW5hbCByZXF1ZXN0IHdpdGggdGhlIG5ldyB0b2tlblxyXG4gICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2ZldGNoZXI8VD4oZW5kcG9pbnQsIG9wdGlvbnMsIHRydWUpO1xyXG4gICAgICAgIH0gY2F0Y2ggKGxvZ2luRXJyb3IpIHtcclxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVG9rZW4gZXhwaXJlZCBhbmQgYXV0b21hdGljIGxvZ2luIGZhaWxlZDogJHsobG9naW5FcnJvciBhcyBFcnJvcikubWVzc2FnZX1gKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgcHJvY2Vzc2luZyByZXF1ZXN0IHRvIExpYnJlIExpbmsgVXAgQVBJLiAke2Vycm9yLm1lc3NhZ2V9YCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gQ2hlY2sgaWYgYW4gZXJyb3IgaW5kaWNhdGVzIHRoYXQgdGhlIGF1dGhlbnRpY2F0aW9uIHRva2VuIGhhcyBleHBpcmVkLlxyXG4gICAqIEBwYXJhbSBzdGF0dXNDb2RlIFRoZSBIVFRQIHN0YXR1cyBjb2RlIGZyb20gdGhlIHJlc3BvbnNlXHJcbiAgICogQHBhcmFtIGVycm9yTWVzc2FnZSBUaGUgZXJyb3IgbWVzc2FnZSBmcm9tIHRoZSByZXNwb25zZVxyXG4gICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGVycm9yIGluZGljYXRlcyB0b2tlbiBleHBpcmF0aW9uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBpc1Rva2VuRXhwaXJlZEVycm9yKHN0YXR1c0NvZGU6IG51bWJlciwgZXJyb3JNZXNzYWdlOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgIC8vIENoZWNrIGZvciBjb21tb24gdG9rZW4gZXhwaXJhdGlvbiBpbmRpY2F0b3JzXHJcbiAgICBjb25zdCB0b2tlbkVycm9ySW5kaWNhdG9ycyA9IFtcclxuICAgICAgJ3Rva2VuJyxcclxuICAgICAgJ2p3dCcsXHJcbiAgICAgICd1bmF1dGhvcml6ZWQnLFxyXG4gICAgICAnYXV0aGVudGljYXRpb24nLFxyXG4gICAgICAnZXhwaXJlZCcsXHJcbiAgICAgICdpbnZhbGlkIHRva2VuJyxcclxuICAgICAgJ2FjY2VzcyBkZW5pZWQnLFxyXG4gICAgICAnbWFsZm9ybWVkIGp3dCcsXHJcbiAgICAgICdtaXNzaW5nIGp3dCdcclxuICAgIF07XHJcblxyXG4gICAgY29uc3QgbWVzc2FnZUNvbnRhaW5zVG9rZW5FcnJvciA9IHRva2VuRXJyb3JJbmRpY2F0b3JzLnNvbWUoaW5kaWNhdG9yID0+XHJcbiAgICAgIGVycm9yTWVzc2FnZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKGluZGljYXRvci50b0xvd2VyQ2FzZSgpKVxyXG4gICAgKTtcclxuXHJcbiAgICAvLyBIVFRQIDQwMSAoVW5hdXRob3JpemVkKSwgNDAzIChGb3JiaWRkZW4pLCBvciA0MDAgKEJhZCBSZXF1ZXN0IHdpdGggSldUIGVycm9ycykgb2Z0ZW4gaW5kaWNhdGUgdG9rZW4gaXNzdWVzXHJcbiAgICBjb25zdCBpc0F1dGhTdGF0dXNDb2RlID0gc3RhdHVzQ29kZSA9PT0gNDAxIHx8IHN0YXR1c0NvZGUgPT09IDQwMyB8fCAoc3RhdHVzQ29kZSA9PT0gNDAwICYmIG1lc3NhZ2VDb250YWluc1Rva2VuRXJyb3IpO1xyXG5cclxuICAgIHJldHVybiBtZXNzYWdlQ29udGFpbnNUb2tlbkVycm9yIHx8IGlzQXV0aFN0YXR1c0NvZGU7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gQ2FjaGUgYSB2YWx1ZSwgaWYgY2FjaGluZyBpcyBlbmFibGVkLlxyXG4gICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byBjYWNoZSB0aGUgdmFsdWUgdW5kZXIuXHJcbiAgICogQHBhcmFtIHZhbHVlIFRoZSB2YWx1ZSB0byBjYWNoZS5cclxuICAgKi9cclxuICBwcml2YXRlIHNldENhY2hlKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XHJcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5jYWNoZSkgcmV0dXJuO1xyXG5cclxuICAgIHRoaXMuY2FjaGUuc2V0KGtleSwgdmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIENsZWFyIHRoZSBjYWNoZS5cclxuICAgKi9cclxuICBwdWJsaWMgY2xlYXJDYWNoZSgpIHtcclxuICAgIHRoaXMuY2FjaGUuY2xlYXIoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiBEZWJ1ZyBtZXRob2QgdG8gY2hlY2sgaWYgdGhlIGNsaWVudCBoYXMgYSB2YWxpZCBhY2Nlc3MgdG9rZW5cclxuICAgKiBAcmV0dXJucyBJbmZvcm1hdGlvbiBhYm91dCB0aGUgY3VycmVudCBhdXRoZW50aWNhdGlvbiBzdGF0ZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBnZXRBdXRoU3RhdHVzKCkge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgaGFzVG9rZW46ICEhdGhpcy5hY2Nlc3NUb2tlbixcclxuICAgICAgdG9rZW5MZW5ndGg6IHRoaXMuYWNjZXNzVG9rZW4/Lmxlbmd0aCB8fCAwLFxyXG4gICAgICBoYXNVc2VyOiAhIXRoaXMubWUsXHJcbiAgICAgIHVzZXJJZDogdGhpcy5tZT8uaWQgfHwgbnVsbFxyXG4gICAgfTtcclxuICB9XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgTGlicmVMaW5rQ2xpZW50T3B0aW9ucyB7XHJcbiAgZW1haWw6IHN0cmluZztcclxuICBwYXNzd29yZDogc3RyaW5nO1xyXG4gIGFwaVVybD86IHN0cmluZztcclxuICBwYXRpZW50SWQ/OiBzdHJpbmc7XHJcbiAgY2FjaGU/OiBib29sZWFuO1xyXG4gIGxsdVZlcnNpb24/OiBzdHJpbmc7XHJcbn1cclxuXHJcbmNvbnN0IERFRkFVTFRfT1BUSU9OUzogUGFydGlhbDxMaWJyZUxpbmtDbGllbnRPcHRpb25zPiA9IHtcclxuICBhcGlVcmw6IFwiaHR0cHM6Ly9hcGktdXMubGlicmV2aWV3LmlvXCIsXHJcbiAgY2FjaGU6IHRydWUsXHJcbiAgbGx1VmVyc2lvbjogXCI0LjcuMFwiXHJcbn07IgogIF0sCiAgIm1hcHBpbmdzIjogIkFBRU8sSUFBTSxFQUFxQixZQU9sQyxFQUVhLEVBQThCLENBQ3ZDLGdCQUNBLGFBQ0EsZ0JBQ0EsT0FDQSxjQUNBLFVBQ0osRUNWTyxJQUFN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