@decaf-ts/utils 0.11.2 → 0.11.4
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.
- package/dist/utils.cjs +2200 -2
- package/dist/utils.js +2216 -2
- package/lib/assets/slogans.cjs +1 -1
- package/lib/bin/build-scripts.cjs +1 -1
- package/lib/bin/tag-release.cjs +1 -1
- package/lib/cli/command.cjs +1 -1
- package/lib/cli/commands/build-scripts.cjs +1 -1
- package/lib/cli/commands/index.cjs +1 -1
- package/lib/cli/commands/tag-release.cjs +1 -1
- package/lib/cli/constants.cjs +1 -1
- package/lib/cli/index.cjs +1 -1
- package/lib/cli/types.cjs +1 -1
- package/lib/esm/assets/slogans.js +1 -1
- package/lib/esm/bin/build-scripts.js +1 -1
- package/lib/esm/bin/tag-release.js +1 -1
- package/lib/esm/cli/command.js +1 -1
- package/lib/esm/cli/commands/build-scripts.js +1 -1
- package/lib/esm/cli/commands/index.js +1 -1
- package/lib/esm/cli/commands/tag-release.js +1 -1
- package/lib/esm/cli/constants.js +1 -1
- package/lib/esm/cli/index.js +1 -1
- package/lib/esm/cli/types.js +1 -1
- package/lib/esm/index.d.ts +1 -1
- package/lib/esm/index.js +2 -2
- package/lib/esm/input/index.js +1 -1
- package/lib/esm/input/input.js +1 -1
- package/lib/esm/input/types.js +1 -1
- package/lib/esm/output/common.js +1 -1
- package/lib/esm/output/index.js +1 -1
- package/lib/esm/tests/Consumer.js +1 -1
- package/lib/esm/tests/ProducerChildProcess.js +1 -1
- package/lib/esm/tests/TestReporter.d.ts +3 -0
- package/lib/esm/tests/TestReporter.js +20 -2
- package/lib/esm/tests/index.js +1 -1
- package/lib/esm/tests/utils.js +1 -1
- package/lib/esm/utils/constants.js +1 -1
- package/lib/esm/utils/fs.js +1 -1
- package/lib/esm/utils/http.js +1 -1
- package/lib/esm/utils/index.js +1 -1
- package/lib/esm/utils/md.js +1 -1
- package/lib/esm/utils/timeout.js +1 -1
- package/lib/esm/utils/types.js +1 -1
- package/lib/esm/utils/utils.js +1 -1
- package/lib/esm/writers/OutputWriter.js +1 -1
- package/lib/esm/writers/RegexpOutputWriter.js +1 -1
- package/lib/esm/writers/StandardOutputWriter.js +11 -4
- package/lib/esm/writers/index.js +1 -1
- package/lib/esm/writers/types.js +1 -1
- package/lib/index.cjs +2 -2
- package/lib/index.d.ts +1 -1
- package/lib/input/index.cjs +1 -1
- package/lib/input/input.cjs +1 -1
- package/lib/input/types.cjs +1 -1
- package/lib/output/common.cjs +1 -1
- package/lib/output/index.cjs +1 -1
- package/lib/tests/Consumer.cjs +1 -1
- package/lib/tests/ProducerChildProcess.cjs +1 -1
- package/lib/tests/TestReporter.cjs +20 -2
- package/lib/tests/TestReporter.d.ts +3 -0
- package/lib/tests/index.cjs +1 -1
- package/lib/tests/utils.cjs +1 -1
- package/lib/utils/constants.cjs +1 -1
- package/lib/utils/fs.cjs +1 -1
- package/lib/utils/http.cjs +1 -1
- package/lib/utils/index.cjs +1 -1
- package/lib/utils/md.cjs +1 -1
- package/lib/utils/timeout.cjs +1 -1
- package/lib/utils/types.cjs +1 -1
- package/lib/utils/utils.cjs +1 -1
- package/lib/writers/OutputWriter.cjs +1 -1
- package/lib/writers/RegexpOutputWriter.cjs +1 -1
- package/lib/writers/StandardOutputWriter.cjs +11 -4
- package/lib/writers/index.cjs +1 -1
- package/lib/writers/types.cjs +1 -1
- package/package.json +3 -1
- package/dist/utils.cjs.map +0 -1
- package/dist/utils.js.map +0 -1
- package/lib/assets/slogans.js.map +0 -1
- package/lib/bin/build-scripts.js.map +0 -1
- package/lib/bin/tag-release.js.map +0 -1
- package/lib/cli/command.js.map +0 -1
- package/lib/cli/commands/build-scripts.js.map +0 -1
- package/lib/cli/commands/index.js.map +0 -1
- package/lib/cli/commands/tag-release.js.map +0 -1
- package/lib/cli/constants.js.map +0 -1
- package/lib/cli/index.js.map +0 -1
- package/lib/cli/types.js.map +0 -1
- package/lib/esm/assets/slogans.js.map +0 -1
- package/lib/esm/bin/build-scripts.js.map +0 -1
- package/lib/esm/bin/tag-release.js.map +0 -1
- package/lib/esm/cli/command.js.map +0 -1
- package/lib/esm/cli/commands/build-scripts.js.map +0 -1
- package/lib/esm/cli/commands/index.js.map +0 -1
- package/lib/esm/cli/commands/tag-release.js.map +0 -1
- package/lib/esm/cli/constants.js.map +0 -1
- package/lib/esm/cli/index.js.map +0 -1
- package/lib/esm/cli/types.js.map +0 -1
- package/lib/esm/index.js.map +0 -1
- package/lib/esm/input/index.js.map +0 -1
- package/lib/esm/input/input.js.map +0 -1
- package/lib/esm/input/types.js.map +0 -1
- package/lib/esm/output/common.js.map +0 -1
- package/lib/esm/output/index.js.map +0 -1
- package/lib/esm/tests/Consumer.js.map +0 -1
- package/lib/esm/tests/ProducerChildProcess.js.map +0 -1
- package/lib/esm/tests/TestReporter.js.map +0 -1
- package/lib/esm/tests/index.js.map +0 -1
- package/lib/esm/tests/utils.js.map +0 -1
- package/lib/esm/utils/constants.js.map +0 -1
- package/lib/esm/utils/fs.js.map +0 -1
- package/lib/esm/utils/http.js.map +0 -1
- package/lib/esm/utils/index.js.map +0 -1
- package/lib/esm/utils/md.js.map +0 -1
- package/lib/esm/utils/timeout.js.map +0 -1
- package/lib/esm/utils/types.js.map +0 -1
- package/lib/esm/utils/utils.js.map +0 -1
- package/lib/esm/writers/OutputWriter.js.map +0 -1
- package/lib/esm/writers/RegexpOutputWriter.js.map +0 -1
- package/lib/esm/writers/StandardOutputWriter.js.map +0 -1
- package/lib/esm/writers/index.js.map +0 -1
- package/lib/esm/writers/types.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/input/index.js.map +0 -1
- package/lib/input/input.js.map +0 -1
- package/lib/input/types.js.map +0 -1
- package/lib/output/common.js.map +0 -1
- package/lib/output/index.js.map +0 -1
- package/lib/tests/Consumer.js.map +0 -1
- package/lib/tests/ProducerChildProcess.js.map +0 -1
- package/lib/tests/TestReporter.js.map +0 -1
- package/lib/tests/index.js.map +0 -1
- package/lib/tests/utils.js.map +0 -1
- package/lib/utils/constants.js.map +0 -1
- package/lib/utils/fs.js.map +0 -1
- package/lib/utils/http.js.map +0 -1
- package/lib/utils/index.js.map +0 -1
- package/lib/utils/md.js.map +0 -1
- package/lib/utils/timeout.js.map +0 -1
- package/lib/utils/types.js.map +0 -1
- package/lib/utils/utils.js.map +0 -1
- package/lib/writers/OutputWriter.js.map +0 -1
- package/lib/writers/RegexpOutputWriter.js.map +0 -1
- package/lib/writers/StandardOutputWriter.js.map +0 -1
- package/lib/writers/index.js.map +0 -1
- package/lib/writers/types.js.map +0 -1
package/dist/utils.js
CHANGED
|
@@ -1,2 +1,2216 @@
|
|
|
1
|
-
import e from"prompts";import{parseArgs as t}from"util";import{Logging as o,escapeRegExp as a,LoggedClass as s,LoggedEnvironment as r,LogLevel as n}from"@decaf-ts/logging";import i from"fs";import c from"path";import{spawn as l}from"child_process";import{style as g}from"styled-string-builder";import f from"zlib";import d from"https";import{rollup as h}from"rollup";import u from"@rollup/plugin-typescript";import m from"@rollup/plugin-commonjs";import{nodeResolve as p}from"@rollup/plugin-node-resolve";import S from"@rollup/plugin-json";import{builtinModules as y}from"module";import*as T from"typescript";import{ModuleKind as b}from"typescript";class w{static{this.logger=o.for(w)}constructor(e){this.type="text",this.name=e}setType(e){return w.logger.verbose("Setting type to: "+e),this.type=e,this}setMessage(e){return w.logger.verbose("Setting message to: "+e),this.message=e,this}setInitial(e){return w.logger.verbose("Setting initial value to: "+e),this.initial=e,this}setStyle(e){return w.logger.verbose("Setting style to: "+e),this.style=e,this}setFormat(e){return w.logger.verbose("Setting format function"),this.format=e,this}setValidate(e){return w.logger.verbose("Setting validate function"),this.validate=e,this}setOnState(e){return w.logger.verbose("Setting onState callback"),this.onState=e,this}setMin(e){return w.logger.verbose("Setting min value to: "+e),this.min=e,this}setMax(e){return w.logger.verbose("Setting max value to: "+e),this.max=e,this}setFloat(e){return w.logger.verbose("Setting float to: "+e),this.float=e,this}setRound(e){return w.logger.verbose("Setting round to: "+e),this.round=e,this}setInstructions(e){return w.logger.verbose("Setting instructions to: "+e),this.instructions=e,this}setIncrement(e){return w.logger.verbose("Setting increment to: "+e),this.increment=e,this}setSeparator(e){return w.logger.verbose("Setting separator to: "+e),this.separator=e,this}setActive(e){return w.logger.verbose("Setting active style to: "+e),this.active=e,this}setInactive(e){return w.logger.verbose("Setting inactive style to: "+e),this.inactive=e,this}setChoices(e){return w.logger.verbose("Setting choices: "+JSON.stringify(e)),this.choices=e,this}setHint(e){return w.logger.verbose("Setting hint to: "+e),this.hint=e,this}setWarn(e){return w.logger.verbose("Setting warn to: "+e),this.warn=e,this}setSuggest(e){return w.logger.verbose("Setting suggest function"),this.suggest=e,this}setLimit(e){return w.logger.verbose("Setting limit to: "+e),this.limit=e,this}setMask(e){return w.logger.verbose("Setting mask to: "+e),this.mask=e,this}setStdout(e){return w.logger.verbose("Setting stdout stream"),this.stdout=e,this}setStdin(e){return this.stdin=e,this}async ask(){return(await w.ask(this))[this.name]}static async ask(t){const o=w.logger.for(this.ask);let a;Array.isArray(t)||(t=[t]);try{o.verbose("Asking questions: "+t.map(e=>e.name).join(", ")),a=await e(t),o.verbose("Received answers: "+JSON.stringify(a,null,2))}catch(e){throw Error("Error while getting input: "+e)}return a}static async askNumber(e,t,o,a,s){w.logger.for(this.askNumber).verbose(`Asking number input: undefined, question: ${t}, min: ${o}, max: ${a}, initial: ${s}`);const r=new w(e).setMessage(t).setType("number");return"number"==typeof o&&r.setMin(o),"number"==typeof a&&r.setMax(a),"number"==typeof s&&r.setInitial(s),(await this.ask(r))[e]}static async askText(e,t,o=void 0,a){w.logger.for(this.askText).verbose(`Asking text input: undefined, question: ${t}, mask: ${o}, initial: ${a}`);const s=new w(e).setMessage(t);return o&&s.setMask(o),"string"==typeof a&&s.setInitial(a),(await this.ask(s))[e]}static async askConfirmation(e,t,o){w.logger.for(this.askConfirmation).verbose(`Asking confirmation input: undefined, question: ${t}, initial: ${o}`);const a=new w(e).setMessage(t).setType("confirm");return void 0!==o&&a.setInitial(o),(await this.ask(a))[e]}static async insist(e,t,o,a=1){const s=w.logger.for(this.insist);let r;s.verbose(`Insisting on input: ${e.name}, test: ${t.toString()}, defaultConfirmation: ${o}, limit: ${a}`);let n,i=0;try{do{r=(await w.ask(e))[e.name],t(r)?(n=await w.askConfirmation(e.name+"-confirm",`Is the ${e.type} correct?`,o),n||(r=void 0)):r=void 0}while(void 0===r&&a>1&&i++<a)}catch(e){throw s.error("Error while insisting: "+e),e}return void 0===r&&s.info("no selection..."),r}static async insistForText(e,t,o,a=void 0,s,r=!1,n=-1){w.logger.for(this.insistForText).verbose(`Insisting for text input: undefined, question: ${t}, test: ${o.toString()}, mask: ${a}, initial: ${s}, defaultConfirmation: ${r}, limit: ${n}`);const i=new w(e).setMessage(t);return a&&i.setMask(a),"string"==typeof s&&i.setInitial(s),await this.insist(i,o,r,n)}static async insistForNumber(e,t,o,a,s,r,n=!1,i=-1){w.logger.for(this.insistForNumber).verbose(`Insisting for number input: undefined, question: ${t}, test: ${o.toString()}, min: ${a}, max: ${s}, initial: ${r}, defaultConfirmation: ${n}, limit: ${i}`);const c=new w(e).setMessage(t).setType("number");return"number"==typeof a&&c.setMin(a),"number"==typeof s&&c.setMax(s),"number"==typeof r&&c.setInitial(r),await this.insist(c,o,n,i)}static parseArgs(e){const o=w.logger.for(this.parseArgs),a={args:process.argv.slice(2),options:e};o.debug("Parsing arguments: "+JSON.stringify(a,null,2));try{return t(a)}catch(t){throw o.debug(`Error while parsing arguments:\n${JSON.stringify(a,null,2)}\n | options\n${JSON.stringify(e,null,2)}\n | ${t}`),Error("Error while parsing arguments: "+t)}}}const C={verbose:{type:"boolean",short:"V",default:void 0},version:{type:"boolean",short:"v",default:void 0},help:{type:"boolean",short:"h",default:!1},logLevel:{type:"string",default:"info"},logStyle:{type:"boolean",default:!0},timestamp:{type:"boolean",default:!0},banner:{type:"boolean",default:!0}},D=Object.keys(C).reduce((e,t)=>(e[t]=C[t].default,e),{}),v="utf-8",k=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z])))/g;var $;(e=>{e.PATCH="patch",e.MINOR="minor",e.MAJOR="major"})($||($={}));const E="-no-ci",I="postinstall";var F;(e=>{e.GIT=".token",e.NPM=".npmtoken",e.DOCKER=".dockertoken",e.CONFLUENCE=".confluence-token"})(F||(F={}));const N="Aborted";class x{constructor(e,t,...a){this.cmd=e,this.lock=t,this.logger=o.for(this.cmd)}log(e,t){t=Buffer.isBuffer(t)?t.toString(v):t;const o="stderr"===e?g(t).red.text:t;this.logger.info(o)}data(e){this.log("stdout",e+"")}error(e){this.log("stderr",e+"")}errors(e){this.log("stderr","Error executing command exited : "+e)}exit(e,t){this.log("stdout","command exited code : "+(0===e?g(e.toString()).green.text:g(null===e?"null":e.toString()).red.text)),0===e?this.resolve(t.map(e=>e.trim()).join("\n")):this.reject(Error(t.length?t.join("\n"):e.toString()))}parseCommand(e){return e="string"==typeof e?e.split(" "):e,this.cmd=e.join(" "),[e[0],e.slice(1)]}resolve(e){this.log("stdout",`${this.cmd} executed successfully: ${g(e?"ran to completion":e).green}`),this.lock.resolve(e)}reject(e){e instanceof Error||(e=Error("number"==typeof e?"Exit code "+e:e)),this.log("stderr",`${this.cmd} failed to execute: ${g(e.message).red}`),this.lock.reject(e)}}function A(e){let t=Promise.resolve();return(...o)=>{const a=t.then(()=>e(...o));return t=a.catch(()=>{}),a}}function j(e,...t){let o,a;if(e instanceof AbortSignal?(a=new AbortController,o=[e,...t]):(a=e,o=t),a.signal.aborted)return a;const s=()=>a.abort();for(const e of o){if(e.aborted){a.abort();break}e.addEventListener("abort",s,{once:!0,signal:a.signal})}return a}function B(e,t,o,a,s){function r(t,a){const[r,n]=e.parseCommand(t);s.info("Running command: "+r),s.debug("with args: "+n.join(" "));const i=l(r,n,{...o,cwd:o.cwd||process.cwd(),env:Object.assign({},process.env,o.env,{PATH:process.env.PATH}),shell:o.shell||!1,signal:a.signal});return s.verbose("pid : "+i.pid),i}const n=t.match(/[<>$#]/g);if(n)throw Error(`Invalid command: ${t}. contains invalid characters: ${n}`);if(t.includes(" | ")){const e=t.split(" | "),o=[],s=Array(e.length);s[0]=a;for(let t=0;t<e.length;t++)0!==t&&(s[t]=j(s[t-1].signal)),o.push(r(e[t],s[t])),0!==t&&o[t-1].stdout.pipe(o[t].stdin);return o[e.length-1]}return r(t,a)}function M(e,t={},a=x,...s){const r=o.for(M),n=new AbortController,i={abort:n,command:e,logs:[],errs:[]},c=new Promise((o,c)=>{let l;try{l=new a(e,{resolve:o,reject:c},...s),i.cmd=B(l,e,t,n,r)}catch(t){return c(Error(`Error running command ${e}: ${t}`))}i.cmd.stdout.setEncoding("utf8"),i.cmd.stdout.on("data",e=>{e=e.toString(),i.logs.push(e),l.data(e)}),i.cmd.stderr.on("data",e=>{e=e.toString(),i.errs.push(e),l.error(e)}),i.cmd.once("error",e=>{l.exit(e.message,i.errs)}),i.cmd.once("exit",(e=0)=>{n.signal.aborted&&null===e&&(e=N),l.exit(e,0===e?i.logs:i.errs)})});return Object.assign(i,{promise:c,pipe:async t=>{const o=r.for("pipe");try{o.verbose(`Executing pipe function ${e}...`);const a=await c;return o.verbose(`Piping output to ${t.name}: ${a}`),t(a)}catch(e){throw o.error("Error piping command output: "+e),e}}}),i}const P=o.for("fs");function U(e,t,o){const s=P.for(U);if(!i.existsSync(e))throw Error(`File not found at path "${e}".`);let r=O(e);s.verbose(`Patching file "${e}"...`),s.debug("with value: "+JSON.stringify(t));try{r=((e,t,o="g",s)=>(Object.entries(t).forEach(([t,r])=>{const n=RegExp(a(t),o);e=e.replace(n,e=>(!s||s(e),r))}),e))(r,t,"g",o)}catch(e){throw Error("Error patching file: "+e)}L(e,r)}function O(e){const t=P.for(O);try{return t.verbose(`Reading file "${e}"...`),i.readFileSync(e,"utf8")}catch(o){throw t.verbose(`Error reading file "${e}": ${o}`),Error(`Error reading file "${e}": ${o}`)}}function L(e,t){const o=P.for(L);try{o.verbose(`Writing file "${e} with ${t.length} bytes...`),i.writeFileSync(e,t,"utf8")}catch(t){throw o.verbose(`Error writing file "${e}": ${t}`),Error(`Error writing file "${e}": ${t}`)}}function R(e,t){const o=P.for(R),a=[];try{return o.verbose(`Retrieving all files from "${e}"...`),i.readdirSync(e).forEach(t=>{const o=c.join(e,t),s=i.statSync(o);s.isFile()?a.push(o):s.isDirectory()&&a.push(...R(o))}),t?a.filter(t):a}catch(t){throw o.verbose(`Error retrieving files from "${e}": ${t}`),Error(`Error retrieving files from "${e}": ${t}`)}}async function J(e,t){const o=P.for(J);let a,s;try{a=i.statSync(e)}catch(t){throw o.verbose(`Source path "${e}" does not exist: ${t}`),Error(`Source path "${e}" does not exist: ${t}`)}try{s=i.statSync(t)}catch(e){}if(s)throw o.verbose(`Destination path "${t}" already exists`),Error(`Destination path "${t}" already exists`);try{o.verbose(`Renaming ${a.isFile()?"file":"directory"} "${e}" to "${t}...`),i.renameSync(e,t),o.verbose(`Successfully renamed to "${t}"`)}catch(s){throw o.verbose(`Error renaming ${a.isFile()?"file":"directory"} "${e}" to "${t}": ${s}`),Error(`Error renaming ${a.isFile()?"file":"directory"} "${e}" to "${t}": ${s}`)}}function W(e,t){const o=P.for(W);let a,s;try{a=i.statSync(e)}catch(t){throw o.verbose(`Source path "${e}" does not exist: ${t}`),Error(`Source path "${e}" does not exist: ${t}`)}try{s=i.statSync(t)}catch(e){a.isDirectory()&&(o.verbose(`Dest path "${t}" does not exist. creating`),i.mkdirSync(t,{recursive:!0}))}try{o.verbose(`Copying ${a.isFile()?"file":"directory"} "${e}" to "${t}...`),i.cpSync(e,t,{recursive:!0})}catch(s){throw o.verbose(`Error copying ${a.isFile()?"file":"directory"} "${e}" to "${t}: ${s}`),Error(`Error copying ${a.isFile()?"file":"directory"} "${e}" to "${t}: ${s}`)}}function X(e){const t=P.for(X);try{const o=i.statSync(e);o.isFile()?(t.verbose(`Deleting file "${e}...`),i.rmSync(e,{recursive:!0,force:!0})):o.isDirectory()&&i.rmSync(e,{recursive:!0,force:!0})}catch(o){throw t.verbose(`Error Deleting "${e}": ${o}`),Error(`Error Deleting "${e}": ${o}`)}}function V(e=process.cwd(),t){let o;try{o=JSON.parse(O(c.join(e,"package.json")))}catch(e){throw Error('Failed to retrieve package information" '+e)}if(t){if(!(t in o))throw Error(`Property "${t}" not found in package.json`);return o[t]}return o}function G(e,t,o=process.cwd()){const a=V(o);a[e]=t,L(c.join(o,"package.json"),JSON.stringify(a,null,2))}function _(e=process.cwd()){return V(e,"version")}async function H(e=process.cwd()){let t;try{t=JSON.parse(await M("npm ls --json",{cwd:e}).promise)}catch(e){throw Error("Failed to retrieve dependencies: "+e)}const o=(e,t)=>({name:e[0],version:e[1].version});return{prod:Object.entries(t.dependencies||{}).map(o),dev:Object.entries(t.devDependencies||{}).map(o),peer:Object.entries(t.peerDependencies||{}).map(o)}}async function K(){const e=P.for(K);e.info("checking for updates..."),await M("npx npm-check-updates -u").promise,e.info("updating..."),await M("npx npm run do-install").promise}async function z(e,t){if(!t){const e=await H();t={prod:e.prod?.map(e=>e.name)||[],dev:e.dev?.map(e=>e.name)||[],peer:e.peer?.map(e=>e.name)||[]}}const{prod:o,dev:a,peer:s}=t,r=Array.from(new Set([...o||[],...a||[],...s||[]])),n=(e="string"==typeof e?[e]:e).filter(e=>!r.includes(e));return n.length&&await q({dev:n}),t.dev=t.dev||[],t.dev.push(...n),t}async function Y(){const e=P.for(Y),t=await M("git config user.name").promise,o=await M("git config user.email").promise;e.verbose(`cached git id: ${t}/${o}. changing to automation`),await M('git config user.email "automation@decaf.ts"').promise,await M('git config user.name "decaf"').promise,e.info("Pushing changes to git..."),await M("git add .").promise,await M('git commit -m "refs #1 - after repo setup"').promise,await M("git push").promise,await M(`git config user.email "${o}"`).promise,await M(`git config user.name "${t}"`).promise,e.verbose(`reverted to git id: ${t}/${o}`)}async function q(e){const t=P.for(q),o=e.prod||[],a=e.dev||[],s=e.peer||[];o.length&&(t.info(`Installing dependencies ${o.join(", ")}...`),await M("npm install "+o.join(" "),{cwd:process.cwd()}).promise),a.length&&(t.info(`Installing devDependencies ${a.join(", ")}...`),await M("npm install --save-dev "+a.join(" "),{cwd:process.cwd()}).promise),s.length&&(t.info(`Installing peerDependencies ${s.join(", ")}...`),await M("npm install --save-peer "+s.join(" "),{cwd:process.cwd()}).promise)}async function Z(e){return e.then(e=>e.default||e)}async function Q(e){const t=P.for(Q);try{const o=i.readdirSync(e).map(t=>c.join(e,t)).filter(e=>{try{return i.statSync(e).isFile()&&(e.endsWith(".js")||e.endsWith(".cjs")||e.endsWith(".mjs"))}catch{return!1}});if(0===o.length)throw Error("No JS files found in directory "+e);let a=o[0],s=i.statSync(a).size;for(const e of o.slice(1)){const t=i.statSync(e).size;s>t&&(a=e,s=t)}t.verbose(`Selected smallest bundle: ${a} (${s} bytes)`);const r=i.readFileSync(a),n=f.gzipSync(r),l=Number((n.length/1024).toFixed(1));return t.verbose(`Gzipped size: ${n.length} bytes (${l} KB)`),l}catch(o){throw t.verbose(`Failed to compute gzipped size for ${e}: ${o}`),o}}function ee(e=process.cwd(),t){const o=P.for(ee);try{return i.existsSync(e)?i.readdirSync(e,{withFileTypes:!0}).filter(e=>!t||t(e.name,e)).map(e=>e.name):[]}catch(t){return o.verbose(`Failed to list folder ${e}: ${t}`),[]}}function te(e=c.join(process.cwd(),"node_modules")){const t=P.for(te);try{if(!i.existsSync(e))return[];const o=i.readdirSync(e,{withFileTypes:!0}),a=[];for(const s of o)try{if(!s.isDirectory())continue;if(s.name.startsWith("."))continue;if(s.name.startsWith("@")){const o=c.join(e,s.name);try{const e=i.readdirSync(o,{withFileTypes:!0});for(const t of e)t.isDirectory()&&!t.name.startsWith(".")&&a.push(`${s.name}/${t.name}`)}catch(e){t.verbose(`Failed to read scope ${o}: ${e}`)}}else a.push(s.name)}catch(e){t.verbose(`Skipping entry ${s.name} due to error: ${e}`)}return a}catch(o){return t.verbose(`Failed to list node_modules packages at ${e}: ${o}`),[]}}const oe=[{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That's Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"Decaf-TS: Where smart contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No CRUD, no problem \u2014 Decaf your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS: Your frontend already understands your smart contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye CRUD, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From smart contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No CRUD. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem \u2014 Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem \u2014 Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem \u2014 Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem \u2014 Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"}],ae=["\x1b[38;5;215m","\x1b[38;5;209m","\x1b[38;5;205m","\x1b[38;5;210m","\x1b[38;5;217m","\x1b[38;5;216m","\x1b[38;5;224m","\x1b[38;5;230m","\x1b[38;5;230m"];function se(e){const t=re(),o="# \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \n# ( ( \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \n# ) ) \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \n# [=======] \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \n# `-----\xb4 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \n# \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \n# \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \n#".split("\n"),a=o.reduce((e,t)=>Math.max(e,t.length),0);o.push("# "+t.padStart(a-3)),o.forEach((t,o)=>{(e?e.info.bind(e):(()=>{}).bind())(g(t||"").raw(ae[o]).text)})}function re(e){try{return e=void 0===e?Math.floor(Math.random()*oe.length):e,oe[e].Slogan}catch(e){throw Error("Failed to retrieve slogans: "+e)}}class ne extends s{constructor(e,t={},a=[]){super(),this.name=e,this.inputs=t,this.requirements=a,ne.log||Object.defineProperty(ne,"log",{writable:!1,value:o.for(ne.name)}),this.inputs=Object.assign({},C,t)}async checkRequirements(){const{prod:e,dev:t,peer:o}=await H(),a=[],s=Array.from(new Set([...e,...t,...o]).values()).map(e=>e.name);for(const e of this.requirements)s.includes(e)||a.push(e);a.length}help(e){return this.log.info("This is help. I'm no use because I should have been overridden.")}async execute(){const e=w.parseArgs(this.inputs),t=r.accumulate(D).accumulate(e.values),{version:o,help:a,banner:s}=t;if(o)return _();if(a)return this.help(e);let n;s&&se(this.log.for(se,{timestamp:!1,style:!1,context:!1,logLevel:!1}));try{n=await this.run(t)}catch(e){throw e}return n}}class ie{static{this.log=o.for(ie)}static async downloadFile(e){return new Promise((t,o)=>{!function e(a){a=encodeURI(a),d.get(a,s=>{if(301===s.statusCode||307===s.statusCode)return e(s.headers.location);if(200!==s.statusCode)return ie.log.error(`Failed to fetch ${a} (status: ${s.statusCode})`),o(Error("Failed to fetch "+a));let r="";s.on("data",e=>{r+=e}),s.on("error",e=>{o(e)}),s.on("end",()=>{t(r)})})}(e)})}}function ce(e){return e?Array.isArray(e)?e.map(e=>(""+e).trim()).filter(Boolean):(""+e).split(",").map(e=>e.trim()).filter(Boolean):[]}function le(e){return e.replace(/^@/,"").split(/[/\-_.]+/).filter(Boolean).map((e,t)=>0===t?e.replace(/[^a-zA-Z0-9]/g,""):`${e.charAt(0).toUpperCase()}${e.slice(1)}`).join("")}function ge(){let e;try{e=V(process.cwd())}catch{e=void 0}try{if(!e||!(Object.keys(e.dependencies||{}).length>0||Object.keys(e.devDependencies||{}).length>0||Object.keys(e.peerDependencies||{}).length>0)){const t=c.resolve(__dirname,"../../..");try{e=V(t)}catch{}}}catch{}const t=Object.keys(e&&e.dependencies||{}),o=Object.keys(e&&e.peerDependencies||{}),a=Object.keys(e&&e.devDependencies||{});return Array.from(new Set([...t,...o,...a]))}const fe="##VERSION##",de="##PACKAGE##",he="##PACKAGE_SIZE##";var ue,me;(e=>{e.CJS="commonjs",e.ESM="es2022"})(ue||(ue={})),(e=>{e.BUILD="build",e.BUNDLE="bundle",e.ALL="all"})(me||(me={}));const pe={prod:{type:"boolean",default:!1},dev:{type:"boolean",default:!1},buildMode:{type:"string",default:me.ALL},includes:{type:"string",default:""},externals:{type:"string",default:""},docs:{type:"boolean",default:!1},commands:{type:"boolean",default:!1},banner:{type:"boolean",default:!1}},Se=(e=".cjs")=>{const t=ye.log.for(Se),o=new Map;return a=>s=>{const r=c.dirname(s.fileName);function n(a){const s=JSON.stringify([r,a]),n=o.get(s);if(null!=n)return n;let l,g=a;try{g=c.resolve(r,g+".ts")}catch(e){throw Error(`Failed to resolve path ${a}: ${e}`)}try{l=i.statSync(g)}catch(e){try{t.verbose(`Testing existence of path ${g} as a folder defaulting to index file`),l=i.statSync(g.replace(/\.ts$/gm,""))}catch(t){throw Error(`Failed to resolve path ${a}: ${e}, ${t}`)}}if(l.isDirectory()&&(g=g.replace(/\.ts$/gm,"/index.ts")),c.isAbsolute(g)){const t=(/\.tsx?$/.exec(c.basename(g))||[])[0]||void 0;g="./"+c.relative(r,c.resolve(c.dirname(g),c.basename(g,t)+e))}return o.set(s,g),g}return T.visitNode(s,function e(t){if((e=>!(!T.isImportDeclaration(e)&&!T.isExportDeclaration(e)||void 0===e.moduleSpecifier||!T.isStringLiteral(e.moduleSpecifier)||!e.moduleSpecifier.text.startsWith("./")&&!e.moduleSpecifier.text.startsWith("../")||""!==c.extname(e.moduleSpecifier.text)))(t)){if(T.isImportDeclaration(t)){const e=n(t.moduleSpecifier.text),o=a.factory.createStringLiteral(e);return a.factory.updateImportDeclaration(t,t.modifiers,t.importClause,o,void 0)}if(T.isExportDeclaration(t)){const e=n(t.moduleSpecifier.text),o=a.factory.createStringLiteral(e);return a.factory.updateExportDeclaration(t,t.modifiers,t.isTypeOnly,t.exportClause,o,void 0)}}return T.visitEachChild(t,e,a)})}};class ye extends ne{constructor(){super("BuildScripts",Object.assign({},C,pe)),this.replacements={};const e=V(),{name:t,version:o}=e;this.pkgName=t.includes("@")?t.split("/")[1]:t,this.pkgVersion=o,this.replacements[fe]=this.pkgVersion,this.replacements[de]=t}patchFiles(e){const t=this.log.for(this.patchFiles),{name:o,version:a}=V();t.info(`Patching ${o} ${a} module in ${e}...`),i.statSync(e).isDirectory()&&i.readdirSync(e,{withFileTypes:!0,recursive:!0}).filter(e=>e.isFile()).forEach(e=>U(c.join(e.parentPath,e.name),Object.entries(this.replacements).reduce((e,[o,a])=>{switch(o){case fe:t.debug("Found VERSION string to replace"),e[`VERSION = "${fe}";`]=`VERSION = "${a}";`;break;case de:t.debug("Found PACKAGE_NAME string to replace"),e[`PACKAGE_NAME = "${de}";`]=`PACKAGE_NAME = "${a}";`;break;default:e[o]=a}return e},{}))),t.verbose(`Module ${o} ${a} patched in ${e}...`)}reportDiagnostics(e,t){const o=this.formatDiagnostics(e);try{this.log[t](o)}catch(e){throw e}return o}formatDiagnostics(e){return e.map(e=>{let t="";if(e.file&&e.start){const{line:o,character:a}=e.file.getLineAndCharacterOfPosition(e.start);t+=`${e.file.fileName} (${o+1},${a+1})`}return t+=": "+T.flattenDiagnosticMessageText(e.messageText,"\n"),t}).join("\n")}readConfigFile(e){const t=i.readFileSync(e).toString(),o=T.parseConfigFileTextToJson(e,t),a=o.config;a||this.reportDiagnostics([o.error],n.error);const s=T.parseJsonConfigFileContent(a,T.sys,c.dirname(e));return s.errors.length>0&&this.reportDiagnostics(s.errors,n.error),s}evalDiagnostics(e){if(e&&e.length>0){const t=e.filter(e=>e.category===T.DiagnosticCategory.Error),o=e.filter(e=>e.category===T.DiagnosticCategory.Warning),a=e.filter(e=>e.category===T.DiagnosticCategory.Suggestion),s=e.filter(e=>e.category===T.DiagnosticCategory.Message);if(o.length&&this.reportDiagnostics(o,n.warn),t.length)throw this.reportDiagnostics(e,n.error),Error(`TypeScript reported ${e.length} diagnostic(s) during check; aborting.`);a.length&&this.reportDiagnostics(a,n.info),s.length&&this.reportDiagnostics(s,n.info)}}preCheckDiagnostics(e){const t=T.getPreEmitDiagnostics(e);this.evalDiagnostics(t)}async checkTsDiagnostics(e,t,o=!1){const a=this.log.for(this.checkTsDiagnostics);let s;try{s=this.readConfigFile("./tsconfig.json")}catch(e){throw Error("Failed to parse tsconfig.json: "+e)}o?(s.options.module=b.AMD,s.options.outDir="dist",s.options.isolatedModules=!1,s.options.outFile=this.pkgName):(s.options.outDir="lib"+(t===ue.ESM?"/esm":""),s.options.module=t===ue.ESM?b.ES2022:b.CommonJS),s.options.inlineSourceMap=!1,s.options.inlineSources=!1,s.options.sourceMap=!0;const r=T.createProgram(s.fileNames,s.options);this.preCheckDiagnostics(r),a.verbose(`TypeScript checks passed (${o?"bundle":"normal"} mode).`)}async buildTs(e,t,o=!1){let a;this.log.for(this.buildTs).info(`Building ${this.pkgName} ${this.pkgVersion} module (${t}) in ${e?"dev":"prod"} mode...`);try{a=this.readConfigFile("./tsconfig.json")}catch(e){throw Error("Failed to parse tsconfig.json: "+e)}o?(a.options.module=b.AMD,a.options.outDir="dist",a.options.isolatedModules=!1,a.options.outFile=this.pkgName):(a.options.outDir="lib"+(t===ue.ESM?"/esm":""),a.options.module=t===ue.ESM?b.ES2022:b.CommonJS),e?(a.options.inlineSourceMap=!0,a.options.inlineSources=!0,a.options.sourceMap=!1):(a.options.inlineSourceMap=!1,a.options.inlineSources=!1,a.options.sourceMap=!0);const s=T.createProgram(a.fileNames,a.options),r={};t===ue.CJS?r.before=[Se(".cjs")]:t===ue.ESM&&(r.before=[Se(".js")]);const n=s.emit(void 0,void 0,void 0,void 0,r),i=T.getPreEmitDiagnostics(s).concat(n.diagnostics);this.evalDiagnostics(i)}async build(e,t,o=!1){const a=this.log.for(this.build);if(await this.buildTs(e,t,o),a.verbose(`Module ${this.pkgName} ${this.pkgVersion} (${t}) built in ${e?"dev":"prod"} mode...`),t===ue.CJS&&!o){const e=R("lib",e=>e.endsWith(".js")&&!e.includes("/esm/"));for(const t of e){a.verbose(`Patching ${t}'s cjs imports...`);const e=t.replace(".js",".cjs");await J(t,e)}}}copyAssets(e){const t=this.log.for(this.copyAssets);let o=!1;try{o=i.statSync("./src/assets").isDirectory()}catch(e){return t.verbose("No assets found in ./src/assets to copy")}o&&W("./src/assets",`./${e===ue.CJS?"lib":"dist"}/assets`)}async bundle(e,t,o,a="src/index.ts",s=this.pkgName,r,n=["prompts","styled-string-builder","typed-object-accumulator","@decaf-ts/logging"]){await this.checkTsDiagnostics(t,e,!0);const i=e===ue.ESM,l=this.pkgName,g=this.log,f=Array.from(new Set([...ce(n)]));let d=ce(r);if(0===d.length){try{d=te(c.join(process.cwd(),"node_modules"))}catch{}d&&0!==d.length||(d=ge())}const T=Array.from(new Set([...(()=>{try{return Array.isArray(y)?y:[]}catch{return["fs","path","process","child_process","util","https","http","os","stream","crypto","zlib","net","tls","url","querystring","assert","events","tty","dns","querystring"]}})(),...d])),b=!t||"inline",w=[u({compilerOptions:{module:"esnext",declaration:!1,outDir:o?"bin":"dist",sourceMap:!t,inlineSourceMap:!!t,inlineSources:!!t},include:["src/**/*.ts"],exclude:["node_modules","**/*.spec.ts"],tsconfig:"./tsconfig.json"}),S()];o&&w.push(m({include:[],exclude:d}),p({resolveOnly:f}));try{const k=await import("@rollup/plugin-terser"),$=k&&k.terser||k.default||k,E={parse:{ecma:2020},compress:!1,mangle:!1,format:{comments:!1,beautify:!0}},I={parse:{ecma:2020},compress:{ecma:2020,passes:5,drop_console:!0,drop_debugger:!0,toplevel:!0,module:i,unsafe:!0,unsafe_arrows:!0,unsafe_comps:!0,collapse_vars:!0,reduce_funcs:!0,reduce_vars:!0},mangle:{toplevel:!0},format:{comments:!1,ascii_only:!0},toplevel:!0};w.push($(t?E:I))}catch{}const C={input:a,plugins:w,external:T,onwarn:void 0,treeshake:!t},D={};T.forEach(e=>{D[e]=le(e)});const v=[{file:`${o?"bin/":"dist/"}${s||".bundle."+(t?"":"min")}${i?".js":".cjs"}`,format:o?"cjs":i?"esm":"umd",name:l,esModule:i,sourcemap:b,globals:D,exports:"auto"}];try{const F=await h(C);async function N(e){for(const t of v)await e.write(t)}g.verbose(F.watchFiles),await N(F)}catch(x){throw Error("Failed to bundle: "+x)}}async buildByEnv(e,t=me.ALL,o,a){try{X("lib")}catch(e){}try{X("dist")}catch(e){}i.mkdirSync("lib"),i.mkdirSync("dist"),[me.ALL,me.BUILD].includes(t)&&(await this.build(e,ue.ESM),await this.build(e,ue.CJS),this.patchFiles("lib")),[me.ALL,me.BUNDLE].includes(t)&&(await this.bundle(ue.ESM,e,!1,"src/index.ts",this.pkgName,a,o),await this.bundle(ue.CJS,e,!1,"src/index.ts",this.pkgName,a,o),this.patchFiles("dist")),this.copyAssets(ue.CJS),this.copyAssets(ue.ESM)}async buildDev(e=me.ALL,t,o){return this.buildByEnv(!0,e,t,o)}async buildProd(e=me.ALL,t,o){return this.buildByEnv(!1,e,t,o)}async buildDocs(){await M("npm install better-docs taffydb").promise,await M("npx markdown-include ./workdocs/readme-md.json").promise,await M("npx jsdoc -c ./workdocs/jsdocs.json -t ./node_modules/better-docs").promise,await M("npm remove better-docs taffydb").promise,[{src:"workdocs/assets",dest:"./docs/workdocs/assets"},{src:"workdocs/reports/coverage",dest:"./docs/workdocs/reports/coverage"},{src:"workdocs/reports/html",dest:"./docs/workdocs/reports/html"},{src:"workdocs/resources",dest:"./docs/workdocs/resources"},{src:"LICENSE.md",dest:"./docs/LICENSE.md"}].forEach(e=>{const{src:t,dest:o}=e;W(t,o)});try{const e=await Q(c.resolve(c.join(process.cwd(),"dist")));this.replacements[he]=e+" KB"}catch{this.replacements[he]="unknown"}try{U("./README.md",this.replacements)}catch(e){this.log.for(this.buildDocs).verbose("Failed to patch README.md: "+e)}}async run(e){const{dev:t,prod:o,docs:a,buildMode:s,includes:r,externals:n}=e;return t?await this.buildDev(s,r,n):o?await this.buildProd(s,r,n):a?await this.buildDocs():void 0}}const Te={ci:{type:"boolean",default:!0},message:{type:"string",short:"m"},tag:{type:"string",short:"t",default:void 0}};class be extends ne{constructor(){super("ReleaseScript",Te)}async prepareVersion(e){const t=this.log.for(this.prepareVersion);return(e=this.testVersion(e||""))||(t.verbose("No release message provided. Prompting for one:"),t.info("Listing latest git tags:"),await M("git tag --sort=-taggerdate | head -n 5").promise,await w.insistForText("tag","Enter the new tag number (accepts v*.*.*[-...])",e=>!!e.toString().match(/^v[0-9]+\.[0-9]+.[0-9]+(-[0-9a-zA-Z-]+)?$/)))}testVersion(e){const t=this.log.for(this.testVersion);switch(e=e.trim().toLowerCase()){case $.PATCH:case $.MINOR:case $.MAJOR:return t.verbose("Using provided SemVer update: "+e,1),e;default:return t.verbose("Testing provided version for SemVer compatibility: "+e,1),RegExp(k).test(e)?(t.verbose("version approved: "+e,1),e):void t.debug("Invalid version number: "+e)}}async prepareMessage(e){const t=this.log.for(this.prepareMessage);return e||(t.verbose("No release message provided. Prompting for one"),await w.insistForText("message","What should be the release message/ticket?",e=>!!e&&e.toString().length>5))}async run(e){let t;const{ci:o}=e;let{tag:a,message:s}=e;a=await this.prepareVersion(a),s=await this.prepareMessage(s),t=await M(`npm run prepare-release -- ${a} ${s}`,{cwd:process.cwd()}).promise,t=await M("git status --porcelain").promise,await t,t.logs.length&&await w.askConfirmation("git-changes","Do you want to push the changes to the remote repository?",!0)&&(await M("git add .").promise,await M(`git commit -m "${a} - ${s} - after release preparation${o?"":E}"`).promise),await M(`npm version "${a}" -m "${s}${o?"":E}"`).promise,await M("git push --follow-tags").promise,o||await M("NPM_TOKEN=$(cat .npmtoken) npm publish --access public").promise}}class we extends x{constructor(e,t,o,a="g"){super(e,t);try{this.regexp="string"==typeof o?RegExp(o,a):o}catch(e){throw Error("Invalid regular expression: "+e)}}test(e){let t;this.regexp.lastIndex=0;try{t=this.regexp.exec(e)}catch(e){return}return t}testAndResolve(e){const t=this.test(e);t&&this.resolve(t[0])}testAndReject(e){const t=this.test(e);t&&this.reject(t[0])}data(e){super.data(e),this.testAndResolve(e+"")}error(e){super.error(e),this.testAndReject(e+"")}}const Ce="##VERSION##",De="##PACKAGE##";export{N as AbortCode,ye as BuildScripts,ne as Command,C as DefaultCommandOptions,D as DefaultCommandValues,v as Encoding,ie as HttpClient,E as NoCIFLag,De as PACKAGE_NAME,we as RegexpOutputWriter,be as ReleaseScript,$ as SemVersion,k as SemVersionRegex,I as SetupScriptKey,x as StandardOutputWriter,F as Tokens,w as UserInput,Ce as VERSION,j as chainAbortController,W as copyFile,X as deletePath,R as getAllFiles,H as getDependencies,Q as getFileSizeZipped,V as getPackage,ge as getPackageDependencies,_ as getPackageVersion,re as getSlogan,q as installDependencies,z as installIfNotAvailable,ee as listFolder,te as listNodeModulesPackages,A as lockify,Z as normalizeImport,le as packageToGlobal,ce as parseList,U as patchFile,se as printBanner,Y as pushToGit,O as readFile,J as renameFile,M as runCommand,G as setPackageAttribute,B as spawnCommand,K as updateDependencies,L as writeFile};
|
|
2
|
-
|
|
1
|
+
import prompts from "prompts";
|
|
2
|
+
|
|
3
|
+
import { parseArgs } from "util";
|
|
4
|
+
|
|
5
|
+
import { Logging, escapeRegExp, LoggedClass, LoggedEnvironment, LogLevel } from "@decaf-ts/logging";
|
|
6
|
+
|
|
7
|
+
import fs from "fs";
|
|
8
|
+
|
|
9
|
+
import path from "path";
|
|
10
|
+
|
|
11
|
+
import { spawn } from "child_process";
|
|
12
|
+
|
|
13
|
+
import { style } from "styled-string-builder";
|
|
14
|
+
|
|
15
|
+
import { parse } from "shell-quote";
|
|
16
|
+
|
|
17
|
+
import zlib from "zlib";
|
|
18
|
+
|
|
19
|
+
import https from "https";
|
|
20
|
+
|
|
21
|
+
import { rollup } from "rollup";
|
|
22
|
+
|
|
23
|
+
import typescript from "@rollup/plugin-typescript";
|
|
24
|
+
|
|
25
|
+
import commonjs from "@rollup/plugin-commonjs";
|
|
26
|
+
|
|
27
|
+
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
|
28
|
+
|
|
29
|
+
import json from "@rollup/plugin-json";
|
|
30
|
+
|
|
31
|
+
import { builtinModules } from "module";
|
|
32
|
+
|
|
33
|
+
import * as ts from "typescript";
|
|
34
|
+
|
|
35
|
+
import { ModuleKind } from "typescript";
|
|
36
|
+
|
|
37
|
+
class UserInput {
|
|
38
|
+
static {
|
|
39
|
+
this.logger = Logging.for(UserInput);
|
|
40
|
+
}
|
|
41
|
+
constructor(name) {
|
|
42
|
+
this.type = "text";
|
|
43
|
+
this.name = name;
|
|
44
|
+
}
|
|
45
|
+
setType(type) {
|
|
46
|
+
UserInput.logger.verbose(`Setting type to: ${type}`);
|
|
47
|
+
this.type = type;
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
setMessage(value) {
|
|
51
|
+
UserInput.logger.verbose(`Setting message to: ${value}`);
|
|
52
|
+
this.message = value;
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
setInitial(value) {
|
|
56
|
+
UserInput.logger.verbose(`Setting initial value to: ${value}`);
|
|
57
|
+
this.initial = value;
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
setStyle(value) {
|
|
61
|
+
UserInput.logger.verbose(`Setting style to: ${value}`);
|
|
62
|
+
this.style = value;
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
setFormat(value) {
|
|
66
|
+
UserInput.logger.verbose(`Setting format function`);
|
|
67
|
+
this.format = value;
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
setValidate(value) {
|
|
71
|
+
UserInput.logger.verbose(`Setting validate function`);
|
|
72
|
+
this.validate = value;
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
setOnState(value) {
|
|
76
|
+
UserInput.logger.verbose(`Setting onState callback`);
|
|
77
|
+
this.onState = value;
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
setMin(value) {
|
|
81
|
+
UserInput.logger.verbose(`Setting min value to: ${value}`);
|
|
82
|
+
this.min = value;
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
setMax(value) {
|
|
86
|
+
UserInput.logger.verbose(`Setting max value to: ${value}`);
|
|
87
|
+
this.max = value;
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
setFloat(value) {
|
|
91
|
+
UserInput.logger.verbose(`Setting float to: ${value}`);
|
|
92
|
+
this.float = value;
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
setRound(value) {
|
|
96
|
+
UserInput.logger.verbose(`Setting round to: ${value}`);
|
|
97
|
+
this.round = value;
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
setInstructions(value) {
|
|
101
|
+
UserInput.logger.verbose(`Setting instructions to: ${value}`);
|
|
102
|
+
this.instructions = value;
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
setIncrement(value) {
|
|
106
|
+
UserInput.logger.verbose(`Setting increment to: ${value}`);
|
|
107
|
+
this.increment = value;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
setSeparator(value) {
|
|
111
|
+
UserInput.logger.verbose(`Setting separator to: ${value}`);
|
|
112
|
+
this.separator = value;
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
setActive(value) {
|
|
116
|
+
UserInput.logger.verbose(`Setting active style to: ${value}`);
|
|
117
|
+
this.active = value;
|
|
118
|
+
return this;
|
|
119
|
+
}
|
|
120
|
+
setInactive(value) {
|
|
121
|
+
UserInput.logger.verbose(`Setting inactive style to: ${value}`);
|
|
122
|
+
this.inactive = value;
|
|
123
|
+
return this;
|
|
124
|
+
}
|
|
125
|
+
setChoices(value) {
|
|
126
|
+
UserInput.logger.verbose(`Setting choices: ${JSON.stringify(value)}`);
|
|
127
|
+
this.choices = value;
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
setHint(value) {
|
|
131
|
+
UserInput.logger.verbose(`Setting hint to: ${value}`);
|
|
132
|
+
this.hint = value;
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
setWarn(value) {
|
|
136
|
+
UserInput.logger.verbose(`Setting warn to: ${value}`);
|
|
137
|
+
this.warn = value;
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
setSuggest(value) {
|
|
141
|
+
UserInput.logger.verbose(`Setting suggest function`);
|
|
142
|
+
this.suggest = value;
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
setLimit(value) {
|
|
146
|
+
UserInput.logger.verbose(`Setting limit to: ${value}`);
|
|
147
|
+
this.limit = value;
|
|
148
|
+
return this;
|
|
149
|
+
}
|
|
150
|
+
setMask(value) {
|
|
151
|
+
UserInput.logger.verbose(`Setting mask to: ${value}`);
|
|
152
|
+
this.mask = value;
|
|
153
|
+
return this;
|
|
154
|
+
}
|
|
155
|
+
setStdout(value) {
|
|
156
|
+
UserInput.logger.verbose(`Setting stdout stream`);
|
|
157
|
+
this.stdout = value;
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
160
|
+
setStdin(value) {
|
|
161
|
+
this.stdin = value;
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
async ask() {
|
|
165
|
+
return (await UserInput.ask(this))[this.name];
|
|
166
|
+
}
|
|
167
|
+
static async ask(question) {
|
|
168
|
+
const log = UserInput.logger.for(this.ask);
|
|
169
|
+
if (!Array.isArray(question)) {
|
|
170
|
+
question = [ question ];
|
|
171
|
+
}
|
|
172
|
+
let answers;
|
|
173
|
+
try {
|
|
174
|
+
log.verbose(`Asking questions: ${question.map(q => q.name).join(", ")}`);
|
|
175
|
+
answers = await prompts(question);
|
|
176
|
+
log.verbose(`Received answers: ${JSON.stringify(answers, null, 2)}`);
|
|
177
|
+
} catch (error) {
|
|
178
|
+
throw new Error(`Error while getting input: ${error}`);
|
|
179
|
+
}
|
|
180
|
+
return answers;
|
|
181
|
+
}
|
|
182
|
+
static async askNumber(name, question, min, max, initial) {
|
|
183
|
+
const log = UserInput.logger.for(this.askNumber);
|
|
184
|
+
log.verbose(`Asking number input: undefined, question: ${question}, min: ${min}, max: ${max}, initial: ${initial}`);
|
|
185
|
+
const userInput = new UserInput(name).setMessage(question).setType("number");
|
|
186
|
+
if (typeof min === "number") userInput.setMin(min);
|
|
187
|
+
if (typeof max === "number") userInput.setMax(max);
|
|
188
|
+
if (typeof initial === "number") userInput.setInitial(initial);
|
|
189
|
+
return (await this.ask(userInput))[name];
|
|
190
|
+
}
|
|
191
|
+
static async askText(name, question, mask = undefined, initial) {
|
|
192
|
+
const log = UserInput.logger.for(this.askText);
|
|
193
|
+
log.verbose(`Asking text input: undefined, question: ${question}, mask: ${mask}, initial: ${initial}`);
|
|
194
|
+
const userInput = new UserInput(name).setMessage(question);
|
|
195
|
+
if (mask) userInput.setMask(mask);
|
|
196
|
+
if (typeof initial === "string") userInput.setInitial(initial);
|
|
197
|
+
return (await this.ask(userInput))[name];
|
|
198
|
+
}
|
|
199
|
+
static async askConfirmation(name, question, initial) {
|
|
200
|
+
const log = UserInput.logger.for(this.askConfirmation);
|
|
201
|
+
log.verbose(`Asking confirmation input: undefined, question: ${question}, initial: ${initial}`);
|
|
202
|
+
const userInput = new UserInput(name).setMessage(question).setType("confirm");
|
|
203
|
+
if (typeof initial !== "undefined") userInput.setInitial(initial);
|
|
204
|
+
return (await this.ask(userInput))[name];
|
|
205
|
+
}
|
|
206
|
+
static async insist(input, test, defaultConfirmation, limit = 1) {
|
|
207
|
+
const log = UserInput.logger.for(this.insist);
|
|
208
|
+
log.verbose(`Insisting on input: ${input.name}, test: ${test.toString()}, defaultConfirmation: ${defaultConfirmation}, limit: ${limit}`);
|
|
209
|
+
let result = undefined;
|
|
210
|
+
let count = 0;
|
|
211
|
+
let confirmation;
|
|
212
|
+
try {
|
|
213
|
+
do {
|
|
214
|
+
result = (await UserInput.ask(input))[input.name];
|
|
215
|
+
if (!test(result)) {
|
|
216
|
+
result = undefined;
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
confirmation = await UserInput.askConfirmation(`${input.name}-confirm`, `Is the ${input.type} correct?`, defaultConfirmation);
|
|
220
|
+
if (!confirmation) result = undefined;
|
|
221
|
+
} while (typeof result === "undefined" && limit > 1 && count++ < limit);
|
|
222
|
+
} catch (e) {
|
|
223
|
+
log.error(`Error while insisting: ${e}`);
|
|
224
|
+
throw e;
|
|
225
|
+
}
|
|
226
|
+
if (typeof result === "undefined") log.info("no selection...");
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
static async insistForText(name, question, test, mask = undefined, initial, defaultConfirmation = false, limit = -1) {
|
|
230
|
+
const log = UserInput.logger.for(this.insistForText);
|
|
231
|
+
log.verbose(`Insisting for text input: undefined, question: ${question}, test: ${test.toString()}, mask: ${mask}, initial: ${initial}, defaultConfirmation: ${defaultConfirmation}, limit: ${limit}`);
|
|
232
|
+
const userInput = new UserInput(name).setMessage(question);
|
|
233
|
+
if (mask) userInput.setMask(mask);
|
|
234
|
+
if (typeof initial === "string") userInput.setInitial(initial);
|
|
235
|
+
return await this.insist(userInput, test, defaultConfirmation, limit);
|
|
236
|
+
}
|
|
237
|
+
static async insistForNumber(name, question, test, min, max, initial, defaultConfirmation = false, limit = -1) {
|
|
238
|
+
const log = UserInput.logger.for(this.insistForNumber);
|
|
239
|
+
log.verbose(`Insisting for number input: undefined, question: ${question}, test: ${test.toString()}, min: ${min}, max: ${max}, initial: ${initial}, defaultConfirmation: ${defaultConfirmation}, limit: ${limit}`);
|
|
240
|
+
const userInput = new UserInput(name).setMessage(question).setType("number");
|
|
241
|
+
if (typeof min === "number") userInput.setMin(min);
|
|
242
|
+
if (typeof max === "number") userInput.setMax(max);
|
|
243
|
+
if (typeof initial === "number") userInput.setInitial(initial);
|
|
244
|
+
return await this.insist(userInput, test, defaultConfirmation, limit);
|
|
245
|
+
}
|
|
246
|
+
static parseArgs(options) {
|
|
247
|
+
const log = UserInput.logger.for(this.parseArgs);
|
|
248
|
+
const args = {
|
|
249
|
+
args: process.argv.slice(2),
|
|
250
|
+
options: options
|
|
251
|
+
};
|
|
252
|
+
log.debug(`Parsing arguments: ${JSON.stringify(args, null, 2)}`);
|
|
253
|
+
try {
|
|
254
|
+
return parseArgs(args);
|
|
255
|
+
} catch (error) {
|
|
256
|
+
log.debug(`Error while parsing arguments:\n${JSON.stringify(args, null, 2)}\n | options\n${JSON.stringify(options, null, 2)}\n | ${error}`);
|
|
257
|
+
throw new Error(`Error while parsing arguments: ${error}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const DefaultCommandOptions = {
|
|
263
|
+
verbose: {
|
|
264
|
+
type: "boolean",
|
|
265
|
+
short: "V",
|
|
266
|
+
default: undefined
|
|
267
|
+
},
|
|
268
|
+
version: {
|
|
269
|
+
type: "boolean",
|
|
270
|
+
short: "v",
|
|
271
|
+
default: undefined
|
|
272
|
+
},
|
|
273
|
+
help: {
|
|
274
|
+
type: "boolean",
|
|
275
|
+
short: "h",
|
|
276
|
+
default: false
|
|
277
|
+
},
|
|
278
|
+
logLevel: {
|
|
279
|
+
type: "string",
|
|
280
|
+
default: "info"
|
|
281
|
+
},
|
|
282
|
+
logStyle: {
|
|
283
|
+
type: "boolean",
|
|
284
|
+
default: true
|
|
285
|
+
},
|
|
286
|
+
timestamp: {
|
|
287
|
+
type: "boolean",
|
|
288
|
+
default: true
|
|
289
|
+
},
|
|
290
|
+
banner: {
|
|
291
|
+
type: "boolean",
|
|
292
|
+
default: true
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
const DefaultCommandValues = Object.keys(DefaultCommandOptions).reduce((acc, key) => {
|
|
297
|
+
acc[key] = DefaultCommandOptions[key].default;
|
|
298
|
+
return acc;
|
|
299
|
+
}, {});
|
|
300
|
+
|
|
301
|
+
const Encoding = "utf-8";
|
|
302
|
+
|
|
303
|
+
const SemVersionRegex = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z])))/g;
|
|
304
|
+
|
|
305
|
+
var SemVersion;
|
|
306
|
+
|
|
307
|
+
(function(SemVersion) {
|
|
308
|
+
SemVersion["PATCH"] = "patch";
|
|
309
|
+
SemVersion["MINOR"] = "minor";
|
|
310
|
+
SemVersion["MAJOR"] = "major";
|
|
311
|
+
})(SemVersion || (SemVersion = {}));
|
|
312
|
+
|
|
313
|
+
const NoCIFLag = "-no-ci";
|
|
314
|
+
|
|
315
|
+
const SetupScriptKey = "postinstall";
|
|
316
|
+
|
|
317
|
+
var Tokens;
|
|
318
|
+
|
|
319
|
+
(function(Tokens) {
|
|
320
|
+
Tokens["GIT"] = ".token";
|
|
321
|
+
Tokens["NPM"] = ".npmtoken";
|
|
322
|
+
Tokens["DOCKER"] = ".dockertoken";
|
|
323
|
+
Tokens["CONFLUENCE"] = ".confluence-token";
|
|
324
|
+
})(Tokens || (Tokens = {}));
|
|
325
|
+
|
|
326
|
+
const AbortCode = "Aborted";
|
|
327
|
+
|
|
328
|
+
class StandardOutputWriter {
|
|
329
|
+
constructor(cmd, lock, ...args) {
|
|
330
|
+
this.cmd = cmd;
|
|
331
|
+
this.lock = lock;
|
|
332
|
+
this.logger = Logging.for(this.cmd);
|
|
333
|
+
}
|
|
334
|
+
log(type, data) {
|
|
335
|
+
data = Buffer.isBuffer(data) ? data.toString(Encoding) : data;
|
|
336
|
+
const log = type === "stderr" ? style(data).red.text : data;
|
|
337
|
+
this.logger.info(log);
|
|
338
|
+
}
|
|
339
|
+
data(chunk) {
|
|
340
|
+
this.log("stdout", String(chunk));
|
|
341
|
+
}
|
|
342
|
+
error(chunk) {
|
|
343
|
+
this.log("stderr", String(chunk));
|
|
344
|
+
}
|
|
345
|
+
errors(err) {
|
|
346
|
+
this.log("stderr", `Error executing command exited : ${err}`);
|
|
347
|
+
}
|
|
348
|
+
exit(code, logs) {
|
|
349
|
+
this.log("stdout", `command exited code : ${code === 0 ? style(code.toString()).green.text : style(code === null ? "null" : code.toString()).red.text}`);
|
|
350
|
+
if (code === 0) {
|
|
351
|
+
this.resolve(logs.map(l => l.trim()).join("\n"));
|
|
352
|
+
} else {
|
|
353
|
+
this.reject(new Error(logs.length ? logs.join("\n") : code.toString()));
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
parseCommand(command) {
|
|
357
|
+
if (Array.isArray(command)) {
|
|
358
|
+
this.cmd = command.join(" ");
|
|
359
|
+
return [ command[0], command.slice(1) ];
|
|
360
|
+
}
|
|
361
|
+
const parts = parse(command).filter(p => typeof p === "string").map(String);
|
|
362
|
+
this.cmd = parts.join(" ");
|
|
363
|
+
return [ parts[0], parts.slice(1) ];
|
|
364
|
+
}
|
|
365
|
+
resolve(reason) {
|
|
366
|
+
this.log("stdout", `${this.cmd} executed successfully: ${style(reason ? "ran to completion" : reason).green}`);
|
|
367
|
+
this.lock.resolve(reason);
|
|
368
|
+
}
|
|
369
|
+
reject(reason) {
|
|
370
|
+
if (!(reason instanceof Error)) {
|
|
371
|
+
reason = new Error(typeof reason === "number" ? `Exit code ${reason}` : reason);
|
|
372
|
+
}
|
|
373
|
+
this.log("stderr", `${this.cmd} failed to execute: ${style(reason.message).red}`);
|
|
374
|
+
this.lock.reject(reason);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function lockify(f) {
|
|
379
|
+
let lock = Promise.resolve();
|
|
380
|
+
return (...params) => {
|
|
381
|
+
const result = lock.then(() => f(...params));
|
|
382
|
+
lock = result.catch(() => {});
|
|
383
|
+
return result;
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function chainAbortController(argument0, ...remainder) {
|
|
388
|
+
let signals;
|
|
389
|
+
let controller;
|
|
390
|
+
if (argument0 instanceof AbortSignal) {
|
|
391
|
+
controller = new AbortController;
|
|
392
|
+
signals = [ argument0, ...remainder ];
|
|
393
|
+
} else {
|
|
394
|
+
controller = argument0;
|
|
395
|
+
signals = remainder;
|
|
396
|
+
}
|
|
397
|
+
if (controller.signal.aborted) {
|
|
398
|
+
return controller;
|
|
399
|
+
}
|
|
400
|
+
const handler = () => controller.abort();
|
|
401
|
+
for (const signal of signals) {
|
|
402
|
+
if (signal.aborted) {
|
|
403
|
+
controller.abort();
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
signal.addEventListener("abort", handler, {
|
|
407
|
+
once: true,
|
|
408
|
+
signal: controller.signal
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
return controller;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function spawnCommand(output, command, opts, abort, logger) {
|
|
415
|
+
function spawnInner(command, controller) {
|
|
416
|
+
const [cmd, argz] = output.parseCommand(command);
|
|
417
|
+
logger.info(`Running command: ${cmd}`);
|
|
418
|
+
logger.debug(`with args: ${argz.join(" ")}`);
|
|
419
|
+
const childProcess = spawn(cmd, argz, {
|
|
420
|
+
...opts,
|
|
421
|
+
cwd: opts.cwd || process.cwd(),
|
|
422
|
+
env: Object.assign({}, process.env, opts.env, {
|
|
423
|
+
PATH: process.env.PATH
|
|
424
|
+
}),
|
|
425
|
+
shell: opts.shell || false,
|
|
426
|
+
signal: controller.signal
|
|
427
|
+
});
|
|
428
|
+
logger.verbose(`pid : ${childProcess.pid}`);
|
|
429
|
+
return childProcess;
|
|
430
|
+
}
|
|
431
|
+
const m = command.match(/[<>$#]/g);
|
|
432
|
+
if (m) throw new Error(`Invalid command: ${command}. contains invalid characters: ${m}`);
|
|
433
|
+
if (command.includes(" | ")) {
|
|
434
|
+
const cmds = command.split(" | ");
|
|
435
|
+
const spawns = [];
|
|
436
|
+
const controllers = new Array(cmds.length);
|
|
437
|
+
controllers[0] = abort;
|
|
438
|
+
for (let i = 0; i < cmds.length; i++) {
|
|
439
|
+
if (i !== 0) controllers[i] = chainAbortController(controllers[i - 1].signal);
|
|
440
|
+
spawns.push(spawnInner(cmds[i], controllers[i]));
|
|
441
|
+
if (i === 0) continue;
|
|
442
|
+
spawns[i - 1].stdout.pipe(spawns[i].stdin);
|
|
443
|
+
}
|
|
444
|
+
return spawns[cmds.length - 1];
|
|
445
|
+
}
|
|
446
|
+
return spawnInner(command, abort);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function runCommand(command, opts = {}, outputConstructor = StandardOutputWriter, ...args) {
|
|
450
|
+
const logger = Logging.for(runCommand);
|
|
451
|
+
const abort = new AbortController;
|
|
452
|
+
const result = {
|
|
453
|
+
abort: abort,
|
|
454
|
+
command: command,
|
|
455
|
+
logs: [],
|
|
456
|
+
errs: []
|
|
457
|
+
};
|
|
458
|
+
const lock = new Promise((resolve, reject) => {
|
|
459
|
+
let output;
|
|
460
|
+
try {
|
|
461
|
+
output = new outputConstructor(command, {
|
|
462
|
+
resolve: resolve,
|
|
463
|
+
reject: reject
|
|
464
|
+
}, ...args);
|
|
465
|
+
result.cmd = spawnCommand(output, command, opts, abort, logger);
|
|
466
|
+
} catch (e) {
|
|
467
|
+
return reject(new Error(`Error running command ${command}: ${e}`));
|
|
468
|
+
}
|
|
469
|
+
result.cmd.stdout.setEncoding("utf8");
|
|
470
|
+
result.cmd.stdout.on("data", chunk => {
|
|
471
|
+
chunk = chunk.toString();
|
|
472
|
+
result.logs.push(chunk);
|
|
473
|
+
output.data(chunk);
|
|
474
|
+
});
|
|
475
|
+
result.cmd.stderr.on("data", data => {
|
|
476
|
+
data = data.toString();
|
|
477
|
+
result.errs.push(data);
|
|
478
|
+
output.error(data);
|
|
479
|
+
});
|
|
480
|
+
result.cmd.once("error", err => {
|
|
481
|
+
output.exit(err.message, result.errs);
|
|
482
|
+
});
|
|
483
|
+
result.cmd.once("exit", (code = 0) => {
|
|
484
|
+
if (abort.signal.aborted && code === null) code = AbortCode;
|
|
485
|
+
output.exit(code, code === 0 ? result.logs : result.errs);
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
Object.assign(result, {
|
|
489
|
+
promise: lock,
|
|
490
|
+
pipe: async cb => {
|
|
491
|
+
const l = logger.for("pipe");
|
|
492
|
+
try {
|
|
493
|
+
l.verbose(`Executing pipe function ${command}...`);
|
|
494
|
+
const result = await lock;
|
|
495
|
+
l.verbose(`Piping output to ${cb.name}: ${result}`);
|
|
496
|
+
return cb(result);
|
|
497
|
+
} catch (e) {
|
|
498
|
+
l.error(`Error piping command output: ${e}`);
|
|
499
|
+
throw e;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
return result;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const logger = Logging.for("fs");
|
|
507
|
+
|
|
508
|
+
function patchString(input, values, flags = "g", filter) {
|
|
509
|
+
Object.entries(values).forEach(([key, val]) => {
|
|
510
|
+
const regexp = new RegExp(escapeRegExp(key), flags);
|
|
511
|
+
input = input.replace(regexp, subStr => {
|
|
512
|
+
if (!filter || filter(subStr)) {
|
|
513
|
+
return val;
|
|
514
|
+
}
|
|
515
|
+
return val;
|
|
516
|
+
});
|
|
517
|
+
});
|
|
518
|
+
return input;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
function patchFile(path, values, filter) {
|
|
522
|
+
const log = logger.for(patchFile);
|
|
523
|
+
if (!fs.existsSync(path)) throw new Error(`File not found at path "${path}".`);
|
|
524
|
+
let content = readFile(path);
|
|
525
|
+
log.verbose(`Patching file "${path}"...`);
|
|
526
|
+
log.debug(`with value: ${JSON.stringify(values)}`);
|
|
527
|
+
try {
|
|
528
|
+
content = patchString(content, values, "g", filter);
|
|
529
|
+
} catch (error) {
|
|
530
|
+
throw new Error(`Error patching file: ${error}`);
|
|
531
|
+
}
|
|
532
|
+
writeFile(path, content);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
function readFile(path) {
|
|
536
|
+
const log = logger.for(readFile);
|
|
537
|
+
try {
|
|
538
|
+
log.verbose(`Reading file "${path}"...`);
|
|
539
|
+
return fs.readFileSync(path, "utf8");
|
|
540
|
+
} catch (error) {
|
|
541
|
+
log.verbose(`Error reading file "${path}": ${error}`);
|
|
542
|
+
throw new Error(`Error reading file "${path}": ${error}`);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
function writeFile(path, data) {
|
|
547
|
+
const log = logger.for(writeFile);
|
|
548
|
+
try {
|
|
549
|
+
log.verbose(`Writing file "${path} with ${data.length} bytes...`);
|
|
550
|
+
fs.writeFileSync(path, data, "utf8");
|
|
551
|
+
} catch (error) {
|
|
552
|
+
log.verbose(`Error writing file "${path}": ${error}`);
|
|
553
|
+
throw new Error(`Error writing file "${path}": ${error}`);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
function getAllFiles(p, filter) {
|
|
558
|
+
const log = logger.for(getAllFiles);
|
|
559
|
+
const files = [];
|
|
560
|
+
try {
|
|
561
|
+
log.verbose(`Retrieving all files from "${p}"...`);
|
|
562
|
+
const entries = fs.readdirSync(p);
|
|
563
|
+
entries.forEach(entry => {
|
|
564
|
+
const fullPath = path.join(p, entry);
|
|
565
|
+
const stat = fs.statSync(fullPath);
|
|
566
|
+
if (stat.isFile()) {
|
|
567
|
+
files.push(fullPath);
|
|
568
|
+
} else if (stat.isDirectory()) {
|
|
569
|
+
files.push(...getAllFiles(fullPath));
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
if (!filter) return files;
|
|
573
|
+
return files.filter(filter);
|
|
574
|
+
} catch (error) {
|
|
575
|
+
log.verbose(`Error retrieving files from "${p}": ${error}`);
|
|
576
|
+
throw new Error(`Error retrieving files from "${p}": ${error}`);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
async function renameFile(source, dest) {
|
|
581
|
+
const log = logger.for(renameFile);
|
|
582
|
+
let descriptorSource, descriptorDest;
|
|
583
|
+
try {
|
|
584
|
+
descriptorSource = fs.statSync(source);
|
|
585
|
+
} catch (error) {
|
|
586
|
+
log.verbose(`Source path "${source}" does not exist: ${error}`);
|
|
587
|
+
throw new Error(`Source path "${source}" does not exist: ${error}`);
|
|
588
|
+
}
|
|
589
|
+
try {
|
|
590
|
+
descriptorDest = fs.statSync(dest);
|
|
591
|
+
} catch (e) {}
|
|
592
|
+
if (descriptorDest) {
|
|
593
|
+
log.verbose(`Destination path "${dest}" already exists`);
|
|
594
|
+
throw new Error(`Destination path "${dest}" already exists`);
|
|
595
|
+
}
|
|
596
|
+
try {
|
|
597
|
+
log.verbose(`Renaming ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}...`);
|
|
598
|
+
fs.renameSync(source, dest);
|
|
599
|
+
log.verbose(`Successfully renamed to "${dest}"`);
|
|
600
|
+
} catch (error) {
|
|
601
|
+
log.verbose(`Error renaming ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}": ${error}`);
|
|
602
|
+
throw new Error(`Error renaming ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}": ${error}`);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
function copyFile(source, dest) {
|
|
607
|
+
const log = logger.for(copyFile);
|
|
608
|
+
let descriptorSource, descriptorDest;
|
|
609
|
+
try {
|
|
610
|
+
descriptorSource = fs.statSync(source);
|
|
611
|
+
} catch (error) {
|
|
612
|
+
log.verbose(`Source path "${source}" does not exist: ${error}`);
|
|
613
|
+
throw new Error(`Source path "${source}" does not exist: ${error}`);
|
|
614
|
+
}
|
|
615
|
+
try {
|
|
616
|
+
descriptorDest = fs.statSync(dest);
|
|
617
|
+
} catch (error) {
|
|
618
|
+
if (descriptorSource.isDirectory()) {
|
|
619
|
+
log.verbose(`Dest path "${dest}" does not exist. creating`);
|
|
620
|
+
fs.mkdirSync(dest, {
|
|
621
|
+
recursive: true
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
try {
|
|
626
|
+
log.verbose(`Copying ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}...`);
|
|
627
|
+
fs.cpSync(source, dest, {
|
|
628
|
+
recursive: true
|
|
629
|
+
});
|
|
630
|
+
} catch (error) {
|
|
631
|
+
log.verbose(`Error copying ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}: ${error}`);
|
|
632
|
+
throw new Error(`Error copying ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}: ${error}`);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function deletePath(p) {
|
|
637
|
+
const log = logger.for(deletePath);
|
|
638
|
+
try {
|
|
639
|
+
const descriptor = fs.statSync(p);
|
|
640
|
+
if (descriptor.isFile()) {
|
|
641
|
+
log.verbose(`Deleting file "${p}...`);
|
|
642
|
+
fs.rmSync(p, {
|
|
643
|
+
recursive: true,
|
|
644
|
+
force: true
|
|
645
|
+
});
|
|
646
|
+
} else if (descriptor.isDirectory()) fs.rmSync(p, {
|
|
647
|
+
recursive: true,
|
|
648
|
+
force: true
|
|
649
|
+
});
|
|
650
|
+
} catch (error) {
|
|
651
|
+
log.verbose(`Error Deleting "${p}": ${error}`);
|
|
652
|
+
throw new Error(`Error Deleting "${p}": ${error}`);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
function getPackage(p = process.cwd(), property) {
|
|
657
|
+
let pkg;
|
|
658
|
+
try {
|
|
659
|
+
pkg = JSON.parse(readFile(path.join(p, `package.json`)));
|
|
660
|
+
} catch (error) {
|
|
661
|
+
throw new Error(`Failed to retrieve package information" ${error}`);
|
|
662
|
+
}
|
|
663
|
+
if (property) {
|
|
664
|
+
if (!(property in pkg)) throw new Error(`Property "${property}" not found in package.json`);
|
|
665
|
+
return pkg[property];
|
|
666
|
+
}
|
|
667
|
+
return pkg;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
function setPackageAttribute(attr, value, p = process.cwd()) {
|
|
671
|
+
const pkg = getPackage(p);
|
|
672
|
+
pkg[attr] = value;
|
|
673
|
+
writeFile(path.join(p, `package.json`), JSON.stringify(pkg, null, 2));
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
function getPackageVersion(p = process.cwd()) {
|
|
677
|
+
return getPackage(p, "version");
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
async function getDependencies(path = process.cwd()) {
|
|
681
|
+
let pkg;
|
|
682
|
+
try {
|
|
683
|
+
pkg = JSON.parse(await runCommand(`npm ls --json`, {
|
|
684
|
+
cwd: path
|
|
685
|
+
}).promise);
|
|
686
|
+
} catch (e) {
|
|
687
|
+
throw new Error(`Failed to retrieve dependencies: ${e}`);
|
|
688
|
+
}
|
|
689
|
+
const mapper = (entry, index) => ({
|
|
690
|
+
name: entry[0],
|
|
691
|
+
version: entry[1].version
|
|
692
|
+
});
|
|
693
|
+
return {
|
|
694
|
+
prod: Object.entries(pkg.dependencies || {}).map(mapper),
|
|
695
|
+
dev: Object.entries(pkg.devDependencies || {}).map(mapper),
|
|
696
|
+
peer: Object.entries(pkg.peerDependencies || {}).map(mapper)
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
async function updateDependencies() {
|
|
701
|
+
const log = logger.for(updateDependencies);
|
|
702
|
+
log.info("checking for updates...");
|
|
703
|
+
await runCommand("npx npm-check-updates -u").promise;
|
|
704
|
+
log.info("updating...");
|
|
705
|
+
await runCommand("npx npm run do-install").promise;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
async function installIfNotAvailable(deps, dependencies) {
|
|
709
|
+
if (!dependencies) {
|
|
710
|
+
const d = await getDependencies();
|
|
711
|
+
dependencies = {
|
|
712
|
+
prod: d.prod?.map(p => p.name) || [],
|
|
713
|
+
dev: d.dev?.map(d => d.name) || [],
|
|
714
|
+
peer: d.peer?.map(p => p.name) || []
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
const {prod: prod, dev: dev, peer: peer} = dependencies;
|
|
718
|
+
const installed = Array.from(new Set([ ...prod || [], ...dev || [], ...peer || [] ]));
|
|
719
|
+
deps = typeof deps === "string" ? [ deps ] : deps;
|
|
720
|
+
const toInstall = deps.filter(d => !installed.includes(d));
|
|
721
|
+
if (toInstall.length) await installDependencies({
|
|
722
|
+
dev: toInstall
|
|
723
|
+
});
|
|
724
|
+
dependencies.dev = dependencies.dev || [];
|
|
725
|
+
dependencies.dev.push(...toInstall);
|
|
726
|
+
return dependencies;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
async function pushToGit() {
|
|
730
|
+
const log = logger.for(pushToGit);
|
|
731
|
+
const gitUser = await runCommand("git config user.name").promise;
|
|
732
|
+
const gitEmail = await runCommand("git config user.email").promise;
|
|
733
|
+
log.verbose(`cached git id: ${gitUser}/${gitEmail}. changing to automation`);
|
|
734
|
+
await runCommand('git config user.email "automation@decaf.ts"').promise;
|
|
735
|
+
await runCommand('git config user.name "decaf"').promise;
|
|
736
|
+
log.info("Pushing changes to git...");
|
|
737
|
+
await runCommand("git add .").promise;
|
|
738
|
+
await runCommand(`git commit -m "refs #1 - after repo setup"`).promise;
|
|
739
|
+
await runCommand("git push").promise;
|
|
740
|
+
await runCommand(`git config user.email "${gitEmail}"`).promise;
|
|
741
|
+
await runCommand(`git config user.name "${gitUser}"`).promise;
|
|
742
|
+
log.verbose(`reverted to git id: ${gitUser}/${gitEmail}`);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
async function installDependencies(dependencies) {
|
|
746
|
+
const log = logger.for(installDependencies);
|
|
747
|
+
const prod = dependencies.prod || [];
|
|
748
|
+
const dev = dependencies.dev || [];
|
|
749
|
+
const peer = dependencies.peer || [];
|
|
750
|
+
if (prod.length) {
|
|
751
|
+
log.info(`Installing dependencies ${prod.join(", ")}...`);
|
|
752
|
+
await runCommand(`npm install ${prod.join(" ")}`, {
|
|
753
|
+
cwd: process.cwd()
|
|
754
|
+
}).promise;
|
|
755
|
+
}
|
|
756
|
+
if (dev.length) {
|
|
757
|
+
log.info(`Installing devDependencies ${dev.join(", ")}...`);
|
|
758
|
+
await runCommand(`npm install --save-dev ${dev.join(" ")}`, {
|
|
759
|
+
cwd: process.cwd()
|
|
760
|
+
}).promise;
|
|
761
|
+
}
|
|
762
|
+
if (peer.length) {
|
|
763
|
+
log.info(`Installing peerDependencies ${peer.join(", ")}...`);
|
|
764
|
+
await runCommand(`npm install --save-peer ${peer.join(" ")}`, {
|
|
765
|
+
cwd: process.cwd()
|
|
766
|
+
}).promise;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
async function normalizeImport(importPromise) {
|
|
771
|
+
return importPromise.then(m => m.default || m);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
async function getFileSizeZipped(dir) {
|
|
775
|
+
const log = logger.for(getFileSizeZipped);
|
|
776
|
+
try {
|
|
777
|
+
const entries = fs.readdirSync(dir);
|
|
778
|
+
const candidates = entries.map(e => path.join(dir, e)).filter(p => {
|
|
779
|
+
try {
|
|
780
|
+
const s = fs.statSync(p);
|
|
781
|
+
return s.isFile() && (p.endsWith(".js") || p.endsWith(".cjs") || p.endsWith(".mjs"));
|
|
782
|
+
} catch {
|
|
783
|
+
return false;
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
if (candidates.length === 0) {
|
|
787
|
+
throw new Error(`No JS files found in directory ${dir}`);
|
|
788
|
+
}
|
|
789
|
+
let smallest = candidates[0];
|
|
790
|
+
let smallestSize = fs.statSync(smallest).size;
|
|
791
|
+
for (const c of candidates.slice(1)) {
|
|
792
|
+
const s = fs.statSync(c).size;
|
|
793
|
+
if (s < smallestSize) {
|
|
794
|
+
smallest = c;
|
|
795
|
+
smallestSize = s;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
log.verbose(`Selected smallest bundle: ${smallest} (${smallestSize} bytes)`);
|
|
799
|
+
const buffer = fs.readFileSync(smallest);
|
|
800
|
+
const gz = zlib.gzipSync(buffer);
|
|
801
|
+
const sizeKb = Number((gz.length / 1024).toFixed(1));
|
|
802
|
+
log.verbose(`Gzipped size: ${gz.length} bytes (${sizeKb} KB)`);
|
|
803
|
+
return sizeKb;
|
|
804
|
+
} catch (e) {
|
|
805
|
+
log.verbose(`Failed to compute gzipped size for ${dir}: ${e}`);
|
|
806
|
+
throw e;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
function listFolder(basePath = process.cwd(), filter) {
|
|
811
|
+
const log = logger.for(listFolder);
|
|
812
|
+
try {
|
|
813
|
+
if (!fs.existsSync(basePath)) return [];
|
|
814
|
+
const entries = fs.readdirSync(basePath, {
|
|
815
|
+
withFileTypes: true
|
|
816
|
+
});
|
|
817
|
+
const names = entries.filter(d => filter ? filter(d.name, d) : true).map(d => d.name);
|
|
818
|
+
return names;
|
|
819
|
+
} catch (e) {
|
|
820
|
+
log.verbose(`Failed to list folder ${basePath}: ${e}`);
|
|
821
|
+
return [];
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
function listNodeModulesPackages(basePath = path.join(process.cwd(), "node_modules")) {
|
|
826
|
+
const log = logger.for(listNodeModulesPackages);
|
|
827
|
+
try {
|
|
828
|
+
if (!fs.existsSync(basePath)) return [];
|
|
829
|
+
const entries = fs.readdirSync(basePath, {
|
|
830
|
+
withFileTypes: true
|
|
831
|
+
});
|
|
832
|
+
const names = [];
|
|
833
|
+
for (const e of entries) {
|
|
834
|
+
try {
|
|
835
|
+
if (!e.isDirectory()) continue;
|
|
836
|
+
if (e.name.startsWith(".")) continue;
|
|
837
|
+
if (e.name.startsWith("@")) {
|
|
838
|
+
const scopePath = path.join(basePath, e.name);
|
|
839
|
+
try {
|
|
840
|
+
const scoped = fs.readdirSync(scopePath, {
|
|
841
|
+
withFileTypes: true
|
|
842
|
+
});
|
|
843
|
+
for (const s of scoped) {
|
|
844
|
+
if (s.isDirectory() && !s.name.startsWith(".")) {
|
|
845
|
+
names.push(`${e.name}/${s.name}`);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
} catch (err) {
|
|
849
|
+
log.verbose(`Failed to read scope ${scopePath}: ${err}`);
|
|
850
|
+
}
|
|
851
|
+
} else {
|
|
852
|
+
names.push(e.name);
|
|
853
|
+
}
|
|
854
|
+
} catch (err) {
|
|
855
|
+
log.verbose(`Skipping entry ${e.name} due to error: ${err}`);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
return names;
|
|
859
|
+
} catch (e) {
|
|
860
|
+
log.verbose(`Failed to list node_modules packages at ${basePath}: ${e}`);
|
|
861
|
+
return [];
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
const slogans = [ {
|
|
866
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
867
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
868
|
+
}, {
|
|
869
|
+
Slogan: "Full flavor, no jitters. That's Decaf-TS.",
|
|
870
|
+
Tags: "Coffee-themed, Cheerful"
|
|
871
|
+
}, {
|
|
872
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
873
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
874
|
+
}, {
|
|
875
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
876
|
+
Tags: "Coffee-themed, Branding"
|
|
877
|
+
}, {
|
|
878
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
879
|
+
Tags: "Coffee-themed, Chill"
|
|
880
|
+
}, {
|
|
881
|
+
Slogan: "All the kick, none of the crash.",
|
|
882
|
+
Tags: "Coffee-themed, Energetic"
|
|
883
|
+
}, {
|
|
884
|
+
Slogan: "Sip back and ship faster.",
|
|
885
|
+
Tags: "Coffee-themed, Fun"
|
|
886
|
+
}, {
|
|
887
|
+
Slogan: "Keep calm and code Decaf.",
|
|
888
|
+
Tags: "Coffee-themed, Playful"
|
|
889
|
+
}, {
|
|
890
|
+
Slogan: "Code without the caffeine shakes.",
|
|
891
|
+
Tags: "Coffee-themed, Humorous"
|
|
892
|
+
}, {
|
|
893
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
894
|
+
Tags: "Coffee-themed, Technical"
|
|
895
|
+
}, {
|
|
896
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
897
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
898
|
+
}, {
|
|
899
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
900
|
+
Tags: "Coffee-themed, Cheerful"
|
|
901
|
+
}, {
|
|
902
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
903
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
904
|
+
}, {
|
|
905
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
906
|
+
Tags: "Coffee-themed, Branding"
|
|
907
|
+
}, {
|
|
908
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
909
|
+
Tags: "Coffee-themed, Chill"
|
|
910
|
+
}, {
|
|
911
|
+
Slogan: "All the kick, none of the crash.",
|
|
912
|
+
Tags: "Coffee-themed, Energetic"
|
|
913
|
+
}, {
|
|
914
|
+
Slogan: "Sip back and ship faster.",
|
|
915
|
+
Tags: "Coffee-themed, Fun"
|
|
916
|
+
}, {
|
|
917
|
+
Slogan: "Keep calm and code Decaf.",
|
|
918
|
+
Tags: "Coffee-themed, Playful"
|
|
919
|
+
}, {
|
|
920
|
+
Slogan: "Code without the caffeine shakes.",
|
|
921
|
+
Tags: "Coffee-themed, Humorous"
|
|
922
|
+
}, {
|
|
923
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
924
|
+
Tags: "Coffee-themed, Technical"
|
|
925
|
+
}, {
|
|
926
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
927
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
928
|
+
}, {
|
|
929
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
930
|
+
Tags: "Coffee-themed, Cheerful"
|
|
931
|
+
}, {
|
|
932
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
933
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
934
|
+
}, {
|
|
935
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
936
|
+
Tags: "Coffee-themed, Branding"
|
|
937
|
+
}, {
|
|
938
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
939
|
+
Tags: "Coffee-themed, Chill"
|
|
940
|
+
}, {
|
|
941
|
+
Slogan: "All the kick, none of the crash.",
|
|
942
|
+
Tags: "Coffee-themed, Energetic"
|
|
943
|
+
}, {
|
|
944
|
+
Slogan: "Sip back and ship faster.",
|
|
945
|
+
Tags: "Coffee-themed, Fun"
|
|
946
|
+
}, {
|
|
947
|
+
Slogan: "Keep calm and code Decaf.",
|
|
948
|
+
Tags: "Coffee-themed, Playful"
|
|
949
|
+
}, {
|
|
950
|
+
Slogan: "Code without the caffeine shakes.",
|
|
951
|
+
Tags: "Coffee-themed, Humorous"
|
|
952
|
+
}, {
|
|
953
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
954
|
+
Tags: "Coffee-themed, Technical"
|
|
955
|
+
}, {
|
|
956
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
957
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
958
|
+
}, {
|
|
959
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
960
|
+
Tags: "Coffee-themed, Cheerful"
|
|
961
|
+
}, {
|
|
962
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
963
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
964
|
+
}, {
|
|
965
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
966
|
+
Tags: "Coffee-themed, Branding"
|
|
967
|
+
}, {
|
|
968
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
969
|
+
Tags: "Coffee-themed, Chill"
|
|
970
|
+
}, {
|
|
971
|
+
Slogan: "All the kick, none of the crash.",
|
|
972
|
+
Tags: "Coffee-themed, Energetic"
|
|
973
|
+
}, {
|
|
974
|
+
Slogan: "Sip back and ship faster.",
|
|
975
|
+
Tags: "Coffee-themed, Fun"
|
|
976
|
+
}, {
|
|
977
|
+
Slogan: "Keep calm and code Decaf.",
|
|
978
|
+
Tags: "Coffee-themed, Playful"
|
|
979
|
+
}, {
|
|
980
|
+
Slogan: "Code without the caffeine shakes.",
|
|
981
|
+
Tags: "Coffee-themed, Humorous"
|
|
982
|
+
}, {
|
|
983
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
984
|
+
Tags: "Coffee-themed, Technical"
|
|
985
|
+
}, {
|
|
986
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
987
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
988
|
+
}, {
|
|
989
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
990
|
+
Tags: "Coffee-themed, Cheerful"
|
|
991
|
+
}, {
|
|
992
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
993
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
994
|
+
}, {
|
|
995
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
996
|
+
Tags: "Coffee-themed, Branding"
|
|
997
|
+
}, {
|
|
998
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
999
|
+
Tags: "Coffee-themed, Chill"
|
|
1000
|
+
}, {
|
|
1001
|
+
Slogan: "All the kick, none of the crash.",
|
|
1002
|
+
Tags: "Coffee-themed, Energetic"
|
|
1003
|
+
}, {
|
|
1004
|
+
Slogan: "Sip back and ship faster.",
|
|
1005
|
+
Tags: "Coffee-themed, Fun"
|
|
1006
|
+
}, {
|
|
1007
|
+
Slogan: "Keep calm and code Decaf.",
|
|
1008
|
+
Tags: "Coffee-themed, Playful"
|
|
1009
|
+
}, {
|
|
1010
|
+
Slogan: "Code without the caffeine shakes.",
|
|
1011
|
+
Tags: "Coffee-themed, Humorous"
|
|
1012
|
+
}, {
|
|
1013
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
1014
|
+
Tags: "Coffee-themed, Technical"
|
|
1015
|
+
}, {
|
|
1016
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
1017
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
1018
|
+
}, {
|
|
1019
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
1020
|
+
Tags: "Coffee-themed, Cheerful"
|
|
1021
|
+
}, {
|
|
1022
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
1023
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
1024
|
+
}, {
|
|
1025
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
1026
|
+
Tags: "Coffee-themed, Branding"
|
|
1027
|
+
}, {
|
|
1028
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
1029
|
+
Tags: "Coffee-themed, Chill"
|
|
1030
|
+
}, {
|
|
1031
|
+
Slogan: "All the kick, none of the crash.",
|
|
1032
|
+
Tags: "Coffee-themed, Energetic"
|
|
1033
|
+
}, {
|
|
1034
|
+
Slogan: "Sip back and ship faster.",
|
|
1035
|
+
Tags: "Coffee-themed, Fun"
|
|
1036
|
+
}, {
|
|
1037
|
+
Slogan: "Keep calm and code Decaf.",
|
|
1038
|
+
Tags: "Coffee-themed, Playful"
|
|
1039
|
+
}, {
|
|
1040
|
+
Slogan: "Code without the caffeine shakes.",
|
|
1041
|
+
Tags: "Coffee-themed, Humorous"
|
|
1042
|
+
}, {
|
|
1043
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
1044
|
+
Tags: "Coffee-themed, Technical"
|
|
1045
|
+
}, {
|
|
1046
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
1047
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
1048
|
+
}, {
|
|
1049
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
1050
|
+
Tags: "Coffee-themed, Cheerful"
|
|
1051
|
+
}, {
|
|
1052
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
1053
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
1054
|
+
}, {
|
|
1055
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
1056
|
+
Tags: "Coffee-themed, Branding"
|
|
1057
|
+
}, {
|
|
1058
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
1059
|
+
Tags: "Coffee-themed, Chill"
|
|
1060
|
+
}, {
|
|
1061
|
+
Slogan: "All the kick, none of the crash.",
|
|
1062
|
+
Tags: "Coffee-themed, Energetic"
|
|
1063
|
+
}, {
|
|
1064
|
+
Slogan: "Sip back and ship faster.",
|
|
1065
|
+
Tags: "Coffee-themed, Fun"
|
|
1066
|
+
}, {
|
|
1067
|
+
Slogan: "Keep calm and code Decaf.",
|
|
1068
|
+
Tags: "Coffee-themed, Playful"
|
|
1069
|
+
}, {
|
|
1070
|
+
Slogan: "Code without the caffeine shakes.",
|
|
1071
|
+
Tags: "Coffee-themed, Humorous"
|
|
1072
|
+
}, {
|
|
1073
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
1074
|
+
Tags: "Coffee-themed, Technical"
|
|
1075
|
+
}, {
|
|
1076
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
1077
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
1078
|
+
}, {
|
|
1079
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
1080
|
+
Tags: "Coffee-themed, Cheerful"
|
|
1081
|
+
}, {
|
|
1082
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
1083
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
1084
|
+
}, {
|
|
1085
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
1086
|
+
Tags: "Coffee-themed, Branding"
|
|
1087
|
+
}, {
|
|
1088
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
1089
|
+
Tags: "Coffee-themed, Chill"
|
|
1090
|
+
}, {
|
|
1091
|
+
Slogan: "All the kick, none of the crash.",
|
|
1092
|
+
Tags: "Coffee-themed, Energetic"
|
|
1093
|
+
}, {
|
|
1094
|
+
Slogan: "Sip back and ship faster.",
|
|
1095
|
+
Tags: "Coffee-themed, Fun"
|
|
1096
|
+
}, {
|
|
1097
|
+
Slogan: "Keep calm and code Decaf.",
|
|
1098
|
+
Tags: "Coffee-themed, Playful"
|
|
1099
|
+
}, {
|
|
1100
|
+
Slogan: "Code without the caffeine shakes.",
|
|
1101
|
+
Tags: "Coffee-themed, Humorous"
|
|
1102
|
+
}, {
|
|
1103
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
1104
|
+
Tags: "Coffee-themed, Technical"
|
|
1105
|
+
}, {
|
|
1106
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
1107
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
1108
|
+
}, {
|
|
1109
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
1110
|
+
Tags: "Coffee-themed, Cheerful"
|
|
1111
|
+
}, {
|
|
1112
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
1113
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
1114
|
+
}, {
|
|
1115
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
1116
|
+
Tags: "Coffee-themed, Branding"
|
|
1117
|
+
}, {
|
|
1118
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
1119
|
+
Tags: "Coffee-themed, Chill"
|
|
1120
|
+
}, {
|
|
1121
|
+
Slogan: "All the kick, none of the crash.",
|
|
1122
|
+
Tags: "Coffee-themed, Energetic"
|
|
1123
|
+
}, {
|
|
1124
|
+
Slogan: "Sip back and ship faster.",
|
|
1125
|
+
Tags: "Coffee-themed, Fun"
|
|
1126
|
+
}, {
|
|
1127
|
+
Slogan: "Keep calm and code Decaf.",
|
|
1128
|
+
Tags: "Coffee-themed, Playful"
|
|
1129
|
+
}, {
|
|
1130
|
+
Slogan: "Code without the caffeine shakes.",
|
|
1131
|
+
Tags: "Coffee-themed, Humorous"
|
|
1132
|
+
}, {
|
|
1133
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
1134
|
+
Tags: "Coffee-themed, Technical"
|
|
1135
|
+
}, {
|
|
1136
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
1137
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
1138
|
+
}, {
|
|
1139
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
1140
|
+
Tags: "Coffee-themed, Cheerful"
|
|
1141
|
+
}, {
|
|
1142
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
1143
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
1144
|
+
}, {
|
|
1145
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
1146
|
+
Tags: "Coffee-themed, Branding"
|
|
1147
|
+
}, {
|
|
1148
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
1149
|
+
Tags: "Coffee-themed, Chill"
|
|
1150
|
+
}, {
|
|
1151
|
+
Slogan: "All the kick, none of the crash.",
|
|
1152
|
+
Tags: "Coffee-themed, Energetic"
|
|
1153
|
+
}, {
|
|
1154
|
+
Slogan: "Sip back and ship faster.",
|
|
1155
|
+
Tags: "Coffee-themed, Fun"
|
|
1156
|
+
}, {
|
|
1157
|
+
Slogan: "Keep calm and code Decaf.",
|
|
1158
|
+
Tags: "Coffee-themed, Playful"
|
|
1159
|
+
}, {
|
|
1160
|
+
Slogan: "Code without the caffeine shakes.",
|
|
1161
|
+
Tags: "Coffee-themed, Humorous"
|
|
1162
|
+
}, {
|
|
1163
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
1164
|
+
Tags: "Coffee-themed, Technical"
|
|
1165
|
+
}, {
|
|
1166
|
+
Slogan: "Decaf-TS: Where smart contracts meet smart interfaces.",
|
|
1167
|
+
Tags: "Blockchain, Smart Contracts, Tech"
|
|
1168
|
+
}, {
|
|
1169
|
+
Slogan: "Ship dApps without the stress.",
|
|
1170
|
+
Tags: "Blockchain, Cheerful, Developer"
|
|
1171
|
+
}, {
|
|
1172
|
+
Slogan: "No CRUD, no problem — Decaf your data.",
|
|
1173
|
+
Tags: "Data, No-CRUD, Chill"
|
|
1174
|
+
}, {
|
|
1175
|
+
Slogan: "From DID to UI, without breaking a sweat.",
|
|
1176
|
+
Tags: "DID, SSI, UI, Calm"
|
|
1177
|
+
}, {
|
|
1178
|
+
Slogan: "Decaf-TS: Your frontend already understands your smart contract.",
|
|
1179
|
+
Tags: "Smart Contracts, DX, Magic"
|
|
1180
|
+
}, {
|
|
1181
|
+
Slogan: "Self-sovereign by design. Productive by default.",
|
|
1182
|
+
Tags: "SSI, Developer, Calm"
|
|
1183
|
+
}, {
|
|
1184
|
+
Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
|
|
1185
|
+
Tags: "Blockchain, Multi-platform, Happy"
|
|
1186
|
+
}, {
|
|
1187
|
+
Slogan: "Data that defines its own destiny.",
|
|
1188
|
+
Tags: "SSI, Data-driven, Empowerment"
|
|
1189
|
+
}, {
|
|
1190
|
+
Slogan: "Goodbye CRUD, hello intent-based interfaces.",
|
|
1191
|
+
Tags: "No-CRUD, UI, Technical"
|
|
1192
|
+
}, {
|
|
1193
|
+
Slogan: "The smoothest path from DID to done.",
|
|
1194
|
+
Tags: "DID, Workflow, Chill"
|
|
1195
|
+
}, {
|
|
1196
|
+
Slogan: "Because your dApp deserves more than boilerplate.",
|
|
1197
|
+
Tags: "Blockchain, DevX, Efficiency"
|
|
1198
|
+
}, {
|
|
1199
|
+
Slogan: "Own your data. Own your flow.",
|
|
1200
|
+
Tags: "SSI, Control, Ownership"
|
|
1201
|
+
}, {
|
|
1202
|
+
Slogan: "Write logic like it belongs with the data — because it does.",
|
|
1203
|
+
Tags: "Data Logic, Developer, Smart"
|
|
1204
|
+
}, {
|
|
1205
|
+
Slogan: "From smart contracts to smarter frontends.",
|
|
1206
|
+
Tags: "Smart Contracts, UI, DX"
|
|
1207
|
+
}, {
|
|
1208
|
+
Slogan: "No caffeine. No CRUD. Just the future.",
|
|
1209
|
+
Tags: "No-CRUD, Coffee-themed, Futuristic"
|
|
1210
|
+
}, {
|
|
1211
|
+
Slogan: "The future of web3 UX is Decaf.",
|
|
1212
|
+
Tags: "Blockchain, UX, Vision"
|
|
1213
|
+
}, {
|
|
1214
|
+
Slogan: "Code with confidence. Govern with clarity.",
|
|
1215
|
+
Tags: "Blockchain, Governance, Calm"
|
|
1216
|
+
}, {
|
|
1217
|
+
Slogan: "Interfaces that obey the data, not the other way around.",
|
|
1218
|
+
Tags: "UI, Data Logic, Self-aware"
|
|
1219
|
+
}, {
|
|
1220
|
+
Slogan: "Brew business logic right into your bytes.",
|
|
1221
|
+
Tags: "Data Logic, Coffee-themed, Fun"
|
|
1222
|
+
}, {
|
|
1223
|
+
Slogan: "DIDs done differently — and delightfully.",
|
|
1224
|
+
Tags: "DID, Self-Sovereign, Playful"
|
|
1225
|
+
}, {
|
|
1226
|
+
Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
|
|
1227
|
+
Tags: "Blockchain, Smart Contracts, Tech"
|
|
1228
|
+
}, {
|
|
1229
|
+
Slogan: "Ship dApps without the stress.",
|
|
1230
|
+
Tags: "Blockchain, Cheerful, Developer"
|
|
1231
|
+
}, {
|
|
1232
|
+
Slogan: "No boilerplate, no problem — Decaf-TS your data.",
|
|
1233
|
+
Tags: "Data, No-CRUD, Chill"
|
|
1234
|
+
}, {
|
|
1235
|
+
Slogan: "From DID to UI, without breaking a sweat.",
|
|
1236
|
+
Tags: "DID, SSI, UI, Calm"
|
|
1237
|
+
}, {
|
|
1238
|
+
Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
|
|
1239
|
+
Tags: "Smart Contracts, DX, Magic"
|
|
1240
|
+
}, {
|
|
1241
|
+
Slogan: "Self-sovereign by design. Productive by default.",
|
|
1242
|
+
Tags: "SSI, Developer, Calm"
|
|
1243
|
+
}, {
|
|
1244
|
+
Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
|
|
1245
|
+
Tags: "Blockchain, Multi-platform, Happy"
|
|
1246
|
+
}, {
|
|
1247
|
+
Slogan: "Data that defines its own destiny.",
|
|
1248
|
+
Tags: "SSI, Data-driven, Empowerment"
|
|
1249
|
+
}, {
|
|
1250
|
+
Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
|
|
1251
|
+
Tags: "No-CRUD, UI, Technical"
|
|
1252
|
+
}, {
|
|
1253
|
+
Slogan: "The smoothest path from DID to done.",
|
|
1254
|
+
Tags: "DID, Workflow, Chill"
|
|
1255
|
+
}, {
|
|
1256
|
+
Slogan: "Because your dApp deserves more than boilerplate.",
|
|
1257
|
+
Tags: "Blockchain, DevX, Efficiency"
|
|
1258
|
+
}, {
|
|
1259
|
+
Slogan: "Own your data. Own your flow.",
|
|
1260
|
+
Tags: "SSI, Control, Ownership"
|
|
1261
|
+
}, {
|
|
1262
|
+
Slogan: "Write logic like it belongs with the data — because it does.",
|
|
1263
|
+
Tags: "Data Logic, Developer, Smart"
|
|
1264
|
+
}, {
|
|
1265
|
+
Slogan: "From blockchain contracts to smarter frontends.",
|
|
1266
|
+
Tags: "Smart Contracts, UI, DX"
|
|
1267
|
+
}, {
|
|
1268
|
+
Slogan: "No caffeine. No boilerplate. Just the future.",
|
|
1269
|
+
Tags: "No-CRUD, Coffee-themed, Futuristic"
|
|
1270
|
+
}, {
|
|
1271
|
+
Slogan: "The future of web3 UX is Decaf-TS.",
|
|
1272
|
+
Tags: "Blockchain, UX, Vision"
|
|
1273
|
+
}, {
|
|
1274
|
+
Slogan: "Code with confidence. Govern with clarity.",
|
|
1275
|
+
Tags: "Blockchain, Governance, Calm"
|
|
1276
|
+
}, {
|
|
1277
|
+
Slogan: "Interfaces that obey the data, not the other way around.",
|
|
1278
|
+
Tags: "UI, Data Logic, Self-aware"
|
|
1279
|
+
}, {
|
|
1280
|
+
Slogan: "Brew business logic right into your bytes.",
|
|
1281
|
+
Tags: "Data Logic, Coffee-themed, Fun"
|
|
1282
|
+
}, {
|
|
1283
|
+
Slogan: "DIDs done differently — and delightfully.",
|
|
1284
|
+
Tags: "DID, Self-Sovereign, Playful"
|
|
1285
|
+
}, {
|
|
1286
|
+
Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
|
|
1287
|
+
Tags: "Blockchain, Smart Contracts, Tech"
|
|
1288
|
+
}, {
|
|
1289
|
+
Slogan: "Ship dApps without the stress.",
|
|
1290
|
+
Tags: "Blockchain, Cheerful, Developer"
|
|
1291
|
+
}, {
|
|
1292
|
+
Slogan: "No boilerplate, no problem — Decaf-TS your data.",
|
|
1293
|
+
Tags: "Data, No-CRUD, Chill"
|
|
1294
|
+
}, {
|
|
1295
|
+
Slogan: "From DID to UI, without breaking a sweat.",
|
|
1296
|
+
Tags: "DID, SSI, UI, Calm"
|
|
1297
|
+
}, {
|
|
1298
|
+
Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
|
|
1299
|
+
Tags: "Smart Contracts, DX, Magic"
|
|
1300
|
+
}, {
|
|
1301
|
+
Slogan: "Self-sovereign by design. Productive by default.",
|
|
1302
|
+
Tags: "SSI, Developer, Calm"
|
|
1303
|
+
}, {
|
|
1304
|
+
Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
|
|
1305
|
+
Tags: "Blockchain, Multi-platform, Happy"
|
|
1306
|
+
}, {
|
|
1307
|
+
Slogan: "Data that defines its own destiny.",
|
|
1308
|
+
Tags: "SSI, Data-driven, Empowerment"
|
|
1309
|
+
}, {
|
|
1310
|
+
Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
|
|
1311
|
+
Tags: "No-CRUD, UI, Technical"
|
|
1312
|
+
}, {
|
|
1313
|
+
Slogan: "The smoothest path from DID to done.",
|
|
1314
|
+
Tags: "DID, Workflow, Chill"
|
|
1315
|
+
}, {
|
|
1316
|
+
Slogan: "Because your dApp deserves more than boilerplate.",
|
|
1317
|
+
Tags: "Blockchain, DevX, Efficiency"
|
|
1318
|
+
}, {
|
|
1319
|
+
Slogan: "Own your data. Own your flow.",
|
|
1320
|
+
Tags: "SSI, Control, Ownership"
|
|
1321
|
+
}, {
|
|
1322
|
+
Slogan: "Write logic like it belongs with the data — because it does.",
|
|
1323
|
+
Tags: "Data Logic, Developer, Smart"
|
|
1324
|
+
}, {
|
|
1325
|
+
Slogan: "From blockchain contracts to smarter frontends.",
|
|
1326
|
+
Tags: "Smart Contracts, UI, DX"
|
|
1327
|
+
}, {
|
|
1328
|
+
Slogan: "No caffeine. No boilerplate. Just the future.",
|
|
1329
|
+
Tags: "No-CRUD, Coffee-themed, Futuristic"
|
|
1330
|
+
}, {
|
|
1331
|
+
Slogan: "The future of web3 UX is Decaf-TS.",
|
|
1332
|
+
Tags: "Blockchain, UX, Vision"
|
|
1333
|
+
}, {
|
|
1334
|
+
Slogan: "Code with confidence. Govern with clarity.",
|
|
1335
|
+
Tags: "Blockchain, Governance, Calm"
|
|
1336
|
+
}, {
|
|
1337
|
+
Slogan: "Interfaces that obey the data, not the other way around.",
|
|
1338
|
+
Tags: "UI, Data Logic, Self-aware"
|
|
1339
|
+
}, {
|
|
1340
|
+
Slogan: "Brew business logic right into your bytes.",
|
|
1341
|
+
Tags: "Data Logic, Coffee-themed, Fun"
|
|
1342
|
+
}, {
|
|
1343
|
+
Slogan: "DIDs done differently — and delightfully.",
|
|
1344
|
+
Tags: "DID, Self-Sovereign, Playful"
|
|
1345
|
+
}, {
|
|
1346
|
+
Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
|
|
1347
|
+
Tags: "Blockchain, Smart Contracts, Tech"
|
|
1348
|
+
}, {
|
|
1349
|
+
Slogan: "Ship dApps without the stress.",
|
|
1350
|
+
Tags: "Blockchain, Cheerful, Developer"
|
|
1351
|
+
}, {
|
|
1352
|
+
Slogan: "No boilerplate, no problem — Decaf-TS your data.",
|
|
1353
|
+
Tags: "Data, No-CRUD, Chill"
|
|
1354
|
+
}, {
|
|
1355
|
+
Slogan: "From DID to UI, without breaking a sweat.",
|
|
1356
|
+
Tags: "DID, SSI, UI, Calm"
|
|
1357
|
+
}, {
|
|
1358
|
+
Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
|
|
1359
|
+
Tags: "Smart Contracts, DX, Magic"
|
|
1360
|
+
}, {
|
|
1361
|
+
Slogan: "Self-sovereign by design. Productive by default.",
|
|
1362
|
+
Tags: "SSI, Developer, Calm"
|
|
1363
|
+
}, {
|
|
1364
|
+
Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
|
|
1365
|
+
Tags: "Blockchain, Multi-platform, Happy"
|
|
1366
|
+
}, {
|
|
1367
|
+
Slogan: "Data that defines its own destiny.",
|
|
1368
|
+
Tags: "SSI, Data-driven, Empowerment"
|
|
1369
|
+
}, {
|
|
1370
|
+
Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
|
|
1371
|
+
Tags: "No-CRUD, UI, Technical"
|
|
1372
|
+
}, {
|
|
1373
|
+
Slogan: "The smoothest path from DID to done.",
|
|
1374
|
+
Tags: "DID, Workflow, Chill"
|
|
1375
|
+
}, {
|
|
1376
|
+
Slogan: "Because your dApp deserves more than boilerplate.",
|
|
1377
|
+
Tags: "Blockchain, DevX, Efficiency"
|
|
1378
|
+
}, {
|
|
1379
|
+
Slogan: "Own your data. Own your flow.",
|
|
1380
|
+
Tags: "SSI, Control, Ownership"
|
|
1381
|
+
}, {
|
|
1382
|
+
Slogan: "Write logic like it belongs with the data — because it does.",
|
|
1383
|
+
Tags: "Data Logic, Developer, Smart"
|
|
1384
|
+
}, {
|
|
1385
|
+
Slogan: "From blockchain contracts to smarter frontends.",
|
|
1386
|
+
Tags: "Smart Contracts, UI, DX"
|
|
1387
|
+
}, {
|
|
1388
|
+
Slogan: "No caffeine. No boilerplate. Just the future.",
|
|
1389
|
+
Tags: "No-CRUD, Coffee-themed, Futuristic"
|
|
1390
|
+
}, {
|
|
1391
|
+
Slogan: "The future of web3 UX is Decaf-TS.",
|
|
1392
|
+
Tags: "Blockchain, UX, Vision"
|
|
1393
|
+
}, {
|
|
1394
|
+
Slogan: "Code with confidence. Govern with clarity.",
|
|
1395
|
+
Tags: "Blockchain, Governance, Calm"
|
|
1396
|
+
}, {
|
|
1397
|
+
Slogan: "Interfaces that obey the data, not the other way around.",
|
|
1398
|
+
Tags: "UI, Data Logic, Self-aware"
|
|
1399
|
+
}, {
|
|
1400
|
+
Slogan: "Brew business logic right into your bytes.",
|
|
1401
|
+
Tags: "Data Logic, Coffee-themed, Fun"
|
|
1402
|
+
}, {
|
|
1403
|
+
Slogan: "DIDs done differently — and delightfully.",
|
|
1404
|
+
Tags: "DID, Self-Sovereign, Playful"
|
|
1405
|
+
}, {
|
|
1406
|
+
Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
|
|
1407
|
+
Tags: "Blockchain, Smart Contracts, Tech"
|
|
1408
|
+
}, {
|
|
1409
|
+
Slogan: "Ship dApps without the stress.",
|
|
1410
|
+
Tags: "Blockchain, Cheerful, Developer"
|
|
1411
|
+
}, {
|
|
1412
|
+
Slogan: "No boilerplate, no problem — Decaf-TS your data.",
|
|
1413
|
+
Tags: "Data, No-CRUD, Chill"
|
|
1414
|
+
}, {
|
|
1415
|
+
Slogan: "From DID to UI, without breaking a sweat.",
|
|
1416
|
+
Tags: "DID, SSI, UI, Calm"
|
|
1417
|
+
}, {
|
|
1418
|
+
Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
|
|
1419
|
+
Tags: "Smart Contracts, DX, Magic"
|
|
1420
|
+
}, {
|
|
1421
|
+
Slogan: "Self-sovereign by design. Productive by default.",
|
|
1422
|
+
Tags: "SSI, Developer, Calm"
|
|
1423
|
+
}, {
|
|
1424
|
+
Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
|
|
1425
|
+
Tags: "Blockchain, Multi-platform, Happy"
|
|
1426
|
+
}, {
|
|
1427
|
+
Slogan: "Data that defines its own destiny.",
|
|
1428
|
+
Tags: "SSI, Data-driven, Empowerment"
|
|
1429
|
+
}, {
|
|
1430
|
+
Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
|
|
1431
|
+
Tags: "No-CRUD, UI, Technical"
|
|
1432
|
+
}, {
|
|
1433
|
+
Slogan: "The smoothest path from DID to done.",
|
|
1434
|
+
Tags: "DID, Workflow, Chill"
|
|
1435
|
+
}, {
|
|
1436
|
+
Slogan: "Because your dApp deserves more than boilerplate.",
|
|
1437
|
+
Tags: "Blockchain, DevX, Efficiency"
|
|
1438
|
+
}, {
|
|
1439
|
+
Slogan: "Own your data. Own your flow.",
|
|
1440
|
+
Tags: "SSI, Control, Ownership"
|
|
1441
|
+
}, {
|
|
1442
|
+
Slogan: "Write logic like it belongs with the data — because it does.",
|
|
1443
|
+
Tags: "Data Logic, Developer, Smart"
|
|
1444
|
+
}, {
|
|
1445
|
+
Slogan: "From blockchain contracts to smarter frontends.",
|
|
1446
|
+
Tags: "Smart Contracts, UI, DX"
|
|
1447
|
+
}, {
|
|
1448
|
+
Slogan: "No caffeine. No boilerplate. Just the future.",
|
|
1449
|
+
Tags: "No-CRUD, Coffee-themed, Futuristic"
|
|
1450
|
+
}, {
|
|
1451
|
+
Slogan: "The future of web3 UX is Decaf-TS.",
|
|
1452
|
+
Tags: "Blockchain, UX, Vision"
|
|
1453
|
+
}, {
|
|
1454
|
+
Slogan: "Code with confidence. Govern with clarity.",
|
|
1455
|
+
Tags: "Blockchain, Governance, Calm"
|
|
1456
|
+
}, {
|
|
1457
|
+
Slogan: "Interfaces that obey the data, not the other way around.",
|
|
1458
|
+
Tags: "UI, Data Logic, Self-aware"
|
|
1459
|
+
}, {
|
|
1460
|
+
Slogan: "Brew business logic right into your bytes.",
|
|
1461
|
+
Tags: "Data Logic, Coffee-themed, Fun"
|
|
1462
|
+
}, {
|
|
1463
|
+
Slogan: "DIDs done differently — and delightfully.",
|
|
1464
|
+
Tags: "DID, Self-Sovereign, Playful"
|
|
1465
|
+
} ];
|
|
1466
|
+
|
|
1467
|
+
const colors = [ "[38;5;215m", "[38;5;209m", "[38;5;205m", "[38;5;210m", "[38;5;217m", "[38;5;216m", "[38;5;224m", "[38;5;230m", "[38;5;230m" ];
|
|
1468
|
+
|
|
1469
|
+
function printBanner(logger) {
|
|
1470
|
+
const message = getSlogan();
|
|
1471
|
+
const banner = `# ░▒▓███████▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓██████▓▒░ ░▒▓████████▓▒░ ░▒▓████████▓▒░ ░▒▓███████▓▒░ \n# ( ( ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# ) ) ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# [=======] ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓██████▓▒░ \n# \`-----´ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# ░▒▓███████▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓███████▓▒░ \n#`.split("\n");
|
|
1472
|
+
const maxLength = banner.reduce((max, line) => Math.max(max, line.length), 0);
|
|
1473
|
+
banner.push(`# ${message.padStart(maxLength - 3)}`);
|
|
1474
|
+
banner.forEach((line, index) => {
|
|
1475
|
+
(logger ? logger.info.bind(logger) : console.log.bind(console))(style(line || "").raw(colors[index]).text);
|
|
1476
|
+
});
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
function getSlogan(i) {
|
|
1480
|
+
try {
|
|
1481
|
+
i = typeof i === "undefined" ? Math.floor(Math.random() * slogans.length) : i;
|
|
1482
|
+
return slogans[i].Slogan;
|
|
1483
|
+
} catch (error) {
|
|
1484
|
+
throw new Error(`Failed to retrieve slogans: ${error}`);
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
class Command extends LoggedClass {
|
|
1489
|
+
constructor(name, inputs = {}, requirements = []) {
|
|
1490
|
+
super();
|
|
1491
|
+
this.name = name;
|
|
1492
|
+
this.inputs = inputs;
|
|
1493
|
+
this.requirements = requirements;
|
|
1494
|
+
if (!Command.log) {
|
|
1495
|
+
Object.defineProperty(Command, "log", {
|
|
1496
|
+
writable: false,
|
|
1497
|
+
value: Logging.for(Command.name)
|
|
1498
|
+
});
|
|
1499
|
+
}
|
|
1500
|
+
this.inputs = Object.assign({}, DefaultCommandOptions, inputs);
|
|
1501
|
+
}
|
|
1502
|
+
async checkRequirements() {
|
|
1503
|
+
const {prod: prod, dev: dev, peer: peer} = await getDependencies();
|
|
1504
|
+
const missing = [];
|
|
1505
|
+
const fullList = Array.from(new Set([ ...prod, ...dev, ...peer ]).values()).map(d => d.name);
|
|
1506
|
+
for (const dep of this.requirements) if (!fullList.includes(dep)) missing.push(dep);
|
|
1507
|
+
if (!missing.length) return;
|
|
1508
|
+
}
|
|
1509
|
+
help(args) {
|
|
1510
|
+
return this.log.info(`This is help. I'm no use because I should have been overridden.`);
|
|
1511
|
+
}
|
|
1512
|
+
async execute() {
|
|
1513
|
+
const args = UserInput.parseArgs(this.inputs);
|
|
1514
|
+
const env = LoggedEnvironment.accumulate(DefaultCommandValues).accumulate(args.values);
|
|
1515
|
+
const {version: version, help: help, banner: banner} = env;
|
|
1516
|
+
if (version) {
|
|
1517
|
+
return getPackageVersion();
|
|
1518
|
+
}
|
|
1519
|
+
if (help) {
|
|
1520
|
+
return this.help(args);
|
|
1521
|
+
}
|
|
1522
|
+
if (banner) printBanner(this.log.for(printBanner, {
|
|
1523
|
+
timestamp: false,
|
|
1524
|
+
style: false,
|
|
1525
|
+
context: false,
|
|
1526
|
+
logLevel: false
|
|
1527
|
+
}));
|
|
1528
|
+
let result;
|
|
1529
|
+
try {
|
|
1530
|
+
result = await this.run(env);
|
|
1531
|
+
} catch (e) {
|
|
1532
|
+
throw e;
|
|
1533
|
+
}
|
|
1534
|
+
return result;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
class HttpClient {
|
|
1539
|
+
static {
|
|
1540
|
+
this.log = Logging.for(HttpClient);
|
|
1541
|
+
}
|
|
1542
|
+
static async downloadFile(url) {
|
|
1543
|
+
return new Promise((resolve, reject) => {
|
|
1544
|
+
function request(url) {
|
|
1545
|
+
url = encodeURI(url);
|
|
1546
|
+
https.get(url, res => {
|
|
1547
|
+
if (res.statusCode === 301 || res.statusCode === 307) return request(res.headers.location);
|
|
1548
|
+
if (res.statusCode !== 200) {
|
|
1549
|
+
HttpClient.log.error(`Failed to fetch ${url} (status: ${res.statusCode})`);
|
|
1550
|
+
return reject(new Error(`Failed to fetch ${url}`));
|
|
1551
|
+
}
|
|
1552
|
+
let data = "";
|
|
1553
|
+
res.on("data", chunk => {
|
|
1554
|
+
data += chunk;
|
|
1555
|
+
});
|
|
1556
|
+
res.on("error", error => {
|
|
1557
|
+
reject(error);
|
|
1558
|
+
});
|
|
1559
|
+
res.on("end", () => {
|
|
1560
|
+
resolve(data);
|
|
1561
|
+
});
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1564
|
+
request(url);
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
function parseList(input) {
|
|
1570
|
+
if (!input) return [];
|
|
1571
|
+
if (Array.isArray(input)) return input.map(i => `${i}`.trim()).filter(Boolean);
|
|
1572
|
+
return `${input}`.split(",").map(p => p.trim()).filter(Boolean);
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
function packageToGlobal(name) {
|
|
1576
|
+
const withoutScope = name.replace(/^@/, "");
|
|
1577
|
+
const parts = withoutScope.split(/[/\-_.]+/).filter(Boolean);
|
|
1578
|
+
return parts.map((p, i) => i === 0 ? p.replace(/[^a-zA-Z0-9]/g, "") : `${p.charAt(0).toUpperCase()}${p.slice(1)}`).join("");
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
function getPackageDependencies() {
|
|
1582
|
+
let pkg;
|
|
1583
|
+
try {
|
|
1584
|
+
pkg = getPackage(process.cwd());
|
|
1585
|
+
} catch {
|
|
1586
|
+
pkg = undefined;
|
|
1587
|
+
}
|
|
1588
|
+
try {
|
|
1589
|
+
const hasDeps = pkg && (Object.keys(pkg.dependencies || {}).length > 0 || Object.keys(pkg.devDependencies || {}).length > 0 || Object.keys(pkg.peerDependencies || {}).length > 0);
|
|
1590
|
+
if (!hasDeps) {
|
|
1591
|
+
const fallbackDir = path.resolve(__dirname, "../../..");
|
|
1592
|
+
try {
|
|
1593
|
+
pkg = getPackage(fallbackDir);
|
|
1594
|
+
} catch {}
|
|
1595
|
+
}
|
|
1596
|
+
} catch {}
|
|
1597
|
+
const deps = Object.keys(pkg && pkg.dependencies || {});
|
|
1598
|
+
const peer = Object.keys(pkg && pkg.peerDependencies || {});
|
|
1599
|
+
const dev = Object.keys(pkg && pkg.devDependencies || {});
|
|
1600
|
+
return Array.from(new Set([ ...deps, ...peer, ...dev ]));
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
const VERSION_STRING = "##VERSION##";
|
|
1604
|
+
|
|
1605
|
+
const PACKAGE_STRING = "##PACKAGE##";
|
|
1606
|
+
|
|
1607
|
+
const PACKAGE_SIZE_STRING = "##PACKAGE_SIZE##";
|
|
1608
|
+
|
|
1609
|
+
var Modes;
|
|
1610
|
+
|
|
1611
|
+
(function(Modes) {
|
|
1612
|
+
Modes["CJS"] = "commonjs";
|
|
1613
|
+
Modes["ESM"] = "es2022";
|
|
1614
|
+
})(Modes || (Modes = {}));
|
|
1615
|
+
|
|
1616
|
+
var BuildMode;
|
|
1617
|
+
|
|
1618
|
+
(function(BuildMode) {
|
|
1619
|
+
BuildMode["BUILD"] = "build";
|
|
1620
|
+
BuildMode["BUNDLE"] = "bundle";
|
|
1621
|
+
BuildMode["ALL"] = "all";
|
|
1622
|
+
})(BuildMode || (BuildMode = {}));
|
|
1623
|
+
|
|
1624
|
+
const options$1 = {
|
|
1625
|
+
prod: {
|
|
1626
|
+
type: "boolean",
|
|
1627
|
+
default: false
|
|
1628
|
+
},
|
|
1629
|
+
dev: {
|
|
1630
|
+
type: "boolean",
|
|
1631
|
+
default: false
|
|
1632
|
+
},
|
|
1633
|
+
buildMode: {
|
|
1634
|
+
type: "string",
|
|
1635
|
+
default: BuildMode.ALL
|
|
1636
|
+
},
|
|
1637
|
+
includes: {
|
|
1638
|
+
type: "string",
|
|
1639
|
+
default: ""
|
|
1640
|
+
},
|
|
1641
|
+
externals: {
|
|
1642
|
+
type: "string",
|
|
1643
|
+
default: ""
|
|
1644
|
+
},
|
|
1645
|
+
docs: {
|
|
1646
|
+
type: "boolean",
|
|
1647
|
+
default: false
|
|
1648
|
+
},
|
|
1649
|
+
commands: {
|
|
1650
|
+
type: "boolean",
|
|
1651
|
+
default: false
|
|
1652
|
+
},
|
|
1653
|
+
banner: {
|
|
1654
|
+
type: "boolean",
|
|
1655
|
+
default: false
|
|
1656
|
+
}
|
|
1657
|
+
};
|
|
1658
|
+
|
|
1659
|
+
const cjs2Transformer = (ext = ".cjs") => {
|
|
1660
|
+
const log = BuildScripts.log.for(cjs2Transformer);
|
|
1661
|
+
const resolutionCache = new Map;
|
|
1662
|
+
return transformationContext => sourceFile => {
|
|
1663
|
+
const sourceDir = path.dirname(sourceFile.fileName);
|
|
1664
|
+
function resolvePath(importPath) {
|
|
1665
|
+
const cacheKey = JSON.stringify([ sourceDir, importPath ]);
|
|
1666
|
+
const cachedValue = resolutionCache.get(cacheKey);
|
|
1667
|
+
if (cachedValue != null) return cachedValue;
|
|
1668
|
+
let resolvedPath = importPath;
|
|
1669
|
+
try {
|
|
1670
|
+
resolvedPath = path.resolve(sourceDir, resolvedPath + ".ts");
|
|
1671
|
+
} catch (error) {
|
|
1672
|
+
throw new Error(`Failed to resolve path ${importPath}: ${error}`);
|
|
1673
|
+
}
|
|
1674
|
+
let stat;
|
|
1675
|
+
try {
|
|
1676
|
+
stat = fs.statSync(resolvedPath);
|
|
1677
|
+
} catch (e) {
|
|
1678
|
+
try {
|
|
1679
|
+
log.verbose(`Testing existence of path ${resolvedPath} as a folder defaulting to index file`);
|
|
1680
|
+
stat = fs.statSync(resolvedPath.replace(/\.ts$/gm, ""));
|
|
1681
|
+
} catch (e2) {
|
|
1682
|
+
throw new Error(`Failed to resolve path ${importPath}: ${e}, ${e2}`);
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
if (stat.isDirectory()) resolvedPath = resolvedPath.replace(/\.ts$/gm, "/index.ts");
|
|
1686
|
+
if (path.isAbsolute(resolvedPath)) {
|
|
1687
|
+
const extension = (/\.tsx?$/.exec(path.basename(resolvedPath)) || [])[0] || void 0;
|
|
1688
|
+
resolvedPath = "./" + path.relative(sourceDir, path.resolve(path.dirname(resolvedPath), path.basename(resolvedPath, extension) + ext));
|
|
1689
|
+
}
|
|
1690
|
+
resolutionCache.set(cacheKey, resolvedPath);
|
|
1691
|
+
return resolvedPath;
|
|
1692
|
+
}
|
|
1693
|
+
function visitNode(node) {
|
|
1694
|
+
if (shouldMutateModuleSpecifier(node)) {
|
|
1695
|
+
if (ts.isImportDeclaration(node)) {
|
|
1696
|
+
const resolvedPath = resolvePath(node.moduleSpecifier.text);
|
|
1697
|
+
const newModuleSpecifier = transformationContext.factory.createStringLiteral(resolvedPath);
|
|
1698
|
+
return transformationContext.factory.updateImportDeclaration(node, node.modifiers, node.importClause, newModuleSpecifier, undefined);
|
|
1699
|
+
} else if (ts.isExportDeclaration(node)) {
|
|
1700
|
+
const resolvedPath = resolvePath(node.moduleSpecifier.text);
|
|
1701
|
+
const newModuleSpecifier = transformationContext.factory.createStringLiteral(resolvedPath);
|
|
1702
|
+
return transformationContext.factory.updateExportDeclaration(node, node.modifiers, node.isTypeOnly, node.exportClause, newModuleSpecifier, undefined);
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
return ts.visitEachChild(node, visitNode, transformationContext);
|
|
1706
|
+
}
|
|
1707
|
+
function shouldMutateModuleSpecifier(node) {
|
|
1708
|
+
if (!ts.isImportDeclaration(node) && !ts.isExportDeclaration(node)) return false;
|
|
1709
|
+
if (node.moduleSpecifier === undefined) return false;
|
|
1710
|
+
if (!ts.isStringLiteral(node.moduleSpecifier)) return false;
|
|
1711
|
+
if (!node.moduleSpecifier.text.startsWith("./") && !node.moduleSpecifier.text.startsWith("../")) return false;
|
|
1712
|
+
if (path.extname(node.moduleSpecifier.text) !== "") return false;
|
|
1713
|
+
return true;
|
|
1714
|
+
}
|
|
1715
|
+
return ts.visitNode(sourceFile, visitNode);
|
|
1716
|
+
};
|
|
1717
|
+
};
|
|
1718
|
+
|
|
1719
|
+
class BuildScripts extends Command {
|
|
1720
|
+
constructor() {
|
|
1721
|
+
super("BuildScripts", Object.assign({}, DefaultCommandOptions, options$1));
|
|
1722
|
+
this.replacements = {};
|
|
1723
|
+
const pkg = getPackage();
|
|
1724
|
+
const {name: name, version: version} = pkg;
|
|
1725
|
+
this.pkgName = name.includes("@") ? name.split("/")[1] : name;
|
|
1726
|
+
this.pkgVersion = version;
|
|
1727
|
+
this.replacements[VERSION_STRING] = this.pkgVersion;
|
|
1728
|
+
this.replacements[PACKAGE_STRING] = name;
|
|
1729
|
+
}
|
|
1730
|
+
patchFiles(p) {
|
|
1731
|
+
const log = this.log.for(this.patchFiles);
|
|
1732
|
+
const {name: name, version: version} = getPackage();
|
|
1733
|
+
log.info(`Patching ${name} ${version} module in ${p}...`);
|
|
1734
|
+
const stat = fs.statSync(p);
|
|
1735
|
+
if (stat.isDirectory()) fs.readdirSync(p, {
|
|
1736
|
+
withFileTypes: true,
|
|
1737
|
+
recursive: true
|
|
1738
|
+
}).filter(p => p.isFile()).forEach(file => patchFile(path.join(file.parentPath, file.name), Object.entries(this.replacements).reduce((acc, [key, val]) => {
|
|
1739
|
+
switch (key) {
|
|
1740
|
+
case VERSION_STRING:
|
|
1741
|
+
log.debug("Found VERSION string to replace");
|
|
1742
|
+
acc[`VERSION = "${VERSION_STRING}";`] = `VERSION = "${val}";`;
|
|
1743
|
+
break;
|
|
1744
|
+
|
|
1745
|
+
case PACKAGE_STRING:
|
|
1746
|
+
log.debug("Found PACKAGE_NAME string to replace");
|
|
1747
|
+
acc[`PACKAGE_NAME = "${PACKAGE_STRING}";`] = `PACKAGE_NAME = "${val}";`;
|
|
1748
|
+
break;
|
|
1749
|
+
|
|
1750
|
+
default:
|
|
1751
|
+
acc[key] = val;
|
|
1752
|
+
}
|
|
1753
|
+
return acc;
|
|
1754
|
+
}, {})));
|
|
1755
|
+
log.verbose(`Module ${name} ${version} patched in ${p}...`);
|
|
1756
|
+
}
|
|
1757
|
+
reportDiagnostics(diagnostics, logLevel) {
|
|
1758
|
+
const msg = this.formatDiagnostics(diagnostics);
|
|
1759
|
+
try {
|
|
1760
|
+
this.log[logLevel](msg);
|
|
1761
|
+
} catch (e) {
|
|
1762
|
+
console.warn(`Failed to get logger for ${logLevel}`);
|
|
1763
|
+
throw e;
|
|
1764
|
+
}
|
|
1765
|
+
return msg;
|
|
1766
|
+
}
|
|
1767
|
+
formatDiagnostics(diagnostics) {
|
|
1768
|
+
return diagnostics.map(diagnostic => {
|
|
1769
|
+
let message = "";
|
|
1770
|
+
if (diagnostic.file && diagnostic.start) {
|
|
1771
|
+
const {line: line, character: character} = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
|
1772
|
+
message += `${diagnostic.file.fileName} (${line + 1},${character + 1})`;
|
|
1773
|
+
}
|
|
1774
|
+
message += ": " + ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
|
1775
|
+
return message;
|
|
1776
|
+
}).join("\n");
|
|
1777
|
+
}
|
|
1778
|
+
readConfigFile(configFileName) {
|
|
1779
|
+
const configFileText = fs.readFileSync(configFileName).toString();
|
|
1780
|
+
const result = ts.parseConfigFileTextToJson(configFileName, configFileText);
|
|
1781
|
+
const configObject = result.config;
|
|
1782
|
+
if (!configObject) {
|
|
1783
|
+
this.reportDiagnostics([ result.error ], LogLevel.error);
|
|
1784
|
+
}
|
|
1785
|
+
const configParseResult = ts.parseJsonConfigFileContent(configObject, ts.sys, path.dirname(configFileName));
|
|
1786
|
+
if (configParseResult.errors.length > 0) this.reportDiagnostics(configParseResult.errors, LogLevel.error);
|
|
1787
|
+
return configParseResult;
|
|
1788
|
+
}
|
|
1789
|
+
evalDiagnostics(diagnostics) {
|
|
1790
|
+
if (diagnostics && diagnostics.length > 0) {
|
|
1791
|
+
const errors = diagnostics.filter(d => d.category === ts.DiagnosticCategory.Error);
|
|
1792
|
+
const warnings = diagnostics.filter(d => d.category === ts.DiagnosticCategory.Warning);
|
|
1793
|
+
const suggestions = diagnostics.filter(d => d.category === ts.DiagnosticCategory.Suggestion);
|
|
1794
|
+
const messages = diagnostics.filter(d => d.category === ts.DiagnosticCategory.Message);
|
|
1795
|
+
if (warnings.length) this.reportDiagnostics(warnings, LogLevel.warn);
|
|
1796
|
+
if (errors.length) {
|
|
1797
|
+
this.reportDiagnostics(diagnostics, LogLevel.error);
|
|
1798
|
+
throw new Error(`TypeScript reported ${diagnostics.length} diagnostic(s) during check; aborting.`);
|
|
1799
|
+
}
|
|
1800
|
+
if (suggestions.length) this.reportDiagnostics(suggestions, LogLevel.info);
|
|
1801
|
+
if (messages.length) this.reportDiagnostics(messages, LogLevel.info);
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
preCheckDiagnostics(program) {
|
|
1805
|
+
const diagnostics = ts.getPreEmitDiagnostics(program);
|
|
1806
|
+
this.evalDiagnostics(diagnostics);
|
|
1807
|
+
}
|
|
1808
|
+
async checkTsDiagnostics(isDev, mode, bundle = false) {
|
|
1809
|
+
const log = this.log.for(this.checkTsDiagnostics);
|
|
1810
|
+
let tsConfig;
|
|
1811
|
+
try {
|
|
1812
|
+
tsConfig = this.readConfigFile("./tsconfig.json");
|
|
1813
|
+
} catch (e) {
|
|
1814
|
+
throw new Error(`Failed to parse tsconfig.json: ${e}`);
|
|
1815
|
+
}
|
|
1816
|
+
if (bundle) {
|
|
1817
|
+
tsConfig.options.module = ModuleKind.AMD;
|
|
1818
|
+
tsConfig.options.outDir = "dist";
|
|
1819
|
+
tsConfig.options.isolatedModules = false;
|
|
1820
|
+
tsConfig.options.outFile = this.pkgName;
|
|
1821
|
+
} else {
|
|
1822
|
+
tsConfig.options.outDir = `lib${mode === Modes.ESM ? "/esm" : ""}`;
|
|
1823
|
+
tsConfig.options.module = mode === Modes.ESM ? ModuleKind.ES2022 : ModuleKind.CommonJS;
|
|
1824
|
+
}
|
|
1825
|
+
tsConfig.options.inlineSourceMap = false;
|
|
1826
|
+
tsConfig.options.inlineSources = false;
|
|
1827
|
+
tsConfig.options.sourceMap = true;
|
|
1828
|
+
const program = ts.createProgram(tsConfig.fileNames, tsConfig.options);
|
|
1829
|
+
this.preCheckDiagnostics(program);
|
|
1830
|
+
log.verbose(`TypeScript checks passed (${bundle ? "bundle" : "normal"} mode).`);
|
|
1831
|
+
}
|
|
1832
|
+
async buildTs(isDev, mode, bundle = false) {
|
|
1833
|
+
const log = this.log.for(this.buildTs);
|
|
1834
|
+
log.info(`Building ${this.pkgName} ${this.pkgVersion} module (${mode}) in ${isDev ? "dev" : "prod"} mode...`);
|
|
1835
|
+
let tsConfig;
|
|
1836
|
+
try {
|
|
1837
|
+
tsConfig = this.readConfigFile("./tsconfig.json");
|
|
1838
|
+
} catch (e) {
|
|
1839
|
+
throw new Error(`Failed to parse tsconfig.json: ${e}`);
|
|
1840
|
+
}
|
|
1841
|
+
if (bundle) {
|
|
1842
|
+
tsConfig.options.module = ModuleKind.AMD;
|
|
1843
|
+
tsConfig.options.outDir = "dist";
|
|
1844
|
+
tsConfig.options.isolatedModules = false;
|
|
1845
|
+
tsConfig.options.outFile = this.pkgName;
|
|
1846
|
+
} else {
|
|
1847
|
+
tsConfig.options.outDir = `lib${mode === Modes.ESM ? "/esm" : ""}`;
|
|
1848
|
+
tsConfig.options.module = mode === Modes.ESM ? ModuleKind.ES2022 : ModuleKind.CommonJS;
|
|
1849
|
+
}
|
|
1850
|
+
if (isDev) {
|
|
1851
|
+
tsConfig.options.inlineSourceMap = true;
|
|
1852
|
+
tsConfig.options.inlineSources = true;
|
|
1853
|
+
tsConfig.options.sourceMap = false;
|
|
1854
|
+
} else {
|
|
1855
|
+
tsConfig.options.inlineSourceMap = false;
|
|
1856
|
+
tsConfig.options.inlineSources = false;
|
|
1857
|
+
tsConfig.options.sourceMap = true;
|
|
1858
|
+
}
|
|
1859
|
+
const program = ts.createProgram(tsConfig.fileNames, tsConfig.options);
|
|
1860
|
+
const transformations = {};
|
|
1861
|
+
if (mode === Modes.CJS) {
|
|
1862
|
+
transformations.before = [ cjs2Transformer(".cjs") ];
|
|
1863
|
+
} else if (mode === Modes.ESM) {
|
|
1864
|
+
transformations.before = [ cjs2Transformer(".js") ];
|
|
1865
|
+
}
|
|
1866
|
+
const emitResult = program.emit(undefined, undefined, undefined, undefined, transformations);
|
|
1867
|
+
const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
|
|
1868
|
+
this.evalDiagnostics(allDiagnostics);
|
|
1869
|
+
}
|
|
1870
|
+
async build(isDev, mode, bundle = false) {
|
|
1871
|
+
const log = this.log.for(this.build);
|
|
1872
|
+
await this.buildTs(isDev, mode, bundle);
|
|
1873
|
+
log.verbose(`Module ${this.pkgName} ${this.pkgVersion} (${mode}) built in ${isDev ? "dev" : "prod"} mode...`);
|
|
1874
|
+
if (mode === Modes.CJS && !bundle) {
|
|
1875
|
+
const files = getAllFiles("lib", file => file.endsWith(".js") && !file.includes("/esm/"));
|
|
1876
|
+
for (const file of files) {
|
|
1877
|
+
log.verbose(`Patching ${file}'s cjs imports...`);
|
|
1878
|
+
const f = file.replace(".js", ".cjs");
|
|
1879
|
+
await renameFile(file, f);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
copyAssets(mode) {
|
|
1884
|
+
const log = this.log.for(this.copyAssets);
|
|
1885
|
+
let hasAssets = false;
|
|
1886
|
+
try {
|
|
1887
|
+
hasAssets = fs.statSync("./src/assets").isDirectory();
|
|
1888
|
+
} catch (e) {
|
|
1889
|
+
return log.verbose(`No assets found in ./src/assets to copy`);
|
|
1890
|
+
}
|
|
1891
|
+
if (hasAssets) copyFile("./src/assets", `./${mode === Modes.CJS ? "lib" : "dist"}/assets`);
|
|
1892
|
+
}
|
|
1893
|
+
async bundle(mode, isDev, isLib, entryFile = "src/index.ts", nameOverride = this.pkgName, externalsArg, includeArg = [ "prompts", "styled-string-builder", "typed-object-accumulator", "@decaf-ts/logging" ]) {
|
|
1894
|
+
await this.checkTsDiagnostics(isDev, mode, true);
|
|
1895
|
+
const isEsm = mode === Modes.ESM;
|
|
1896
|
+
const pkgName = this.pkgName;
|
|
1897
|
+
const log = this.log;
|
|
1898
|
+
const include = Array.from(new Set([ ...parseList(includeArg) ]));
|
|
1899
|
+
let externalsList = parseList(externalsArg);
|
|
1900
|
+
if (externalsList.length === 0) {
|
|
1901
|
+
try {
|
|
1902
|
+
externalsList = listNodeModulesPackages(path.join(process.cwd(), "node_modules"));
|
|
1903
|
+
} catch {}
|
|
1904
|
+
if (!externalsList || externalsList.length === 0) {
|
|
1905
|
+
externalsList = getPackageDependencies();
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
const ext = Array.from(new Set([ ...function builtinList() {
|
|
1909
|
+
try {
|
|
1910
|
+
return Array.isArray(builtinModules) ? builtinModules : [];
|
|
1911
|
+
} catch {
|
|
1912
|
+
return [ "fs", "path", "process", "child_process", "util", "https", "http", "os", "stream", "crypto", "zlib", "net", "tls", "url", "querystring", "assert", "events", "tty", "dns", "querystring" ];
|
|
1913
|
+
}
|
|
1914
|
+
}(), ...externalsList ]));
|
|
1915
|
+
const rollupSourceMapOutput = isDev ? "inline" : true;
|
|
1916
|
+
const plugins = [ typescript({
|
|
1917
|
+
compilerOptions: {
|
|
1918
|
+
module: "esnext",
|
|
1919
|
+
declaration: false,
|
|
1920
|
+
outDir: isLib ? "bin" : "dist",
|
|
1921
|
+
sourceMap: isDev ? false : true,
|
|
1922
|
+
inlineSourceMap: isDev ? true : false,
|
|
1923
|
+
inlineSources: isDev ? true : false
|
|
1924
|
+
},
|
|
1925
|
+
include: [ "src/**/*.ts" ],
|
|
1926
|
+
exclude: [ "node_modules", "**/*.spec.ts" ],
|
|
1927
|
+
tsconfig: "./tsconfig.json"
|
|
1928
|
+
}), json() ];
|
|
1929
|
+
if (isLib) {
|
|
1930
|
+
plugins.push(commonjs({
|
|
1931
|
+
include: [],
|
|
1932
|
+
exclude: externalsList
|
|
1933
|
+
}), nodeResolve({
|
|
1934
|
+
resolveOnly: include
|
|
1935
|
+
}));
|
|
1936
|
+
}
|
|
1937
|
+
try {
|
|
1938
|
+
const terserMod = await import("@rollup/plugin-terser");
|
|
1939
|
+
const terserFn = terserMod && terserMod.terser || terserMod.default || terserMod;
|
|
1940
|
+
const terserOptionsDev = {
|
|
1941
|
+
parse: {
|
|
1942
|
+
ecma: 2020
|
|
1943
|
+
},
|
|
1944
|
+
compress: false,
|
|
1945
|
+
mangle: false,
|
|
1946
|
+
format: {
|
|
1947
|
+
comments: false,
|
|
1948
|
+
beautify: true
|
|
1949
|
+
}
|
|
1950
|
+
};
|
|
1951
|
+
const terserOptionsProd = {
|
|
1952
|
+
parse: {
|
|
1953
|
+
ecma: 2020
|
|
1954
|
+
},
|
|
1955
|
+
compress: {
|
|
1956
|
+
ecma: 2020,
|
|
1957
|
+
passes: 5,
|
|
1958
|
+
drop_console: true,
|
|
1959
|
+
drop_debugger: true,
|
|
1960
|
+
toplevel: true,
|
|
1961
|
+
module: isEsm,
|
|
1962
|
+
unsafe: true,
|
|
1963
|
+
unsafe_arrows: true,
|
|
1964
|
+
unsafe_comps: true,
|
|
1965
|
+
collapse_vars: true,
|
|
1966
|
+
reduce_funcs: true,
|
|
1967
|
+
reduce_vars: true
|
|
1968
|
+
},
|
|
1969
|
+
mangle: {
|
|
1970
|
+
toplevel: true
|
|
1971
|
+
},
|
|
1972
|
+
format: {
|
|
1973
|
+
comments: false,
|
|
1974
|
+
ascii_only: true
|
|
1975
|
+
},
|
|
1976
|
+
toplevel: true
|
|
1977
|
+
};
|
|
1978
|
+
plugins.push(terserFn(isDev ? terserOptionsDev : terserOptionsProd));
|
|
1979
|
+
} catch {}
|
|
1980
|
+
const input = {
|
|
1981
|
+
input: entryFile,
|
|
1982
|
+
plugins: plugins,
|
|
1983
|
+
external: ext,
|
|
1984
|
+
onwarn: undefined,
|
|
1985
|
+
treeshake: !isDev
|
|
1986
|
+
};
|
|
1987
|
+
const globals = {};
|
|
1988
|
+
ext.forEach(e => {
|
|
1989
|
+
globals[e] = packageToGlobal(e);
|
|
1990
|
+
});
|
|
1991
|
+
const outputs = [ {
|
|
1992
|
+
file: `${isLib ? "bin/" : "dist/"}${nameOverride ? nameOverride : `.bundle.${!isDev ? "min" : ""}`}${isEsm ? ".js" : ".cjs"}`,
|
|
1993
|
+
format: isLib ? "cjs" : isEsm ? "esm" : "umd",
|
|
1994
|
+
name: pkgName,
|
|
1995
|
+
esModule: isEsm,
|
|
1996
|
+
sourcemap: rollupSourceMapOutput,
|
|
1997
|
+
globals: globals,
|
|
1998
|
+
exports: "auto"
|
|
1999
|
+
} ];
|
|
2000
|
+
try {
|
|
2001
|
+
const bundle = await rollup(input);
|
|
2002
|
+
log.verbose(bundle.watchFiles);
|
|
2003
|
+
async function generateOutputs(bundle) {
|
|
2004
|
+
for (const outputOptions of outputs) {
|
|
2005
|
+
await bundle.write(outputOptions);
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
await generateOutputs(bundle);
|
|
2009
|
+
} catch (e) {
|
|
2010
|
+
throw new Error(`Failed to bundle: ${e}`);
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
async buildByEnv(isDev, mode = BuildMode.ALL, includesArg, externalsArg) {
|
|
2014
|
+
try {
|
|
2015
|
+
deletePath("lib");
|
|
2016
|
+
} catch (e) {}
|
|
2017
|
+
try {
|
|
2018
|
+
deletePath("dist");
|
|
2019
|
+
} catch (e) {}
|
|
2020
|
+
fs.mkdirSync("lib");
|
|
2021
|
+
fs.mkdirSync("dist");
|
|
2022
|
+
if ([ BuildMode.ALL, BuildMode.BUILD ].includes(mode)) {
|
|
2023
|
+
await this.build(isDev, Modes.ESM);
|
|
2024
|
+
await this.build(isDev, Modes.CJS);
|
|
2025
|
+
this.patchFiles("lib");
|
|
2026
|
+
}
|
|
2027
|
+
if ([ BuildMode.ALL, BuildMode.BUNDLE ].includes(mode)) {
|
|
2028
|
+
await this.bundle(Modes.ESM, isDev, false, "src/index.ts", this.pkgName, externalsArg, includesArg);
|
|
2029
|
+
await this.bundle(Modes.CJS, isDev, false, "src/index.ts", this.pkgName, externalsArg, includesArg);
|
|
2030
|
+
this.patchFiles("dist");
|
|
2031
|
+
}
|
|
2032
|
+
this.copyAssets(Modes.CJS);
|
|
2033
|
+
this.copyAssets(Modes.ESM);
|
|
2034
|
+
}
|
|
2035
|
+
async buildDev(mode = BuildMode.ALL, includesArg, externalsArg) {
|
|
2036
|
+
return this.buildByEnv(true, mode, includesArg, externalsArg);
|
|
2037
|
+
}
|
|
2038
|
+
async buildProd(mode = BuildMode.ALL, includesArg, externalsArg) {
|
|
2039
|
+
return this.buildByEnv(false, mode, includesArg, externalsArg);
|
|
2040
|
+
}
|
|
2041
|
+
async buildDocs() {
|
|
2042
|
+
await runCommand(`npm install better-docs taffydb`).promise;
|
|
2043
|
+
await runCommand(`npx markdown-include ./workdocs/readme-md.json`).promise;
|
|
2044
|
+
await runCommand(`npx jsdoc -c ./workdocs/jsdocs.json -t ./node_modules/better-docs`).promise;
|
|
2045
|
+
await runCommand(`npm remove better-docs taffydb`).promise;
|
|
2046
|
+
[ {
|
|
2047
|
+
src: "workdocs/assets",
|
|
2048
|
+
dest: "./docs/workdocs/assets"
|
|
2049
|
+
}, {
|
|
2050
|
+
src: "workdocs/reports/coverage",
|
|
2051
|
+
dest: "./docs/workdocs/reports/coverage"
|
|
2052
|
+
}, {
|
|
2053
|
+
src: "workdocs/reports/html",
|
|
2054
|
+
dest: "./docs/workdocs/reports/html"
|
|
2055
|
+
}, {
|
|
2056
|
+
src: "workdocs/resources",
|
|
2057
|
+
dest: "./docs/workdocs/resources"
|
|
2058
|
+
}, {
|
|
2059
|
+
src: "LICENSE.md",
|
|
2060
|
+
dest: "./docs/LICENSE.md"
|
|
2061
|
+
} ].forEach(f => {
|
|
2062
|
+
const {src: src, dest: dest} = f;
|
|
2063
|
+
copyFile(src, dest);
|
|
2064
|
+
});
|
|
2065
|
+
try {
|
|
2066
|
+
const sizeKb = await getFileSizeZipped(path.resolve(path.join(process.cwd(), "dist")));
|
|
2067
|
+
this.replacements[PACKAGE_SIZE_STRING] = `${sizeKb} KB`;
|
|
2068
|
+
} catch {
|
|
2069
|
+
this.replacements[PACKAGE_SIZE_STRING] = "unknown";
|
|
2070
|
+
}
|
|
2071
|
+
try {
|
|
2072
|
+
patchFile("./README.md", this.replacements);
|
|
2073
|
+
} catch (e) {
|
|
2074
|
+
const log = this.log.for(this.buildDocs);
|
|
2075
|
+
log.verbose(`Failed to patch README.md: ${e}`);
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
async run(answers) {
|
|
2079
|
+
const {dev: dev, prod: prod, docs: docs, buildMode: buildMode, includes: includes, externals: externals} = answers;
|
|
2080
|
+
if (dev) {
|
|
2081
|
+
return await this.buildDev(buildMode, includes, externals);
|
|
2082
|
+
}
|
|
2083
|
+
if (prod) {
|
|
2084
|
+
return await this.buildProd(buildMode, includes, externals);
|
|
2085
|
+
}
|
|
2086
|
+
if (docs) {
|
|
2087
|
+
return await this.buildDocs();
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
const options = {
|
|
2093
|
+
ci: {
|
|
2094
|
+
type: "boolean",
|
|
2095
|
+
default: true
|
|
2096
|
+
},
|
|
2097
|
+
message: {
|
|
2098
|
+
type: "string",
|
|
2099
|
+
short: "m"
|
|
2100
|
+
},
|
|
2101
|
+
tag: {
|
|
2102
|
+
type: "string",
|
|
2103
|
+
short: "t",
|
|
2104
|
+
default: undefined
|
|
2105
|
+
}
|
|
2106
|
+
};
|
|
2107
|
+
|
|
2108
|
+
class ReleaseScript extends Command {
|
|
2109
|
+
constructor() {
|
|
2110
|
+
super("ReleaseScript", options);
|
|
2111
|
+
}
|
|
2112
|
+
async prepareVersion(tag) {
|
|
2113
|
+
const log = this.log.for(this.prepareVersion);
|
|
2114
|
+
tag = this.testVersion(tag || "");
|
|
2115
|
+
if (!tag) {
|
|
2116
|
+
log.verbose("No release message provided. Prompting for one:");
|
|
2117
|
+
log.info(`Listing latest git tags:`);
|
|
2118
|
+
await runCommand("git tag --sort=-taggerdate | head -n 5").promise;
|
|
2119
|
+
return await UserInput.insistForText("tag", "Enter the new tag number (accepts v*.*.*[-...])", val => !!val.toString().match(/^v[0-9]+\.[0-9]+.[0-9]+(-[0-9a-zA-Z-]+)?$/));
|
|
2120
|
+
}
|
|
2121
|
+
return tag;
|
|
2122
|
+
}
|
|
2123
|
+
testVersion(version) {
|
|
2124
|
+
const log = this.log.for(this.testVersion);
|
|
2125
|
+
version = version.trim().toLowerCase();
|
|
2126
|
+
switch (version) {
|
|
2127
|
+
case SemVersion.PATCH:
|
|
2128
|
+
case SemVersion.MINOR:
|
|
2129
|
+
case SemVersion.MAJOR:
|
|
2130
|
+
log.verbose(`Using provided SemVer update: ${version}`, 1);
|
|
2131
|
+
return version;
|
|
2132
|
+
|
|
2133
|
+
default:
|
|
2134
|
+
log.verbose(`Testing provided version for SemVer compatibility: ${version}`, 1);
|
|
2135
|
+
if (!new RegExp(SemVersionRegex).test(version)) {
|
|
2136
|
+
log.debug(`Invalid version number: ${version}`);
|
|
2137
|
+
return undefined;
|
|
2138
|
+
}
|
|
2139
|
+
log.verbose(`version approved: ${version}`, 1);
|
|
2140
|
+
return version;
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
async prepareMessage(message) {
|
|
2144
|
+
const log = this.log.for(this.prepareMessage);
|
|
2145
|
+
if (!message) {
|
|
2146
|
+
log.verbose("No release message provided. Prompting for one");
|
|
2147
|
+
return await UserInput.insistForText("message", "What should be the release message/ticket?", val => !!val && val.toString().length > 5);
|
|
2148
|
+
}
|
|
2149
|
+
return message;
|
|
2150
|
+
}
|
|
2151
|
+
async run(args) {
|
|
2152
|
+
let result;
|
|
2153
|
+
const {ci: ci} = args;
|
|
2154
|
+
let {tag: tag, message: message} = args;
|
|
2155
|
+
tag = await this.prepareVersion(tag);
|
|
2156
|
+
message = await this.prepareMessage(message);
|
|
2157
|
+
result = await runCommand(`npm run prepare-release -- ${tag} ${message}`, {
|
|
2158
|
+
cwd: process.cwd()
|
|
2159
|
+
}).promise;
|
|
2160
|
+
result = await runCommand("git status --porcelain").promise;
|
|
2161
|
+
await result;
|
|
2162
|
+
if (result.logs.length && await UserInput.askConfirmation("git-changes", "Do you want to push the changes to the remote repository?", true)) {
|
|
2163
|
+
await runCommand("git add .").promise;
|
|
2164
|
+
await runCommand(`git commit -m "${tag} - ${message} - after release preparation${ci ? "" : NoCIFLag}"`).promise;
|
|
2165
|
+
}
|
|
2166
|
+
await runCommand(`npm version "${tag}" -m "${message}${ci ? "" : NoCIFLag}"`).promise;
|
|
2167
|
+
await runCommand("git push --follow-tags").promise;
|
|
2168
|
+
if (!ci) {
|
|
2169
|
+
await runCommand("NPM_TOKEN=$(cat .npmtoken) npm publish --access public").promise;
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
class RegexpOutputWriter extends StandardOutputWriter {
|
|
2175
|
+
constructor(cmd, lock, regexp, flags = "g") {
|
|
2176
|
+
super(cmd, lock);
|
|
2177
|
+
try {
|
|
2178
|
+
this.regexp = typeof regexp === "string" ? new RegExp(regexp, flags) : regexp;
|
|
2179
|
+
} catch (e) {
|
|
2180
|
+
throw new Error(`Invalid regular expression: ${e}`);
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
test(data) {
|
|
2184
|
+
this.regexp.lastIndex = 0;
|
|
2185
|
+
let match;
|
|
2186
|
+
try {
|
|
2187
|
+
match = this.regexp.exec(data);
|
|
2188
|
+
} catch (e) {
|
|
2189
|
+
return console.debug(`Failed to parse chunk: ${data}\nError: ${e} `);
|
|
2190
|
+
}
|
|
2191
|
+
return match;
|
|
2192
|
+
}
|
|
2193
|
+
testAndResolve(data) {
|
|
2194
|
+
const match = this.test(data);
|
|
2195
|
+
if (match) this.resolve(match[0]);
|
|
2196
|
+
}
|
|
2197
|
+
testAndReject(data) {
|
|
2198
|
+
const match = this.test(data);
|
|
2199
|
+
if (match) this.reject(match[0]);
|
|
2200
|
+
}
|
|
2201
|
+
data(chunk) {
|
|
2202
|
+
super.data(chunk);
|
|
2203
|
+
this.testAndResolve(String(chunk));
|
|
2204
|
+
}
|
|
2205
|
+
error(chunk) {
|
|
2206
|
+
super.error(chunk);
|
|
2207
|
+
this.testAndReject(String(chunk));
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
const VERSION = "0.11.3";
|
|
2212
|
+
|
|
2213
|
+
const PACKAGE_NAME = "@decaf-ts/utils";
|
|
2214
|
+
|
|
2215
|
+
export { AbortCode, BuildScripts, Command, DefaultCommandOptions, DefaultCommandValues, Encoding, HttpClient, NoCIFLag, PACKAGE_NAME, RegexpOutputWriter, ReleaseScript, SemVersion, SemVersionRegex, SetupScriptKey, StandardOutputWriter, Tokens, UserInput, VERSION, chainAbortController, copyFile, deletePath, getAllFiles, getDependencies, getFileSizeZipped, getPackage, getPackageDependencies, getPackageVersion, getSlogan, installDependencies, installIfNotAvailable, listFolder, listNodeModulesPackages, lockify, normalizeImport, packageToGlobal, parseList, patchFile, printBanner, pushToGit, readFile, renameFile, runCommand, setPackageAttribute, spawnCommand, updateDependencies, writeFile };
|
|
2216
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbnB1dC9pbnB1dC50cyIsIi4uL3NyYy9jbGkvY29uc3RhbnRzLnRzIiwiLi4vc3JjL3V0aWxzL2NvbnN0YW50cy50cyIsIi4uL3NyYy93cml0ZXJzL1N0YW5kYXJkT3V0cHV0V3JpdGVyLnRzIiwiLi4vc3JjL3V0aWxzL3V0aWxzLnRzIiwiLi4vc3JjL3V0aWxzL2ZzLnRzIiwiLi4vc3JjL2Fzc2V0cy9zbG9nYW5zLnRzIiwiLi4vc3JjL291dHB1dC9jb21tb24udHMiLCIuLi9zcmMvY2xpL2NvbW1hbmQudHMiLCIuLi9zcmMvdXRpbHMvaHR0cC50cyIsIi4uL3NyYy9jbGkvY29tbWFuZHMvYnVpbGQtc2NyaXB0cy50cyIsIi4uL3NyYy9jbGkvY29tbWFuZHMvdGFnLXJlbGVhc2UudHMiLCIuLi9zcmMvd3JpdGVycy9SZWdleHBPdXRwdXRXcml0ZXIudHMiLCIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQW5zd2VycyxcbiAgQ2hvaWNlLFxuICBGYWxzeSxcbiAgSW5pdGlhbFJldHVyblZhbHVlLFxuICBQcmV2Q2FsbGVyLFxuICBQcm9tcHRPYmplY3QsXG4gIFByb21wdFR5cGUsXG4gIFZhbHVlT3JGdW5jLFxufSBmcm9tIFwicHJvbXB0c1wiO1xuaW1wb3J0IHByb21wdHMgZnJvbSBcInByb21wdHNcIjtcbmltcG9ydCB7IHBhcnNlQXJncywgUGFyc2VBcmdzQ29uZmlnIH0gZnJvbSBcInV0aWxcIjtcbmltcG9ydCB7IFdyaXRhYmxlLCBSZWFkYWJsZSB9IGZyb20gXCJzdHJlYW1cIjtcbmltcG9ydCB7IFBhcnNlQXJnc09wdGlvbnNDb25maWcsIFBhcnNlQXJnc1Jlc3VsdCB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlcHJlc2VudHMgYSB1c2VyIGlucHV0IHByb21wdCB3aXRoIHZhcmlvdXMgY29uZmlndXJhdGlvbiBvcHRpb25zLlxuICogQHN1bW1hcnkgVGhpcyBjbGFzcyBwcm92aWRlcyBhIGZsZXhpYmxlIGludGVyZmFjZSBmb3IgY3JlYXRpbmcgYW5kIG1hbmFnaW5nIHVzZXIgaW5wdXQgcHJvbXB0cy5cbiAqIEl0IGltcGxlbWVudHMgdGhlIFByb21wdE9iamVjdCBpbnRlcmZhY2UgZnJvbSB0aGUgJ3Byb21wdHMnIGxpYnJhcnkgYW5kIG9mZmVycyBtZXRob2RzIHRvIHNldFxuICogdmFyaW91cyBwcm9wZXJ0aWVzIG9mIHRoZSBwcm9tcHQuIFRoZSBjbGFzcyBhbHNvIGluY2x1ZGVzIHN0YXRpYyBtZXRob2RzIGZvciBjb21tb24gaW5wdXQgc2NlbmFyaW9zXG4gKiBhbmQgYXJndW1lbnQgcGFyc2luZy5cbiAqXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSBwcm9tcHQgbmFtZSwgZXh0ZW5kaW5nIHN0cmluZy5cbiAqXG4gKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gKlxuICogQGNsYXNzXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgVXNlcklucHV0IH0gZnJvbSAnQGRlY2FmLXRzL3V0aWxzJztcbiAqXG4gKiAvLyBDcmVhdGUgYSBzaW1wbGUgdGV4dCBpbnB1dFxuICogY29uc3QgbmFtZUlucHV0ID0gbmV3IFVzZXJJbnB1dCgnbmFtZScpXG4gKiAgIC5zZXRNZXNzYWdlKCdXaGF0IGlzIHlvdXIgbmFtZT8nKVxuICogICAuc2V0SW5pdGlhbCgnVXNlcicpO1xuICpcbiAqIC8vIENyZWF0ZSBhIG51bWJlciBpbnB1dCB3aXRoIHZhbGlkYXRpb25cbiAqIGNvbnN0IGFnZUlucHV0ID0gbmV3IFVzZXJJbnB1dCgnYWdlJylcbiAqICAgLnNldFR5cGUoJ251bWJlcicpXG4gKiAgIC5zZXRNZXNzYWdlKCdIb3cgb2xkIGFyZSB5b3U/JylcbiAqICAgLnNldE1pbigwKVxuICogICAuc2V0TWF4KDEyMCk7XG4gKlxuICogLy8gQXNrIGZvciBpbnB1dCBhbmQgcHJvY2VzcyB0aGUgcmVzdWx0c1xuICogYXN5bmMgZnVuY3Rpb24gZ2V0VXNlckluZm8oKSB7XG4gKiAgIGNvbnN0IGFuc3dlcnMgPSBhd2FpdCBVc2VySW5wdXQuYXNrKFtuYW1lSW5wdXQsIGFnZUlucHV0XSk7XG4gKiAgIGNvbnNvbGUubG9nKGBIZWxsbyAke2Fuc3dlcnMubmFtZX0sIHlvdSBhcmUgJHthbnN3ZXJzLmFnZX0geWVhcnMgb2xkLmApO1xuICogfVxuICpcbiAqIGdldFVzZXJJbmZvKCk7XG4gKiBgYGBcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICogICBwYXJ0aWNpcGFudCBVc2VySW5wdXRcbiAqICAgcGFydGljaXBhbnQgUHJvbXB0TGlicmFyeVxuICpcbiAqICAgQ2xpZW50LT4+VXNlcklucHV0OiBuZXcgVXNlcklucHV0KG5hbWUpXG4gKiAgIENsaWVudC0+PlVzZXJJbnB1dDogc2V0TWVzc2FnZShtZXNzYWdlKVxuICogICBDbGllbnQtPj5Vc2VySW5wdXQ6IHNldFR5cGUodHlwZSlcbiAqICAgQ2xpZW50LT4+VXNlcklucHV0OiBzZXRJbml0aWFsKGluaXRpYWwpXG4gKiAgIENsaWVudC0+PlVzZXJJbnB1dDogT3RoZXIgY29uZmlndXJhdGlvbiBtZXRob2RzXG4gKlxuICogICBDbGllbnQtPj5Vc2VySW5wdXQ6IGFzaygpXG4gKiAgIFVzZXJJbnB1dC0+PlByb21wdExpYnJhcnk6IHByb21wdHMocXVlc3Rpb24pXG4gKiAgIFByb21wdExpYnJhcnktPj5DbGllbnQ6IERpc3BsYXkgcHJvbXB0XG4gKiAgIENsaWVudC0+PlByb21wdExpYnJhcnk6IFVzZXIgcHJvdmlkZXMgaW5wdXRcbiAqICAgUHJvbXB0TGlicmFyeS0+PlVzZXJJbnB1dDogUmV0dXJuIGFuc3dlcnNcbiAqICAgVXNlcklucHV0LT4+Q2xpZW50OiBSZXR1cm4gcHJvY2Vzc2VkIGFuc3dlcnNcbiAqL1xuZXhwb3J0IGNsYXNzIFVzZXJJbnB1dDxSIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nPiBpbXBsZW1lbnRzIFByb21wdE9iamVjdDxSPiB7XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IGxvZ2dlciA9IExvZ2dpbmcuZm9yKFVzZXJJbnB1dCk7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHR5cGUgb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyB0aGUgaW5wdXQgbWV0aG9kIChlLmcuLCB0ZXh0LCBudW1iZXIsIGNvbmZpcm0pLlxuICAgKi9cbiAgdHlwZTogUHJvbXB0VHlwZSB8IEZhbHN5IHwgUHJldkNhbGxlcjxSLCBQcm9tcHRUeXBlIHwgRmFsc3k+ID0gXCJ0ZXh0XCI7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbmFtZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBVc2VkIGFzIHRoZSBrZXkgaW4gdGhlIHJldHVybmVkIGFuc3dlcnMgb2JqZWN0LlxuICAgKi9cbiAgbmFtZTogVmFsdWVPckZ1bmM8Uj47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbWVzc2FnZSBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqIEBzdW1tYXJ5IFRoZSBxdWVzdGlvbiBvciBpbnN0cnVjdGlvbiBwcmVzZW50ZWQgdG8gdGhlIHVzZXIuXG4gICAqL1xuICBtZXNzYWdlPzogVmFsdWVPckZ1bmM8c3RyaW5nPiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBpbml0aWFsIHZhbHVlIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IFRoZSBkZWZhdWx0IHZhbHVlIHByZXNlbnRlZCB0byB0aGUgdXNlci5cbiAgICovXG4gIGluaXRpYWw/OlxuICAgIHwgSW5pdGlhbFJldHVyblZhbHVlXG4gICAgfCBQcmV2Q2FsbGVyPFIsIEluaXRpYWxSZXR1cm5WYWx1ZSB8IFByb21pc2U8SW5pdGlhbFJldHVyblZhbHVlPj5cbiAgICB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBzdHlsZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBEZXRlcm1pbmVzIHRoZSB2aXN1YWwgc3R5bGUgb2YgdGhlIHByb21wdC5cbiAgICovXG4gIHN0eWxlPzogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgZm9ybWF0IGZ1bmN0aW9uIGZvciB0aGUgaW5wdXQuXG4gICAqIEBzdW1tYXJ5IEEgZnVuY3Rpb24gdG8gZm9ybWF0IHRoZSB1c2VyJ3MgaW5wdXQgYmVmb3JlIGl0J3MgcmV0dXJuZWQuXG4gICAqL1xuICBmb3JtYXQ/OiBQcmV2Q2FsbGVyPFIsIHZvaWQ+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHZhbGlkYXRpb24gZnVuY3Rpb24gZm9yIHRoZSBpbnB1dC5cbiAgICogQHN1bW1hcnkgQSBmdW5jdGlvbiB0byB2YWxpZGF0ZSB0aGUgdXNlcidzIGlucHV0LlxuICAgKi9cbiAgdmFsaWRhdGU/OlxuICAgIHwgUHJldkNhbGxlcjxSLCBib29sZWFuIHwgc3RyaW5nIHwgUHJvbWlzZTxib29sZWFuIHwgc3RyaW5nPj5cbiAgICB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBvblN0YXRlIGNhbGxiYWNrIGZ1bmN0aW9uLlxuICAgKiBAc3VtbWFyeSBBIGZ1bmN0aW9uIGNhbGxlZCB3aGVuIHRoZSBzdGF0ZSBvZiB0aGUgcHJvbXB0IGNoYW5nZXMuXG4gICAqL1xuICBvblN0YXRlPzogUHJldkNhbGxlcjxSLCB2b2lkPiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBtaW5pbXVtIHZhbHVlIGZvciBudW1iZXIgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgbG93ZXN0IG51bWJlciB0aGUgdXNlciBjYW4gaW5wdXQuXG4gICAqL1xuICBtaW4/OiBudW1iZXIgfCBQcmV2Q2FsbGVyPFIsIG51bWJlciB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBtYXhpbXVtIHZhbHVlIGZvciBudW1iZXIgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgaGlnaGVzdCBudW1iZXIgdGhlIHVzZXIgY2FuIGlucHV0LlxuICAgKi9cbiAgbWF4PzogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGFsbG93IGZsb2F0IHZhbHVlcyBmb3IgbnVtYmVyIGlucHV0cy5cbiAgICogQHN1bW1hcnkgSWYgdHJ1ZSwgYWxsb3dzIGRlY2ltYWwgbnVtYmVycy5cbiAgICovXG4gIGZsb2F0PzogYm9vbGVhbiB8IFByZXZDYWxsZXI8UiwgYm9vbGVhbiB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gcm91bmQgdG8gZm9yIGZsb2F0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyB0aGUgcHJlY2lzaW9uIG9mIGZsb2F0IGlucHV0cy5cbiAgICovXG4gIHJvdW5kPzogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbnN0cnVjdGlvbnMgZm9yIHRoZSB1c2VyLlxuICAgKiBAc3VtbWFyeSBBZGRpdGlvbmFsIGd1aWRhbmNlIHByb3ZpZGVkIHRvIHRoZSB1c2VyLlxuICAgKi9cbiAgaW5zdHJ1Y3Rpb25zPzogc3RyaW5nIHwgYm9vbGVhbiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBpbmNyZW1lbnQgdmFsdWUgZm9yIG51bWJlciBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBzdGVwIHNpemUgd2hlbiBpbmNyZWFzaW5nIG9yIGRlY3JlYXNpbmcgdGhlIG51bWJlci5cbiAgICovXG4gIGluY3JlbWVudD86IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHNlcGFyYXRvciBmb3IgbGlzdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBjaGFyYWN0ZXIgdXNlZCB0byBzZXBhcmF0ZSBsaXN0IGl0ZW1zLlxuICAgKi9cbiAgc2VwYXJhdG9yPzogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgYWN0aXZlIG9wdGlvbiBzdHlsZSBmb3Igc2VsZWN0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgVGhlIHN0eWxlIGFwcGxpZWQgdG8gdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBvcHRpb24uXG4gICAqL1xuICBhY3RpdmU/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBpbmFjdGl2ZSBvcHRpb24gc3R5bGUgZm9yIHNlbGVjdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBzdHlsZSBhcHBsaWVkIHRvIG5vbi1zZWxlY3RlZCBvcHRpb25zLlxuICAgKi9cbiAgaW5hY3RpdmU/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBhdmFpbGFibGUgY2hvaWNlcyBmb3Igc2VsZWN0LCBtdWx0aXNlbGVjdCwgb3IgYXV0b2NvbXBsZXRlIGlucHV0cy5cbiAgICogQHN1bW1hcnkgQW4gYXJyYXkgb2Ygb3B0aW9ucyB0aGF0IHRoZSB1c2VyIGNhbiBzZWxlY3QgZnJvbSBpbiBjaG9pY2UtYmFzZWQgcHJvbXB0cy5cbiAgICovXG4gIGNob2ljZXM/OiBDaG9pY2VbXSB8IFByZXZDYWxsZXI8UiwgQ2hvaWNlW10gfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgaGludCB0ZXh0IGZvciB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBBZGRpdGlvbmFsIGluZm9ybWF0aW9uIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICovXG4gIGhpbnQ/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSB3YXJuaW5nIHRleHQgZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IEEgd2FybmluZyBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICovXG4gIHdhcm4/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICBzdWdnZXN0PzogKChpbnB1dDogYW55LCBjaG9pY2VzOiBDaG9pY2VbXSkgPT4gUHJvbWlzZTxhbnk+KSB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBsaW1pdCBmb3IgbGlzdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBtYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0aGF0IGNhbiBiZSBzZWxlY3RlZC5cbiAgICovXG4gIGxpbWl0PzogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbWFzayBmb3IgcGFzc3dvcmQgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgY2hhcmFjdGVyIHVzZWQgdG8gaGlkZSB0aGUgdXNlcidzIGlucHV0LlxuICAgKi9cbiAgbWFzaz86IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHN0ZG91dCBzdHJlYW0gZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IFRoZSBvdXRwdXQgc3RyZWFtIHVzZWQgYnkgdGhlIHByb21wdC5cbiAgICovXG4gIHN0ZG91dD86IFdyaXRhYmxlIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHN0ZGluIHN0cmVhbSBmb3IgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgVGhlIGlucHV0IHN0cmVhbSB1c2VkIGJ5IHRoZSBwcm9tcHQuXG4gICAqL1xuICBzdGRpbj86IFJlYWRhYmxlIHwgdW5kZWZpbmVkO1xuXG4gIGNvbnN0cnVjdG9yKG5hbWU6IFZhbHVlT3JGdW5jPFI+KSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgdHlwZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBpbnB1dCBtZXRob2QgZm9yIHRoZSBwcm9tcHQuXG4gICAqXG4gICAqIEBwYXJhbSB0eXBlIC0gVGhlIHR5cGUgb2YgdGhlIHByb21wdC5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldFR5cGUodHlwZTogUHJvbXB0VHlwZSB8IEZhbHN5IHwgUHJldkNhbGxlcjxSLCBQcm9tcHRUeXBlIHwgRmFsc3k+KTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIHR5cGUgdG86ICR7dHlwZX1gKTtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBtZXNzYWdlIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIHF1ZXN0aW9uIG9yIGluc3RydWN0aW9uIHByZXNlbnRlZCB0byB0aGUgdXNlci5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIG1lc3NhZ2UgdG8gYmUgZGlzcGxheWVkLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0TWVzc2FnZSh2YWx1ZTogVmFsdWVPckZ1bmM8c3RyaW5nPiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBtZXNzYWdlIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMubWVzc2FnZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBpbml0aWFsIHZhbHVlIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGRlZmF1bHQgdmFsdWUgcHJlc2VudGVkIHRvIHRoZSB1c2VyLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgaW5pdGlhbCB2YWx1ZS5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldEluaXRpYWwoXG4gICAgdmFsdWU6XG4gICAgICB8IEluaXRpYWxSZXR1cm5WYWx1ZVxuICAgICAgfCBQcmV2Q2FsbGVyPFIsIEluaXRpYWxSZXR1cm5WYWx1ZSB8IFByb21pc2U8SW5pdGlhbFJldHVyblZhbHVlPj5cbiAgICAgIHwgdW5kZWZpbmVkXG4gICk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBpbml0aWFsIHZhbHVlIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuaW5pdGlhbCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBzdHlsZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSB2aXN1YWwgc3R5bGUgb2YgdGhlIHByb21wdC5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHN0eWxlIHRvIGJlIGFwcGxpZWQuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRTdHlsZSh2YWx1ZTogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgc3R5bGUgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5zdHlsZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBmb3JtYXQgZnVuY3Rpb24gb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhIGZ1bmN0aW9uIHRvIGZvcm1hdCB0aGUgdXNlcidzIGlucHV0IGJlZm9yZSBpdCdzIHJldHVybmVkLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgZm9ybWF0IGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0Rm9ybWF0KHZhbHVlOiBQcmV2Q2FsbGVyPFIsIHZvaWQ+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGZvcm1hdCBmdW5jdGlvbmApO1xuICAgIHRoaXMuZm9ybWF0ID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIHZhbGlkYXRpb24gZnVuY3Rpb24gb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhIGZ1bmN0aW9uIHRvIHZhbGlkYXRlIHRoZSB1c2VyJ3MgaW5wdXQuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWxpZGF0aW9uIGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0VmFsaWRhdGUoXG4gICAgdmFsdWU6XG4gICAgICB8IFByZXZDYWxsZXI8UiwgYm9vbGVhbiB8IHN0cmluZyB8IFByb21pc2U8Ym9vbGVhbiB8IHN0cmluZz4+XG4gICAgICB8IHVuZGVmaW5lZFxuICApOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgdmFsaWRhdGUgZnVuY3Rpb25gKTtcbiAgICB0aGlzLnZhbGlkYXRlID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIG9uU3RhdGUgY2FsbGJhY2sgb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBzdGF0ZSBvZiB0aGUgcHJvbXB0IGNoYW5nZXMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBvblN0YXRlIGNhbGxiYWNrIGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0T25TdGF0ZSh2YWx1ZTogUHJldkNhbGxlcjxSLCB2b2lkPiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBvblN0YXRlIGNhbGxiYWNrYCk7XG4gICAgdGhpcy5vblN0YXRlID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIG1pbmltdW0gdmFsdWUgZm9yIG51bWJlciBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGxvd2VzdCBudW1iZXIgdGhlIHVzZXIgY2FuIGlucHV0LlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgbWluaW11bSB2YWx1ZS5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldE1pbih2YWx1ZTogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgbWluIHZhbHVlIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMubWluID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIG1heGltdW0gdmFsdWUgZm9yIG51bWJlciBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGhpZ2hlc3QgbnVtYmVyIHRoZSB1c2VyIGNhbiBpbnB1dC5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIG1heGltdW0gdmFsdWUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRNYXgodmFsdWU6IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIG1heCB2YWx1ZSB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLm1heCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHdoZXRoZXIgdG8gYWxsb3cgZmxvYXQgdmFsdWVzIGZvciBudW1iZXIgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHdoZXRoZXIgZGVjaW1hbCBudW1iZXJzIGFyZSBhbGxvd2VkLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBXaGV0aGVyIHRvIGFsbG93IGZsb2F0IHZhbHVlcy5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldEZsb2F0KHZhbHVlOiBib29sZWFuIHwgUHJldkNhbGxlcjxSLCBib29sZWFuIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGZsb2F0IHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuZmxvYXQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHJvdW5kIHRvIGZvciBmbG9hdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIHByZWNpc2lvbiBvZiBmbG9hdCBpbnB1dHMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRSb3VuZCh2YWx1ZTogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgcm91bmQgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5yb3VuZCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBpbnN0cnVjdGlvbnMgZm9yIHRoZSB1c2VyLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIGFkZGl0aW9uYWwgZ3VpZGFuY2UgcHJvdmlkZWQgdG8gdGhlIHVzZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBpbnN0cnVjdGlvbnMuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRJbnN0cnVjdGlvbnModmFsdWU6IHN0cmluZyB8IGJvb2xlYW4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgaW5zdHJ1Y3Rpb25zIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuaW5zdHJ1Y3Rpb25zID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGluY3JlbWVudCB2YWx1ZSBmb3IgbnVtYmVyIGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgc3RlcCBzaXplIHdoZW4gaW5jcmVhc2luZyBvciBkZWNyZWFzaW5nIHRoZSBudW1iZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBpbmNyZW1lbnQgdmFsdWUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRJbmNyZW1lbnQoXG4gICAgdmFsdWU6IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkXG4gICk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBpbmNyZW1lbnQgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5pbmNyZW1lbnQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgc2VwYXJhdG9yIGZvciBsaXN0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgY2hhcmFjdGVyIHVzZWQgdG8gc2VwYXJhdGUgbGlzdCBpdGVtcy5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHNlcGFyYXRvciBjaGFyYWN0ZXIuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRTZXBhcmF0b3IoXG4gICAgdmFsdWU6IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkXG4gICk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBzZXBhcmF0b3IgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5zZXBhcmF0b3IgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgYWN0aXZlIG9wdGlvbiBzdHlsZSBmb3Igc2VsZWN0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgc3R5bGUgYXBwbGllZCB0byB0aGUgY3VycmVudGx5IHNlbGVjdGVkIG9wdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGFjdGl2ZSBvcHRpb24gc3R5bGUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRBY3RpdmUodmFsdWU6IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGFjdGl2ZSBzdHlsZSB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLmFjdGl2ZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBpbmFjdGl2ZSBvcHRpb24gc3R5bGUgZm9yIHNlbGVjdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIHN0eWxlIGFwcGxpZWQgdG8gbm9uLXNlbGVjdGVkIG9wdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBpbmFjdGl2ZSBvcHRpb24gc3R5bGUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRJbmFjdGl2ZSh2YWx1ZTogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgaW5hY3RpdmUgc3R5bGUgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5pbmFjdGl2ZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBjaG9pY2VzIGZvciBzZWxlY3QsIG11bHRpc2VsZWN0LCBvciBhdXRvY29tcGxldGUgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBhdmFpbGFibGUgb3B0aW9ucyB0aGF0IHRoZSB1c2VyIGNhbiBzZWxlY3QgZnJvbSBpbiBjaG9pY2UtYmFzZWQgcHJvbXB0cy5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGFycmF5IG9mIGNob2ljZXMgb3IgYSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgdGhlIGNob2ljZXMuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRDaG9pY2VzKFxuICAgIHZhbHVlOiBDaG9pY2VbXSB8IFByZXZDYWxsZXI8UiwgQ2hvaWNlW10gfCBGYWxzeT4gfCB1bmRlZmluZWRcbiAgKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGNob2ljZXM6ICR7SlNPTi5zdHJpbmdpZnkodmFsdWUpfWApO1xuICAgIHRoaXMuY2hvaWNlcyA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBoaW50IHRleHQgZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBoaW50IHRleHQuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRIaW50KHZhbHVlOiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBoaW50IHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuaGludCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSB3YXJuaW5nIHRleHQgZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgYSB3YXJuaW5nIG1lc3NhZ2UgZGlzcGxheWVkIHRvIHRoZSB1c2VyLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgd2FybmluZyB0ZXh0LlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0V2Fybih2YWx1ZTogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgd2FybiB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLndhcm4gPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgc3VnZ2VzdGlvbiBmdW5jdGlvbiBmb3IgYXV0b2NvbXBsZXRlIGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhIGZ1bmN0aW9uIHRoYXQgcHJvdmlkZXMgc3VnZ2VzdGlvbnMgYmFzZWQgb24gdGhlIHVzZXIncyBpbnB1dCBhbmQgYXZhaWxhYmxlIGNob2ljZXMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIEEgZnVuY3Rpb24gdGhhdCB0YWtlcyB0aGUgY3VycmVudCBpbnB1dCBhbmQgYXZhaWxhYmxlIGNob2ljZXMgYW5kIHJldHVybnMgYSBQcm9taXNlIHJlc29sdmluZyB0byBzdWdnZXN0aW9ucy5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldFN1Z2dlc3QoXG4gICAgdmFsdWU6ICgoaW5wdXQ6IGFueSwgY2hvaWNlczogQ2hvaWNlW10pID0+IFByb21pc2U8YW55PikgfCB1bmRlZmluZWRcbiAgKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIHN1Z2dlc3QgZnVuY3Rpb25gKTtcbiAgICB0aGlzLnN1Z2dlc3QgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgbGltaXQgZm9yIGxpc3QgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBtYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0aGF0IGNhbiBiZSBzZWxlY3RlZCBpbiBsaXN0LXR5cGUgcHJvbXB0cy5cbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgcHJvbXB0IG5hbWUsIGV4dGVuZGluZyBzdHJpbmcuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0aGF0IGNhbiBiZSBzZWxlY3RlZCwgb3IgYSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgdGhpcyB2YWx1ZS5cbiAgICogQHJldHVybiBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0TGltaXQodmFsdWU6IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGxpbWl0IHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMubGltaXQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgbWFzayBmb3IgcGFzc3dvcmQgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBjaGFyYWN0ZXIgdXNlZCB0byBoaWRlIHRoZSB1c2VyJ3MgaW5wdXQgaW4gcGFzc3dvcmQtdHlwZSBwcm9tcHRzLlxuICAgKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSBwcm9tcHQgbmFtZSwgZXh0ZW5kaW5nIHN0cmluZy5cbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGNoYXJhY3RlciB1c2VkIHRvIG1hc2sgdGhlIGlucHV0LCBvciBhIGZ1bmN0aW9uIHRvIGRldGVybWluZSB0aGlzIHZhbHVlLlxuICAgKiBAcmV0dXJuIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRNYXNrKHZhbHVlOiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBtYXNrIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMubWFzayA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBzdGRvdXQgc3RyZWFtIGZvciB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBvdXRwdXQgc3RyZWFtIHVzZWQgYnkgdGhlIHByb21wdCBmb3IgZGlzcGxheWluZyBtZXNzYWdlcyBhbmQgcmVzdWx0cy5cbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIFdyaXRhYmxlIHN0cmVhbSB0byBiZSB1c2VkIGFzIHN0ZG91dC5cbiAgICogQHJldHVybiBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0U3Rkb3V0KHZhbHVlOiBXcml0YWJsZSB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBzdGRvdXQgc3RyZWFtYCk7XG4gICAgdGhpcy5zdGRvdXQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIHN0ZGluIHN0cmVhbSBmb3IgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgaW5wdXQgc3RyZWFtIHVzZWQgYnkgdGhlIHByb21wdCBmb3IgcmVjZWl2aW5nIHVzZXIgaW5wdXQuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBSZWFkYWJsZSBzdHJlYW0gdG8gYmUgdXNlZCBhcyBzdGRpbi5cbiAgICogQHJldHVybiBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0U3RkaW4odmFsdWU6IFJlYWRhYmxlIHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgdGhpcy5zdGRpbiA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBc2tzIHRoZSB1c2VyIGZvciBpbnB1dCBiYXNlZCBvbiB0aGUgY3VycmVudCBVc2VySW5wdXQgY29uZmlndXJhdGlvbi5cbiAgICogQHN1bW1hcnkgUHJvbXB0cyB0aGUgdXNlciBhbmQgcmV0dXJucyB0aGVpciByZXNwb25zZSBhcyBhIHNpbmdsZSB2YWx1ZS5cbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgcHJvbXB0IG5hbWUsIGV4dGVuZGluZyBzdHJpbmcuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHVzZXIncyBhbnN3ZXIuXG4gICAqL1xuICBhc3luYyBhc2soKSB7XG4gICAgcmV0dXJuIChhd2FpdCBVc2VySW5wdXQuYXNrKHRoaXMpKVt0aGlzLm5hbWUgYXMga2V5b2YgQW5zd2VyczxSPl07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFza3MgdGhlIHVzZXIgb25lIG9yIG1vcmUgcXVlc3Rpb25zIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBVc2VySW5wdXQgY29uZmlndXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFByb21wdHMgdGhlIHVzZXIgd2l0aCBvbmUgb3IgbW9yZSBxdWVzdGlvbnMgYW5kIHJldHVybnMgdGhlaXIgYW5zd2VycyBhcyBhbiBvYmplY3QuXG4gICAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgdGhlIHByb21wdCBuYW1lLCBleHRlbmRpbmcgc3RyaW5nLlxuICAgKiBAcGFyYW0gcXVlc3Rpb24gLSBBIHNpbmdsZSBVc2VySW5wdXQgaW5zdGFuY2Ugb3IgYW4gYXJyYXkgb2YgVXNlcklucHV0IGluc3RhbmNlcy5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgdXNlcidzIGFuc3dlcnMuXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IFUgYXMgVXNlclxuICAgKiAgIHBhcnRpY2lwYW50IEEgYXMgYXNrIG1ldGhvZFxuICAgKiAgIHBhcnRpY2lwYW50IFAgYXMgcHJvbXB0cyBsaWJyYXJ5XG4gICAqICAgQS0+PlA6IENhbGwgcHJvbXB0cyB3aXRoIHF1ZXN0aW9uKHMpXG4gICAqICAgUC0+PlU6IERpc3BsYXkgcHJvbXB0KHMpXG4gICAqICAgVS0+PlA6IFByb3ZpZGUgaW5wdXRcbiAgICogICBQLT4+QTogUmV0dXJuIGFuc3dlcnNcbiAgICogICBBLT4+QTogUHJvY2VzcyBhbnN3ZXJzXG4gICAqICAgQS0tPj5DYWxsZXI6IFJldHVybiBwcm9jZXNzZWQgYW5zd2Vyc1xuICAgKi9cbiAgc3RhdGljIGFzeW5jIGFzazxSIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nPihcbiAgICBxdWVzdGlvbjogVXNlcklucHV0PFI+IHwgVXNlcklucHV0PFI+W11cbiAgKSB7XG4gICAgY29uc3QgbG9nID0gVXNlcklucHV0LmxvZ2dlci5mb3IodGhpcy5hc2spO1xuICAgIGlmICghQXJyYXkuaXNBcnJheShxdWVzdGlvbikpIHtcbiAgICAgIHF1ZXN0aW9uID0gW3F1ZXN0aW9uXTtcbiAgICB9XG4gICAgbGV0IGFuc3dlcnM6IEFuc3dlcnM8Uj47XG4gICAgdHJ5IHtcbiAgICAgIGxvZy52ZXJib3NlKFxuICAgICAgICBgQXNraW5nIHF1ZXN0aW9uczogJHtxdWVzdGlvbi5tYXAoKHEpID0+IHEubmFtZSkuam9pbihcIiwgXCIpfWBcbiAgICAgICk7XG4gICAgICBhbnN3ZXJzID0gYXdhaXQgcHJvbXB0cyhxdWVzdGlvbik7XG4gICAgICBsb2cudmVyYm9zZShgUmVjZWl2ZWQgYW5zd2VyczogJHtKU09OLnN0cmluZ2lmeShhbnN3ZXJzLCBudWxsLCAyKX1gKTtcbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciB3aGlsZSBnZXR0aW5nIGlucHV0OiAke2Vycm9yfWApO1xuICAgIH1cbiAgICByZXR1cm4gYW5zd2VycztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXNrcyB0aGUgdXNlciBmb3IgYSBudW1iZXIgaW5wdXQuXG4gICAqIEBzdW1tYXJ5IFByb21wdHMgdGhlIHVzZXIgdG8gZW50ZXIgYSBudW1iZXIsIHdpdGggb3B0aW9uYWwgbWluaW11bSwgbWF4aW11bSwgYW5kIGluaXRpYWwgdmFsdWVzLlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIG1pbiAtIFRoZSBtaW5pbXVtIGFsbG93ZWQgdmFsdWUgKG9wdGlvbmFsKS5cbiAgICogQHBhcmFtIG1heCAtIFRoZSBtYXhpbXVtIGFsbG93ZWQgdmFsdWUgKG9wdGlvbmFsKS5cbiAgICogQHBhcmFtIGluaXRpYWwgLSBUaGUgaW5pdGlhbCB2YWx1ZSBwcmVzZW50ZWQgdG8gdGhlIHVzZXIgKG9wdGlvbmFsKS5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgbnVtYmVyIGVudGVyZWQgYnkgdGhlIHVzZXIuXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgYXNrTnVtYmVyKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBxdWVzdGlvbjogc3RyaW5nLFxuICAgIG1pbj86IG51bWJlcixcbiAgICBtYXg/OiBudW1iZXIsXG4gICAgaW5pdGlhbD86IG51bWJlclxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGxvZyA9IFVzZXJJbnB1dC5sb2dnZXIuZm9yKHRoaXMuYXNrTnVtYmVyKTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBBc2tpbmcgbnVtYmVyIGlucHV0OiB1bmRlZmluZWQsIHF1ZXN0aW9uOiAke3F1ZXN0aW9ufSwgbWluOiAke21pbn0sIG1heDogJHttYXh9LCBpbml0aWFsOiAke2luaXRpYWx9YFxuICAgICk7XG4gICAgY29uc3QgdXNlcklucHV0ID0gbmV3IFVzZXJJbnB1dChuYW1lKVxuICAgICAgLnNldE1lc3NhZ2UocXVlc3Rpb24pXG4gICAgICAuc2V0VHlwZShcIm51bWJlclwiKTtcblxuICAgIGlmICh0eXBlb2YgbWluID09PSBcIm51bWJlclwiKSB1c2VySW5wdXQuc2V0TWluKG1pbik7XG5cbiAgICBpZiAodHlwZW9mIG1heCA9PT0gXCJudW1iZXJcIikgdXNlcklucHV0LnNldE1heChtYXgpO1xuXG4gICAgaWYgKHR5cGVvZiBpbml0aWFsID09PSBcIm51bWJlclwiKSB1c2VySW5wdXQuc2V0SW5pdGlhbChpbml0aWFsKTtcblxuICAgIHJldHVybiAoYXdhaXQgdGhpcy5hc2sodXNlcklucHV0KSlbbmFtZV07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFza3MgdGhlIHVzZXIgZm9yIGEgdGV4dCBpbnB1dC5cbiAgICogQHN1bW1hcnkgUHJvbXB0cyB0aGUgdXNlciB0byBlbnRlciB0ZXh0LCB3aXRoIG9wdGlvbmFsIG1hc2tpbmcgYW5kIGluaXRpYWwgdmFsdWUuXG4gICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHByb21wdCwgdXNlZCBhcyB0aGUga2V5IGluIHRoZSByZXR1cm5lZCBhbnN3ZXJzIG9iamVjdC5cbiAgICogQHBhcmFtIHF1ZXN0aW9uIC0gVGhlIG1lc3NhZ2UgZGlzcGxheWVkIHRvIHRoZSB1c2VyLlxuICAgKiBAcGFyYW0gbWFzayAtIFRoZSBjaGFyYWN0ZXIgdXNlZCB0byBtYXNrIHRoZSBpbnB1dCAob3B0aW9uYWwsIGZvciBwYXNzd29yZC1saWtlIGlucHV0cykuXG4gICAqIEBwYXJhbSBpbml0aWFsIC0gVGhlIGluaXRpYWwgdmFsdWUgcHJlc2VudGVkIHRvIHRoZSB1c2VyIChvcHRpb25hbCkuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHRleHQgZW50ZXJlZCBieSB0aGUgdXNlci5cbiAgICovXG4gIHN0YXRpYyBhc3luYyBhc2tUZXh0KFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBxdWVzdGlvbjogc3RyaW5nLFxuICAgIG1hc2s6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbiAgICBpbml0aWFsPzogc3RyaW5nXG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgbG9nID0gVXNlcklucHV0LmxvZ2dlci5mb3IodGhpcy5hc2tUZXh0KTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBBc2tpbmcgdGV4dCBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIG1hc2s6ICR7bWFza30sIGluaXRpYWw6ICR7aW5pdGlhbH1gXG4gICAgKTtcbiAgICBjb25zdCB1c2VySW5wdXQgPSBuZXcgVXNlcklucHV0KG5hbWUpLnNldE1lc3NhZ2UocXVlc3Rpb24pO1xuXG4gICAgaWYgKG1hc2spIHVzZXJJbnB1dC5zZXRNYXNrKG1hc2spO1xuICAgIGlmICh0eXBlb2YgaW5pdGlhbCA9PT0gXCJzdHJpbmdcIikgdXNlcklucHV0LnNldEluaXRpYWwoaW5pdGlhbCk7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLmFzayh1c2VySW5wdXQpKVtuYW1lXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXNrcyB0aGUgdXNlciBmb3IgYSBjb25maXJtYXRpb24gKHllcy9ubykuXG4gICAqIEBzdW1tYXJ5IFByb21wdHMgdGhlIHVzZXIgd2l0aCBhIHllcy9ubyBxdWVzdGlvbiBhbmQgcmV0dXJucyBhIGJvb2xlYW4gcmVzdWx0LlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIGluaXRpYWwgLSBUaGUgaW5pdGlhbCB2YWx1ZSBwcmVzZW50ZWQgdG8gdGhlIHVzZXIgKG9wdGlvbmFsKS5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSB1c2VyJ3MgYW5zd2VyLlxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGFza0NvbmZpcm1hdGlvbihcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgcXVlc3Rpb246IHN0cmluZyxcbiAgICBpbml0aWFsPzogYm9vbGVhblxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBsb2cgPSBVc2VySW5wdXQubG9nZ2VyLmZvcih0aGlzLmFza0NvbmZpcm1hdGlvbik7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgQXNraW5nIGNvbmZpcm1hdGlvbiBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIGluaXRpYWw6ICR7aW5pdGlhbH1gXG4gICAgKTtcbiAgICBjb25zdCB1c2VySW5wdXQgPSBuZXcgVXNlcklucHV0KG5hbWUpXG4gICAgICAuc2V0TWVzc2FnZShxdWVzdGlvbilcbiAgICAgIC5zZXRUeXBlKFwiY29uZmlybVwiKTtcblxuICAgIGlmICh0eXBlb2YgaW5pdGlhbCAhPT0gXCJ1bmRlZmluZWRcIikgdXNlcklucHV0LnNldEluaXRpYWwoaW5pdGlhbCk7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLmFzayh1c2VySW5wdXQpKVtuYW1lXTtcbiAgfVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlcGVhdGVkbHkgYXNrcyBmb3IgaW5wdXQgdW50aWwgYSB2YWxpZCByZXNwb25zZSBpcyBnaXZlbiBvciB0aGUgbGltaXQgaXMgcmVhY2hlZC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaW5zaXN0cyBvbiBnZXR0aW5nIGEgdmFsaWQgaW5wdXQgZnJvbSB0aGUgdXNlciwgYWxsb3dpbmcgZm9yIGEgc3BlY2lmaWVkIG51bWJlciBvZiBhdHRlbXB0cy5cbiAgICpcbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgZXhwZWN0ZWQgcmVzdWx0LlxuICAgKiBAcGFyYW0gaW5wdXQgLSBUaGUgVXNlcklucHV0IGluc3RhbmNlIHRvIHVzZSBmb3IgcHJvbXB0aW5nLlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKHN0cmluZyk6Ym9vbGVhbn0gdGVzdCAtIFZhbGlkYXRvciBmdW5jdGlvbiByZWNlaXZpbmcgdGhlIHVzZXIgaW5wdXQgYW5kIHJldHVybmluZyB3aGV0aGVyIGl0IGlzIHZhbGlkLlxuICAgKiBAcGFyYW0gZGVmYXVsdENvbmZpcm1hdGlvbiAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGUgY29uZmlybWF0aW9uIHByb21wdCAodHJ1ZSBmb3IgeWVzLCBmYWxzZSBmb3Igbm8pLlxuICAgKiBAcGFyYW0gbGltaXQgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgYXR0ZW1wdHMgYWxsb3dlZCAoZGVmYXVsdCBpcyAxKS5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgdmFsaWQgaW5wdXQgb3IgdW5kZWZpbmVkIGlmIHRoZSBsaW1pdCBpcyByZWFjaGVkLlxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXJcbiAgICogICBwYXJ0aWNpcGFudCBJIGFzIGluc2lzdCBtZXRob2RcbiAgICogICBwYXJ0aWNpcGFudCBBIGFzIGFzayBtZXRob2RcbiAgICogICBwYXJ0aWNpcGFudCBUIGFzIHRlc3QgZnVuY3Rpb25cbiAgICogICBwYXJ0aWNpcGFudCBDIGFzIGFza0NvbmZpcm1hdGlvbiBtZXRob2RcbiAgICogICBsb29wIFVudGlsIHZhbGlkIGlucHV0IG9yIGxpbWl0IHJlYWNoZWRcbiAgICogICAgIEktPj5BOiBDYWxsIGFzayB3aXRoIGlucHV0XG4gICAqICAgICBBLT4+VTogUHJvbXB0IHVzZXJcbiAgICogICAgIFUtPj5BOiBQcm92aWRlIGlucHV0XG4gICAqICAgICBBLT4+STogUmV0dXJuIHJlc3VsdFxuICAgKiAgICAgSS0+PlQ6IFRlc3QgcmVzdWx0XG4gICAqICAgICBhbHQgVGVzdCBwYXNzZXNcbiAgICogICAgICAgSS0+PkM6IEFzayBmb3IgY29uZmlybWF0aW9uXG4gICAqICAgICAgIEMtPj5VOiBDb25maXJtIGlucHV0XG4gICAqICAgICAgIFUtPj5DOiBQcm92aWRlIGNvbmZpcm1hdGlvblxuICAgKiAgICAgICBDLT4+STogUmV0dXJuIGNvbmZpcm1hdGlvblxuICAgKiAgICAgICBhbHQgQ29uZmlybWVkXG4gICAqICAgICAgICAgSS0tPj5DYWxsZXI6IFJldHVybiB2YWxpZCByZXN1bHRcbiAgICogICAgICAgZWxzZSBOb3QgY29uZmlybWVkXG4gICAqICAgICAgICAgSS0+Pkk6IENvbnRpbnVlIGxvb3BcbiAgICogICAgICAgZW5kXG4gICAqICAgICBlbHNlIFRlc3QgZmFpbHNcbiAgICogICAgICAgSS0+Pkk6IENvbnRpbnVlIGxvb3BcbiAgICogICAgIGVuZFxuICAgKiAgIGVuZFxuICAgKiAgIEktLT4+Q2FsbGVyOiBSZXR1cm4gdW5kZWZpbmVkIGlmIGxpbWl0IHJlYWNoZWRcbiAgICovXG4gIHN0YXRpYyBhc3luYyBpbnNpc3Q8Uj4oXG4gICAgaW5wdXQ6IFVzZXJJbnB1dCxcbiAgICB0ZXN0OiAocmVzOiBzdHJpbmcgfCBudW1iZXIpID0+IGJvb2xlYW4sXG4gICAgZGVmYXVsdENvbmZpcm1hdGlvbjogYm9vbGVhbixcbiAgICBsaW1pdCA9IDFcbiAgKTogUHJvbWlzZTxSIHwgdW5kZWZpbmVkPiB7XG4gICAgY29uc3QgbG9nID0gVXNlcklucHV0LmxvZ2dlci5mb3IodGhpcy5pbnNpc3QpO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYEluc2lzdGluZyBvbiBpbnB1dDogJHtpbnB1dC5uYW1lfSwgdGVzdDogJHt0ZXN0LnRvU3RyaW5nKCl9LCBkZWZhdWx0Q29uZmlybWF0aW9uOiAke2RlZmF1bHRDb25maXJtYXRpb259LCBsaW1pdDogJHtsaW1pdH1gXG4gICAgKTtcbiAgICBsZXQgcmVzdWx0OiBzdHJpbmcgfCBudW1iZXIgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgbGV0IGNvdW50ID0gMDtcbiAgICBsZXQgY29uZmlybWF0aW9uOiBib29sZWFuO1xuICAgIHRyeSB7XG4gICAgICBkbyB7XG4gICAgICAgIHJlc3VsdCA9IChhd2FpdCBVc2VySW5wdXQuYXNrKGlucHV0KSlbXG4gICAgICAgICAgaW5wdXQubmFtZSBhcyBrZXlvZiBBbnN3ZXJzPHN0cmluZz5cbiAgICAgICAgXSBhcyBzdHJpbmc7XG4gICAgICAgIGlmICghdGVzdChyZXN1bHQpKSB7XG4gICAgICAgICAgcmVzdWx0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbmZpcm1hdGlvbiA9IGF3YWl0IFVzZXJJbnB1dC5hc2tDb25maXJtYXRpb24oXG4gICAgICAgICAgYCR7aW5wdXQubmFtZX0tY29uZmlybWAsXG4gICAgICAgICAgYElzIHRoZSAke2lucHV0LnR5cGV9IGNvcnJlY3Q/YCxcbiAgICAgICAgICBkZWZhdWx0Q29uZmlybWF0aW9uXG4gICAgICAgICk7XG4gICAgICAgIGlmICghY29uZmlybWF0aW9uKSByZXN1bHQgPSB1bmRlZmluZWQ7XG4gICAgICB9IHdoaWxlICh0eXBlb2YgcmVzdWx0ID09PSBcInVuZGVmaW5lZFwiICYmIGxpbWl0ID4gMSAmJiBjb3VudCsrIDwgbGltaXQpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGxvZy5lcnJvcihgRXJyb3Igd2hpbGUgaW5zaXN0aW5nOiAke2V9YCk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgcmVzdWx0ID09PSBcInVuZGVmaW5lZFwiKSBsb2cuaW5mbyhcIm5vIHNlbGVjdGlvbi4uLlwiKTtcbiAgICByZXR1cm4gcmVzdWx0IGFzIFIgfCB1bmRlZmluZWQ7XG4gIH1cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXBlYXRlZGx5IGFza3MgZm9yIHRleHQgaW5wdXQgdW50aWwgYSB2YWxpZCByZXNwb25zZSBpcyBnaXZlbiBvciB0aGUgbGltaXQgaXMgcmVhY2hlZC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaW5zaXN0cyBvbiBnZXR0aW5nIGEgdmFsaWQgdGV4dCBpbnB1dCBmcm9tIHRoZSB1c2VyLCBhbGxvd2luZyBmb3IgYSBzcGVjaWZpZWQgbnVtYmVyIG9mIGF0dGVtcHRzLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIHtmdW5jdGlvbihudW1iZXIpOmJvb2xlYW59IHRlc3QgLSBWYWxpZGF0b3IgZnVuY3Rpb24gcmVjZWl2aW5nIHRoZSB1c2VyIGlucHV0IGFuZCByZXR1cm5pbmcgd2hldGhlciBpdCBpcyB2YWxpZC5cbiAgICogQHBhcmFtIG1hc2sgLSBUaGUgY2hhcmFjdGVyIHVzZWQgdG8gbWFzayB0aGUgaW5wdXQgKG9wdGlvbmFsLCBmb3IgcGFzc3dvcmQtbGlrZSBpbnB1dHMpLlxuICAgKiBAcGFyYW0gaW5pdGlhbCAtIFRoZSBpbml0aWFsIHZhbHVlIHByZXNlbnRlZCB0byB0aGUgdXNlciAob3B0aW9uYWwpLlxuICAgKiBAcGFyYW0gZGVmYXVsdENvbmZpcm1hdGlvbiAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGUgY29uZmlybWF0aW9uIHByb21wdCAodHJ1ZSBmb3IgeWVzLCBmYWxzZSBmb3Igbm8pLlxuICAgKiBAcGFyYW0gbGltaXQgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgYXR0ZW1wdHMgYWxsb3dlZCAoZGVmYXVsdCBpcyAtMSwgbWVhbmluZyB1bmxpbWl0ZWQpLlxuICAgKiBAcmV0dXJuIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSB2YWxpZCBpbnB1dCBvciB1bmRlZmluZWQgaWYgdGhlIGxpbWl0IGlzIHJlYWNoZWQuXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgaW5zaXN0Rm9yVGV4dChcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgcXVlc3Rpb246IHN0cmluZyxcbiAgICB0ZXN0OiAocmVzOiBzdHJpbmcpID0+IGJvb2xlYW4sXG4gICAgbWFzazogc3RyaW5nIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkLFxuICAgIGluaXRpYWw/OiBzdHJpbmcsXG4gICAgZGVmYXVsdENvbmZpcm1hdGlvbiA9IGZhbHNlLFxuICAgIGxpbWl0ID0gLTFcbiAgKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBsb2cgPSBVc2VySW5wdXQubG9nZ2VyLmZvcih0aGlzLmluc2lzdEZvclRleHQpO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYEluc2lzdGluZyBmb3IgdGV4dCBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIHRlc3Q6ICR7dGVzdC50b1N0cmluZygpfSwgbWFzazogJHttYXNrfSwgaW5pdGlhbDogJHtpbml0aWFsfSwgZGVmYXVsdENvbmZpcm1hdGlvbjogJHtkZWZhdWx0Q29uZmlybWF0aW9ufSwgbGltaXQ6ICR7bGltaXR9YFxuICAgICk7XG4gICAgY29uc3QgdXNlcklucHV0ID0gbmV3IFVzZXJJbnB1dChuYW1lKS5zZXRNZXNzYWdlKHF1ZXN0aW9uKTtcblxuICAgIGlmIChtYXNrKSB1c2VySW5wdXQuc2V0TWFzayhtYXNrKTtcbiAgICBpZiAodHlwZW9mIGluaXRpYWwgPT09IFwic3RyaW5nXCIpIHVzZXJJbnB1dC5zZXRJbml0aWFsKGluaXRpYWwpO1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5pbnNpc3QoXG4gICAgICB1c2VySW5wdXQsXG4gICAgICB0ZXN0IGFzIChyZXM6IHN0cmluZyB8IG51bWJlcikgPT4gYm9vbGVhbixcbiAgICAgIGRlZmF1bHRDb25maXJtYXRpb24sXG4gICAgICBsaW1pdFxuICAgICkpIGFzIHN0cmluZztcbiAgfVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlcGVhdGVkbHkgYXNrcyBmb3IgbnVtYmVyIGlucHV0IHVudGlsIGEgdmFsaWQgcmVzcG9uc2UgaXMgZ2l2ZW4gb3IgdGhlIGxpbWl0IGlzIHJlYWNoZWQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGluc2lzdHMgb24gZ2V0dGluZyBhIHZhbGlkIG51bWJlciBpbnB1dCBmcm9tIHRoZSB1c2VyLCBhbGxvd2luZyBmb3IgYSBzcGVjaWZpZWQgbnVtYmVyIG9mIGF0dGVtcHRzLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIHRlc3QgLSBBIGZ1bmN0aW9uIHRvIHZhbGlkYXRlIHRoZSB1c2VyJ3MgaW5wdXQuXG4gICAqIEBwYXJhbSBtaW4gLSBUaGUgbWluaW11bSBhbGxvd2VkIHZhbHVlIChvcHRpb25hbCkuXG4gICAqIEBwYXJhbSBtYXggLSBUaGUgbWF4aW11bSBhbGxvd2VkIHZhbHVlIChvcHRpb25hbCkuXG4gICAqIEBwYXJhbSBpbml0aWFsIC0gVGhlIGluaXRpYWwgdmFsdWUgcHJlc2VudGVkIHRvIHRoZSB1c2VyIChvcHRpb25hbCkuXG4gICAqIEBwYXJhbSBkZWZhdWx0Q29uZmlybWF0aW9uIC0gVGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRoZSBjb25maXJtYXRpb24gcHJvbXB0ICh0cnVlIGZvciB5ZXMsIGZhbHNlIGZvciBubykuXG4gICAqIEBwYXJhbSBsaW1pdCAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiBhdHRlbXB0cyBhbGxvd2VkIChkZWZhdWx0IGlzIC0xLCBtZWFuaW5nIHVubGltaXRlZCkuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHZhbGlkIGlucHV0IG9yIHVuZGVmaW5lZCBpZiB0aGUgbGltaXQgaXMgcmVhY2hlZC5cbiAgICovXG4gIHN0YXRpYyBhc3luYyBpbnNpc3RGb3JOdW1iZXIoXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIHF1ZXN0aW9uOiBzdHJpbmcsXG4gICAgdGVzdDogKHJlczogbnVtYmVyKSA9PiBib29sZWFuLFxuICAgIG1pbj86IG51bWJlcixcbiAgICBtYXg/OiBudW1iZXIsXG4gICAgaW5pdGlhbD86IG51bWJlcixcbiAgICBkZWZhdWx0Q29uZmlybWF0aW9uID0gZmFsc2UsXG4gICAgbGltaXQgPSAtMVxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGxvZyA9IFVzZXJJbnB1dC5sb2dnZXIuZm9yKHRoaXMuaW5zaXN0Rm9yTnVtYmVyKTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBJbnNpc3RpbmcgZm9yIG51bWJlciBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIHRlc3Q6ICR7dGVzdC50b1N0cmluZygpfSwgbWluOiAke21pbn0sIG1heDogJHttYXh9LCBpbml0aWFsOiAke2luaXRpYWx9LCBkZWZhdWx0Q29uZmlybWF0aW9uOiAke2RlZmF1bHRDb25maXJtYXRpb259LCBsaW1pdDogJHtsaW1pdH1gXG4gICAgKTtcbiAgICBjb25zdCB1c2VySW5wdXQgPSBuZXcgVXNlcklucHV0KG5hbWUpXG4gICAgICAuc2V0TWVzc2FnZShxdWVzdGlvbilcbiAgICAgIC5zZXRUeXBlKFwibnVtYmVyXCIpO1xuXG4gICAgaWYgKHR5cGVvZiBtaW4gPT09IFwibnVtYmVyXCIpIHVzZXJJbnB1dC5zZXRNaW4obWluKTtcblxuICAgIGlmICh0eXBlb2YgbWF4ID09PSBcIm51bWJlclwiKSB1c2VySW5wdXQuc2V0TWF4KG1heCk7XG5cbiAgICBpZiAodHlwZW9mIGluaXRpYWwgPT09IFwibnVtYmVyXCIpIHVzZXJJbnB1dC5zZXRJbml0aWFsKGluaXRpYWwpO1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5pbnNpc3QoXG4gICAgICB1c2VySW5wdXQsXG4gICAgICB0ZXN0IGFzIChyZXM6IHN0cmluZyB8IG51bWJlcikgPT4gYm9vbGVhbixcbiAgICAgIGRlZmF1bHRDb25maXJtYXRpb24sXG4gICAgICBsaW1pdFxuICAgICkpIGFzIG51bWJlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGFyc2VzIGNvbW1hbmQtbGluZSBhcmd1bWVudHMgYmFzZWQgb24gdGhlIHByb3ZpZGVkIG9wdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFVzZXMgTm9kZS5qcydzIHV0aWwucGFyc2VBcmdzIHRvIHBhcnNlIGNvbW1hbmQtbGluZSBhcmd1bWVudHMgYW5kIHJldHVybiB0aGUgcmVzdWx0LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgcGFyc2luZyBhcmd1bWVudHMuXG4gICAqIEByZXR1cm4gQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHBhcnNlZCBhcmd1bWVudHMuXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgUCBhcyBwYXJzZUFyZ3MgbWV0aG9kXG4gICAqICAgcGFydGljaXBhbnQgVSBhcyB1dGlsLnBhcnNlQXJnc1xuICAgKiAgIEMtPj5QOiBDYWxsIHdpdGggb3B0aW9uc1xuICAgKiAgIFAtPj5QOiBQcmVwYXJlIGFyZ3Mgb2JqZWN0XG4gICAqICAgUC0+PlU6IENhbGwgcGFyc2VBcmdzIHdpdGggcHJlcGFyZWQgYXJnc1xuICAgKiAgIFUtPj5QOiBSZXR1cm4gcGFyc2VkIHJlc3VsdFxuICAgKiAgIFAtLT4+QzogUmV0dXJuIFBhcnNlQXJnc1Jlc3VsdFxuICAgKi9cbiAgc3RhdGljIHBhcnNlQXJncyhvcHRpb25zOiBQYXJzZUFyZ3NPcHRpb25zQ29uZmlnKTogUGFyc2VBcmdzUmVzdWx0IHtcbiAgICBjb25zdCBsb2cgPSBVc2VySW5wdXQubG9nZ2VyLmZvcih0aGlzLnBhcnNlQXJncyk7XG4gICAgY29uc3QgYXJnczogUGFyc2VBcmdzQ29uZmlnID0ge1xuICAgICAgYXJnczogcHJvY2Vzcy5hcmd2LnNsaWNlKDIpLFxuICAgICAgb3B0aW9uczogb3B0aW9ucyxcbiAgICB9O1xuICAgIGxvZy5kZWJ1ZyhgUGFyc2luZyBhcmd1bWVudHM6ICR7SlNPTi5zdHJpbmdpZnkoYXJncywgbnVsbCwgMil9YCk7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBwYXJzZUFyZ3MoYXJncyk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgYEVycm9yIHdoaWxlIHBhcnNpbmcgYXJndW1lbnRzOlxcbiR7SlNPTi5zdHJpbmdpZnkoYXJncywgbnVsbCwgMil9XFxuIHwgb3B0aW9uc1xcbiR7SlNPTi5zdHJpbmdpZnkob3B0aW9ucywgbnVsbCwgMil9XFxuIHwgJHtlcnJvcn1gXG4gICAgICApO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciB3aGlsZSBwYXJzaW5nIGFyZ3VtZW50czogJHtlcnJvcn1gKTtcbiAgICB9XG4gIH1cbn1cbiIsIi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgY29tbWFuZCBvcHRpb25zIGZvciBDTEkgY29tbWFuZHMuXG4gKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBzdHJ1Y3R1cmUgYW5kIGRlZmF1bHQgdmFsdWVzIGZvciBjb21tb24gY29tbWFuZC1saW5lIG9wdGlvbnMgdXNlZCBhY3Jvc3MgdmFyaW91cyBDTEkgY29tbWFuZHMuXG4gKiBAY29uc3QgRGVmYXVsdENvbW1hbmRPcHRpb25zXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBEZWZhdWx0Q29tbWFuZE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSB2ZXJib3NlIC0gVmVyYm9zaXR5IGxldmVsIG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB2ZXJib3NlLnR5cGUgLSBUaGUgdHlwZSBvZiB0aGUgdmVyYm9zZSBvcHRpb24gKG51bWJlcikuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdmVyYm9zZS5zaG9ydCAtIFRoZSBzaG9ydCBmbGFnIGZvciB0aGUgdmVyYm9zZSBvcHRpb24gKFYpLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IHZlcmJvc2UuZGVmYXVsdCAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB2ZXJib3NpdHkgKDApLlxuICogQHByb3BlcnR5IHtPYmplY3R9IHZlcnNpb24gLSBWZXJzaW9uIGRpc3BsYXkgb3B0aW9uLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHZlcnNpb24udHlwZSAtIFRoZSB0eXBlIG9mIHRoZSB2ZXJzaW9uIG9wdGlvbiAoYm9vbGVhbikuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdmVyc2lvbi5zaG9ydCAtIFRoZSBzaG9ydCBmbGFnIGZvciB0aGUgdmVyc2lvbiBvcHRpb24gKHYpLlxuICogQHByb3BlcnR5IHt1bmRlZmluZWR9IHZlcnNpb24uZGVmYXVsdCAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB2ZXJzaW9uIGRpc3BsYXkgKHVuZGVmaW5lZCkuXG4gKiBAcHJvcGVydHkge09iamVjdH0gaGVscCAtIEhlbHAgZGlzcGxheSBvcHRpb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gaGVscC50eXBlIC0gVGhlIHR5cGUgb2YgdGhlIGhlbHAgb3B0aW9uIChib29sZWFuKS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBoZWxwLnNob3J0IC0gVGhlIHNob3J0IGZsYWcgZm9yIHRoZSBoZWxwIG9wdGlvbiAoaCkuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGhlbHAuZGVmYXVsdCAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciBoZWxwIGRpc3BsYXkgKGZhbHNlKS5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBsb2dMZXZlbCAtIExvZyBsZXZlbCBvcHRpb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gbG9nTGV2ZWwudHlwZSAtIFRoZSB0eXBlIG9mIHRoZSBsb2dMZXZlbCBvcHRpb24gKHN0cmluZykuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gbG9nTGV2ZWwuZGVmYXVsdCAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciBsb2cgbGV2ZWwgKFwiaW5mb1wiKS5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBsb2dTdHlsZSAtIExvZyBzdHlsaW5nIG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBsb2dTdHlsZS50eXBlIC0gVGhlIHR5cGUgb2YgdGhlIGxvZ1N0eWxlIG9wdGlvbiAoYm9vbGVhbikuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGxvZ1N0eWxlLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgbG9nIHN0eWxpbmcgKHRydWUpLlxuICogQHByb3BlcnR5IHtPYmplY3R9IHRpbWVzdGFtcCAtIFRpbWVzdGFtcCBkaXNwbGF5IG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB0aW1lc3RhbXAudHlwZSAtIFRoZSB0eXBlIG9mIHRoZSB0aW1lc3RhbXAgb3B0aW9uIChib29sZWFuKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gdGltZXN0YW1wLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgdGltZXN0YW1wIGRpc3BsYXkgKHRydWUpLlxuICogQHByb3BlcnR5IHtPYmplY3R9IGJhbm5lciAtIEJhbm5lciBkaXNwbGF5IG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBiYW5uZXIudHlwZSAtIFRoZSB0eXBlIG9mIHRoZSBiYW5uZXIgb3B0aW9uIChib29sZWFuKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gYmFubmVyLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgYmFubmVyIGRpc3BsYXkgKGZhbHNlKS5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IERlZmF1bHRDb21tYW5kT3B0aW9ucyA9IHtcbiAgdmVyYm9zZToge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIHNob3J0OiBcIlZcIixcbiAgICBkZWZhdWx0OiB1bmRlZmluZWQsXG4gIH0sXG4gIHZlcnNpb246IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICBzaG9ydDogXCJ2XCIsXG4gICAgZGVmYXVsdDogdW5kZWZpbmVkLFxuICB9LFxuICBoZWxwOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgc2hvcnQ6IFwiaFwiLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBsb2dMZXZlbDoge1xuICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgZGVmYXVsdDogXCJpbmZvXCIsXG4gIH0sXG4gIGxvZ1N0eWxlOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbiAgdGltZXN0YW1wOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbiAgYmFubmVyOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgY29tbWFuZCB2YWx1ZXMgZGVyaXZlZCBmcm9tIERlZmF1bHRDb21tYW5kT3B0aW9ucy5cbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYW4gb2JqZWN0IHdpdGggdGhlIGRlZmF1bHQgdmFsdWVzIG9mIGFsbCBvcHRpb25zIGRlZmluZWQgaW4gRGVmYXVsdENvbW1hbmRPcHRpb25zLlxuICogQGNvbnN0IERlZmF1bHRDb21tYW5kVmFsdWVzXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBEZWZhdWx0Q29tbWFuZFZhbHVlc1xuICogQHByb3BlcnR5IHt1bmtub3dufSBba2V5OiBzdHJpbmddIC0gVGhlIGRlZmF1bHQgdmFsdWUgZm9yIGVhY2ggb3B0aW9uIGluIERlZmF1bHRDb21tYW5kT3B0aW9ucy5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IERlZmF1bHRDb21tYW5kVmFsdWVzOiB7XG4gIFtrIGluIGtleW9mIHR5cGVvZiBEZWZhdWx0Q29tbWFuZE9wdGlvbnNdOiB1bmtub3duO1xufSA9IE9iamVjdC5rZXlzKERlZmF1bHRDb21tYW5kT3B0aW9ucykucmVkdWNlKFxuICAoYWNjOiBSZWNvcmQ8a2V5b2YgdHlwZW9mIERlZmF1bHRDb21tYW5kT3B0aW9ucywgdW5rbm93bj4sIGtleTogc3RyaW5nKSA9PiB7XG4gICAgYWNjW2tleSBhcyBrZXlvZiB0eXBlb2YgRGVmYXVsdENvbW1hbmRPcHRpb25zXSA9XG4gICAgICBEZWZhdWx0Q29tbWFuZE9wdGlvbnNba2V5IGFzIGtleW9mIHR5cGVvZiBEZWZhdWx0Q29tbWFuZE9wdGlvbnNdLmRlZmF1bHQ7XG4gICAgcmV0dXJuIGFjYztcbiAgfSxcbiAge30gYXMgUmVjb3JkPGtleW9mIHR5cGVvZiBEZWZhdWx0Q29tbWFuZFZhbHVlcywgdW5rbm93bj5cbik7XG4iLCIvKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IGVuY29kaW5nIGZvciB0ZXh0IG9wZXJhdGlvbnMuXG4gKiBAc3VtbWFyeSBUaGUgc3RhbmRhcmQgVVRGLTggZW5jb2RpbmcgdXNlZCBmb3IgdGV4dCBwcm9jZXNzaW5nLlxuICogQGNvbnN0IHtzdHJpbmd9IEVuY29kaW5nXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBFbmNvZGluZyA9IFwidXRmLThcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVndWxhciBleHByZXNzaW9uIGZvciBzZW1hbnRpYyB2ZXJzaW9uaW5nLlxuICogQHN1bW1hcnkgQSByZWdleCBwYXR0ZXJuIHRvIG1hdGNoIGFuZCBwYXJzZSBzZW1hbnRpYyB2ZXJzaW9uIHN0cmluZ3MuXG4gKiBAY29uc3Qge1JlZ0V4cH0gU2VtVmVyc2lvblJlZ2V4XG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBTZW1WZXJzaW9uUmVnZXggPVxuICAvXihcXGQrKVxcLihcXGQrKVxcLihcXGQrKSg/Oi0oWzAtOUEtWmEtei1dKyg/OlxcLlswLTlBLVphLXpdKSkpL2c7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVudW0gZm9yIHNlbWFudGljIHZlcnNpb24gY29tcG9uZW50cy5cbiAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIHRocmVlIGxldmVscyBvZiBzZW1hbnRpYyB2ZXJzaW9uaW5nOiBQQVRDSCwgTUlOT1IsIGFuZCBNQUpPUi5cbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBlbnVtIFNlbVZlcnNpb24ge1xuICAvKiogUGF0Y2ggdmVyc2lvbiBmb3IgYmFja3dhcmRzLWNvbXBhdGlibGUgYnVnIGZpeGVzLiAqL1xuICBQQVRDSCA9IFwicGF0Y2hcIixcbiAgLyoqIE1pbm9yIHZlcnNpb24gZm9yIGJhY2t3YXJkcy1jb21wYXRpYmxlIG5ldyBmZWF0dXJlcy4gKi9cbiAgTUlOT1IgPSBcIm1pbm9yXCIsXG4gIC8qKiBNYWpvciB2ZXJzaW9uIGZvciBjaGFuZ2VzIHRoYXQgYnJlYWsgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuICovXG4gIE1BSk9SID0gXCJtYWpvclwiLFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBGbGFnIHRvIGluZGljYXRlIG5vbi1DSSBlbnZpcm9ubWVudC5cbiAqIEBzdW1tYXJ5IFVzZWQgdG8gc3BlY2lmeSB0aGF0IGEgY29tbWFuZCBzaG91bGQgcnVuIG91dHNpZGUgb2YgYSBDb250aW51b3VzIEludGVncmF0aW9uIGVudmlyb25tZW50LlxuICogQGNvbnN0IHtzdHJpbmd9IE5vQ0lGTGFnXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBOb0NJRkxhZyA9IFwiLW5vLWNpXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEtleSBmb3IgdGhlIHNldHVwIHNjcmlwdCBpbiBwYWNrYWdlLmpzb24uXG4gKiBAc3VtbWFyeSBJZGVudGlmaWVzIHRoZSBzY3JpcHQgdGhhdCBydW5zIGFmdGVyIHBhY2thZ2UgaW5zdGFsbGF0aW9uLlxuICogQGNvbnN0IHtzdHJpbmd9IFNldHVwU2NyaXB0S2V5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBTZXR1cFNjcmlwdEtleSA9IFwicG9zdGluc3RhbGxcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRW51bSBmb3IgdmFyaW91cyBhdXRoZW50aWNhdGlvbiB0b2tlbnMuXG4gKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBmaWxlIG5hbWVzIGZvciBzdG9yaW5nIGRpZmZlcmVudCB0eXBlcyBvZiBhdXRoZW50aWNhdGlvbiB0b2tlbnMuXG4gKiBAZW51bSB7c3RyaW5nfVxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZW51bSBUb2tlbnMge1xuICAvKiogR2l0IGF1dGhlbnRpY2F0aW9uIHRva2VuIGZpbGUgbmFtZS4gKi9cbiAgR0lUID0gXCIudG9rZW5cIixcbiAgLyoqIE5QTSBhdXRoZW50aWNhdGlvbiB0b2tlbiBmaWxlIG5hbWUuICovXG4gIE5QTSA9IFwiLm5wbXRva2VuXCIsXG4gIC8qKiBEb2NrZXIgYXV0aGVudGljYXRpb24gdG9rZW4gZmlsZSBuYW1lLiAqL1xuICBET0NLRVIgPSBcIi5kb2NrZXJ0b2tlblwiLFxuICAvKiogQ29uZmx1ZW5jZSBhdXRoZW50aWNhdGlvbiB0b2tlbiBmaWxlIG5hbWUuICovXG4gIENPTkZMVUVOQ0UgPSBcIi5jb25mbHVlbmNlLXRva2VuXCIsXG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvZGUgdXNlZCB0byBpbmRpY2F0ZSBhbiBvcGVyYXRpb24gd2FzIGFib3J0ZWQuXG4gKiBAc3VtbWFyeSBTdGFuZGFyZCBtZXNzYWdlIHVzZWQgd2hlbiBhIHByb2Nlc3MgaXMgbWFudWFsbHkgdGVybWluYXRlZC5cbiAqIEBjb25zdCB7c3RyaW5nfSBBYm9ydENvZGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IEFib3J0Q29kZSA9IFwiQWJvcnRlZFwiO1xuIiwiaW1wb3J0IHsgRW5jb2RpbmcgfSBmcm9tIFwiLi4vdXRpbHMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBPdXRwdXRXcml0ZXIgfSBmcm9tIFwiLi9PdXRwdXRXcml0ZXJcIjtcbmltcG9ydCB7IFByb21pc2VFeGVjdXRvciB9IGZyb20gXCIuLi91dGlscy90eXBlc1wiO1xuaW1wb3J0IHsgT3V0cHV0VHlwZSB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBzdHlsZSB9IGZyb20gXCJzdHlsZWQtc3RyaW5nLWJ1aWxkZXJcIjtcbmltcG9ydCB7IExvZ2dlciwgTG9nZ2luZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuaW1wb3J0IHsgcGFyc2UgfSBmcm9tIFwic2hlbGwtcXVvdGVcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBzdGFuZGFyZCBvdXRwdXQgd3JpdGVyIGZvciBoYW5kbGluZyBjb21tYW5kIGV4ZWN1dGlvbiBvdXRwdXQuXG4gKiBAc3VtbWFyeSBUaGlzIGNsYXNzIGltcGxlbWVudHMgdGhlIE91dHB1dFdyaXRlciBpbnRlcmZhY2UgYW5kIHByb3ZpZGVzIG1ldGhvZHMgZm9yXG4gKiBoYW5kbGluZyB2YXJpb3VzIHR5cGVzIG9mIG91dHB1dCBmcm9tIGNvbW1hbmQgZXhlY3V0aW9uLCBpbmNsdWRpbmcgc3RhbmRhcmQgb3V0cHV0LFxuICogZXJyb3Igb3V0cHV0LCBhbmQgZXhpdCBjb2Rlcy4gSXQgYWxzbyBpbmNsdWRlcyB1dGlsaXR5IG1ldGhvZHMgZm9yIHBhcnNpbmcgY29tbWFuZHNcbiAqIGFuZCByZXNvbHZpbmcgb3IgcmVqZWN0aW5nIHByb21pc2VzIGJhc2VkIG9uIGV4ZWN1dGlvbiByZXN1bHRzLlxuICpcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgdGhlIHJlc29sdmVkIHZhbHVlLCBkZWZhdWx0aW5nIHRvIHN0cmluZy5cbiAqXG4gKiBAcGFyYW0gY21kIC0gVGhlIGNvbW1hbmQgc3RyaW5nIHRvIGJlIGV4ZWN1dGVkLlxuICogQHBhcmFtIGxvY2sgLSBBIFByb21pc2VFeGVjdXRvciB0byBjb250cm9sIHRoZSBhc3luY2hyb25vdXMgZmxvdy5cbiAqIEBwYXJhbSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgKHVudXNlZCBpbiB0aGUgY3VycmVudCBpbXBsZW1lbnRhdGlvbikuXG4gKlxuICogQGNsYXNzXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgU3RhbmRhcmRPdXRwdXRXcml0ZXIgfSBmcm9tICdAZGVjYWYtdHMvdXRpbHMnO1xuICogaW1wb3J0IHsgUHJvbWlzZUV4ZWN1dG9yIH0gZnJvbSAnQGRlY2FmLXRzL3V0aWxzJztcbiAqXG4gKiAvLyBDcmVhdGUgYSBwcm9taXNlIGV4ZWN1dG9yXG4gKiBjb25zdCBleGVjdXRvcjogUHJvbWlzZUV4ZWN1dG9yPHN0cmluZz4gPSB7XG4gKiAgIHJlc29sdmU6ICh2YWx1ZSkgPT4gY29uc29sZS5sb2coYFJlc29sdmVkOiAke3ZhbHVlfWApLFxuICogICByZWplY3Q6IChlcnJvcikgPT4gY29uc29sZS5lcnJvcihgUmVqZWN0ZWQ6ICR7ZXJyb3IubWVzc2FnZX1gKVxuICogfTtcbiAqXG4gKiAvLyBDcmVhdGUgYSBzdGFuZGFyZCBvdXRwdXQgd3JpdGVyXG4gKiBjb25zdCB3cml0ZXIgPSBuZXcgU3RhbmRhcmRPdXRwdXRXcml0ZXIoJ2xzIC1sYScsIGV4ZWN1dG9yKTtcbiAqXG4gKiAvLyBVc2UgdGhlIHdyaXRlciB0byBoYW5kbGUgY29tbWFuZCBvdXRwdXRcbiAqIHdyaXRlci5kYXRhKCdGaWxlIGxpc3Qgb3V0cHV0Li4uJyk7XG4gKiB3cml0ZXIuZXhpdCgwLCBbJ0NvbW1hbmQgZXhlY3V0ZWQgc3VjY2Vzc2Z1bGx5J10pO1xuICogYGBgXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgU3RhbmRhcmRPdXRwdXRXcml0ZXJcbiAqICAgcGFydGljaXBhbnQgTG9nZ2VyXG4gKiAgIHBhcnRpY2lwYW50IFByb21pc2VFeGVjdXRvclxuICpcbiAqICAgQ2xpZW50LT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IG5ldyBTdGFuZGFyZE91dHB1dFdyaXRlcihjbWQsIGxvY2spXG4gKiAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+TG9nZ2VyOiBMb2dnaW5nLmZvcihjbWQpXG4gKlxuICogICBDbGllbnQtPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogZGF0YShjaHVuaylcbiAqICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogbG9nKFwic3Rkb3V0XCIsIGNodW5rKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PkxvZ2dlcjogbG9nZ2VyLmluZm8obG9nKVxuICpcbiAqICAgQ2xpZW50LT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IGVycm9yKGNodW5rKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiBsb2coXCJzdGRlcnJcIiwgY2h1bmspXG4gKiAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+TG9nZ2VyOiBsb2dnZXIuaW5mbyhsb2cpXG4gKlxuICogICBDbGllbnQtPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogZXhpdChjb2RlLCBsb2dzKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiBsb2coXCJzdGRvdXRcIiwgZXhpdE1lc3NhZ2UpXG4gKiAgIGFsdCBjb2RlID09PSAwXG4gKiAgICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogcmVzb2x2ZShsb2dzKVxuICogICAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+UHJvbWlzZUV4ZWN1dG9yOiBsb2NrLnJlc29sdmUocmVhc29uKVxuICogICBlbHNlIGNvZGUgIT09IDBcbiAqICAgICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiByZWplY3QoZXJyb3IpXG4gKiAgICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5Qcm9taXNlRXhlY3V0b3I6IGxvY2sucmVqZWN0KHJlYXNvbilcbiAqICAgZW5kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdGFuZGFyZE91dHB1dFdyaXRlcjxSID0gc3RyaW5nPiBpbXBsZW1lbnRzIE91dHB1dFdyaXRlciB7XG4gIHByb3RlY3RlZCBsb2dnZXI6IExvZ2dlcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgY21kOiBzdHJpbmcsXG4gICAgcHJvdGVjdGVkIGxvY2s6IFByb21pc2VFeGVjdXRvcjxSPixcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgLi4uYXJnczogdW5rbm93bltdXG4gICkge1xuICAgIHRoaXMubG9nZ2VyID0gTG9nZ2luZy5mb3IodGhpcy5jbWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMb2dzIG91dHB1dCB0byB0aGUgY29uc29sZS5cbiAgICogQHN1bW1hcnkgRm9ybWF0cyBhbmQgbG9ncyB0aGUgZ2l2ZW4gZGF0YSB3aXRoIGEgdGltZXN0YW1wIGFuZCB0eXBlIGluZGljYXRvci5cbiAgICpcbiAgICogQHBhcmFtIHR5cGUgLSBUaGUgdHlwZSBvZiBvdXRwdXQgKHN0ZG91dCBvciBzdGRlcnIpLlxuICAgKiBAcGFyYW0gZGF0YSAtIFRoZSBkYXRhIHRvIGJlIGxvZ2dlZC5cbiAgICovXG4gIHByb3RlY3RlZCBsb2codHlwZTogT3V0cHV0VHlwZSwgZGF0YTogc3RyaW5nIHwgQnVmZmVyKSB7XG4gICAgZGF0YSA9IEJ1ZmZlci5pc0J1ZmZlcihkYXRhKSA/IGRhdGEudG9TdHJpbmcoRW5jb2RpbmcpIDogZGF0YTtcbiAgICBjb25zdCBsb2cgPSB0eXBlID09PSBcInN0ZGVyclwiID8gc3R5bGUoZGF0YSkucmVkLnRleHQgOiBkYXRhO1xuICAgIHRoaXMubG9nZ2VyLmluZm8obG9nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBzdGFuZGFyZCBvdXRwdXQgZGF0YS5cbiAgICogQHN1bW1hcnkgTG9ncyB0aGUgZ2l2ZW4gY2h1bmsgYXMgc3RhbmRhcmQgb3V0cHV0LlxuICAgKlxuICAgKiBAcGFyYW0gY2h1bmsgLSBUaGUgZGF0YSBjaHVuayB0byBiZSBsb2dnZWQuXG4gICAqL1xuICBkYXRhKGNodW5rOiBhbnkpIHtcbiAgICB0aGlzLmxvZyhcInN0ZG91dFwiLCBTdHJpbmcoY2h1bmspKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBlcnJvciBvdXRwdXQgZGF0YS5cbiAgICogQHN1bW1hcnkgTG9ncyB0aGUgZ2l2ZW4gY2h1bmsgYXMgZXJyb3Igb3V0cHV0LlxuICAgKlxuICAgKiBAcGFyYW0gY2h1bmsgLSBUaGUgZXJyb3IgZGF0YSBjaHVuayB0byBiZSBsb2dnZWQuXG4gICAqL1xuICBlcnJvcihjaHVuazogYW55KSB7XG4gICAgdGhpcy5sb2coXCJzdGRlcnJcIiwgU3RyaW5nKGNodW5rKSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgZXJyb3Igb2JqZWN0cy5cbiAgICogQHN1bW1hcnkgTG9ncyB0aGUgZXJyb3IgbWVzc2FnZSBmcm9tIHRoZSBnaXZlbiBFcnJvciBvYmplY3QuXG4gICAqXG4gICAqIEBwYXJhbSBlcnIgLSBUaGUgRXJyb3Igb2JqZWN0IHRvIGJlIGxvZ2dlZC5cbiAgICovXG4gIGVycm9ycyhlcnI6IEVycm9yKSB7XG4gICAgdGhpcy5sb2coXCJzdGRlcnJcIiwgYEVycm9yIGV4ZWN1dGluZyBjb21tYW5kIGV4aXRlZCA6ICR7ZXJyfWApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIHRoZSBleGl0IG9mIGEgY29tbWFuZC5cbiAgICogQHN1bW1hcnkgTG9ncyB0aGUgZXhpdCBjb2RlIGFuZCByZXNvbHZlcyBvciByZWplY3RzIHRoZSBwcm9taXNlIGJhc2VkIG9uIHRoZSBjb2RlLlxuICAgKlxuICAgKiBAcGFyYW0gY29kZSAtIFRoZSBleGl0IGNvZGUgb2YgdGhlIGNvbW1hbmQuXG4gICAqIEBwYXJhbSBsb2dzIC0gQXJyYXkgb2YgbG9nIG1lc3NhZ2VzIHRvIGJlIHByb2Nlc3NlZCBiZWZvcmUgZXhpdGluZy5cbiAgICovXG4gIGV4aXQoY29kZTogbnVtYmVyIHwgc3RyaW5nLCBsb2dzOiBzdHJpbmdbXSkge1xuICAgIHRoaXMubG9nKFxuICAgICAgXCJzdGRvdXRcIixcbiAgICAgIGBjb21tYW5kIGV4aXRlZCBjb2RlIDogJHtjb2RlID09PSAwID8gc3R5bGUoY29kZS50b1N0cmluZygpKS5ncmVlbi50ZXh0IDogc3R5bGUoY29kZSA9PT0gbnVsbCA/IFwibnVsbFwiIDogY29kZS50b1N0cmluZygpKS5yZWQudGV4dH1gXG4gICAgKTtcbiAgICBpZiAoY29kZSA9PT0gMCkge1xuICAgICAgdGhpcy5yZXNvbHZlKGxvZ3MubWFwKChsKSA9PiBsLnRyaW0oKSkuam9pbihcIlxcblwiKSBhcyBSKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZWplY3QobmV3IEVycm9yKGxvZ3MubGVuZ3RoID8gbG9ncy5qb2luKFwiXFxuXCIpIDogY29kZS50b1N0cmluZygpKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQYXJzZXMgYSBjb21tYW5kIHN0cmluZyBvciBhcnJheSBpbnRvIGNvbXBvbmVudHMuXG4gICAqIEBzdW1tYXJ5IENvbnZlcnRzIHRoZSBjb21tYW5kIGludG8gYSBjb25zaXN0ZW50IGZvcm1hdCBhbmQgc3RvcmVzIGl0LCB0aGVuIHJldHVybnMgaXQgc3BsaXQgaW50byBjb21tYW5kIGFuZCBhcmd1bWVudHMuXG4gICAqXG4gICAqIEBwYXJhbSBjb21tYW5kIC0gVGhlIGNvbW1hbmQgYXMgYSBzdHJpbmcgb3IgYXJyYXkgb2Ygc3RyaW5ncy5cbiAgICogQHJldHVybiBBIHR1cGxlIGNvbnRhaW5pbmcgdGhlIGNvbW1hbmQgYW5kIGl0cyBhcmd1bWVudHMgYXMgc2VwYXJhdGUgZWxlbWVudHMuXG4gICAqL1xuICBwYXJzZUNvbW1hbmQoY29tbWFuZDogc3RyaW5nIHwgc3RyaW5nW10pOiBbc3RyaW5nLCBzdHJpbmdbXV0ge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbW1hbmQpKSB7XG4gICAgICB0aGlzLmNtZCA9IGNvbW1hbmQuam9pbihcIiBcIik7XG4gICAgICByZXR1cm4gW2NvbW1hbmRbMF0sIGNvbW1hbmQuc2xpY2UoMSldO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnRzID0gcGFyc2UoY29tbWFuZClcbiAgICAgIC5maWx0ZXIoKHApID0+IHR5cGVvZiBwID09PSBcInN0cmluZ1wiKVxuICAgICAgLm1hcChTdHJpbmcpO1xuXG4gICAgdGhpcy5jbWQgPSBwYXJ0cy5qb2luKFwiIFwiKTtcbiAgICByZXR1cm4gW3BhcnRzWzBdLCBwYXJ0cy5zbGljZSgxKV07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlc29sdmVzIHRoZSBwcm9taXNlIHdpdGggYSBzdWNjZXNzIG1lc3NhZ2UuXG4gICAqIEBzdW1tYXJ5IExvZ3MgYSBzdWNjZXNzIG1lc3NhZ2UgYW5kIHJlc29sdmVzIHRoZSBwcm9taXNlIHdpdGggdGhlIGdpdmVuIHJlYXNvbi5cbiAgICpcbiAgICogQHBhcmFtIHJlYXNvbiAtIFRoZSByZWFzb24gZm9yIHJlc29sdmluZyB0aGUgcHJvbWlzZS5cbiAgICovXG4gIHByb3RlY3RlZCByZXNvbHZlKHJlYXNvbjogUikge1xuICAgIHRoaXMubG9nKFxuICAgICAgXCJzdGRvdXRcIixcbiAgICAgIGAke3RoaXMuY21kfSBleGVjdXRlZCBzdWNjZXNzZnVsbHk6ICR7c3R5bGUocmVhc29uID8gXCJyYW4gdG8gY29tcGxldGlvblwiIDogKHJlYXNvbiBhcyBzdHJpbmcpKS5ncmVlbn1gXG4gICAgKTtcbiAgICB0aGlzLmxvY2sucmVzb2x2ZShyZWFzb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWplY3RzIHRoZSBwcm9taXNlIHdpdGggYW4gZXJyb3IgbWVzc2FnZS5cbiAgICogQHN1bW1hcnkgTG9ncyBhbiBlcnJvciBtZXNzYWdlIGFuZCByZWplY3RzIHRoZSBwcm9taXNlIHdpdGggdGhlIGdpdmVuIHJlYXNvbi5cbiAgICpcbiAgICogQHBhcmFtIHJlYXNvbiAtIFRoZSByZWFzb24gZm9yIHJlamVjdGluZyB0aGUgcHJvbWlzZSwgZWl0aGVyIGEgbnVtYmVyIChleGl0IGNvZGUpIG9yIGEgc3RyaW5nLlxuICAgKi9cbiAgcHJvdGVjdGVkIHJlamVjdChyZWFzb246IG51bWJlciB8IHN0cmluZyB8IEVycm9yKSB7XG4gICAgaWYgKCEocmVhc29uIGluc3RhbmNlb2YgRXJyb3IpKSB7XG4gICAgICByZWFzb24gPSBuZXcgRXJyb3IoXG4gICAgICAgIHR5cGVvZiByZWFzb24gPT09IFwibnVtYmVyXCIgPyBgRXhpdCBjb2RlICR7cmVhc29ufWAgOiByZWFzb25cbiAgICAgICk7XG4gICAgfVxuICAgIHRoaXMubG9nKFxuICAgICAgXCJzdGRlcnJcIixcbiAgICAgIGAke3RoaXMuY21kfSBmYWlsZWQgdG8gZXhlY3V0ZTogJHtzdHlsZShyZWFzb24ubWVzc2FnZSkucmVkfWBcbiAgICApO1xuICAgIHRoaXMubG9jay5yZWplY3QocmVhc29uKTtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgQ2hpbGRQcm9jZXNzV2l0aG91dE51bGxTdHJlYW1zLFxuICBzcGF3bixcbiAgU3Bhd25PcHRpb25zV2l0aG91dFN0ZGlvLFxufSBmcm9tIFwiY2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgU3RhbmRhcmRPdXRwdXRXcml0ZXIgfSBmcm9tIFwiLi4vd3JpdGVycy9TdGFuZGFyZE91dHB1dFdyaXRlclwiO1xuaW1wb3J0IHsgQ29tbWFuZFJlc3VsdCB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBPdXRwdXRXcml0ZXJDb25zdHJ1Y3RvciB9IGZyb20gXCIuLi93cml0ZXJzL3R5cGVzXCI7XG5pbXBvcnQgeyBBYm9ydENvZGUgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IExvZ2dlciwgTG9nZ2luZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbG9ja2VkIHZlcnNpb24gb2YgYSBmdW5jdGlvbi5cbiAqIEBzdW1tYXJ5IFRoaXMgaGlnaGVyLW9yZGVyIGZ1bmN0aW9uIHRha2VzIGEgZnVuY3Rpb24gYW5kIHJldHVybnMgYSBuZXcgZnVuY3Rpb24gdGhhdCBlbnN1cmVzXG4gKiBzZXF1ZW50aWFsIGV4ZWN1dGlvbiBvZiB0aGUgb3JpZ2luYWwgZnVuY3Rpb24sIGV2ZW4gd2hlbiBjYWxsZWQgbXVsdGlwbGUgdGltZXMgY29uY3VycmVudGx5LlxuICogSXQgdXNlcyBhIFByb21pc2UtYmFzZWQgbG9ja2luZyBtZWNoYW5pc20gdG8gcXVldWUgZnVuY3Rpb24gY2FsbHMuXG4gKlxuICogQHRlbXBsYXRlIFIgLSBUaGUgcmV0dXJuIHR5cGUgb2YgdGhlIGlucHV0IGZ1bmN0aW9uLlxuICpcbiAqIEBwYXJhbSBmIC0gVGhlIGZ1bmN0aW9uIHRvIGJlIGxvY2tlZC4gSXQgY2FuIHRha2UgYW55IG51bWJlciBvZiBwYXJhbWV0ZXJzIGFuZCByZXR1cm4gYSB2YWx1ZSBvZiB0eXBlIFIuXG4gKiBAcmV0dXJuIEEgbmV3IGZ1bmN0aW9uIHdpdGggdGhlIHNhbWUgc2lnbmF0dXJlIGFzIHRoZSBpbnB1dCBmdW5jdGlvbiwgYnV0IHdpdGggc2VxdWVudGlhbCBleGVjdXRpb24gZ3VhcmFudGVlZC5cbiAqXG4gKiBAZnVuY3Rpb24gbG9ja2lmeVxuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IExvY2tlZEZ1bmN0aW9uXG4gKiAgIHBhcnRpY2lwYW50IE9yaWdpbmFsRnVuY3Rpb25cbiAqICAgQ2FsbGVyLT4+TG9ja2VkRnVuY3Rpb246IENhbGwgd2l0aCBwYXJhbXNcbiAqICAgTG9ja2VkRnVuY3Rpb24tPj5Mb2NrZWRGdW5jdGlvbjogQ2hlY2sgY3VycmVudCBsb2NrXG4gKiAgIGFsdCBMb2NrIGlzIHJlc29sdmVkXG4gKiAgICAgTG9ja2VkRnVuY3Rpb24tPj5PcmlnaW5hbEZ1bmN0aW9uOiBFeGVjdXRlIHdpdGggcGFyYW1zXG4gKiAgICAgT3JpZ2luYWxGdW5jdGlvbi0tPj5Mb2NrZWRGdW5jdGlvbjogUmV0dXJuIHJlc3VsdFxuICogICAgIExvY2tlZEZ1bmN0aW9uLS0+PkNhbGxlcjogUmV0dXJuIHJlc3VsdFxuICogICBlbHNlIExvY2sgaXMgcGVuZGluZ1xuICogICAgIExvY2tlZEZ1bmN0aW9uLT4+TG9ja2VkRnVuY3Rpb246IFF1ZXVlIGV4ZWN1dGlvblxuICogICAgIExvY2tlZEZ1bmN0aW9uLS0+PkNhbGxlcjogUmV0dXJuIHByb21pc2VcbiAqICAgICBOb3RlIG92ZXIgTG9ja2VkRnVuY3Rpb246IFdhaXQgZm9yIHByZXZpb3VzIGV4ZWN1dGlvblxuICogICAgIExvY2tlZEZ1bmN0aW9uLT4+T3JpZ2luYWxGdW5jdGlvbjogRXhlY3V0ZSB3aXRoIHBhcmFtc1xuICogICAgIE9yaWdpbmFsRnVuY3Rpb24tLT4+TG9ja2VkRnVuY3Rpb246IFJldHVybiByZXN1bHRcbiAqICAgICBMb2NrZWRGdW5jdGlvbi0tPj5DYWxsZXI6IFJlc29sdmUgcHJvbWlzZSB3aXRoIHJlc3VsdFxuICogICBlbmRcbiAqICAgTG9ja2VkRnVuY3Rpb24tPj5Mb2NrZWRGdW5jdGlvbjogVXBkYXRlIGxvY2tcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsb2NraWZ5PFI+KGY6ICguLi5wYXJhbXM6IHVua25vd25bXSkgPT4gUikge1xuICBsZXQgbG9jazogUHJvbWlzZTxSIHwgdm9pZD4gPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgcmV0dXJuICguLi5wYXJhbXM6IHVua25vd25bXSkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IGxvY2sudGhlbigoKSA9PiBmKC4uLnBhcmFtcykpO1xuICAgIGxvY2sgPSByZXN1bHQuY2F0Y2goKCkgPT4ge30pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENoYWlucyBtdWx0aXBsZSBhYm9ydCBzaWduYWxzIHRvIGEgY29udHJvbGxlci5cbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBtZWNoYW5pc20gd2hlcmUgbXVsdGlwbGUgYWJvcnQgc2lnbmFscyBjYW4gdHJpZ2dlciBhIHNpbmdsZSBhYm9ydCBjb250cm9sbGVyLlxuICogVGhpcyBpcyB1c2VmdWwgZm9yIGNvb3JkaW5hdGluZyBjYW5jZWxsYXRpb24gYWNyb3NzIG11bHRpcGxlIGFzeW5jaHJvbm91cyBvcGVyYXRpb25zLlxuICpcbiAqIEBwYXJhbSB7QWJvcnRDb250cm9sbGVyfSBjb250cm9sbGVyIC0gVGhlIGFib3J0IGNvbnRyb2xsZXIgdG8gYmUgdHJpZ2dlcmVkIGJ5IHNpZ25hbHMuXG4gKiBAcGFyYW0gey4uLkFib3J0U2lnbmFsfSBzaWduYWxzIC0gT25lIG9yIG1vcmUgYWJvcnQgc2lnbmFscyB0aGF0IGNhbiB0cmlnZ2VyIHRoZSBjb250cm9sbGVyLlxuICogQHJldHVybiB7QWJvcnRDb250cm9sbGVyfSBUaGUgaW5wdXQgY29udHJvbGxlciwgbm93IGNvbm5lY3RlZCB0byB0aGUgc2lnbmFscy5cbiAqXG4gKiBAZnVuY3Rpb24gY2hhaW5BYm9ydENvbnRyb2xsZXJcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGFpbkFib3J0Q29udHJvbGxlcihcbiAgY29udHJvbGxlcjogQWJvcnRDb250cm9sbGVyLFxuICAuLi5zaWduYWxzOiBBYm9ydFNpZ25hbFtdXG4pOiBBYm9ydENvbnRyb2xsZXI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgY29udHJvbGxlciBjaGFpbmVkIHRvIG11bHRpcGxlIGFib3J0IHNpZ25hbHMuXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgbmV3IGFib3J0IGNvbnRyb2xsZXIgdGhhdCB3aWxsIGJlIHRyaWdnZXJlZCBpZiBhbnkgb2YgdGhlIHByb3ZpZGVkIHNpZ25hbHMgYXJlIGFib3J0ZWQuXG4gKlxuICogQHBhcmFtIHsuLi5BYm9ydFNpZ25hbH0gc2lnbmFscyAtIE9uZSBvciBtb3JlIGFib3J0IHNpZ25hbHMgdGhhdCBjYW4gdHJpZ2dlciB0aGUgbmV3IGNvbnRyb2xsZXIuXG4gKiBAcmV0dXJuIHtBYm9ydENvbnRyb2xsZXJ9IEEgbmV3IGFib3J0IGNvbnRyb2xsZXIgY29ubmVjdGVkIHRvIHRoZSBzaWduYWxzLlxuICpcbiAqIEBmdW5jdGlvbiBjaGFpbkFib3J0Q29udHJvbGxlclxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoYWluQWJvcnRDb250cm9sbGVyKFxuICAuLi5zaWduYWxzOiBBYm9ydFNpZ25hbFtdXG4pOiBBYm9ydENvbnRyb2xsZXI7XG5cbmV4cG9ydCBmdW5jdGlvbiBjaGFpbkFib3J0Q29udHJvbGxlcihcbiAgYXJndW1lbnQwOiBBYm9ydENvbnRyb2xsZXIgfCBBYm9ydFNpZ25hbCxcbiAgLi4ucmVtYWluZGVyOiBBYm9ydFNpZ25hbFtdXG4pOiBBYm9ydENvbnRyb2xsZXIge1xuICBsZXQgc2lnbmFsczogQWJvcnRTaWduYWxbXTtcbiAgbGV0IGNvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcjtcblxuICAvLyBub3JtYWxpemUgYXJnc1xuICBpZiAoYXJndW1lbnQwIGluc3RhbmNlb2YgQWJvcnRTaWduYWwpIHtcbiAgICBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgIHNpZ25hbHMgPSBbYXJndW1lbnQwLCAuLi5yZW1haW5kZXJdO1xuICB9IGVsc2Uge1xuICAgIGNvbnRyb2xsZXIgPSBhcmd1bWVudDA7XG4gICAgc2lnbmFscyA9IHJlbWFpbmRlcjtcbiAgfVxuXG4gIC8vIGlmIHRoZSBjb250cm9sbGVyIGlzIGFscmVhZHkgYWJvcnRlZCwgZXhpdCBlYXJseVxuICBpZiAoY29udHJvbGxlci5zaWduYWwuYWJvcnRlZCkge1xuICAgIHJldHVybiBjb250cm9sbGVyO1xuICB9XG5cbiAgY29uc3QgaGFuZGxlciA9ICgpID0+IGNvbnRyb2xsZXIuYWJvcnQoKTtcblxuICBmb3IgKGNvbnN0IHNpZ25hbCBvZiBzaWduYWxzKSB7XG4gICAgLy8gY2hlY2sgYmVmb3JlIGFkZGluZyEgKGFuZCBhc3N1bWUgdGhlcmUgaXMgbm8gcG9zc2libGUgd2F5IHRoYXQgdGhlIHNpZ25hbCBjb3VsZFxuICAgIC8vIGFib3J0IGJldHdlZW4gdGhlIGBpZmAgY2hlY2sgYW5kIGFkZGluZyB0aGUgZXZlbnQgbGlzdGVuZXIpXG4gICAgaWYgKHNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICBjb250cm9sbGVyLmFib3J0KCk7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCBoYW5kbGVyLCB7XG4gICAgICBvbmNlOiB0cnVlLFxuICAgICAgc2lnbmFsOiBjb250cm9sbGVyLnNpZ25hbCxcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBjb250cm9sbGVyO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTcGF3bnMgYSBjb21tYW5kIGFzIGEgY2hpbGQgcHJvY2VzcyB3aXRoIG91dHB1dCBoYW5kbGluZy5cbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBjaGlsZCBwcm9jZXNzIHRvIGV4ZWN1dGUgYSBjb21tYW5kIHdpdGggc3VwcG9ydCBmb3IgcGlwaW5nIG11bHRpcGxlIGNvbW1hbmRzLFxuICogY3VzdG9tIG91dHB1dCBoYW5kbGluZywgYW5kIGFib3J0IGNvbnRyb2wuIFRoaXMgZnVuY3Rpb24gaGFuZGxlcyB0aGUgbG93LWxldmVsIGRldGFpbHMgb2ZcbiAqIHNwYXduaW5nIHByb2Nlc3NlcyBhbmQgY29ubmVjdGluZyB0aGVpciBpbnB1dHMvb3V0cHV0cyB3aGVuIHBpcGluZyBpcyB1c2VkLlxuICpcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgdGhlIHByb2Nlc3NlZCBvdXRwdXQsIGRlZmF1bHRpbmcgdG8gc3RyaW5nLlxuICogQHBhcmFtIHtTdGFuZGFyZE91dHB1dFdyaXRlcjxSPn0gb3V0cHV0IC0gVGhlIG91dHB1dCB3cml0ZXIgdG8gaGFuZGxlIGNvbW1hbmQgb3V0cHV0LlxuICogQHBhcmFtIHtzdHJpbmd9IGNvbW1hbmQgLSBUaGUgY29tbWFuZCB0byBleGVjdXRlLCBjYW4gaW5jbHVkZSBwaXBlIG9wZXJhdG9ycy5cbiAqIEBwYXJhbSB7U3Bhd25PcHRpb25zV2l0aG91dFN0ZGlvfSBvcHRzIC0gT3B0aW9ucyBmb3IgdGhlIHNwYXduZWQgcHJvY2Vzcy5cbiAqIEBwYXJhbSB7QWJvcnRDb250cm9sbGVyfSBhYm9ydCAtIENvbnRyb2xsZXIgdG8gYWJvcnQgdGhlIGNvbW1hbmQgZXhlY3V0aW9uLlxuICogQHBhcmFtIHtMb2dnZXJ9IGxvZ2dlciAtIExvZ2dlciBmb3IgcmVjb3JkaW5nIGNvbW1hbmQgZXhlY3V0aW9uIGRldGFpbHMuXG4gKiBAcmV0dXJuIHtDaGlsZFByb2Nlc3NXaXRob3V0TnVsbFN0cmVhbXN9IFRoZSBzcGF3bmVkIGNoaWxkIHByb2Nlc3MuXG4gKlxuICogQGZ1bmN0aW9uIHNwYXduQ29tbWFuZFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNwYXduQ29tbWFuZDxSID0gc3RyaW5nPihcbiAgb3V0cHV0OiBTdGFuZGFyZE91dHB1dFdyaXRlcjxSPixcbiAgY29tbWFuZDogc3RyaW5nLFxuICBvcHRzOiBTcGF3bk9wdGlvbnNXaXRob3V0U3RkaW8sXG4gIGFib3J0OiBBYm9ydENvbnRyb2xsZXIsXG4gIGxvZ2dlcjogTG9nZ2VyXG4pOiBDaGlsZFByb2Nlc3NXaXRob3V0TnVsbFN0cmVhbXMge1xuICBmdW5jdGlvbiBzcGF3bklubmVyKGNvbW1hbmQ6IHN0cmluZywgY29udHJvbGxlcjogQWJvcnRDb250cm9sbGVyKSB7XG4gICAgY29uc3QgW2NtZCwgYXJnel0gPSBvdXRwdXQucGFyc2VDb21tYW5kKGNvbW1hbmQpO1xuICAgIGxvZ2dlci5pbmZvKGBSdW5uaW5nIGNvbW1hbmQ6ICR7Y21kfWApO1xuICAgIGxvZ2dlci5kZWJ1Zyhgd2l0aCBhcmdzOiAke2FyZ3ouam9pbihcIiBcIil9YCk7XG4gICAgY29uc3QgY2hpbGRQcm9jZXNzID0gc3Bhd24oY21kLCBhcmd6LCB7XG4gICAgICAuLi5vcHRzLFxuICAgICAgY3dkOiBvcHRzLmN3ZCB8fCBwcm9jZXNzLmN3ZCgpLFxuICAgICAgZW52OiBPYmplY3QuYXNzaWduKHt9LCBwcm9jZXNzLmVudiwgb3B0cy5lbnYsIHsgUEFUSDogcHJvY2Vzcy5lbnYuUEFUSCB9KSxcbiAgICAgIHNoZWxsOiBvcHRzLnNoZWxsIHx8IGZhbHNlLFxuICAgICAgc2lnbmFsOiBjb250cm9sbGVyLnNpZ25hbCxcbiAgICB9KTtcbiAgICBsb2dnZXIudmVyYm9zZShgcGlkIDogJHtjaGlsZFByb2Nlc3MucGlkfWApO1xuICAgIHJldHVybiBjaGlsZFByb2Nlc3M7XG4gIH1cblxuICBjb25zdCBtID0gY29tbWFuZC5tYXRjaCgvWzw+JCNdL2cpO1xuICBpZiAobSlcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgSW52YWxpZCBjb21tYW5kOiAke2NvbW1hbmR9LiBjb250YWlucyBpbnZhbGlkIGNoYXJhY3RlcnM6ICR7bX1gXG4gICAgKTtcbiAgaWYgKGNvbW1hbmQuaW5jbHVkZXMoXCIgfCBcIikpIHtcbiAgICBjb25zdCBjbWRzID0gY29tbWFuZC5zcGxpdChcIiB8IFwiKTtcbiAgICBjb25zdCBzcGF3bnMgPSBbXTtcbiAgICBjb25zdCBjb250cm9sbGVycyA9IG5ldyBBcnJheShjbWRzLmxlbmd0aCk7XG4gICAgY29udHJvbGxlcnNbMF0gPSBhYm9ydDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNtZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChpICE9PSAwKVxuICAgICAgICBjb250cm9sbGVyc1tpXSA9IGNoYWluQWJvcnRDb250cm9sbGVyKGNvbnRyb2xsZXJzW2kgLSAxXS5zaWduYWwpO1xuICAgICAgc3Bhd25zLnB1c2goc3Bhd25Jbm5lcihjbWRzW2ldLCBjb250cm9sbGVyc1tpXSkpO1xuICAgICAgaWYgKGkgPT09IDApIGNvbnRpbnVlO1xuICAgICAgc3Bhd25zW2kgLSAxXS5zdGRvdXQucGlwZShzcGF3bnNbaV0uc3RkaW4pO1xuICAgIH1cbiAgICByZXR1cm4gc3Bhd25zW2NtZHMubGVuZ3RoIC0gMV07XG4gIH1cblxuICByZXR1cm4gc3Bhd25Jbm5lcihjb21tYW5kLCBhYm9ydCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgY29tbWFuZCBhc3luY2hyb25vdXNseSB3aXRoIGN1c3RvbWl6YWJsZSBvdXRwdXQgaGFuZGxpbmcuXG4gKiBAc3VtbWFyeSBUaGlzIGZ1bmN0aW9uIHJ1bnMgYSBzaGVsbCBjb21tYW5kIGFzIGEgY2hpbGQgcHJvY2VzcywgcHJvdmlkaW5nIGZpbmUtZ3JhaW5lZFxuICogY29udHJvbCBvdmVyIGl0cyBleGVjdXRpb24gYW5kIG91dHB1dCBoYW5kbGluZy4gSXQgc3VwcG9ydHMgY3VzdG9tIG91dHB1dCB3cml0ZXJzLFxuICogYWxsb3dzIGZvciBjb21tYW5kIGFib3J0aW9uLCBhbmQgY2FwdHVyZXMgYm90aCBzdGRvdXQgYW5kIHN0ZGVyci5cbiAqXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSByZXNvbHZlZCB2YWx1ZSBmcm9tIHRoZSBjb21tYW5kIGV4ZWN1dGlvbi5cbiAqXG4gKiBAcGFyYW0gY29tbWFuZCAtIFRoZSBjb21tYW5kIHRvIHJ1biwgZWl0aGVyIGFzIGEgc3RyaW5nIG9yIGFuIGFycmF5IG9mIHN0cmluZ3MuXG4gKiBAcGFyYW0gb3B0cyAtIFNwYXduIG9wdGlvbnMgZm9yIHRoZSBjaGlsZCBwcm9jZXNzLiBEZWZhdWx0cyB0byBhbiBlbXB0eSBvYmplY3QuXG4gKiBAcGFyYW0gb3V0cHV0Q29uc3RydWN0b3IgLSBDb25zdHJ1Y3RvciBmb3IgdGhlIG91dHB1dCB3cml0ZXIuIERlZmF1bHRzIHRvIFN0YW5kYXJkT3V0cHV0V3JpdGVyLlxuICogQHBhcmFtIGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBvdXRwdXQgY29uc3RydWN0b3IuXG4gKiBAcmV0dXJuIHtDb21tYW5kUmVzdWx0fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgY29tbWFuZCByZXN1bHQgb2YgdHlwZSBSLlxuICpcbiAqIEBmdW5jdGlvbiBydW5Db21tYW5kXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgcnVuQ29tbWFuZFxuICogICBwYXJ0aWNpcGFudCBPdXRwdXRXcml0ZXJcbiAqICAgcGFydGljaXBhbnQgQ2hpbGRQcm9jZXNzXG4gKiAgIENhbGxlci0+PnJ1bkNvbW1hbmQ6IENhbGwgd2l0aCBjb21tYW5kIGFuZCBvcHRpb25zXG4gKiAgIHJ1bkNvbW1hbmQtPj5PdXRwdXRXcml0ZXI6IENyZWF0ZSBuZXcgaW5zdGFuY2VcbiAqICAgcnVuQ29tbWFuZC0+Pk91dHB1dFdyaXRlcjogUGFyc2UgY29tbWFuZFxuICogICBydW5Db21tYW5kLT4+Q2hpbGRQcm9jZXNzOiBTcGF3biBwcm9jZXNzXG4gKiAgIENoaWxkUHJvY2Vzcy0tPj5ydW5Db21tYW5kOiBSZXR1cm4gcHJvY2VzcyBvYmplY3RcbiAqICAgcnVuQ29tbWFuZC0+PkNoaWxkUHJvY2VzczogU2V0IHVwIGV2ZW50IGxpc3RlbmVyc1xuICogICBsb29wIEZvciBlYWNoIHN0ZG91dCBkYXRhXG4gKiAgICAgQ2hpbGRQcm9jZXNzLT4+cnVuQ29tbWFuZDogRW1pdCBzdGRvdXQgZGF0YVxuICogICAgIHJ1bkNvbW1hbmQtPj5PdXRwdXRXcml0ZXI6IEhhbmRsZSBzdGRvdXQgZGF0YVxuICogICBlbmRcbiAqICAgbG9vcCBGb3IgZWFjaCBzdGRlcnIgZGF0YVxuICogICAgIENoaWxkUHJvY2Vzcy0+PnJ1bkNvbW1hbmQ6IEVtaXQgc3RkZXJyIGRhdGFcbiAqICAgICBydW5Db21tYW5kLT4+T3V0cHV0V3JpdGVyOiBIYW5kbGUgc3RkZXJyIGRhdGFcbiAqICAgZW5kXG4gKiAgIENoaWxkUHJvY2Vzcy0+PnJ1bkNvbW1hbmQ6IEVtaXQgZXJyb3IgKGlmIGFueSlcbiAqICAgcnVuQ29tbWFuZC0+Pk91dHB1dFdyaXRlcjogSGFuZGxlIGVycm9yXG4gKiAgIENoaWxkUHJvY2Vzcy0+PnJ1bkNvbW1hbmQ6IEVtaXQgZXhpdFxuICogICBydW5Db21tYW5kLT4+T3V0cHV0V3JpdGVyOiBIYW5kbGUgZXhpdFxuICogICBPdXRwdXRXcml0ZXItLT4+cnVuQ29tbWFuZDogUmVzb2x2ZSBvciByZWplY3QgcHJvbWlzZVxuICogICBydW5Db21tYW5kLS0+PkNhbGxlcjogUmV0dXJuIENvbW1hbmRSZXN1bHRcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBydW5Db21tYW5kPFIgPSBzdHJpbmc+KFxuICBjb21tYW5kOiBzdHJpbmcsXG4gIG9wdHM6IFNwYXduT3B0aW9uc1dpdGhvdXRTdGRpbyA9IHt9LFxuICBvdXRwdXRDb25zdHJ1Y3RvcjogT3V0cHV0V3JpdGVyQ29uc3RydWN0b3I8XG4gICAgUixcbiAgICBTdGFuZGFyZE91dHB1dFdyaXRlcjxSPixcbiAgICBFcnJvclxuICA+ID0gU3RhbmRhcmRPdXRwdXRXcml0ZXI8Uj4sXG4gIC4uLmFyZ3M6IHVua25vd25bXVxuKTogQ29tbWFuZFJlc3VsdDxSPiB7XG4gIGNvbnN0IGxvZ2dlciA9IExvZ2dpbmcuZm9yKHJ1bkNvbW1hbmQpO1xuICBjb25zdCBhYm9ydCA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblxuICBjb25zdCByZXN1bHQ6IE9taXQ8Q29tbWFuZFJlc3VsdCwgXCJwcm9taXNlXCIgfCBcInBpcGVcIj4gPSB7XG4gICAgYWJvcnQ6IGFib3J0LFxuICAgIGNvbW1hbmQ6IGNvbW1hbmQsXG4gICAgbG9nczogW10sXG4gICAgZXJyczogW10sXG4gIH07XG5cbiAgY29uc3QgbG9jayA9IG5ldyBQcm9taXNlPFI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBsZXQgb3V0cHV0O1xuICAgIHRyeSB7XG4gICAgICBvdXRwdXQgPSBuZXcgb3V0cHV0Q29uc3RydWN0b3IoXG4gICAgICAgIGNvbW1hbmQsXG4gICAgICAgIHtcbiAgICAgICAgICByZXNvbHZlLFxuICAgICAgICAgIHJlamVjdCxcbiAgICAgICAgfSxcbiAgICAgICAgLi4uYXJnc1xuICAgICAgKTtcblxuICAgICAgcmVzdWx0LmNtZCA9IHNwYXduQ29tbWFuZDxSPihvdXRwdXQsIGNvbW1hbmQsIG9wdHMsIGFib3J0LCBsb2dnZXIpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKGBFcnJvciBydW5uaW5nIGNvbW1hbmQgJHtjb21tYW5kfTogJHtlfWApKTtcbiAgICB9XG5cbiAgICByZXN1bHQuY21kLnN0ZG91dC5zZXRFbmNvZGluZyhcInV0ZjhcIik7XG5cbiAgICByZXN1bHQuY21kLnN0ZG91dC5vbihcImRhdGFcIiwgKGNodW5rOiBhbnkpID0+IHtcbiAgICAgIGNodW5rID0gY2h1bmsudG9TdHJpbmcoKTtcbiAgICAgIHJlc3VsdC5sb2dzLnB1c2goY2h1bmspO1xuICAgICAgb3V0cHV0LmRhdGEoY2h1bmspO1xuICAgIH0pO1xuXG4gICAgcmVzdWx0LmNtZC5zdGRlcnIub24oXCJkYXRhXCIsIChkYXRhOiBhbnkpID0+IHtcbiAgICAgIGRhdGEgPSBkYXRhLnRvU3RyaW5nKCk7XG4gICAgICByZXN1bHQuZXJycy5wdXNoKGRhdGEpO1xuICAgICAgb3V0cHV0LmVycm9yKGRhdGEpO1xuICAgIH0pO1xuXG4gICAgcmVzdWx0LmNtZC5vbmNlKFwiZXJyb3JcIiwgKGVycjogRXJyb3IpID0+IHtcbiAgICAgIG91dHB1dC5leGl0KGVyci5tZXNzYWdlLCByZXN1bHQuZXJycyk7XG4gICAgfSk7XG5cbiAgICByZXN1bHQuY21kLm9uY2UoXCJleGl0XCIsIChjb2RlOiBudW1iZXIgPSAwKSA9PiB7XG4gICAgICBpZiAoYWJvcnQuc2lnbmFsLmFib3J0ZWQgJiYgY29kZSA9PT0gbnVsbCkgY29kZSA9IEFib3J0Q29kZSBhcyBhbnk7XG4gICAgICBvdXRwdXQuZXhpdChjb2RlLCBjb2RlID09PSAwID8gcmVzdWx0LmxvZ3MgOiByZXN1bHQuZXJycyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIE9iamVjdC5hc3NpZ24ocmVzdWx0LCB7XG4gICAgcHJvbWlzZTogbG9jayxcbiAgICBwaXBlOiBhc3luYyA8RT4oY2I6IChyOiBSKSA9PiBFKSA9PiB7XG4gICAgICBjb25zdCBsID0gbG9nZ2VyLmZvcihcInBpcGVcIik7XG4gICAgICB0cnkge1xuICAgICAgICBsLnZlcmJvc2UoYEV4ZWN1dGluZyBwaXBlIGZ1bmN0aW9uICR7Y29tbWFuZH0uLi5gKTtcbiAgICAgICAgY29uc3QgcmVzdWx0OiBSID0gYXdhaXQgbG9jaztcbiAgICAgICAgbC52ZXJib3NlKGBQaXBpbmcgb3V0cHV0IHRvICR7Y2IubmFtZX06ICR7cmVzdWx0fWApO1xuICAgICAgICByZXR1cm4gY2IocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgICAgbC5lcnJvcihgRXJyb3IgcGlwaW5nIGNvbW1hbmQgb3V0cHV0OiAke2V9YCk7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfSxcbiAgfSk7XG5cbiAgcmV0dXJuIHJlc3VsdCBhcyBDb21tYW5kUmVzdWx0PFI+O1xufVxuIiwiaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IHJ1bkNvbW1hbmQgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgRGVwZW5kZW5jeU1hcCwgU2ltcGxlRGVwZW5kZW5jeU1hcCB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBlc2NhcGVSZWdFeHAsIExvZ2dpbmcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcbmltcG9ydCB6bGliIGZyb20gXCJ6bGliXCI7XG5cbmNvbnN0IGxvZ2dlciA9IExvZ2dpbmcuZm9yKFwiZnNcIik7XG5cbmZ1bmN0aW9uIHBhdGNoU3RyaW5nKFxuICBpbnB1dDogc3RyaW5nLFxuICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIG51bWJlciB8IHN0cmluZz4sXG4gIGZsYWdzOiBzdHJpbmcgPSBcImdcIixcbiAgZmlsdGVyPzogKHN0cjogc3RyaW5nKSA9PiBib29sZWFuXG4pOiBzdHJpbmcge1xuICBPYmplY3QuZW50cmllcyh2YWx1ZXMpLmZvckVhY2goKFtrZXksIHZhbF0pID0+IHtcbiAgICBjb25zdCByZWdleHAgPSBuZXcgUmVnRXhwKGVzY2FwZVJlZ0V4cChrZXkpLCBmbGFncyk7XG4gICAgaW5wdXQgPSBpbnB1dC5yZXBsYWNlKHJlZ2V4cCwgKHN1YlN0cjogc3RyaW5nKSA9PiB7XG4gICAgICBpZiAoIWZpbHRlciB8fCBmaWx0ZXIoc3ViU3RyKSkge1xuICAgICAgICByZXR1cm4gdmFsIGFzIHN0cmluZztcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWwgYXMgc3RyaW5nO1xuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIGlucHV0O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQYXRjaGVzIGEgZmlsZSB3aXRoIGdpdmVuIHZhbHVlcy5cbiAqIEBzdW1tYXJ5IFJlYWRzIGEgZmlsZSwgYXBwbGllcyBwYXRjaGVzIHVzaW5nIFRleHRVdGlscywgYW5kIHdyaXRlcyB0aGUgcmVzdWx0IGJhY2sgdG8gdGhlIGZpbGUuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBUaGUgcGF0aCB0byB0aGUgZmlsZSB0byBiZSBwYXRjaGVkLlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBudW1iZXIgfCBzdHJpbmc+fSB2YWx1ZXMgLSBUaGUgdmFsdWVzIHRvIHBhdGNoIGludG8gdGhlIGZpbGUuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICpcbiAqIEBmdW5jdGlvbiBwYXRjaEZpbGVcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBwYXRjaEZpbGVcbiAqICAgcGFydGljaXBhbnQgZnNcbiAqICAgcGFydGljaXBhbnQgcmVhZEZpbGVcbiAqICAgcGFydGljaXBhbnQgVGV4dFV0aWxzXG4gKiAgIHBhcnRpY2lwYW50IHdyaXRlRmlsZVxuICogICBDYWxsZXItPj5wYXRjaEZpbGU6IENhbGwgd2l0aCBwYXRoIGFuZCB2YWx1ZXNcbiAqICAgcGF0Y2hGaWxlLT4+ZnM6IENoZWNrIGlmIGZpbGUgZXhpc3RzXG4gKiAgIHBhdGNoRmlsZS0+PnJlYWRGaWxlOiBSZWFkIGZpbGUgY29udGVudFxuICogICByZWFkRmlsZS0+PmZzOiBSZWFkIGZpbGVcbiAqICAgZnMtLT4+cmVhZEZpbGU6IFJldHVybiBmaWxlIGNvbnRlbnRcbiAqICAgcmVhZEZpbGUtLT4+cGF0Y2hGaWxlOiBSZXR1cm4gZmlsZSBjb250ZW50XG4gKiAgIHBhdGNoRmlsZS0+PlRleHRVdGlsczogUGF0Y2ggc3RyaW5nXG4gKiAgIFRleHRVdGlscy0tPj5wYXRjaEZpbGU6IFJldHVybiBwYXRjaGVkIGNvbnRlbnRcbiAqICAgcGF0Y2hGaWxlLT4+d3JpdGVGaWxlOiBXcml0ZSBwYXRjaGVkIGNvbnRlbnRcbiAqICAgd3JpdGVGaWxlLT4+ZnM6IFdyaXRlIHRvIGZpbGVcbiAqICAgZnMtLT4+d3JpdGVGaWxlOiBGaWxlIHdyaXR0ZW5cbiAqICAgd3JpdGVGaWxlLS0+PnBhdGNoRmlsZTogRmlsZSB3cml0dGVuXG4gKiAgIHBhdGNoRmlsZS0tPj5DYWxsZXI6IFBhdGNoaW5nIGNvbXBsZXRlXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcGF0Y2hGaWxlKFxuICBwYXRoOiBzdHJpbmcsXG4gIHZhbHVlczogUmVjb3JkPHN0cmluZywgbnVtYmVyIHwgc3RyaW5nPixcbiAgZmlsdGVyPzogKHN0cjogc3RyaW5nKSA9PiBib29sZWFuXG4pIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihwYXRjaEZpbGUpO1xuICBpZiAoIWZzLmV4aXN0c1N5bmMocGF0aCkpXG4gICAgdGhyb3cgbmV3IEVycm9yKGBGaWxlIG5vdCBmb3VuZCBhdCBwYXRoIFwiJHtwYXRofVwiLmApO1xuICBsZXQgY29udGVudCA9IHJlYWRGaWxlKHBhdGgpO1xuXG4gIGxvZy52ZXJib3NlKGBQYXRjaGluZyBmaWxlIFwiJHtwYXRofVwiLi4uYCk7XG4gIGxvZy5kZWJ1Zyhgd2l0aCB2YWx1ZTogJHtKU09OLnN0cmluZ2lmeSh2YWx1ZXMpfWApO1xuICB0cnkge1xuICAgIGNvbnRlbnQgPSBwYXRjaFN0cmluZyhjb250ZW50LCB2YWx1ZXMsIFwiZ1wiLCBmaWx0ZXIpO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgcGF0Y2hpbmcgZmlsZTogJHtlcnJvcn1gKTtcbiAgfVxuICB3cml0ZUZpbGUocGF0aCwgY29udGVudCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlYWRzIGEgZmlsZSBhbmQgcmV0dXJucyBpdHMgY29udGVudC5cbiAqIEBzdW1tYXJ5IFJlYWRzIHRoZSBjb250ZW50IG9mIGEgZmlsZSBhdCB0aGUgc3BlY2lmaWVkIHBhdGggYW5kIHJldHVybnMgaXQgYXMgYSBzdHJpbmcuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBUaGUgcGF0aCB0byB0aGUgZmlsZSB0byBiZSByZWFkLlxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgY29udGVudCBvZiB0aGUgZmlsZS5cbiAqXG4gKiBAZnVuY3Rpb24gcmVhZEZpbGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkRmlsZShwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHJlYWRGaWxlKTtcbiAgdHJ5IHtcbiAgICBsb2cudmVyYm9zZShgUmVhZGluZyBmaWxlIFwiJHtwYXRofVwiLi4uYCk7XG4gICAgcmV0dXJuIGZzLnJlYWRGaWxlU3luYyhwYXRoLCBcInV0ZjhcIik7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoYEVycm9yIHJlYWRpbmcgZmlsZSBcIiR7cGF0aH1cIjogJHtlcnJvcn1gKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHJlYWRpbmcgZmlsZSBcIiR7cGF0aH1cIjogJHtlcnJvcn1gKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBXcml0ZXMgZGF0YSB0byBhIGZpbGUuXG4gKiBAc3VtbWFyeSBXcml0ZXMgdGhlIHByb3ZpZGVkIGRhdGEgdG8gYSBmaWxlIGF0IHRoZSBzcGVjaWZpZWQgcGF0aC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIFRoZSBwYXRoIHRvIHRoZSBmaWxlIHRvIGJlIHdyaXR0ZW4uXG4gKiBAcGFyYW0ge3N0cmluZyB8IEJ1ZmZlcn0gZGF0YSAtIFRoZSBkYXRhIHRvIGJlIHdyaXR0ZW4gdG8gdGhlIGZpbGUuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICpcbiAqIEBmdW5jdGlvbiB3cml0ZUZpbGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZUZpbGUocGF0aDogc3RyaW5nLCBkYXRhOiBzdHJpbmcgfCBCdWZmZXIpOiB2b2lkIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcih3cml0ZUZpbGUpO1xuICB0cnkge1xuICAgIGxvZy52ZXJib3NlKGBXcml0aW5nIGZpbGUgXCIke3BhdGh9IHdpdGggJHtkYXRhLmxlbmd0aH0gYnl0ZXMuLi5gKTtcbiAgICBmcy53cml0ZUZpbGVTeW5jKHBhdGgsIGRhdGEsIFwidXRmOFwiKTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShgRXJyb3Igd3JpdGluZyBmaWxlIFwiJHtwYXRofVwiOiAke2Vycm9yfWApO1xuICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd3JpdGluZyBmaWxlIFwiJHtwYXRofVwiOiAke2Vycm9yfWApO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhbGwgZmlsZXMgcmVjdXJzaXZlbHkgZnJvbSBhIGRpcmVjdG9yeS5cbiAqIEBzdW1tYXJ5IFRyYXZlcnNlcyB0aHJvdWdoIGRpcmVjdG9yaWVzIGFuZCBzdWJkaXJlY3RvcmllcyB0byBjb2xsZWN0IGFsbCBmaWxlIHBhdGhzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwIC0gVGhlIHBhdGggdG8gc3RhcnQgc2VhcmNoaW5nIGZyb20uXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBbZmlsdGVyXSAtIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGZpbHRlciBmaWxlcyBieSBuYW1lIG9yIGluZGV4LlxuICogQHJldHVybiB7c3RyaW5nW119IEFycmF5IG9mIGZpbGUgcGF0aHMuXG4gKlxuICogQGZ1bmN0aW9uIGdldEFsbEZpbGVzXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWxsRmlsZXMoXG4gIHA6IHN0cmluZyxcbiAgZmlsdGVyPzogKGY6IHN0cmluZywgaT86IG51bWJlcikgPT4gYm9vbGVhblxuKTogc3RyaW5nW10ge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKGdldEFsbEZpbGVzKTtcbiAgY29uc3QgZmlsZXM6IHN0cmluZ1tdID0gW107XG5cbiAgdHJ5IHtcbiAgICBsb2cudmVyYm9zZShgUmV0cmlldmluZyBhbGwgZmlsZXMgZnJvbSBcIiR7cH1cIi4uLmApO1xuICAgIGNvbnN0IGVudHJpZXMgPSBmcy5yZWFkZGlyU3luYyhwKTtcblxuICAgIGVudHJpZXMuZm9yRWFjaCgoZW50cnkpID0+IHtcbiAgICAgIGNvbnN0IGZ1bGxQYXRoID0gcGF0aC5qb2luKHAsIGVudHJ5KTtcbiAgICAgIGNvbnN0IHN0YXQgPSBmcy5zdGF0U3luYyhmdWxsUGF0aCk7XG5cbiAgICAgIGlmIChzdGF0LmlzRmlsZSgpKSB7XG4gICAgICAgIGZpbGVzLnB1c2goZnVsbFBhdGgpO1xuICAgICAgfSBlbHNlIGlmIChzdGF0LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgZmlsZXMucHVzaCguLi5nZXRBbGxGaWxlcyhmdWxsUGF0aCkpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmICghZmlsdGVyKSByZXR1cm4gZmlsZXM7XG4gICAgcmV0dXJuIGZpbGVzLmZpbHRlcihmaWx0ZXIpO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGxvZy52ZXJib3NlKGBFcnJvciByZXRyaWV2aW5nIGZpbGVzIGZyb20gXCIke3B9XCI6ICR7ZXJyb3J9YCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciByZXRyaWV2aW5nIGZpbGVzIGZyb20gXCIke3B9XCI6ICR7ZXJyb3J9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVuYW1lcyBhIGZpbGUgb3IgZGlyZWN0b3J5LlxuICogQHN1bW1hcnkgTW92ZXMgYSBmaWxlIG9yIGRpcmVjdG9yeSBmcm9tIHRoZSBzb3VyY2UgcGF0aCB0byB0aGUgZGVzdGluYXRpb24gcGF0aC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gVGhlIHNvdXJjZSBwYXRoIG9mIHRoZSBmaWxlIG9yIGRpcmVjdG9yeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkZXN0IC0gVGhlIGRlc3RpbmF0aW9uIHBhdGggZm9yIHRoZSBmaWxlIG9yIGRpcmVjdG9yeS5cbiAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHJlbmFtZSBvcGVyYXRpb24gaXMgY29tcGxldGUuXG4gKlxuICogQGZ1bmN0aW9uIHJlbmFtZUZpbGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZW5hbWVGaWxlKHNvdXJjZTogc3RyaW5nLCBkZXN0OiBzdHJpbmcpIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihyZW5hbWVGaWxlKTtcbiAgbGV0IGRlc2NyaXB0b3JTb3VyY2UsIGRlc2NyaXB0b3JEZXN0O1xuXG4gIHRyeSB7XG4gICAgZGVzY3JpcHRvclNvdXJjZSA9IGZzLnN0YXRTeW5jKHNvdXJjZSk7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoYFNvdXJjZSBwYXRoIFwiJHtzb3VyY2V9XCIgZG9lcyBub3QgZXhpc3Q6ICR7ZXJyb3J9YCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBTb3VyY2UgcGF0aCBcIiR7c291cmNlfVwiIGRvZXMgbm90IGV4aXN0OiAke2Vycm9yfWApO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBkZXNjcmlwdG9yRGVzdCA9IGZzLnN0YXRTeW5jKGRlc3QpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIC8vIGRvIG5vdGhpbmcuIGl0cyBva1xuICB9XG4gIGlmIChkZXNjcmlwdG9yRGVzdCkge1xuICAgIGxvZy52ZXJib3NlKGBEZXN0aW5hdGlvbiBwYXRoIFwiJHtkZXN0fVwiIGFscmVhZHkgZXhpc3RzYCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBEZXN0aW5hdGlvbiBwYXRoIFwiJHtkZXN0fVwiIGFscmVhZHkgZXhpc3RzYCk7XG4gIH1cblxuICB0cnkge1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYFJlbmFtaW5nICR7ZGVzY3JpcHRvclNvdXJjZS5pc0ZpbGUoKSA/IFwiZmlsZVwiIDogXCJkaXJlY3RvcnlcIn0gXCIke3NvdXJjZX1cIiB0byBcIiR7ZGVzdH0uLi5gXG4gICAgKTtcbiAgICBmcy5yZW5hbWVTeW5jKHNvdXJjZSwgZGVzdCk7XG4gICAgbG9nLnZlcmJvc2UoYFN1Y2Nlc3NmdWxseSByZW5hbWVkIHRvIFwiJHtkZXN0fVwiYCk7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgRXJyb3IgcmVuYW1pbmcgJHtkZXNjcmlwdG9yU291cmNlLmlzRmlsZSgpID8gXCJmaWxlXCIgOiBcImRpcmVjdG9yeVwifSBcIiR7c291cmNlfVwiIHRvIFwiJHtkZXN0fVwiOiAke2Vycm9yfWBcbiAgICApO1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBFcnJvciByZW5hbWluZyAke2Rlc2NyaXB0b3JTb3VyY2UuaXNGaWxlKCkgPyBcImZpbGVcIiA6IFwiZGlyZWN0b3J5XCJ9IFwiJHtzb3VyY2V9XCIgdG8gXCIke2Rlc3R9XCI6ICR7ZXJyb3J9YFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ29waWVzIGEgZmlsZSBvciBkaXJlY3RvcnkuXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgY29weSBvZiBhIGZpbGUgb3IgZGlyZWN0b3J5IGZyb20gdGhlIHNvdXJjZSBwYXRoIHRvIHRoZSBkZXN0aW5hdGlvbiBwYXRoLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBUaGUgc291cmNlIHBhdGggb2YgdGhlIGZpbGUgb3IgZGlyZWN0b3J5LlxuICogQHBhcmFtIHtzdHJpbmd9IGRlc3QgLSBUaGUgZGVzdGluYXRpb24gcGF0aCBmb3IgdGhlIGZpbGUgb3IgZGlyZWN0b3J5LlxuICogQHJldHVybiB7dm9pZH1cbiAqXG4gKiBAZnVuY3Rpb24gY29weUZpbGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb3B5RmlsZShzb3VyY2U6IHN0cmluZywgZGVzdDogc3RyaW5nKSB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IoY29weUZpbGUpO1xuICBsZXQgZGVzY3JpcHRvclNvdXJjZSwgZGVzY3JpcHRvckRlc3Q7XG4gIHRyeSB7XG4gICAgZGVzY3JpcHRvclNvdXJjZSA9IGZzLnN0YXRTeW5jKHNvdXJjZSk7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoYFNvdXJjZSBwYXRoIFwiJHtzb3VyY2V9XCIgZG9lcyBub3QgZXhpc3Q6ICR7ZXJyb3J9YCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBTb3VyY2UgcGF0aCBcIiR7c291cmNlfVwiIGRvZXMgbm90IGV4aXN0OiAke2Vycm9yfWApO1xuICB9XG4gIHRyeSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIGRlc2NyaXB0b3JEZXN0ID0gZnMuc3RhdFN5bmMoZGVzdCk7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGlmIChkZXNjcmlwdG9yU291cmNlLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIGxvZy52ZXJib3NlKGBEZXN0IHBhdGggXCIke2Rlc3R9XCIgZG9lcyBub3QgZXhpc3QuIGNyZWF0aW5nYCk7XG4gICAgICBmcy5ta2RpclN5bmMoZGVzdCwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgfVxuICB9XG5cbiAgdHJ5IHtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBDb3B5aW5nICR7ZGVzY3JpcHRvclNvdXJjZS5pc0ZpbGUoKSA/IFwiZmlsZVwiIDogXCJkaXJlY3RvcnlcIn0gXCIke3NvdXJjZX1cIiB0byBcIiR7ZGVzdH0uLi5gXG4gICAgKTtcbiAgICBmcy5jcFN5bmMoc291cmNlLCBkZXN0LCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBFcnJvciBjb3B5aW5nICR7ZGVzY3JpcHRvclNvdXJjZS5pc0ZpbGUoKSA/IFwiZmlsZVwiIDogXCJkaXJlY3RvcnlcIn0gXCIke3NvdXJjZX1cIiB0byBcIiR7ZGVzdH06ICR7ZXJyb3J9YFxuICAgICk7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYEVycm9yIGNvcHlpbmcgJHtkZXNjcmlwdG9yU291cmNlLmlzRmlsZSgpID8gXCJmaWxlXCIgOiBcImRpcmVjdG9yeVwifSBcIiR7c291cmNlfVwiIHRvIFwiJHtkZXN0fTogJHtlcnJvcn1gXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWxldGVzIGEgZmlsZSBvciBkaXJlY3RvcnkuXG4gKiBAc3VtbWFyeSBSZW1vdmVzIGEgZmlsZSBvciBkaXJlY3RvcnkgYXQgdGhlIHNwZWNpZmllZCBwYXRoLCB3aXRoIHJlY3Vyc2l2ZSBhbmQgZm9yY2Ugb3B0aW9ucyBlbmFibGVkLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwIC0gVGhlIHBhdGggdG8gdGhlIGZpbGUgb3IgZGlyZWN0b3J5IHRvIGRlbGV0ZS5cbiAqIEByZXR1cm4ge3ZvaWR9XG4gKlxuICogQGZ1bmN0aW9uIGRlbGV0ZVBhdGhcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWxldGVQYXRoKHA6IHN0cmluZykge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKGRlbGV0ZVBhdGgpO1xuICB0cnkge1xuICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBmcy5zdGF0U3luYyhwKTtcbiAgICBpZiAoZGVzY3JpcHRvci5pc0ZpbGUoKSkge1xuICAgICAgbG9nLnZlcmJvc2UoYERlbGV0aW5nIGZpbGUgXCIke3B9Li4uYCk7XG4gICAgICBmcy5ybVN5bmMocCwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICAgIH0gZWxzZSBpZiAoZGVzY3JpcHRvci5pc0RpcmVjdG9yeSgpKVxuICAgICAgZnMucm1TeW5jKHAsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShgRXJyb3IgRGVsZXRpbmcgXCIke3B9XCI6ICR7ZXJyb3J9YCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBEZWxldGluZyBcIiR7cH1cIjogJHtlcnJvcn1gKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgcGFja2FnZSBpbmZvcm1hdGlvbiBmcm9tIHBhY2thZ2UuanNvbi5cbiAqIEBzdW1tYXJ5IExvYWRzIGFuZCBwYXJzZXMgdGhlIHBhY2thZ2UuanNvbiBmaWxlIGZyb20gYSBzcGVjaWZpZWQgZGlyZWN0b3J5IG9yIHRoZSBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5LiBDYW4gcmV0dXJuIHRoZSBlbnRpcmUgcGFja2FnZSBvYmplY3Qgb3IgYSBzcGVjaWZpYyBwcm9wZXJ0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbcD1wcm9jZXNzLmN3ZCgpXSAtIFRoZSBkaXJlY3RvcnkgcGF0aCB3aGVyZSB0aGUgcGFja2FnZS5qc29uIGZpbGUgaXMgbG9jYXRlZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbcHJvcGVydHldIC0gT3B0aW9uYWwuIFRoZSBzcGVjaWZpYyBwcm9wZXJ0eSB0byByZXRyaWV2ZSBmcm9tIHBhY2thZ2UuanNvbi5cbiAqIEByZXR1cm4ge29iamVjdCB8IHN0cmluZ30gVGhlIHBhcnNlZCBjb250ZW50cyBvZiBwYWNrYWdlLmpzb24gb3IgdGhlIHZhbHVlIG9mIHRoZSBzcGVjaWZpZWQgcHJvcGVydHkuXG4gKiBAZnVuY3Rpb24gZ2V0UGFja2FnZVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgZ2V0UGFja2FnZVxuICogICBwYXJ0aWNpcGFudCByZWFkRmlsZVxuICogICBwYXJ0aWNpcGFudCBKU09OXG4gKiAgIENhbGxlci0+PmdldFBhY2thZ2U6IENhbGwgd2l0aCBwYXRoIGFuZCBvcHRpb25hbCBwcm9wZXJ0eVxuICogICBnZXRQYWNrYWdlLT4+cmVhZEZpbGU6IFJlYWQgcGFja2FnZS5qc29uXG4gKiAgIHJlYWRGaWxlLS0+PmdldFBhY2thZ2U6IFJldHVybiBmaWxlIGNvbnRlbnRcbiAqICAgZ2V0UGFja2FnZS0+PkpTT046IFBhcnNlIGZpbGUgY29udGVudFxuICogICBKU09OLS0+PmdldFBhY2thZ2U6IFJldHVybiBwYXJzZWQgb2JqZWN0XG4gKiAgIGFsdCBwcm9wZXJ0eSBzcGVjaWZpZWRcbiAqICAgICBnZXRQYWNrYWdlLT4+Z2V0UGFja2FnZTogQ2hlY2sgaWYgcHJvcGVydHkgZXhpc3RzXG4gKiAgICAgYWx0IHByb3BlcnR5IGV4aXN0c1xuICogICAgICAgZ2V0UGFja2FnZS0tPj5DYWxsZXI6IFJldHVybiBwcm9wZXJ0eSB2YWx1ZVxuICogICAgIGVsc2UgcHJvcGVydHkgZG9lc24ndCBleGlzdFxuICogICAgICAgZ2V0UGFja2FnZS0tPj5DYWxsZXI6IFRocm93IEVycm9yXG4gKiAgICAgZW5kXG4gKiAgIGVsc2Ugbm8gcHJvcGVydHkgc3BlY2lmaWVkXG4gKiAgICAgZ2V0UGFja2FnZS0tPj5DYWxsZXI6IFJldHVybiBlbnRpcmUgcGFja2FnZSBvYmplY3RcbiAqICAgZW5kXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQYWNrYWdlKFxuICBwOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpLFxuICBwcm9wZXJ0eT86IHN0cmluZ1xuKTogb2JqZWN0IHwgc3RyaW5nIHtcbiAgbGV0IHBrZzogYW55O1xuICB0cnkge1xuICAgIHBrZyA9IEpTT04ucGFyc2UocmVhZEZpbGUocGF0aC5qb2luKHAsIGBwYWNrYWdlLmpzb25gKSkpO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHJldHJpZXZlIHBhY2thZ2UgaW5mb3JtYXRpb25cIiAke2Vycm9yfWApO1xuICB9XG5cbiAgaWYgKHByb3BlcnR5KSB7XG4gICAgaWYgKCEocHJvcGVydHkgaW4gcGtnKSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgXCIke3Byb3BlcnR5fVwiIG5vdCBmb3VuZCBpbiBwYWNrYWdlLmpzb25gKTtcbiAgICByZXR1cm4gcGtnW3Byb3BlcnR5XSBhcyBzdHJpbmc7XG4gIH1cbiAgcmV0dXJuIHBrZztcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2V0cyBhbiBhdHRyaWJ1dGUgaW4gdGhlIHBhY2thZ2UuanNvbiBmaWxlLlxuICogQHN1bW1hcnkgVXBkYXRlcyBhIHNwZWNpZmljIGF0dHJpYnV0ZSBpbiB0aGUgcGFja2FnZS5qc29uIGZpbGUgd2l0aCB0aGUgcHJvdmlkZWQgdmFsdWUuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGF0dHIgLSBUaGUgYXR0cmlidXRlIG5hbWUgdG8gc2V0IGluIHBhY2thZ2UuanNvbi5cbiAqIEBwYXJhbSB7c3RyaW5nIHwgbnVtYmVyIHwgb2JqZWN0fSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBzZXQgZm9yIHRoZSBhdHRyaWJ1dGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gW3A9cHJvY2Vzcy5jd2QoKV0gLSBUaGUgZGlyZWN0b3J5IHBhdGggd2hlcmUgdGhlIHBhY2thZ2UuanNvbiBmaWxlIGlzIGxvY2F0ZWQuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICpcbiAqIEBmdW5jdGlvbiBzZXRQYWNrYWdlQXR0cmlidXRlXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0UGFja2FnZUF0dHJpYnV0ZShcbiAgYXR0cjogc3RyaW5nLFxuICB2YWx1ZTogc3RyaW5nLFxuICBwOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpXG4pOiB2b2lkIHtcbiAgY29uc3QgcGtnID0gZ2V0UGFja2FnZShwKSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICBwa2dbYXR0cl0gPSB2YWx1ZTtcbiAgd3JpdGVGaWxlKHBhdGguam9pbihwLCBgcGFja2FnZS5qc29uYCksIEpTT04uc3RyaW5naWZ5KHBrZywgbnVsbCwgMikpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgdGhlIHZlcnNpb24gZnJvbSBwYWNrYWdlLmpzb24uXG4gKiBAc3VtbWFyeSBBIGNvbnZlbmllbmNlIGZ1bmN0aW9uIHRoYXQgY2FsbHMgZ2V0UGFja2FnZSB0byByZXRyaWV2ZSB0aGUgXCJ2ZXJzaW9uXCIgcHJvcGVydHkgZnJvbSBwYWNrYWdlLmpzb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gW3A9cHJvY2Vzcy5jd2QoKV0gLSBUaGUgZGlyZWN0b3J5IHBhdGggd2hlcmUgdGhlIHBhY2thZ2UuanNvbiBmaWxlIGlzIGxvY2F0ZWQuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSB2ZXJzaW9uIHN0cmluZyBmcm9tIHBhY2thZ2UuanNvbi5cbiAqIEBmdW5jdGlvbiBnZXRQYWNrYWdlVmVyc2lvblxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UGFja2FnZVZlcnNpb24ocCA9IHByb2Nlc3MuY3dkKCkpOiBzdHJpbmcge1xuICByZXR1cm4gZ2V0UGFja2FnZShwLCBcInZlcnNpb25cIikgYXMgc3RyaW5nO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYWxsIGRlcGVuZGVuY2llcyBmcm9tIHRoZSBwcm9qZWN0LlxuICogQHN1bW1hcnkgRXhlY3V0ZXMgJ25wbSBscyAtLWpzb24nIGNvbW1hbmQgdG8gZ2V0IGEgZGV0YWlsZWQgbGlzdCBvZiBhbGwgZGVwZW5kZW5jaWVzIChwcm9kdWN0aW9uLCBkZXZlbG9wbWVudCwgYW5kIHBlZXIpIGFuZCB0aGVpciB2ZXJzaW9ucy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0aD1wcm9jZXNzLmN3ZCgpXSAtIFRoZSBkaXJlY3RvcnkgcGF0aCBvZiB0aGUgcHJvamVjdC5cbiAqIEByZXR1cm4ge1Byb21pc2U8e3Byb2Q6IEFycmF5PHtuYW1lOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZ30+LCBkZXY6IEFycmF5PHtuYW1lOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZ30+LCBwZWVyOiBBcnJheTx7bmFtZTogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmd9Pn0+fSBBbiBvYmplY3QgY29udGFpbmluZyBhcnJheXMgb2YgcHJvZHVjdGlvbiwgZGV2ZWxvcG1lbnQsIGFuZCBwZWVyIGRlcGVuZGVuY2llcy5cbiAqIEBmdW5jdGlvbiBnZXREZXBlbmRlbmNpZXNcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IGdldERlcGVuZGVuY2llc1xuICogICBwYXJ0aWNpcGFudCBydW5Db21tYW5kXG4gKiAgIHBhcnRpY2lwYW50IEpTT05cbiAqICAgQ2FsbGVyLT4+Z2V0RGVwZW5kZW5jaWVzOiBDYWxsIHdpdGggb3B0aW9uYWwgcGF0aFxuICogICBnZXREZXBlbmRlbmNpZXMtPj5ydW5Db21tYW5kOiBFeGVjdXRlICducG0gbHMgLS1qc29uJ1xuICogICBydW5Db21tYW5kLS0+PmdldERlcGVuZGVuY2llczogUmV0dXJuIGNvbW1hbmQgb3V0cHV0XG4gKiAgIGdldERlcGVuZGVuY2llcy0+PkpTT046IFBhcnNlIGNvbW1hbmQgb3V0cHV0XG4gKiAgIEpTT04tLT4+Z2V0RGVwZW5kZW5jaWVzOiBSZXR1cm4gcGFyc2VkIG9iamVjdFxuICogICBnZXREZXBlbmRlbmNpZXMtPj5nZXREZXBlbmRlbmNpZXM6IFByb2Nlc3MgZGVwZW5kZW5jaWVzXG4gKiAgIGdldERlcGVuZGVuY2llcy0tPj5DYWxsZXI6IFJldHVybiBwcm9jZXNzZWQgZGVwZW5kZW5jaWVzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXREZXBlbmRlbmNpZXMoXG4gIHBhdGg6IHN0cmluZyA9IHByb2Nlc3MuY3dkKClcbik6IFByb21pc2U8RGVwZW5kZW5jeU1hcD4ge1xuICBsZXQgcGtnOiBhbnk7XG5cbiAgdHJ5IHtcbiAgICBwa2cgPSBKU09OLnBhcnNlKGF3YWl0IHJ1bkNvbW1hbmQoYG5wbSBscyAtLWpzb25gLCB7IGN3ZDogcGF0aCB9KS5wcm9taXNlKTtcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHJldHJpZXZlIGRlcGVuZGVuY2llczogJHtlfWApO1xuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBjb25zdCBtYXBwZXIgPSAoZW50cnk6IFtzdHJpbmcsIHVua25vd25dLCBpbmRleDogbnVtYmVyKSA9PiAoe1xuICAgIG5hbWU6IGVudHJ5WzBdLFxuICAgIHZlcnNpb246IChlbnRyeVsxXSBhcyBhbnkpLnZlcnNpb24sXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgcHJvZDogT2JqZWN0LmVudHJpZXMocGtnLmRlcGVuZGVuY2llcyB8fCB7fSkubWFwKG1hcHBlciksXG4gICAgZGV2OiBPYmplY3QuZW50cmllcyhwa2cuZGV2RGVwZW5kZW5jaWVzIHx8IHt9KS5tYXAobWFwcGVyKSxcbiAgICBwZWVyOiBPYmplY3QuZW50cmllcyhwa2cucGVlckRlcGVuZGVuY2llcyB8fCB7fSkubWFwKG1hcHBlciksXG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgcHJvamVjdCBkZXBlbmRlbmNpZXMgdG8gdGhlaXIgbGF0ZXN0IHZlcnNpb25zLlxuICogQHN1bW1hcnkgUnVucyBucG0tY2hlY2stdXBkYXRlcyB0byB1cGRhdGUgcGFja2FnZS5qc29uIGFuZCB0aGVuIGluc3RhbGxzIHRoZSB1cGRhdGVkIGRlcGVuZGVuY2llcy5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGRlcGVuZGVuY2llcyBhcmUgdXBkYXRlZC5cbiAqXG4gKiBAZnVuY3Rpb24gdXBkYXRlRGVwZW5kZW5jaWVzXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdXBkYXRlRGVwZW5kZW5jaWVzKCkge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHVwZGF0ZURlcGVuZGVuY2llcyk7XG4gIGxvZy5pbmZvKFwiY2hlY2tpbmcgZm9yIHVwZGF0ZXMuLi5cIik7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoXCJucHggbnBtLWNoZWNrLXVwZGF0ZXMgLXVcIikucHJvbWlzZTtcbiAgbG9nLmluZm8oXCJ1cGRhdGluZy4uLlwiKTtcbiAgYXdhaXQgcnVuQ29tbWFuZChcIm5weCBucG0gcnVuIGRvLWluc3RhbGxcIikucHJvbWlzZTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSW5zdGFsbHMgZGVwZW5kZW5jaWVzIGlmIHRoZXkgYXJlIG5vdCBhbHJlYWR5IGF2YWlsYWJsZS5cbiAqIEBzdW1tYXJ5IENoZWNrcyBpZiBzcGVjaWZpZWQgZGVwZW5kZW5jaWVzIGFyZSBpbnN0YWxsZWQgYW5kIGluc3RhbGxzIGFueSB0aGF0IGFyZSBtaXNzaW5nLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nW10gfCBzdHJpbmd9IGRlcHMgLSBUaGUgZGVwZW5kZW5jaWVzIHRvIGNoZWNrIGFuZCBwb3RlbnRpYWxseSBpbnN0YWxsLlxuICogQHBhcmFtIHtTaW1wbGVEZXBlbmRlbmN5TWFwfSBbZGVwZW5kZW5jaWVzXSAtIE9wdGlvbmFsIG1hcCBvZiBleGlzdGluZyBkZXBlbmRlbmNpZXMuXG4gKiBAcmV0dXJuIHtQcm9taXNlPFNpbXBsZURlcGVuZGVuY3lNYXA+fSBVcGRhdGVkIG1hcCBvZiBkZXBlbmRlbmNpZXMuXG4gKlxuICogQGZ1bmN0aW9uIGluc3RhbGxJZk5vdEF2YWlsYWJsZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGluc3RhbGxJZk5vdEF2YWlsYWJsZShcbiAgZGVwczogc3RyaW5nW10gfCBzdHJpbmcsXG4gIGRlcGVuZGVuY2llcz86IFNpbXBsZURlcGVuZGVuY3lNYXBcbikge1xuICBpZiAoIWRlcGVuZGVuY2llcykge1xuICAgIGNvbnN0IGQ6IERlcGVuZGVuY3lNYXAgPSBhd2FpdCBnZXREZXBlbmRlbmNpZXMoKTtcbiAgICBkZXBlbmRlbmNpZXMgPSB7XG4gICAgICBwcm9kOiBkLnByb2Q/Lm1hcCgocCkgPT4gcC5uYW1lKSB8fCBbXSxcbiAgICAgIGRldjogZC5kZXY/Lm1hcCgoZCkgPT4gZC5uYW1lKSB8fCBbXSxcbiAgICAgIHBlZXI6IGQucGVlcj8ubWFwKChwKSA9PiBwLm5hbWUpIHx8IFtdLFxuICAgIH07XG4gIH1cbiAgY29uc3QgeyBwcm9kLCBkZXYsIHBlZXIgfSA9IGRlcGVuZGVuY2llcztcbiAgY29uc3QgaW5zdGFsbGVkID0gQXJyYXkuZnJvbShcbiAgICBuZXcgU2V0KFsuLi4ocHJvZCB8fCBbXSksIC4uLihkZXYgfHwgW10pLCAuLi4ocGVlciB8fCBbXSldKVxuICApO1xuICBkZXBzID0gdHlwZW9mIGRlcHMgPT09IFwic3RyaW5nXCIgPyBbZGVwc10gOiBkZXBzO1xuICBjb25zdCB0b0luc3RhbGwgPSBkZXBzLmZpbHRlcigoZCkgPT4gIWluc3RhbGxlZC5pbmNsdWRlcyhkKSk7XG5cbiAgaWYgKHRvSW5zdGFsbC5sZW5ndGgpIGF3YWl0IGluc3RhbGxEZXBlbmRlbmNpZXMoeyBkZXY6IHRvSW5zdGFsbCB9KTtcbiAgZGVwZW5kZW5jaWVzLmRldiA9IGRlcGVuZGVuY2llcy5kZXYgfHwgW107XG4gIGRlcGVuZGVuY2llcy5kZXYucHVzaCguLi50b0luc3RhbGwpO1xuICByZXR1cm4gZGVwZW5kZW5jaWVzO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQdXNoZXMgY2hhbmdlcyB0byBHaXQgcmVwb3NpdG9yeS5cbiAqIEBzdW1tYXJ5IFRlbXBvcmFyaWx5IGNoYW5nZXMgR2l0IHVzZXIgY29uZmlndXJhdGlvbiwgY29tbWl0cyBhbGwgY2hhbmdlcywgcHVzaGVzIHRvIHJlbW90ZSwgYW5kIHJlc3RvcmVzIG9yaWdpbmFsIHVzZXIgY29uZmlndXJhdGlvbi5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGNoYW5nZXMgYXJlIHB1c2hlZC5cbiAqXG4gKiBAZnVuY3Rpb24gcHVzaFRvR2l0XG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHVzaFRvR2l0KCkge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHB1c2hUb0dpdCk7XG4gIGNvbnN0IGdpdFVzZXIgPSBhd2FpdCBydW5Db21tYW5kKFwiZ2l0IGNvbmZpZyB1c2VyLm5hbWVcIikucHJvbWlzZTtcbiAgY29uc3QgZ2l0RW1haWwgPSBhd2FpdCBydW5Db21tYW5kKFwiZ2l0IGNvbmZpZyB1c2VyLmVtYWlsXCIpLnByb21pc2U7XG4gIGxvZy52ZXJib3NlKGBjYWNoZWQgZ2l0IGlkOiAke2dpdFVzZXJ9LyR7Z2l0RW1haWx9LiBjaGFuZ2luZyB0byBhdXRvbWF0aW9uYCk7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoJ2dpdCBjb25maWcgdXNlci5lbWFpbCBcImF1dG9tYXRpb25AZGVjYWYudHNcIicpLnByb21pc2U7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoJ2dpdCBjb25maWcgdXNlci5uYW1lIFwiZGVjYWZcIicpLnByb21pc2U7XG4gIGxvZy5pbmZvKFwiUHVzaGluZyBjaGFuZ2VzIHRvIGdpdC4uLlwiKTtcbiAgYXdhaXQgcnVuQ29tbWFuZChcImdpdCBhZGQgLlwiKS5wcm9taXNlO1xuICBhd2FpdCBydW5Db21tYW5kKGBnaXQgY29tbWl0IC1tIFwicmVmcyAjMSAtIGFmdGVyIHJlcG8gc2V0dXBcImApLnByb21pc2U7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoXCJnaXQgcHVzaFwiKS5wcm9taXNlO1xuICBhd2FpdCBydW5Db21tYW5kKGBnaXQgY29uZmlnIHVzZXIuZW1haWwgXCIke2dpdEVtYWlsfVwiYCkucHJvbWlzZTtcbiAgYXdhaXQgcnVuQ29tbWFuZChgZ2l0IGNvbmZpZyB1c2VyLm5hbWUgXCIke2dpdFVzZXJ9XCJgKS5wcm9taXNlO1xuICBsb2cudmVyYm9zZShgcmV2ZXJ0ZWQgdG8gZ2l0IGlkOiAke2dpdFVzZXJ9LyR7Z2l0RW1haWx9YCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEluc3RhbGxzIHByb2plY3QgZGVwZW5kZW5jaWVzLlxuICogQHN1bW1hcnkgSW5zdGFsbHMgcHJvZHVjdGlvbiwgZGV2ZWxvcG1lbnQsIGFuZCBwZWVyIGRlcGVuZGVuY2llcyBhcyBzcGVjaWZpZWQuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGRlcGVuZGVuY2llcyAtIE9iamVjdCBjb250YWluaW5nIGFycmF5cyBvZiBkZXBlbmRlbmNpZXMgdG8gaW5zdGFsbC5cbiAqIEBwYXJhbSB7c3RyaW5nW119IFtkZXBlbmRlbmNpZXMucHJvZF0gLSBQcm9kdWN0aW9uIGRlcGVuZGVuY2llcyB0byBpbnN0YWxsLlxuICogQHBhcmFtIHtzdHJpbmdbXX0gW2RlcGVuZGVuY2llcy5kZXZdIC0gRGV2ZWxvcG1lbnQgZGVwZW5kZW5jaWVzIHRvIGluc3RhbGwuXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBbZGVwZW5kZW5jaWVzLnBlZXJdIC0gUGVlciBkZXBlbmRlbmNpZXMgdG8gaW5zdGFsbC5cbiAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIGRlcGVuZGVuY2llcyBhcmUgaW5zdGFsbGVkLlxuICpcbiAqIEBmdW5jdGlvbiBpbnN0YWxsRGVwZW5kZW5jaWVzXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW5zdGFsbERlcGVuZGVuY2llcyhkZXBlbmRlbmNpZXM6IHtcbiAgcHJvZD86IHN0cmluZ1tdO1xuICBkZXY/OiBzdHJpbmdbXTtcbiAgcGVlcj86IHN0cmluZ1tdO1xufSkge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKGluc3RhbGxEZXBlbmRlbmNpZXMpO1xuICBjb25zdCBwcm9kID0gZGVwZW5kZW5jaWVzLnByb2QgfHwgW107XG4gIGNvbnN0IGRldiA9IGRlcGVuZGVuY2llcy5kZXYgfHwgW107XG4gIGNvbnN0IHBlZXIgPSBkZXBlbmRlbmNpZXMucGVlciB8fCBbXTtcbiAgaWYgKHByb2QubGVuZ3RoKSB7XG4gICAgbG9nLmluZm8oYEluc3RhbGxpbmcgZGVwZW5kZW5jaWVzICR7cHJvZC5qb2luKFwiLCBcIil9Li4uYCk7XG4gICAgYXdhaXQgcnVuQ29tbWFuZChgbnBtIGluc3RhbGwgJHtwcm9kLmpvaW4oXCIgXCIpfWAsIHsgY3dkOiBwcm9jZXNzLmN3ZCgpIH0pXG4gICAgICAucHJvbWlzZTtcbiAgfVxuICBpZiAoZGV2Lmxlbmd0aCkge1xuICAgIGxvZy5pbmZvKGBJbnN0YWxsaW5nIGRldkRlcGVuZGVuY2llcyAke2Rldi5qb2luKFwiLCBcIil9Li4uYCk7XG4gICAgYXdhaXQgcnVuQ29tbWFuZChgbnBtIGluc3RhbGwgLS1zYXZlLWRldiAke2Rldi5qb2luKFwiIFwiKX1gLCB7XG4gICAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgfSkucHJvbWlzZTtcbiAgfVxuICBpZiAocGVlci5sZW5ndGgpIHtcbiAgICBsb2cuaW5mbyhgSW5zdGFsbGluZyBwZWVyRGVwZW5kZW5jaWVzICR7cGVlci5qb2luKFwiLCBcIil9Li4uYCk7XG4gICAgYXdhaXQgcnVuQ29tbWFuZChgbnBtIGluc3RhbGwgLS1zYXZlLXBlZXIgJHtwZWVyLmpvaW4oXCIgXCIpfWAsIHtcbiAgICAgIGN3ZDogcHJvY2Vzcy5jd2QoKSxcbiAgICB9KS5wcm9taXNlO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIE5vcm1hbGl6ZXMgaW1wb3J0cyB0byBoYW5kbGUgYm90aCBDb21tb25KUyBhbmQgRVNNb2R1bGUgZm9ybWF0cy5cbiAqIEBzdW1tYXJ5IFV0aWxpdHkgZnVuY3Rpb24gdG8gaGFuZGxlIG1vZHVsZSBpbXBvcnQgZGlmZmVyZW5jZXMgYmV0d2VlbiBmb3JtYXRzLlxuICpcbiAqIEB0ZW1wbGF0ZSBUIC0gVHlwZSBvZiB0aGUgaW1wb3J0ZWQgbW9kdWxlLlxuICogQHBhcmFtIHtQcm9taXNlPFQ+fSBpbXBvcnRQcm9taXNlIC0gUHJvbWlzZSByZXR1cm5lZCBieSBkeW5hbWljIGltcG9ydC5cbiAqIEByZXR1cm4ge1Byb21pc2U8VD59IE5vcm1hbGl6ZWQgbW9kdWxlLlxuICpcbiAqIEBmdW5jdGlvbiBub3JtYWxpemVJbXBvcnRcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBub3JtYWxpemVJbXBvcnQ8VD4oXG4gIGltcG9ydFByb21pc2U6IFByb21pc2U8VD5cbik6IFByb21pc2U8VD4ge1xuICAvLyBDb21tb25KUydzIGBtb2R1bGUuZXhwb3J0c2AgaXMgd3JhcHBlZCBhcyBgZGVmYXVsdGAgaW4gRVNNb2R1bGUuXG4gIHJldHVybiBpbXBvcnRQcm9taXNlLnRoZW4oKG06IGFueSkgPT4gKG0uZGVmYXVsdCB8fCBtKSBhcyBUKTtcbn1cblxuLy8gTmV3IGhlbHBlcjogY29tcHV0ZSBnemlwcGVkIHNpemUgb2Ygc21hbGxlc3QgSlMgZmlsZSBpbiBhIGRpcmVjdG9yeVxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEZpbGVTaXplWmlwcGVkKGRpcjogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihnZXRGaWxlU2l6ZVppcHBlZCk7XG4gIHRyeSB7XG4gICAgY29uc3QgZW50cmllcyA9IGZzLnJlYWRkaXJTeW5jKGRpcik7XG4gICAgY29uc3QgY2FuZGlkYXRlcyA9IGVudHJpZXNcbiAgICAgIC5tYXAoKGUpID0+IHBhdGguam9pbihkaXIsIGUpKVxuICAgICAgLmZpbHRlcigocCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHMgPSBmcy5zdGF0U3luYyhwKTtcbiAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgcy5pc0ZpbGUoKSAmJlxuICAgICAgICAgICAgKHAuZW5kc1dpdGgoXCIuanNcIikgfHwgcC5lbmRzV2l0aChcIi5janNcIikgfHwgcC5lbmRzV2l0aChcIi5tanNcIikpXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgIGlmIChjYW5kaWRhdGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBKUyBmaWxlcyBmb3VuZCBpbiBkaXJlY3RvcnkgJHtkaXJ9YCk7XG4gICAgfVxuXG4gICAgLy8gY2hvb3NlIHRoZSBzbWFsbGVzdCBieSByYXcgZmlsZSBzaXplXG4gICAgbGV0IHNtYWxsZXN0ID0gY2FuZGlkYXRlc1swXTtcbiAgICBsZXQgc21hbGxlc3RTaXplID0gZnMuc3RhdFN5bmMoc21hbGxlc3QpLnNpemU7XG4gICAgZm9yIChjb25zdCBjIG9mIGNhbmRpZGF0ZXMuc2xpY2UoMSkpIHtcbiAgICAgIGNvbnN0IHMgPSBmcy5zdGF0U3luYyhjKS5zaXplO1xuICAgICAgaWYgKHMgPCBzbWFsbGVzdFNpemUpIHtcbiAgICAgICAgc21hbGxlc3QgPSBjO1xuICAgICAgICBzbWFsbGVzdFNpemUgPSBzO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYFNlbGVjdGVkIHNtYWxsZXN0IGJ1bmRsZTogJHtzbWFsbGVzdH0gKCR7c21hbGxlc3RTaXplfSBieXRlcylgXG4gICAgKTtcblxuICAgIGNvbnN0IGJ1ZmZlciA9IGZzLnJlYWRGaWxlU3luYyhzbWFsbGVzdCk7XG4gICAgY29uc3QgZ3ogPSB6bGliLmd6aXBTeW5jKGJ1ZmZlcik7XG4gICAgY29uc3Qgc2l6ZUtiID0gTnVtYmVyKChnei5sZW5ndGggLyAxMDI0KS50b0ZpeGVkKDEpKTtcbiAgICBsb2cudmVyYm9zZShgR3ppcHBlZCBzaXplOiAke2d6Lmxlbmd0aH0gYnl0ZXMgKCR7c2l6ZUtifSBLQilgKTtcbiAgICByZXR1cm4gc2l6ZUtiO1xuICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoYEZhaWxlZCB0byBjb21wdXRlIGd6aXBwZWQgc2l6ZSBmb3IgJHtkaXJ9OiAke2V9YCk7XG4gICAgdGhyb3cgZSBhcyBFcnJvcjtcbiAgfVxufVxuXG4vLyBOZXcgaGVscGVyOiBsaXN0IGZvbGRlciBlbnRyaWVzIChuYW1lcykgd2l0aCBvcHRpb25hbCBmaWx0ZXJcbmV4cG9ydCBmdW5jdGlvbiBsaXN0Rm9sZGVyKFxuICBiYXNlUGF0aDogc3RyaW5nID0gcHJvY2Vzcy5jd2QoKSxcbiAgZmlsdGVyPzogKG5hbWU6IHN0cmluZywgZGlyZW50OiBmcy5EaXJlbnQpID0+IGJvb2xlYW5cbik6IHN0cmluZ1tdIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihsaXN0Rm9sZGVyKTtcbiAgdHJ5IHtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoYmFzZVBhdGgpKSByZXR1cm4gW107XG4gICAgY29uc3QgZW50cmllcyA9IGZzLnJlYWRkaXJTeW5jKGJhc2VQYXRoLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gICAgY29uc3QgbmFtZXMgPSBlbnRyaWVzXG4gICAgICAuZmlsdGVyKChkKSA9PiAoZmlsdGVyID8gZmlsdGVyKGQubmFtZSwgZCkgOiB0cnVlKSlcbiAgICAgIC5tYXAoKGQpID0+IGQubmFtZSk7XG4gICAgcmV0dXJuIG5hbWVzO1xuICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoYEZhaWxlZCB0byBsaXN0IGZvbGRlciAke2Jhc2VQYXRofTogJHtlfWApO1xuICAgIHJldHVybiBbXTtcbiAgfVxufVxuXG4vLyBOZXcgaGVscGVyOiBsaXN0IG5vZGVfbW9kdWxlcyBwYWNrYWdlIG5hbWVzLCBleHBhbmRpbmcgc2NvcGVkIHBhY2thZ2VzXG5leHBvcnQgZnVuY3Rpb24gbGlzdE5vZGVNb2R1bGVzUGFja2FnZXMoXG4gIGJhc2VQYXRoOiBzdHJpbmcgPSBwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgXCJub2RlX21vZHVsZXNcIilcbik6IHN0cmluZ1tdIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihsaXN0Tm9kZU1vZHVsZXNQYWNrYWdlcyk7XG4gIHRyeSB7XG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKGJhc2VQYXRoKSkgcmV0dXJuIFtdO1xuICAgIGNvbnN0IGVudHJpZXMgPSBmcy5yZWFkZGlyU3luYyhiYXNlUGF0aCwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pO1xuICAgIGNvbnN0IG5hbWVzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgZm9yIChjb25zdCBlIG9mIGVudHJpZXMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmICghZS5pc0RpcmVjdG9yeSgpKSBjb250aW51ZTtcbiAgICAgICAgLy8gaWdub3JlIGhpZGRlbiBmb2xkZXJzXG4gICAgICAgIGlmIChlLm5hbWUuc3RhcnRzV2l0aChcIi5cIikpIGNvbnRpbnVlO1xuICAgICAgICBpZiAoZS5uYW1lLnN0YXJ0c1dpdGgoXCJAXCIpKSB7XG4gICAgICAgICAgLy8gYSBzY29wZSBmb2xkZXI7IGV4cGFuZCBjb250YWluZWQgcGFja2FnZXNcbiAgICAgICAgICBjb25zdCBzY29wZVBhdGggPSBwYXRoLmpvaW4oYmFzZVBhdGgsIGUubmFtZSk7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHNjb3BlZCA9IGZzLnJlYWRkaXJTeW5jKHNjb3BlUGF0aCwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pO1xuICAgICAgICAgICAgZm9yIChjb25zdCBzIG9mIHNjb3BlZCkge1xuICAgICAgICAgICAgICBpZiAocy5pc0RpcmVjdG9yeSgpICYmICFzLm5hbWUuc3RhcnRzV2l0aChcIi5cIikpIHtcbiAgICAgICAgICAgICAgICBuYW1lcy5wdXNoKGAke2UubmFtZX0vJHtzLm5hbWV9YCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIC8vIGlnbm9yZSBzY29wZSByZWFkIGVycm9yc1xuICAgICAgICAgICAgbG9nLnZlcmJvc2UoYEZhaWxlZCB0byByZWFkIHNjb3BlICR7c2NvcGVQYXRofTogJHtlcnJ9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5hbWVzLnB1c2goZS5uYW1lKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGxvZy52ZXJib3NlKGBTa2lwcGluZyBlbnRyeSAke2UubmFtZX0gZHVlIHRvIGVycm9yOiAke2Vycn1gKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5hbWVzO1xuICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoYEZhaWxlZCB0byBsaXN0IG5vZGVfbW9kdWxlcyBwYWNrYWdlcyBhdCAke2Jhc2VQYXRofTogJHtlfWApO1xuICAgIHJldHVybiBbXTtcbiAgfVxufVxuIiwiLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVmaW5pdGlvbiBvZiBhIHNsb2dhbiBpdGVtLlxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIHNpbmdsZSBzbG9nYW4gZW50cnkgd2l0aCB0ZXh0IGFuZCB0YWdzLlxuICogQHR5cGVkZWYge09iamVjdH0gU2xvZ2FuSXRlbVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFNsb2dhbiAtIFRoZSBzbG9nYW4gdGV4dC5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBUYWdzIC0gQ29tbWEtc2VwYXJhdGVkIHRhZ3MgZGVzY3JpYmluZyB0aGUgc2xvZ2FuLlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIExpc3Qgb2YgYXZhaWxhYmxlIHNsb2dhbnMgZm9yIGJhbm5lcnMgYW5kIG1lc3NhZ2VzLlxuICogQHN1bW1hcnkgSW1tdXRhYmxlIGFycmF5IG9mIHNsb2dhbiBlbnRyaWVzIHVzZWQgYnkge0BsaW5rIGdldFNsb2dhbn0gYW5kIGJhbm5lciByZW5kZXJpbmcuXG4gKiBAdHlwZSB7U2xvZ2FuSXRlbVtdfVxuICogQGNvbnN0IHNsb2dhbnNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IHNsb2dhbnMgPSBbXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXQncyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0XFx1MjAxOXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdFxcdTIwMTlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXRcXHUyMDE5cyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0XFx1MjAxOXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdFxcdTIwMTlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXRcXHUyMDE5cyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0XFx1MjAxOXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdFxcdTIwMTlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXRcXHUyMDE5cyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBXaGVyZSBzbWFydCBjb250cmFjdHMgbWVldCBzbWFydCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgU21hcnQgQ29udHJhY3RzLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2hpcCBkQXBwcyB3aXRob3V0IHRoZSBzdHJlc3MuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBDaGVlcmZ1bCwgRGV2ZWxvcGVyXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gQ1JVRCwgbm8gcHJvYmxlbSBcXHUyMDE0IERlY2FmIHlvdXIgZGF0YS5cIixcbiAgICBUYWdzOiBcIkRhdGEsIE5vLUNSVUQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBESUQgdG8gVUksIHdpdGhvdXQgYnJlYWtpbmcgYSBzd2VhdC5cIixcbiAgICBUYWdzOiBcIkRJRCwgU1NJLCBVSSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBZb3VyIGZyb250ZW5kIGFscmVhZHkgdW5kZXJzdGFuZHMgeW91ciBzbWFydCBjb250cmFjdC5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgRFgsIE1hZ2ljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2VsZi1zb3ZlcmVpZ24gYnkgZGVzaWduLiBQcm9kdWN0aXZlIGJ5IGRlZmF1bHQuXCIsXG4gICAgVGFnczogXCJTU0ksIERldmVsb3BlciwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJ1aWxkIG9uY2UuIERlcGxveSBldmVyeXdoZXJlLiBEZWNlbnRyYWxpemVkIGFuZCBkZWxpZ2h0ZnVsLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgTXVsdGktcGxhdGZvcm0sIEhhcHB5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGF0YSB0aGF0IGRlZmluZXMgaXRzIG93biBkZXN0aW55LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEYXRhLWRyaXZlbiwgRW1wb3dlcm1lbnRcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJHb29kYnllIENSVUQsIGhlbGxvIGludGVudC1iYXNlZCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgVUksIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBzbW9vdGhlc3QgcGF0aCBmcm9tIERJRCB0byBkb25lLlwiLFxuICAgIFRhZ3M6IFwiRElELCBXb3JrZmxvdywgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCZWNhdXNlIHlvdXIgZEFwcCBkZXNlcnZlcyBtb3JlIHRoYW4gYm9pbGVycGxhdGUuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBEZXZYLCBFZmZpY2llbmN5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiT3duIHlvdXIgZGF0YS4gT3duIHlvdXIgZmxvdy5cIixcbiAgICBUYWdzOiBcIlNTSSwgQ29udHJvbCwgT3duZXJzaGlwXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiV3JpdGUgbG9naWMgbGlrZSBpdCBiZWxvbmdzIHdpdGggdGhlIGRhdGEgXFx1MjAxNCBiZWNhdXNlIGl0IGRvZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBEZXZlbG9wZXIsIFNtYXJ0XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBzbWFydCBjb250cmFjdHMgdG8gc21hcnRlciBmcm9udGVuZHMuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIFVJLCBEWFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLiBObyBDUlVELiBKdXN0IHRoZSBmdXR1cmUuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBDb2ZmZWUtdGhlbWVkLCBGdXR1cmlzdGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIGZ1dHVyZSBvZiB3ZWIzIFVYIGlzIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgVVgsIFZpc2lvblwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aCBjb25maWRlbmNlLiBHb3Zlcm4gd2l0aCBjbGFyaXR5LlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgR292ZXJuYW5jZSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkludGVyZmFjZXMgdGhhdCBvYmV5IHRoZSBkYXRhLCBub3QgdGhlIG90aGVyIHdheSBhcm91bmQuXCIsXG4gICAgVGFnczogXCJVSSwgRGF0YSBMb2dpYywgU2VsZi1hd2FyZVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJyZXcgYnVzaW5lc3MgbG9naWMgcmlnaHQgaW50byB5b3VyIGJ5dGVzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRElEcyBkb25lIGRpZmZlcmVudGx5IFxcdTIwMTQgYW5kIGRlbGlnaHRmdWxseS5cIixcbiAgICBUYWdzOiBcIkRJRCwgU2VsZi1Tb3ZlcmVpZ24sIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUy1UUzogV2hlcmUgYmxvY2tjaGFpbiBjb250cmFjdHMgbWVldCBzbWFydCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgU21hcnQgQ29udHJhY3RzLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2hpcCBkQXBwcyB3aXRob3V0IHRoZSBzdHJlc3MuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBDaGVlcmZ1bCwgRGV2ZWxvcGVyXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gYm9pbGVycGxhdGUsIG5vIHByb2JsZW0gXFx1MjAxNCBEZWNhZi1UUyB5b3VyIGRhdGEuXCIsXG4gICAgVGFnczogXCJEYXRhLCBOby1DUlVELCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gRElEIHRvIFVJLCB3aXRob3V0IGJyZWFraW5nIGEgc3dlYXQuXCIsXG4gICAgVGFnczogXCJESUQsIFNTSSwgVUksIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjpcbiAgICAgIFwiRGVjYWYtVFMtVFM6IFlvdXIgZnJvbnRlbmQgYWxyZWFkeSB1bmRlcnN0YW5kcyB5b3VyIGJsb2NrY2hhaW4gY29udHJhY3QuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIERYLCBNYWdpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNlbGYtc292ZXJlaWduIGJ5IGRlc2lnbi4gUHJvZHVjdGl2ZSBieSBkZWZhdWx0LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEZXZlbG9wZXIsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCdWlsZCBvbmNlLiBEZXBsb3kgZXZlcnl3aGVyZS4gRGVjZW50cmFsaXplZCBhbmQgZGVsaWdodGZ1bC5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIE11bHRpLXBsYXRmb3JtLCBIYXBweVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRhdGEgdGhhdCBkZWZpbmVzIGl0cyBvd24gZGVzdGlueS5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGF0YS1kcml2ZW4sIEVtcG93ZXJtZW50XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiR29vZGJ5ZSBib2lsZXJwbGF0ZSwgaGVsbG8gaW50ZW50LWJhc2VkIGludGVyZmFjZXMuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBVSSwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIHNtb290aGVzdCBwYXRoIGZyb20gRElEIHRvIGRvbmUuXCIsXG4gICAgVGFnczogXCJESUQsIFdvcmtmbG93LCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJlY2F1c2UgeW91ciBkQXBwIGRlc2VydmVzIG1vcmUgdGhhbiBib2lsZXJwbGF0ZS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIERldlgsIEVmZmljaWVuY3lcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJPd24geW91ciBkYXRhLiBPd24geW91ciBmbG93LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBDb250cm9sLCBPd25lcnNoaXBcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJXcml0ZSBsb2dpYyBsaWtlIGl0IGJlbG9uZ3Mgd2l0aCB0aGUgZGF0YSBcXHUyMDE0IGJlY2F1c2UgaXQgZG9lcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIERldmVsb3BlciwgU21hcnRcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIGJsb2NrY2hhaW4gY29udHJhY3RzIHRvIHNtYXJ0ZXIgZnJvbnRlbmRzLlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBVSSwgRFhcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZS4gTm8gYm9pbGVycGxhdGUuIEp1c3QgdGhlIGZ1dHVyZS5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIENvZmZlZS10aGVtZWQsIEZ1dHVyaXN0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgZnV0dXJlIG9mIHdlYjMgVVggaXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBVWCwgVmlzaW9uXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRoIGNvbmZpZGVuY2UuIEdvdmVybiB3aXRoIGNsYXJpdHkuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBHb3Zlcm5hbmNlLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiSW50ZXJmYWNlcyB0aGF0IG9iZXkgdGhlIGRhdGEsIG5vdCB0aGUgb3RoZXIgd2F5IGFyb3VuZC5cIixcbiAgICBUYWdzOiBcIlVJLCBEYXRhIExvZ2ljLCBTZWxmLWF3YXJlXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnJldyBidXNpbmVzcyBsb2dpYyByaWdodCBpbnRvIHlvdXIgYnl0ZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJESURzIGRvbmUgZGlmZmVyZW50bHkgXFx1MjAxNCBhbmQgZGVsaWdodGZ1bGx5LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTZWxmLVNvdmVyZWlnbiwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTLVRTOiBXaGVyZSBibG9ja2NoYWluIGNvbnRyYWN0cyBtZWV0IHNtYXJ0IGludGVyZmFjZXMuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBTbWFydCBDb250cmFjdHMsIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaGlwIGRBcHBzIHdpdGhvdXQgdGhlIHN0cmVzcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIENoZWVyZnVsLCBEZXZlbG9wZXJcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBib2lsZXJwbGF0ZSwgbm8gcHJvYmxlbSBcXHUyMDE0IERlY2FmLVRTIHlvdXIgZGF0YS5cIixcbiAgICBUYWdzOiBcIkRhdGEsIE5vLUNSVUQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBESUQgdG8gVUksIHdpdGhvdXQgYnJlYWtpbmcgYSBzd2VhdC5cIixcbiAgICBUYWdzOiBcIkRJRCwgU1NJLCBVSSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOlxuICAgICAgXCJEZWNhZi1UUy1UUzogWW91ciBmcm9udGVuZCBhbHJlYWR5IHVuZGVyc3RhbmRzIHlvdXIgYmxvY2tjaGFpbiBjb250cmFjdC5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgRFgsIE1hZ2ljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2VsZi1zb3ZlcmVpZ24gYnkgZGVzaWduLiBQcm9kdWN0aXZlIGJ5IGRlZmF1bHQuXCIsXG4gICAgVGFnczogXCJTU0ksIERldmVsb3BlciwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJ1aWxkIG9uY2UuIERlcGxveSBldmVyeXdoZXJlLiBEZWNlbnRyYWxpemVkIGFuZCBkZWxpZ2h0ZnVsLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgTXVsdGktcGxhdGZvcm0sIEhhcHB5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGF0YSB0aGF0IGRlZmluZXMgaXRzIG93biBkZXN0aW55LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEYXRhLWRyaXZlbiwgRW1wb3dlcm1lbnRcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJHb29kYnllIGJvaWxlcnBsYXRlLCBoZWxsbyBpbnRlbnQtYmFzZWQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIFVJLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgc21vb3RoZXN0IHBhdGggZnJvbSBESUQgdG8gZG9uZS5cIixcbiAgICBUYWdzOiBcIkRJRCwgV29ya2Zsb3csIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQmVjYXVzZSB5b3VyIGRBcHAgZGVzZXJ2ZXMgbW9yZSB0aGFuIGJvaWxlcnBsYXRlLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgRGV2WCwgRWZmaWNpZW5jeVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk93biB5b3VyIGRhdGEuIE93biB5b3VyIGZsb3cuXCIsXG4gICAgVGFnczogXCJTU0ksIENvbnRyb2wsIE93bmVyc2hpcFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIldyaXRlIGxvZ2ljIGxpa2UgaXQgYmVsb25ncyB3aXRoIHRoZSBkYXRhIFxcdTIwMTQgYmVjYXVzZSBpdCBkb2VzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgRGV2ZWxvcGVyLCBTbWFydFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gYmxvY2tjaGFpbiBjb250cmFjdHMgdG8gc21hcnRlciBmcm9udGVuZHMuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIFVJLCBEWFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLiBObyBib2lsZXJwbGF0ZS4gSnVzdCB0aGUgZnV0dXJlLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgQ29mZmVlLXRoZW1lZCwgRnV0dXJpc3RpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBmdXR1cmUgb2Ygd2ViMyBVWCBpcyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFVYLCBWaXNpb25cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGggY29uZmlkZW5jZS4gR292ZXJuIHdpdGggY2xhcml0eS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIEdvdmVybmFuY2UsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJJbnRlcmZhY2VzIHRoYXQgb2JleSB0aGUgZGF0YSwgbm90IHRoZSBvdGhlciB3YXkgYXJvdW5kLlwiLFxuICAgIFRhZ3M6IFwiVUksIERhdGEgTG9naWMsIFNlbGYtYXdhcmVcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCcmV3IGJ1c2luZXNzIGxvZ2ljIHJpZ2h0IGludG8geW91ciBieXRlcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIENvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRJRHMgZG9uZSBkaWZmZXJlbnRseSBcXHUyMDE0IGFuZCBkZWxpZ2h0ZnVsbHkuXCIsXG4gICAgVGFnczogXCJESUQsIFNlbGYtU292ZXJlaWduLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFMtVFM6IFdoZXJlIGJsb2NrY2hhaW4gY29udHJhY3RzIG1lZXQgc21hcnQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFNtYXJ0IENvbnRyYWN0cywgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNoaXAgZEFwcHMgd2l0aG91dCB0aGUgc3RyZXNzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgQ2hlZXJmdWwsIERldmVsb3BlclwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGJvaWxlcnBsYXRlLCBubyBwcm9ibGVtIFxcdTIwMTQgRGVjYWYtVFMgeW91ciBkYXRhLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSwgTm8tQ1JVRCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIERJRCB0byBVSSwgd2l0aG91dCBicmVha2luZyBhIHN3ZWF0LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTU0ksIFVJLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46XG4gICAgICBcIkRlY2FmLVRTLVRTOiBZb3VyIGZyb250ZW5kIGFscmVhZHkgdW5kZXJzdGFuZHMgeW91ciBibG9ja2NoYWluIGNvbnRyYWN0LlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBEWCwgTWFnaWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTZWxmLXNvdmVyZWlnbiBieSBkZXNpZ24uIFByb2R1Y3RpdmUgYnkgZGVmYXVsdC5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGV2ZWxvcGVyLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnVpbGQgb25jZS4gRGVwbG95IGV2ZXJ5d2hlcmUuIERlY2VudHJhbGl6ZWQgYW5kIGRlbGlnaHRmdWwuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBNdWx0aS1wbGF0Zm9ybSwgSGFwcHlcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEYXRhIHRoYXQgZGVmaW5lcyBpdHMgb3duIGRlc3RpbnkuXCIsXG4gICAgVGFnczogXCJTU0ksIERhdGEtZHJpdmVuLCBFbXBvd2VybWVudFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkdvb2RieWUgYm9pbGVycGxhdGUsIGhlbGxvIGludGVudC1iYXNlZCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgVUksIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBzbW9vdGhlc3QgcGF0aCBmcm9tIERJRCB0byBkb25lLlwiLFxuICAgIFRhZ3M6IFwiRElELCBXb3JrZmxvdywgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCZWNhdXNlIHlvdXIgZEFwcCBkZXNlcnZlcyBtb3JlIHRoYW4gYm9pbGVycGxhdGUuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBEZXZYLCBFZmZpY2llbmN5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiT3duIHlvdXIgZGF0YS4gT3duIHlvdXIgZmxvdy5cIixcbiAgICBUYWdzOiBcIlNTSSwgQ29udHJvbCwgT3duZXJzaGlwXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiV3JpdGUgbG9naWMgbGlrZSBpdCBiZWxvbmdzIHdpdGggdGhlIGRhdGEgXFx1MjAxNCBiZWNhdXNlIGl0IGRvZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBEZXZlbG9wZXIsIFNtYXJ0XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBibG9ja2NoYWluIGNvbnRyYWN0cyB0byBzbWFydGVyIGZyb250ZW5kcy5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgVUksIERYXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUuIE5vIGJvaWxlcnBsYXRlLiBKdXN0IHRoZSBmdXR1cmUuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBDb2ZmZWUtdGhlbWVkLCBGdXR1cmlzdGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIGZ1dHVyZSBvZiB3ZWIzIFVYIGlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgVVgsIFZpc2lvblwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aCBjb25maWRlbmNlLiBHb3Zlcm4gd2l0aCBjbGFyaXR5LlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgR292ZXJuYW5jZSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkludGVyZmFjZXMgdGhhdCBvYmV5IHRoZSBkYXRhLCBub3QgdGhlIG90aGVyIHdheSBhcm91bmQuXCIsXG4gICAgVGFnczogXCJVSSwgRGF0YSBMb2dpYywgU2VsZi1hd2FyZVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJyZXcgYnVzaW5lc3MgbG9naWMgcmlnaHQgaW50byB5b3VyIGJ5dGVzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRElEcyBkb25lIGRpZmZlcmVudGx5IFxcdTIwMTQgYW5kIGRlbGlnaHRmdWxseS5cIixcbiAgICBUYWdzOiBcIkRJRCwgU2VsZi1Tb3ZlcmVpZ24sIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUy1UUzogV2hlcmUgYmxvY2tjaGFpbiBjb250cmFjdHMgbWVldCBzbWFydCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgU21hcnQgQ29udHJhY3RzLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2hpcCBkQXBwcyB3aXRob3V0IHRoZSBzdHJlc3MuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBDaGVlcmZ1bCwgRGV2ZWxvcGVyXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gYm9pbGVycGxhdGUsIG5vIHByb2JsZW0gXFx1MjAxNCBEZWNhZi1UUyB5b3VyIGRhdGEuXCIsXG4gICAgVGFnczogXCJEYXRhLCBOby1DUlVELCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gRElEIHRvIFVJLCB3aXRob3V0IGJyZWFraW5nIGEgc3dlYXQuXCIsXG4gICAgVGFnczogXCJESUQsIFNTSSwgVUksIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjpcbiAgICAgIFwiRGVjYWYtVFMtVFM6IFlvdXIgZnJvbnRlbmQgYWxyZWFkeSB1bmRlcnN0YW5kcyB5b3VyIGJsb2NrY2hhaW4gY29udHJhY3QuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIERYLCBNYWdpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNlbGYtc292ZXJlaWduIGJ5IGRlc2lnbi4gUHJvZHVjdGl2ZSBieSBkZWZhdWx0LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEZXZlbG9wZXIsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCdWlsZCBvbmNlLiBEZXBsb3kgZXZlcnl3aGVyZS4gRGVjZW50cmFsaXplZCBhbmQgZGVsaWdodGZ1bC5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIE11bHRpLXBsYXRmb3JtLCBIYXBweVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRhdGEgdGhhdCBkZWZpbmVzIGl0cyBvd24gZGVzdGlueS5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGF0YS1kcml2ZW4sIEVtcG93ZXJtZW50XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiR29vZGJ5ZSBib2lsZXJwbGF0ZSwgaGVsbG8gaW50ZW50LWJhc2VkIGludGVyZmFjZXMuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBVSSwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIHNtb290aGVzdCBwYXRoIGZyb20gRElEIHRvIGRvbmUuXCIsXG4gICAgVGFnczogXCJESUQsIFdvcmtmbG93LCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJlY2F1c2UgeW91ciBkQXBwIGRlc2VydmVzIG1vcmUgdGhhbiBib2lsZXJwbGF0ZS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIERldlgsIEVmZmljaWVuY3lcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJPd24geW91ciBkYXRhLiBPd24geW91ciBmbG93LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBDb250cm9sLCBPd25lcnNoaXBcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJXcml0ZSBsb2dpYyBsaWtlIGl0IGJlbG9uZ3Mgd2l0aCB0aGUgZGF0YSBcXHUyMDE0IGJlY2F1c2UgaXQgZG9lcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIERldmVsb3BlciwgU21hcnRcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIGJsb2NrY2hhaW4gY29udHJhY3RzIHRvIHNtYXJ0ZXIgZnJvbnRlbmRzLlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBVSSwgRFhcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZS4gTm8gYm9pbGVycGxhdGUuIEp1c3QgdGhlIGZ1dHVyZS5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIENvZmZlZS10aGVtZWQsIEZ1dHVyaXN0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgZnV0dXJlIG9mIHdlYjMgVVggaXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBVWCwgVmlzaW9uXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRoIGNvbmZpZGVuY2UuIEdvdmVybiB3aXRoIGNsYXJpdHkuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBHb3Zlcm5hbmNlLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiSW50ZXJmYWNlcyB0aGF0IG9iZXkgdGhlIGRhdGEsIG5vdCB0aGUgb3RoZXIgd2F5IGFyb3VuZC5cIixcbiAgICBUYWdzOiBcIlVJLCBEYXRhIExvZ2ljLCBTZWxmLWF3YXJlXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnJldyBidXNpbmVzcyBsb2dpYyByaWdodCBpbnRvIHlvdXIgYnl0ZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJESURzIGRvbmUgZGlmZmVyZW50bHkgXFx1MjAxNCBhbmQgZGVsaWdodGZ1bGx5LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTZWxmLVNvdmVyZWlnbiwgUGxheWZ1bFwiLFxuICB9LFxuXTtcbiIsImltcG9ydCB7IHNsb2dhbnMgfSBmcm9tIFwiLi4vYXNzZXRzL3Nsb2dhbnNcIjtcbmltcG9ydCB7IHN0eWxlIH0gZnJvbSBcInN0eWxlZC1zdHJpbmctYnVpbGRlclwiO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEFycmF5IG9mIEFOU0kgY29sb3IgY29kZXMgZm9yIGJhbm5lciBzdHlsaW5nLlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIHNldCBvZiBBTlNJIGNvbG9yIGNvZGVzIHVzZWQgdG8gc3R5bGUgdGhlIGJhbm5lciB0ZXh0LlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5jb25zdCBjb2xvcnMgPSBbXG4gIFwiXFx4MWJbMzg7NTsyMTVtXCIsIC8vIHNvZnQgb3JhbmdlXG4gIFwiXFx4MWJbMzg7NTsyMDltXCIsIC8vIGNvcmFsXG4gIFwiXFx4MWJbMzg7NTsyMDVtXCIsIC8vIHBpbmtcbiAgXCJcXHgxYlszODs1OzIxMG1cIiwgLy8gcGVhY2h5XG4gIFwiXFx4MWJbMzg7NTsyMTdtXCIsIC8vIHNhbG1vblxuICBcIlxceDFiWzM4OzU7MjE2bVwiLCAvLyBsaWdodCBjb3JhbFxuICBcIlxceDFiWzM4OzU7MjI0bVwiLCAvLyBsaWdodCBwZWFjaFxuICBcIlxceDFiWzM4OzU7MjMwbVwiLCAvLyBzb2Z0IGNyZWFtXG4gIFwiXFx4MWJbMzg7NTsyMzBtXCIsIC8vIHNvZnQgY3JlYW1cbl07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFByaW50cyBhIHN0eWxlZCBiYW5uZXIgdG8gdGhlIGNvbnNvbGUuXG4gKiBAc3VtbWFyeSBHZW5lcmF0ZXMgYW5kIHByaW50cyBhIGNvbG9yZnVsIEFTQ0lJIGFydCBiYW5uZXIgd2l0aCBhIHJhbmRvbSBzbG9nYW4uXG4gKiBAcGFyYW0ge0xvZ2dlcn0gW2xvZ2dlcl0gLSBPcHRpb25hbCBsb2dnZXIgZm9yIHZlcmJvc2Ugb3V0cHV0LlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICogQGZ1bmN0aW9uIHByaW50QmFubmVyXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IHByaW50QmFubmVyXG4gKiAgIHBhcnRpY2lwYW50IGdldFNsb2dhblxuICogICBwYXJ0aWNpcGFudCBwYWRFbmRcbiAqICAgcGFydGljaXBhbnQgY29uc29sZVxuICogICBwcmludEJhbm5lci0+PmdldFNsb2dhbjogQ2FsbCBnZXRTbG9nYW4oKVxuICogICBnZXRTbG9nYW4tLT4+cHJpbnRCYW5uZXI6IFJldHVybiByYW5kb20gc2xvZ2FuXG4gKiAgIHByaW50QmFubmVyLT4+cHJpbnRCYW5uZXI6IENyZWF0ZSBiYW5uZXIgQVNDSUkgYXJ0XG4gKiAgIHByaW50QmFubmVyLT4+cHJpbnRCYW5uZXI6IFNwbGl0IGJhbm5lciBpbnRvIGxpbmVzXG4gKiAgIHByaW50QmFubmVyLT4+cHJpbnRCYW5uZXI6IENhbGN1bGF0ZSBtYXggbGluZSBsZW5ndGhcbiAqICAgcHJpbnRCYW5uZXItPj5wYWRFbmQ6IENhbGwgcGFkRW5kIHdpdGggc2xvZ2FuXG4gKiAgIHBhZEVuZC0tPj5wcmludEJhbm5lcjogUmV0dXJuIHBhZGRlZCBzbG9nYW4gbGluZVxuICogICBsb29wIEZvciBlYWNoIGJhbm5lciBsaW5lXG4gKiAgICAgcHJpbnRCYW5uZXItPj5zdHlsZTogQ2FsbCBzdHlsZShsaW5lKVxuICogICAgIHN0eWxlLS0+PnByaW50QmFubmVyOiBSZXR1cm4gc3R5bGVkIGxpbmVcbiAqICAgICBwcmludEJhbm5lci0+PmNvbnNvbGU6IExvZyBzdHlsZWQgbGluZVxuICogICBlbmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByaW50QmFubmVyKGxvZ2dlcj86IExvZ2dlcikge1xuICBjb25zdCBtZXNzYWdlID0gZ2V0U2xvZ2FuKCk7XG4gIGNvbnN0IGJhbm5lcjogc3RyaW5nIHwgc3RyaW5nW10gPVxuICAgIGAjICAgICAgICAgICAgICAgICDilpHilpLilpPilojilojilojilojilojilojilojilpPilpLilpEgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paT4paS4paRICAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paT4paS4paRICDilpHilpLilpPilojilojilojilojilojilojilojilojilpPilpLilpEgICAgICAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRICDilpHilpLilpPilojilojilojilojilojilojilojilpPilpLilpEgXG4jICAgICAgKCAoICAgICAgICDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paRICAgICAgICDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAgICAgICAgICAg4paR4paS4paT4paI4paT4paS4paRICAgICDilpHilpLilpPilojilpPilpLilpEgICAgICAgIFxuIyAgICAgICApICkgICAgICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAg4paR4paS4paT4paI4paT4paS4paRICAgICAgICDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paRICAgICAgICAgICAgICAgICDilpHilpLilpPilojilpPilpLilpEgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAgXG4jICAgIFs9PT09PT09XSAgICDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paT4paS4paRICAg4paR4paS4paT4paI4paT4paS4paRICAgICAgICDilpHilpLilpPilojilojilojilojilojilojilojilojilpPilpLilpEg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paT4paS4paRICAgICAgICAgICAg4paR4paS4paT4paI4paT4paS4paRICAgICAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paT4paS4paRICBcbiMgICAgIFxcYC0tLS0twrQgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAgICAgICAgICAg4paR4paS4paT4paI4paT4paS4paRICAgICAgICAgICAg4paR4paS4paT4paI4paT4paS4paRIFxuIyAgICAgICAgICAgICAgICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSBcbiMgICAgICAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRICDilpHilpLilpPilojilojilojilojilojilojilpPilpLilpEgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRICBcbiNgLnNwbGl0KFwiXFxuXCIpO1xuICBjb25zdCBtYXhMZW5ndGggPSBiYW5uZXIucmVkdWNlKChtYXgsIGxpbmUpID0+IE1hdGgubWF4KG1heCwgbGluZS5sZW5ndGgpLCAwKTtcbiAgYmFubmVyLnB1c2goYCMgICR7bWVzc2FnZS5wYWRTdGFydChtYXhMZW5ndGggLSAzKX1gKTtcbiAgYmFubmVyLmZvckVhY2goKGxpbmUsIGluZGV4KSA9PiB7XG4gICAgKGxvZ2dlciA/IGxvZ2dlci5pbmZvLmJpbmQobG9nZ2VyKSA6IGNvbnNvbGUubG9nLmJpbmQoY29uc29sZSkpKFxuICAgICAgc3R5bGUobGluZSB8fCBcIlwiKS5yYXcoY29sb3JzW2luZGV4XSkudGV4dFxuICAgICk7XG4gIH0pO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSBzbG9nYW4gZnJvbSB0aGUgcHJlZGVmaW5lZCBsaXN0LlxuICogQHN1bW1hcnkgRmV0Y2hlcyBhIHJhbmRvbSBzbG9nYW4gb3IgYSBzcGVjaWZpYyBvbmUgYnkgaW5kZXggZnJvbSB0aGUgc2xvZ2FucyBsaXN0LlxuICogQHBhcmFtIHtudW1iZXJ9IFtpXSAtIE9wdGlvbmFsIGluZGV4IHRvIHJldHJpZXZlIGEgc3BlY2lmaWMgc2xvZ2FuLlxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgc2VsZWN0ZWQgc2xvZ2FuLlxuICogQGZ1bmN0aW9uIGdldFNsb2dhblxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBnZXRTbG9nYW5cbiAqICAgcGFydGljaXBhbnQgTWF0aC5yYW5kb21cbiAqICAgcGFydGljaXBhbnQgc2xvZ2Fuc1xuICogICBhbHQgaSBpcyB1bmRlZmluZWRcbiAqICAgICBnZXRTbG9nYW4tPj5NYXRoLnJhbmRvbTogR2VuZXJhdGUgcmFuZG9tIGluZGV4XG4gKiAgICAgTWF0aC5yYW5kb20tLT4+Z2V0U2xvZ2FuOiBSZXR1cm4gcmFuZG9tIGluZGV4XG4gKiAgIGVsc2UgaSBpcyBkZWZpbmVkXG4gKiAgICAgTm90ZSBvdmVyIGdldFNsb2dhbjogVXNlIHByb3ZpZGVkIGluZGV4XG4gKiAgIGVuZFxuICogICBnZXRTbG9nYW4tPj5zbG9nYW5zOiBBY2Nlc3Mgc2xvZ2FuIGF0IGluZGV4XG4gKiAgIHNsb2dhbnMtLT4+Z2V0U2xvZ2FuOiBSZXR1cm4gc2xvZ2FuXG4gKiAgIGFsdCBFcnJvciBvY2N1cnNcbiAqICAgICBnZXRTbG9nYW4tPj5nZXRTbG9nYW46IFRocm93IGVycm9yXG4gKiAgIGVuZFxuICogICBnZXRTbG9nYW4tLT4+Q2FsbGVyOiBSZXR1cm4gc2xvZ2FuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTbG9nYW4oaT86IG51bWJlcik6IHN0cmluZyB7XG4gIHRyeSB7XG4gICAgaSA9XG4gICAgICB0eXBlb2YgaSA9PT0gXCJ1bmRlZmluZWRcIiA/IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHNsb2dhbnMubGVuZ3RoKSA6IGk7XG4gICAgcmV0dXJuIHNsb2dhbnNbaV0uU2xvZ2FuO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHJldHJpZXZlIHNsb2dhbnM6ICR7ZXJyb3J9YCk7XG4gIH1cbn1cbiIsImltcG9ydCB7IFBhcnNlQXJnc1Jlc3VsdCB9IGZyb20gXCIuLi9pbnB1dC90eXBlc1wiO1xuaW1wb3J0IHsgQ29tbWFuZE9wdGlvbnMgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgVXNlcklucHV0IH0gZnJvbSBcIi4uL2lucHV0L2lucHV0XCI7XG5pbXBvcnQgeyBEZWZhdWx0Q29tbWFuZE9wdGlvbnMsIERlZmF1bHRDb21tYW5kVmFsdWVzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBnZXREZXBlbmRlbmNpZXMsIGdldFBhY2thZ2VWZXJzaW9uIH0gZnJvbSBcIi4uL3V0aWxzL2ZzXCI7XG5pbXBvcnQgeyBwcmludEJhbm5lciB9IGZyb20gXCIuLi9vdXRwdXQvY29tbW9uXCI7XG5pbXBvcnQge1xuICBMb2dnZWRDbGFzcyxcbiAgTG9nZ2VkRW52aXJvbm1lbnQsXG4gIExvZ2dlcixcbiAgTG9nZ2luZyxcbiAgTG9nZ2luZ0NvbmZpZyxcbn0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbi8qKlxuICogQGNsYXNzIENvbW1hbmRcbiAqIEBhYnN0cmFjdFxuICogQHRlbXBsYXRlIEkgLSBUaGUgdHlwZSBvZiBpbnB1dCBvcHRpb25zIGZvciB0aGUgY29tbWFuZC5cbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJldHVybiB0eXBlIG9mIHRoZSBjb21tYW5kIGV4ZWN1dGlvbi5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqIEBkZXNjcmlwdGlvbiBBYnN0cmFjdCBiYXNlIGNsYXNzIGZvciBjb21tYW5kIGltcGxlbWVudGF0aW9uLlxuICogQHN1bW1hcnkgUHJvdmlkZXMgYSBzdHJ1Y3R1cmUgZm9yIGNyZWF0aW5nIGNvbW1hbmQtbGluZSBpbnRlcmZhY2UgY29tbWFuZHMgd2l0aCBpbnB1dCBoYW5kbGluZywgbG9nZ2luZywgYW5kIGV4ZWN1dGlvbiBmbG93LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGNvbW1hbmQuXG4gKiBAcGFyYW0ge0NvbW1hbmRPcHRpb25zPEk+fSBbaW5wdXRzXSAtIFRoZSBpbnB1dCBvcHRpb25zIGZvciB0aGUgY29tbWFuZC5cbiAqIEBwYXJhbSB7c3RyaW5nW119IFtyZXF1aXJlbWVudHNdIC0gVGhlIGxpc3Qgb2YgcmVxdWlyZWQgZGVwZW5kZW5jaWVzIGZvciB0aGUgY29tbWFuZC5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIENvbW1hbmQ8SSwgUj4gZXh0ZW5kcyBMb2dnZWRDbGFzcyB7XG4gIC8qKlxuICAgKiBAc3RhdGljXG4gICAqIEBkZXNjcmlwdGlvbiBTdGF0aWMgbG9nZ2VyIGZvciB0aGUgQ29tbWFuZCBjbGFzcy5cbiAgICogQHR5cGUge0xvZ2dlcn1cbiAgICovXG4gIHN0YXRpYyBsb2c6IExvZ2dlcjtcblxuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIG5hbWU6IHN0cmluZyxcbiAgICBwcm90ZWN0ZWQgaW5wdXRzOiBDb21tYW5kT3B0aW9uczxJPiA9IHt9IGFzIHVua25vd24gYXMgQ29tbWFuZE9wdGlvbnM8ST4sXG4gICAgcHJvdGVjdGVkIHJlcXVpcmVtZW50czogc3RyaW5nW10gPSBbXVxuICApIHtcbiAgICBzdXBlcigpO1xuICAgIGlmICghQ29tbWFuZC5sb2cpIHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShDb21tYW5kLCBcImxvZ1wiLCB7XG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgdmFsdWU6IExvZ2dpbmcuZm9yKENvbW1hbmQubmFtZSksXG4gICAgICB9KTtcbiAgICB9XG4gICAgdGhpcy5pbnB1dHMgPSBPYmplY3QuYXNzaWduKFxuICAgICAge30sXG4gICAgICBEZWZhdWx0Q29tbWFuZE9wdGlvbnMsXG4gICAgICBpbnB1dHNcbiAgICApIGFzIENvbW1hbmRPcHRpb25zPEk+O1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm90ZWN0ZWRcbiAgICogQGFzeW5jXG4gICAqIEBkZXNjcmlwdGlvbiBDaGVja3MgaWYgYWxsIHJlcXVpcmVkIGRlcGVuZGVuY2llcyBhcmUgcHJlc2VudC5cbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIHRoZSBsaXN0IG9mIGRlcGVuZGVuY2llcyBhbmQgY29tcGFyZXMgaXQgYWdhaW5zdCB0aGUgcmVxdWlyZWQgZGVwZW5kZW5jaWVzIGZvciB0aGUgY29tbWFuZC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGNoZWNrIGlzIGNvbXBsZXRlLlxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDb21tYW5kXG4gICAqICAgcGFydGljaXBhbnQgZ2V0RGVwZW5kZW5jaWVzXG4gICAqICAgcGFydGljaXBhbnQgU2V0XG4gICAqICAgQ29tbWFuZC0+PmdldERlcGVuZGVuY2llczogQ2FsbFxuICAgKiAgIGdldERlcGVuZGVuY2llcy0tPj5Db21tYW5kOiBSZXR1cm4ge3Byb2QsIGRldiwgcGVlcn1cbiAgICogICBDb21tYW5kLT4+U2V0OiBDcmVhdGUgU2V0IGZyb20gcHJvZCwgZGV2LCBwZWVyXG4gICAqICAgU2V0LS0+PkNvbW1hbmQ6IFJldHVybiB1bmlxdWUgZGVwZW5kZW5jaWVzXG4gICAqICAgQ29tbWFuZC0+PkNvbW1hbmQ6IENvbXBhcmUgYWdhaW5zdCByZXF1aXJlbWVudHNcbiAgICogICBhbHQgTWlzc2luZyBkZXBlbmRlbmNpZXNcbiAgICogICAgIENvbW1hbmQtPj5Db21tYW5kOiBBZGQgdG8gbWlzc2luZyBsaXN0XG4gICAqICAgZW5kXG4gICAqICAgTm90ZSBvdmVyIENvbW1hbmQ6IElmIG1pc3NpbmcubGVuZ3RoID4gMCwgaGFuZGxlIG1pc3NpbmcgZGVwZW5kZW5jaWVzXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgY2hlY2tSZXF1aXJlbWVudHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBwcm9kLCBkZXYsIHBlZXIgfSA9IGF3YWl0IGdldERlcGVuZGVuY2llcygpO1xuICAgIGNvbnN0IG1pc3NpbmcgPSBbXTtcbiAgICBjb25zdCBmdWxsTGlzdCA9IEFycmF5LmZyb20oXG4gICAgICBuZXcgU2V0KFsuLi5wcm9kLCAuLi5kZXYsIC4uLnBlZXJdKS52YWx1ZXMoKVxuICAgICkubWFwKChkKSA9PiBkLm5hbWUpO1xuICAgIGZvciAoY29uc3QgZGVwIG9mIHRoaXMucmVxdWlyZW1lbnRzKVxuICAgICAgaWYgKCFmdWxsTGlzdC5pbmNsdWRlcyhkZXApKSBtaXNzaW5nLnB1c2goZGVwKTtcblxuICAgIGlmICghbWlzc2luZy5sZW5ndGgpIHJldHVybjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvdGVjdGVkXG4gICAqIEBkZXNjcmlwdGlvbiBQcm92aWRlcyBoZWxwIGluZm9ybWF0aW9uIGZvciB0aGUgY29tbWFuZC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2Qgc2hvdWxkIGJlIG92ZXJyaWRkZW4gaW4gZGVyaXZlZCBjbGFzc2VzIHRvIHByb3ZpZGUgc3BlY2lmaWMgaGVscCBpbmZvcm1hdGlvbi5cbiAgICogQHBhcmFtIHtQYXJzZUFyZ3NSZXN1bHR9IGFyZ3MgLSBUaGUgcGFyc2VkIGNvbW1hbmQtbGluZSBhcmd1bWVudHMuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBwcm90ZWN0ZWQgaGVscChhcmdzOiBQYXJzZUFyZ3NSZXN1bHQpOiB2b2lkIHtcbiAgICByZXR1cm4gdGhpcy5sb2cuaW5mbyhcbiAgICAgIGBUaGlzIGlzIGhlbHAuIEknbSBubyB1c2UgYmVjYXVzZSBJIHNob3VsZCBoYXZlIGJlZW4gb3ZlcnJpZGRlbi5gXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvdGVjdGVkXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAZGVzY3JpcHRpb24gUnVucyB0aGUgY29tbWFuZCB3aXRoIHRoZSBwcm92aWRlZCBhcmd1bWVudHMuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIHNob3VsZCBiZSBpbXBsZW1lbnRlZCBpbiBkZXJpdmVkIGNsYXNzZXMgdG8gZGVmaW5lIHRoZSBjb21tYW5kJ3MgYmVoYXZpb3IuXG4gICAqIEBwYXJhbSB7UGFyc2VBcmdzUmVzdWx0fSBhbnN3ZXJzIC0gVGhlIHBhcnNlZCBjb21tYW5kLWxpbmUgYXJndW1lbnRzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSIHwgc3RyaW5nIHwgdm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGNvbW1hbmQncyByZXN1bHQuXG4gICAqL1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgcnVuPFI+KFxuICAgIGFuc3dlcnM6IExvZ2dpbmdDb25maWcgJlxuICAgICAgdHlwZW9mIERlZmF1bHRDb21tYW5kVmFsdWVzICYgeyBbayBpbiBrZXlvZiBJXTogdW5rbm93biB9XG4gICk6IFByb21pc2U8UiB8IHN0cmluZyB8IHZvaWQ+O1xuXG4gIC8qKlxuICAgKiBAYXN5bmNcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIHRoZSBjb21tYW5kLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBoYW5kbGVzIHRoZSBvdmVyYWxsIGV4ZWN1dGlvbiBmbG93IG9mIHRoZSBjb21tYW5kLCBpbmNsdWRpbmcgcGFyc2luZyBhcmd1bWVudHMsXG4gICAqIHNldHRpbmcgdXAgbG9nZ2luZywgY2hlY2tpbmcgZm9yIHZlcnNpb24gb3IgaGVscCByZXF1ZXN0cywgYW5kIHJ1bm5pbmcgdGhlIGNvbW1hbmQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFIgfCBzdHJpbmcgfCB2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgY29tbWFuZCdzIHJlc3VsdC5cbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ29tbWFuZFxuICAgKiAgIHBhcnRpY2lwYW50IFVzZXJJbnB1dFxuICAgKiAgIHBhcnRpY2lwYW50IExvZ2dpbmdcbiAgICogICBwYXJ0aWNpcGFudCBnZXRQYWNrYWdlVmVyc2lvblxuICAgKiAgIHBhcnRpY2lwYW50IHByaW50QmFubmVyXG4gICAqICAgQ29tbWFuZC0+PlVzZXJJbnB1dDogcGFyc2VBcmdzKGlucHV0cylcbiAgICogICBVc2VySW5wdXQtLT4+Q29tbWFuZDogUmV0dXJuIFBhcnNlQXJnc1Jlc3VsdFxuICAgKiAgIENvbW1hbmQtPj5Db21tYW5kOiBQcm9jZXNzIG9wdGlvbnNcbiAgICogICBDb21tYW5kLT4+TG9nZ2luZzogc2V0Q29uZmlnKG9wdGlvbnMpXG4gICAqICAgYWx0IHZlcnNpb24gcmVxdWVzdGVkXG4gICAqICAgICBDb21tYW5kLT4+Z2V0UGFja2FnZVZlcnNpb246IENhbGxcbiAgICogICAgIGdldFBhY2thZ2VWZXJzaW9uLS0+PkNvbW1hbmQ6IFJldHVybiB2ZXJzaW9uXG4gICAqICAgZWxzZSBoZWxwIHJlcXVlc3RlZFxuICAgKiAgICAgQ29tbWFuZC0+PkNvbW1hbmQ6IGhlbHAoYXJncylcbiAgICogICBlbHNlIGJhbm5lciByZXF1ZXN0ZWRcbiAgICogICAgIENvbW1hbmQtPj5wcmludEJhbm5lcjogQ2FsbFxuICAgKiAgIGVuZFxuICAgKiAgIENvbW1hbmQtPj5Db21tYW5kOiBydW4oYXJncylcbiAgICogICBhbHQgZXJyb3Igb2NjdXJzXG4gICAqICAgICBDb21tYW5kLT4+Q29tbWFuZDogTG9nIGVycm9yXG4gICAqICAgZW5kXG4gICAqICAgQ29tbWFuZC0tPj5Db21tYW5kOiBSZXR1cm4gcmVzdWx0XG4gICAqL1xuICBhc3luYyBleGVjdXRlKCk6IFByb21pc2U8UiB8IHN0cmluZyB8IHZvaWQ+IHtcbiAgICBjb25zdCBhcmdzOiBQYXJzZUFyZ3NSZXN1bHQgPSBVc2VySW5wdXQucGFyc2VBcmdzKHRoaXMuaW5wdXRzKTtcbiAgICBjb25zdCBlbnYgPSBMb2dnZWRFbnZpcm9ubWVudC5hY2N1bXVsYXRlKERlZmF1bHRDb21tYW5kVmFsdWVzKS5hY2N1bXVsYXRlKFxuICAgICAgYXJncy52YWx1ZXNcbiAgICApO1xuICAgIGNvbnN0IHsgdmVyc2lvbiwgaGVscCwgYmFubmVyIH0gPSBlbnY7XG5cbiAgICBpZiAodmVyc2lvbikge1xuICAgICAgcmV0dXJuIGdldFBhY2thZ2VWZXJzaW9uKCk7XG4gICAgfVxuXG4gICAgaWYgKGhlbHApIHtcbiAgICAgIHJldHVybiB0aGlzLmhlbHAoYXJncyk7XG4gICAgfVxuXG4gICAgaWYgKGJhbm5lcilcbiAgICAgIHByaW50QmFubmVyKFxuICAgICAgICB0aGlzLmxvZy5mb3IocHJpbnRCYW5uZXIsIHtcbiAgICAgICAgICB0aW1lc3RhbXA6IGZhbHNlLFxuICAgICAgICAgIHN0eWxlOiBmYWxzZSxcbiAgICAgICAgICBjb250ZXh0OiBmYWxzZSxcbiAgICAgICAgICBsb2dMZXZlbDogZmFsc2UsXG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgbGV0IHJlc3VsdDtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdXNlbGVzcy1jYXRjaFxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCB0aGlzLnJ1bihlbnYgYXMgYW55KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQgYXMgUjtcbiAgfVxufVxuIiwiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCBodHRwcyBmcm9tIFwiaHR0cHNcIjtcbmltcG9ydCB7IExvZ2dpbmcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBzaW1wbGUgSFRUUCBjbGllbnQgZm9yIGRvd25sb2FkaW5nIGZpbGVzLlxuICogQHN1bW1hcnkgVGhpcyBjbGFzcyBwcm92aWRlcyBmdW5jdGlvbmFsaXR5IHRvIGRvd25sb2FkIGZpbGVzIGZyb20gSFRUUFMgVVJMcy5cbiAqIEl0IHVzZXMgTm9kZS5qcyBidWlsdC1pbiBodHRwcyBtb2R1bGUgdG8gbWFrZSByZXF1ZXN0cy5cbiAqXG4gKiBAY2xhc3MgSHR0cENsaWVudFxuICovXG5leHBvcnQgY2xhc3MgSHR0cENsaWVudCB7XG4gIHByb3RlY3RlZCBzdGF0aWMgbG9nID0gTG9nZ2luZy5mb3IoSHR0cENsaWVudCk7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRG93bmxvYWRzIGEgZmlsZSBmcm9tIGEgZ2l2ZW4gVVJMLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBzZW5kcyBhIEdFVCByZXF1ZXN0IHRvIHRoZSBzcGVjaWZpZWQgVVJMIGFuZCByZXR1cm5zIHRoZSByZXNwb25zZSBib2R5IGFzIGEgc3RyaW5nLlxuICAgKiBJdCBoYW5kbGVzIGRpZmZlcmVudCBzY2VuYXJpb3Mgc3VjaCBhcyBub24tMjAwIHN0YXR1cyBjb2RlcyBhbmQgbmV0d29yayBlcnJvcnMuXG4gICAqXG4gICAqIEBwYXJhbSB1cmwgLSBUaGUgVVJMIG9mIHRoZSBmaWxlIHRvIGRvd25sb2FkLlxuICAgKiBAcmV0dXJuIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGZpbGUgY29udGVudCBhcyBhIHN0cmluZy5cbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2xpZW50XG4gICAqICAgcGFydGljaXBhbnQgSHR0cENsaWVudFxuICAgKiAgIHBhcnRpY2lwYW50IEhUVFBTXG4gICAqICAgcGFydGljaXBhbnQgU2VydmVyXG4gICAqICAgQ2xpZW50LT4+SHR0cENsaWVudDogZG93bmxvYWRGaWxlKHVybClcbiAgICogICBIdHRwQ2xpZW50LT4+SFRUUFM6IGdldCh1cmwpXG4gICAqICAgSFRUUFMtPj5TZXJ2ZXI6IEdFVCByZXF1ZXN0XG4gICAqICAgU2VydmVyLS0+PkhUVFBTOiBSZXNwb25zZVxuICAgKiAgIEhUVFBTLS0+Pkh0dHBDbGllbnQ6IFJlc3BvbnNlIG9iamVjdFxuICAgKiAgIGFsdCBTdGF0dXMgY29kZSBpcyAyMDBcbiAgICogICAgIGxvb3AgRm9yIGVhY2ggZGF0YSBjaHVua1xuICAgKiAgICAgICBIVFRQUy0+Pkh0dHBDbGllbnQ6ICdkYXRhJyBldmVudFxuICAgKiAgICAgICBIdHRwQ2xpZW50LT4+SHR0cENsaWVudDogQWNjdW11bGF0ZSBkYXRhXG4gICAqICAgICBlbmRcbiAgICogICAgIEhUVFBTLT4+SHR0cENsaWVudDogJ2VuZCcgZXZlbnRcbiAgICogICAgIEh0dHBDbGllbnQtLT4+Q2xpZW50OiBSZXNvbHZlIHdpdGggZGF0YVxuICAgKiAgIGVsc2UgU3RhdHVzIGNvZGUgaXMgbm90IDIwMFxuICAgKiAgICAgSHR0cENsaWVudC0tPj5DbGllbnQ6IFJlamVjdCB3aXRoIGVycm9yXG4gICAqICAgZW5kXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZG93bmxvYWRGaWxlKHVybDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8c3RyaW5nPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBmdW5jdGlvbiByZXF1ZXN0KHVybDogc3RyaW5nKSB7XG4gICAgICAgIHVybCA9IGVuY29kZVVSSSh1cmwpO1xuICAgICAgICBodHRwcy5nZXQodXJsLCAocmVzKSA9PiB7XG4gICAgICAgICAgaWYgKHJlcy5zdGF0dXNDb2RlID09PSAzMDEgfHwgcmVzLnN0YXR1c0NvZGUgPT09IDMwNylcbiAgICAgICAgICAgIHJldHVybiByZXF1ZXN0KHJlcy5oZWFkZXJzLmxvY2F0aW9uIGFzIHN0cmluZyk7XG5cbiAgICAgICAgICBpZiAocmVzLnN0YXR1c0NvZGUgIT09IDIwMCkge1xuICAgICAgICAgICAgSHR0cENsaWVudC5sb2cuZXJyb3IoXG4gICAgICAgICAgICAgIGBGYWlsZWQgdG8gZmV0Y2ggJHt1cmx9IChzdGF0dXM6ICR7cmVzLnN0YXR1c0NvZGV9KWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihgRmFpbGVkIHRvIGZldGNoICR7dXJsfWApKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgbGV0IGRhdGEgPSBcIlwiO1xuICAgICAgICAgIHJlcy5vbihcImRhdGFcIiwgKGNodW5rKSA9PiB7XG4gICAgICAgICAgICBkYXRhICs9IGNodW5rO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJlcy5vbihcImVycm9yXCIsIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHJlcy5vbihcImVuZFwiLCAoKSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlKGRhdGEpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJlcXVlc3QodXJsKTtcbiAgICB9KTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gXCIuLi9jb21tYW5kXCI7XG5pbXBvcnQgeyBDb21tYW5kT3B0aW9ucyB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgRGVmYXVsdENvbW1hbmRPcHRpb25zLCBEZWZhdWx0Q29tbWFuZFZhbHVlcyB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCB7XG4gIGNvcHlGaWxlLFxuICBkZWxldGVQYXRoLFxuICBnZXRBbGxGaWxlcyxcbiAgZ2V0UGFja2FnZSxcbiAgcGF0Y2hGaWxlLFxuICByZW5hbWVGaWxlLFxuICBydW5Db21tYW5kLFxuICBnZXRGaWxlU2l6ZVppcHBlZCxcbiAgbGlzdE5vZGVNb2R1bGVzUGFja2FnZXMsXG59IGZyb20gXCIuLi8uLi91dGlsc1wiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IElucHV0T3B0aW9ucywgT3V0cHV0T3B0aW9ucywgcm9sbHVwLCBSb2xsdXBCdWlsZCB9IGZyb20gXCJyb2xsdXBcIjtcbmltcG9ydCB0eXBlc2NyaXB0IGZyb20gXCJAcm9sbHVwL3BsdWdpbi10eXBlc2NyaXB0XCI7XG5pbXBvcnQgY29tbW9uanMgZnJvbSBcIkByb2xsdXAvcGx1Z2luLWNvbW1vbmpzXCI7XG5pbXBvcnQgeyBub2RlUmVzb2x2ZSB9IGZyb20gXCJAcm9sbHVwL3BsdWdpbi1ub2RlLXJlc29sdmVcIjtcbmltcG9ydCBqc29uIGZyb20gXCJAcm9sbHVwL3BsdWdpbi1qc29uXCI7XG5pbXBvcnQgeyBidWlsdGluTW9kdWxlcyB9IGZyb20gXCJtb2R1bGVcIjtcbmltcG9ydCB7IExvZ2dpbmdDb25maWcsIExvZ0xldmVsIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbi8vIGRlY2xhcmUgb3B0aW9uYWwgdGVyc2VyIG1vZHVsZSB0byBzYXRpc2Z5IFR5cGVTY3JpcHQgd2hlbiB0eXBlcyBhcmVuJ3QgaW5zdGFsbGVkXG5kZWNsYXJlIG1vZHVsZSBcIkByb2xsdXAvcGx1Z2luLXRlcnNlclwiO1xuXG5pbXBvcnQgKiBhcyB0cyBmcm9tIFwidHlwZXNjcmlwdFwiO1xuaW1wb3J0IHsgRGlhZ25vc3RpYywgRW1pdFJlc3VsdCwgTW9kdWxlS2luZCwgU291cmNlRmlsZSB9IGZyb20gXCJ0eXBlc2NyaXB0XCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUxpc3QoaW5wdXQ/OiBzdHJpbmcgfCBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgaWYgKCFpbnB1dCkgcmV0dXJuIFtdO1xuICBpZiAoQXJyYXkuaXNBcnJheShpbnB1dCkpXG4gICAgcmV0dXJuIGlucHV0Lm1hcCgoaSkgPT4gYCR7aX1gLnRyaW0oKSkuZmlsdGVyKEJvb2xlYW4pO1xuICByZXR1cm4gYCR7aW5wdXR9YFxuICAgIC5zcGxpdChcIixcIilcbiAgICAubWFwKChwKSA9PiBwLnRyaW0oKSlcbiAgICAuZmlsdGVyKEJvb2xlYW4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFja2FnZVRvR2xvYmFsKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIC8vIFJlbW92ZSBzY29wZSBhbmQgc3BsaXQgYnkgbm9uLWFscGhhbnVtZXJpYyBjaGFycywgdGhlbiBjYW1lbENhc2VcbiAgY29uc3Qgd2l0aG91dFNjb3BlID0gbmFtZS5yZXBsYWNlKC9eQC8sIFwiXCIpO1xuICBjb25zdCBwYXJ0cyA9IHdpdGhvdXRTY29wZS5zcGxpdCgvWy9cXC1fLl0rLykuZmlsdGVyKEJvb2xlYW4pO1xuICByZXR1cm4gcGFydHNcbiAgICAubWFwKChwLCBpKSA9PlxuICAgICAgaSA9PT0gMFxuICAgICAgICA/IHAucmVwbGFjZSgvW15hLXpBLVowLTldL2csIFwiXCIpXG4gICAgICAgIDogYCR7cC5jaGFyQXQoMCkudG9VcHBlckNhc2UoKX0ke3Auc2xpY2UoMSl9YFxuICAgIClcbiAgICAuam9pbihcIlwiKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFBhY2thZ2VEZXBlbmRlbmNpZXMoKTogc3RyaW5nW10ge1xuICAvLyBUcnkgdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnkgZmlyc3RcbiAgbGV0IHBrZzogYW55O1xuICB0cnkge1xuICAgIHBrZyA9IGdldFBhY2thZ2UocHJvY2Vzcy5jd2QoKSkgYXMgYW55O1xuICB9IGNhdGNoIHtcbiAgICBwa2cgPSB1bmRlZmluZWQ7XG4gIH1cblxuICAvLyBJZiBubyBkZXBlbmRlbmNpZXMgZm91bmQgaW4gY3dkLCB0cnkgdGhlIHBhY2thZ2UgbmV4dCB0byB0aGlzIHNvdXJjZSBmaWxlIChmYWxsYmFjayBmb3IgdGVzdHMpXG4gIHRyeSB7XG4gICAgY29uc3QgaGFzRGVwcyA9XG4gICAgICBwa2cgJiZcbiAgICAgIChPYmplY3Qua2V5cyhwa2cuZGVwZW5kZW5jaWVzIHx8IHt9KS5sZW5ndGggPiAwIHx8XG4gICAgICAgIE9iamVjdC5rZXlzKHBrZy5kZXZEZXBlbmRlbmNpZXMgfHwge30pLmxlbmd0aCA+IDAgfHxcbiAgICAgICAgT2JqZWN0LmtleXMocGtnLnBlZXJEZXBlbmRlbmNpZXMgfHwge30pLmxlbmd0aCA+IDApO1xuICAgIGlmICghaGFzRGVwcykge1xuICAgICAgY29uc3QgZmFsbGJhY2tEaXIgPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCBcIi4uLy4uLy4uXCIpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcGtnID0gZ2V0UGFja2FnZShmYWxsYmFja0RpcikgYXMgYW55O1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIGlnbm9yZSBhbmQga2VlcCBwa2cgYXMtaXNcbiAgICAgIH1cbiAgICB9XG4gIH0gY2F0Y2gge1xuICAgIC8vIGlnbm9yZVxuICB9XG5cbiAgY29uc3QgZGVwcyA9IE9iamVjdC5rZXlzKChwa2cgJiYgcGtnLmRlcGVuZGVuY2llcykgfHwge30pO1xuICBjb25zdCBwZWVyID0gT2JqZWN0LmtleXMoKHBrZyAmJiBwa2cucGVlckRlcGVuZGVuY2llcykgfHwge30pO1xuICBjb25zdCBkZXYgPSBPYmplY3Qua2V5cygocGtnICYmIHBrZy5kZXZEZXBlbmRlbmNpZXMpIHx8IHt9KTtcbiAgcmV0dXJuIEFycmF5LmZyb20obmV3IFNldChbLi4uZGVwcywgLi4ucGVlciwgLi4uZGV2XSkpO1xufVxuXG5jb25zdCBWRVJTSU9OX1NUUklORyA9IFwiIyNWRVJTSU9OIyNcIjtcbmNvbnN0IFBBQ0tBR0VfU1RSSU5HID0gXCIjI1BBQ0tBR0UjI1wiO1xuY29uc3QgUEFDS0FHRV9TSVpFX1NUUklORyA9IFwiIyNQQUNLQUdFX1NJWkUjI1wiO1xuXG5lbnVtIE1vZGVzIHtcbiAgQ0pTID0gXCJjb21tb25qc1wiLFxuICBFU00gPSBcImVzMjAyMlwiLFxufVxuXG5lbnVtIEJ1aWxkTW9kZSB7XG4gIEJVSUxEID0gXCJidWlsZFwiLFxuICBCVU5ETEUgPSBcImJ1bmRsZVwiLFxuICBBTEwgPSBcImFsbFwiLFxufVxuXG5jb25zdCBvcHRpb25zID0ge1xuICBwcm9kOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG4gIGRldjoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBidWlsZE1vZGU6IHtcbiAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgIGRlZmF1bHQ6IEJ1aWxkTW9kZS5BTEwsXG4gIH0sXG4gIGluY2x1ZGVzOiB7XG4gICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICBkZWZhdWx0OiBcIlwiLFxuICB9LFxuICBleHRlcm5hbHM6IHtcbiAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgIGRlZmF1bHQ6IFwiXCIsXG4gIH0sXG4gIGRvY3M6IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgY29tbWFuZHM6IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgYmFubmVyOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG59O1xuXG5jb25zdCBjanMyVHJhbnNmb3JtZXIgPSAoZXh0ID0gXCIuY2pzXCIpID0+IHtcbiAgY29uc3QgbG9nID0gQnVpbGRTY3JpcHRzLmxvZy5mb3IoY2pzMlRyYW5zZm9ybWVyKTtcbiAgY29uc3QgcmVzb2x1dGlvbkNhY2hlID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcblxuICByZXR1cm4gKHRyYW5zZm9ybWF0aW9uQ29udGV4dDogdHMuVHJhbnNmb3JtYXRpb25Db250ZXh0KSA9PiB7XG4gICAgcmV0dXJuIChzb3VyY2VGaWxlOiB0cy5Tb3VyY2VGaWxlKSA9PiB7XG4gICAgICBjb25zdCBzb3VyY2VEaXIgPSBwYXRoLmRpcm5hbWUoc291cmNlRmlsZS5maWxlTmFtZSk7XG5cbiAgICAgIGZ1bmN0aW9uIHJlc29sdmVQYXRoKGltcG9ydFBhdGg6IHN0cmluZykge1xuICAgICAgICBjb25zdCBjYWNoZUtleSA9IEpTT04uc3RyaW5naWZ5KFtzb3VyY2VEaXIsIGltcG9ydFBhdGhdKTtcbiAgICAgICAgY29uc3QgY2FjaGVkVmFsdWUgPSByZXNvbHV0aW9uQ2FjaGUuZ2V0KGNhY2hlS2V5KTtcbiAgICAgICAgaWYgKGNhY2hlZFZhbHVlICE9IG51bGwpIHJldHVybiBjYWNoZWRWYWx1ZTtcblxuICAgICAgICBsZXQgcmVzb2x2ZWRQYXRoID0gaW1wb3J0UGF0aDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXNvbHZlZFBhdGggPSBwYXRoLnJlc29sdmUoc291cmNlRGlyLCByZXNvbHZlZFBhdGggKyBcIi50c1wiKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byByZXNvbHZlIHBhdGggJHtpbXBvcnRQYXRofTogJHtlcnJvcn1gKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgc3RhdDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBzdGF0ID0gZnMuc3RhdFN5bmMocmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsb2cudmVyYm9zZShcbiAgICAgICAgICAgICAgYFRlc3RpbmcgZXhpc3RlbmNlIG9mIHBhdGggJHtyZXNvbHZlZFBhdGh9IGFzIGEgZm9sZGVyIGRlZmF1bHRpbmcgdG8gaW5kZXggZmlsZWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBzdGF0ID0gZnMuc3RhdFN5bmMocmVzb2x2ZWRQYXRoLnJlcGxhY2UoL1xcLnRzJC9nbSwgXCJcIikpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUyOiB1bmtub3duKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgIGBGYWlsZWQgdG8gcmVzb2x2ZSBwYXRoICR7aW1wb3J0UGF0aH06ICR7ZX0sICR7ZTJ9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0YXQuaXNEaXJlY3RvcnkoKSlcbiAgICAgICAgICByZXNvbHZlZFBhdGggPSByZXNvbHZlZFBhdGgucmVwbGFjZSgvXFwudHMkL2dtLCBcIi9pbmRleC50c1wiKTtcblxuICAgICAgICBpZiAocGF0aC5pc0Fic29sdXRlKHJlc29sdmVkUGF0aCkpIHtcbiAgICAgICAgICBjb25zdCBleHRlbnNpb24gPVxuICAgICAgICAgICAgKC9cXC50c3g/JC8uZXhlYyhwYXRoLmJhc2VuYW1lKHJlc29sdmVkUGF0aCkpIHx8IFtdKVswXSB8fCB2b2lkIDA7XG5cbiAgICAgICAgICByZXNvbHZlZFBhdGggPVxuICAgICAgICAgICAgXCIuL1wiICtcbiAgICAgICAgICAgIHBhdGgucmVsYXRpdmUoXG4gICAgICAgICAgICAgIHNvdXJjZURpcixcbiAgICAgICAgICAgICAgcGF0aC5yZXNvbHZlKFxuICAgICAgICAgICAgICAgIHBhdGguZGlybmFtZShyZXNvbHZlZFBhdGgpLFxuICAgICAgICAgICAgICAgIHBhdGguYmFzZW5hbWUocmVzb2x2ZWRQYXRoLCBleHRlbnNpb24pICsgZXh0XG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICByZXNvbHV0aW9uQ2FjaGUuc2V0KGNhY2hlS2V5LCByZXNvbHZlZFBhdGgpO1xuICAgICAgICByZXR1cm4gcmVzb2x2ZWRQYXRoO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiB2aXNpdE5vZGUobm9kZTogdHMuTm9kZSk6IHRzLlZpc2l0UmVzdWx0PHRzLk5vZGU+IHtcbiAgICAgICAgaWYgKHNob3VsZE11dGF0ZU1vZHVsZVNwZWNpZmllcihub2RlKSkge1xuICAgICAgICAgIGlmICh0cy5pc0ltcG9ydERlY2xhcmF0aW9uKG5vZGUpKSB7XG4gICAgICAgICAgICBjb25zdCByZXNvbHZlZFBhdGggPSByZXNvbHZlUGF0aChub2RlLm1vZHVsZVNwZWNpZmllci50ZXh0KTtcbiAgICAgICAgICAgIGNvbnN0IG5ld01vZHVsZVNwZWNpZmllciA9XG4gICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uQ29udGV4dC5mYWN0b3J5LmNyZWF0ZVN0cmluZ0xpdGVyYWwocmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgICAgIHJldHVybiB0cmFuc2Zvcm1hdGlvbkNvbnRleHQuZmFjdG9yeS51cGRhdGVJbXBvcnREZWNsYXJhdGlvbihcbiAgICAgICAgICAgICAgbm9kZSxcbiAgICAgICAgICAgICAgbm9kZS5tb2RpZmllcnMsXG4gICAgICAgICAgICAgIG5vZGUuaW1wb3J0Q2xhdXNlLFxuICAgICAgICAgICAgICBuZXdNb2R1bGVTcGVjaWZpZXIsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHRzLmlzRXhwb3J0RGVjbGFyYXRpb24obm9kZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkUGF0aCA9IHJlc29sdmVQYXRoKG5vZGUubW9kdWxlU3BlY2lmaWVyLnRleHQpO1xuICAgICAgICAgICAgY29uc3QgbmV3TW9kdWxlU3BlY2lmaWVyID1cbiAgICAgICAgICAgICAgdHJhbnNmb3JtYXRpb25Db250ZXh0LmZhY3RvcnkuY3JlYXRlU3RyaW5nTGl0ZXJhbChyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgICAgcmV0dXJuIHRyYW5zZm9ybWF0aW9uQ29udGV4dC5mYWN0b3J5LnVwZGF0ZUV4cG9ydERlY2xhcmF0aW9uKFxuICAgICAgICAgICAgICBub2RlLFxuICAgICAgICAgICAgICBub2RlLm1vZGlmaWVycyxcbiAgICAgICAgICAgICAgbm9kZS5pc1R5cGVPbmx5LFxuICAgICAgICAgICAgICBub2RlLmV4cG9ydENsYXVzZSxcbiAgICAgICAgICAgICAgbmV3TW9kdWxlU3BlY2lmaWVyLFxuICAgICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRzLnZpc2l0RWFjaENoaWxkKG5vZGUsIHZpc2l0Tm9kZSwgdHJhbnNmb3JtYXRpb25Db250ZXh0KTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gc2hvdWxkTXV0YXRlTW9kdWxlU3BlY2lmaWVyKG5vZGU6IHRzLk5vZGUpOiBub2RlIGlzIChcbiAgICAgICAgfCB0cy5JbXBvcnREZWNsYXJhdGlvblxuICAgICAgICB8IHRzLkV4cG9ydERlY2xhcmF0aW9uXG4gICAgICApICYge1xuICAgICAgICBtb2R1bGVTcGVjaWZpZXI6IHRzLlN0cmluZ0xpdGVyYWw7XG4gICAgICB9IHtcbiAgICAgICAgaWYgKCF0cy5pc0ltcG9ydERlY2xhcmF0aW9uKG5vZGUpICYmICF0cy5pc0V4cG9ydERlY2xhcmF0aW9uKG5vZGUpKVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgICAgICBpZiAobm9kZS5tb2R1bGVTcGVjaWZpZXIgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAvLyBvbmx5IHdoZW4gbW9kdWxlIHNwZWNpZmllciBpcyB2YWxpZFxuICAgICAgICBpZiAoIXRzLmlzU3RyaW5nTGl0ZXJhbChub2RlLm1vZHVsZVNwZWNpZmllcikpIHJldHVybiBmYWxzZTtcbiAgICAgICAgLy8gb25seSB3aGVuIHBhdGggaXMgcmVsYXRpdmVcbiAgICAgICAgaWYgKFxuICAgICAgICAgICFub2RlLm1vZHVsZVNwZWNpZmllci50ZXh0LnN0YXJ0c1dpdGgoXCIuL1wiKSAmJlxuICAgICAgICAgICFub2RlLm1vZHVsZVNwZWNpZmllci50ZXh0LnN0YXJ0c1dpdGgoXCIuLi9cIilcbiAgICAgICAgKVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgLy8gb25seSB3aGVuIG1vZHVsZSBzcGVjaWZpZXIgaGFzIG5vIGV4dGVuc2lvblxuICAgICAgICBpZiAocGF0aC5leHRuYW1lKG5vZGUubW9kdWxlU3BlY2lmaWVyLnRleHQpICE9PSBcIlwiKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdHMudmlzaXROb2RlKHNvdXJjZUZpbGUsIHZpc2l0Tm9kZSkgYXMgU291cmNlRmlsZTtcbiAgICB9O1xuICB9O1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBjb21tYW5kLWxpbmUgc2NyaXB0IGZvciBidWlsZGluZyBhbmQgYnVuZGxpbmcgVHlwZVNjcmlwdCBwcm9qZWN0cy5cbiAqIEBzdW1tYXJ5IFRoaXMgY2xhc3MgcHJvdmlkZXMgYSBjb21wcmVoZW5zaXZlIGJ1aWxkIHNjcmlwdCB0aGF0IGhhbmRsZXMgVHlwZVNjcmlwdCBjb21waWxhdGlvbixcbiAqIGJ1bmRsaW5nIHdpdGggUm9sbHVwLCBhbmQgZG9jdW1lbnRhdGlvbiBnZW5lcmF0aW9uLiBJdCBzdXBwb3J0cyBkaWZmZXJlbnQgYnVpbGQgbW9kZXNcbiAqIChkZXZlbG9wbWVudCwgcHJvZHVjdGlvbiksIG1vZHVsZSBmb3JtYXRzIChDSlMsIEVTTSksIGFuZCBjYW4gYmUgZXh0ZW5kZWQgd2l0aCBjdXN0b21cbiAqIGNvbmZpZ3VyYXRpb25zLlxuICogQGNsYXNzIEJ1aWxkU2NyaXB0c1xuICovXG5leHBvcnQgY2xhc3MgQnVpbGRTY3JpcHRzIGV4dGVuZHMgQ29tbWFuZDxcbiAgQ29tbWFuZE9wdGlvbnM8dHlwZW9mIG9wdGlvbnM+LFxuICB2b2lkXG4+IHtcbiAgcHJpdmF0ZSByZXBsYWNlbWVudHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgcHJpdmF0ZSByZWFkb25seSBwa2dWZXJzaW9uOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGtnTmFtZTogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKFxuICAgICAgXCJCdWlsZFNjcmlwdHNcIixcbiAgICAgIE9iamVjdC5hc3NpZ24oe30sIERlZmF1bHRDb21tYW5kT3B0aW9ucywgb3B0aW9ucykgYXMgQ29tbWFuZE9wdGlvbnM8XG4gICAgICAgIHR5cGVvZiBvcHRpb25zXG4gICAgICA+XG4gICAgKTtcbiAgICBjb25zdCBwa2cgPSBnZXRQYWNrYWdlKCkgYXMgeyBuYW1lOiBzdHJpbmc7IHZlcnNpb246IHN0cmluZyB9O1xuICAgIGNvbnN0IHsgbmFtZSwgdmVyc2lvbiB9ID0gcGtnO1xuICAgIHRoaXMucGtnTmFtZSA9IG5hbWUuaW5jbHVkZXMoXCJAXCIpID8gbmFtZS5zcGxpdChcIi9cIilbMV0gOiBuYW1lO1xuICAgIHRoaXMucGtnVmVyc2lvbiA9IHZlcnNpb247XG4gICAgdGhpcy5yZXBsYWNlbWVudHNbVkVSU0lPTl9TVFJJTkddID0gdGhpcy5wa2dWZXJzaW9uO1xuICAgIHRoaXMucmVwbGFjZW1lbnRzW1BBQ0tBR0VfU1RSSU5HXSA9IG5hbWU7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBhdGNoZXMgZmlsZXMgd2l0aCB2ZXJzaW9uIGFuZCBwYWNrYWdlIG5hbWUuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIHJlYWRzIGFsbCBmaWxlcyBpbiBhIGRpcmVjdG9yeSwgZmluZHMgcGxhY2Vob2xkZXJzIGZvciB2ZXJzaW9uXG4gICAqIGFuZCBwYWNrYWdlIG5hbWUsIGFuZCByZXBsYWNlcyB0aGVtIHdpdGggdGhlIGFjdHVhbCB2YWx1ZXMgZnJvbSBwYWNrYWdlLmpzb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwIC0gVGhlIHBhdGggdG8gdGhlIGRpcmVjdG9yeSBjb250YWluaW5nIHRoZSBmaWxlcyB0byBwYXRjaC5cbiAgICovXG4gIHBhdGNoRmlsZXMocDogc3RyaW5nKSB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMucGF0Y2hGaWxlcyk7XG4gICAgY29uc3QgeyBuYW1lLCB2ZXJzaW9uIH0gPSBnZXRQYWNrYWdlKCkgYXMgYW55O1xuICAgIGxvZy5pbmZvKGBQYXRjaGluZyAke25hbWV9ICR7dmVyc2lvbn0gbW9kdWxlIGluICR7cH0uLi5gKTtcbiAgICBjb25zdCBzdGF0ID0gZnMuc3RhdFN5bmMocCk7XG4gICAgaWYgKHN0YXQuaXNEaXJlY3RvcnkoKSlcbiAgICAgIGZzLnJlYWRkaXJTeW5jKHAsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSwgcmVjdXJzaXZlOiB0cnVlIH0pXG4gICAgICAgIC5maWx0ZXIoKHApID0+IHAuaXNGaWxlKCkpXG4gICAgICAgIC5mb3JFYWNoKChmaWxlKSA9PlxuICAgICAgICAgIHBhdGNoRmlsZShcbiAgICAgICAgICAgIHBhdGguam9pbihmaWxlLnBhcmVudFBhdGgsIGZpbGUubmFtZSksXG4gICAgICAgICAgICBPYmplY3QuZW50cmllcyh0aGlzLnJlcGxhY2VtZW50cykucmVkdWNlKFxuICAgICAgICAgICAgICAoYWNjOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICAgICAgICAgIGNhc2UgVkVSU0lPTl9TVFJJTkc6XG4gICAgICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIkZvdW5kIFZFUlNJT04gc3RyaW5nIHRvIHJlcGxhY2VcIik7XG4gICAgICAgICAgICAgICAgICAgIGFjY1tgVkVSU0lPTiA9IFwiJHtWRVJTSU9OX1NUUklOR31cIjtgXSA9XG4gICAgICAgICAgICAgICAgICAgICAgYFZFUlNJT04gPSBcIiR7dmFsfVwiO2A7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgY2FzZSBQQUNLQUdFX1NUUklORzpcbiAgICAgICAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiRm91bmQgUEFDS0FHRV9OQU1FIHN0cmluZyB0byByZXBsYWNlXCIpO1xuICAgICAgICAgICAgICAgICAgICBhY2NbYFBBQ0tBR0VfTkFNRSA9IFwiJHtQQUNLQUdFX1NUUklOR31cIjtgXSA9XG4gICAgICAgICAgICAgICAgICAgICAgYFBBQ0tBR0VfTkFNRSA9IFwiJHt2YWx9XCI7YDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBhY2Nba2V5XSA9IHZhbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAge31cbiAgICAgICAgICAgIClcbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgbG9nLnZlcmJvc2UoYE1vZHVsZSAke25hbWV9ICR7dmVyc2lvbn0gcGF0Y2hlZCBpbiAke3B9Li4uYCk7XG4gIH1cblxuICBwcml2YXRlIHJlcG9ydERpYWdub3N0aWNzKFxuICAgIGRpYWdub3N0aWNzOiBEaWFnbm9zdGljW10sXG4gICAgbG9nTGV2ZWw6IExvZ0xldmVsXG4gICk6IHN0cmluZyB7XG4gICAgY29uc3QgbXNnID0gdGhpcy5mb3JtYXREaWFnbm9zdGljcyhkaWFnbm9zdGljcyk7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMubG9nW2xvZ0xldmVsXShtc2cpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGNvbnNvbGUud2FybihgRmFpbGVkIHRvIGdldCBsb2dnZXIgZm9yICR7bG9nTGV2ZWx9YCk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgICByZXR1cm4gbXNnO1xuICB9XG5cbiAgLy8gRm9ybWF0IGRpYWdub3N0aWNzIGludG8gYSBzaW5nbGUgc3RyaW5nIGZvciB0aHJvd2luZyBvciBsb2dnaW5nXG4gIHByaXZhdGUgZm9ybWF0RGlhZ25vc3RpY3MoZGlhZ25vc3RpY3M6IERpYWdub3N0aWNbXSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGRpYWdub3N0aWNzXG4gICAgICAubWFwKChkaWFnbm9zdGljKSA9PiB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gXCJcIjtcbiAgICAgICAgaWYgKGRpYWdub3N0aWMuZmlsZSAmJiBkaWFnbm9zdGljLnN0YXJ0KSB7XG4gICAgICAgICAgY29uc3QgeyBsaW5lLCBjaGFyYWN0ZXIgfSA9XG4gICAgICAgICAgICBkaWFnbm9zdGljLmZpbGUuZ2V0TGluZUFuZENoYXJhY3Rlck9mUG9zaXRpb24oZGlhZ25vc3RpYy5zdGFydCk7XG4gICAgICAgICAgbWVzc2FnZSArPSBgJHtkaWFnbm9zdGljLmZpbGUuZmlsZU5hbWV9ICgke2xpbmUgKyAxfSwke2NoYXJhY3RlciArIDF9KWA7XG4gICAgICAgIH1cbiAgICAgICAgbWVzc2FnZSArPVxuICAgICAgICAgIFwiOiBcIiArIHRzLmZsYXR0ZW5EaWFnbm9zdGljTWVzc2FnZVRleHQoZGlhZ25vc3RpYy5tZXNzYWdlVGV4dCwgXCJcXG5cIik7XG4gICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgfSlcbiAgICAgIC5qb2luKFwiXFxuXCIpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkQ29uZmlnRmlsZShjb25maWdGaWxlTmFtZTogc3RyaW5nKSB7XG4gICAgLy8gUmVhZCBjb25maWcgZmlsZVxuICAgIGNvbnN0IGNvbmZpZ0ZpbGVUZXh0ID0gZnMucmVhZEZpbGVTeW5jKGNvbmZpZ0ZpbGVOYW1lKS50b1N0cmluZygpO1xuXG4gICAgLy8gUGFyc2UgSlNPTiwgYWZ0ZXIgcmVtb3ZpbmcgY29tbWVudHMuIEp1c3QgZmFuY2llciBKU09OLnBhcnNlXG4gICAgY29uc3QgcmVzdWx0ID0gdHMucGFyc2VDb25maWdGaWxlVGV4dFRvSnNvbihjb25maWdGaWxlTmFtZSwgY29uZmlnRmlsZVRleHQpO1xuICAgIGNvbnN0IGNvbmZpZ09iamVjdCA9IHJlc3VsdC5jb25maWc7XG4gICAgaWYgKCFjb25maWdPYmplY3QpIHtcbiAgICAgIHRoaXMucmVwb3J0RGlhZ25vc3RpY3MoW3Jlc3VsdC5lcnJvciFdLCBMb2dMZXZlbC5lcnJvcik7XG4gICAgfVxuXG4gICAgLy8gRXh0cmFjdCBjb25maWcgaW5mcm9tYXRpb25cbiAgICBjb25zdCBjb25maWdQYXJzZVJlc3VsdCA9IHRzLnBhcnNlSnNvbkNvbmZpZ0ZpbGVDb250ZW50KFxuICAgICAgY29uZmlnT2JqZWN0LFxuICAgICAgdHMuc3lzLFxuICAgICAgcGF0aC5kaXJuYW1lKGNvbmZpZ0ZpbGVOYW1lKVxuICAgICk7XG4gICAgaWYgKGNvbmZpZ1BhcnNlUmVzdWx0LmVycm9ycy5sZW5ndGggPiAwKVxuICAgICAgdGhpcy5yZXBvcnREaWFnbm9zdGljcyhjb25maWdQYXJzZVJlc3VsdC5lcnJvcnMsIExvZ0xldmVsLmVycm9yKTtcblxuICAgIHJldHVybiBjb25maWdQYXJzZVJlc3VsdDtcbiAgfVxuXG4gIHByaXZhdGUgZXZhbERpYWdub3N0aWNzKGRpYWdub3N0aWNzOiBEaWFnbm9zdGljW10pIHtcbiAgICBpZiAoZGlhZ25vc3RpY3MgJiYgZGlhZ25vc3RpY3MubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgZXJyb3JzID0gZGlhZ25vc3RpY3MuZmlsdGVyKFxuICAgICAgICAoZCkgPT4gZC5jYXRlZ29yeSA9PT0gdHMuRGlhZ25vc3RpY0NhdGVnb3J5LkVycm9yXG4gICAgICApO1xuICAgICAgY29uc3Qgd2FybmluZ3MgPSBkaWFnbm9zdGljcy5maWx0ZXIoXG4gICAgICAgIChkKSA9PiBkLmNhdGVnb3J5ID09PSB0cy5EaWFnbm9zdGljQ2F0ZWdvcnkuV2FybmluZ1xuICAgICAgKTtcbiAgICAgIGNvbnN0IHN1Z2dlc3Rpb25zID0gZGlhZ25vc3RpY3MuZmlsdGVyKFxuICAgICAgICAoZCkgPT4gZC5jYXRlZ29yeSA9PT0gdHMuRGlhZ25vc3RpY0NhdGVnb3J5LlN1Z2dlc3Rpb25cbiAgICAgICk7XG4gICAgICBjb25zdCBtZXNzYWdlcyA9IGRpYWdub3N0aWNzLmZpbHRlcihcbiAgICAgICAgKGQpID0+IGQuY2F0ZWdvcnkgPT09IHRzLkRpYWdub3N0aWNDYXRlZ29yeS5NZXNzYWdlXG4gICAgICApO1xuICAgICAgLy8gTG9nIGRpYWdub3N0aWNzIHRvIGNvbnNvbGVcblxuICAgICAgaWYgKHdhcm5pbmdzLmxlbmd0aCkgdGhpcy5yZXBvcnREaWFnbm9zdGljcyh3YXJuaW5ncywgTG9nTGV2ZWwud2Fybik7XG4gICAgICBpZiAoZXJyb3JzLmxlbmd0aCkge1xuICAgICAgICB0aGlzLnJlcG9ydERpYWdub3N0aWNzKGRpYWdub3N0aWNzIGFzIERpYWdub3N0aWNbXSwgTG9nTGV2ZWwuZXJyb3IpO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYFR5cGVTY3JpcHQgcmVwb3J0ZWQgJHtkaWFnbm9zdGljcy5sZW5ndGh9IGRpYWdub3N0aWMocykgZHVyaW5nIGNoZWNrOyBhYm9ydGluZy5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoc3VnZ2VzdGlvbnMubGVuZ3RoKVxuICAgICAgICB0aGlzLnJlcG9ydERpYWdub3N0aWNzKHN1Z2dlc3Rpb25zLCBMb2dMZXZlbC5pbmZvKTtcbiAgICAgIGlmIChtZXNzYWdlcy5sZW5ndGgpIHRoaXMucmVwb3J0RGlhZ25vc3RpY3MobWVzc2FnZXMsIExvZ0xldmVsLmluZm8pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcHJlQ2hlY2tEaWFnbm9zdGljcyhwcm9ncmFtOiB0cy5Qcm9ncmFtKSB7XG4gICAgY29uc3QgZGlhZ25vc3RpY3MgPSB0cy5nZXRQcmVFbWl0RGlhZ25vc3RpY3MocHJvZ3JhbSk7XG4gICAgdGhpcy5ldmFsRGlhZ25vc3RpY3MoZGlhZ25vc3RpY3MgYXMgYW55KTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBhIFR5cGVTY3JpcHQgcHJvZ3JhbSBmb3IgdGhlIGN1cnJlbnQgdHNjb25maWcgYW5kIGZhaWwgaWYgdGhlcmUgYXJlIGFueSBlcnJvciBkaWFnbm9zdGljcy5cbiAgcHJpdmF0ZSBhc3luYyBjaGVja1RzRGlhZ25vc3RpY3MoXG4gICAgaXNEZXY6IGJvb2xlYW4sXG4gICAgbW9kZTogTW9kZXMsXG4gICAgYnVuZGxlID0gZmFsc2VcbiAgKSB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuY2hlY2tUc0RpYWdub3N0aWNzKTtcbiAgICBsZXQgdHNDb25maWc7XG4gICAgdHJ5IHtcbiAgICAgIHRzQ29uZmlnID0gdGhpcy5yZWFkQ29uZmlnRmlsZShcIi4vdHNjb25maWcuanNvblwiKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBwYXJzZSB0c2NvbmZpZy5qc29uOiAke2V9YCk7XG4gICAgfVxuXG4gICAgaWYgKGJ1bmRsZSkge1xuICAgICAgdHNDb25maWcub3B0aW9ucy5tb2R1bGUgPSBNb2R1bGVLaW5kLkFNRDtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMub3V0RGlyID0gXCJkaXN0XCI7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLmlzb2xhdGVkTW9kdWxlcyA9IGZhbHNlO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5vdXRGaWxlID0gdGhpcy5wa2dOYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLm91dERpciA9IGBsaWIke21vZGUgPT09IE1vZGVzLkVTTSA/IFwiL2VzbVwiIDogXCJcIn1gO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5tb2R1bGUgPVxuICAgICAgICBtb2RlID09PSBNb2Rlcy5FU00gPyBNb2R1bGVLaW5kLkVTMjAyMiA6IE1vZHVsZUtpbmQuQ29tbW9uSlM7XG4gICAgfVxuXG4gICAgLy8gRW5zdXJlIFR5cGVTY3JpcHQgZW1pdHMgaW5saW5lIHNvdXJjZSBtYXBzIGZvciBib3RoIGRldiBhbmQgcHJvZCAoYnVuZGxlcnMgd2lsbCBjb250cm9sIGV4dGVybmFsIG1hcHMpXG4gICAgLy8gS2VlcCBjb21tZW50cyBpbiBUUyBlbWl0IGJ5IGRlZmF1bHQ7IGJ1bmRsaW5nL21pbmlmaWNhdGlvbiB3aWxsIGhhbmRsZSByZW1vdmFsIHdoZXJlIHJlcXVlc3RlZC5cbiAgICAvLyBFbWl0IGV4dGVybmFsIHNvdXJjZSBtYXBzIGZyb20gVHlwZVNjcmlwdCBzbyBlZGl0b3JzL2RlYnVnZ2VycyBjYW4gZmluZCB0aGVtLlxuICAgIC8vIFR1cm4gb2ZmIGlubGluZSBtYXBzL3NvdXJjZXMgc28gYnVuZGxlcnMgKFJvbGx1cCkgY2FuIGNvbnRyb2wgd2hldGhlciBtYXBzIGFyZSBpbmxpbmVkIG9yIHdyaXR0ZW4gZXh0ZXJuYWxseS5cbiAgICB0c0NvbmZpZy5vcHRpb25zLmlubGluZVNvdXJjZU1hcCA9IGZhbHNlO1xuICAgIHRzQ29uZmlnLm9wdGlvbnMuaW5saW5lU291cmNlcyA9IGZhbHNlO1xuICAgIHRzQ29uZmlnLm9wdGlvbnMuc291cmNlTWFwID0gdHJ1ZTtcblxuICAgIGNvbnN0IHByb2dyYW0gPSB0cy5jcmVhdGVQcm9ncmFtKHRzQ29uZmlnLmZpbGVOYW1lcywgdHNDb25maWcub3B0aW9ucyk7XG4gICAgdGhpcy5wcmVDaGVja0RpYWdub3N0aWNzKHByb2dyYW0pO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYFR5cGVTY3JpcHQgY2hlY2tzIHBhc3NlZCAoJHtidW5kbGUgPyBcImJ1bmRsZVwiIDogXCJub3JtYWxcIn0gbW9kZSkuYFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJ1aWxkVHMoaXNEZXY6IGJvb2xlYW4sIG1vZGU6IE1vZGVzLCBidW5kbGUgPSBmYWxzZSkge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLmJ1aWxkVHMpO1xuICAgIGxvZy5pbmZvKFxuICAgICAgYEJ1aWxkaW5nICR7dGhpcy5wa2dOYW1lfSAke3RoaXMucGtnVmVyc2lvbn0gbW9kdWxlICgke21vZGV9KSBpbiAke2lzRGV2ID8gXCJkZXZcIiA6IFwicHJvZFwifSBtb2RlLi4uYFxuICAgICk7XG4gICAgbGV0IHRzQ29uZmlnO1xuICAgIHRyeSB7XG4gICAgICB0c0NvbmZpZyA9IHRoaXMucmVhZENvbmZpZ0ZpbGUoXCIuL3RzY29uZmlnLmpzb25cIik7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcGFyc2UgdHNjb25maWcuanNvbjogJHtlfWApO1xuICAgIH1cblxuICAgIGlmIChidW5kbGUpIHtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMubW9kdWxlID0gTW9kdWxlS2luZC5BTUQ7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLm91dERpciA9IFwiZGlzdFwiO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5pc29sYXRlZE1vZHVsZXMgPSBmYWxzZTtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMub3V0RmlsZSA9IHRoaXMucGtnTmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdHNDb25maWcub3B0aW9ucy5vdXREaXIgPSBgbGliJHttb2RlID09PSBNb2Rlcy5FU00gPyBcIi9lc21cIiA6IFwiXCJ9YDtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMubW9kdWxlID1cbiAgICAgICAgbW9kZSA9PT0gTW9kZXMuRVNNID8gTW9kdWxlS2luZC5FUzIwMjIgOiBNb2R1bGVLaW5kLkNvbW1vbkpTO1xuICAgIH1cblxuICAgIC8vIEFsd2F5cyBlbWl0IGlubGluZSBzb3VyY2UgbWFwcyBmcm9tIHRzYyAoYnVuZGxlciB3aWxsIGVtaXQgZXh0ZXJuYWwgbWFwcyBmb3IgcHJvZHVjdGlvbiBidW5kbGVzKS5cbiAgICAvLyBGb3IgZGV2IGJ1aWxkcyB3ZSB3YW50IFR5cGVTY3JpcHQgdG8gZW1pdCBpbmxpbmUgc291cmNlIG1hcHMgc28gbm8gc2VwYXJhdGUgLm1hcCBmaWxlcyBhcmUgcHJvZHVjZWQuXG4gICAgLy8gRm9yIHByb2R1Y3Rpb24gd2UgZW1pdCBleHRlcm5hbCBzb3VyY2UgbWFwcyBzbyB0aGUgYnVuZGxlciBjYW4gZnVydGhlciB0cmFuc2Zvcm0gYW5kIGVtaXQgdGhlbS5cbiAgICBpZiAoaXNEZXYpIHtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMuaW5saW5lU291cmNlTWFwID0gdHJ1ZTtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMuaW5saW5lU291cmNlcyA9IHRydWU7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLnNvdXJjZU1hcCA9IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLmlubGluZVNvdXJjZU1hcCA9IGZhbHNlO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5pbmxpbmVTb3VyY2VzID0gZmFsc2U7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLnNvdXJjZU1hcCA9IHRydWU7XG4gICAgfVxuXG4gICAgLy8gRm9yIHByb2R1Y3Rpb24gYnVpbGRzIHdlIHN0aWxsIGtlZXAgVHlwZVNjcmlwdCBjb21tZW50cyAocmVtb3ZlQ29tbWVudHM9ZmFsc2UgaW4gdHNjb25maWcpXG4gICAgLy8gQnVuZGxlci90ZXJzZXIgd2lsbCBzdHJpcCBjb21tZW50cyBmb3IgcHJvZHVjdGlvbiBidW5kbGVzIGFzIHJlcXVlc3RlZC5cblxuICAgIGNvbnN0IHByb2dyYW0gPSB0cy5jcmVhdGVQcm9ncmFtKHRzQ29uZmlnLmZpbGVOYW1lcywgdHNDb25maWcub3B0aW9ucyk7XG5cbiAgICBjb25zdCB0cmFuc2Zvcm1hdGlvbnM6IHsgYmVmb3JlPzogYW55W10gfSA9IHt9O1xuICAgIGlmIChtb2RlID09PSBNb2Rlcy5DSlMpIHtcbiAgICAgIHRyYW5zZm9ybWF0aW9ucy5iZWZvcmUgPSBbY2pzMlRyYW5zZm9ybWVyKFwiLmNqc1wiKV07XG4gICAgfSBlbHNlIGlmIChtb2RlID09PSBNb2Rlcy5FU00pIHtcbiAgICAgIHRyYW5zZm9ybWF0aW9ucy5iZWZvcmUgPSBbY2pzMlRyYW5zZm9ybWVyKFwiLmpzXCIpXTtcbiAgICB9XG5cbiAgICBjb25zdCBlbWl0UmVzdWx0OiBFbWl0UmVzdWx0ID0gcHJvZ3JhbS5lbWl0KFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdHJhbnNmb3JtYXRpb25zXG4gICAgKTtcblxuICAgIGNvbnN0IGFsbERpYWdub3N0aWNzID0gdHNcbiAgICAgIC5nZXRQcmVFbWl0RGlhZ25vc3RpY3MocHJvZ3JhbSlcbiAgICAgIC5jb25jYXQoZW1pdFJlc3VsdC5kaWFnbm9zdGljcyk7XG5cbiAgICB0aGlzLmV2YWxEaWFnbm9zdGljcyhhbGxEaWFnbm9zdGljcyk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJ1aWxkKGlzRGV2OiBib29sZWFuLCBtb2RlOiBNb2RlcywgYnVuZGxlID0gZmFsc2UpIHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5idWlsZCk7XG4gICAgYXdhaXQgdGhpcy5idWlsZFRzKGlzRGV2LCBtb2RlLCBidW5kbGUpO1xuXG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgTW9kdWxlICR7dGhpcy5wa2dOYW1lfSAke3RoaXMucGtnVmVyc2lvbn0gKCR7bW9kZX0pIGJ1aWx0IGluICR7aXNEZXYgPyBcImRldlwiIDogXCJwcm9kXCJ9IG1vZGUuLi5gXG4gICAgKTtcbiAgICBpZiAobW9kZSA9PT0gTW9kZXMuQ0pTICYmICFidW5kbGUpIHtcbiAgICAgIGNvbnN0IGZpbGVzID0gZ2V0QWxsRmlsZXMoXG4gICAgICAgIFwibGliXCIsXG4gICAgICAgIChmaWxlKSA9PiBmaWxlLmVuZHNXaXRoKFwiLmpzXCIpICYmICFmaWxlLmluY2x1ZGVzKFwiL2VzbS9cIilcbiAgICAgICk7XG5cbiAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgICAgICBsb2cudmVyYm9zZShgUGF0Y2hpbmcgJHtmaWxlfSdzIGNqcyBpbXBvcnRzLi4uYCk7XG4gICAgICAgIGNvbnN0IGYgPSBmaWxlLnJlcGxhY2UoXCIuanNcIiwgXCIuY2pzXCIpO1xuICAgICAgICBhd2FpdCByZW5hbWVGaWxlKGZpbGUsIGYpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29waWVzIGFzc2V0cyB0byB0aGUgYnVpbGQgb3V0cHV0IGRpcmVjdG9yeS5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgY2hlY2tzIGZvciB0aGUgZXhpc3RlbmNlIG9mIGFuICdhc3NldHMnIGRpcmVjdG9yeSBpbiB0aGUgc291cmNlXG4gICAqIGFuZCBjb3BpZXMgaXQgdG8gdGhlIGFwcHJvcHJpYXRlIGJ1aWxkIG91dHB1dCBkaXJlY3RvcnkgKGxpYiBvciBkaXN0KS5cbiAgICogQHBhcmFtIHtNb2Rlc30gbW9kZSAtIFRoZSBidWlsZCBtb2RlIChDSlMgb3IgRVNNKS5cbiAgICovXG4gIGNvcHlBc3NldHMobW9kZTogTW9kZXMpIHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5jb3B5QXNzZXRzKTtcbiAgICBsZXQgaGFzQXNzZXRzID0gZmFsc2U7XG4gICAgdHJ5IHtcbiAgICAgIGhhc0Fzc2V0cyA9IGZzLnN0YXRTeW5jKFwiLi9zcmMvYXNzZXRzXCIpLmlzRGlyZWN0b3J5KCk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgcmV0dXJuIGxvZy52ZXJib3NlKGBObyBhc3NldHMgZm91bmQgaW4gLi9zcmMvYXNzZXRzIHRvIGNvcHlgKTtcbiAgICB9XG4gICAgaWYgKGhhc0Fzc2V0cylcbiAgICAgIGNvcHlGaWxlKFxuICAgICAgICBcIi4vc3JjL2Fzc2V0c1wiLFxuICAgICAgICBgLi8ke21vZGUgPT09IE1vZGVzLkNKUyA/IFwibGliXCIgOiBcImRpc3RcIn0vYXNzZXRzYFxuICAgICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQnVuZGxlcyB0aGUgcHJvamVjdCB1c2luZyBSb2xsdXAuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGNvbmZpZ3VyZXMgYW5kIHJ1bnMgUm9sbHVwIHRvIGJ1bmRsZSB0aGUgcHJvamVjdC4gSXQgaGFuZGxlc1xuICAgKiBkaWZmZXJlbnQgbW9kdWxlIGZvcm1hdHMsIGRldmVsb3BtZW50IGFuZCBwcm9kdWN0aW9uIGJ1aWxkcywgYW5kIGV4dGVybmFsIGRlcGVuZGVuY2llcy5cbiAgICogQHBhcmFtIHtNb2Rlc30gbW9kZSAtIFRoZSBtb2R1bGUgZm9ybWF0IChDSlMgb3IgRVNNKS5cbiAgICogQHBhcmFtIHtib29sZWFufSBpc0RldiAtIFdoZXRoZXIgaXQncyBhIGRldmVsb3BtZW50IGJ1aWxkLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzTGliIC0gV2hldGhlciBpdCdzIGEgbGlicmFyeSBidWlsZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtlbnRyeUZpbGU9XCJzcmMvaW5kZXgudHNcIl0gLSBUaGUgZW50cnkgZmlsZSBmb3IgdGhlIGJ1bmRsZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtuYW1lT3ZlcnJpZGU9dGhpcy5wa2dOYW1lXSAtIFRoZSBuYW1lIG9mIHRoZSBvdXRwdXQgYnVuZGxlLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xzdHJpbmdbXX0gW2V4dGVybmFsc0FyZ10gLSBBIGxpc3Qgb2YgZXh0ZXJuYWwgZGVwZW5kZW5jaWVzLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xzdHJpbmdbXX0gW2luY2x1ZGVBcmddIC0gQSBsaXN0IG9mIGRlcGVuZGVuY2llcyB0byBpbmNsdWRlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIGJ1bmRsZShcbiAgICBtb2RlOiBNb2RlcyxcbiAgICBpc0RldjogYm9vbGVhbixcbiAgICBpc0xpYjogYm9vbGVhbixcbiAgICBlbnRyeUZpbGU6IHN0cmluZyA9IFwic3JjL2luZGV4LnRzXCIsXG4gICAgbmFtZU92ZXJyaWRlOiBzdHJpbmcgPSB0aGlzLnBrZ05hbWUsXG4gICAgZXh0ZXJuYWxzQXJnPzogc3RyaW5nIHwgc3RyaW5nW10sXG4gICAgaW5jbHVkZUFyZzogc3RyaW5nIHwgc3RyaW5nW10gPSBbXG4gICAgICBcInByb21wdHNcIixcbiAgICAgIFwic3R5bGVkLXN0cmluZy1idWlsZGVyXCIsXG4gICAgICBcInR5cGVkLW9iamVjdC1hY2N1bXVsYXRvclwiLFxuICAgICAgXCJAZGVjYWYtdHMvbG9nZ2luZ1wiLFxuICAgIF1cbiAgKSB7XG4gICAgLy8gUnVuIGEgVHlwZVNjcmlwdC1vbmx5IGRpYWdub3N0aWMgY2hlY2sgZm9yIHRoZSBidW5kbGluZyBjb25maWd1cmF0aW9uIGFuZCBmYWlsIGZhc3Qgb24gYW55IGVycm9ycy5cbiAgICBhd2FpdCB0aGlzLmNoZWNrVHNEaWFnbm9zdGljcyhpc0RldiwgbW9kZSwgdHJ1ZSk7XG4gICAgY29uc3QgaXNFc20gPSBtb2RlID09PSBNb2Rlcy5FU007XG4gICAgY29uc3QgcGtnTmFtZSA9IHRoaXMucGtnTmFtZTtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZztcblxuICAgIC8vIG5vcm1hbGl6ZSBpbmNsdWRlIGFuZCBleHRlcm5hbHNcbiAgICBjb25zdCBpbmNsdWRlID0gQXJyYXkuZnJvbShcbiAgICAgIG5ldyBTZXQoWy4uLihwYXJzZUxpc3QoaW5jbHVkZUFyZykgYXMgc3RyaW5nW10pXSlcbiAgICApO1xuICAgIGxldCBleHRlcm5hbHNMaXN0ID0gcGFyc2VMaXN0KGV4dGVybmFsc0FyZyk7XG4gICAgaWYgKGV4dGVybmFsc0xpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICAvLyBpZiBubyBleHRlcm5hbHMgc3BlY2lmaWVkLCBsaXN0IHRvcC1sZXZlbCBwYWNrYWdlcyBpbiBub2RlX21vZHVsZXMgKGV4cGFuZCBzY29wZXMpXG4gICAgICB0cnkge1xuICAgICAgICBleHRlcm5hbHNMaXN0ID0gbGlzdE5vZGVNb2R1bGVzUGFja2FnZXMoXG4gICAgICAgICAgcGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIFwibm9kZV9tb2R1bGVzXCIpXG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gZmFsbGJhY2sgdG8gcGFja2FnZS5qc29uIGRlcGVuZGVuY2llcyBpZiBsaXN0aW5nIGZhaWxzIG9yIHlpZWxkcyBub3RoaW5nXG4gICAgICB9XG4gICAgICBpZiAoIWV4dGVybmFsc0xpc3QgfHwgZXh0ZXJuYWxzTGlzdC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgZXh0ZXJuYWxzTGlzdCA9IGdldFBhY2thZ2VEZXBlbmRlbmNpZXMoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBleHQgPSBBcnJheS5mcm9tKFxuICAgICAgbmV3IFNldChbXG4gICAgICAgIC8vIGJ1aWx0aW5zIGFuZCBhbHdheXMgZXh0ZXJuYWwgcnVudGltZSBkZXBzXG4gICAgICAgIC4uLihmdW5jdGlvbiBidWlsdGluTGlzdCgpOiBzdHJpbmdbXSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoYnVpbHRpbk1vZHVsZXMpID8gYnVpbHRpbk1vZHVsZXMgOiBbXVxuICAgICAgICAgICAgKSBhcyBzdHJpbmdbXTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIGZhbGxiYWNrIHRvIGEgcmVhc29uYWJsZSBzdWJzZXQgaWYgYGJ1aWx0aW5Nb2R1bGVzYCBpcyB1bmF2YWlsYWJsZVxuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgXCJmc1wiLFxuICAgICAgICAgICAgICBcInBhdGhcIixcbiAgICAgICAgICAgICAgXCJwcm9jZXNzXCIsXG4gICAgICAgICAgICAgIFwiY2hpbGRfcHJvY2Vzc1wiLFxuICAgICAgICAgICAgICBcInV0aWxcIixcbiAgICAgICAgICAgICAgXCJodHRwc1wiLFxuICAgICAgICAgICAgICBcImh0dHBcIixcbiAgICAgICAgICAgICAgXCJvc1wiLFxuICAgICAgICAgICAgICBcInN0cmVhbVwiLFxuICAgICAgICAgICAgICBcImNyeXB0b1wiLFxuICAgICAgICAgICAgICBcInpsaWJcIixcbiAgICAgICAgICAgICAgXCJuZXRcIixcbiAgICAgICAgICAgICAgXCJ0bHNcIixcbiAgICAgICAgICAgICAgXCJ1cmxcIixcbiAgICAgICAgICAgICAgXCJxdWVyeXN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImFzc2VydFwiLFxuICAgICAgICAgICAgICBcImV2ZW50c1wiLFxuICAgICAgICAgICAgICBcInR0eVwiLFxuICAgICAgICAgICAgICBcImRuc1wiLFxuICAgICAgICAgICAgICBcInF1ZXJ5c3RyaW5nXCIsXG4gICAgICAgICAgICBdO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkoKSxcbiAgICAgICAgLi4uZXh0ZXJuYWxzTGlzdCxcbiAgICAgIF0pXG4gICAgKTtcblxuICAgIC8vIEZvciBwbHVnaW4tdHlwZXNjcmlwdCB3ZSB3YW50IGl0IHRvIGVtaXQgc291cmNlIG1hcHMgKG5vdCBpbmxpbmUpIHNvIFJvbGx1cCBjYW5cbiAgICAvLyBkZWNpZGUgd2hldGhlciB0byBpbmxpbmUgb3IgZW1pdCBleHRlcm5hbCBmaWxlcy4gVGhlIFJvbGx1cCBvdXRwdXQuc291cmNlbWFwXG4gICAgLy8gY29udHJvbHMgZmluYWwgbWFwIHBsYWNlbWVudC4gRG8gTk9UIHNldCBhIG5vbi1zdGFuZGFyZCBgc291cmNlbWFwYCBmaWVsZCBvblxuICAgIC8vIHRoZSByb2xsdXAgaW5wdXQgb3B0aW9ucyAoUm9sbHVwIHdpbGwgcmVqZWN0IGl0KS5cbiAgICBjb25zdCByb2xsdXBTb3VyY2VNYXBPdXRwdXQ6IGZhbHNlIHwgdHJ1ZSB8IFwiaW5saW5lXCIgfCBcImhpZGRlblwiID0gaXNEZXZcbiAgICAgID8gXCJpbmxpbmVcIlxuICAgICAgOiB0cnVlO1xuXG4gICAgY29uc3QgcGx1Z2lucyA9IFtcbiAgICAgIHR5cGVzY3JpcHQoe1xuICAgICAgICBjb21waWxlck9wdGlvbnM6IHtcbiAgICAgICAgICBtb2R1bGU6IFwiZXNuZXh0XCIsXG4gICAgICAgICAgZGVjbGFyYXRpb246IGZhbHNlLFxuICAgICAgICAgIG91dERpcjogaXNMaWIgPyBcImJpblwiIDogXCJkaXN0XCIsXG4gICAgICAgICAgLy8gRm9yIGRldiBidW5kbGVzIGVtaXQgaW5saW5lIHNvdXJjZSBtYXBzIChubyBzZXBhcmF0ZSAubWFwIGZpbGVzKS5cbiAgICAgICAgICAvLyBGb3IgcHJvZCBidW5kbGVzIGVtaXQgZXh0ZXJuYWwgbWFwcyBzbyBSb2xsdXAgY2FuIHdyaXRlIHRoZW0gdG8gZGlzay5cbiAgICAgICAgICBzb3VyY2VNYXA6IGlzRGV2ID8gZmFsc2UgOiB0cnVlLFxuICAgICAgICAgIGlubGluZVNvdXJjZU1hcDogaXNEZXYgPyB0cnVlIDogZmFsc2UsXG4gICAgICAgICAgaW5saW5lU291cmNlczogaXNEZXYgPyB0cnVlIDogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICAgIGluY2x1ZGU6IFtcInNyYy8qKi8qLnRzXCJdLFxuICAgICAgICBleGNsdWRlOiBbXCJub2RlX21vZHVsZXNcIiwgXCIqKi8qLnNwZWMudHNcIl0sXG4gICAgICAgIHRzY29uZmlnOiBcIi4vdHNjb25maWcuanNvblwiLFxuICAgICAgfSksXG4gICAgICBqc29uKCksXG4gICAgXTtcblxuICAgIGlmIChpc0xpYikge1xuICAgICAgcGx1Z2lucy5wdXNoKFxuICAgICAgICBjb21tb25qcyh7XG4gICAgICAgICAgaW5jbHVkZTogW10sXG4gICAgICAgICAgZXhjbHVkZTogZXh0ZXJuYWxzTGlzdCxcbiAgICAgICAgfSksXG4gICAgICAgIG5vZGVSZXNvbHZlKHtcbiAgICAgICAgICByZXNvbHZlT25seTogaW5jbHVkZSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gcHJvZHVjdGlvbiBtaW5pZmljYXRpb246IGFkZCB0ZXJzZXIgbGFzdCBzbyBpdCBzZWVzIHByaW9yIHNvdXJjZSBtYXBzXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRlcnNlck1vZDogYW55ID0gYXdhaXQgaW1wb3J0KFwiQHJvbGx1cC9wbHVnaW4tdGVyc2VyXCIpO1xuICAgICAgY29uc3QgdGVyc2VyRm4gPVxuICAgICAgICAodGVyc2VyTW9kICYmIHRlcnNlck1vZC50ZXJzZXIpIHx8IHRlcnNlck1vZC5kZWZhdWx0IHx8IHRlcnNlck1vZDtcblxuICAgICAgY29uc3QgdGVyc2VyT3B0aW9uc0RldjogYW55ID0ge1xuICAgICAgICBwYXJzZTogeyBlY21hOiAyMDIwIH0sXG4gICAgICAgIGNvbXByZXNzOiBmYWxzZSxcbiAgICAgICAgbWFuZ2xlOiBmYWxzZSxcbiAgICAgICAgZm9ybWF0OiB7XG4gICAgICAgICAgY29tbWVudHM6IGZhbHNlLFxuICAgICAgICAgIGJlYXV0aWZ5OiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdGVyc2VyT3B0aW9uc1Byb2Q6IGFueSA9IHtcbiAgICAgICAgcGFyc2U6IHsgZWNtYTogMjAyMCB9LFxuICAgICAgICBjb21wcmVzczoge1xuICAgICAgICAgIGVjbWE6IDIwMjAsXG4gICAgICAgICAgcGFzc2VzOiA1LFxuICAgICAgICAgIGRyb3BfY29uc29sZTogdHJ1ZSxcbiAgICAgICAgICBkcm9wX2RlYnVnZ2VyOiB0cnVlLFxuICAgICAgICAgIHRvcGxldmVsOiB0cnVlLFxuICAgICAgICAgIG1vZHVsZTogaXNFc20sXG4gICAgICAgICAgdW5zYWZlOiB0cnVlLFxuICAgICAgICAgIHVuc2FmZV9hcnJvd3M6IHRydWUsXG4gICAgICAgICAgdW5zYWZlX2NvbXBzOiB0cnVlLFxuICAgICAgICAgIGNvbGxhcHNlX3ZhcnM6IHRydWUsXG4gICAgICAgICAgcmVkdWNlX2Z1bmNzOiB0cnVlLFxuICAgICAgICAgIHJlZHVjZV92YXJzOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgICBtYW5nbGU6IHtcbiAgICAgICAgICB0b3BsZXZlbDogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgICAgZm9ybWF0OiB7XG4gICAgICAgICAgY29tbWVudHM6IGZhbHNlLFxuICAgICAgICAgIGFzY2lpX29ubHk6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIHRvcGxldmVsOiB0cnVlLFxuICAgICAgfTtcblxuICAgICAgcGx1Z2lucy5wdXNoKHRlcnNlckZuKGlzRGV2ID8gdGVyc2VyT3B0aW9uc0RldiA6IHRlcnNlck9wdGlvbnNQcm9kKSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBpZiB0ZXJzZXIgaXNuJ3QgYXZhaWxhYmxlLCBpZ25vcmVcbiAgICB9XG5cbiAgICBjb25zdCBpbnB1dDogSW5wdXRPcHRpb25zID0ge1xuICAgICAgaW5wdXQ6IGVudHJ5RmlsZSxcbiAgICAgIHBsdWdpbnM6IHBsdWdpbnMsXG4gICAgICBleHRlcm5hbDogZXh0LFxuICAgICAgb253YXJuOiB1bmRlZmluZWQsXG4gICAgICAvLyBlbmFibGUgdHJlZS1zaGFraW5nIGZvciBwcm9kdWN0aW9uIGJ1bmRsZXNcbiAgICAgIHRyZWVzaGFrZTogIWlzRGV2LFxuICAgIH0gYXMgYW55O1xuXG4gICAgLy8gcHJlcGFyZSBvdXRwdXQgZ2xvYmFscyBtYXBwaW5nIGZvciBleHRlcm5hbHNcbiAgICBjb25zdCBnbG9iYWxzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgLy8gaW5jbHVkZSBhbGwgZXh0ZXJuYWxzIGFuZCBidWlsdGlucyAoZXh0KSBzbyBSb2xsdXAgd29uJ3QgZ3Vlc3MgbmFtZXMgZm9yIGJ1aWx0aW5zXG4gICAgZXh0LmZvckVhY2goKGUpID0+IHtcbiAgICAgIGdsb2JhbHNbZV0gPSBwYWNrYWdlVG9HbG9iYWwoZSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBvdXRwdXRzOiBPdXRwdXRPcHRpb25zW10gPSBbXG4gICAgICB7XG4gICAgICAgIGZpbGU6IGAke2lzTGliID8gXCJiaW4vXCIgOiBcImRpc3QvXCJ9JHtuYW1lT3ZlcnJpZGUgPyBuYW1lT3ZlcnJpZGUgOiBgLmJ1bmRsZS4keyFpc0RldiA/IFwibWluXCIgOiBcIlwifWB9JHtpc0VzbSA/IFwiLmpzXCIgOiBcIi5janNcIn1gLFxuICAgICAgICBmb3JtYXQ6IGlzTGliID8gXCJjanNcIiA6IGlzRXNtID8gXCJlc21cIiA6IFwidW1kXCIsXG4gICAgICAgIG5hbWU6IHBrZ05hbWUsXG4gICAgICAgIGVzTW9kdWxlOiBpc0VzbSxcbiAgICAgICAgLy8gb3V0cHV0IHNvdXJjZW1hcDogaW5saW5lIGZvciBkZXYsIGV4dGVybmFsIGZvciBwcm9kXG4gICAgICAgIHNvdXJjZW1hcDogcm9sbHVwU291cmNlTWFwT3V0cHV0LFxuICAgICAgICBnbG9iYWxzOiBnbG9iYWxzLFxuICAgICAgICBleHBvcnRzOiBcImF1dG9cIixcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBidW5kbGUgPSBhd2FpdCByb2xsdXAoaW5wdXQgYXMgYW55KTtcbiAgICAgIC8vIG9ubHkgbG9nIHdhdGNoRmlsZXMgYXQgdmVyYm9zZSBsZXZlbCB0byBhdm9pZCBub2lzeSBjb25zb2xlIG91dHB1dFxuICAgICAgbG9nLnZlcmJvc2UoYnVuZGxlLndhdGNoRmlsZXMpO1xuICAgICAgYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVPdXRwdXRzKGJ1bmRsZTogUm9sbHVwQnVpbGQpIHtcbiAgICAgICAgZm9yIChjb25zdCBvdXRwdXRPcHRpb25zIG9mIG91dHB1dHMpIHtcbiAgICAgICAgICBhd2FpdCBidW5kbGUud3JpdGUob3V0cHV0T3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgYXdhaXQgZ2VuZXJhdGVPdXRwdXRzKGJ1bmRsZSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gYnVuZGxlOiAke2V9YCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBidWlsZEJ5RW52KFxuICAgIGlzRGV2OiBib29sZWFuLFxuICAgIG1vZGU6IEJ1aWxkTW9kZSA9IEJ1aWxkTW9kZS5BTEwsXG4gICAgaW5jbHVkZXNBcmc/OiBzdHJpbmcgfCBzdHJpbmdbXSxcbiAgICBleHRlcm5hbHNBcmc/OiBzdHJpbmcgfCBzdHJpbmdbXVxuICApIHtcbiAgICAvLyBub3RlOiBpbmNsdWRlcyBhbmQgZXh0ZXJuYWxzIHdpbGwgYmUgcGFzc2VkIHRocm91Z2ggZnJvbSBydW4oKSBpbnRvIHRoaXMgbWV0aG9kIGJ5IGNhbGxlcnNcbiAgICB0cnkge1xuICAgICAgZGVsZXRlUGF0aChcImxpYlwiKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAvLyBkbyBub3RoaW5nXG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBkZWxldGVQYXRoKFwiZGlzdFwiKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAvLyBkbyBub3RoaW5nXG4gICAgfVxuICAgIGZzLm1rZGlyU3luYyhcImxpYlwiKTtcbiAgICBmcy5ta2RpclN5bmMoXCJkaXN0XCIpO1xuXG4gICAgaWYgKFtCdWlsZE1vZGUuQUxMLCBCdWlsZE1vZGUuQlVJTERdLmluY2x1ZGVzKG1vZGUpKSB7XG4gICAgICBhd2FpdCB0aGlzLmJ1aWxkKGlzRGV2LCBNb2Rlcy5FU00pO1xuICAgICAgYXdhaXQgdGhpcy5idWlsZChpc0RldiwgTW9kZXMuQ0pTKTtcbiAgICAgIHRoaXMucGF0Y2hGaWxlcyhcImxpYlwiKTtcbiAgICB9XG5cbiAgICBpZiAoW0J1aWxkTW9kZS5BTEwsIEJ1aWxkTW9kZS5CVU5ETEVdLmluY2x1ZGVzKG1vZGUpKSB7XG4gICAgICBhd2FpdCB0aGlzLmJ1bmRsZShcbiAgICAgICAgTW9kZXMuRVNNLFxuICAgICAgICBpc0RldixcbiAgICAgICAgZmFsc2UsXG4gICAgICAgIFwic3JjL2luZGV4LnRzXCIsXG4gICAgICAgIHRoaXMucGtnTmFtZSxcbiAgICAgICAgZXh0ZXJuYWxzQXJnLFxuICAgICAgICBpbmNsdWRlc0FyZ1xuICAgICAgKTtcbiAgICAgIGF3YWl0IHRoaXMuYnVuZGxlKFxuICAgICAgICBNb2Rlcy5DSlMsXG4gICAgICAgIGlzRGV2LFxuICAgICAgICBmYWxzZSxcbiAgICAgICAgXCJzcmMvaW5kZXgudHNcIixcbiAgICAgICAgdGhpcy5wa2dOYW1lLFxuICAgICAgICBleHRlcm5hbHNBcmcsXG4gICAgICAgIGluY2x1ZGVzQXJnXG4gICAgICApO1xuICAgICAgdGhpcy5wYXRjaEZpbGVzKFwiZGlzdFwiKTtcbiAgICB9XG5cbiAgICB0aGlzLmNvcHlBc3NldHMoTW9kZXMuQ0pTKTtcbiAgICB0aGlzLmNvcHlBc3NldHMoTW9kZXMuRVNNKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQnVpbGRzIHRoZSBwcm9qZWN0IGZvciBkZXZlbG9wbWVudC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgcnVucyB0aGUgYnVpbGQgcHJvY2VzcyB3aXRoIGRldmVsb3BtZW50LXNwZWNpZmljIGNvbmZpZ3VyYXRpb25zLlxuICAgKiBAcGFyYW0ge0J1aWxkTW9kZX0gW21vZGU9QnVpbGRNb2RlLkFMTF0gLSBUaGUgYnVpbGQgbW9kZSAoYnVpbGQsIGJ1bmRsZSwgb3IgYWxsKS5cbiAgICogQHBhcmFtIHtzdHJpbmd8c3RyaW5nW119IFtpbmNsdWRlc0FyZ10gLSBBIGxpc3Qgb2YgZGVwZW5kZW5jaWVzIHRvIGluY2x1ZGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfHN0cmluZ1tdfSBbZXh0ZXJuYWxzQXJnXSAtIEEgbGlzdCBvZiBleHRlcm5hbCBkZXBlbmRlbmNpZXMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgYnVpbGREZXYoXG4gICAgbW9kZTogQnVpbGRNb2RlID0gQnVpbGRNb2RlLkFMTCxcbiAgICBpbmNsdWRlc0FyZz86IHN0cmluZyB8IHN0cmluZ1tdLFxuICAgIGV4dGVybmFsc0FyZz86IHN0cmluZyB8IHN0cmluZ1tdXG4gICkge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkQnlFbnYodHJ1ZSwgbW9kZSwgaW5jbHVkZXNBcmcsIGV4dGVybmFsc0FyZyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJ1aWxkcyB0aGUgcHJvamVjdCBmb3IgcHJvZHVjdGlvbi5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgcnVucyB0aGUgYnVpbGQgcHJvY2VzcyB3aXRoIHByb2R1Y3Rpb24tc3BlY2lmaWMgY29uZmlndXJhdGlvbnMsXG4gICAqIGluY2x1ZGluZyBtaW5pZmljYXRpb24gYW5kIG90aGVyIG9wdGltaXphdGlvbnMuXG4gICAqIEBwYXJhbSB7QnVpbGRNb2RlfSBbbW9kZT1CdWlsZE1vZGUuQUxMXSAtIFRoZSBidWlsZCBtb2RlIChidWlsZCwgYnVuZGxlLCBvciBhbGwpLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xzdHJpbmdbXX0gW2luY2x1ZGVzQXJnXSAtIEEgbGlzdCBvZiBkZXBlbmRlbmNpZXMgdG8gaW5jbHVkZS5cbiAgICogQHBhcmFtIHtzdHJpbmd8c3RyaW5nW119IFtleHRlcm5hbHNBcmddIC0gQSBsaXN0IG9mIGV4dGVybmFsIGRlcGVuZGVuY2llcy5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBidWlsZFByb2QoXG4gICAgbW9kZTogQnVpbGRNb2RlID0gQnVpbGRNb2RlLkFMTCxcbiAgICBpbmNsdWRlc0FyZz86IHN0cmluZyB8IHN0cmluZ1tdLFxuICAgIGV4dGVybmFsc0FyZz86IHN0cmluZyB8IHN0cmluZ1tdXG4gICkge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkQnlFbnYoZmFsc2UsIG1vZGUsIGluY2x1ZGVzQXJnLCBleHRlcm5hbHNBcmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgdGhlIHByb2plY3QgZG9jdW1lbnRhdGlvbi5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgdXNlcyBKU0RvYyBhbmQgb3RoZXIgdG9vbHMgdG8gZ2VuZXJhdGUgSFRNTCBkb2N1bWVudGF0aW9uIGZvciB0aGUgcHJvamVjdC5cbiAgICogSXQgYWxzbyBwYXRjaGVzIHRoZSBSRUFETUUubWQgZmlsZSB3aXRoIHZlcnNpb24gYW5kIHBhY2thZ2Ugc2l6ZSBpbmZvcm1hdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBidWlsZERvY3MoKSB7XG4gICAgYXdhaXQgcnVuQ29tbWFuZChgbnBtIGluc3RhbGwgYmV0dGVyLWRvY3MgdGFmZnlkYmApLnByb21pc2U7XG4gICAgYXdhaXQgcnVuQ29tbWFuZChgbnB4IG1hcmtkb3duLWluY2x1ZGUgLi93b3JrZG9jcy9yZWFkbWUtbWQuanNvbmApLnByb21pc2U7XG4gICAgYXdhaXQgcnVuQ29tbWFuZChcbiAgICAgIGBucHgganNkb2MgLWMgLi93b3JrZG9jcy9qc2RvY3MuanNvbiAtdCAuL25vZGVfbW9kdWxlcy9iZXR0ZXItZG9jc2BcbiAgICApLnByb21pc2U7XG4gICAgYXdhaXQgcnVuQ29tbWFuZChgbnBtIHJlbW92ZSBiZXR0ZXItZG9jcyB0YWZmeWRiYCkucHJvbWlzZTtcbiAgICBbXG4gICAgICB7XG4gICAgICAgIHNyYzogXCJ3b3JrZG9jcy9hc3NldHNcIixcbiAgICAgICAgZGVzdDogXCIuL2RvY3Mvd29ya2RvY3MvYXNzZXRzXCIsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBzcmM6IFwid29ya2RvY3MvcmVwb3J0cy9jb3ZlcmFnZVwiLFxuICAgICAgICBkZXN0OiBcIi4vZG9jcy93b3JrZG9jcy9yZXBvcnRzL2NvdmVyYWdlXCIsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBzcmM6IFwid29ya2RvY3MvcmVwb3J0cy9odG1sXCIsXG4gICAgICAgIGRlc3Q6IFwiLi9kb2NzL3dvcmtkb2NzL3JlcG9ydHMvaHRtbFwiLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgc3JjOiBcIndvcmtkb2NzL3Jlc291cmNlc1wiLFxuICAgICAgICBkZXN0OiBcIi4vZG9jcy93b3JrZG9jcy9yZXNvdXJjZXNcIixcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHNyYzogXCJMSUNFTlNFLm1kXCIsXG4gICAgICAgIGRlc3Q6IFwiLi9kb2NzL0xJQ0VOU0UubWRcIixcbiAgICAgIH0sXG4gICAgXS5mb3JFYWNoKChmKSA9PiB7XG4gICAgICBjb25zdCB7IHNyYywgZGVzdCB9ID0gZjtcbiAgICAgIGNvcHlGaWxlKHNyYywgZGVzdCk7XG4gICAgfSk7XG5cbiAgICAvLyBwYXRjaCAuL1JFQURNRS5tZCBmaWxlIHRvIHJlcGxhY2UgdmVyc2lvbi9wYWNrYWdlL3BhY2thZ2Ugc2l6ZSBzdHJpbmdzXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHNpemVLYiA9IGF3YWl0IGdldEZpbGVTaXplWmlwcGVkKFxuICAgICAgICBwYXRoLnJlc29sdmUocGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIFwiZGlzdFwiKSlcbiAgICAgICk7XG4gICAgICB0aGlzLnJlcGxhY2VtZW50c1tQQUNLQUdFX1NJWkVfU1RSSU5HXSA9IGAke3NpemVLYn0gS0JgO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gaWYgd2UgY291bGRuJ3QgY29tcHV0ZSBzaXplLCBsZWF2ZSBwbGFjZWhvbGRlciBvciBzZXQgdG8gdW5rbm93blxuICAgICAgdGhpcy5yZXBsYWNlbWVudHNbUEFDS0FHRV9TSVpFX1NUUklOR10gPSBcInVua25vd25cIjtcbiAgICB9XG5cbiAgICAvLyBQYXRjaCBSRUFETUUubWQgaW4gcHJvamVjdCByb290XG4gICAgdHJ5IHtcbiAgICAgIHBhdGNoRmlsZShcIi4vUkVBRE1FLm1kXCIsIHRoaXMucmVwbGFjZW1lbnRzKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5idWlsZERvY3MgYXMgYW55KTtcbiAgICAgIGxvZy52ZXJib3NlKGBGYWlsZWQgdG8gcGF0Y2ggUkVBRE1FLm1kOiAke2V9YCk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHJ1bjxSPihcbiAgICBhbnN3ZXJzOiBMb2dnaW5nQ29uZmlnICZcbiAgICAgIHR5cGVvZiBEZWZhdWx0Q29tbWFuZFZhbHVlcyAmIHsgW2sgaW4ga2V5b2YgdHlwZW9mIG9wdGlvbnNdOiB1bmtub3duIH1cbiAgKTogUHJvbWlzZTxzdHJpbmcgfCB2b2lkIHwgUj4ge1xuICAgIGNvbnN0IHsgZGV2LCBwcm9kLCBkb2NzLCBidWlsZE1vZGUsIGluY2x1ZGVzLCBleHRlcm5hbHMgfSA9IGFuc3dlcnMgYXMgYW55O1xuICAgIGlmIChkZXYpIHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmJ1aWxkRGV2KGJ1aWxkTW9kZSBhcyBCdWlsZE1vZGUsIGluY2x1ZGVzLCBleHRlcm5hbHMpO1xuICAgIH1cbiAgICBpZiAocHJvZCkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuYnVpbGRQcm9kKGJ1aWxkTW9kZSBhcyBCdWlsZE1vZGUsIGluY2x1ZGVzLCBleHRlcm5hbHMpO1xuICAgIH1cbiAgICBpZiAoZG9jcykge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuYnVpbGREb2NzKCk7XG4gICAgfVxuICB9XG59XG4iLCIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0IHsgcnVuQ29tbWFuZCB9IGZyb20gXCIuLi8uLi91dGlscy91dGlsc1wiO1xuaW1wb3J0IHsgTm9DSUZMYWcsIFNlbVZlcnNpb24sIFNlbVZlcnNpb25SZWdleCB9IGZyb20gXCIuLi8uLi91dGlscy9jb25zdGFudHNcIjtcbmltcG9ydCB7IFVzZXJJbnB1dCB9IGZyb20gXCIuLi8uLi9pbnB1dC9pbnB1dFwiO1xuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gXCIuLi9jb21tYW5kXCI7XG5pbXBvcnQgeyBEZWZhdWx0Q29tbWFuZFZhbHVlcyB9IGZyb20gXCIuLi9pbmRleFwiO1xuaW1wb3J0IHsgTG9nZ2luZ0NvbmZpZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG5jb25zdCBvcHRpb25zID0ge1xuICBjaToge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIGRlZmF1bHQ6IHRydWUsXG4gIH0sXG4gIG1lc3NhZ2U6IHtcbiAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgIHNob3J0OiBcIm1cIixcbiAgfSxcbiAgdGFnOiB7XG4gICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICBzaG9ydDogXCJ0XCIsXG4gICAgZGVmYXVsdDogdW5kZWZpbmVkLFxuICB9LFxufTtcblxuLyoqXG4gKiBAY2xhc3MgUmVsZWFzZVNjcmlwdFxuICogQGV4dGVuZHMge0NvbW1hbmR9XG4gKiBAY2F2ZWdvcnkgc2NyaXB0c1xuICogQGRlc2NyaXB0aW9uIEEgY29tbWFuZC1saW5lIHNjcmlwdCBmb3IgbWFuYWdpbmcgcmVsZWFzZXMgYW5kIHZlcnNpb24gdXBkYXRlcy5cbiAqIEBzdW1tYXJ5IFRoaXMgc2NyaXB0IGF1dG9tYXRlcyB0aGUgcHJvY2VzcyBvZiBjcmVhdGluZyBhbmQgcHVzaGluZyBuZXcgcmVsZWFzZXMuIEl0IGhhbmRsZXMgdmVyc2lvbiB1cGRhdGVzLFxuICogY29tbWl0IG1lc3NhZ2VzLCBhbmQgb3B0aW9uYWxseSBwdWJsaXNoZXMgdG8gTlBNLiBUaGUgc2NyaXB0IHN1cHBvcnRzIHNlbWFudGljIHZlcnNpb25pbmcgYW5kIGNhbiB3b3JrIGluIGJvdGggQ0kgYW5kIG5vbi1DSSBlbnZpcm9ubWVudHMuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBDb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIHRoZSBzY3JpcHRcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gb3B0aW9ucy5jaSAtIFdoZXRoZXIgdGhlIHNjcmlwdCBpcyBydW5uaW5nIGluIGEgQ0kgZW52aXJvbm1lbnQgKGRlZmF1bHQ6IHRydWUpXG4gKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5tZXNzYWdlIC0gVGhlIHJlbGVhc2UgbWVzc2FnZSAoc2hvcnQ6ICdtJylcbiAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLnRhZyAtIFRoZSB2ZXJzaW9uIHRhZyB0byB1c2UgKHNob3J0OiAndCcsIGRlZmF1bHQ6IHVuZGVmaW5lZClcbiAqL1xuZXhwb3J0IGNsYXNzIFJlbGVhc2VTY3JpcHQgZXh0ZW5kcyBDb21tYW5kPHR5cGVvZiBvcHRpb25zLCB2b2lkPiB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKFwiUmVsZWFzZVNjcmlwdFwiLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgdGhlIHZlcnNpb24gZm9yIHRoZSByZWxlYXNlLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCB2YWxpZGF0ZXMgdGhlIHByb3ZpZGVkIHRhZyBvciBwcm9tcHRzIHRoZSB1c2VyIGZvciBhIG5ldyBvbmUgaWYgbm90IHByb3ZpZGVkIG9yIGludmFsaWQuXG4gICAqIEl0IGFsc28gZGlzcGxheXMgdGhlIGxhdGVzdCBnaXQgdGFncyBmb3IgcmVmZXJlbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGFnIC0gVGhlIHZlcnNpb24gdGFnIHRvIHByZXBhcmVcbiAgICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gVGhlIHByZXBhcmVkIHZlcnNpb24gdGFnXG4gICAqXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IFIgYXMgUmVsZWFzZVNjcmlwdFxuICAgKiAgIHBhcnRpY2lwYW50IFQgYXMgVGVzdFZlcnNpb25cbiAgICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXJJbnB1dFxuICAgKiAgIHBhcnRpY2lwYW50IEcgYXMgR2l0XG4gICAqICAgUi0+PlQ6IHRlc3RWZXJzaW9uKHRhZylcbiAgICogICBhbHQgdGFnIGlzIHZhbGlkXG4gICAqICAgICBULS0+PlI6IHJldHVybiB0YWdcbiAgICogICBlbHNlIHRhZyBpcyBpbnZhbGlkIG9yIG5vdCBwcm92aWRlZFxuICAgKiAgICAgUi0+Pkc6IExpc3QgbGF0ZXN0IGdpdCB0YWdzXG4gICAqICAgICBSLT4+VTogUHJvbXB0IGZvciBuZXcgdGFnXG4gICAqICAgICBVLS0+PlI6IHJldHVybiBuZXcgdGFnXG4gICAqICAgZW5kXG4gICAqL1xuICBhc3luYyBwcmVwYXJlVmVyc2lvbih0YWc/OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnByZXBhcmVWZXJzaW9uKTtcbiAgICB0YWcgPSB0aGlzLnRlc3RWZXJzaW9uKCh0YWcgYXMgc3RyaW5nKSB8fCBcIlwiKTtcbiAgICBpZiAoIXRhZykge1xuICAgICAgbG9nLnZlcmJvc2UoXCJObyByZWxlYXNlIG1lc3NhZ2UgcHJvdmlkZWQuIFByb21wdGluZyBmb3Igb25lOlwiKTtcbiAgICAgIGxvZy5pbmZvKGBMaXN0aW5nIGxhdGVzdCBnaXQgdGFnczpgKTtcbiAgICAgIGF3YWl0IHJ1bkNvbW1hbmQoXCJnaXQgdGFnIC0tc29ydD0tdGFnZ2VyZGF0ZSB8IGhlYWQgLW4gNVwiKS5wcm9taXNlO1xuICAgICAgcmV0dXJuIGF3YWl0IFVzZXJJbnB1dC5pbnNpc3RGb3JUZXh0KFxuICAgICAgICBcInRhZ1wiLFxuICAgICAgICBcIkVudGVyIHRoZSBuZXcgdGFnIG51bWJlciAoYWNjZXB0cyB2Ki4qLipbLS4uLl0pXCIsXG4gICAgICAgICh2YWwpID0+XG4gICAgICAgICAgISF2YWwudG9TdHJpbmcoKS5tYXRjaCgvXnZbMC05XStcXC5bMC05XSsuWzAtOV0rKC1bMC05YS16QS1aLV0rKT8kLylcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0YWc7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRlc3RzIGlmIHRoZSBwcm92aWRlZCB2ZXJzaW9uIGlzIHZhbGlkLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBjaGVja3MgaWYgdGhlIHZlcnNpb24gaXMgYSB2YWxpZCBzZW1hbnRpYyB2ZXJzaW9uIG9yIGEgcHJlZGVmaW5lZCB1cGRhdGUgdHlwZSAoUEFUQ0gsIE1JTk9SLCBNQUpPUikuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2ZXJzaW9uIC0gVGhlIHZlcnNpb24gdG8gdGVzdFxuICAgKiBAcmV0dXJucyB7c3RyaW5nIHwgdW5kZWZpbmVkfSBUaGUgdmFsaWRhdGVkIHZlcnNpb24gb3IgdW5kZWZpbmVkIGlmIGludmFsaWRcbiAgICovXG4gIHRlc3RWZXJzaW9uKHZlcnNpb246IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMudGVzdFZlcnNpb24pO1xuICAgIHZlcnNpb24gPSB2ZXJzaW9uLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xuICAgIHN3aXRjaCAodmVyc2lvbikge1xuICAgICAgY2FzZSBTZW1WZXJzaW9uLlBBVENIOlxuICAgICAgY2FzZSBTZW1WZXJzaW9uLk1JTk9SOlxuICAgICAgY2FzZSBTZW1WZXJzaW9uLk1BSk9SOlxuICAgICAgICBsb2cudmVyYm9zZShgVXNpbmcgcHJvdmlkZWQgU2VtVmVyIHVwZGF0ZTogJHt2ZXJzaW9ufWAsIDEpO1xuICAgICAgICByZXR1cm4gdmVyc2lvbjtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGxvZy52ZXJib3NlKFxuICAgICAgICAgIGBUZXN0aW5nIHByb3ZpZGVkIHZlcnNpb24gZm9yIFNlbVZlciBjb21wYXRpYmlsaXR5OiAke3ZlcnNpb259YCxcbiAgICAgICAgICAxXG4gICAgICAgICk7XG4gICAgICAgIGlmICghbmV3IFJlZ0V4cChTZW1WZXJzaW9uUmVnZXgpLnRlc3QodmVyc2lvbikpIHtcbiAgICAgICAgICBsb2cuZGVidWcoYEludmFsaWQgdmVyc2lvbiBudW1iZXI6ICR7dmVyc2lvbn1gKTtcbiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIGxvZy52ZXJib3NlKGB2ZXJzaW9uIGFwcHJvdmVkOiAke3ZlcnNpb259YCwgMSk7XG4gICAgICAgIHJldHVybiB2ZXJzaW9uO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgdGhlIHJlbGVhc2UgbWVzc2FnZS5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgZWl0aGVyIHJldHVybnMgdGhlIHByb3ZpZGVkIG1lc3NhZ2Ugb3IgcHJvbXB0cyB0aGUgdXNlciBmb3IgYSBuZXcgb25lIGlmIG5vdCBwcm92aWRlZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSAtIFRoZSByZWxlYXNlIG1lc3NhZ2VcbiAgICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gVGhlIHByZXBhcmVkIHJlbGVhc2UgbWVzc2FnZVxuICAgKi9cbiAgYXN5bmMgcHJlcGFyZU1lc3NhZ2UobWVzc2FnZT86IHN0cmluZykge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnByZXBhcmVNZXNzYWdlKTtcbiAgICBpZiAoIW1lc3NhZ2UpIHtcbiAgICAgIGxvZy52ZXJib3NlKFwiTm8gcmVsZWFzZSBtZXNzYWdlIHByb3ZpZGVkLiBQcm9tcHRpbmcgZm9yIG9uZVwiKTtcbiAgICAgIHJldHVybiBhd2FpdCBVc2VySW5wdXQuaW5zaXN0Rm9yVGV4dChcbiAgICAgICAgXCJtZXNzYWdlXCIsXG4gICAgICAgIFwiV2hhdCBzaG91bGQgYmUgdGhlIHJlbGVhc2UgbWVzc2FnZS90aWNrZXQ/XCIsXG4gICAgICAgICh2YWwpID0+ICEhdmFsICYmIHZhbC50b1N0cmluZygpLmxlbmd0aCA+IDVcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSdW5zIHRoZSByZWxlYXNlIHNjcmlwdC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2Qgb3JjaGVzdHJhdGVzIHRoZSBlbnRpcmUgcmVsZWFzZSBwcm9jZXNzLCBpbmNsdWRpbmcgdmVyc2lvbiBwcmVwYXJhdGlvbiwgbWVzc2FnZSBjcmVhdGlvbixcbiAgICogZ2l0IG9wZXJhdGlvbnMsIGFuZCBucG0gcHVibGlzaGluZyAoaWYgbm90IGluIENJIGVudmlyb25tZW50KS5cbiAgICogQHBhcmFtIHtQYXJzZUFyZ3NSZXN1bHR9IGFyZ3MgLSBUaGUgcGFyc2VkIGNvbW1hbmQtbGluZSBhcmd1bWVudHNcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IFIgYXMgUmVsZWFzZVNjcmlwdFxuICAgKiAgIHBhcnRpY2lwYW50IFYgYXMgUHJlcGFyZVZlcnNpb25cbiAgICogICBwYXJ0aWNpcGFudCBNIGFzIFByZXBhcmVNZXNzYWdlXG4gICAqICAgcGFydGljaXBhbnQgTiBhcyBOUE1cbiAgICogICBwYXJ0aWNpcGFudCBHIGFzIEdpdFxuICAgKiAgIHBhcnRpY2lwYW50IFUgYXMgVXNlcklucHV0XG4gICAqICAgUi0+PlY6IHByZXBhcmVWZXJzaW9uKHRhZylcbiAgICogICBSLT4+TTogcHJlcGFyZU1lc3NhZ2UobWVzc2FnZSlcbiAgICogICBSLT4+TjogUnVuIHByZXBhcmUtcmVsZWFzZSBzY3JpcHRcbiAgICogICBSLT4+RzogQ2hlY2sgZ2l0IHN0YXR1c1xuICAgKiAgIGFsdCBjaGFuZ2VzIGV4aXN0XG4gICAqICAgICBSLT4+VTogQXNrIGZvciBjb25maXJtYXRpb25cbiAgICogICAgIFUtLT4+UjogQ29uZmlybVxuICAgKiAgICAgUi0+Pkc6IEFkZCBhbmQgY29tbWl0IGNoYW5nZXNcbiAgICogICBlbmRcbiAgICogICBSLT4+TjogVXBkYXRlIG5wbSB2ZXJzaW9uXG4gICAqICAgUi0+Pkc6IFB1c2ggY2hhbmdlcyBhbmQgdGFnc1xuICAgKiAgIGFsdCBub3QgQ0kgZW52aXJvbm1lbnRcbiAgICogICAgIFItPj5OOiBQdWJsaXNoIHRvIG5wbVxuICAgKiAgIGVuZFxuICAgKi9cbiAgYXN5bmMgcnVuKFxuICAgIGFyZ3M6IExvZ2dpbmdDb25maWcgJlxuICAgICAgdHlwZW9mIERlZmF1bHRDb21tYW5kVmFsdWVzICYgeyBbayBpbiBrZXlvZiB0eXBlb2Ygb3B0aW9uc106IHVua25vd24gfVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQgcmVzdWx0OiBhbnk7XG4gICAgY29uc3QgeyBjaSB9ID0gYXJncztcbiAgICBsZXQgeyB0YWcsIG1lc3NhZ2UgfSA9IGFyZ3M7XG4gICAgdGFnID0gYXdhaXQgdGhpcy5wcmVwYXJlVmVyc2lvbih0YWcgYXMgc3RyaW5nKTtcbiAgICBtZXNzYWdlID0gYXdhaXQgdGhpcy5wcmVwYXJlTWVzc2FnZShtZXNzYWdlIGFzIHN0cmluZyk7XG4gICAgcmVzdWx0ID0gYXdhaXQgcnVuQ29tbWFuZChgbnBtIHJ1biBwcmVwYXJlLXJlbGVhc2UgLS0gJHt0YWd9ICR7bWVzc2FnZX1gLCB7XG4gICAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgfSkucHJvbWlzZTtcbiAgICByZXN1bHQgPSBhd2FpdCBydW5Db21tYW5kKFwiZ2l0IHN0YXR1cyAtLXBvcmNlbGFpblwiKS5wcm9taXNlO1xuICAgIGF3YWl0IHJlc3VsdDtcbiAgICBpZiAoXG4gICAgICByZXN1bHQubG9ncy5sZW5ndGggJiZcbiAgICAgIChhd2FpdCBVc2VySW5wdXQuYXNrQ29uZmlybWF0aW9uKFxuICAgICAgICBcImdpdC1jaGFuZ2VzXCIsXG4gICAgICAgIFwiRG8geW91IHdhbnQgdG8gcHVzaCB0aGUgY2hhbmdlcyB0byB0aGUgcmVtb3RlIHJlcG9zaXRvcnk/XCIsXG4gICAgICAgIHRydWVcbiAgICAgICkpXG4gICAgKSB7XG4gICAgICBhd2FpdCBydW5Db21tYW5kKFwiZ2l0IGFkZCAuXCIpLnByb21pc2U7XG4gICAgICBhd2FpdCBydW5Db21tYW5kKFxuICAgICAgICBgZ2l0IGNvbW1pdCAtbSBcIiR7dGFnfSAtICR7bWVzc2FnZX0gLSBhZnRlciByZWxlYXNlIHByZXBhcmF0aW9uJHtjaSA/IFwiXCIgOiBOb0NJRkxhZ31cImBcbiAgICAgICkucHJvbWlzZTtcbiAgICB9XG4gICAgYXdhaXQgcnVuQ29tbWFuZChcbiAgICAgIGBucG0gdmVyc2lvbiBcIiR7dGFnfVwiIC1tIFwiJHttZXNzYWdlfSR7Y2kgPyBcIlwiIDogTm9DSUZMYWd9XCJgXG4gICAgKS5wcm9taXNlO1xuICAgIGF3YWl0IHJ1bkNvbW1hbmQoXCJnaXQgcHVzaCAtLWZvbGxvdy10YWdzXCIpLnByb21pc2U7XG4gICAgaWYgKCFjaSkge1xuICAgICAgYXdhaXQgcnVuQ29tbWFuZChcIk5QTV9UT0tFTj0kKGNhdCAubnBtdG9rZW4pIG5wbSBwdWJsaXNoIC0tYWNjZXNzIHB1YmxpY1wiKVxuICAgICAgICAucHJvbWlzZTtcbiAgICB9XG4gIH1cbn1cbiIsImltcG9ydCB7IFN0YW5kYXJkT3V0cHV0V3JpdGVyIH0gZnJvbSBcIi4vU3RhbmRhcmRPdXRwdXRXcml0ZXJcIjtcbmltcG9ydCB7IFByb21pc2VFeGVjdXRvciB9IGZyb20gXCIuLi91dGlscy90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBIHNwZWNpYWxpemVkIG91dHB1dCB3cml0ZXIgdGhhdCB1c2VzIHJlZ3VsYXIgZXhwcmVzc2lvbnMgdG8gcHJvY2VzcyBvdXRwdXQuXG4gKiBAc3VtbWFyeSBUaGlzIGNsYXNzIGV4dGVuZHMgU3RhbmRhcmRPdXRwdXRXcml0ZXIgdG8gcHJvdmlkZSByZWdleC1iYXNlZCBvdXRwdXQgcHJvY2Vzc2luZy5cbiAqIEl0IGFsbG93cyBmb3IgcGF0dGVybiBtYXRjaGluZyBpbiB0aGUgb3V0cHV0IHN0cmVhbSBhbmQgY2FuIHRyaWdnZXIgc3BlY2lmaWMgYWN0aW9uc1xuICogYmFzZWQgb24gbWF0Y2hlZCBwYXR0ZXJucy5cbiAqXG4gKiBAdGVtcGxhdGUgVCAtIFRoZSB0eXBlIG9mIHRoZSByZXNvbHZlZCB2YWx1ZSwgZGVmYXVsdGluZyB0byBzdHJpbmcuXG4gKlxuICogQHBhcmFtIGNtZCAtIFRoZSBjb21tYW5kIHN0cmluZyB0byBiZSBleGVjdXRlZC5cbiAqIEBwYXJhbSBsb2NrIC0gQSBQcm9taXNlRXhlY3V0b3IgdG8gY29udHJvbCB0aGUgYXN5bmNocm9ub3VzIGZsb3cuXG4gKiBAcGFyYW0gcmVnZXhwIC0gQSBzdHJpbmcgb3IgUmVnRXhwIHRvIG1hdGNoIGFnYWluc3QgdGhlIG91dHB1dC5cbiAqIEBwYXJhbSBmbGFncyAtIE9wdGlvbmFsIGZsYWdzIGZvciB0aGUgUmVnRXhwIGNvbnN0cnVjdG9yLCBkZWZhdWx0cyB0byBcImdcIi5cbiAqXG4gKiBAY2xhc3NcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBSZWdleHBPdXRwdXRXcml0ZXIgfSBmcm9tICdAZGVjYWYtdHMvdXRpbHMnO1xuICogaW1wb3J0IHsgUHJvbWlzZUV4ZWN1dG9yIH0gZnJvbSAnQGRlY2FmLXRzL3V0aWxzJztcbiAqIFxuICogLy8gQ3JlYXRlIGEgcHJvbWlzZSBleGVjdXRvclxuICogY29uc3QgZXhlY3V0b3I6IFByb21pc2VFeGVjdXRvcjxzdHJpbmcsIEVycm9yPiA9IHtcbiAqICAgcmVzb2x2ZTogKHZhbHVlKSA9PiBjb25zb2xlLmxvZyhgUmVzb2x2ZWQ6ICR7dmFsdWV9YCksXG4gKiAgIHJlamVjdDogKGVycm9yKSA9PiBjb25zb2xlLmVycm9yKGBSZWplY3RlZDogJHtlcnJvci5tZXNzYWdlfWApXG4gKiB9O1xuICogXG4gKiAvLyBDcmVhdGUgYSByZWdleHAgb3V0cHV0IHdyaXRlciB0aGF0IG1hdGNoZXMgdmVyc2lvbiBudW1iZXJzXG4gKiBjb25zdCB3cml0ZXIgPSBuZXcgUmVnZXhwT3V0cHV0V3JpdGVyKCdub2RlIC0tdmVyc2lvbicsIGV4ZWN1dG9yLCAvdihcXGQrXFwuXFxkK1xcLlxcZCspLyk7XG4gKiBcbiAqIC8vIFVzZSB0aGUgd3JpdGVyIHRvIGhhbmRsZSBjb21tYW5kIG91dHB1dFxuICogd3JpdGVyLmRhdGEoJ3YxNC4xNy4wJyk7ICAvLyBUaGlzIHdpbGwgYXV0b21hdGljYWxseSByZXNvbHZlIHdpdGggXCJ2MTQuMTcuMFwiXG4gKiBgYGBcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICogICBwYXJ0aWNpcGFudCBSZWdleHBPdXRwdXRXcml0ZXJcbiAqICAgcGFydGljaXBhbnQgU3RhbmRhcmRPdXRwdXRXcml0ZXJcbiAqICAgcGFydGljaXBhbnQgTG9nZ2VyXG4gKiAgIFxuICogICBDbGllbnQtPj5SZWdleHBPdXRwdXRXcml0ZXI6IG5ldyBSZWdleHBPdXRwdXRXcml0ZXIoY21kLCBsb2NrLCByZWdleHAsIGZsYWdzKVxuICogICBSZWdleHBPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogc3VwZXIoY21kLCBsb2NrKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PkxvZ2dlcjogTG9nZ2luZy5mb3IoY21kKVxuICogICBSZWdleHBPdXRwdXRXcml0ZXItPj5SZWdleHBPdXRwdXRXcml0ZXI6IGNvbXBpbGUgcmVnZXhwXG4gKiAgIFxuICogICBDbGllbnQtPj5SZWdleHBPdXRwdXRXcml0ZXI6IGRhdGEoY2h1bmspXG4gKiAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiBzdXBlci5kYXRhKGNodW5rKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PkxvZ2dlcjogbG9nZ2VyLmluZm8obG9nKVxuICogICBSZWdleHBPdXRwdXRXcml0ZXItPj5SZWdleHBPdXRwdXRXcml0ZXI6IHRlc3RBbmRSZXNvbHZlKGNodW5rKVxuICogICBSZWdleHBPdXRwdXRXcml0ZXItPj5SZWdleHBPdXRwdXRXcml0ZXI6IHRlc3QoY2h1bmspXG4gKiAgIGFsdCBtYXRjaCBmb3VuZFxuICogICAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlJlZ2V4cE91dHB1dFdyaXRlcjogcmVzb2x2ZShtYXRjaFswXSlcbiAqICAgICBSZWdleHBPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogcmVzb2x2ZShtYXRjaFswXSlcbiAqICAgZW5kXG4gKiAgIFxuICogICBDbGllbnQtPj5SZWdleHBPdXRwdXRXcml0ZXI6IGVycm9yKGNodW5rKVxuICogICBSZWdleHBPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogc3VwZXIuZXJyb3IoY2h1bmspXG4gKiAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+TG9nZ2VyOiBsb2dnZXIuaW5mbyhsb2cpXG4gKiAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlJlZ2V4cE91dHB1dFdyaXRlcjogdGVzdEFuZFJlamVjdChjaHVuaylcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+UmVnZXhwT3V0cHV0V3JpdGVyOiB0ZXN0KGNodW5rKVxuICogICBhbHQgbWF0Y2ggZm91bmRcbiAqICAgICBSZWdleHBPdXRwdXRXcml0ZXItPj5SZWdleHBPdXRwdXRXcml0ZXI6IHJlamVjdChtYXRjaFswXSlcbiAqICAgICBSZWdleHBPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogcmVqZWN0KG1hdGNoWzBdKVxuICogICBlbmRcbiAqL1xuZXhwb3J0IGNsYXNzIFJlZ2V4cE91dHB1dFdyaXRlciBleHRlbmRzIFN0YW5kYXJkT3V0cHV0V3JpdGVyPHN0cmluZz4ge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSByZWd1bGFyIGV4cHJlc3Npb24gdXNlZCBmb3IgbWF0Y2hpbmcgb3V0cHV0LlxuICAgKiBAc3VtbWFyeSBUaGlzIHJlYWRvbmx5IHByb3BlcnR5IHN0b3JlcyB0aGUgY29tcGlsZWQgUmVnRXhwIHVzZWQgZm9yIHBhdHRlcm4gbWF0Y2hpbmcuXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmVnZXhwOiBSZWdFeHA7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgY21kOiBzdHJpbmcsXG4gICAgbG9jazogUHJvbWlzZUV4ZWN1dG9yPHN0cmluZywgRXJyb3I+LFxuICAgIHJlZ2V4cDogc3RyaW5nIHwgUmVnRXhwLFxuICAgIGZsYWdzID0gXCJnXCJcbiAgKSB7XG4gICAgc3VwZXIoY21kLCBsb2NrKTtcbiAgICB0cnkge1xuICAgICAgdGhpcy5yZWdleHAgPVxuICAgICAgICB0eXBlb2YgcmVnZXhwID09PSBcInN0cmluZ1wiID8gbmV3IFJlZ0V4cChyZWdleHAsIGZsYWdzKSA6IHJlZ2V4cDtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcmVndWxhciBleHByZXNzaW9uOiAke2V9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUZXN0cyB0aGUgaW5wdXQgZGF0YSBhZ2FpbnN0IHRoZSBzdG9yZWQgcmVndWxhciBleHByZXNzaW9uLlxuICAgKiBAc3VtbWFyeSBFeGVjdXRlcyB0aGUgcmVndWxhciBleHByZXNzaW9uIG9uIHRoZSBpbnB1dCBkYXRhIGFuZCByZXR1cm5zIHRoZSBtYXRjaCByZXN1bHQuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gVGhlIHN0cmluZyB0byB0ZXN0IGFnYWluc3QgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICogQHJldHVybiBUaGUgcmVzdWx0IG9mIHRoZSByZWd1bGFyIGV4cHJlc3Npb24gZXhlY3V0aW9uLCBvciB1bmRlZmluZWQgaWYgYW4gZXJyb3Igb2NjdXJzLlxuICAgKi9cbiAgcHJpdmF0ZSB0ZXN0KGRhdGE6IHN0cmluZykge1xuICAgIHRoaXMucmVnZXhwLmxhc3RJbmRleCA9IDA7XG4gICAgbGV0IG1hdGNoO1xuICAgIHRyeSB7XG4gICAgICBtYXRjaCA9IHRoaXMucmVnZXhwLmV4ZWMoZGF0YSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgcmV0dXJuIGNvbnNvbGUuZGVidWcoYEZhaWxlZCB0byBwYXJzZSBjaHVuazogJHtkYXRhfVxcbkVycm9yOiAke2V9IGApO1xuICAgIH1cbiAgICByZXR1cm4gbWF0Y2g7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRlc3RzIHRoZSBkYXRhIGFuZCByZXNvbHZlcyB0aGUgcHJvbWlzZSBpZiBhIG1hdGNoIGlzIGZvdW5kLlxuICAgKiBAc3VtbWFyeSBFeGVjdXRlcyB0aGUgdGVzdCBtZXRob2QgYW5kIHJlc29sdmVzIHRoZSBwcm9taXNlIHdpdGggdGhlIGZpcnN0IG1hdGNoIGdyb3VwIGlmIHN1Y2Nlc3NmdWwuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gVGhlIHN0cmluZyB0byB0ZXN0IGFnYWluc3QgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICovXG4gIHByb3RlY3RlZCB0ZXN0QW5kUmVzb2x2ZShkYXRhOiBzdHJpbmcpIHtcbiAgICBjb25zdCBtYXRjaCA9IHRoaXMudGVzdChkYXRhKTtcbiAgICBpZiAobWF0Y2gpIHRoaXMucmVzb2x2ZShtYXRjaFswXSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRlc3RzIHRoZSBkYXRhIGFuZCByZWplY3RzIHRoZSBwcm9taXNlIGlmIGEgbWF0Y2ggaXMgZm91bmQuXG4gICAqIEBzdW1tYXJ5IEV4ZWN1dGVzIHRoZSB0ZXN0IG1ldGhvZCBhbmQgcmVqZWN0cyB0aGUgcHJvbWlzZSB3aXRoIHRoZSBmaXJzdCBtYXRjaCBncm91cCBpZiBzdWNjZXNzZnVsLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFRoZSBzdHJpbmcgdG8gdGVzdCBhZ2FpbnN0IHRoZSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAqL1xuICBwcm90ZWN0ZWQgdGVzdEFuZFJlamVjdChkYXRhOiBzdHJpbmcpIHtcbiAgICBjb25zdCBtYXRjaCA9IHRoaXMudGVzdChkYXRhKTtcbiAgICBpZiAobWF0Y2gpIHRoaXMucmVqZWN0KG1hdGNoWzBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvY2Vzc2VzIGluY29taW5nIGRhdGEgY2h1bmtzLlxuICAgKiBAc3VtbWFyeSBDYWxscyB0aGUgcGFyZW50IGNsYXNzIGRhdGEgbWV0aG9kIGFuZCB0aGVuIHRlc3RzIHRoZSBkYXRhIGZvciBhIG1hdGNoIHRvIHBvdGVudGlhbGx5IHJlc29sdmUgdGhlIHByb21pc2UuXG4gICAqXG4gICAqIEBwYXJhbSBjaHVuayAtIFRoZSBkYXRhIGNodW5rIHRvIHByb2Nlc3MuXG4gICAqL1xuICBvdmVycmlkZSBkYXRhKGNodW5rOiBhbnkpIHtcbiAgICBzdXBlci5kYXRhKGNodW5rKTtcbiAgICB0aGlzLnRlc3RBbmRSZXNvbHZlKFN0cmluZyhjaHVuaykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgaW5jb21pbmcgZXJyb3IgY2h1bmtzLlxuICAgKiBAc3VtbWFyeSBDYWxscyB0aGUgcGFyZW50IGNsYXNzIGVycm9yIG1ldGhvZCBhbmQgdGhlbiB0ZXN0cyB0aGUgZGF0YSBmb3IgYSBtYXRjaCB0byBwb3RlbnRpYWxseSByZWplY3QgdGhlIHByb21pc2UuXG4gICAqXG4gICAqIEBwYXJhbSBjaHVuayAtIFRoZSBlcnJvciBjaHVuayB0byBwcm9jZXNzLlxuICAgKi9cbiAgb3ZlcnJpZGUgZXJyb3IoY2h1bms6IGFueSkge1xuICAgIHN1cGVyLmVycm9yKGNodW5rKTtcbiAgICB0aGlzLnRlc3RBbmRSZWplY3QoU3RyaW5nKGNodW5rKSk7XG4gIH1cbn1cbiIsImV4cG9ydCAqIGZyb20gXCIuL2NsaVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vaW5wdXRcIjtcbmV4cG9ydCAqIGZyb20gXCIuL291dHB1dFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vdXRpbHNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3dyaXRlcnNcIjtcblxuLyoqXG4gKiBAbW9kdWxlIHV0aWxzXG4gKiBAZGVzY3JpcHRpb24gVXRpbGl0aWVzIGFuZCBidWlsZGluZyBibG9ja3MgZm9yIERlY2FmLVRTIENMSSBhbmQgc2NyaXB0aW5nLlxuICogQHN1bW1hcnkgQWdncmVnYXRlcyBDTEkgY29tbWFuZCBpbmZyYXN0cnVjdHVyZSwgaW5wdXQgaGVscGVycywgb3V0cHV0IHdyaXRlcnMsIGZpbGVzeXN0ZW0vbmV0d29yayB1dGlsaXRpZXMsXG4gKiBhbmQgc2hhcmVkIHR5cGVzLiBDb25zdW1lcnMgdHlwaWNhbGx5IHVzZSB7QGxpbmsgQ29tbWFuZH0sIHtAbGluayBVc2VySW5wdXR9LCB7QGxpbmsgU3RhbmRhcmRPdXRwdXRXcml0ZXJ9LFxuICoge0BsaW5rIHByaW50QmFubmVyfSwgYW5kIHV0aWxpdGllcyBmcm9tIHtAbGluayBtb2R1bGU6dXRpbHN8dXRpbHN9LlxuICpcbiAqIFRoaXMgZW50cnlwb2ludCByZS1leHBvcnRzIHN1YnBhY2thZ2VzOlxuICogLSBDTEkgZnJhbWV3b3JrIHVuZGVyIGAuL2NsaWAgKGNvbW1hbmQgYmFzZSwgb3B0aW9ucywgYnVpbHQtaW4gY29tbWFuZHMpXG4gKiAtIElucHV0IGhlbHBlcnMgdW5kZXIgYC4vaW5wdXRgIChwcm9tcHRpbmcgYW5kIGFyZyBwYXJzaW5nKVxuICogLSBPdXRwdXQgaGVscGVycyB1bmRlciBgLi9vdXRwdXRgIChiYW5uZXIgYW5kIHN0eWxpbmcpXG4gKiAtIEdlbmVyYWwgdXRpbGl0aWVzIHVuZGVyIGAuL3V0aWxzYCAoZnMsIGh0dHAsIGV4ZWMsIHR5cGVzKVxuICogLSBXcml0ZXJzIHVuZGVyIGAuL3dyaXRlcnNgIChzdGRvdXQvc3RkZXJyIHByb2Nlc3NvcnMpXG4gKlxuICogTm90ZTogSW5kaXZpZHVhbCBleHBvcnRzIGFyZSBkb2N1bWVudGVkIGluIHRoZWlyIHNvdXJjZSBmaWxlcy5cbiAqL1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXByZXNlbnRzIHRoZSBjdXJyZW50IHZlcnNpb24gb2YgdGhlIG1vZHVsZS5cbiAqIEBzdW1tYXJ5IFN0b3JlcyB0aGUgdmVyc2lvbiBmb3IgdGhlIEBkZWNhZi10cy91dGlscyBwYWNrYWdlLiBUaGUgYnVpbGQgcmVwbGFjZXNcbiAqIHRoZSBwbGFjZWhvbGRlciB3aXRoIHRoZSBhY3R1YWwgdmVyc2lvbiBudW1iZXIgYXQgcHVibGlzaCB0aW1lLlxuICogQGNvbnN0IFZFUlNJT05cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IFZFUlNJT04gPSBcIiMjVkVSU0lPTiMjXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlcHJlc2VudHMgdGhlIGN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgbW9kdWxlLlxuICogQHN1bW1hcnkgU3RvcmVzIHRoZSB2ZXJzaW9uIGZvciB0aGUgQGRlY2FmLXRzL3V0aWxzIHBhY2thZ2UuIFRoZSBidWlsZCByZXBsYWNlc1xuICogdGhlIHBsYWNlaG9sZGVyIHdpdGggdGhlIGFjdHVhbCB2ZXJzaW9uIG51bWJlciBhdCBwdWJsaXNoIHRpbWUuXG4gKiBAY29uc3QgVkVSU0lPTlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgY29uc3QgUEFDS0FHRV9OQU1FID0gXCIjI1BBQ0tBR0UjI1wiO1xuIl0sIm5hbWVzIjpbIlVzZXJJbnB1dCIsInRoaXMiLCJsb2dnZXIiLCJMb2dnaW5nIiwiZm9yIiwiY29uc3RydWN0b3IiLCJuYW1lIiwidHlwZSIsInNldFR5cGUiLCJ2ZXJib3NlIiwic2V0TWVzc2FnZSIsInZhbHVlIiwibWVzc2FnZSIsInNldEluaXRpYWwiLCJpbml0aWFsIiwic2V0U3R5bGUiLCJzdHlsZSIsInNldEZvcm1hdCIsImZvcm1hdCIsInNldFZhbGlkYXRlIiwidmFsaWRhdGUiLCJzZXRPblN0YXRlIiwib25TdGF0ZSIsInNldE1pbiIsIm1pbiIsInNldE1heCIsIm1heCIsInNldEZsb2F0IiwiZmxvYXQiLCJzZXRSb3VuZCIsInJvdW5kIiwic2V0SW5zdHJ1Y3Rpb25zIiwiaW5zdHJ1Y3Rpb25zIiwic2V0SW5jcmVtZW50IiwiaW5jcmVtZW50Iiwic2V0U2VwYXJhdG9yIiwic2VwYXJhdG9yIiwic2V0QWN0aXZlIiwiYWN0aXZlIiwic2V0SW5hY3RpdmUiLCJpbmFjdGl2ZSIsInNldENob2ljZXMiLCJKU09OIiwic3RyaW5naWZ5IiwiY2hvaWNlcyIsInNldEhpbnQiLCJoaW50Iiwic2V0V2FybiIsIndhcm4iLCJzZXRTdWdnZXN0Iiwic3VnZ2VzdCIsInNldExpbWl0IiwibGltaXQiLCJzZXRNYXNrIiwibWFzayIsInNldFN0ZG91dCIsInN0ZG91dCIsInNldFN0ZGluIiwic3RkaW4iLCJhc2siLCJxdWVzdGlvbiIsImxvZyIsIkFycmF5IiwiaXNBcnJheSIsImFuc3dlcnMiLCJtYXAiLCJxIiwiam9pbiIsInByb21wdHMiLCJlcnJvciIsIkVycm9yIiwiYXNrTnVtYmVyIiwidXNlcklucHV0IiwiYXNrVGV4dCIsInVuZGVmaW5lZCIsImFza0NvbmZpcm1hdGlvbiIsImluc2lzdCIsImlucHV0IiwidGVzdCIsImRlZmF1bHRDb25maXJtYXRpb24iLCJ0b1N0cmluZyIsInJlc3VsdCIsImNvdW50IiwiY29uZmlybWF0aW9uIiwiZSIsImluZm8iLCJpbnNpc3RGb3JUZXh0IiwiaW5zaXN0Rm9yTnVtYmVyIiwicGFyc2VBcmdzIiwib3B0aW9ucyIsImFyZ3MiLCJwcm9jZXNzIiwiYXJndiIsInNsaWNlIiwiZGVidWciLCJEZWZhdWx0Q29tbWFuZE9wdGlvbnMiLCJzaG9ydCIsImRlZmF1bHQiLCJ2ZXJzaW9uIiwiaGVscCIsImxvZ0xldmVsIiwibG9nU3R5bGUiLCJ0aW1lc3RhbXAiLCJiYW5uZXIiLCJEZWZhdWx0Q29tbWFuZFZhbHVlcyIsIk9iamVjdCIsImtleXMiLCJyZWR1Y2UiLCJhY2MiLCJrZXkiLCJFbmNvZGluZyIsIlNlbVZlcnNpb25SZWdleCIsIlNlbVZlcnNpb24iLCJOb0NJRkxhZyIsIlNldHVwU2NyaXB0S2V5IiwiVG9rZW5zIiwiQWJvcnRDb2RlIiwiU3RhbmRhcmRPdXRwdXRXcml0ZXIiLCJjbWQiLCJsb2NrIiwiZGF0YSIsIkJ1ZmZlciIsImlzQnVmZmVyIiwicmVkIiwidGV4dCIsImNodW5rIiwiU3RyaW5nIiwiZXJyb3JzIiwiZXJyIiwiZXhpdCIsImNvZGUiLCJsb2dzIiwiZ3JlZW4iLCJyZXNvbHZlIiwibCIsInRyaW0iLCJyZWplY3QiLCJsZW5ndGgiLCJwYXJzZUNvbW1hbmQiLCJjb21tYW5kIiwicGFydHMiLCJwYXJzZSIsImZpbHRlciIsInAiLCJyZWFzb24iLCJsb2NraWZ5IiwiZiIsIlByb21pc2UiLCJwYXJhbXMiLCJ0aGVuIiwiY2F0Y2giLCJjaGFpbkFib3J0Q29udHJvbGxlciIsImFyZ3VtZW50MCIsInJlbWFpbmRlciIsInNpZ25hbHMiLCJjb250cm9sbGVyIiwiQWJvcnRTaWduYWwiLCJBYm9ydENvbnRyb2xsZXIiLCJzaWduYWwiLCJhYm9ydGVkIiwiaGFuZGxlciIsImFib3J0IiwiYWRkRXZlbnRMaXN0ZW5lciIsIm9uY2UiLCJzcGF3bkNvbW1hbmQiLCJvdXRwdXQiLCJvcHRzIiwic3Bhd25Jbm5lciIsImFyZ3oiLCJjaGlsZFByb2Nlc3MiLCJzcGF3biIsImN3ZCIsImVudiIsImFzc2lnbiIsIlBBVEgiLCJzaGVsbCIsInBpZCIsIm0iLCJtYXRjaCIsImluY2x1ZGVzIiwiY21kcyIsInNwbGl0Iiwic3Bhd25zIiwiY29udHJvbGxlcnMiLCJpIiwicHVzaCIsInBpcGUiLCJydW5Db21tYW5kIiwib3V0cHV0Q29uc3RydWN0b3IiLCJlcnJzIiwic2V0RW5jb2RpbmciLCJvbiIsInN0ZGVyciIsInByb21pc2UiLCJhc3luYyIsImNiIiwicGF0Y2hTdHJpbmciLCJ2YWx1ZXMiLCJmbGFncyIsImVudHJpZXMiLCJmb3JFYWNoIiwidmFsIiwicmVnZXhwIiwiUmVnRXhwIiwiZXNjYXBlUmVnRXhwIiwicmVwbGFjZSIsInN1YlN0ciIsInBhdGNoRmlsZSIsInBhdGgiLCJmcyIsImV4aXN0c1N5bmMiLCJjb250ZW50IiwicmVhZEZpbGUiLCJ3cml0ZUZpbGUiLCJyZWFkRmlsZVN5bmMiLCJ3cml0ZUZpbGVTeW5jIiwiZ2V0QWxsRmlsZXMiLCJmaWxlcyIsInJlYWRkaXJTeW5jIiwiZW50cnkiLCJmdWxsUGF0aCIsInN0YXQiLCJzdGF0U3luYyIsImlzRmlsZSIsImlzRGlyZWN0b3J5IiwicmVuYW1lRmlsZSIsInNvdXJjZSIsImRlc3QiLCJkZXNjcmlwdG9yU291cmNlIiwiZGVzY3JpcHRvckRlc3QiLCJyZW5hbWVTeW5jIiwiY29weUZpbGUiLCJta2RpclN5bmMiLCJyZWN1cnNpdmUiLCJjcFN5bmMiLCJkZWxldGVQYXRoIiwiZGVzY3JpcHRvciIsInJtU3luYyIsImZvcmNlIiwiZ2V0UGFja2FnZSIsInByb3BlcnR5IiwicGtnIiwic2V0UGFja2FnZUF0dHJpYnV0ZSIsImF0dHIiLCJnZXRQYWNrYWdlVmVyc2lvbiIsImdldERlcGVuZGVuY2llcyIsIm1hcHBlciIsImluZGV4IiwicHJvZCIsImRlcGVuZGVuY2llcyIsImRldiIsImRldkRlcGVuZGVuY2llcyIsInBlZXIiLCJwZWVyRGVwZW5kZW5jaWVzIiwidXBkYXRlRGVwZW5kZW5jaWVzIiwiaW5zdGFsbElmTm90QXZhaWxhYmxlIiwiZGVwcyIsImQiLCJpbnN0YWxsZWQiLCJmcm9tIiwiU2V0IiwidG9JbnN0YWxsIiwiaW5zdGFsbERlcGVuZGVuY2llcyIsInB1c2hUb0dpdCIsImdpdFVzZXIiLCJnaXRFbWFpbCIsIm5vcm1hbGl6ZUltcG9ydCIsImltcG9ydFByb21pc2UiLCJnZXRGaWxlU2l6ZVppcHBlZCIsImRpciIsImNhbmRpZGF0ZXMiLCJzIiwiZW5kc1dpdGgiLCJzbWFsbGVzdCIsInNtYWxsZXN0U2l6ZSIsInNpemUiLCJjIiwiYnVmZmVyIiwiZ3oiLCJ6bGliIiwiZ3ppcFN5bmMiLCJzaXplS2IiLCJOdW1iZXIiLCJ0b0ZpeGVkIiwibGlzdEZvbGRlciIsImJhc2VQYXRoIiwid2l0aEZpbGVUeXBlcyIsIm5hbWVzIiwibGlzdE5vZGVNb2R1bGVzUGFja2FnZXMiLCJzdGFydHNXaXRoIiwic2NvcGVQYXRoIiwic2NvcGVkIiwic2xvZ2FucyIsIlNsb2dhbiIsIlRhZ3MiLCJjb2xvcnMiLCJwcmludEJhbm5lciIsImdldFNsb2dhbiIsIm1heExlbmd0aCIsImxpbmUiLCJNYXRoIiwicGFkU3RhcnQiLCJiaW5kIiwiY29uc29sZSIsInJhdyIsImZsb29yIiwicmFuZG9tIiwiQ29tbWFuZCIsIkxvZ2dlZENsYXNzIiwiaW5wdXRzIiwicmVxdWlyZW1lbnRzIiwic3VwZXIiLCJkZWZpbmVQcm9wZXJ0eSIsIndyaXRhYmxlIiwiY2hlY2tSZXF1aXJlbWVudHMiLCJtaXNzaW5nIiwiZnVsbExpc3QiLCJkZXAiLCJleGVjdXRlIiwiTG9nZ2VkRW52aXJvbm1lbnQiLCJhY2N1bXVsYXRlIiwiY29udGV4dCIsInJ1biIsIkh0dHBDbGllbnQiLCJkb3dubG9hZEZpbGUiLCJ1cmwiLCJyZXF1ZXN0IiwiZW5jb2RlVVJJIiwiaHR0cHMiLCJnZXQiLCJyZXMiLCJzdGF0dXNDb2RlIiwiaGVhZGVycyIsImxvY2F0aW9uIiwicGFyc2VMaXN0IiwiQm9vbGVhbiIsInBhY2thZ2VUb0dsb2JhbCIsIndpdGhvdXRTY29wZSIsImNoYXJBdCIsInRvVXBwZXJDYXNlIiwiZ2V0UGFja2FnZURlcGVuZGVuY2llcyIsImhhc0RlcHMiLCJmYWxsYmFja0RpciIsIl9fZGlybmFtZSIsIlZFUlNJT05fU1RSSU5HIiwiUEFDS0FHRV9TVFJJTkciLCJQQUNLQUdFX1NJWkVfU1RSSU5HIiwiTW9kZXMiLCJCdWlsZE1vZGUiLCJidWlsZE1vZGUiLCJBTEwiLCJleHRlcm5hbHMiLCJkb2NzIiwiY29tbWFuZHMiLCJjanMyVHJhbnNmb3JtZXIiLCJleHQiLCJCdWlsZFNjcmlwdHMiLCJyZXNvbHV0aW9uQ2FjaGUiLCJNYXAiLCJ0cmFuc2Zvcm1hdGlvbkNvbnRleHQiLCJzb3VyY2VGaWxlIiwic291cmNlRGlyIiwiZGlybmFtZSIsImZpbGVOYW1lIiwicmVzb2x2ZVBhdGgiLCJpbXBvcnRQYXRoIiwiY2FjaGVLZXkiLCJjYWNoZWRWYWx1ZSIsInJlc29sdmVkUGF0aCIsImUyIiwiaXNBYnNvbHV0ZSIsImV4dGVuc2lvbiIsImV4ZWMiLCJiYXNlbmFtZSIsInJlbGF0aXZlIiwic2V0IiwidmlzaXROb2RlIiwibm9kZSIsInNob3VsZE11dGF0ZU1vZHVsZVNwZWNpZmllciIsInRzIiwiaXNJbXBvcnREZWNsYXJhdGlvbiIsIm1vZHVsZVNwZWNpZmllciIsIm5ld01vZHVsZVNwZWNpZmllciIsImZhY3RvcnkiLCJjcmVhdGVTdHJpbmdMaXRlcmFsIiwidXBkYXRlSW1wb3J0RGVjbGFyYXRpb24iLCJtb2RpZmllcnMiLCJpbXBvcnRDbGF1c2UiLCJpc0V4cG9ydERlY2xhcmF0aW9uIiwidXBkYXRlRXhwb3J0RGVjbGFyYXRpb24iLCJpc1R5cGVPbmx5IiwiZXhwb3J0Q2xhdXNlIiwidmlzaXRFYWNoQ2hpbGQiLCJpc1N0cmluZ0xpdGVyYWwiLCJleHRuYW1lIiwicmVwbGFjZW1lbnRzIiwicGtnTmFtZSIsInBrZ1ZlcnNpb24iLCJwYXRjaEZpbGVzIiwiZmlsZSIsInBhcmVudFBhdGgiLCJyZXBvcnREaWFnbm9zdGljcyIsImRpYWdub3N0aWNzIiwibXNnIiwiZm9ybWF0RGlhZ25vc3RpY3MiLCJkaWFnbm9zdGljIiwic3RhcnQiLCJjaGFyYWN0ZXIiLCJnZXRMaW5lQW5kQ2hhcmFjdGVyT2ZQb3NpdGlvbiIsImZsYXR0ZW5EaWFnbm9zdGljTWVzc2FnZVRleHQiLCJtZXNzYWdlVGV4dCIsInJlYWRDb25maWdGaWxlIiwiY29uZmlnRmlsZU5hbWUiLCJjb25maWdGaWxlVGV4dCIsInBhcnNlQ29uZmlnRmlsZVRleHRUb0pzb24iLCJjb25maWdPYmplY3QiLCJjb25maWciLCJMb2dMZXZlbCIsImNvbmZpZ1BhcnNlUmVzdWx0IiwicGFyc2VKc29uQ29uZmlnRmlsZUNvbnRlbnQiLCJzeXMiLCJldmFsRGlhZ25vc3RpY3MiLCJjYXRlZ29yeSIsIkRpYWdub3N0aWNDYXRlZ29yeSIsIndhcm5pbmdzIiwiV2FybmluZyIsInN1Z2dlc3Rpb25zIiwiU3VnZ2VzdGlvbiIsIm1lc3NhZ2VzIiwiTWVzc2FnZSIsInByZUNoZWNrRGlhZ25vc3RpY3MiLCJwcm9ncmFtIiwiZ2V0UHJlRW1pdERpYWdub3N0aWNzIiwiY2hlY2tUc0RpYWdub3N0aWNzIiwiaXNEZXYiLCJtb2RlIiwiYnVuZGxlIiwidHNDb25maWciLCJtb2R1bGUiLCJNb2R1bGVLaW5kIiwiQU1EIiwib3V0RGlyIiwiaXNvbGF0ZWRNb2R1bGVzIiwib3V0RmlsZSIsIkVTTSIsIkVTMjAyMiIsIkNvbW1vbkpTIiwiaW5saW5lU291cmNlTWFwIiwiaW5saW5lU291cmNlcyIsInNvdXJjZU1hcCIsImNyZWF0ZVByb2dyYW0iLCJmaWxlTmFtZXMiLCJidWlsZFRzIiwidHJhbnNmb3JtYXRpb25zIiwiQ0pTIiwiYmVmb3JlIiwiZW1pdFJlc3VsdCIsImVtaXQiLCJhbGxEaWFnbm9zdGljcyIsImNvbmNhdCIsImJ1aWxkIiwiY29weUFzc2V0cyIsImhhc0Fzc2V0cyIsImlzTGliIiwiZW50cnlGaWxlIiwibmFtZU92ZXJyaWRlIiwiZXh0ZXJuYWxzQXJnIiwiaW5jbHVkZUFyZyIsImlzRXNtIiwiaW5jbHVkZSIsImV4dGVybmFsc0xpc3QiLCJidWlsdGluTGlzdCIsImJ1aWx0aW5Nb2R1bGVzIiwicm9sbHVwU291cmNlTWFwT3V0cHV0IiwicGx1Z2lucyIsInR5cGVzY3JpcHQiLCJjb21waWxlck9wdGlvbnMiLCJkZWNsYXJhdGlvbiIsImV4Y2x1ZGUiLCJ0c2NvbmZpZyIsImpzb24iLCJjb21tb25qcyIsIm5vZGVSZXNvbHZlIiwicmVzb2x2ZU9ubHkiLCJ0ZXJzZXJNb2QiLCJpbXBvcnQiLCJ0ZXJzZXJGbiIsInRlcnNlciIsInRlcnNlck9wdGlvbnNEZXYiLCJlY21hIiwiY29tcHJlc3MiLCJtYW5nbGUiLCJjb21tZW50cyIsImJlYXV0aWZ5IiwidGVyc2VyT3B0aW9uc1Byb2QiLCJwYXNzZXMiLCJkcm9wX2NvbnNvbGUiLCJkcm9wX2RlYnVnZ2VyIiwidG9wbGV2ZWwiLCJ1bnNhZmUiLCJ1bnNhZmVfYXJyb3dzIiwidW5zYWZlX2NvbXBzIiwiY29sbGFwc2VfdmFycyIsInJlZHVjZV9mdW5jcyIsInJlZHVjZV92YXJzIiwiYXNjaWlfb25seSIsImV4dGVybmFsIiwib253YXJuIiwidHJlZXNoYWtlIiwiZ2xvYmFscyIsIm91dHB1dHMiLCJlc01vZHVsZSIsInNvdXJjZW1hcCIsImV4cG9ydHMiLCJyb2xsdXAiLCJ3YXRjaEZpbGVzIiwiZ2VuZXJhdGVPdXRwdXRzIiwib3V0cHV0T3B0aW9ucyIsIndyaXRlIiwiYnVpbGRCeUVudiIsImluY2x1ZGVzQXJnIiwiQlVJTEQiLCJCVU5ETEUiLCJidWlsZERldiIsImJ1aWxkUHJvZCIsImJ1aWxkRG9jcyIsInNyYyIsImNpIiwidGFnIiwiUmVsZWFzZVNjcmlwdCIsInByZXBhcmVWZXJzaW9uIiwidGVzdFZlcnNpb24iLCJ0b0xvd2VyQ2FzZSIsIlBBVENIIiwiTUlOT1IiLCJNQUpPUiIsInByZXBhcmVNZXNzYWdlIiwiUmVnZXhwT3V0cHV0V3JpdGVyIiwibGFzdEluZGV4IiwidGVzdEFuZFJlc29sdmUiLCJ0ZXN0QW5kUmVqZWN0IiwiVkVSU0lPTiIsIlBBQ0tBR0VfTkFNRSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O01Bd0VhQTs7UUFDYUMsS0FBTUMsU0FBR0MsUUFBUUMsSUFBSUo7QUFBVztJQXdKeEQsV0FBQUssQ0FBWUM7UUFuSlpMLEtBQUlNLE9BQTJEO1FBb0o3RE4sS0FBS0ssT0FBT0E7QUFDYjtJQVNELE9BQUFFLENBQVFEO1FBQ05QLFVBQVVFLE9BQU9PLFFBQVEsb0JBQW9CRjtRQUM3Q04sS0FBS00sT0FBT0E7UUFDWixPQUFPTjtBQUNSO0lBU0QsVUFBQVMsQ0FBV0M7UUFDVFgsVUFBVUUsT0FBT08sUUFBUSx1QkFBdUJFO1FBQ2hEVixLQUFLVyxVQUFVRDtRQUNmLE9BQU9WO0FBQ1I7SUFTRCxVQUFBWSxDQUNFRjtRQUtBWCxVQUFVRSxPQUFPTyxRQUFRLDZCQUE2QkU7UUFDdERWLEtBQUthLFVBQVVIO1FBQ2YsT0FBT1Y7QUFDUjtJQVNELFFBQUFjLENBQVNKO1FBQ1BYLFVBQVVFLE9BQU9PLFFBQVEscUJBQXFCRTtRQUM5Q1YsS0FBS2UsUUFBUUw7UUFDYixPQUFPVjtBQUNSO0lBU0QsU0FBQWdCLENBQVVOO1FBQ1JYLFVBQVVFLE9BQU9PLFFBQVE7UUFDekJSLEtBQUtpQixTQUFTUDtRQUNkLE9BQU9WO0FBQ1I7SUFTRCxXQUFBa0IsQ0FDRVI7UUFJQVgsVUFBVUUsT0FBT08sUUFBUTtRQUN6QlIsS0FBS21CLFdBQVdUO1FBQ2hCLE9BQU9WO0FBQ1I7SUFTRCxVQUFBb0IsQ0FBV1Y7UUFDVFgsVUFBVUUsT0FBT08sUUFBUTtRQUN6QlIsS0FBS3FCLFVBQVVYO1FBQ2YsT0FBT1Y7QUFDUjtJQVNELE1BQUFzQixDQUFPWjtRQUNMWCxVQUFVRSxPQUFPTyxRQUFRLHlCQUF5QkU7UUFDbERWLEtBQUt1QixNQUFNYjtRQUNYLE9BQU9WO0FBQ1I7SUFTRCxNQUFBd0IsQ0FBT2Q7UUFDTFgsVUFBVUUsT0FBT08sUUFBUSx5QkFBeUJFO1FBQ2xEVixLQUFLeUIsTUFBTWY7UUFDWCxPQUFPVjtBQUNSO0lBU0QsUUFBQTBCLENBQVNoQjtRQUNQWCxVQUFVRSxPQUFPTyxRQUFRLHFCQUFxQkU7UUFDOUNWLEtBQUsyQixRQUFRakI7UUFDYixPQUFPVjtBQUNSO0lBU0QsUUFBQTRCLENBQVNsQjtRQUNQWCxVQUFVRSxPQUFPTyxRQUFRLHFCQUFxQkU7UUFDOUNWLEtBQUs2QixRQUFRbkI7UUFDYixPQUFPVjtBQUNSO0lBU0QsZUFBQThCLENBQWdCcEI7UUFDZFgsVUFBVUUsT0FBT08sUUFBUSw0QkFBNEJFO1FBQ3JEVixLQUFLK0IsZUFBZXJCO1FBQ3BCLE9BQU9WO0FBQ1I7SUFTRCxZQUFBZ0MsQ0FDRXRCO1FBRUFYLFVBQVVFLE9BQU9PLFFBQVEseUJBQXlCRTtRQUNsRFYsS0FBS2lDLFlBQVl2QjtRQUNqQixPQUFPVjtBQUNSO0lBU0QsWUFBQWtDLENBQ0V4QjtRQUVBWCxVQUFVRSxPQUFPTyxRQUFRLHlCQUF5QkU7UUFDbERWLEtBQUttQyxZQUFZekI7UUFDakIsT0FBT1Y7QUFDUjtJQVNELFNBQUFvQyxDQUFVMUI7UUFDUlgsVUFBVUUsT0FBT08sUUFBUSw0QkFBNEJFO1FBQ3JEVixLQUFLcUMsU0FBUzNCO1FBQ2QsT0FBT1Y7QUFDUjtJQVNELFdBQUFzQyxDQUFZNUI7UUFDVlgsVUFBVUUsT0FBT08sUUFBUSw4QkFBOEJFO1FBQ3ZEVixLQUFLdUMsV0FBVzdCO1FBQ2hCLE9BQU9WO0FBQ1I7SUFTRCxVQUFBd0MsQ0FDRTlCO1FBRUFYLFVBQVVFLE9BQU9PLFFBQVEsb0JBQW9CaUMsS0FBS0MsVUFBVWhDO1FBQzVEVixLQUFLMkMsVUFBVWpDO1FBQ2YsT0FBT1Y7QUFDUjtJQVNELE9BQUE0QyxDQUFRbEM7UUFDTlgsVUFBVUUsT0FBT08sUUFBUSxvQkFBb0JFO1FBQzdDVixLQUFLNkMsT0FBT25DO1FBQ1osT0FBT1Y7QUFDUjtJQVNELE9BQUE4QyxDQUFRcEM7UUFDTlgsVUFBVUUsT0FBT08sUUFBUSxvQkFBb0JFO1FBQzdDVixLQUFLK0MsT0FBT3JDO1FBQ1osT0FBT1Y7QUFDUjtJQVNELFVBQUFnRCxDQUNFdEM7UUFFQVgsVUFBVUUsT0FBT08sUUFBUTtRQUN6QlIsS0FBS2lELFVBQVV2QztRQUNmLE9BQU9WO0FBQ1I7SUFTRCxRQUFBa0QsQ0FBU3hDO1FBQ1BYLFVBQVVFLE9BQU9PLFFBQVEscUJBQXFCRTtRQUM5Q1YsS0FBS21ELFFBQVF6QztRQUNiLE9BQU9WO0FBQ1I7SUFTRCxPQUFBb0QsQ0FBUTFDO1FBQ05YLFVBQVVFLE9BQU9PLFFBQVEsb0JBQW9CRTtRQUM3Q1YsS0FBS3FELE9BQU8zQztRQUNaLE9BQU9WO0FBQ1I7SUFRRCxTQUFBc0QsQ0FBVTVDO1FBQ1JYLFVBQVVFLE9BQU9PLFFBQVE7UUFDekJSLEtBQUt1RCxTQUFTN0M7UUFDZCxPQUFPVjtBQUNSO0lBT0QsUUFBQXdELENBQVM5QztRQUNQVixLQUFLeUQsUUFBUS9DO1FBQ2IsT0FBT1Y7QUFDUjtJQVFELFNBQU0wRDtRQUNKLGNBQWMzRCxVQUFVMkQsSUFBSTFELE9BQU9BLEtBQUtLO0FBQ3pDO0lBb0JELGdCQUFhcUQsQ0FDWEM7UUFFQSxNQUFNQyxNQUFNN0QsVUFBVUUsT0FBT0UsSUFBSUgsS0FBSzBEO1FBQ3RDLEtBQUtHLE1BQU1DLFFBQVFILFdBQVc7WUFDNUJBLFdBQVcsRUFBQ0E7QUFDYjtRQUNELElBQUlJO1FBQ0o7WUFDRUgsSUFBSXBELFFBQ0YscUJBQXFCbUQsU0FBU0ssSUFBS0MsS0FBTUEsRUFBRTVELE1BQU02RCxLQUFLO1lBRXhESCxnQkFBZ0JJLFFBQVFSO1lBQ3hCQyxJQUFJcEQsUUFBUSxxQkFBcUJpQyxLQUFLQyxVQUFVcUIsU0FBUyxNQUFNO0FBQ2hFLFVBQUMsT0FBT0s7WUFDUCxNQUFNLElBQUlDLE1BQU0sOEJBQThCRDtBQUMvQztRQUNELE9BQU9MO0FBQ1I7SUFZRCxzQkFBYU8sQ0FDWGpFLE1BQ0FzRCxVQUNBcEMsS0FDQUUsS0FDQVo7UUFFQSxNQUFNK0MsTUFBTTdELFVBQVVFLE9BQU9FLElBQUlILEtBQUtzRTtRQUN0Q1YsSUFBSXBELFFBQ0YsNkNBQTZDbUQsa0JBQWtCcEMsYUFBYUUsaUJBQWlCWjtRQUUvRixNQUFNMEQsWUFBWSxJQUFJeEUsVUFBVU0sTUFDN0JJLFdBQVdrRCxVQUNYcEQsUUFBUTtRQUVYLFdBQVdnQixRQUFRLFVBQVVnRCxVQUFVakQsT0FBT0M7UUFFOUMsV0FBV0UsUUFBUSxVQUFVOEMsVUFBVS9DLE9BQU9DO1FBRTlDLFdBQVdaLFlBQVksVUFBVTBELFVBQVUzRCxXQUFXQztRQUV0RCxjQUFjYixLQUFLMEQsSUFBSWEsWUFBWWxFO0FBQ3BDO0lBV0Qsb0JBQWFtRSxDQUNYbkUsTUFDQXNELFVBQ0FOLE9BQTJCb0IsV0FDM0I1RDtRQUVBLE1BQU0rQyxNQUFNN0QsVUFBVUUsT0FBT0UsSUFBSUgsS0FBS3dFO1FBQ3RDWixJQUFJcEQsUUFDRiwyQ0FBMkNtRCxtQkFBbUJOLGtCQUFrQnhDO1FBRWxGLE1BQU0wRCxZQUFZLElBQUl4RSxVQUFVTSxNQUFNSSxXQUFXa0Q7UUFFakQsSUFBSU4sTUFBTWtCLFVBQVVuQixRQUFRQztRQUM1QixXQUFXeEMsWUFBWSxVQUFVMEQsVUFBVTNELFdBQVdDO1FBQ3RELGNBQWNiLEtBQUswRCxJQUFJYSxZQUFZbEU7QUFDcEM7SUFVRCw0QkFBYXFFLENBQ1hyRSxNQUNBc0QsVUFDQTlDO1FBRUEsTUFBTStDLE1BQU03RCxVQUFVRSxPQUFPRSxJQUFJSCxLQUFLMEU7UUFDdENkLElBQUlwRCxRQUNGLG1EQUFtRG1ELHNCQUFzQjlDO1FBRTNFLE1BQU0wRCxZQUFZLElBQUl4RSxVQUFVTSxNQUM3QkksV0FBV2tELFVBQ1hwRCxRQUFRO1FBRVgsV0FBV00sWUFBWSxhQUFhMEQsVUFBVTNELFdBQVdDO1FBQ3pELGNBQWNiLEtBQUswRCxJQUFJYSxZQUFZbEU7QUFDcEM7SUF5Q0QsbUJBQWFzRSxDQUNYQyxPQUNBQyxNQUNBQyxxQkFDQTNCLFFBQVE7UUFFUixNQUFNUyxNQUFNN0QsVUFBVUUsT0FBT0UsSUFBSUgsS0FBSzJFO1FBQ3RDZixJQUFJcEQsUUFDRix1QkFBdUJvRSxNQUFNdkUsZUFBZXdFLEtBQUtFLG9DQUFvQ0QsK0JBQStCM0I7UUFFdEgsSUFBSTZCLFNBQXNDUDtRQUMxQyxJQUFJUSxRQUFRO1FBQ1osSUFBSUM7UUFDSjtZQUNFLEdBQUc7Z0JBQ0RGLGdCQUFnQmpGLFVBQVUyRCxJQUFJa0IsUUFDNUJBLE1BQU12RTtnQkFFUixLQUFLd0UsS0FBS0csU0FBUztvQkFDakJBLFNBQVNQO29CQUNUO0FBQ0Q7Z0JBQ0RTLHFCQUFxQm5GLFVBQVUyRSxnQkFDN0IsR0FBR0UsTUFBTXZFLGdCQUNULFVBQVV1RSxNQUFNdEUsaUJBQ2hCd0U7Z0JBRUYsS0FBS0ksY0FBY0YsU0FBU1A7QUFDOUIsNEJBQWdCTyxXQUFXLGVBQWU3QixRQUFRLEtBQUs4QixVQUFVOUI7QUFDbEUsVUFBQyxPQUFPZ0M7WUFDUHZCLElBQUlRLE1BQU0sMEJBQTBCZTtZQUNwQyxNQUFNQTtBQUNQO1FBRUQsV0FBV0gsV0FBVyxhQUFhcEIsSUFBSXdCLEtBQUs7UUFDNUMsT0FBT0o7QUFDUjtJQWNELDBCQUFhSyxDQUNYaEYsTUFDQXNELFVBQ0FrQixNQUNBeEIsT0FBMkJvQixXQUMzQjVELFNBQ0FpRSxzQkFBc0IsT0FDdEIzQixTQUFTO1FBRVQsTUFBTVMsTUFBTTdELFVBQVVFLE9BQU9FLElBQUlILEtBQUtxRjtRQUN0Q3pCLElBQUlwRCxRQUNGLGtEQUFrRG1ELG1CQUFtQmtCLEtBQUtFLHFCQUFxQjFCLGtCQUFrQnhDLGlDQUFpQ2lFLCtCQUErQjNCO1FBRW5MLE1BQU1vQixZQUFZLElBQUl4RSxVQUFVTSxNQUFNSSxXQUFXa0Q7UUFFakQsSUFBSU4sTUFBTWtCLFVBQVVuQixRQUFRQztRQUM1QixXQUFXeEMsWUFBWSxVQUFVMEQsVUFBVTNELFdBQVdDO1FBQ3RELGFBQWNiLEtBQUsyRSxPQUNqQkosV0FDQU0sTUFDQUMscUJBQ0EzQjtBQUVIO0lBZUQsNEJBQWFtQyxDQUNYakYsTUFDQXNELFVBQ0FrQixNQUNBdEQsS0FDQUUsS0FDQVosU0FDQWlFLHNCQUFzQixPQUN0QjNCLFNBQVM7UUFFVCxNQUFNUyxNQUFNN0QsVUFBVUUsT0FBT0UsSUFBSUgsS0FBS3NGO1FBQ3RDMUIsSUFBSXBELFFBQ0Ysb0RBQW9EbUQsbUJBQW1Ca0IsS0FBS0Usb0JBQW9CeEQsYUFBYUUsaUJBQWlCWixpQ0FBaUNpRSwrQkFBK0IzQjtRQUVoTSxNQUFNb0IsWUFBWSxJQUFJeEUsVUFBVU0sTUFDN0JJLFdBQVdrRCxVQUNYcEQsUUFBUTtRQUVYLFdBQVdnQixRQUFRLFVBQVVnRCxVQUFVakQsT0FBT0M7UUFFOUMsV0FBV0UsUUFBUSxVQUFVOEMsVUFBVS9DLE9BQU9DO1FBRTlDLFdBQVdaLFlBQVksVUFBVTBELFVBQVUzRCxXQUFXQztRQUN0RCxhQUFjYixLQUFLMkUsT0FDakJKLFdBQ0FNLE1BQ0FDLHFCQUNBM0I7QUFFSDtJQWtCRCxnQkFBT29DLENBQVVDO1FBQ2YsTUFBTTVCLE1BQU03RCxVQUFVRSxPQUFPRSxJQUFJSCxLQUFLdUY7UUFDdEMsTUFBTUUsT0FBd0I7WUFDNUJBLE1BQU1DLFFBQVFDLEtBQUtDLE1BQU07WUFDekJKLFNBQVNBOztRQUVYNUIsSUFBSWlDLE1BQU0sc0JBQXNCcEQsS0FBS0MsVUFBVStDLE1BQU0sTUFBTTtRQUMzRDtZQUNFLE9BQU9GLFVBQVVFO0FBQ2xCLFVBQUMsT0FBT3JCO1lBQ1BSLElBQUlpQyxNQUNGLG1DQUFtQ3BELEtBQUtDLFVBQVUrQyxNQUFNLE1BQU0sbUJBQW1CaEQsS0FBS0MsVUFBVThDLFNBQVMsTUFBTSxVQUFVcEI7WUFFM0gsTUFBTSxJQUFJQyxNQUFNLGtDQUFrQ0Q7QUFDbkQ7QUFDRjs7O0FDNzBCVSxNQUFBMEIsd0JBQXdCO0lBQ25DdEYsU0FBUztRQUNQRixNQUFNO1FBQ055RixPQUFPO1FBQ1BDLFNBQVN2Qjs7SUFFWHdCLFNBQVM7UUFDUDNGLE1BQU07UUFDTnlGLE9BQU87UUFDUEMsU0FBU3ZCOztJQUVYeUIsTUFBTTtRQUNKNUYsTUFBTTtRQUNOeUYsT0FBTztRQUNQQyxTQUFTOztJQUVYRyxVQUFVO1FBQ1I3RixNQUFNO1FBQ04wRixTQUFTOztJQUVYSSxVQUFVO1FBQ1I5RixNQUFNO1FBQ04wRixTQUFTOztJQUVYSyxXQUFXO1FBQ1QvRixNQUFNO1FBQ04wRixTQUFTOztJQUVYTSxRQUFRO1FBQ05oRyxNQUFNO1FBQ04wRixTQUFTOzs7O0FBWUEsTUFBQU8sdUJBRVRDLE9BQU9DLEtBQUtYLHVCQUF1QlksT0FDckMsQ0FBQ0MsS0FBMERDO0lBQ3pERCxJQUFJQyxPQUNGZCxzQkFBc0JjLEtBQTJDWjtJQUNuRSxPQUFPVztHQUVULENBQXdEOztBQzNFbkQsTUFBTUUsV0FBVzs7QUFRakIsTUFBTUMsa0JBQ1g7O0lBUVVDOztDQUFaLFNBQVlBO0lBRVZBLFdBQUEsV0FBQTtJQUVBQSxXQUFBLFdBQUE7SUFFQUEsV0FBQSxXQUFBO0FBQ0QsRUFQRCxDQUFZQSxlQUFBQSxhQU9YLENBQUE7O0FBUU0sTUFBTUMsV0FBVzs7QUFRakIsTUFBTUMsaUJBQWlCOztJQVFsQkM7O0NBQVosU0FBWUE7SUFFVkEsT0FBQSxTQUFBO0lBRUFBLE9BQUEsU0FBQTtJQUVBQSxPQUFBLFlBQUE7SUFFQUEsT0FBQSxnQkFBQTtBQUNELEVBVEQsQ0FBWUEsV0FBQUEsU0FTWCxDQUFBOztBQVFNLE1BQU1DLFlBQVk7O01DRlpDO0lBR1gsV0FBQWhILENBQ1lpSCxLQUNBQyxTQUVQN0I7UUFIT3pGLEtBQUdxSCxNQUFIQTtRQUNBckgsS0FBSXNILE9BQUpBO1FBSVZ0SCxLQUFLQyxTQUFTQyxRQUFRQyxJQUFJSCxLQUFLcUg7QUFDaEM7SUFTUyxHQUFBekQsQ0FBSXRELE1BQWtCaUg7UUFDOUJBLE9BQU9DLE9BQU9DLFNBQVNGLFFBQVFBLEtBQUt4QyxTQUFTOEIsWUFBWVU7UUFDekQsTUFBTTNELE1BQU10RCxTQUFTLFdBQVdTLE1BQU13RyxNQUFNRyxJQUFJQyxPQUFPSjtRQUN2RHZILEtBQUtDLE9BQU9tRixLQUFLeEI7QUFDbEI7SUFRRCxJQUFBMkQsQ0FBS0s7UUFDSDVILEtBQUs0RCxJQUFJLFVBQVVpRSxPQUFPRDtBQUMzQjtJQVFELEtBQUF4RCxDQUFNd0Q7UUFDSjVILEtBQUs0RCxJQUFJLFVBQVVpRSxPQUFPRDtBQUMzQjtJQVFELE1BQUFFLENBQU9DO1FBQ0wvSCxLQUFLNEQsSUFBSSxVQUFVLG9DQUFvQ21FO0FBQ3hEO0lBU0QsSUFBQUMsQ0FBS0MsTUFBdUJDO1FBQzFCbEksS0FBSzRELElBQ0gsVUFDQSx5QkFBeUJxRSxTQUFTLElBQUlsSCxNQUFNa0gsS0FBS2xELFlBQVlvRCxNQUFNUixPQUFPNUcsTUFBTWtILFNBQVMsT0FBTyxTQUFTQSxLQUFLbEQsWUFBWTJDLElBQUlDO1FBRWhJLElBQUlNLFNBQVMsR0FBRztZQUNkakksS0FBS29JLFFBQVFGLEtBQUtsRSxJQUFLcUUsS0FBTUEsRUFBRUMsUUFBUXBFLEtBQUs7QUFDN0MsZUFBTTtZQUNMbEUsS0FBS3VJLE9BQU8sSUFBSWxFLE1BQU02RCxLQUFLTSxTQUFTTixLQUFLaEUsS0FBSyxRQUFRK0QsS0FBS2xEO0FBQzVEO0FBQ0Y7SUFTRCxZQUFBMEQsQ0FBYUM7UUFDWCxJQUFJN0UsTUFBTUMsUUFBUTRFLFVBQVU7WUFDMUIxSSxLQUFLcUgsTUFBTXFCLFFBQVF4RSxLQUFLO1lBQ3hCLE9BQU8sRUFBQ3dFLFFBQVEsSUFBSUEsUUFBUTlDLE1BQU07QUFDbkM7UUFFRCxNQUFNK0MsUUFBUUMsTUFBTUYsU0FDakJHLE9BQVFDLFlBQWFBLE1BQU0sVUFDM0I5RSxJQUFJNkQ7UUFFUDdILEtBQUtxSCxNQUFNc0IsTUFBTXpFLEtBQUs7UUFDdEIsT0FBTyxFQUFDeUUsTUFBTSxJQUFJQSxNQUFNL0MsTUFBTTtBQUMvQjtJQVFTLE9BQUF3QyxDQUFRVztRQUNoQi9JLEtBQUs0RCxJQUNILFVBQ0EsR0FBRzVELEtBQUtxSCw4QkFBOEJ0RyxNQUFNZ0ksU0FBUyxzQkFBdUJBLFFBQW1CWjtRQUVqR25JLEtBQUtzSCxLQUFLYyxRQUFRVztBQUNuQjtJQVFTLE1BQUFSLENBQU9RO1FBQ2YsTUFBTUEsa0JBQWtCMUUsUUFBUTtZQUM5QjBFLFNBQVMsSUFBSTFFLGFBQ0owRSxXQUFXLFdBQVcsYUFBYUEsV0FBV0E7QUFFeEQ7UUFDRC9JLEtBQUs0RCxJQUNILFVBQ0EsR0FBRzVELEtBQUtxSCwwQkFBMEJ0RyxNQUFNZ0ksT0FBT3BJLFNBQVMrRztRQUUxRDFILEtBQUtzSCxLQUFLaUIsT0FBT1E7QUFDbEI7OztBQ3BKRyxTQUFVQyxRQUFXQztJQUN6QixJQUFJM0IsT0FBMEI0QixRQUFRZDtJQUN0QyxPQUFPLElBQUllO1FBQ1QsTUFBTW5FLFNBQVNzQyxLQUFLOEIsS0FBSyxNQUFNSCxLQUFLRTtRQUNwQzdCLE9BQU90QyxPQUFPcUUsTUFBTTtRQUNwQixPQUFPckU7O0FBRVg7O1NBbUNnQnNFLHFCQUNkQyxjQUNHQztJQUVILElBQUlDO0lBQ0osSUFBSUM7SUFHSixJQUFJSCxxQkFBcUJJLGFBQWE7UUFDcENELGFBQWEsSUFBSUU7UUFDakJILFVBQVUsRUFBQ0YsY0FBY0M7QUFDMUIsV0FBTTtRQUNMRSxhQUFhSDtRQUNiRSxVQUFVRDtBQUNYO0lBR0QsSUFBSUUsV0FBV0csT0FBT0MsU0FBUztRQUM3QixPQUFPSjtBQUNSO0lBRUQsTUFBTUssVUFBVSxNQUFNTCxXQUFXTTtJQUVqQyxLQUFLLE1BQU1ILFVBQVVKLFNBQVM7UUFHNUIsSUFBSUksT0FBT0MsU0FBUztZQUNsQkosV0FBV007WUFDWDtBQUNEO1FBQ0RILE9BQU9JLGlCQUFpQixTQUFTRixTQUFTO1lBQ3hDRyxNQUFNO1lBQ05MLFFBQVFILFdBQVdHOztBQUV0QjtJQUVELE9BQU9IO0FBQ1Q7O0FBb0JNLFNBQVVTLGFBQ2RDLFFBQ0ExQixTQUNBMkIsTUFDQUwsT0FDQS9KO0lBRUEsU0FBU3FLLFdBQVc1QixTQUFpQmdCO1FBQ25DLE9BQU9yQyxLQUFLa0QsUUFBUUgsT0FBTzNCLGFBQWFDO1FBQ3hDekksT0FBT21GLEtBQUssb0JBQW9CaUM7UUFDaENwSCxPQUFPNEYsTUFBTSxjQUFjMEUsS0FBS3JHLEtBQUs7UUFDckMsTUFBTXNHLGVBQWVDLE1BQU1wRCxLQUFLa0QsTUFBTTtlQUNqQ0Y7WUFDSEssS0FBS0wsS0FBS0ssT0FBT2hGLFFBQVFnRjtZQUN6QkMsS0FBS25FLE9BQU9vRSxPQUFPLENBQUUsR0FBRWxGLFFBQVFpRixLQUFLTixLQUFLTSxLQUFLO2dCQUFFRSxNQUFNbkYsUUFBUWlGLElBQUlFOztZQUNsRUMsT0FBT1QsS0FBS1MsU0FBUztZQUNyQmpCLFFBQVFILFdBQVdHOztRQUVyQjVKLE9BQU9PLFFBQVEsU0FBU2dLLGFBQWFPO1FBQ3JDLE9BQU9QO0FBQ1I7SUFFRCxNQUFNUSxJQUFJdEMsUUFBUXVDLE1BQU07SUFDeEIsSUFBSUQsR0FDRixNQUFNLElBQUkzRyxNQUNSLG9CQUFvQnFFLHlDQUF5Q3NDO0lBRWpFLElBQUl0QyxRQUFRd0MsU0FBUyxRQUFRO1FBQzNCLE1BQU1DLE9BQU96QyxRQUFRMEMsTUFBTTtRQUMzQixNQUFNQyxTQUFTO1FBQ2YsTUFBTUMsY0FBYyxJQUFJekgsTUFBTXNILEtBQUszQztRQUNuQzhDLFlBQVksS0FBS3RCO1FBQ2pCLEtBQUssSUFBSXVCLElBQUksR0FBR0EsSUFBSUosS0FBSzNDLFFBQVErQyxLQUFLO1lBQ3BDLElBQUlBLE1BQU0sR0FDUkQsWUFBWUMsS0FBS2pDLHFCQUFxQmdDLFlBQVlDLElBQUksR0FBRzFCO1lBQzNEd0IsT0FBT0csS0FBS2xCLFdBQVdhLEtBQUtJLElBQUlELFlBQVlDO1lBQzVDLElBQUlBLE1BQU0sR0FBRztZQUNiRixPQUFPRSxJQUFJLEdBQUdoSSxPQUFPa0ksS0FBS0osT0FBT0UsR0FBRzlIO0FBQ3JDO1FBQ0QsT0FBTzRILE9BQU9GLEtBQUszQyxTQUFTO0FBQzdCO0lBRUQsT0FBTzhCLFdBQVc1QixTQUFTc0I7QUFDN0I7O0FBK0NnQixTQUFBMEIsV0FDZGhELFNBQ0EyQixPQUFpQyxDQUFBLEdBQ2pDc0IsNkNBS0dsRztJQUVILE1BQU14RixTQUFTQyxRQUFRQyxJQUFJdUw7SUFDM0IsTUFBTTFCLFFBQVEsSUFBSUo7SUFFbEIsTUFBTTVFLFNBQWtEO1FBQ3REZ0YsT0FBT0E7UUFDUHRCLFNBQVNBO1FBQ1RSLE1BQU07UUFDTjBELE1BQU07O0lBR1IsTUFBTXRFLE9BQU8sSUFBSTRCLFFBQVcsQ0FBQ2QsU0FBU0c7UUFDcEMsSUFBSTZCO1FBQ0o7WUFDRUEsU0FBUyxJQUFJdUIsa0JBQ1hqRCxTQUNBO2dCQUNFTjtnQkFDQUc7a0JBRUM5QztZQUdMVCxPQUFPcUMsTUFBTThDLGFBQWdCQyxRQUFRMUIsU0FBUzJCLE1BQU1MLE9BQU8vSjtBQUM1RCxVQUFDLE9BQU9rRjtZQUNQLE9BQU9vRCxPQUFPLElBQUlsRSxNQUFNLHlCQUF5QnFFLFlBQVl2RDtBQUM5RDtRQUVESCxPQUFPcUMsSUFBSTlELE9BQU9zSSxZQUFZO1FBRTlCN0csT0FBT3FDLElBQUk5RCxPQUFPdUksR0FBRyxRQUFTbEU7WUFDNUJBLFFBQVFBLE1BQU03QztZQUNkQyxPQUFPa0QsS0FBS3NELEtBQUs1RDtZQUNqQndDLE9BQU83QyxLQUFLSzs7UUFHZDVDLE9BQU9xQyxJQUFJMEUsT0FBT0QsR0FBRyxRQUFTdkU7WUFDNUJBLE9BQU9BLEtBQUt4QztZQUNaQyxPQUFPNEcsS0FBS0osS0FBS2pFO1lBQ2pCNkMsT0FBT2hHLE1BQU1tRDs7UUFHZnZDLE9BQU9xQyxJQUFJNkMsS0FBSyxTQUFVbkM7WUFDeEJxQyxPQUFPcEMsS0FBS0QsSUFBSXBILFNBQVNxRSxPQUFPNEc7O1FBR2xDNUcsT0FBT3FDLElBQUk2QyxLQUFLLFFBQVEsQ0FBQ2pDLE9BQWU7WUFDdEMsSUFBSStCLE1BQU1ILE9BQU9DLFdBQVc3QixTQUFTLE1BQU1BLE9BQU9kO1lBQ2xEaUQsT0FBT3BDLEtBQUtDLE1BQU1BLFNBQVMsSUFBSWpELE9BQU9rRCxPQUFPbEQsT0FBTzRHOzs7SUFJeERwRixPQUFPb0UsT0FBTzVGLFFBQVE7UUFDcEJnSCxTQUFTMUU7UUFDVG1FLE1BQU1RLE1BQVVDO1lBQ2QsTUFBTTdELElBQUlwSSxPQUFPRSxJQUFJO1lBQ3JCO2dCQUNFa0ksRUFBRTdILFFBQVEsMkJBQTJCa0k7Z0JBQ3JDLE1BQU0xRCxlQUFrQnNDO2dCQUN4QmUsRUFBRTdILFFBQVEsb0JBQW9CMEwsR0FBRzdMLFNBQVMyRTtnQkFDMUMsT0FBT2tILEdBQUdsSDtBQUNYLGNBQUMsT0FBT0c7Z0JBQ1BrRCxFQUFFakUsTUFBTSxnQ0FBZ0NlO2dCQUN4QyxNQUFNQTtBQUNQOzs7SUFJTCxPQUFPSDtBQUNUOztBQ25UQSxNQUFNL0UsU0FBU0MsUUFBUUMsSUFBSTs7QUFFM0IsU0FBU2dNLFlBQ1B2SCxPQUNBd0gsUUFDQUMsUUFBZ0IsS0FDaEJ4RDtJQUVBckMsT0FBTzhGLFFBQVFGLFFBQVFHLFFBQVEsRUFBRTNGLEtBQUs0RjtRQUNwQyxNQUFNQyxTQUFTLElBQUlDLE9BQU9DLGFBQWEvRixNQUFNeUY7UUFDN0N6SCxRQUFRQSxNQUFNZ0ksUUFBUUgsUUFBU0k7WUFDN0IsS0FBS2hFLFVBQVVBLE9BQU9nRSxTQUFTO2dCQUM3QixPQUFPTDtBQUNSO1lBQ0QsT0FBT0E7OztJQUdYLE9BQU81SDtBQUNUOztTQW9DZ0JrSSxVQUNkQyxNQUNBWCxRQUNBdkQ7SUFFQSxNQUFNakYsTUFBTTNELE9BQU9FLElBQUkyTTtJQUN2QixLQUFLRSxHQUFHQyxXQUFXRixPQUNqQixNQUFNLElBQUkxSSxNQUFNLDJCQUEyQjBJO0lBQzdDLElBQUlHLFVBQVVDLFNBQVNKO0lBRXZCbkosSUFBSXBELFFBQVEsa0JBQWtCdU07SUFDOUJuSixJQUFJaUMsTUFBTSxlQUFlcEQsS0FBS0MsVUFBVTBKO0lBQ3hDO1FBQ0VjLFVBQVVmLFlBQVllLFNBQVNkLFFBQVEsS0FBS3ZEO0FBQzdDLE1BQUMsT0FBT3pFO1FBQ1AsTUFBTSxJQUFJQyxNQUFNLHdCQUF3QkQ7QUFDekM7SUFDRGdKLFVBQVVMLE1BQU1HO0FBQ2xCOztBQWFNLFNBQVVDLFNBQVNKO0lBQ3ZCLE1BQU1uSixNQUFNM0QsT0FBT0UsSUFBSWdOO0lBQ3ZCO1FBQ0V2SixJQUFJcEQsUUFBUSxpQkFBaUJ1TTtRQUM3QixPQUFPQyxHQUFHSyxhQUFhTixNQUFNO0FBQzlCLE1BQUMsT0FBTzNJO1FBQ1BSLElBQUlwRCxRQUFRLHVCQUF1QnVNLFVBQVUzSTtRQUM3QyxNQUFNLElBQUlDLE1BQU0sdUJBQXVCMEksVUFBVTNJO0FBQ2xEO0FBQ0g7O0FBY2dCLFNBQUFnSixVQUFVTCxNQUFjeEY7SUFDdEMsTUFBTTNELE1BQU0zRCxPQUFPRSxJQUFJaU47SUFDdkI7UUFDRXhKLElBQUlwRCxRQUFRLGlCQUFpQnVNLGFBQWF4RixLQUFLaUI7UUFDL0N3RSxHQUFHTSxjQUFjUCxNQUFNeEYsTUFBTTtBQUM5QixNQUFDLE9BQU9uRDtRQUNQUixJQUFJcEQsUUFBUSx1QkFBdUJ1TSxVQUFVM0k7UUFDN0MsTUFBTSxJQUFJQyxNQUFNLHVCQUF1QjBJLFVBQVUzSTtBQUNsRDtBQUNIOztBQWNnQixTQUFBbUosWUFDZHpFLEdBQ0FEO0lBRUEsTUFBTWpGLE1BQU0zRCxPQUFPRSxJQUFJb047SUFDdkIsTUFBTUMsUUFBa0I7SUFFeEI7UUFDRTVKLElBQUlwRCxRQUFRLDhCQUE4QnNJO1FBQzFDLE1BQU13RCxVQUFVVSxHQUFHUyxZQUFZM0U7UUFFL0J3RCxRQUFRQyxRQUFTbUI7WUFDZixNQUFNQyxXQUFXWixLQUFLN0ksS0FBSzRFLEdBQUc0RTtZQUM5QixNQUFNRSxPQUFPWixHQUFHYSxTQUFTRjtZQUV6QixJQUFJQyxLQUFLRSxVQUFVO2dCQUNqQk4sTUFBTWhDLEtBQUttQztBQUNaLG1CQUFNLElBQUlDLEtBQUtHLGVBQWU7Z0JBQzdCUCxNQUFNaEMsUUFBUStCLFlBQVlJO0FBQzNCOztRQUVILEtBQUs5RSxRQUFRLE9BQU8yRTtRQUNwQixPQUFPQSxNQUFNM0UsT0FBT0E7QUFDckIsTUFBQyxPQUFPekU7UUFDUFIsSUFBSXBELFFBQVEsZ0NBQWdDc0ksT0FBTzFFO1FBQ25ELE1BQU0sSUFBSUMsTUFBTSxnQ0FBZ0N5RSxPQUFPMUU7QUFDeEQ7QUFDSDs7QUFjTzZILGVBQWUrQixXQUFXQyxRQUFnQkM7SUFDL0MsTUFBTXRLLE1BQU0zRCxPQUFPRSxJQUFJNk47SUFDdkIsSUFBSUcsa0JBQWtCQztJQUV0QjtRQUNFRCxtQkFBbUJuQixHQUFHYSxTQUFTSTtBQUNoQyxNQUFDLE9BQU83SjtRQUNQUixJQUFJcEQsUUFBUSxnQkFBZ0J5TiwyQkFBMkI3SjtRQUN2RCxNQUFNLElBQUlDLE1BQU0sZ0JBQWdCNEosMkJBQTJCN0o7QUFDNUQ7SUFFRDtRQUNFZ0ssaUJBQWlCcEIsR0FBR2EsU0FBU0s7QUFFOUIsTUFBQyxPQUFPL0ksSUFFUjtJQUNELElBQUlpSixnQkFBZ0I7UUFDbEJ4SyxJQUFJcEQsUUFBUSxxQkFBcUIwTjtRQUNqQyxNQUFNLElBQUk3SixNQUFNLHFCQUFxQjZKO0FBQ3RDO0lBRUQ7UUFDRXRLLElBQUlwRCxRQUNGLFlBQVkyTixpQkFBaUJMLFdBQVcsU0FBUyxnQkFBZ0JHLGVBQWVDO1FBRWxGbEIsR0FBR3FCLFdBQVdKLFFBQVFDO1FBQ3RCdEssSUFBSXBELFFBQVEsNEJBQTRCME47QUFDekMsTUFBQyxPQUFPOUo7UUFDUFIsSUFBSXBELFFBQ0Ysa0JBQWtCMk4saUJBQWlCTCxXQUFXLFNBQVMsZ0JBQWdCRyxlQUFlQyxVQUFVOUo7UUFFbEcsTUFBTSxJQUFJQyxNQUNSLGtCQUFrQjhKLGlCQUFpQkwsV0FBVyxTQUFTLGdCQUFnQkcsZUFBZUMsVUFBVTlKO0FBRW5HO0FBQ0g7O0FBY2dCLFNBQUFrSyxTQUFTTCxRQUFnQkM7SUFDdkMsTUFBTXRLLE1BQU0zRCxPQUFPRSxJQUFJbU87SUFDdkIsSUFBSUgsa0JBQWtCQztJQUN0QjtRQUNFRCxtQkFBbUJuQixHQUFHYSxTQUFTSTtBQUNoQyxNQUFDLE9BQU83SjtRQUNQUixJQUFJcEQsUUFBUSxnQkFBZ0J5TiwyQkFBMkI3SjtRQUN2RCxNQUFNLElBQUlDLE1BQU0sZ0JBQWdCNEosMkJBQTJCN0o7QUFDNUQ7SUFDRDtRQUVFZ0ssaUJBQWlCcEIsR0FBR2EsU0FBU0s7QUFFOUIsTUFBQyxPQUFPOUo7UUFDUCxJQUFJK0osaUJBQWlCSixlQUFlO1lBQ2xDbkssSUFBSXBELFFBQVEsY0FBYzBOO1lBQzFCbEIsR0FBR3VCLFVBQVVMLE1BQU07Z0JBQUVNLFdBQVc7O0FBQ2pDO0FBQ0Y7SUFFRDtRQUNFNUssSUFBSXBELFFBQ0YsV0FBVzJOLGlCQUFpQkwsV0FBVyxTQUFTLGdCQUFnQkcsZUFBZUM7UUFFakZsQixHQUFHeUIsT0FBT1IsUUFBUUMsTUFBTTtZQUFFTSxXQUFXOztBQUN0QyxNQUFDLE9BQU9wSztRQUNQUixJQUFJcEQsUUFDRixpQkFBaUIyTixpQkFBaUJMLFdBQVcsU0FBUyxnQkFBZ0JHLGVBQWVDLFNBQVM5SjtRQUVoRyxNQUFNLElBQUlDLE1BQ1IsaUJBQWlCOEosaUJBQWlCTCxXQUFXLFNBQVMsZ0JBQWdCRyxlQUFlQyxTQUFTOUo7QUFFakc7QUFDSDs7QUFhTSxTQUFVc0ssV0FBVzVGO0lBQ3pCLE1BQU1sRixNQUFNM0QsT0FBT0UsSUFBSXVPO0lBQ3ZCO1FBQ0UsTUFBTUMsYUFBYTNCLEdBQUdhLFNBQVMvRTtRQUMvQixJQUFJNkYsV0FBV2IsVUFBVTtZQUN2QmxLLElBQUlwRCxRQUFRLGtCQUFrQnNJO1lBQzlCa0UsR0FBRzRCLE9BQU85RixHQUFHO2dCQUFFMEYsV0FBVztnQkFBTUssT0FBTzs7QUFDeEMsZUFBTSxJQUFJRixXQUFXWixlQUNwQmYsR0FBRzRCLE9BQU85RixHQUFHO1lBQUUwRixXQUFXO1lBQU1LLE9BQU87O0FBQzFDLE1BQUMsT0FBT3pLO1FBQ1BSLElBQUlwRCxRQUFRLG1CQUFtQnNJLE9BQU8xRTtRQUN0QyxNQUFNLElBQUlDLE1BQU0sbUJBQW1CeUUsT0FBTzFFO0FBQzNDO0FBQ0g7O0FBZ0NNLFNBQVUwSyxXQUNkaEcsSUFBWXBELFFBQVFnRixPQUNwQnFFO0lBRUEsSUFBSUM7SUFDSjtRQUNFQSxNQUFNdk0sS0FBS21HLE1BQU11RSxTQUFTSixLQUFLN0ksS0FBSzRFLEdBQUc7QUFDeEMsTUFBQyxPQUFPMUU7UUFDUCxNQUFNLElBQUlDLE1BQU0sMkNBQTJDRDtBQUM1RDtJQUVELElBQUkySyxVQUFVO1FBQ1osTUFBTUEsWUFBWUMsTUFDaEIsTUFBTSxJQUFJM0ssTUFBTSxhQUFhMEs7UUFDL0IsT0FBT0MsSUFBSUQ7QUFDWjtJQUNELE9BQU9DO0FBQ1Q7O0FBZU0sU0FBVUMsb0JBQ2RDLE1BQ0F4TyxPQUNBb0ksSUFBWXBELFFBQVFnRjtJQUVwQixNQUFNc0UsTUFBTUYsV0FBV2hHO0lBQ3ZCa0csSUFBSUUsUUFBUXhPO0lBQ1owTSxVQUFVTCxLQUFLN0ksS0FBSzRFLEdBQUcsaUJBQWlCckcsS0FBS0MsVUFBVXNNLEtBQUssTUFBTTtBQUNwRTs7QUFVTSxTQUFVRyxrQkFBa0JyRyxJQUFJcEQsUUFBUWdGO0lBQzVDLE9BQU9vRSxXQUFXaEcsR0FBRztBQUN2Qjs7QUF1Qk9tRCxlQUFlbUQsZ0JBQ3BCckMsT0FBZXJILFFBQVFnRjtJQUV2QixJQUFJc0U7SUFFSjtRQUNFQSxNQUFNdk0sS0FBS21HLFlBQVk4QyxXQUFXLGlCQUFpQjtZQUFFaEIsS0FBS3FDO1dBQVFmO0FBQ25FLE1BQUMsT0FBTzdHO1FBQ1AsTUFBTSxJQUFJZCxNQUFNLG9DQUFvQ2M7QUFDckQ7SUFHRCxNQUFNa0ssU0FBUyxDQUFDM0IsT0FBMEI0QixXQUFtQjtRQUMzRGpQLE1BQU1xTixNQUFNO1FBQ1p6SCxTQUFVeUgsTUFBTSxHQUFXekg7O0lBRzdCLE9BQU87UUFDTHNKLE1BQU0vSSxPQUFPOEYsUUFBUTBDLElBQUlRLGdCQUFnQixJQUFJeEwsSUFBSXFMO1FBQ2pESSxLQUFLakosT0FBTzhGLFFBQVEwQyxJQUFJVSxtQkFBbUIsSUFBSTFMLElBQUlxTDtRQUNuRE0sTUFBTW5KLE9BQU84RixRQUFRMEMsSUFBSVksb0JBQW9CLElBQUk1TCxJQUFJcUw7O0FBRXpEOztBQVlPcEQsZUFBZTREO0lBQ3BCLE1BQU1qTSxNQUFNM0QsT0FBT0UsSUFBSTBQO0lBQ3ZCak0sSUFBSXdCLEtBQUs7VUFDSHNHLFdBQVcsNEJBQTRCTTtJQUM3Q3BJLElBQUl3QixLQUFLO1VBQ0hzRyxXQUFXLDBCQUEwQk07QUFDN0M7O0FBY09DLGVBQWU2RCxzQkFDcEJDLE1BQ0FQO0lBRUEsS0FBS0EsY0FBYztRQUNqQixNQUFNUSxVQUF5Qlo7UUFDL0JJLGVBQWU7WUFDYkQsTUFBTVMsRUFBRVQsTUFBTXZMLElBQUs4RSxLQUFNQSxFQUFFekksU0FBUztZQUNwQ29QLEtBQUtPLEVBQUVQLEtBQUt6TCxJQUFLZ00sS0FBTUEsRUFBRTNQLFNBQVM7WUFDbENzUCxNQUFNSyxFQUFFTCxNQUFNM0wsSUFBSzhFLEtBQU1BLEVBQUV6SSxTQUFTOztBQUV2QztJQUNELE9BQU1rUCxNQUFFQSxNQUFJRSxLQUFFQSxLQUFHRSxNQUFFQSxRQUFTSDtJQUM1QixNQUFNUyxZQUFZcE0sTUFBTXFNLEtBQ3RCLElBQUlDLElBQUksS0FBS1osUUFBUSxPQUFTRSxPQUFPLE9BQVNFLFFBQVE7SUFFeERJLGNBQWNBLFNBQVMsV0FBVyxFQUFDQSxTQUFRQTtJQUMzQyxNQUFNSyxZQUFZTCxLQUFLbEgsT0FBUW1ILE1BQU9DLFVBQVUvRSxTQUFTOEU7SUFFekQsSUFBSUksVUFBVTVILGNBQWM2SCxvQkFBb0I7UUFBRVosS0FBS1c7O0lBQ3ZEWixhQUFhQyxNQUFNRCxhQUFhQyxPQUFPO0lBQ3ZDRCxhQUFhQyxJQUFJakUsUUFBUTRFO0lBQ3pCLE9BQU9aO0FBQ1Q7O0FBWU92RCxlQUFlcUU7SUFDcEIsTUFBTTFNLE1BQU0zRCxPQUFPRSxJQUFJbVE7SUFDdkIsTUFBTUMsZ0JBQWdCN0UsV0FBVyx3QkFBd0JNO0lBQ3pELE1BQU13RSxpQkFBaUI5RSxXQUFXLHlCQUF5Qk07SUFDM0RwSSxJQUFJcEQsUUFBUSxrQkFBa0IrUCxXQUFXQztVQUNuQzlFLFdBQVcsK0NBQStDTTtVQUMxRE4sV0FBVyxnQ0FBZ0NNO0lBQ2pEcEksSUFBSXdCLEtBQUs7VUFDSHNHLFdBQVcsYUFBYU07VUFDeEJOLFdBQVcsOENBQThDTTtVQUN6RE4sV0FBVyxZQUFZTTtVQUN2Qk4sV0FBVywwQkFBMEI4RSxhQUFheEU7VUFDbEROLFdBQVcseUJBQXlCNkUsWUFBWXZFO0lBQ3REcEksSUFBSXBELFFBQVEsdUJBQXVCK1AsV0FBV0M7QUFDaEQ7O0FBZ0JPdkUsZUFBZW9FLG9CQUFvQmI7SUFLeEMsTUFBTTVMLE1BQU0zRCxPQUFPRSxJQUFJa1E7SUFDdkIsTUFBTWQsT0FBT0MsYUFBYUQsUUFBUTtJQUNsQyxNQUFNRSxNQUFNRCxhQUFhQyxPQUFPO0lBQ2hDLE1BQU1FLE9BQU9ILGFBQWFHLFFBQVE7SUFDbEMsSUFBSUosS0FBSy9HLFFBQVE7UUFDZjVFLElBQUl3QixLQUFLLDJCQUEyQm1LLEtBQUtyTCxLQUFLO2NBQ3hDd0gsV0FBVyxlQUFlNkQsS0FBS3JMLEtBQUssUUFBUTtZQUFFd0csS0FBS2hGLFFBQVFnRjtXQUM5RHNCO0FBQ0o7SUFDRCxJQUFJeUQsSUFBSWpILFFBQVE7UUFDZDVFLElBQUl3QixLQUFLLDhCQUE4QnFLLElBQUl2TCxLQUFLO2NBQzFDd0gsV0FBVywwQkFBMEIrRCxJQUFJdkwsS0FBSyxRQUFRO1lBQzFEd0csS0FBS2hGLFFBQVFnRjtXQUNac0I7QUFDSjtJQUNELElBQUkyRCxLQUFLbkgsUUFBUTtRQUNmNUUsSUFBSXdCLEtBQUssK0JBQStCdUssS0FBS3pMLEtBQUs7Y0FDNUN3SCxXQUFXLDJCQUEyQmlFLEtBQUt6TCxLQUFLLFFBQVE7WUFDNUR3RyxLQUFLaEYsUUFBUWdGO1dBQ1pzQjtBQUNKO0FBQ0g7O0FBY09DLGVBQWV3RSxnQkFDcEJDO0lBR0EsT0FBT0EsY0FBY3RILEtBQU00QixLQUFZQSxFQUFFaEYsV0FBV2dGO0FBQ3REOztBQUdPaUIsZUFBZTBFLGtCQUFrQkM7SUFDdEMsTUFBTWhOLE1BQU0zRCxPQUFPRSxJQUFJd1E7SUFDdkI7UUFDRSxNQUFNckUsVUFBVVUsR0FBR1MsWUFBWW1EO1FBQy9CLE1BQU1DLGFBQWF2RSxRQUNoQnRJLElBQUttQixLQUFNNEgsS0FBSzdJLEtBQUswTSxLQUFLekwsSUFDMUIwRCxPQUFRQztZQUNQO2dCQUNFLE1BQU1nSSxJQUFJOUQsR0FBR2EsU0FBUy9FO2dCQUN0QixPQUNFZ0ksRUFBRWhELGFBQ0RoRixFQUFFaUksU0FBUyxVQUFVakksRUFBRWlJLFNBQVMsV0FBV2pJLEVBQUVpSSxTQUFTO0FBRTFELGNBQUM7Z0JBQ0EsT0FBTztBQUNSOztRQUdMLElBQUlGLFdBQVdySSxXQUFXLEdBQUc7WUFDM0IsTUFBTSxJQUFJbkUsTUFBTSxrQ0FBa0N1TTtBQUNuRDtRQUdELElBQUlJLFdBQVdILFdBQVc7UUFDMUIsSUFBSUksZUFBZWpFLEdBQUdhLFNBQVNtRCxVQUFVRTtRQUN6QyxLQUFLLE1BQU1DLEtBQUtOLFdBQVdqTCxNQUFNLElBQUk7WUFDbkMsTUFBTWtMLElBQUk5RCxHQUFHYSxTQUFTc0QsR0FBR0Q7WUFDekIsSUFBSUosSUFBSUcsY0FBYztnQkFDcEJELFdBQVdHO2dCQUNYRixlQUFlSDtBQUNoQjtBQUNGO1FBRURsTixJQUFJcEQsUUFDRiw2QkFBNkJ3USxhQUFhQztRQUc1QyxNQUFNRyxTQUFTcEUsR0FBR0ssYUFBYTJEO1FBQy9CLE1BQU1LLEtBQUtDLEtBQUtDLFNBQVNIO1FBQ3pCLE1BQU1JLFNBQVNDLFFBQVFKLEdBQUc3SSxTQUFTLE1BQU1rSixRQUFRO1FBQ2pEOU4sSUFBSXBELFFBQVEsaUJBQWlCNlEsR0FBRzdJLGlCQUFpQmdKO1FBQ2pELE9BQU9BO0FBQ1IsTUFBQyxPQUFPck07UUFDUHZCLElBQUlwRCxRQUFRLHNDQUFzQ29RLFFBQVF6TDtRQUMxRCxNQUFNQTtBQUNQO0FBQ0g7O0FBR00sU0FBVXdNLFdBQ2RDLFdBQW1CbE0sUUFBUWdGLE9BQzNCN0I7SUFFQSxNQUFNakYsTUFBTTNELE9BQU9FLElBQUl3UjtJQUN2QjtRQUNFLEtBQUszRSxHQUFHQyxXQUFXMkUsV0FBVyxPQUFPO1FBQ3JDLE1BQU10RixVQUFVVSxHQUFHUyxZQUFZbUUsVUFBVTtZQUFFQyxlQUFlOztRQUMxRCxNQUFNQyxRQUFReEYsUUFDWHpELE9BQVFtSCxLQUFPbkgsU0FBU0EsT0FBT21ILEVBQUUzUCxNQUFNMlAsS0FBSyxNQUM1Q2hNLElBQUtnTSxLQUFNQSxFQUFFM1A7UUFDaEIsT0FBT3lSO0FBQ1IsTUFBQyxPQUFPM007UUFDUHZCLElBQUlwRCxRQUFRLHlCQUF5Qm9SLGFBQWF6TTtRQUNsRCxPQUFPO0FBQ1I7QUFDSDs7QUFHZ0IsU0FBQTRNLHdCQUNkSCxXQUFtQjdFLEtBQUs3SSxLQUFLd0IsUUFBUWdGLE9BQU87SUFFNUMsTUFBTTlHLE1BQU0zRCxPQUFPRSxJQUFJNFI7SUFDdkI7UUFDRSxLQUFLL0UsR0FBR0MsV0FBVzJFLFdBQVcsT0FBTztRQUNyQyxNQUFNdEYsVUFBVVUsR0FBR1MsWUFBWW1FLFVBQVU7WUFBRUMsZUFBZTs7UUFDMUQsTUFBTUMsUUFBa0I7UUFFeEIsS0FBSyxNQUFNM00sS0FBS21ILFNBQVM7WUFDdkI7Z0JBQ0UsS0FBS25ILEVBQUU0SSxlQUFlO2dCQUV0QixJQUFJNUksRUFBRTlFLEtBQUsyUixXQUFXLE1BQU07Z0JBQzVCLElBQUk3TSxFQUFFOUUsS0FBSzJSLFdBQVcsTUFBTTtvQkFFMUIsTUFBTUMsWUFBWWxGLEtBQUs3SSxLQUFLME4sVUFBVXpNLEVBQUU5RTtvQkFDeEM7d0JBQ0UsTUFBTTZSLFNBQVNsRixHQUFHUyxZQUFZd0UsV0FBVzs0QkFBRUosZUFBZTs7d0JBQzFELEtBQUssTUFBTWYsS0FBS29CLFFBQVE7NEJBQ3RCLElBQUlwQixFQUFFL0Msa0JBQWtCK0MsRUFBRXpRLEtBQUsyUixXQUFXLE1BQU07Z0NBQzlDRixNQUFNdEcsS0FBSyxHQUFHckcsRUFBRTlFLFFBQVF5USxFQUFFelE7QUFDM0I7QUFDRjtBQUNGLHNCQUFDLE9BQU8wSDt3QkFFUG5FLElBQUlwRCxRQUFRLHdCQUF3QnlSLGNBQWNsSztBQUNuRDtBQUNGLHVCQUFNO29CQUNMK0osTUFBTXRHLEtBQUtyRyxFQUFFOUU7QUFDZDtBQUNGLGNBQUMsT0FBTzBIO2dCQUNQbkUsSUFBSXBELFFBQVEsa0JBQWtCMkUsRUFBRTlFLHNCQUFzQjBIO0FBQ3ZEO0FBQ0Y7UUFDRCxPQUFPK0o7QUFDUixNQUFDLE9BQU8zTTtRQUNQdkIsSUFBSXBELFFBQVEsMkNBQTJDb1IsYUFBYXpNO1FBQ3BFLE9BQU87QUFDUjtBQUNIOztBQzlvQk8sTUFBTWdOLFVBQVUsRUFDckI7SUFDRUMsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFDRTtJQUNGQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFDRTtJQUNGQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFDRTtJQUNGQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFBUTtJQUNSQyxNQUFNO0dBRVI7SUFDRUQsUUFB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
|