flightdeck 0.2.9 → 0.2.10

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,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- var K=Object.defineProperty;var ae=(e,t)=>{for(var i in t)K(e,i,{get:t[i],enumerable:!0,configurable:!0,set:(o)=>t[i]=()=>o})};import*as O from"node:path";import{cli as ee,optional as te,parseBooleanOption as ie,parseNumberOption as se}from"comline";import{z as r}from"zod";import{execSync as x,spawn as V}from"node:child_process";import{createServer as B}from"node:http";import{homedir as z}from"node:os";import{resolve as U}from"node:path";import{inspect as J}from"node:util";import{Future as d}from"atom.io/internal";import{discoverType as q}from"atom.io/introspection";import{fromEntries as k,toEntries as f}from"atom.io/json";import{ChildSocket as W}from"atom.io/realtime-server";import{CronJob as Y}from"cron";import{z as l}from"zod";import{existsSync as D,mkdirSync as A,readdirSync as C,readFileSync as H,rmSync as R,statSync as I,writeFileSync as G}from"node:fs";import{resolve as F}from"node:path";class L{rootDir;constructor(e){if(this.rootDir=e.path,!D(this.rootDir))A(this.rootDir,{recursive:!0})}getItem(e){let t=F(this.rootDir,e);if(D(t))return H(t,"utf-8");return null}setItem(e,t){let i=F(this.rootDir,e);G(i,t)}removeItem(e){let t=F(this.rootDir,e);if(D(t))R(t)}key(e){return C(this.rootDir).sort((o,n)=>{let c=I(o);return I(n).ctimeMs-c.ctimeMs})[e]??null}clear(){R(this.rootDir,{recursive:!0}),A(this.rootDir,{recursive:!0})}get length(){return C(this.rootDir).length}}import{createEnv as N}from"@t3-oss/env-core";import{z as M}from"zod";var _=N({server:{FLIGHTDECK_SECRET:M.string().optional()},clientPrefix:"NEVER",client:{},runtimeEnv:import.meta.env,emptyStringAsUndefined:!0});var Te=["downloaded","installed"],Ee=["notified","confirmed"];function Z(e){return/^\d+\.\d+\.\d+$/.test(e)||!Number.isNaN(Number.parseFloat(e))}class P{options;safety=0;storage;webhookServer;services;serviceIdx;defaultServicesReadyToUpdate;servicesReadyToUpdate;autoRespawnDeadServices;logger;serviceLoggers;updateAvailabilityChecker=null;servicesLive;servicesDead;live=new d(()=>{});dead=new d(()=>{});restartTimes=[];constructor(e){this.options=e;let{FLIGHTDECK_SECRET:t}=_,{flightdeckRootDir:i=U(z(),".flightdeck")}=e,o=e.port??8080,n=`http://localhost:${o}`,c=f(e.services);if(this.services=k(c.map(([s])=>[s,null])),this.serviceIdx=k(c.map(([s],a)=>[s,a])),this.defaultServicesReadyToUpdate=k(c.map(([s,{waitFor:a}])=>[s,!a])),this.servicesReadyToUpdate={...this.defaultServicesReadyToUpdate},this.autoRespawnDeadServices=!0,this.logger=new u(this.options.packageName,process.pid,void 0,{jsonLogging:this.options.jsonLogging??!1}),this.serviceLoggers=k(c.map(([s])=>[s,new u(this.options.packageName,process.pid,s,{jsonLogging:this.options.jsonLogging??!1})])),this.servicesLive=c.map(()=>new d(()=>{})),this.servicesDead=c.map(()=>new d(()=>{})),this.live.use(Promise.all(this.servicesLive)),this.dead.use(Promise.all(this.servicesDead)),this.storage=new L({path:U(i,"storage",e.packageName)}),t===void 0)this.logger.warn("No FLIGHTDECK_SECRET environment variable found. FlightDeck will not run an update server.");else B((s,a)=>{let m=[];s.on("data",(p)=>{m.push(p instanceof Buffer?p:Buffer.from(p))}).on("end",()=>{let p=s.headers.authorization;try{if(typeof s.url==="undefined")throw 400;let h=`Bearer ${t}`;if(p!==`Bearer ${t}`)throw this.logger.info(`Unauthorized: needed \`${h}\`, got \`${p}\``),401;let S=new URL(s.url,n);this.logger.info(s.method,S.pathname);let v=Buffer.concat(m).toString();if(!Z(v))throw 400;a.writeHead(200),a.end(),this.storage.setItem("updatePhase","notified"),this.storage.setItem("updateAwaitedVersion",v);let{checkAvailability:j}=e.scripts;if(j){this.updateAvailabilityChecker?.stop(),this.seekUpdate(v);let E=this.storage.getItem("updatePhase");if(this.logger.info('> storage("updatePhase") >',E),E==="notified")this.updateAvailabilityChecker=new Y("30 * * * * *",()=>{this.seekUpdate(v)}),this.updateAvailabilityChecker.start()}else this.downloadPackage()}catch(h){if(this.logger.error(h,s.url),typeof h==="number")a.writeHead(h),a.end()}finally{m=[]}})}).listen(o,()=>{this.logger.info(`Server started on port ${o}`)});this.startAllServices().then(()=>{this.logger.info("All services started.")}).catch((s)=>{if(s instanceof Error)this.logger.error("Failed to start all services:",s.message)})}seekUpdate(e){this.logger.info("Checking for updates...");let{checkAvailability:t}=this.options.scripts;if(!t){this.logger.info("No checkAvailability script found.");return}try{let i=x(`${t} ${e}`);this.logger.info("Check stdout:",i.toString()),this.updateAvailabilityChecker?.stop(),this.storage.setItem("updatePhase","confirmed"),this.downloadPackage(),this.announceUpdate()}catch(i){if(i instanceof Error)this.logger.error("Check failed:",i.message);else{let o=q(i);this.logger.error("Check threw",o,i)}}}announceUpdate(){for(let e of f(this.services)){let[t,i]=e;if(i){if(this.options.services[t].waitFor)i.emit("updatesReady")}else this.startService(t)}}tryUpdate(){if(f(this.servicesReadyToUpdate).every(([,e])=>e))this.logger.info("All services are ready to update."),this.stopAllServices().then(()=>{this.logger.info("All services stopped; starting up fresh..."),this.startAllServices().then(()=>{this.logger.info("All services started; we're back online.")}).catch((e)=>{if(e instanceof Error)this.logger.error("Failed to start all services:",e.message)})}).catch((e)=>{if(e instanceof Error)this.logger.error("Failed to stop all services:",e.message)})}startAllServices(){this.logger.info("Starting all services..."),this.autoRespawnDeadServices=!0;let e=this.storage.getItem("setupPhase");switch(this.logger.info('> storage("setupPhase") >',e),e){case null:return this.logger.info("Starting from scratch."),this.downloadPackage(),this.installPackage(),this.startAllServices();case"downloaded":return this.logger.info("Found package downloaded but not installed."),this.installPackage(),this.startAllServices();case"installed":{for(let[t]of f(this.services))this.startService(t);return this.live}}}startService(e){if(this.logger.info(`Starting service ${this.options.packageName}::${e}, try ${this.safety}/2...`),this.safety>=2)throw new Error("Out of tries...");this.safety++;let[t,...i]=this.options.services[e].run.split(" "),o=V(t,i,{cwd:this.options.flightdeckRootDir,env:import.meta.env}),n=this.serviceLoggers[e],c=this.services[e]=new W(o,`${this.options.packageName}::${e}`,n);n.processCode=c.process.pid??-1,this.services[e].onAny((...s)=>{n.info("\uD83D\uDCAC",...s)}),this.services[e].on("readyToUpdate",()=>{this.logger.info(`Service "${e}" is ready to update.`),this.servicesReadyToUpdate[e]=!0,this.tryUpdate()}),this.services[e].on("alive",()=>{if(this.servicesLive[this.serviceIdx[e]].use(Promise.resolve()),this.servicesDead[this.serviceIdx[e]]=new d(()=>{}),this.dead.done)this.dead=new d(()=>{});this.dead.use(Promise.all(this.servicesDead))}),this.services[e].process.once("close",(s)=>{if(this.logger.info(`Auto-respawn saw "${e}" exit with code ${s}`),this.services[e]=null,!this.autoRespawnDeadServices){this.logger.info(`Auto-respawn is off; "${e}" rests.`);return}let a=this.storage.getItem("updatePhase");if(this.logger.info('> storage("updatePhase") >',a),a==="confirmed")this.serviceLoggers[e].info("Updating before startup..."),this.restartTimes=[],this.installPackage(),this.startService(e);else{let p=Date.now(),h=p-300000;if(this.restartTimes=this.restartTimes.filter((S)=>S>h),this.restartTimes.push(p),this.restartTimes.length<5)this.serviceLoggers[e].info("Crashed. Restarting..."),this.startService(e);else this.serviceLoggers[e].info("Crashed 5 times in 5 minutes. Not restarting.")}}),this.safety=0}downloadPackage(){this.logger.info("Downloading...");try{let e=x(this.options.scripts.download);this.logger.info("Download stdout:",e.toString()),this.storage.setItem("setupPhase","downloaded"),this.logger.info("Downloaded!")}catch(e){if(e instanceof Error)this.logger.error(`Failed to get the latest release: ${e.message}`);return}}installPackage(){this.logger.info("Installing...");try{let e=x(this.options.scripts.install);this.logger.info("Install stdout:",e.toString()),this.storage.setItem("setupPhase","installed"),this.logger.info("Installed!")}catch(e){if(e instanceof Error)this.logger.error(`Failed to get the latest release: ${e.message}`);return}}stopAllServices(){this.logger.info("Stopping all services... auto-respawn disabled."),this.autoRespawnDeadServices=!1;for(let[e]of f(this.services))this.stopService(e);return this.dead}stopService(e){let t=this.services[e];if(t){if(this.logger.info(`Stopping service "${e}"...`),this.servicesDead[this.serviceIdx[e]].use(new Promise((i)=>{t.emit("timeToStop"),t.process.once("close",(o)=>{this.logger.info(`Stopped service "${e}"; exited with code ${o}`),this.services[e]=null,i()})})),this.dead.use(Promise.all(this.servicesDead)),this.servicesLive[this.serviceIdx[e]]=new d(()=>{}),this.live.done)this.live=new d(()=>{});this.live.use(Promise.all(this.servicesLive))}else this.serviceLoggers[e].error("Tried to stop service, but it wasn't running.")}}var y="info",b="warn",w="ERR!",Ae=l.object({level:l.union([l.literal(y),l.literal(b),l.literal(w)]),timestamp:l.number(),package:l.string(),service:l.string().optional(),process:l.number(),body:l.string()}),Q="line-format",X="value",Ce={title:"FlightDeck Log",description:"Format for events logged by the FlightDeck process manager.","file-type":"json","timestamp-field":"timestamp","timestamp-divisor":1000,"module-field":"package","opid-field":"service","level-field":"level",level:{info:y,warning:b,error:w},[Q]:[{field:"level"},{prefix:" ",field:"__timestamp__","timestamp-format":"%Y-%m-%dT%H:%M:%S.%L%Z"},{prefix:" ",field:"process","min-width":5},{prefix:":",field:"package"},{prefix:":",field:"service","default-value":""},{prefix:": ",field:"body"}],[X]:{timestamp:{kind:"integer"},level:{kind:"string"},package:{kind:"string"},service:{kind:"string"},process:{kind:"integer"},body:{kind:"string"}}};class u{packageName;serviceName;jsonLogging;processCode;constructor(e,t,i,o){if(this.packageName=e,i)this.serviceName=i;this.processCode=t,this.jsonLogging=o?.jsonLogging??!1}log(e,...t){if(this.jsonLogging){let i=t.map((n)=>typeof n==="string"?n:J(n,!1,null,!0)).join(" ");if(i.includes(`
3
- `))i=`
4
- ${i.split(`
2
+ var R=Object.defineProperty;var X=(e,i)=>{for(var t in i)R(e,t,{get:i[t],enumerable:!0,configurable:!0,set:(o)=>i[t]=()=>o})};import*as T from"node:path";import{cli as z,optional as J,parseBooleanOption as q,parseNumberOption as W}from"comline";import{z as r}from"zod";import{execSync as F,spawn as U}from"node:child_process";import{createServer as $}from"node:http";import{homedir as j}from"node:os";import{resolve as A}from"node:path";import{inspect as O}from"node:util";import{Future as d}from"atom.io/internal";import{discoverType as H}from"atom.io/introspection";import{fromEntries as k,toEntries as f}from"atom.io/json";import{ChildSocket as G}from"atom.io/realtime-server";import{CronJob as N}from"cron";import{FilesystemStorage as K}from"safedeposit";import{z as a}from"zod";import{createEnv as I}from"@t3-oss/env-core";import{z as _}from"zod";var x=I({server:{FLIGHTDECK_SECRET:_.string().optional()},clientPrefix:"NEVER",client:{},runtimeEnv:import.meta.env,emptyStringAsUndefined:!0});var ve=["downloaded","installed"],ke=["notified","confirmed"];function M(e){return/^\d+\.\d+\.\d+$/.test(e)||!Number.isNaN(Number.parseFloat(e))}class L{options;safety=0;storage;webhookServer;services;serviceIdx;defaultServicesReadyToUpdate;servicesReadyToUpdate;autoRespawnDeadServices;logger;serviceLoggers;updateAvailabilityChecker=null;servicesLive;servicesDead;live=new d(()=>{});dead=new d(()=>{});restartTimes=[];constructor(e){this.options=e;let{FLIGHTDECK_SECRET:i}=x,{flightdeckRootDir:t=A(j(),".flightdeck")}=e,o=e.port??8080,c=`http://localhost:${o}`,p=f(e.services);if(this.services=k(p.map(([s])=>[s,null])),this.serviceIdx=k(p.map(([s],n)=>[s,n])),this.defaultServicesReadyToUpdate=k(p.map(([s,{waitFor:n}])=>[s,!n])),this.servicesReadyToUpdate={...this.defaultServicesReadyToUpdate},this.autoRespawnDeadServices=!0,this.logger=new u(this.options.packageName,process.pid,void 0,{jsonLogging:this.options.jsonLogging??!1}),this.serviceLoggers=k(p.map(([s])=>[s,new u(this.options.packageName,process.pid,s,{jsonLogging:this.options.jsonLogging??!1})])),this.servicesLive=p.map(()=>new d(()=>{})),this.servicesDead=p.map(()=>new d(()=>{})),this.live.use(Promise.all(this.servicesLive)),this.dead.use(Promise.all(this.servicesDead)),this.storage=new K({path:A(t,"storage",e.packageName)}),i===void 0)this.logger.warn("No FLIGHTDECK_SECRET environment variable found. FlightDeck will not run an update server.");else $((s,n)=>{let m=[];s.on("data",(l)=>{m.push(l instanceof Buffer?l:Buffer.from(l))}).on("end",()=>{let l=s.headers.authorization;try{if(typeof s.url==="undefined")throw 400;let h=`Bearer ${i}`;if(l!==`Bearer ${i}`)throw this.logger.info(`Unauthorized: needed \`${h}\`, got \`${l}\``),401;let S=new URL(s.url,c);this.logger.info(s.method,S.pathname);let v=Buffer.concat(m).toString();if(!M(v))throw 400;n.writeHead(200),n.end(),this.storage.setItem("updatePhase","notified"),this.storage.setItem("updateAwaitedVersion",v);let{checkAvailability:C}=e.scripts;if(C){this.updateAvailabilityChecker?.stop(),this.seekUpdate(v);let E=this.storage.getItem("updatePhase");if(this.logger.info('> storage("updatePhase") >',E),E==="notified")this.updateAvailabilityChecker=new N("30 * * * * *",()=>{this.seekUpdate(v)}),this.updateAvailabilityChecker.start()}else this.downloadPackage()}catch(h){if(this.logger.error(h,s.url),typeof h==="number")n.writeHead(h),n.end()}finally{m=[]}})}).listen(o,()=>{this.logger.info(`Server started on port ${o}`)});this.startAllServices().then(()=>{this.logger.info("All services started.")}).catch((s)=>{if(s instanceof Error)this.logger.error("Failed to start all services:",s.message)})}seekUpdate(e){this.logger.info("Checking for updates...");let{checkAvailability:i}=this.options.scripts;if(!i){this.logger.info("No checkAvailability script found.");return}try{let t=F(`${i} ${e}`);this.logger.info("Check stdout:",t.toString()),this.updateAvailabilityChecker?.stop(),this.storage.setItem("updatePhase","confirmed"),this.downloadPackage(),this.announceUpdate()}catch(t){if(t instanceof Error)this.logger.error("Check failed:",t.message);else{let o=H(t);this.logger.error("Check threw",o,t)}}}announceUpdate(){for(let e of f(this.services)){let[i,t]=e;if(t){if(this.options.services[i].waitFor)t.emit("updatesReady")}else this.startService(i)}}tryUpdate(){if(f(this.servicesReadyToUpdate).every(([,e])=>e))this.logger.info("All services are ready to update."),this.stopAllServices().then(()=>{this.logger.info("All services stopped; starting up fresh..."),this.startAllServices().then(()=>{this.logger.info("All services started; we're back online.")}).catch((e)=>{if(e instanceof Error)this.logger.error("Failed to start all services:",e.message)})}).catch((e)=>{if(e instanceof Error)this.logger.error("Failed to stop all services:",e.message)})}startAllServices(){this.logger.info("Starting all services..."),this.autoRespawnDeadServices=!0;let e=this.storage.getItem("setupPhase");switch(this.logger.info('> storage("setupPhase") >',e),e){case null:return this.logger.info("Starting from scratch."),this.downloadPackage(),this.installPackage(),this.startAllServices();case"downloaded":return this.logger.info("Found package downloaded but not installed."),this.installPackage(),this.startAllServices();case"installed":{for(let[i]of f(this.services))this.startService(i);return this.live}}}startService(e){if(this.logger.info(`Starting service ${this.options.packageName}::${e}, try ${this.safety}/2...`),this.safety>=2)throw new Error("Out of tries...");this.safety++;let[i,...t]=this.options.services[e].run.split(" "),o=U(i,t,{cwd:this.options.flightdeckRootDir,env:import.meta.env}),c=this.serviceLoggers[e],p=this.services[e]=new G(o,`${this.options.packageName}::${e}`,c);c.processCode=p.process.pid??-1,this.services[e].onAny((...s)=>{c.info("\uD83D\uDCAC",...s)}),this.services[e].on("readyToUpdate",()=>{this.logger.info(`Service "${e}" is ready to update.`),this.servicesReadyToUpdate[e]=!0,this.tryUpdate()}),this.services[e].on("alive",()=>{if(this.servicesLive[this.serviceIdx[e]].use(Promise.resolve()),this.servicesDead[this.serviceIdx[e]]=new d(()=>{}),this.dead.done)this.dead=new d(()=>{});this.dead.use(Promise.all(this.servicesDead))}),this.services[e].process.once("close",(s)=>{if(this.logger.info(`Auto-respawn saw "${e}" exit with code ${s}`),this.services[e]=null,!this.autoRespawnDeadServices){this.logger.info(`Auto-respawn is off; "${e}" rests.`);return}let n=this.storage.getItem("updatePhase");if(this.logger.info('> storage("updatePhase") >',n),n==="confirmed")this.serviceLoggers[e].info("Updating before startup..."),this.restartTimes=[],this.installPackage(),this.startService(e);else{let l=Date.now(),h=l-300000;if(this.restartTimes=this.restartTimes.filter((S)=>S>h),this.restartTimes.push(l),this.restartTimes.length<5)this.serviceLoggers[e].info("Crashed. Restarting..."),this.startService(e);else this.serviceLoggers[e].info("Crashed 5 times in 5 minutes. Not restarting.")}}),this.safety=0}downloadPackage(){this.logger.info("Downloading...");try{let e=F(this.options.scripts.download);this.logger.info("Download stdout:",e.toString()),this.storage.setItem("setupPhase","downloaded"),this.logger.info("Downloaded!")}catch(e){if(e instanceof Error)this.logger.error(`Failed to get the latest release: ${e.message}`);return}}installPackage(){this.logger.info("Installing...");try{let e=F(this.options.scripts.install);this.logger.info("Install stdout:",e.toString()),this.storage.setItem("setupPhase","installed"),this.logger.info("Installed!")}catch(e){if(e instanceof Error)this.logger.error(`Failed to get the latest release: ${e.message}`);return}}stopAllServices(){this.logger.info("Stopping all services... auto-respawn disabled."),this.autoRespawnDeadServices=!1;for(let[e]of f(this.services))this.stopService(e);return this.dead}stopService(e){let i=this.services[e];if(i){if(this.logger.info(`Stopping service "${e}"...`),this.servicesDead[this.serviceIdx[e]].use(new Promise((t)=>{i.emit("timeToStop"),i.process.once("close",(o)=>{this.logger.info(`Stopped service "${e}"; exited with code ${o}`),this.services[e]=null,t()})})),this.dead.use(Promise.all(this.servicesDead)),this.servicesLive[this.serviceIdx[e]]=new d(()=>{}),this.live.done)this.live=new d(()=>{});this.live.use(Promise.all(this.servicesLive))}else this.serviceLoggers[e].error("Tried to stop service, but it wasn't running.")}}var w="info",b="warn",y="ERR!",we=a.object({level:a.union([a.literal(w),a.literal(b),a.literal(y)]),timestamp:a.number(),package:a.string(),service:a.string().optional(),process:a.number(),body:a.string()}),V="line-format",B="value",be={title:"FlightDeck Log",description:"Format for events logged by the FlightDeck process manager.","file-type":"json","timestamp-field":"timestamp","timestamp-divisor":1000,"module-field":"package","opid-field":"service","level-field":"level",level:{info:w,warning:b,error:y},[V]:[{field:"level"},{prefix:" ",field:"__timestamp__","timestamp-format":"%Y-%m-%dT%H:%M:%S.%L%Z"},{prefix:" ",field:"process","min-width":5},{prefix:":",field:"package"},{prefix:":",field:"service","default-value":""},{prefix:": ",field:"body"}],[B]:{timestamp:{kind:"integer"},level:{kind:"string"},package:{kind:"string"},service:{kind:"string"},process:{kind:"integer"},body:{kind:"string"}}};class u{packageName;serviceName;jsonLogging;processCode;constructor(e,i,t,o){if(this.packageName=e,t)this.serviceName=t;this.processCode=i,this.jsonLogging=o?.jsonLogging??!1}log(e,...i){if(this.jsonLogging){let t=i.map((c)=>typeof c==="string"?c:O(c,!1,null,!0)).join(" ");if(t.includes(`
3
+ `))t=`
4
+ ${t.split(`
5
5
  `).join(`
6
- `)}`;let o={timestamp:Date.now(),level:e,process:this.processCode,package:this.packageName,body:i};if(this.serviceName)o.service=this.serviceName;process.stdout.write(JSON.stringify(o)+`
7
- `)}else{let i=this.serviceName?`${this.packageName}:${this.serviceName}`:this.packageName;switch(e){case y:console.log(`${i}:`,...t);break;case b:console.warn(`${i}:`,...t);break;case w:console.error(`${i}:`,...t);break}}}info(...e){this.log(y,...e)}warn(...e){this.log(b,...e)}error(...e){this.log(w,...e)}}var g=new u("comline",process.pid,void 0,{jsonLogging:!0});Object.assign(console,{log:g.info.bind(g),info:g.info.bind(g),warn:g.warn.bind(g),error:g.error.bind(g)});var $={optionsSchema:r.object({port:r.number().optional(),packageName:r.string(),services:r.record(r.object({run:r.string(),waitFor:r.boolean()})),flightdeckRootDir:r.string(),scripts:r.object({download:r.string(),install:r.string(),checkAvailability:r.string()}),jsonLogging:r.boolean().optional()}),options:{port:{flag:"p",required:!1,description:"Port to run the flightdeck server on.",example:"--port=8080",parse:se},packageName:{flag:"n",required:!0,description:"Name of the package.",example:'--packageName="my-app"'},services:{flag:"s",required:!0,description:"Map of service names to executables.",example:'--services="{\\"frontend\\":{\\"run\\":\\"./frontend\\",\\"waitFor\\":false},\\"backend\\":{\\"run\\":\\"./backend\\",\\"waitFor\\":true}}"',parse:JSON.parse},flightdeckRootDir:{flag:"d",required:!0,description:"Directory where the service is stored.",example:'--flightdeckRootDir="./services/sample/repo/my-app/current"'},scripts:{flag:"r",required:!0,description:"Map of scripts to run.",example:'--scripts="{\\"download\\":\\"npm i",\\"install\\":\\"npm run build\\"}"',parse:JSON.parse},jsonLogging:{flag:"j",required:!1,description:"Enable json logging.",example:"--jsonLogging",parse:ie}}},oe={optionsSchema:r.object({outdir:r.string().optional()}),options:{outdir:{flag:"o",required:!1,description:"Directory to write the schema to.",example:"--outdir=./dist"}}},re=ee({cliName:"flightdeck",routes:te({schema:null,$configPath:null}),routeOptions:{"":$,$configPath:$,schema:oe},debugOutput:!0,discoverConfigPath:(e)=>{if(e[0]==="schema")return;return e[0]??O.join(process.cwd(),"flightdeck.config.json")}},console),{inputs:T,writeJsonSchema:ne}=re(process.argv);switch(T.case){case"schema":{let{outdir:e}=T.opts;ne(e??".")}break;default:{let e=new P(T.opts);process.on("close",async()=>{await e.stopAllServices()})}}
6
+ `)}`;let o={timestamp:Date.now(),level:e,process:this.processCode,package:this.packageName,body:t};if(this.serviceName)o.service=this.serviceName;process.stdout.write(JSON.stringify(o)+`
7
+ `)}else{let t=this.serviceName?`${this.packageName}:${this.serviceName}`:this.packageName;switch(e){case w:console.log(`${t}:`,...i);break;case b:console.warn(`${t}:`,...i);break;case y:console.error(`${t}:`,...i);break}}}info(...e){this.log(w,...e)}warn(...e){this.log(b,...e)}error(...e){this.log(y,...e)}}var g=new u("comline",process.pid,void 0,{jsonLogging:!0});Object.assign(console,{log:g.info.bind(g),info:g.info.bind(g),warn:g.warn.bind(g),error:g.error.bind(g)});var P={optionsSchema:r.object({port:r.number().optional(),packageName:r.string(),services:r.record(r.object({run:r.string(),waitFor:r.boolean()})),flightdeckRootDir:r.string(),scripts:r.object({download:r.string(),install:r.string(),checkAvailability:r.string()}),jsonLogging:r.boolean().optional()}),options:{port:{flag:"p",required:!1,description:"Port to run the flightdeck server on.",example:"--port=8080",parse:W},packageName:{flag:"n",required:!0,description:"Name of the package.",example:'--packageName="my-app"'},services:{flag:"s",required:!0,description:"Map of service names to executables.",example:'--services="{\\"frontend\\":{\\"run\\":\\"./frontend\\",\\"waitFor\\":false},\\"backend\\":{\\"run\\":\\"./backend\\",\\"waitFor\\":true}}"',parse:JSON.parse},flightdeckRootDir:{flag:"d",required:!0,description:"Directory where the service is stored.",example:'--flightdeckRootDir="./services/sample/repo/my-app/current"'},scripts:{flag:"r",required:!0,description:"Map of scripts to run.",example:'--scripts="{\\"download\\":\\"npm i",\\"install\\":\\"npm run build\\"}"',parse:JSON.parse},jsonLogging:{flag:"j",required:!1,description:"Enable json logging.",example:"--jsonLogging",parse:q}}},Y={optionsSchema:r.object({outdir:r.string().optional()}),options:{outdir:{flag:"o",required:!1,description:"Directory to write the schema to.",example:"--outdir=./dist"}}},Z=z({cliName:"flightdeck",routes:J({schema:null,$configPath:null}),routeOptions:{"":P,$configPath:P,schema:Y},debugOutput:!0,discoverConfigPath:(e)=>{if(e[0]==="schema")return;return e[0]??T.join(process.cwd(),"flightdeck.config.json")}},console),{inputs:D,writeJsonSchema:Q}=Z(process.argv);switch(D.case){case"schema":{let{outdir:e}=D.opts;Q(e??".")}break;default:{let e=new L(D.opts);process.on("close",async()=>{await e.stopAllServices()})}}
8
8
 
9
- //# debugId=8C257A7694D940D664756E2164756E21
10
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2ZsaWdodGRlY2suYmluLnRzIiwgIi4uL3NyYy9mbGlnaHRkZWNrLmxpYi50cyIsICIuLi9zcmMvZmlsZXN5c3RlbS1zdG9yYWdlLnRzIiwgIi4uL3NyYy9mbGlnaHRkZWNrLmVudi50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsKICAgICIjIS91c3IvYmluL2VudiBub2RlXG5cbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiXG5cbmltcG9ydCB0eXBlIHsgT3B0aW9uc0dyb3VwIH0gZnJvbSBcImNvbWxpbmVcIlxuaW1wb3J0IHsgY2xpLCBvcHRpb25hbCwgcGFyc2VCb29sZWFuT3B0aW9uLCBwYXJzZU51bWJlck9wdGlvbiB9IGZyb20gXCJjb21saW5lXCJcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCJcblxuaW1wb3J0IHR5cGUgeyBGbGlnaHREZWNrT3B0aW9ucyB9IGZyb20gXCIuL2ZsaWdodGRlY2subGliXCJcbmltcG9ydCB7IEZsaWdodERlY2ssIEZsaWdodERlY2tMb2dnZXIgfSBmcm9tIFwiLi9mbGlnaHRkZWNrLmxpYlwiXG5cbmNvbnN0IENMSV9MT0dHRVIgPSBuZXcgRmxpZ2h0RGVja0xvZ2dlcihgY29tbGluZWAsIHByb2Nlc3MucGlkLCB1bmRlZmluZWQsIHtcblx0anNvbkxvZ2dpbmc6IHRydWUsXG59KVxuT2JqZWN0LmFzc2lnbihjb25zb2xlLCB7XG5cdGxvZzogQ0xJX0xPR0dFUi5pbmZvLmJpbmQoQ0xJX0xPR0dFUiksXG5cdGluZm86IENMSV9MT0dHRVIuaW5mby5iaW5kKENMSV9MT0dHRVIpLFxuXHR3YXJuOiBDTElfTE9HR0VSLndhcm4uYmluZChDTElfTE9HR0VSKSxcblx0ZXJyb3I6IENMSV9MT0dHRVIuZXJyb3IuYmluZChDTElfTE9HR0VSKSxcbn0pXG5cbmNvbnN0IEZMSUdIVERFQ0tfTUFOVUFMID0ge1xuXHRvcHRpb25zU2NoZW1hOiB6Lm9iamVjdCh7XG5cdFx0cG9ydDogei5udW1iZXIoKS5vcHRpb25hbCgpLFxuXHRcdHBhY2thZ2VOYW1lOiB6LnN0cmluZygpLFxuXHRcdHNlcnZpY2VzOiB6LnJlY29yZCh6Lm9iamVjdCh7IHJ1bjogei5zdHJpbmcoKSwgd2FpdEZvcjogei5ib29sZWFuKCkgfSkpLFxuXHRcdGZsaWdodGRlY2tSb290RGlyOiB6LnN0cmluZygpLFxuXHRcdHNjcmlwdHM6IHoub2JqZWN0KHtcblx0XHRcdGRvd25sb2FkOiB6LnN0cmluZygpLFxuXHRcdFx0aW5zdGFsbDogei5zdHJpbmcoKSxcblx0XHRcdGNoZWNrQXZhaWxhYmlsaXR5OiB6LnN0cmluZygpLFxuXHRcdH0pLFxuXHRcdGpzb25Mb2dnaW5nOiB6LmJvb2xlYW4oKS5vcHRpb25hbCgpLFxuXHR9KSxcblx0b3B0aW9uczoge1xuXHRcdHBvcnQ6IHtcblx0XHRcdGZsYWc6IGBwYCxcblx0XHRcdHJlcXVpcmVkOiBmYWxzZSxcblx0XHRcdGRlc2NyaXB0aW9uOiBgUG9ydCB0byBydW4gdGhlIGZsaWdodGRlY2sgc2VydmVyIG9uLmAsXG5cdFx0XHRleGFtcGxlOiBgLS1wb3J0PTgwODBgLFxuXHRcdFx0cGFyc2U6IHBhcnNlTnVtYmVyT3B0aW9uLFxuXHRcdH0sXG5cdFx0cGFja2FnZU5hbWU6IHtcblx0XHRcdGZsYWc6IGBuYCxcblx0XHRcdHJlcXVpcmVkOiB0cnVlLFxuXHRcdFx0ZGVzY3JpcHRpb246IGBOYW1lIG9mIHRoZSBwYWNrYWdlLmAsXG5cdFx0XHRleGFtcGxlOiBgLS1wYWNrYWdlTmFtZT1cXFwibXktYXBwXFxcImAsXG5cdFx0fSxcblx0XHRzZXJ2aWNlczoge1xuXHRcdFx0ZmxhZzogYHNgLFxuXHRcdFx0cmVxdWlyZWQ6IHRydWUsXG5cdFx0XHRkZXNjcmlwdGlvbjogYE1hcCBvZiBzZXJ2aWNlIG5hbWVzIHRvIGV4ZWN1dGFibGVzLmAsXG5cdFx0XHRleGFtcGxlOiBgLS1zZXJ2aWNlcz1cIntcXFxcXCJmcm9udGVuZFxcXFxcIjp7XFxcXFwicnVuXFxcXFwiOlxcXFxcIi4vZnJvbnRlbmRcXFxcXCIsXFxcXFwid2FpdEZvclxcXFxcIjpmYWxzZX0sXFxcXFwiYmFja2VuZFxcXFxcIjp7XFxcXFwicnVuXFxcXFwiOlxcXFxcIi4vYmFja2VuZFxcXFxcIixcXFxcXCJ3YWl0Rm9yXFxcXFwiOnRydWV9fVwiYCxcblx0XHRcdHBhcnNlOiBKU09OLnBhcnNlLFxuXHRcdH0sXG5cdFx0ZmxpZ2h0ZGVja1Jvb3REaXI6IHtcblx0XHRcdGZsYWc6IGBkYCxcblx0XHRcdHJlcXVpcmVkOiB0cnVlLFxuXHRcdFx0ZGVzY3JpcHRpb246IGBEaXJlY3Rvcnkgd2hlcmUgdGhlIHNlcnZpY2UgaXMgc3RvcmVkLmAsXG5cdFx0XHRleGFtcGxlOiBgLS1mbGlnaHRkZWNrUm9vdERpcj1cXFwiLi9zZXJ2aWNlcy9zYW1wbGUvcmVwby9teS1hcHAvY3VycmVudFxcXCJgLFxuXHRcdH0sXG5cdFx0c2NyaXB0czoge1xuXHRcdFx0ZmxhZzogYHJgLFxuXHRcdFx0cmVxdWlyZWQ6IHRydWUsXG5cdFx0XHRkZXNjcmlwdGlvbjogYE1hcCBvZiBzY3JpcHRzIHRvIHJ1bi5gLFxuXHRcdFx0ZXhhbXBsZTogYC0tc2NyaXB0cz1cIntcXFxcXCJkb3dubG9hZFxcXFxcIjpcXFxcXCJucG0gaVwiLFxcXFxcImluc3RhbGxcXFxcXCI6XFxcXFwibnBtIHJ1biBidWlsZFxcXFxcIn1cImAsXG5cdFx0XHRwYXJzZTogSlNPTi5wYXJzZSxcblx0XHR9LFxuXHRcdGpzb25Mb2dnaW5nOiB7XG5cdFx0XHRmbGFnOiBgamAsXG5cdFx0XHRyZXF1aXJlZDogZmFsc2UsXG5cdFx0XHRkZXNjcmlwdGlvbjogYEVuYWJsZSBqc29uIGxvZ2dpbmcuYCxcblx0XHRcdGV4YW1wbGU6IGAtLWpzb25Mb2dnaW5nYCxcblx0XHRcdHBhcnNlOiBwYXJzZUJvb2xlYW5PcHRpb24sXG5cdFx0fSxcblx0fSxcbn0gc2F0aXNmaWVzIE9wdGlvbnNHcm91cDxGbGlnaHREZWNrT3B0aW9ucz5cblxuY29uc3QgU0NIRU1BX01BTlVBTCA9IHtcblx0b3B0aW9uc1NjaGVtYTogei5vYmplY3Qoe1xuXHRcdG91dGRpcjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuXHR9KSxcblx0b3B0aW9uczoge1xuXHRcdG91dGRpcjoge1xuXHRcdFx0ZmxhZzogYG9gLFxuXHRcdFx0cmVxdWlyZWQ6IGZhbHNlLFxuXHRcdFx0ZGVzY3JpcHRpb246IGBEaXJlY3RvcnkgdG8gd3JpdGUgdGhlIHNjaGVtYSB0by5gLFxuXHRcdFx0ZXhhbXBsZTogYC0tb3V0ZGlyPS4vZGlzdGAsXG5cdFx0fSxcblx0fSxcbn0gc2F0aXNmaWVzIE9wdGlvbnNHcm91cDx7IG91dGRpcj86IHN0cmluZyB8IHVuZGVmaW5lZCB9PlxuXG5jb25zdCBwYXJzZSA9IGNsaShcblx0e1xuXHRcdGNsaU5hbWU6IGBmbGlnaHRkZWNrYCxcblx0XHRyb3V0ZXM6IG9wdGlvbmFsKHsgc2NoZW1hOiBudWxsLCAkY29uZmlnUGF0aDogbnVsbCB9KSxcblx0XHRyb3V0ZU9wdGlvbnM6IHtcblx0XHRcdFwiXCI6IEZMSUdIVERFQ0tfTUFOVUFMLFxuXHRcdFx0JGNvbmZpZ1BhdGg6IEZMSUdIVERFQ0tfTUFOVUFMLFxuXHRcdFx0c2NoZW1hOiBTQ0hFTUFfTUFOVUFMLFxuXHRcdH0sXG5cdFx0ZGVidWdPdXRwdXQ6IHRydWUsXG5cdFx0ZGlzY292ZXJDb25maWdQYXRoOiAoYXJncykgPT4ge1xuXHRcdFx0aWYgKGFyZ3NbMF0gPT09IGBzY2hlbWFgKSB7XG5cdFx0XHRcdHJldHVyblxuXHRcdFx0fVxuXHRcdFx0Y29uc3QgY29uZmlnUGF0aCA9XG5cdFx0XHRcdGFyZ3NbMF0gPz8gcGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIGBmbGlnaHRkZWNrLmNvbmZpZy5qc29uYClcblx0XHRcdHJldHVybiBjb25maWdQYXRoXG5cdFx0fSxcblx0fSxcblx0Y29uc29sZSxcbilcblxuY29uc3QgeyBpbnB1dHMsIHdyaXRlSnNvblNjaGVtYSB9ID0gcGFyc2UocHJvY2Vzcy5hcmd2KVxuXG5zd2l0Y2ggKGlucHV0cy5jYXNlKSB7XG5cdGNhc2UgYHNjaGVtYWA6XG5cdFx0e1xuXHRcdFx0Y29uc3QgeyBvdXRkaXIgfSA9IGlucHV0cy5vcHRzXG5cdFx0XHR3cml0ZUpzb25TY2hlbWEob3V0ZGlyID8/IGAuYClcblx0XHR9XG5cdFx0YnJlYWtcblx0ZGVmYXVsdDoge1xuXHRcdGNvbnN0IGZsaWdodERlY2sgPSBuZXcgRmxpZ2h0RGVjayhpbnB1dHMub3B0cylcblx0XHRwcm9jZXNzLm9uKGBjbG9zZWAsIGFzeW5jICgpID0+IHtcblx0XHRcdGF3YWl0IGZsaWdodERlY2suc3RvcEFsbFNlcnZpY2VzKClcblx0XHR9KVxuXHR9XG59XG4iLAogICAgImltcG9ydCB7IGV4ZWNTeW5jLCBzcGF3biB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIlxuaW1wb3J0IHR5cGUgeyBTZXJ2ZXIgfSBmcm9tIFwibm9kZTpodHRwXCJcbmltcG9ydCB7IGNyZWF0ZVNlcnZlciB9IGZyb20gXCJub2RlOmh0dHBcIlxuaW1wb3J0IHsgaG9tZWRpciB9IGZyb20gXCJub2RlOm9zXCJcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tIFwibm9kZTpwYXRoXCJcbmltcG9ydCB7IGluc3BlY3QgfSBmcm9tIFwibm9kZTp1dGlsXCJcblxuaW1wb3J0IHsgRnV0dXJlIH0gZnJvbSBcImF0b20uaW8vaW50ZXJuYWxcIlxuaW1wb3J0IHsgZGlzY292ZXJUeXBlIH0gZnJvbSBcImF0b20uaW8vaW50cm9zcGVjdGlvblwiXG5pbXBvcnQgeyBmcm9tRW50cmllcywgdG9FbnRyaWVzIH0gZnJvbSBcImF0b20uaW8vanNvblwiXG5pbXBvcnQgeyBDaGlsZFNvY2tldCB9IGZyb20gXCJhdG9tLmlvL3JlYWx0aW1lLXNlcnZlclwiXG5pbXBvcnQgeyBDcm9uSm9iIH0gZnJvbSBcImNyb25cIlxuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIlxuXG5pbXBvcnQgdHlwZSB7IExuYXZGb3JtYXQgfSBmcm9tIFwiLi4vZ2VuL2xuYXYtZm9ybWF0LXNjaGVtYS5nZW5cIlxuaW1wb3J0IHsgRmlsZXN5c3RlbVN0b3JhZ2UgfSBmcm9tIFwiLi9maWxlc3lzdGVtLXN0b3JhZ2VcIlxuaW1wb3J0IHsgZW52IH0gZnJvbSBcIi4vZmxpZ2h0ZGVjay5lbnZcIlxuXG5leHBvcnQgY29uc3QgRkxJR0hUREVDS19TRVRVUF9QSEFTRVMgPSBbYGRvd25sb2FkZWRgLCBgaW5zdGFsbGVkYF0gYXMgY29uc3RcblxuZXhwb3J0IHR5cGUgRmxpZ2h0RGVja1NldHVwUGhhc2UgPSAodHlwZW9mIEZMSUdIVERFQ0tfU0VUVVBfUEhBU0VTKVtudW1iZXJdXG5cbmV4cG9ydCBjb25zdCBGTElHSFRERUNLX1VQREFURV9QSEFTRVMgPSBbYG5vdGlmaWVkYCwgYGNvbmZpcm1lZGBdIGFzIGNvbnN0XG5cbmV4cG9ydCB0eXBlIEZsaWdodERlY2tVcGRhdGVQaGFzZSA9ICh0eXBlb2YgRkxJR0hUREVDS19VUERBVEVfUEhBU0VTKVtudW1iZXJdXG5cbmV4cG9ydCBmdW5jdGlvbiBpc1ZlcnNpb25OdW1iZXIodmVyc2lvbjogc3RyaW5nKTogYm9vbGVhbiB7XG5cdHJldHVybiAoXG5cdFx0L15cXGQrXFwuXFxkK1xcLlxcZCskLy50ZXN0KHZlcnNpb24pIHx8ICFOdW1iZXIuaXNOYU4oTnVtYmVyLnBhcnNlRmxvYXQodmVyc2lvbikpXG5cdClcbn1cblxuZXhwb3J0IHR5cGUgRmxpZ2h0RGVja09wdGlvbnM8UyBleHRlbmRzIHN0cmluZyA9IHN0cmluZz4gPSB7XG5cdHBhY2thZ2VOYW1lOiBzdHJpbmdcblx0c2VydmljZXM6IHsgW3NlcnZpY2UgaW4gU106IHsgcnVuOiBzdHJpbmc7IHdhaXRGb3I6IGJvb2xlYW4gfSB9XG5cdHNjcmlwdHM6IHtcblx0XHRkb3dubG9hZDogc3RyaW5nXG5cdFx0aW5zdGFsbDogc3RyaW5nXG5cdFx0Y2hlY2tBdmFpbGFiaWxpdHk/OiBzdHJpbmdcblx0fVxuXHRwb3J0PzogbnVtYmVyIHwgdW5kZWZpbmVkXG5cdGZsaWdodGRlY2tSb290RGlyPzogc3RyaW5nIHwgdW5kZWZpbmVkXG5cdGpzb25Mb2dnaW5nPzogYm9vbGVhbiB8IHVuZGVmaW5lZFxufVxuXG5leHBvcnQgY2xhc3MgRmxpZ2h0RGVjazxTIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nPiB7XG5cdHByb3RlY3RlZCBzYWZldHkgPSAwXG5cblx0cHJvdGVjdGVkIHN0b3JhZ2U6IEZpbGVzeXN0ZW1TdG9yYWdlPHtcblx0XHRzZXR1cFBoYXNlOiBGbGlnaHREZWNrU2V0dXBQaGFzZVxuXHRcdHVwZGF0ZVBoYXNlOiBGbGlnaHREZWNrVXBkYXRlUGhhc2Vcblx0XHR1cGRhdGVBd2FpdGVkVmVyc2lvbjogc3RyaW5nXG5cdH0+XG5cdHByb3RlY3RlZCB3ZWJob29rU2VydmVyOiBTZXJ2ZXJcblx0cHJvdGVjdGVkIHNlcnZpY2VzOiB7XG5cdFx0W3NlcnZpY2UgaW4gU106IENoaWxkU29ja2V0PFxuXHRcdFx0eyB0aW1lVG9TdG9wOiBbXTsgdXBkYXRlc1JlYWR5OiBbXSB9LFxuXHRcdFx0eyByZWFkeVRvVXBkYXRlOiBbXTsgYWxpdmU6IFtdIH1cblx0XHQ+IHwgbnVsbFxuXHR9XG5cdHByb3RlY3RlZCBzZXJ2aWNlSWR4OiB7IHJlYWRvbmx5IFtzZXJ2aWNlIGluIFNdOiBudW1iZXIgfVxuXHRwdWJsaWMgZGVmYXVsdFNlcnZpY2VzUmVhZHlUb1VwZGF0ZTogeyByZWFkb25seSBbc2VydmljZSBpbiBTXTogYm9vbGVhbiB9XG5cdHB1YmxpYyBzZXJ2aWNlc1JlYWR5VG9VcGRhdGU6IHsgW3NlcnZpY2UgaW4gU106IGJvb2xlYW4gfVxuXHRwdWJsaWMgYXV0b1Jlc3Bhd25EZWFkU2VydmljZXM6IGJvb2xlYW5cblxuXHRwcm90ZWN0ZWQgbG9nZ2VyOiBQaWNrPENvbnNvbGUsIGBlcnJvcmAgfCBgaW5mb2AgfCBgd2FybmA+XG5cdHByb3RlY3RlZCBzZXJ2aWNlTG9nZ2Vyczoge1xuXHRcdHJlYWRvbmx5IFtzZXJ2aWNlIGluIFNdOiBGbGlnaHREZWNrTG9nZ2VyXG5cdH1cblxuXHRwcm90ZWN0ZWQgdXBkYXRlQXZhaWxhYmlsaXR5Q2hlY2tlcjogQ3JvbkpvYiB8IG51bGwgPSBudWxsXG5cblx0cHVibGljIHNlcnZpY2VzTGl2ZTogRnV0dXJlPHZvaWQ+W11cblx0cHVibGljIHNlcnZpY2VzRGVhZDogRnV0dXJlPHZvaWQ+W11cblx0cHVibGljIGxpdmUgPSBuZXcgRnV0dXJlKCgpID0+IHt9KVxuXHRwdWJsaWMgZGVhZCA9IG5ldyBGdXR1cmUoKCkgPT4ge30pXG5cblx0cHJvdGVjdGVkIHJlc3RhcnRUaW1lczogbnVtYmVyW10gPSBbXVxuXG5cdHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgb3B0aW9uczogRmxpZ2h0RGVja09wdGlvbnM8Uz4pIHtcblx0XHRjb25zdCB7IEZMSUdIVERFQ0tfU0VDUkVUIH0gPSBlbnZcblx0XHRjb25zdCB7IGZsaWdodGRlY2tSb290RGlyID0gcmVzb2x2ZShob21lZGlyKCksIGAuZmxpZ2h0ZGVja2ApIH0gPSBvcHRpb25zXG5cdFx0Y29uc3QgcG9ydCA9IG9wdGlvbnMucG9ydCA/PyA4MDgwXG5cdFx0Y29uc3Qgb3JpZ2luID0gYGh0dHA6Ly9sb2NhbGhvc3Q6JHtwb3J0fWBcblxuXHRcdGNvbnN0IHNlcnZpY2VzRW50cmllcyA9IHRvRW50cmllcyhvcHRpb25zLnNlcnZpY2VzKVxuXHRcdHRoaXMuc2VydmljZXMgPSBmcm9tRW50cmllcyhcblx0XHRcdHNlcnZpY2VzRW50cmllcy5tYXAoKFtzZXJ2aWNlTmFtZV0pID0+IFtzZXJ2aWNlTmFtZSwgbnVsbF0pLFxuXHRcdClcblx0XHR0aGlzLnNlcnZpY2VJZHggPSBmcm9tRW50cmllcyhcblx0XHRcdHNlcnZpY2VzRW50cmllcy5tYXAoKFtzZXJ2aWNlTmFtZV0sIGlkeCkgPT4gW3NlcnZpY2VOYW1lLCBpZHhdKSxcblx0XHQpXG5cdFx0dGhpcy5kZWZhdWx0U2VydmljZXNSZWFkeVRvVXBkYXRlID0gZnJvbUVudHJpZXMoXG5cdFx0XHRzZXJ2aWNlc0VudHJpZXMubWFwKChbc2VydmljZU5hbWUsIHsgd2FpdEZvciB9XSkgPT4gW1xuXHRcdFx0XHRzZXJ2aWNlTmFtZSxcblx0XHRcdFx0IXdhaXRGb3IsXG5cdFx0XHRdKSxcblx0XHQpXG5cdFx0dGhpcy5zZXJ2aWNlc1JlYWR5VG9VcGRhdGUgPSB7IC4uLnRoaXMuZGVmYXVsdFNlcnZpY2VzUmVhZHlUb1VwZGF0ZSB9XG5cdFx0dGhpcy5hdXRvUmVzcGF3bkRlYWRTZXJ2aWNlcyA9IHRydWVcblxuXHRcdHRoaXMubG9nZ2VyID0gbmV3IEZsaWdodERlY2tMb2dnZXIoXG5cdFx0XHR0aGlzLm9wdGlvbnMucGFja2FnZU5hbWUsXG5cdFx0XHRwcm9jZXNzLnBpZCxcblx0XHRcdHVuZGVmaW5lZCxcblx0XHRcdHsganNvbkxvZ2dpbmc6IHRoaXMub3B0aW9ucy5qc29uTG9nZ2luZyA/PyBmYWxzZSB9LFxuXHRcdClcblx0XHR0aGlzLnNlcnZpY2VMb2dnZXJzID0gZnJvbUVudHJpZXMoXG5cdFx0XHRzZXJ2aWNlc0VudHJpZXMubWFwKChbc2VydmljZU5hbWVdKSA9PiBbXG5cdFx0XHRcdHNlcnZpY2VOYW1lLFxuXHRcdFx0XHRuZXcgRmxpZ2h0RGVja0xvZ2dlcihcblx0XHRcdFx0XHR0aGlzLm9wdGlvbnMucGFja2FnZU5hbWUsXG5cdFx0XHRcdFx0cHJvY2Vzcy5waWQsXG5cdFx0XHRcdFx0c2VydmljZU5hbWUsXG5cdFx0XHRcdFx0eyBqc29uTG9nZ2luZzogdGhpcy5vcHRpb25zLmpzb25Mb2dnaW5nID8/IGZhbHNlIH0sXG5cdFx0XHRcdCksXG5cdFx0XHRdKSxcblx0XHQpXG5cblx0XHR0aGlzLnNlcnZpY2VzTGl2ZSA9IHNlcnZpY2VzRW50cmllcy5tYXAoKCkgPT4gbmV3IEZ1dHVyZSgoKSA9PiB7fSkpXG5cdFx0dGhpcy5zZXJ2aWNlc0RlYWQgPSBzZXJ2aWNlc0VudHJpZXMubWFwKCgpID0+IG5ldyBGdXR1cmUoKCkgPT4ge30pKVxuXHRcdHRoaXMubGl2ZS51c2UoUHJvbWlzZS5hbGwodGhpcy5zZXJ2aWNlc0xpdmUpKVxuXHRcdHRoaXMuZGVhZC51c2UoUHJvbWlzZS5hbGwodGhpcy5zZXJ2aWNlc0RlYWQpKVxuXG5cdFx0dGhpcy5zdG9yYWdlID0gbmV3IEZpbGVzeXN0ZW1TdG9yYWdlKHtcblx0XHRcdHBhdGg6IHJlc29sdmUoZmxpZ2h0ZGVja1Jvb3REaXIsIGBzdG9yYWdlYCwgb3B0aW9ucy5wYWNrYWdlTmFtZSksXG5cdFx0fSlcblxuXHRcdGlmIChGTElHSFRERUNLX1NFQ1JFVCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHR0aGlzLmxvZ2dlci53YXJuKFxuXHRcdFx0XHRgTm8gRkxJR0hUREVDS19TRUNSRVQgZW52aXJvbm1lbnQgdmFyaWFibGUgZm91bmQuIEZsaWdodERlY2sgd2lsbCBub3QgcnVuIGFuIHVwZGF0ZSBzZXJ2ZXIuYCxcblx0XHRcdClcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y3JlYXRlU2VydmVyKChyZXEsIHJlcykgPT4ge1xuXHRcdFx0XHRsZXQgZGF0YTogVWludDhBcnJheVtdID0gW11cblx0XHRcdFx0cmVxXG5cdFx0XHRcdFx0Lm9uKGBkYXRhYCwgKGNodW5rKSA9PiB7XG5cdFx0XHRcdFx0XHRkYXRhLnB1c2goY2h1bmsgaW5zdGFuY2VvZiBCdWZmZXIgPyBjaHVuayA6IEJ1ZmZlci5mcm9tKGNodW5rKSlcblx0XHRcdFx0XHR9KVxuXHRcdFx0XHRcdC5vbihgZW5kYCwgKCkgPT4ge1xuXHRcdFx0XHRcdFx0Y29uc3QgYXV0aEhlYWRlciA9IHJlcS5oZWFkZXJzLmF1dGhvcml6YXRpb25cblx0XHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRcdGlmICh0eXBlb2YgcmVxLnVybCA9PT0gYHVuZGVmaW5lZGApIHRocm93IDQwMFxuXHRcdFx0XHRcdFx0XHRjb25zdCBleHBlY3RlZEF1dGhIZWFkZXIgPSBgQmVhcmVyICR7RkxJR0hUREVDS19TRUNSRVR9YFxuXHRcdFx0XHRcdFx0XHRpZiAoYXV0aEhlYWRlciAhPT0gYEJlYXJlciAke0ZMSUdIVERFQ0tfU0VDUkVUfWApIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKFxuXHRcdFx0XHRcdFx0XHRcdFx0YFVuYXV0aG9yaXplZDogbmVlZGVkIFxcYCR7ZXhwZWN0ZWRBdXRoSGVhZGVyfVxcYCwgZ290IFxcYCR7YXV0aEhlYWRlcn1cXGBgLFxuXHRcdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdFx0XHR0aHJvdyA0MDFcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRjb25zdCB1cmwgPSBuZXcgVVJMKHJlcS51cmwsIG9yaWdpbilcblx0XHRcdFx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhyZXEubWV0aG9kLCB1cmwucGF0aG5hbWUpXG5cblx0XHRcdFx0XHRcdFx0Y29uc3QgdmVyc2lvbkZvcmVpZ25JbnB1dCA9IEJ1ZmZlci5jb25jYXQoZGF0YSkudG9TdHJpbmcoKVxuXHRcdFx0XHRcdFx0XHRpZiAoIWlzVmVyc2lvbk51bWJlcih2ZXJzaW9uRm9yZWlnbklucHV0KSkge1xuXHRcdFx0XHRcdFx0XHRcdHRocm93IDQwMFxuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0cmVzLndyaXRlSGVhZCgyMDApXG5cdFx0XHRcdFx0XHRcdHJlcy5lbmQoKVxuXG5cdFx0XHRcdFx0XHRcdHRoaXMuc3RvcmFnZS5zZXRJdGVtKGB1cGRhdGVQaGFzZWAsIGBub3RpZmllZGApXG5cdFx0XHRcdFx0XHRcdHRoaXMuc3RvcmFnZS5zZXRJdGVtKGB1cGRhdGVBd2FpdGVkVmVyc2lvbmAsIHZlcnNpb25Gb3JlaWduSW5wdXQpXG5cdFx0XHRcdFx0XHRcdGNvbnN0IHsgY2hlY2tBdmFpbGFiaWxpdHkgfSA9IG9wdGlvbnMuc2NyaXB0c1xuXHRcdFx0XHRcdFx0XHRpZiAoY2hlY2tBdmFpbGFiaWxpdHkpIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnVwZGF0ZUF2YWlsYWJpbGl0eUNoZWNrZXI/LnN0b3AoKVxuXHRcdFx0XHRcdFx0XHRcdHRoaXMuc2Vla1VwZGF0ZSh2ZXJzaW9uRm9yZWlnbklucHV0KVxuXHRcdFx0XHRcdFx0XHRcdGNvbnN0IHVwZGF0ZVBoYXNlID0gdGhpcy5zdG9yYWdlLmdldEl0ZW0oYHVwZGF0ZVBoYXNlYClcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGA+IHN0b3JhZ2UoXCJ1cGRhdGVQaGFzZVwiKSA+YCwgdXBkYXRlUGhhc2UpXG5cdFx0XHRcdFx0XHRcdFx0aWYgKHVwZGF0ZVBoYXNlID09PSBgbm90aWZpZWRgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR0aGlzLnVwZGF0ZUF2YWlsYWJpbGl0eUNoZWNrZXIgPSBuZXcgQ3JvbkpvYihcblx0XHRcdFx0XHRcdFx0XHRcdFx0YDMwICogKiAqICogKmAsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCgpID0+IHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0aGlzLnNlZWtVcGRhdGUodmVyc2lvbkZvcmVpZ25JbnB1dClcblx0XHRcdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdFx0XHRcdHRoaXMudXBkYXRlQXZhaWxhYmlsaXR5Q2hlY2tlci5zdGFydCgpXG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMuZG93bmxvYWRQYWNrYWdlKClcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBjYXRjaCAodGhyb3duKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKHRocm93biwgcmVxLnVybClcblx0XHRcdFx0XHRcdFx0aWYgKHR5cGVvZiB0aHJvd24gPT09IGBudW1iZXJgKSB7XG5cdFx0XHRcdFx0XHRcdFx0cmVzLndyaXRlSGVhZCh0aHJvd24pXG5cdFx0XHRcdFx0XHRcdFx0cmVzLmVuZCgpXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0gZmluYWxseSB7XG5cdFx0XHRcdFx0XHRcdGRhdGEgPSBbXVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pXG5cdFx0XHR9KS5saXN0ZW4ocG9ydCwgKCkgPT4ge1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBTZXJ2ZXIgc3RhcnRlZCBvbiBwb3J0ICR7cG9ydH1gKVxuXHRcdFx0fSlcblx0XHR9XG5cblx0XHR0aGlzLnN0YXJ0QWxsU2VydmljZXMoKVxuXHRcdFx0LnRoZW4oKCkgPT4ge1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBBbGwgc2VydmljZXMgc3RhcnRlZC5gKVxuXHRcdFx0fSlcblx0XHRcdC5jYXRjaCgodGhyb3duKSA9PiB7XG5cdFx0XHRcdGlmICh0aHJvd24gaW5zdGFuY2VvZiBFcnJvcikge1xuXHRcdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBGYWlsZWQgdG8gc3RhcnQgYWxsIHNlcnZpY2VzOmAsIHRocm93bi5tZXNzYWdlKVxuXHRcdFx0XHR9XG5cdFx0XHR9KVxuXHR9XG5cblx0cHJvdGVjdGVkIHNlZWtVcGRhdGUodmVyc2lvbjogc3RyaW5nKTogdm9pZCB7XG5cdFx0dGhpcy5sb2dnZXIuaW5mbyhgQ2hlY2tpbmcgZm9yIHVwZGF0ZXMuLi5gKVxuXHRcdGNvbnN0IHsgY2hlY2tBdmFpbGFiaWxpdHkgfSA9IHRoaXMub3B0aW9ucy5zY3JpcHRzXG5cdFx0aWYgKCFjaGVja0F2YWlsYWJpbGl0eSkge1xuXHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgTm8gY2hlY2tBdmFpbGFiaWxpdHkgc2NyaXB0IGZvdW5kLmApXG5cdFx0XHRyZXR1cm5cblx0XHR9XG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IG91dCA9IGV4ZWNTeW5jKGAke2NoZWNrQXZhaWxhYmlsaXR5fSAke3ZlcnNpb259YClcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYENoZWNrIHN0ZG91dDpgLCBvdXQudG9TdHJpbmcoKSlcblx0XHRcdHRoaXMudXBkYXRlQXZhaWxhYmlsaXR5Q2hlY2tlcj8uc3RvcCgpXG5cdFx0XHR0aGlzLnN0b3JhZ2Uuc2V0SXRlbShgdXBkYXRlUGhhc2VgLCBgY29uZmlybWVkYClcblx0XHRcdHRoaXMuZG93bmxvYWRQYWNrYWdlKClcblx0XHRcdHRoaXMuYW5ub3VuY2VVcGRhdGUoKVxuXHRcdH0gY2F0Y2ggKHRocm93bikge1xuXHRcdFx0aWYgKHRocm93biBpbnN0YW5jZW9mIEVycm9yKSB7XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBDaGVjayBmYWlsZWQ6YCwgdGhyb3duLm1lc3NhZ2UpXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjb25zdCB0aHJvd25UeXBlID0gZGlzY292ZXJUeXBlKHRocm93bilcblx0XHRcdFx0dGhpcy5sb2dnZXIuZXJyb3IoYENoZWNrIHRocmV3YCwgdGhyb3duVHlwZSwgdGhyb3duKVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHByb3RlY3RlZCBhbm5vdW5jZVVwZGF0ZSgpOiB2b2lkIHtcblx0XHRmb3IgKGNvbnN0IGVudHJ5IG9mIHRvRW50cmllcyh0aGlzLnNlcnZpY2VzKSkge1xuXHRcdFx0Y29uc3QgW3NlcnZpY2VOYW1lLCBzZXJ2aWNlXSA9IGVudHJ5XG5cdFx0XHRpZiAoc2VydmljZSkge1xuXHRcdFx0XHRpZiAodGhpcy5vcHRpb25zLnNlcnZpY2VzW3NlcnZpY2VOYW1lXS53YWl0Rm9yKSB7XG5cdFx0XHRcdFx0c2VydmljZS5lbWl0KGB1cGRhdGVzUmVhZHlgKVxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnN0YXJ0U2VydmljZShzZXJ2aWNlTmFtZSlcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRwcm90ZWN0ZWQgdHJ5VXBkYXRlKCk6IHZvaWQge1xuXHRcdGlmICh0b0VudHJpZXModGhpcy5zZXJ2aWNlc1JlYWR5VG9VcGRhdGUpLmV2ZXJ5KChbLCBpc1JlYWR5XSkgPT4gaXNSZWFkeSkpIHtcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYEFsbCBzZXJ2aWNlcyBhcmUgcmVhZHkgdG8gdXBkYXRlLmApXG5cdFx0XHR0aGlzLnN0b3BBbGxTZXJ2aWNlcygpXG5cdFx0XHRcdC50aGVuKCgpID0+IHtcblx0XHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBBbGwgc2VydmljZXMgc3RvcHBlZDsgc3RhcnRpbmcgdXAgZnJlc2guLi5gKVxuXHRcdFx0XHRcdHRoaXMuc3RhcnRBbGxTZXJ2aWNlcygpXG5cdFx0XHRcdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYEFsbCBzZXJ2aWNlcyBzdGFydGVkOyB3ZSdyZSBiYWNrIG9ubGluZS5gKVxuXHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0XHRcdC5jYXRjaCgodGhyb3duKSA9PiB7XG5cdFx0XHRcdFx0XHRcdGlmICh0aHJvd24gaW5zdGFuY2VvZiBFcnJvcikge1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKFxuXHRcdFx0XHRcdFx0XHRcdFx0YEZhaWxlZCB0byBzdGFydCBhbGwgc2VydmljZXM6YCxcblx0XHRcdFx0XHRcdFx0XHRcdHRocm93bi5tZXNzYWdlLFxuXHRcdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0fSlcblx0XHRcdFx0LmNhdGNoKCh0aHJvd24pID0+IHtcblx0XHRcdFx0XHRpZiAodGhyb3duIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRcdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBGYWlsZWQgdG8gc3RvcCBhbGwgc2VydmljZXM6YCwgdGhyb3duLm1lc3NhZ2UpXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KVxuXHRcdH1cblx0fVxuXG5cdHByb3RlY3RlZCBzdGFydEFsbFNlcnZpY2VzKCk6IEZ1dHVyZTx1bmtub3duPiB7XG5cdFx0dGhpcy5sb2dnZXIuaW5mbyhgU3RhcnRpbmcgYWxsIHNlcnZpY2VzLi4uYClcblx0XHR0aGlzLmF1dG9SZXNwYXduRGVhZFNlcnZpY2VzID0gdHJ1ZVxuXHRcdGNvbnN0IHNldHVwUGhhc2UgPSB0aGlzLnN0b3JhZ2UuZ2V0SXRlbShgc2V0dXBQaGFzZWApXG5cdFx0dGhpcy5sb2dnZXIuaW5mbyhgPiBzdG9yYWdlKFwic2V0dXBQaGFzZVwiKSA+YCwgc2V0dXBQaGFzZSlcblx0XHRzd2l0Y2ggKHNldHVwUGhhc2UpIHtcblx0XHRcdGNhc2UgbnVsbDpcblx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgU3RhcnRpbmcgZnJvbSBzY3JhdGNoLmApXG5cdFx0XHRcdHRoaXMuZG93bmxvYWRQYWNrYWdlKClcblx0XHRcdFx0dGhpcy5pbnN0YWxsUGFja2FnZSgpXG5cdFx0XHRcdHJldHVybiB0aGlzLnN0YXJ0QWxsU2VydmljZXMoKVxuXHRcdFx0Y2FzZSBgZG93bmxvYWRlZGA6XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYEZvdW5kIHBhY2thZ2UgZG93bmxvYWRlZCBidXQgbm90IGluc3RhbGxlZC5gKVxuXHRcdFx0XHR0aGlzLmluc3RhbGxQYWNrYWdlKClcblx0XHRcdFx0cmV0dXJuIHRoaXMuc3RhcnRBbGxTZXJ2aWNlcygpXG5cdFx0XHRjYXNlIGBpbnN0YWxsZWRgOiB7XG5cdFx0XHRcdGZvciAoY29uc3QgW3NlcnZpY2VOYW1lXSBvZiB0b0VudHJpZXModGhpcy5zZXJ2aWNlcykpIHtcblx0XHRcdFx0XHR0aGlzLnN0YXJ0U2VydmljZShzZXJ2aWNlTmFtZSlcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcy5saXZlXG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cHJvdGVjdGVkIHN0YXJ0U2VydmljZShzZXJ2aWNlTmFtZTogUyk6IHZvaWQge1xuXHRcdHRoaXMubG9nZ2VyLmluZm8oXG5cdFx0XHRgU3RhcnRpbmcgc2VydmljZSAke3RoaXMub3B0aW9ucy5wYWNrYWdlTmFtZX06OiR7c2VydmljZU5hbWV9LCB0cnkgJHt0aGlzLnNhZmV0eX0vMi4uLmAsXG5cdFx0KVxuXHRcdGlmICh0aGlzLnNhZmV0eSA+PSAyKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYE91dCBvZiB0cmllcy4uLmApXG5cdFx0fVxuXHRcdHRoaXMuc2FmZXR5KytcblxuXHRcdGNvbnN0IFtleGUsIC4uLmFyZ3NdID0gdGhpcy5vcHRpb25zLnNlcnZpY2VzW3NlcnZpY2VOYW1lXS5ydW4uc3BsaXQoYCBgKVxuXHRcdGNvbnN0IHNlcnZpY2VQcm9jZXNzID0gc3Bhd24oZXhlLCBhcmdzLCB7XG5cdFx0XHRjd2Q6IHRoaXMub3B0aW9ucy5mbGlnaHRkZWNrUm9vdERpcixcblx0XHRcdGVudjogaW1wb3J0Lm1ldGEuZW52LFxuXHRcdH0pXG5cdFx0Y29uc3Qgc2VydmljZUxvZ2dlciA9IHRoaXMuc2VydmljZUxvZ2dlcnNbc2VydmljZU5hbWVdXG5cdFx0Y29uc3Qgc2VydmljZSA9ICh0aGlzLnNlcnZpY2VzW3NlcnZpY2VOYW1lXSA9IG5ldyBDaGlsZFNvY2tldChcblx0XHRcdHNlcnZpY2VQcm9jZXNzLFxuXHRcdFx0YCR7dGhpcy5vcHRpb25zLnBhY2thZ2VOYW1lfTo6JHtzZXJ2aWNlTmFtZX1gLFxuXHRcdFx0c2VydmljZUxvZ2dlcixcblx0XHQpKVxuXHRcdHNlcnZpY2VMb2dnZXIucHJvY2Vzc0NvZGUgPSBzZXJ2aWNlLnByb2Nlc3MucGlkID8/IC0xXG5cdFx0dGhpcy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0ub25BbnkoKC4uLm1lc3NhZ2VzKSA9PiB7XG5cdFx0XHRzZXJ2aWNlTG9nZ2VyLmluZm8oYPCfkqxgLCAuLi5tZXNzYWdlcylcblx0XHR9KVxuXHRcdHRoaXMuc2VydmljZXNbc2VydmljZU5hbWVdLm9uKGByZWFkeVRvVXBkYXRlYCwgKCkgPT4ge1xuXHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgU2VydmljZSBcIiR7c2VydmljZU5hbWV9XCIgaXMgcmVhZHkgdG8gdXBkYXRlLmApXG5cdFx0XHR0aGlzLnNlcnZpY2VzUmVhZHlUb1VwZGF0ZVtzZXJ2aWNlTmFtZV0gPSB0cnVlXG5cdFx0XHR0aGlzLnRyeVVwZGF0ZSgpXG5cdFx0fSlcblx0XHR0aGlzLnNlcnZpY2VzW3NlcnZpY2VOYW1lXS5vbihgYWxpdmVgLCAoKSA9PiB7XG5cdFx0XHR0aGlzLnNlcnZpY2VzTGl2ZVt0aGlzLnNlcnZpY2VJZHhbc2VydmljZU5hbWVdXS51c2UoUHJvbWlzZS5yZXNvbHZlKCkpXG5cdFx0XHR0aGlzLnNlcnZpY2VzRGVhZFt0aGlzLnNlcnZpY2VJZHhbc2VydmljZU5hbWVdXSA9IG5ldyBGdXR1cmUoKCkgPT4ge30pXG5cdFx0XHRpZiAodGhpcy5kZWFkLmRvbmUpIHtcblx0XHRcdFx0dGhpcy5kZWFkID0gbmV3IEZ1dHVyZSgoKSA9PiB7fSlcblx0XHRcdH1cblx0XHRcdHRoaXMuZGVhZC51c2UoUHJvbWlzZS5hbGwodGhpcy5zZXJ2aWNlc0RlYWQpKVxuXHRcdH0pXG5cdFx0dGhpcy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0ucHJvY2Vzcy5vbmNlKGBjbG9zZWAsIChleGl0Q29kZSkgPT4ge1xuXHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhcblx0XHRcdFx0YEF1dG8tcmVzcGF3biBzYXcgXCIke3NlcnZpY2VOYW1lfVwiIGV4aXQgd2l0aCBjb2RlICR7ZXhpdENvZGV9YCxcblx0XHRcdClcblx0XHRcdHRoaXMuc2VydmljZXNbc2VydmljZU5hbWVdID0gbnVsbFxuXHRcdFx0aWYgKCF0aGlzLmF1dG9SZXNwYXduRGVhZFNlcnZpY2VzKSB7XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYEF1dG8tcmVzcGF3biBpcyBvZmY7IFwiJHtzZXJ2aWNlTmFtZX1cIiByZXN0cy5gKVxuXHRcdFx0XHRyZXR1cm5cblx0XHRcdH1cblx0XHRcdGNvbnN0IHVwZGF0ZVBoYXNlID0gdGhpcy5zdG9yYWdlLmdldEl0ZW0oYHVwZGF0ZVBoYXNlYClcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYD4gc3RvcmFnZShcInVwZGF0ZVBoYXNlXCIpID5gLCB1cGRhdGVQaGFzZSlcblx0XHRcdGNvbnN0IHVwZGF0ZXNBcmVSZWFkeSA9IHVwZGF0ZVBoYXNlID09PSBgY29uZmlybWVkYFxuXHRcdFx0aWYgKHVwZGF0ZXNBcmVSZWFkeSkge1xuXHRcdFx0XHR0aGlzLnNlcnZpY2VMb2dnZXJzW3NlcnZpY2VOYW1lXS5pbmZvKGBVcGRhdGluZyBiZWZvcmUgc3RhcnR1cC4uLmApXG5cdFx0XHRcdHRoaXMucmVzdGFydFRpbWVzID0gW11cblx0XHRcdFx0dGhpcy5pbnN0YWxsUGFja2FnZSgpXG5cdFx0XHRcdHRoaXMuc3RhcnRTZXJ2aWNlKHNlcnZpY2VOYW1lKVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y29uc3Qgbm93ID0gRGF0ZS5ub3coKVxuXHRcdFx0XHRjb25zdCBmaXZlTWludXRlc0FnbyA9IG5vdyAtIDUgKiA2MCAqIDEwMDBcblx0XHRcdFx0dGhpcy5yZXN0YXJ0VGltZXMgPSB0aGlzLnJlc3RhcnRUaW1lcy5maWx0ZXIoXG5cdFx0XHRcdFx0KHRpbWUpID0+IHRpbWUgPiBmaXZlTWludXRlc0Fnbyxcblx0XHRcdFx0KVxuXHRcdFx0XHR0aGlzLnJlc3RhcnRUaW1lcy5wdXNoKG5vdylcblxuXHRcdFx0XHRpZiAodGhpcy5yZXN0YXJ0VGltZXMubGVuZ3RoIDwgNSkge1xuXHRcdFx0XHRcdHRoaXMuc2VydmljZUxvZ2dlcnNbc2VydmljZU5hbWVdLmluZm8oYENyYXNoZWQuIFJlc3RhcnRpbmcuLi5gKVxuXHRcdFx0XHRcdHRoaXMuc3RhcnRTZXJ2aWNlKHNlcnZpY2VOYW1lKVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRoaXMuc2VydmljZUxvZ2dlcnNbc2VydmljZU5hbWVdLmluZm8oXG5cdFx0XHRcdFx0XHRgQ3Jhc2hlZCA1IHRpbWVzIGluIDUgbWludXRlcy4gTm90IHJlc3RhcnRpbmcuYCxcblx0XHRcdFx0XHQpXG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KVxuXHRcdHRoaXMuc2FmZXR5ID0gMFxuXHR9XG5cblx0cHJvdGVjdGVkIGRvd25sb2FkUGFja2FnZSgpOiB2b2lkIHtcblx0XHR0aGlzLmxvZ2dlci5pbmZvKGBEb3dubG9hZGluZy4uLmApXG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IG91dCA9IGV4ZWNTeW5jKHRoaXMub3B0aW9ucy5zY3JpcHRzLmRvd25sb2FkKVxuXHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgRG93bmxvYWQgc3Rkb3V0OmAsIG91dC50b1N0cmluZygpKVxuXHRcdFx0dGhpcy5zdG9yYWdlLnNldEl0ZW0oYHNldHVwUGhhc2VgLCBgZG93bmxvYWRlZGApXG5cdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBEb3dubG9hZGVkIWApXG5cdFx0fSBjYXRjaCAodGhyb3duKSB7XG5cdFx0XHRpZiAodGhyb3duIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRcdFx0dGhpcy5sb2dnZXIuZXJyb3IoYEZhaWxlZCB0byBnZXQgdGhlIGxhdGVzdCByZWxlYXNlOiAke3Rocm93bi5tZXNzYWdlfWApXG5cdFx0XHR9XG5cdFx0XHRyZXR1cm5cblx0XHR9XG5cdH1cblxuXHRwcm90ZWN0ZWQgaW5zdGFsbFBhY2thZ2UoKTogdm9pZCB7XG5cdFx0dGhpcy5sb2dnZXIuaW5mbyhgSW5zdGFsbGluZy4uLmApXG5cblx0XHR0cnkge1xuXHRcdFx0Y29uc3Qgb3V0ID0gZXhlY1N5bmModGhpcy5vcHRpb25zLnNjcmlwdHMuaW5zdGFsbClcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYEluc3RhbGwgc3Rkb3V0OmAsIG91dC50b1N0cmluZygpKVxuXHRcdFx0dGhpcy5zdG9yYWdlLnNldEl0ZW0oYHNldHVwUGhhc2VgLCBgaW5zdGFsbGVkYClcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYEluc3RhbGxlZCFgKVxuXHRcdH0gY2F0Y2ggKHRocm93bikge1xuXHRcdFx0aWYgKHRocm93biBpbnN0YW5jZW9mIEVycm9yKSB7XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBGYWlsZWQgdG8gZ2V0IHRoZSBsYXRlc3QgcmVsZWFzZTogJHt0aHJvd24ubWVzc2FnZX1gKVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuXG5cdFx0fVxuXHR9XG5cblx0cHVibGljIHN0b3BBbGxTZXJ2aWNlcygpOiBGdXR1cmU8dW5rbm93bj4ge1xuXHRcdHRoaXMubG9nZ2VyLmluZm8oYFN0b3BwaW5nIGFsbCBzZXJ2aWNlcy4uLiBhdXRvLXJlc3Bhd24gZGlzYWJsZWQuYClcblx0XHR0aGlzLmF1dG9SZXNwYXduRGVhZFNlcnZpY2VzID0gZmFsc2Vcblx0XHRmb3IgKGNvbnN0IFtzZXJ2aWNlTmFtZV0gb2YgdG9FbnRyaWVzKHRoaXMuc2VydmljZXMpKSB7XG5cdFx0XHR0aGlzLnN0b3BTZXJ2aWNlKHNlcnZpY2VOYW1lKVxuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5kZWFkXG5cdH1cblxuXHRwdWJsaWMgc3RvcFNlcnZpY2Uoc2VydmljZU5hbWU6IFMpOiB2b2lkIHtcblx0XHRjb25zdCBzZXJ2aWNlID0gdGhpcy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV1cblx0XHRpZiAoc2VydmljZSkge1xuXHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgU3RvcHBpbmcgc2VydmljZSBcIiR7c2VydmljZU5hbWV9XCIuLi5gKVxuXHRcdFx0dGhpcy5zZXJ2aWNlc0RlYWRbdGhpcy5zZXJ2aWNlSWR4W3NlcnZpY2VOYW1lXV0udXNlKFxuXHRcdFx0XHRuZXcgUHJvbWlzZSgocGFzcykgPT4ge1xuXHRcdFx0XHRcdHNlcnZpY2UuZW1pdChgdGltZVRvU3RvcGApXG5cdFx0XHRcdFx0c2VydmljZS5wcm9jZXNzLm9uY2UoYGNsb3NlYCwgKGV4aXRDb2RlKSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKFxuXHRcdFx0XHRcdFx0XHRgU3RvcHBlZCBzZXJ2aWNlIFwiJHtzZXJ2aWNlTmFtZX1cIjsgZXhpdGVkIHdpdGggY29kZSAke2V4aXRDb2RlfWAsXG5cdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHR0aGlzLnNlcnZpY2VzW3NlcnZpY2VOYW1lXSA9IG51bGxcblx0XHRcdFx0XHRcdHBhc3MoKVxuXHRcdFx0XHRcdH0pXG5cdFx0XHRcdH0pLFxuXHRcdFx0KVxuXHRcdFx0dGhpcy5kZWFkLnVzZShQcm9taXNlLmFsbCh0aGlzLnNlcnZpY2VzRGVhZCkpXG5cdFx0XHR0aGlzLnNlcnZpY2VzTGl2ZVt0aGlzLnNlcnZpY2VJZHhbc2VydmljZU5hbWVdXSA9IG5ldyBGdXR1cmUoKCkgPT4ge30pXG5cdFx0XHRpZiAodGhpcy5saXZlLmRvbmUpIHtcblx0XHRcdFx0dGhpcy5saXZlID0gbmV3IEZ1dHVyZSgoKSA9PiB7fSlcblx0XHRcdH1cblx0XHRcdHRoaXMubGl2ZS51c2UoUHJvbWlzZS5hbGwodGhpcy5zZXJ2aWNlc0xpdmUpKVxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnNlcnZpY2VMb2dnZXJzW3NlcnZpY2VOYW1lXS5lcnJvcihcblx0XHRcdFx0YFRyaWVkIHRvIHN0b3Agc2VydmljZSwgYnV0IGl0IHdhc24ndCBydW5uaW5nLmAsXG5cdFx0XHQpXG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBjb25zdCBGTElHSFRERUNLX0lORk8gPSBgaW5mb2BcbmV4cG9ydCBjb25zdCBGTElHSFRERUNLX1dBUk4gPSBgd2FybmBcbmV4cG9ydCBjb25zdCBGTElHSFRERUNLX0VSUk9SID0gYEVSUiFgXG5cbmV4cG9ydCBjb25zdCBmbGlnaHREZWNrTG9nU2NoZW1hID0gei5vYmplY3Qoe1xuXHRsZXZlbDogei51bmlvbihbXG5cdFx0ei5saXRlcmFsKEZMSUdIVERFQ0tfSU5GTyksXG5cdFx0ei5saXRlcmFsKEZMSUdIVERFQ0tfV0FSTiksXG5cdFx0ei5saXRlcmFsKEZMSUdIVERFQ0tfRVJST1IpLFxuXHRdKSxcblx0dGltZXN0YW1wOiB6Lm51bWJlcigpLFxuXHRwYWNrYWdlOiB6LnN0cmluZygpLFxuXHRzZXJ2aWNlOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG5cdHByb2Nlc3M6IHoubnVtYmVyKCksXG5cdGJvZHk6IHouc3RyaW5nKCksXG59KVxuZXhwb3J0IHR5cGUgRmxpZ2h0RGVja0xvZyA9IHouaW5mZXI8dHlwZW9mIGZsaWdodERlY2tMb2dTY2hlbWE+XG5cbmNvbnN0IExJTkVfRk9STUFUID0gYGxpbmUtZm9ybWF0YCBzYXRpc2ZpZXMga2V5b2YgTG5hdkZvcm1hdFxuY29uc3QgVkFMVUUgPSBgdmFsdWVgIHNhdGlzZmllcyBrZXlvZiBMbmF2Rm9ybWF0XG5cbmV4cG9ydCB0eXBlIExuYXZGb3JtYXRWaXN1YWxDb21wb25lbnQgPSBFeGNsdWRlPFxuXHRFeGNsdWRlPExuYXZGb3JtYXRbYGxpbmUtZm9ybWF0YF0sIHVuZGVmaW5lZD5bbnVtYmVyXSxcblx0c3RyaW5nXG4+XG5cbmV4cG9ydCB0eXBlIExuYXZGb3JtYXRCcmVha2Rvd24gPSBFeGNsdWRlPExuYXZGb3JtYXRbYHZhbHVlYF0sIHVuZGVmaW5lZD5cbmV4cG9ydCB0eXBlIE1lbWJlck9mPFQ+ID0gVFtrZXlvZiBUXVxuZXhwb3J0IHR5cGUgTG5hdkZvcm1hdFZhbHVlRGVmaW5pdGlvbiA9IE1lbWJlck9mPExuYXZGb3JtYXRCcmVha2Rvd24+XG5cbmV4cG9ydCB0eXBlIEZsaWdodERlY2tGb3JtYXQgPSB7XG5cdFtMSU5FX0ZPUk1BVF06IChcblx0XHR8IHN0cmluZ1xuXHRcdHwgKExuYXZGb3JtYXRWaXN1YWxDb21wb25lbnQgJiB7XG5cdFx0XHRcdGZpZWxkOiBrZXlvZiBGbGlnaHREZWNrTG9nIHwgYF9fbGV2ZWxfX2AgfCBgX190aW1lc3RhbXBfX2Bcblx0XHQgIH0pXG5cdClbXVxuXHRbVkFMVUVdOiB7XG5cdFx0W0sgaW4ga2V5b2YgRmxpZ2h0RGVja0xvZ106IExuYXZGb3JtYXRWYWx1ZURlZmluaXRpb24gJiB7XG5cdFx0XHRraW5kOiBGbGlnaHREZWNrTG9nW0tdIGV4dGVuZHMgbnVtYmVyIHwgdW5kZWZpbmVkXG5cdFx0XHRcdD8gYGludGVnZXJgXG5cdFx0XHRcdDogRmxpZ2h0RGVja0xvZ1tLXSBleHRlbmRzIHN0cmluZyB8IHVuZGVmaW5lZFxuXHRcdFx0XHRcdD8gYHN0cmluZ2Bcblx0XHRcdFx0XHQ6IG5ldmVyXG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBjb25zdCBGTElHSFRERUNLX0xOQVZfRk9STUFUID0ge1xuXHR0aXRsZTogYEZsaWdodERlY2sgTG9nYCxcblx0ZGVzY3JpcHRpb246IGBGb3JtYXQgZm9yIGV2ZW50cyBsb2dnZWQgYnkgdGhlIEZsaWdodERlY2sgcHJvY2VzcyBtYW5hZ2VyLmAsXG5cdFwiZmlsZS10eXBlXCI6IGBqc29uYCxcblx0XCJ0aW1lc3RhbXAtZmllbGRcIjogYHRpbWVzdGFtcGAsXG5cdFwidGltZXN0YW1wLWRpdmlzb3JcIjogMTAwMCxcblx0XCJtb2R1bGUtZmllbGRcIjogYHBhY2thZ2VgLFxuXHRcIm9waWQtZmllbGRcIjogYHNlcnZpY2VgLFxuXHRcImxldmVsLWZpZWxkXCI6IGBsZXZlbGAsXG5cdGxldmVsOiB7XG5cdFx0aW5mbzogRkxJR0hUREVDS19JTkZPLFxuXHRcdHdhcm5pbmc6IEZMSUdIVERFQ0tfV0FSTixcblx0XHRlcnJvcjogRkxJR0hUREVDS19FUlJPUixcblx0fSxcblxuXHRbTElORV9GT1JNQVRdOiBbXG5cdFx0e1xuXHRcdFx0ZmllbGQ6IGBsZXZlbGAsXG5cdFx0fSxcblx0XHR7XG5cdFx0XHRwcmVmaXg6IGAgYCxcblx0XHRcdGZpZWxkOiBgX190aW1lc3RhbXBfX2AsXG5cdFx0XHRcInRpbWVzdGFtcC1mb3JtYXRcIjogYCVZLSVtLSVkVCVIOiVNOiVTLiVMJVpgLFxuXHRcdH0sXG5cdFx0e1xuXHRcdFx0cHJlZml4OiBgIGAsXG5cdFx0XHRmaWVsZDogYHByb2Nlc3NgLFxuXHRcdFx0XCJtaW4td2lkdGhcIjogNSxcblx0XHR9LFxuXHRcdHtcblx0XHRcdHByZWZpeDogYDpgLFxuXHRcdFx0ZmllbGQ6IGBwYWNrYWdlYCxcblx0XHR9LFxuXHRcdHtcblx0XHRcdHByZWZpeDogYDpgLFxuXHRcdFx0ZmllbGQ6IGBzZXJ2aWNlYCxcblx0XHRcdFwiZGVmYXVsdC12YWx1ZVwiOiBgYCxcblx0XHR9LFxuXHRcdHtcblx0XHRcdHByZWZpeDogYDogYCxcblx0XHRcdGZpZWxkOiBgYm9keWAsXG5cdFx0fSxcblx0XSxcblxuXHRbVkFMVUVdOiB7XG5cdFx0dGltZXN0YW1wOiB7XG5cdFx0XHRraW5kOiBgaW50ZWdlcmAsXG5cdFx0fSxcblx0XHRsZXZlbDoge1xuXHRcdFx0a2luZDogYHN0cmluZ2AsXG5cdFx0fSxcblx0XHRwYWNrYWdlOiB7XG5cdFx0XHRraW5kOiBgc3RyaW5nYCxcblx0XHR9LFxuXHRcdHNlcnZpY2U6IHtcblx0XHRcdGtpbmQ6IGBzdHJpbmdgLFxuXHRcdH0sXG5cdFx0cHJvY2Vzczoge1xuXHRcdFx0a2luZDogYGludGVnZXJgLFxuXHRcdH0sXG5cdFx0Ym9keToge1xuXHRcdFx0a2luZDogYHN0cmluZ2AsXG5cdFx0fSxcblx0fSxcbn0gYXMgY29uc3Qgc2F0aXNmaWVzIEZsaWdodERlY2tGb3JtYXQgJiBMbmF2Rm9ybWF0XG5cbmV4cG9ydCBjbGFzcyBGbGlnaHREZWNrTG9nZ2VyXG5cdGltcGxlbWVudHMgUGljazxDb25zb2xlLCBgZXJyb3JgIHwgYGluZm9gIHwgYHdhcm5gPlxue1xuXHRwdWJsaWMgcmVhZG9ubHkgcGFja2FnZU5hbWU6IHN0cmluZ1xuXHRwdWJsaWMgcmVhZG9ubHkgc2VydmljZU5hbWU/OiBzdHJpbmdcblx0cHVibGljIHJlYWRvbmx5IGpzb25Mb2dnaW5nOiBib29sZWFuXG5cdHB1YmxpYyBwcm9jZXNzQ29kZTogbnVtYmVyXG5cdHB1YmxpYyBjb25zdHJ1Y3Rvcihcblx0XHRwYWNrYWdlTmFtZTogc3RyaW5nLFxuXHRcdHByb2Nlc3NDb2RlOiBudW1iZXIsXG5cdFx0c2VydmljZU5hbWU/OiBzdHJpbmcsXG5cdFx0b3B0aW9ucz86IHsganNvbkxvZ2dpbmc6IGJvb2xlYW4gfSxcblx0KSB7XG5cdFx0dGhpcy5wYWNrYWdlTmFtZSA9IHBhY2thZ2VOYW1lXG5cdFx0aWYgKHNlcnZpY2VOYW1lKSB7XG5cdFx0XHR0aGlzLnNlcnZpY2VOYW1lID0gc2VydmljZU5hbWVcblx0XHR9XG5cdFx0dGhpcy5wcm9jZXNzQ29kZSA9IHByb2Nlc3NDb2RlXG5cdFx0dGhpcy5qc29uTG9nZ2luZyA9IG9wdGlvbnM/Lmpzb25Mb2dnaW5nID8/IGZhbHNlXG5cdH1cblx0cHJvdGVjdGVkIGxvZyhcblx0XHRsZXZlbDpcblx0XHRcdHwgdHlwZW9mIEZMSUdIVERFQ0tfRVJST1Jcblx0XHRcdHwgdHlwZW9mIEZMSUdIVERFQ0tfSU5GT1xuXHRcdFx0fCB0eXBlb2YgRkxJR0hUREVDS19XQVJOLFxuXHRcdC4uLm1lc3NhZ2VzOiB1bmtub3duW11cblx0KTogdm9pZCB7XG5cdFx0aWYgKHRoaXMuanNvbkxvZ2dpbmcpIHtcblx0XHRcdGxldCBib2R5ID0gbWVzc2FnZXNcblx0XHRcdFx0Lm1hcCgobWVzc2FnZSkgPT5cblx0XHRcdFx0XHR0eXBlb2YgbWVzc2FnZSA9PT0gYHN0cmluZ2Bcblx0XHRcdFx0XHRcdD8gbWVzc2FnZVxuXHRcdFx0XHRcdFx0OiBpbnNwZWN0KG1lc3NhZ2UsIGZhbHNlLCBudWxsLCB0cnVlKSxcblx0XHRcdFx0KVxuXHRcdFx0XHQuam9pbihgIGApXG5cdFx0XHRpZiAoYm9keS5pbmNsdWRlcyhgXFxuYCkpIHtcblx0XHRcdFx0Ym9keSA9IGBcXG4gICR7Ym9keS5zcGxpdChgXFxuYCkuam9pbihgXFxuICBgKX1gXG5cdFx0XHR9XG5cdFx0XHRjb25zdCBsb2c6IEZsaWdodERlY2tMb2cgPSB7XG5cdFx0XHRcdHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcblx0XHRcdFx0bGV2ZWwsXG5cdFx0XHRcdHByb2Nlc3M6IHRoaXMucHJvY2Vzc0NvZGUsXG5cdFx0XHRcdHBhY2thZ2U6IHRoaXMucGFja2FnZU5hbWUsXG5cdFx0XHRcdGJvZHksXG5cdFx0XHR9XG5cdFx0XHRpZiAodGhpcy5zZXJ2aWNlTmFtZSkge1xuXHRcdFx0XHRsb2cuc2VydmljZSA9IHRoaXMuc2VydmljZU5hbWVcblx0XHRcdH1cblx0XHRcdHByb2Nlc3Muc3Rkb3V0LndyaXRlKEpTT04uc3RyaW5naWZ5KGxvZykgKyBgXFxuYClcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y29uc3Qgc291cmNlID0gdGhpcy5zZXJ2aWNlTmFtZVxuXHRcdFx0XHQ/IGAke3RoaXMucGFja2FnZU5hbWV9OiR7dGhpcy5zZXJ2aWNlTmFtZX1gXG5cdFx0XHRcdDogdGhpcy5wYWNrYWdlTmFtZVxuXHRcdFx0c3dpdGNoIChsZXZlbCkge1xuXHRcdFx0XHRjYXNlIEZMSUdIVERFQ0tfSU5GTzpcblx0XHRcdFx0XHRjb25zb2xlLmxvZyhgJHtzb3VyY2V9OmAsIC4uLm1lc3NhZ2VzKVxuXHRcdFx0XHRcdGJyZWFrXG5cdFx0XHRcdGNhc2UgRkxJR0hUREVDS19XQVJOOlxuXHRcdFx0XHRcdGNvbnNvbGUud2FybihgJHtzb3VyY2V9OmAsIC4uLm1lc3NhZ2VzKVxuXHRcdFx0XHRcdGJyZWFrXG5cdFx0XHRcdGNhc2UgRkxJR0hUREVDS19FUlJPUjpcblx0XHRcdFx0XHRjb25zb2xlLmVycm9yKGAke3NvdXJjZX06YCwgLi4ubWVzc2FnZXMpXG5cdFx0XHRcdFx0YnJlYWtcblx0XHRcdH1cblx0XHR9XG5cdH1cblx0cHVibGljIGluZm8oLi4ubWVzc2FnZXM6IHVua25vd25bXSk6IHZvaWQge1xuXHRcdHRoaXMubG9nKEZMSUdIVERFQ0tfSU5GTywgLi4ubWVzc2FnZXMpXG5cdH1cblxuXHRwdWJsaWMgd2FybiguLi5tZXNzYWdlczogdW5rbm93bltdKTogdm9pZCB7XG5cdFx0dGhpcy5sb2coRkxJR0hUREVDS19XQVJOLCAuLi5tZXNzYWdlcylcblx0fVxuXG5cdHB1YmxpYyBlcnJvciguLi5tZXNzYWdlczogdW5rbm93bltdKTogdm9pZCB7XG5cdFx0dGhpcy5sb2coRkxJR0hUREVDS19FUlJPUiwgLi4ubWVzc2FnZXMpXG5cdH1cbn1cbiIsCiAgICAiaW1wb3J0IHtcblx0ZXhpc3RzU3luYyxcblx0bWtkaXJTeW5jLFxuXHRyZWFkZGlyU3luYyxcblx0cmVhZEZpbGVTeW5jLFxuXHRybVN5bmMsXG5cdHN0YXRTeW5jLFxuXHR3cml0ZUZpbGVTeW5jLFxufSBmcm9tIFwibm9kZTpmc1wiXG5pbXBvcnQgeyByZXNvbHZlIH0gZnJvbSBcIm5vZGU6cGF0aFwiXG5cbmV4cG9ydCB0eXBlIEZpbGVzeXN0ZW1TdG9yYWdlT3B0aW9ucyA9IHtcblx0cGF0aDogc3RyaW5nXG59XG5cbmV4cG9ydCBjbGFzcyBGaWxlc3lzdGVtU3RvcmFnZTxcblx0VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuPiBpbXBsZW1lbnRzIFN0b3JhZ2Vcbntcblx0cHVibGljIHJvb3REaXI6IHN0cmluZ1xuXG5cdHB1YmxpYyBjb25zdHJ1Y3RvcihvcHRpb25zOiBGaWxlc3lzdGVtU3RvcmFnZU9wdGlvbnMpIHtcblx0XHR0aGlzLnJvb3REaXIgPSBvcHRpb25zLnBhdGhcblx0XHRpZiAoIWV4aXN0c1N5bmModGhpcy5yb290RGlyKSkge1xuXHRcdFx0bWtkaXJTeW5jKHRoaXMucm9vdERpciwgeyByZWN1cnNpdmU6IHRydWUgfSlcblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgZ2V0SXRlbTxLIGV4dGVuZHMgc3RyaW5nICYga2V5b2YgVD4oa2V5OiBLKTogVFtLXSB8IG51bGwge1xuXHRcdGNvbnN0IGZpbGVQYXRoID0gcmVzb2x2ZSh0aGlzLnJvb3REaXIsIGtleSlcblx0XHRpZiAoZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcblx0XHRcdHJldHVybiByZWFkRmlsZVN5bmMoZmlsZVBhdGgsIGB1dGYtOGApIGFzIFRbS11cblx0XHR9XG5cdFx0cmV0dXJuIG51bGxcblx0fVxuXG5cdHB1YmxpYyBzZXRJdGVtPEsgZXh0ZW5kcyBzdHJpbmcgJiBrZXlvZiBUPihrZXk6IEssIHZhbHVlOiBUW0tdKTogdm9pZCB7XG5cdFx0Y29uc3QgZmlsZVBhdGggPSByZXNvbHZlKHRoaXMucm9vdERpciwga2V5KVxuXHRcdHdyaXRlRmlsZVN5bmMoZmlsZVBhdGgsIHZhbHVlKVxuXHR9XG5cblx0cHVibGljIHJlbW92ZUl0ZW08SyBleHRlbmRzIHN0cmluZyAmIGtleW9mIFQ+KGtleTogSyk6IHZvaWQge1xuXHRcdGNvbnN0IGZpbGVQYXRoID0gcmVzb2x2ZSh0aGlzLnJvb3REaXIsIGtleSlcblx0XHRpZiAoZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcblx0XHRcdHJtU3luYyhmaWxlUGF0aClcblx0XHR9XG5cdH1cblxuXHRwdWJsaWMga2V5KGluZGV4OiBudW1iZXIpOiAoc3RyaW5nICYga2V5b2YgVCkgfCBudWxsIHtcblx0XHRjb25zdCBmaWxlUGF0aHMgPSByZWFkZGlyU3luYyh0aGlzLnJvb3REaXIpXG5cdFx0Y29uc3QgZmlsZVBhdGhzQnlEYXRlQ3JlYXRlZCA9IGZpbGVQYXRocy5zb3J0KChhLCBiKSA9PiB7XG5cdFx0XHRjb25zdCBhU3RhdCA9IHN0YXRTeW5jKGEpXG5cdFx0XHRjb25zdCBiU3RhdCA9IHN0YXRTeW5jKGIpXG5cdFx0XHRyZXR1cm4gYlN0YXQuY3RpbWVNcyAtIGFTdGF0LmN0aW1lTXNcblx0XHR9KVxuXHRcdHJldHVybiAoZmlsZVBhdGhzQnlEYXRlQ3JlYXRlZFtpbmRleF0gYXMgc3RyaW5nICYga2V5b2YgVCkgPz8gbnVsbFxuXHR9XG5cblx0cHVibGljIGNsZWFyKCk6IHZvaWQge1xuXHRcdHJtU3luYyh0aGlzLnJvb3REaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG5cdFx0bWtkaXJTeW5jKHRoaXMucm9vdERpciwgeyByZWN1cnNpdmU6IHRydWUgfSlcblx0fVxuXG5cdHB1YmxpYyBnZXQgbGVuZ3RoKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIHJlYWRkaXJTeW5jKHRoaXMucm9vdERpcikubGVuZ3RoXG5cdH1cbn1cbiIsCiAgICAiaW1wb3J0IHsgY3JlYXRlRW52IH0gZnJvbSBcIkB0My1vc3MvZW52LWNvcmVcIlxuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIlxuXG5leHBvcnQgY29uc3QgZW52ID0gY3JlYXRlRW52KHtcblx0c2VydmVyOiB7IEZMSUdIVERFQ0tfU0VDUkVUOiB6LnN0cmluZygpLm9wdGlvbmFsKCkgfSxcblx0Y2xpZW50UHJlZml4OiBgTkVWRVJgLFxuXHRjbGllbnQ6IHt9LFxuXHRydW50aW1lRW52OiBpbXBvcnQubWV0YS5lbnYsXG5cdGVtcHR5U3RyaW5nQXNVbmRlZmluZWQ6IHRydWUsXG59KVxuIgogIF0sCiAgIm1hcHBp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QU8sRUFDbEIsa0JBQW1CLEVBQUUsT0FBTyxDQUM3QixDQUFDLEVBQ0QsWUFBYSxFQUFFLFFBQVEsRUFBRSxTQUFTLENBQ25DLENBQUMsRUFDRCxRQUFTLENBQ1IsS0FBTSxDQUNMLEtBQU0sSUFDTixTQUFVLEdBQ1YsWUFBYSx3Q0FDYixRQUFTLGNBQ1QsTUFBTyxFQUNSLEVBQ0EsWUFBYSxDQUNaLEtBQU0sSUFDTixTQUFVLEdBQ1YsWUFBYSx1QkFDYixRQUFTLHdCQUNWLEVBQ0EsU0FBVSxDQUNULEtBQU0sSUFDTixTQUFVLEdBQ1YsWUFBYSx1Q0FDYixRQUFTLDhJQUNULE1BQU8sS0FBSyxLQUNiLEVBQ0Esa0JBQW1CLENBQ2xCLEtBQU0sSUFDTixTQUFVLEdBQ1YsWUFBYSx5Q0FDYixRQUFTLDZEQUNWLEVBQ0EsUUFBUyxDQUNSLEtBQU0sSUFDTixTQUFVLEdBQ1YsWUFBYSx5QkFDYixRQUFTLDJFQUNULE1BQU8sS0FBSyxLQUNiLEVBQ0EsWUFBYSxDQUNaLEtBQU0sSUFDTixTQUFVLEdBQ1YsWUFBYSx1QkFDYixRQUFTLGdCQUNULE1BQU8sRUFDUixDQUNELENBQ0QsRUFFTSxHQUFnQixDQUNyQixjQUFlLEVBQUUsT0FBTyxDQUN2QixPQUFRLEVBQUUsT0FBTyxFQUFFLFNBQVMsQ0FDN0IsQ0FBQyxFQUNELFFBQVMsQ0FDUixPQUFRLENBQ1AsS0FBTSxJQUNOLFNBQVUsR0FDVixZQUFhLG9DQUNiLFFBQVMsaUJBQ1YsQ0FDRCxDQUNELEVBRU0sR0FBUSxHQUNiLENBQ0MsUUFBUyxhQUNULE9BQVEsR0FBUyxDQUFFLE9BQVEsS0FBTSxZQUFhLElBQUssQ0FBQyxFQUNwRCxhQUFjLENBQ2IsR0FBSSxFQUNKLFlBQWEsRUFDYixPQUFRLEVBQ1QsRUFDQSxZQUFhLEdBQ2IsbUJBQW9CLENBQUMsSUFBUyxDQUM3QixHQUFJLEVBQUssS0FBTyxTQUNmLE9BSUQsT0FEQyxFQUFLLElBQVcsT0FBSyxRQUFRLElBQUksRUFBRyx3QkFBd0IsRUFHL0QsRUFDQSxPQUNELEdBRVEsU0FBUSxvQkFBb0IsR0FBTSxRQUFRLElBQUksRUFFdEQsT0FBUSxFQUFPLFVBQ1QsU0FDSixDQUNDLElBQVEsVUFBVyxFQUFPLEtBQzFCLEdBQWdCLEdBQVUsR0FBRyxDQUM5QixDQUNBLGNBQ1EsQ0FDUixJQUFNLEVBQWEsSUFBSSxFQUFXLEVBQU8sSUFBSSxFQUM3QyxRQUFRLEdBQUcsUUFBUyxTQUFZLENBQy9CLE1BQU0sRUFBVyxnQkFBZ0IsRUFDakMsQ0FDRiIsCiAgImRlYnVnSWQiOiAiOEMyNTdBNzY5NEQ5NDBENjY0NzU2RTIxNjQ3NTZFMjEiLAogICJuYW1lcyI6IFtdCn0=
9
+ //# debugId=6467DBABFBD56FAE64756E2164756E21
10
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2ZsaWdodGRlY2suYmluLnRzIiwgIi4uL3NyYy9mbGlnaHRkZWNrLmxpYi50cyIsICIuLi9zcmMvZmxpZ2h0ZGVjay5lbnYudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbCiAgICAiIyEvdXNyL2Jpbi9lbnYgbm9kZVxuXG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIlxuXG5pbXBvcnQgdHlwZSB7IE9wdGlvbnNHcm91cCB9IGZyb20gXCJjb21saW5lXCJcbmltcG9ydCB7IGNsaSwgb3B0aW9uYWwsIHBhcnNlQm9vbGVhbk9wdGlvbiwgcGFyc2VOdW1iZXJPcHRpb24gfSBmcm9tIFwiY29tbGluZVwiXG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiXG5cbmltcG9ydCB0eXBlIHsgRmxpZ2h0RGVja09wdGlvbnMgfSBmcm9tIFwiLi9mbGlnaHRkZWNrLmxpYlwiXG5pbXBvcnQgeyBGbGlnaHREZWNrLCBGbGlnaHREZWNrTG9nZ2VyIH0gZnJvbSBcIi4vZmxpZ2h0ZGVjay5saWJcIlxuXG5jb25zdCBDTElfTE9HR0VSID0gbmV3IEZsaWdodERlY2tMb2dnZXIoYGNvbWxpbmVgLCBwcm9jZXNzLnBpZCwgdW5kZWZpbmVkLCB7XG5cdGpzb25Mb2dnaW5nOiB0cnVlLFxufSlcbk9iamVjdC5hc3NpZ24oY29uc29sZSwge1xuXHRsb2c6IENMSV9MT0dHRVIuaW5mby5iaW5kKENMSV9MT0dHRVIpLFxuXHRpbmZvOiBDTElfTE9HR0VSLmluZm8uYmluZChDTElfTE9HR0VSKSxcblx0d2FybjogQ0xJX0xPR0dFUi53YXJuLmJpbmQoQ0xJX0xPR0dFUiksXG5cdGVycm9yOiBDTElfTE9HR0VSLmVycm9yLmJpbmQoQ0xJX0xPR0dFUiksXG59KVxuXG5jb25zdCBGTElHSFRERUNLX01BTlVBTCA9IHtcblx0b3B0aW9uc1NjaGVtYTogei5vYmplY3Qoe1xuXHRcdHBvcnQ6IHoubnVtYmVyKCkub3B0aW9uYWwoKSxcblx0XHRwYWNrYWdlTmFtZTogei5zdHJpbmcoKSxcblx0XHRzZXJ2aWNlczogei5yZWNvcmQoei5vYmplY3QoeyBydW46IHouc3RyaW5nKCksIHdhaXRGb3I6IHouYm9vbGVhbigpIH0pKSxcblx0XHRmbGlnaHRkZWNrUm9vdERpcjogei5zdHJpbmcoKSxcblx0XHRzY3JpcHRzOiB6Lm9iamVjdCh7XG5cdFx0XHRkb3dubG9hZDogei5zdHJpbmcoKSxcblx0XHRcdGluc3RhbGw6IHouc3RyaW5nKCksXG5cdFx0XHRjaGVja0F2YWlsYWJpbGl0eTogei5zdHJpbmcoKSxcblx0XHR9KSxcblx0XHRqc29uTG9nZ2luZzogei5ib29sZWFuKCkub3B0aW9uYWwoKSxcblx0fSksXG5cdG9wdGlvbnM6IHtcblx0XHRwb3J0OiB7XG5cdFx0XHRmbGFnOiBgcGAsXG5cdFx0XHRyZXF1aXJlZDogZmFsc2UsXG5cdFx0XHRkZXNjcmlwdGlvbjogYFBvcnQgdG8gcnVuIHRoZSBmbGlnaHRkZWNrIHNlcnZlciBvbi5gLFxuXHRcdFx0ZXhhbXBsZTogYC0tcG9ydD04MDgwYCxcblx0XHRcdHBhcnNlOiBwYXJzZU51bWJlck9wdGlvbixcblx0XHR9LFxuXHRcdHBhY2thZ2VOYW1lOiB7XG5cdFx0XHRmbGFnOiBgbmAsXG5cdFx0XHRyZXF1aXJlZDogdHJ1ZSxcblx0XHRcdGRlc2NyaXB0aW9uOiBgTmFtZSBvZiB0aGUgcGFja2FnZS5gLFxuXHRcdFx0ZXhhbXBsZTogYC0tcGFja2FnZU5hbWU9XFxcIm15LWFwcFxcXCJgLFxuXHRcdH0sXG5cdFx0c2VydmljZXM6IHtcblx0XHRcdGZsYWc6IGBzYCxcblx0XHRcdHJlcXVpcmVkOiB0cnVlLFxuXHRcdFx0ZGVzY3JpcHRpb246IGBNYXAgb2Ygc2VydmljZSBuYW1lcyB0byBleGVjdXRhYmxlcy5gLFxuXHRcdFx0ZXhhbXBsZTogYC0tc2VydmljZXM9XCJ7XFxcXFwiZnJvbnRlbmRcXFxcXCI6e1xcXFxcInJ1blxcXFxcIjpcXFxcXCIuL2Zyb250ZW5kXFxcXFwiLFxcXFxcIndhaXRGb3JcXFxcXCI6ZmFsc2V9LFxcXFxcImJhY2tlbmRcXFxcXCI6e1xcXFxcInJ1blxcXFxcIjpcXFxcXCIuL2JhY2tlbmRcXFxcXCIsXFxcXFwid2FpdEZvclxcXFxcIjp0cnVlfX1cImAsXG5cdFx0XHRwYXJzZTogSlNPTi5wYXJzZSxcblx0XHR9LFxuXHRcdGZsaWdodGRlY2tSb290RGlyOiB7XG5cdFx0XHRmbGFnOiBgZGAsXG5cdFx0XHRyZXF1aXJlZDogdHJ1ZSxcblx0XHRcdGRlc2NyaXB0aW9uOiBgRGlyZWN0b3J5IHdoZXJlIHRoZSBzZXJ2aWNlIGlzIHN0b3JlZC5gLFxuXHRcdFx0ZXhhbXBsZTogYC0tZmxpZ2h0ZGVja1Jvb3REaXI9XFxcIi4vc2VydmljZXMvc2FtcGxlL3JlcG8vbXktYXBwL2N1cnJlbnRcXFwiYCxcblx0XHR9LFxuXHRcdHNjcmlwdHM6IHtcblx0XHRcdGZsYWc6IGByYCxcblx0XHRcdHJlcXVpcmVkOiB0cnVlLFxuXHRcdFx0ZGVzY3JpcHRpb246IGBNYXAgb2Ygc2NyaXB0cyB0byBydW4uYCxcblx0XHRcdGV4YW1wbGU6IGAtLXNjcmlwdHM9XCJ7XFxcXFwiZG93bmxvYWRcXFxcXCI6XFxcXFwibnBtIGlcIixcXFxcXCJpbnN0YWxsXFxcXFwiOlxcXFxcIm5wbSBydW4gYnVpbGRcXFxcXCJ9XCJgLFxuXHRcdFx0cGFyc2U6IEpTT04ucGFyc2UsXG5cdFx0fSxcblx0XHRqc29uTG9nZ2luZzoge1xuXHRcdFx0ZmxhZzogYGpgLFxuXHRcdFx0cmVxdWlyZWQ6IGZhbHNlLFxuXHRcdFx0ZGVzY3JpcHRpb246IGBFbmFibGUganNvbiBsb2dnaW5nLmAsXG5cdFx0XHRleGFtcGxlOiBgLS1qc29uTG9nZ2luZ2AsXG5cdFx0XHRwYXJzZTogcGFyc2VCb29sZWFuT3B0aW9uLFxuXHRcdH0sXG5cdH0sXG59IHNhdGlzZmllcyBPcHRpb25zR3JvdXA8RmxpZ2h0RGVja09wdGlvbnM+XG5cbmNvbnN0IFNDSEVNQV9NQU5VQUwgPSB7XG5cdG9wdGlvbnNTY2hlbWE6IHoub2JqZWN0KHtcblx0XHRvdXRkaXI6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcblx0fSksXG5cdG9wdGlvbnM6IHtcblx0XHRvdXRkaXI6IHtcblx0XHRcdGZsYWc6IGBvYCxcblx0XHRcdHJlcXVpcmVkOiBmYWxzZSxcblx0XHRcdGRlc2NyaXB0aW9uOiBgRGlyZWN0b3J5IHRvIHdyaXRlIHRoZSBzY2hlbWEgdG8uYCxcblx0XHRcdGV4YW1wbGU6IGAtLW91dGRpcj0uL2Rpc3RgLFxuXHRcdH0sXG5cdH0sXG59IHNhdGlzZmllcyBPcHRpb25zR3JvdXA8eyBvdXRkaXI/OiBzdHJpbmcgfCB1bmRlZmluZWQgfT5cblxuY29uc3QgcGFyc2UgPSBjbGkoXG5cdHtcblx0XHRjbGlOYW1lOiBgZmxpZ2h0ZGVja2AsXG5cdFx0cm91dGVzOiBvcHRpb25hbCh7IHNjaGVtYTogbnVsbCwgJGNvbmZpZ1BhdGg6IG51bGwgfSksXG5cdFx0cm91dGVPcHRpb25zOiB7XG5cdFx0XHRcIlwiOiBGTElHSFRERUNLX01BTlVBTCxcblx0XHRcdCRjb25maWdQYXRoOiBGTElHSFRERUNLX01BTlVBTCxcblx0XHRcdHNjaGVtYTogU0NIRU1BX01BTlVBTCxcblx0XHR9LFxuXHRcdGRlYnVnT3V0cHV0OiB0cnVlLFxuXHRcdGRpc2NvdmVyQ29uZmlnUGF0aDogKGFyZ3MpID0+IHtcblx0XHRcdGlmIChhcmdzWzBdID09PSBgc2NoZW1hYCkge1xuXHRcdFx0XHRyZXR1cm5cblx0XHRcdH1cblx0XHRcdGNvbnN0IGNvbmZpZ1BhdGggPVxuXHRcdFx0XHRhcmdzWzBdID8/IHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBgZmxpZ2h0ZGVjay5jb25maWcuanNvbmApXG5cdFx0XHRyZXR1cm4gY29uZmlnUGF0aFxuXHRcdH0sXG5cdH0sXG5cdGNvbnNvbGUsXG4pXG5cbmNvbnN0IHsgaW5wdXRzLCB3cml0ZUpzb25TY2hlbWEgfSA9IHBhcnNlKHByb2Nlc3MuYXJndilcblxuc3dpdGNoIChpbnB1dHMuY2FzZSkge1xuXHRjYXNlIGBzY2hlbWFgOlxuXHRcdHtcblx0XHRcdGNvbnN0IHsgb3V0ZGlyIH0gPSBpbnB1dHMub3B0c1xuXHRcdFx0d3JpdGVKc29uU2NoZW1hKG91dGRpciA/PyBgLmApXG5cdFx0fVxuXHRcdGJyZWFrXG5cdGRlZmF1bHQ6IHtcblx0XHRjb25zdCBmbGlnaHREZWNrID0gbmV3IEZsaWdodERlY2soaW5wdXRzLm9wdHMpXG5cdFx0cHJvY2Vzcy5vbihgY2xvc2VgLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRhd2FpdCBmbGlnaHREZWNrLnN0b3BBbGxTZXJ2aWNlcygpXG5cdFx0fSlcblx0fVxufVxuIiwKICAgICJpbXBvcnQgeyBleGVjU3luYywgc3Bhd24gfSBmcm9tIFwibm9kZTpjaGlsZF9wcm9jZXNzXCJcbmltcG9ydCB0eXBlIHsgU2VydmVyIH0gZnJvbSBcIm5vZGU6aHR0cFwiXG5pbXBvcnQgeyBjcmVhdGVTZXJ2ZXIgfSBmcm9tIFwibm9kZTpodHRwXCJcbmltcG9ydCB7IGhvbWVkaXIgfSBmcm9tIFwibm9kZTpvc1wiXG5pbXBvcnQgeyByZXNvbHZlIH0gZnJvbSBcIm5vZGU6cGF0aFwiXG5pbXBvcnQgeyBpbnNwZWN0IH0gZnJvbSBcIm5vZGU6dXRpbFwiXG5cbmltcG9ydCB7IEZ1dHVyZSB9IGZyb20gXCJhdG9tLmlvL2ludGVybmFsXCJcbmltcG9ydCB7IGRpc2NvdmVyVHlwZSB9IGZyb20gXCJhdG9tLmlvL2ludHJvc3BlY3Rpb25cIlxuaW1wb3J0IHsgZnJvbUVudHJpZXMsIHRvRW50cmllcyB9IGZyb20gXCJhdG9tLmlvL2pzb25cIlxuaW1wb3J0IHsgQ2hpbGRTb2NrZXQgfSBmcm9tIFwiYXRvbS5pby9yZWFsdGltZS1zZXJ2ZXJcIlxuaW1wb3J0IHsgQ3JvbkpvYiB9IGZyb20gXCJjcm9uXCJcbmltcG9ydCB7IEZpbGVzeXN0ZW1TdG9yYWdlIH0gZnJvbSBcInNhZmVkZXBvc2l0XCJcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCJcblxuaW1wb3J0IHR5cGUgeyBMbmF2Rm9ybWF0IH0gZnJvbSBcIi4uL2dlbi9sbmF2LWZvcm1hdC1zY2hlbWEuZ2VuXCJcbmltcG9ydCB7IGVudiB9IGZyb20gXCIuL2ZsaWdodGRlY2suZW52XCJcblxuZXhwb3J0IGNvbnN0IEZMSUdIVERFQ0tfU0VUVVBfUEhBU0VTID0gW2Bkb3dubG9hZGVkYCwgYGluc3RhbGxlZGBdIGFzIGNvbnN0XG5cbmV4cG9ydCB0eXBlIEZsaWdodERlY2tTZXR1cFBoYXNlID0gKHR5cGVvZiBGTElHSFRERUNLX1NFVFVQX1BIQVNFUylbbnVtYmVyXVxuXG5leHBvcnQgY29uc3QgRkxJR0hUREVDS19VUERBVEVfUEhBU0VTID0gW2Bub3RpZmllZGAsIGBjb25maXJtZWRgXSBhcyBjb25zdFxuXG5leHBvcnQgdHlwZSBGbGlnaHREZWNrVXBkYXRlUGhhc2UgPSAodHlwZW9mIEZMSUdIVERFQ0tfVVBEQVRFX1BIQVNFUylbbnVtYmVyXVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWZXJzaW9uTnVtYmVyKHZlcnNpb246IHN0cmluZyk6IGJvb2xlYW4ge1xuXHRyZXR1cm4gKFxuXHRcdC9eXFxkK1xcLlxcZCtcXC5cXGQrJC8udGVzdCh2ZXJzaW9uKSB8fCAhTnVtYmVyLmlzTmFOKE51bWJlci5wYXJzZUZsb2F0KHZlcnNpb24pKVxuXHQpXG59XG5cbmV4cG9ydCB0eXBlIEZsaWdodERlY2tPcHRpb25zPFMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmc+ID0ge1xuXHRwYWNrYWdlTmFtZTogc3RyaW5nXG5cdHNlcnZpY2VzOiB7IFtzZXJ2aWNlIGluIFNdOiB7IHJ1bjogc3RyaW5nOyB3YWl0Rm9yOiBib29sZWFuIH0gfVxuXHRzY3JpcHRzOiB7XG5cdFx0ZG93bmxvYWQ6IHN0cmluZ1xuXHRcdGluc3RhbGw6IHN0cmluZ1xuXHRcdGNoZWNrQXZhaWxhYmlsaXR5Pzogc3RyaW5nXG5cdH1cblx0cG9ydD86IG51bWJlciB8IHVuZGVmaW5lZFxuXHRmbGlnaHRkZWNrUm9vdERpcj86IHN0cmluZyB8IHVuZGVmaW5lZFxuXHRqc29uTG9nZ2luZz86IGJvb2xlYW4gfCB1bmRlZmluZWRcbn1cblxuZXhwb3J0IGNsYXNzIEZsaWdodERlY2s8UyBleHRlbmRzIHN0cmluZyA9IHN0cmluZz4ge1xuXHRwcm90ZWN0ZWQgc2FmZXR5ID0gMFxuXG5cdHByb3RlY3RlZCBzdG9yYWdlOiBGaWxlc3lzdGVtU3RvcmFnZTx7XG5cdFx0c2V0dXBQaGFzZTogRmxpZ2h0RGVja1NldHVwUGhhc2Vcblx0XHR1cGRhdGVQaGFzZTogRmxpZ2h0RGVja1VwZGF0ZVBoYXNlXG5cdFx0dXBkYXRlQXdhaXRlZFZlcnNpb246IHN0cmluZ1xuXHR9PlxuXHRwcm90ZWN0ZWQgd2ViaG9va1NlcnZlcjogU2VydmVyXG5cdHByb3RlY3RlZCBzZXJ2aWNlczoge1xuXHRcdFtzZXJ2aWNlIGluIFNdOiBDaGlsZFNvY2tldDxcblx0XHRcdHsgdGltZVRvU3RvcDogW107IHVwZGF0ZXNSZWFkeTogW10gfSxcblx0XHRcdHsgcmVhZHlUb1VwZGF0ZTogW107IGFsaXZlOiBbXSB9XG5cdFx0PiB8IG51bGxcblx0fVxuXHRwcm90ZWN0ZWQgc2VydmljZUlkeDogeyByZWFkb25seSBbc2VydmljZSBpbiBTXTogbnVtYmVyIH1cblx0cHVibGljIGRlZmF1bHRTZXJ2aWNlc1JlYWR5VG9VcGRhdGU6IHsgcmVhZG9ubHkgW3NlcnZpY2UgaW4gU106IGJvb2xlYW4gfVxuXHRwdWJsaWMgc2VydmljZXNSZWFkeVRvVXBkYXRlOiB7IFtzZXJ2aWNlIGluIFNdOiBib29sZWFuIH1cblx0cHVibGljIGF1dG9SZXNwYXduRGVhZFNlcnZpY2VzOiBib29sZWFuXG5cblx0cHJvdGVjdGVkIGxvZ2dlcjogUGljazxDb25zb2xlLCBgZXJyb3JgIHwgYGluZm9gIHwgYHdhcm5gPlxuXHRwcm90ZWN0ZWQgc2VydmljZUxvZ2dlcnM6IHtcblx0XHRyZWFkb25seSBbc2VydmljZSBpbiBTXTogRmxpZ2h0RGVja0xvZ2dlclxuXHR9XG5cblx0cHJvdGVjdGVkIHVwZGF0ZUF2YWlsYWJpbGl0eUNoZWNrZXI6IENyb25Kb2IgfCBudWxsID0gbnVsbFxuXG5cdHB1YmxpYyBzZXJ2aWNlc0xpdmU6IEZ1dHVyZTx2b2lkPltdXG5cdHB1YmxpYyBzZXJ2aWNlc0RlYWQ6IEZ1dHVyZTx2b2lkPltdXG5cdHB1YmxpYyBsaXZlID0gbmV3IEZ1dHVyZSgoKSA9PiB7fSlcblx0cHVibGljIGRlYWQgPSBuZXcgRnV0dXJlKCgpID0+IHt9KVxuXG5cdHByb3RlY3RlZCByZXN0YXJ0VGltZXM6IG51bWJlcltdID0gW11cblxuXHRwdWJsaWMgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IG9wdGlvbnM6IEZsaWdodERlY2tPcHRpb25zPFM+KSB7XG5cdFx0Y29uc3QgeyBGTElHSFRERUNLX1NFQ1JFVCB9ID0gZW52XG5cdFx0Y29uc3QgeyBmbGlnaHRkZWNrUm9vdERpciA9IHJlc29sdmUoaG9tZWRpcigpLCBgLmZsaWdodGRlY2tgKSB9ID0gb3B0aW9uc1xuXHRcdGNvbnN0IHBvcnQgPSBvcHRpb25zLnBvcnQgPz8gODA4MFxuXHRcdGNvbnN0IG9yaWdpbiA9IGBodHRwOi8vbG9jYWxob3N0OiR7cG9ydH1gXG5cblx0XHRjb25zdCBzZXJ2aWNlc0VudHJpZXMgPSB0b0VudHJpZXMob3B0aW9ucy5zZXJ2aWNlcylcblx0XHR0aGlzLnNlcnZpY2VzID0gZnJvbUVudHJpZXMoXG5cdFx0XHRzZXJ2aWNlc0VudHJpZXMubWFwKChbc2VydmljZU5hbWVdKSA9PiBbc2VydmljZU5hbWUsIG51bGxdKSxcblx0XHQpXG5cdFx0dGhpcy5zZXJ2aWNlSWR4ID0gZnJvbUVudHJpZXMoXG5cdFx0XHRzZXJ2aWNlc0VudHJpZXMubWFwKChbc2VydmljZU5hbWVdLCBpZHgpID0+IFtzZXJ2aWNlTmFtZSwgaWR4XSksXG5cdFx0KVxuXHRcdHRoaXMuZGVmYXVsdFNlcnZpY2VzUmVhZHlUb1VwZGF0ZSA9IGZyb21FbnRyaWVzKFxuXHRcdFx0c2VydmljZXNFbnRyaWVzLm1hcCgoW3NlcnZpY2VOYW1lLCB7IHdhaXRGb3IgfV0pID0+IFtcblx0XHRcdFx0c2VydmljZU5hbWUsXG5cdFx0XHRcdCF3YWl0Rm9yLFxuXHRcdFx0XSksXG5cdFx0KVxuXHRcdHRoaXMuc2VydmljZXNSZWFkeVRvVXBkYXRlID0geyAuLi50aGlzLmRlZmF1bHRTZXJ2aWNlc1JlYWR5VG9VcGRhdGUgfVxuXHRcdHRoaXMuYXV0b1Jlc3Bhd25EZWFkU2VydmljZXMgPSB0cnVlXG5cblx0XHR0aGlzLmxvZ2dlciA9IG5ldyBGbGlnaHREZWNrTG9nZ2VyKFxuXHRcdFx0dGhpcy5vcHRpb25zLnBhY2thZ2VOYW1lLFxuXHRcdFx0cHJvY2Vzcy5waWQsXG5cdFx0XHR1bmRlZmluZWQsXG5cdFx0XHR7IGpzb25Mb2dnaW5nOiB0aGlzLm9wdGlvbnMuanNvbkxvZ2dpbmcgPz8gZmFsc2UgfSxcblx0XHQpXG5cdFx0dGhpcy5zZXJ2aWNlTG9nZ2VycyA9IGZyb21FbnRyaWVzKFxuXHRcdFx0c2VydmljZXNFbnRyaWVzLm1hcCgoW3NlcnZpY2VOYW1lXSkgPT4gW1xuXHRcdFx0XHRzZXJ2aWNlTmFtZSxcblx0XHRcdFx0bmV3IEZsaWdodERlY2tMb2dnZXIoXG5cdFx0XHRcdFx0dGhpcy5vcHRpb25zLnBhY2thZ2VOYW1lLFxuXHRcdFx0XHRcdHByb2Nlc3MucGlkLFxuXHRcdFx0XHRcdHNlcnZpY2VOYW1lLFxuXHRcdFx0XHRcdHsganNvbkxvZ2dpbmc6IHRoaXMub3B0aW9ucy5qc29uTG9nZ2luZyA/PyBmYWxzZSB9LFxuXHRcdFx0XHQpLFxuXHRcdFx0XSksXG5cdFx0KVxuXG5cdFx0dGhpcy5zZXJ2aWNlc0xpdmUgPSBzZXJ2aWNlc0VudHJpZXMubWFwKCgpID0+IG5ldyBGdXR1cmUoKCkgPT4ge30pKVxuXHRcdHRoaXMuc2VydmljZXNEZWFkID0gc2VydmljZXNFbnRyaWVzLm1hcCgoKSA9PiBuZXcgRnV0dXJlKCgpID0+IHt9KSlcblx0XHR0aGlzLmxpdmUudXNlKFByb21pc2UuYWxsKHRoaXMuc2VydmljZXNMaXZlKSlcblx0XHR0aGlzLmRlYWQudXNlKFByb21pc2UuYWxsKHRoaXMuc2VydmljZXNEZWFkKSlcblxuXHRcdHRoaXMuc3RvcmFnZSA9IG5ldyBGaWxlc3lzdGVtU3RvcmFnZSh7XG5cdFx0XHRwYXRoOiByZXNvbHZlKGZsaWdodGRlY2tSb290RGlyLCBgc3RvcmFnZWAsIG9wdGlvbnMucGFja2FnZU5hbWUpLFxuXHRcdH0pXG5cblx0XHRpZiAoRkxJR0hUREVDS19TRUNSRVQgPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0dGhpcy5sb2dnZXIud2Fybihcblx0XHRcdFx0YE5vIEZMSUdIVERFQ0tfU0VDUkVUIGVudmlyb25tZW50IHZhcmlhYmxlIGZvdW5kLiBGbGlnaHREZWNrIHdpbGwgbm90IHJ1biBhbiB1cGRhdGUgc2VydmVyLmAsXG5cdFx0XHQpXG5cdFx0fSBlbHNlIHtcblx0XHRcdGNyZWF0ZVNlcnZlcigocmVxLCByZXMpID0+IHtcblx0XHRcdFx0bGV0IGRhdGE6IFVpbnQ4QXJyYXlbXSA9IFtdXG5cdFx0XHRcdHJlcVxuXHRcdFx0XHRcdC5vbihgZGF0YWAsIChjaHVuaykgPT4ge1xuXHRcdFx0XHRcdFx0ZGF0YS5wdXNoKGNodW5rIGluc3RhbmNlb2YgQnVmZmVyID8gY2h1bmsgOiBCdWZmZXIuZnJvbShjaHVuaykpXG5cdFx0XHRcdFx0fSlcblx0XHRcdFx0XHQub24oYGVuZGAsICgpID0+IHtcblx0XHRcdFx0XHRcdGNvbnN0IGF1dGhIZWFkZXIgPSByZXEuaGVhZGVycy5hdXRob3JpemF0aW9uXG5cdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRpZiAodHlwZW9mIHJlcS51cmwgPT09IGB1bmRlZmluZWRgKSB0aHJvdyA0MDBcblx0XHRcdFx0XHRcdFx0Y29uc3QgZXhwZWN0ZWRBdXRoSGVhZGVyID0gYEJlYXJlciAke0ZMSUdIVERFQ0tfU0VDUkVUfWBcblx0XHRcdFx0XHRcdFx0aWYgKGF1dGhIZWFkZXIgIT09IGBCZWFyZXIgJHtGTElHSFRERUNLX1NFQ1JFVH1gKSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhcblx0XHRcdFx0XHRcdFx0XHRcdGBVbmF1dGhvcml6ZWQ6IG5lZWRlZCBcXGAke2V4cGVjdGVkQXV0aEhlYWRlcn1cXGAsIGdvdCBcXGAke2F1dGhIZWFkZXJ9XFxgYCxcblx0XHRcdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHRcdFx0dGhyb3cgNDAxXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0Y29uc3QgdXJsID0gbmV3IFVSTChyZXEudXJsLCBvcmlnaW4pXG5cdFx0XHRcdFx0XHRcdHRoaXMubG9nZ2VyLmluZm8ocmVxLm1ldGhvZCwgdXJsLnBhdGhuYW1lKVxuXG5cdFx0XHRcdFx0XHRcdGNvbnN0IHZlcnNpb25Gb3JlaWduSW5wdXQgPSBCdWZmZXIuY29uY2F0KGRhdGEpLnRvU3RyaW5nKClcblx0XHRcdFx0XHRcdFx0aWYgKCFpc1ZlcnNpb25OdW1iZXIodmVyc2lvbkZvcmVpZ25JbnB1dCkpIHtcblx0XHRcdFx0XHRcdFx0XHR0aHJvdyA0MDBcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdHJlcy53cml0ZUhlYWQoMjAwKVxuXHRcdFx0XHRcdFx0XHRyZXMuZW5kKClcblxuXHRcdFx0XHRcdFx0XHR0aGlzLnN0b3JhZ2Uuc2V0SXRlbShgdXBkYXRlUGhhc2VgLCBgbm90aWZpZWRgKVxuXHRcdFx0XHRcdFx0XHR0aGlzLnN0b3JhZ2Uuc2V0SXRlbShgdXBkYXRlQXdhaXRlZFZlcnNpb25gLCB2ZXJzaW9uRm9yZWlnbklucHV0KVxuXHRcdFx0XHRcdFx0XHRjb25zdCB7IGNoZWNrQXZhaWxhYmlsaXR5IH0gPSBvcHRpb25zLnNjcmlwdHNcblx0XHRcdFx0XHRcdFx0aWYgKGNoZWNrQXZhaWxhYmlsaXR5KSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhpcy51cGRhdGVBdmFpbGFiaWxpdHlDaGVja2VyPy5zdG9wKClcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnNlZWtVcGRhdGUodmVyc2lvbkZvcmVpZ25JbnB1dClcblx0XHRcdFx0XHRcdFx0XHRjb25zdCB1cGRhdGVQaGFzZSA9IHRoaXMuc3RvcmFnZS5nZXRJdGVtKGB1cGRhdGVQaGFzZWApXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgPiBzdG9yYWdlKFwidXBkYXRlUGhhc2VcIikgPmAsIHVwZGF0ZVBoYXNlKVxuXHRcdFx0XHRcdFx0XHRcdGlmICh1cGRhdGVQaGFzZSA9PT0gYG5vdGlmaWVkYCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0dGhpcy51cGRhdGVBdmFpbGFiaWxpdHlDaGVja2VyID0gbmV3IENyb25Kb2IoXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGAzMCAqICogKiAqICpgLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHQoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0dGhpcy5zZWVrVXBkYXRlKHZlcnNpb25Gb3JlaWduSW5wdXQpXG5cdFx0XHRcdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHRcdFx0XHR0aGlzLnVwZGF0ZUF2YWlsYWJpbGl0eUNoZWNrZXIuc3RhcnQoKVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmRvd25sb2FkUGFja2FnZSgpXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0gY2F0Y2ggKHRocm93bikge1xuXHRcdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcih0aHJvd24sIHJlcS51cmwpXG5cdFx0XHRcdFx0XHRcdGlmICh0eXBlb2YgdGhyb3duID09PSBgbnVtYmVyYCkge1xuXHRcdFx0XHRcdFx0XHRcdHJlcy53cml0ZUhlYWQodGhyb3duKVxuXHRcdFx0XHRcdFx0XHRcdHJlcy5lbmQoKVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGZpbmFsbHkge1xuXHRcdFx0XHRcdFx0XHRkYXRhID0gW11cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KVxuXHRcdFx0fSkubGlzdGVuKHBvcnQsICgpID0+IHtcblx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgU2VydmVyIHN0YXJ0ZWQgb24gcG9ydCAke3BvcnR9YClcblx0XHRcdH0pXG5cdFx0fVxuXG5cdFx0dGhpcy5zdGFydEFsbFNlcnZpY2VzKClcblx0XHRcdC50aGVuKCgpID0+IHtcblx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgQWxsIHNlcnZpY2VzIHN0YXJ0ZWQuYClcblx0XHRcdH0pXG5cdFx0XHQuY2F0Y2goKHRocm93bikgPT4ge1xuXHRcdFx0XHRpZiAodGhyb3duIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIHN0YXJ0IGFsbCBzZXJ2aWNlczpgLCB0aHJvd24ubWVzc2FnZSlcblx0XHRcdFx0fVxuXHRcdFx0fSlcblx0fVxuXG5cdHByb3RlY3RlZCBzZWVrVXBkYXRlKHZlcnNpb246IHN0cmluZyk6IHZvaWQge1xuXHRcdHRoaXMubG9nZ2VyLmluZm8oYENoZWNraW5nIGZvciB1cGRhdGVzLi4uYClcblx0XHRjb25zdCB7IGNoZWNrQXZhaWxhYmlsaXR5IH0gPSB0aGlzLm9wdGlvbnMuc2NyaXB0c1xuXHRcdGlmICghY2hlY2tBdmFpbGFiaWxpdHkpIHtcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYE5vIGNoZWNrQXZhaWxhYmlsaXR5IHNjcmlwdCBmb3VuZC5gKVxuXHRcdFx0cmV0dXJuXG5cdFx0fVxuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBvdXQgPSBleGVjU3luYyhgJHtjaGVja0F2YWlsYWJpbGl0eX0gJHt2ZXJzaW9ufWApXG5cdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBDaGVjayBzdGRvdXQ6YCwgb3V0LnRvU3RyaW5nKCkpXG5cdFx0XHR0aGlzLnVwZGF0ZUF2YWlsYWJpbGl0eUNoZWNrZXI/LnN0b3AoKVxuXHRcdFx0dGhpcy5zdG9yYWdlLnNldEl0ZW0oYHVwZGF0ZVBoYXNlYCwgYGNvbmZpcm1lZGApXG5cdFx0XHR0aGlzLmRvd25sb2FkUGFja2FnZSgpXG5cdFx0XHR0aGlzLmFubm91bmNlVXBkYXRlKClcblx0XHR9IGNhdGNoICh0aHJvd24pIHtcblx0XHRcdGlmICh0aHJvd24gaW5zdGFuY2VvZiBFcnJvcikge1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihgQ2hlY2sgZmFpbGVkOmAsIHRocm93bi5tZXNzYWdlKVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y29uc3QgdGhyb3duVHlwZSA9IGRpc2NvdmVyVHlwZSh0aHJvd24pXG5cdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBDaGVjayB0aHJld2AsIHRocm93blR5cGUsIHRocm93bilcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRwcm90ZWN0ZWQgYW5ub3VuY2VVcGRhdGUoKTogdm9pZCB7XG5cdFx0Zm9yIChjb25zdCBlbnRyeSBvZiB0b0VudHJpZXModGhpcy5zZXJ2aWNlcykpIHtcblx0XHRcdGNvbnN0IFtzZXJ2aWNlTmFtZSwgc2VydmljZV0gPSBlbnRyeVxuXHRcdFx0aWYgKHNlcnZpY2UpIHtcblx0XHRcdFx0aWYgKHRoaXMub3B0aW9ucy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0ud2FpdEZvcikge1xuXHRcdFx0XHRcdHNlcnZpY2UuZW1pdChgdXBkYXRlc1JlYWR5YClcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5zdGFydFNlcnZpY2Uoc2VydmljZU5hbWUpXG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cHJvdGVjdGVkIHRyeVVwZGF0ZSgpOiB2b2lkIHtcblx0XHRpZiAodG9FbnRyaWVzKHRoaXMuc2VydmljZXNSZWFkeVRvVXBkYXRlKS5ldmVyeSgoWywgaXNSZWFkeV0pID0+IGlzUmVhZHkpKSB7XG5cdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBBbGwgc2VydmljZXMgYXJlIHJlYWR5IHRvIHVwZGF0ZS5gKVxuXHRcdFx0dGhpcy5zdG9wQWxsU2VydmljZXMoKVxuXHRcdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgQWxsIHNlcnZpY2VzIHN0b3BwZWQ7IHN0YXJ0aW5nIHVwIGZyZXNoLi4uYClcblx0XHRcdFx0XHR0aGlzLnN0YXJ0QWxsU2VydmljZXMoKVxuXHRcdFx0XHRcdFx0LnRoZW4oKCkgPT4ge1xuXHRcdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBBbGwgc2VydmljZXMgc3RhcnRlZDsgd2UncmUgYmFjayBvbmxpbmUuYClcblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdFx0XHQuY2F0Y2goKHRocm93bikgPT4ge1xuXHRcdFx0XHRcdFx0XHRpZiAodGhyb3duIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihcblx0XHRcdFx0XHRcdFx0XHRcdGBGYWlsZWQgdG8gc3RhcnQgYWxsIHNlcnZpY2VzOmAsXG5cdFx0XHRcdFx0XHRcdFx0XHR0aHJvd24ubWVzc2FnZSxcblx0XHRcdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdH0pXG5cdFx0XHRcdC5jYXRjaCgodGhyb3duKSA9PiB7XG5cdFx0XHRcdFx0aWYgKHRocm93biBpbnN0YW5jZW9mIEVycm9yKSB7XG5cdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIHN0b3AgYWxsIHNlcnZpY2VzOmAsIHRocm93bi5tZXNzYWdlKVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSlcblx0XHR9XG5cdH1cblxuXHRwcm90ZWN0ZWQgc3RhcnRBbGxTZXJ2aWNlcygpOiBGdXR1cmU8dW5rbm93bj4ge1xuXHRcdHRoaXMubG9nZ2VyLmluZm8oYFN0YXJ0aW5nIGFsbCBzZXJ2aWNlcy4uLmApXG5cdFx0dGhpcy5hdXRvUmVzcGF3bkRlYWRTZXJ2aWNlcyA9IHRydWVcblx0XHRjb25zdCBzZXR1cFBoYXNlID0gdGhpcy5zdG9yYWdlLmdldEl0ZW0oYHNldHVwUGhhc2VgKVxuXHRcdHRoaXMubG9nZ2VyLmluZm8oYD4gc3RvcmFnZShcInNldHVwUGhhc2VcIikgPmAsIHNldHVwUGhhc2UpXG5cdFx0c3dpdGNoIChzZXR1cFBoYXNlKSB7XG5cdFx0XHRjYXNlIG51bGw6XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYFN0YXJ0aW5nIGZyb20gc2NyYXRjaC5gKVxuXHRcdFx0XHR0aGlzLmRvd25sb2FkUGFja2FnZSgpXG5cdFx0XHRcdHRoaXMuaW5zdGFsbFBhY2thZ2UoKVxuXHRcdFx0XHRyZXR1cm4gdGhpcy5zdGFydEFsbFNlcnZpY2VzKClcblx0XHRcdGNhc2UgYGRvd25sb2FkZWRgOlxuXHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBGb3VuZCBwYWNrYWdlIGRvd25sb2FkZWQgYnV0IG5vdCBpbnN0YWxsZWQuYClcblx0XHRcdFx0dGhpcy5pbnN0YWxsUGFja2FnZSgpXG5cdFx0XHRcdHJldHVybiB0aGlzLnN0YXJ0QWxsU2VydmljZXMoKVxuXHRcdFx0Y2FzZSBgaW5zdGFsbGVkYDoge1xuXHRcdFx0XHRmb3IgKGNvbnN0IFtzZXJ2aWNlTmFtZV0gb2YgdG9FbnRyaWVzKHRoaXMuc2VydmljZXMpKSB7XG5cdFx0XHRcdFx0dGhpcy5zdGFydFNlcnZpY2Uoc2VydmljZU5hbWUpXG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXMubGl2ZVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHByb3RlY3RlZCBzdGFydFNlcnZpY2Uoc2VydmljZU5hbWU6IFMpOiB2b2lkIHtcblx0XHR0aGlzLmxvZ2dlci5pbmZvKFxuXHRcdFx0YFN0YXJ0aW5nIHNlcnZpY2UgJHt0aGlzLm9wdGlvbnMucGFja2FnZU5hbWV9Ojoke3NlcnZpY2VOYW1lfSwgdHJ5ICR7dGhpcy5zYWZldHl9LzIuLi5gLFxuXHRcdClcblx0XHRpZiAodGhpcy5zYWZldHkgPj0gMikge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBPdXQgb2YgdHJpZXMuLi5gKVxuXHRcdH1cblx0XHR0aGlzLnNhZmV0eSsrXG5cblx0XHRjb25zdCBbZXhlLCAuLi5hcmdzXSA9IHRoaXMub3B0aW9ucy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0ucnVuLnNwbGl0KGAgYClcblx0XHRjb25zdCBzZXJ2aWNlUHJvY2VzcyA9IHNwYXduKGV4ZSwgYXJncywge1xuXHRcdFx0Y3dkOiB0aGlzLm9wdGlvbnMuZmxpZ2h0ZGVja1Jvb3REaXIsXG5cdFx0XHRlbnY6IGltcG9ydC5tZXRhLmVudixcblx0XHR9KVxuXHRcdGNvbnN0IHNlcnZpY2VMb2dnZXIgPSB0aGlzLnNlcnZpY2VMb2dnZXJzW3NlcnZpY2VOYW1lXVxuXHRcdGNvbnN0IHNlcnZpY2UgPSAodGhpcy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0gPSBuZXcgQ2hpbGRTb2NrZXQoXG5cdFx0XHRzZXJ2aWNlUHJvY2Vzcyxcblx0XHRcdGAke3RoaXMub3B0aW9ucy5wYWNrYWdlTmFtZX06OiR7c2VydmljZU5hbWV9YCxcblx0XHRcdHNlcnZpY2VMb2dnZXIsXG5cdFx0KSlcblx0XHRzZXJ2aWNlTG9nZ2VyLnByb2Nlc3NDb2RlID0gc2VydmljZS5wcm9jZXNzLnBpZCA/PyAtMVxuXHRcdHRoaXMuc2VydmljZXNbc2VydmljZU5hbWVdLm9uQW55KCguLi5tZXNzYWdlcykgPT4ge1xuXHRcdFx0c2VydmljZUxvZ2dlci5pbmZvKGDwn5KsYCwgLi4ubWVzc2FnZXMpXG5cdFx0fSlcblx0XHR0aGlzLnNlcnZpY2VzW3NlcnZpY2VOYW1lXS5vbihgcmVhZHlUb1VwZGF0ZWAsICgpID0+IHtcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYFNlcnZpY2UgXCIke3NlcnZpY2VOYW1lfVwiIGlzIHJlYWR5IHRvIHVwZGF0ZS5gKVxuXHRcdFx0dGhpcy5zZXJ2aWNlc1JlYWR5VG9VcGRhdGVbc2VydmljZU5hbWVdID0gdHJ1ZVxuXHRcdFx0dGhpcy50cnlVcGRhdGUoKVxuXHRcdH0pXG5cdFx0dGhpcy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0ub24oYGFsaXZlYCwgKCkgPT4ge1xuXHRcdFx0dGhpcy5zZXJ2aWNlc0xpdmVbdGhpcy5zZXJ2aWNlSWR4W3NlcnZpY2VOYW1lXV0udXNlKFByb21pc2UucmVzb2x2ZSgpKVxuXHRcdFx0dGhpcy5zZXJ2aWNlc0RlYWRbdGhpcy5zZXJ2aWNlSWR4W3NlcnZpY2VOYW1lXV0gPSBuZXcgRnV0dXJlKCgpID0+IHt9KVxuXHRcdFx0aWYgKHRoaXMuZGVhZC5kb25lKSB7XG5cdFx0XHRcdHRoaXMuZGVhZCA9IG5ldyBGdXR1cmUoKCkgPT4ge30pXG5cdFx0XHR9XG5cdFx0XHR0aGlzLmRlYWQudXNlKFByb21pc2UuYWxsKHRoaXMuc2VydmljZXNEZWFkKSlcblx0XHR9KVxuXHRcdHRoaXMuc2VydmljZXNbc2VydmljZU5hbWVdLnByb2Nlc3Mub25jZShgY2xvc2VgLCAoZXhpdENvZGUpID0+IHtcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oXG5cdFx0XHRcdGBBdXRvLXJlc3Bhd24gc2F3IFwiJHtzZXJ2aWNlTmFtZX1cIiBleGl0IHdpdGggY29kZSAke2V4aXRDb2RlfWAsXG5cdFx0XHQpXG5cdFx0XHR0aGlzLnNlcnZpY2VzW3NlcnZpY2VOYW1lXSA9IG51bGxcblx0XHRcdGlmICghdGhpcy5hdXRvUmVzcGF3bkRlYWRTZXJ2aWNlcykge1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBBdXRvLXJlc3Bhd24gaXMgb2ZmOyBcIiR7c2VydmljZU5hbWV9XCIgcmVzdHMuYClcblx0XHRcdFx0cmV0dXJuXG5cdFx0XHR9XG5cdFx0XHRjb25zdCB1cGRhdGVQaGFzZSA9IHRoaXMuc3RvcmFnZS5nZXRJdGVtKGB1cGRhdGVQaGFzZWApXG5cdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGA+IHN0b3JhZ2UoXCJ1cGRhdGVQaGFzZVwiKSA+YCwgdXBkYXRlUGhhc2UpXG5cdFx0XHRjb25zdCB1cGRhdGVzQXJlUmVhZHkgPSB1cGRhdGVQaGFzZSA9PT0gYGNvbmZpcm1lZGBcblx0XHRcdGlmICh1cGRhdGVzQXJlUmVhZHkpIHtcblx0XHRcdFx0dGhpcy5zZXJ2aWNlTG9nZ2Vyc1tzZXJ2aWNlTmFtZV0uaW5mbyhgVXBkYXRpbmcgYmVmb3JlIHN0YXJ0dXAuLi5gKVxuXHRcdFx0XHR0aGlzLnJlc3RhcnRUaW1lcyA9IFtdXG5cdFx0XHRcdHRoaXMuaW5zdGFsbFBhY2thZ2UoKVxuXHRcdFx0XHR0aGlzLnN0YXJ0U2VydmljZShzZXJ2aWNlTmFtZSlcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNvbnN0IG5vdyA9IERhdGUubm93KClcblx0XHRcdFx0Y29uc3QgZml2ZU1pbnV0ZXNBZ28gPSBub3cgLSA1ICogNjAgKiAxMDAwXG5cdFx0XHRcdHRoaXMucmVzdGFydFRpbWVzID0gdGhpcy5yZXN0YXJ0VGltZXMuZmlsdGVyKFxuXHRcdFx0XHRcdCh0aW1lKSA9PiB0aW1lID4gZml2ZU1pbnV0ZXNBZ28sXG5cdFx0XHRcdClcblx0XHRcdFx0dGhpcy5yZXN0YXJ0VGltZXMucHVzaChub3cpXG5cblx0XHRcdFx0aWYgKHRoaXMucmVzdGFydFRpbWVzLmxlbmd0aCA8IDUpIHtcblx0XHRcdFx0XHR0aGlzLnNlcnZpY2VMb2dnZXJzW3NlcnZpY2VOYW1lXS5pbmZvKGBDcmFzaGVkLiBSZXN0YXJ0aW5nLi4uYClcblx0XHRcdFx0XHR0aGlzLnN0YXJ0U2VydmljZShzZXJ2aWNlTmFtZSlcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLnNlcnZpY2VMb2dnZXJzW3NlcnZpY2VOYW1lXS5pbmZvKFxuXHRcdFx0XHRcdFx0YENyYXNoZWQgNSB0aW1lcyBpbiA1IG1pbnV0ZXMuIE5vdCByZXN0YXJ0aW5nLmAsXG5cdFx0XHRcdFx0KVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSlcblx0XHR0aGlzLnNhZmV0eSA9IDBcblx0fVxuXG5cdHByb3RlY3RlZCBkb3dubG9hZFBhY2thZ2UoKTogdm9pZCB7XG5cdFx0dGhpcy5sb2dnZXIuaW5mbyhgRG93bmxvYWRpbmcuLi5gKVxuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBvdXQgPSBleGVjU3luYyh0aGlzLm9wdGlvbnMuc2NyaXB0cy5kb3dubG9hZClcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYERvd25sb2FkIHN0ZG91dDpgLCBvdXQudG9TdHJpbmcoKSlcblx0XHRcdHRoaXMuc3RvcmFnZS5zZXRJdGVtKGBzZXR1cFBoYXNlYCwgYGRvd25sb2FkZWRgKVxuXHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgRG93bmxvYWRlZCFgKVxuXHRcdH0gY2F0Y2ggKHRocm93bikge1xuXHRcdFx0aWYgKHRocm93biBpbnN0YW5jZW9mIEVycm9yKSB7XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBGYWlsZWQgdG8gZ2V0IHRoZSBsYXRlc3QgcmVsZWFzZTogJHt0aHJvd24ubWVzc2FnZX1gKVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuXG5cdFx0fVxuXHR9XG5cblx0cHJvdGVjdGVkIGluc3RhbGxQYWNrYWdlKCk6IHZvaWQge1xuXHRcdHRoaXMubG9nZ2VyLmluZm8oYEluc3RhbGxpbmcuLi5gKVxuXG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IG91dCA9IGV4ZWNTeW5jKHRoaXMub3B0aW9ucy5zY3JpcHRzLmluc3RhbGwpXG5cdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBJbnN0YWxsIHN0ZG91dDpgLCBvdXQudG9TdHJpbmcoKSlcblx0XHRcdHRoaXMuc3RvcmFnZS5zZXRJdGVtKGBzZXR1cFBoYXNlYCwgYGluc3RhbGxlZGApXG5cdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBJbnN0YWxsZWQhYClcblx0XHR9IGNhdGNoICh0aHJvd24pIHtcblx0XHRcdGlmICh0aHJvd24gaW5zdGFuY2VvZiBFcnJvcikge1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIGdldCB0aGUgbGF0ZXN0IHJlbGVhc2U6ICR7dGhyb3duLm1lc3NhZ2V9YClcblx0XHRcdH1cblx0XHRcdHJldHVyblxuXHRcdH1cblx0fVxuXG5cdHB1YmxpYyBzdG9wQWxsU2VydmljZXMoKTogRnV0dXJlPHVua25vd24+IHtcblx0XHR0aGlzLmxvZ2dlci5pbmZvKGBTdG9wcGluZyBhbGwgc2VydmljZXMuLi4gYXV0by1yZXNwYXduIGRpc2FibGVkLmApXG5cdFx0dGhpcy5hdXRvUmVzcGF3bkRlYWRTZXJ2aWNlcyA9IGZhbHNlXG5cdFx0Zm9yIChjb25zdCBbc2VydmljZU5hbWVdIG9mIHRvRW50cmllcyh0aGlzLnNlcnZpY2VzKSkge1xuXHRcdFx0dGhpcy5zdG9wU2VydmljZShzZXJ2aWNlTmFtZSlcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuZGVhZFxuXHR9XG5cblx0cHVibGljIHN0b3BTZXJ2aWNlKHNlcnZpY2VOYW1lOiBTKTogdm9pZCB7XG5cdFx0Y29uc3Qgc2VydmljZSA9IHRoaXMuc2VydmljZXNbc2VydmljZU5hbWVdXG5cdFx0aWYgKHNlcnZpY2UpIHtcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYFN0b3BwaW5nIHNlcnZpY2UgXCIke3NlcnZpY2VOYW1lfVwiLi4uYClcblx0XHRcdHRoaXMuc2VydmljZXNEZWFkW3RoaXMuc2VydmljZUlkeFtzZXJ2aWNlTmFtZV1dLnVzZShcblx0XHRcdFx0bmV3IFByb21pc2UoKHBhc3MpID0+IHtcblx0XHRcdFx0XHRzZXJ2aWNlLmVtaXQoYHRpbWVUb1N0b3BgKVxuXHRcdFx0XHRcdHNlcnZpY2UucHJvY2Vzcy5vbmNlKGBjbG9zZWAsIChleGl0Q29kZSkgPT4ge1xuXHRcdFx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhcblx0XHRcdFx0XHRcdFx0YFN0b3BwZWQgc2VydmljZSBcIiR7c2VydmljZU5hbWV9XCI7IGV4aXRlZCB3aXRoIGNvZGUgJHtleGl0Q29kZX1gLFxuXHRcdFx0XHRcdFx0KVxuXHRcdFx0XHRcdFx0dGhpcy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0gPSBudWxsXG5cdFx0XHRcdFx0XHRwYXNzKClcblx0XHRcdFx0XHR9KVxuXHRcdFx0XHR9KSxcblx0XHRcdClcblx0XHRcdHRoaXMuZGVhZC51c2UoUHJvbWlzZS5hbGwodGhpcy5zZXJ2aWNlc0RlYWQpKVxuXHRcdFx0dGhpcy5zZXJ2aWNlc0xpdmVbdGhpcy5zZXJ2aWNlSWR4W3NlcnZpY2VOYW1lXV0gPSBuZXcgRnV0dXJlKCgpID0+IHt9KVxuXHRcdFx0aWYgKHRoaXMubGl2ZS5kb25lKSB7XG5cdFx0XHRcdHRoaXMubGl2ZSA9IG5ldyBGdXR1cmUoKCkgPT4ge30pXG5cdFx0XHR9XG5cdFx0XHR0aGlzLmxpdmUudXNlKFByb21pc2UuYWxsKHRoaXMuc2VydmljZXNMaXZlKSlcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zZXJ2aWNlTG9nZ2Vyc1tzZXJ2aWNlTmFtZV0uZXJyb3IoXG5cdFx0XHRcdGBUcmllZCB0byBzdG9wIHNlcnZpY2UsIGJ1dCBpdCB3YXNuJ3QgcnVubmluZy5gLFxuXHRcdFx0KVxuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgY29uc3QgRkxJR0hUREVDS19JTkZPID0gYGluZm9gXG5leHBvcnQgY29uc3QgRkxJR0hUREVDS19XQVJOID0gYHdhcm5gXG5leHBvcnQgY29uc3QgRkxJR0hUREVDS19FUlJPUiA9IGBFUlIhYFxuXG5leHBvcnQgY29uc3QgZmxpZ2h0RGVja0xvZ1NjaGVtYSA9IHoub2JqZWN0KHtcblx0bGV2ZWw6IHoudW5pb24oW1xuXHRcdHoubGl0ZXJhbChGTElHSFRERUNLX0lORk8pLFxuXHRcdHoubGl0ZXJhbChGTElHSFRERUNLX1dBUk4pLFxuXHRcdHoubGl0ZXJhbChGTElHSFRERUNLX0VSUk9SKSxcblx0XSksXG5cdHRpbWVzdGFtcDogei5udW1iZXIoKSxcblx0cGFja2FnZTogei5zdHJpbmcoKSxcblx0c2VydmljZTogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuXHRwcm9jZXNzOiB6Lm51bWJlcigpLFxuXHRib2R5OiB6LnN0cmluZygpLFxufSlcbmV4cG9ydCB0eXBlIEZsaWdodERlY2tMb2cgPSB6LmluZmVyPHR5cGVvZiBmbGlnaHREZWNrTG9nU2NoZW1hPlxuXG5jb25zdCBMSU5FX0ZPUk1BVCA9IGBsaW5lLWZvcm1hdGAgc2F0aXNmaWVzIGtleW9mIExuYXZGb3JtYXRcbmNvbnN0IFZBTFVFID0gYHZhbHVlYCBzYXRpc2ZpZXMga2V5b2YgTG5hdkZvcm1hdFxuXG5leHBvcnQgdHlwZSBMbmF2Rm9ybWF0VmlzdWFsQ29tcG9uZW50ID0gRXhjbHVkZTxcblx0RXhjbHVkZTxMbmF2Rm9ybWF0W2BsaW5lLWZvcm1hdGBdLCB1bmRlZmluZWQ+W251bWJlcl0sXG5cdHN0cmluZ1xuPlxuXG5leHBvcnQgdHlwZSBMbmF2Rm9ybWF0QnJlYWtkb3duID0gRXhjbHVkZTxMbmF2Rm9ybWF0W2B2YWx1ZWBdLCB1bmRlZmluZWQ+XG5leHBvcnQgdHlwZSBNZW1iZXJPZjxUPiA9IFRba2V5b2YgVF1cbmV4cG9ydCB0eXBlIExuYXZGb3JtYXRWYWx1ZURlZmluaXRpb24gPSBNZW1iZXJPZjxMbmF2Rm9ybWF0QnJlYWtkb3duPlxuXG5leHBvcnQgdHlwZSBGbGlnaHREZWNrRm9ybWF0ID0ge1xuXHRbTElORV9GT1JNQVRdOiAoXG5cdFx0fCBzdHJpbmdcblx0XHR8IChMbmF2Rm9ybWF0VmlzdWFsQ29tcG9uZW50ICYge1xuXHRcdFx0XHRmaWVsZDoga2V5b2YgRmxpZ2h0RGVja0xvZyB8IGBfX2xldmVsX19gIHwgYF9fdGltZXN0YW1wX19gXG5cdFx0ICB9KVxuXHQpW11cblx0W1ZBTFVFXToge1xuXHRcdFtLIGluIGtleW9mIEZsaWdodERlY2tMb2ddOiBMbmF2Rm9ybWF0VmFsdWVEZWZpbml0aW9uICYge1xuXHRcdFx0a2luZDogRmxpZ2h0RGVja0xvZ1tLXSBleHRlbmRzIG51bWJlciB8IHVuZGVmaW5lZFxuXHRcdFx0XHQ/IGBpbnRlZ2VyYFxuXHRcdFx0XHQ6IEZsaWdodERlY2tMb2dbS10gZXh0ZW5kcyBzdHJpbmcgfCB1bmRlZmluZWRcblx0XHRcdFx0XHQ/IGBzdHJpbmdgXG5cdFx0XHRcdFx0OiBuZXZlclxuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgY29uc3QgRkxJR0hUREVDS19MTkFWX0ZPUk1BVCA9IHtcblx0dGl0bGU6IGBGbGlnaHREZWNrIExvZ2AsXG5cdGRlc2NyaXB0aW9uOiBgRm9ybWF0IGZvciBldmVudHMgbG9nZ2VkIGJ5IHRoZSBGbGlnaHREZWNrIHByb2Nlc3MgbWFuYWdlci5gLFxuXHRcImZpbGUtdHlwZVwiOiBganNvbmAsXG5cdFwidGltZXN0YW1wLWZpZWxkXCI6IGB0aW1lc3RhbXBgLFxuXHRcInRpbWVzdGFtcC1kaXZpc29yXCI6IDEwMDAsXG5cdFwibW9kdWxlLWZpZWxkXCI6IGBwYWNrYWdlYCxcblx0XCJvcGlkLWZpZWxkXCI6IGBzZXJ2aWNlYCxcblx0XCJsZXZlbC1maWVsZFwiOiBgbGV2ZWxgLFxuXHRsZXZlbDoge1xuXHRcdGluZm86IEZMSUdIVERFQ0tfSU5GTyxcblx0XHR3YXJuaW5nOiBGTElHSFRERUNLX1dBUk4sXG5cdFx0ZXJyb3I6IEZMSUdIVERFQ0tfRVJST1IsXG5cdH0sXG5cblx0W0xJTkVfRk9STUFUXTogW1xuXHRcdHtcblx0XHRcdGZpZWxkOiBgbGV2ZWxgLFxuXHRcdH0sXG5cdFx0e1xuXHRcdFx0cHJlZml4OiBgIGAsXG5cdFx0XHRmaWVsZDogYF9fdGltZXN0YW1wX19gLFxuXHRcdFx0XCJ0aW1lc3RhbXAtZm9ybWF0XCI6IGAlWS0lbS0lZFQlSDolTTolUy4lTCVaYCxcblx0XHR9LFxuXHRcdHtcblx0XHRcdHByZWZpeDogYCBgLFxuXHRcdFx0ZmllbGQ6IGBwcm9jZXNzYCxcblx0XHRcdFwibWluLXdpZHRoXCI6IDUsXG5cdFx0fSxcblx0XHR7XG5cdFx0XHRwcmVmaXg6IGA6YCxcblx0XHRcdGZpZWxkOiBgcGFja2FnZWAsXG5cdFx0fSxcblx0XHR7XG5cdFx0XHRwcmVmaXg6IGA6YCxcblx0XHRcdGZpZWxkOiBgc2VydmljZWAsXG5cdFx0XHRcImRlZmF1bHQtdmFsdWVcIjogYGAsXG5cdFx0fSxcblx0XHR7XG5cdFx0XHRwcmVmaXg6IGA6IGAsXG5cdFx0XHRmaWVsZDogYGJvZHlgLFxuXHRcdH0sXG5cdF0sXG5cblx0W1ZBTFVFXToge1xuXHRcdHRpbWVzdGFtcDoge1xuXHRcdFx0a2luZDogYGludGVnZXJgLFxuXHRcdH0sXG5cdFx0bGV2ZWw6IHtcblx0XHRcdGtpbmQ6IGBzdHJpbmdgLFxuXHRcdH0sXG5cdFx0cGFja2FnZToge1xuXHRcdFx0a2luZDogYHN0cmluZ2AsXG5cdFx0fSxcblx0XHRzZXJ2aWNlOiB7XG5cdFx0XHRraW5kOiBgc3RyaW5nYCxcblx0XHR9LFxuXHRcdHByb2Nlc3M6IHtcblx0XHRcdGtpbmQ6IGBpbnRlZ2VyYCxcblx0XHR9LFxuXHRcdGJvZHk6IHtcblx0XHRcdGtpbmQ6IGBzdHJpbmdgLFxuXHRcdH0sXG5cdH0sXG59IGFzIGNvbnN0IHNhdGlzZmllcyBGbGlnaHREZWNrRm9ybWF0ICYgTG5hdkZvcm1hdFxuXG5leHBvcnQgY2xhc3MgRmxpZ2h0RGVja0xvZ2dlclxuXHRpbXBsZW1lbnRzIFBpY2s8Q29uc29sZSwgYGVycm9yYCB8IGBpbmZvYCB8IGB3YXJuYD5cbntcblx0cHVibGljIHJlYWRvbmx5IHBhY2thZ2VOYW1lOiBzdHJpbmdcblx0cHVibGljIHJlYWRvbmx5IHNlcnZpY2VOYW1lPzogc3RyaW5nXG5cdHB1YmxpYyByZWFkb25seSBqc29uTG9nZ2luZzogYm9vbGVhblxuXHRwdWJsaWMgcHJvY2Vzc0NvZGU6IG51bWJlclxuXHRwdWJsaWMgY29uc3RydWN0b3IoXG5cdFx0cGFja2FnZU5hbWU6IHN0cmluZyxcblx0XHRwcm9jZXNzQ29kZTogbnVtYmVyLFxuXHRcdHNlcnZpY2VOYW1lPzogc3RyaW5nLFxuXHRcdG9wdGlvbnM/OiB7IGpzb25Mb2dnaW5nOiBib29sZWFuIH0sXG5cdCkge1xuXHRcdHRoaXMucGFja2FnZU5hbWUgPSBwYWNrYWdlTmFtZVxuXHRcdGlmIChzZXJ2aWNlTmFtZSkge1xuXHRcdFx0dGhpcy5zZXJ2aWNlTmFtZSA9IHNlcnZpY2VOYW1lXG5cdFx0fVxuXHRcdHRoaXMucHJvY2Vzc0NvZGUgPSBwcm9jZXNzQ29kZVxuXHRcdHRoaXMuanNvbkxvZ2dpbmcgPSBvcHRpb25zPy5qc29uTG9nZ2luZyA/PyBmYWxzZVxuXHR9XG5cdHByb3RlY3RlZCBsb2coXG5cdFx0bGV2ZWw6XG5cdFx0XHR8IHR5cGVvZiBGTElHSFRERUNLX0VSUk9SXG5cdFx0XHR8IHR5cGVvZiBGTElHSFRERUNLX0lORk9cblx0XHRcdHwgdHlwZW9mIEZMSUdIVERFQ0tfV0FSTixcblx0XHQuLi5tZXNzYWdlczogdW5rbm93bltdXG5cdCk6IHZvaWQge1xuXHRcdGlmICh0aGlzLmpzb25Mb2dnaW5nKSB7XG5cdFx0XHRsZXQgYm9keSA9IG1lc3NhZ2VzXG5cdFx0XHRcdC5tYXAoKG1lc3NhZ2UpID0+XG5cdFx0XHRcdFx0dHlwZW9mIG1lc3NhZ2UgPT09IGBzdHJpbmdgXG5cdFx0XHRcdFx0XHQ/IG1lc3NhZ2Vcblx0XHRcdFx0XHRcdDogaW5zcGVjdChtZXNzYWdlLCBmYWxzZSwgbnVsbCwgdHJ1ZSksXG5cdFx0XHRcdClcblx0XHRcdFx0LmpvaW4oYCBgKVxuXHRcdFx0aWYgKGJvZHkuaW5jbHVkZXMoYFxcbmApKSB7XG5cdFx0XHRcdGJvZHkgPSBgXFxuICAke2JvZHkuc3BsaXQoYFxcbmApLmpvaW4oYFxcbiAgYCl9YFxuXHRcdFx0fVxuXHRcdFx0Y29uc3QgbG9nOiBGbGlnaHREZWNrTG9nID0ge1xuXHRcdFx0XHR0aW1lc3RhbXA6IERhdGUubm93KCksXG5cdFx0XHRcdGxldmVsLFxuXHRcdFx0XHRwcm9jZXNzOiB0aGlzLnByb2Nlc3NDb2RlLFxuXHRcdFx0XHRwYWNrYWdlOiB0aGlzLnBhY2thZ2VOYW1lLFxuXHRcdFx0XHRib2R5LFxuXHRcdFx0fVxuXHRcdFx0aWYgKHRoaXMuc2VydmljZU5hbWUpIHtcblx0XHRcdFx0bG9nLnNlcnZpY2UgPSB0aGlzLnNlcnZpY2VOYW1lXG5cdFx0XHR9XG5cdFx0XHRwcm9jZXNzLnN0ZG91dC53cml0ZShKU09OLnN0cmluZ2lmeShsb2cpICsgYFxcbmApXG5cdFx0fSBlbHNlIHtcblx0XHRcdGNvbnN0IHNvdXJjZSA9IHRoaXMuc2VydmljZU5hbWVcblx0XHRcdFx0PyBgJHt0aGlzLnBhY2thZ2VOYW1lfToke3RoaXMuc2VydmljZU5hbWV9YFxuXHRcdFx0XHQ6IHRoaXMucGFja2FnZU5hbWVcblx0XHRcdHN3aXRjaCAobGV2ZWwpIHtcblx0XHRcdFx0Y2FzZSBGTElHSFRERUNLX0lORk86XG5cdFx0XHRcdFx0Y29uc29sZS5sb2coYCR7c291cmNlfTpgLCAuLi5tZXNzYWdlcylcblx0XHRcdFx0XHRicmVha1xuXHRcdFx0XHRjYXNlIEZMSUdIVERFQ0tfV0FSTjpcblx0XHRcdFx0XHRjb25zb2xlLndhcm4oYCR7c291cmNlfTpgLCAuLi5tZXNzYWdlcylcblx0XHRcdFx0XHRicmVha1xuXHRcdFx0XHRjYXNlIEZMSUdIVERFQ0tfRVJST1I6XG5cdFx0XHRcdFx0Y29uc29sZS5lcnJvcihgJHtzb3VyY2V9OmAsIC4uLm1lc3NhZ2VzKVxuXHRcdFx0XHRcdGJyZWFrXG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdHB1YmxpYyBpbmZvKC4uLm1lc3NhZ2VzOiB1bmtub3duW10pOiB2b2lkIHtcblx0XHR0aGlzLmxvZyhGTElHSFRERUNLX0lORk8sIC4uLm1lc3NhZ2VzKVxuXHR9XG5cblx0cHVibGljIHdhcm4oLi4ubWVzc2FnZXM6IHVua25vd25bXSk6IHZvaWQge1xuXHRcdHRoaXMubG9nKEZMSUdIVERFQ0tfV0FSTiwgLi4ubWVzc2FnZXMpXG5cdH1cblxuXHRwdWJsaWMgZXJyb3IoLi4ubWVzc2FnZXM6IHVua25vd25bXSk6IHZvaWQge1xuXHRcdHRoaXMubG9nKEZMSUdIVERFQ0tfRVJST1IsIC4uLm1lc3NhZ2VzKVxuXHR9XG59XG4iLAogICAgImltcG9ydCB7IGNyZWF0ZUVudiB9IGZyb20gXCJAdDMtb3NzL2Vudi1jb3JlXCJcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCJcblxuZXhwb3J0IGNvbnN0IGVudiA9IGNyZWF0ZUVudih7XG5cdHNlcnZlcjogeyBGTElHSFRERUNLX1NFQ1JFVDogei5zdHJpbmcoKS5vcHRpb25hbCgpIH0sXG5cdGNsaWVudFByZWZpeDogYE5FVkVSYCxcblx0Y2xpZW50OiB7fSxcblx0cnVudGltZUVudjogaW1wb3J0Lm1ldGEuZW52LFxuXHRlbXB0eVN0cmluZ0FzVW5kZWZpbmVkOiB0cnVlLFxufSlcbiIKICBdLAogICJtYXBwaW5n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T0FBTyxFQUFHLFFBQVMsRUFBRSxRQUFRLENBQUUsQ0FBQyxDQUFDLEVBQ3RFLGtCQUFtQixFQUFFLE9BQU8sRUFDNUIsUUFBUyxFQUFFLE9BQU8sQ0FDakIsU0FBVSxFQUFFLE9BQU8sRUFDbkIsUUFBUyxFQUFFLE9BQU8sRUFDbEIsa0JBQW1CLEVBQUUsT0FBTyxDQUM3QixDQUFDLEVBQ0QsWUFBYSxFQUFFLFFBQVEsRUFBRSxTQUFTLENBQ25DLENBQUMsRUFDRCxRQUFTLENBQ1IsS0FBTSxDQUNMLEtBQU0sSUFDTixTQUFVLEdBQ1YsWUFBYSx3Q0FDYixRQUFTLGNBQ1QsTUFBTyxDQUNSLEVBQ0EsWUFBYSxDQUNaLEtBQU0sSUFDTixTQUFVLEdBQ1YsWUFBYSx1QkFDYixRQUFTLHdCQUNWLEVBQ0EsU0FBVSxDQUNULEtBQU0sSUFDTixTQUFVLEdBQ1YsWUFBYSx1Q0FDYixRQUFTLDhJQUNULE1BQU8sS0FBSyxLQUNiLEVBQ0Esa0JBQW1CLENBQ2xCLEtBQU0sSUFDTixTQUFVLEdBQ1YsWUFBYSx5Q0FDYixRQUFTLDZEQUNWLEVBQ0EsUUFBUyxDQUNSLEtBQU0sSUFDTixTQUFVLEdBQ1YsWUFBYSx5QkFDYixRQUFTLDJFQUNULE1BQU8sS0FBSyxLQUNiLEVBQ0EsWUFBYSxDQUNaLEtBQU0sSUFDTixTQUFVLEdBQ1YsWUFBYSx1QkFDYixRQUFTLGdCQUNULE1BQU8sQ0FDUixDQUNELENBQ0QsRUFFTSxFQUFnQixDQUNyQixjQUFlLEVBQUUsT0FBTyxDQUN2QixPQUFRLEVBQUUsT0FBTyxFQUFFLFNBQVMsQ0FDN0IsQ0FBQyxFQUNELFFBQVMsQ0FDUixPQUFRLENBQ1AsS0FBTSxJQUNOLFNBQVUsR0FDVixZQUFhLG9DQUNiLFFBQVMsaUJBQ1YsQ0FDRCxDQUNELEVBRU0sRUFBUSxFQUNiLENBQ0MsUUFBUyxhQUNULE9BQVEsRUFBUyxDQUFFLE9BQVEsS0FBTSxZQUFhLElBQUssQ0FBQyxFQUNwRCxhQUFjLENBQ2IsR0FBSSxFQUNKLFlBQWEsRUFDYixPQUFRLENBQ1QsRUFDQSxZQUFhLEdBQ2IsbUJBQW9CLENBQUMsSUFBUyxDQUM3QixHQUFJLEVBQUssS0FBTyxTQUNmLE9BSUQsT0FEQyxFQUFLLElBQVcsT0FBSyxRQUFRLElBQUksRUFBRyx3QkFBd0IsRUFHL0QsRUFDQSxPQUNELEdBRVEsU0FBUSxtQkFBb0IsRUFBTSxRQUFRLElBQUksRUFFdEQsT0FBUSxFQUFPLFVBQ1QsU0FDSixDQUNDLElBQVEsVUFBVyxFQUFPLEtBQzFCLEVBQWdCLEdBQVUsR0FBRyxDQUM5QixDQUNBLGNBQ1EsQ0FDUixJQUFNLEVBQWEsSUFBSSxFQUFXLEVBQU8sSUFBSSxFQUM3QyxRQUFRLEdBQUcsUUFBUyxTQUFZLENBQy9CLE1BQU0sRUFBVyxnQkFBZ0IsRUFDakMsQ0FDRiIsCiAgImRlYnVnSWQiOiAiNjQ2N0RCQUJGQkQ1NkZBRTY0NzU2RTIxNjQ3NTZFMjEiLAogICJuYW1lcyI6IFtdCn0=
package/dist/lib.d.ts CHANGED
@@ -2,22 +2,9 @@ import { Server } from 'node:http';
2
2
  import { Future } from 'atom.io/internal';
3
3
  import { ChildSocket } from 'atom.io/realtime-server';
4
4
  import { CronJob } from 'cron';
5
+ import { FilesystemStorage } from 'safedeposit';
5
6
  import { z } from 'zod';
6
7
 
7
- type FilesystemStorageOptions = {
8
- path: string;
9
- };
10
- declare class FilesystemStorage<T extends Record<string, string> = Record<string, string>> implements Storage {
11
- rootDir: string;
12
- constructor(options: FilesystemStorageOptions);
13
- getItem<K extends string & keyof T>(key: K): T[K] | null;
14
- setItem<K extends string & keyof T>(key: K, value: T[K]): void;
15
- removeItem<K extends string & keyof T>(key: K): void;
16
- key(index: number): (string & keyof T) | null;
17
- clear(): void;
18
- get length(): number;
19
- }
20
-
21
8
  declare const lnavFormatSchema: z.ZodObject<{
22
9
  regex: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodObject<{
23
10
  pattern: z.ZodOptional<z.ZodString>;
@@ -1032,4 +1019,4 @@ declare namespace klaxon_lib {
1032
1019
  export { type klaxon_lib_AlertOptions as AlertOptions, type klaxon_lib_ChangesetsPublishResult as ChangesetsPublishResult, type klaxon_lib_ChangesetsPublishedPackage as ChangesetsPublishedPackage, type klaxon_lib_PackageConfig as PackageConfig, type klaxon_lib_ScrambleOptions as ScrambleOptions, type klaxon_lib_ScrambleResult as ScrambleResult, type klaxon_lib_SecretsConfig as SecretsConfig, klaxon_lib_alert as alert, klaxon_lib_scramble as scramble };
1033
1020
  }
1034
1021
 
1035
- export { FLIGHTDECK_ERROR, FLIGHTDECK_INFO, FLIGHTDECK_LNAV_FORMAT, FLIGHTDECK_SETUP_PHASES, FLIGHTDECK_UPDATE_PHASES, FLIGHTDECK_WARN, FilesystemStorage, type FilesystemStorageOptions, FlightDeck, type FlightDeckFormat, type FlightDeckLog, FlightDeckLogger, type FlightDeckOptions, type FlightDeckSetupPhase, type FlightDeckUpdatePhase, klaxon_lib as Klaxon, type LnavFormatBreakdown, type LnavFormatValueDefinition, type LnavFormatVisualComponent, type MemberOf, flightDeckLogSchema, isVersionNumber };
1022
+ export { FLIGHTDECK_ERROR, FLIGHTDECK_INFO, FLIGHTDECK_LNAV_FORMAT, FLIGHTDECK_SETUP_PHASES, FLIGHTDECK_UPDATE_PHASES, FLIGHTDECK_WARN, FlightDeck, type FlightDeckFormat, type FlightDeckLog, FlightDeckLogger, type FlightDeckOptions, type FlightDeckSetupPhase, type FlightDeckUpdatePhase, klaxon_lib as Klaxon, type LnavFormatBreakdown, type LnavFormatValueDefinition, type LnavFormatVisualComponent, type MemberOf, flightDeckLogSchema, isVersionNumber };
package/dist/lib.js CHANGED
@@ -1,9 +1,9 @@
1
- var U=Object.defineProperty;var $=(e,t)=>{for(var i in t)U(e,i,{get:t[i],enumerable:!0,configurable:!0,set:(r)=>t[i]=()=>r})};import{existsSync as S,mkdirSync as T,readdirSync as x,readFileSync as K,rmSync as E,statSync as P,writeFileSync as H}from"node:fs";import{resolve as w}from"node:path";class b{rootDir;constructor(e){if(this.rootDir=e.path,!S(this.rootDir))T(this.rootDir,{recursive:!0})}getItem(e){let t=w(this.rootDir,e);if(S(t))return K(t,"utf-8");return null}setItem(e,t){let i=w(this.rootDir,e);H(i,t)}removeItem(e){let t=w(this.rootDir,e);if(S(t))E(t)}key(e){return x(this.rootDir).sort((r,n)=>{let a=P(r);return P(n).ctimeMs-a.ctimeMs})[e]??null}clear(){E(this.rootDir,{recursive:!0}),T(this.rootDir,{recursive:!0})}get length(){return x(this.rootDir).length}}import{execSync as F,spawn as G}from"node:child_process";import{createServer as V}from"node:http";import{homedir as B}from"node:os";import{resolve as I}from"node:path";import{inspect as M}from"node:util";import{Future as p}from"atom.io/internal";import{discoverType as N}from"atom.io/introspection";import{fromEntries as v,toEntries as u}from"atom.io/json";import{ChildSocket as z}from"atom.io/realtime-server";import{CronJob as J}from"cron";import{z as c}from"zod";import{createEnv as O}from"@t3-oss/env-core";import{z as j}from"zod";var A=O({server:{FLIGHTDECK_SECRET:j.string().optional()},clientPrefix:"NEVER",client:{},runtimeEnv:import.meta.env,emptyStringAsUndefined:!0});var ke=["downloaded","installed"],Se=["notified","confirmed"];function W(e){return/^\d+\.\d+\.\d+$/.test(e)||!Number.isNaN(Number.parseFloat(e))}class Y{options;safety=0;storage;webhookServer;services;serviceIdx;defaultServicesReadyToUpdate;servicesReadyToUpdate;autoRespawnDeadServices;logger;serviceLoggers;updateAvailabilityChecker=null;servicesLive;servicesDead;live=new p(()=>{});dead=new p(()=>{});restartTimes=[];constructor(e){this.options=e;let{FLIGHTDECK_SECRET:t}=A,{flightdeckRootDir:i=I(B(),".flightdeck")}=e,r=e.port??8080,n=`http://localhost:${r}`,a=u(e.services);if(this.services=v(a.map(([s])=>[s,null])),this.serviceIdx=v(a.map(([s],o)=>[s,o])),this.defaultServicesReadyToUpdate=v(a.map(([s,{waitFor:o}])=>[s,!o])),this.servicesReadyToUpdate={...this.defaultServicesReadyToUpdate},this.autoRespawnDeadServices=!0,this.logger=new D(this.options.packageName,process.pid,void 0,{jsonLogging:this.options.jsonLogging??!1}),this.serviceLoggers=v(a.map(([s])=>[s,new D(this.options.packageName,process.pid,s,{jsonLogging:this.options.jsonLogging??!1})])),this.servicesLive=a.map(()=>new p(()=>{})),this.servicesDead=a.map(()=>new p(()=>{})),this.live.use(Promise.all(this.servicesLive)),this.dead.use(Promise.all(this.servicesDead)),this.storage=new b({path:I(i,"storage",e.packageName)}),t===void 0)this.logger.warn("No FLIGHTDECK_SECRET environment variable found. FlightDeck will not run an update server.");else V((s,o)=>{let h=[];s.on("data",(l)=>{h.push(l instanceof Buffer?l:Buffer.from(l))}).on("end",()=>{let l=s.headers.authorization;try{if(typeof s.url==="undefined")throw 400;let d=`Bearer ${t}`;if(l!==`Bearer ${t}`)throw this.logger.info(`Unauthorized: needed \`${d}\`, got \`${l}\``),401;let f=new URL(s.url,n);this.logger.info(s.method,f.pathname);let g=Buffer.concat(h).toString();if(!W(g))throw 400;o.writeHead(200),o.end(),this.storage.setItem("updatePhase","notified"),this.storage.setItem("updateAwaitedVersion",g);let{checkAvailability:_}=e.scripts;if(_){this.updateAvailabilityChecker?.stop(),this.seekUpdate(g);let L=this.storage.getItem("updatePhase");if(this.logger.info('> storage("updatePhase") >',L),L==="notified")this.updateAvailabilityChecker=new J("30 * * * * *",()=>{this.seekUpdate(g)}),this.updateAvailabilityChecker.start()}else this.downloadPackage()}catch(d){if(this.logger.error(d,s.url),typeof d==="number")o.writeHead(d),o.end()}finally{h=[]}})}).listen(r,()=>{this.logger.info(`Server started on port ${r}`)});this.startAllServices().then(()=>{this.logger.info("All services started.")}).catch((s)=>{if(s instanceof Error)this.logger.error("Failed to start all services:",s.message)})}seekUpdate(e){this.logger.info("Checking for updates...");let{checkAvailability:t}=this.options.scripts;if(!t){this.logger.info("No checkAvailability script found.");return}try{let i=F(`${t} ${e}`);this.logger.info("Check stdout:",i.toString()),this.updateAvailabilityChecker?.stop(),this.storage.setItem("updatePhase","confirmed"),this.downloadPackage(),this.announceUpdate()}catch(i){if(i instanceof Error)this.logger.error("Check failed:",i.message);else{let r=N(i);this.logger.error("Check threw",r,i)}}}announceUpdate(){for(let e of u(this.services)){let[t,i]=e;if(i){if(this.options.services[t].waitFor)i.emit("updatesReady")}else this.startService(t)}}tryUpdate(){if(u(this.servicesReadyToUpdate).every(([,e])=>e))this.logger.info("All services are ready to update."),this.stopAllServices().then(()=>{this.logger.info("All services stopped; starting up fresh..."),this.startAllServices().then(()=>{this.logger.info("All services started; we're back online.")}).catch((e)=>{if(e instanceof Error)this.logger.error("Failed to start all services:",e.message)})}).catch((e)=>{if(e instanceof Error)this.logger.error("Failed to stop all services:",e.message)})}startAllServices(){this.logger.info("Starting all services..."),this.autoRespawnDeadServices=!0;let e=this.storage.getItem("setupPhase");switch(this.logger.info('> storage("setupPhase") >',e),e){case null:return this.logger.info("Starting from scratch."),this.downloadPackage(),this.installPackage(),this.startAllServices();case"downloaded":return this.logger.info("Found package downloaded but not installed."),this.installPackage(),this.startAllServices();case"installed":{for(let[t]of u(this.services))this.startService(t);return this.live}}}startService(e){if(this.logger.info(`Starting service ${this.options.packageName}::${e}, try ${this.safety}/2...`),this.safety>=2)throw new Error("Out of tries...");this.safety++;let[t,...i]=this.options.services[e].run.split(" "),r=G(t,i,{cwd:this.options.flightdeckRootDir,env:import.meta.env}),n=this.serviceLoggers[e],a=this.services[e]=new z(r,`${this.options.packageName}::${e}`,n);n.processCode=a.process.pid??-1,this.services[e].onAny((...s)=>{n.info("\uD83D\uDCAC",...s)}),this.services[e].on("readyToUpdate",()=>{this.logger.info(`Service "${e}" is ready to update.`),this.servicesReadyToUpdate[e]=!0,this.tryUpdate()}),this.services[e].on("alive",()=>{if(this.servicesLive[this.serviceIdx[e]].use(Promise.resolve()),this.servicesDead[this.serviceIdx[e]]=new p(()=>{}),this.dead.done)this.dead=new p(()=>{});this.dead.use(Promise.all(this.servicesDead))}),this.services[e].process.once("close",(s)=>{if(this.logger.info(`Auto-respawn saw "${e}" exit with code ${s}`),this.services[e]=null,!this.autoRespawnDeadServices){this.logger.info(`Auto-respawn is off; "${e}" rests.`);return}let o=this.storage.getItem("updatePhase");if(this.logger.info('> storage("updatePhase") >',o),o==="confirmed")this.serviceLoggers[e].info("Updating before startup..."),this.restartTimes=[],this.installPackage(),this.startService(e);else{let l=Date.now(),d=l-300000;if(this.restartTimes=this.restartTimes.filter((f)=>f>d),this.restartTimes.push(l),this.restartTimes.length<5)this.serviceLoggers[e].info("Crashed. Restarting..."),this.startService(e);else this.serviceLoggers[e].info("Crashed 5 times in 5 minutes. Not restarting.")}}),this.safety=0}downloadPackage(){this.logger.info("Downloading...");try{let e=F(this.options.scripts.download);this.logger.info("Download stdout:",e.toString()),this.storage.setItem("setupPhase","downloaded"),this.logger.info("Downloaded!")}catch(e){if(e instanceof Error)this.logger.error(`Failed to get the latest release: ${e.message}`);return}}installPackage(){this.logger.info("Installing...");try{let e=F(this.options.scripts.install);this.logger.info("Install stdout:",e.toString()),this.storage.setItem("setupPhase","installed"),this.logger.info("Installed!")}catch(e){if(e instanceof Error)this.logger.error(`Failed to get the latest release: ${e.message}`);return}}stopAllServices(){this.logger.info("Stopping all services... auto-respawn disabled."),this.autoRespawnDeadServices=!1;for(let[e]of u(this.services))this.stopService(e);return this.dead}stopService(e){let t=this.services[e];if(t){if(this.logger.info(`Stopping service "${e}"...`),this.servicesDead[this.serviceIdx[e]].use(new Promise((i)=>{t.emit("timeToStop"),t.process.once("close",(r)=>{this.logger.info(`Stopped service "${e}"; exited with code ${r}`),this.services[e]=null,i()})})),this.dead.use(Promise.all(this.servicesDead)),this.servicesLive[this.serviceIdx[e]]=new p(()=>{}),this.live.done)this.live=new p(()=>{});this.live.use(Promise.all(this.servicesLive))}else this.serviceLoggers[e].error("Tried to stop service, but it wasn't running.")}}var m="info",y="warn",k="ERR!",we=c.object({level:c.union([c.literal(m),c.literal(y),c.literal(k)]),timestamp:c.number(),package:c.string(),service:c.string().optional(),process:c.number(),body:c.string()}),Z="line-format",Q="value",be={title:"FlightDeck Log",description:"Format for events logged by the FlightDeck process manager.","file-type":"json","timestamp-field":"timestamp","timestamp-divisor":1000,"module-field":"package","opid-field":"service","level-field":"level",level:{info:m,warning:y,error:k},[Z]:[{field:"level"},{prefix:" ",field:"__timestamp__","timestamp-format":"%Y-%m-%dT%H:%M:%S.%L%Z"},{prefix:" ",field:"process","min-width":5},{prefix:":",field:"package"},{prefix:":",field:"service","default-value":""},{prefix:": ",field:"body"}],[Q]:{timestamp:{kind:"integer"},level:{kind:"string"},package:{kind:"string"},service:{kind:"string"},process:{kind:"integer"},body:{kind:"string"}}};class D{packageName;serviceName;jsonLogging;processCode;constructor(e,t,i,r){if(this.packageName=e,i)this.serviceName=i;this.processCode=t,this.jsonLogging=r?.jsonLogging??!1}log(e,...t){if(this.jsonLogging){let i=t.map((n)=>typeof n==="string"?n:M(n,!1,null,!0)).join(" ");if(i.includes(`
2
- `))i=`
3
- ${i.split(`
1
+ var x=Object.defineProperty;var A=(e,i)=>{for(var t in i)x(e,t,{get:i[t],enumerable:!0,configurable:!0,set:(o)=>i[t]=()=>o})};import{execSync as w,spawn as C}from"node:child_process";import{createServer as _}from"node:http";import{homedir as R}from"node:os";import{resolve as b}from"node:path";import{inspect as U}from"node:util";import{Future as p}from"atom.io/internal";import{discoverType as $}from"atom.io/introspection";import{fromEntries as v,toEntries as u}from"atom.io/json";import{ChildSocket as H}from"atom.io/realtime-server";import{CronJob as K}from"cron";import{FilesystemStorage as j}from"safedeposit";import{z as l}from"zod";import{createEnv as P}from"@t3-oss/env-core";import{z as I}from"zod";var L=P({server:{FLIGHTDECK_SECRET:I.string().optional()},clientPrefix:"NEVER",client:{},runtimeEnv:import.meta.env,emptyStringAsUndefined:!0});var le=["downloaded","installed"],ce=["notified","confirmed"];function G(e){return/^\d+\.\d+\.\d+$/.test(e)||!Number.isNaN(Number.parseFloat(e))}class O{options;safety=0;storage;webhookServer;services;serviceIdx;defaultServicesReadyToUpdate;servicesReadyToUpdate;autoRespawnDeadServices;logger;serviceLoggers;updateAvailabilityChecker=null;servicesLive;servicesDead;live=new p(()=>{});dead=new p(()=>{});restartTimes=[];constructor(e){this.options=e;let{FLIGHTDECK_SECRET:i}=L,{flightdeckRootDir:t=b(R(),".flightdeck")}=e,o=e.port??8080,n=`http://localhost:${o}`,c=u(e.services);if(this.services=v(c.map(([s])=>[s,null])),this.serviceIdx=v(c.map(([s],r)=>[s,r])),this.defaultServicesReadyToUpdate=v(c.map(([s,{waitFor:r}])=>[s,!r])),this.servicesReadyToUpdate={...this.defaultServicesReadyToUpdate},this.autoRespawnDeadServices=!0,this.logger=new S(this.options.packageName,process.pid,void 0,{jsonLogging:this.options.jsonLogging??!1}),this.serviceLoggers=v(c.map(([s])=>[s,new S(this.options.packageName,process.pid,s,{jsonLogging:this.options.jsonLogging??!1})])),this.servicesLive=c.map(()=>new p(()=>{})),this.servicesDead=c.map(()=>new p(()=>{})),this.live.use(Promise.all(this.servicesLive)),this.dead.use(Promise.all(this.servicesDead)),this.storage=new j({path:b(t,"storage",e.packageName)}),i===void 0)this.logger.warn("No FLIGHTDECK_SECRET environment variable found. FlightDeck will not run an update server.");else _((s,r)=>{let g=[];s.on("data",(a)=>{g.push(a instanceof Buffer?a:Buffer.from(a))}).on("end",()=>{let a=s.headers.authorization;try{if(typeof s.url==="undefined")throw 400;let d=`Bearer ${i}`;if(a!==`Bearer ${i}`)throw this.logger.info(`Unauthorized: needed \`${d}\`, got \`${a}\``),401;let f=new URL(s.url,n);this.logger.info(s.method,f.pathname);let h=Buffer.concat(g).toString();if(!G(h))throw 400;r.writeHead(200),r.end(),this.storage.setItem("updatePhase","notified"),this.storage.setItem("updateAwaitedVersion",h);let{checkAvailability:T}=e.scripts;if(T){this.updateAvailabilityChecker?.stop(),this.seekUpdate(h);let F=this.storage.getItem("updatePhase");if(this.logger.info('> storage("updatePhase") >',F),F==="notified")this.updateAvailabilityChecker=new K("30 * * * * *",()=>{this.seekUpdate(h)}),this.updateAvailabilityChecker.start()}else this.downloadPackage()}catch(d){if(this.logger.error(d,s.url),typeof d==="number")r.writeHead(d),r.end()}finally{g=[]}})}).listen(o,()=>{this.logger.info(`Server started on port ${o}`)});this.startAllServices().then(()=>{this.logger.info("All services started.")}).catch((s)=>{if(s instanceof Error)this.logger.error("Failed to start all services:",s.message)})}seekUpdate(e){this.logger.info("Checking for updates...");let{checkAvailability:i}=this.options.scripts;if(!i){this.logger.info("No checkAvailability script found.");return}try{let t=w(`${i} ${e}`);this.logger.info("Check stdout:",t.toString()),this.updateAvailabilityChecker?.stop(),this.storage.setItem("updatePhase","confirmed"),this.downloadPackage(),this.announceUpdate()}catch(t){if(t instanceof Error)this.logger.error("Check failed:",t.message);else{let o=$(t);this.logger.error("Check threw",o,t)}}}announceUpdate(){for(let e of u(this.services)){let[i,t]=e;if(t){if(this.options.services[i].waitFor)t.emit("updatesReady")}else this.startService(i)}}tryUpdate(){if(u(this.servicesReadyToUpdate).every(([,e])=>e))this.logger.info("All services are ready to update."),this.stopAllServices().then(()=>{this.logger.info("All services stopped; starting up fresh..."),this.startAllServices().then(()=>{this.logger.info("All services started; we're back online.")}).catch((e)=>{if(e instanceof Error)this.logger.error("Failed to start all services:",e.message)})}).catch((e)=>{if(e instanceof Error)this.logger.error("Failed to stop all services:",e.message)})}startAllServices(){this.logger.info("Starting all services..."),this.autoRespawnDeadServices=!0;let e=this.storage.getItem("setupPhase");switch(this.logger.info('> storage("setupPhase") >',e),e){case null:return this.logger.info("Starting from scratch."),this.downloadPackage(),this.installPackage(),this.startAllServices();case"downloaded":return this.logger.info("Found package downloaded but not installed."),this.installPackage(),this.startAllServices();case"installed":{for(let[i]of u(this.services))this.startService(i);return this.live}}}startService(e){if(this.logger.info(`Starting service ${this.options.packageName}::${e}, try ${this.safety}/2...`),this.safety>=2)throw new Error("Out of tries...");this.safety++;let[i,...t]=this.options.services[e].run.split(" "),o=C(i,t,{cwd:this.options.flightdeckRootDir,env:import.meta.env}),n=this.serviceLoggers[e],c=this.services[e]=new H(o,`${this.options.packageName}::${e}`,n);n.processCode=c.process.pid??-1,this.services[e].onAny((...s)=>{n.info("\uD83D\uDCAC",...s)}),this.services[e].on("readyToUpdate",()=>{this.logger.info(`Service "${e}" is ready to update.`),this.servicesReadyToUpdate[e]=!0,this.tryUpdate()}),this.services[e].on("alive",()=>{if(this.servicesLive[this.serviceIdx[e]].use(Promise.resolve()),this.servicesDead[this.serviceIdx[e]]=new p(()=>{}),this.dead.done)this.dead=new p(()=>{});this.dead.use(Promise.all(this.servicesDead))}),this.services[e].process.once("close",(s)=>{if(this.logger.info(`Auto-respawn saw "${e}" exit with code ${s}`),this.services[e]=null,!this.autoRespawnDeadServices){this.logger.info(`Auto-respawn is off; "${e}" rests.`);return}let r=this.storage.getItem("updatePhase");if(this.logger.info('> storage("updatePhase") >',r),r==="confirmed")this.serviceLoggers[e].info("Updating before startup..."),this.restartTimes=[],this.installPackage(),this.startService(e);else{let a=Date.now(),d=a-300000;if(this.restartTimes=this.restartTimes.filter((f)=>f>d),this.restartTimes.push(a),this.restartTimes.length<5)this.serviceLoggers[e].info("Crashed. Restarting..."),this.startService(e);else this.serviceLoggers[e].info("Crashed 5 times in 5 minutes. Not restarting.")}}),this.safety=0}downloadPackage(){this.logger.info("Downloading...");try{let e=w(this.options.scripts.download);this.logger.info("Download stdout:",e.toString()),this.storage.setItem("setupPhase","downloaded"),this.logger.info("Downloaded!")}catch(e){if(e instanceof Error)this.logger.error(`Failed to get the latest release: ${e.message}`);return}}installPackage(){this.logger.info("Installing...");try{let e=w(this.options.scripts.install);this.logger.info("Install stdout:",e.toString()),this.storage.setItem("setupPhase","installed"),this.logger.info("Installed!")}catch(e){if(e instanceof Error)this.logger.error(`Failed to get the latest release: ${e.message}`);return}}stopAllServices(){this.logger.info("Stopping all services... auto-respawn disabled."),this.autoRespawnDeadServices=!1;for(let[e]of u(this.services))this.stopService(e);return this.dead}stopService(e){let i=this.services[e];if(i){if(this.logger.info(`Stopping service "${e}"...`),this.servicesDead[this.serviceIdx[e]].use(new Promise((t)=>{i.emit("timeToStop"),i.process.once("close",(o)=>{this.logger.info(`Stopped service "${e}"; exited with code ${o}`),this.services[e]=null,t()})})),this.dead.use(Promise.all(this.servicesDead)),this.servicesLive[this.serviceIdx[e]]=new p(()=>{}),this.live.done)this.live=new p(()=>{});this.live.use(Promise.all(this.servicesLive))}else this.serviceLoggers[e].error("Tried to stop service, but it wasn't running.")}}var m="info",y="warn",k="ERR!",de=l.object({level:l.union([l.literal(m),l.literal(y),l.literal(k)]),timestamp:l.number(),package:l.string(),service:l.string().optional(),process:l.number(),body:l.string()}),V="line-format",N="value",pe={title:"FlightDeck Log",description:"Format for events logged by the FlightDeck process manager.","file-type":"json","timestamp-field":"timestamp","timestamp-divisor":1000,"module-field":"package","opid-field":"service","level-field":"level",level:{info:m,warning:y,error:k},[V]:[{field:"level"},{prefix:" ",field:"__timestamp__","timestamp-format":"%Y-%m-%dT%H:%M:%S.%L%Z"},{prefix:" ",field:"process","min-width":5},{prefix:":",field:"package"},{prefix:":",field:"service","default-value":""},{prefix:": ",field:"body"}],[N]:{timestamp:{kind:"integer"},level:{kind:"string"},package:{kind:"string"},service:{kind:"string"},process:{kind:"integer"},body:{kind:"string"}}};class S{packageName;serviceName;jsonLogging;processCode;constructor(e,i,t,o){if(this.packageName=e,t)this.serviceName=t;this.processCode=i,this.jsonLogging=o?.jsonLogging??!1}log(e,...i){if(this.jsonLogging){let t=i.map((n)=>typeof n==="string"?n:U(n,!1,null,!0)).join(" ");if(t.includes(`
2
+ `))t=`
3
+ ${t.split(`
4
4
  `).join(`
5
- `)}`;let r={timestamp:Date.now(),level:e,process:this.processCode,package:this.packageName,body:i};if(this.serviceName)r.service=this.serviceName;process.stdout.write(JSON.stringify(r)+`
6
- `)}else{let i=this.serviceName?`${this.packageName}:${this.serviceName}`:this.packageName;switch(e){case m:console.log(`${i}:`,...t);break;case y:console.warn(`${i}:`,...t);break;case k:console.error(`${i}:`,...t);break}}}info(...e){this.log(m,...e)}warn(...e){this.log(y,...e)}error(...e){this.log(k,...e)}}var R={};$(R,{scramble:()=>X,alert:()=>C});async function C({secret:e,endpoint:t,version:i}){return await fetch(t,{method:"POST",headers:{"Content-Type":"text/plain;charset=UTF-8",Authorization:`Bearer ${e}`},body:i})}async function X({packageConfig:e,secretsConfig:t,publishedPackages:i}){let r=[];for(let s of i)if(s.name in e){let o=s.name,{endpoint:h}=e[o],l=t[o],d=s.version,f=C({secret:l,endpoint:h,version:d}).then((g)=>[o,g]);r.push(f)}let n=await Promise.all(r);return Object.fromEntries(n)}export{W as isVersionNumber,we as flightDeckLogSchema,R as Klaxon,D as FlightDeckLogger,Y as FlightDeck,b as FilesystemStorage,y as FLIGHTDECK_WARN,Se as FLIGHTDECK_UPDATE_PHASES,ke as FLIGHTDECK_SETUP_PHASES,be as FLIGHTDECK_LNAV_FORMAT,m as FLIGHTDECK_INFO,k as FLIGHTDECK_ERROR};
5
+ `)}`;let o={timestamp:Date.now(),level:e,process:this.processCode,package:this.packageName,body:t};if(this.serviceName)o.service=this.serviceName;process.stdout.write(JSON.stringify(o)+`
6
+ `)}else{let t=this.serviceName?`${this.packageName}:${this.serviceName}`:this.packageName;switch(e){case m:console.log(`${t}:`,...i);break;case y:console.warn(`${t}:`,...i);break;case k:console.error(`${t}:`,...i);break}}}info(...e){this.log(m,...e)}warn(...e){this.log(y,...e)}error(...e){this.log(k,...e)}}var E={};A(E,{scramble:()=>B,alert:()=>D});async function D({secret:e,endpoint:i,version:t}){return await fetch(i,{method:"POST",headers:{"Content-Type":"text/plain;charset=UTF-8",Authorization:`Bearer ${e}`},body:t})}async function B({packageConfig:e,secretsConfig:i,publishedPackages:t}){let o=[];for(let s of t)if(s.name in e){let r=s.name,{endpoint:g}=e[r],a=i[r],d=s.version,f=D({secret:a,endpoint:g,version:d}).then((h)=>[r,h]);o.push(f)}let n=await Promise.all(o);return Object.fromEntries(n)}export{G as isVersionNumber,de as flightDeckLogSchema,E as Klaxon,S as FlightDeckLogger,O as FlightDeck,y as FLIGHTDECK_WARN,ce as FLIGHTDECK_UPDATE_PHASES,le as FLIGHTDECK_SETUP_PHASES,pe as FLIGHTDECK_LNAV_FORMAT,m as FLIGHTDECK_INFO,k as FLIGHTDECK_ERROR};
7
7
 
8
- //# debugId=16A02FFB0350BCFF64756E2164756E21
9
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2ZpbGVzeXN0ZW0tc3RvcmFnZS50cyIsICIuLi9zcmMvZmxpZ2h0ZGVjay5saWIudHMiLCAiLi4vc3JjL2ZsaWdodGRlY2suZW52LnRzIiwgIi4uL3NyYy9rbGF4b24ubGliLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWwogICAgImltcG9ydCB7XG5cdGV4aXN0c1N5bmMsXG5cdG1rZGlyU3luYyxcblx0cmVhZGRpclN5bmMsXG5cdHJlYWRGaWxlU3luYyxcblx0cm1TeW5jLFxuXHRzdGF0U3luYyxcblx0d3JpdGVGaWxlU3luYyxcbn0gZnJvbSBcIm5vZGU6ZnNcIlxuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gXCJub2RlOnBhdGhcIlxuXG5leHBvcnQgdHlwZSBGaWxlc3lzdGVtU3RvcmFnZU9wdGlvbnMgPSB7XG5cdHBhdGg6IHN0cmluZ1xufVxuXG5leHBvcnQgY2xhc3MgRmlsZXN5c3RlbVN0b3JhZ2U8XG5cdFQgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0gUmVjb3JkPHN0cmluZywgc3RyaW5nPixcbj4gaW1wbGVtZW50cyBTdG9yYWdlXG57XG5cdHB1YmxpYyByb290RGlyOiBzdHJpbmdcblxuXHRwdWJsaWMgY29uc3RydWN0b3Iob3B0aW9uczogRmlsZXN5c3RlbVN0b3JhZ2VPcHRpb25zKSB7XG5cdFx0dGhpcy5yb290RGlyID0gb3B0aW9ucy5wYXRoXG5cdFx0aWYgKCFleGlzdHNTeW5jKHRoaXMucm9vdERpcikpIHtcblx0XHRcdG1rZGlyU3luYyh0aGlzLnJvb3REaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG5cdFx0fVxuXHR9XG5cblx0cHVibGljIGdldEl0ZW08SyBleHRlbmRzIHN0cmluZyAmIGtleW9mIFQ+KGtleTogSyk6IFRbS10gfCBudWxsIHtcblx0XHRjb25zdCBmaWxlUGF0aCA9IHJlc29sdmUodGhpcy5yb290RGlyLCBrZXkpXG5cdFx0aWYgKGV4aXN0c1N5bmMoZmlsZVBhdGgpKSB7XG5cdFx0XHRyZXR1cm4gcmVhZEZpbGVTeW5jKGZpbGVQYXRoLCBgdXRmLThgKSBhcyBUW0tdXG5cdFx0fVxuXHRcdHJldHVybiBudWxsXG5cdH1cblxuXHRwdWJsaWMgc2V0SXRlbTxLIGV4dGVuZHMgc3RyaW5nICYga2V5b2YgVD4oa2V5OiBLLCB2YWx1ZTogVFtLXSk6IHZvaWQge1xuXHRcdGNvbnN0IGZpbGVQYXRoID0gcmVzb2x2ZSh0aGlzLnJvb3REaXIsIGtleSlcblx0XHR3cml0ZUZpbGVTeW5jKGZpbGVQYXRoLCB2YWx1ZSlcblx0fVxuXG5cdHB1YmxpYyByZW1vdmVJdGVtPEsgZXh0ZW5kcyBzdHJpbmcgJiBrZXlvZiBUPihrZXk6IEspOiB2b2lkIHtcblx0XHRjb25zdCBmaWxlUGF0aCA9IHJlc29sdmUodGhpcy5yb290RGlyLCBrZXkpXG5cdFx0aWYgKGV4aXN0c1N5bmMoZmlsZVBhdGgpKSB7XG5cdFx0XHRybVN5bmMoZmlsZVBhdGgpXG5cdFx0fVxuXHR9XG5cblx0cHVibGljIGtleShpbmRleDogbnVtYmVyKTogKHN0cmluZyAmIGtleW9mIFQpIHwgbnVsbCB7XG5cdFx0Y29uc3QgZmlsZVBhdGhzID0gcmVhZGRpclN5bmModGhpcy5yb290RGlyKVxuXHRcdGNvbnN0IGZpbGVQYXRoc0J5RGF0ZUNyZWF0ZWQgPSBmaWxlUGF0aHMuc29ydCgoYSwgYikgPT4ge1xuXHRcdFx0Y29uc3QgYVN0YXQgPSBzdGF0U3luYyhhKVxuXHRcdFx0Y29uc3QgYlN0YXQgPSBzdGF0U3luYyhiKVxuXHRcdFx0cmV0dXJuIGJTdGF0LmN0aW1lTXMgLSBhU3RhdC5jdGltZU1zXG5cdFx0fSlcblx0XHRyZXR1cm4gKGZpbGVQYXRoc0J5RGF0ZUNyZWF0ZWRbaW5kZXhdIGFzIHN0cmluZyAmIGtleW9mIFQpID8/IG51bGxcblx0fVxuXG5cdHB1YmxpYyBjbGVhcigpOiB2b2lkIHtcblx0XHRybVN5bmModGhpcy5yb290RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KVxuXHRcdG1rZGlyU3luYyh0aGlzLnJvb3REaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG5cdH1cblxuXHRwdWJsaWMgZ2V0IGxlbmd0aCgpOiBudW1iZXIge1xuXHRcdHJldHVybiByZWFkZGlyU3luYyh0aGlzLnJvb3REaXIpLmxlbmd0aFxuXHR9XG59XG4iLAogICAgImltcG9ydCB7IGV4ZWNTeW5jLCBzcGF3biB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIlxuaW1wb3J0IHR5cGUgeyBTZXJ2ZXIgfSBmcm9tIFwibm9kZTpodHRwXCJcbmltcG9ydCB7IGNyZWF0ZVNlcnZlciB9IGZyb20gXCJub2RlOmh0dHBcIlxuaW1wb3J0IHsgaG9tZWRpciB9IGZyb20gXCJub2RlOm9zXCJcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tIFwibm9kZTpwYXRoXCJcbmltcG9ydCB7IGluc3BlY3QgfSBmcm9tIFwibm9kZTp1dGlsXCJcblxuaW1wb3J0IHsgRnV0dXJlIH0gZnJvbSBcImF0b20uaW8vaW50ZXJuYWxcIlxuaW1wb3J0IHsgZGlzY292ZXJUeXBlIH0gZnJvbSBcImF0b20uaW8vaW50cm9zcGVjdGlvblwiXG5pbXBvcnQgeyBmcm9tRW50cmllcywgdG9FbnRyaWVzIH0gZnJvbSBcImF0b20uaW8vanNvblwiXG5pbXBvcnQgeyBDaGlsZFNvY2tldCB9IGZyb20gXCJhdG9tLmlvL3JlYWx0aW1lLXNlcnZlclwiXG5pbXBvcnQgeyBDcm9uSm9iIH0gZnJvbSBcImNyb25cIlxuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIlxuXG5pbXBvcnQgdHlwZSB7IExuYXZGb3JtYXQgfSBmcm9tIFwiLi4vZ2VuL2xuYXYtZm9ybWF0LXNjaGVtYS5nZW5cIlxuaW1wb3J0IHsgRmlsZXN5c3RlbVN0b3JhZ2UgfSBmcm9tIFwiLi9maWxlc3lzdGVtLXN0b3JhZ2VcIlxuaW1wb3J0IHsgZW52IH0gZnJvbSBcIi4vZmxpZ2h0ZGVjay5lbnZcIlxuXG5leHBvcnQgY29uc3QgRkxJR0hUREVDS19TRVRVUF9QSEFTRVMgPSBbYGRvd25sb2FkZWRgLCBgaW5zdGFsbGVkYF0gYXMgY29uc3RcblxuZXhwb3J0IHR5cGUgRmxpZ2h0RGVja1NldHVwUGhhc2UgPSAodHlwZW9mIEZMSUdIVERFQ0tfU0VUVVBfUEhBU0VTKVtudW1iZXJdXG5cbmV4cG9ydCBjb25zdCBGTElHSFRERUNLX1VQREFURV9QSEFTRVMgPSBbYG5vdGlmaWVkYCwgYGNvbmZpcm1lZGBdIGFzIGNvbnN0XG5cbmV4cG9ydCB0eXBlIEZsaWdodERlY2tVcGRhdGVQaGFzZSA9ICh0eXBlb2YgRkxJR0hUREVDS19VUERBVEVfUEhBU0VTKVtudW1iZXJdXG5cbmV4cG9ydCBmdW5jdGlvbiBpc1ZlcnNpb25OdW1iZXIodmVyc2lvbjogc3RyaW5nKTogYm9vbGVhbiB7XG5cdHJldHVybiAoXG5cdFx0L15cXGQrXFwuXFxkK1xcLlxcZCskLy50ZXN0KHZlcnNpb24pIHx8ICFOdW1iZXIuaXNOYU4oTnVtYmVyLnBhcnNlRmxvYXQodmVyc2lvbikpXG5cdClcbn1cblxuZXhwb3J0IHR5cGUgRmxpZ2h0RGVja09wdGlvbnM8UyBleHRlbmRzIHN0cmluZyA9IHN0cmluZz4gPSB7XG5cdHBhY2thZ2VOYW1lOiBzdHJpbmdcblx0c2VydmljZXM6IHsgW3NlcnZpY2UgaW4gU106IHsgcnVuOiBzdHJpbmc7IHdhaXRGb3I6IGJvb2xlYW4gfSB9XG5cdHNjcmlwdHM6IHtcblx0XHRkb3dubG9hZDogc3RyaW5nXG5cdFx0aW5zdGFsbDogc3RyaW5nXG5cdFx0Y2hlY2tBdmFpbGFiaWxpdHk/OiBzdHJpbmdcblx0fVxuXHRwb3J0PzogbnVtYmVyIHwgdW5kZWZpbmVkXG5cdGZsaWdodGRlY2tSb290RGlyPzogc3RyaW5nIHwgdW5kZWZpbmVkXG5cdGpzb25Mb2dnaW5nPzogYm9vbGVhbiB8IHVuZGVmaW5lZFxufVxuXG5leHBvcnQgY2xhc3MgRmxpZ2h0RGVjazxTIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nPiB7XG5cdHByb3RlY3RlZCBzYWZldHkgPSAwXG5cblx0cHJvdGVjdGVkIHN0b3JhZ2U6IEZpbGVzeXN0ZW1TdG9yYWdlPHtcblx0XHRzZXR1cFBoYXNlOiBGbGlnaHREZWNrU2V0dXBQaGFzZVxuXHRcdHVwZGF0ZVBoYXNlOiBGbGlnaHREZWNrVXBkYXRlUGhhc2Vcblx0XHR1cGRhdGVBd2FpdGVkVmVyc2lvbjogc3RyaW5nXG5cdH0+XG5cdHByb3RlY3RlZCB3ZWJob29rU2VydmVyOiBTZXJ2ZXJcblx0cHJvdGVjdGVkIHNlcnZpY2VzOiB7XG5cdFx0W3NlcnZpY2UgaW4gU106IENoaWxkU29ja2V0PFxuXHRcdFx0eyB0aW1lVG9TdG9wOiBbXTsgdXBkYXRlc1JlYWR5OiBbXSB9LFxuXHRcdFx0eyByZWFkeVRvVXBkYXRlOiBbXTsgYWxpdmU6IFtdIH1cblx0XHQ+IHwgbnVsbFxuXHR9XG5cdHByb3RlY3RlZCBzZXJ2aWNlSWR4OiB7IHJlYWRvbmx5IFtzZXJ2aWNlIGluIFNdOiBudW1iZXIgfVxuXHRwdWJsaWMgZGVmYXVsdFNlcnZpY2VzUmVhZHlUb1VwZGF0ZTogeyByZWFkb25seSBbc2VydmljZSBpbiBTXTogYm9vbGVhbiB9XG5cdHB1YmxpYyBzZXJ2aWNlc1JlYWR5VG9VcGRhdGU6IHsgW3NlcnZpY2UgaW4gU106IGJvb2xlYW4gfVxuXHRwdWJsaWMgYXV0b1Jlc3Bhd25EZWFkU2VydmljZXM6IGJvb2xlYW5cblxuXHRwcm90ZWN0ZWQgbG9nZ2VyOiBQaWNrPENvbnNvbGUsIGBlcnJvcmAgfCBgaW5mb2AgfCBgd2FybmA+XG5cdHByb3RlY3RlZCBzZXJ2aWNlTG9nZ2Vyczoge1xuXHRcdHJlYWRvbmx5IFtzZXJ2aWNlIGluIFNdOiBGbGlnaHREZWNrTG9nZ2VyXG5cdH1cblxuXHRwcm90ZWN0ZWQgdXBkYXRlQXZhaWxhYmlsaXR5Q2hlY2tlcjogQ3JvbkpvYiB8IG51bGwgPSBudWxsXG5cblx0cHVibGljIHNlcnZpY2VzTGl2ZTogRnV0dXJlPHZvaWQ+W11cblx0cHVibGljIHNlcnZpY2VzRGVhZDogRnV0dXJlPHZvaWQ+W11cblx0cHVibGljIGxpdmUgPSBuZXcgRnV0dXJlKCgpID0+IHt9KVxuXHRwdWJsaWMgZGVhZCA9IG5ldyBGdXR1cmUoKCkgPT4ge30pXG5cblx0cHJvdGVjdGVkIHJlc3RhcnRUaW1lczogbnVtYmVyW10gPSBbXVxuXG5cdHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgb3B0aW9uczogRmxpZ2h0RGVja09wdGlvbnM8Uz4pIHtcblx0XHRjb25zdCB7IEZMSUdIVERFQ0tfU0VDUkVUIH0gPSBlbnZcblx0XHRjb25zdCB7IGZsaWdodGRlY2tSb290RGlyID0gcmVzb2x2ZShob21lZGlyKCksIGAuZmxpZ2h0ZGVja2ApIH0gPSBvcHRpb25zXG5cdFx0Y29uc3QgcG9ydCA9IG9wdGlvbnMucG9ydCA/PyA4MDgwXG5cdFx0Y29uc3Qgb3JpZ2luID0gYGh0dHA6Ly9sb2NhbGhvc3Q6JHtwb3J0fWBcblxuXHRcdGNvbnN0IHNlcnZpY2VzRW50cmllcyA9IHRvRW50cmllcyhvcHRpb25zLnNlcnZpY2VzKVxuXHRcdHRoaXMuc2VydmljZXMgPSBmcm9tRW50cmllcyhcblx0XHRcdHNlcnZpY2VzRW50cmllcy5tYXAoKFtzZXJ2aWNlTmFtZV0pID0+IFtzZXJ2aWNlTmFtZSwgbnVsbF0pLFxuXHRcdClcblx0XHR0aGlzLnNlcnZpY2VJZHggPSBmcm9tRW50cmllcyhcblx0XHRcdHNlcnZpY2VzRW50cmllcy5tYXAoKFtzZXJ2aWNlTmFtZV0sIGlkeCkgPT4gW3NlcnZpY2VOYW1lLCBpZHhdKSxcblx0XHQpXG5cdFx0dGhpcy5kZWZhdWx0U2VydmljZXNSZWFkeVRvVXBkYXRlID0gZnJvbUVudHJpZXMoXG5cdFx0XHRzZXJ2aWNlc0VudHJpZXMubWFwKChbc2VydmljZU5hbWUsIHsgd2FpdEZvciB9XSkgPT4gW1xuXHRcdFx0XHRzZXJ2aWNlTmFtZSxcblx0XHRcdFx0IXdhaXRGb3IsXG5cdFx0XHRdKSxcblx0XHQpXG5cdFx0dGhpcy5zZXJ2aWNlc1JlYWR5VG9VcGRhdGUgPSB7IC4uLnRoaXMuZGVmYXVsdFNlcnZpY2VzUmVhZHlUb1VwZGF0ZSB9XG5cdFx0dGhpcy5hdXRvUmVzcGF3bkRlYWRTZXJ2aWNlcyA9IHRydWVcblxuXHRcdHRoaXMubG9nZ2VyID0gbmV3IEZsaWdodERlY2tMb2dnZXIoXG5cdFx0XHR0aGlzLm9wdGlvbnMucGFja2FnZU5hbWUsXG5cdFx0XHRwcm9jZXNzLnBpZCxcblx0XHRcdHVuZGVmaW5lZCxcblx0XHRcdHsganNvbkxvZ2dpbmc6IHRoaXMub3B0aW9ucy5qc29uTG9nZ2luZyA/PyBmYWxzZSB9LFxuXHRcdClcblx0XHR0aGlzLnNlcnZpY2VMb2dnZXJzID0gZnJvbUVudHJpZXMoXG5cdFx0XHRzZXJ2aWNlc0VudHJpZXMubWFwKChbc2VydmljZU5hbWVdKSA9PiBbXG5cdFx0XHRcdHNlcnZpY2VOYW1lLFxuXHRcdFx0XHRuZXcgRmxpZ2h0RGVja0xvZ2dlcihcblx0XHRcdFx0XHR0aGlzLm9wdGlvbnMucGFja2FnZU5hbWUsXG5cdFx0XHRcdFx0cHJvY2Vzcy5waWQsXG5cdFx0XHRcdFx0c2VydmljZU5hbWUsXG5cdFx0XHRcdFx0eyBqc29uTG9nZ2luZzogdGhpcy5vcHRpb25zLmpzb25Mb2dnaW5nID8/IGZhbHNlIH0sXG5cdFx0XHRcdCksXG5cdFx0XHRdKSxcblx0XHQpXG5cblx0XHR0aGlzLnNlcnZpY2VzTGl2ZSA9IHNlcnZpY2VzRW50cmllcy5tYXAoKCkgPT4gbmV3IEZ1dHVyZSgoKSA9PiB7fSkpXG5cdFx0dGhpcy5zZXJ2aWNlc0RlYWQgPSBzZXJ2aWNlc0VudHJpZXMubWFwKCgpID0+IG5ldyBGdXR1cmUoKCkgPT4ge30pKVxuXHRcdHRoaXMubGl2ZS51c2UoUHJvbWlzZS5hbGwodGhpcy5zZXJ2aWNlc0xpdmUpKVxuXHRcdHRoaXMuZGVhZC51c2UoUHJvbWlzZS5hbGwodGhpcy5zZXJ2aWNlc0RlYWQpKVxuXG5cdFx0dGhpcy5zdG9yYWdlID0gbmV3IEZpbGVzeXN0ZW1TdG9yYWdlKHtcblx0XHRcdHBhdGg6IHJlc29sdmUoZmxpZ2h0ZGVja1Jvb3REaXIsIGBzdG9yYWdlYCwgb3B0aW9ucy5wYWNrYWdlTmFtZSksXG5cdFx0fSlcblxuXHRcdGlmIChGTElHSFRERUNLX1NFQ1JFVCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHR0aGlzLmxvZ2dlci53YXJuKFxuXHRcdFx0XHRgTm8gRkxJR0hUREVDS19TRUNSRVQgZW52aXJvbm1lbnQgdmFyaWFibGUgZm91bmQuIEZsaWdodERlY2sgd2lsbCBub3QgcnVuIGFuIHVwZGF0ZSBzZXJ2ZXIuYCxcblx0XHRcdClcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y3JlYXRlU2VydmVyKChyZXEsIHJlcykgPT4ge1xuXHRcdFx0XHRsZXQgZGF0YTogVWludDhBcnJheVtdID0gW11cblx0XHRcdFx0cmVxXG5cdFx0XHRcdFx0Lm9uKGBkYXRhYCwgKGNodW5rKSA9PiB7XG5cdFx0XHRcdFx0XHRkYXRhLnB1c2goY2h1bmsgaW5zdGFuY2VvZiBCdWZmZXIgPyBjaHVuayA6IEJ1ZmZlci5mcm9tKGNodW5rKSlcblx0XHRcdFx0XHR9KVxuXHRcdFx0XHRcdC5vbihgZW5kYCwgKCkgPT4ge1xuXHRcdFx0XHRcdFx0Y29uc3QgYXV0aEhlYWRlciA9IHJlcS5oZWFkZXJzLmF1dGhvcml6YXRpb25cblx0XHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRcdGlmICh0eXBlb2YgcmVxLnVybCA9PT0gYHVuZGVmaW5lZGApIHRocm93IDQwMFxuXHRcdFx0XHRcdFx0XHRjb25zdCBleHBlY3RlZEF1dGhIZWFkZXIgPSBgQmVhcmVyICR7RkxJR0hUREVDS19TRUNSRVR9YFxuXHRcdFx0XHRcdFx0XHRpZiAoYXV0aEhlYWRlciAhPT0gYEJlYXJlciAke0ZMSUdIVERFQ0tfU0VDUkVUfWApIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKFxuXHRcdFx0XHRcdFx0XHRcdFx0YFVuYXV0aG9yaXplZDogbmVlZGVkIFxcYCR7ZXhwZWN0ZWRBdXRoSGVhZGVyfVxcYCwgZ290IFxcYCR7YXV0aEhlYWRlcn1cXGBgLFxuXHRcdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdFx0XHR0aHJvdyA0MDFcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRjb25zdCB1cmwgPSBuZXcgVVJMKHJlcS51cmwsIG9yaWdpbilcblx0XHRcdFx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhyZXEubWV0aG9kLCB1cmwucGF0aG5hbWUpXG5cblx0XHRcdFx0XHRcdFx0Y29uc3QgdmVyc2lvbkZvcmVpZ25JbnB1dCA9IEJ1ZmZlci5jb25jYXQoZGF0YSkudG9TdHJpbmcoKVxuXHRcdFx0XHRcdFx0XHRpZiAoIWlzVmVyc2lvbk51bWJlcih2ZXJzaW9uRm9yZWlnbklucHV0KSkge1xuXHRcdFx0XHRcdFx0XHRcdHRocm93IDQwMFxuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0cmVzLndyaXRlSGVhZCgyMDApXG5cdFx0XHRcdFx0XHRcdHJlcy5lbmQoKVxuXG5cdFx0XHRcdFx0XHRcdHRoaXMuc3RvcmFnZS5zZXRJdGVtKGB1cGRhdGVQaGFzZWAsIGBub3RpZmllZGApXG5cdFx0XHRcdFx0XHRcdHRoaXMuc3RvcmFnZS5zZXRJdGVtKGB1cGRhdGVBd2FpdGVkVmVyc2lvbmAsIHZlcnNpb25Gb3JlaWduSW5wdXQpXG5cdFx0XHRcdFx0XHRcdGNvbnN0IHsgY2hlY2tBdmFpbGFiaWxpdHkgfSA9IG9wdGlvbnMuc2NyaXB0c1xuXHRcdFx0XHRcdFx0XHRpZiAoY2hlY2tBdmFpbGFiaWxpdHkpIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnVwZGF0ZUF2YWlsYWJpbGl0eUNoZWNrZXI/LnN0b3AoKVxuXHRcdFx0XHRcdFx0XHRcdHRoaXMuc2Vla1VwZGF0ZSh2ZXJzaW9uRm9yZWlnbklucHV0KVxuXHRcdFx0XHRcdFx0XHRcdGNvbnN0IHVwZGF0ZVBoYXNlID0gdGhpcy5zdG9yYWdlLmdldEl0ZW0oYHVwZGF0ZVBoYXNlYClcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGA+IHN0b3JhZ2UoXCJ1cGRhdGVQaGFzZVwiKSA+YCwgdXBkYXRlUGhhc2UpXG5cdFx0XHRcdFx0XHRcdFx0aWYgKHVwZGF0ZVBoYXNlID09PSBgbm90aWZpZWRgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHR0aGlzLnVwZGF0ZUF2YWlsYWJpbGl0eUNoZWNrZXIgPSBuZXcgQ3JvbkpvYihcblx0XHRcdFx0XHRcdFx0XHRcdFx0YDMwICogKiAqICogKmAsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCgpID0+IHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0aGlzLnNlZWtVcGRhdGUodmVyc2lvbkZvcmVpZ25JbnB1dClcblx0XHRcdFx0XHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdFx0XHRcdHRoaXMudXBkYXRlQXZhaWxhYmlsaXR5Q2hlY2tlci5zdGFydCgpXG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMuZG93bmxvYWRQYWNrYWdlKClcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBjYXRjaCAodGhyb3duKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKHRocm93biwgcmVxLnVybClcblx0XHRcdFx0XHRcdFx0aWYgKHR5cGVvZiB0aHJvd24gPT09IGBudW1iZXJgKSB7XG5cdFx0XHRcdFx0XHRcdFx0cmVzLndyaXRlSGVhZCh0aHJvd24pXG5cdFx0XHRcdFx0XHRcdFx0cmVzLmVuZCgpXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0gZmluYWxseSB7XG5cdFx0XHRcdFx0XHRcdGRhdGEgPSBbXVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pXG5cdFx0XHR9KS5saXN0ZW4ocG9ydCwgKCkgPT4ge1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBTZXJ2ZXIgc3RhcnRlZCBvbiBwb3J0ICR7cG9ydH1gKVxuXHRcdFx0fSlcblx0XHR9XG5cblx0XHR0aGlzLnN0YXJ0QWxsU2VydmljZXMoKVxuXHRcdFx0LnRoZW4oKCkgPT4ge1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBBbGwgc2VydmljZXMgc3RhcnRlZC5gKVxuXHRcdFx0fSlcblx0XHRcdC5jYXRjaCgodGhyb3duKSA9PiB7XG5cdFx0XHRcdGlmICh0aHJvd24gaW5zdGFuY2VvZiBFcnJvcikge1xuXHRcdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBGYWlsZWQgdG8gc3RhcnQgYWxsIHNlcnZpY2VzOmAsIHRocm93bi5tZXNzYWdlKVxuXHRcdFx0XHR9XG5cdFx0XHR9KVxuXHR9XG5cblx0cHJvdGVjdGVkIHNlZWtVcGRhdGUodmVyc2lvbjogc3RyaW5nKTogdm9pZCB7XG5cdFx0dGhpcy5sb2dnZXIuaW5mbyhgQ2hlY2tpbmcgZm9yIHVwZGF0ZXMuLi5gKVxuXHRcdGNvbnN0IHsgY2hlY2tBdmFpbGFiaWxpdHkgfSA9IHRoaXMub3B0aW9ucy5zY3JpcHRzXG5cdFx0aWYgKCFjaGVja0F2YWlsYWJpbGl0eSkge1xuXHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgTm8gY2hlY2tBdmFpbGFiaWxpdHkgc2NyaXB0IGZvdW5kLmApXG5cdFx0XHRyZXR1cm5cblx0XHR9XG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IG91dCA9IGV4ZWNTeW5jKGAke2NoZWNrQXZhaWxhYmlsaXR5fSAke3ZlcnNpb259YClcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYENoZWNrIHN0ZG91dDpgLCBvdXQudG9TdHJpbmcoKSlcblx0XHRcdHRoaXMudXBkYXRlQXZhaWxhYmlsaXR5Q2hlY2tlcj8uc3RvcCgpXG5cdFx0XHR0aGlzLnN0b3JhZ2Uuc2V0SXRlbShgdXBkYXRlUGhhc2VgLCBgY29uZmlybWVkYClcblx0XHRcdHRoaXMuZG93bmxvYWRQYWNrYWdlKClcblx0XHRcdHRoaXMuYW5ub3VuY2VVcGRhdGUoKVxuXHRcdH0gY2F0Y2ggKHRocm93bikge1xuXHRcdFx0aWYgKHRocm93biBpbnN0YW5jZW9mIEVycm9yKSB7XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBDaGVjayBmYWlsZWQ6YCwgdGhyb3duLm1lc3NhZ2UpXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjb25zdCB0aHJvd25UeXBlID0gZGlzY292ZXJUeXBlKHRocm93bilcblx0XHRcdFx0dGhpcy5sb2dnZXIuZXJyb3IoYENoZWNrIHRocmV3YCwgdGhyb3duVHlwZSwgdGhyb3duKVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHByb3RlY3RlZCBhbm5vdW5jZVVwZGF0ZSgpOiB2b2lkIHtcblx0XHRmb3IgKGNvbnN0IGVudHJ5IG9mIHRvRW50cmllcyh0aGlzLnNlcnZpY2VzKSkge1xuXHRcdFx0Y29uc3QgW3NlcnZpY2VOYW1lLCBzZXJ2aWNlXSA9IGVudHJ5XG5cdFx0XHRpZiAoc2VydmljZSkge1xuXHRcdFx0XHRpZiAodGhpcy5vcHRpb25zLnNlcnZpY2VzW3NlcnZpY2VOYW1lXS53YWl0Rm9yKSB7XG5cdFx0XHRcdFx0c2VydmljZS5lbWl0KGB1cGRhdGVzUmVhZHlgKVxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnN0YXJ0U2VydmljZShzZXJ2aWNlTmFtZSlcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRwcm90ZWN0ZWQgdHJ5VXBkYXRlKCk6IHZvaWQge1xuXHRcdGlmICh0b0VudHJpZXModGhpcy5zZXJ2aWNlc1JlYWR5VG9VcGRhdGUpLmV2ZXJ5KChbLCBpc1JlYWR5XSkgPT4gaXNSZWFkeSkpIHtcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYEFsbCBzZXJ2aWNlcyBhcmUgcmVhZHkgdG8gdXBkYXRlLmApXG5cdFx0XHR0aGlzLnN0b3BBbGxTZXJ2aWNlcygpXG5cdFx0XHRcdC50aGVuKCgpID0+IHtcblx0XHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBBbGwgc2VydmljZXMgc3RvcHBlZDsgc3RhcnRpbmcgdXAgZnJlc2guLi5gKVxuXHRcdFx0XHRcdHRoaXMuc3RhcnRBbGxTZXJ2aWNlcygpXG5cdFx0XHRcdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYEFsbCBzZXJ2aWNlcyBzdGFydGVkOyB3ZSdyZSBiYWNrIG9ubGluZS5gKVxuXHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0XHRcdC5jYXRjaCgodGhyb3duKSA9PiB7XG5cdFx0XHRcdFx0XHRcdGlmICh0aHJvd24gaW5zdGFuY2VvZiBFcnJvcikge1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKFxuXHRcdFx0XHRcdFx0XHRcdFx0YEZhaWxlZCB0byBzdGFydCBhbGwgc2VydmljZXM6YCxcblx0XHRcdFx0XHRcdFx0XHRcdHRocm93bi5tZXNzYWdlLFxuXHRcdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0fSlcblx0XHRcdFx0LmNhdGNoKCh0aHJvd24pID0+IHtcblx0XHRcdFx0XHRpZiAodGhyb3duIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRcdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBGYWlsZWQgdG8gc3RvcCBhbGwgc2VydmljZXM6YCwgdGhyb3duLm1lc3NhZ2UpXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KVxuXHRcdH1cblx0fVxuXG5cdHByb3RlY3RlZCBzdGFydEFsbFNlcnZpY2VzKCk6IEZ1dHVyZTx1bmtub3duPiB7XG5cdFx0dGhpcy5sb2dnZXIuaW5mbyhgU3RhcnRpbmcgYWxsIHNlcnZpY2VzLi4uYClcblx0XHR0aGlzLmF1dG9SZXNwYXduRGVhZFNlcnZpY2VzID0gdHJ1ZVxuXHRcdGNvbnN0IHNldHVwUGhhc2UgPSB0aGlzLnN0b3JhZ2UuZ2V0SXRlbShgc2V0dXBQaGFzZWApXG5cdFx0dGhpcy5sb2dnZXIuaW5mbyhgPiBzdG9yYWdlKFwic2V0dXBQaGFzZVwiKSA+YCwgc2V0dXBQaGFzZSlcblx0XHRzd2l0Y2ggKHNldHVwUGhhc2UpIHtcblx0XHRcdGNhc2UgbnVsbDpcblx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgU3RhcnRpbmcgZnJvbSBzY3JhdGNoLmApXG5cdFx0XHRcdHRoaXMuZG93bmxvYWRQYWNrYWdlKClcblx0XHRcdFx0dGhpcy5pbnN0YWxsUGFja2FnZSgpXG5cdFx0XHRcdHJldHVybiB0aGlzLnN0YXJ0QWxsU2VydmljZXMoKVxuXHRcdFx0Y2FzZSBgZG93bmxvYWRlZGA6XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYEZvdW5kIHBhY2thZ2UgZG93bmxvYWRlZCBidXQgbm90IGluc3RhbGxlZC5gKVxuXHRcdFx0XHR0aGlzLmluc3RhbGxQYWNrYWdlKClcblx0XHRcdFx0cmV0dXJuIHRoaXMuc3RhcnRBbGxTZXJ2aWNlcygpXG5cdFx0XHRjYXNlIGBpbnN0YWxsZWRgOiB7XG5cdFx0XHRcdGZvciAoY29uc3QgW3NlcnZpY2VOYW1lXSBvZiB0b0VudHJpZXModGhpcy5zZXJ2aWNlcykpIHtcblx0XHRcdFx0XHR0aGlzLnN0YXJ0U2VydmljZShzZXJ2aWNlTmFtZSlcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcy5saXZlXG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cHJvdGVjdGVkIHN0YXJ0U2VydmljZShzZXJ2aWNlTmFtZTogUyk6IHZvaWQge1xuXHRcdHRoaXMubG9nZ2VyLmluZm8oXG5cdFx0XHRgU3RhcnRpbmcgc2VydmljZSAke3RoaXMub3B0aW9ucy5wYWNrYWdlTmFtZX06OiR7c2VydmljZU5hbWV9LCB0cnkgJHt0aGlzLnNhZmV0eX0vMi4uLmAsXG5cdFx0KVxuXHRcdGlmICh0aGlzLnNhZmV0eSA+PSAyKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYE91dCBvZiB0cmllcy4uLmApXG5cdFx0fVxuXHRcdHRoaXMuc2FmZXR5KytcblxuXHRcdGNvbnN0IFtleGUsIC4uLmFyZ3NdID0gdGhpcy5vcHRpb25zLnNlcnZpY2VzW3NlcnZpY2VOYW1lXS5ydW4uc3BsaXQoYCBgKVxuXHRcdGNvbnN0IHNlcnZpY2VQcm9jZXNzID0gc3Bhd24oZXhlLCBhcmdzLCB7XG5cdFx0XHRjd2Q6IHRoaXMub3B0aW9ucy5mbGlnaHRkZWNrUm9vdERpcixcblx0XHRcdGVudjogaW1wb3J0Lm1ldGEuZW52LFxuXHRcdH0pXG5cdFx0Y29uc3Qgc2VydmljZUxvZ2dlciA9IHRoaXMuc2VydmljZUxvZ2dlcnNbc2VydmljZU5hbWVdXG5cdFx0Y29uc3Qgc2VydmljZSA9ICh0aGlzLnNlcnZpY2VzW3NlcnZpY2VOYW1lXSA9IG5ldyBDaGlsZFNvY2tldChcblx0XHRcdHNlcnZpY2VQcm9jZXNzLFxuXHRcdFx0YCR7dGhpcy5vcHRpb25zLnBhY2thZ2VOYW1lfTo6JHtzZXJ2aWNlTmFtZX1gLFxuXHRcdFx0c2VydmljZUxvZ2dlcixcblx0XHQpKVxuXHRcdHNlcnZpY2VMb2dnZXIucHJvY2Vzc0NvZGUgPSBzZXJ2aWNlLnByb2Nlc3MucGlkID8/IC0xXG5cdFx0dGhpcy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0ub25BbnkoKC4uLm1lc3NhZ2VzKSA9PiB7XG5cdFx0XHRzZXJ2aWNlTG9nZ2VyLmluZm8oYPCfkqxgLCAuLi5tZXNzYWdlcylcblx0XHR9KVxuXHRcdHRoaXMuc2VydmljZXNbc2VydmljZU5hbWVdLm9uKGByZWFkeVRvVXBkYXRlYCwgKCkgPT4ge1xuXHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgU2VydmljZSBcIiR7c2VydmljZU5hbWV9XCIgaXMgcmVhZHkgdG8gdXBkYXRlLmApXG5cdFx0XHR0aGlzLnNlcnZpY2VzUmVhZHlUb1VwZGF0ZVtzZXJ2aWNlTmFtZV0gPSB0cnVlXG5cdFx0XHR0aGlzLnRyeVVwZGF0ZSgpXG5cdFx0fSlcblx0XHR0aGlzLnNlcnZpY2VzW3NlcnZpY2VOYW1lXS5vbihgYWxpdmVgLCAoKSA9PiB7XG5cdFx0XHR0aGlzLnNlcnZpY2VzTGl2ZVt0aGlzLnNlcnZpY2VJZHhbc2VydmljZU5hbWVdXS51c2UoUHJvbWlzZS5yZXNvbHZlKCkpXG5cdFx0XHR0aGlzLnNlcnZpY2VzRGVhZFt0aGlzLnNlcnZpY2VJZHhbc2VydmljZU5hbWVdXSA9IG5ldyBGdXR1cmUoKCkgPT4ge30pXG5cdFx0XHRpZiAodGhpcy5kZWFkLmRvbmUpIHtcblx0XHRcdFx0dGhpcy5kZWFkID0gbmV3IEZ1dHVyZSgoKSA9PiB7fSlcblx0XHRcdH1cblx0XHRcdHRoaXMuZGVhZC51c2UoUHJvbWlzZS5hbGwodGhpcy5zZXJ2aWNlc0RlYWQpKVxuXHRcdH0pXG5cdFx0dGhpcy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0ucHJvY2Vzcy5vbmNlKGBjbG9zZWAsIChleGl0Q29kZSkgPT4ge1xuXHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhcblx0XHRcdFx0YEF1dG8tcmVzcGF3biBzYXcgXCIke3NlcnZpY2VOYW1lfVwiIGV4aXQgd2l0aCBjb2RlICR7ZXhpdENvZGV9YCxcblx0XHRcdClcblx0XHRcdHRoaXMuc2VydmljZXNbc2VydmljZU5hbWVdID0gbnVsbFxuXHRcdFx0aWYgKCF0aGlzLmF1dG9SZXNwYXduRGVhZFNlcnZpY2VzKSB7XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYEF1dG8tcmVzcGF3biBpcyBvZmY7IFwiJHtzZXJ2aWNlTmFtZX1cIiByZXN0cy5gKVxuXHRcdFx0XHRyZXR1cm5cblx0XHRcdH1cblx0XHRcdGNvbnN0IHVwZGF0ZVBoYXNlID0gdGhpcy5zdG9yYWdlLmdldEl0ZW0oYHVwZGF0ZVBoYXNlYClcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYD4gc3RvcmFnZShcInVwZGF0ZVBoYXNlXCIpID5gLCB1cGRhdGVQaGFzZSlcblx0XHRcdGNvbnN0IHVwZGF0ZXNBcmVSZWFkeSA9IHVwZGF0ZVBoYXNlID09PSBgY29uZmlybWVkYFxuXHRcdFx0aWYgKHVwZGF0ZXNBcmVSZWFkeSkge1xuXHRcdFx0XHR0aGlzLnNlcnZpY2VMb2dnZXJzW3NlcnZpY2VOYW1lXS5pbmZvKGBVcGRhdGluZyBiZWZvcmUgc3RhcnR1cC4uLmApXG5cdFx0XHRcdHRoaXMucmVzdGFydFRpbWVzID0gW11cblx0XHRcdFx0dGhpcy5pbnN0YWxsUGFja2FnZSgpXG5cdFx0XHRcdHRoaXMuc3RhcnRTZXJ2aWNlKHNlcnZpY2VOYW1lKVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y29uc3Qgbm93ID0gRGF0ZS5ub3coKVxuXHRcdFx0XHRjb25zdCBmaXZlTWludXRlc0FnbyA9IG5vdyAtIDUgKiA2MCAqIDEwMDBcblx0XHRcdFx0dGhpcy5yZXN0YXJ0VGltZXMgPSB0aGlzLnJlc3RhcnRUaW1lcy5maWx0ZXIoXG5cdFx0XHRcdFx0KHRpbWUpID0+IHRpbWUgPiBmaXZlTWludXRlc0Fnbyxcblx0XHRcdFx0KVxuXHRcdFx0XHR0aGlzLnJlc3RhcnRUaW1lcy5wdXNoKG5vdylcblxuXHRcdFx0XHRpZiAodGhpcy5yZXN0YXJ0VGltZXMubGVuZ3RoIDwgNSkge1xuXHRcdFx0XHRcdHRoaXMuc2VydmljZUxvZ2dlcnNbc2VydmljZU5hbWVdLmluZm8oYENyYXNoZWQuIFJlc3RhcnRpbmcuLi5gKVxuXHRcdFx0XHRcdHRoaXMuc3RhcnRTZXJ2aWNlKHNlcnZpY2VOYW1lKVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRoaXMuc2VydmljZUxvZ2dlcnNbc2VydmljZU5hbWVdLmluZm8oXG5cdFx0XHRcdFx0XHRgQ3Jhc2hlZCA1IHRpbWVzIGluIDUgbWludXRlcy4gTm90IHJlc3RhcnRpbmcuYCxcblx0XHRcdFx0XHQpXG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KVxuXHRcdHRoaXMuc2FmZXR5ID0gMFxuXHR9XG5cblx0cHJvdGVjdGVkIGRvd25sb2FkUGFja2FnZSgpOiB2b2lkIHtcblx0XHR0aGlzLmxvZ2dlci5pbmZvKGBEb3dubG9hZGluZy4uLmApXG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IG91dCA9IGV4ZWNTeW5jKHRoaXMub3B0aW9ucy5zY3JpcHRzLmRvd25sb2FkKVxuXHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgRG93bmxvYWQgc3Rkb3V0OmAsIG91dC50b1N0cmluZygpKVxuXHRcdFx0dGhpcy5zdG9yYWdlLnNldEl0ZW0oYHNldHVwUGhhc2VgLCBgZG93bmxvYWRlZGApXG5cdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBEb3dubG9hZGVkIWApXG5cdFx0fSBjYXRjaCAodGhyb3duKSB7XG5cdFx0XHRpZiAodGhyb3duIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRcdFx0dGhpcy5sb2dnZXIuZXJyb3IoYEZhaWxlZCB0byBnZXQgdGhlIGxhdGVzdCByZWxlYXNlOiAke3Rocm93bi5tZXNzYWdlfWApXG5cdFx0XHR9XG5cdFx0XHRyZXR1cm5cblx0XHR9XG5cdH1cblxuXHRwcm90ZWN0ZWQgaW5zdGFsbFBhY2thZ2UoKTogdm9pZCB7XG5cdFx0dGhpcy5sb2dnZXIuaW5mbyhgSW5zdGFsbGluZy4uLmApXG5cblx0XHR0cnkge1xuXHRcdFx0Y29uc3Qgb3V0ID0gZXhlY1N5bmModGhpcy5vcHRpb25zLnNjcmlwdHMuaW5zdGFsbClcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYEluc3RhbGwgc3Rkb3V0OmAsIG91dC50b1N0cmluZygpKVxuXHRcdFx0dGhpcy5zdG9yYWdlLnNldEl0ZW0oYHNldHVwUGhhc2VgLCBgaW5zdGFsbGVkYClcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYEluc3RhbGxlZCFgKVxuXHRcdH0gY2F0Y2ggKHRocm93bikge1xuXHRcdFx0aWYgKHRocm93biBpbnN0YW5jZW9mIEVycm9yKSB7XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBGYWlsZWQgdG8gZ2V0IHRoZSBsYXRlc3QgcmVsZWFzZTogJHt0aHJvd24ubWVzc2FnZX1gKVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuXG5cdFx0fVxuXHR9XG5cblx0cHVibGljIHN0b3BBbGxTZXJ2aWNlcygpOiBGdXR1cmU8dW5rbm93bj4ge1xuXHRcdHRoaXMubG9nZ2VyLmluZm8oYFN0b3BwaW5nIGFsbCBzZXJ2aWNlcy4uLiBhdXRvLXJlc3Bhd24gZGlzYWJsZWQuYClcblx0XHR0aGlzLmF1dG9SZXNwYXduRGVhZFNlcnZpY2VzID0gZmFsc2Vcblx0XHRmb3IgKGNvbnN0IFtzZXJ2aWNlTmFtZV0gb2YgdG9FbnRyaWVzKHRoaXMuc2VydmljZXMpKSB7XG5cdFx0XHR0aGlzLnN0b3BTZXJ2aWNlKHNlcnZpY2VOYW1lKVxuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5kZWFkXG5cdH1cblxuXHRwdWJsaWMgc3RvcFNlcnZpY2Uoc2VydmljZU5hbWU6IFMpOiB2b2lkIHtcblx0XHRjb25zdCBzZXJ2aWNlID0gdGhpcy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV1cblx0XHRpZiAoc2VydmljZSkge1xuXHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgU3RvcHBpbmcgc2VydmljZSBcIiR7c2VydmljZU5hbWV9XCIuLi5gKVxuXHRcdFx0dGhpcy5zZXJ2aWNlc0RlYWRbdGhpcy5zZXJ2aWNlSWR4W3NlcnZpY2VOYW1lXV0udXNlKFxuXHRcdFx0XHRuZXcgUHJvbWlzZSgocGFzcykgPT4ge1xuXHRcdFx0XHRcdHNlcnZpY2UuZW1pdChgdGltZVRvU3RvcGApXG5cdFx0XHRcdFx0c2VydmljZS5wcm9jZXNzLm9uY2UoYGNsb3NlYCwgKGV4aXRDb2RlKSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKFxuXHRcdFx0XHRcdFx0XHRgU3RvcHBlZCBzZXJ2aWNlIFwiJHtzZXJ2aWNlTmFtZX1cIjsgZXhpdGVkIHdpdGggY29kZSAke2V4aXRDb2RlfWAsXG5cdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHR0aGlzLnNlcnZpY2VzW3NlcnZpY2VOYW1lXSA9IG51bGxcblx0XHRcdFx0XHRcdHBhc3MoKVxuXHRcdFx0XHRcdH0pXG5cdFx0XHRcdH0pLFxuXHRcdFx0KVxuXHRcdFx0dGhpcy5kZWFkLnVzZShQcm9taXNlLmFsbCh0aGlzLnNlcnZpY2VzRGVhZCkpXG5cdFx0XHR0aGlzLnNlcnZpY2VzTGl2ZVt0aGlzLnNlcnZpY2VJZHhbc2VydmljZU5hbWVdXSA9IG5ldyBGdXR1cmUoKCkgPT4ge30pXG5cdFx0XHRpZiAodGhpcy5saXZlLmRvbmUpIHtcblx0XHRcdFx0dGhpcy5saXZlID0gbmV3IEZ1dHVyZSgoKSA9PiB7fSlcblx0XHRcdH1cblx0XHRcdHRoaXMubGl2ZS51c2UoUHJvbWlzZS5hbGwodGhpcy5zZXJ2aWNlc0xpdmUpKVxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnNlcnZpY2VMb2dnZXJzW3NlcnZpY2VOYW1lXS5lcnJvcihcblx0XHRcdFx0YFRyaWVkIHRvIHN0b3Agc2VydmljZSwgYnV0IGl0IHdhc24ndCBydW5uaW5nLmAsXG5cdFx0XHQpXG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBjb25zdCBGTElHSFRERUNLX0lORk8gPSBgaW5mb2BcbmV4cG9ydCBjb25zdCBGTElHSFRERUNLX1dBUk4gPSBgd2FybmBcbmV4cG9ydCBjb25zdCBGTElHSFRERUNLX0VSUk9SID0gYEVSUiFgXG5cbmV4cG9ydCBjb25zdCBmbGlnaHREZWNrTG9nU2NoZW1hID0gei5vYmplY3Qoe1xuXHRsZXZlbDogei51bmlvbihbXG5cdFx0ei5saXRlcmFsKEZMSUdIVERFQ0tfSU5GTyksXG5cdFx0ei5saXRlcmFsKEZMSUdIVERFQ0tfV0FSTiksXG5cdFx0ei5saXRlcmFsKEZMSUdIVERFQ0tfRVJST1IpLFxuXHRdKSxcblx0dGltZXN0YW1wOiB6Lm51bWJlcigpLFxuXHRwYWNrYWdlOiB6LnN0cmluZygpLFxuXHRzZXJ2aWNlOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG5cdHByb2Nlc3M6IHoubnVtYmVyKCksXG5cdGJvZHk6IHouc3RyaW5nKCksXG59KVxuZXhwb3J0IHR5cGUgRmxpZ2h0RGVja0xvZyA9IHouaW5mZXI8dHlwZW9mIGZsaWdodERlY2tMb2dTY2hlbWE+XG5cbmNvbnN0IExJTkVfRk9STUFUID0gYGxpbmUtZm9ybWF0YCBzYXRpc2ZpZXMga2V5b2YgTG5hdkZvcm1hdFxuY29uc3QgVkFMVUUgPSBgdmFsdWVgIHNhdGlzZmllcyBrZXlvZiBMbmF2Rm9ybWF0XG5cbmV4cG9ydCB0eXBlIExuYXZGb3JtYXRWaXN1YWxDb21wb25lbnQgPSBFeGNsdWRlPFxuXHRFeGNsdWRlPExuYXZGb3JtYXRbYGxpbmUtZm9ybWF0YF0sIHVuZGVmaW5lZD5bbnVtYmVyXSxcblx0c3RyaW5nXG4+XG5cbmV4cG9ydCB0eXBlIExuYXZGb3JtYXRCcmVha2Rvd24gPSBFeGNsdWRlPExuYXZGb3JtYXRbYHZhbHVlYF0sIHVuZGVmaW5lZD5cbmV4cG9ydCB0eXBlIE1lbWJlck9mPFQ+ID0gVFtrZXlvZiBUXVxuZXhwb3J0IHR5cGUgTG5hdkZvcm1hdFZhbHVlRGVmaW5pdGlvbiA9IE1lbWJlck9mPExuYXZGb3JtYXRCcmVha2Rvd24+XG5cbmV4cG9ydCB0eXBlIEZsaWdodERlY2tGb3JtYXQgPSB7XG5cdFtMSU5FX0ZPUk1BVF06IChcblx0XHR8IHN0cmluZ1xuXHRcdHwgKExuYXZGb3JtYXRWaXN1YWxDb21wb25lbnQgJiB7XG5cdFx0XHRcdGZpZWxkOiBrZXlvZiBGbGlnaHREZWNrTG9nIHwgYF9fbGV2ZWxfX2AgfCBgX190aW1lc3RhbXBfX2Bcblx0XHQgIH0pXG5cdClbXVxuXHRbVkFMVUVdOiB7XG5cdFx0W0sgaW4ga2V5b2YgRmxpZ2h0RGVja0xvZ106IExuYXZGb3JtYXRWYWx1ZURlZmluaXRpb24gJiB7XG5cdFx0XHRraW5kOiBGbGlnaHREZWNrTG9nW0tdIGV4dGVuZHMgbnVtYmVyIHwgdW5kZWZpbmVkXG5cdFx0XHRcdD8gYGludGVnZXJgXG5cdFx0XHRcdDogRmxpZ2h0RGVja0xvZ1tLXSBleHRlbmRzIHN0cmluZyB8IHVuZGVmaW5lZFxuXHRcdFx0XHRcdD8gYHN0cmluZ2Bcblx0XHRcdFx0XHQ6IG5ldmVyXG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBjb25zdCBGTElHSFRERUNLX0xOQVZfRk9STUFUID0ge1xuXHR0aXRsZTogYEZsaWdodERlY2sgTG9nYCxcblx0ZGVzY3JpcHRpb246IGBGb3JtYXQgZm9yIGV2ZW50cyBsb2dnZWQgYnkgdGhlIEZsaWdodERlY2sgcHJvY2VzcyBtYW5hZ2VyLmAsXG5cdFwiZmlsZS10eXBlXCI6IGBqc29uYCxcblx0XCJ0aW1lc3RhbXAtZmllbGRcIjogYHRpbWVzdGFtcGAsXG5cdFwidGltZXN0YW1wLWRpdmlzb3JcIjogMTAwMCxcblx0XCJtb2R1bGUtZmllbGRcIjogYHBhY2thZ2VgLFxuXHRcIm9waWQtZmllbGRcIjogYHNlcnZpY2VgLFxuXHRcImxldmVsLWZpZWxkXCI6IGBsZXZlbGAsXG5cdGxldmVsOiB7XG5cdFx0aW5mbzogRkxJR0hUREVDS19JTkZPLFxuXHRcdHdhcm5pbmc6IEZMSUdIVERFQ0tfV0FSTixcblx0XHRlcnJvcjogRkxJR0hUREVDS19FUlJPUixcblx0fSxcblxuXHRbTElORV9GT1JNQVRdOiBbXG5cdFx0e1xuXHRcdFx0ZmllbGQ6IGBsZXZlbGAsXG5cdFx0fSxcblx0XHR7XG5cdFx0XHRwcmVmaXg6IGAgYCxcblx0XHRcdGZpZWxkOiBgX190aW1lc3RhbXBfX2AsXG5cdFx0XHRcInRpbWVzdGFtcC1mb3JtYXRcIjogYCVZLSVtLSVkVCVIOiVNOiVTLiVMJVpgLFxuXHRcdH0sXG5cdFx0e1xuXHRcdFx0cHJlZml4OiBgIGAsXG5cdFx0XHRmaWVsZDogYHByb2Nlc3NgLFxuXHRcdFx0XCJtaW4td2lkdGhcIjogNSxcblx0XHR9LFxuXHRcdHtcblx0XHRcdHByZWZpeDogYDpgLFxuXHRcdFx0ZmllbGQ6IGBwYWNrYWdlYCxcblx0XHR9LFxuXHRcdHtcblx0XHRcdHByZWZpeDogYDpgLFxuXHRcdFx0ZmllbGQ6IGBzZXJ2aWNlYCxcblx0XHRcdFwiZGVmYXVsdC12YWx1ZVwiOiBgYCxcblx0XHR9LFxuXHRcdHtcblx0XHRcdHByZWZpeDogYDogYCxcblx0XHRcdGZpZWxkOiBgYm9keWAsXG5cdFx0fSxcblx0XSxcblxuXHRbVkFMVUVdOiB7XG5cdFx0dGltZXN0YW1wOiB7XG5cdFx0XHRraW5kOiBgaW50ZWdlcmAsXG5cdFx0fSxcblx0XHRsZXZlbDoge1xuXHRcdFx0a2luZDogYHN0cmluZ2AsXG5cdFx0fSxcblx0XHRwYWNrYWdlOiB7XG5cdFx0XHRraW5kOiBgc3RyaW5nYCxcblx0XHR9LFxuXHRcdHNlcnZpY2U6IHtcblx0XHRcdGtpbmQ6IGBzdHJpbmdgLFxuXHRcdH0sXG5cdFx0cHJvY2Vzczoge1xuXHRcdFx0a2luZDogYGludGVnZXJgLFxuXHRcdH0sXG5cdFx0Ym9keToge1xuXHRcdFx0a2luZDogYHN0cmluZ2AsXG5cdFx0fSxcblx0fSxcbn0gYXMgY29uc3Qgc2F0aXNmaWVzIEZsaWdodERlY2tGb3JtYXQgJiBMbmF2Rm9ybWF0XG5cbmV4cG9ydCBjbGFzcyBGbGlnaHREZWNrTG9nZ2VyXG5cdGltcGxlbWVudHMgUGljazxDb25zb2xlLCBgZXJyb3JgIHwgYGluZm9gIHwgYHdhcm5gPlxue1xuXHRwdWJsaWMgcmVhZG9ubHkgcGFja2FnZU5hbWU6IHN0cmluZ1xuXHRwdWJsaWMgcmVhZG9ubHkgc2VydmljZU5hbWU/OiBzdHJpbmdcblx0cHVibGljIHJlYWRvbmx5IGpzb25Mb2dnaW5nOiBib29sZWFuXG5cdHB1YmxpYyBwcm9jZXNzQ29kZTogbnVtYmVyXG5cdHB1YmxpYyBjb25zdHJ1Y3Rvcihcblx0XHRwYWNrYWdlTmFtZTogc3RyaW5nLFxuXHRcdHByb2Nlc3NDb2RlOiBudW1iZXIsXG5cdFx0c2VydmljZU5hbWU/OiBzdHJpbmcsXG5cdFx0b3B0aW9ucz86IHsganNvbkxvZ2dpbmc6IGJvb2xlYW4gfSxcblx0KSB7XG5cdFx0dGhpcy5wYWNrYWdlTmFtZSA9IHBhY2thZ2VOYW1lXG5cdFx0aWYgKHNlcnZpY2VOYW1lKSB7XG5cdFx0XHR0aGlzLnNlcnZpY2VOYW1lID0gc2VydmljZU5hbWVcblx0XHR9XG5cdFx0dGhpcy5wcm9jZXNzQ29kZSA9IHByb2Nlc3NDb2RlXG5cdFx0dGhpcy5qc29uTG9nZ2luZyA9IG9wdGlvbnM/Lmpzb25Mb2dnaW5nID8/IGZhbHNlXG5cdH1cblx0cHJvdGVjdGVkIGxvZyhcblx0XHRsZXZlbDpcblx0XHRcdHwgdHlwZW9mIEZMSUdIVERFQ0tfRVJST1Jcblx0XHRcdHwgdHlwZW9mIEZMSUdIVERFQ0tfSU5GT1xuXHRcdFx0fCB0eXBlb2YgRkxJR0hUREVDS19XQVJOLFxuXHRcdC4uLm1lc3NhZ2VzOiB1bmtub3duW11cblx0KTogdm9pZCB7XG5cdFx0aWYgKHRoaXMuanNvbkxvZ2dpbmcpIHtcblx0XHRcdGxldCBib2R5ID0gbWVzc2FnZXNcblx0XHRcdFx0Lm1hcCgobWVzc2FnZSkgPT5cblx0XHRcdFx0XHR0eXBlb2YgbWVzc2FnZSA9PT0gYHN0cmluZ2Bcblx0XHRcdFx0XHRcdD8gbWVzc2FnZVxuXHRcdFx0XHRcdFx0OiBpbnNwZWN0KG1lc3NhZ2UsIGZhbHNlLCBudWxsLCB0cnVlKSxcblx0XHRcdFx0KVxuXHRcdFx0XHQuam9pbihgIGApXG5cdFx0XHRpZiAoYm9keS5pbmNsdWRlcyhgXFxuYCkpIHtcblx0XHRcdFx0Ym9keSA9IGBcXG4gICR7Ym9keS5zcGxpdChgXFxuYCkuam9pbihgXFxuICBgKX1gXG5cdFx0XHR9XG5cdFx0XHRjb25zdCBsb2c6IEZsaWdodERlY2tMb2cgPSB7XG5cdFx0XHRcdHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcblx0XHRcdFx0bGV2ZWwsXG5cdFx0XHRcdHByb2Nlc3M6IHRoaXMucHJvY2Vzc0NvZGUsXG5cdFx0XHRcdHBhY2thZ2U6IHRoaXMucGFja2FnZU5hbWUsXG5cdFx0XHRcdGJvZHksXG5cdFx0XHR9XG5cdFx0XHRpZiAodGhpcy5zZXJ2aWNlTmFtZSkge1xuXHRcdFx0XHRsb2cuc2VydmljZSA9IHRoaXMuc2VydmljZU5hbWVcblx0XHRcdH1cblx0XHRcdHByb2Nlc3Muc3Rkb3V0LndyaXRlKEpTT04uc3RyaW5naWZ5KGxvZykgKyBgXFxuYClcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y29uc3Qgc291cmNlID0gdGhpcy5zZXJ2aWNlTmFtZVxuXHRcdFx0XHQ/IGAke3RoaXMucGFja2FnZU5hbWV9OiR7dGhpcy5zZXJ2aWNlTmFtZX1gXG5cdFx0XHRcdDogdGhpcy5wYWNrYWdlTmFtZVxuXHRcdFx0c3dpdGNoIChsZXZlbCkge1xuXHRcdFx0XHRjYXNlIEZMSUdIVERFQ0tfSU5GTzpcblx0XHRcdFx0XHRjb25zb2xlLmxvZyhgJHtzb3VyY2V9OmAsIC4uLm1lc3NhZ2VzKVxuXHRcdFx0XHRcdGJyZWFrXG5cdFx0XHRcdGNhc2UgRkxJR0hUREVDS19XQVJOOlxuXHRcdFx0XHRcdGNvbnNvbGUud2FybihgJHtzb3VyY2V9OmAsIC4uLm1lc3NhZ2VzKVxuXHRcdFx0XHRcdGJyZWFrXG5cdFx0XHRcdGNhc2UgRkxJR0hUREVDS19FUlJPUjpcblx0XHRcdFx0XHRjb25zb2xlLmVycm9yKGAke3NvdXJjZX06YCwgLi4ubWVzc2FnZXMpXG5cdFx0XHRcdFx0YnJlYWtcblx0XHRcdH1cblx0XHR9XG5cdH1cblx0cHVibGljIGluZm8oLi4ubWVzc2FnZXM6IHVua25vd25bXSk6IHZvaWQge1xuXHRcdHRoaXMubG9nKEZMSUdIVERFQ0tfSU5GTywgLi4ubWVzc2FnZXMpXG5cdH1cblxuXHRwdWJsaWMgd2FybiguLi5tZXNzYWdlczogdW5rbm93bltdKTogdm9pZCB7XG5cdFx0dGhpcy5sb2coRkxJR0hUREVDS19XQVJOLCAuLi5tZXNzYWdlcylcblx0fVxuXG5cdHB1YmxpYyBlcnJvciguLi5tZXNzYWdlczogdW5rbm93bltdKTogdm9pZCB7XG5cdFx0dGhpcy5sb2coRkxJR0hUREVDS19FUlJPUiwgLi4ubWVzc2FnZXMpXG5cdH1cbn1cbiIsCiAgICAiaW1wb3J0IHsgY3JlYXRlRW52IH0gZnJvbSBcIkB0My1vc3MvZW52LWNvcmVcIlxuaW1wb3J0IHsgeiB9IGZyb20gXCJ6b2RcIlxuXG5leHBvcnQgY29uc3QgZW52ID0gY3JlYXRlRW52KHtcblx0c2VydmVyOiB7IEZMSUdIVERFQ0tfU0VDUkVUOiB6LnN0cmluZygpLm9wdGlvbmFsKCkgfSxcblx0Y2xpZW50UHJlZml4OiBgTkVWRVJgLFxuXHRjbGllbnQ6IHt9LFxuXHRydW50aW1lRW52OiBpbXBvcnQubWV0YS5lbnYsXG5cdGVtcHR5U3RyaW5nQXNVbmRlZmluZWQ6IHRydWUsXG59KVxuIiwKICAgICJleHBvcnQgdHlwZSBBbGVydE9wdGlvbnMgPSB7XG5cdHNlY3JldDogc3RyaW5nXG5cdGVuZHBvaW50OiBzdHJpbmdcblx0dmVyc2lvbjogc3RyaW5nXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhbGVydCh7XG5cdHNlY3JldCxcblx0ZW5kcG9pbnQsXG5cdHZlcnNpb24sXG59OiBBbGVydE9wdGlvbnMpOiBQcm9taXNlPFJlc3BvbnNlPiB7XG5cdGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goZW5kcG9pbnQsIHtcblx0XHRtZXRob2Q6IGBQT1NUYCxcblx0XHRoZWFkZXJzOiB7XG5cdFx0XHRcIkNvbnRlbnQtVHlwZVwiOiBgdGV4dC9wbGFpbjtjaGFyc2V0PVVURi04YCxcblx0XHRcdEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtzZWNyZXR9YCxcblx0XHR9LFxuXHRcdGJvZHk6IHZlcnNpb24sXG5cdH0pXG5cblx0cmV0dXJuIHJlc3BvbnNlXG59XG5cbi8qKlxuICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vY2hhbmdlc2V0cy9hY3Rpb24vYmxvYi9tYWluL3NyYy9ydW4udHNcbiAqL1xuZXhwb3J0IHR5cGUgQ2hhbmdlc2V0c1B1Ymxpc2hlZFBhY2thZ2UgPSB7XG5cdG5hbWU6IHN0cmluZ1xuXHR2ZXJzaW9uOiBzdHJpbmdcbn1cblxuLyoqXG4gKiBAc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9jaGFuZ2VzZXRzL2FjdGlvbi9ibG9iL21haW4vc3JjL3J1bi50c1xuICovXG5leHBvcnQgdHlwZSBDaGFuZ2VzZXRzUHVibGlzaFJlc3VsdCA9XG5cdHwge1xuXHRcdFx0cHVibGlzaGVkOiB0cnVlXG5cdFx0XHRwdWJsaXNoZWRQYWNrYWdlczogQ2hhbmdlc2V0c1B1Ymxpc2hlZFBhY2thZ2VbXVxuXHQgIH1cblx0fCB7IHB1Ymxpc2hlZDogZmFsc2UgfVxuXG5leHBvcnQgdHlwZSBQYWNrYWdlQ29uZmlnPEsgZXh0ZW5kcyBzdHJpbmc+ID0ge1xuXHRba2V5IGluIEtdOiB7IGVuZHBvaW50OiBzdHJpbmcgfVxufVxuZXhwb3J0IHR5cGUgU2VjcmV0c0NvbmZpZzxLIGV4dGVuZHMgc3RyaW5nPiA9IHtcblx0W2tleSBpbiBLXTogc3RyaW5nXG59XG5cbmV4cG9ydCB0eXBlIFNjcmFtYmxlT3B0aW9uczxLIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nPiA9IHtcblx0cGFja2FnZUNvbmZpZzogUGFja2FnZUNvbmZpZzxLPlxuXHRzZWNyZXRzQ29uZmlnOiBTZWNyZXRzQ29uZmlnPEs+XG5cdHB1Ymxpc2hlZFBhY2thZ2VzOiBDaGFuZ2VzZXRzUHVibGlzaGVkUGFja2FnZVtdXG59XG5cbmV4cG9ydCB0eXBlIFNjcmFtYmxlUmVzdWx0PEsgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmc+ID0ge1xuXHRba2V5IGluIEtdOiBSZXNwb25zZVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2NyYW1ibGU8SyBleHRlbmRzIHN0cmluZyA9IHN0cmluZz4oe1xuXHRwYWNrYWdlQ29uZmlnLFxuXHRzZWNyZXRzQ29uZmlnLFxuXHRwdWJsaXNoZWRQYWNrYWdlcyxcbn06IFNjcmFtYmxlT3B0aW9uczxLPik6IFByb21pc2U8U2NyYW1ibGVSZXN1bHQ8Sz4+IHtcblx0Y29uc3QgYWxlcnRSZXN1bHRzOiBQcm9taXNlPHJlYWRvbmx5IFtLLCBSZXNwb25zZV0+W10gPSBbXVxuXHRmb3IgKGNvbnN0IHB1Ymxpc2hlZFBhY2thZ2Ugb2YgcHVibGlzaGVkUGFja2FnZXMpIHtcblx0XHRpZiAocHVibGlzaGVkUGFja2FnZS5uYW1lIGluIHBhY2thZ2VDb25maWcpIHtcblx0XHRcdGNvbnN0IG5hbWUgPSBwdWJsaXNoZWRQYWNrYWdlLm5hbWUgYXMgS1xuXHRcdFx0Y29uc3QgeyBlbmRwb2ludCB9ID0gcGFja2FnZUNvbmZpZ1tuYW1lXVxuXHRcdFx0Y29uc3Qgc2VjcmV0ID0gc2VjcmV0c0NvbmZpZ1tuYW1lXVxuXHRcdFx0Y29uc3QgdmVyc2lvbiA9IHB1Ymxpc2hlZFBhY2thZ2UudmVyc2lvblxuXHRcdFx0Y29uc3QgYWxlcnRSZXN1bHRQcm9taXNlID0gYWxlcnQoeyBzZWNyZXQsIGVuZHBvaW50LCB2ZXJzaW9uIH0pLnRoZW4oXG5cdFx0XHRcdChhbGVydFJlc3VsdCkgPT4gW25hbWUsIGFsZXJ0UmVzdWx0XSBhcyBjb25zdCxcblx0XHRcdClcblx0XHRcdGFsZXJ0UmVzdWx0cy5wdXNoKGFsZXJ0UmVzdWx0UHJvbWlzZSlcblx0XHR9XG5cdH1cblx0Y29uc3QgYWxlcnRSZXN1bHRzUmVzb2x2ZWQgPSBhd2FpdCBQcm9taXNlLmFsbChhbGVydFJlc3VsdHMpXG5cdGNvbnN0IHNjcmFtYmxlUmVzdWx0ID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuXHRcdGFsZXJ0UmVzdWx0c1Jlc29sdmVkLFxuXHQpIGFzIFNjcmFtYmxlUmVzdWx0PEs+XG5cdHJldHVybiBzY3JhbWJsZVJlc3VsdFxufVxuIgogIF0sCiAgIm1hcHBpbmdzIjogIjhIQUFBLHFCQUNDLGVBQ0EsaUJBQ0Esa0JBQ0EsWUFDQSxjQUNBLG1CQUNBLGdCQUVELGtCQUFTLGtCQU1GLE1BQU0sQ0FHYixDQUNRLFFBRUEsV0FBVyxDQUFDLEVBQW1DLENBRXJELEdBREEsS0FBSyxRQUFVLEVBQVEsTUFDbEIsRUFBVyxLQUFLLE9BQU8sRUFDM0IsRUFBVSxLQUFLLFFBQVMsQ0FBRSxVQUFXLEVBQUssQ0FBQyxFQUl0QyxPQUFtQyxDQUFDLEVBQXFCLENBQy9ELElBQU0sRUFBVyxFQUFRLEtBQUssUUFBUyxDQUFHLEVBQzFDLEdBQUksRUFBVyxDQUFRLEVBQ3RCLE9BQU8sRUFBYSxFQUFVLE9BQU8sRUFFdEMsT0FBTyxLQUdELE9BQW1DLENBQUMsRUFBUSxFQUFtQixDQUNyRSxJQUFNLEVBQVcsRUFBUSxLQUFLLFFBQVMsQ0FBRyxFQUMxQyxFQUFjLEVBQVUsQ0FBSyxFQUd2QixVQUFzQyxDQUFDLEVBQWMsQ0FDM0QsSUFBTSxFQUFXLEVBQVEsS0FBSyxRQUFTLENBQUcsRUFDMUMsR0FBSSxFQUFXLENBQVEsRUFDdEIsRUFBTyxDQUFRLEVBSVYsR0FBRyxDQUFDLEVBQTBDLENBT3BELE9BTmtCLEVBQVksS0FBSyxPQUFPLEVBQ0QsS0FBSyxDQUFDLEVBQUcsSUFBTSxDQUN2RCxJQUFNLEVBQVEsRUFBUyxDQUFDLEVBRXhCLE9BRGMsRUFBUyxDQUFDLEVBQ1gsUUFBVSxFQUFNLFFBQzdCLEVBQzhCLElBQStC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RUFBSyxTQUFTO0FBQUEsQ0FBSSxFQUNyQixFQUFPO0FBQUEsSUFBTyxFQUFLLE1BQU07QUFBQSxDQUFJLEVBQUUsS0FBSztBQUFBLEdBQU0sSUFFM0MsSUFBTSxFQUFxQixDQUMxQixVQUFXLEtBQUssSUFBSSxFQUNwQixRQUNBLFFBQVMsS0FBSyxZQUNkLFFBQVMsS0FBSyxZQUNkLE1BQ0QsRUFDQSxHQUFJLEtBQUssWUFDUixFQUFJLFFBQVUsS0FBSyxZQUVwQixRQUFRLE9BQU8sTUFBTSxLQUFLLFVBQVUsQ0FBRyxFQUFJO0FBQUEsQ0FBSSxNQUN6QyxDQUNOLElBQU0sRUFBUyxLQUFLLFlBQ2pCLEdBQUcsS0FBSyxlQUFlLEtBQUssY0FDNUIsS0FBSyxZQUNSLE9BQVEsUUFDRixFQUNKLFFBQVEsSUFBSSxHQUFHLEtBQVcsR0FBRyxDQUFRLEVBQ3JDLFdBQ0ksRUFDSixRQUFRLEtBQUssR0FBRyxLQUFXLEdBQUcsQ0FBUSxFQUN0QyxXQUNJLEVBQ0osUUFBUSxNQUFNLEdBQUcsS0FBVyxHQUFHLENBQVEsRUFDdkMsUUFJRyxJQUFJLElBQUksRUFBMkIsQ0FDekMsS0FBSyxJQUFJLEVBQWlCLEdBQUcsQ0FBUSxFQUcvQixJQUFJLElBQUksRUFBMkIsQ0FDekMsS0FBSyxJQUFJLEVBQWlCLEdBQUcsQ0FBUSxFQUcvQixLQUFLLElBQUksRUFBMkIsQ0FDMUMsS0FBSyxJQUFJLEVBQWtCLEdBQUcsQ0FBUSxFQUV4Qyw0Q0VqbkJBLGVBQXNCLENBQUssRUFDMUIsU0FDQSxXQUNBLFdBQ21DLENBVW5DLE9BVGlCLE1BQU0sTUFBTSxFQUFVLENBQ3RDLE9BQVEsT0FDUixRQUFTLENBQ1IsZUFBZ0IsMkJBQ2hCLGNBQWUsVUFBVSxHQUMxQixFQUNBLEtBQU0sQ0FDUCxDQUFDLEVBd0NGLGVBQXNCLENBQW1DLEVBQ3hELGdCQUNBLGdCQUNBLHFCQUNrRCxDQUNsRCxJQUFNLEVBQWtELENBQUMsRUFDekQsUUFBVyxLQUFvQixFQUM5QixHQUFJLEVBQWlCLFFBQVEsRUFBZSxDQUMzQyxJQUFNLEVBQU8sRUFBaUIsTUFDdEIsWUFBYSxFQUFjLEdBQzdCLEVBQVMsRUFBYyxHQUN2QixFQUFVLEVBQWlCLFFBQzNCLEVBQXFCLEVBQU0sQ0FBRSxTQUFRLFdBQVUsU0FBUSxDQUFDLEVBQUUsS0FDL0QsQ0FBQyxJQUFnQixDQUFDLEVBQU0sQ0FBVyxDQUNwQyxFQUNBLEVBQWEsS0FBSyxDQUFrQixFQUd0QyxJQUFNLEVBQXVCLE1BQU0sUUFBUSxJQUFJLENBQVksRUFJM0QsT0FIdUIsT0FBTyxZQUM3QixDQUNEIiwKICAiZGVidWdJZCI6ICIxNkEwMkZGQjAzNTBCQ0ZGNjQ3NTZFMjE2NDc1NkUyMSIsCiAgIm5hbWVzIjogW10KfQ==
8
+ //# debugId=F5FF89C57D926E5564756E2164756E21
9
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2ZsaWdodGRlY2subGliLnRzIiwgIi4uL3NyYy9mbGlnaHRkZWNrLmVudi50cyIsICIuLi9zcmMva2xheG9uLmxpYi50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsKICAgICJpbXBvcnQgeyBleGVjU3luYywgc3Bhd24gfSBmcm9tIFwibm9kZTpjaGlsZF9wcm9jZXNzXCJcbmltcG9ydCB0eXBlIHsgU2VydmVyIH0gZnJvbSBcIm5vZGU6aHR0cFwiXG5pbXBvcnQgeyBjcmVhdGVTZXJ2ZXIgfSBmcm9tIFwibm9kZTpodHRwXCJcbmltcG9ydCB7IGhvbWVkaXIgfSBmcm9tIFwibm9kZTpvc1wiXG5pbXBvcnQgeyByZXNvbHZlIH0gZnJvbSBcIm5vZGU6cGF0aFwiXG5pbXBvcnQgeyBpbnNwZWN0IH0gZnJvbSBcIm5vZGU6dXRpbFwiXG5cbmltcG9ydCB7IEZ1dHVyZSB9IGZyb20gXCJhdG9tLmlvL2ludGVybmFsXCJcbmltcG9ydCB7IGRpc2NvdmVyVHlwZSB9IGZyb20gXCJhdG9tLmlvL2ludHJvc3BlY3Rpb25cIlxuaW1wb3J0IHsgZnJvbUVudHJpZXMsIHRvRW50cmllcyB9IGZyb20gXCJhdG9tLmlvL2pzb25cIlxuaW1wb3J0IHsgQ2hpbGRTb2NrZXQgfSBmcm9tIFwiYXRvbS5pby9yZWFsdGltZS1zZXJ2ZXJcIlxuaW1wb3J0IHsgQ3JvbkpvYiB9IGZyb20gXCJjcm9uXCJcbmltcG9ydCB7IEZpbGVzeXN0ZW1TdG9yYWdlIH0gZnJvbSBcInNhZmVkZXBvc2l0XCJcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCJcblxuaW1wb3J0IHR5cGUgeyBMbmF2Rm9ybWF0IH0gZnJvbSBcIi4uL2dlbi9sbmF2LWZvcm1hdC1zY2hlbWEuZ2VuXCJcbmltcG9ydCB7IGVudiB9IGZyb20gXCIuL2ZsaWdodGRlY2suZW52XCJcblxuZXhwb3J0IGNvbnN0IEZMSUdIVERFQ0tfU0VUVVBfUEhBU0VTID0gW2Bkb3dubG9hZGVkYCwgYGluc3RhbGxlZGBdIGFzIGNvbnN0XG5cbmV4cG9ydCB0eXBlIEZsaWdodERlY2tTZXR1cFBoYXNlID0gKHR5cGVvZiBGTElHSFRERUNLX1NFVFVQX1BIQVNFUylbbnVtYmVyXVxuXG5leHBvcnQgY29uc3QgRkxJR0hUREVDS19VUERBVEVfUEhBU0VTID0gW2Bub3RpZmllZGAsIGBjb25maXJtZWRgXSBhcyBjb25zdFxuXG5leHBvcnQgdHlwZSBGbGlnaHREZWNrVXBkYXRlUGhhc2UgPSAodHlwZW9mIEZMSUdIVERFQ0tfVVBEQVRFX1BIQVNFUylbbnVtYmVyXVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWZXJzaW9uTnVtYmVyKHZlcnNpb246IHN0cmluZyk6IGJvb2xlYW4ge1xuXHRyZXR1cm4gKFxuXHRcdC9eXFxkK1xcLlxcZCtcXC5cXGQrJC8udGVzdCh2ZXJzaW9uKSB8fCAhTnVtYmVyLmlzTmFOKE51bWJlci5wYXJzZUZsb2F0KHZlcnNpb24pKVxuXHQpXG59XG5cbmV4cG9ydCB0eXBlIEZsaWdodERlY2tPcHRpb25zPFMgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmc+ID0ge1xuXHRwYWNrYWdlTmFtZTogc3RyaW5nXG5cdHNlcnZpY2VzOiB7IFtzZXJ2aWNlIGluIFNdOiB7IHJ1bjogc3RyaW5nOyB3YWl0Rm9yOiBib29sZWFuIH0gfVxuXHRzY3JpcHRzOiB7XG5cdFx0ZG93bmxvYWQ6IHN0cmluZ1xuXHRcdGluc3RhbGw6IHN0cmluZ1xuXHRcdGNoZWNrQXZhaWxhYmlsaXR5Pzogc3RyaW5nXG5cdH1cblx0cG9ydD86IG51bWJlciB8IHVuZGVmaW5lZFxuXHRmbGlnaHRkZWNrUm9vdERpcj86IHN0cmluZyB8IHVuZGVmaW5lZFxuXHRqc29uTG9nZ2luZz86IGJvb2xlYW4gfCB1bmRlZmluZWRcbn1cblxuZXhwb3J0IGNsYXNzIEZsaWdodERlY2s8UyBleHRlbmRzIHN0cmluZyA9IHN0cmluZz4ge1xuXHRwcm90ZWN0ZWQgc2FmZXR5ID0gMFxuXG5cdHByb3RlY3RlZCBzdG9yYWdlOiBGaWxlc3lzdGVtU3RvcmFnZTx7XG5cdFx0c2V0dXBQaGFzZTogRmxpZ2h0RGVja1NldHVwUGhhc2Vcblx0XHR1cGRhdGVQaGFzZTogRmxpZ2h0RGVja1VwZGF0ZVBoYXNlXG5cdFx0dXBkYXRlQXdhaXRlZFZlcnNpb246IHN0cmluZ1xuXHR9PlxuXHRwcm90ZWN0ZWQgd2ViaG9va1NlcnZlcjogU2VydmVyXG5cdHByb3RlY3RlZCBzZXJ2aWNlczoge1xuXHRcdFtzZXJ2aWNlIGluIFNdOiBDaGlsZFNvY2tldDxcblx0XHRcdHsgdGltZVRvU3RvcDogW107IHVwZGF0ZXNSZWFkeTogW10gfSxcblx0XHRcdHsgcmVhZHlUb1VwZGF0ZTogW107IGFsaXZlOiBbXSB9XG5cdFx0PiB8IG51bGxcblx0fVxuXHRwcm90ZWN0ZWQgc2VydmljZUlkeDogeyByZWFkb25seSBbc2VydmljZSBpbiBTXTogbnVtYmVyIH1cblx0cHVibGljIGRlZmF1bHRTZXJ2aWNlc1JlYWR5VG9VcGRhdGU6IHsgcmVhZG9ubHkgW3NlcnZpY2UgaW4gU106IGJvb2xlYW4gfVxuXHRwdWJsaWMgc2VydmljZXNSZWFkeVRvVXBkYXRlOiB7IFtzZXJ2aWNlIGluIFNdOiBib29sZWFuIH1cblx0cHVibGljIGF1dG9SZXNwYXduRGVhZFNlcnZpY2VzOiBib29sZWFuXG5cblx0cHJvdGVjdGVkIGxvZ2dlcjogUGljazxDb25zb2xlLCBgZXJyb3JgIHwgYGluZm9gIHwgYHdhcm5gPlxuXHRwcm90ZWN0ZWQgc2VydmljZUxvZ2dlcnM6IHtcblx0XHRyZWFkb25seSBbc2VydmljZSBpbiBTXTogRmxpZ2h0RGVja0xvZ2dlclxuXHR9XG5cblx0cHJvdGVjdGVkIHVwZGF0ZUF2YWlsYWJpbGl0eUNoZWNrZXI6IENyb25Kb2IgfCBudWxsID0gbnVsbFxuXG5cdHB1YmxpYyBzZXJ2aWNlc0xpdmU6IEZ1dHVyZTx2b2lkPltdXG5cdHB1YmxpYyBzZXJ2aWNlc0RlYWQ6IEZ1dHVyZTx2b2lkPltdXG5cdHB1YmxpYyBsaXZlID0gbmV3IEZ1dHVyZSgoKSA9PiB7fSlcblx0cHVibGljIGRlYWQgPSBuZXcgRnV0dXJlKCgpID0+IHt9KVxuXG5cdHByb3RlY3RlZCByZXN0YXJ0VGltZXM6IG51bWJlcltdID0gW11cblxuXHRwdWJsaWMgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IG9wdGlvbnM6IEZsaWdodERlY2tPcHRpb25zPFM+KSB7XG5cdFx0Y29uc3QgeyBGTElHSFRERUNLX1NFQ1JFVCB9ID0gZW52XG5cdFx0Y29uc3QgeyBmbGlnaHRkZWNrUm9vdERpciA9IHJlc29sdmUoaG9tZWRpcigpLCBgLmZsaWdodGRlY2tgKSB9ID0gb3B0aW9uc1xuXHRcdGNvbnN0IHBvcnQgPSBvcHRpb25zLnBvcnQgPz8gODA4MFxuXHRcdGNvbnN0IG9yaWdpbiA9IGBodHRwOi8vbG9jYWxob3N0OiR7cG9ydH1gXG5cblx0XHRjb25zdCBzZXJ2aWNlc0VudHJpZXMgPSB0b0VudHJpZXMob3B0aW9ucy5zZXJ2aWNlcylcblx0XHR0aGlzLnNlcnZpY2VzID0gZnJvbUVudHJpZXMoXG5cdFx0XHRzZXJ2aWNlc0VudHJpZXMubWFwKChbc2VydmljZU5hbWVdKSA9PiBbc2VydmljZU5hbWUsIG51bGxdKSxcblx0XHQpXG5cdFx0dGhpcy5zZXJ2aWNlSWR4ID0gZnJvbUVudHJpZXMoXG5cdFx0XHRzZXJ2aWNlc0VudHJpZXMubWFwKChbc2VydmljZU5hbWVdLCBpZHgpID0+IFtzZXJ2aWNlTmFtZSwgaWR4XSksXG5cdFx0KVxuXHRcdHRoaXMuZGVmYXVsdFNlcnZpY2VzUmVhZHlUb1VwZGF0ZSA9IGZyb21FbnRyaWVzKFxuXHRcdFx0c2VydmljZXNFbnRyaWVzLm1hcCgoW3NlcnZpY2VOYW1lLCB7IHdhaXRGb3IgfV0pID0+IFtcblx0XHRcdFx0c2VydmljZU5hbWUsXG5cdFx0XHRcdCF3YWl0Rm9yLFxuXHRcdFx0XSksXG5cdFx0KVxuXHRcdHRoaXMuc2VydmljZXNSZWFkeVRvVXBkYXRlID0geyAuLi50aGlzLmRlZmF1bHRTZXJ2aWNlc1JlYWR5VG9VcGRhdGUgfVxuXHRcdHRoaXMuYXV0b1Jlc3Bhd25EZWFkU2VydmljZXMgPSB0cnVlXG5cblx0XHR0aGlzLmxvZ2dlciA9IG5ldyBGbGlnaHREZWNrTG9nZ2VyKFxuXHRcdFx0dGhpcy5vcHRpb25zLnBhY2thZ2VOYW1lLFxuXHRcdFx0cHJvY2Vzcy5waWQsXG5cdFx0XHR1bmRlZmluZWQsXG5cdFx0XHR7IGpzb25Mb2dnaW5nOiB0aGlzLm9wdGlvbnMuanNvbkxvZ2dpbmcgPz8gZmFsc2UgfSxcblx0XHQpXG5cdFx0dGhpcy5zZXJ2aWNlTG9nZ2VycyA9IGZyb21FbnRyaWVzKFxuXHRcdFx0c2VydmljZXNFbnRyaWVzLm1hcCgoW3NlcnZpY2VOYW1lXSkgPT4gW1xuXHRcdFx0XHRzZXJ2aWNlTmFtZSxcblx0XHRcdFx0bmV3IEZsaWdodERlY2tMb2dnZXIoXG5cdFx0XHRcdFx0dGhpcy5vcHRpb25zLnBhY2thZ2VOYW1lLFxuXHRcdFx0XHRcdHByb2Nlc3MucGlkLFxuXHRcdFx0XHRcdHNlcnZpY2VOYW1lLFxuXHRcdFx0XHRcdHsganNvbkxvZ2dpbmc6IHRoaXMub3B0aW9ucy5qc29uTG9nZ2luZyA/PyBmYWxzZSB9LFxuXHRcdFx0XHQpLFxuXHRcdFx0XSksXG5cdFx0KVxuXG5cdFx0dGhpcy5zZXJ2aWNlc0xpdmUgPSBzZXJ2aWNlc0VudHJpZXMubWFwKCgpID0+IG5ldyBGdXR1cmUoKCkgPT4ge30pKVxuXHRcdHRoaXMuc2VydmljZXNEZWFkID0gc2VydmljZXNFbnRyaWVzLm1hcCgoKSA9PiBuZXcgRnV0dXJlKCgpID0+IHt9KSlcblx0XHR0aGlzLmxpdmUudXNlKFByb21pc2UuYWxsKHRoaXMuc2VydmljZXNMaXZlKSlcblx0XHR0aGlzLmRlYWQudXNlKFByb21pc2UuYWxsKHRoaXMuc2VydmljZXNEZWFkKSlcblxuXHRcdHRoaXMuc3RvcmFnZSA9IG5ldyBGaWxlc3lzdGVtU3RvcmFnZSh7XG5cdFx0XHRwYXRoOiByZXNvbHZlKGZsaWdodGRlY2tSb290RGlyLCBgc3RvcmFnZWAsIG9wdGlvbnMucGFja2FnZU5hbWUpLFxuXHRcdH0pXG5cblx0XHRpZiAoRkxJR0hUREVDS19TRUNSRVQgPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0dGhpcy5sb2dnZXIud2Fybihcblx0XHRcdFx0YE5vIEZMSUdIVERFQ0tfU0VDUkVUIGVudmlyb25tZW50IHZhcmlhYmxlIGZvdW5kLiBGbGlnaHREZWNrIHdpbGwgbm90IHJ1biBhbiB1cGRhdGUgc2VydmVyLmAsXG5cdFx0XHQpXG5cdFx0fSBlbHNlIHtcblx0XHRcdGNyZWF0ZVNlcnZlcigocmVxLCByZXMpID0+IHtcblx0XHRcdFx0bGV0IGRhdGE6IFVpbnQ4QXJyYXlbXSA9IFtdXG5cdFx0XHRcdHJlcVxuXHRcdFx0XHRcdC5vbihgZGF0YWAsIChjaHVuaykgPT4ge1xuXHRcdFx0XHRcdFx0ZGF0YS5wdXNoKGNodW5rIGluc3RhbmNlb2YgQnVmZmVyID8gY2h1bmsgOiBCdWZmZXIuZnJvbShjaHVuaykpXG5cdFx0XHRcdFx0fSlcblx0XHRcdFx0XHQub24oYGVuZGAsICgpID0+IHtcblx0XHRcdFx0XHRcdGNvbnN0IGF1dGhIZWFkZXIgPSByZXEuaGVhZGVycy5hdXRob3JpemF0aW9uXG5cdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRpZiAodHlwZW9mIHJlcS51cmwgPT09IGB1bmRlZmluZWRgKSB0aHJvdyA0MDBcblx0XHRcdFx0XHRcdFx0Y29uc3QgZXhwZWN0ZWRBdXRoSGVhZGVyID0gYEJlYXJlciAke0ZMSUdIVERFQ0tfU0VDUkVUfWBcblx0XHRcdFx0XHRcdFx0aWYgKGF1dGhIZWFkZXIgIT09IGBCZWFyZXIgJHtGTElHSFRERUNLX1NFQ1JFVH1gKSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhcblx0XHRcdFx0XHRcdFx0XHRcdGBVbmF1dGhvcml6ZWQ6IG5lZWRlZCBcXGAke2V4cGVjdGVkQXV0aEhlYWRlcn1cXGAsIGdvdCBcXGAke2F1dGhIZWFkZXJ9XFxgYCxcblx0XHRcdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHRcdFx0dGhyb3cgNDAxXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0Y29uc3QgdXJsID0gbmV3IFVSTChyZXEudXJsLCBvcmlnaW4pXG5cdFx0XHRcdFx0XHRcdHRoaXMubG9nZ2VyLmluZm8ocmVxLm1ldGhvZCwgdXJsLnBhdGhuYW1lKVxuXG5cdFx0XHRcdFx0XHRcdGNvbnN0IHZlcnNpb25Gb3JlaWduSW5wdXQgPSBCdWZmZXIuY29uY2F0KGRhdGEpLnRvU3RyaW5nKClcblx0XHRcdFx0XHRcdFx0aWYgKCFpc1ZlcnNpb25OdW1iZXIodmVyc2lvbkZvcmVpZ25JbnB1dCkpIHtcblx0XHRcdFx0XHRcdFx0XHR0aHJvdyA0MDBcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdHJlcy53cml0ZUhlYWQoMjAwKVxuXHRcdFx0XHRcdFx0XHRyZXMuZW5kKClcblxuXHRcdFx0XHRcdFx0XHR0aGlzLnN0b3JhZ2Uuc2V0SXRlbShgdXBkYXRlUGhhc2VgLCBgbm90aWZpZWRgKVxuXHRcdFx0XHRcdFx0XHR0aGlzLnN0b3JhZ2Uuc2V0SXRlbShgdXBkYXRlQXdhaXRlZFZlcnNpb25gLCB2ZXJzaW9uRm9yZWlnbklucHV0KVxuXHRcdFx0XHRcdFx0XHRjb25zdCB7IGNoZWNrQXZhaWxhYmlsaXR5IH0gPSBvcHRpb25zLnNjcmlwdHNcblx0XHRcdFx0XHRcdFx0aWYgKGNoZWNrQXZhaWxhYmlsaXR5KSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhpcy51cGRhdGVBdmFpbGFiaWxpdHlDaGVja2VyPy5zdG9wKClcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnNlZWtVcGRhdGUodmVyc2lvbkZvcmVpZ25JbnB1dClcblx0XHRcdFx0XHRcdFx0XHRjb25zdCB1cGRhdGVQaGFzZSA9IHRoaXMuc3RvcmFnZS5nZXRJdGVtKGB1cGRhdGVQaGFzZWApXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgPiBzdG9yYWdlKFwidXBkYXRlUGhhc2VcIikgPmAsIHVwZGF0ZVBoYXNlKVxuXHRcdFx0XHRcdFx0XHRcdGlmICh1cGRhdGVQaGFzZSA9PT0gYG5vdGlmaWVkYCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0dGhpcy51cGRhdGVBdmFpbGFiaWxpdHlDaGVja2VyID0gbmV3IENyb25Kb2IoXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGAzMCAqICogKiAqICpgLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHQoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0dGhpcy5zZWVrVXBkYXRlKHZlcnNpb25Gb3JlaWduSW5wdXQpXG5cdFx0XHRcdFx0XHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHRcdFx0XHR0aGlzLnVwZGF0ZUF2YWlsYWJpbGl0eUNoZWNrZXIuc3RhcnQoKVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmRvd25sb2FkUGFja2FnZSgpXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0gY2F0Y2ggKHRocm93bikge1xuXHRcdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcih0aHJvd24sIHJlcS51cmwpXG5cdFx0XHRcdFx0XHRcdGlmICh0eXBlb2YgdGhyb3duID09PSBgbnVtYmVyYCkge1xuXHRcdFx0XHRcdFx0XHRcdHJlcy53cml0ZUhlYWQodGhyb3duKVxuXHRcdFx0XHRcdFx0XHRcdHJlcy5lbmQoKVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9IGZpbmFsbHkge1xuXHRcdFx0XHRcdFx0XHRkYXRhID0gW11cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KVxuXHRcdFx0fSkubGlzdGVuKHBvcnQsICgpID0+IHtcblx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgU2VydmVyIHN0YXJ0ZWQgb24gcG9ydCAke3BvcnR9YClcblx0XHRcdH0pXG5cdFx0fVxuXG5cdFx0dGhpcy5zdGFydEFsbFNlcnZpY2VzKClcblx0XHRcdC50aGVuKCgpID0+IHtcblx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgQWxsIHNlcnZpY2VzIHN0YXJ0ZWQuYClcblx0XHRcdH0pXG5cdFx0XHQuY2F0Y2goKHRocm93bikgPT4ge1xuXHRcdFx0XHRpZiAodGhyb3duIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIHN0YXJ0IGFsbCBzZXJ2aWNlczpgLCB0aHJvd24ubWVzc2FnZSlcblx0XHRcdFx0fVxuXHRcdFx0fSlcblx0fVxuXG5cdHByb3RlY3RlZCBzZWVrVXBkYXRlKHZlcnNpb246IHN0cmluZyk6IHZvaWQge1xuXHRcdHRoaXMubG9nZ2VyLmluZm8oYENoZWNraW5nIGZvciB1cGRhdGVzLi4uYClcblx0XHRjb25zdCB7IGNoZWNrQXZhaWxhYmlsaXR5IH0gPSB0aGlzLm9wdGlvbnMuc2NyaXB0c1xuXHRcdGlmICghY2hlY2tBdmFpbGFiaWxpdHkpIHtcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYE5vIGNoZWNrQXZhaWxhYmlsaXR5IHNjcmlwdCBmb3VuZC5gKVxuXHRcdFx0cmV0dXJuXG5cdFx0fVxuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBvdXQgPSBleGVjU3luYyhgJHtjaGVja0F2YWlsYWJpbGl0eX0gJHt2ZXJzaW9ufWApXG5cdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBDaGVjayBzdGRvdXQ6YCwgb3V0LnRvU3RyaW5nKCkpXG5cdFx0XHR0aGlzLnVwZGF0ZUF2YWlsYWJpbGl0eUNoZWNrZXI/LnN0b3AoKVxuXHRcdFx0dGhpcy5zdG9yYWdlLnNldEl0ZW0oYHVwZGF0ZVBoYXNlYCwgYGNvbmZpcm1lZGApXG5cdFx0XHR0aGlzLmRvd25sb2FkUGFja2FnZSgpXG5cdFx0XHR0aGlzLmFubm91bmNlVXBkYXRlKClcblx0XHR9IGNhdGNoICh0aHJvd24pIHtcblx0XHRcdGlmICh0aHJvd24gaW5zdGFuY2VvZiBFcnJvcikge1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihgQ2hlY2sgZmFpbGVkOmAsIHRocm93bi5tZXNzYWdlKVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y29uc3QgdGhyb3duVHlwZSA9IGRpc2NvdmVyVHlwZSh0aHJvd24pXG5cdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBDaGVjayB0aHJld2AsIHRocm93blR5cGUsIHRocm93bilcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRwcm90ZWN0ZWQgYW5ub3VuY2VVcGRhdGUoKTogdm9pZCB7XG5cdFx0Zm9yIChjb25zdCBlbnRyeSBvZiB0b0VudHJpZXModGhpcy5zZXJ2aWNlcykpIHtcblx0XHRcdGNvbnN0IFtzZXJ2aWNlTmFtZSwgc2VydmljZV0gPSBlbnRyeVxuXHRcdFx0aWYgKHNlcnZpY2UpIHtcblx0XHRcdFx0aWYgKHRoaXMub3B0aW9ucy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0ud2FpdEZvcikge1xuXHRcdFx0XHRcdHNlcnZpY2UuZW1pdChgdXBkYXRlc1JlYWR5YClcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5zdGFydFNlcnZpY2Uoc2VydmljZU5hbWUpXG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cHJvdGVjdGVkIHRyeVVwZGF0ZSgpOiB2b2lkIHtcblx0XHRpZiAodG9FbnRyaWVzKHRoaXMuc2VydmljZXNSZWFkeVRvVXBkYXRlKS5ldmVyeSgoWywgaXNSZWFkeV0pID0+IGlzUmVhZHkpKSB7XG5cdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBBbGwgc2VydmljZXMgYXJlIHJlYWR5IHRvIHVwZGF0ZS5gKVxuXHRcdFx0dGhpcy5zdG9wQWxsU2VydmljZXMoKVxuXHRcdFx0XHQudGhlbigoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgQWxsIHNlcnZpY2VzIHN0b3BwZWQ7IHN0YXJ0aW5nIHVwIGZyZXNoLi4uYClcblx0XHRcdFx0XHR0aGlzLnN0YXJ0QWxsU2VydmljZXMoKVxuXHRcdFx0XHRcdFx0LnRoZW4oKCkgPT4ge1xuXHRcdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBBbGwgc2VydmljZXMgc3RhcnRlZDsgd2UncmUgYmFjayBvbmxpbmUuYClcblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdFx0XHQuY2F0Y2goKHRocm93bikgPT4ge1xuXHRcdFx0XHRcdFx0XHRpZiAodGhyb3duIGluc3RhbmNlb2YgRXJyb3IpIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihcblx0XHRcdFx0XHRcdFx0XHRcdGBGYWlsZWQgdG8gc3RhcnQgYWxsIHNlcnZpY2VzOmAsXG5cdFx0XHRcdFx0XHRcdFx0XHR0aHJvd24ubWVzc2FnZSxcblx0XHRcdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdH0pXG5cdFx0XHRcdC5jYXRjaCgodGhyb3duKSA9PiB7XG5cdFx0XHRcdFx0aWYgKHRocm93biBpbnN0YW5jZW9mIEVycm9yKSB7XG5cdFx0XHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIHN0b3AgYWxsIHNlcnZpY2VzOmAsIHRocm93bi5tZXNzYWdlKVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSlcblx0XHR9XG5cdH1cblxuXHRwcm90ZWN0ZWQgc3RhcnRBbGxTZXJ2aWNlcygpOiBGdXR1cmU8dW5rbm93bj4ge1xuXHRcdHRoaXMubG9nZ2VyLmluZm8oYFN0YXJ0aW5nIGFsbCBzZXJ2aWNlcy4uLmApXG5cdFx0dGhpcy5hdXRvUmVzcGF3bkRlYWRTZXJ2aWNlcyA9IHRydWVcblx0XHRjb25zdCBzZXR1cFBoYXNlID0gdGhpcy5zdG9yYWdlLmdldEl0ZW0oYHNldHVwUGhhc2VgKVxuXHRcdHRoaXMubG9nZ2VyLmluZm8oYD4gc3RvcmFnZShcInNldHVwUGhhc2VcIikgPmAsIHNldHVwUGhhc2UpXG5cdFx0c3dpdGNoIChzZXR1cFBoYXNlKSB7XG5cdFx0XHRjYXNlIG51bGw6XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYFN0YXJ0aW5nIGZyb20gc2NyYXRjaC5gKVxuXHRcdFx0XHR0aGlzLmRvd25sb2FkUGFja2FnZSgpXG5cdFx0XHRcdHRoaXMuaW5zdGFsbFBhY2thZ2UoKVxuXHRcdFx0XHRyZXR1cm4gdGhpcy5zdGFydEFsbFNlcnZpY2VzKClcblx0XHRcdGNhc2UgYGRvd25sb2FkZWRgOlxuXHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBGb3VuZCBwYWNrYWdlIGRvd25sb2FkZWQgYnV0IG5vdCBpbnN0YWxsZWQuYClcblx0XHRcdFx0dGhpcy5pbnN0YWxsUGFja2FnZSgpXG5cdFx0XHRcdHJldHVybiB0aGlzLnN0YXJ0QWxsU2VydmljZXMoKVxuXHRcdFx0Y2FzZSBgaW5zdGFsbGVkYDoge1xuXHRcdFx0XHRmb3IgKGNvbnN0IFtzZXJ2aWNlTmFtZV0gb2YgdG9FbnRyaWVzKHRoaXMuc2VydmljZXMpKSB7XG5cdFx0XHRcdFx0dGhpcy5zdGFydFNlcnZpY2Uoc2VydmljZU5hbWUpXG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXMubGl2ZVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHByb3RlY3RlZCBzdGFydFNlcnZpY2Uoc2VydmljZU5hbWU6IFMpOiB2b2lkIHtcblx0XHR0aGlzLmxvZ2dlci5pbmZvKFxuXHRcdFx0YFN0YXJ0aW5nIHNlcnZpY2UgJHt0aGlzLm9wdGlvbnMucGFja2FnZU5hbWV9Ojoke3NlcnZpY2VOYW1lfSwgdHJ5ICR7dGhpcy5zYWZldHl9LzIuLi5gLFxuXHRcdClcblx0XHRpZiAodGhpcy5zYWZldHkgPj0gMikge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBPdXQgb2YgdHJpZXMuLi5gKVxuXHRcdH1cblx0XHR0aGlzLnNhZmV0eSsrXG5cblx0XHRjb25zdCBbZXhlLCAuLi5hcmdzXSA9IHRoaXMub3B0aW9ucy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0ucnVuLnNwbGl0KGAgYClcblx0XHRjb25zdCBzZXJ2aWNlUHJvY2VzcyA9IHNwYXduKGV4ZSwgYXJncywge1xuXHRcdFx0Y3dkOiB0aGlzLm9wdGlvbnMuZmxpZ2h0ZGVja1Jvb3REaXIsXG5cdFx0XHRlbnY6IGltcG9ydC5tZXRhLmVudixcblx0XHR9KVxuXHRcdGNvbnN0IHNlcnZpY2VMb2dnZXIgPSB0aGlzLnNlcnZpY2VMb2dnZXJzW3NlcnZpY2VOYW1lXVxuXHRcdGNvbnN0IHNlcnZpY2UgPSAodGhpcy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0gPSBuZXcgQ2hpbGRTb2NrZXQoXG5cdFx0XHRzZXJ2aWNlUHJvY2Vzcyxcblx0XHRcdGAke3RoaXMub3B0aW9ucy5wYWNrYWdlTmFtZX06OiR7c2VydmljZU5hbWV9YCxcblx0XHRcdHNlcnZpY2VMb2dnZXIsXG5cdFx0KSlcblx0XHRzZXJ2aWNlTG9nZ2VyLnByb2Nlc3NDb2RlID0gc2VydmljZS5wcm9jZXNzLnBpZCA/PyAtMVxuXHRcdHRoaXMuc2VydmljZXNbc2VydmljZU5hbWVdLm9uQW55KCguLi5tZXNzYWdlcykgPT4ge1xuXHRcdFx0c2VydmljZUxvZ2dlci5pbmZvKGDwn5KsYCwgLi4ubWVzc2FnZXMpXG5cdFx0fSlcblx0XHR0aGlzLnNlcnZpY2VzW3NlcnZpY2VOYW1lXS5vbihgcmVhZHlUb1VwZGF0ZWAsICgpID0+IHtcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYFNlcnZpY2UgXCIke3NlcnZpY2VOYW1lfVwiIGlzIHJlYWR5IHRvIHVwZGF0ZS5gKVxuXHRcdFx0dGhpcy5zZXJ2aWNlc1JlYWR5VG9VcGRhdGVbc2VydmljZU5hbWVdID0gdHJ1ZVxuXHRcdFx0dGhpcy50cnlVcGRhdGUoKVxuXHRcdH0pXG5cdFx0dGhpcy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0ub24oYGFsaXZlYCwgKCkgPT4ge1xuXHRcdFx0dGhpcy5zZXJ2aWNlc0xpdmVbdGhpcy5zZXJ2aWNlSWR4W3NlcnZpY2VOYW1lXV0udXNlKFByb21pc2UucmVzb2x2ZSgpKVxuXHRcdFx0dGhpcy5zZXJ2aWNlc0RlYWRbdGhpcy5zZXJ2aWNlSWR4W3NlcnZpY2VOYW1lXV0gPSBuZXcgRnV0dXJlKCgpID0+IHt9KVxuXHRcdFx0aWYgKHRoaXMuZGVhZC5kb25lKSB7XG5cdFx0XHRcdHRoaXMuZGVhZCA9IG5ldyBGdXR1cmUoKCkgPT4ge30pXG5cdFx0XHR9XG5cdFx0XHR0aGlzLmRlYWQudXNlKFByb21pc2UuYWxsKHRoaXMuc2VydmljZXNEZWFkKSlcblx0XHR9KVxuXHRcdHRoaXMuc2VydmljZXNbc2VydmljZU5hbWVdLnByb2Nlc3Mub25jZShgY2xvc2VgLCAoZXhpdENvZGUpID0+IHtcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oXG5cdFx0XHRcdGBBdXRvLXJlc3Bhd24gc2F3IFwiJHtzZXJ2aWNlTmFtZX1cIiBleGl0IHdpdGggY29kZSAke2V4aXRDb2RlfWAsXG5cdFx0XHQpXG5cdFx0XHR0aGlzLnNlcnZpY2VzW3NlcnZpY2VOYW1lXSA9IG51bGxcblx0XHRcdGlmICghdGhpcy5hdXRvUmVzcGF3bkRlYWRTZXJ2aWNlcykge1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBBdXRvLXJlc3Bhd24gaXMgb2ZmOyBcIiR7c2VydmljZU5hbWV9XCIgcmVzdHMuYClcblx0XHRcdFx0cmV0dXJuXG5cdFx0XHR9XG5cdFx0XHRjb25zdCB1cGRhdGVQaGFzZSA9IHRoaXMuc3RvcmFnZS5nZXRJdGVtKGB1cGRhdGVQaGFzZWApXG5cdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGA+IHN0b3JhZ2UoXCJ1cGRhdGVQaGFzZVwiKSA+YCwgdXBkYXRlUGhhc2UpXG5cdFx0XHRjb25zdCB1cGRhdGVzQXJlUmVhZHkgPSB1cGRhdGVQaGFzZSA9PT0gYGNvbmZpcm1lZGBcblx0XHRcdGlmICh1cGRhdGVzQXJlUmVhZHkpIHtcblx0XHRcdFx0dGhpcy5zZXJ2aWNlTG9nZ2Vyc1tzZXJ2aWNlTmFtZV0uaW5mbyhgVXBkYXRpbmcgYmVmb3JlIHN0YXJ0dXAuLi5gKVxuXHRcdFx0XHR0aGlzLnJlc3RhcnRUaW1lcyA9IFtdXG5cdFx0XHRcdHRoaXMuaW5zdGFsbFBhY2thZ2UoKVxuXHRcdFx0XHR0aGlzLnN0YXJ0U2VydmljZShzZXJ2aWNlTmFtZSlcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNvbnN0IG5vdyA9IERhdGUubm93KClcblx0XHRcdFx0Y29uc3QgZml2ZU1pbnV0ZXNBZ28gPSBub3cgLSA1ICogNjAgKiAxMDAwXG5cdFx0XHRcdHRoaXMucmVzdGFydFRpbWVzID0gdGhpcy5yZXN0YXJ0VGltZXMuZmlsdGVyKFxuXHRcdFx0XHRcdCh0aW1lKSA9PiB0aW1lID4gZml2ZU1pbnV0ZXNBZ28sXG5cdFx0XHRcdClcblx0XHRcdFx0dGhpcy5yZXN0YXJ0VGltZXMucHVzaChub3cpXG5cblx0XHRcdFx0aWYgKHRoaXMucmVzdGFydFRpbWVzLmxlbmd0aCA8IDUpIHtcblx0XHRcdFx0XHR0aGlzLnNlcnZpY2VMb2dnZXJzW3NlcnZpY2VOYW1lXS5pbmZvKGBDcmFzaGVkLiBSZXN0YXJ0aW5nLi4uYClcblx0XHRcdFx0XHR0aGlzLnN0YXJ0U2VydmljZShzZXJ2aWNlTmFtZSlcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLnNlcnZpY2VMb2dnZXJzW3NlcnZpY2VOYW1lXS5pbmZvKFxuXHRcdFx0XHRcdFx0YENyYXNoZWQgNSB0aW1lcyBpbiA1IG1pbnV0ZXMuIE5vdCByZXN0YXJ0aW5nLmAsXG5cdFx0XHRcdFx0KVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSlcblx0XHR0aGlzLnNhZmV0eSA9IDBcblx0fVxuXG5cdHByb3RlY3RlZCBkb3dubG9hZFBhY2thZ2UoKTogdm9pZCB7XG5cdFx0dGhpcy5sb2dnZXIuaW5mbyhgRG93bmxvYWRpbmcuLi5gKVxuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBvdXQgPSBleGVjU3luYyh0aGlzLm9wdGlvbnMuc2NyaXB0cy5kb3dubG9hZClcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYERvd25sb2FkIHN0ZG91dDpgLCBvdXQudG9TdHJpbmcoKSlcblx0XHRcdHRoaXMuc3RvcmFnZS5zZXRJdGVtKGBzZXR1cFBoYXNlYCwgYGRvd25sb2FkZWRgKVxuXHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhgRG93bmxvYWRlZCFgKVxuXHRcdH0gY2F0Y2ggKHRocm93bikge1xuXHRcdFx0aWYgKHRocm93biBpbnN0YW5jZW9mIEVycm9yKSB7XG5cdFx0XHRcdHRoaXMubG9nZ2VyLmVycm9yKGBGYWlsZWQgdG8gZ2V0IHRoZSBsYXRlc3QgcmVsZWFzZTogJHt0aHJvd24ubWVzc2FnZX1gKVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuXG5cdFx0fVxuXHR9XG5cblx0cHJvdGVjdGVkIGluc3RhbGxQYWNrYWdlKCk6IHZvaWQge1xuXHRcdHRoaXMubG9nZ2VyLmluZm8oYEluc3RhbGxpbmcuLi5gKVxuXG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IG91dCA9IGV4ZWNTeW5jKHRoaXMub3B0aW9ucy5zY3JpcHRzLmluc3RhbGwpXG5cdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBJbnN0YWxsIHN0ZG91dDpgLCBvdXQudG9TdHJpbmcoKSlcblx0XHRcdHRoaXMuc3RvcmFnZS5zZXRJdGVtKGBzZXR1cFBoYXNlYCwgYGluc3RhbGxlZGApXG5cdFx0XHR0aGlzLmxvZ2dlci5pbmZvKGBJbnN0YWxsZWQhYClcblx0XHR9IGNhdGNoICh0aHJvd24pIHtcblx0XHRcdGlmICh0aHJvd24gaW5zdGFuY2VvZiBFcnJvcikge1xuXHRcdFx0XHR0aGlzLmxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIGdldCB0aGUgbGF0ZXN0IHJlbGVhc2U6ICR7dGhyb3duLm1lc3NhZ2V9YClcblx0XHRcdH1cblx0XHRcdHJldHVyblxuXHRcdH1cblx0fVxuXG5cdHB1YmxpYyBzdG9wQWxsU2VydmljZXMoKTogRnV0dXJlPHVua25vd24+IHtcblx0XHR0aGlzLmxvZ2dlci5pbmZvKGBTdG9wcGluZyBhbGwgc2VydmljZXMuLi4gYXV0by1yZXNwYXduIGRpc2FibGVkLmApXG5cdFx0dGhpcy5hdXRvUmVzcGF3bkRlYWRTZXJ2aWNlcyA9IGZhbHNlXG5cdFx0Zm9yIChjb25zdCBbc2VydmljZU5hbWVdIG9mIHRvRW50cmllcyh0aGlzLnNlcnZpY2VzKSkge1xuXHRcdFx0dGhpcy5zdG9wU2VydmljZShzZXJ2aWNlTmFtZSlcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuZGVhZFxuXHR9XG5cblx0cHVibGljIHN0b3BTZXJ2aWNlKHNlcnZpY2VOYW1lOiBTKTogdm9pZCB7XG5cdFx0Y29uc3Qgc2VydmljZSA9IHRoaXMuc2VydmljZXNbc2VydmljZU5hbWVdXG5cdFx0aWYgKHNlcnZpY2UpIHtcblx0XHRcdHRoaXMubG9nZ2VyLmluZm8oYFN0b3BwaW5nIHNlcnZpY2UgXCIke3NlcnZpY2VOYW1lfVwiLi4uYClcblx0XHRcdHRoaXMuc2VydmljZXNEZWFkW3RoaXMuc2VydmljZUlkeFtzZXJ2aWNlTmFtZV1dLnVzZShcblx0XHRcdFx0bmV3IFByb21pc2UoKHBhc3MpID0+IHtcblx0XHRcdFx0XHRzZXJ2aWNlLmVtaXQoYHRpbWVUb1N0b3BgKVxuXHRcdFx0XHRcdHNlcnZpY2UucHJvY2Vzcy5vbmNlKGBjbG9zZWAsIChleGl0Q29kZSkgPT4ge1xuXHRcdFx0XHRcdFx0dGhpcy5sb2dnZXIuaW5mbyhcblx0XHRcdFx0XHRcdFx0YFN0b3BwZWQgc2VydmljZSBcIiR7c2VydmljZU5hbWV9XCI7IGV4aXRlZCB3aXRoIGNvZGUgJHtleGl0Q29kZX1gLFxuXHRcdFx0XHRcdFx0KVxuXHRcdFx0XHRcdFx0dGhpcy5zZXJ2aWNlc1tzZXJ2aWNlTmFtZV0gPSBudWxsXG5cdFx0XHRcdFx0XHRwYXNzKClcblx0XHRcdFx0XHR9KVxuXHRcdFx0XHR9KSxcblx0XHRcdClcblx0XHRcdHRoaXMuZGVhZC51c2UoUHJvbWlzZS5hbGwodGhpcy5zZXJ2aWNlc0RlYWQpKVxuXHRcdFx0dGhpcy5zZXJ2aWNlc0xpdmVbdGhpcy5zZXJ2aWNlSWR4W3NlcnZpY2VOYW1lXV0gPSBuZXcgRnV0dXJlKCgpID0+IHt9KVxuXHRcdFx0aWYgKHRoaXMubGl2ZS5kb25lKSB7XG5cdFx0XHRcdHRoaXMubGl2ZSA9IG5ldyBGdXR1cmUoKCkgPT4ge30pXG5cdFx0XHR9XG5cdFx0XHR0aGlzLmxpdmUudXNlKFByb21pc2UuYWxsKHRoaXMuc2VydmljZXNMaXZlKSlcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5zZXJ2aWNlTG9nZ2Vyc1tzZXJ2aWNlTmFtZV0uZXJyb3IoXG5cdFx0XHRcdGBUcmllZCB0byBzdG9wIHNlcnZpY2UsIGJ1dCBpdCB3YXNuJ3QgcnVubmluZy5gLFxuXHRcdFx0KVxuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgY29uc3QgRkxJR0hUREVDS19JTkZPID0gYGluZm9gXG5leHBvcnQgY29uc3QgRkxJR0hUREVDS19XQVJOID0gYHdhcm5gXG5leHBvcnQgY29uc3QgRkxJR0hUREVDS19FUlJPUiA9IGBFUlIhYFxuXG5leHBvcnQgY29uc3QgZmxpZ2h0RGVja0xvZ1NjaGVtYSA9IHoub2JqZWN0KHtcblx0bGV2ZWw6IHoudW5pb24oW1xuXHRcdHoubGl0ZXJhbChGTElHSFRERUNLX0lORk8pLFxuXHRcdHoubGl0ZXJhbChGTElHSFRERUNLX1dBUk4pLFxuXHRcdHoubGl0ZXJhbChGTElHSFRERUNLX0VSUk9SKSxcblx0XSksXG5cdHRpbWVzdGFtcDogei5udW1iZXIoKSxcblx0cGFja2FnZTogei5zdHJpbmcoKSxcblx0c2VydmljZTogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuXHRwcm9jZXNzOiB6Lm51bWJlcigpLFxuXHRib2R5OiB6LnN0cmluZygpLFxufSlcbmV4cG9ydCB0eXBlIEZsaWdodERlY2tMb2cgPSB6LmluZmVyPHR5cGVvZiBmbGlnaHREZWNrTG9nU2NoZW1hPlxuXG5jb25zdCBMSU5FX0ZPUk1BVCA9IGBsaW5lLWZvcm1hdGAgc2F0aXNmaWVzIGtleW9mIExuYXZGb3JtYXRcbmNvbnN0IFZBTFVFID0gYHZhbHVlYCBzYXRpc2ZpZXMga2V5b2YgTG5hdkZvcm1hdFxuXG5leHBvcnQgdHlwZSBMbmF2Rm9ybWF0VmlzdWFsQ29tcG9uZW50ID0gRXhjbHVkZTxcblx0RXhjbHVkZTxMbmF2Rm9ybWF0W2BsaW5lLWZvcm1hdGBdLCB1bmRlZmluZWQ+W251bWJlcl0sXG5cdHN0cmluZ1xuPlxuXG5leHBvcnQgdHlwZSBMbmF2Rm9ybWF0QnJlYWtkb3duID0gRXhjbHVkZTxMbmF2Rm9ybWF0W2B2YWx1ZWBdLCB1bmRlZmluZWQ+XG5leHBvcnQgdHlwZSBNZW1iZXJPZjxUPiA9IFRba2V5b2YgVF1cbmV4cG9ydCB0eXBlIExuYXZGb3JtYXRWYWx1ZURlZmluaXRpb24gPSBNZW1iZXJPZjxMbmF2Rm9ybWF0QnJlYWtkb3duPlxuXG5leHBvcnQgdHlwZSBGbGlnaHREZWNrRm9ybWF0ID0ge1xuXHRbTElORV9GT1JNQVRdOiAoXG5cdFx0fCBzdHJpbmdcblx0XHR8IChMbmF2Rm9ybWF0VmlzdWFsQ29tcG9uZW50ICYge1xuXHRcdFx0XHRmaWVsZDoga2V5b2YgRmxpZ2h0RGVja0xvZyB8IGBfX2xldmVsX19gIHwgYF9fdGltZXN0YW1wX19gXG5cdFx0ICB9KVxuXHQpW11cblx0W1ZBTFVFXToge1xuXHRcdFtLIGluIGtleW9mIEZsaWdodERlY2tMb2ddOiBMbmF2Rm9ybWF0VmFsdWVEZWZpbml0aW9uICYge1xuXHRcdFx0a2luZDogRmxpZ2h0RGVja0xvZ1tLXSBleHRlbmRzIG51bWJlciB8IHVuZGVmaW5lZFxuXHRcdFx0XHQ/IGBpbnRlZ2VyYFxuXHRcdFx0XHQ6IEZsaWdodERlY2tMb2dbS10gZXh0ZW5kcyBzdHJpbmcgfCB1bmRlZmluZWRcblx0XHRcdFx0XHQ/IGBzdHJpbmdgXG5cdFx0XHRcdFx0OiBuZXZlclxuXHRcdH1cblx0fVxufVxuXG5leHBvcnQgY29uc3QgRkxJR0hUREVDS19MTkFWX0ZPUk1BVCA9IHtcblx0dGl0bGU6IGBGbGlnaHREZWNrIExvZ2AsXG5cdGRlc2NyaXB0aW9uOiBgRm9ybWF0IGZvciBldmVudHMgbG9nZ2VkIGJ5IHRoZSBGbGlnaHREZWNrIHByb2Nlc3MgbWFuYWdlci5gLFxuXHRcImZpbGUtdHlwZVwiOiBganNvbmAsXG5cdFwidGltZXN0YW1wLWZpZWxkXCI6IGB0aW1lc3RhbXBgLFxuXHRcInRpbWVzdGFtcC1kaXZpc29yXCI6IDEwMDAsXG5cdFwibW9kdWxlLWZpZWxkXCI6IGBwYWNrYWdlYCxcblx0XCJvcGlkLWZpZWxkXCI6IGBzZXJ2aWNlYCxcblx0XCJsZXZlbC1maWVsZFwiOiBgbGV2ZWxgLFxuXHRsZXZlbDoge1xuXHRcdGluZm86IEZMSUdIVERFQ0tfSU5GTyxcblx0XHR3YXJuaW5nOiBGTElHSFRERUNLX1dBUk4sXG5cdFx0ZXJyb3I6IEZMSUdIVERFQ0tfRVJST1IsXG5cdH0sXG5cblx0W0xJTkVfRk9STUFUXTogW1xuXHRcdHtcblx0XHRcdGZpZWxkOiBgbGV2ZWxgLFxuXHRcdH0sXG5cdFx0e1xuXHRcdFx0cHJlZml4OiBgIGAsXG5cdFx0XHRmaWVsZDogYF9fdGltZXN0YW1wX19gLFxuXHRcdFx0XCJ0aW1lc3RhbXAtZm9ybWF0XCI6IGAlWS0lbS0lZFQlSDolTTolUy4lTCVaYCxcblx0XHR9LFxuXHRcdHtcblx0XHRcdHByZWZpeDogYCBgLFxuXHRcdFx0ZmllbGQ6IGBwcm9jZXNzYCxcblx0XHRcdFwibWluLXdpZHRoXCI6IDUsXG5cdFx0fSxcblx0XHR7XG5cdFx0XHRwcmVmaXg6IGA6YCxcblx0XHRcdGZpZWxkOiBgcGFja2FnZWAsXG5cdFx0fSxcblx0XHR7XG5cdFx0XHRwcmVmaXg6IGA6YCxcblx0XHRcdGZpZWxkOiBgc2VydmljZWAsXG5cdFx0XHRcImRlZmF1bHQtdmFsdWVcIjogYGAsXG5cdFx0fSxcblx0XHR7XG5cdFx0XHRwcmVmaXg6IGA6IGAsXG5cdFx0XHRmaWVsZDogYGJvZHlgLFxuXHRcdH0sXG5cdF0sXG5cblx0W1ZBTFVFXToge1xuXHRcdHRpbWVzdGFtcDoge1xuXHRcdFx0a2luZDogYGludGVnZXJgLFxuXHRcdH0sXG5cdFx0bGV2ZWw6IHtcblx0XHRcdGtpbmQ6IGBzdHJpbmdgLFxuXHRcdH0sXG5cdFx0cGFja2FnZToge1xuXHRcdFx0a2luZDogYHN0cmluZ2AsXG5cdFx0fSxcblx0XHRzZXJ2aWNlOiB7XG5cdFx0XHRraW5kOiBgc3RyaW5nYCxcblx0XHR9LFxuXHRcdHByb2Nlc3M6IHtcblx0XHRcdGtpbmQ6IGBpbnRlZ2VyYCxcblx0XHR9LFxuXHRcdGJvZHk6IHtcblx0XHRcdGtpbmQ6IGBzdHJpbmdgLFxuXHRcdH0sXG5cdH0sXG59IGFzIGNvbnN0IHNhdGlzZmllcyBGbGlnaHREZWNrRm9ybWF0ICYgTG5hdkZvcm1hdFxuXG5leHBvcnQgY2xhc3MgRmxpZ2h0RGVja0xvZ2dlclxuXHRpbXBsZW1lbnRzIFBpY2s8Q29uc29sZSwgYGVycm9yYCB8IGBpbmZvYCB8IGB3YXJuYD5cbntcblx0cHVibGljIHJlYWRvbmx5IHBhY2thZ2VOYW1lOiBzdHJpbmdcblx0cHVibGljIHJlYWRvbmx5IHNlcnZpY2VOYW1lPzogc3RyaW5nXG5cdHB1YmxpYyByZWFkb25seSBqc29uTG9nZ2luZzogYm9vbGVhblxuXHRwdWJsaWMgcHJvY2Vzc0NvZGU6IG51bWJlclxuXHRwdWJsaWMgY29uc3RydWN0b3IoXG5cdFx0cGFja2FnZU5hbWU6IHN0cmluZyxcblx0XHRwcm9jZXNzQ29kZTogbnVtYmVyLFxuXHRcdHNlcnZpY2VOYW1lPzogc3RyaW5nLFxuXHRcdG9wdGlvbnM/OiB7IGpzb25Mb2dnaW5nOiBib29sZWFuIH0sXG5cdCkge1xuXHRcdHRoaXMucGFja2FnZU5hbWUgPSBwYWNrYWdlTmFtZVxuXHRcdGlmIChzZXJ2aWNlTmFtZSkge1xuXHRcdFx0dGhpcy5zZXJ2aWNlTmFtZSA9IHNlcnZpY2VOYW1lXG5cdFx0fVxuXHRcdHRoaXMucHJvY2Vzc0NvZGUgPSBwcm9jZXNzQ29kZVxuXHRcdHRoaXMuanNvbkxvZ2dpbmcgPSBvcHRpb25zPy5qc29uTG9nZ2luZyA/PyBmYWxzZVxuXHR9XG5cdHByb3RlY3RlZCBsb2coXG5cdFx0bGV2ZWw6XG5cdFx0XHR8IHR5cGVvZiBGTElHSFRERUNLX0VSUk9SXG5cdFx0XHR8IHR5cGVvZiBGTElHSFRERUNLX0lORk9cblx0XHRcdHwgdHlwZW9mIEZMSUdIVERFQ0tfV0FSTixcblx0XHQuLi5tZXNzYWdlczogdW5rbm93bltdXG5cdCk6IHZvaWQge1xuXHRcdGlmICh0aGlzLmpzb25Mb2dnaW5nKSB7XG5cdFx0XHRsZXQgYm9keSA9IG1lc3NhZ2VzXG5cdFx0XHRcdC5tYXAoKG1lc3NhZ2UpID0+XG5cdFx0XHRcdFx0dHlwZW9mIG1lc3NhZ2UgPT09IGBzdHJpbmdgXG5cdFx0XHRcdFx0XHQ/IG1lc3NhZ2Vcblx0XHRcdFx0XHRcdDogaW5zcGVjdChtZXNzYWdlLCBmYWxzZSwgbnVsbCwgdHJ1ZSksXG5cdFx0XHRcdClcblx0XHRcdFx0LmpvaW4oYCBgKVxuXHRcdFx0aWYgKGJvZHkuaW5jbHVkZXMoYFxcbmApKSB7XG5cdFx0XHRcdGJvZHkgPSBgXFxuICAke2JvZHkuc3BsaXQoYFxcbmApLmpvaW4oYFxcbiAgYCl9YFxuXHRcdFx0fVxuXHRcdFx0Y29uc3QgbG9nOiBGbGlnaHREZWNrTG9nID0ge1xuXHRcdFx0XHR0aW1lc3RhbXA6IERhdGUubm93KCksXG5cdFx0XHRcdGxldmVsLFxuXHRcdFx0XHRwcm9jZXNzOiB0aGlzLnByb2Nlc3NDb2RlLFxuXHRcdFx0XHRwYWNrYWdlOiB0aGlzLnBhY2thZ2VOYW1lLFxuXHRcdFx0XHRib2R5LFxuXHRcdFx0fVxuXHRcdFx0aWYgKHRoaXMuc2VydmljZU5hbWUpIHtcblx0XHRcdFx0bG9nLnNlcnZpY2UgPSB0aGlzLnNlcnZpY2VOYW1lXG5cdFx0XHR9XG5cdFx0XHRwcm9jZXNzLnN0ZG91dC53cml0ZShKU09OLnN0cmluZ2lmeShsb2cpICsgYFxcbmApXG5cdFx0fSBlbHNlIHtcblx0XHRcdGNvbnN0IHNvdXJjZSA9IHRoaXMuc2VydmljZU5hbWVcblx0XHRcdFx0PyBgJHt0aGlzLnBhY2thZ2VOYW1lfToke3RoaXMuc2VydmljZU5hbWV9YFxuXHRcdFx0XHQ6IHRoaXMucGFja2FnZU5hbWVcblx0XHRcdHN3aXRjaCAobGV2ZWwpIHtcblx0XHRcdFx0Y2FzZSBGTElHSFRERUNLX0lORk86XG5cdFx0XHRcdFx0Y29uc29sZS5sb2coYCR7c291cmNlfTpgLCAuLi5tZXNzYWdlcylcblx0XHRcdFx0XHRicmVha1xuXHRcdFx0XHRjYXNlIEZMSUdIVERFQ0tfV0FSTjpcblx0XHRcdFx0XHRjb25zb2xlLndhcm4oYCR7c291cmNlfTpgLCAuLi5tZXNzYWdlcylcblx0XHRcdFx0XHRicmVha1xuXHRcdFx0XHRjYXNlIEZMSUdIVERFQ0tfRVJST1I6XG5cdFx0XHRcdFx0Y29uc29sZS5lcnJvcihgJHtzb3VyY2V9OmAsIC4uLm1lc3NhZ2VzKVxuXHRcdFx0XHRcdGJyZWFrXG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdHB1YmxpYyBpbmZvKC4uLm1lc3NhZ2VzOiB1bmtub3duW10pOiB2b2lkIHtcblx0XHR0aGlzLmxvZyhGTElHSFRERUNLX0lORk8sIC4uLm1lc3NhZ2VzKVxuXHR9XG5cblx0cHVibGljIHdhcm4oLi4ubWVzc2FnZXM6IHVua25vd25bXSk6IHZvaWQge1xuXHRcdHRoaXMubG9nKEZMSUdIVERFQ0tfV0FSTiwgLi4ubWVzc2FnZXMpXG5cdH1cblxuXHRwdWJsaWMgZXJyb3IoLi4ubWVzc2FnZXM6IHVua25vd25bXSk6IHZvaWQge1xuXHRcdHRoaXMubG9nKEZMSUdIVERFQ0tfRVJST1IsIC4uLm1lc3NhZ2VzKVxuXHR9XG59XG4iLAogICAgImltcG9ydCB7IGNyZWF0ZUVudiB9IGZyb20gXCJAdDMtb3NzL2Vudi1jb3JlXCJcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCJcblxuZXhwb3J0IGNvbnN0IGVudiA9IGNyZWF0ZUVudih7XG5cdHNlcnZlcjogeyBGTElHSFRERUNLX1NFQ1JFVDogei5zdHJpbmcoKS5vcHRpb25hbCgpIH0sXG5cdGNsaWVudFByZWZpeDogYE5FVkVSYCxcblx0Y2xpZW50OiB7fSxcblx0cnVudGltZUVudjogaW1wb3J0Lm1ldGEuZW52LFxuXHRlbXB0eVN0cmluZ0FzVW5kZWZpbmVkOiB0cnVlLFxufSlcbiIsCiAgICAiZXhwb3J0IHR5cGUgQWxlcnRPcHRpb25zID0ge1xuXHRzZWNyZXQ6IHN0cmluZ1xuXHRlbmRwb2ludDogc3RyaW5nXG5cdHZlcnNpb246IHN0cmluZ1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYWxlcnQoe1xuXHRzZWNyZXQsXG5cdGVuZHBvaW50LFxuXHR2ZXJzaW9uLFxufTogQWxlcnRPcHRpb25zKTogUHJvbWlzZTxSZXNwb25zZT4ge1xuXHRjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGVuZHBvaW50LCB7XG5cdFx0bWV0aG9kOiBgUE9TVGAsXG5cdFx0aGVhZGVyczoge1xuXHRcdFx0XCJDb250ZW50LVR5cGVcIjogYHRleHQvcGxhaW47Y2hhcnNldD1VVEYtOGAsXG5cdFx0XHRBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7c2VjcmV0fWAsXG5cdFx0fSxcblx0XHRib2R5OiB2ZXJzaW9uLFxuXHR9KVxuXG5cdHJldHVybiByZXNwb25zZVxufVxuXG4vKipcbiAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2NoYW5nZXNldHMvYWN0aW9uL2Jsb2IvbWFpbi9zcmMvcnVuLnRzXG4gKi9cbmV4cG9ydCB0eXBlIENoYW5nZXNldHNQdWJsaXNoZWRQYWNrYWdlID0ge1xuXHRuYW1lOiBzdHJpbmdcblx0dmVyc2lvbjogc3RyaW5nXG59XG5cbi8qKlxuICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vY2hhbmdlc2V0cy9hY3Rpb24vYmxvYi9tYWluL3NyYy9ydW4udHNcbiAqL1xuZXhwb3J0IHR5cGUgQ2hhbmdlc2V0c1B1Ymxpc2hSZXN1bHQgPVxuXHR8IHtcblx0XHRcdHB1Ymxpc2hlZDogdHJ1ZVxuXHRcdFx0cHVibGlzaGVkUGFja2FnZXM6IENoYW5nZXNldHNQdWJsaXNoZWRQYWNrYWdlW11cblx0ICB9XG5cdHwgeyBwdWJsaXNoZWQ6IGZhbHNlIH1cblxuZXhwb3J0IHR5cGUgUGFja2FnZUNvbmZpZzxLIGV4dGVuZHMgc3RyaW5nPiA9IHtcblx0W2tleSBpbiBLXTogeyBlbmRwb2ludDogc3RyaW5nIH1cbn1cbmV4cG9ydCB0eXBlIFNlY3JldHNDb25maWc8SyBleHRlbmRzIHN0cmluZz4gPSB7XG5cdFtrZXkgaW4gS106IHN0cmluZ1xufVxuXG5leHBvcnQgdHlwZSBTY3JhbWJsZU9wdGlvbnM8SyBleHRlbmRzIHN0cmluZyA9IHN0cmluZz4gPSB7XG5cdHBhY2thZ2VDb25maWc6IFBhY2thZ2VDb25maWc8Sz5cblx0c2VjcmV0c0NvbmZpZzogU2VjcmV0c0NvbmZpZzxLPlxuXHRwdWJsaXNoZWRQYWNrYWdlczogQ2hhbmdlc2V0c1B1Ymxpc2hlZFBhY2thZ2VbXVxufVxuXG5leHBvcnQgdHlwZSBTY3JhbWJsZVJlc3VsdDxLIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nPiA9IHtcblx0W2tleSBpbiBLXTogUmVzcG9uc2Vcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNjcmFtYmxlPEsgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmc+KHtcblx0cGFja2FnZUNvbmZpZyxcblx0c2VjcmV0c0NvbmZpZyxcblx0cHVibGlzaGVkUGFja2FnZXMsXG59OiBTY3JhbWJsZU9wdGlvbnM8Sz4pOiBQcm9taXNlPFNjcmFtYmxlUmVzdWx0PEs+PiB7XG5cdGNvbnN0IGFsZXJ0UmVzdWx0czogUHJvbWlzZTxyZWFkb25seSBbSywgUmVzcG9uc2VdPltdID0gW11cblx0Zm9yIChjb25zdCBwdWJsaXNoZWRQYWNrYWdlIG9mIHB1Ymxpc2hlZFBhY2thZ2VzKSB7XG5cdFx0aWYgKHB1Ymxpc2hlZFBhY2thZ2UubmFtZSBpbiBwYWNrYWdlQ29uZmlnKSB7XG5cdFx0XHRjb25zdCBuYW1lID0gcHVibGlzaGVkUGFja2FnZS5uYW1lIGFzIEtcblx0XHRcdGNvbnN0IHsgZW5kcG9pbnQgfSA9IHBhY2thZ2VDb25maWdbbmFtZV1cblx0XHRcdGNvbnN0IHNlY3JldCA9IHNlY3JldHNDb25maWdbbmFtZV1cblx0XHRcdGNvbnN0IHZlcnNpb24gPSBwdWJsaXNoZWRQYWNrYWdlLnZlcnNpb25cblx0XHRcdGNvbnN0IGFsZXJ0UmVzdWx0UHJvbWlzZSA9IGFsZXJ0KHsgc2VjcmV0LCBlbmRwb2ludCwgdmVyc2lvbiB9KS50aGVuKFxuXHRcdFx0XHQoYWxlcnRSZXN1bHQpID0+IFtuYW1lLCBhbGVydFJlc3VsdF0gYXMgY29uc3QsXG5cdFx0XHQpXG5cdFx0XHRhbGVydFJlc3VsdHMucHVzaChhbGVydFJlc3VsdFByb21pc2UpXG5cdFx0fVxuXHR9XG5cdGNvbnN0IGFsZXJ0UmVzdWx0c1Jlc29sdmVkID0gYXdhaXQgUHJvbWlzZS5hbGwoYWxlcnRSZXN1bHRzKVxuXHRjb25zdCBzY3JhbWJsZVJlc3VsdCA9IE9iamVjdC5mcm9tRW50cmllcyhcblx0XHRhbGVydFJlc3VsdHNSZXNvbHZlZCxcblx0KSBhcyBTY3JhbWJsZVJlc3VsdDxLPlxuXHRyZXR1cm4gc2NyYW1ibGVSZXN1bHRcbn1cbiIKICBdLAogICJtYXBwaW5ncyI6ICI4SEFBQSxtQkFBUyxXQUFVLDJCQUVuQix1QkFBUyxrQkFDVCxrQkFBUyxnQkFDVCxrQkFBUyxrQkFDVCxrQkFBUyxrQkFFVCxpQkFBUyx5QkFDVCx1QkFBUyw4QkFDVCxzQkFBUyxlQUFhLHFCQUN0QixzQkFBUyxnQ0FDVCxrQkFBUyxhQUNULDRCQUFTLG9CQUNULFlBQVMsWUNiVCxvQkFBUyx5QkFDVCxZQUFTLFlBRUYsSUFBTSxFQUFNLEVBQVUsQ0FDNUIsT0FBUSxDQUFFLGtCQUFtQixFQUFFLE9BQU8sRUFBRSxTQUFTLENBQUUsRUFDbkQsYUFBYyxRQUNkLE9BQVEsQ0FBQyxFQUNULFdBQVksWUFBWSxJQUN4Qix1QkFBd0IsRUFDekIsQ0FBQyxFRFNNLElBQU0sR0FBMEIsQ0FBQyxhQUFjLFdBQVcsRUFJcEQsR0FBMkIsQ0FBQyxXQUFZLFdBQVcsRUFJekQsU0FBUyxDQUFlLENBQUMsRUFBMEIsQ0FDekQsTUFDQyxrQkFBa0IsS0FBSyxDQUFPLElBQU0sT0FBTyxNQUFNLE9BQU8sV0FBVyxDQUFPLENBQUMsRUFpQnRFLE1BQU0sQ0FBc0MsQ0FrQ2YsUUFqQ3pCLE9BQVMsRUFFVCxRQUtBLGNBQ0EsU0FNQSxXQUNILDZCQUNBLHNCQUNBLHdCQUVHLE9BQ0EsZUFJQSwwQkFBNEMsS0FFL0MsYUFDQSxhQUNBLEtBQU8sSUFBSSxFQUFPLElBQU0sRUFBRSxFQUMxQixLQUFPLElBQUksRUFBTyxJQUFNLEVBQUUsRUFFdkIsYUFBeUIs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R0FBSSxLQUFLLFlBQWEsQ0FDckIsSUFBSSxFQUFPLEVBQ1QsSUFBSSxDQUFDLFdBQ0UsSUFBWSxTQUNoQixFQUNBLEVBQVEsRUFBUyxHQUFPLEtBQU0sRUFBSSxDQUN0QyxFQUNDLEtBQUssR0FBRyxFQUNWLEdBQUksRUFBSyxTQUFTO0FBQUEsQ0FBSSxFQUNyQixFQUFPO0FBQUEsSUFBTyxFQUFLLE1BQU07QUFBQSxDQUFJLEVBQUUsS0FBSztBQUFBLEdBQU0sSUFFM0MsSUFBTSxFQUFxQixDQUMxQixVQUFXLEtBQUssSUFBSSxFQUNwQixRQUNBLFFBQVMsS0FBSyxZQUNkLFFBQVMsS0FBSyxZQUNkLE1BQ0QsRUFDQSxHQUFJLEtBQUssWUFDUixFQUFJLFFBQVUsS0FBSyxZQUVwQixRQUFRLE9BQU8sTUFBTSxLQUFLLFVBQVUsQ0FBRyxFQUFJO0FBQUEsQ0FBSSxNQUN6QyxDQUNOLElBQU0sRUFBUyxLQUFLLFlBQ2pCLEdBQUcsS0FBSyxlQUFlLEtBQUssY0FDNUIsS0FBSyxZQUNSLE9BQVEsUUFDRixFQUNKLFFBQVEsSUFBSSxHQUFHLEtBQVcsR0FBRyxDQUFRLEVBQ3JDLFdBQ0ksRUFDSixRQUFRLEtBQUssR0FBRyxLQUFXLEdBQUcsQ0FBUSxFQUN0QyxXQUNJLEVBQ0osUUFBUSxNQUFNLEdBQUcsS0FBVyxHQUFHLENBQVEsRUFDdkMsUUFJRyxJQUFJLElBQUksRUFBMkIsQ0FDekMsS0FBSyxJQUFJLEVBQWlCLEdBQUcsQ0FBUSxFQUcvQixJQUFJLElBQUksRUFBMkIsQ0FDekMsS0FBSyxJQUFJLEVBQWlCLEdBQUcsQ0FBUSxFQUcvQixLQUFLLElBQUksRUFBMkIsQ0FDMUMsS0FBSyxJQUFJLEVBQWtCLEdBQUcsQ0FBUSxFQUV4Qyw0Q0VqbkJBLGVBQXNCLENBQUssRUFDMUIsU0FDQSxXQUNBLFdBQ21DLENBVW5DLE9BVGlCLE1BQU0sTUFBTSxFQUFVLENBQ3RDLE9BQVEsT0FDUixRQUFTLENBQ1IsZUFBZ0IsMkJBQ2hCLGNBQWUsVUFBVSxHQUMxQixFQUNBLEtBQU0sQ0FDUCxDQUFDLEVBd0NGLGVBQXNCLENBQW1DLEVBQ3hELGdCQUNBLGdCQUNBLHFCQUNrRCxDQUNsRCxJQUFNLEVBQWtELENBQUMsRUFDekQsUUFBVyxLQUFvQixFQUM5QixHQUFJLEVBQWlCLFFBQVEsRUFBZSxDQUMzQyxJQUFNLEVBQU8sRUFBaUIsTUFDdEIsWUFBYSxFQUFjLEdBQzdCLEVBQVMsRUFBYyxHQUN2QixFQUFVLEVBQWlCLFFBQzNCLEVBQXFCLEVBQU0sQ0FBRSxTQUFRLFdBQVUsU0FBUSxDQUFDLEVBQUUsS0FDL0QsQ0FBQyxJQUFnQixDQUFDLEVBQU0sQ0FBVyxDQUNwQyxFQUNBLEVBQWEsS0FBSyxDQUFrQixFQUd0QyxJQUFNLEVBQXVCLE1BQU0sUUFBUSxJQUFJLENBQVksRUFJM0QsT0FIdUIsT0FBTyxZQUM3QixDQUNEIiwKICAiZGVidWdJZCI6ICJGNUZGODlDNTdEOTI2RTU1NjQ3NTZFMjE2NDc1NkUyMSIsCiAgIm5hbWVzIjogW10KfQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flightdeck",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "license": "MIT",
5
5
  "author": {
6
6
  "name": "Jeremy Banka",
@@ -22,25 +22,26 @@
22
22
  "klaxon": "./dist/klaxon.bin.js"
23
23
  },
24
24
  "dependencies": {
25
- "@t3-oss/env-core": "0.11.1",
26
- "cron": "3.3.2",
25
+ "@t3-oss/env-core": "0.12.0",
26
+ "cron": "3.5.0",
27
27
  "zod": "3.24.1",
28
28
  "atom.io": "0.30.7",
29
- "comline": "0.1.6"
29
+ "comline": "0.1.6",
30
+ "safedeposit": "0.0.1"
30
31
  },
31
32
  "devDependencies": {
32
33
  "@biomejs/js-api": "0.7.1",
33
34
  "@biomejs/wasm-nodejs": "1.9.4",
34
- "@types/node": "22.10.5",
35
+ "@types/node": "22.12.0",
35
36
  "@types/tmp": "0.2.6",
36
- "bun-types": "1.1.42",
37
+ "bun-types": "1.2.1",
37
38
  "concurrently": "9.1.2",
38
39
  "json-schema-to-zod": "2.6.0",
39
40
  "rimraf": "6.0.1",
40
41
  "tmp": "0.2.3",
41
- "tsup": "8.3.5",
42
- "vitest": "3.0.0-beta.3",
43
- "varmint": "0.3.4"
42
+ "tsup": "8.3.6",
43
+ "vitest": "3.0.4",
44
+ "varmint": "0.3.6"
44
45
  },
45
46
  "scripts": {
46
47
  "gen": "bun ./__scripts__/gen.bun.ts",
@@ -49,7 +50,7 @@
49
50
  "build:dts": "tsup",
50
51
  "schema:flightdeck": "bun ./src/flightdeck.bin.ts --outdir=dist -- schema",
51
52
  "lint:biome": "biome check -- .",
52
- "lint:eslint": "eslint --flag unstable_ts_config -- .",
53
+ "lint:eslint": "eslint -- .",
53
54
  "lint:types": "tsc --noEmit",
54
55
  "lint:types:watch": "tsc --watch --noEmit",
55
56
  "lint": "bun run lint:biome && bun run lint:eslint && bun run lint:types",
@@ -10,10 +10,10 @@ import { discoverType } from "atom.io/introspection"
10
10
  import { fromEntries, toEntries } from "atom.io/json"
11
11
  import { ChildSocket } from "atom.io/realtime-server"
12
12
  import { CronJob } from "cron"
13
+ import { FilesystemStorage } from "safedeposit"
13
14
  import { z } from "zod"
14
15
 
15
16
  import type { LnavFormat } from "../gen/lnav-format-schema.gen"
16
- import { FilesystemStorage } from "./filesystem-storage"
17
17
  import { env } from "./flightdeck.env"
18
18
 
19
19
  export const FLIGHTDECK_SETUP_PHASES = [`downloaded`, `installed`] as const
package/src/lib.ts CHANGED
@@ -1,4 +1,3 @@
1
- export * from "./filesystem-storage"
2
1
  export * from "./flightdeck.lib"
3
2
  import * as Klaxon from "./klaxon.lib"
4
3
 
package/gen/.gitkeep DELETED
File without changes
@@ -1,168 +0,0 @@
1
- {
2
- "$schema": "https://lnav.org/schemas/format-v1.schema.json",
3
- "flightdeck_log": {
4
- "title": "FlightDeck Log",
5
- "description": "Format for events logged by the FlightDeck process manager.",
6
- "file-type": "json",
7
- "timestamp-field": "created_at",
8
- "opid-field": "actor/display_login",
9
- "line-format": [
10
- {
11
- "field": "__timestamp__"
12
- },
13
- {
14
- "prefix": " ",
15
- "field": "type"
16
- },
17
- {
18
- "prefix": " ",
19
- "field": "actor/display_login"
20
- },
21
- {
22
- "prefix": " ",
23
- "field": "payload/action",
24
- "default-value": ""
25
- },
26
- {
27
- "prefix": " ",
28
- "field": "payload/member/login",
29
- "suffix": " to",
30
- "default-value": ""
31
- },
32
- {
33
- "prefix": " committed \u201c",
34
- "field": "payload/commits#/message",
35
- "suffix": "\u201d to",
36
- "default-value": ""
37
- },
38
- {
39
- "prefix": " forked ",
40
- "field": "payload/forkee/full_name",
41
- "suffix": " from",
42
- "default-value": ""
43
- },
44
- {
45
- "prefix": " review ",
46
- "field": "payload/review/id",
47
- "suffix": " for",
48
- "default-value": ""
49
- },
50
- {
51
- "prefix": " pull-request #",
52
- "field": "payload/pull_request/number",
53
- "default-value": ""
54
- },
55
- {
56
- "prefix": " \u201c",
57
- "field": "payload/pull_request/title",
58
- "suffix": "\u201d in",
59
- "default-value": ""
60
- },
61
- {
62
- "prefix": " issue #",
63
- "field": "payload/issue/number",
64
- "default-value": ""
65
- },
66
- {
67
- "prefix": " \u201c",
68
- "field": "payload/issue/title",
69
- "suffix": "\u201d in",
70
- "default-value": ""
71
- },
72
- {
73
- "prefix": " ",
74
- "field": "payload/ref_type",
75
- "default-value": ""
76
- },
77
- {
78
- "prefix": " off ",
79
- "field": "payload/master_branch",
80
- "suffix": " in",
81
- "default-value": ""
82
- },
83
- {
84
- "prefix": " ",
85
- "field": "payload/pages#/action",
86
- "default-value": ""
87
- },
88
- {
89
- "prefix": " page ",
90
- "field": "payload/pages#/title",
91
- "suffix": " in",
92
- "default-value": ""
93
- },
94
- {
95
- "prefix": " ",
96
- "field": "payload/release/name",
97
- "suffix": " in",
98
- "default-value": ""
99
- },
100
- {
101
- "prefix": " ",
102
- "field": "repo/name",
103
- "default-value": ""
104
- }
105
- ],
106
- "value": {
107
- "id": {
108
- "kind": "string",
109
- "identifier": true,
110
- "hidden": true
111
- },
112
- "type": {
113
- "kind": "string",
114
- "identifier": true
115
- },
116
- "actor": {
117
- "kind": "json",
118
- "hidden": true
119
- },
120
- "actor/display_login": {
121
- "kind": "string",
122
- "identifier": true
123
- },
124
- "org": {
125
- "kind": "json",
126
- "hidden": true
127
- },
128
- "payload": {
129
- "kind": "json",
130
- "hidden": true
131
- },
132
- "payload/action": {
133
- "kind": "string"
134
- },
135
- "payload/commits#/message": {
136
- "kind": "string"
137
- },
138
- "payload/forkee/full_name": {
139
- "kind": "string"
140
- },
141
- "payload/issue/number": {
142
- "kind": "integer",
143
- "identifier": true
144
- },
145
- "payload/issue/title": {
146
- "kind": "string"
147
- },
148
- "payload/pages#/action": {
149
- "kind": "string"
150
- },
151
- "payload/pages#/title": {
152
- "kind": "string"
153
- },
154
- "public": {
155
- "kind": "boolean",
156
- "hidden": true
157
- },
158
- "repo": {
159
- "kind": "json",
160
- "hidden": true
161
- },
162
- "repo/name": {
163
- "kind": "string",
164
- "identifier": true
165
- }
166
- }
167
- }
168
- }
@@ -1,67 +0,0 @@
1
- import {
2
- existsSync,
3
- mkdirSync,
4
- readdirSync,
5
- readFileSync,
6
- rmSync,
7
- statSync,
8
- writeFileSync,
9
- } from "node:fs"
10
- import { resolve } from "node:path"
11
-
12
- export type FilesystemStorageOptions = {
13
- path: string
14
- }
15
-
16
- export class FilesystemStorage<
17
- T extends Record<string, string> = Record<string, string>,
18
- > implements Storage
19
- {
20
- public rootDir: string
21
-
22
- public constructor(options: FilesystemStorageOptions) {
23
- this.rootDir = options.path
24
- if (!existsSync(this.rootDir)) {
25
- mkdirSync(this.rootDir, { recursive: true })
26
- }
27
- }
28
-
29
- public getItem<K extends string & keyof T>(key: K): T[K] | null {
30
- const filePath = resolve(this.rootDir, key)
31
- if (existsSync(filePath)) {
32
- return readFileSync(filePath, `utf-8`) as T[K]
33
- }
34
- return null
35
- }
36
-
37
- public setItem<K extends string & keyof T>(key: K, value: T[K]): void {
38
- const filePath = resolve(this.rootDir, key)
39
- writeFileSync(filePath, value)
40
- }
41
-
42
- public removeItem<K extends string & keyof T>(key: K): void {
43
- const filePath = resolve(this.rootDir, key)
44
- if (existsSync(filePath)) {
45
- rmSync(filePath)
46
- }
47
- }
48
-
49
- public key(index: number): (string & keyof T) | null {
50
- const filePaths = readdirSync(this.rootDir)
51
- const filePathsByDateCreated = filePaths.sort((a, b) => {
52
- const aStat = statSync(a)
53
- const bStat = statSync(b)
54
- return bStat.ctimeMs - aStat.ctimeMs
55
- })
56
- return (filePathsByDateCreated[index] as string & keyof T) ?? null
57
- }
58
-
59
- public clear(): void {
60
- rmSync(this.rootDir, { recursive: true })
61
- mkdirSync(this.rootDir, { recursive: true })
62
- }
63
-
64
- public get length(): number {
65
- return readdirSync(this.rootDir).length
66
- }
67
- }