@decaf-ts/utils 0.10.3 → 0.11.1-0.experimental.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/utils.cjs +2561 -2
- package/dist/utils.js +2602 -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 +74 -14
- package/lib/cli/commands/build-scripts.d.ts +62 -2
- 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.d.ts +62 -2
- package/lib/esm/cli/commands/build-scripts.js +74 -14
- 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.d.ts +106 -0
- package/lib/esm/tests/Consumer.js +79 -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.d.ts +3 -1
- package/lib/esm/tests/index.js +4 -2
- package/lib/esm/tests/jestPerformanceRunner.d.ts +7 -0
- package/lib/esm/tests/jestPerformanceRunner.js +15 -0
- package/lib/esm/tests/utils.d.ts +5 -0
- package/lib/esm/tests/utils.js +33 -0
- package/lib/esm/utils/constants.js +1 -1
- package/lib/esm/utils/fs.d.ts +1 -1
- package/lib/esm/utils/fs.js +76 -29
- package/lib/esm/utils/http.js +1 -1
- package/lib/esm/utils/index.d.ts +1 -0
- package/lib/esm/utils/index.js +2 -1
- package/lib/esm/utils/md.js +1 -1
- package/lib/esm/utils/performanceRunner.d.ts +126 -0
- package/lib/esm/utils/performanceRunner.js +344 -0
- 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 +79 -1
- package/lib/tests/Consumer.d.ts +106 -0
- 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 +4 -2
- package/lib/tests/index.d.ts +3 -1
- package/lib/tests/jestPerformanceRunner.cjs +19 -0
- package/lib/tests/jestPerformanceRunner.d.ts +7 -0
- package/lib/tests/utils.cjs +36 -0
- package/lib/tests/utils.d.ts +5 -0
- package/lib/utils/constants.cjs +1 -1
- package/lib/utils/fs.cjs +76 -29
- package/lib/utils/fs.d.ts +1 -1
- package/lib/utils/http.cjs +1 -1
- package/lib/utils/index.cjs +2 -1
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/md.cjs +1 -1
- package/lib/utils/performanceRunner.cjs +384 -0
- package/lib/utils/performanceRunner.d.ts +126 -0
- 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 +17 -10
- package/workdocs/assets/slogans.json +802 -0
- 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/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/tests.d.ts +0 -1
- package/lib/esm/utils/tests.js +0 -2
- package/lib/esm/utils/tests.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/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/tests.cjs +0 -18
- package/lib/utils/tests.d.ts +0 -1
- package/lib/utils/tests.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.cjs
CHANGED
|
@@ -1,2 +1,2561 @@
|
|
|
1
|
-
var e,t;e=this,t=function(e,t,o,a,s,r,n,i,l,c,g,d,f,u,h,m,p){"use strict";function S(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function y(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach(o=>{if("default"!==o){var a=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(t,o,a.get?a:{enumerable:!0,get:()=>e[o]})}}),t.default=e,Object.freeze(t)}var T=S(t),b=S(s),v=S(r),C=S(l),w=S(c),D=S(d),k=S(f),$=S(h),E=y(p);class I{static{this.logger=a.Logging.for(I)}constructor(e){this.type="text",this.name=e}setType(e){return I.logger.verbose("Setting type to: "+e),this.type=e,this}setMessage(e){return I.logger.verbose("Setting message to: "+e),this.message=e,this}setInitial(e){return I.logger.verbose("Setting initial value to: "+e),this.initial=e,this}setStyle(e){return I.logger.verbose("Setting style to: "+e),this.style=e,this}setFormat(e){return I.logger.verbose("Setting format function"),this.format=e,this}setValidate(e){return I.logger.verbose("Setting validate function"),this.validate=e,this}setOnState(e){return I.logger.verbose("Setting onState callback"),this.onState=e,this}setMin(e){return I.logger.verbose("Setting min value to: "+e),this.min=e,this}setMax(e){return I.logger.verbose("Setting max value to: "+e),this.max=e,this}setFloat(e){return I.logger.verbose("Setting float to: "+e),this.float=e,this}setRound(e){return I.logger.verbose("Setting round to: "+e),this.round=e,this}setInstructions(e){return I.logger.verbose("Setting instructions to: "+e),this.instructions=e,this}setIncrement(e){return I.logger.verbose("Setting increment to: "+e),this.increment=e,this}setSeparator(e){return I.logger.verbose("Setting separator to: "+e),this.separator=e,this}setActive(e){return I.logger.verbose("Setting active style to: "+e),this.active=e,this}setInactive(e){return I.logger.verbose("Setting inactive style to: "+e),this.inactive=e,this}setChoices(e){return I.logger.verbose("Setting choices: "+JSON.stringify(e)),this.choices=e,this}setHint(e){return I.logger.verbose("Setting hint to: "+e),this.hint=e,this}setWarn(e){return I.logger.verbose("Setting warn to: "+e),this.warn=e,this}setSuggest(e){return I.logger.verbose("Setting suggest function"),this.suggest=e,this}setLimit(e){return I.logger.verbose("Setting limit to: "+e),this.limit=e,this}setMask(e){return I.logger.verbose("Setting mask to: "+e),this.mask=e,this}setStdout(e){return I.logger.verbose("Setting stdout stream"),this.stdout=e,this}setStdin(e){return this.stdin=e,this}async ask(){return(await I.ask(this))[this.name]}static async ask(e){const t=I.logger.for(this.ask);let o;Array.isArray(e)||(e=[e]);try{t.verbose("Asking questions: "+e.map(e=>e.name).join(", ")),o=await T.default(e),t.verbose("Received answers: "+JSON.stringify(o,null,2))}catch(e){throw Error("Error while getting input: "+e)}return o}static async askNumber(e,t,o,a,s){I.logger.for(this.askNumber).verbose(`Asking number input: undefined, question: ${t}, min: ${o}, max: ${a}, initial: ${s}`);const r=new I(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){I.logger.for(this.askText).verbose(`Asking text input: undefined, question: ${t}, mask: ${o}, initial: ${a}`);const s=new I(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){I.logger.for(this.askConfirmation).verbose(`Asking confirmation input: undefined, question: ${t}, initial: ${o}`);const a=new I(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=I.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 I.ask(e))[e.name],t(r)?(n=await I.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){I.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 I(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){I.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 l=new I(e).setMessage(t).setType("number");return"number"==typeof a&&l.setMin(a),"number"==typeof s&&l.setMax(s),"number"==typeof r&&l.setInitial(r),await this.insist(l,o,n,i)}static parseArgs(e){const t=I.logger.for(this.parseArgs),a={args:process.argv.slice(2),options:e};t.debug("Parsing arguments: "+JSON.stringify(a,null,2));try{return o.parseArgs(a)}catch(o){throw t.debug(`Error while parsing arguments:\n${JSON.stringify(a,null,2)}\n | options\n${JSON.stringify(e,null,2)}\n | ${o}`),Error("Error while parsing arguments: "+o)}}}const F={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}},A=Object.keys(F).reduce((e,t)=>(e[t]=F[t].default,e),{}),N="utf-8",j=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z])))/g;var x;e.SemVersion=void 0,(x=e.SemVersion||(e.SemVersion={})).PATCH="patch",x.MINOR="minor",x.MAJOR="major";const B="-no-ci";var M;e.Tokens=void 0,(M=e.Tokens||(e.Tokens={})).GIT=".token",M.NPM=".npmtoken",M.DOCKER=".dockertoken",M.CONFLUENCE=".confluence-token";const P="Aborted";class L{constructor(e,t,...o){this.cmd=e,this.lock=t,this.logger=a.Logging.for(this.cmd)}log(e,t){t=Buffer.isBuffer(t)?t.toString(N):t;const o="stderr"===e?i.style(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?i.style(e.toString()).green.text:i.style(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: ${i.style(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: ${i.style(e.message).red}`),this.lock.reject(e)}}function O(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 U(e,t,o,a,s){function r(t,a){const[r,i]=e.parseCommand(t);s.info("Running command: "+r),s.debug("with args: "+i.join(" "));const l=n.spawn(r,i,{...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 : "+l.pid),l}const i=t.match(/[<>$#]/g);if(i)throw Error(`Invalid command: ${t}. contains invalid characters: ${i}`);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]=O(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 R(e,t={},o=L,...s){const r=a.Logging.for(R),n=new AbortController,i={abort:n,command:e,logs:[],errs:[]},l=new Promise((a,l)=>{let c;try{c=new o(e,{resolve:a,reject:l},...s),i.cmd=U(c,e,t,n,r)}catch(t){return l(Error(`Error running command ${e}: ${t}`))}i.cmd.stdout.setEncoding("utf8"),i.cmd.stdout.on("data",e=>{e=e.toString(),i.logs.push(e),c.data(e)}),i.cmd.stderr.on("data",e=>{e=e.toString(),i.errs.push(e),c.error(e)}),i.cmd.once("error",e=>{c.exit(e.message,i.errs)}),i.cmd.once("exit",(e=0)=>{n.signal.aborted&&null===e&&(e=P),c.exit(e,0===e?i.logs:i.errs)})});return Object.assign(i,{promise:l,pipe:async t=>{const o=r.for("pipe");try{o.verbose(`Executing pipe function ${e}...`);const a=await l;return o.verbose(`Piping output to ${t.name}: ${a}`),t(a)}catch(e){throw o.error("Error piping command output: "+e),e}}}),i}const J=a.Logging.for("fs");function V(e,t,o){const s=J.for(V);if(!b.default.existsSync(e))throw Error(`File not found at path "${e}".`);let r=W(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.escapeRegExp(t),o);e=e.replace(n,e=>(!s||s(e),r))}),e))(r,t,"g",o)}catch(e){throw Error("Error patching file: "+e)}K(e,r)}function W(e){const t=J.for(W);try{return t.verbose(`Reading file "${e}"...`),b.default.readFileSync(e,"utf8")}catch(o){throw t.verbose(`Error reading file "${e}": ${o}`),Error(`Error reading file "${e}": ${o}`)}}function K(e,t){const o=J.for(K);try{o.verbose(`Writing file "${e} with ${t.length} bytes...`),b.default.writeFileSync(e,t,"utf8")}catch(t){throw o.verbose(`Error writing file "${e}": ${t}`),Error(`Error writing file "${e}": ${t}`)}}function q(e,t){const o=J.for(q),a=[];try{return o.verbose(`Retrieving all files from "${e}"...`),b.default.readdirSync(e).forEach(t=>{const o=v.default.join(e,t),s=b.default.statSync(o);s.isFile()?a.push(o):s.isDirectory()&&a.push(...q(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 _(e,t){const o=J.for(_);let a,s;try{a=b.default.statSync(e)}catch(t){throw o.verbose(`Source path "${e}" does not exist: ${t}`),Error(`Source path "${e}" does not exist: ${t}`)}try{s=b.default.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}...`),b.default.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 G(e,t){const o=J.for(G);let a,s;try{a=b.default.statSync(e)}catch(t){throw o.verbose(`Source path "${e}" does not exist: ${t}`),Error(`Source path "${e}" does not exist: ${t}`)}try{s=b.default.statSync(t)}catch(e){a.isDirectory()&&(o.verbose(`Dest path "${t}" does not exist. creating`),b.default.mkdirSync(t,{recursive:!0}))}try{o.verbose(`Copying ${a.isFile()?"file":"directory"} "${e}" to "${t}...`),b.default.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=J.for(X);try{const o=b.default.statSync(e);o.isFile()?(t.verbose(`Deleting file "${e}...`),b.default.rmSync(e,{recursive:!0,force:!0})):o.isDirectory()&&b.default.rmSync(e,{recursive:!0,force:!0})}catch(o){throw t.verbose(`Error Deleting "${e}": ${o}`),Error(`Error Deleting "${e}": ${o}`)}}function z(e=process.cwd(),t){let o;try{o=JSON.parse(W(v.default.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 H(e=process.cwd()){return z(e,"version")}async function Y(e=process.cwd()){let t;try{t=JSON.parse(await R("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 Z(e){const t=J.for(Z),o=e.prod||[],a=e.dev||[],s=e.peer||[];o.length&&(t.info(`Installing dependencies ${o.join(", ")}...`),await R("npm install "+o.join(" "),{cwd:process.cwd()}).promise),a.length&&(t.info(`Installing devDependencies ${a.join(", ")}...`),await R("npm install --save-dev "+a.join(" "),{cwd:process.cwd()}).promise),s.length&&(t.info(`Installing peerDependencies ${s.join(", ")}...`),await R("npm install --save-peer "+s.join(" "),{cwd:process.cwd()}).promise)}async function Q(e){const t=J.for(Q);try{const o=b.default.readdirSync(e).map(t=>v.default.join(e,t)).filter(e=>{try{return b.default.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=b.default.statSync(a).size;for(const e of o.slice(1)){const t=b.default.statSync(e).size;s>t&&(a=e,s=t)}t.verbose(`Selected smallest bundle: ${a} (${s} bytes)`);const r=b.default.readFileSync(a),n=C.default.gzipSync(r),i=Number((n.length/1024).toFixed(1));return t.verbose(`Gzipped size: ${n.length} bytes (${i} KB)`),i}catch(o){throw t.verbose(`Failed to compute gzipped size for ${e}: ${o}`),o}}function ee(e=v.default.join(process.cwd(),"node_modules")){const t=J.for(ee);try{if(!b.default.existsSync(e))return[];const o=b.default.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=v.default.join(e,s.name);try{const e=b.default.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 te=[{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"}],oe=["\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 ae(e){const t=se(),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())(i.style(t||"").raw(oe[o]).text)})}function se(e){try{return e=void 0===e?Math.floor(Math.random()*te.length):e,te[e].Slogan}catch(e){throw Error("Failed to retrieve slogans: "+e)}}class re extends a.LoggedClass{constructor(e,t={},o=[]){super(),this.name=e,this.inputs=t,this.requirements=o,re.log||Object.defineProperty(re,"log",{writable:!1,value:a.Logging.for(re.name)}),this.inputs=Object.assign({},F,t)}async checkRequirements(){const{prod:e,dev:t,peer:o}=await Y(),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=I.parseArgs(this.inputs),t=a.LoggedEnvironment.accumulate(A).accumulate(e.values),{version:o,help:s,banner:r}=t;if(o)return H();if(s)return this.help(e);let n;r&&ae(this.log.for(ae,{timestamp:!1,style:!1,context:!1,logLevel:!1}));try{n=await this.run(t)}catch(e){throw e}return n}}class ne{static{this.log=a.Logging.for(ne)}static async downloadFile(e){return new Promise((t,o)=>{!function e(a){a=encodeURI(a),w.default.get(a,s=>{if(301===s.statusCode||307===s.statusCode)return e(s.headers.location);if(200!==s.statusCode)return ne.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 ie(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 ce(){let e;try{e=z(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=v.default.resolve(__dirname,"../../..");try{e=z(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 ge="##VERSION##",de="##PACKAGE##",fe="##PACKAGE_SIZE##";var ue,he;(e=>{e.CJS="commonjs",e.ESM="es2022"})(ue||(ue={})),(e=>{e.BUILD="build",e.BUNDLE="bundle",e.ALL="all"})(he||(he={}));const me={prod:{type:"boolean",default:!1},dev:{type:"boolean",default:!1},buildMode:{type:"string",default:he.ALL},includes:{type:"string",default:""},externals:{type:"string",default:""},docs:{type:"boolean",default:!1},commands:{type:"boolean",default:!1},banner:{type:"boolean",default:!1}},pe=(e=".cjs")=>{const t=Se.log.for(pe),o=new Map;return a=>s=>{const r=v.default.dirname(s.fileName);function n(a){const s=JSON.stringify([r,a]),n=o.get(s);if(null!=n)return n;let i,l=a;try{l=v.default.resolve(r,l+".ts")}catch(e){throw Error(`Failed to resolve path ${a}: ${e}`)}try{i=b.default.statSync(l)}catch(e){try{t.verbose(`Testing existence of path ${l} as a folder defaulting to index file`),i=b.default.statSync(l.replace(/\.ts$/gm,""))}catch(t){throw Error(`Failed to resolve path ${a}: ${e}, ${t}`)}}if(i.isDirectory()&&(l=l.replace(/\.ts$/gm,"/index.ts")),v.default.isAbsolute(l)){const t=(/\.tsx?$/.exec(v.default.basename(l))||[])[0]||void 0;l="./"+v.default.relative(r,v.default.resolve(v.default.dirname(l),v.default.basename(l,t)+e))}return o.set(s,l),l}return E.visitNode(s,function e(t){if((e=>!(!E.isImportDeclaration(e)&&!E.isExportDeclaration(e)||void 0===e.moduleSpecifier||!E.isStringLiteral(e.moduleSpecifier)||!e.moduleSpecifier.text.startsWith("./")&&!e.moduleSpecifier.text.startsWith("../")||""!==v.default.extname(e.moduleSpecifier.text)))(t)){if(E.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(E.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 E.visitEachChild(t,e,a)})}};class Se extends re{constructor(){super("BuildScripts",Object.assign({},F,me)),this.replacements={};const e=z(),{name:t,version:o}=e;this.pkgName=t.includes("@")?t.split("/")[1]:t,this.pkgVersion=o,this.replacements[ge]=this.pkgVersion,this.replacements[de]=t}patchFiles(e){const t=this.log.for(this.patchFiles),{name:o,version:a}=z();t.info(`Patching ${o} ${a} module in ${e}...`),b.default.statSync(e).isDirectory()&&b.default.readdirSync(e,{withFileTypes:!0,recursive:!0}).filter(e=>e.isFile()).forEach(e=>V(v.default.join(e.parentPath,e.name),Object.entries(this.replacements).reduce((e,[o,a])=>{switch(o){case ge:t.debug("Found VERSION string to replace"),e[`VERSION = "${ge}";`]=`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+=": "+E.flattenDiagnosticMessageText(e.messageText,"\n"),t}).join("\n")}readConfigFile(e){const t=b.default.readFileSync(e).toString(),o=E.parseConfigFileTextToJson(e,t),s=o.config;s||this.reportDiagnostics([o.error],a.LogLevel.error);const r=E.parseJsonConfigFileContent(s,E.sys,v.default.dirname(e));return r.errors.length>0&&this.reportDiagnostics(r.errors,a.LogLevel.error),r}evalDiagnostics(e){if(e&&e.length>0){const t=e.filter(e=>e.category===E.DiagnosticCategory.Error),o=e.filter(e=>e.category===E.DiagnosticCategory.Warning),s=e.filter(e=>e.category===E.DiagnosticCategory.Suggestion),r=e.filter(e=>e.category===E.DiagnosticCategory.Message);if(o.length&&this.reportDiagnostics(o,a.LogLevel.warn),t.length)throw this.reportDiagnostics(e,a.LogLevel.error),Error(`TypeScript reported ${e.length} diagnostic(s) during check; aborting.`);s.length&&this.reportDiagnostics(s,a.LogLevel.info),r.length&&this.reportDiagnostics(r,a.LogLevel.info)}}preCheckDiagnostics(e){const t=E.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=p.ModuleKind.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?p.ModuleKind.ES2022:p.ModuleKind.CommonJS),s.options.inlineSourceMap=!1,s.options.inlineSources=!1,s.options.sourceMap=!0;const r=E.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=p.ModuleKind.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?p.ModuleKind.ES2022:p.ModuleKind.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=E.createProgram(a.fileNames,a.options),r={};t===ue.CJS?r.before=[pe(".cjs")]:t===ue.ESM&&(r.before=[pe(".js")]);const n=s.emit(void 0,void 0,void 0,void 0,r),i=E.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=q("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 _(t,e)}}}copyAssets(e){const t=this.log.for(this.copyAssets);let o=!1;try{o=b.default.statSync("./src/assets").isDirectory()}catch(e){return t.verbose("No assets found in ./src/assets to copy")}o&&G("./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,c=this.log,d=Array.from(new Set([...ie(n)]));let f=ie(r);if(0===f.length){try{f=ee(v.default.join(process.cwd(),"node_modules"))}catch{}f&&0!==f.length||(f=ce())}const h=Array.from(new Set([...(()=>{try{return Array.isArray(m.builtinModules)?m.builtinModules:[]}catch{return["fs","path","process","child_process","util","https","http","os","stream","crypto","zlib","net","tls","url","querystring","assert","events","tty","dns","querystring"]}})(),...f])),p=!t||"inline",S=[D.default({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"}),$.default()];o&&S.push(k.default({include:[],exclude:f}),u.nodeResolve({resolveOnly:d}));try{const C=await import("@rollup/plugin-terser"),w=C&&C.terser||C.default||C,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};S.push(w(t?E:I))}catch{}const y={input:a,plugins:S,external:h,onwarn:void 0,treeshake:!t},T={};h.forEach(e=>{T[e]=le(e)});const b=[{file:`${o?"bin/":"dist/"}${s||".bundle."+(t?"":"min")}${i?".js":".cjs"}`,format:o?"cjs":i?"esm":"umd",name:l,esModule:i,sourcemap:p,globals:T,exports:"auto"}];try{const F=await g.rollup(y);async function A(e){for(const t of b)await e.write(t)}c.verbose(F.watchFiles),await A(F)}catch(N){throw Error("Failed to bundle: "+N)}}async buildByEnv(e,t=he.ALL,o,a){try{X("lib")}catch(e){}try{X("dist")}catch(e){}b.default.mkdirSync("lib"),b.default.mkdirSync("dist"),[he.ALL,he.BUILD].includes(t)&&(await this.build(e,ue.ESM),await this.build(e,ue.CJS),this.patchFiles("lib")),[he.ALL,he.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=he.ALL,t,o){return this.buildByEnv(!0,e,t,o)}async buildProd(e=he.ALL,t,o){return this.buildByEnv(!1,e,t,o)}async buildDocs(){await R("npm install better-docs taffydb").promise,await R("npx markdown-include ./workdocs/readme-md.json").promise,await R("npx jsdoc -c ./workdocs/jsdocs.json -t ./node_modules/better-docs").promise,await R("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;G(t,o)});try{const e=await Q(v.default.resolve(v.default.join(process.cwd(),"dist")));this.replacements[fe]=e+" KB"}catch{this.replacements[fe]="unknown"}try{V("./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 ye={ci:{type:"boolean",default:!0},message:{type:"string",short:"m"},tag:{type:"string",short:"t",default:void 0}};e.AbortCode=P,e.BuildScripts=Se,e.Command=re,e.DefaultCommandOptions=F,e.DefaultCommandValues=A,e.Encoding=N,e.HttpClient=ne,e.NoCIFLag=B,e.PACKAGE_NAME="##PACKAGE##",e.RegexpOutputWriter=class extends L{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+"")}},e.ReleaseScript=class extends re{constructor(){super("ReleaseScript",ye)}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 R("git tag --sort=-taggerdate | head -n 5").promise,await I.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(t){const o=this.log.for(this.testVersion);switch(t=t.trim().toLowerCase()){case e.SemVersion.PATCH:case e.SemVersion.MINOR:case e.SemVersion.MAJOR:return o.verbose("Using provided SemVer update: "+t,1),t;default:return o.verbose("Testing provided version for SemVer compatibility: "+t,1),RegExp(j).test(t)?(o.verbose("version approved: "+t,1),t):void o.debug("Invalid version number: "+t)}}async prepareMessage(e){const t=this.log.for(this.prepareMessage);return e||(t.verbose("No release message provided. Prompting for one"),await I.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 R(`npm run prepare-release -- ${a} ${s}`,{cwd:process.cwd()}).promise,t=await R("git status --porcelain").promise,await t,t.logs.length&&await I.askConfirmation("git-changes","Do you want to push the changes to the remote repository?",!0)&&(await R("git add .").promise,await R(`git commit -m "${a} - ${s} - after release preparation${o?"":B}"`).promise),await R(`npm version "${a}" -m "${s}${o?"":B}"`).promise,await R("git push --follow-tags").promise,o||await R("NPM_TOKEN=$(cat .npmtoken) npm publish --access public").promise}},e.SemVersionRegex=j,e.SetupScriptKey="postinstall",e.StandardOutputWriter=L,e.UserInput=I,e.VERSION="##VERSION##",e.chainAbortController=O,e.copyFile=G,e.deletePath=X,e.getAllFiles=q,e.getDependencies=Y,e.getFileSizeZipped=Q,e.getPackage=z,e.getPackageDependencies=ce,e.getPackageVersion=H,e.getSlogan=se,e.installDependencies=Z,e.installIfNotAvailable=async(e,t)=>{if(!t){const e=await Y();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 Z({dev:n}),t.dev=t.dev||[],t.dev.push(...n),t},e.listFolder=function e(t=process.cwd(),o){const a=J.for(e);try{return b.default.existsSync(t)?b.default.readdirSync(t,{withFileTypes:!0}).filter(e=>!o||o(e.name,e)).map(e=>e.name):[]}catch(e){return a.verbose(`Failed to list folder ${t}: ${e}`),[]}},e.listNodeModulesPackages=ee,e.lockify=e=>{let t=Promise.resolve();return(...o)=>{const a=t.then(()=>e(...o));return t=a.catch(()=>{}),a}},e.normalizeImport=async e=>e.then(e=>e.default||e),e.packageToGlobal=le,e.parseList=ie,e.patchFile=V,e.printBanner=ae,e.pushToGit=async function e(){const t=J.for(e),o=await R("git config user.name").promise,a=await R("git config user.email").promise;t.verbose(`cached git id: ${o}/${a}. changing to automation`),await R('git config user.email "automation@decaf.ts"').promise,await R('git config user.name "decaf"').promise,t.info("Pushing changes to git..."),await R("git add .").promise,await R('git commit -m "refs #1 - after repo setup"').promise,await R("git push").promise,await R(`git config user.email "${a}"`).promise,await R(`git config user.name "${o}"`).promise,t.verbose(`reverted to git id: ${o}/${a}`)},e.readFile=W,e.renameFile=_,e.runCommand=R,e.setPackageAttribute=(e,t,o=process.cwd())=>{const a=z(o);a[e]=t,K(v.default.join(o,"package.json"),JSON.stringify(a,null,2))},e.spawnCommand=U,e.updateDependencies=async function e(){const t=J.for(e);t.info("checking for updates..."),await R("npx npm-check-updates -u").promise,t.info("updating..."),await R("npx npm run do-install").promise},e.writeFile=K},"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("prompts"),require("util"),require("@decaf-ts/logging"),require("fs"),require("path"),require("child_process"),require("styled-string-builder"),require("zlib"),require("https"),require("rollup"),require("@rollup/plugin-typescript"),require("@rollup/plugin-commonjs"),require("@rollup/plugin-node-resolve"),require("@rollup/plugin-json"),require("module"),require("typescript")):"function"==typeof define&&define.amd?define(["exports","prompts","util","@decaf-ts/logging","fs","path","child_process","styled-string-builder","zlib","https","rollup","@rollup/plugin-typescript","@rollup/plugin-commonjs","@rollup/plugin-node-resolve","@rollup/plugin-json","module","typescript"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).utils={},e.prompts,e.util,e.decafTsLogging,e.fs,e.path,e.childProcess,e.styledStringBuilder,e.zlib,e.https,e.rollup,e.rollupPluginTypescript,e.rollupPluginCommonjs,e.rollupPluginNodeResolve,e.rollupPluginJson,e.module,e.typescript);
|
|
2
|
-
|
|
1
|
+
(function(global, factory) {
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("prompts"), require("util"), require("@decaf-ts/logging"), require("fs"), require("path"), require("module"), require("child_process"), require("styled-string-builder"), require("shell-quote"), require("zlib"), require("https"), require("fs/promises"), require("rollup"), require("@rollup/plugin-typescript"), require("@rollup/plugin-commonjs"), require("@rollup/plugin-node-resolve"), require("@rollup/plugin-json"), require("typescript")) : typeof define === "function" && define.amd ? define([ "exports", "prompts", "util", "@decaf-ts/logging", "fs", "path", "module", "child_process", "styled-string-builder", "shell-quote", "zlib", "https", "fs/promises", "rollup", "@rollup/plugin-typescript", "@rollup/plugin-commonjs", "@rollup/plugin-node-resolve", "@rollup/plugin-json", "typescript" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self,
|
|
3
|
+
factory(global.utils = {}, global.prompts, global.util, global.decafTsLogging, global.fs, global.path, global.module, global.childProcess, global.styledStringBuilder, global.shellQuote, global.zlib, global.https, global.fsPromises, global.rollup, global.rollupPluginTypescript, global.rollupPluginCommonjs, global.rollupPluginNodeResolve, global.rollupPluginJson, global.typescript));
|
|
4
|
+
})(this, function(exports, prompts, util, logging, fs, path, module$1, child_process, styledStringBuilder, shellQuote, zlib, https, promises, rollup, typescript, commonjs, pluginNodeResolve, json, ts) {
|
|
5
|
+
"use strict";
|
|
6
|
+
function _interopNamespaceDefault(e) {
|
|
7
|
+
var n = Object.create(null);
|
|
8
|
+
if (e) {
|
|
9
|
+
Object.keys(e).forEach(function(k) {
|
|
10
|
+
if (k !== "default") {
|
|
11
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
12
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function() {
|
|
15
|
+
return e[k];
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
|
+
}
|
|
24
|
+
var ts__namespace = _interopNamespaceDefault(ts);
|
|
25
|
+
class UserInput {
|
|
26
|
+
static {
|
|
27
|
+
this.logger = logging.Logging.for(UserInput);
|
|
28
|
+
}
|
|
29
|
+
constructor(name) {
|
|
30
|
+
this.type = "text";
|
|
31
|
+
this.name = name;
|
|
32
|
+
}
|
|
33
|
+
setType(type) {
|
|
34
|
+
UserInput.logger.verbose(`Setting type to: ${type}`);
|
|
35
|
+
this.type = type;
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
setMessage(value) {
|
|
39
|
+
UserInput.logger.verbose(`Setting message to: ${value}`);
|
|
40
|
+
this.message = value;
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
43
|
+
setInitial(value) {
|
|
44
|
+
UserInput.logger.verbose(`Setting initial value to: ${value}`);
|
|
45
|
+
this.initial = value;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
setStyle(value) {
|
|
49
|
+
UserInput.logger.verbose(`Setting style to: ${value}`);
|
|
50
|
+
this.style = value;
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
setFormat(value) {
|
|
54
|
+
UserInput.logger.verbose(`Setting format function`);
|
|
55
|
+
this.format = value;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
setValidate(value) {
|
|
59
|
+
UserInput.logger.verbose(`Setting validate function`);
|
|
60
|
+
this.validate = value;
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
setOnState(value) {
|
|
64
|
+
UserInput.logger.verbose(`Setting onState callback`);
|
|
65
|
+
this.onState = value;
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
setMin(value) {
|
|
69
|
+
UserInput.logger.verbose(`Setting min value to: ${value}`);
|
|
70
|
+
this.min = value;
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
setMax(value) {
|
|
74
|
+
UserInput.logger.verbose(`Setting max value to: ${value}`);
|
|
75
|
+
this.max = value;
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
setFloat(value) {
|
|
79
|
+
UserInput.logger.verbose(`Setting float to: ${value}`);
|
|
80
|
+
this.float = value;
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
setRound(value) {
|
|
84
|
+
UserInput.logger.verbose(`Setting round to: ${value}`);
|
|
85
|
+
this.round = value;
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
setInstructions(value) {
|
|
89
|
+
UserInput.logger.verbose(`Setting instructions to: ${value}`);
|
|
90
|
+
this.instructions = value;
|
|
91
|
+
return this;
|
|
92
|
+
}
|
|
93
|
+
setIncrement(value) {
|
|
94
|
+
UserInput.logger.verbose(`Setting increment to: ${value}`);
|
|
95
|
+
this.increment = value;
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
setSeparator(value) {
|
|
99
|
+
UserInput.logger.verbose(`Setting separator to: ${value}`);
|
|
100
|
+
this.separator = value;
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
setActive(value) {
|
|
104
|
+
UserInput.logger.verbose(`Setting active style to: ${value}`);
|
|
105
|
+
this.active = value;
|
|
106
|
+
return this;
|
|
107
|
+
}
|
|
108
|
+
setInactive(value) {
|
|
109
|
+
UserInput.logger.verbose(`Setting inactive style to: ${value}`);
|
|
110
|
+
this.inactive = value;
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
setChoices(value) {
|
|
114
|
+
UserInput.logger.verbose(`Setting choices: ${JSON.stringify(value)}`);
|
|
115
|
+
this.choices = value;
|
|
116
|
+
return this;
|
|
117
|
+
}
|
|
118
|
+
setHint(value) {
|
|
119
|
+
UserInput.logger.verbose(`Setting hint to: ${value}`);
|
|
120
|
+
this.hint = value;
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
setWarn(value) {
|
|
124
|
+
UserInput.logger.verbose(`Setting warn to: ${value}`);
|
|
125
|
+
this.warn = value;
|
|
126
|
+
return this;
|
|
127
|
+
}
|
|
128
|
+
setSuggest(value) {
|
|
129
|
+
UserInput.logger.verbose(`Setting suggest function`);
|
|
130
|
+
this.suggest = value;
|
|
131
|
+
return this;
|
|
132
|
+
}
|
|
133
|
+
setLimit(value) {
|
|
134
|
+
UserInput.logger.verbose(`Setting limit to: ${value}`);
|
|
135
|
+
this.limit = value;
|
|
136
|
+
return this;
|
|
137
|
+
}
|
|
138
|
+
setMask(value) {
|
|
139
|
+
UserInput.logger.verbose(`Setting mask to: ${value}`);
|
|
140
|
+
this.mask = value;
|
|
141
|
+
return this;
|
|
142
|
+
}
|
|
143
|
+
setStdout(value) {
|
|
144
|
+
UserInput.logger.verbose(`Setting stdout stream`);
|
|
145
|
+
this.stdout = value;
|
|
146
|
+
return this;
|
|
147
|
+
}
|
|
148
|
+
setStdin(value) {
|
|
149
|
+
this.stdin = value;
|
|
150
|
+
return this;
|
|
151
|
+
}
|
|
152
|
+
async ask() {
|
|
153
|
+
return (await UserInput.ask(this))[this.name];
|
|
154
|
+
}
|
|
155
|
+
static async ask(question) {
|
|
156
|
+
const log = UserInput.logger.for(this.ask);
|
|
157
|
+
if (!Array.isArray(question)) {
|
|
158
|
+
question = [ question ];
|
|
159
|
+
}
|
|
160
|
+
let answers;
|
|
161
|
+
try {
|
|
162
|
+
log.verbose(`Asking questions: ${question.map(q => q.name).join(", ")}`);
|
|
163
|
+
answers = await prompts(question);
|
|
164
|
+
log.verbose(`Received answers: ${JSON.stringify(answers, null, 2)}`);
|
|
165
|
+
} catch (error) {
|
|
166
|
+
throw new Error(`Error while getting input: ${error}`);
|
|
167
|
+
}
|
|
168
|
+
return answers;
|
|
169
|
+
}
|
|
170
|
+
static async askNumber(name, question, min, max, initial) {
|
|
171
|
+
const log = UserInput.logger.for(this.askNumber);
|
|
172
|
+
log.verbose(`Asking number input: undefined, question: ${question}, min: ${min}, max: ${max}, initial: ${initial}`);
|
|
173
|
+
const userInput = new UserInput(name).setMessage(question).setType("number");
|
|
174
|
+
if (typeof min === "number") userInput.setMin(min);
|
|
175
|
+
if (typeof max === "number") userInput.setMax(max);
|
|
176
|
+
if (typeof initial === "number") userInput.setInitial(initial);
|
|
177
|
+
return (await this.ask(userInput))[name];
|
|
178
|
+
}
|
|
179
|
+
static async askText(name, question, mask = undefined, initial) {
|
|
180
|
+
const log = UserInput.logger.for(this.askText);
|
|
181
|
+
log.verbose(`Asking text input: undefined, question: ${question}, mask: ${mask}, initial: ${initial}`);
|
|
182
|
+
const userInput = new UserInput(name).setMessage(question);
|
|
183
|
+
if (mask) userInput.setMask(mask);
|
|
184
|
+
if (typeof initial === "string") userInput.setInitial(initial);
|
|
185
|
+
return (await this.ask(userInput))[name];
|
|
186
|
+
}
|
|
187
|
+
static async askConfirmation(name, question, initial) {
|
|
188
|
+
const log = UserInput.logger.for(this.askConfirmation);
|
|
189
|
+
log.verbose(`Asking confirmation input: undefined, question: ${question}, initial: ${initial}`);
|
|
190
|
+
const userInput = new UserInput(name).setMessage(question).setType("confirm");
|
|
191
|
+
if (typeof initial !== "undefined") userInput.setInitial(initial);
|
|
192
|
+
return (await this.ask(userInput))[name];
|
|
193
|
+
}
|
|
194
|
+
static async insist(input, test, defaultConfirmation, limit = 1) {
|
|
195
|
+
const log = UserInput.logger.for(this.insist);
|
|
196
|
+
log.verbose(`Insisting on input: ${input.name}, test: ${test.toString()}, defaultConfirmation: ${defaultConfirmation}, limit: ${limit}`);
|
|
197
|
+
let result = undefined;
|
|
198
|
+
let count = 0;
|
|
199
|
+
let confirmation;
|
|
200
|
+
try {
|
|
201
|
+
do {
|
|
202
|
+
result = (await UserInput.ask(input))[input.name];
|
|
203
|
+
if (!test(result)) {
|
|
204
|
+
result = undefined;
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
confirmation = await UserInput.askConfirmation(`${input.name}-confirm`, `Is the ${input.type} correct?`, defaultConfirmation);
|
|
208
|
+
if (!confirmation) result = undefined;
|
|
209
|
+
} while (typeof result === "undefined" && limit > 1 && count++ < limit);
|
|
210
|
+
} catch (e) {
|
|
211
|
+
log.error(`Error while insisting: ${e}`);
|
|
212
|
+
throw e;
|
|
213
|
+
}
|
|
214
|
+
if (typeof result === "undefined") log.info("no selection...");
|
|
215
|
+
return result;
|
|
216
|
+
}
|
|
217
|
+
static async insistForText(name, question, test, mask = undefined, initial, defaultConfirmation = false, limit = -1) {
|
|
218
|
+
const log = UserInput.logger.for(this.insistForText);
|
|
219
|
+
log.verbose(`Insisting for text input: undefined, question: ${question}, test: ${test.toString()}, mask: ${mask}, initial: ${initial}, defaultConfirmation: ${defaultConfirmation}, limit: ${limit}`);
|
|
220
|
+
const userInput = new UserInput(name).setMessage(question);
|
|
221
|
+
if (mask) userInput.setMask(mask);
|
|
222
|
+
if (typeof initial === "string") userInput.setInitial(initial);
|
|
223
|
+
return await this.insist(userInput, test, defaultConfirmation, limit);
|
|
224
|
+
}
|
|
225
|
+
static async insistForNumber(name, question, test, min, max, initial, defaultConfirmation = false, limit = -1) {
|
|
226
|
+
const log = UserInput.logger.for(this.insistForNumber);
|
|
227
|
+
log.verbose(`Insisting for number input: undefined, question: ${question}, test: ${test.toString()}, min: ${min}, max: ${max}, initial: ${initial}, defaultConfirmation: ${defaultConfirmation}, limit: ${limit}`);
|
|
228
|
+
const userInput = new UserInput(name).setMessage(question).setType("number");
|
|
229
|
+
if (typeof min === "number") userInput.setMin(min);
|
|
230
|
+
if (typeof max === "number") userInput.setMax(max);
|
|
231
|
+
if (typeof initial === "number") userInput.setInitial(initial);
|
|
232
|
+
return await this.insist(userInput, test, defaultConfirmation, limit);
|
|
233
|
+
}
|
|
234
|
+
static parseArgs(options) {
|
|
235
|
+
const log = UserInput.logger.for(this.parseArgs);
|
|
236
|
+
const args = {
|
|
237
|
+
args: process.argv.slice(2),
|
|
238
|
+
options: options
|
|
239
|
+
};
|
|
240
|
+
log.debug(`Parsing arguments: ${JSON.stringify(args, null, 2)}`);
|
|
241
|
+
try {
|
|
242
|
+
return util.parseArgs(args);
|
|
243
|
+
} catch (error) {
|
|
244
|
+
log.debug(`Error while parsing arguments:\n${JSON.stringify(args, null, 2)}\n | options\n${JSON.stringify(options, null, 2)}\n | ${error}`);
|
|
245
|
+
throw new Error(`Error while parsing arguments: ${error}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const DefaultCommandOptions = {
|
|
250
|
+
verbose: {
|
|
251
|
+
type: "boolean",
|
|
252
|
+
short: "V",
|
|
253
|
+
default: undefined
|
|
254
|
+
},
|
|
255
|
+
version: {
|
|
256
|
+
type: "boolean",
|
|
257
|
+
short: "v",
|
|
258
|
+
default: undefined
|
|
259
|
+
},
|
|
260
|
+
help: {
|
|
261
|
+
type: "boolean",
|
|
262
|
+
short: "h",
|
|
263
|
+
default: false
|
|
264
|
+
},
|
|
265
|
+
logLevel: {
|
|
266
|
+
type: "string",
|
|
267
|
+
default: "info"
|
|
268
|
+
},
|
|
269
|
+
logStyle: {
|
|
270
|
+
type: "boolean",
|
|
271
|
+
default: true
|
|
272
|
+
},
|
|
273
|
+
timestamp: {
|
|
274
|
+
type: "boolean",
|
|
275
|
+
default: true
|
|
276
|
+
},
|
|
277
|
+
banner: {
|
|
278
|
+
type: "boolean",
|
|
279
|
+
default: true
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
const DefaultCommandValues = Object.keys(DefaultCommandOptions).reduce((acc, key) => {
|
|
283
|
+
acc[key] = DefaultCommandOptions[key].default;
|
|
284
|
+
return acc;
|
|
285
|
+
}, {});
|
|
286
|
+
const Encoding = "utf-8";
|
|
287
|
+
const SemVersionRegex = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z])))/g;
|
|
288
|
+
exports.SemVersion = void 0;
|
|
289
|
+
(function(SemVersion) {
|
|
290
|
+
SemVersion["PATCH"] = "patch";
|
|
291
|
+
SemVersion["MINOR"] = "minor";
|
|
292
|
+
SemVersion["MAJOR"] = "major";
|
|
293
|
+
})(exports.SemVersion || (exports.SemVersion = {}));
|
|
294
|
+
const NoCIFLag = "-no-ci";
|
|
295
|
+
const SetupScriptKey = "postinstall";
|
|
296
|
+
exports.Tokens = void 0;
|
|
297
|
+
(function(Tokens) {
|
|
298
|
+
Tokens["GIT"] = ".token";
|
|
299
|
+
Tokens["NPM"] = ".npmtoken";
|
|
300
|
+
Tokens["DOCKER"] = ".dockertoken";
|
|
301
|
+
Tokens["CONFLUENCE"] = ".confluence-token";
|
|
302
|
+
})(exports.Tokens || (exports.Tokens = {}));
|
|
303
|
+
const AbortCode = "Aborted";
|
|
304
|
+
class StandardOutputWriter {
|
|
305
|
+
constructor(cmd, lock, ...args) {
|
|
306
|
+
this.cmd = cmd;
|
|
307
|
+
this.lock = lock;
|
|
308
|
+
this.logger = logging.Logging.for(this.cmd);
|
|
309
|
+
}
|
|
310
|
+
log(type, data) {
|
|
311
|
+
data = Buffer.isBuffer(data) ? data.toString(Encoding) : data;
|
|
312
|
+
const log = type === "stderr" ? styledStringBuilder.style(data).red.text : data;
|
|
313
|
+
this.logger.info(log);
|
|
314
|
+
}
|
|
315
|
+
data(chunk) {
|
|
316
|
+
this.log("stdout", String(chunk));
|
|
317
|
+
}
|
|
318
|
+
error(chunk) {
|
|
319
|
+
this.log("stderr", String(chunk));
|
|
320
|
+
}
|
|
321
|
+
errors(err) {
|
|
322
|
+
this.log("stderr", `Error executing command exited : ${err}`);
|
|
323
|
+
}
|
|
324
|
+
exit(code, logs) {
|
|
325
|
+
this.log("stdout", `command exited code : ${code === 0 ? styledStringBuilder.style(code.toString()).green.text : styledStringBuilder.style(code === null ? "null" : code.toString()).red.text}`);
|
|
326
|
+
if (code === 0) {
|
|
327
|
+
this.resolve(logs.map(l => l.trim()).join("\n"));
|
|
328
|
+
} else {
|
|
329
|
+
this.reject(new Error(logs.length ? logs.join("\n") : code.toString()));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
parseCommand(command) {
|
|
333
|
+
if (Array.isArray(command)) {
|
|
334
|
+
this.cmd = command.join(" ");
|
|
335
|
+
return [ command[0], command.slice(1) ];
|
|
336
|
+
}
|
|
337
|
+
const parts = shellQuote.parse(command).filter(p => typeof p === "string").map(String);
|
|
338
|
+
this.cmd = parts.join(" ");
|
|
339
|
+
return [ parts[0], parts.slice(1) ];
|
|
340
|
+
}
|
|
341
|
+
resolve(reason) {
|
|
342
|
+
this.log("stdout", `${this.cmd} executed successfully: ${styledStringBuilder.style(reason ? "ran to completion" : reason).green}`);
|
|
343
|
+
this.lock.resolve(reason);
|
|
344
|
+
}
|
|
345
|
+
reject(reason) {
|
|
346
|
+
if (!(reason instanceof Error)) {
|
|
347
|
+
reason = new Error(typeof reason === "number" ? `Exit code ${reason}` : reason);
|
|
348
|
+
}
|
|
349
|
+
this.log("stderr", `${this.cmd} failed to execute: ${styledStringBuilder.style(reason.message).red}`);
|
|
350
|
+
this.lock.reject(reason);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function lockify(f) {
|
|
354
|
+
let lock = Promise.resolve();
|
|
355
|
+
return (...params) => {
|
|
356
|
+
const result = lock.then(() => f(...params));
|
|
357
|
+
lock = result.catch(() => {});
|
|
358
|
+
return result;
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
function chainAbortController(argument0, ...remainder) {
|
|
362
|
+
let signals;
|
|
363
|
+
let controller;
|
|
364
|
+
if (argument0 instanceof AbortSignal) {
|
|
365
|
+
controller = new AbortController;
|
|
366
|
+
signals = [ argument0, ...remainder ];
|
|
367
|
+
} else {
|
|
368
|
+
controller = argument0;
|
|
369
|
+
signals = remainder;
|
|
370
|
+
}
|
|
371
|
+
if (controller.signal.aborted) {
|
|
372
|
+
return controller;
|
|
373
|
+
}
|
|
374
|
+
const handler = () => controller.abort();
|
|
375
|
+
for (const signal of signals) {
|
|
376
|
+
if (signal.aborted) {
|
|
377
|
+
controller.abort();
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
380
|
+
signal.addEventListener("abort", handler, {
|
|
381
|
+
once: true,
|
|
382
|
+
signal: controller.signal
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
return controller;
|
|
386
|
+
}
|
|
387
|
+
function spawnCommand(output, command, opts, abort, logger) {
|
|
388
|
+
function spawnInner(command, controller) {
|
|
389
|
+
const [cmd, argz] = output.parseCommand(command);
|
|
390
|
+
logger.info(`Running command: ${cmd}`);
|
|
391
|
+
logger.debug(`with args: ${argz.join(" ")}`);
|
|
392
|
+
const childProcess = child_process.spawn(cmd, argz, {
|
|
393
|
+
...opts,
|
|
394
|
+
cwd: opts.cwd || process.cwd(),
|
|
395
|
+
env: Object.assign({}, process.env, opts.env, {
|
|
396
|
+
PATH: process.env.PATH
|
|
397
|
+
}),
|
|
398
|
+
shell: opts.shell || false,
|
|
399
|
+
signal: controller.signal
|
|
400
|
+
});
|
|
401
|
+
logger.verbose(`pid : ${childProcess.pid}`);
|
|
402
|
+
return childProcess;
|
|
403
|
+
}
|
|
404
|
+
const m = command.match(/[<>$#]/g);
|
|
405
|
+
if (m) throw new Error(`Invalid command: ${command}. contains invalid characters: ${m}`);
|
|
406
|
+
if (command.includes(" | ")) {
|
|
407
|
+
const cmds = command.split(" | ");
|
|
408
|
+
const spawns = [];
|
|
409
|
+
const controllers = new Array(cmds.length);
|
|
410
|
+
controllers[0] = abort;
|
|
411
|
+
for (let i = 0; i < cmds.length; i++) {
|
|
412
|
+
if (i !== 0) controllers[i] = chainAbortController(controllers[i - 1].signal);
|
|
413
|
+
spawns.push(spawnInner(cmds[i], controllers[i]));
|
|
414
|
+
if (i === 0) continue;
|
|
415
|
+
spawns[i - 1].stdout.pipe(spawns[i].stdin);
|
|
416
|
+
}
|
|
417
|
+
return spawns[cmds.length - 1];
|
|
418
|
+
}
|
|
419
|
+
return spawnInner(command, abort);
|
|
420
|
+
}
|
|
421
|
+
function runCommand(command, opts = {}, outputConstructor = StandardOutputWriter, ...args) {
|
|
422
|
+
const logger = logging.Logging.for(runCommand);
|
|
423
|
+
const abort = new AbortController;
|
|
424
|
+
const result = {
|
|
425
|
+
abort: abort,
|
|
426
|
+
command: command,
|
|
427
|
+
logs: [],
|
|
428
|
+
errs: []
|
|
429
|
+
};
|
|
430
|
+
const lock = new Promise((resolve, reject) => {
|
|
431
|
+
let output;
|
|
432
|
+
try {
|
|
433
|
+
output = new outputConstructor(command, {
|
|
434
|
+
resolve: resolve,
|
|
435
|
+
reject: reject
|
|
436
|
+
}, ...args);
|
|
437
|
+
result.cmd = spawnCommand(output, command, opts, abort, logger);
|
|
438
|
+
} catch (e) {
|
|
439
|
+
return reject(new Error(`Error running command ${command}: ${e}`));
|
|
440
|
+
}
|
|
441
|
+
result.cmd.stdout.setEncoding("utf8");
|
|
442
|
+
result.cmd.stdout.on("data", chunk => {
|
|
443
|
+
chunk = chunk.toString();
|
|
444
|
+
result.logs.push(chunk);
|
|
445
|
+
output.data(chunk);
|
|
446
|
+
});
|
|
447
|
+
result.cmd.stderr.on("data", data => {
|
|
448
|
+
data = data.toString();
|
|
449
|
+
result.errs.push(data);
|
|
450
|
+
output.error(data);
|
|
451
|
+
});
|
|
452
|
+
result.cmd.once("error", err => {
|
|
453
|
+
output.exit(err.message, result.errs);
|
|
454
|
+
});
|
|
455
|
+
result.cmd.once("exit", (code = 0) => {
|
|
456
|
+
if (abort.signal.aborted && code === null) code = AbortCode;
|
|
457
|
+
output.exit(code, code === 0 ? result.logs : result.errs);
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
Object.assign(result, {
|
|
461
|
+
promise: lock,
|
|
462
|
+
pipe: async cb => {
|
|
463
|
+
const l = logger.for("pipe");
|
|
464
|
+
try {
|
|
465
|
+
l.verbose(`Executing pipe function ${command}...`);
|
|
466
|
+
const result = await lock;
|
|
467
|
+
l.verbose(`Piping output to ${cb.name}: ${result}`);
|
|
468
|
+
return cb(result);
|
|
469
|
+
} catch (e) {
|
|
470
|
+
l.error(`Error piping command output: ${e}`);
|
|
471
|
+
throw e;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
return result;
|
|
476
|
+
}
|
|
477
|
+
const logger = logging.Logging.for("fs");
|
|
478
|
+
const localRequire = module$1.createRequire(`${process.cwd()}/package.json`);
|
|
479
|
+
function isTestEnvironment() {
|
|
480
|
+
return process.env.NODE_ENV === "test" || typeof process.env.JEST_WORKER_ID !== "undefined";
|
|
481
|
+
}
|
|
482
|
+
function patchString(input, values, flags = "g", filter) {
|
|
483
|
+
Object.entries(values).forEach(([key, val]) => {
|
|
484
|
+
const regexp = new RegExp(logging.escapeRegExp(key), flags);
|
|
485
|
+
input = input.replace(regexp, subStr => {
|
|
486
|
+
if (!filter || filter(subStr)) {
|
|
487
|
+
return val;
|
|
488
|
+
}
|
|
489
|
+
return val;
|
|
490
|
+
});
|
|
491
|
+
});
|
|
492
|
+
return input;
|
|
493
|
+
}
|
|
494
|
+
function patchFile(path, values, filter) {
|
|
495
|
+
const log = logger.for(patchFile);
|
|
496
|
+
if (!fs.existsSync(path)) throw new Error(`File not found at path "${path}".`);
|
|
497
|
+
let content = readFile(path);
|
|
498
|
+
log.verbose(`Patching file "${path}"...`);
|
|
499
|
+
log.debug(`with value: ${JSON.stringify(values)}`);
|
|
500
|
+
try {
|
|
501
|
+
content = patchString(content, values, "g", filter);
|
|
502
|
+
} catch (error) {
|
|
503
|
+
throw new Error(`Error patching file: ${error}`);
|
|
504
|
+
}
|
|
505
|
+
writeFile(path, content);
|
|
506
|
+
}
|
|
507
|
+
function readFile(path) {
|
|
508
|
+
const log = logger.for(readFile);
|
|
509
|
+
try {
|
|
510
|
+
log.verbose(`Reading file "${path}"...`);
|
|
511
|
+
return fs.readFileSync(path, "utf8");
|
|
512
|
+
} catch (error) {
|
|
513
|
+
log.verbose(`Error reading file "${path}": ${error}`);
|
|
514
|
+
throw new Error(`Error reading file "${path}": ${error}`);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
function writeFile(path, data) {
|
|
518
|
+
const log = logger.for(writeFile);
|
|
519
|
+
try {
|
|
520
|
+
log.verbose(`Writing file "${path} with ${data.length} bytes...`);
|
|
521
|
+
fs.writeFileSync(path, data, "utf8");
|
|
522
|
+
} catch (error) {
|
|
523
|
+
log.verbose(`Error writing file "${path}": ${error}`);
|
|
524
|
+
throw new Error(`Error writing file "${path}": ${error}`);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
function getAllFiles(p, filter) {
|
|
528
|
+
const log = logger.for(getAllFiles);
|
|
529
|
+
const files = [];
|
|
530
|
+
try {
|
|
531
|
+
log.verbose(`Retrieving all files from "${p}"...`);
|
|
532
|
+
const entries = fs.readdirSync(p);
|
|
533
|
+
entries.forEach(entry => {
|
|
534
|
+
const fullPath = path.join(p, entry);
|
|
535
|
+
const stat = fs.statSync(fullPath);
|
|
536
|
+
if (stat.isFile()) {
|
|
537
|
+
files.push(fullPath);
|
|
538
|
+
} else if (stat.isDirectory()) {
|
|
539
|
+
files.push(...getAllFiles(fullPath));
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
if (!filter) return files;
|
|
543
|
+
return files.filter(filter);
|
|
544
|
+
} catch (error) {
|
|
545
|
+
log.verbose(`Error retrieving files from "${p}": ${error}`);
|
|
546
|
+
throw new Error(`Error retrieving files from "${p}": ${error}`);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
async function renameFile(source, dest) {
|
|
550
|
+
const log = logger.for(renameFile);
|
|
551
|
+
let descriptorSource, descriptorDest;
|
|
552
|
+
try {
|
|
553
|
+
descriptorSource = fs.statSync(source);
|
|
554
|
+
} catch (error) {
|
|
555
|
+
log.verbose(`Source path "${source}" does not exist: ${error}`);
|
|
556
|
+
throw new Error(`Source path "${source}" does not exist: ${error}`);
|
|
557
|
+
}
|
|
558
|
+
try {
|
|
559
|
+
descriptorDest = fs.statSync(dest);
|
|
560
|
+
} catch (e) {}
|
|
561
|
+
if (descriptorDest) {
|
|
562
|
+
log.verbose(`Destination path "${dest}" already exists`);
|
|
563
|
+
throw new Error(`Destination path "${dest}" already exists`);
|
|
564
|
+
}
|
|
565
|
+
try {
|
|
566
|
+
log.verbose(`Renaming ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}...`);
|
|
567
|
+
fs.renameSync(source, dest);
|
|
568
|
+
log.verbose(`Successfully renamed to "${dest}"`);
|
|
569
|
+
} catch (error) {
|
|
570
|
+
log.verbose(`Error renaming ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}": ${error}`);
|
|
571
|
+
throw new Error(`Error renaming ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}": ${error}`);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
function copyFile(source, dest) {
|
|
575
|
+
const log = logger.for(copyFile);
|
|
576
|
+
let descriptorSource, descriptorDest;
|
|
577
|
+
try {
|
|
578
|
+
descriptorSource = fs.statSync(source);
|
|
579
|
+
} catch (error) {
|
|
580
|
+
log.verbose(`Source path "${source}" does not exist: ${error}`);
|
|
581
|
+
throw new Error(`Source path "${source}" does not exist: ${error}`);
|
|
582
|
+
}
|
|
583
|
+
try {
|
|
584
|
+
descriptorDest = fs.statSync(dest);
|
|
585
|
+
} catch (error) {
|
|
586
|
+
if (descriptorSource.isDirectory()) {
|
|
587
|
+
log.verbose(`Dest path "${dest}" does not exist. creating`);
|
|
588
|
+
fs.mkdirSync(dest, {
|
|
589
|
+
recursive: true
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
try {
|
|
594
|
+
log.verbose(`Copying ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}...`);
|
|
595
|
+
fs.cpSync(source, dest, {
|
|
596
|
+
recursive: true
|
|
597
|
+
});
|
|
598
|
+
} catch (error) {
|
|
599
|
+
log.verbose(`Error copying ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}: ${error}`);
|
|
600
|
+
throw new Error(`Error copying ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}: ${error}`);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
function deletePath(p) {
|
|
604
|
+
const log = logger.for(deletePath);
|
|
605
|
+
try {
|
|
606
|
+
const descriptor = fs.statSync(p);
|
|
607
|
+
if (descriptor.isFile()) {
|
|
608
|
+
log.verbose(`Deleting file "${p}...`);
|
|
609
|
+
fs.rmSync(p, {
|
|
610
|
+
recursive: true,
|
|
611
|
+
force: true
|
|
612
|
+
});
|
|
613
|
+
} else if (descriptor.isDirectory()) fs.rmSync(p, {
|
|
614
|
+
recursive: true,
|
|
615
|
+
force: true
|
|
616
|
+
});
|
|
617
|
+
} catch (error) {
|
|
618
|
+
log.verbose(`Error Deleting "${p}": ${error}`);
|
|
619
|
+
throw new Error(`Error Deleting "${p}": ${error}`);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
function getPackage(p = process.cwd(), property) {
|
|
623
|
+
let pkg;
|
|
624
|
+
try {
|
|
625
|
+
pkg = JSON.parse(readFile(path.join(p, `package.json`)));
|
|
626
|
+
} catch (error) {
|
|
627
|
+
throw new Error(`Failed to retrieve package information" ${error}`);
|
|
628
|
+
}
|
|
629
|
+
if (property) {
|
|
630
|
+
if (!(property in pkg)) throw new Error(`Property "${property}" not found in package.json`);
|
|
631
|
+
return pkg[property];
|
|
632
|
+
}
|
|
633
|
+
return pkg;
|
|
634
|
+
}
|
|
635
|
+
function setPackageAttribute(attr, value, p = process.cwd()) {
|
|
636
|
+
const pkg = getPackage(p);
|
|
637
|
+
pkg[attr] = value;
|
|
638
|
+
writeFile(path.join(p, `package.json`), JSON.stringify(pkg, null, 2));
|
|
639
|
+
}
|
|
640
|
+
function getPackageVersion(p = process.cwd()) {
|
|
641
|
+
return getPackage(p, "version");
|
|
642
|
+
}
|
|
643
|
+
async function getDependencies(p = process.cwd()) {
|
|
644
|
+
const pkgPath = path.join(p, "package.json");
|
|
645
|
+
const lockPath = path.join(p, "package-lock.json");
|
|
646
|
+
let pkg;
|
|
647
|
+
try {
|
|
648
|
+
pkg = JSON.parse(readFile(pkgPath));
|
|
649
|
+
} catch (error) {
|
|
650
|
+
throw new Error(`Could not read package.json at ${pkgPath}: ${error}`);
|
|
651
|
+
}
|
|
652
|
+
let lock;
|
|
653
|
+
if (fs.existsSync(lockPath)) {
|
|
654
|
+
try {
|
|
655
|
+
lock = JSON.parse(readFile(lockPath));
|
|
656
|
+
} catch (error) {
|
|
657
|
+
logger.warn(`Unable to parse package-lock.json at ${lockPath}: ${error}`);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
const mapDeps = (entries = {}) => Object.entries(entries).map(([name, version]) => ({
|
|
661
|
+
name: name,
|
|
662
|
+
version: resolveDependencyVersion(lock, name, version)
|
|
663
|
+
}));
|
|
664
|
+
return {
|
|
665
|
+
prod: mapDeps(pkg.dependencies),
|
|
666
|
+
dev: mapDeps(pkg.devDependencies),
|
|
667
|
+
peer: mapDeps(pkg.peerDependencies)
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
function resolveDependencyVersion(lock, name, fallback) {
|
|
671
|
+
if (lock) {
|
|
672
|
+
const packages = lock.packages || {};
|
|
673
|
+
const key = `node_modules/${name}`;
|
|
674
|
+
if (packages[key] && packages[key].version) {
|
|
675
|
+
return packages[key].version;
|
|
676
|
+
}
|
|
677
|
+
if (lock.dependencies && lock.dependencies[name]) {
|
|
678
|
+
return lock.dependencies[name].version || fallback;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return fallback;
|
|
682
|
+
}
|
|
683
|
+
async function updateDependencies() {
|
|
684
|
+
const log = logger.for(updateDependencies);
|
|
685
|
+
log.info("checking for updates...");
|
|
686
|
+
await runCommand("npx npm-check-updates -u").promise;
|
|
687
|
+
log.info("updating...");
|
|
688
|
+
await runCommand("npx npm run do-install").promise;
|
|
689
|
+
}
|
|
690
|
+
async function installIfNotAvailable(deps, dependencies) {
|
|
691
|
+
deps = typeof deps === "string" ? [ deps ] : deps;
|
|
692
|
+
const current = {
|
|
693
|
+
prod: dependencies?.prod ? [ ...dependencies.prod ] : [],
|
|
694
|
+
dev: dependencies?.dev ? [ ...dependencies.dev ] : [],
|
|
695
|
+
peer: dependencies?.peer ? [ ...dependencies.peer ] : []
|
|
696
|
+
};
|
|
697
|
+
const known = new Set([ ...current.prod ?? [], ...current.dev ?? [], ...current.peer ?? [] ]);
|
|
698
|
+
const toInstall = [];
|
|
699
|
+
for (const dep of deps) {
|
|
700
|
+
if (known.has(dep)) continue;
|
|
701
|
+
try {
|
|
702
|
+
localRequire.resolve(dep);
|
|
703
|
+
known.add(dep);
|
|
704
|
+
} catch {
|
|
705
|
+
toInstall.push(dep);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
if (toInstall.length) {
|
|
709
|
+
if (isTestEnvironment()) {
|
|
710
|
+
logger.verbose(`Skipping dependency install in test environment for: ${toInstall.join(", ")}`);
|
|
711
|
+
} else {
|
|
712
|
+
await installDependencies({
|
|
713
|
+
dev: toInstall
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
const devDeps = new Set(current.dev ?? []);
|
|
717
|
+
toInstall.forEach(dep => devDeps.add(dep));
|
|
718
|
+
current.dev = Array.from(devDeps);
|
|
719
|
+
}
|
|
720
|
+
return current;
|
|
721
|
+
}
|
|
722
|
+
async function pushToGit() {
|
|
723
|
+
const log = logger.for(pushToGit);
|
|
724
|
+
const gitUser = await runCommand("git config user.name").promise;
|
|
725
|
+
const gitEmail = await runCommand("git config user.email").promise;
|
|
726
|
+
log.verbose(`cached git id: ${gitUser}/${gitEmail}. changing to automation`);
|
|
727
|
+
await runCommand('git config user.email "automation@decaf.ts"').promise;
|
|
728
|
+
await runCommand('git config user.name "decaf"').promise;
|
|
729
|
+
log.info("Pushing changes to git...");
|
|
730
|
+
await runCommand("git add .").promise;
|
|
731
|
+
await runCommand(`git commit -m "refs #1 - after repo setup"`).promise;
|
|
732
|
+
await runCommand("git push").promise;
|
|
733
|
+
await runCommand(`git config user.email "${gitEmail}"`).promise;
|
|
734
|
+
await runCommand(`git config user.name "${gitUser}"`).promise;
|
|
735
|
+
log.verbose(`reverted to git id: ${gitUser}/${gitEmail}`);
|
|
736
|
+
}
|
|
737
|
+
async function installDependencies(dependencies) {
|
|
738
|
+
const log = logger.for(installDependencies);
|
|
739
|
+
const prod = dependencies.prod || [];
|
|
740
|
+
const dev = dependencies.dev || [];
|
|
741
|
+
const peer = dependencies.peer || [];
|
|
742
|
+
if (prod.length) {
|
|
743
|
+
log.info(`Installing dependencies ${prod.join(", ")}...`);
|
|
744
|
+
await runCommand(`npm install ${prod.join(" ")}`, {
|
|
745
|
+
cwd: process.cwd()
|
|
746
|
+
}).promise;
|
|
747
|
+
}
|
|
748
|
+
if (dev.length) {
|
|
749
|
+
log.info(`Installing devDependencies ${dev.join(", ")}...`);
|
|
750
|
+
await runCommand(`npm install --save-dev ${dev.join(" ")}`, {
|
|
751
|
+
cwd: process.cwd()
|
|
752
|
+
}).promise;
|
|
753
|
+
}
|
|
754
|
+
if (peer.length) {
|
|
755
|
+
log.info(`Installing peerDependencies ${peer.join(", ")}...`);
|
|
756
|
+
await runCommand(`npm install --save-peer ${peer.join(" ")}`, {
|
|
757
|
+
cwd: process.cwd()
|
|
758
|
+
}).promise;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
async function normalizeImport(importPromise) {
|
|
762
|
+
return importPromise.then(m => m.default || m);
|
|
763
|
+
}
|
|
764
|
+
async function getFileSizeZipped(dir) {
|
|
765
|
+
const log = logger.for(getFileSizeZipped);
|
|
766
|
+
try {
|
|
767
|
+
const entries = fs.readdirSync(dir);
|
|
768
|
+
const candidates = entries.map(e => path.join(dir, e)).filter(p => {
|
|
769
|
+
try {
|
|
770
|
+
const s = fs.statSync(p);
|
|
771
|
+
return s.isFile() && (p.endsWith(".js") || p.endsWith(".cjs") || p.endsWith(".mjs"));
|
|
772
|
+
} catch {
|
|
773
|
+
return false;
|
|
774
|
+
}
|
|
775
|
+
});
|
|
776
|
+
if (candidates.length === 0) {
|
|
777
|
+
throw new Error(`No JS files found in directory ${dir}`);
|
|
778
|
+
}
|
|
779
|
+
let smallest = candidates[0];
|
|
780
|
+
let smallestSize = fs.statSync(smallest).size;
|
|
781
|
+
for (const c of candidates.slice(1)) {
|
|
782
|
+
const s = fs.statSync(c).size;
|
|
783
|
+
if (s < smallestSize) {
|
|
784
|
+
smallest = c;
|
|
785
|
+
smallestSize = s;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
log.verbose(`Selected smallest bundle: ${smallest} (${smallestSize} bytes)`);
|
|
789
|
+
const buffer = fs.readFileSync(smallest);
|
|
790
|
+
const gz = zlib.gzipSync(buffer);
|
|
791
|
+
const sizeKb = Number((gz.length / 1024).toFixed(1));
|
|
792
|
+
log.verbose(`Gzipped size: ${gz.length} bytes (${sizeKb} KB)`);
|
|
793
|
+
return sizeKb;
|
|
794
|
+
} catch (e) {
|
|
795
|
+
log.verbose(`Failed to compute gzipped size for ${dir}: ${e}`);
|
|
796
|
+
throw e;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
function listFolder(basePath = process.cwd(), filter) {
|
|
800
|
+
const log = logger.for(listFolder);
|
|
801
|
+
try {
|
|
802
|
+
if (!fs.existsSync(basePath)) return [];
|
|
803
|
+
const entries = fs.readdirSync(basePath, {
|
|
804
|
+
withFileTypes: true
|
|
805
|
+
});
|
|
806
|
+
const names = entries.filter(d => filter ? filter(d.name, d) : true).map(d => d.name);
|
|
807
|
+
return names;
|
|
808
|
+
} catch (e) {
|
|
809
|
+
log.verbose(`Failed to list folder ${basePath}: ${e}`);
|
|
810
|
+
return [];
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
function listNodeModulesPackages(basePath = path.join(process.cwd(), "node_modules")) {
|
|
814
|
+
const log = logger.for(listNodeModulesPackages);
|
|
815
|
+
try {
|
|
816
|
+
if (!fs.existsSync(basePath)) return [];
|
|
817
|
+
const entries = fs.readdirSync(basePath, {
|
|
818
|
+
withFileTypes: true
|
|
819
|
+
});
|
|
820
|
+
const names = [];
|
|
821
|
+
for (const e of entries) {
|
|
822
|
+
try {
|
|
823
|
+
if (!e.isDirectory()) continue;
|
|
824
|
+
if (e.name.startsWith(".")) continue;
|
|
825
|
+
if (e.name.startsWith("@")) {
|
|
826
|
+
const scopePath = path.join(basePath, e.name);
|
|
827
|
+
try {
|
|
828
|
+
const scoped = fs.readdirSync(scopePath, {
|
|
829
|
+
withFileTypes: true
|
|
830
|
+
});
|
|
831
|
+
for (const s of scoped) {
|
|
832
|
+
if (s.isDirectory() && !s.name.startsWith(".")) {
|
|
833
|
+
names.push(`${e.name}/${s.name}`);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
} catch (err) {
|
|
837
|
+
log.verbose(`Failed to read scope ${scopePath}: ${err}`);
|
|
838
|
+
}
|
|
839
|
+
} else {
|
|
840
|
+
names.push(e.name);
|
|
841
|
+
}
|
|
842
|
+
} catch (err) {
|
|
843
|
+
log.verbose(`Skipping entry ${e.name} due to error: ${err}`);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
return names;
|
|
847
|
+
} catch (e) {
|
|
848
|
+
log.verbose(`Failed to list node_modules packages at ${basePath}: ${e}`);
|
|
849
|
+
return [];
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
const slogans = [ {
|
|
853
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
854
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
855
|
+
}, {
|
|
856
|
+
Slogan: "Full flavor, no jitters. That's Decaf-TS.",
|
|
857
|
+
Tags: "Coffee-themed, Cheerful"
|
|
858
|
+
}, {
|
|
859
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
860
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
861
|
+
}, {
|
|
862
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
863
|
+
Tags: "Coffee-themed, Branding"
|
|
864
|
+
}, {
|
|
865
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
866
|
+
Tags: "Coffee-themed, Chill"
|
|
867
|
+
}, {
|
|
868
|
+
Slogan: "All the kick, none of the crash.",
|
|
869
|
+
Tags: "Coffee-themed, Energetic"
|
|
870
|
+
}, {
|
|
871
|
+
Slogan: "Sip back and ship faster.",
|
|
872
|
+
Tags: "Coffee-themed, Fun"
|
|
873
|
+
}, {
|
|
874
|
+
Slogan: "Keep calm and code Decaf.",
|
|
875
|
+
Tags: "Coffee-themed, Playful"
|
|
876
|
+
}, {
|
|
877
|
+
Slogan: "Code without the caffeine shakes.",
|
|
878
|
+
Tags: "Coffee-themed, Humorous"
|
|
879
|
+
}, {
|
|
880
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
881
|
+
Tags: "Coffee-themed, Technical"
|
|
882
|
+
}, {
|
|
883
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
884
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
885
|
+
}, {
|
|
886
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
887
|
+
Tags: "Coffee-themed, Cheerful"
|
|
888
|
+
}, {
|
|
889
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
890
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
891
|
+
}, {
|
|
892
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
893
|
+
Tags: "Coffee-themed, Branding"
|
|
894
|
+
}, {
|
|
895
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
896
|
+
Tags: "Coffee-themed, Chill"
|
|
897
|
+
}, {
|
|
898
|
+
Slogan: "All the kick, none of the crash.",
|
|
899
|
+
Tags: "Coffee-themed, Energetic"
|
|
900
|
+
}, {
|
|
901
|
+
Slogan: "Sip back and ship faster.",
|
|
902
|
+
Tags: "Coffee-themed, Fun"
|
|
903
|
+
}, {
|
|
904
|
+
Slogan: "Keep calm and code Decaf.",
|
|
905
|
+
Tags: "Coffee-themed, Playful"
|
|
906
|
+
}, {
|
|
907
|
+
Slogan: "Code without the caffeine shakes.",
|
|
908
|
+
Tags: "Coffee-themed, Humorous"
|
|
909
|
+
}, {
|
|
910
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
911
|
+
Tags: "Coffee-themed, Technical"
|
|
912
|
+
}, {
|
|
913
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
914
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
915
|
+
}, {
|
|
916
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
917
|
+
Tags: "Coffee-themed, Cheerful"
|
|
918
|
+
}, {
|
|
919
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
920
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
921
|
+
}, {
|
|
922
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
923
|
+
Tags: "Coffee-themed, Branding"
|
|
924
|
+
}, {
|
|
925
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
926
|
+
Tags: "Coffee-themed, Chill"
|
|
927
|
+
}, {
|
|
928
|
+
Slogan: "All the kick, none of the crash.",
|
|
929
|
+
Tags: "Coffee-themed, Energetic"
|
|
930
|
+
}, {
|
|
931
|
+
Slogan: "Sip back and ship faster.",
|
|
932
|
+
Tags: "Coffee-themed, Fun"
|
|
933
|
+
}, {
|
|
934
|
+
Slogan: "Keep calm and code Decaf.",
|
|
935
|
+
Tags: "Coffee-themed, Playful"
|
|
936
|
+
}, {
|
|
937
|
+
Slogan: "Code without the caffeine shakes.",
|
|
938
|
+
Tags: "Coffee-themed, Humorous"
|
|
939
|
+
}, {
|
|
940
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
941
|
+
Tags: "Coffee-themed, Technical"
|
|
942
|
+
}, {
|
|
943
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
944
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
945
|
+
}, {
|
|
946
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
947
|
+
Tags: "Coffee-themed, Cheerful"
|
|
948
|
+
}, {
|
|
949
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
950
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
951
|
+
}, {
|
|
952
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
953
|
+
Tags: "Coffee-themed, Branding"
|
|
954
|
+
}, {
|
|
955
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
956
|
+
Tags: "Coffee-themed, Chill"
|
|
957
|
+
}, {
|
|
958
|
+
Slogan: "All the kick, none of the crash.",
|
|
959
|
+
Tags: "Coffee-themed, Energetic"
|
|
960
|
+
}, {
|
|
961
|
+
Slogan: "Sip back and ship faster.",
|
|
962
|
+
Tags: "Coffee-themed, Fun"
|
|
963
|
+
}, {
|
|
964
|
+
Slogan: "Keep calm and code Decaf.",
|
|
965
|
+
Tags: "Coffee-themed, Playful"
|
|
966
|
+
}, {
|
|
967
|
+
Slogan: "Code without the caffeine shakes.",
|
|
968
|
+
Tags: "Coffee-themed, Humorous"
|
|
969
|
+
}, {
|
|
970
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
971
|
+
Tags: "Coffee-themed, Technical"
|
|
972
|
+
}, {
|
|
973
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
974
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
975
|
+
}, {
|
|
976
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
977
|
+
Tags: "Coffee-themed, Cheerful"
|
|
978
|
+
}, {
|
|
979
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
980
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
981
|
+
}, {
|
|
982
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
983
|
+
Tags: "Coffee-themed, Branding"
|
|
984
|
+
}, {
|
|
985
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
986
|
+
Tags: "Coffee-themed, Chill"
|
|
987
|
+
}, {
|
|
988
|
+
Slogan: "All the kick, none of the crash.",
|
|
989
|
+
Tags: "Coffee-themed, Energetic"
|
|
990
|
+
}, {
|
|
991
|
+
Slogan: "Sip back and ship faster.",
|
|
992
|
+
Tags: "Coffee-themed, Fun"
|
|
993
|
+
}, {
|
|
994
|
+
Slogan: "Keep calm and code Decaf.",
|
|
995
|
+
Tags: "Coffee-themed, Playful"
|
|
996
|
+
}, {
|
|
997
|
+
Slogan: "Code without the caffeine shakes.",
|
|
998
|
+
Tags: "Coffee-themed, Humorous"
|
|
999
|
+
}, {
|
|
1000
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
1001
|
+
Tags: "Coffee-themed, Technical"
|
|
1002
|
+
}, {
|
|
1003
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
1004
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
1005
|
+
}, {
|
|
1006
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
1007
|
+
Tags: "Coffee-themed, Cheerful"
|
|
1008
|
+
}, {
|
|
1009
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
1010
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
1011
|
+
}, {
|
|
1012
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
1013
|
+
Tags: "Coffee-themed, Branding"
|
|
1014
|
+
}, {
|
|
1015
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
1016
|
+
Tags: "Coffee-themed, Chill"
|
|
1017
|
+
}, {
|
|
1018
|
+
Slogan: "All the kick, none of the crash.",
|
|
1019
|
+
Tags: "Coffee-themed, Energetic"
|
|
1020
|
+
}, {
|
|
1021
|
+
Slogan: "Sip back and ship faster.",
|
|
1022
|
+
Tags: "Coffee-themed, Fun"
|
|
1023
|
+
}, {
|
|
1024
|
+
Slogan: "Keep calm and code Decaf.",
|
|
1025
|
+
Tags: "Coffee-themed, Playful"
|
|
1026
|
+
}, {
|
|
1027
|
+
Slogan: "Code without the caffeine shakes.",
|
|
1028
|
+
Tags: "Coffee-themed, Humorous"
|
|
1029
|
+
}, {
|
|
1030
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
1031
|
+
Tags: "Coffee-themed, Technical"
|
|
1032
|
+
}, {
|
|
1033
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
1034
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
1035
|
+
}, {
|
|
1036
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
1037
|
+
Tags: "Coffee-themed, Cheerful"
|
|
1038
|
+
}, {
|
|
1039
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
1040
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
1041
|
+
}, {
|
|
1042
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
1043
|
+
Tags: "Coffee-themed, Branding"
|
|
1044
|
+
}, {
|
|
1045
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
1046
|
+
Tags: "Coffee-themed, Chill"
|
|
1047
|
+
}, {
|
|
1048
|
+
Slogan: "All the kick, none of the crash.",
|
|
1049
|
+
Tags: "Coffee-themed, Energetic"
|
|
1050
|
+
}, {
|
|
1051
|
+
Slogan: "Sip back and ship faster.",
|
|
1052
|
+
Tags: "Coffee-themed, Fun"
|
|
1053
|
+
}, {
|
|
1054
|
+
Slogan: "Keep calm and code Decaf.",
|
|
1055
|
+
Tags: "Coffee-themed, Playful"
|
|
1056
|
+
}, {
|
|
1057
|
+
Slogan: "Code without the caffeine shakes.",
|
|
1058
|
+
Tags: "Coffee-themed, Humorous"
|
|
1059
|
+
}, {
|
|
1060
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
1061
|
+
Tags: "Coffee-themed, Technical"
|
|
1062
|
+
}, {
|
|
1063
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
1064
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
1065
|
+
}, {
|
|
1066
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
1067
|
+
Tags: "Coffee-themed, Cheerful"
|
|
1068
|
+
}, {
|
|
1069
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
1070
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
1071
|
+
}, {
|
|
1072
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
1073
|
+
Tags: "Coffee-themed, Branding"
|
|
1074
|
+
}, {
|
|
1075
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
1076
|
+
Tags: "Coffee-themed, Chill"
|
|
1077
|
+
}, {
|
|
1078
|
+
Slogan: "All the kick, none of the crash.",
|
|
1079
|
+
Tags: "Coffee-themed, Energetic"
|
|
1080
|
+
}, {
|
|
1081
|
+
Slogan: "Sip back and ship faster.",
|
|
1082
|
+
Tags: "Coffee-themed, Fun"
|
|
1083
|
+
}, {
|
|
1084
|
+
Slogan: "Keep calm and code Decaf.",
|
|
1085
|
+
Tags: "Coffee-themed, Playful"
|
|
1086
|
+
}, {
|
|
1087
|
+
Slogan: "Code without the caffeine shakes.",
|
|
1088
|
+
Tags: "Coffee-themed, Humorous"
|
|
1089
|
+
}, {
|
|
1090
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
1091
|
+
Tags: "Coffee-themed, Technical"
|
|
1092
|
+
}, {
|
|
1093
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
1094
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
1095
|
+
}, {
|
|
1096
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
1097
|
+
Tags: "Coffee-themed, Cheerful"
|
|
1098
|
+
}, {
|
|
1099
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
1100
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
1101
|
+
}, {
|
|
1102
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
1103
|
+
Tags: "Coffee-themed, Branding"
|
|
1104
|
+
}, {
|
|
1105
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
1106
|
+
Tags: "Coffee-themed, Chill"
|
|
1107
|
+
}, {
|
|
1108
|
+
Slogan: "All the kick, none of the crash.",
|
|
1109
|
+
Tags: "Coffee-themed, Energetic"
|
|
1110
|
+
}, {
|
|
1111
|
+
Slogan: "Sip back and ship faster.",
|
|
1112
|
+
Tags: "Coffee-themed, Fun"
|
|
1113
|
+
}, {
|
|
1114
|
+
Slogan: "Keep calm and code Decaf.",
|
|
1115
|
+
Tags: "Coffee-themed, Playful"
|
|
1116
|
+
}, {
|
|
1117
|
+
Slogan: "Code without the caffeine shakes.",
|
|
1118
|
+
Tags: "Coffee-themed, Humorous"
|
|
1119
|
+
}, {
|
|
1120
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
1121
|
+
Tags: "Coffee-themed, Technical"
|
|
1122
|
+
}, {
|
|
1123
|
+
Slogan: "No caffeine, no chaos. Just clean code.",
|
|
1124
|
+
Tags: "Coffee-themed, Calm, Tech"
|
|
1125
|
+
}, {
|
|
1126
|
+
Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
|
|
1127
|
+
Tags: "Coffee-themed, Cheerful"
|
|
1128
|
+
}, {
|
|
1129
|
+
Slogan: "Chill fullstack. Powered by Decaf.",
|
|
1130
|
+
Tags: "Coffee-themed, Fun, Tech"
|
|
1131
|
+
}, {
|
|
1132
|
+
Slogan: "Decaf-TS: Brewed for calm code.",
|
|
1133
|
+
Tags: "Coffee-themed, Branding"
|
|
1134
|
+
}, {
|
|
1135
|
+
Slogan: "Smooth as your morning Decaf.",
|
|
1136
|
+
Tags: "Coffee-themed, Chill"
|
|
1137
|
+
}, {
|
|
1138
|
+
Slogan: "All the kick, none of the crash.",
|
|
1139
|
+
Tags: "Coffee-themed, Energetic"
|
|
1140
|
+
}, {
|
|
1141
|
+
Slogan: "Sip back and ship faster.",
|
|
1142
|
+
Tags: "Coffee-themed, Fun"
|
|
1143
|
+
}, {
|
|
1144
|
+
Slogan: "Keep calm and code Decaf.",
|
|
1145
|
+
Tags: "Coffee-themed, Playful"
|
|
1146
|
+
}, {
|
|
1147
|
+
Slogan: "Code without the caffeine shakes.",
|
|
1148
|
+
Tags: "Coffee-themed, Humorous"
|
|
1149
|
+
}, {
|
|
1150
|
+
Slogan: "Your fullstack, decaffeinated.",
|
|
1151
|
+
Tags: "Coffee-themed, Technical"
|
|
1152
|
+
}, {
|
|
1153
|
+
Slogan: "Decaf-TS: Where smart contracts meet smart interfaces.",
|
|
1154
|
+
Tags: "Blockchain, Smart Contracts, Tech"
|
|
1155
|
+
}, {
|
|
1156
|
+
Slogan: "Ship dApps without the stress.",
|
|
1157
|
+
Tags: "Blockchain, Cheerful, Developer"
|
|
1158
|
+
}, {
|
|
1159
|
+
Slogan: "No CRUD, no problem — Decaf your data.",
|
|
1160
|
+
Tags: "Data, No-CRUD, Chill"
|
|
1161
|
+
}, {
|
|
1162
|
+
Slogan: "From DID to UI, without breaking a sweat.",
|
|
1163
|
+
Tags: "DID, SSI, UI, Calm"
|
|
1164
|
+
}, {
|
|
1165
|
+
Slogan: "Decaf-TS: Your frontend already understands your smart contract.",
|
|
1166
|
+
Tags: "Smart Contracts, DX, Magic"
|
|
1167
|
+
}, {
|
|
1168
|
+
Slogan: "Self-sovereign by design. Productive by default.",
|
|
1169
|
+
Tags: "SSI, Developer, Calm"
|
|
1170
|
+
}, {
|
|
1171
|
+
Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
|
|
1172
|
+
Tags: "Blockchain, Multi-platform, Happy"
|
|
1173
|
+
}, {
|
|
1174
|
+
Slogan: "Data that defines its own destiny.",
|
|
1175
|
+
Tags: "SSI, Data-driven, Empowerment"
|
|
1176
|
+
}, {
|
|
1177
|
+
Slogan: "Goodbye CRUD, hello intent-based interfaces.",
|
|
1178
|
+
Tags: "No-CRUD, UI, Technical"
|
|
1179
|
+
}, {
|
|
1180
|
+
Slogan: "The smoothest path from DID to done.",
|
|
1181
|
+
Tags: "DID, Workflow, Chill"
|
|
1182
|
+
}, {
|
|
1183
|
+
Slogan: "Because your dApp deserves more than boilerplate.",
|
|
1184
|
+
Tags: "Blockchain, DevX, Efficiency"
|
|
1185
|
+
}, {
|
|
1186
|
+
Slogan: "Own your data. Own your flow.",
|
|
1187
|
+
Tags: "SSI, Control, Ownership"
|
|
1188
|
+
}, {
|
|
1189
|
+
Slogan: "Write logic like it belongs with the data — because it does.",
|
|
1190
|
+
Tags: "Data Logic, Developer, Smart"
|
|
1191
|
+
}, {
|
|
1192
|
+
Slogan: "From smart contracts to smarter frontends.",
|
|
1193
|
+
Tags: "Smart Contracts, UI, DX"
|
|
1194
|
+
}, {
|
|
1195
|
+
Slogan: "No caffeine. No CRUD. Just the future.",
|
|
1196
|
+
Tags: "No-CRUD, Coffee-themed, Futuristic"
|
|
1197
|
+
}, {
|
|
1198
|
+
Slogan: "The future of web3 UX is Decaf.",
|
|
1199
|
+
Tags: "Blockchain, UX, Vision"
|
|
1200
|
+
}, {
|
|
1201
|
+
Slogan: "Code with confidence. Govern with clarity.",
|
|
1202
|
+
Tags: "Blockchain, Governance, Calm"
|
|
1203
|
+
}, {
|
|
1204
|
+
Slogan: "Interfaces that obey the data, not the other way around.",
|
|
1205
|
+
Tags: "UI, Data Logic, Self-aware"
|
|
1206
|
+
}, {
|
|
1207
|
+
Slogan: "Brew business logic right into your bytes.",
|
|
1208
|
+
Tags: "Data Logic, Coffee-themed, Fun"
|
|
1209
|
+
}, {
|
|
1210
|
+
Slogan: "DIDs done differently — and delightfully.",
|
|
1211
|
+
Tags: "DID, Self-Sovereign, Playful"
|
|
1212
|
+
}, {
|
|
1213
|
+
Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
|
|
1214
|
+
Tags: "Blockchain, Smart Contracts, Tech"
|
|
1215
|
+
}, {
|
|
1216
|
+
Slogan: "Ship dApps without the stress.",
|
|
1217
|
+
Tags: "Blockchain, Cheerful, Developer"
|
|
1218
|
+
}, {
|
|
1219
|
+
Slogan: "No boilerplate, no problem — Decaf-TS your data.",
|
|
1220
|
+
Tags: "Data, No-CRUD, Chill"
|
|
1221
|
+
}, {
|
|
1222
|
+
Slogan: "From DID to UI, without breaking a sweat.",
|
|
1223
|
+
Tags: "DID, SSI, UI, Calm"
|
|
1224
|
+
}, {
|
|
1225
|
+
Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
|
|
1226
|
+
Tags: "Smart Contracts, DX, Magic"
|
|
1227
|
+
}, {
|
|
1228
|
+
Slogan: "Self-sovereign by design. Productive by default.",
|
|
1229
|
+
Tags: "SSI, Developer, Calm"
|
|
1230
|
+
}, {
|
|
1231
|
+
Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
|
|
1232
|
+
Tags: "Blockchain, Multi-platform, Happy"
|
|
1233
|
+
}, {
|
|
1234
|
+
Slogan: "Data that defines its own destiny.",
|
|
1235
|
+
Tags: "SSI, Data-driven, Empowerment"
|
|
1236
|
+
}, {
|
|
1237
|
+
Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
|
|
1238
|
+
Tags: "No-CRUD, UI, Technical"
|
|
1239
|
+
}, {
|
|
1240
|
+
Slogan: "The smoothest path from DID to done.",
|
|
1241
|
+
Tags: "DID, Workflow, Chill"
|
|
1242
|
+
}, {
|
|
1243
|
+
Slogan: "Because your dApp deserves more than boilerplate.",
|
|
1244
|
+
Tags: "Blockchain, DevX, Efficiency"
|
|
1245
|
+
}, {
|
|
1246
|
+
Slogan: "Own your data. Own your flow.",
|
|
1247
|
+
Tags: "SSI, Control, Ownership"
|
|
1248
|
+
}, {
|
|
1249
|
+
Slogan: "Write logic like it belongs with the data — because it does.",
|
|
1250
|
+
Tags: "Data Logic, Developer, Smart"
|
|
1251
|
+
}, {
|
|
1252
|
+
Slogan: "From blockchain contracts to smarter frontends.",
|
|
1253
|
+
Tags: "Smart Contracts, UI, DX"
|
|
1254
|
+
}, {
|
|
1255
|
+
Slogan: "No caffeine. No boilerplate. Just the future.",
|
|
1256
|
+
Tags: "No-CRUD, Coffee-themed, Futuristic"
|
|
1257
|
+
}, {
|
|
1258
|
+
Slogan: "The future of web3 UX is Decaf-TS.",
|
|
1259
|
+
Tags: "Blockchain, UX, Vision"
|
|
1260
|
+
}, {
|
|
1261
|
+
Slogan: "Code with confidence. Govern with clarity.",
|
|
1262
|
+
Tags: "Blockchain, Governance, Calm"
|
|
1263
|
+
}, {
|
|
1264
|
+
Slogan: "Interfaces that obey the data, not the other way around.",
|
|
1265
|
+
Tags: "UI, Data Logic, Self-aware"
|
|
1266
|
+
}, {
|
|
1267
|
+
Slogan: "Brew business logic right into your bytes.",
|
|
1268
|
+
Tags: "Data Logic, Coffee-themed, Fun"
|
|
1269
|
+
}, {
|
|
1270
|
+
Slogan: "DIDs done differently — and delightfully.",
|
|
1271
|
+
Tags: "DID, Self-Sovereign, Playful"
|
|
1272
|
+
}, {
|
|
1273
|
+
Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
|
|
1274
|
+
Tags: "Blockchain, Smart Contracts, Tech"
|
|
1275
|
+
}, {
|
|
1276
|
+
Slogan: "Ship dApps without the stress.",
|
|
1277
|
+
Tags: "Blockchain, Cheerful, Developer"
|
|
1278
|
+
}, {
|
|
1279
|
+
Slogan: "No boilerplate, no problem — Decaf-TS your data.",
|
|
1280
|
+
Tags: "Data, No-CRUD, Chill"
|
|
1281
|
+
}, {
|
|
1282
|
+
Slogan: "From DID to UI, without breaking a sweat.",
|
|
1283
|
+
Tags: "DID, SSI, UI, Calm"
|
|
1284
|
+
}, {
|
|
1285
|
+
Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
|
|
1286
|
+
Tags: "Smart Contracts, DX, Magic"
|
|
1287
|
+
}, {
|
|
1288
|
+
Slogan: "Self-sovereign by design. Productive by default.",
|
|
1289
|
+
Tags: "SSI, Developer, Calm"
|
|
1290
|
+
}, {
|
|
1291
|
+
Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
|
|
1292
|
+
Tags: "Blockchain, Multi-platform, Happy"
|
|
1293
|
+
}, {
|
|
1294
|
+
Slogan: "Data that defines its own destiny.",
|
|
1295
|
+
Tags: "SSI, Data-driven, Empowerment"
|
|
1296
|
+
}, {
|
|
1297
|
+
Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
|
|
1298
|
+
Tags: "No-CRUD, UI, Technical"
|
|
1299
|
+
}, {
|
|
1300
|
+
Slogan: "The smoothest path from DID to done.",
|
|
1301
|
+
Tags: "DID, Workflow, Chill"
|
|
1302
|
+
}, {
|
|
1303
|
+
Slogan: "Because your dApp deserves more than boilerplate.",
|
|
1304
|
+
Tags: "Blockchain, DevX, Efficiency"
|
|
1305
|
+
}, {
|
|
1306
|
+
Slogan: "Own your data. Own your flow.",
|
|
1307
|
+
Tags: "SSI, Control, Ownership"
|
|
1308
|
+
}, {
|
|
1309
|
+
Slogan: "Write logic like it belongs with the data — because it does.",
|
|
1310
|
+
Tags: "Data Logic, Developer, Smart"
|
|
1311
|
+
}, {
|
|
1312
|
+
Slogan: "From blockchain contracts to smarter frontends.",
|
|
1313
|
+
Tags: "Smart Contracts, UI, DX"
|
|
1314
|
+
}, {
|
|
1315
|
+
Slogan: "No caffeine. No boilerplate. Just the future.",
|
|
1316
|
+
Tags: "No-CRUD, Coffee-themed, Futuristic"
|
|
1317
|
+
}, {
|
|
1318
|
+
Slogan: "The future of web3 UX is Decaf-TS.",
|
|
1319
|
+
Tags: "Blockchain, UX, Vision"
|
|
1320
|
+
}, {
|
|
1321
|
+
Slogan: "Code with confidence. Govern with clarity.",
|
|
1322
|
+
Tags: "Blockchain, Governance, Calm"
|
|
1323
|
+
}, {
|
|
1324
|
+
Slogan: "Interfaces that obey the data, not the other way around.",
|
|
1325
|
+
Tags: "UI, Data Logic, Self-aware"
|
|
1326
|
+
}, {
|
|
1327
|
+
Slogan: "Brew business logic right into your bytes.",
|
|
1328
|
+
Tags: "Data Logic, Coffee-themed, Fun"
|
|
1329
|
+
}, {
|
|
1330
|
+
Slogan: "DIDs done differently — and delightfully.",
|
|
1331
|
+
Tags: "DID, Self-Sovereign, Playful"
|
|
1332
|
+
}, {
|
|
1333
|
+
Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
|
|
1334
|
+
Tags: "Blockchain, Smart Contracts, Tech"
|
|
1335
|
+
}, {
|
|
1336
|
+
Slogan: "Ship dApps without the stress.",
|
|
1337
|
+
Tags: "Blockchain, Cheerful, Developer"
|
|
1338
|
+
}, {
|
|
1339
|
+
Slogan: "No boilerplate, no problem — Decaf-TS your data.",
|
|
1340
|
+
Tags: "Data, No-CRUD, Chill"
|
|
1341
|
+
}, {
|
|
1342
|
+
Slogan: "From DID to UI, without breaking a sweat.",
|
|
1343
|
+
Tags: "DID, SSI, UI, Calm"
|
|
1344
|
+
}, {
|
|
1345
|
+
Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
|
|
1346
|
+
Tags: "Smart Contracts, DX, Magic"
|
|
1347
|
+
}, {
|
|
1348
|
+
Slogan: "Self-sovereign by design. Productive by default.",
|
|
1349
|
+
Tags: "SSI, Developer, Calm"
|
|
1350
|
+
}, {
|
|
1351
|
+
Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
|
|
1352
|
+
Tags: "Blockchain, Multi-platform, Happy"
|
|
1353
|
+
}, {
|
|
1354
|
+
Slogan: "Data that defines its own destiny.",
|
|
1355
|
+
Tags: "SSI, Data-driven, Empowerment"
|
|
1356
|
+
}, {
|
|
1357
|
+
Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
|
|
1358
|
+
Tags: "No-CRUD, UI, Technical"
|
|
1359
|
+
}, {
|
|
1360
|
+
Slogan: "The smoothest path from DID to done.",
|
|
1361
|
+
Tags: "DID, Workflow, Chill"
|
|
1362
|
+
}, {
|
|
1363
|
+
Slogan: "Because your dApp deserves more than boilerplate.",
|
|
1364
|
+
Tags: "Blockchain, DevX, Efficiency"
|
|
1365
|
+
}, {
|
|
1366
|
+
Slogan: "Own your data. Own your flow.",
|
|
1367
|
+
Tags: "SSI, Control, Ownership"
|
|
1368
|
+
}, {
|
|
1369
|
+
Slogan: "Write logic like it belongs with the data — because it does.",
|
|
1370
|
+
Tags: "Data Logic, Developer, Smart"
|
|
1371
|
+
}, {
|
|
1372
|
+
Slogan: "From blockchain contracts to smarter frontends.",
|
|
1373
|
+
Tags: "Smart Contracts, UI, DX"
|
|
1374
|
+
}, {
|
|
1375
|
+
Slogan: "No caffeine. No boilerplate. Just the future.",
|
|
1376
|
+
Tags: "No-CRUD, Coffee-themed, Futuristic"
|
|
1377
|
+
}, {
|
|
1378
|
+
Slogan: "The future of web3 UX is Decaf-TS.",
|
|
1379
|
+
Tags: "Blockchain, UX, Vision"
|
|
1380
|
+
}, {
|
|
1381
|
+
Slogan: "Code with confidence. Govern with clarity.",
|
|
1382
|
+
Tags: "Blockchain, Governance, Calm"
|
|
1383
|
+
}, {
|
|
1384
|
+
Slogan: "Interfaces that obey the data, not the other way around.",
|
|
1385
|
+
Tags: "UI, Data Logic, Self-aware"
|
|
1386
|
+
}, {
|
|
1387
|
+
Slogan: "Brew business logic right into your bytes.",
|
|
1388
|
+
Tags: "Data Logic, Coffee-themed, Fun"
|
|
1389
|
+
}, {
|
|
1390
|
+
Slogan: "DIDs done differently — and delightfully.",
|
|
1391
|
+
Tags: "DID, Self-Sovereign, Playful"
|
|
1392
|
+
}, {
|
|
1393
|
+
Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
|
|
1394
|
+
Tags: "Blockchain, Smart Contracts, Tech"
|
|
1395
|
+
}, {
|
|
1396
|
+
Slogan: "Ship dApps without the stress.",
|
|
1397
|
+
Tags: "Blockchain, Cheerful, Developer"
|
|
1398
|
+
}, {
|
|
1399
|
+
Slogan: "No boilerplate, no problem — Decaf-TS your data.",
|
|
1400
|
+
Tags: "Data, No-CRUD, Chill"
|
|
1401
|
+
}, {
|
|
1402
|
+
Slogan: "From DID to UI, without breaking a sweat.",
|
|
1403
|
+
Tags: "DID, SSI, UI, Calm"
|
|
1404
|
+
}, {
|
|
1405
|
+
Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
|
|
1406
|
+
Tags: "Smart Contracts, DX, Magic"
|
|
1407
|
+
}, {
|
|
1408
|
+
Slogan: "Self-sovereign by design. Productive by default.",
|
|
1409
|
+
Tags: "SSI, Developer, Calm"
|
|
1410
|
+
}, {
|
|
1411
|
+
Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
|
|
1412
|
+
Tags: "Blockchain, Multi-platform, Happy"
|
|
1413
|
+
}, {
|
|
1414
|
+
Slogan: "Data that defines its own destiny.",
|
|
1415
|
+
Tags: "SSI, Data-driven, Empowerment"
|
|
1416
|
+
}, {
|
|
1417
|
+
Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
|
|
1418
|
+
Tags: "No-CRUD, UI, Technical"
|
|
1419
|
+
}, {
|
|
1420
|
+
Slogan: "The smoothest path from DID to done.",
|
|
1421
|
+
Tags: "DID, Workflow, Chill"
|
|
1422
|
+
}, {
|
|
1423
|
+
Slogan: "Because your dApp deserves more than boilerplate.",
|
|
1424
|
+
Tags: "Blockchain, DevX, Efficiency"
|
|
1425
|
+
}, {
|
|
1426
|
+
Slogan: "Own your data. Own your flow.",
|
|
1427
|
+
Tags: "SSI, Control, Ownership"
|
|
1428
|
+
}, {
|
|
1429
|
+
Slogan: "Write logic like it belongs with the data — because it does.",
|
|
1430
|
+
Tags: "Data Logic, Developer, Smart"
|
|
1431
|
+
}, {
|
|
1432
|
+
Slogan: "From blockchain contracts to smarter frontends.",
|
|
1433
|
+
Tags: "Smart Contracts, UI, DX"
|
|
1434
|
+
}, {
|
|
1435
|
+
Slogan: "No caffeine. No boilerplate. Just the future.",
|
|
1436
|
+
Tags: "No-CRUD, Coffee-themed, Futuristic"
|
|
1437
|
+
}, {
|
|
1438
|
+
Slogan: "The future of web3 UX is Decaf-TS.",
|
|
1439
|
+
Tags: "Blockchain, UX, Vision"
|
|
1440
|
+
}, {
|
|
1441
|
+
Slogan: "Code with confidence. Govern with clarity.",
|
|
1442
|
+
Tags: "Blockchain, Governance, Calm"
|
|
1443
|
+
}, {
|
|
1444
|
+
Slogan: "Interfaces that obey the data, not the other way around.",
|
|
1445
|
+
Tags: "UI, Data Logic, Self-aware"
|
|
1446
|
+
}, {
|
|
1447
|
+
Slogan: "Brew business logic right into your bytes.",
|
|
1448
|
+
Tags: "Data Logic, Coffee-themed, Fun"
|
|
1449
|
+
}, {
|
|
1450
|
+
Slogan: "DIDs done differently — and delightfully.",
|
|
1451
|
+
Tags: "DID, Self-Sovereign, Playful"
|
|
1452
|
+
} ];
|
|
1453
|
+
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" ];
|
|
1454
|
+
function printBanner(logger) {
|
|
1455
|
+
const message = getSlogan();
|
|
1456
|
+
const banner = `# ░▒▓███████▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓██████▓▒░ ░▒▓████████▓▒░ ░▒▓████████▓▒░ ░▒▓███████▓▒░ \n# ( ( ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# ) ) ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# [=======] ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓██████▓▒░ \n# \`-----´ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# ░▒▓███████▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓███████▓▒░ \n#`.split("\n");
|
|
1457
|
+
const maxLength = banner.reduce((max, line) => Math.max(max, line.length), 0);
|
|
1458
|
+
banner.push(`# ${message.padStart(maxLength - 3)}`);
|
|
1459
|
+
banner.forEach((line, index) => {
|
|
1460
|
+
(logger ? logger.info.bind(logger) : console.log.bind(console))(styledStringBuilder.style(line || "").raw(colors[index]).text);
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
function getSlogan(i) {
|
|
1464
|
+
try {
|
|
1465
|
+
i = typeof i === "undefined" ? Math.floor(Math.random() * slogans.length) : i;
|
|
1466
|
+
return slogans[i].Slogan;
|
|
1467
|
+
} catch (error) {
|
|
1468
|
+
throw new Error(`Failed to retrieve slogans: ${error}`);
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
class Command extends logging.LoggedClass {
|
|
1472
|
+
constructor(name, inputs = {}, requirements = []) {
|
|
1473
|
+
super();
|
|
1474
|
+
this.name = name;
|
|
1475
|
+
this.inputs = inputs;
|
|
1476
|
+
this.requirements = requirements;
|
|
1477
|
+
if (!Command.log) {
|
|
1478
|
+
Object.defineProperty(Command, "log", {
|
|
1479
|
+
writable: false,
|
|
1480
|
+
value: logging.Logging.for(Command.name)
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
this.inputs = Object.assign({}, DefaultCommandOptions, inputs);
|
|
1484
|
+
}
|
|
1485
|
+
async checkRequirements() {
|
|
1486
|
+
const {prod: prod, dev: dev, peer: peer} = await getDependencies();
|
|
1487
|
+
const missing = [];
|
|
1488
|
+
const fullList = Array.from(new Set([ ...prod, ...dev, ...peer ]).values()).map(d => d.name);
|
|
1489
|
+
for (const dep of this.requirements) if (!fullList.includes(dep)) missing.push(dep);
|
|
1490
|
+
if (!missing.length) return;
|
|
1491
|
+
}
|
|
1492
|
+
help(args) {
|
|
1493
|
+
return this.log.info(`This is help. I'm no use because I should have been overridden.`);
|
|
1494
|
+
}
|
|
1495
|
+
async execute() {
|
|
1496
|
+
const args = UserInput.parseArgs(this.inputs);
|
|
1497
|
+
const env = logging.LoggedEnvironment.accumulate(DefaultCommandValues).accumulate(args.values);
|
|
1498
|
+
const {version: version, help: help, banner: banner} = env;
|
|
1499
|
+
if (version) {
|
|
1500
|
+
return getPackageVersion();
|
|
1501
|
+
}
|
|
1502
|
+
if (help) {
|
|
1503
|
+
return this.help(args);
|
|
1504
|
+
}
|
|
1505
|
+
if (banner) printBanner(this.log.for(printBanner, {
|
|
1506
|
+
timestamp: false,
|
|
1507
|
+
style: false,
|
|
1508
|
+
context: false,
|
|
1509
|
+
logLevel: false
|
|
1510
|
+
}));
|
|
1511
|
+
let result;
|
|
1512
|
+
try {
|
|
1513
|
+
result = await this.run(env);
|
|
1514
|
+
} catch (e) {
|
|
1515
|
+
throw e;
|
|
1516
|
+
}
|
|
1517
|
+
return result;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
class HttpClient {
|
|
1521
|
+
static {
|
|
1522
|
+
this.log = logging.Logging.for(HttpClient);
|
|
1523
|
+
}
|
|
1524
|
+
static async downloadFile(url) {
|
|
1525
|
+
return new Promise((resolve, reject) => {
|
|
1526
|
+
function request(url) {
|
|
1527
|
+
url = encodeURI(url);
|
|
1528
|
+
https.get(url, res => {
|
|
1529
|
+
if (res.statusCode === 301 || res.statusCode === 307) return request(res.headers.location);
|
|
1530
|
+
if (res.statusCode !== 200) {
|
|
1531
|
+
HttpClient.log.error(`Failed to fetch ${url} (status: ${res.statusCode})`);
|
|
1532
|
+
return reject(new Error(`Failed to fetch ${url}`));
|
|
1533
|
+
}
|
|
1534
|
+
let data = "";
|
|
1535
|
+
res.on("data", chunk => {
|
|
1536
|
+
data += chunk;
|
|
1537
|
+
});
|
|
1538
|
+
res.on("error", error => {
|
|
1539
|
+
reject(error);
|
|
1540
|
+
});
|
|
1541
|
+
res.on("end", () => {
|
|
1542
|
+
resolve(data);
|
|
1543
|
+
});
|
|
1544
|
+
});
|
|
1545
|
+
}
|
|
1546
|
+
request(url);
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
const defaultCanvasOptions = {
|
|
1551
|
+
width: 1200,
|
|
1552
|
+
height: 260,
|
|
1553
|
+
padding: 32,
|
|
1554
|
+
backgroundColor: "#0f172a",
|
|
1555
|
+
headerFont: "bold 18px 'Segoe UI', sans-serif",
|
|
1556
|
+
rowFont: "14px 'Segoe UI', sans-serif",
|
|
1557
|
+
headerColor: "#f8fafc",
|
|
1558
|
+
rowColor: "#cbd5f5"
|
|
1559
|
+
};
|
|
1560
|
+
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
1561
|
+
const perfDebugEnabled = process.env.PERF_VERBOSE === "true";
|
|
1562
|
+
const debugLog = (...args) => {
|
|
1563
|
+
if (perfDebugEnabled) {
|
|
1564
|
+
console.debug(...args);
|
|
1565
|
+
}
|
|
1566
|
+
};
|
|
1567
|
+
const formatTable = (title, headers, rows) => {
|
|
1568
|
+
const columnWidths = headers.map((header, index) => Math.max(header.length, ...rows.map(row => row[index]?.length ?? 0)));
|
|
1569
|
+
const formatRow = values => "| " + values.map((value, index) => value.padEnd(columnWidths[index])).join(" | ") + " |";
|
|
1570
|
+
const headerLine = formatRow(headers);
|
|
1571
|
+
const divider = "| " + columnWidths.map(width => "-".repeat(width)).join(" | ") + " |";
|
|
1572
|
+
const body = rows.map(formatRow).join("\n");
|
|
1573
|
+
return `${title}\n${headerLine}\n${divider}\n${body}`;
|
|
1574
|
+
};
|
|
1575
|
+
const ensureDirectory = async targetPath => {
|
|
1576
|
+
await promises.mkdir(path.dirname(targetPath), {
|
|
1577
|
+
recursive: true
|
|
1578
|
+
});
|
|
1579
|
+
};
|
|
1580
|
+
const renderMetricsTableToCanvas = async (headers, rows, options, outputPath) => {
|
|
1581
|
+
const config = {
|
|
1582
|
+
...defaultCanvasOptions,
|
|
1583
|
+
...options
|
|
1584
|
+
};
|
|
1585
|
+
let createCanvas;
|
|
1586
|
+
try {
|
|
1587
|
+
const canvasModule = await import("canvas");
|
|
1588
|
+
createCanvas = canvasModule.createCanvas;
|
|
1589
|
+
} catch (error) {
|
|
1590
|
+
console.warn("[PerfRunner] Canvas module not available, skipping chart.", error);
|
|
1591
|
+
return;
|
|
1592
|
+
}
|
|
1593
|
+
const canvas = createCanvas(config.width, config.height);
|
|
1594
|
+
const ctx = canvas.getContext("2d");
|
|
1595
|
+
ctx.fillStyle = config.backgroundColor;
|
|
1596
|
+
ctx.fillRect(0, 0, config.width, config.height);
|
|
1597
|
+
ctx.font = config.headerFont;
|
|
1598
|
+
ctx.fillStyle = config.headerColor;
|
|
1599
|
+
const columnWidth = (config.width - config.padding * 2) / headers.length;
|
|
1600
|
+
const headerY = config.padding + 24;
|
|
1601
|
+
headers.forEach((header, index) => {
|
|
1602
|
+
ctx.fillText(header, config.padding + columnWidth * index, headerY);
|
|
1603
|
+
});
|
|
1604
|
+
ctx.font = config.rowFont;
|
|
1605
|
+
ctx.fillStyle = config.rowColor;
|
|
1606
|
+
const rowHeight = 24;
|
|
1607
|
+
rows.forEach((row, rowIndex) => {
|
|
1608
|
+
const y = headerY + 12 + rowHeight * (rowIndex + 1);
|
|
1609
|
+
row.forEach((cell, cellIndex) => {
|
|
1610
|
+
ctx.fillText(cell, config.padding + columnWidth * cellIndex, y);
|
|
1611
|
+
});
|
|
1612
|
+
});
|
|
1613
|
+
await ensureDirectory(outputPath);
|
|
1614
|
+
await promises.writeFile(outputPath, canvas.toBuffer("image/png"));
|
|
1615
|
+
console.log(`Stored performance chart at ${outputPath}`);
|
|
1616
|
+
};
|
|
1617
|
+
class PerformanceRunner {
|
|
1618
|
+
constructor(scenario) {
|
|
1619
|
+
this.scenario = scenario;
|
|
1620
|
+
}
|
|
1621
|
+
async run() {
|
|
1622
|
+
if (this.scenario.initialize) {
|
|
1623
|
+
await this.scenario.initialize();
|
|
1624
|
+
}
|
|
1625
|
+
let phaseCounter = 0;
|
|
1626
|
+
const queue = this.scenario.phases.map(phase => ({
|
|
1627
|
+
phase: phase,
|
|
1628
|
+
phaseNumber: ++phaseCounter
|
|
1629
|
+
}));
|
|
1630
|
+
const results = [];
|
|
1631
|
+
while (queue.length) {
|
|
1632
|
+
const item = queue.shift();
|
|
1633
|
+
const phase = item.phase;
|
|
1634
|
+
const context = this.mergeContext(phase);
|
|
1635
|
+
console.info(`[PerfRunner] Starting phase #${item.phaseNumber} "${phase.name}"`, {
|
|
1636
|
+
iterations: phase.config.iterations,
|
|
1637
|
+
mode: phase.config.mode,
|
|
1638
|
+
concurrency: phase.config.concurrency,
|
|
1639
|
+
burst: phase.config.burst
|
|
1640
|
+
});
|
|
1641
|
+
const result = await this.runPhase(phase, context);
|
|
1642
|
+
console.info(`[PerfRunner] Completed phase #${item.phaseNumber} "${phase.name}"`, {
|
|
1643
|
+
total: result.aggregated.totalDurationMs.toFixed(2),
|
|
1644
|
+
avg: result.aggregated.averageMs.toFixed(2),
|
|
1645
|
+
failureCount: result.aggregated.failureCount
|
|
1646
|
+
});
|
|
1647
|
+
results.push(result);
|
|
1648
|
+
if (phase.generator) {
|
|
1649
|
+
const historySnapshot = [ ...results ];
|
|
1650
|
+
const metadata = {
|
|
1651
|
+
phaseNumber: item.phaseNumber,
|
|
1652
|
+
phaseName: phase.name,
|
|
1653
|
+
iterationCount: phase.config.iterations,
|
|
1654
|
+
burstSegments: result.segmentCount,
|
|
1655
|
+
segmentCount: result.segmentCount,
|
|
1656
|
+
mode: phase.config.mode,
|
|
1657
|
+
history: historySnapshot
|
|
1658
|
+
};
|
|
1659
|
+
const generatorResult = await phase.generator({
|
|
1660
|
+
result: result,
|
|
1661
|
+
history: historySnapshot,
|
|
1662
|
+
metadata: metadata
|
|
1663
|
+
});
|
|
1664
|
+
if (generatorResult) {
|
|
1665
|
+
const nextPhase = "config" in generatorResult ? {
|
|
1666
|
+
name: generatorResult.name ?? `${phase.name} → gen`,
|
|
1667
|
+
config: generatorResult.config,
|
|
1668
|
+
generator: phase.generator
|
|
1669
|
+
} : {
|
|
1670
|
+
name: `${phase.name} → gen`,
|
|
1671
|
+
config: generatorResult,
|
|
1672
|
+
generator: phase.generator
|
|
1673
|
+
};
|
|
1674
|
+
queue.push({
|
|
1675
|
+
phase: nextPhase,
|
|
1676
|
+
phaseNumber: ++phaseCounter
|
|
1677
|
+
});
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
await this.logSummary(results);
|
|
1682
|
+
return results;
|
|
1683
|
+
}
|
|
1684
|
+
async runPhase(phase, context) {
|
|
1685
|
+
await this.runWarmup(phase, context);
|
|
1686
|
+
const segments = this.buildSegmentIndices(phase.config.iterations, phase.config.burst);
|
|
1687
|
+
const collected = [];
|
|
1688
|
+
for (let segmentIndex = 0; segmentIndex < segments.length; segmentIndex += 1) {
|
|
1689
|
+
const indices = segments[segmentIndex];
|
|
1690
|
+
if (!indices.length) {
|
|
1691
|
+
continue;
|
|
1692
|
+
}
|
|
1693
|
+
debugLog(`[PerfRunner] Phase "${phase.name}" executing segment ${segmentIndex + 1}/${segments.length} (iterations ${indices[0]}-${indices[indices.length - 1]})`);
|
|
1694
|
+
const metrics = await this.executeSegment(this.scenario.handler, phase.config, context, indices);
|
|
1695
|
+
collected.push(...metrics);
|
|
1696
|
+
const burstInterval = phase.config.burst?.intervalMs;
|
|
1697
|
+
if (burstInterval && segmentIndex < segments.length - 1) {
|
|
1698
|
+
await delay(burstInterval);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
const sorted = [ ...collected ].sort((a, b) => a.iteration - b.iteration);
|
|
1702
|
+
const aggregated = this.aggregateMetrics(sorted);
|
|
1703
|
+
if (phase.config.pauseAfterMs) {
|
|
1704
|
+
await delay(phase.config.pauseAfterMs);
|
|
1705
|
+
}
|
|
1706
|
+
if (aggregated.failureCount > 0 && this.scenario.failOnError !== false) {
|
|
1707
|
+
throw new Error(`Phase ${phase.name} recorded ${aggregated.failureCount} failures`);
|
|
1708
|
+
}
|
|
1709
|
+
return {
|
|
1710
|
+
phase: phase,
|
|
1711
|
+
config: phase.config,
|
|
1712
|
+
iterationMetrics: sorted,
|
|
1713
|
+
aggregated: aggregated,
|
|
1714
|
+
context: context,
|
|
1715
|
+
segmentCount: segments.length
|
|
1716
|
+
};
|
|
1717
|
+
}
|
|
1718
|
+
async runWarmup(phase, context) {
|
|
1719
|
+
const warmup = phase.config.warmup;
|
|
1720
|
+
if (!warmup?.iterations) {
|
|
1721
|
+
return;
|
|
1722
|
+
}
|
|
1723
|
+
const handler = warmup.handler ?? this.scenario.handler;
|
|
1724
|
+
for (let index = 0; index < warmup.iterations; index += 1) {
|
|
1725
|
+
await handler({
|
|
1726
|
+
iteration: index,
|
|
1727
|
+
config: phase.config,
|
|
1728
|
+
loadFactor: this.computeLoadFactor(phase.config, index),
|
|
1729
|
+
context: context
|
|
1730
|
+
});
|
|
1731
|
+
if (warmup.delayBetweenIterationsMs && index < warmup.iterations - 1) {
|
|
1732
|
+
await delay(warmup.delayBetweenIterationsMs);
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
computeLoadFactor(config, iteration) {
|
|
1737
|
+
const base = config.loadStart ?? 1;
|
|
1738
|
+
const step = config.loadStep ?? 0;
|
|
1739
|
+
const multiplier = config.loadMultiplier ?? 1;
|
|
1740
|
+
return (base + step * iteration) * multiplier;
|
|
1741
|
+
}
|
|
1742
|
+
buildSegmentIndices(iterations, burst) {
|
|
1743
|
+
const total = Math.max(0, iterations);
|
|
1744
|
+
if (total === 0) {
|
|
1745
|
+
return [];
|
|
1746
|
+
}
|
|
1747
|
+
const chunk = burst?.size && burst.size > 0 ? Math.min(burst.size, total) : total;
|
|
1748
|
+
const segments = [];
|
|
1749
|
+
for (let cursor = 0; cursor < total; cursor += chunk) {
|
|
1750
|
+
const end = Math.min(total, cursor + chunk);
|
|
1751
|
+
segments.push(Array.from({
|
|
1752
|
+
length: end - cursor
|
|
1753
|
+
}, (_, idx) => cursor + idx));
|
|
1754
|
+
}
|
|
1755
|
+
return segments;
|
|
1756
|
+
}
|
|
1757
|
+
mergeContext(phase) {
|
|
1758
|
+
const baseContext = this.scenario.baseContext ?? {};
|
|
1759
|
+
const phaseContext = phase.config.context ?? {};
|
|
1760
|
+
return this.mergeContexts(baseContext, phaseContext);
|
|
1761
|
+
}
|
|
1762
|
+
mergeContexts(a, b) {
|
|
1763
|
+
return Object.assign({}, a, b);
|
|
1764
|
+
}
|
|
1765
|
+
async executeSegment(handler, config, context, indices) {
|
|
1766
|
+
if (!indices.length) {
|
|
1767
|
+
return [];
|
|
1768
|
+
}
|
|
1769
|
+
if (config.mode === "concurrent") {
|
|
1770
|
+
return this.collectConcurrent(handler, config, context, indices);
|
|
1771
|
+
}
|
|
1772
|
+
return this.collectSequential(handler, config, context, indices);
|
|
1773
|
+
}
|
|
1774
|
+
async collectSequential(handler, config, context, indices) {
|
|
1775
|
+
const metrics = [];
|
|
1776
|
+
const delayBetween = config.delayBetweenIterationsMs;
|
|
1777
|
+
for (let idx = 0; idx < indices.length; idx += 1) {
|
|
1778
|
+
metrics.push(await this.runIteration(handler, config, context, indices[idx]));
|
|
1779
|
+
if (delayBetween && idx < indices.length - 1) {
|
|
1780
|
+
await delay(delayBetween);
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
return metrics;
|
|
1784
|
+
}
|
|
1785
|
+
async collectConcurrent(handler, config, context, indices) {
|
|
1786
|
+
const concurrency = Math.max(1, Math.min(config.concurrency ?? indices.length, indices.length));
|
|
1787
|
+
const metrics = [];
|
|
1788
|
+
let pointer = 0;
|
|
1789
|
+
const worker = async () => {
|
|
1790
|
+
while (pointer < indices.length) {
|
|
1791
|
+
const iteration = indices[pointer];
|
|
1792
|
+
pointer += 1;
|
|
1793
|
+
metrics.push(await this.runIteration(handler, config, context, iteration));
|
|
1794
|
+
}
|
|
1795
|
+
};
|
|
1796
|
+
await Promise.all(Array.from({
|
|
1797
|
+
length: concurrency
|
|
1798
|
+
}, () => worker()));
|
|
1799
|
+
return metrics;
|
|
1800
|
+
}
|
|
1801
|
+
async runIteration(handler, config, context, iteration) {
|
|
1802
|
+
const loadFactor = this.computeLoadFactor(config, iteration);
|
|
1803
|
+
const stopwatch = new logging.StopWatch(true);
|
|
1804
|
+
let success = true;
|
|
1805
|
+
let meta;
|
|
1806
|
+
debugLog(`[PerfRunner] Iteration ${iteration} (phase=${config.metadata?.phaseName ?? "n/a"}, load=${loadFactor.toFixed(2)}) starting`);
|
|
1807
|
+
try {
|
|
1808
|
+
const result = await handler({
|
|
1809
|
+
iteration: iteration,
|
|
1810
|
+
config: config,
|
|
1811
|
+
loadFactor: loadFactor,
|
|
1812
|
+
context: context
|
|
1813
|
+
});
|
|
1814
|
+
if (typeof result?.success === "boolean") {
|
|
1815
|
+
success = result.success;
|
|
1816
|
+
}
|
|
1817
|
+
meta = result?.meta;
|
|
1818
|
+
} catch (error) {
|
|
1819
|
+
success = false;
|
|
1820
|
+
meta = {
|
|
1821
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1822
|
+
};
|
|
1823
|
+
}
|
|
1824
|
+
const durationMs = stopwatch.stop();
|
|
1825
|
+
debugLog(`[PerfRunner] Iteration ${iteration} complete in ${durationMs.toFixed(2)}ms, success=${success}`);
|
|
1826
|
+
return {
|
|
1827
|
+
iteration: iteration,
|
|
1828
|
+
durationMs: durationMs,
|
|
1829
|
+
success: success,
|
|
1830
|
+
meta: meta,
|
|
1831
|
+
loadFactor: loadFactor
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
aggregateMetrics(metrics) {
|
|
1835
|
+
if (metrics.length === 0) {
|
|
1836
|
+
return {
|
|
1837
|
+
totalDurationMs: 0,
|
|
1838
|
+
minMs: 0,
|
|
1839
|
+
maxMs: 0,
|
|
1840
|
+
averageMs: 0,
|
|
1841
|
+
successCount: 0,
|
|
1842
|
+
failureCount: 0,
|
|
1843
|
+
loadStart: 0,
|
|
1844
|
+
loadEnd: 0
|
|
1845
|
+
};
|
|
1846
|
+
}
|
|
1847
|
+
const totalDurationMs = metrics.reduce((acc, metric) => acc + metric.durationMs, 0);
|
|
1848
|
+
const minMs = Math.min(...metrics.map(metric => metric.durationMs));
|
|
1849
|
+
const maxMs = Math.max(...metrics.map(metric => metric.durationMs));
|
|
1850
|
+
const averageMs = totalDurationMs / metrics.length;
|
|
1851
|
+
const successCount = metrics.filter(metric => metric.success).length;
|
|
1852
|
+
const failureCount = metrics.length - successCount;
|
|
1853
|
+
const loadStart = metrics[0]?.loadFactor ?? 0;
|
|
1854
|
+
const loadEnd = metrics[metrics.length - 1]?.loadFactor ?? loadStart;
|
|
1855
|
+
return {
|
|
1856
|
+
totalDurationMs: totalDurationMs,
|
|
1857
|
+
minMs: minMs,
|
|
1858
|
+
maxMs: maxMs,
|
|
1859
|
+
averageMs: averageMs,
|
|
1860
|
+
successCount: successCount,
|
|
1861
|
+
failureCount: failureCount,
|
|
1862
|
+
loadStart: loadStart,
|
|
1863
|
+
loadEnd: loadEnd
|
|
1864
|
+
};
|
|
1865
|
+
}
|
|
1866
|
+
async logSummary(results) {
|
|
1867
|
+
if (!results.length) {
|
|
1868
|
+
return;
|
|
1869
|
+
}
|
|
1870
|
+
const headers = [ "Phase", "Mode", "Iterations", "Total ms", "Avg ms", "Min ms", "Max ms", "Success", "Failures", "Load range" ];
|
|
1871
|
+
const rows = results.map(result => [ result.phase.name, result.config.mode, result.config.iterations.toString(), result.aggregated.totalDurationMs.toFixed(2), result.aggregated.averageMs.toFixed(2), result.aggregated.minMs.toFixed(2), result.aggregated.maxMs.toFixed(2), result.aggregated.successCount.toString(), result.aggregated.failureCount.toString(), `${result.aggregated.loadStart.toFixed(2)} → ${result.aggregated.loadEnd.toFixed(2)}` ]);
|
|
1872
|
+
console.log(formatTable(`Performance summary for ${this.scenario.name}`, headers, rows));
|
|
1873
|
+
if (this.shouldRenderCanvas()) {
|
|
1874
|
+
const chartPath = this.scenario.canvasOutputPath ?? path.join(process.cwd(), "workdocs", "reports", "performance-runner.png");
|
|
1875
|
+
await renderMetricsTableToCanvas(headers, rows, this.scenario.canvasOptions ?? defaultCanvasOptions, chartPath);
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
shouldRenderCanvas() {
|
|
1879
|
+
return this.scenario.enableCanvas ?? Boolean(this.scenario.canvasOptions);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
function parseList(input) {
|
|
1883
|
+
if (!input) return [];
|
|
1884
|
+
if (Array.isArray(input)) return input.map(i => `${i}`.trim()).filter(Boolean);
|
|
1885
|
+
return `${input}`.split(",").map(p => p.trim()).filter(Boolean);
|
|
1886
|
+
}
|
|
1887
|
+
function packageToGlobal(name) {
|
|
1888
|
+
const withoutScope = name.replace(/^@/, "");
|
|
1889
|
+
const parts = withoutScope.split(/[/\-_.]+/).filter(Boolean);
|
|
1890
|
+
return parts.map((p, i) => i === 0 ? p.replace(/[^a-zA-Z0-9]/g, "") : `${p.charAt(0).toUpperCase()}${p.slice(1)}`).join("");
|
|
1891
|
+
}
|
|
1892
|
+
function getPackageDependencies() {
|
|
1893
|
+
let pkg;
|
|
1894
|
+
try {
|
|
1895
|
+
pkg = getPackage(process.cwd());
|
|
1896
|
+
} catch {
|
|
1897
|
+
pkg = undefined;
|
|
1898
|
+
}
|
|
1899
|
+
try {
|
|
1900
|
+
const hasDeps = pkg && (Object.keys(pkg.dependencies || {}).length > 0 || Object.keys(pkg.devDependencies || {}).length > 0 || Object.keys(pkg.peerDependencies || {}).length > 0);
|
|
1901
|
+
if (!hasDeps) {
|
|
1902
|
+
const fallbackDir = path.resolve(__dirname, "../../..");
|
|
1903
|
+
try {
|
|
1904
|
+
pkg = getPackage(fallbackDir);
|
|
1905
|
+
} catch {}
|
|
1906
|
+
}
|
|
1907
|
+
} catch {}
|
|
1908
|
+
const deps = Object.keys(pkg && pkg.dependencies || {});
|
|
1909
|
+
const peer = Object.keys(pkg && pkg.peerDependencies || {});
|
|
1910
|
+
const dev = Object.keys(pkg && pkg.devDependencies || {});
|
|
1911
|
+
return Array.from(new Set([ ...deps, ...peer, ...dev ]));
|
|
1912
|
+
}
|
|
1913
|
+
const VERSION_STRING = "##VERSION##";
|
|
1914
|
+
const PACKAGE_STRING = "##PACKAGE##";
|
|
1915
|
+
const PACKAGE_SIZE_STRING = "##PACKAGE_SIZE##";
|
|
1916
|
+
var Modes;
|
|
1917
|
+
(function(Modes) {
|
|
1918
|
+
Modes["CJS"] = "commonjs";
|
|
1919
|
+
Modes["ESM"] = "es2022";
|
|
1920
|
+
})(Modes || (Modes = {}));
|
|
1921
|
+
var BuildMode;
|
|
1922
|
+
(function(BuildMode) {
|
|
1923
|
+
BuildMode["BUILD"] = "build";
|
|
1924
|
+
BuildMode["BUNDLE"] = "bundle";
|
|
1925
|
+
BuildMode["ALL"] = "all";
|
|
1926
|
+
})(BuildMode || (BuildMode = {}));
|
|
1927
|
+
const options$1 = {
|
|
1928
|
+
prod: {
|
|
1929
|
+
type: "boolean",
|
|
1930
|
+
default: false
|
|
1931
|
+
},
|
|
1932
|
+
dev: {
|
|
1933
|
+
type: "boolean",
|
|
1934
|
+
default: false
|
|
1935
|
+
},
|
|
1936
|
+
buildMode: {
|
|
1937
|
+
type: "string",
|
|
1938
|
+
default: BuildMode.ALL
|
|
1939
|
+
},
|
|
1940
|
+
includes: {
|
|
1941
|
+
type: "string",
|
|
1942
|
+
default: ""
|
|
1943
|
+
},
|
|
1944
|
+
externals: {
|
|
1945
|
+
type: "string",
|
|
1946
|
+
default: ""
|
|
1947
|
+
},
|
|
1948
|
+
docs: {
|
|
1949
|
+
type: "boolean",
|
|
1950
|
+
default: false
|
|
1951
|
+
},
|
|
1952
|
+
commands: {
|
|
1953
|
+
type: "boolean",
|
|
1954
|
+
default: false
|
|
1955
|
+
},
|
|
1956
|
+
entry: {
|
|
1957
|
+
type: "string",
|
|
1958
|
+
default: "./src/index.ts"
|
|
1959
|
+
},
|
|
1960
|
+
banner: {
|
|
1961
|
+
type: "boolean",
|
|
1962
|
+
default: false
|
|
1963
|
+
}
|
|
1964
|
+
};
|
|
1965
|
+
const cjs2Transformer = (ext = ".cjs") => {
|
|
1966
|
+
const log = BuildScripts.log.for(cjs2Transformer);
|
|
1967
|
+
const resolutionCache = new Map;
|
|
1968
|
+
return transformationContext => sourceFile => {
|
|
1969
|
+
const sourceDir = path.dirname(sourceFile.fileName);
|
|
1970
|
+
function resolvePath(importPath) {
|
|
1971
|
+
const cacheKey = JSON.stringify([ sourceDir, importPath ]);
|
|
1972
|
+
const cachedValue = resolutionCache.get(cacheKey);
|
|
1973
|
+
if (cachedValue != null) return cachedValue;
|
|
1974
|
+
let resolvedPath = importPath;
|
|
1975
|
+
try {
|
|
1976
|
+
resolvedPath = path.resolve(sourceDir, resolvedPath + ".ts");
|
|
1977
|
+
} catch (error) {
|
|
1978
|
+
throw new Error(`Failed to resolve path ${importPath}: ${error}`);
|
|
1979
|
+
}
|
|
1980
|
+
let stat;
|
|
1981
|
+
try {
|
|
1982
|
+
stat = fs.statSync(resolvedPath);
|
|
1983
|
+
} catch (e) {
|
|
1984
|
+
try {
|
|
1985
|
+
log.verbose(`Testing existence of path ${resolvedPath} as a folder defaulting to index file`);
|
|
1986
|
+
stat = fs.statSync(resolvedPath.replace(/\.ts$/gm, ""));
|
|
1987
|
+
} catch (e2) {
|
|
1988
|
+
throw new Error(`Failed to resolve path ${importPath}: ${e}, ${e2}`);
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
if (stat.isDirectory()) resolvedPath = resolvedPath.replace(/\.ts$/gm, "/index.ts");
|
|
1992
|
+
if (path.isAbsolute(resolvedPath)) {
|
|
1993
|
+
const extension = (/\.tsx?$/.exec(path.basename(resolvedPath)) || [])[0] || void 0;
|
|
1994
|
+
resolvedPath = "./" + path.relative(sourceDir, path.resolve(path.dirname(resolvedPath), path.basename(resolvedPath, extension) + ext));
|
|
1995
|
+
}
|
|
1996
|
+
resolutionCache.set(cacheKey, resolvedPath);
|
|
1997
|
+
return resolvedPath;
|
|
1998
|
+
}
|
|
1999
|
+
function visitNode(node) {
|
|
2000
|
+
if (shouldMutateModuleSpecifier(node)) {
|
|
2001
|
+
if (ts__namespace.isImportDeclaration(node)) {
|
|
2002
|
+
const resolvedPath = resolvePath(node.moduleSpecifier.text);
|
|
2003
|
+
const newModuleSpecifier = transformationContext.factory.createStringLiteral(resolvedPath);
|
|
2004
|
+
return transformationContext.factory.updateImportDeclaration(node, node.modifiers, node.importClause, newModuleSpecifier, undefined);
|
|
2005
|
+
} else if (ts__namespace.isExportDeclaration(node)) {
|
|
2006
|
+
const resolvedPath = resolvePath(node.moduleSpecifier.text);
|
|
2007
|
+
const newModuleSpecifier = transformationContext.factory.createStringLiteral(resolvedPath);
|
|
2008
|
+
return transformationContext.factory.updateExportDeclaration(node, node.modifiers, node.isTypeOnly, node.exportClause, newModuleSpecifier, undefined);
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
return ts__namespace.visitEachChild(node, visitNode, transformationContext);
|
|
2012
|
+
}
|
|
2013
|
+
function shouldMutateModuleSpecifier(node) {
|
|
2014
|
+
if (!ts__namespace.isImportDeclaration(node) && !ts__namespace.isExportDeclaration(node)) return false;
|
|
2015
|
+
if (node.moduleSpecifier === undefined) return false;
|
|
2016
|
+
if (!ts__namespace.isStringLiteral(node.moduleSpecifier)) return false;
|
|
2017
|
+
if (!node.moduleSpecifier.text.startsWith("./") && !node.moduleSpecifier.text.startsWith("../")) return false;
|
|
2018
|
+
if (path.extname(node.moduleSpecifier.text) !== "") return false;
|
|
2019
|
+
return true;
|
|
2020
|
+
}
|
|
2021
|
+
return ts__namespace.visitNode(sourceFile, visitNode);
|
|
2022
|
+
};
|
|
2023
|
+
};
|
|
2024
|
+
class BuildScripts extends Command {
|
|
2025
|
+
constructor() {
|
|
2026
|
+
super("BuildScripts", Object.assign({}, DefaultCommandOptions, options$1));
|
|
2027
|
+
this.replacements = {};
|
|
2028
|
+
const pkg = getPackage();
|
|
2029
|
+
const {name: name, version: version} = pkg;
|
|
2030
|
+
this.pkgName = name.includes("@") ? name.split("/")[1] : name;
|
|
2031
|
+
this.pkgVersion = version;
|
|
2032
|
+
this.replacements[VERSION_STRING] = this.pkgVersion;
|
|
2033
|
+
this.replacements[PACKAGE_STRING] = name;
|
|
2034
|
+
}
|
|
2035
|
+
patchFiles(p) {
|
|
2036
|
+
const log = this.log.for(this.patchFiles);
|
|
2037
|
+
const {name: name, version: version} = getPackage();
|
|
2038
|
+
log.info(`Patching ${name} ${version} module in ${p}...`);
|
|
2039
|
+
const stat = fs.statSync(p);
|
|
2040
|
+
if (stat.isDirectory()) fs.readdirSync(p, {
|
|
2041
|
+
withFileTypes: true,
|
|
2042
|
+
recursive: true
|
|
2043
|
+
}).filter(p => p.isFile()).forEach(file => patchFile(path.join(file.parentPath, file.name), Object.entries(this.replacements).reduce((acc, [key, val]) => {
|
|
2044
|
+
switch (key) {
|
|
2045
|
+
case VERSION_STRING:
|
|
2046
|
+
log.debug("Found VERSION string to replace");
|
|
2047
|
+
acc[`VERSION = "${VERSION_STRING}";`] = `VERSION = "${val}";`;
|
|
2048
|
+
break;
|
|
2049
|
+
|
|
2050
|
+
case PACKAGE_STRING:
|
|
2051
|
+
log.debug("Found PACKAGE_NAME string to replace");
|
|
2052
|
+
acc[`PACKAGE_NAME = "${PACKAGE_STRING}";`] = `PACKAGE_NAME = "${val}";`;
|
|
2053
|
+
break;
|
|
2054
|
+
|
|
2055
|
+
default:
|
|
2056
|
+
acc[key] = val;
|
|
2057
|
+
}
|
|
2058
|
+
return acc;
|
|
2059
|
+
}, {})));
|
|
2060
|
+
log.verbose(`Module ${name} ${version} patched in ${p}...`);
|
|
2061
|
+
}
|
|
2062
|
+
reportDiagnostics(diagnostics, logLevel) {
|
|
2063
|
+
const msg = this.formatDiagnostics(diagnostics);
|
|
2064
|
+
try {
|
|
2065
|
+
this.log[logLevel](msg);
|
|
2066
|
+
} catch (e) {
|
|
2067
|
+
console.warn(`Failed to get logger for ${logLevel}`);
|
|
2068
|
+
throw e;
|
|
2069
|
+
}
|
|
2070
|
+
return msg;
|
|
2071
|
+
}
|
|
2072
|
+
formatDiagnostics(diagnostics) {
|
|
2073
|
+
return diagnostics.map(diagnostic => {
|
|
2074
|
+
let message = "";
|
|
2075
|
+
if (diagnostic.file && diagnostic.start) {
|
|
2076
|
+
const {line: line, character: character} = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
|
2077
|
+
message += `${diagnostic.file.fileName} (${line + 1},${character + 1})`;
|
|
2078
|
+
}
|
|
2079
|
+
message += ": " + ts__namespace.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
|
2080
|
+
return message;
|
|
2081
|
+
}).join("\n");
|
|
2082
|
+
}
|
|
2083
|
+
readConfigFile(configFileName) {
|
|
2084
|
+
const configFileText = fs.readFileSync(configFileName).toString();
|
|
2085
|
+
const result = ts__namespace.parseConfigFileTextToJson(configFileName, configFileText);
|
|
2086
|
+
const configObject = result.config;
|
|
2087
|
+
if (!configObject) {
|
|
2088
|
+
this.reportDiagnostics([ result.error ], logging.LogLevel.error);
|
|
2089
|
+
}
|
|
2090
|
+
const configParseResult = ts__namespace.parseJsonConfigFileContent(configObject, ts__namespace.sys, path.dirname(configFileName));
|
|
2091
|
+
if (configParseResult.errors.length > 0) this.reportDiagnostics(configParseResult.errors, logging.LogLevel.error);
|
|
2092
|
+
return configParseResult;
|
|
2093
|
+
}
|
|
2094
|
+
evalDiagnostics(diagnostics) {
|
|
2095
|
+
if (diagnostics && diagnostics.length > 0) {
|
|
2096
|
+
const errors = diagnostics.filter(d => d.category === ts__namespace.DiagnosticCategory.Error);
|
|
2097
|
+
const warnings = diagnostics.filter(d => d.category === ts__namespace.DiagnosticCategory.Warning);
|
|
2098
|
+
const suggestions = diagnostics.filter(d => d.category === ts__namespace.DiagnosticCategory.Suggestion);
|
|
2099
|
+
const messages = diagnostics.filter(d => d.category === ts__namespace.DiagnosticCategory.Message);
|
|
2100
|
+
if (warnings.length) this.reportDiagnostics(warnings, logging.LogLevel.warn);
|
|
2101
|
+
if (errors.length) {
|
|
2102
|
+
this.reportDiagnostics(diagnostics, logging.LogLevel.error);
|
|
2103
|
+
throw new Error(`TypeScript reported ${diagnostics.length} diagnostic(s) during check; aborting.`);
|
|
2104
|
+
}
|
|
2105
|
+
if (suggestions.length) this.reportDiagnostics(suggestions, logging.LogLevel.info);
|
|
2106
|
+
if (messages.length) this.reportDiagnostics(messages, logging.LogLevel.info);
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
preCheckDiagnostics(program) {
|
|
2110
|
+
const diagnostics = ts__namespace.getPreEmitDiagnostics(program);
|
|
2111
|
+
this.evalDiagnostics(diagnostics);
|
|
2112
|
+
}
|
|
2113
|
+
async checkTsDiagnostics(isDev, mode, bundle = false) {
|
|
2114
|
+
const log = this.log.for(this.checkTsDiagnostics);
|
|
2115
|
+
let tsConfig;
|
|
2116
|
+
try {
|
|
2117
|
+
tsConfig = this.readConfigFile("./tsconfig.json");
|
|
2118
|
+
} catch (e) {
|
|
2119
|
+
throw new Error(`Failed to parse tsconfig.json: ${e}`);
|
|
2120
|
+
}
|
|
2121
|
+
if (bundle) {
|
|
2122
|
+
tsConfig.options.module = ts.ModuleKind.AMD;
|
|
2123
|
+
tsConfig.options.outDir = "dist";
|
|
2124
|
+
tsConfig.options.isolatedModules = false;
|
|
2125
|
+
tsConfig.options.outFile = this.pkgName;
|
|
2126
|
+
} else {
|
|
2127
|
+
tsConfig.options.outDir = `lib${mode === Modes.ESM ? "/esm" : ""}`;
|
|
2128
|
+
tsConfig.options.module = mode === Modes.ESM ? ts.ModuleKind.ES2022 : ts.ModuleKind.CommonJS;
|
|
2129
|
+
}
|
|
2130
|
+
tsConfig.options.inlineSourceMap = false;
|
|
2131
|
+
tsConfig.options.inlineSources = false;
|
|
2132
|
+
tsConfig.options.sourceMap = true;
|
|
2133
|
+
const program = ts__namespace.createProgram(tsConfig.fileNames, tsConfig.options);
|
|
2134
|
+
this.preCheckDiagnostics(program);
|
|
2135
|
+
log.verbose(`TypeScript checks passed (${bundle ? "bundle" : "normal"} mode).`);
|
|
2136
|
+
}
|
|
2137
|
+
async buildTs(isDev, mode, bundle = false) {
|
|
2138
|
+
const log = this.log.for(this.buildTs);
|
|
2139
|
+
log.info(`Building ${this.pkgName} ${this.pkgVersion} module (${mode}) in ${isDev ? "dev" : "prod"} mode...`);
|
|
2140
|
+
let tsConfig;
|
|
2141
|
+
try {
|
|
2142
|
+
tsConfig = this.readConfigFile("./tsconfig.json");
|
|
2143
|
+
} catch (e) {
|
|
2144
|
+
throw new Error(`Failed to parse tsconfig.json: ${e}`);
|
|
2145
|
+
}
|
|
2146
|
+
if (bundle) {
|
|
2147
|
+
tsConfig.options.module = ts.ModuleKind.AMD;
|
|
2148
|
+
tsConfig.options.outDir = "dist";
|
|
2149
|
+
tsConfig.options.isolatedModules = false;
|
|
2150
|
+
tsConfig.options.outFile = this.pkgName;
|
|
2151
|
+
} else {
|
|
2152
|
+
tsConfig.options.outDir = `lib${mode === Modes.ESM ? "/esm" : ""}`;
|
|
2153
|
+
tsConfig.options.module = mode === Modes.ESM ? ts.ModuleKind.ES2022 : ts.ModuleKind.CommonJS;
|
|
2154
|
+
}
|
|
2155
|
+
if (isDev) {
|
|
2156
|
+
tsConfig.options.inlineSourceMap = true;
|
|
2157
|
+
tsConfig.options.inlineSources = true;
|
|
2158
|
+
tsConfig.options.sourceMap = false;
|
|
2159
|
+
} else {
|
|
2160
|
+
tsConfig.options.inlineSourceMap = false;
|
|
2161
|
+
tsConfig.options.inlineSources = false;
|
|
2162
|
+
tsConfig.options.sourceMap = true;
|
|
2163
|
+
}
|
|
2164
|
+
const program = ts__namespace.createProgram(tsConfig.fileNames, tsConfig.options);
|
|
2165
|
+
const transformations = {};
|
|
2166
|
+
if (mode === Modes.CJS) {
|
|
2167
|
+
transformations.before = [ cjs2Transformer(".cjs") ];
|
|
2168
|
+
} else if (mode === Modes.ESM) {
|
|
2169
|
+
transformations.before = [ cjs2Transformer(".js") ];
|
|
2170
|
+
}
|
|
2171
|
+
const emitResult = program.emit(undefined, undefined, undefined, undefined, transformations);
|
|
2172
|
+
const allDiagnostics = ts__namespace.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
|
|
2173
|
+
this.evalDiagnostics(allDiagnostics);
|
|
2174
|
+
}
|
|
2175
|
+
async build(isDev, mode, bundle = false) {
|
|
2176
|
+
const log = this.log.for(this.build);
|
|
2177
|
+
await this.buildTs(isDev, mode, bundle);
|
|
2178
|
+
log.verbose(`Module ${this.pkgName} ${this.pkgVersion} (${mode}) built in ${isDev ? "dev" : "prod"} mode...`);
|
|
2179
|
+
if (mode === Modes.CJS && !bundle) {
|
|
2180
|
+
const files = getAllFiles("lib", file => file.endsWith(".js") && !file.includes("/esm/"));
|
|
2181
|
+
for (const file of files) {
|
|
2182
|
+
log.verbose(`Patching ${file}'s cjs imports...`);
|
|
2183
|
+
const f = file.replace(".js", ".cjs");
|
|
2184
|
+
await renameFile(file, f);
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
copyAssets(mode) {
|
|
2189
|
+
const log = this.log.for(this.copyAssets);
|
|
2190
|
+
let hasAssets = false;
|
|
2191
|
+
try {
|
|
2192
|
+
hasAssets = fs.statSync("./src/assets").isDirectory();
|
|
2193
|
+
} catch (e) {
|
|
2194
|
+
return log.verbose(`No assets found in ./src/assets to copy`);
|
|
2195
|
+
}
|
|
2196
|
+
if (hasAssets) copyFile("./src/assets", `./${mode === Modes.CJS ? "lib" : "dist"}/assets`);
|
|
2197
|
+
}
|
|
2198
|
+
async bundle(mode, isDev, isLib, entryFile = "./src/index.ts", nameOverride = this.pkgName, externalsArg, includeArg = [ "prompts", "styled-string-builder", "typed-object-accumulator", "@decaf-ts/logging" ]) {
|
|
2199
|
+
await this.checkTsDiagnostics(isDev, mode, true);
|
|
2200
|
+
const isEsm = mode === Modes.ESM;
|
|
2201
|
+
const pkgName = this.pkgName;
|
|
2202
|
+
const log = this.log;
|
|
2203
|
+
const include = Array.from(new Set([ ...parseList(includeArg) ]));
|
|
2204
|
+
let externalsList = parseList(externalsArg);
|
|
2205
|
+
if (externalsList.length === 0) {
|
|
2206
|
+
try {
|
|
2207
|
+
externalsList = listNodeModulesPackages(path.join(process.cwd(), "node_modules"));
|
|
2208
|
+
} catch {}
|
|
2209
|
+
if (!externalsList || externalsList.length === 0) {
|
|
2210
|
+
externalsList = getPackageDependencies();
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
const ext = Array.from(new Set([ ...function builtinList() {
|
|
2214
|
+
try {
|
|
2215
|
+
return Array.isArray(module$1.builtinModules) ? module$1.builtinModules : [];
|
|
2216
|
+
} catch {
|
|
2217
|
+
return [ "fs", "path", "process", "child_process", "util", "https", "http", "os", "stream", "crypto", "zlib", "net", "tls", "url", "querystring", "assert", "events", "tty", "dns", "querystring" ];
|
|
2218
|
+
}
|
|
2219
|
+
}(), ...externalsList ]));
|
|
2220
|
+
const rollupSourceMapOutput = isDev ? "inline" : true;
|
|
2221
|
+
const plugins = [ typescript({
|
|
2222
|
+
compilerOptions: {
|
|
2223
|
+
module: "esnext",
|
|
2224
|
+
declaration: false,
|
|
2225
|
+
outDir: isLib ? "bin" : "dist",
|
|
2226
|
+
sourceMap: isDev ? false : true,
|
|
2227
|
+
inlineSourceMap: isDev ? true : false,
|
|
2228
|
+
inlineSources: isDev ? true : false
|
|
2229
|
+
},
|
|
2230
|
+
include: [ "src/**/*.ts" ],
|
|
2231
|
+
exclude: [ "node_modules", "**/*.spec.ts" ],
|
|
2232
|
+
tsconfig: "./tsconfig.json"
|
|
2233
|
+
}), json() ];
|
|
2234
|
+
if (isLib) {
|
|
2235
|
+
plugins.push(commonjs({
|
|
2236
|
+
include: [],
|
|
2237
|
+
exclude: externalsList
|
|
2238
|
+
}), pluginNodeResolve.nodeResolve({
|
|
2239
|
+
resolveOnly: include
|
|
2240
|
+
}));
|
|
2241
|
+
}
|
|
2242
|
+
try {
|
|
2243
|
+
const terserMod = await import("@rollup/plugin-terser");
|
|
2244
|
+
const terserFn = terserMod && terserMod.terser || terserMod.default || terserMod;
|
|
2245
|
+
const terserOptionsDev = {
|
|
2246
|
+
parse: {
|
|
2247
|
+
ecma: 2020
|
|
2248
|
+
},
|
|
2249
|
+
compress: false,
|
|
2250
|
+
mangle: false,
|
|
2251
|
+
format: {
|
|
2252
|
+
comments: false,
|
|
2253
|
+
beautify: true
|
|
2254
|
+
}
|
|
2255
|
+
};
|
|
2256
|
+
const terserOptionsProd = {
|
|
2257
|
+
parse: {
|
|
2258
|
+
ecma: 2020
|
|
2259
|
+
},
|
|
2260
|
+
compress: {
|
|
2261
|
+
ecma: 2020,
|
|
2262
|
+
passes: 5,
|
|
2263
|
+
drop_console: true,
|
|
2264
|
+
drop_debugger: true,
|
|
2265
|
+
toplevel: true,
|
|
2266
|
+
module: isEsm,
|
|
2267
|
+
unsafe: true,
|
|
2268
|
+
unsafe_arrows: true,
|
|
2269
|
+
unsafe_comps: true,
|
|
2270
|
+
collapse_vars: true,
|
|
2271
|
+
reduce_funcs: true,
|
|
2272
|
+
reduce_vars: true
|
|
2273
|
+
},
|
|
2274
|
+
mangle: {
|
|
2275
|
+
toplevel: true
|
|
2276
|
+
},
|
|
2277
|
+
format: {
|
|
2278
|
+
comments: false,
|
|
2279
|
+
ascii_only: true
|
|
2280
|
+
},
|
|
2281
|
+
toplevel: true
|
|
2282
|
+
};
|
|
2283
|
+
plugins.push(terserFn(isDev ? terserOptionsDev : terserOptionsProd));
|
|
2284
|
+
} catch {}
|
|
2285
|
+
const input = {
|
|
2286
|
+
input: entryFile,
|
|
2287
|
+
plugins: plugins,
|
|
2288
|
+
external: ext,
|
|
2289
|
+
onwarn: undefined,
|
|
2290
|
+
treeshake: !isDev
|
|
2291
|
+
};
|
|
2292
|
+
const globals = {};
|
|
2293
|
+
ext.forEach(e => {
|
|
2294
|
+
globals[e] = packageToGlobal(e);
|
|
2295
|
+
});
|
|
2296
|
+
const outputs = [ {
|
|
2297
|
+
file: `${isLib ? "bin/" : "dist/"}${nameOverride ? nameOverride : `.bundle.${!isDev ? "min" : ""}`}${isEsm ? ".js" : ".cjs"}`,
|
|
2298
|
+
format: isLib ? "cjs" : isEsm ? "esm" : "umd",
|
|
2299
|
+
name: pkgName,
|
|
2300
|
+
esModule: isEsm,
|
|
2301
|
+
sourcemap: rollupSourceMapOutput,
|
|
2302
|
+
globals: globals,
|
|
2303
|
+
exports: "auto"
|
|
2304
|
+
} ];
|
|
2305
|
+
try {
|
|
2306
|
+
const bundle = await rollup.rollup(input);
|
|
2307
|
+
log.verbose(bundle.watchFiles);
|
|
2308
|
+
async function generateOutputs(bundle) {
|
|
2309
|
+
for (const outputOptions of outputs) {
|
|
2310
|
+
await bundle.write(outputOptions);
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
await generateOutputs(bundle);
|
|
2314
|
+
} catch (e) {
|
|
2315
|
+
throw new Error(`Failed to bundle: ${e}`);
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
async buildByEnv(entryFile = "./src/index.ts", isDev, mode = BuildMode.ALL, includesArg, externalsArg) {
|
|
2319
|
+
try {
|
|
2320
|
+
deletePath("lib");
|
|
2321
|
+
} catch (e) {}
|
|
2322
|
+
try {
|
|
2323
|
+
deletePath("dist");
|
|
2324
|
+
} catch (e) {}
|
|
2325
|
+
if ([ BuildMode.ALL, BuildMode.BUILD ].includes(mode)) {
|
|
2326
|
+
fs.mkdirSync("lib");
|
|
2327
|
+
await this.build(isDev, Modes.ESM);
|
|
2328
|
+
await this.build(isDev, Modes.CJS);
|
|
2329
|
+
this.patchFiles("lib");
|
|
2330
|
+
}
|
|
2331
|
+
if ([ BuildMode.ALL, BuildMode.BUNDLE ].includes(mode)) {
|
|
2332
|
+
fs.mkdirSync("dist");
|
|
2333
|
+
await this.bundle(Modes.ESM, isDev, false, entryFile || "./src/index.ts", this.pkgName, externalsArg, includesArg);
|
|
2334
|
+
await this.bundle(Modes.CJS, isDev, false, entryFile || "./src/index.ts", this.pkgName, externalsArg, includesArg);
|
|
2335
|
+
this.patchFiles("dist");
|
|
2336
|
+
}
|
|
2337
|
+
this.copyAssets(Modes.CJS);
|
|
2338
|
+
this.copyAssets(Modes.ESM);
|
|
2339
|
+
}
|
|
2340
|
+
async buildDev(entryFile = "./src/index.ts", mode = BuildMode.ALL, includesArg, externalsArg) {
|
|
2341
|
+
return this.buildByEnv(entryFile, true, mode, includesArg, externalsArg);
|
|
2342
|
+
}
|
|
2343
|
+
async buildProd(entryFile = "./src/index.ts", mode = BuildMode.ALL, includesArg, externalsArg) {
|
|
2344
|
+
return this.buildByEnv(entryFile, false, mode, includesArg, externalsArg);
|
|
2345
|
+
}
|
|
2346
|
+
async buildDocs() {
|
|
2347
|
+
await runCommand(`npm install better-docs taffydb`).promise;
|
|
2348
|
+
await runCommand(`npx markdown-include ./workdocs/readme-md.json`).promise;
|
|
2349
|
+
await runCommand(`npx jsdoc -c ./workdocs/jsdocs.json -t ./node_modules/better-docs`).promise;
|
|
2350
|
+
await runCommand(`npm remove better-docs taffydb`).promise;
|
|
2351
|
+
[ {
|
|
2352
|
+
src: "workdocs/assets",
|
|
2353
|
+
dest: "./docs/workdocs/assets"
|
|
2354
|
+
}, {
|
|
2355
|
+
src: "workdocs/reports/coverage",
|
|
2356
|
+
dest: "./docs/workdocs/reports/coverage"
|
|
2357
|
+
}, {
|
|
2358
|
+
src: "workdocs/reports/html",
|
|
2359
|
+
dest: "./docs/workdocs/reports/html"
|
|
2360
|
+
}, {
|
|
2361
|
+
src: "workdocs/resources",
|
|
2362
|
+
dest: "./docs/workdocs/resources"
|
|
2363
|
+
}, {
|
|
2364
|
+
src: "LICENSE.md",
|
|
2365
|
+
dest: "./docs/LICENSE.md"
|
|
2366
|
+
} ].forEach(f => {
|
|
2367
|
+
const {src: src, dest: dest} = f;
|
|
2368
|
+
copyFile(src, dest);
|
|
2369
|
+
});
|
|
2370
|
+
try {
|
|
2371
|
+
const sizeKb = await getFileSizeZipped(path.resolve(path.join(process.cwd(), "dist")));
|
|
2372
|
+
this.replacements[PACKAGE_SIZE_STRING] = `${sizeKb} KB`;
|
|
2373
|
+
} catch {
|
|
2374
|
+
this.replacements[PACKAGE_SIZE_STRING] = "unknown";
|
|
2375
|
+
}
|
|
2376
|
+
try {
|
|
2377
|
+
patchFile("./README.md", this.replacements);
|
|
2378
|
+
} catch (e) {
|
|
2379
|
+
const log = this.log.for(this.buildDocs);
|
|
2380
|
+
log.verbose(`Failed to patch README.md: ${e}`);
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
async run(answers) {
|
|
2384
|
+
const {dev: dev, prod: prod, docs: docs, buildMode: buildMode, includes: includes, externals: externals, entry: entry} = answers;
|
|
2385
|
+
if (dev) {
|
|
2386
|
+
return await this.buildDev(entry || "./src/index.ts", buildMode, includes, externals);
|
|
2387
|
+
}
|
|
2388
|
+
if (prod) {
|
|
2389
|
+
return await this.buildProd(entry || "./src/index.ts", buildMode, includes, externals);
|
|
2390
|
+
}
|
|
2391
|
+
if (docs) {
|
|
2392
|
+
return await this.buildDocs();
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
const options = {
|
|
2397
|
+
ci: {
|
|
2398
|
+
type: "boolean",
|
|
2399
|
+
default: true
|
|
2400
|
+
},
|
|
2401
|
+
message: {
|
|
2402
|
+
type: "string",
|
|
2403
|
+
short: "m"
|
|
2404
|
+
},
|
|
2405
|
+
tag: {
|
|
2406
|
+
type: "string",
|
|
2407
|
+
short: "t",
|
|
2408
|
+
default: undefined
|
|
2409
|
+
}
|
|
2410
|
+
};
|
|
2411
|
+
class ReleaseScript extends Command {
|
|
2412
|
+
constructor() {
|
|
2413
|
+
super("ReleaseScript", options);
|
|
2414
|
+
}
|
|
2415
|
+
async prepareVersion(tag) {
|
|
2416
|
+
const log = this.log.for(this.prepareVersion);
|
|
2417
|
+
tag = this.testVersion(tag || "");
|
|
2418
|
+
if (!tag) {
|
|
2419
|
+
log.verbose("No release message provided. Prompting for one:");
|
|
2420
|
+
log.info(`Listing latest git tags:`);
|
|
2421
|
+
await runCommand("git tag --sort=-taggerdate | head -n 5").promise;
|
|
2422
|
+
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-]+)?$/));
|
|
2423
|
+
}
|
|
2424
|
+
return tag;
|
|
2425
|
+
}
|
|
2426
|
+
testVersion(version) {
|
|
2427
|
+
const log = this.log.for(this.testVersion);
|
|
2428
|
+
version = version.trim().toLowerCase();
|
|
2429
|
+
switch (version) {
|
|
2430
|
+
case exports.SemVersion.PATCH:
|
|
2431
|
+
case exports.SemVersion.MINOR:
|
|
2432
|
+
case exports.SemVersion.MAJOR:
|
|
2433
|
+
log.verbose(`Using provided SemVer update: ${version}`, 1);
|
|
2434
|
+
return version;
|
|
2435
|
+
|
|
2436
|
+
default:
|
|
2437
|
+
log.verbose(`Testing provided version for SemVer compatibility: ${version}`, 1);
|
|
2438
|
+
if (!new RegExp(SemVersionRegex).test(version)) {
|
|
2439
|
+
log.debug(`Invalid version number: ${version}`);
|
|
2440
|
+
return undefined;
|
|
2441
|
+
}
|
|
2442
|
+
log.verbose(`version approved: ${version}`, 1);
|
|
2443
|
+
return version;
|
|
2444
|
+
}
|
|
2445
|
+
}
|
|
2446
|
+
async prepareMessage(message) {
|
|
2447
|
+
const log = this.log.for(this.prepareMessage);
|
|
2448
|
+
if (!message) {
|
|
2449
|
+
log.verbose("No release message provided. Prompting for one");
|
|
2450
|
+
return await UserInput.insistForText("message", "What should be the release message/ticket?", val => !!val && val.toString().length > 5);
|
|
2451
|
+
}
|
|
2452
|
+
return message;
|
|
2453
|
+
}
|
|
2454
|
+
async run(args) {
|
|
2455
|
+
let result;
|
|
2456
|
+
const {ci: ci} = args;
|
|
2457
|
+
let {tag: tag, message: message} = args;
|
|
2458
|
+
tag = await this.prepareVersion(tag);
|
|
2459
|
+
message = await this.prepareMessage(message);
|
|
2460
|
+
result = await runCommand(`npm run prepare-release -- ${tag} ${message}`, {
|
|
2461
|
+
cwd: process.cwd()
|
|
2462
|
+
}).promise;
|
|
2463
|
+
result = await runCommand("git status --porcelain").promise;
|
|
2464
|
+
await result;
|
|
2465
|
+
if (result.logs.length && await UserInput.askConfirmation("git-changes", "Do you want to push the changes to the remote repository?", true)) {
|
|
2466
|
+
await runCommand("git add .").promise;
|
|
2467
|
+
await runCommand(`git commit -m "${tag} - ${message} - after release preparation${ci ? "" : NoCIFLag}"`).promise;
|
|
2468
|
+
}
|
|
2469
|
+
await runCommand(`npm version "${tag}" -m "${message}${ci ? "" : NoCIFLag}"`).promise;
|
|
2470
|
+
await runCommand("git push --follow-tags").promise;
|
|
2471
|
+
if (!ci) {
|
|
2472
|
+
await runCommand("NPM_TOKEN=$(cat .npmtoken) npm publish --access public").promise;
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
class RegexpOutputWriter extends StandardOutputWriter {
|
|
2477
|
+
constructor(cmd, lock, regexp, flags = "g") {
|
|
2478
|
+
super(cmd, lock);
|
|
2479
|
+
try {
|
|
2480
|
+
this.regexp = typeof regexp === "string" ? new RegExp(regexp, flags) : regexp;
|
|
2481
|
+
} catch (e) {
|
|
2482
|
+
throw new Error(`Invalid regular expression: ${e}`);
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
test(data) {
|
|
2486
|
+
this.regexp.lastIndex = 0;
|
|
2487
|
+
let match;
|
|
2488
|
+
try {
|
|
2489
|
+
match = this.regexp.exec(data);
|
|
2490
|
+
} catch (e) {
|
|
2491
|
+
return console.debug(`Failed to parse chunk: ${data}\nError: ${e} `);
|
|
2492
|
+
}
|
|
2493
|
+
return match;
|
|
2494
|
+
}
|
|
2495
|
+
testAndResolve(data) {
|
|
2496
|
+
const match = this.test(data);
|
|
2497
|
+
if (match) this.resolve(match[0]);
|
|
2498
|
+
}
|
|
2499
|
+
testAndReject(data) {
|
|
2500
|
+
const match = this.test(data);
|
|
2501
|
+
if (match) this.reject(match[0]);
|
|
2502
|
+
}
|
|
2503
|
+
data(chunk) {
|
|
2504
|
+
super.data(chunk);
|
|
2505
|
+
this.testAndResolve(String(chunk));
|
|
2506
|
+
}
|
|
2507
|
+
error(chunk) {
|
|
2508
|
+
super.error(chunk);
|
|
2509
|
+
this.testAndReject(String(chunk));
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
const VERSION = "0.11.10.experimental.1";
|
|
2513
|
+
const PACKAGE_NAME = "@decaf-ts/utils";
|
|
2514
|
+
exports.AbortCode = AbortCode;
|
|
2515
|
+
exports.BuildScripts = BuildScripts;
|
|
2516
|
+
exports.Command = Command;
|
|
2517
|
+
exports.DefaultCommandOptions = DefaultCommandOptions;
|
|
2518
|
+
exports.DefaultCommandValues = DefaultCommandValues;
|
|
2519
|
+
exports.Encoding = Encoding;
|
|
2520
|
+
exports.HttpClient = HttpClient;
|
|
2521
|
+
exports.NoCIFLag = NoCIFLag;
|
|
2522
|
+
exports.PACKAGE_NAME = PACKAGE_NAME;
|
|
2523
|
+
exports.PerformanceRunner = PerformanceRunner;
|
|
2524
|
+
exports.RegexpOutputWriter = RegexpOutputWriter;
|
|
2525
|
+
exports.ReleaseScript = ReleaseScript;
|
|
2526
|
+
exports.SemVersionRegex = SemVersionRegex;
|
|
2527
|
+
exports.SetupScriptKey = SetupScriptKey;
|
|
2528
|
+
exports.StandardOutputWriter = StandardOutputWriter;
|
|
2529
|
+
exports.UserInput = UserInput;
|
|
2530
|
+
exports.VERSION = VERSION;
|
|
2531
|
+
exports.chainAbortController = chainAbortController;
|
|
2532
|
+
exports.copyFile = copyFile;
|
|
2533
|
+
exports.defaultCanvasOptions = defaultCanvasOptions;
|
|
2534
|
+
exports.deletePath = deletePath;
|
|
2535
|
+
exports.getAllFiles = getAllFiles;
|
|
2536
|
+
exports.getDependencies = getDependencies;
|
|
2537
|
+
exports.getFileSizeZipped = getFileSizeZipped;
|
|
2538
|
+
exports.getPackage = getPackage;
|
|
2539
|
+
exports.getPackageDependencies = getPackageDependencies;
|
|
2540
|
+
exports.getPackageVersion = getPackageVersion;
|
|
2541
|
+
exports.getSlogan = getSlogan;
|
|
2542
|
+
exports.installDependencies = installDependencies;
|
|
2543
|
+
exports.installIfNotAvailable = installIfNotAvailable;
|
|
2544
|
+
exports.listFolder = listFolder;
|
|
2545
|
+
exports.listNodeModulesPackages = listNodeModulesPackages;
|
|
2546
|
+
exports.lockify = lockify;
|
|
2547
|
+
exports.normalizeImport = normalizeImport;
|
|
2548
|
+
exports.packageToGlobal = packageToGlobal;
|
|
2549
|
+
exports.parseList = parseList;
|
|
2550
|
+
exports.patchFile = patchFile;
|
|
2551
|
+
exports.printBanner = printBanner;
|
|
2552
|
+
exports.pushToGit = pushToGit;
|
|
2553
|
+
exports.readFile = readFile;
|
|
2554
|
+
exports.renameFile = renameFile;
|
|
2555
|
+
exports.runCommand = runCommand;
|
|
2556
|
+
exports.setPackageAttribute = setPackageAttribute;
|
|
2557
|
+
exports.spawnCommand = spawnCommand;
|
|
2558
|
+
exports.updateDependencies = updateDependencies;
|
|
2559
|
+
exports.writeFile = writeFile;
|
|
2560
|
+
});
|
|
2561
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuY2pzIiwic291cmNlcyI6WyIuLi9zcmMvaW5wdXQvaW5wdXQudHMiLCIuLi9zcmMvY2xpL2NvbnN0YW50cy50cyIsIi4uL3NyYy91dGlscy9jb25zdGFudHMudHMiLCIuLi9zcmMvd3JpdGVycy9TdGFuZGFyZE91dHB1dFdyaXRlci50cyIsIi4uL3NyYy91dGlscy91dGlscy50cyIsIi4uL3NyYy91dGlscy9mcy50cyIsIi4uL3NyYy9hc3NldHMvc2xvZ2Fucy50cyIsIi4uL3NyYy9vdXRwdXQvY29tbW9uLnRzIiwiLi4vc3JjL2NsaS9jb21tYW5kLnRzIiwiLi4vc3JjL3V0aWxzL2h0dHAudHMiLCIuLi9zcmMvdXRpbHMvcGVyZm9ybWFuY2VSdW5uZXIudHMiLCIuLi9zcmMvY2xpL2NvbW1hbmRzL2J1aWxkLXNjcmlwdHMudHMiLCIuLi9zcmMvY2xpL2NvbW1hbmRzL3RhZy1yZWxlYXNlLnRzIiwiLi4vc3JjL3dyaXRlcnMvUmVnZXhwT3V0cHV0V3JpdGVyLnRzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFuc3dlcnMsXG4gIENob2ljZSxcbiAgRmFsc3ksXG4gIEluaXRpYWxSZXR1cm5WYWx1ZSxcbiAgUHJldkNhbGxlcixcbiAgUHJvbXB0T2JqZWN0LFxuICBQcm9tcHRUeXBlLFxuICBWYWx1ZU9yRnVuYyxcbn0gZnJvbSBcInByb21wdHNcIjtcbmltcG9ydCBwcm9tcHRzIGZyb20gXCJwcm9tcHRzXCI7XG5pbXBvcnQgeyBwYXJzZUFyZ3MsIFBhcnNlQXJnc0NvbmZpZyB9IGZyb20gXCJ1dGlsXCI7XG5pbXBvcnQgeyBXcml0YWJsZSwgUmVhZGFibGUgfSBmcm9tIFwic3RyZWFtXCI7XG5pbXBvcnQgeyBQYXJzZUFyZ3NPcHRpb25zQ29uZmlnLCBQYXJzZUFyZ3NSZXN1bHQgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgTG9nZ2luZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXByZXNlbnRzIGEgdXNlciBpbnB1dCBwcm9tcHQgd2l0aCB2YXJpb3VzIGNvbmZpZ3VyYXRpb24gb3B0aW9ucy5cbiAqIEBzdW1tYXJ5IFRoaXMgY2xhc3MgcHJvdmlkZXMgYSBmbGV4aWJsZSBpbnRlcmZhY2UgZm9yIGNyZWF0aW5nIGFuZCBtYW5hZ2luZyB1c2VyIGlucHV0IHByb21wdHMuXG4gKiBJdCBpbXBsZW1lbnRzIHRoZSBQcm9tcHRPYmplY3QgaW50ZXJmYWNlIGZyb20gdGhlICdwcm9tcHRzJyBsaWJyYXJ5IGFuZCBvZmZlcnMgbWV0aG9kcyB0byBzZXRcbiAqIHZhcmlvdXMgcHJvcGVydGllcyBvZiB0aGUgcHJvbXB0LiBUaGUgY2xhc3MgYWxzbyBpbmNsdWRlcyBzdGF0aWMgbWV0aG9kcyBmb3IgY29tbW9uIGlucHV0IHNjZW5hcmlvc1xuICogYW5kIGFyZ3VtZW50IHBhcnNpbmcuXG4gKlxuICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgcHJvbXB0IG5hbWUsIGV4dGVuZGluZyBzdHJpbmcuXG4gKlxuICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcHJvbXB0LCB1c2VkIGFzIHRoZSBrZXkgaW4gdGhlIHJldHVybmVkIGFuc3dlcnMgb2JqZWN0LlxuICpcbiAqIEBjbGFzc1xuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IFVzZXJJbnB1dCB9IGZyb20gJ0BkZWNhZi10cy91dGlscyc7XG4gKlxuICogLy8gQ3JlYXRlIGEgc2ltcGxlIHRleHQgaW5wdXRcbiAqIGNvbnN0IG5hbWVJbnB1dCA9IG5ldyBVc2VySW5wdXQoJ25hbWUnKVxuICogICAuc2V0TWVzc2FnZSgnV2hhdCBpcyB5b3VyIG5hbWU/JylcbiAqICAgLnNldEluaXRpYWwoJ1VzZXInKTtcbiAqXG4gKiAvLyBDcmVhdGUgYSBudW1iZXIgaW5wdXQgd2l0aCB2YWxpZGF0aW9uXG4gKiBjb25zdCBhZ2VJbnB1dCA9IG5ldyBVc2VySW5wdXQoJ2FnZScpXG4gKiAgIC5zZXRUeXBlKCdudW1iZXInKVxuICogICAuc2V0TWVzc2FnZSgnSG93IG9sZCBhcmUgeW91PycpXG4gKiAgIC5zZXRNaW4oMClcbiAqICAgLnNldE1heCgxMjApO1xuICpcbiAqIC8vIEFzayBmb3IgaW5wdXQgYW5kIHByb2Nlc3MgdGhlIHJlc3VsdHNcbiAqIGFzeW5jIGZ1bmN0aW9uIGdldFVzZXJJbmZvKCkge1xuICogICBjb25zdCBhbnN3ZXJzID0gYXdhaXQgVXNlcklucHV0LmFzayhbbmFtZUlucHV0LCBhZ2VJbnB1dF0pO1xuICogICBjb25zb2xlLmxvZyhgSGVsbG8gJHthbnN3ZXJzLm5hbWV9LCB5b3UgYXJlICR7YW5zd2Vycy5hZ2V9IHllYXJzIG9sZC5gKTtcbiAqIH1cbiAqXG4gKiBnZXRVc2VySW5mbygpO1xuICogYGBgXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgVXNlcklucHV0XG4gKiAgIHBhcnRpY2lwYW50IFByb21wdExpYnJhcnlcbiAqXG4gKiAgIENsaWVudC0+PlVzZXJJbnB1dDogbmV3IFVzZXJJbnB1dChuYW1lKVxuICogICBDbGllbnQtPj5Vc2VySW5wdXQ6IHNldE1lc3NhZ2UobWVzc2FnZSlcbiAqICAgQ2xpZW50LT4+VXNlcklucHV0OiBzZXRUeXBlKHR5cGUpXG4gKiAgIENsaWVudC0+PlVzZXJJbnB1dDogc2V0SW5pdGlhbChpbml0aWFsKVxuICogICBDbGllbnQtPj5Vc2VySW5wdXQ6IE90aGVyIGNvbmZpZ3VyYXRpb24gbWV0aG9kc1xuICpcbiAqICAgQ2xpZW50LT4+VXNlcklucHV0OiBhc2soKVxuICogICBVc2VySW5wdXQtPj5Qcm9tcHRMaWJyYXJ5OiBwcm9tcHRzKHF1ZXN0aW9uKVxuICogICBQcm9tcHRMaWJyYXJ5LT4+Q2xpZW50OiBEaXNwbGF5IHByb21wdFxuICogICBDbGllbnQtPj5Qcm9tcHRMaWJyYXJ5OiBVc2VyIHByb3ZpZGVzIGlucHV0XG4gKiAgIFByb21wdExpYnJhcnktPj5Vc2VySW5wdXQ6IFJldHVybiBhbnN3ZXJzXG4gKiAgIFVzZXJJbnB1dC0+PkNsaWVudDogUmV0dXJuIHByb2Nlc3NlZCBhbnN3ZXJzXG4gKi9cbmV4cG9ydCBjbGFzcyBVc2VySW5wdXQ8UiBleHRlbmRzIHN0cmluZyA9IHN0cmluZz4gaW1wbGVtZW50cyBQcm9tcHRPYmplY3Q8Uj4ge1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBsb2dnZXIgPSBMb2dnaW5nLmZvcihVc2VySW5wdXQpO1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSB0eXBlIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IERldGVybWluZXMgdGhlIGlucHV0IG1ldGhvZCAoZS5nLiwgdGV4dCwgbnVtYmVyLCBjb25maXJtKS5cbiAgICovXG4gIHR5cGU6IFByb21wdFR5cGUgfCBGYWxzeSB8IFByZXZDYWxsZXI8UiwgUHJvbXB0VHlwZSB8IEZhbHN5PiA9IFwidGV4dFwiO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIG5hbWUgb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgVXNlZCBhcyB0aGUga2V5IGluIHRoZSByZXR1cm5lZCBhbnN3ZXJzIG9iamVjdC5cbiAgICovXG4gIG5hbWU6IFZhbHVlT3JGdW5jPFI+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIG1lc3NhZ2UgZGlzcGxheWVkIHRvIHRoZSB1c2VyLlxuICAgKiBAc3VtbWFyeSBUaGUgcXVlc3Rpb24gb3IgaW5zdHJ1Y3Rpb24gcHJlc2VudGVkIHRvIHRoZSB1c2VyLlxuICAgKi9cbiAgbWVzc2FnZT86IFZhbHVlT3JGdW5jPHN0cmluZz4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgaW5pdGlhbCB2YWx1ZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBUaGUgZGVmYXVsdCB2YWx1ZSBwcmVzZW50ZWQgdG8gdGhlIHVzZXIuXG4gICAqL1xuICBpbml0aWFsPzpcbiAgICB8IEluaXRpYWxSZXR1cm5WYWx1ZVxuICAgIHwgUHJldkNhbGxlcjxSLCBJbml0aWFsUmV0dXJuVmFsdWUgfCBQcm9taXNlPEluaXRpYWxSZXR1cm5WYWx1ZT4+XG4gICAgfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgc3R5bGUgb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyB0aGUgdmlzdWFsIHN0eWxlIG9mIHRoZSBwcm9tcHQuXG4gICAqL1xuICBzdHlsZT86IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIGZvcm1hdCBmdW5jdGlvbiBmb3IgdGhlIGlucHV0LlxuICAgKiBAc3VtbWFyeSBBIGZ1bmN0aW9uIHRvIGZvcm1hdCB0aGUgdXNlcidzIGlucHV0IGJlZm9yZSBpdCdzIHJldHVybmVkLlxuICAgKi9cbiAgZm9ybWF0PzogUHJldkNhbGxlcjxSLCB2b2lkPiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSB2YWxpZGF0aW9uIGZ1bmN0aW9uIGZvciB0aGUgaW5wdXQuXG4gICAqIEBzdW1tYXJ5IEEgZnVuY3Rpb24gdG8gdmFsaWRhdGUgdGhlIHVzZXIncyBpbnB1dC5cbiAgICovXG4gIHZhbGlkYXRlPzpcbiAgICB8IFByZXZDYWxsZXI8UiwgYm9vbGVhbiB8IHN0cmluZyB8IFByb21pc2U8Ym9vbGVhbiB8IHN0cmluZz4+XG4gICAgfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgb25TdGF0ZSBjYWxsYmFjayBmdW5jdGlvbi5cbiAgICogQHN1bW1hcnkgQSBmdW5jdGlvbiBjYWxsZWQgd2hlbiB0aGUgc3RhdGUgb2YgdGhlIHByb21wdCBjaGFuZ2VzLlxuICAgKi9cbiAgb25TdGF0ZT86IFByZXZDYWxsZXI8Uiwgdm9pZD4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbWluaW11bSB2YWx1ZSBmb3IgbnVtYmVyIGlucHV0cy5cbiAgICogQHN1bW1hcnkgVGhlIGxvd2VzdCBudW1iZXIgdGhlIHVzZXIgY2FuIGlucHV0LlxuICAgKi9cbiAgbWluPzogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbWF4aW11bSB2YWx1ZSBmb3IgbnVtYmVyIGlucHV0cy5cbiAgICogQHN1bW1hcnkgVGhlIGhpZ2hlc3QgbnVtYmVyIHRoZSB1c2VyIGNhbiBpbnB1dC5cbiAgICovXG4gIG1heD86IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0byBhbGxvdyBmbG9hdCB2YWx1ZXMgZm9yIG51bWJlciBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IElmIHRydWUsIGFsbG93cyBkZWNpbWFsIG51bWJlcnMuXG4gICAqL1xuICBmbG9hdD86IGJvb2xlYW4gfCBQcmV2Q2FsbGVyPFIsIGJvb2xlYW4gfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHJvdW5kIHRvIGZvciBmbG9hdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IERldGVybWluZXMgdGhlIHByZWNpc2lvbiBvZiBmbG9hdCBpbnB1dHMuXG4gICAqL1xuICByb3VuZD86IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSW5zdHJ1Y3Rpb25zIGZvciB0aGUgdXNlci5cbiAgICogQHN1bW1hcnkgQWRkaXRpb25hbCBndWlkYW5jZSBwcm92aWRlZCB0byB0aGUgdXNlci5cbiAgICovXG4gIGluc3RydWN0aW9ucz86IHN0cmluZyB8IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgaW5jcmVtZW50IHZhbHVlIGZvciBudW1iZXIgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgc3RlcCBzaXplIHdoZW4gaW5jcmVhc2luZyBvciBkZWNyZWFzaW5nIHRoZSBudW1iZXIuXG4gICAqL1xuICBpbmNyZW1lbnQ/OiBudW1iZXIgfCBQcmV2Q2FsbGVyPFIsIG51bWJlciB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBzZXBhcmF0b3IgZm9yIGxpc3QgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgY2hhcmFjdGVyIHVzZWQgdG8gc2VwYXJhdGUgbGlzdCBpdGVtcy5cbiAgICovXG4gIHNlcGFyYXRvcj86IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIGFjdGl2ZSBvcHRpb24gc3R5bGUgZm9yIHNlbGVjdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBzdHlsZSBhcHBsaWVkIHRvIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgb3B0aW9uLlxuICAgKi9cbiAgYWN0aXZlPzogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgaW5hY3RpdmUgb3B0aW9uIHN0eWxlIGZvciBzZWxlY3QgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgc3R5bGUgYXBwbGllZCB0byBub24tc2VsZWN0ZWQgb3B0aW9ucy5cbiAgICovXG4gIGluYWN0aXZlPzogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgYXZhaWxhYmxlIGNob2ljZXMgZm9yIHNlbGVjdCwgbXVsdGlzZWxlY3QsIG9yIGF1dG9jb21wbGV0ZSBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IEFuIGFycmF5IG9mIG9wdGlvbnMgdGhhdCB0aGUgdXNlciBjYW4gc2VsZWN0IGZyb20gaW4gY2hvaWNlLWJhc2VkIHByb21wdHMuXG4gICAqL1xuICBjaG9pY2VzPzogQ2hvaWNlW10gfCBQcmV2Q2FsbGVyPFIsIENob2ljZVtdIHwgRmFsc3k+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIGhpbnQgdGV4dCBmb3IgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQWRkaXRpb25hbCBpbmZvcm1hdGlvbiBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqL1xuICBoaW50Pzogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgd2FybmluZyB0ZXh0IGZvciB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBBIHdhcm5pbmcgbWVzc2FnZSBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqL1xuICB3YXJuPzogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgc3VnZ2VzdD86ICgoaW5wdXQ6IGFueSwgY2hvaWNlczogQ2hvaWNlW10pID0+IFByb21pc2U8YW55PikgfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbGltaXQgZm9yIGxpc3QgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgbWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdGhhdCBjYW4gYmUgc2VsZWN0ZWQuXG4gICAqL1xuICBsaW1pdD86IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIG1hc2sgZm9yIHBhc3N3b3JkIGlucHV0cy5cbiAgICogQHN1bW1hcnkgVGhlIGNoYXJhY3RlciB1c2VkIHRvIGhpZGUgdGhlIHVzZXIncyBpbnB1dC5cbiAgICovXG4gIG1hc2s/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBzdGRvdXQgc3RyZWFtIGZvciB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBUaGUgb3V0cHV0IHN0cmVhbSB1c2VkIGJ5IHRoZSBwcm9tcHQuXG4gICAqL1xuICBzdGRvdXQ/OiBXcml0YWJsZSB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBzdGRpbiBzdHJlYW0gZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IFRoZSBpbnB1dCBzdHJlYW0gdXNlZCBieSB0aGUgcHJvbXB0LlxuICAgKi9cbiAgc3RkaW4/OiBSZWFkYWJsZSB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcihuYW1lOiBWYWx1ZU9yRnVuYzxSPikge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIHR5cGUgb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgaW5wdXQgbWV0aG9kIGZvciB0aGUgcHJvbXB0LlxuICAgKlxuICAgKiBAcGFyYW0gdHlwZSAtIFRoZSB0eXBlIG9mIHRoZSBwcm9tcHQuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRUeXBlKHR5cGU6IFByb21wdFR5cGUgfCBGYWxzeSB8IFByZXZDYWxsZXI8UiwgUHJvbXB0VHlwZSB8IEZhbHN5Pik6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyB0eXBlIHRvOiAke3R5cGV9YCk7XG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgbWVzc2FnZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBxdWVzdGlvbiBvciBpbnN0cnVjdGlvbiBwcmVzZW50ZWQgdG8gdGhlIHVzZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBtZXNzYWdlIHRvIGJlIGRpc3BsYXllZC5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldE1lc3NhZ2UodmFsdWU6IFZhbHVlT3JGdW5jPHN0cmluZz4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgbWVzc2FnZSB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLm1lc3NhZ2UgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgaW5pdGlhbCB2YWx1ZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBkZWZhdWx0IHZhbHVlIHByZXNlbnRlZCB0byB0aGUgdXNlci5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGluaXRpYWwgdmFsdWUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRJbml0aWFsKFxuICAgIHZhbHVlOlxuICAgICAgfCBJbml0aWFsUmV0dXJuVmFsdWVcbiAgICAgIHwgUHJldkNhbGxlcjxSLCBJbml0aWFsUmV0dXJuVmFsdWUgfCBQcm9taXNlPEluaXRpYWxSZXR1cm5WYWx1ZT4+XG4gICAgICB8IHVuZGVmaW5lZFxuICApOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgaW5pdGlhbCB2YWx1ZSB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLmluaXRpYWwgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgc3R5bGUgb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgdmlzdWFsIHN0eWxlIG9mIHRoZSBwcm9tcHQuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBzdHlsZSB0byBiZSBhcHBsaWVkLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0U3R5bGUodmFsdWU6IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIHN0eWxlIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuc3R5bGUgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgZm9ybWF0IGZ1bmN0aW9uIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgYSBmdW5jdGlvbiB0byBmb3JtYXQgdGhlIHVzZXIncyBpbnB1dCBiZWZvcmUgaXQncyByZXR1cm5lZC5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGZvcm1hdCBmdW5jdGlvbi5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldEZvcm1hdCh2YWx1ZTogUHJldkNhbGxlcjxSLCB2b2lkPiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBmb3JtYXQgZnVuY3Rpb25gKTtcbiAgICB0aGlzLmZvcm1hdCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSB2YWxpZGF0aW9uIGZ1bmN0aW9uIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgYSBmdW5jdGlvbiB0byB2YWxpZGF0ZSB0aGUgdXNlcidzIGlucHV0LlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsaWRhdGlvbiBmdW5jdGlvbi5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldFZhbGlkYXRlKFxuICAgIHZhbHVlOlxuICAgICAgfCBQcmV2Q2FsbGVyPFIsIGJvb2xlYW4gfCBzdHJpbmcgfCBQcm9taXNlPGJvb2xlYW4gfCBzdHJpbmc+PlxuICAgICAgfCB1bmRlZmluZWRcbiAgKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIHZhbGlkYXRlIGZ1bmN0aW9uYCk7XG4gICAgdGhpcy52YWxpZGF0ZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBvblN0YXRlIGNhbGxiYWNrIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgYSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgc3RhdGUgb2YgdGhlIHByb21wdCBjaGFuZ2VzLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgb25TdGF0ZSBjYWxsYmFjayBmdW5jdGlvbi5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldE9uU3RhdGUodmFsdWU6IFByZXZDYWxsZXI8Uiwgdm9pZD4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgb25TdGF0ZSBjYWxsYmFja2ApO1xuICAgIHRoaXMub25TdGF0ZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBtaW5pbXVtIHZhbHVlIGZvciBudW1iZXIgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBsb3dlc3QgbnVtYmVyIHRoZSB1c2VyIGNhbiBpbnB1dC5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIG1pbmltdW0gdmFsdWUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRNaW4odmFsdWU6IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIG1pbiB2YWx1ZSB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLm1pbiA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBtYXhpbXVtIHZhbHVlIGZvciBudW1iZXIgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBoaWdoZXN0IG51bWJlciB0aGUgdXNlciBjYW4gaW5wdXQuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBtYXhpbXVtIHZhbHVlLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0TWF4KHZhbHVlOiBudW1iZXIgfCBQcmV2Q2FsbGVyPFIsIG51bWJlciB8IEZhbHN5PiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBtYXggdmFsdWUgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5tYXggPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB3aGV0aGVyIHRvIGFsbG93IGZsb2F0IHZhbHVlcyBmb3IgbnVtYmVyIGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB3aGV0aGVyIGRlY2ltYWwgbnVtYmVycyBhcmUgYWxsb3dlZC5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gV2hldGhlciB0byBhbGxvdyBmbG9hdCB2YWx1ZXMuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRGbG9hdCh2YWx1ZTogYm9vbGVhbiB8IFByZXZDYWxsZXI8UiwgYm9vbGVhbiB8IEZhbHN5PiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBmbG9hdCB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLmZsb2F0ID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0byByb3VuZCB0byBmb3IgZmxvYXQgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBwcmVjaXNpb24gb2YgZmxvYXQgaW5wdXRzLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0Um91bmQodmFsdWU6IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIHJvdW5kIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMucm91bmQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgaW5zdHJ1Y3Rpb25zIGZvciB0aGUgdXNlci5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhZGRpdGlvbmFsIGd1aWRhbmNlIHByb3ZpZGVkIHRvIHRoZSB1c2VyLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgaW5zdHJ1Y3Rpb25zLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0SW5zdHJ1Y3Rpb25zKHZhbHVlOiBzdHJpbmcgfCBib29sZWFuIHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGluc3RydWN0aW9ucyB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLmluc3RydWN0aW9ucyA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBpbmNyZW1lbnQgdmFsdWUgZm9yIG51bWJlciBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIHN0ZXAgc2l6ZSB3aGVuIGluY3JlYXNpbmcgb3IgZGVjcmVhc2luZyB0aGUgbnVtYmVyLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgaW5jcmVtZW50IHZhbHVlLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0SW5jcmVtZW50KFxuICAgIHZhbHVlOiBudW1iZXIgfCBQcmV2Q2FsbGVyPFIsIG51bWJlciB8IEZhbHN5PiB8IHVuZGVmaW5lZFxuICApOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgaW5jcmVtZW50IHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuaW5jcmVtZW50ID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIHNlcGFyYXRvciBmb3IgbGlzdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGNoYXJhY3RlciB1c2VkIHRvIHNlcGFyYXRlIGxpc3QgaXRlbXMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBzZXBhcmF0b3IgY2hhcmFjdGVyLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0U2VwYXJhdG9yKFxuICAgIHZhbHVlOiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZFxuICApOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgc2VwYXJhdG9yIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuc2VwYXJhdG9yID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGFjdGl2ZSBvcHRpb24gc3R5bGUgZm9yIHNlbGVjdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIHN0eWxlIGFwcGxpZWQgdG8gdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBvcHRpb24uXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBhY3RpdmUgb3B0aW9uIHN0eWxlLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0QWN0aXZlKHZhbHVlOiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBhY3RpdmUgc3R5bGUgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5hY3RpdmUgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgaW5hY3RpdmUgb3B0aW9uIHN0eWxlIGZvciBzZWxlY3QgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBzdHlsZSBhcHBsaWVkIHRvIG5vbi1zZWxlY3RlZCBvcHRpb25zLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgaW5hY3RpdmUgb3B0aW9uIHN0eWxlLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0SW5hY3RpdmUodmFsdWU6IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGluYWN0aXZlIHN0eWxlIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuaW5hY3RpdmUgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgY2hvaWNlcyBmb3Igc2VsZWN0LCBtdWx0aXNlbGVjdCwgb3IgYXV0b2NvbXBsZXRlIGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgYXZhaWxhYmxlIG9wdGlvbnMgdGhhdCB0aGUgdXNlciBjYW4gc2VsZWN0IGZyb20gaW4gY2hvaWNlLWJhc2VkIHByb21wdHMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBhcnJheSBvZiBjaG9pY2VzIG9yIGEgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIHRoZSBjaG9pY2VzLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0Q2hvaWNlcyhcbiAgICB2YWx1ZTogQ2hvaWNlW10gfCBQcmV2Q2FsbGVyPFIsIENob2ljZVtdIHwgRmFsc3k+IHwgdW5kZWZpbmVkXG4gICk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBjaG9pY2VzOiAke0pTT04uc3RyaW5naWZ5KHZhbHVlKX1gKTtcbiAgICB0aGlzLmNob2ljZXMgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgaGludCB0ZXh0IGZvciB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gZGlzcGxheWVkIHRvIHRoZSB1c2VyLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgaGludCB0ZXh0LlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0SGludCh2YWx1ZTogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgaGludCB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLmhpbnQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgd2FybmluZyB0ZXh0IGZvciB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIGEgd2FybmluZyBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHdhcm5pbmcgdGV4dC5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldFdhcm4odmFsdWU6IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIHdhcm4gdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy53YXJuID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIHN1Z2dlc3Rpb24gZnVuY3Rpb24gZm9yIGF1dG9jb21wbGV0ZSBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgYSBmdW5jdGlvbiB0aGF0IHByb3ZpZGVzIHN1Z2dlc3Rpb25zIGJhc2VkIG9uIHRoZSB1c2VyJ3MgaW5wdXQgYW5kIGF2YWlsYWJsZSBjaG9pY2VzLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgdGhlIGN1cnJlbnQgaW5wdXQgYW5kIGF2YWlsYWJsZSBjaG9pY2VzIGFuZCByZXR1cm5zIGEgUHJvbWlzZSByZXNvbHZpbmcgdG8gc3VnZ2VzdGlvbnMuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRTdWdnZXN0KFxuICAgIHZhbHVlOiAoKGlucHV0OiBhbnksIGNob2ljZXM6IENob2ljZVtdKSA9PiBQcm9taXNlPGFueT4pIHwgdW5kZWZpbmVkXG4gICk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBzdWdnZXN0IGZ1bmN0aW9uYCk7XG4gICAgdGhpcy5zdWdnZXN0ID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGxpbWl0IGZvciBsaXN0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgbWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdGhhdCBjYW4gYmUgc2VsZWN0ZWQgaW4gbGlzdC10eXBlIHByb21wdHMuXG4gICAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgdGhlIHByb21wdCBuYW1lLCBleHRlbmRpbmcgc3RyaW5nLlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdGhhdCBjYW4gYmUgc2VsZWN0ZWQsIG9yIGEgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIHRoaXMgdmFsdWUuXG4gICAqIEByZXR1cm4gVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldExpbWl0KHZhbHVlOiBudW1iZXIgfCBQcmV2Q2FsbGVyPFIsIG51bWJlciB8IEZhbHN5PiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBsaW1pdCB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLmxpbWl0ID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIG1hc2sgZm9yIHBhc3N3b3JkIGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgY2hhcmFjdGVyIHVzZWQgdG8gaGlkZSB0aGUgdXNlcidzIGlucHV0IGluIHBhc3N3b3JkLXR5cGUgcHJvbXB0cy5cbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgcHJvbXB0IG5hbWUsIGV4dGVuZGluZyBzdHJpbmcuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBjaGFyYWN0ZXIgdXNlZCB0byBtYXNrIHRoZSBpbnB1dCwgb3IgYSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgdGhpcyB2YWx1ZS5cbiAgICogQHJldHVybiBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0TWFzayh2YWx1ZTogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgbWFzayB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLm1hc2sgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgc3Rkb3V0IHN0cmVhbSBmb3IgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgb3V0cHV0IHN0cmVhbSB1c2VkIGJ5IHRoZSBwcm9tcHQgZm9yIGRpc3BsYXlpbmcgbWVzc2FnZXMgYW5kIHJlc3VsdHMuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBXcml0YWJsZSBzdHJlYW0gdG8gYmUgdXNlZCBhcyBzdGRvdXQuXG4gICAqIEByZXR1cm4gVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldFN0ZG91dCh2YWx1ZTogV3JpdGFibGUgfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgc3Rkb3V0IHN0cmVhbWApO1xuICAgIHRoaXMuc3Rkb3V0ID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBzdGRpbiBzdHJlYW0gZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGlucHV0IHN0cmVhbSB1c2VkIGJ5IHRoZSBwcm9tcHQgZm9yIHJlY2VpdmluZyB1c2VyIGlucHV0LlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgUmVhZGFibGUgc3RyZWFtIHRvIGJlIHVzZWQgYXMgc3RkaW4uXG4gICAqIEByZXR1cm4gVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldFN0ZGluKHZhbHVlOiBSZWFkYWJsZSB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIHRoaXMuc3RkaW4gPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXNrcyB0aGUgdXNlciBmb3IgaW5wdXQgYmFzZWQgb24gdGhlIGN1cnJlbnQgVXNlcklucHV0IGNvbmZpZ3VyYXRpb24uXG4gICAqIEBzdW1tYXJ5IFByb21wdHMgdGhlIHVzZXIgYW5kIHJldHVybnMgdGhlaXIgcmVzcG9uc2UgYXMgYSBzaW5nbGUgdmFsdWUuXG4gICAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgdGhlIHByb21wdCBuYW1lLCBleHRlbmRpbmcgc3RyaW5nLlxuICAgKiBAcmV0dXJuIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSB1c2VyJ3MgYW5zd2VyLlxuICAgKi9cbiAgYXN5bmMgYXNrKCkge1xuICAgIHJldHVybiAoYXdhaXQgVXNlcklucHV0LmFzayh0aGlzKSlbdGhpcy5uYW1lIGFzIGtleW9mIEFuc3dlcnM8Uj5dO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBc2tzIHRoZSB1c2VyIG9uZSBvciBtb3JlIHF1ZXN0aW9ucyBiYXNlZCBvbiB0aGUgcHJvdmlkZWQgVXNlcklucHV0IGNvbmZpZ3VyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBQcm9tcHRzIHRoZSB1c2VyIHdpdGggb25lIG9yIG1vcmUgcXVlc3Rpb25zIGFuZCByZXR1cm5zIHRoZWlyIGFuc3dlcnMgYXMgYW4gb2JqZWN0LlxuICAgKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSBwcm9tcHQgbmFtZSwgZXh0ZW5kaW5nIHN0cmluZy5cbiAgICogQHBhcmFtIHF1ZXN0aW9uIC0gQSBzaW5nbGUgVXNlcklucHV0IGluc3RhbmNlIG9yIGFuIGFycmF5IG9mIFVzZXJJbnB1dCBpbnN0YW5jZXMuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHVzZXIncyBhbnN3ZXJzLlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXJcbiAgICogICBwYXJ0aWNpcGFudCBBIGFzIGFzayBtZXRob2RcbiAgICogICBwYXJ0aWNpcGFudCBQIGFzIHByb21wdHMgbGlicmFyeVxuICAgKiAgIEEtPj5QOiBDYWxsIHByb21wdHMgd2l0aCBxdWVzdGlvbihzKVxuICAgKiAgIFAtPj5VOiBEaXNwbGF5IHByb21wdChzKVxuICAgKiAgIFUtPj5QOiBQcm92aWRlIGlucHV0XG4gICAqICAgUC0+PkE6IFJldHVybiBhbnN3ZXJzXG4gICAqICAgQS0+PkE6IFByb2Nlc3MgYW5zd2Vyc1xuICAgKiAgIEEtLT4+Q2FsbGVyOiBSZXR1cm4gcHJvY2Vzc2VkIGFuc3dlcnNcbiAgICovXG4gIHN0YXRpYyBhc3luYyBhc2s8UiBleHRlbmRzIHN0cmluZyA9IHN0cmluZz4oXG4gICAgcXVlc3Rpb246IFVzZXJJbnB1dDxSPiB8IFVzZXJJbnB1dDxSPltdXG4gICkge1xuICAgIGNvbnN0IGxvZyA9IFVzZXJJbnB1dC5sb2dnZXIuZm9yKHRoaXMuYXNrKTtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkocXVlc3Rpb24pKSB7XG4gICAgICBxdWVzdGlvbiA9IFtxdWVzdGlvbl07XG4gICAgfVxuICAgIGxldCBhbnN3ZXJzOiBBbnN3ZXJzPFI+O1xuICAgIHRyeSB7XG4gICAgICBsb2cudmVyYm9zZShcbiAgICAgICAgYEFza2luZyBxdWVzdGlvbnM6ICR7cXVlc3Rpb24ubWFwKChxKSA9PiBxLm5hbWUpLmpvaW4oXCIsIFwiKX1gXG4gICAgICApO1xuICAgICAgYW5zd2VycyA9IGF3YWl0IHByb21wdHMocXVlc3Rpb24pO1xuICAgICAgbG9nLnZlcmJvc2UoYFJlY2VpdmVkIGFuc3dlcnM6ICR7SlNPTi5zdHJpbmdpZnkoYW5zd2VycywgbnVsbCwgMil9YCk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hpbGUgZ2V0dGluZyBpbnB1dDogJHtlcnJvcn1gKTtcbiAgICB9XG4gICAgcmV0dXJuIGFuc3dlcnM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFza3MgdGhlIHVzZXIgZm9yIGEgbnVtYmVyIGlucHV0LlxuICAgKiBAc3VtbWFyeSBQcm9tcHRzIHRoZSB1c2VyIHRvIGVudGVyIGEgbnVtYmVyLCB3aXRoIG9wdGlvbmFsIG1pbmltdW0sIG1heGltdW0sIGFuZCBpbml0aWFsIHZhbHVlcy5cbiAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcHJvbXB0LCB1c2VkIGFzIHRoZSBrZXkgaW4gdGhlIHJldHVybmVkIGFuc3dlcnMgb2JqZWN0LlxuICAgKiBAcGFyYW0gcXVlc3Rpb24gLSBUaGUgbWVzc2FnZSBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqIEBwYXJhbSBtaW4gLSBUaGUgbWluaW11bSBhbGxvd2VkIHZhbHVlIChvcHRpb25hbCkuXG4gICAqIEBwYXJhbSBtYXggLSBUaGUgbWF4aW11bSBhbGxvd2VkIHZhbHVlIChvcHRpb25hbCkuXG4gICAqIEBwYXJhbSBpbml0aWFsIC0gVGhlIGluaXRpYWwgdmFsdWUgcHJlc2VudGVkIHRvIHRoZSB1c2VyIChvcHRpb25hbCkuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIG51bWJlciBlbnRlcmVkIGJ5IHRoZSB1c2VyLlxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGFza051bWJlcihcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgcXVlc3Rpb246IHN0cmluZyxcbiAgICBtaW4/OiBudW1iZXIsXG4gICAgbWF4PzogbnVtYmVyLFxuICAgIGluaXRpYWw/OiBudW1iZXJcbiAgKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCBsb2cgPSBVc2VySW5wdXQubG9nZ2VyLmZvcih0aGlzLmFza051bWJlcik7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgQXNraW5nIG51bWJlciBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIG1pbjogJHttaW59LCBtYXg6ICR7bWF4fSwgaW5pdGlhbDogJHtpbml0aWFsfWBcbiAgICApO1xuICAgIGNvbnN0IHVzZXJJbnB1dCA9IG5ldyBVc2VySW5wdXQobmFtZSlcbiAgICAgIC5zZXRNZXNzYWdlKHF1ZXN0aW9uKVxuICAgICAgLnNldFR5cGUoXCJudW1iZXJcIik7XG5cbiAgICBpZiAodHlwZW9mIG1pbiA9PT0gXCJudW1iZXJcIikgdXNlcklucHV0LnNldE1pbihtaW4pO1xuXG4gICAgaWYgKHR5cGVvZiBtYXggPT09IFwibnVtYmVyXCIpIHVzZXJJbnB1dC5zZXRNYXgobWF4KTtcblxuICAgIGlmICh0eXBlb2YgaW5pdGlhbCA9PT0gXCJudW1iZXJcIikgdXNlcklucHV0LnNldEluaXRpYWwoaW5pdGlhbCk7XG5cbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuYXNrKHVzZXJJbnB1dCkpW25hbWVdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBc2tzIHRoZSB1c2VyIGZvciBhIHRleHQgaW5wdXQuXG4gICAqIEBzdW1tYXJ5IFByb21wdHMgdGhlIHVzZXIgdG8gZW50ZXIgdGV4dCwgd2l0aCBvcHRpb25hbCBtYXNraW5nIGFuZCBpbml0aWFsIHZhbHVlLlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIG1hc2sgLSBUaGUgY2hhcmFjdGVyIHVzZWQgdG8gbWFzayB0aGUgaW5wdXQgKG9wdGlvbmFsLCBmb3IgcGFzc3dvcmQtbGlrZSBpbnB1dHMpLlxuICAgKiBAcGFyYW0gaW5pdGlhbCAtIFRoZSBpbml0aWFsIHZhbHVlIHByZXNlbnRlZCB0byB0aGUgdXNlciAob3B0aW9uYWwpLlxuICAgKiBAcmV0dXJuIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSB0ZXh0IGVudGVyZWQgYnkgdGhlIHVzZXIuXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgYXNrVGV4dChcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgcXVlc3Rpb246IHN0cmluZyxcbiAgICBtYXNrOiBzdHJpbmcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQsXG4gICAgaW5pdGlhbD86IHN0cmluZ1xuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IGxvZyA9IFVzZXJJbnB1dC5sb2dnZXIuZm9yKHRoaXMuYXNrVGV4dCk7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgQXNraW5nIHRleHQgaW5wdXQ6IHVuZGVmaW5lZCwgcXVlc3Rpb246ICR7cXVlc3Rpb259LCBtYXNrOiAke21hc2t9LCBpbml0aWFsOiAke2luaXRpYWx9YFxuICAgICk7XG4gICAgY29uc3QgdXNlcklucHV0ID0gbmV3IFVzZXJJbnB1dChuYW1lKS5zZXRNZXNzYWdlKHF1ZXN0aW9uKTtcblxuICAgIGlmIChtYXNrKSB1c2VySW5wdXQuc2V0TWFzayhtYXNrKTtcbiAgICBpZiAodHlwZW9mIGluaXRpYWwgPT09IFwic3RyaW5nXCIpIHVzZXJJbnB1dC5zZXRJbml0aWFsKGluaXRpYWwpO1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5hc2sodXNlcklucHV0KSlbbmFtZV07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFza3MgdGhlIHVzZXIgZm9yIGEgY29uZmlybWF0aW9uICh5ZXMvbm8pLlxuICAgKiBAc3VtbWFyeSBQcm9tcHRzIHRoZSB1c2VyIHdpdGggYSB5ZXMvbm8gcXVlc3Rpb24gYW5kIHJldHVybnMgYSBib29sZWFuIHJlc3VsdC5cbiAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcHJvbXB0LCB1c2VkIGFzIHRoZSBrZXkgaW4gdGhlIHJldHVybmVkIGFuc3dlcnMgb2JqZWN0LlxuICAgKiBAcGFyYW0gcXVlc3Rpb24gLSBUaGUgbWVzc2FnZSBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqIEBwYXJhbSBpbml0aWFsIC0gVGhlIGluaXRpYWwgdmFsdWUgcHJlc2VudGVkIHRvIHRoZSB1c2VyIChvcHRpb25hbCkuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBib29sZWFuIHJlcHJlc2VudGluZyB0aGUgdXNlcidzIGFuc3dlci5cbiAgICovXG4gIHN0YXRpYyBhc3luYyBhc2tDb25maXJtYXRpb24oXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIHF1ZXN0aW9uOiBzdHJpbmcsXG4gICAgaW5pdGlhbD86IGJvb2xlYW5cbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgbG9nID0gVXNlcklucHV0LmxvZ2dlci5mb3IodGhpcy5hc2tDb25maXJtYXRpb24pO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYEFza2luZyBjb25maXJtYXRpb24gaW5wdXQ6IHVuZGVmaW5lZCwgcXVlc3Rpb246ICR7cXVlc3Rpb259LCBpbml0aWFsOiAke2luaXRpYWx9YFxuICAgICk7XG4gICAgY29uc3QgdXNlcklucHV0ID0gbmV3IFVzZXJJbnB1dChuYW1lKVxuICAgICAgLnNldE1lc3NhZ2UocXVlc3Rpb24pXG4gICAgICAuc2V0VHlwZShcImNvbmZpcm1cIik7XG5cbiAgICBpZiAodHlwZW9mIGluaXRpYWwgIT09IFwidW5kZWZpbmVkXCIpIHVzZXJJbnB1dC5zZXRJbml0aWFsKGluaXRpYWwpO1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5hc2sodXNlcklucHV0KSlbbmFtZV07XG4gIH1cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXBlYXRlZGx5IGFza3MgZm9yIGlucHV0IHVudGlsIGEgdmFsaWQgcmVzcG9uc2UgaXMgZ2l2ZW4gb3IgdGhlIGxpbWl0IGlzIHJlYWNoZWQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGluc2lzdHMgb24gZ2V0dGluZyBhIHZhbGlkIGlucHV0IGZyb20gdGhlIHVzZXIsIGFsbG93aW5nIGZvciBhIHNwZWNpZmllZCBudW1iZXIgb2YgYXR0ZW1wdHMuXG4gICAqXG4gICAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgdGhlIGV4cGVjdGVkIHJlc3VsdC5cbiAgICogQHBhcmFtIGlucHV0IC0gVGhlIFVzZXJJbnB1dCBpbnN0YW5jZSB0byB1c2UgZm9yIHByb21wdGluZy5cbiAgICogQHBhcmFtIHtmdW5jdGlvbihzdHJpbmcpOmJvb2xlYW59IHRlc3QgLSBWYWxpZGF0b3IgZnVuY3Rpb24gcmVjZWl2aW5nIHRoZSB1c2VyIGlucHV0IGFuZCByZXR1cm5pbmcgd2hldGhlciBpdCBpcyB2YWxpZC5cbiAgICogQHBhcmFtIGRlZmF1bHRDb25maXJtYXRpb24gLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgdGhlIGNvbmZpcm1hdGlvbiBwcm9tcHQgKHRydWUgZm9yIHllcywgZmFsc2UgZm9yIG5vKS5cbiAgICogQHBhcmFtIGxpbWl0IC0gVGhlIG1heGltdW0gbnVtYmVyIG9mIGF0dGVtcHRzIGFsbG93ZWQgKGRlZmF1bHQgaXMgMSkuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHZhbGlkIGlucHV0IG9yIHVuZGVmaW5lZCBpZiB0aGUgbGltaXQgaXMgcmVhY2hlZC5cbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgVSBhcyBVc2VyXG4gICAqICAgcGFydGljaXBhbnQgSSBhcyBpbnNpc3QgbWV0aG9kXG4gICAqICAgcGFydGljaXBhbnQgQSBhcyBhc2sgbWV0aG9kXG4gICAqICAgcGFydGljaXBhbnQgVCBhcyB0ZXN0IGZ1bmN0aW9uXG4gICAqICAgcGFydGljaXBhbnQgQyBhcyBhc2tDb25maXJtYXRpb24gbWV0aG9kXG4gICAqICAgbG9vcCBVbnRpbCB2YWxpZCBpbnB1dCBvciBsaW1pdCByZWFjaGVkXG4gICAqICAgICBJLT4+QTogQ2FsbCBhc2sgd2l0aCBpbnB1dFxuICAgKiAgICAgQS0+PlU6IFByb21wdCB1c2VyXG4gICAqICAgICBVLT4+QTogUHJvdmlkZSBpbnB1dFxuICAgKiAgICAgQS0+Pkk6IFJldHVybiByZXN1bHRcbiAgICogICAgIEktPj5UOiBUZXN0IHJlc3VsdFxuICAgKiAgICAgYWx0IFRlc3QgcGFzc2VzXG4gICAqICAgICAgIEktPj5DOiBBc2sgZm9yIGNvbmZpcm1hdGlvblxuICAgKiAgICAgICBDLT4+VTogQ29uZmlybSBpbnB1dFxuICAgKiAgICAgICBVLT4+QzogUHJvdmlkZSBjb25maXJtYXRpb25cbiAgICogICAgICAgQy0+Pkk6IFJldHVybiBjb25maXJtYXRpb25cbiAgICogICAgICAgYWx0IENvbmZpcm1lZFxuICAgKiAgICAgICAgIEktLT4+Q2FsbGVyOiBSZXR1cm4gdmFsaWQgcmVzdWx0XG4gICAqICAgICAgIGVsc2UgTm90IGNvbmZpcm1lZFxuICAgKiAgICAgICAgIEktPj5JOiBDb250aW51ZSBsb29wXG4gICAqICAgICAgIGVuZFxuICAgKiAgICAgZWxzZSBUZXN0IGZhaWxzXG4gICAqICAgICAgIEktPj5JOiBDb250aW51ZSBsb29wXG4gICAqICAgICBlbmRcbiAgICogICBlbmRcbiAgICogICBJLS0+PkNhbGxlcjogUmV0dXJuIHVuZGVmaW5lZCBpZiBsaW1pdCByZWFjaGVkXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgaW5zaXN0PFI+KFxuICAgIGlucHV0OiBVc2VySW5wdXQsXG4gICAgdGVzdDogKHJlczogc3RyaW5nIHwgbnVtYmVyKSA9PiBib29sZWFuLFxuICAgIGRlZmF1bHRDb25maXJtYXRpb246IGJvb2xlYW4sXG4gICAgbGltaXQgPSAxXG4gICk6IFByb21pc2U8UiB8IHVuZGVmaW5lZD4ge1xuICAgIGNvbnN0IGxvZyA9IFVzZXJJbnB1dC5sb2dnZXIuZm9yKHRoaXMuaW5zaXN0KTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBJbnNpc3Rpbmcgb24gaW5wdXQ6ICR7aW5wdXQubmFtZX0sIHRlc3Q6ICR7dGVzdC50b1N0cmluZygpfSwgZGVmYXVsdENvbmZpcm1hdGlvbjogJHtkZWZhdWx0Q29uZmlybWF0aW9ufSwgbGltaXQ6ICR7bGltaXR9YFxuICAgICk7XG4gICAgbGV0IHJlc3VsdDogc3RyaW5nIHwgbnVtYmVyIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgIGxldCBjb3VudCA9IDA7XG4gICAgbGV0IGNvbmZpcm1hdGlvbjogYm9vbGVhbjtcbiAgICB0cnkge1xuICAgICAgZG8ge1xuICAgICAgICByZXN1bHQgPSAoYXdhaXQgVXNlcklucHV0LmFzayhpbnB1dCkpW1xuICAgICAgICAgIGlucHV0Lm5hbWUgYXMga2V5b2YgQW5zd2VyczxzdHJpbmc+XG4gICAgICAgIF0gYXMgc3RyaW5nO1xuICAgICAgICBpZiAoIXRlc3QocmVzdWx0KSkge1xuICAgICAgICAgIHJlc3VsdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25maXJtYXRpb24gPSBhd2FpdCBVc2VySW5wdXQuYXNrQ29uZmlybWF0aW9uKFxuICAgICAgICAgIGAke2lucHV0Lm5hbWV9LWNvbmZpcm1gLFxuICAgICAgICAgIGBJcyB0aGUgJHtpbnB1dC50eXBlfSBjb3JyZWN0P2AsXG4gICAgICAgICAgZGVmYXVsdENvbmZpcm1hdGlvblxuICAgICAgICApO1xuICAgICAgICBpZiAoIWNvbmZpcm1hdGlvbikgcmVzdWx0ID0gdW5kZWZpbmVkO1xuICAgICAgfSB3aGlsZSAodHlwZW9mIHJlc3VsdCA9PT0gXCJ1bmRlZmluZWRcIiAmJiBsaW1pdCA+IDEgJiYgY291bnQrKyA8IGxpbWl0KTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBsb2cuZXJyb3IoYEVycm9yIHdoaWxlIGluc2lzdGluZzogJHtlfWApO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIHJlc3VsdCA9PT0gXCJ1bmRlZmluZWRcIikgbG9nLmluZm8oXCJubyBzZWxlY3Rpb24uLi5cIik7XG4gICAgcmV0dXJuIHJlc3VsdCBhcyBSIHwgdW5kZWZpbmVkO1xuICB9XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVwZWF0ZWRseSBhc2tzIGZvciB0ZXh0IGlucHV0IHVudGlsIGEgdmFsaWQgcmVzcG9uc2UgaXMgZ2l2ZW4gb3IgdGhlIGxpbWl0IGlzIHJlYWNoZWQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGluc2lzdHMgb24gZ2V0dGluZyBhIHZhbGlkIHRleHQgaW5wdXQgZnJvbSB0aGUgdXNlciwgYWxsb3dpbmcgZm9yIGEgc3BlY2lmaWVkIG51bWJlciBvZiBhdHRlbXB0cy5cbiAgICpcbiAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcHJvbXB0LCB1c2VkIGFzIHRoZSBrZXkgaW4gdGhlIHJldHVybmVkIGFuc3dlcnMgb2JqZWN0LlxuICAgKiBAcGFyYW0gcXVlc3Rpb24gLSBUaGUgbWVzc2FnZSBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24obnVtYmVyKTpib29sZWFufSB0ZXN0IC0gVmFsaWRhdG9yIGZ1bmN0aW9uIHJlY2VpdmluZyB0aGUgdXNlciBpbnB1dCBhbmQgcmV0dXJuaW5nIHdoZXRoZXIgaXQgaXMgdmFsaWQuXG4gICAqIEBwYXJhbSBtYXNrIC0gVGhlIGNoYXJhY3RlciB1c2VkIHRvIG1hc2sgdGhlIGlucHV0IChvcHRpb25hbCwgZm9yIHBhc3N3b3JkLWxpa2UgaW5wdXRzKS5cbiAgICogQHBhcmFtIGluaXRpYWwgLSBUaGUgaW5pdGlhbCB2YWx1ZSBwcmVzZW50ZWQgdG8gdGhlIHVzZXIgKG9wdGlvbmFsKS5cbiAgICogQHBhcmFtIGRlZmF1bHRDb25maXJtYXRpb24gLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgdGhlIGNvbmZpcm1hdGlvbiBwcm9tcHQgKHRydWUgZm9yIHllcywgZmFsc2UgZm9yIG5vKS5cbiAgICogQHBhcmFtIGxpbWl0IC0gVGhlIG1heGltdW0gbnVtYmVyIG9mIGF0dGVtcHRzIGFsbG93ZWQgKGRlZmF1bHQgaXMgLTEsIG1lYW5pbmcgdW5saW1pdGVkKS5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgdmFsaWQgaW5wdXQgb3IgdW5kZWZpbmVkIGlmIHRoZSBsaW1pdCBpcyByZWFjaGVkLlxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGluc2lzdEZvclRleHQoXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIHF1ZXN0aW9uOiBzdHJpbmcsXG4gICAgdGVzdDogKHJlczogc3RyaW5nKSA9PiBib29sZWFuLFxuICAgIG1hc2s6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbiAgICBpbml0aWFsPzogc3RyaW5nLFxuICAgIGRlZmF1bHRDb25maXJtYXRpb24gPSBmYWxzZSxcbiAgICBsaW1pdCA9IC0xXG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgbG9nID0gVXNlcklucHV0LmxvZ2dlci5mb3IodGhpcy5pbnNpc3RGb3JUZXh0KTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBJbnNpc3RpbmcgZm9yIHRleHQgaW5wdXQ6IHVuZGVmaW5lZCwgcXVlc3Rpb246ICR7cXVlc3Rpb259LCB0ZXN0OiAke3Rlc3QudG9TdHJpbmcoKX0sIG1hc2s6ICR7bWFza30sIGluaXRpYWw6ICR7aW5pdGlhbH0sIGRlZmF1bHRDb25maXJtYXRpb246ICR7ZGVmYXVsdENvbmZpcm1hdGlvbn0sIGxpbWl0OiAke2xpbWl0fWBcbiAgICApO1xuICAgIGNvbnN0IHVzZXJJbnB1dCA9IG5ldyBVc2VySW5wdXQobmFtZSkuc2V0TWVzc2FnZShxdWVzdGlvbik7XG5cbiAgICBpZiAobWFzaykgdXNlcklucHV0LnNldE1hc2sobWFzayk7XG4gICAgaWYgKHR5cGVvZiBpbml0aWFsID09PSBcInN0cmluZ1wiKSB1c2VySW5wdXQuc2V0SW5pdGlhbChpbml0aWFsKTtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuaW5zaXN0KFxuICAgICAgdXNlcklucHV0LFxuICAgICAgdGVzdCBhcyAocmVzOiBzdHJpbmcgfCBudW1iZXIpID0+IGJvb2xlYW4sXG4gICAgICBkZWZhdWx0Q29uZmlybWF0aW9uLFxuICAgICAgbGltaXRcbiAgICApKSBhcyBzdHJpbmc7XG4gIH1cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXBlYXRlZGx5IGFza3MgZm9yIG51bWJlciBpbnB1dCB1bnRpbCBhIHZhbGlkIHJlc3BvbnNlIGlzIGdpdmVuIG9yIHRoZSBsaW1pdCBpcyByZWFjaGVkLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBpbnNpc3RzIG9uIGdldHRpbmcgYSB2YWxpZCBudW1iZXIgaW5wdXQgZnJvbSB0aGUgdXNlciwgYWxsb3dpbmcgZm9yIGEgc3BlY2lmaWVkIG51bWJlciBvZiBhdHRlbXB0cy5cbiAgICpcbiAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcHJvbXB0LCB1c2VkIGFzIHRoZSBrZXkgaW4gdGhlIHJldHVybmVkIGFuc3dlcnMgb2JqZWN0LlxuICAgKiBAcGFyYW0gcXVlc3Rpb24gLSBUaGUgbWVzc2FnZSBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqIEBwYXJhbSB0ZXN0IC0gQSBmdW5jdGlvbiB0byB2YWxpZGF0ZSB0aGUgdXNlcidzIGlucHV0LlxuICAgKiBAcGFyYW0gbWluIC0gVGhlIG1pbmltdW0gYWxsb3dlZCB2YWx1ZSAob3B0aW9uYWwpLlxuICAgKiBAcGFyYW0gbWF4IC0gVGhlIG1heGltdW0gYWxsb3dlZCB2YWx1ZSAob3B0aW9uYWwpLlxuICAgKiBAcGFyYW0gaW5pdGlhbCAtIFRoZSBpbml0aWFsIHZhbHVlIHByZXNlbnRlZCB0byB0aGUgdXNlciAob3B0aW9uYWwpLlxuICAgKiBAcGFyYW0gZGVmYXVsdENvbmZpcm1hdGlvbiAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGUgY29uZmlybWF0aW9uIHByb21wdCAodHJ1ZSBmb3IgeWVzLCBmYWxzZSBmb3Igbm8pLlxuICAgKiBAcGFyYW0gbGltaXQgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgYXR0ZW1wdHMgYWxsb3dlZCAoZGVmYXVsdCBpcyAtMSwgbWVhbmluZyB1bmxpbWl0ZWQpLlxuICAgKiBAcmV0dXJuIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSB2YWxpZCBpbnB1dCBvciB1bmRlZmluZWQgaWYgdGhlIGxpbWl0IGlzIHJlYWNoZWQuXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgaW5zaXN0Rm9yTnVtYmVyKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBxdWVzdGlvbjogc3RyaW5nLFxuICAgIHRlc3Q6IChyZXM6IG51bWJlcikgPT4gYm9vbGVhbixcbiAgICBtaW4/OiBudW1iZXIsXG4gICAgbWF4PzogbnVtYmVyLFxuICAgIGluaXRpYWw/OiBudW1iZXIsXG4gICAgZGVmYXVsdENvbmZpcm1hdGlvbiA9IGZhbHNlLFxuICAgIGxpbWl0ID0gLTFcbiAgKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBjb25zdCBsb2cgPSBVc2VySW5wdXQubG9nZ2VyLmZvcih0aGlzLmluc2lzdEZvck51bWJlcik7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgSW5zaXN0aW5nIGZvciBudW1iZXIgaW5wdXQ6IHVuZGVmaW5lZCwgcXVlc3Rpb246ICR7cXVlc3Rpb259LCB0ZXN0OiAke3Rlc3QudG9TdHJpbmcoKX0sIG1pbjogJHttaW59LCBtYXg6ICR7bWF4fSwgaW5pdGlhbDogJHtpbml0aWFsfSwgZGVmYXVsdENvbmZpcm1hdGlvbjogJHtkZWZhdWx0Q29uZmlybWF0aW9ufSwgbGltaXQ6ICR7bGltaXR9YFxuICAgICk7XG4gICAgY29uc3QgdXNlcklucHV0ID0gbmV3IFVzZXJJbnB1dChuYW1lKVxuICAgICAgLnNldE1lc3NhZ2UocXVlc3Rpb24pXG4gICAgICAuc2V0VHlwZShcIm51bWJlclwiKTtcblxuICAgIGlmICh0eXBlb2YgbWluID09PSBcIm51bWJlclwiKSB1c2VySW5wdXQuc2V0TWluKG1pbik7XG5cbiAgICBpZiAodHlwZW9mIG1heCA9PT0gXCJudW1iZXJcIikgdXNlcklucHV0LnNldE1heChtYXgpO1xuXG4gICAgaWYgKHR5cGVvZiBpbml0aWFsID09PSBcIm51bWJlclwiKSB1c2VySW5wdXQuc2V0SW5pdGlhbChpbml0aWFsKTtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuaW5zaXN0KFxuICAgICAgdXNlcklucHV0LFxuICAgICAgdGVzdCBhcyAocmVzOiBzdHJpbmcgfCBudW1iZXIpID0+IGJvb2xlYW4sXG4gICAgICBkZWZhdWx0Q29uZmlybWF0aW9uLFxuICAgICAgbGltaXRcbiAgICApKSBhcyBudW1iZXI7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBhcnNlcyBjb21tYW5kLWxpbmUgYXJndW1lbnRzIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBvcHRpb25zLlxuICAgKiBAc3VtbWFyeSBVc2VzIE5vZGUuanMncyB1dGlsLnBhcnNlQXJncyB0byBwYXJzZSBjb21tYW5kLWxpbmUgYXJndW1lbnRzIGFuZCByZXR1cm4gdGhlIHJlc3VsdC5cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBDb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIHBhcnNpbmcgYXJndW1lbnRzLlxuICAgKiBAcmV0dXJuIEFuIG9iamVjdCBjb250YWluaW5nIHRoZSBwYXJzZWQgYXJndW1lbnRzLlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDIGFzIENhbGxlclxuICAgKiAgIHBhcnRpY2lwYW50IFAgYXMgcGFyc2VBcmdzIG1ldGhvZFxuICAgKiAgIHBhcnRpY2lwYW50IFUgYXMgdXRpbC5wYXJzZUFyZ3NcbiAgICogICBDLT4+UDogQ2FsbCB3aXRoIG9wdGlvbnNcbiAgICogICBQLT4+UDogUHJlcGFyZSBhcmdzIG9iamVjdFxuICAgKiAgIFAtPj5VOiBDYWxsIHBhcnNlQXJncyB3aXRoIHByZXBhcmVkIGFyZ3NcbiAgICogICBVLT4+UDogUmV0dXJuIHBhcnNlZCByZXN1bHRcbiAgICogICBQLS0+PkM6IFJldHVybiBQYXJzZUFyZ3NSZXN1bHRcbiAgICovXG4gIHN0YXRpYyBwYXJzZUFyZ3Mob3B0aW9uczogUGFyc2VBcmdzT3B0aW9uc0NvbmZpZyk6IFBhcnNlQXJnc1Jlc3VsdCB7XG4gICAgY29uc3QgbG9nID0gVXNlcklucHV0LmxvZ2dlci5mb3IodGhpcy5wYXJzZUFyZ3MpO1xuICAgIGNvbnN0IGFyZ3M6IFBhcnNlQXJnc0NvbmZpZyA9IHtcbiAgICAgIGFyZ3M6IHByb2Nlc3MuYXJndi5zbGljZSgyKSxcbiAgICAgIG9wdGlvbnM6IG9wdGlvbnMsXG4gICAgfTtcbiAgICBsb2cuZGVidWcoYFBhcnNpbmcgYXJndW1lbnRzOiAke0pTT04uc3RyaW5naWZ5KGFyZ3MsIG51bGwsIDIpfWApO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gcGFyc2VBcmdzKGFyZ3MpO1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBsb2cuZGVidWcoXG4gICAgICAgIGBFcnJvciB3aGlsZSBwYXJzaW5nIGFyZ3VtZW50czpcXG4ke0pTT04uc3RyaW5naWZ5KGFyZ3MsIG51bGwsIDIpfVxcbiB8IG9wdGlvbnNcXG4ke0pTT04uc3RyaW5naWZ5KG9wdGlvbnMsIG51bGwsIDIpfVxcbiB8ICR7ZXJyb3J9YFxuICAgICAgKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hpbGUgcGFyc2luZyBhcmd1bWVudHM6ICR7ZXJyb3J9YCk7XG4gICAgfVxuICB9XG59XG4iLCIvKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IGNvbW1hbmQgb3B0aW9ucyBmb3IgQ0xJIGNvbW1hbmRzLlxuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgc3RydWN0dXJlIGFuZCBkZWZhdWx0IHZhbHVlcyBmb3IgY29tbW9uIGNvbW1hbmQtbGluZSBvcHRpb25zIHVzZWQgYWNyb3NzIHZhcmlvdXMgQ0xJIGNvbW1hbmRzLlxuICogQGNvbnN0IERlZmF1bHRDb21tYW5kT3B0aW9uc1xuICogQHR5cGVkZWYge09iamVjdH0gRGVmYXVsdENvbW1hbmRPcHRpb25zXG4gKiBAcHJvcGVydHkge09iamVjdH0gdmVyYm9zZSAtIFZlcmJvc2l0eSBsZXZlbCBvcHRpb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdmVyYm9zZS50eXBlIC0gVGhlIHR5cGUgb2YgdGhlIHZlcmJvc2Ugb3B0aW9uIChudW1iZXIpLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHZlcmJvc2Uuc2hvcnQgLSBUaGUgc2hvcnQgZmxhZyBmb3IgdGhlIHZlcmJvc2Ugb3B0aW9uIChWKS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSB2ZXJib3NlLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgdmVyYm9zaXR5ICgwKS5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSB2ZXJzaW9uIC0gVmVyc2lvbiBkaXNwbGF5IG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB2ZXJzaW9uLnR5cGUgLSBUaGUgdHlwZSBvZiB0aGUgdmVyc2lvbiBvcHRpb24gKGJvb2xlYW4pLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHZlcnNpb24uc2hvcnQgLSBUaGUgc2hvcnQgZmxhZyBmb3IgdGhlIHZlcnNpb24gb3B0aW9uICh2KS5cbiAqIEBwcm9wZXJ0eSB7dW5kZWZpbmVkfSB2ZXJzaW9uLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgdmVyc2lvbiBkaXNwbGF5ICh1bmRlZmluZWQpLlxuICogQHByb3BlcnR5IHtPYmplY3R9IGhlbHAgLSBIZWxwIGRpc3BsYXkgb3B0aW9uLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IGhlbHAudHlwZSAtIFRoZSB0eXBlIG9mIHRoZSBoZWxwIG9wdGlvbiAoYm9vbGVhbikuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gaGVscC5zaG9ydCAtIFRoZSBzaG9ydCBmbGFnIGZvciB0aGUgaGVscCBvcHRpb24gKGgpLlxuICogQHByb3BlcnR5IHtib29sZWFufSBoZWxwLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgaGVscCBkaXNwbGF5IChmYWxzZSkuXG4gKiBAcHJvcGVydHkge09iamVjdH0gbG9nTGV2ZWwgLSBMb2cgbGV2ZWwgb3B0aW9uLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IGxvZ0xldmVsLnR5cGUgLSBUaGUgdHlwZSBvZiB0aGUgbG9nTGV2ZWwgb3B0aW9uIChzdHJpbmcpLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IGxvZ0xldmVsLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgbG9nIGxldmVsIChcImluZm9cIikuXG4gKiBAcHJvcGVydHkge09iamVjdH0gbG9nU3R5bGUgLSBMb2cgc3R5bGluZyBvcHRpb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gbG9nU3R5bGUudHlwZSAtIFRoZSB0eXBlIG9mIHRoZSBsb2dTdHlsZSBvcHRpb24gKGJvb2xlYW4pLlxuICogQHByb3BlcnR5IHtib29sZWFufSBsb2dTdHlsZS5kZWZhdWx0IC0gVGhlIGRlZmF1bHQgdmFsdWUgZm9yIGxvZyBzdHlsaW5nICh0cnVlKS5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSB0aW1lc3RhbXAgLSBUaW1lc3RhbXAgZGlzcGxheSBvcHRpb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdGltZXN0YW1wLnR5cGUgLSBUaGUgdHlwZSBvZiB0aGUgdGltZXN0YW1wIG9wdGlvbiAoYm9vbGVhbikuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IHRpbWVzdGFtcC5kZWZhdWx0IC0gVGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRpbWVzdGFtcCBkaXNwbGF5ICh0cnVlKS5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBiYW5uZXIgLSBCYW5uZXIgZGlzcGxheSBvcHRpb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gYmFubmVyLnR5cGUgLSBUaGUgdHlwZSBvZiB0aGUgYmFubmVyIG9wdGlvbiAoYm9vbGVhbikuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGJhbm5lci5kZWZhdWx0IC0gVGhlIGRlZmF1bHQgdmFsdWUgZm9yIGJhbm5lciBkaXNwbGF5IChmYWxzZSkuXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBEZWZhdWx0Q29tbWFuZE9wdGlvbnMgPSB7XG4gIHZlcmJvc2U6IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICBzaG9ydDogXCJWXCIsXG4gICAgZGVmYXVsdDogdW5kZWZpbmVkLFxuICB9LFxuICB2ZXJzaW9uOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgc2hvcnQ6IFwidlwiLFxuICAgIGRlZmF1bHQ6IHVuZGVmaW5lZCxcbiAgfSxcbiAgaGVscDoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIHNob3J0OiBcImhcIixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgbG9nTGV2ZWw6IHtcbiAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgIGRlZmF1bHQ6IFwiaW5mb1wiLFxuICB9LFxuICBsb2dTdHlsZToge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIGRlZmF1bHQ6IHRydWUsXG4gIH0sXG4gIHRpbWVzdGFtcDoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIGRlZmF1bHQ6IHRydWUsXG4gIH0sXG4gIGJhbm5lcjoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIGRlZmF1bHQ6IHRydWUsXG4gIH0sXG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IGNvbW1hbmQgdmFsdWVzIGRlcml2ZWQgZnJvbSBEZWZhdWx0Q29tbWFuZE9wdGlvbnMuXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGFuIG9iamVjdCB3aXRoIHRoZSBkZWZhdWx0IHZhbHVlcyBvZiBhbGwgb3B0aW9ucyBkZWZpbmVkIGluIERlZmF1bHRDb21tYW5kT3B0aW9ucy5cbiAqIEBjb25zdCBEZWZhdWx0Q29tbWFuZFZhbHVlc1xuICogQHR5cGVkZWYge09iamVjdH0gRGVmYXVsdENvbW1hbmRWYWx1ZXNcbiAqIEBwcm9wZXJ0eSB7dW5rbm93bn0gW2tleTogc3RyaW5nXSAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciBlYWNoIG9wdGlvbiBpbiBEZWZhdWx0Q29tbWFuZE9wdGlvbnMuXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBEZWZhdWx0Q29tbWFuZFZhbHVlczoge1xuICBbayBpbiBrZXlvZiB0eXBlb2YgRGVmYXVsdENvbW1hbmRPcHRpb25zXTogdW5rbm93bjtcbn0gPSBPYmplY3Qua2V5cyhEZWZhdWx0Q29tbWFuZE9wdGlvbnMpLnJlZHVjZShcbiAgKGFjYzogUmVjb3JkPGtleW9mIHR5cGVvZiBEZWZhdWx0Q29tbWFuZE9wdGlvbnMsIHVua25vd24+LCBrZXk6IHN0cmluZykgPT4ge1xuICAgIGFjY1trZXkgYXMga2V5b2YgdHlwZW9mIERlZmF1bHRDb21tYW5kT3B0aW9uc10gPVxuICAgICAgRGVmYXVsdENvbW1hbmRPcHRpb25zW2tleSBhcyBrZXlvZiB0eXBlb2YgRGVmYXVsdENvbW1hbmRPcHRpb25zXS5kZWZhdWx0O1xuICAgIHJldHVybiBhY2M7XG4gIH0sXG4gIHt9IGFzIFJlY29yZDxrZXlvZiB0eXBlb2YgRGVmYXVsdENvbW1hbmRWYWx1ZXMsIHVua25vd24+XG4pO1xuIiwiLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVmYXVsdCBlbmNvZGluZyBmb3IgdGV4dCBvcGVyYXRpb25zLlxuICogQHN1bW1hcnkgVGhlIHN0YW5kYXJkIFVURi04IGVuY29kaW5nIHVzZWQgZm9yIHRleHQgcHJvY2Vzc2luZy5cbiAqIEBjb25zdCB7c3RyaW5nfSBFbmNvZGluZ1xuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgY29uc3QgRW5jb2RpbmcgPSBcInV0Zi04XCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlZ3VsYXIgZXhwcmVzc2lvbiBmb3Igc2VtYW50aWMgdmVyc2lvbmluZy5cbiAqIEBzdW1tYXJ5IEEgcmVnZXggcGF0dGVybiB0byBtYXRjaCBhbmQgcGFyc2Ugc2VtYW50aWMgdmVyc2lvbiBzdHJpbmdzLlxuICogQGNvbnN0IHtSZWdFeHB9IFNlbVZlcnNpb25SZWdleFxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgY29uc3QgU2VtVmVyc2lvblJlZ2V4ID1cbiAgL14oXFxkKylcXC4oXFxkKylcXC4oXFxkKykoPzotKFswLTlBLVphLXotXSsoPzpcXC5bMC05QS1aYS16XSkpKS9nO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFbnVtIGZvciBzZW1hbnRpYyB2ZXJzaW9uIGNvbXBvbmVudHMuXG4gKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSB0aHJlZSBsZXZlbHMgb2Ygc2VtYW50aWMgdmVyc2lvbmluZzogUEFUQ0gsIE1JTk9SLCBhbmQgTUFKT1IuXG4gKiBAZW51bSB7c3RyaW5nfVxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZW51bSBTZW1WZXJzaW9uIHtcbiAgLyoqIFBhdGNoIHZlcnNpb24gZm9yIGJhY2t3YXJkcy1jb21wYXRpYmxlIGJ1ZyBmaXhlcy4gKi9cbiAgUEFUQ0ggPSBcInBhdGNoXCIsXG4gIC8qKiBNaW5vciB2ZXJzaW9uIGZvciBiYWNrd2FyZHMtY29tcGF0aWJsZSBuZXcgZmVhdHVyZXMuICovXG4gIE1JTk9SID0gXCJtaW5vclwiLFxuICAvKiogTWFqb3IgdmVyc2lvbiBmb3IgY2hhbmdlcyB0aGF0IGJyZWFrIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LiAqL1xuICBNQUpPUiA9IFwibWFqb3JcIixcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRmxhZyB0byBpbmRpY2F0ZSBub24tQ0kgZW52aXJvbm1lbnQuXG4gKiBAc3VtbWFyeSBVc2VkIHRvIHNwZWNpZnkgdGhhdCBhIGNvbW1hbmQgc2hvdWxkIHJ1biBvdXRzaWRlIG9mIGEgQ29udGludW91cyBJbnRlZ3JhdGlvbiBlbnZpcm9ubWVudC5cbiAqIEBjb25zdCB7c3RyaW5nfSBOb0NJRkxhZ1xuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgY29uc3QgTm9DSUZMYWcgPSBcIi1uby1jaVwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBLZXkgZm9yIHRoZSBzZXR1cCBzY3JpcHQgaW4gcGFja2FnZS5qc29uLlxuICogQHN1bW1hcnkgSWRlbnRpZmllcyB0aGUgc2NyaXB0IHRoYXQgcnVucyBhZnRlciBwYWNrYWdlIGluc3RhbGxhdGlvbi5cbiAqIEBjb25zdCB7c3RyaW5nfSBTZXR1cFNjcmlwdEtleVxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgY29uc3QgU2V0dXBTY3JpcHRLZXkgPSBcInBvc3RpbnN0YWxsXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVudW0gZm9yIHZhcmlvdXMgYXV0aGVudGljYXRpb24gdG9rZW5zLlxuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgZmlsZSBuYW1lcyBmb3Igc3RvcmluZyBkaWZmZXJlbnQgdHlwZXMgb2YgYXV0aGVudGljYXRpb24gdG9rZW5zLlxuICogQGVudW0ge3N0cmluZ31cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGVudW0gVG9rZW5zIHtcbiAgLyoqIEdpdCBhdXRoZW50aWNhdGlvbiB0b2tlbiBmaWxlIG5hbWUuICovXG4gIEdJVCA9IFwiLnRva2VuXCIsXG4gIC8qKiBOUE0gYXV0aGVudGljYXRpb24gdG9rZW4gZmlsZSBuYW1lLiAqL1xuICBOUE0gPSBcIi5ucG10b2tlblwiLFxuICAvKiogRG9ja2VyIGF1dGhlbnRpY2F0aW9uIHRva2VuIGZpbGUgbmFtZS4gKi9cbiAgRE9DS0VSID0gXCIuZG9ja2VydG9rZW5cIixcbiAgLyoqIENvbmZsdWVuY2UgYXV0aGVudGljYXRpb24gdG9rZW4gZmlsZSBuYW1lLiAqL1xuICBDT05GTFVFTkNFID0gXCIuY29uZmx1ZW5jZS10b2tlblwiLFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDb2RlIHVzZWQgdG8gaW5kaWNhdGUgYW4gb3BlcmF0aW9uIHdhcyBhYm9ydGVkLlxuICogQHN1bW1hcnkgU3RhbmRhcmQgbWVzc2FnZSB1c2VkIHdoZW4gYSBwcm9jZXNzIGlzIG1hbnVhbGx5IHRlcm1pbmF0ZWQuXG4gKiBAY29uc3Qge3N0cmluZ30gQWJvcnRDb2RlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBBYm9ydENvZGUgPSBcIkFib3J0ZWRcIjtcbiIsImltcG9ydCB7IEVuY29kaW5nIH0gZnJvbSBcIi4uL3V0aWxzL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgT3V0cHV0V3JpdGVyIH0gZnJvbSBcIi4vT3V0cHV0V3JpdGVyXCI7XG5pbXBvcnQgeyBQcm9taXNlRXhlY3V0b3IgfSBmcm9tIFwiLi4vdXRpbHMvdHlwZXNcIjtcbmltcG9ydCB7IE91dHB1dFR5cGUgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgc3R5bGUgfSBmcm9tIFwic3R5bGVkLXN0cmluZy1idWlsZGVyXCI7XG5pbXBvcnQgeyBMb2dnZXIsIExvZ2dpbmcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcbmltcG9ydCB7IHBhcnNlIH0gZnJvbSBcInNoZWxsLXF1b3RlXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgc3RhbmRhcmQgb3V0cHV0IHdyaXRlciBmb3IgaGFuZGxpbmcgY29tbWFuZCBleGVjdXRpb24gb3V0cHV0LlxuICogQHN1bW1hcnkgVGhpcyBjbGFzcyBpbXBsZW1lbnRzIHRoZSBPdXRwdXRXcml0ZXIgaW50ZXJmYWNlIGFuZCBwcm92aWRlcyBtZXRob2RzIGZvclxuICogaGFuZGxpbmcgdmFyaW91cyB0eXBlcyBvZiBvdXRwdXQgZnJvbSBjb21tYW5kIGV4ZWN1dGlvbiwgaW5jbHVkaW5nIHN0YW5kYXJkIG91dHB1dCxcbiAqIGVycm9yIG91dHB1dCwgYW5kIGV4aXQgY29kZXMuIEl0IGFsc28gaW5jbHVkZXMgdXRpbGl0eSBtZXRob2RzIGZvciBwYXJzaW5nIGNvbW1hbmRzXG4gKiBhbmQgcmVzb2x2aW5nIG9yIHJlamVjdGluZyBwcm9taXNlcyBiYXNlZCBvbiBleGVjdXRpb24gcmVzdWx0cy5cbiAqXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSByZXNvbHZlZCB2YWx1ZSwgZGVmYXVsdGluZyB0byBzdHJpbmcuXG4gKlxuICogQHBhcmFtIGNtZCAtIFRoZSBjb21tYW5kIHN0cmluZyB0byBiZSBleGVjdXRlZC5cbiAqIEBwYXJhbSBsb2NrIC0gQSBQcm9taXNlRXhlY3V0b3IgdG8gY29udHJvbCB0aGUgYXN5bmNocm9ub3VzIGZsb3cuXG4gKiBAcGFyYW0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzICh1bnVzZWQgaW4gdGhlIGN1cnJlbnQgaW1wbGVtZW50YXRpb24pLlxuICpcbiAqIEBjbGFzc1xuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IFN0YW5kYXJkT3V0cHV0V3JpdGVyIH0gZnJvbSAnQGRlY2FmLXRzL3V0aWxzJztcbiAqIGltcG9ydCB7IFByb21pc2VFeGVjdXRvciB9IGZyb20gJ0BkZWNhZi10cy91dGlscyc7XG4gKlxuICogLy8gQ3JlYXRlIGEgcHJvbWlzZSBleGVjdXRvclxuICogY29uc3QgZXhlY3V0b3I6IFByb21pc2VFeGVjdXRvcjxzdHJpbmc+ID0ge1xuICogICByZXNvbHZlOiAodmFsdWUpID0+IGNvbnNvbGUubG9nKGBSZXNvbHZlZDogJHt2YWx1ZX1gKSxcbiAqICAgcmVqZWN0OiAoZXJyb3IpID0+IGNvbnNvbGUuZXJyb3IoYFJlamVjdGVkOiAke2Vycm9yLm1lc3NhZ2V9YClcbiAqIH07XG4gKlxuICogLy8gQ3JlYXRlIGEgc3RhbmRhcmQgb3V0cHV0IHdyaXRlclxuICogY29uc3Qgd3JpdGVyID0gbmV3IFN0YW5kYXJkT3V0cHV0V3JpdGVyKCdscyAtbGEnLCBleGVjdXRvcik7XG4gKlxuICogLy8gVXNlIHRoZSB3cml0ZXIgdG8gaGFuZGxlIGNvbW1hbmQgb3V0cHV0XG4gKiB3cml0ZXIuZGF0YSgnRmlsZSBsaXN0IG91dHB1dC4uLicpO1xuICogd3JpdGVyLmV4aXQoMCwgWydDb21tYW5kIGV4ZWN1dGVkIHN1Y2Nlc3NmdWxseSddKTtcbiAqIGBgYFxuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IFN0YW5kYXJkT3V0cHV0V3JpdGVyXG4gKiAgIHBhcnRpY2lwYW50IExvZ2dlclxuICogICBwYXJ0aWNpcGFudCBQcm9taXNlRXhlY3V0b3JcbiAqXG4gKiAgIENsaWVudC0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiBuZXcgU3RhbmRhcmRPdXRwdXRXcml0ZXIoY21kLCBsb2NrKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PkxvZ2dlcjogTG9nZ2luZy5mb3IoY21kKVxuICpcbiAqICAgQ2xpZW50LT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IGRhdGEoY2h1bmspXG4gKiAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IGxvZyhcInN0ZG91dFwiLCBjaHVuaylcbiAqICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5Mb2dnZXI6IGxvZ2dlci5pbmZvKGxvZylcbiAqXG4gKiAgIENsaWVudC0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiBlcnJvcihjaHVuaylcbiAqICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogbG9nKFwic3RkZXJyXCIsIGNodW5rKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PkxvZ2dlcjogbG9nZ2VyLmluZm8obG9nKVxuICpcbiAqICAgQ2xpZW50LT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IGV4aXQoY29kZSwgbG9ncylcbiAqICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogbG9nKFwic3Rkb3V0XCIsIGV4aXRNZXNzYWdlKVxuICogICBhbHQgY29kZSA9PT0gMFxuICogICAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IHJlc29sdmUobG9ncylcbiAqICAgICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PlByb21pc2VFeGVjdXRvcjogbG9jay5yZXNvbHZlKHJlYXNvbilcbiAqICAgZWxzZSBjb2RlICE9PSAwXG4gKiAgICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogcmVqZWN0KGVycm9yKVxuICogICAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+UHJvbWlzZUV4ZWN1dG9yOiBsb2NrLnJlamVjdChyZWFzb24pXG4gKiAgIGVuZFxuICovXG5leHBvcnQgY2xhc3MgU3RhbmRhcmRPdXRwdXRXcml0ZXI8UiA9IHN0cmluZz4gaW1wbGVtZW50cyBPdXRwdXRXcml0ZXIge1xuICBwcm90ZWN0ZWQgbG9nZ2VyOiBMb2dnZXI7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIGNtZDogc3RyaW5nLFxuICAgIHByb3RlY3RlZCBsb2NrOiBQcm9taXNlRXhlY3V0b3I8Uj4sXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIC4uLmFyZ3M6IHVua25vd25bXVxuICApIHtcbiAgICB0aGlzLmxvZ2dlciA9IExvZ2dpbmcuZm9yKHRoaXMuY21kKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9ncyBvdXRwdXQgdG8gdGhlIGNvbnNvbGUuXG4gICAqIEBzdW1tYXJ5IEZvcm1hdHMgYW5kIGxvZ3MgdGhlIGdpdmVuIGRhdGEgd2l0aCBhIHRpbWVzdGFtcCBhbmQgdHlwZSBpbmRpY2F0b3IuXG4gICAqXG4gICAqIEBwYXJhbSB0eXBlIC0gVGhlIHR5cGUgb2Ygb3V0cHV0IChzdGRvdXQgb3Igc3RkZXJyKS5cbiAgICogQHBhcmFtIGRhdGEgLSBUaGUgZGF0YSB0byBiZSBsb2dnZWQuXG4gICAqL1xuICBwcm90ZWN0ZWQgbG9nKHR5cGU6IE91dHB1dFR5cGUsIGRhdGE6IHN0cmluZyB8IEJ1ZmZlcikge1xuICAgIGRhdGEgPSBCdWZmZXIuaXNCdWZmZXIoZGF0YSkgPyBkYXRhLnRvU3RyaW5nKEVuY29kaW5nKSA6IGRhdGE7XG4gICAgY29uc3QgbG9nID0gdHlwZSA9PT0gXCJzdGRlcnJcIiA/IHN0eWxlKGRhdGEpLnJlZC50ZXh0IDogZGF0YTtcbiAgICB0aGlzLmxvZ2dlci5pbmZvKGxvZyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgc3RhbmRhcmQgb3V0cHV0IGRhdGEuXG4gICAqIEBzdW1tYXJ5IExvZ3MgdGhlIGdpdmVuIGNodW5rIGFzIHN0YW5kYXJkIG91dHB1dC5cbiAgICpcbiAgICogQHBhcmFtIGNodW5rIC0gVGhlIGRhdGEgY2h1bmsgdG8gYmUgbG9nZ2VkLlxuICAgKi9cbiAgZGF0YShjaHVuazogYW55KSB7XG4gICAgdGhpcy5sb2coXCJzdGRvdXRcIiwgU3RyaW5nKGNodW5rKSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgZXJyb3Igb3V0cHV0IGRhdGEuXG4gICAqIEBzdW1tYXJ5IExvZ3MgdGhlIGdpdmVuIGNodW5rIGFzIGVycm9yIG91dHB1dC5cbiAgICpcbiAgICogQHBhcmFtIGNodW5rIC0gVGhlIGVycm9yIGRhdGEgY2h1bmsgdG8gYmUgbG9nZ2VkLlxuICAgKi9cbiAgZXJyb3IoY2h1bms6IGFueSkge1xuICAgIHRoaXMubG9nKFwic3RkZXJyXCIsIFN0cmluZyhjaHVuaykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIGVycm9yIG9iamVjdHMuXG4gICAqIEBzdW1tYXJ5IExvZ3MgdGhlIGVycm9yIG1lc3NhZ2UgZnJvbSB0aGUgZ2l2ZW4gRXJyb3Igb2JqZWN0LlxuICAgKlxuICAgKiBAcGFyYW0gZXJyIC0gVGhlIEVycm9yIG9iamVjdCB0byBiZSBsb2dnZWQuXG4gICAqL1xuICBlcnJvcnMoZXJyOiBFcnJvcikge1xuICAgIHRoaXMubG9nKFwic3RkZXJyXCIsIGBFcnJvciBleGVjdXRpbmcgY29tbWFuZCBleGl0ZWQgOiAke2Vycn1gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyB0aGUgZXhpdCBvZiBhIGNvbW1hbmQuXG4gICAqIEBzdW1tYXJ5IExvZ3MgdGhlIGV4aXQgY29kZSBhbmQgcmVzb2x2ZXMgb3IgcmVqZWN0cyB0aGUgcHJvbWlzZSBiYXNlZCBvbiB0aGUgY29kZS5cbiAgICpcbiAgICogQHBhcmFtIGNvZGUgLSBUaGUgZXhpdCBjb2RlIG9mIHRoZSBjb21tYW5kLlxuICAgKiBAcGFyYW0gbG9ncyAtIEFycmF5IG9mIGxvZyBtZXNzYWdlcyB0byBiZSBwcm9jZXNzZWQgYmVmb3JlIGV4aXRpbmcuXG4gICAqL1xuICBleGl0KGNvZGU6IG51bWJlciB8IHN0cmluZywgbG9nczogc3RyaW5nW10pIHtcbiAgICB0aGlzLmxvZyhcbiAgICAgIFwic3Rkb3V0XCIsXG4gICAgICBgY29tbWFuZCBleGl0ZWQgY29kZSA6ICR7Y29kZSA9PT0gMCA/IHN0eWxlKGNvZGUudG9TdHJpbmcoKSkuZ3JlZW4udGV4dCA6IHN0eWxlKGNvZGUgPT09IG51bGwgPyBcIm51bGxcIiA6IGNvZGUudG9TdHJpbmcoKSkucmVkLnRleHR9YFxuICAgICk7XG4gICAgaWYgKGNvZGUgPT09IDApIHtcbiAgICAgIHRoaXMucmVzb2x2ZShsb2dzLm1hcCgobCkgPT4gbC50cmltKCkpLmpvaW4oXCJcXG5cIikgYXMgUik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVqZWN0KG5ldyBFcnJvcihsb2dzLmxlbmd0aCA/IGxvZ3Muam9pbihcIlxcblwiKSA6IGNvZGUudG9TdHJpbmcoKSkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGFyc2VzIGEgY29tbWFuZCBzdHJpbmcgb3IgYXJyYXkgaW50byBjb21wb25lbnRzLlxuICAgKiBAc3VtbWFyeSBDb252ZXJ0cyB0aGUgY29tbWFuZCBpbnRvIGEgY29uc2lzdGVudCBmb3JtYXQgYW5kIHN0b3JlcyBpdCwgdGhlbiByZXR1cm5zIGl0IHNwbGl0IGludG8gY29tbWFuZCBhbmQgYXJndW1lbnRzLlxuICAgKlxuICAgKiBAcGFyYW0gY29tbWFuZCAtIFRoZSBjb21tYW5kIGFzIGEgc3RyaW5nIG9yIGFycmF5IG9mIHN0cmluZ3MuXG4gICAqIEByZXR1cm4gQSB0dXBsZSBjb250YWluaW5nIHRoZSBjb21tYW5kIGFuZCBpdHMgYXJndW1lbnRzIGFzIHNlcGFyYXRlIGVsZW1lbnRzLlxuICAgKi9cbiAgcGFyc2VDb21tYW5kKGNvbW1hbmQ6IHN0cmluZyB8IHN0cmluZ1tdKTogW3N0cmluZywgc3RyaW5nW11dIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShjb21tYW5kKSkge1xuICAgICAgdGhpcy5jbWQgPSBjb21tYW5kLmpvaW4oXCIgXCIpO1xuICAgICAgcmV0dXJuIFtjb21tYW5kWzBdLCBjb21tYW5kLnNsaWNlKDEpXTtcbiAgICB9XG5cbiAgICBjb25zdCBwYXJ0cyA9IHBhcnNlKGNvbW1hbmQpXG4gICAgICAuZmlsdGVyKChwKSA9PiB0eXBlb2YgcCA9PT0gXCJzdHJpbmdcIilcbiAgICAgIC5tYXAoU3RyaW5nKTtcblxuICAgIHRoaXMuY21kID0gcGFydHMuam9pbihcIiBcIik7XG4gICAgcmV0dXJuIFtwYXJ0c1swXSwgcGFydHMuc2xpY2UoMSldO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXNvbHZlcyB0aGUgcHJvbWlzZSB3aXRoIGEgc3VjY2VzcyBtZXNzYWdlLlxuICAgKiBAc3VtbWFyeSBMb2dzIGEgc3VjY2VzcyBtZXNzYWdlIGFuZCByZXNvbHZlcyB0aGUgcHJvbWlzZSB3aXRoIHRoZSBnaXZlbiByZWFzb24uXG4gICAqXG4gICAqIEBwYXJhbSByZWFzb24gLSBUaGUgcmVhc29uIGZvciByZXNvbHZpbmcgdGhlIHByb21pc2UuXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVzb2x2ZShyZWFzb246IFIpIHtcbiAgICB0aGlzLmxvZyhcbiAgICAgIFwic3Rkb3V0XCIsXG4gICAgICBgJHt0aGlzLmNtZH0gZXhlY3V0ZWQgc3VjY2Vzc2Z1bGx5OiAke3N0eWxlKHJlYXNvbiA/IFwicmFuIHRvIGNvbXBsZXRpb25cIiA6IChyZWFzb24gYXMgc3RyaW5nKSkuZ3JlZW59YFxuICAgICk7XG4gICAgdGhpcy5sb2NrLnJlc29sdmUocmVhc29uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVqZWN0cyB0aGUgcHJvbWlzZSB3aXRoIGFuIGVycm9yIG1lc3NhZ2UuXG4gICAqIEBzdW1tYXJ5IExvZ3MgYW4gZXJyb3IgbWVzc2FnZSBhbmQgcmVqZWN0cyB0aGUgcHJvbWlzZSB3aXRoIHRoZSBnaXZlbiByZWFzb24uXG4gICAqXG4gICAqIEBwYXJhbSByZWFzb24gLSBUaGUgcmVhc29uIGZvciByZWplY3RpbmcgdGhlIHByb21pc2UsIGVpdGhlciBhIG51bWJlciAoZXhpdCBjb2RlKSBvciBhIHN0cmluZy5cbiAgICovXG4gIHByb3RlY3RlZCByZWplY3QocmVhc29uOiBudW1iZXIgfCBzdHJpbmcgfCBFcnJvcikge1xuICAgIGlmICghKHJlYXNvbiBpbnN0YW5jZW9mIEVycm9yKSkge1xuICAgICAgcmVhc29uID0gbmV3IEVycm9yKFxuICAgICAgICB0eXBlb2YgcmVhc29uID09PSBcIm51bWJlclwiID8gYEV4aXQgY29kZSAke3JlYXNvbn1gIDogcmVhc29uXG4gICAgICApO1xuICAgIH1cbiAgICB0aGlzLmxvZyhcbiAgICAgIFwic3RkZXJyXCIsXG4gICAgICBgJHt0aGlzLmNtZH0gZmFpbGVkIHRvIGV4ZWN1dGU6ICR7c3R5bGUocmVhc29uLm1lc3NhZ2UpLnJlZH1gXG4gICAgKTtcbiAgICB0aGlzLmxvY2sucmVqZWN0KHJlYXNvbik7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIENoaWxkUHJvY2Vzc1dpdGhvdXROdWxsU3RyZWFtcyxcbiAgc3Bhd24sXG4gIFNwYXduT3B0aW9uc1dpdGhvdXRTdGRpbyxcbn0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IFN0YW5kYXJkT3V0cHV0V3JpdGVyIH0gZnJvbSBcIi4uL3dyaXRlcnMvU3RhbmRhcmRPdXRwdXRXcml0ZXJcIjtcbmltcG9ydCB7IENvbW1hbmRSZXN1bHQgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgT3V0cHV0V3JpdGVyQ29uc3RydWN0b3IgfSBmcm9tIFwiLi4vd3JpdGVycy90eXBlc1wiO1xuaW1wb3J0IHsgQWJvcnRDb2RlIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBMb2dnZXIsIExvZ2dpbmcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIGxvY2tlZCB2ZXJzaW9uIG9mIGEgZnVuY3Rpb24uXG4gKiBAc3VtbWFyeSBUaGlzIGhpZ2hlci1vcmRlciBmdW5jdGlvbiB0YWtlcyBhIGZ1bmN0aW9uIGFuZCByZXR1cm5zIGEgbmV3IGZ1bmN0aW9uIHRoYXQgZW5zdXJlc1xuICogc2VxdWVudGlhbCBleGVjdXRpb24gb2YgdGhlIG9yaWdpbmFsIGZ1bmN0aW9uLCBldmVuIHdoZW4gY2FsbGVkIG11bHRpcGxlIHRpbWVzIGNvbmN1cnJlbnRseS5cbiAqIEl0IHVzZXMgYSBQcm9taXNlLWJhc2VkIGxvY2tpbmcgbWVjaGFuaXNtIHRvIHF1ZXVlIGZ1bmN0aW9uIGNhbGxzLlxuICpcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJldHVybiB0eXBlIG9mIHRoZSBpbnB1dCBmdW5jdGlvbi5cbiAqXG4gKiBAcGFyYW0gZiAtIFRoZSBmdW5jdGlvbiB0byBiZSBsb2NrZWQuIEl0IGNhbiB0YWtlIGFueSBudW1iZXIgb2YgcGFyYW1ldGVycyBhbmQgcmV0dXJuIGEgdmFsdWUgb2YgdHlwZSBSLlxuICogQHJldHVybiBBIG5ldyBmdW5jdGlvbiB3aXRoIHRoZSBzYW1lIHNpZ25hdHVyZSBhcyB0aGUgaW5wdXQgZnVuY3Rpb24sIGJ1dCB3aXRoIHNlcXVlbnRpYWwgZXhlY3V0aW9uIGd1YXJhbnRlZWQuXG4gKlxuICogQGZ1bmN0aW9uIGxvY2tpZnlcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBMb2NrZWRGdW5jdGlvblxuICogICBwYXJ0aWNpcGFudCBPcmlnaW5hbEZ1bmN0aW9uXG4gKiAgIENhbGxlci0+PkxvY2tlZEZ1bmN0aW9uOiBDYWxsIHdpdGggcGFyYW1zXG4gKiAgIExvY2tlZEZ1bmN0aW9uLT4+TG9ja2VkRnVuY3Rpb246IENoZWNrIGN1cnJlbnQgbG9ja1xuICogICBhbHQgTG9jayBpcyByZXNvbHZlZFxuICogICAgIExvY2tlZEZ1bmN0aW9uLT4+T3JpZ2luYWxGdW5jdGlvbjogRXhlY3V0ZSB3aXRoIHBhcmFtc1xuICogICAgIE9yaWdpbmFsRnVuY3Rpb24tLT4+TG9ja2VkRnVuY3Rpb246IFJldHVybiByZXN1bHRcbiAqICAgICBMb2NrZWRGdW5jdGlvbi0tPj5DYWxsZXI6IFJldHVybiByZXN1bHRcbiAqICAgZWxzZSBMb2NrIGlzIHBlbmRpbmdcbiAqICAgICBMb2NrZWRGdW5jdGlvbi0+PkxvY2tlZEZ1bmN0aW9uOiBRdWV1ZSBleGVjdXRpb25cbiAqICAgICBMb2NrZWRGdW5jdGlvbi0tPj5DYWxsZXI6IFJldHVybiBwcm9taXNlXG4gKiAgICAgTm90ZSBvdmVyIExvY2tlZEZ1bmN0aW9uOiBXYWl0IGZvciBwcmV2aW91cyBleGVjdXRpb25cbiAqICAgICBMb2NrZWRGdW5jdGlvbi0+Pk9yaWdpbmFsRnVuY3Rpb246IEV4ZWN1dGUgd2l0aCBwYXJhbXNcbiAqICAgICBPcmlnaW5hbEZ1bmN0aW9uLS0+PkxvY2tlZEZ1bmN0aW9uOiBSZXR1cm4gcmVzdWx0XG4gKiAgICAgTG9ja2VkRnVuY3Rpb24tLT4+Q2FsbGVyOiBSZXNvbHZlIHByb21pc2Ugd2l0aCByZXN1bHRcbiAqICAgZW5kXG4gKiAgIExvY2tlZEZ1bmN0aW9uLT4+TG9ja2VkRnVuY3Rpb246IFVwZGF0ZSBsb2NrXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gbG9ja2lmeTxSPihmOiAoLi4ucGFyYW1zOiB1bmtub3duW10pID0+IFIpIHtcbiAgbGV0IGxvY2s6IFByb21pc2U8UiB8IHZvaWQ+ID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIHJldHVybiAoLi4ucGFyYW1zOiB1bmtub3duW10pID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBsb2NrLnRoZW4oKCkgPT4gZiguLi5wYXJhbXMpKTtcbiAgICBsb2NrID0gcmVzdWx0LmNhdGNoKCgpID0+IHt9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDaGFpbnMgbXVsdGlwbGUgYWJvcnQgc2lnbmFscyB0byBhIGNvbnRyb2xsZXIuXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgbWVjaGFuaXNtIHdoZXJlIG11bHRpcGxlIGFib3J0IHNpZ25hbHMgY2FuIHRyaWdnZXIgYSBzaW5nbGUgYWJvcnQgY29udHJvbGxlci5cbiAqIFRoaXMgaXMgdXNlZnVsIGZvciBjb29yZGluYXRpbmcgY2FuY2VsbGF0aW9uIGFjcm9zcyBtdWx0aXBsZSBhc3luY2hyb25vdXMgb3BlcmF0aW9ucy5cbiAqXG4gKiBAcGFyYW0ge0Fib3J0Q29udHJvbGxlcn0gY29udHJvbGxlciAtIFRoZSBhYm9ydCBjb250cm9sbGVyIHRvIGJlIHRyaWdnZXJlZCBieSBzaWduYWxzLlxuICogQHBhcmFtIHsuLi5BYm9ydFNpZ25hbH0gc2lnbmFscyAtIE9uZSBvciBtb3JlIGFib3J0IHNpZ25hbHMgdGhhdCBjYW4gdHJpZ2dlciB0aGUgY29udHJvbGxlci5cbiAqIEByZXR1cm4ge0Fib3J0Q29udHJvbGxlcn0gVGhlIGlucHV0IGNvbnRyb2xsZXIsIG5vdyBjb25uZWN0ZWQgdG8gdGhlIHNpZ25hbHMuXG4gKlxuICogQGZ1bmN0aW9uIGNoYWluQWJvcnRDb250cm9sbGVyXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY2hhaW5BYm9ydENvbnRyb2xsZXIoXG4gIGNvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcixcbiAgLi4uc2lnbmFsczogQWJvcnRTaWduYWxbXVxuKTogQWJvcnRDb250cm9sbGVyO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IGNvbnRyb2xsZXIgY2hhaW5lZCB0byBtdWx0aXBsZSBhYm9ydCBzaWduYWxzLlxuICogQHN1bW1hcnkgQ3JlYXRlcyBhIG5ldyBhYm9ydCBjb250cm9sbGVyIHRoYXQgd2lsbCBiZSB0cmlnZ2VyZWQgaWYgYW55IG9mIHRoZSBwcm92aWRlZCBzaWduYWxzIGFyZSBhYm9ydGVkLlxuICpcbiAqIEBwYXJhbSB7Li4uQWJvcnRTaWduYWx9IHNpZ25hbHMgLSBPbmUgb3IgbW9yZSBhYm9ydCBzaWduYWxzIHRoYXQgY2FuIHRyaWdnZXIgdGhlIG5ldyBjb250cm9sbGVyLlxuICogQHJldHVybiB7QWJvcnRDb250cm9sbGVyfSBBIG5ldyBhYm9ydCBjb250cm9sbGVyIGNvbm5lY3RlZCB0byB0aGUgc2lnbmFscy5cbiAqXG4gKiBAZnVuY3Rpb24gY2hhaW5BYm9ydENvbnRyb2xsZXJcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGFpbkFib3J0Q29udHJvbGxlcihcbiAgLi4uc2lnbmFsczogQWJvcnRTaWduYWxbXVxuKTogQWJvcnRDb250cm9sbGVyO1xuXG5leHBvcnQgZnVuY3Rpb24gY2hhaW5BYm9ydENvbnRyb2xsZXIoXG4gIGFyZ3VtZW50MDogQWJvcnRDb250cm9sbGVyIHwgQWJvcnRTaWduYWwsXG4gIC4uLnJlbWFpbmRlcjogQWJvcnRTaWduYWxbXVxuKTogQWJvcnRDb250cm9sbGVyIHtcbiAgbGV0IHNpZ25hbHM6IEFib3J0U2lnbmFsW107XG4gIGxldCBjb250cm9sbGVyOiBBYm9ydENvbnRyb2xsZXI7XG5cbiAgLy8gbm9ybWFsaXplIGFyZ3NcbiAgaWYgKGFyZ3VtZW50MCBpbnN0YW5jZW9mIEFib3J0U2lnbmFsKSB7XG4gICAgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICBzaWduYWxzID0gW2FyZ3VtZW50MCwgLi4ucmVtYWluZGVyXTtcbiAgfSBlbHNlIHtcbiAgICBjb250cm9sbGVyID0gYXJndW1lbnQwO1xuICAgIHNpZ25hbHMgPSByZW1haW5kZXI7XG4gIH1cblxuICAvLyBpZiB0aGUgY29udHJvbGxlciBpcyBhbHJlYWR5IGFib3J0ZWQsIGV4aXQgZWFybHlcbiAgaWYgKGNvbnRyb2xsZXIuc2lnbmFsLmFib3J0ZWQpIHtcbiAgICByZXR1cm4gY29udHJvbGxlcjtcbiAgfVxuXG4gIGNvbnN0IGhhbmRsZXIgPSAoKSA9PiBjb250cm9sbGVyLmFib3J0KCk7XG5cbiAgZm9yIChjb25zdCBzaWduYWwgb2Ygc2lnbmFscykge1xuICAgIC8vIGNoZWNrIGJlZm9yZSBhZGRpbmchIChhbmQgYXNzdW1lIHRoZXJlIGlzIG5vIHBvc3NpYmxlIHdheSB0aGF0IHRoZSBzaWduYWwgY291bGRcbiAgICAvLyBhYm9ydCBiZXR3ZWVuIHRoZSBgaWZgIGNoZWNrIGFuZCBhZGRpbmcgdGhlIGV2ZW50IGxpc3RlbmVyKVxuICAgIGlmIChzaWduYWwuYWJvcnRlZCkge1xuICAgICAgY29udHJvbGxlci5hYm9ydCgpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgaGFuZGxlciwge1xuICAgICAgb25jZTogdHJ1ZSxcbiAgICAgIHNpZ25hbDogY29udHJvbGxlci5zaWduYWwsXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gY29udHJvbGxlcjtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3Bhd25zIGEgY29tbWFuZCBhcyBhIGNoaWxkIHByb2Nlc3Mgd2l0aCBvdXRwdXQgaGFuZGxpbmcuXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgY2hpbGQgcHJvY2VzcyB0byBleGVjdXRlIGEgY29tbWFuZCB3aXRoIHN1cHBvcnQgZm9yIHBpcGluZyBtdWx0aXBsZSBjb21tYW5kcyxcbiAqIGN1c3RvbSBvdXRwdXQgaGFuZGxpbmcsIGFuZCBhYm9ydCBjb250cm9sLiBUaGlzIGZ1bmN0aW9uIGhhbmRsZXMgdGhlIGxvdy1sZXZlbCBkZXRhaWxzIG9mXG4gKiBzcGF3bmluZyBwcm9jZXNzZXMgYW5kIGNvbm5lY3RpbmcgdGhlaXIgaW5wdXRzL291dHB1dHMgd2hlbiBwaXBpbmcgaXMgdXNlZC5cbiAqXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSBwcm9jZXNzZWQgb3V0cHV0LCBkZWZhdWx0aW5nIHRvIHN0cmluZy5cbiAqIEBwYXJhbSB7U3RhbmRhcmRPdXRwdXRXcml0ZXI8Uj59IG91dHB1dCAtIFRoZSBvdXRwdXQgd3JpdGVyIHRvIGhhbmRsZSBjb21tYW5kIG91dHB1dC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjb21tYW5kIC0gVGhlIGNvbW1hbmQgdG8gZXhlY3V0ZSwgY2FuIGluY2x1ZGUgcGlwZSBvcGVyYXRvcnMuXG4gKiBAcGFyYW0ge1NwYXduT3B0aW9uc1dpdGhvdXRTdGRpb30gb3B0cyAtIE9wdGlvbnMgZm9yIHRoZSBzcGF3bmVkIHByb2Nlc3MuXG4gKiBAcGFyYW0ge0Fib3J0Q29udHJvbGxlcn0gYWJvcnQgLSBDb250cm9sbGVyIHRvIGFib3J0IHRoZSBjb21tYW5kIGV4ZWN1dGlvbi5cbiAqIEBwYXJhbSB7TG9nZ2VyfSBsb2dnZXIgLSBMb2dnZXIgZm9yIHJlY29yZGluZyBjb21tYW5kIGV4ZWN1dGlvbiBkZXRhaWxzLlxuICogQHJldHVybiB7Q2hpbGRQcm9jZXNzV2l0aG91dE51bGxTdHJlYW1zfSBUaGUgc3Bhd25lZCBjaGlsZCBwcm9jZXNzLlxuICpcbiAqIEBmdW5jdGlvbiBzcGF3bkNvbW1hbmRcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzcGF3bkNvbW1hbmQ8UiA9IHN0cmluZz4oXG4gIG91dHB1dDogU3RhbmRhcmRPdXRwdXRXcml0ZXI8Uj4sXG4gIGNvbW1hbmQ6IHN0cmluZyxcbiAgb3B0czogU3Bhd25PcHRpb25zV2l0aG91dFN0ZGlvLFxuICBhYm9ydDogQWJvcnRDb250cm9sbGVyLFxuICBsb2dnZXI6IExvZ2dlclxuKTogQ2hpbGRQcm9jZXNzV2l0aG91dE51bGxTdHJlYW1zIHtcbiAgZnVuY3Rpb24gc3Bhd25Jbm5lcihjb21tYW5kOiBzdHJpbmcsIGNvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcikge1xuICAgIGNvbnN0IFtjbWQsIGFyZ3pdID0gb3V0cHV0LnBhcnNlQ29tbWFuZChjb21tYW5kKTtcbiAgICBsb2dnZXIuaW5mbyhgUnVubmluZyBjb21tYW5kOiAke2NtZH1gKTtcbiAgICBsb2dnZXIuZGVidWcoYHdpdGggYXJnczogJHthcmd6LmpvaW4oXCIgXCIpfWApO1xuICAgIGNvbnN0IGNoaWxkUHJvY2VzcyA9IHNwYXduKGNtZCwgYXJneiwge1xuICAgICAgLi4ub3B0cyxcbiAgICAgIGN3ZDogb3B0cy5jd2QgfHwgcHJvY2Vzcy5jd2QoKSxcbiAgICAgIGVudjogT2JqZWN0LmFzc2lnbih7fSwgcHJvY2Vzcy5lbnYsIG9wdHMuZW52LCB7IFBBVEg6IHByb2Nlc3MuZW52LlBBVEggfSksXG4gICAgICBzaGVsbDogb3B0cy5zaGVsbCB8fCBmYWxzZSxcbiAgICAgIHNpZ25hbDogY29udHJvbGxlci5zaWduYWwsXG4gICAgfSk7XG4gICAgbG9nZ2VyLnZlcmJvc2UoYHBpZCA6ICR7Y2hpbGRQcm9jZXNzLnBpZH1gKTtcbiAgICByZXR1cm4gY2hpbGRQcm9jZXNzO1xuICB9XG5cbiAgY29uc3QgbSA9IGNvbW1hbmQubWF0Y2goL1s8PiQjXS9nKTtcbiAgaWYgKG0pXG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYEludmFsaWQgY29tbWFuZDogJHtjb21tYW5kfS4gY29udGFpbnMgaW52YWxpZCBjaGFyYWN0ZXJzOiAke219YFxuICAgICk7XG4gIGlmIChjb21tYW5kLmluY2x1ZGVzKFwiIHwgXCIpKSB7XG4gICAgY29uc3QgY21kcyA9IGNvbW1hbmQuc3BsaXQoXCIgfCBcIik7XG4gICAgY29uc3Qgc3Bhd25zID0gW107XG4gICAgY29uc3QgY29udHJvbGxlcnMgPSBuZXcgQXJyYXkoY21kcy5sZW5ndGgpO1xuICAgIGNvbnRyb2xsZXJzWzBdID0gYWJvcnQ7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjbWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoaSAhPT0gMClcbiAgICAgICAgY29udHJvbGxlcnNbaV0gPSBjaGFpbkFib3J0Q29udHJvbGxlcihjb250cm9sbGVyc1tpIC0gMV0uc2lnbmFsKTtcbiAgICAgIHNwYXducy5wdXNoKHNwYXduSW5uZXIoY21kc1tpXSwgY29udHJvbGxlcnNbaV0pKTtcbiAgICAgIGlmIChpID09PSAwKSBjb250aW51ZTtcbiAgICAgIHNwYXduc1tpIC0gMV0uc3Rkb3V0LnBpcGUoc3Bhd25zW2ldLnN0ZGluKTtcbiAgICB9XG4gICAgcmV0dXJuIHNwYXduc1tjbWRzLmxlbmd0aCAtIDFdO1xuICB9XG5cbiAgcmV0dXJuIHNwYXduSW5uZXIoY29tbWFuZCwgYWJvcnQpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFeGVjdXRlcyBhIGNvbW1hbmQgYXN5bmNocm9ub3VzbHkgd2l0aCBjdXN0b21pemFibGUgb3V0cHV0IGhhbmRsaW5nLlxuICogQHN1bW1hcnkgVGhpcyBmdW5jdGlvbiBydW5zIGEgc2hlbGwgY29tbWFuZCBhcyBhIGNoaWxkIHByb2Nlc3MsIHByb3ZpZGluZyBmaW5lLWdyYWluZWRcbiAqIGNvbnRyb2wgb3ZlciBpdHMgZXhlY3V0aW9uIGFuZCBvdXRwdXQgaGFuZGxpbmcuIEl0IHN1cHBvcnRzIGN1c3RvbSBvdXRwdXQgd3JpdGVycyxcbiAqIGFsbG93cyBmb3IgY29tbWFuZCBhYm9ydGlvbiwgYW5kIGNhcHR1cmVzIGJvdGggc3Rkb3V0IGFuZCBzdGRlcnIuXG4gKlxuICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgcmVzb2x2ZWQgdmFsdWUgZnJvbSB0aGUgY29tbWFuZCBleGVjdXRpb24uXG4gKlxuICogQHBhcmFtIGNvbW1hbmQgLSBUaGUgY29tbWFuZCB0byBydW4sIGVpdGhlciBhcyBhIHN0cmluZyBvciBhbiBhcnJheSBvZiBzdHJpbmdzLlxuICogQHBhcmFtIG9wdHMgLSBTcGF3biBvcHRpb25zIGZvciB0aGUgY2hpbGQgcHJvY2Vzcy4gRGVmYXVsdHMgdG8gYW4gZW1wdHkgb2JqZWN0LlxuICogQHBhcmFtIG91dHB1dENvbnN0cnVjdG9yIC0gQ29uc3RydWN0b3IgZm9yIHRoZSBvdXRwdXQgd3JpdGVyLiBEZWZhdWx0cyB0byBTdGFuZGFyZE91dHB1dFdyaXRlci5cbiAqIEBwYXJhbSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgb3V0cHV0IGNvbnN0cnVjdG9yLlxuICogQHJldHVybiB7Q29tbWFuZFJlc3VsdH0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGNvbW1hbmQgcmVzdWx0IG9mIHR5cGUgUi5cbiAqXG4gKiBAZnVuY3Rpb24gcnVuQ29tbWFuZFxuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IHJ1bkNvbW1hbmRcbiAqICAgcGFydGljaXBhbnQgT3V0cHV0V3JpdGVyXG4gKiAgIHBhcnRpY2lwYW50IENoaWxkUHJvY2Vzc1xuICogICBDYWxsZXItPj5ydW5Db21tYW5kOiBDYWxsIHdpdGggY29tbWFuZCBhbmQgb3B0aW9uc1xuICogICBydW5Db21tYW5kLT4+T3V0cHV0V3JpdGVyOiBDcmVhdGUgbmV3IGluc3RhbmNlXG4gKiAgIHJ1bkNvbW1hbmQtPj5PdXRwdXRXcml0ZXI6IFBhcnNlIGNvbW1hbmRcbiAqICAgcnVuQ29tbWFuZC0+PkNoaWxkUHJvY2VzczogU3Bhd24gcHJvY2Vzc1xuICogICBDaGlsZFByb2Nlc3MtLT4+cnVuQ29tbWFuZDogUmV0dXJuIHByb2Nlc3Mgb2JqZWN0XG4gKiAgIHJ1bkNvbW1hbmQtPj5DaGlsZFByb2Nlc3M6IFNldCB1cCBldmVudCBsaXN0ZW5lcnNcbiAqICAgbG9vcCBGb3IgZWFjaCBzdGRvdXQgZGF0YVxuICogICAgIENoaWxkUHJvY2Vzcy0+PnJ1bkNvbW1hbmQ6IEVtaXQgc3Rkb3V0IGRhdGFcbiAqICAgICBydW5Db21tYW5kLT4+T3V0cHV0V3JpdGVyOiBIYW5kbGUgc3Rkb3V0IGRhdGFcbiAqICAgZW5kXG4gKiAgIGxvb3AgRm9yIGVhY2ggc3RkZXJyIGRhdGFcbiAqICAgICBDaGlsZFByb2Nlc3MtPj5ydW5Db21tYW5kOiBFbWl0IHN0ZGVyciBkYXRhXG4gKiAgICAgcnVuQ29tbWFuZC0+Pk91dHB1dFdyaXRlcjogSGFuZGxlIHN0ZGVyciBkYXRhXG4gKiAgIGVuZFxuICogICBDaGlsZFByb2Nlc3MtPj5ydW5Db21tYW5kOiBFbWl0IGVycm9yIChpZiBhbnkpXG4gKiAgIHJ1bkNvbW1hbmQtPj5PdXRwdXRXcml0ZXI6IEhhbmRsZSBlcnJvclxuICogICBDaGlsZFByb2Nlc3MtPj5ydW5Db21tYW5kOiBFbWl0IGV4aXRcbiAqICAgcnVuQ29tbWFuZC0+Pk91dHB1dFdyaXRlcjogSGFuZGxlIGV4aXRcbiAqICAgT3V0cHV0V3JpdGVyLS0+PnJ1bkNvbW1hbmQ6IFJlc29sdmUgb3IgcmVqZWN0IHByb21pc2VcbiAqICAgcnVuQ29tbWFuZC0tPj5DYWxsZXI6IFJldHVybiBDb21tYW5kUmVzdWx0XG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuQ29tbWFuZDxSID0gc3RyaW5nPihcbiAgY29tbWFuZDogc3RyaW5nLFxuICBvcHRzOiBTcGF3bk9wdGlvbnNXaXRob3V0U3RkaW8gPSB7fSxcbiAgb3V0cHV0Q29uc3RydWN0b3I6IE91dHB1dFdyaXRlckNvbnN0cnVjdG9yPFxuICAgIFIsXG4gICAgU3RhbmRhcmRPdXRwdXRXcml0ZXI8Uj4sXG4gICAgRXJyb3JcbiAgPiA9IFN0YW5kYXJkT3V0cHV0V3JpdGVyPFI+LFxuICAuLi5hcmdzOiB1bmtub3duW11cbik6IENvbW1hbmRSZXN1bHQ8Uj4ge1xuICBjb25zdCBsb2dnZXIgPSBMb2dnaW5nLmZvcihydW5Db21tYW5kKTtcbiAgY29uc3QgYWJvcnQgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgY29uc3QgcmVzdWx0OiBPbWl0PENvbW1hbmRSZXN1bHQsIFwicHJvbWlzZVwiIHwgXCJwaXBlXCI+ID0ge1xuICAgIGFib3J0OiBhYm9ydCxcbiAgICBjb21tYW5kOiBjb21tYW5kLFxuICAgIGxvZ3M6IFtdLFxuICAgIGVycnM6IFtdLFxuICB9O1xuXG4gIGNvbnN0IGxvY2sgPSBuZXcgUHJvbWlzZTxSPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgbGV0IG91dHB1dDtcbiAgICB0cnkge1xuICAgICAgb3V0cHV0ID0gbmV3IG91dHB1dENvbnN0cnVjdG9yKFxuICAgICAgICBjb21tYW5kLFxuICAgICAgICB7XG4gICAgICAgICAgcmVzb2x2ZSxcbiAgICAgICAgICByZWplY3QsXG4gICAgICAgIH0sXG4gICAgICAgIC4uLmFyZ3NcbiAgICAgICk7XG5cbiAgICAgIHJlc3VsdC5jbWQgPSBzcGF3bkNvbW1hbmQ8Uj4ob3V0cHV0LCBjb21tYW5kLCBvcHRzLCBhYm9ydCwgbG9nZ2VyKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihgRXJyb3IgcnVubmluZyBjb21tYW5kICR7Y29tbWFuZH06ICR7ZX1gKSk7XG4gICAgfVxuXG4gICAgcmVzdWx0LmNtZC5zdGRvdXQuc2V0RW5jb2RpbmcoXCJ1dGY4XCIpO1xuXG4gICAgcmVzdWx0LmNtZC5zdGRvdXQub24oXCJkYXRhXCIsIChjaHVuazogYW55KSA9PiB7XG4gICAgICBjaHVuayA9IGNodW5rLnRvU3RyaW5nKCk7XG4gICAgICByZXN1bHQubG9ncy5wdXNoKGNodW5rKTtcbiAgICAgIG91dHB1dC5kYXRhKGNodW5rKTtcbiAgICB9KTtcblxuICAgIHJlc3VsdC5jbWQuc3RkZXJyLm9uKFwiZGF0YVwiLCAoZGF0YTogYW55KSA9PiB7XG4gICAgICBkYXRhID0gZGF0YS50b1N0cmluZygpO1xuICAgICAgcmVzdWx0LmVycnMucHVzaChkYXRhKTtcbiAgICAgIG91dHB1dC5lcnJvcihkYXRhKTtcbiAgICB9KTtcblxuICAgIHJlc3VsdC5jbWQub25jZShcImVycm9yXCIsIChlcnI6IEVycm9yKSA9PiB7XG4gICAgICBvdXRwdXQuZXhpdChlcnIubWVzc2FnZSwgcmVzdWx0LmVycnMpO1xuICAgIH0pO1xuXG4gICAgcmVzdWx0LmNtZC5vbmNlKFwiZXhpdFwiLCAoY29kZTogbnVtYmVyID0gMCkgPT4ge1xuICAgICAgaWYgKGFib3J0LnNpZ25hbC5hYm9ydGVkICYmIGNvZGUgPT09IG51bGwpIGNvZGUgPSBBYm9ydENvZGUgYXMgYW55O1xuICAgICAgb3V0cHV0LmV4aXQoY29kZSwgY29kZSA9PT0gMCA/IHJlc3VsdC5sb2dzIDogcmVzdWx0LmVycnMpO1xuICAgIH0pO1xuICB9KTtcblxuICBPYmplY3QuYXNzaWduKHJlc3VsdCwge1xuICAgIHByb21pc2U6IGxvY2ssXG4gICAgcGlwZTogYXN5bmMgPEU+KGNiOiAocjogUikgPT4gRSkgPT4ge1xuICAgICAgY29uc3QgbCA9IGxvZ2dlci5mb3IoXCJwaXBlXCIpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgbC52ZXJib3NlKGBFeGVjdXRpbmcgcGlwZSBmdW5jdGlvbiAke2NvbW1hbmR9Li4uYCk7XG4gICAgICAgIGNvbnN0IHJlc3VsdDogUiA9IGF3YWl0IGxvY2s7XG4gICAgICAgIGwudmVyYm9zZShgUGlwaW5nIG91dHB1dCB0byAke2NiLm5hbWV9OiAke3Jlc3VsdH1gKTtcbiAgICAgICAgcmV0dXJuIGNiKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgIGwuZXJyb3IoYEVycm9yIHBpcGluZyBjb21tYW5kIG91dHB1dDogJHtlfWApO1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH0sXG4gIH0pO1xuXG4gIHJldHVybiByZXN1bHQgYXMgQ29tbWFuZFJlc3VsdDxSPjtcbn1cbiIsImltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBjcmVhdGVSZXF1aXJlIH0gZnJvbSBcIm1vZHVsZVwiO1xuaW1wb3J0IHsgcnVuQ29tbWFuZCB9IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgeyBEZXBlbmRlbmN5TWFwLCBTaW1wbGVEZXBlbmRlbmN5TWFwIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IGVzY2FwZVJlZ0V4cCwgTG9nZ2luZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuaW1wb3J0IHpsaWIgZnJvbSBcInpsaWJcIjtcblxuY29uc3QgbG9nZ2VyID0gTG9nZ2luZy5mb3IoXCJmc1wiKTtcbmNvbnN0IGxvY2FsUmVxdWlyZSA9IGNyZWF0ZVJlcXVpcmUoYCR7cHJvY2Vzcy5jd2QoKX0vcGFja2FnZS5qc29uYCk7XG5mdW5jdGlvbiBpc1Rlc3RFbnZpcm9ubWVudCgpIHtcbiAgcmV0dXJuIChcbiAgICBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gXCJ0ZXN0XCIgfHxcbiAgICB0eXBlb2YgcHJvY2Vzcy5lbnYuSkVTVF9XT1JLRVJfSUQgIT09IFwidW5kZWZpbmVkXCJcbiAgKTtcbn1cblxuZnVuY3Rpb24gcGF0Y2hTdHJpbmcoXG4gIGlucHV0OiBzdHJpbmcsXG4gIHZhbHVlczogUmVjb3JkPHN0cmluZywgbnVtYmVyIHwgc3RyaW5nPixcbiAgZmxhZ3M6IHN0cmluZyA9IFwiZ1wiLFxuICBmaWx0ZXI/OiAoc3RyOiBzdHJpbmcpID0+IGJvb2xlYW5cbik6IHN0cmluZyB7XG4gIE9iamVjdC5lbnRyaWVzKHZhbHVlcykuZm9yRWFjaCgoW2tleSwgdmFsXSkgPT4ge1xuICAgIGNvbnN0IHJlZ2V4cCA9IG5ldyBSZWdFeHAoZXNjYXBlUmVnRXhwKGtleSksIGZsYWdzKTtcbiAgICBpbnB1dCA9IGlucHV0LnJlcGxhY2UocmVnZXhwLCAoc3ViU3RyOiBzdHJpbmcpID0+IHtcbiAgICAgIGlmICghZmlsdGVyIHx8IGZpbHRlcihzdWJTdHIpKSB7XG4gICAgICAgIHJldHVybiB2YWwgYXMgc3RyaW5nO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbCBhcyBzdHJpbmc7XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gaW5wdXQ7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFBhdGNoZXMgYSBmaWxlIHdpdGggZ2l2ZW4gdmFsdWVzLlxuICogQHN1bW1hcnkgUmVhZHMgYSBmaWxlLCBhcHBsaWVzIHBhdGNoZXMgdXNpbmcgVGV4dFV0aWxzLCBhbmQgd3JpdGVzIHRoZSByZXN1bHQgYmFjayB0byB0aGUgZmlsZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIFRoZSBwYXRoIHRvIHRoZSBmaWxlIHRvIGJlIHBhdGNoZWQuXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIG51bWJlciB8IHN0cmluZz59IHZhbHVlcyAtIFRoZSB2YWx1ZXMgdG8gcGF0Y2ggaW50byB0aGUgZmlsZS5cbiAqIEByZXR1cm4ge3ZvaWR9XG4gKlxuICogQGZ1bmN0aW9uIHBhdGNoRmlsZVxuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IHBhdGNoRmlsZVxuICogICBwYXJ0aWNpcGFudCBmc1xuICogICBwYXJ0aWNpcGFudCByZWFkRmlsZVxuICogICBwYXJ0aWNpcGFudCBUZXh0VXRpbHNcbiAqICAgcGFydGljaXBhbnQgd3JpdGVGaWxlXG4gKiAgIENhbGxlci0+PnBhdGNoRmlsZTogQ2FsbCB3aXRoIHBhdGggYW5kIHZhbHVlc1xuICogICBwYXRjaEZpbGUtPj5mczogQ2hlY2sgaWYgZmlsZSBleGlzdHNcbiAqICAgcGF0Y2hGaWxlLT4+cmVhZEZpbGU6IFJlYWQgZmlsZSBjb250ZW50XG4gKiAgIHJlYWRGaWxlLT4+ZnM6IFJlYWQgZmlsZVxuICogICBmcy0tPj5yZWFkRmlsZTogUmV0dXJuIGZpbGUgY29udGVudFxuICogICByZWFkRmlsZS0tPj5wYXRjaEZpbGU6IFJldHVybiBmaWxlIGNvbnRlbnRcbiAqICAgcGF0Y2hGaWxlLT4+VGV4dFV0aWxzOiBQYXRjaCBzdHJpbmdcbiAqICAgVGV4dFV0aWxzLS0+PnBhdGNoRmlsZTogUmV0dXJuIHBhdGNoZWQgY29udGVudFxuICogICBwYXRjaEZpbGUtPj53cml0ZUZpbGU6IFdyaXRlIHBhdGNoZWQgY29udGVudFxuICogICB3cml0ZUZpbGUtPj5mczogV3JpdGUgdG8gZmlsZVxuICogICBmcy0tPj53cml0ZUZpbGU6IEZpbGUgd3JpdHRlblxuICogICB3cml0ZUZpbGUtLT4+cGF0Y2hGaWxlOiBGaWxlIHdyaXR0ZW5cbiAqICAgcGF0Y2hGaWxlLS0+PkNhbGxlcjogUGF0Y2hpbmcgY29tcGxldGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXRjaEZpbGUoXG4gIHBhdGg6IHN0cmluZyxcbiAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXIgfCBzdHJpbmc+LFxuICBmaWx0ZXI/OiAoc3RyOiBzdHJpbmcpID0+IGJvb2xlYW5cbikge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHBhdGNoRmlsZSk7XG4gIGlmICghZnMuZXhpc3RzU3luYyhwYXRoKSlcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEZpbGUgbm90IGZvdW5kIGF0IHBhdGggXCIke3BhdGh9XCIuYCk7XG4gIGxldCBjb250ZW50ID0gcmVhZEZpbGUocGF0aCk7XG5cbiAgbG9nLnZlcmJvc2UoYFBhdGNoaW5nIGZpbGUgXCIke3BhdGh9XCIuLi5gKTtcbiAgbG9nLmRlYnVnKGB3aXRoIHZhbHVlOiAke0pTT04uc3RyaW5naWZ5KHZhbHVlcyl9YCk7XG4gIHRyeSB7XG4gICAgY29udGVudCA9IHBhdGNoU3RyaW5nKGNvbnRlbnQsIHZhbHVlcywgXCJnXCIsIGZpbHRlcik7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBwYXRjaGluZyBmaWxlOiAke2Vycm9yfWApO1xuICB9XG4gIHdyaXRlRmlsZShwYXRoLCBjb250ZW50KTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVhZHMgYSBmaWxlIGFuZCByZXR1cm5zIGl0cyBjb250ZW50LlxuICogQHN1bW1hcnkgUmVhZHMgdGhlIGNvbnRlbnQgb2YgYSBmaWxlIGF0IHRoZSBzcGVjaWZpZWQgcGF0aCBhbmQgcmV0dXJucyBpdCBhcyBhIHN0cmluZy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGF0aCAtIFRoZSBwYXRoIHRvIHRoZSBmaWxlIHRvIGJlIHJlYWQuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBjb250ZW50IG9mIHRoZSBmaWxlLlxuICpcbiAqIEBmdW5jdGlvbiByZWFkRmlsZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlYWRGaWxlKHBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IocmVhZEZpbGUpO1xuICB0cnkge1xuICAgIGxvZy52ZXJib3NlKGBSZWFkaW5nIGZpbGUgXCIke3BhdGh9XCIuLi5gKTtcbiAgICByZXR1cm4gZnMucmVhZEZpbGVTeW5jKHBhdGgsIFwidXRmOFwiKTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShgRXJyb3IgcmVhZGluZyBmaWxlIFwiJHtwYXRofVwiOiAke2Vycm9yfWApO1xuICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgcmVhZGluZyBmaWxlIFwiJHtwYXRofVwiOiAke2Vycm9yfWApO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFdyaXRlcyBkYXRhIHRvIGEgZmlsZS5cbiAqIEBzdW1tYXJ5IFdyaXRlcyB0aGUgcHJvdmlkZWQgZGF0YSB0byBhIGZpbGUgYXQgdGhlIHNwZWNpZmllZCBwYXRoLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gVGhlIHBhdGggdG8gdGhlIGZpbGUgdG8gYmUgd3JpdHRlbi5cbiAqIEBwYXJhbSB7c3RyaW5nIHwgQnVmZmVyfSBkYXRhIC0gVGhlIGRhdGEgdG8gYmUgd3JpdHRlbiB0byB0aGUgZmlsZS5cbiAqIEByZXR1cm4ge3ZvaWR9XG4gKlxuICogQGZ1bmN0aW9uIHdyaXRlRmlsZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdyaXRlRmlsZShwYXRoOiBzdHJpbmcsIGRhdGE6IHN0cmluZyB8IEJ1ZmZlcik6IHZvaWQge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHdyaXRlRmlsZSk7XG4gIHRyeSB7XG4gICAgbG9nLnZlcmJvc2UoYFdyaXRpbmcgZmlsZSBcIiR7cGF0aH0gd2l0aCAke2RhdGEubGVuZ3RofSBieXRlcy4uLmApO1xuICAgIGZzLndyaXRlRmlsZVN5bmMocGF0aCwgZGF0YSwgXCJ1dGY4XCIpO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGxvZy52ZXJib3NlKGBFcnJvciB3cml0aW5nIGZpbGUgXCIke3BhdGh9XCI6ICR7ZXJyb3J9YCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciB3cml0aW5nIGZpbGUgXCIke3BhdGh9XCI6ICR7ZXJyb3J9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGFsbCBmaWxlcyByZWN1cnNpdmVseSBmcm9tIGEgZGlyZWN0b3J5LlxuICogQHN1bW1hcnkgVHJhdmVyc2VzIHRocm91Z2ggZGlyZWN0b3JpZXMgYW5kIHN1YmRpcmVjdG9yaWVzIHRvIGNvbGxlY3QgYWxsIGZpbGUgcGF0aHMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHAgLSBUaGUgcGF0aCB0byBzdGFydCBzZWFyY2hpbmcgZnJvbS5cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IFtmaWx0ZXJdIC0gT3B0aW9uYWwgZnVuY3Rpb24gdG8gZmlsdGVyIGZpbGVzIGJ5IG5hbWUgb3IgaW5kZXguXG4gKiBAcmV0dXJuIHtzdHJpbmdbXX0gQXJyYXkgb2YgZmlsZSBwYXRocy5cbiAqXG4gKiBAZnVuY3Rpb24gZ2V0QWxsRmlsZXNcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBbGxGaWxlcyhcbiAgcDogc3RyaW5nLFxuICBmaWx0ZXI/OiAoZjogc3RyaW5nLCBpPzogbnVtYmVyKSA9PiBib29sZWFuXG4pOiBzdHJpbmdbXSB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IoZ2V0QWxsRmlsZXMpO1xuICBjb25zdCBmaWxlczogc3RyaW5nW10gPSBbXTtcblxuICB0cnkge1xuICAgIGxvZy52ZXJib3NlKGBSZXRyaWV2aW5nIGFsbCBmaWxlcyBmcm9tIFwiJHtwfVwiLi4uYCk7XG4gICAgY29uc3QgZW50cmllcyA9IGZzLnJlYWRkaXJTeW5jKHApO1xuXG4gICAgZW50cmllcy5mb3JFYWNoKChlbnRyeSkgPT4ge1xuICAgICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4ocCwgZW50cnkpO1xuICAgICAgY29uc3Qgc3RhdCA9IGZzLnN0YXRTeW5jKGZ1bGxQYXRoKTtcblxuICAgICAgaWYgKHN0YXQuaXNGaWxlKCkpIHtcbiAgICAgICAgZmlsZXMucHVzaChmdWxsUGF0aCk7XG4gICAgICB9IGVsc2UgaWYgKHN0YXQuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICBmaWxlcy5wdXNoKC4uLmdldEFsbEZpbGVzKGZ1bGxQYXRoKSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKCFmaWx0ZXIpIHJldHVybiBmaWxlcztcbiAgICByZXR1cm4gZmlsZXMuZmlsdGVyKGZpbHRlcik7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoYEVycm9yIHJldHJpZXZpbmcgZmlsZXMgZnJvbSBcIiR7cH1cIjogJHtlcnJvcn1gKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHJldHJpZXZpbmcgZmlsZXMgZnJvbSBcIiR7cH1cIjogJHtlcnJvcn1gKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZW5hbWVzIGEgZmlsZSBvciBkaXJlY3RvcnkuXG4gKiBAc3VtbWFyeSBNb3ZlcyBhIGZpbGUgb3IgZGlyZWN0b3J5IGZyb20gdGhlIHNvdXJjZSBwYXRoIHRvIHRoZSBkZXN0aW5hdGlvbiBwYXRoLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBUaGUgc291cmNlIHBhdGggb2YgdGhlIGZpbGUgb3IgZGlyZWN0b3J5LlxuICogQHBhcmFtIHtzdHJpbmd9IGRlc3QgLSBUaGUgZGVzdGluYXRpb24gcGF0aCBmb3IgdGhlIGZpbGUgb3IgZGlyZWN0b3J5LlxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgcmVuYW1lIG9wZXJhdGlvbiBpcyBjb21wbGV0ZS5cbiAqXG4gKiBAZnVuY3Rpb24gcmVuYW1lRmlsZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlbmFtZUZpbGUoc291cmNlOiBzdHJpbmcsIGRlc3Q6IHN0cmluZykge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHJlbmFtZUZpbGUpO1xuICBsZXQgZGVzY3JpcHRvclNvdXJjZSwgZGVzY3JpcHRvckRlc3Q7XG5cbiAgdHJ5IHtcbiAgICBkZXNjcmlwdG9yU291cmNlID0gZnMuc3RhdFN5bmMoc291cmNlKTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShgU291cmNlIHBhdGggXCIke3NvdXJjZX1cIiBkb2VzIG5vdCBleGlzdDogJHtlcnJvcn1gKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFNvdXJjZSBwYXRoIFwiJHtzb3VyY2V9XCIgZG9lcyBub3QgZXhpc3Q6ICR7ZXJyb3J9YCk7XG4gIH1cblxuICB0cnkge1xuICAgIGRlc2NyaXB0b3JEZXN0ID0gZnMuc3RhdFN5bmMoZGVzdCk7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgLy8gZG8gbm90aGluZy4gaXRzIG9rXG4gIH1cbiAgaWYgKGRlc2NyaXB0b3JEZXN0KSB7XG4gICAgbG9nLnZlcmJvc2UoYERlc3RpbmF0aW9uIHBhdGggXCIke2Rlc3R9XCIgYWxyZWFkeSBleGlzdHNgKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYERlc3RpbmF0aW9uIHBhdGggXCIke2Rlc3R9XCIgYWxyZWFkeSBleGlzdHNgKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgUmVuYW1pbmcgJHtkZXNjcmlwdG9yU291cmNlLmlzRmlsZSgpID8gXCJmaWxlXCIgOiBcImRpcmVjdG9yeVwifSBcIiR7c291cmNlfVwiIHRvIFwiJHtkZXN0fS4uLmBcbiAgICApO1xuICAgIGZzLnJlbmFtZVN5bmMoc291cmNlLCBkZXN0KTtcbiAgICBsb2cudmVyYm9zZShgU3VjY2Vzc2Z1bGx5IHJlbmFtZWQgdG8gXCIke2Rlc3R9XCJgKTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBFcnJvciByZW5hbWluZyAke2Rlc2NyaXB0b3JTb3VyY2UuaXNGaWxlKCkgPyBcImZpbGVcIiA6IFwiZGlyZWN0b3J5XCJ9IFwiJHtzb3VyY2V9XCIgdG8gXCIke2Rlc3R9XCI6ICR7ZXJyb3J9YFxuICAgICk7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYEVycm9yIHJlbmFtaW5nICR7ZGVzY3JpcHRvclNvdXJjZS5pc0ZpbGUoKSA/IFwiZmlsZVwiIDogXCJkaXJlY3RvcnlcIn0gXCIke3NvdXJjZX1cIiB0byBcIiR7ZGVzdH1cIjogJHtlcnJvcn1gXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDb3BpZXMgYSBmaWxlIG9yIGRpcmVjdG9yeS5cbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBjb3B5IG9mIGEgZmlsZSBvciBkaXJlY3RvcnkgZnJvbSB0aGUgc291cmNlIHBhdGggdG8gdGhlIGRlc3RpbmF0aW9uIHBhdGguXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIFRoZSBzb3VyY2UgcGF0aCBvZiB0aGUgZmlsZSBvciBkaXJlY3RvcnkuXG4gKiBAcGFyYW0ge3N0cmluZ30gZGVzdCAtIFRoZSBkZXN0aW5hdGlvbiBwYXRoIGZvciB0aGUgZmlsZSBvciBkaXJlY3RvcnkuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICpcbiAqIEBmdW5jdGlvbiBjb3B5RmlsZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvcHlGaWxlKHNvdXJjZTogc3RyaW5nLCBkZXN0OiBzdHJpbmcpIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihjb3B5RmlsZSk7XG4gIGxldCBkZXNjcmlwdG9yU291cmNlLCBkZXNjcmlwdG9yRGVzdDtcbiAgdHJ5IHtcbiAgICBkZXNjcmlwdG9yU291cmNlID0gZnMuc3RhdFN5bmMoc291cmNlKTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShgU291cmNlIHBhdGggXCIke3NvdXJjZX1cIiBkb2VzIG5vdCBleGlzdDogJHtlcnJvcn1gKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFNvdXJjZSBwYXRoIFwiJHtzb3VyY2V9XCIgZG9lcyBub3QgZXhpc3Q6ICR7ZXJyb3J9YCk7XG4gIH1cbiAgdHJ5IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgZGVzY3JpcHRvckRlc3QgPSBmcy5zdGF0U3luYyhkZXN0KTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgaWYgKGRlc2NyaXB0b3JTb3VyY2UuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgbG9nLnZlcmJvc2UoYERlc3QgcGF0aCBcIiR7ZGVzdH1cIiBkb2VzIG5vdCBleGlzdC4gY3JlYXRpbmdgKTtcbiAgICAgIGZzLm1rZGlyU3luYyhkZXN0LCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICB9XG4gIH1cblxuICB0cnkge1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYENvcHlpbmcgJHtkZXNjcmlwdG9yU291cmNlLmlzRmlsZSgpID8gXCJmaWxlXCIgOiBcImRpcmVjdG9yeVwifSBcIiR7c291cmNlfVwiIHRvIFwiJHtkZXN0fS4uLmBcbiAgICApO1xuICAgIGZzLmNwU3luYyhzb3VyY2UsIGRlc3QsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYEVycm9yIGNvcHlpbmcgJHtkZXNjcmlwdG9yU291cmNlLmlzRmlsZSgpID8gXCJmaWxlXCIgOiBcImRpcmVjdG9yeVwifSBcIiR7c291cmNlfVwiIHRvIFwiJHtkZXN0fTogJHtlcnJvcn1gXG4gICAgKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgRXJyb3IgY29weWluZyAke2Rlc2NyaXB0b3JTb3VyY2UuaXNGaWxlKCkgPyBcImZpbGVcIiA6IFwiZGlyZWN0b3J5XCJ9IFwiJHtzb3VyY2V9XCIgdG8gXCIke2Rlc3R9OiAke2Vycm9yfWBcbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgYSBmaWxlIG9yIGRpcmVjdG9yeS5cbiAqIEBzdW1tYXJ5IFJlbW92ZXMgYSBmaWxlIG9yIGRpcmVjdG9yeSBhdCB0aGUgc3BlY2lmaWVkIHBhdGgsIHdpdGggcmVjdXJzaXZlIGFuZCBmb3JjZSBvcHRpb25zIGVuYWJsZWQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHAgLSBUaGUgcGF0aCB0byB0aGUgZmlsZSBvciBkaXJlY3RvcnkgdG8gZGVsZXRlLlxuICogQHJldHVybiB7dm9pZH1cbiAqXG4gKiBAZnVuY3Rpb24gZGVsZXRlUGF0aFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlbGV0ZVBhdGgocDogc3RyaW5nKSB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IoZGVsZXRlUGF0aCk7XG4gIHRyeSB7XG4gICAgY29uc3QgZGVzY3JpcHRvciA9IGZzLnN0YXRTeW5jKHApO1xuICAgIGlmIChkZXNjcmlwdG9yLmlzRmlsZSgpKSB7XG4gICAgICBsb2cudmVyYm9zZShgRGVsZXRpbmcgZmlsZSBcIiR7cH0uLi5gKTtcbiAgICAgIGZzLnJtU3luYyhwLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgfSBlbHNlIGlmIChkZXNjcmlwdG9yLmlzRGlyZWN0b3J5KCkpXG4gICAgICBmcy5ybVN5bmMocCwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGxvZy52ZXJib3NlKGBFcnJvciBEZWxldGluZyBcIiR7cH1cIjogJHtlcnJvcn1gKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIERlbGV0aW5nIFwiJHtwfVwiOiAke2Vycm9yfWApO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBwYWNrYWdlIGluZm9ybWF0aW9uIGZyb20gcGFja2FnZS5qc29uLlxuICogQHN1bW1hcnkgTG9hZHMgYW5kIHBhcnNlcyB0aGUgcGFja2FnZS5qc29uIGZpbGUgZnJvbSBhIHNwZWNpZmllZCBkaXJlY3Rvcnkgb3IgdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnkuIENhbiByZXR1cm4gdGhlIGVudGlyZSBwYWNrYWdlIG9iamVjdCBvciBhIHNwZWNpZmljIHByb3BlcnR5LlxuICogQHBhcmFtIHtzdHJpbmd9IFtwPXByb2Nlc3MuY3dkKCldIC0gVGhlIGRpcmVjdG9yeSBwYXRoIHdoZXJlIHRoZSBwYWNrYWdlLmpzb24gZmlsZSBpcyBsb2NhdGVkLlxuICogQHBhcmFtIHtzdHJpbmd9IFtwcm9wZXJ0eV0gLSBPcHRpb25hbC4gVGhlIHNwZWNpZmljIHByb3BlcnR5IHRvIHJldHJpZXZlIGZyb20gcGFja2FnZS5qc29uLlxuICogQHJldHVybiB7b2JqZWN0IHwgc3RyaW5nfSBUaGUgcGFyc2VkIGNvbnRlbnRzIG9mIHBhY2thZ2UuanNvbiBvciB0aGUgdmFsdWUgb2YgdGhlIHNwZWNpZmllZCBwcm9wZXJ0eS5cbiAqIEBmdW5jdGlvbiBnZXRQYWNrYWdlXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBnZXRQYWNrYWdlXG4gKiAgIHBhcnRpY2lwYW50IHJlYWRGaWxlXG4gKiAgIHBhcnRpY2lwYW50IEpTT05cbiAqICAgQ2FsbGVyLT4+Z2V0UGFja2FnZTogQ2FsbCB3aXRoIHBhdGggYW5kIG9wdGlvbmFsIHByb3BlcnR5XG4gKiAgIGdldFBhY2thZ2UtPj5yZWFkRmlsZTogUmVhZCBwYWNrYWdlLmpzb25cbiAqICAgcmVhZEZpbGUtLT4+Z2V0UGFja2FnZTogUmV0dXJuIGZpbGUgY29udGVudFxuICogICBnZXRQYWNrYWdlLT4+SlNPTjogUGFyc2UgZmlsZSBjb250ZW50XG4gKiAgIEpTT04tLT4+Z2V0UGFja2FnZTogUmV0dXJuIHBhcnNlZCBvYmplY3RcbiAqICAgYWx0IHByb3BlcnR5IHNwZWNpZmllZFxuICogICAgIGdldFBhY2thZ2UtPj5nZXRQYWNrYWdlOiBDaGVjayBpZiBwcm9wZXJ0eSBleGlzdHNcbiAqICAgICBhbHQgcHJvcGVydHkgZXhpc3RzXG4gKiAgICAgICBnZXRQYWNrYWdlLS0+PkNhbGxlcjogUmV0dXJuIHByb3BlcnR5IHZhbHVlXG4gKiAgICAgZWxzZSBwcm9wZXJ0eSBkb2Vzbid0IGV4aXN0XG4gKiAgICAgICBnZXRQYWNrYWdlLS0+PkNhbGxlcjogVGhyb3cgRXJyb3JcbiAqICAgICBlbmRcbiAqICAgZWxzZSBubyBwcm9wZXJ0eSBzcGVjaWZpZWRcbiAqICAgICBnZXRQYWNrYWdlLS0+PkNhbGxlcjogUmV0dXJuIGVudGlyZSBwYWNrYWdlIG9iamVjdFxuICogICBlbmRcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFBhY2thZ2UoXG4gIHA6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCksXG4gIHByb3BlcnR5Pzogc3RyaW5nXG4pOiBvYmplY3QgfCBzdHJpbmcge1xuICBsZXQgcGtnOiBhbnk7XG4gIHRyeSB7XG4gICAgcGtnID0gSlNPTi5wYXJzZShyZWFkRmlsZShwYXRoLmpvaW4ocCwgYHBhY2thZ2UuanNvbmApKSk7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcmV0cmlldmUgcGFja2FnZSBpbmZvcm1hdGlvblwiICR7ZXJyb3J9YCk7XG4gIH1cblxuICBpZiAocHJvcGVydHkpIHtcbiAgICBpZiAoIShwcm9wZXJ0eSBpbiBwa2cpKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBQcm9wZXJ0eSBcIiR7cHJvcGVydHl9XCIgbm90IGZvdW5kIGluIHBhY2thZ2UuanNvbmApO1xuICAgIHJldHVybiBwa2dbcHJvcGVydHldIGFzIHN0cmluZztcbiAgfVxuICByZXR1cm4gcGtnO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTZXRzIGFuIGF0dHJpYnV0ZSBpbiB0aGUgcGFja2FnZS5qc29uIGZpbGUuXG4gKiBAc3VtbWFyeSBVcGRhdGVzIGEgc3BlY2lmaWMgYXR0cmlidXRlIGluIHRoZSBwYWNrYWdlLmpzb24gZmlsZSB3aXRoIHRoZSBwcm92aWRlZCB2YWx1ZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gYXR0ciAtIFRoZSBhdHRyaWJ1dGUgbmFtZSB0byBzZXQgaW4gcGFja2FnZS5qc29uLlxuICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXIgfCBvYmplY3R9IHZhbHVlIC0gVGhlIHZhbHVlIHRvIHNldCBmb3IgdGhlIGF0dHJpYnV0ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbcD1wcm9jZXNzLmN3ZCgpXSAtIFRoZSBkaXJlY3RvcnkgcGF0aCB3aGVyZSB0aGUgcGFja2FnZS5qc29uIGZpbGUgaXMgbG9jYXRlZC5cbiAqIEByZXR1cm4ge3ZvaWR9XG4gKlxuICogQGZ1bmN0aW9uIHNldFBhY2thZ2VBdHRyaWJ1dGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRQYWNrYWdlQXR0cmlidXRlKFxuICBhdHRyOiBzdHJpbmcsXG4gIHZhbHVlOiBzdHJpbmcsXG4gIHA6IHN0cmluZyA9IHByb2Nlc3MuY3dkKClcbik6IHZvaWQge1xuICBjb25zdCBwa2cgPSBnZXRQYWNrYWdlKHApIGFzIFJlY29yZDxzdHJpbmcsIGFueT47XG4gIHBrZ1thdHRyXSA9IHZhbHVlO1xuICB3cml0ZUZpbGUocGF0aC5qb2luKHAsIGBwYWNrYWdlLmpzb25gKSwgSlNPTi5zdHJpbmdpZnkocGtnLCBudWxsLCAyKSk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyB0aGUgdmVyc2lvbiBmcm9tIHBhY2thZ2UuanNvbi5cbiAqIEBzdW1tYXJ5IEEgY29udmVuaWVuY2UgZnVuY3Rpb24gdGhhdCBjYWxscyBnZXRQYWNrYWdlIHRvIHJldHJpZXZlIHRoZSBcInZlcnNpb25cIiBwcm9wZXJ0eSBmcm9tIHBhY2thZ2UuanNvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbcD1wcm9jZXNzLmN3ZCgpXSAtIFRoZSBkaXJlY3RvcnkgcGF0aCB3aGVyZSB0aGUgcGFja2FnZS5qc29uIGZpbGUgaXMgbG9jYXRlZC5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHZlcnNpb24gc3RyaW5nIGZyb20gcGFja2FnZS5qc29uLlxuICogQGZ1bmN0aW9uIGdldFBhY2thZ2VWZXJzaW9uXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQYWNrYWdlVmVyc2lvbihwID0gcHJvY2Vzcy5jd2QoKSk6IHN0cmluZyB7XG4gIHJldHVybiBnZXRQYWNrYWdlKHAsIFwidmVyc2lvblwiKSBhcyBzdHJpbmc7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhbGwgZGVwZW5kZW5jaWVzIGZyb20gdGhlIHByb2plY3QuXG4gKiBAc3VtbWFyeSBFeGVjdXRlcyAnbnBtIGxzIC0tanNvbicgY29tbWFuZCB0byBnZXQgYSBkZXRhaWxlZCBsaXN0IG9mIGFsbCBkZXBlbmRlbmNpZXMgKHByb2R1Y3Rpb24sIGRldmVsb3BtZW50LCBhbmQgcGVlcikgYW5kIHRoZWlyIHZlcnNpb25zLlxuICogQHBhcmFtIHtzdHJpbmd9IFtwYXRoPXByb2Nlc3MuY3dkKCldIC0gVGhlIGRpcmVjdG9yeSBwYXRoIG9mIHRoZSBwcm9qZWN0LlxuICogQHJldHVybiB7UHJvbWlzZTx7cHJvZDogQXJyYXk8e25hbWU6IHN0cmluZywgdmVyc2lvbjogc3RyaW5nfT4sIGRldjogQXJyYXk8e25hbWU6IHN0cmluZywgdmVyc2lvbjogc3RyaW5nfT4sIHBlZXI6IEFycmF5PHtuYW1lOiBzdHJpbmcsIHZlcnNpb246IHN0cmluZ30+fT59IEFuIG9iamVjdCBjb250YWluaW5nIGFycmF5cyBvZiBwcm9kdWN0aW9uLCBkZXZlbG9wbWVudCwgYW5kIHBlZXIgZGVwZW5kZW5jaWVzLlxuICogQGZ1bmN0aW9uIGdldERlcGVuZGVuY2llc1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgZ2V0RGVwZW5kZW5jaWVzXG4gKiAgIHBhcnRpY2lwYW50IHJ1bkNvbW1hbmRcbiAqICAgcGFydGljaXBhbnQgSlNPTlxuICogICBDYWxsZXItPj5nZXREZXBlbmRlbmNpZXM6IENhbGwgd2l0aCBvcHRpb25hbCBwYXRoXG4gKiAgIGdldERlcGVuZGVuY2llcy0+PnJ1bkNvbW1hbmQ6IEV4ZWN1dGUgJ25wbSBscyAtLWpzb24nXG4gKiAgIHJ1bkNvbW1hbmQtLT4+Z2V0RGVwZW5kZW5jaWVzOiBSZXR1cm4gY29tbWFuZCBvdXRwdXRcbiAqICAgZ2V0RGVwZW5kZW5jaWVzLT4+SlNPTjogUGFyc2UgY29tbWFuZCBvdXRwdXRcbiAqICAgSlNPTi0tPj5nZXREZXBlbmRlbmNpZXM6IFJldHVybiBwYXJzZWQgb2JqZWN0XG4gKiAgIGdldERlcGVuZGVuY2llcy0+PmdldERlcGVuZGVuY2llczogUHJvY2VzcyBkZXBlbmRlbmNpZXNcbiAqICAgZ2V0RGVwZW5kZW5jaWVzLS0+PkNhbGxlcjogUmV0dXJuIHByb2Nlc3NlZCBkZXBlbmRlbmNpZXNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldERlcGVuZGVuY2llcyhcbiAgcDogc3RyaW5nID0gcHJvY2Vzcy5jd2QoKVxuKTogUHJvbWlzZTxEZXBlbmRlbmN5TWFwPiB7XG4gIGNvbnN0IHBrZ1BhdGggPSBwYXRoLmpvaW4ocCwgXCJwYWNrYWdlLmpzb25cIik7XG4gIGNvbnN0IGxvY2tQYXRoID0gcGF0aC5qb2luKHAsIFwicGFja2FnZS1sb2NrLmpzb25cIik7XG4gIGxldCBwa2c6IGFueTtcbiAgdHJ5IHtcbiAgICBwa2cgPSBKU09OLnBhcnNlKHJlYWRGaWxlKHBrZ1BhdGgpKTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCByZWFkIHBhY2thZ2UuanNvbiBhdCAke3BrZ1BhdGh9OiAke2Vycm9yfWApO1xuICB9XG5cbiAgbGV0IGxvY2s6IGFueTtcbiAgaWYgKGZzLmV4aXN0c1N5bmMobG9ja1BhdGgpKSB7XG4gICAgdHJ5IHtcbiAgICAgIGxvY2sgPSBKU09OLnBhcnNlKHJlYWRGaWxlKGxvY2tQYXRoKSk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIGxvZ2dlci53YXJuKGBVbmFibGUgdG8gcGFyc2UgcGFja2FnZS1sb2NrLmpzb24gYXQgJHtsb2NrUGF0aH06ICR7ZXJyb3J9YCk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgbWFwRGVwcyA9IChlbnRyaWVzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge30pID0+XG4gICAgT2JqZWN0LmVudHJpZXMoZW50cmllcykubWFwKChbbmFtZSwgdmVyc2lvbl0pID0+ICh7XG4gICAgICBuYW1lLFxuICAgICAgdmVyc2lvbjogcmVzb2x2ZURlcGVuZGVuY3lWZXJzaW9uKGxvY2ssIG5hbWUsIHZlcnNpb24pLFxuICAgIH0pKTtcblxuICByZXR1cm4ge1xuICAgIHByb2Q6IG1hcERlcHMocGtnLmRlcGVuZGVuY2llcyksXG4gICAgZGV2OiBtYXBEZXBzKHBrZy5kZXZEZXBlbmRlbmNpZXMpLFxuICAgIHBlZXI6IG1hcERlcHMocGtnLnBlZXJEZXBlbmRlbmNpZXMpLFxuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRGVwZW5kZW5jeVZlcnNpb24oXG4gIGxvY2s6IGFueSxcbiAgbmFtZTogc3RyaW5nLFxuICBmYWxsYmFjazogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBpZiAobG9jaykge1xuICAgIGNvbnN0IHBhY2thZ2VzID0gbG9jay5wYWNrYWdlcyB8fCB7fTtcbiAgICBjb25zdCBrZXkgPSBgbm9kZV9tb2R1bGVzLyR7bmFtZX1gO1xuICAgIGlmIChwYWNrYWdlc1trZXldICYmIHBhY2thZ2VzW2tleV0udmVyc2lvbikge1xuICAgICAgcmV0dXJuIHBhY2thZ2VzW2tleV0udmVyc2lvbjtcbiAgICB9XG4gICAgaWYgKGxvY2suZGVwZW5kZW5jaWVzICYmIGxvY2suZGVwZW5kZW5jaWVzW25hbWVdKSB7XG4gICAgICByZXR1cm4gbG9jay5kZXBlbmRlbmNpZXNbbmFtZV0udmVyc2lvbiB8fCBmYWxsYmFjaztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbGxiYWNrO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIHByb2plY3QgZGVwZW5kZW5jaWVzIHRvIHRoZWlyIGxhdGVzdCB2ZXJzaW9ucy5cbiAqIEBzdW1tYXJ5IFJ1bnMgbnBtLWNoZWNrLXVwZGF0ZXMgdG8gdXBkYXRlIHBhY2thZ2UuanNvbiBhbmQgdGhlbiBpbnN0YWxscyB0aGUgdXBkYXRlZCBkZXBlbmRlbmNpZXMuXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBkZXBlbmRlbmNpZXMgYXJlIHVwZGF0ZWQuXG4gKlxuICogQGZ1bmN0aW9uIHVwZGF0ZURlcGVuZGVuY2llc1xuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZURlcGVuZGVuY2llcygpIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcih1cGRhdGVEZXBlbmRlbmNpZXMpO1xuICBsb2cuaW5mbyhcImNoZWNraW5nIGZvciB1cGRhdGVzLi4uXCIpO1xuICBhd2FpdCBydW5Db21tYW5kKFwibnB4IG5wbS1jaGVjay11cGRhdGVzIC11XCIpLnByb21pc2U7XG4gIGxvZy5pbmZvKFwidXBkYXRpbmcuLi5cIik7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoXCJucHggbnBtIHJ1biBkby1pbnN0YWxsXCIpLnByb21pc2U7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEluc3RhbGxzIGRlcGVuZGVuY2llcyBpZiB0aGV5IGFyZSBub3QgYWxyZWFkeSBhdmFpbGFibGUuXG4gKiBAc3VtbWFyeSBDaGVja3MgaWYgc3BlY2lmaWVkIGRlcGVuZGVuY2llcyBhcmUgaW5zdGFsbGVkIGFuZCBpbnN0YWxscyBhbnkgdGhhdCBhcmUgbWlzc2luZy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ1tdIHwgc3RyaW5nfSBkZXBzIC0gVGhlIGRlcGVuZGVuY2llcyB0byBjaGVjayBhbmQgcG90ZW50aWFsbHkgaW5zdGFsbC5cbiAqIEBwYXJhbSB7U2ltcGxlRGVwZW5kZW5jeU1hcH0gW2RlcGVuZGVuY2llc10gLSBPcHRpb25hbCBtYXAgb2YgZXhpc3RpbmcgZGVwZW5kZW5jaWVzLlxuICogQHJldHVybiB7UHJvbWlzZTxTaW1wbGVEZXBlbmRlbmN5TWFwPn0gVXBkYXRlZCBtYXAgb2YgZGVwZW5kZW5jaWVzLlxuICpcbiAqIEBmdW5jdGlvbiBpbnN0YWxsSWZOb3RBdmFpbGFibGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnN0YWxsSWZOb3RBdmFpbGFibGUoXG4gIGRlcHM6IHN0cmluZ1tdIHwgc3RyaW5nLFxuICBkZXBlbmRlbmNpZXM/OiBTaW1wbGVEZXBlbmRlbmN5TWFwXG4pIHtcbiAgZGVwcyA9IHR5cGVvZiBkZXBzID09PSBcInN0cmluZ1wiID8gW2RlcHNdIDogZGVwcztcbiAgY29uc3QgY3VycmVudDogU2ltcGxlRGVwZW5kZW5jeU1hcCA9IHtcbiAgICBwcm9kOiBkZXBlbmRlbmNpZXM/LnByb2QgPyBbLi4uZGVwZW5kZW5jaWVzLnByb2RdIDogW10sXG4gICAgZGV2OiBkZXBlbmRlbmNpZXM/LmRldiA/IFsuLi5kZXBlbmRlbmNpZXMuZGV2XSA6IFtdLFxuICAgIHBlZXI6IGRlcGVuZGVuY2llcz8ucGVlciA/IFsuLi5kZXBlbmRlbmNpZXMucGVlcl0gOiBbXSxcbiAgfTtcblxuICBjb25zdCBrbm93biA9IG5ldyBTZXQoW1xuICAgIC4uLihjdXJyZW50LnByb2QgPz8gW10pLFxuICAgIC4uLihjdXJyZW50LmRldiA/PyBbXSksXG4gICAgLi4uKGN1cnJlbnQucGVlciA/PyBbXSksXG4gIF0pO1xuXG4gIGNvbnN0IHRvSW5zdGFsbDogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChjb25zdCBkZXAgb2YgZGVwcykge1xuICAgIGlmIChrbm93bi5oYXMoZGVwKSkgY29udGludWU7XG4gICAgdHJ5IHtcbiAgICAgIGxvY2FsUmVxdWlyZS5yZXNvbHZlKGRlcCk7XG4gICAgICBrbm93bi5hZGQoZGVwKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHRvSW5zdGFsbC5wdXNoKGRlcCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHRvSW5zdGFsbC5sZW5ndGgpIHtcbiAgICBpZiAoaXNUZXN0RW52aXJvbm1lbnQoKSkge1xuICAgICAgbG9nZ2VyLnZlcmJvc2UoXG4gICAgICAgIGBTa2lwcGluZyBkZXBlbmRlbmN5IGluc3RhbGwgaW4gdGVzdCBlbnZpcm9ubWVudCBmb3I6ICR7dG9JbnN0YWxsLmpvaW4oXG4gICAgICAgICAgXCIsIFwiXG4gICAgICAgICl9YFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgaW5zdGFsbERlcGVuZGVuY2llcyh7IGRldjogdG9JbnN0YWxsIH0pO1xuICAgIH1cbiAgICBjb25zdCBkZXZEZXBzID0gbmV3IFNldChjdXJyZW50LmRldiA/PyBbXSk7XG4gICAgdG9JbnN0YWxsLmZvckVhY2goKGRlcCkgPT4gZGV2RGVwcy5hZGQoZGVwKSk7XG4gICAgY3VycmVudC5kZXYgPSBBcnJheS5mcm9tKGRldkRlcHMpO1xuICB9XG5cbiAgcmV0dXJuIGN1cnJlbnQ7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFB1c2hlcyBjaGFuZ2VzIHRvIEdpdCByZXBvc2l0b3J5LlxuICogQHN1bW1hcnkgVGVtcG9yYXJpbHkgY2hhbmdlcyBHaXQgdXNlciBjb25maWd1cmF0aW9uLCBjb21taXRzIGFsbCBjaGFuZ2VzLCBwdXNoZXMgdG8gcmVtb3RlLCBhbmQgcmVzdG9yZXMgb3JpZ2luYWwgdXNlciBjb25maWd1cmF0aW9uLlxuICpcbiAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gY2hhbmdlcyBhcmUgcHVzaGVkLlxuICpcbiAqIEBmdW5jdGlvbiBwdXNoVG9HaXRcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwdXNoVG9HaXQoKSB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IocHVzaFRvR2l0KTtcbiAgY29uc3QgZ2l0VXNlciA9IGF3YWl0IHJ1bkNvbW1hbmQoXCJnaXQgY29uZmlnIHVzZXIubmFtZVwiKS5wcm9taXNlO1xuICBjb25zdCBnaXRFbWFpbCA9IGF3YWl0IHJ1bkNvbW1hbmQoXCJnaXQgY29uZmlnIHVzZXIuZW1haWxcIikucHJvbWlzZTtcbiAgbG9nLnZlcmJvc2UoYGNhY2hlZCBnaXQgaWQ6ICR7Z2l0VXNlcn0vJHtnaXRFbWFpbH0uIGNoYW5naW5nIHRvIGF1dG9tYXRpb25gKTtcbiAgYXdhaXQgcnVuQ29tbWFuZCgnZ2l0IGNvbmZpZyB1c2VyLmVtYWlsIFwiYXV0b21hdGlvbkBkZWNhZi50c1wiJykucHJvbWlzZTtcbiAgYXdhaXQgcnVuQ29tbWFuZCgnZ2l0IGNvbmZpZyB1c2VyLm5hbWUgXCJkZWNhZlwiJykucHJvbWlzZTtcbiAgbG9nLmluZm8oXCJQdXNoaW5nIGNoYW5nZXMgdG8gZ2l0Li4uXCIpO1xuICBhd2FpdCBydW5Db21tYW5kKFwiZ2l0IGFkZCAuXCIpLnByb21pc2U7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoYGdpdCBjb21taXQgLW0gXCJyZWZzICMxIC0gYWZ0ZXIgcmVwbyBzZXR1cFwiYCkucHJvbWlzZTtcbiAgYXdhaXQgcnVuQ29tbWFuZChcImdpdCBwdXNoXCIpLnByb21pc2U7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoYGdpdCBjb25maWcgdXNlci5lbWFpbCBcIiR7Z2l0RW1haWx9XCJgKS5wcm9taXNlO1xuICBhd2FpdCBydW5Db21tYW5kKGBnaXQgY29uZmlnIHVzZXIubmFtZSBcIiR7Z2l0VXNlcn1cImApLnByb21pc2U7XG4gIGxvZy52ZXJib3NlKGByZXZlcnRlZCB0byBnaXQgaWQ6ICR7Z2l0VXNlcn0vJHtnaXRFbWFpbH1gKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSW5zdGFsbHMgcHJvamVjdCBkZXBlbmRlbmNpZXMuXG4gKiBAc3VtbWFyeSBJbnN0YWxscyBwcm9kdWN0aW9uLCBkZXZlbG9wbWVudCwgYW5kIHBlZXIgZGVwZW5kZW5jaWVzIGFzIHNwZWNpZmllZC5cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gZGVwZW5kZW5jaWVzIC0gT2JqZWN0IGNvbnRhaW5pbmcgYXJyYXlzIG9mIGRlcGVuZGVuY2llcyB0byBpbnN0YWxsLlxuICogQHBhcmFtIHtzdHJpbmdbXX0gW2RlcGVuZGVuY2llcy5wcm9kXSAtIFByb2R1Y3Rpb24gZGVwZW5kZW5jaWVzIHRvIGluc3RhbGwuXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBbZGVwZW5kZW5jaWVzLmRldl0gLSBEZXZlbG9wbWVudCBkZXBlbmRlbmNpZXMgdG8gaW5zdGFsbC5cbiAqIEBwYXJhbSB7c3RyaW5nW119IFtkZXBlbmRlbmNpZXMucGVlcl0gLSBQZWVyIGRlcGVuZGVuY2llcyB0byBpbnN0YWxsLlxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgZGVwZW5kZW5jaWVzIGFyZSBpbnN0YWxsZWQuXG4gKlxuICogQGZ1bmN0aW9uIGluc3RhbGxEZXBlbmRlbmNpZXNcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnN0YWxsRGVwZW5kZW5jaWVzKGRlcGVuZGVuY2llczoge1xuICBwcm9kPzogc3RyaW5nW107XG4gIGRldj86IHN0cmluZ1tdO1xuICBwZWVyPzogc3RyaW5nW107XG59KSB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IoaW5zdGFsbERlcGVuZGVuY2llcyk7XG4gIGNvbnN0IHByb2QgPSBkZXBlbmRlbmNpZXMucHJvZCB8fCBbXTtcbiAgY29uc3QgZGV2ID0gZGVwZW5kZW5jaWVzLmRldiB8fCBbXTtcbiAgY29uc3QgcGVlciA9IGRlcGVuZGVuY2llcy5wZWVyIHx8IFtdO1xuICBpZiAocHJvZC5sZW5ndGgpIHtcbiAgICBsb2cuaW5mbyhgSW5zdGFsbGluZyBkZXBlbmRlbmNpZXMgJHtwcm9kLmpvaW4oXCIsIFwiKX0uLi5gKTtcbiAgICBhd2FpdCBydW5Db21tYW5kKGBucG0gaW5zdGFsbCAke3Byb2Quam9pbihcIiBcIil9YCwgeyBjd2Q6IHByb2Nlc3MuY3dkKCkgfSlcbiAgICAgIC5wcm9taXNlO1xuICB9XG4gIGlmIChkZXYubGVuZ3RoKSB7XG4gICAgbG9nLmluZm8oYEluc3RhbGxpbmcgZGV2RGVwZW5kZW5jaWVzICR7ZGV2LmpvaW4oXCIsIFwiKX0uLi5gKTtcbiAgICBhd2FpdCBydW5Db21tYW5kKGBucG0gaW5zdGFsbCAtLXNhdmUtZGV2ICR7ZGV2LmpvaW4oXCIgXCIpfWAsIHtcbiAgICAgIGN3ZDogcHJvY2Vzcy5jd2QoKSxcbiAgICB9KS5wcm9taXNlO1xuICB9XG4gIGlmIChwZWVyLmxlbmd0aCkge1xuICAgIGxvZy5pbmZvKGBJbnN0YWxsaW5nIHBlZXJEZXBlbmRlbmNpZXMgJHtwZWVyLmpvaW4oXCIsIFwiKX0uLi5gKTtcbiAgICBhd2FpdCBydW5Db21tYW5kKGBucG0gaW5zdGFsbCAtLXNhdmUtcGVlciAke3BlZXIuam9pbihcIiBcIil9YCwge1xuICAgICAgY3dkOiBwcm9jZXNzLmN3ZCgpLFxuICAgIH0pLnByb21pc2U7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTm9ybWFsaXplcyBpbXBvcnRzIHRvIGhhbmRsZSBib3RoIENvbW1vbkpTIGFuZCBFU01vZHVsZSBmb3JtYXRzLlxuICogQHN1bW1hcnkgVXRpbGl0eSBmdW5jdGlvbiB0byBoYW5kbGUgbW9kdWxlIGltcG9ydCBkaWZmZXJlbmNlcyBiZXR3ZWVuIGZvcm1hdHMuXG4gKlxuICogQHRlbXBsYXRlIFQgLSBUeXBlIG9mIHRoZSBpbXBvcnRlZCBtb2R1bGUuXG4gKiBAcGFyYW0ge1Byb21pc2U8VD59IGltcG9ydFByb21pc2UgLSBQcm9taXNlIHJldHVybmVkIGJ5IGR5bmFtaWMgaW1wb3J0LlxuICogQHJldHVybiB7UHJvbWlzZTxUPn0gTm9ybWFsaXplZCBtb2R1bGUuXG4gKlxuICogQGZ1bmN0aW9uIG5vcm1hbGl6ZUltcG9ydFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG5vcm1hbGl6ZUltcG9ydDxUPihcbiAgaW1wb3J0UHJvbWlzZTogUHJvbWlzZTxUPlxuKTogUHJvbWlzZTxUPiB7XG4gIC8vIENvbW1vbkpTJ3MgYG1vZHVsZS5leHBvcnRzYCBpcyB3cmFwcGVkIGFzIGBkZWZhdWx0YCBpbiBFU01vZHVsZS5cbiAgcmV0dXJuIGltcG9ydFByb21pc2UudGhlbigobTogYW55KSA9PiAobS5kZWZhdWx0IHx8IG0pIGFzIFQpO1xufVxuXG4vLyBOZXcgaGVscGVyOiBjb21wdXRlIGd6aXBwZWQgc2l6ZSBvZiBzbWFsbGVzdCBKUyBmaWxlIGluIGEgZGlyZWN0b3J5XG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0RmlsZVNpemVaaXBwZWQoZGlyOiBzdHJpbmcpOiBQcm9taXNlPG51bWJlcj4ge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKGdldEZpbGVTaXplWmlwcGVkKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBlbnRyaWVzID0gZnMucmVhZGRpclN5bmMoZGlyKTtcbiAgICBjb25zdCBjYW5kaWRhdGVzID0gZW50cmllc1xuICAgICAgLm1hcCgoZSkgPT4gcGF0aC5qb2luKGRpciwgZSkpXG4gICAgICAuZmlsdGVyKChwKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcyA9IGZzLnN0YXRTeW5jKHApO1xuICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBzLmlzRmlsZSgpICYmXG4gICAgICAgICAgICAocC5lbmRzV2l0aChcIi5qc1wiKSB8fCBwLmVuZHNXaXRoKFwiLmNqc1wiKSB8fCBwLmVuZHNXaXRoKFwiLm1qc1wiKSlcbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgaWYgKGNhbmRpZGF0ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIEpTIGZpbGVzIGZvdW5kIGluIGRpcmVjdG9yeSAke2Rpcn1gKTtcbiAgICB9XG5cbiAgICAvLyBjaG9vc2UgdGhlIHNtYWxsZXN0IGJ5IHJhdyBmaWxlIHNpemVcbiAgICBsZXQgc21hbGxlc3QgPSBjYW5kaWRhdGVzWzBdO1xuICAgIGxldCBzbWFsbGVzdFNpemUgPSBmcy5zdGF0U3luYyhzbWFsbGVzdCkuc2l6ZTtcbiAgICBmb3IgKGNvbnN0IGMgb2YgY2FuZGlkYXRlcy5zbGljZSgxKSkge1xuICAgICAgY29uc3QgcyA9IGZzLnN0YXRTeW5jKGMpLnNpemU7XG4gICAgICBpZiAocyA8IHNtYWxsZXN0U2l6ZSkge1xuICAgICAgICBzbWFsbGVzdCA9IGM7XG4gICAgICAgIHNtYWxsZXN0U2l6ZSA9IHM7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgU2VsZWN0ZWQgc21hbGxlc3QgYnVuZGxlOiAke3NtYWxsZXN0fSAoJHtzbWFsbGVzdFNpemV9IGJ5dGVzKWBcbiAgICApO1xuXG4gICAgY29uc3QgYnVmZmVyID0gZnMucmVhZEZpbGVTeW5jKHNtYWxsZXN0KTtcbiAgICBjb25zdCBneiA9IHpsaWIuZ3ppcFN5bmMoYnVmZmVyKTtcbiAgICBjb25zdCBzaXplS2IgPSBOdW1iZXIoKGd6Lmxlbmd0aCAvIDEwMjQpLnRvRml4ZWQoMSkpO1xuICAgIGxvZy52ZXJib3NlKGBHemlwcGVkIHNpemU6ICR7Z3oubGVuZ3RofSBieXRlcyAoJHtzaXplS2J9IEtCKWApO1xuICAgIHJldHVybiBzaXplS2I7XG4gIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShgRmFpbGVkIHRvIGNvbXB1dGUgZ3ppcHBlZCBzaXplIGZvciAke2Rpcn06ICR7ZX1gKTtcbiAgICB0aHJvdyBlIGFzIEVycm9yO1xuICB9XG59XG5cbi8vIE5ldyBoZWxwZXI6IGxpc3QgZm9sZGVyIGVudHJpZXMgKG5hbWVzKSB3aXRoIG9wdGlvbmFsIGZpbHRlclxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RGb2xkZXIoXG4gIGJhc2VQYXRoOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpLFxuICBmaWx0ZXI/OiAobmFtZTogc3RyaW5nLCBkaXJlbnQ6IGZzLkRpcmVudCkgPT4gYm9vbGVhblxuKTogc3RyaW5nW10ge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKGxpc3RGb2xkZXIpO1xuICB0cnkge1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhiYXNlUGF0aCkpIHJldHVybiBbXTtcbiAgICBjb25zdCBlbnRyaWVzID0gZnMucmVhZGRpclN5bmMoYmFzZVBhdGgsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KTtcbiAgICBjb25zdCBuYW1lcyA9IGVudHJpZXNcbiAgICAgIC5maWx0ZXIoKGQpID0+IChmaWx0ZXIgPyBmaWx0ZXIoZC5uYW1lLCBkKSA6IHRydWUpKVxuICAgICAgLm1hcCgoZCkgPT4gZC5uYW1lKTtcbiAgICByZXR1cm4gbmFtZXM7XG4gIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShgRmFpbGVkIHRvIGxpc3QgZm9sZGVyICR7YmFzZVBhdGh9OiAke2V9YCk7XG4gICAgcmV0dXJuIFtdO1xuICB9XG59XG5cbi8vIE5ldyBoZWxwZXI6IGxpc3Qgbm9kZV9tb2R1bGVzIHBhY2thZ2UgbmFtZXMsIGV4cGFuZGluZyBzY29wZWQgcGFja2FnZXNcbmV4cG9ydCBmdW5jdGlvbiBsaXN0Tm9kZU1vZHVsZXNQYWNrYWdlcyhcbiAgYmFzZVBhdGg6IHN0cmluZyA9IHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBcIm5vZGVfbW9kdWxlc1wiKVxuKTogc3RyaW5nW10ge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKGxpc3ROb2RlTW9kdWxlc1BhY2thZ2VzKTtcbiAgdHJ5IHtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoYmFzZVBhdGgpKSByZXR1cm4gW107XG4gICAgY29uc3QgZW50cmllcyA9IGZzLnJlYWRkaXJTeW5jKGJhc2VQYXRoLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gICAgY29uc3QgbmFtZXM6IHN0cmluZ1tdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IGUgb2YgZW50cmllcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKCFlLmlzRGlyZWN0b3J5KCkpIGNvbnRpbnVlO1xuICAgICAgICAvLyBpZ25vcmUgaGlkZGVuIGZvbGRlcnNcbiAgICAgICAgaWYgKGUubmFtZS5zdGFydHNXaXRoKFwiLlwiKSkgY29udGludWU7XG4gICAgICAgIGlmIChlLm5hbWUuc3RhcnRzV2l0aChcIkBcIikpIHtcbiAgICAgICAgICAvLyBhIHNjb3BlIGZvbGRlcjsgZXhwYW5kIGNvbnRhaW5lZCBwYWNrYWdlc1xuICAgICAgICAgIGNvbnN0IHNjb3BlUGF0aCA9IHBhdGguam9pbihiYXNlUGF0aCwgZS5uYW1lKTtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qgc2NvcGVkID0gZnMucmVhZGRpclN5bmMoc2NvcGVQYXRoLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHMgb2Ygc2NvcGVkKSB7XG4gICAgICAgICAgICAgIGlmIChzLmlzRGlyZWN0b3J5KCkgJiYgIXMubmFtZS5zdGFydHNXaXRoKFwiLlwiKSkge1xuICAgICAgICAgICAgICAgIG5hbWVzLnB1c2goYCR7ZS5uYW1lfS8ke3MubmFtZX1gKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgLy8gaWdub3JlIHNjb3BlIHJlYWQgZXJyb3JzXG4gICAgICAgICAgICBsb2cudmVyYm9zZShgRmFpbGVkIHRvIHJlYWQgc2NvcGUgJHtzY29wZVBhdGh9OiAke2Vycn1gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbmFtZXMucHVzaChlLm5hbWUpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgbG9nLnZlcmJvc2UoYFNraXBwaW5nIGVudHJ5ICR7ZS5uYW1lfSBkdWUgdG8gZXJyb3I6ICR7ZXJyfWApO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbmFtZXM7XG4gIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShgRmFpbGVkIHRvIGxpc3Qgbm9kZV9tb2R1bGVzIHBhY2thZ2VzIGF0ICR7YmFzZVBhdGh9OiAke2V9YCk7XG4gICAgcmV0dXJuIFtdO1xuICB9XG59XG4iLCIvKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZpbml0aW9uIG9mIGEgc2xvZ2FuIGl0ZW0uXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgc2luZ2xlIHNsb2dhbiBlbnRyeSB3aXRoIHRleHQgYW5kIHRhZ3MuXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBTbG9nYW5JdGVtXG4gKiBAcHJvcGVydHkge3N0cmluZ30gU2xvZ2FuIC0gVGhlIHNsb2dhbiB0ZXh0LlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFRhZ3MgLSBDb21tYS1zZXBhcmF0ZWQgdGFncyBkZXNjcmliaW5nIHRoZSBzbG9nYW4uXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gTGlzdCBvZiBhdmFpbGFibGUgc2xvZ2FucyBmb3IgYmFubmVycyBhbmQgbWVzc2FnZXMuXG4gKiBAc3VtbWFyeSBJbW11dGFibGUgYXJyYXkgb2Ygc2xvZ2FuIGVudHJpZXMgdXNlZCBieSB7QGxpbmsgZ2V0U2xvZ2FufSBhbmQgYmFubmVyIHJlbmRlcmluZy5cbiAqIEB0eXBlIHtTbG9nYW5JdGVtW119XG4gKiBAY29uc3Qgc2xvZ2Fuc1xuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgY29uc3Qgc2xvZ2FucyA9IFtcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdCdzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXRcXHUyMDE5cyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0XFx1MjAxOXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdFxcdTIwMTlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXRcXHUyMDE5cyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0XFx1MjAxOXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdFxcdTIwMTlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXRcXHUyMDE5cyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0XFx1MjAxOXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdFxcdTIwMTlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IFdoZXJlIHNtYXJ0IGNvbnRyYWN0cyBtZWV0IHNtYXJ0IGludGVyZmFjZXMuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBTbWFydCBDb250cmFjdHMsIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaGlwIGRBcHBzIHdpdGhvdXQgdGhlIHN0cmVzcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIENoZWVyZnVsLCBEZXZlbG9wZXJcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBDUlVELCBubyBwcm9ibGVtIFxcdTIwMTQgRGVjYWYgeW91ciBkYXRhLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSwgTm8tQ1JVRCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIERJRCB0byBVSSwgd2l0aG91dCBicmVha2luZyBhIHN3ZWF0LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTU0ksIFVJLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IFlvdXIgZnJvbnRlbmQgYWxyZWFkeSB1bmRlcnN0YW5kcyB5b3VyIHNtYXJ0IGNvbnRyYWN0LlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBEWCwgTWFnaWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTZWxmLXNvdmVyZWlnbiBieSBkZXNpZ24uIFByb2R1Y3RpdmUgYnkgZGVmYXVsdC5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGV2ZWxvcGVyLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnVpbGQgb25jZS4gRGVwbG95IGV2ZXJ5d2hlcmUuIERlY2VudHJhbGl6ZWQgYW5kIGRlbGlnaHRmdWwuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBNdWx0aS1wbGF0Zm9ybSwgSGFwcHlcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEYXRhIHRoYXQgZGVmaW5lcyBpdHMgb3duIGRlc3RpbnkuXCIsXG4gICAgVGFnczogXCJTU0ksIERhdGEtZHJpdmVuLCBFbXBvd2VybWVudFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkdvb2RieWUgQ1JVRCwgaGVsbG8gaW50ZW50LWJhc2VkIGludGVyZmFjZXMuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBVSSwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIHNtb290aGVzdCBwYXRoIGZyb20gRElEIHRvIGRvbmUuXCIsXG4gICAgVGFnczogXCJESUQsIFdvcmtmbG93LCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJlY2F1c2UgeW91ciBkQXBwIGRlc2VydmVzIG1vcmUgdGhhbiBib2lsZXJwbGF0ZS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIERldlgsIEVmZmljaWVuY3lcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJPd24geW91ciBkYXRhLiBPd24geW91ciBmbG93LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBDb250cm9sLCBPd25lcnNoaXBcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJXcml0ZSBsb2dpYyBsaWtlIGl0IGJlbG9uZ3Mgd2l0aCB0aGUgZGF0YSBcXHUyMDE0IGJlY2F1c2UgaXQgZG9lcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIERldmVsb3BlciwgU21hcnRcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIHNtYXJ0IGNvbnRyYWN0cyB0byBzbWFydGVyIGZyb250ZW5kcy5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgVUksIERYXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUuIE5vIENSVUQuIEp1c3QgdGhlIGZ1dHVyZS5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIENvZmZlZS10aGVtZWQsIEZ1dHVyaXN0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgZnV0dXJlIG9mIHdlYjMgVVggaXMgRGVjYWYuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBVWCwgVmlzaW9uXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRoIGNvbmZpZGVuY2UuIEdvdmVybiB3aXRoIGNsYXJpdHkuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBHb3Zlcm5hbmNlLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiSW50ZXJmYWNlcyB0aGF0IG9iZXkgdGhlIGRhdGEsIG5vdCB0aGUgb3RoZXIgd2F5IGFyb3VuZC5cIixcbiAgICBUYWdzOiBcIlVJLCBEYXRhIExvZ2ljLCBTZWxmLWF3YXJlXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnJldyBidXNpbmVzcyBsb2dpYyByaWdodCBpbnRvIHlvdXIgYnl0ZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJESURzIGRvbmUgZGlmZmVyZW50bHkgXFx1MjAxNCBhbmQgZGVsaWdodGZ1bGx5LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTZWxmLVNvdmVyZWlnbiwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTLVRTOiBXaGVyZSBibG9ja2NoYWluIGNvbnRyYWN0cyBtZWV0IHNtYXJ0IGludGVyZmFjZXMuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBTbWFydCBDb250cmFjdHMsIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaGlwIGRBcHBzIHdpdGhvdXQgdGhlIHN0cmVzcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIENoZWVyZnVsLCBEZXZlbG9wZXJcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBib2lsZXJwbGF0ZSwgbm8gcHJvYmxlbSBcXHUyMDE0IERlY2FmLVRTIHlvdXIgZGF0YS5cIixcbiAgICBUYWdzOiBcIkRhdGEsIE5vLUNSVUQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBESUQgdG8gVUksIHdpdGhvdXQgYnJlYWtpbmcgYSBzd2VhdC5cIixcbiAgICBUYWdzOiBcIkRJRCwgU1NJLCBVSSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOlxuICAgICAgXCJEZWNhZi1UUy1UUzogWW91ciBmcm9udGVuZCBhbHJlYWR5IHVuZGVyc3RhbmRzIHlvdXIgYmxvY2tjaGFpbiBjb250cmFjdC5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgRFgsIE1hZ2ljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2VsZi1zb3ZlcmVpZ24gYnkgZGVzaWduLiBQcm9kdWN0aXZlIGJ5IGRlZmF1bHQuXCIsXG4gICAgVGFnczogXCJTU0ksIERldmVsb3BlciwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJ1aWxkIG9uY2UuIERlcGxveSBldmVyeXdoZXJlLiBEZWNlbnRyYWxpemVkIGFuZCBkZWxpZ2h0ZnVsLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgTXVsdGktcGxhdGZvcm0sIEhhcHB5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGF0YSB0aGF0IGRlZmluZXMgaXRzIG93biBkZXN0aW55LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEYXRhLWRyaXZlbiwgRW1wb3dlcm1lbnRcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJHb29kYnllIGJvaWxlcnBsYXRlLCBoZWxsbyBpbnRlbnQtYmFzZWQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIFVJLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgc21vb3RoZXN0IHBhdGggZnJvbSBESUQgdG8gZG9uZS5cIixcbiAgICBUYWdzOiBcIkRJRCwgV29ya2Zsb3csIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQmVjYXVzZSB5b3VyIGRBcHAgZGVzZXJ2ZXMgbW9yZSB0aGFuIGJvaWxlcnBsYXRlLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgRGV2WCwgRWZmaWNpZW5jeVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk93biB5b3VyIGRhdGEuIE93biB5b3VyIGZsb3cuXCIsXG4gICAgVGFnczogXCJTU0ksIENvbnRyb2wsIE93bmVyc2hpcFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIldyaXRlIGxvZ2ljIGxpa2UgaXQgYmVsb25ncyB3aXRoIHRoZSBkYXRhIFxcdTIwMTQgYmVjYXVzZSBpdCBkb2VzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgRGV2ZWxvcGVyLCBTbWFydFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gYmxvY2tjaGFpbiBjb250cmFjdHMgdG8gc21hcnRlciBmcm9udGVuZHMuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIFVJLCBEWFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLiBObyBib2lsZXJwbGF0ZS4gSnVzdCB0aGUgZnV0dXJlLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgQ29mZmVlLXRoZW1lZCwgRnV0dXJpc3RpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBmdXR1cmUgb2Ygd2ViMyBVWCBpcyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFVYLCBWaXNpb25cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGggY29uZmlkZW5jZS4gR292ZXJuIHdpdGggY2xhcml0eS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIEdvdmVybmFuY2UsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJJbnRlcmZhY2VzIHRoYXQgb2JleSB0aGUgZGF0YSwgbm90IHRoZSBvdGhlciB3YXkgYXJvdW5kLlwiLFxuICAgIFRhZ3M6IFwiVUksIERhdGEgTG9naWMsIFNlbGYtYXdhcmVcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCcmV3IGJ1c2luZXNzIGxvZ2ljIHJpZ2h0IGludG8geW91ciBieXRlcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIENvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRJRHMgZG9uZSBkaWZmZXJlbnRseSBcXHUyMDE0IGFuZCBkZWxpZ2h0ZnVsbHkuXCIsXG4gICAgVGFnczogXCJESUQsIFNlbGYtU292ZXJlaWduLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFMtVFM6IFdoZXJlIGJsb2NrY2hhaW4gY29udHJhY3RzIG1lZXQgc21hcnQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFNtYXJ0IENvbnRyYWN0cywgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNoaXAgZEFwcHMgd2l0aG91dCB0aGUgc3RyZXNzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgQ2hlZXJmdWwsIERldmVsb3BlclwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGJvaWxlcnBsYXRlLCBubyBwcm9ibGVtIFxcdTIwMTQgRGVjYWYtVFMgeW91ciBkYXRhLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSwgTm8tQ1JVRCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIERJRCB0byBVSSwgd2l0aG91dCBicmVha2luZyBhIHN3ZWF0LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTU0ksIFVJLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46XG4gICAgICBcIkRlY2FmLVRTLVRTOiBZb3VyIGZyb250ZW5kIGFscmVhZHkgdW5kZXJzdGFuZHMgeW91ciBibG9ja2NoYWluIGNvbnRyYWN0LlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBEWCwgTWFnaWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTZWxmLXNvdmVyZWlnbiBieSBkZXNpZ24uIFByb2R1Y3RpdmUgYnkgZGVmYXVsdC5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGV2ZWxvcGVyLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnVpbGQgb25jZS4gRGVwbG95IGV2ZXJ5d2hlcmUuIERlY2VudHJhbGl6ZWQgYW5kIGRlbGlnaHRmdWwuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBNdWx0aS1wbGF0Zm9ybSwgSGFwcHlcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEYXRhIHRoYXQgZGVmaW5lcyBpdHMgb3duIGRlc3RpbnkuXCIsXG4gICAgVGFnczogXCJTU0ksIERhdGEtZHJpdmVuLCBFbXBvd2VybWVudFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkdvb2RieWUgYm9pbGVycGxhdGUsIGhlbGxvIGludGVudC1iYXNlZCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgVUksIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBzbW9vdGhlc3QgcGF0aCBmcm9tIERJRCB0byBkb25lLlwiLFxuICAgIFRhZ3M6IFwiRElELCBXb3JrZmxvdywgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCZWNhdXNlIHlvdXIgZEFwcCBkZXNlcnZlcyBtb3JlIHRoYW4gYm9pbGVycGxhdGUuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBEZXZYLCBFZmZpY2llbmN5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiT3duIHlvdXIgZGF0YS4gT3duIHlvdXIgZmxvdy5cIixcbiAgICBUYWdzOiBcIlNTSSwgQ29udHJvbCwgT3duZXJzaGlwXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiV3JpdGUgbG9naWMgbGlrZSBpdCBiZWxvbmdzIHdpdGggdGhlIGRhdGEgXFx1MjAxNCBiZWNhdXNlIGl0IGRvZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBEZXZlbG9wZXIsIFNtYXJ0XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBibG9ja2NoYWluIGNvbnRyYWN0cyB0byBzbWFydGVyIGZyb250ZW5kcy5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgVUksIERYXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUuIE5vIGJvaWxlcnBsYXRlLiBKdXN0IHRoZSBmdXR1cmUuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBDb2ZmZWUtdGhlbWVkLCBGdXR1cmlzdGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIGZ1dHVyZSBvZiB3ZWIzIFVYIGlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgVVgsIFZpc2lvblwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aCBjb25maWRlbmNlLiBHb3Zlcm4gd2l0aCBjbGFyaXR5LlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgR292ZXJuYW5jZSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkludGVyZmFjZXMgdGhhdCBvYmV5IHRoZSBkYXRhLCBub3QgdGhlIG90aGVyIHdheSBhcm91bmQuXCIsXG4gICAgVGFnczogXCJVSSwgRGF0YSBMb2dpYywgU2VsZi1hd2FyZVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJyZXcgYnVzaW5lc3MgbG9naWMgcmlnaHQgaW50byB5b3VyIGJ5dGVzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRElEcyBkb25lIGRpZmZlcmVudGx5IFxcdTIwMTQgYW5kIGRlbGlnaHRmdWxseS5cIixcbiAgICBUYWdzOiBcIkRJRCwgU2VsZi1Tb3ZlcmVpZ24sIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUy1UUzogV2hlcmUgYmxvY2tjaGFpbiBjb250cmFjdHMgbWVldCBzbWFydCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgU21hcnQgQ29udHJhY3RzLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2hpcCBkQXBwcyB3aXRob3V0IHRoZSBzdHJlc3MuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBDaGVlcmZ1bCwgRGV2ZWxvcGVyXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gYm9pbGVycGxhdGUsIG5vIHByb2JsZW0gXFx1MjAxNCBEZWNhZi1UUyB5b3VyIGRhdGEuXCIsXG4gICAgVGFnczogXCJEYXRhLCBOby1DUlVELCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gRElEIHRvIFVJLCB3aXRob3V0IGJyZWFraW5nIGEgc3dlYXQuXCIsXG4gICAgVGFnczogXCJESUQsIFNTSSwgVUksIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjpcbiAgICAgIFwiRGVjYWYtVFMtVFM6IFlvdXIgZnJvbnRlbmQgYWxyZWFkeSB1bmRlcnN0YW5kcyB5b3VyIGJsb2NrY2hhaW4gY29udHJhY3QuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIERYLCBNYWdpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNlbGYtc292ZXJlaWduIGJ5IGRlc2lnbi4gUHJvZHVjdGl2ZSBieSBkZWZhdWx0LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEZXZlbG9wZXIsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCdWlsZCBvbmNlLiBEZXBsb3kgZXZlcnl3aGVyZS4gRGVjZW50cmFsaXplZCBhbmQgZGVsaWdodGZ1bC5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIE11bHRpLXBsYXRmb3JtLCBIYXBweVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRhdGEgdGhhdCBkZWZpbmVzIGl0cyBvd24gZGVzdGlueS5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGF0YS1kcml2ZW4sIEVtcG93ZXJtZW50XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiR29vZGJ5ZSBib2lsZXJwbGF0ZSwgaGVsbG8gaW50ZW50LWJhc2VkIGludGVyZmFjZXMuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBVSSwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIHNtb290aGVzdCBwYXRoIGZyb20gRElEIHRvIGRvbmUuXCIsXG4gICAgVGFnczogXCJESUQsIFdvcmtmbG93LCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJlY2F1c2UgeW91ciBkQXBwIGRlc2VydmVzIG1vcmUgdGhhbiBib2lsZXJwbGF0ZS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIERldlgsIEVmZmljaWVuY3lcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJPd24geW91ciBkYXRhLiBPd24geW91ciBmbG93LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBDb250cm9sLCBPd25lcnNoaXBcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJXcml0ZSBsb2dpYyBsaWtlIGl0IGJlbG9uZ3Mgd2l0aCB0aGUgZGF0YSBcXHUyMDE0IGJlY2F1c2UgaXQgZG9lcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIERldmVsb3BlciwgU21hcnRcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIGJsb2NrY2hhaW4gY29udHJhY3RzIHRvIHNtYXJ0ZXIgZnJvbnRlbmRzLlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBVSSwgRFhcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZS4gTm8gYm9pbGVycGxhdGUuIEp1c3QgdGhlIGZ1dHVyZS5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIENvZmZlZS10aGVtZWQsIEZ1dHVyaXN0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgZnV0dXJlIG9mIHdlYjMgVVggaXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBVWCwgVmlzaW9uXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRoIGNvbmZpZGVuY2UuIEdvdmVybiB3aXRoIGNsYXJpdHkuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBHb3Zlcm5hbmNlLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiSW50ZXJmYWNlcyB0aGF0IG9iZXkgdGhlIGRhdGEsIG5vdCB0aGUgb3RoZXIgd2F5IGFyb3VuZC5cIixcbiAgICBUYWdzOiBcIlVJLCBEYXRhIExvZ2ljLCBTZWxmLWF3YXJlXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnJldyBidXNpbmVzcyBsb2dpYyByaWdodCBpbnRvIHlvdXIgYnl0ZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJESURzIGRvbmUgZGlmZmVyZW50bHkgXFx1MjAxNCBhbmQgZGVsaWdodGZ1bGx5LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTZWxmLVNvdmVyZWlnbiwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTLVRTOiBXaGVyZSBibG9ja2NoYWluIGNvbnRyYWN0cyBtZWV0IHNtYXJ0IGludGVyZmFjZXMuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBTbWFydCBDb250cmFjdHMsIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaGlwIGRBcHBzIHdpdGhvdXQgdGhlIHN0cmVzcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIENoZWVyZnVsLCBEZXZlbG9wZXJcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBib2lsZXJwbGF0ZSwgbm8gcHJvYmxlbSBcXHUyMDE0IERlY2FmLVRTIHlvdXIgZGF0YS5cIixcbiAgICBUYWdzOiBcIkRhdGEsIE5vLUNSVUQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBESUQgdG8gVUksIHdpdGhvdXQgYnJlYWtpbmcgYSBzd2VhdC5cIixcbiAgICBUYWdzOiBcIkRJRCwgU1NJLCBVSSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOlxuICAgICAgXCJEZWNhZi1UUy1UUzogWW91ciBmcm9udGVuZCBhbHJlYWR5IHVuZGVyc3RhbmRzIHlvdXIgYmxvY2tjaGFpbiBjb250cmFjdC5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgRFgsIE1hZ2ljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2VsZi1zb3ZlcmVpZ24gYnkgZGVzaWduLiBQcm9kdWN0aXZlIGJ5IGRlZmF1bHQuXCIsXG4gICAgVGFnczogXCJTU0ksIERldmVsb3BlciwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJ1aWxkIG9uY2UuIERlcGxveSBldmVyeXdoZXJlLiBEZWNlbnRyYWxpemVkIGFuZCBkZWxpZ2h0ZnVsLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgTXVsdGktcGxhdGZvcm0sIEhhcHB5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGF0YSB0aGF0IGRlZmluZXMgaXRzIG93biBkZXN0aW55LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEYXRhLWRyaXZlbiwgRW1wb3dlcm1lbnRcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJHb29kYnllIGJvaWxlcnBsYXRlLCBoZWxsbyBpbnRlbnQtYmFzZWQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIFVJLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgc21vb3RoZXN0IHBhdGggZnJvbSBESUQgdG8gZG9uZS5cIixcbiAgICBUYWdzOiBcIkRJRCwgV29ya2Zsb3csIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQmVjYXVzZSB5b3VyIGRBcHAgZGVzZXJ2ZXMgbW9yZSB0aGFuIGJvaWxlcnBsYXRlLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgRGV2WCwgRWZmaWNpZW5jeVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk93biB5b3VyIGRhdGEuIE93biB5b3VyIGZsb3cuXCIsXG4gICAgVGFnczogXCJTU0ksIENvbnRyb2wsIE93bmVyc2hpcFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIldyaXRlIGxvZ2ljIGxpa2UgaXQgYmVsb25ncyB3aXRoIHRoZSBkYXRhIFxcdTIwMTQgYmVjYXVzZSBpdCBkb2VzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgRGV2ZWxvcGVyLCBTbWFydFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gYmxvY2tjaGFpbiBjb250cmFjdHMgdG8gc21hcnRlciBmcm9udGVuZHMuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIFVJLCBEWFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLiBObyBib2lsZXJwbGF0ZS4gSnVzdCB0aGUgZnV0dXJlLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgQ29mZmVlLXRoZW1lZCwgRnV0dXJpc3RpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBmdXR1cmUgb2Ygd2ViMyBVWCBpcyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFVYLCBWaXNpb25cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGggY29uZmlkZW5jZS4gR292ZXJuIHdpdGggY2xhcml0eS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIEdvdmVybmFuY2UsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJJbnRlcmZhY2VzIHRoYXQgb2JleSB0aGUgZGF0YSwgbm90IHRoZSBvdGhlciB3YXkgYXJvdW5kLlwiLFxuICAgIFRhZ3M6IFwiVUksIERhdGEgTG9naWMsIFNlbGYtYXdhcmVcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCcmV3IGJ1c2luZXNzIGxvZ2ljIHJpZ2h0IGludG8geW91ciBieXRlcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIENvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRJRHMgZG9uZSBkaWZmZXJlbnRseSBcXHUyMDE0IGFuZCBkZWxpZ2h0ZnVsbHkuXCIsXG4gICAgVGFnczogXCJESUQsIFNlbGYtU292ZXJlaWduLCBQbGF5ZnVsXCIsXG4gIH0sXG5dO1xuIiwiaW1wb3J0IHsgc2xvZ2FucyB9IGZyb20gXCIuLi9hc3NldHMvc2xvZ2Fuc1wiO1xuaW1wb3J0IHsgc3R5bGUgfSBmcm9tIFwic3R5bGVkLXN0cmluZy1idWlsZGVyXCI7XG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQXJyYXkgb2YgQU5TSSBjb2xvciBjb2RlcyBmb3IgYmFubmVyIHN0eWxpbmcuXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgc2V0IG9mIEFOU0kgY29sb3IgY29kZXMgdXNlZCB0byBzdHlsZSB0aGUgYmFubmVyIHRleHQuXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmNvbnN0IGNvbG9ycyA9IFtcbiAgXCJcXHgxYlszODs1OzIxNW1cIiwgLy8gc29mdCBvcmFuZ2VcbiAgXCJcXHgxYlszODs1OzIwOW1cIiwgLy8gY29yYWxcbiAgXCJcXHgxYlszODs1OzIwNW1cIiwgLy8gcGlua1xuICBcIlxceDFiWzM4OzU7MjEwbVwiLCAvLyBwZWFjaHlcbiAgXCJcXHgxYlszODs1OzIxN21cIiwgLy8gc2FsbW9uXG4gIFwiXFx4MWJbMzg7NTsyMTZtXCIsIC8vIGxpZ2h0IGNvcmFsXG4gIFwiXFx4MWJbMzg7NTsyMjRtXCIsIC8vIGxpZ2h0IHBlYWNoXG4gIFwiXFx4MWJbMzg7NTsyMzBtXCIsIC8vIHNvZnQgY3JlYW1cbiAgXCJcXHgxYlszODs1OzIzMG1cIiwgLy8gc29mdCBjcmVhbVxuXTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUHJpbnRzIGEgc3R5bGVkIGJhbm5lciB0byB0aGUgY29uc29sZS5cbiAqIEBzdW1tYXJ5IEdlbmVyYXRlcyBhbmQgcHJpbnRzIGEgY29sb3JmdWwgQVNDSUkgYXJ0IGJhbm5lciB3aXRoIGEgcmFuZG9tIHNsb2dhbi5cbiAqIEBwYXJhbSB7TG9nZ2VyfSBbbG9nZ2VyXSAtIE9wdGlvbmFsIGxvZ2dlciBmb3IgdmVyYm9zZSBvdXRwdXQuXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKiBAZnVuY3Rpb24gcHJpbnRCYW5uZXJcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgcHJpbnRCYW5uZXJcbiAqICAgcGFydGljaXBhbnQgZ2V0U2xvZ2FuXG4gKiAgIHBhcnRpY2lwYW50IHBhZEVuZFxuICogICBwYXJ0aWNpcGFudCBjb25zb2xlXG4gKiAgIHByaW50QmFubmVyLT4+Z2V0U2xvZ2FuOiBDYWxsIGdldFNsb2dhbigpXG4gKiAgIGdldFNsb2dhbi0tPj5wcmludEJhbm5lcjogUmV0dXJuIHJhbmRvbSBzbG9nYW5cbiAqICAgcHJpbnRCYW5uZXItPj5wcmludEJhbm5lcjogQ3JlYXRlIGJhbm5lciBBU0NJSSBhcnRcbiAqICAgcHJpbnRCYW5uZXItPj5wcmludEJhbm5lcjogU3BsaXQgYmFubmVyIGludG8gbGluZXNcbiAqICAgcHJpbnRCYW5uZXItPj5wcmludEJhbm5lcjogQ2FsY3VsYXRlIG1heCBsaW5lIGxlbmd0aFxuICogICBwcmludEJhbm5lci0+PnBhZEVuZDogQ2FsbCBwYWRFbmQgd2l0aCBzbG9nYW5cbiAqICAgcGFkRW5kLS0+PnByaW50QmFubmVyOiBSZXR1cm4gcGFkZGVkIHNsb2dhbiBsaW5lXG4gKiAgIGxvb3AgRm9yIGVhY2ggYmFubmVyIGxpbmVcbiAqICAgICBwcmludEJhbm5lci0+PnN0eWxlOiBDYWxsIHN0eWxlKGxpbmUpXG4gKiAgICAgc3R5bGUtLT4+cHJpbnRCYW5uZXI6IFJldHVybiBzdHlsZWQgbGluZVxuICogICAgIHByaW50QmFubmVyLT4+Y29uc29sZTogTG9nIHN0eWxlZCBsaW5lXG4gKiAgIGVuZFxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJpbnRCYW5uZXIobG9nZ2VyPzogTG9nZ2VyKSB7XG4gIGNvbnN0IG1lc3NhZ2UgPSBnZXRTbG9nYW4oKTtcbiAgY29uc3QgYmFubmVyOiBzdHJpbmcgfCBzdHJpbmdbXSA9XG4gICAgYCMgICAgICAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRICDilpHilpLilpPilojilojilojilojilojilojilpPilpLilpEgICDilpHilpLilpPilojilojilojilojilojilojilpPilpLilpEgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAgICAgICDilpHilpLilpPilojilojilojilojilojilojilojilojilpPilpLilpEgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSBcbiMgICAgICAoICggICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paRICAgICAgICAgICAgICAgICDilpHilpLilpPilojilpPilpLilpEgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAgXG4jICAgICAgICkgKSAgICAgICDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paRICAgICAgICDilpHilpLilpPilojilpPilpLilpEgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAg4paR4paS4paT4paI4paT4paS4paRICAgICAgICBcbiMgICAgWz09PT09PT1dICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilojilojilojilojilojilpPilpLilpEgICDilpHilpLilpPilojilpPilpLilpEgICAgICAgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSDilpHilpLilpPilojilojilojilojilojilojilpPilpLilpEgICAgICAgICAgICDilpHilpLilpPilojilpPilpLilpEgICAgICDilpHilpLilpPilojilojilojilojilojilojilpPilpLilpEgIFxuIyAgICAgXFxgLS0tLS3CtCAgICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAg4paR4paS4paT4paI4paT4paS4paRICAgICAgICDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paRICAgICAgICAgICAgICAgICDilpHilpLilpPilojilpPilpLilpEgICAgICAgICAgICDilpHilpLilpPilojilpPilpLilpEgXG4jICAgICAgICAgICAgICAgICDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paRICAgICAgICDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAgICAgICAgICAg4paR4paS4paT4paI4paT4paS4paRICAgICAgICAgICAg4paR4paS4paT4paI4paT4paS4paRIFxuIyAgICAgICAgICAgICAgICAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRICDilpHilpLilpPilojilojilojilojilojilojilojilojilpPilpLilpEgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAgICAgICAgICAg4paR4paS4paT4paI4paT4paS4paRICAgICDilpHilpLilpPilojilojilojilojilojilojilojilpPilpLilpEgIFxuI2Auc3BsaXQoXCJcXG5cIik7XG4gIGNvbnN0IG1heExlbmd0aCA9IGJhbm5lci5yZWR1Y2UoKG1heCwgbGluZSkgPT4gTWF0aC5tYXgobWF4LCBsaW5lLmxlbmd0aCksIDApO1xuICBiYW5uZXIucHVzaChgIyAgJHttZXNzYWdlLnBhZFN0YXJ0KG1heExlbmd0aCAtIDMpfWApO1xuICBiYW5uZXIuZm9yRWFjaCgobGluZSwgaW5kZXgpID0+IHtcbiAgICAobG9nZ2VyID8gbG9nZ2VyLmluZm8uYmluZChsb2dnZXIpIDogY29uc29sZS5sb2cuYmluZChjb25zb2xlKSkoXG4gICAgICBzdHlsZShsaW5lIHx8IFwiXCIpLnJhdyhjb2xvcnNbaW5kZXhdKS50ZXh0XG4gICAgKTtcbiAgfSk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIHNsb2dhbiBmcm9tIHRoZSBwcmVkZWZpbmVkIGxpc3QuXG4gKiBAc3VtbWFyeSBGZXRjaGVzIGEgcmFuZG9tIHNsb2dhbiBvciBhIHNwZWNpZmljIG9uZSBieSBpbmRleCBmcm9tIHRoZSBzbG9nYW5zIGxpc3QuXG4gKiBAcGFyYW0ge251bWJlcn0gW2ldIC0gT3B0aW9uYWwgaW5kZXggdG8gcmV0cmlldmUgYSBzcGVjaWZpYyBzbG9nYW4uXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBzZWxlY3RlZCBzbG9nYW4uXG4gKiBAZnVuY3Rpb24gZ2V0U2xvZ2FuXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IGdldFNsb2dhblxuICogICBwYXJ0aWNpcGFudCBNYXRoLnJhbmRvbVxuICogICBwYXJ0aWNpcGFudCBzbG9nYW5zXG4gKiAgIGFsdCBpIGlzIHVuZGVmaW5lZFxuICogICAgIGdldFNsb2dhbi0+Pk1hdGgucmFuZG9tOiBHZW5lcmF0ZSByYW5kb20gaW5kZXhcbiAqICAgICBNYXRoLnJhbmRvbS0tPj5nZXRTbG9nYW46IFJldHVybiByYW5kb20gaW5kZXhcbiAqICAgZWxzZSBpIGlzIGRlZmluZWRcbiAqICAgICBOb3RlIG92ZXIgZ2V0U2xvZ2FuOiBVc2UgcHJvdmlkZWQgaW5kZXhcbiAqICAgZW5kXG4gKiAgIGdldFNsb2dhbi0+PnNsb2dhbnM6IEFjY2VzcyBzbG9nYW4gYXQgaW5kZXhcbiAqICAgc2xvZ2Fucy0tPj5nZXRTbG9nYW46IFJldHVybiBzbG9nYW5cbiAqICAgYWx0IEVycm9yIG9jY3Vyc1xuICogICAgIGdldFNsb2dhbi0+PmdldFNsb2dhbjogVGhyb3cgZXJyb3JcbiAqICAgZW5kXG4gKiAgIGdldFNsb2dhbi0tPj5DYWxsZXI6IFJldHVybiBzbG9nYW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFNsb2dhbihpPzogbnVtYmVyKTogc3RyaW5nIHtcbiAgdHJ5IHtcbiAgICBpID1cbiAgICAgIHR5cGVvZiBpID09PSBcInVuZGVmaW5lZFwiID8gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogc2xvZ2Fucy5sZW5ndGgpIDogaTtcbiAgICByZXR1cm4gc2xvZ2Fuc1tpXS5TbG9nYW47XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcmV0cmlldmUgc2xvZ2FuczogJHtlcnJvcn1gKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgUGFyc2VBcmdzUmVzdWx0IH0gZnJvbSBcIi4uL2lucHV0L3R5cGVzXCI7XG5pbXBvcnQgeyBDb21tYW5kT3B0aW9ucyB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBVc2VySW5wdXQgfSBmcm9tIFwiLi4vaW5wdXQvaW5wdXRcIjtcbmltcG9ydCB7IERlZmF1bHRDb21tYW5kT3B0aW9ucywgRGVmYXVsdENvbW1hbmRWYWx1ZXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IGdldERlcGVuZGVuY2llcywgZ2V0UGFja2FnZVZlcnNpb24gfSBmcm9tIFwiLi4vdXRpbHMvZnNcIjtcbmltcG9ydCB7IHByaW50QmFubmVyIH0gZnJvbSBcIi4uL291dHB1dC9jb21tb25cIjtcbmltcG9ydCB7XG4gIExvZ2dlZENsYXNzLFxuICBMb2dnZWRFbnZpcm9ubWVudCxcbiAgTG9nZ2VyLFxuICBMb2dnaW5nLFxuICBMb2dnaW5nQ29uZmlnLFxufSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcblxuLyoqXG4gKiBAY2xhc3MgQ29tbWFuZFxuICogQGFic3RyYWN0XG4gKiBAdGVtcGxhdGUgSSAtIFRoZSB0eXBlIG9mIGlucHV0IG9wdGlvbnMgZm9yIHRoZSBjb21tYW5kLlxuICogQHRlbXBsYXRlIFIgLSBUaGUgcmV0dXJuIHR5cGUgb2YgdGhlIGNvbW1hbmQgZXhlY3V0aW9uLlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICogQGRlc2NyaXB0aW9uIEFic3RyYWN0IGJhc2UgY2xhc3MgZm9yIGNvbW1hbmQgaW1wbGVtZW50YXRpb24uXG4gKiBAc3VtbWFyeSBQcm92aWRlcyBhIHN0cnVjdHVyZSBmb3IgY3JlYXRpbmcgY29tbWFuZC1saW5lIGludGVyZmFjZSBjb21tYW5kcyB3aXRoIGlucHV0IGhhbmRsaW5nLCBsb2dnaW5nLCBhbmQgZXhlY3V0aW9uIGZsb3cuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgY29tbWFuZC5cbiAqIEBwYXJhbSB7Q29tbWFuZE9wdGlvbnM8ST59IFtpbnB1dHNdIC0gVGhlIGlucHV0IG9wdGlvbnMgZm9yIHRoZSBjb21tYW5kLlxuICogQHBhcmFtIHtzdHJpbmdbXX0gW3JlcXVpcmVtZW50c10gLSBUaGUgbGlzdCBvZiByZXF1aXJlZCBkZXBlbmRlbmNpZXMgZm9yIHRoZSBjb21tYW5kLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQ29tbWFuZDxJLCBSPiBleHRlbmRzIExvZ2dlZENsYXNzIHtcbiAgLyoqXG4gICAqIEBzdGF0aWNcbiAgICogQGRlc2NyaXB0aW9uIFN0YXRpYyBsb2dnZXIgZm9yIHRoZSBDb21tYW5kIGNsYXNzLlxuICAgKiBAdHlwZSB7TG9nZ2VyfVxuICAgKi9cbiAgc3RhdGljIGxvZzogTG9nZ2VyO1xuXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgbmFtZTogc3RyaW5nLFxuICAgIHByb3RlY3RlZCBpbnB1dHM6IENvbW1hbmRPcHRpb25zPEk+ID0ge30gYXMgdW5rbm93biBhcyBDb21tYW5kT3B0aW9uczxJPixcbiAgICBwcm90ZWN0ZWQgcmVxdWlyZW1lbnRzOiBzdHJpbmdbXSA9IFtdXG4gICkge1xuICAgIHN1cGVyKCk7XG4gICAgaWYgKCFDb21tYW5kLmxvZykge1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KENvbW1hbmQsIFwibG9nXCIsIHtcbiAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICB2YWx1ZTogTG9nZ2luZy5mb3IoQ29tbWFuZC5uYW1lKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICB0aGlzLmlucHV0cyA9IE9iamVjdC5hc3NpZ24oXG4gICAgICB7fSxcbiAgICAgIERlZmF1bHRDb21tYW5kT3B0aW9ucyxcbiAgICAgIGlucHV0c1xuICAgICkgYXMgQ29tbWFuZE9wdGlvbnM8ST47XG4gIH1cblxuICAvKipcbiAgICogQHByb3RlY3RlZFxuICAgKiBAYXN5bmNcbiAgICogQGRlc2NyaXB0aW9uIENoZWNrcyBpZiBhbGwgcmVxdWlyZWQgZGVwZW5kZW5jaWVzIGFyZSBwcmVzZW50LlxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgdGhlIGxpc3Qgb2YgZGVwZW5kZW5jaWVzIGFuZCBjb21wYXJlcyBpdCBhZ2FpbnN0IHRoZSByZXF1aXJlZCBkZXBlbmRlbmNpZXMgZm9yIHRoZSBjb21tYW5kLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgY2hlY2sgaXMgY29tcGxldGUuXG4gICAqXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IENvbW1hbmRcbiAgICogICBwYXJ0aWNpcGFudCBnZXREZXBlbmRlbmNpZXNcbiAgICogICBwYXJ0aWNpcGFudCBTZXRcbiAgICogICBDb21tYW5kLT4+Z2V0RGVwZW5kZW5jaWVzOiBDYWxsXG4gICAqICAgZ2V0RGVwZW5kZW5jaWVzLS0+PkNvbW1hbmQ6IFJldHVybiB7cHJvZCwgZGV2LCBwZWVyfVxuICAgKiAgIENvbW1hbmQtPj5TZXQ6IENyZWF0ZSBTZXQgZnJvbSBwcm9kLCBkZXYsIHBlZXJcbiAgICogICBTZXQtLT4+Q29tbWFuZDogUmV0dXJuIHVuaXF1ZSBkZXBlbmRlbmNpZXNcbiAgICogICBDb21tYW5kLT4+Q29tbWFuZDogQ29tcGFyZSBhZ2FpbnN0IHJlcXVpcmVtZW50c1xuICAgKiAgIGFsdCBNaXNzaW5nIGRlcGVuZGVuY2llc1xuICAgKiAgICAgQ29tbWFuZC0+PkNvbW1hbmQ6IEFkZCB0byBtaXNzaW5nIGxpc3RcbiAgICogICBlbmRcbiAgICogICBOb3RlIG92ZXIgQ29tbWFuZDogSWYgbWlzc2luZy5sZW5ndGggPiAwLCBoYW5kbGUgbWlzc2luZyBkZXBlbmRlbmNpZXNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBjaGVja1JlcXVpcmVtZW50cygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IHByb2QsIGRldiwgcGVlciB9ID0gYXdhaXQgZ2V0RGVwZW5kZW5jaWVzKCk7XG4gICAgY29uc3QgbWlzc2luZyA9IFtdO1xuICAgIGNvbnN0IGZ1bGxMaXN0ID0gQXJyYXkuZnJvbShcbiAgICAgIG5ldyBTZXQoWy4uLnByb2QsIC4uLmRldiwgLi4ucGVlcl0pLnZhbHVlcygpXG4gICAgKS5tYXAoKGQpID0+IGQubmFtZSk7XG4gICAgZm9yIChjb25zdCBkZXAgb2YgdGhpcy5yZXF1aXJlbWVudHMpXG4gICAgICBpZiAoIWZ1bGxMaXN0LmluY2x1ZGVzKGRlcCkpIG1pc3NpbmcucHVzaChkZXApO1xuXG4gICAgaWYgKCFtaXNzaW5nLmxlbmd0aCkgcmV0dXJuO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm90ZWN0ZWRcbiAgICogQGRlc2NyaXB0aW9uIFByb3ZpZGVzIGhlbHAgaW5mb3JtYXRpb24gZm9yIHRoZSBjb21tYW5kLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBzaG91bGQgYmUgb3ZlcnJpZGRlbiBpbiBkZXJpdmVkIGNsYXNzZXMgdG8gcHJvdmlkZSBzcGVjaWZpYyBoZWxwIGluZm9ybWF0aW9uLlxuICAgKiBAcGFyYW0ge1BhcnNlQXJnc1Jlc3VsdH0gYXJncyAtIFRoZSBwYXJzZWQgY29tbWFuZC1saW5lIGFyZ3VtZW50cy5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIHByb3RlY3RlZCBoZWxwKGFyZ3M6IFBhcnNlQXJnc1Jlc3VsdCk6IHZvaWQge1xuICAgIHJldHVybiB0aGlzLmxvZy5pbmZvKFxuICAgICAgYFRoaXMgaXMgaGVscC4gSSdtIG5vIHVzZSBiZWNhdXNlIEkgc2hvdWxkIGhhdmUgYmVlbiBvdmVycmlkZGVuLmBcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm90ZWN0ZWRcbiAgICogQGFic3RyYWN0XG4gICAqIEBkZXNjcmlwdGlvbiBSdW5zIHRoZSBjb21tYW5kIHdpdGggdGhlIHByb3ZpZGVkIGFyZ3VtZW50cy5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2Qgc2hvdWxkIGJlIGltcGxlbWVudGVkIGluIGRlcml2ZWQgY2xhc3NlcyB0byBkZWZpbmUgdGhlIGNvbW1hbmQncyBiZWhhdmlvci5cbiAgICogQHBhcmFtIHtQYXJzZUFyZ3NSZXN1bHR9IGFuc3dlcnMgLSBUaGUgcGFyc2VkIGNvbW1hbmQtbGluZSBhcmd1bWVudHMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFIgfCBzdHJpbmcgfCB2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgY29tbWFuZCdzIHJlc3VsdC5cbiAgICovXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBydW48Uj4oXG4gICAgYW5zd2VyczogTG9nZ2luZ0NvbmZpZyAmXG4gICAgICB0eXBlb2YgRGVmYXVsdENvbW1hbmRWYWx1ZXMgJiB7IFtrIGluIGtleW9mIEldOiB1bmtub3duIH1cbiAgKTogUHJvbWlzZTxSIHwgc3RyaW5nIHwgdm9pZD47XG5cbiAgLyoqXG4gICAqIEBhc3luY1xuICAgKiBAZGVzY3JpcHRpb24gRXhlY3V0ZXMgdGhlIGNvbW1hbmQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGhhbmRsZXMgdGhlIG92ZXJhbGwgZXhlY3V0aW9uIGZsb3cgb2YgdGhlIGNvbW1hbmQsIGluY2x1ZGluZyBwYXJzaW5nIGFyZ3VtZW50cyxcbiAgICogc2V0dGluZyB1cCBsb2dnaW5nLCBjaGVja2luZyBmb3IgdmVyc2lvbiBvciBoZWxwIHJlcXVlc3RzLCBhbmQgcnVubmluZyB0aGUgY29tbWFuZC5cbiAgICogQHJldHVybnMge1Byb21pc2U8UiB8IHN0cmluZyB8IHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjb21tYW5kJ3MgcmVzdWx0LlxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDb21tYW5kXG4gICAqICAgcGFydGljaXBhbnQgVXNlcklucHV0XG4gICAqICAgcGFydGljaXBhbnQgTG9nZ2luZ1xuICAgKiAgIHBhcnRpY2lwYW50IGdldFBhY2thZ2VWZXJzaW9uXG4gICAqICAgcGFydGljaXBhbnQgcHJpbnRCYW5uZXJcbiAgICogICBDb21tYW5kLT4+VXNlcklucHV0OiBwYXJzZUFyZ3MoaW5wdXRzKVxuICAgKiAgIFVzZXJJbnB1dC0tPj5Db21tYW5kOiBSZXR1cm4gUGFyc2VBcmdzUmVzdWx0XG4gICAqICAgQ29tbWFuZC0+PkNvbW1hbmQ6IFByb2Nlc3Mgb3B0aW9uc1xuICAgKiAgIENvbW1hbmQtPj5Mb2dnaW5nOiBzZXRDb25maWcob3B0aW9ucylcbiAgICogICBhbHQgdmVyc2lvbiByZXF1ZXN0ZWRcbiAgICogICAgIENvbW1hbmQtPj5nZXRQYWNrYWdlVmVyc2lvbjogQ2FsbFxuICAgKiAgICAgZ2V0UGFja2FnZVZlcnNpb24tLT4+Q29tbWFuZDogUmV0dXJuIHZlcnNpb25cbiAgICogICBlbHNlIGhlbHAgcmVxdWVzdGVkXG4gICAqICAgICBDb21tYW5kLT4+Q29tbWFuZDogaGVscChhcmdzKVxuICAgKiAgIGVsc2UgYmFubmVyIHJlcXVlc3RlZFxuICAgKiAgICAgQ29tbWFuZC0+PnByaW50QmFubmVyOiBDYWxsXG4gICAqICAgZW5kXG4gICAqICAgQ29tbWFuZC0+PkNvbW1hbmQ6IHJ1bihhcmdzKVxuICAgKiAgIGFsdCBlcnJvciBvY2N1cnNcbiAgICogICAgIENvbW1hbmQtPj5Db21tYW5kOiBMb2cgZXJyb3JcbiAgICogICBlbmRcbiAgICogICBDb21tYW5kLS0+PkNvbW1hbmQ6IFJldHVybiByZXN1bHRcbiAgICovXG4gIGFzeW5jIGV4ZWN1dGUoKTogUHJvbWlzZTxSIHwgc3RyaW5nIHwgdm9pZD4ge1xuICAgIGNvbnN0IGFyZ3M6IFBhcnNlQXJnc1Jlc3VsdCA9IFVzZXJJbnB1dC5wYXJzZUFyZ3ModGhpcy5pbnB1dHMpO1xuICAgIGNvbnN0IGVudiA9IExvZ2dlZEVudmlyb25tZW50LmFjY3VtdWxhdGUoRGVmYXVsdENvbW1hbmRWYWx1ZXMpLmFjY3VtdWxhdGUoXG4gICAgICBhcmdzLnZhbHVlc1xuICAgICk7XG4gICAgY29uc3QgeyB2ZXJzaW9uLCBoZWxwLCBiYW5uZXIgfSA9IGVudjtcblxuICAgIGlmICh2ZXJzaW9uKSB7XG4gICAgICByZXR1cm4gZ2V0UGFja2FnZVZlcnNpb24oKTtcbiAgICB9XG5cbiAgICBpZiAoaGVscCkge1xuICAgICAgcmV0dXJuIHRoaXMuaGVscChhcmdzKTtcbiAgICB9XG5cbiAgICBpZiAoYmFubmVyKVxuICAgICAgcHJpbnRCYW5uZXIoXG4gICAgICAgIHRoaXMubG9nLmZvcihwcmludEJhbm5lciwge1xuICAgICAgICAgIHRpbWVzdGFtcDogZmFsc2UsXG4gICAgICAgICAgc3R5bGU6IGZhbHNlLFxuICAgICAgICAgIGNvbnRleHQ6IGZhbHNlLFxuICAgICAgICAgIGxvZ0xldmVsOiBmYWxzZSxcbiAgICAgICAgfSlcbiAgICAgICk7XG5cbiAgICBsZXQgcmVzdWx0O1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11c2VsZXNzLWNhdGNoXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGF3YWl0IHRoaXMucnVuKGVudiBhcyBhbnkpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdCBhcyBSO1xuICB9XG59XG4iLCIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0IGh0dHBzIGZyb20gXCJodHRwc1wiO1xuaW1wb3J0IHsgTG9nZ2luZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBIHNpbXBsZSBIVFRQIGNsaWVudCBmb3IgZG93bmxvYWRpbmcgZmlsZXMuXG4gKiBAc3VtbWFyeSBUaGlzIGNsYXNzIHByb3ZpZGVzIGZ1bmN0aW9uYWxpdHkgdG8gZG93bmxvYWQgZmlsZXMgZnJvbSBIVFRQUyBVUkxzLlxuICogSXQgdXNlcyBOb2RlLmpzIGJ1aWx0LWluIGh0dHBzIG1vZHVsZSB0byBtYWtlIHJlcXVlc3RzLlxuICpcbiAqIEBjbGFzcyBIdHRwQ2xpZW50XG4gKi9cbmV4cG9ydCBjbGFzcyBIdHRwQ2xpZW50IHtcbiAgcHJvdGVjdGVkIHN0YXRpYyBsb2cgPSBMb2dnaW5nLmZvcihIdHRwQ2xpZW50KTtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEb3dubG9hZHMgYSBmaWxlIGZyb20gYSBnaXZlbiBVUkwuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIHNlbmRzIGEgR0VUIHJlcXVlc3QgdG8gdGhlIHNwZWNpZmllZCBVUkwgYW5kIHJldHVybnMgdGhlIHJlc3BvbnNlIGJvZHkgYXMgYSBzdHJpbmcuXG4gICAqIEl0IGhhbmRsZXMgZGlmZmVyZW50IHNjZW5hcmlvcyBzdWNoIGFzIG5vbi0yMDAgc3RhdHVzIGNvZGVzIGFuZCBuZXR3b3JrIGVycm9ycy5cbiAgICpcbiAgICogQHBhcmFtIHVybCAtIFRoZSBVUkwgb2YgdGhlIGZpbGUgdG8gZG93bmxvYWQuXG4gICAqIEByZXR1cm4gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgZmlsZSBjb250ZW50IGFzIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAgICogICBwYXJ0aWNpcGFudCBIdHRwQ2xpZW50XG4gICAqICAgcGFydGljaXBhbnQgSFRUUFNcbiAgICogICBwYXJ0aWNpcGFudCBTZXJ2ZXJcbiAgICogICBDbGllbnQtPj5IdHRwQ2xpZW50OiBkb3dubG9hZEZpbGUodXJsKVxuICAgKiAgIEh0dHBDbGllbnQtPj5IVFRQUzogZ2V0KHVybClcbiAgICogICBIVFRQUy0+PlNlcnZlcjogR0VUIHJlcXVlc3RcbiAgICogICBTZXJ2ZXItLT4+SFRUUFM6IFJlc3BvbnNlXG4gICAqICAgSFRUUFMtLT4+SHR0cENsaWVudDogUmVzcG9uc2Ugb2JqZWN0XG4gICAqICAgYWx0IFN0YXR1cyBjb2RlIGlzIDIwMFxuICAgKiAgICAgbG9vcCBGb3IgZWFjaCBkYXRhIGNodW5rXG4gICAqICAgICAgIEhUVFBTLT4+SHR0cENsaWVudDogJ2RhdGEnIGV2ZW50XG4gICAqICAgICAgIEh0dHBDbGllbnQtPj5IdHRwQ2xpZW50OiBBY2N1bXVsYXRlIGRhdGFcbiAgICogICAgIGVuZFxuICAgKiAgICAgSFRUUFMtPj5IdHRwQ2xpZW50OiAnZW5kJyBldmVudFxuICAgKiAgICAgSHR0cENsaWVudC0tPj5DbGllbnQ6IFJlc29sdmUgd2l0aCBkYXRhXG4gICAqICAgZWxzZSBTdGF0dXMgY29kZSBpcyBub3QgMjAwXG4gICAqICAgICBIdHRwQ2xpZW50LS0+PkNsaWVudDogUmVqZWN0IHdpdGggZXJyb3JcbiAgICogICBlbmRcbiAgICovXG4gIHN0YXRpYyBhc3luYyBkb3dubG9hZEZpbGUodXJsOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxzdHJpbmc+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGZ1bmN0aW9uIHJlcXVlc3QodXJsOiBzdHJpbmcpIHtcbiAgICAgICAgdXJsID0gZW5jb2RlVVJJKHVybCk7XG4gICAgICAgIGh0dHBzLmdldCh1cmwsIChyZXMpID0+IHtcbiAgICAgICAgICBpZiAocmVzLnN0YXR1c0NvZGUgPT09IDMwMSB8fCByZXMuc3RhdHVzQ29kZSA9PT0gMzA3KVxuICAgICAgICAgICAgcmV0dXJuIHJlcXVlc3QocmVzLmhlYWRlcnMubG9jYXRpb24gYXMgc3RyaW5nKTtcblxuICAgICAgICAgIGlmIChyZXMuc3RhdHVzQ29kZSAhPT0gMjAwKSB7XG4gICAgICAgICAgICBIdHRwQ2xpZW50LmxvZy5lcnJvcihcbiAgICAgICAgICAgICAgYEZhaWxlZCB0byBmZXRjaCAke3VybH0gKHN0YXR1czogJHtyZXMuc3RhdHVzQ29kZX0pYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKGBGYWlsZWQgdG8gZmV0Y2ggJHt1cmx9YCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBsZXQgZGF0YSA9IFwiXCI7XG4gICAgICAgICAgcmVzLm9uKFwiZGF0YVwiLCAoY2h1bmspID0+IHtcbiAgICAgICAgICAgIGRhdGEgKz0gY2h1bms7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmVzLm9uKFwiZXJyb3JcIiwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgcmVzLm9uKFwiZW5kXCIsICgpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmUoZGF0YSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmVxdWVzdCh1cmwpO1xuICAgIH0pO1xuICB9XG59XG4iLCJpbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgbWtkaXIsIHdyaXRlRmlsZSB9IGZyb20gXCJmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHsgU3RvcFdhdGNoIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbmV4cG9ydCB0eXBlIEV4ZWN1dGlvbk1vZGUgPSBcInNlcXVlbnRpYWxcIiB8IFwiY29uY3VycmVudFwiIHwgXCJidXJzdFwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBoYXNlQnVyc3RDb25maWcge1xuICBzaXplOiBudW1iZXI7XG4gIGludGVydmFsTXM/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGhhc2VXYXJtdXBDb25maWc8VENvbnRleHQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICBpdGVyYXRpb25zOiBudW1iZXI7XG4gIGhhbmRsZXI/OiBQZXJmb3JtYW5jZUhhbmRsZXI8VENvbnRleHQ+O1xuICBkZWxheUJldHdlZW5JdGVyYXRpb25zTXM/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGhhc2VDb25maWc8VENvbnRleHQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICBpdGVyYXRpb25zOiBudW1iZXI7XG4gIG1vZGU6IEV4ZWN1dGlvbk1vZGU7XG4gIGNvbmN1cnJlbmN5PzogbnVtYmVyO1xuICBkZWxheUJldHdlZW5JdGVyYXRpb25zTXM/OiBudW1iZXI7XG4gIGJ1cnN0PzogUGhhc2VCdXJzdENvbmZpZztcbiAgbG9hZFN0YXJ0PzogbnVtYmVyO1xuICBsb2FkU3RlcD86IG51bWJlcjtcbiAgbG9hZE11bHRpcGxpZXI/OiBudW1iZXI7XG4gIGNvbnRleHQ/OiBQYXJ0aWFsPFRDb250ZXh0PjtcbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgd2FybXVwPzogUGhhc2VXYXJtdXBDb25maWc8VENvbnRleHQ+O1xuICBwYXVzZUFmdGVyTXM/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGhhc2U8VENvbnRleHQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICBuYW1lOiBzdHJpbmc7XG4gIGNvbmZpZzogUGhhc2VDb25maWc8VENvbnRleHQ+O1xuICBnZW5lcmF0b3I/OiBQaGFzZUdlbmVyYXRvcjxUQ29udGV4dD47XG4gIHN1YlBoYXNlcz86IFBoYXNlPFRDb250ZXh0PltdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBoYXNlR2VuZXJhdG9yUGhhc2U8VENvbnRleHQ+IHtcbiAgbmFtZT86IHN0cmluZztcbiAgY29uZmlnOiBQaGFzZUNvbmZpZzxQYXJ0aWFsPFRDb250ZXh0Pj47XG59XG5cbmV4cG9ydCB0eXBlIFBoYXNlR2VuZXJhdG9yUmVzdWx0PFRDb250ZXh0PiA9XG4gIHwgUGhhc2VDb25maWc8VENvbnRleHQ+XG4gIHwgUGhhc2VHZW5lcmF0b3JQaGFzZTxUQ29udGV4dD47XG5cbmV4cG9ydCB0eXBlIFBoYXNlR2VuZXJhdG9yPFRDb250ZXh0PiA9IChcbiAgcGF5bG9hZDogUGhhc2VHZW5lcmF0b3JQYXlsb2FkPFRDb250ZXh0PlxuKSA9PlxuICB8IFByb21pc2U8UGhhc2VHZW5lcmF0b3JSZXN1bHQ8VENvbnRleHQ+IHwgdW5kZWZpbmVkPlxuICB8IFBoYXNlR2VuZXJhdG9yUmVzdWx0PFRDb250ZXh0PlxuICB8IHVuZGVmaW5lZDtcblxuZXhwb3J0IGludGVyZmFjZSBQaGFzZVJlc3VsdDxUQ29udGV4dCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+PiB7XG4gIHBoYXNlOiBQaGFzZTxUQ29udGV4dD47XG4gIGNvbmZpZzogUGhhc2VDb25maWc8VENvbnRleHQ+O1xuICBpdGVyYXRpb25NZXRyaWNzOiBJdGVyYXRpb25NZXRyaWNbXTtcbiAgYWdncmVnYXRlZDogQWdncmVnYXRlZE1ldHJpY3M7XG4gIGNvbnRleHQ6IFRDb250ZXh0O1xuICBzZWdtZW50Q291bnQ6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQaGFzZUdlbmVyYXRvck1ldGFkYXRhPFRDb250ZXh0ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4+IHtcbiAgcGhhc2VOdW1iZXI6IG51bWJlcjtcbiAgcGhhc2VOYW1lOiBzdHJpbmc7XG4gIGl0ZXJhdGlvbkNvdW50OiBudW1iZXI7XG4gIGJ1cnN0U2VnbWVudHM6IG51bWJlcjtcbiAgc2VnbWVudENvdW50OiBudW1iZXI7XG4gIG1vZGU6IEV4ZWN1dGlvbk1vZGU7XG4gIGhpc3Rvcnk6IFBoYXNlUmVzdWx0PFRDb250ZXh0PltdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBoYXNlR2VuZXJhdG9yUGF5bG9hZDxUQ29udGV4dCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+PiB7XG4gIHJlc3VsdDogUGhhc2VSZXN1bHQ8VENvbnRleHQ+O1xuICBoaXN0b3J5OiBQaGFzZVJlc3VsdDxUQ29udGV4dD5bXTtcbiAgbWV0YWRhdGE6IFBoYXNlR2VuZXJhdG9yTWV0YWRhdGE8VENvbnRleHQ+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFnZ3JlZ2F0ZWRNZXRyaWNzIHtcbiAgdG90YWxEdXJhdGlvbk1zOiBudW1iZXI7XG4gIG1pbk1zOiBudW1iZXI7XG4gIG1heE1zOiBudW1iZXI7XG4gIGF2ZXJhZ2VNczogbnVtYmVyO1xuICBzdWNjZXNzQ291bnQ6IG51bWJlcjtcbiAgZmFpbHVyZUNvdW50OiBudW1iZXI7XG4gIGxvYWRTdGFydDogbnVtYmVyO1xuICBsb2FkRW5kOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSXRlcmF0aW9uTWV0cmljIHtcbiAgaXRlcmF0aW9uOiBudW1iZXI7XG4gIGR1cmF0aW9uTXM6IG51bWJlcjtcbiAgc3VjY2VzczogYm9vbGVhbjtcbiAgbWV0YT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBsb2FkRmFjdG9yOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSGFuZGxlclBheWxvYWQ8VENvbnRleHQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICBpdGVyYXRpb246IG51bWJlcjtcbiAgY29uZmlnOiBQaGFzZUNvbmZpZzxUQ29udGV4dD47XG4gIGxvYWRGYWN0b3I6IG51bWJlcjtcbiAgY29udGV4dDogVENvbnRleHQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSGFuZGxlclJlc3VsdCB7XG4gIHN1Y2Nlc3M/OiBib29sZWFuO1xuICBtZXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbmV4cG9ydCB0eXBlIFBlcmZvcm1hbmNlSGFuZGxlcjxUQ29udGV4dCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+PiA9IChcbiAgcGF5bG9hZDogSGFuZGxlclBheWxvYWQ8VENvbnRleHQ+XG4pID0+IFByb21pc2U8SGFuZGxlclJlc3VsdD4gfCBIYW5kbGVyUmVzdWx0O1xuXG5leHBvcnQgaW50ZXJmYWNlIENhbnZhc1JlbmRlck9wdGlvbnMge1xuICB3aWR0aD86IG51bWJlcjtcbiAgaGVpZ2h0PzogbnVtYmVyO1xuICBwYWRkaW5nPzogbnVtYmVyO1xuICBiYWNrZ3JvdW5kQ29sb3I/OiBzdHJpbmc7XG4gIGhlYWRlckZvbnQ/OiBzdHJpbmc7XG4gIHJvd0ZvbnQ/OiBzdHJpbmc7XG4gIGhlYWRlckNvbG9yPzogc3RyaW5nO1xuICByb3dDb2xvcj86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQZXJmb3JtYW5jZVNjZW5hcmlvPFRDb250ZXh0ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4+IHtcbiAgbmFtZTogc3RyaW5nO1xuICBoYW5kbGVyOiBQZXJmb3JtYW5jZUhhbmRsZXI8VENvbnRleHQ+O1xuICBwaGFzZXM6IFBoYXNlPFRDb250ZXh0PltdO1xuICBiYXNlQ29udGV4dD86IFRDb250ZXh0O1xuICBmYWlsT25FcnJvcj86IGJvb2xlYW47XG4gIGluaXRpYWxpemU/OiAoKSA9PiBQcm9taXNlPHZvaWQ+IHwgdm9pZDtcbiAgY2FudmFzT3B0aW9ucz86IENhbnZhc1JlbmRlck9wdGlvbnM7XG4gIGNhbnZhc091dHB1dFBhdGg/OiBzdHJpbmc7XG4gIGVuYWJsZUNhbnZhcz86IGJvb2xlYW47XG59XG5cbmludGVyZmFjZSBQaGFzZVF1ZXVlSXRlbTxUQ29udGV4dD4ge1xuICBwaGFzZTogUGhhc2U8VENvbnRleHQ+O1xuICBwaGFzZU51bWJlcjogbnVtYmVyO1xufVxuXG5leHBvcnQgY29uc3QgZGVmYXVsdENhbnZhc09wdGlvbnM6IFJlcXVpcmVkPENhbnZhc1JlbmRlck9wdGlvbnM+ID0ge1xuICB3aWR0aDogMTIwMCxcbiAgaGVpZ2h0OiAyNjAsXG4gIHBhZGRpbmc6IDMyLFxuICBiYWNrZ3JvdW5kQ29sb3I6IFwiIzBmMTcyYVwiLFxuICBoZWFkZXJGb250OiBcImJvbGQgMThweCAnU2Vnb2UgVUknLCBzYW5zLXNlcmlmXCIsXG4gIHJvd0ZvbnQ6IFwiMTRweCAnU2Vnb2UgVUknLCBzYW5zLXNlcmlmXCIsXG4gIGhlYWRlckNvbG9yOiBcIiNmOGZhZmNcIixcbiAgcm93Q29sb3I6IFwiI2NiZDVmNVwiLFxufTtcblxuY29uc3QgZGVsYXkgPSAobXM6IG51bWJlcikgPT4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbmNvbnN0IHBlcmZEZWJ1Z0VuYWJsZWQgPSBwcm9jZXNzLmVudi5QRVJGX1ZFUkJPU0UgPT09IFwidHJ1ZVwiO1xuY29uc3QgZGVidWdMb2cgPSAoLi4uYXJnczogdW5rbm93bltdKSA9PiB7XG4gIGlmIChwZXJmRGVidWdFbmFibGVkKSB7XG4gICAgY29uc29sZS5kZWJ1ZyguLi5hcmdzKTtcbiAgfVxufTtcblxuY29uc3QgZm9ybWF0VGFibGUgPSAoXG4gIHRpdGxlOiBzdHJpbmcsXG4gIGhlYWRlcnM6IHN0cmluZ1tdLFxuICByb3dzOiBzdHJpbmdbXVtdXG4pOiBzdHJpbmcgPT4ge1xuICBjb25zdCBjb2x1bW5XaWR0aHMgPSBoZWFkZXJzLm1hcCgoaGVhZGVyLCBpbmRleCkgPT5cbiAgICBNYXRoLm1heChoZWFkZXIubGVuZ3RoLCAuLi5yb3dzLm1hcCgocm93KSA9PiByb3dbaW5kZXhdPy5sZW5ndGggPz8gMCkpXG4gICk7XG4gIGNvbnN0IGZvcm1hdFJvdyA9ICh2YWx1ZXM6IHN0cmluZ1tdKSA9PlxuICAgIFwifCBcIiArXG4gICAgdmFsdWVzXG4gICAgICAubWFwKCh2YWx1ZSwgaW5kZXgpID0+IHZhbHVlLnBhZEVuZChjb2x1bW5XaWR0aHNbaW5kZXhdKSlcbiAgICAgIC5qb2luKFwiIHwgXCIpICtcbiAgICBcIiB8XCI7XG4gIGNvbnN0IGhlYWRlckxpbmUgPSBmb3JtYXRSb3coaGVhZGVycyk7XG4gIGNvbnN0IGRpdmlkZXIgPVxuICAgIFwifCBcIiArIGNvbHVtbldpZHRocy5tYXAoKHdpZHRoKSA9PiBcIi1cIi5yZXBlYXQod2lkdGgpKS5qb2luKFwiIHwgXCIpICsgXCIgfFwiO1xuICBjb25zdCBib2R5ID0gcm93cy5tYXAoZm9ybWF0Um93KS5qb2luKFwiXFxuXCIpO1xuICByZXR1cm4gYCR7dGl0bGV9XFxuJHtoZWFkZXJMaW5lfVxcbiR7ZGl2aWRlcn1cXG4ke2JvZHl9YDtcbn07XG5cbmNvbnN0IGVuc3VyZURpcmVjdG9yeSA9IGFzeW5jICh0YXJnZXRQYXRoOiBzdHJpbmcpID0+IHtcbiAgYXdhaXQgbWtkaXIocGF0aC5kaXJuYW1lKHRhcmdldFBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbn07XG5cbmNvbnN0IHJlbmRlck1ldHJpY3NUYWJsZVRvQ2FudmFzID0gYXN5bmMgKFxuICBoZWFkZXJzOiBzdHJpbmdbXSxcbiAgcm93czogc3RyaW5nW11bXSxcbiAgb3B0aW9uczogQ2FudmFzUmVuZGVyT3B0aW9ucyxcbiAgb3V0cHV0UGF0aDogc3RyaW5nXG4pID0+IHtcbiAgY29uc3QgY29uZmlnID0geyAuLi5kZWZhdWx0Q2FudmFzT3B0aW9ucywgLi4ub3B0aW9ucyB9O1xuICAvLyBAdHMtZXhwZWN0LWVycm9yIGNhbnZhcyBpbXBvcnRcbiAgbGV0IGNyZWF0ZUNhbnZhczogKHR5cGVvZiBpbXBvcnQoXCJjYW52YXNcIikpW1wiY3JlYXRlQ2FudmFzXCJdO1xuICB0cnkge1xuICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgYmVjYXVzZSB3ZSBhbGxvdyBvcHRpb25hbCBkZXBlbmRlbmN5XG4gICAgY29uc3QgY2FudmFzTW9kdWxlID0gYXdhaXQgaW1wb3J0KFwiY2FudmFzXCIpO1xuICAgIGNyZWF0ZUNhbnZhcyA9IGNhbnZhc01vZHVsZS5jcmVhdGVDYW52YXM7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc29sZS53YXJuKFxuICAgICAgXCJbUGVyZlJ1bm5lcl0gQ2FudmFzIG1vZHVsZSBub3QgYXZhaWxhYmxlLCBza2lwcGluZyBjaGFydC5cIixcbiAgICAgIGVycm9yXG4gICAgKTtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgY2FudmFzID0gY3JlYXRlQ2FudmFzKGNvbmZpZy53aWR0aCwgY29uZmlnLmhlaWdodCk7XG4gIGNvbnN0IGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG5cbiAgY3R4LmZpbGxTdHlsZSA9IGNvbmZpZy5iYWNrZ3JvdW5kQ29sb3I7XG4gIGN0eC5maWxsUmVjdCgwLCAwLCBjb25maWcud2lkdGgsIGNvbmZpZy5oZWlnaHQpO1xuXG4gIGN0eC5mb250ID0gY29uZmlnLmhlYWRlckZvbnQ7XG4gIGN0eC5maWxsU3R5bGUgPSBjb25maWcuaGVhZGVyQ29sb3I7XG4gIGNvbnN0IGNvbHVtbldpZHRoID0gKGNvbmZpZy53aWR0aCAtIGNvbmZpZy5wYWRkaW5nICogMikgLyBoZWFkZXJzLmxlbmd0aDtcbiAgY29uc3QgaGVhZGVyWSA9IGNvbmZpZy5wYWRkaW5nICsgMjQ7XG5cbiAgaGVhZGVycy5mb3JFYWNoKChoZWFkZXIsIGluZGV4KSA9PiB7XG4gICAgY3R4LmZpbGxUZXh0KGhlYWRlciwgY29uZmlnLnBhZGRpbmcgKyBjb2x1bW5XaWR0aCAqIGluZGV4LCBoZWFkZXJZKTtcbiAgfSk7XG5cbiAgY3R4LmZvbnQgPSBjb25maWcucm93Rm9udDtcbiAgY3R4LmZpbGxTdHlsZSA9IGNvbmZpZy5yb3dDb2xvcjtcbiAgY29uc3Qgcm93SGVpZ2h0ID0gMjQ7XG4gIHJvd3MuZm9yRWFjaCgocm93LCByb3dJbmRleCkgPT4ge1xuICAgIGNvbnN0IHkgPSBoZWFkZXJZICsgMTIgKyByb3dIZWlnaHQgKiAocm93SW5kZXggKyAxKTtcbiAgICByb3cuZm9yRWFjaCgoY2VsbCwgY2VsbEluZGV4KSA9PiB7XG4gICAgICBjdHguZmlsbFRleHQoY2VsbCwgY29uZmlnLnBhZGRpbmcgKyBjb2x1bW5XaWR0aCAqIGNlbGxJbmRleCwgeSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGF3YWl0IGVuc3VyZURpcmVjdG9yeShvdXRwdXRQYXRoKTtcbiAgYXdhaXQgd3JpdGVGaWxlKG91dHB1dFBhdGgsIGNhbnZhcy50b0J1ZmZlcihcImltYWdlL3BuZ1wiKSk7XG4gIGNvbnNvbGUubG9nKGBTdG9yZWQgcGVyZm9ybWFuY2UgY2hhcnQgYXQgJHtvdXRwdXRQYXRofWApO1xufTtcblxuZXhwb3J0IGNsYXNzIFBlcmZvcm1hbmNlUnVubmVyPFRDb250ZXh0ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4+IHtcbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIHJlYWRvbmx5IHNjZW5hcmlvOiBQZXJmb3JtYW5jZVNjZW5hcmlvPFRDb250ZXh0Pikge31cblxuICBwdWJsaWMgYXN5bmMgcnVuKCk6IFByb21pc2U8UGhhc2VSZXN1bHQ8VENvbnRleHQ+W10+IHtcbiAgICBpZiAodGhpcy5zY2VuYXJpby5pbml0aWFsaXplKSB7XG4gICAgICBhd2FpdCB0aGlzLnNjZW5hcmlvLmluaXRpYWxpemUoKTtcbiAgICB9XG5cbiAgICBsZXQgcGhhc2VDb3VudGVyID0gMDtcbiAgICBjb25zdCBxdWV1ZTogUGhhc2VRdWV1ZUl0ZW08VENvbnRleHQ+W10gPSB0aGlzLnNjZW5hcmlvLnBoYXNlcy5tYXAoXG4gICAgICAocGhhc2UpID0+ICh7IHBoYXNlLCBwaGFzZU51bWJlcjogKytwaGFzZUNvdW50ZXIgfSlcbiAgICApO1xuICAgIGNvbnN0IHJlc3VsdHM6IFBoYXNlUmVzdWx0PFRDb250ZXh0PltdID0gW107XG5cbiAgICB3aGlsZSAocXVldWUubGVuZ3RoKSB7XG4gICAgICBjb25zdCBpdGVtID0gcXVldWUuc2hpZnQoKSE7XG4gICAgICBjb25zdCBwaGFzZSA9IGl0ZW0ucGhhc2U7XG4gICAgICBjb25zdCBjb250ZXh0ID0gdGhpcy5tZXJnZUNvbnRleHQocGhhc2UpO1xuICAgICAgY29uc29sZS5pbmZvKFxuICAgICAgICBgW1BlcmZSdW5uZXJdIFN0YXJ0aW5nIHBoYXNlICMke2l0ZW0ucGhhc2VOdW1iZXJ9IFwiJHtwaGFzZS5uYW1lfVwiYCxcbiAgICAgICAge1xuICAgICAgICAgIGl0ZXJhdGlvbnM6IHBoYXNlLmNvbmZpZy5pdGVyYXRpb25zLFxuICAgICAgICAgIG1vZGU6IHBoYXNlLmNvbmZpZy5tb2RlLFxuICAgICAgICAgIGNvbmN1cnJlbmN5OiBwaGFzZS5jb25maWcuY29uY3VycmVuY3ksXG4gICAgICAgICAgYnVyc3Q6IHBoYXNlLmNvbmZpZy5idXJzdCxcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMucnVuUGhhc2UocGhhc2UsIGNvbnRleHQpO1xuICAgICAgY29uc29sZS5pbmZvKFxuICAgICAgICBgW1BlcmZSdW5uZXJdIENvbXBsZXRlZCBwaGFzZSAjJHtpdGVtLnBoYXNlTnVtYmVyfSBcIiR7cGhhc2UubmFtZX1cImAsXG4gICAgICAgIHtcbiAgICAgICAgICB0b3RhbDogcmVzdWx0LmFnZ3JlZ2F0ZWQudG90YWxEdXJhdGlvbk1zLnRvRml4ZWQoMiksXG4gICAgICAgICAgYXZnOiByZXN1bHQuYWdncmVnYXRlZC5hdmVyYWdlTXMudG9GaXhlZCgyKSxcbiAgICAgICAgICBmYWlsdXJlQ291bnQ6IHJlc3VsdC5hZ2dyZWdhdGVkLmZhaWx1cmVDb3VudCxcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICAgIHJlc3VsdHMucHVzaChyZXN1bHQpO1xuXG4gICAgICBpZiAocGhhc2UuZ2VuZXJhdG9yKSB7XG4gICAgICAgIGNvbnN0IGhpc3RvcnlTbmFwc2hvdCA9IFsuLi5yZXN1bHRzXTtcbiAgICAgICAgY29uc3QgbWV0YWRhdGE6IFBoYXNlR2VuZXJhdG9yTWV0YWRhdGE8VENvbnRleHQ+ID0ge1xuICAgICAgICAgIHBoYXNlTnVtYmVyOiBpdGVtLnBoYXNlTnVtYmVyLFxuICAgICAgICAgIHBoYXNlTmFtZTogcGhhc2UubmFtZSxcbiAgICAgICAgICBpdGVyYXRpb25Db3VudDogcGhhc2UuY29uZmlnLml0ZXJhdGlvbnMsXG4gICAgICAgICAgYnVyc3RTZWdtZW50czogcmVzdWx0LnNlZ21lbnRDb3VudCxcbiAgICAgICAgICBzZWdtZW50Q291bnQ6IHJlc3VsdC5zZWdtZW50Q291bnQsXG4gICAgICAgICAgbW9kZTogcGhhc2UuY29uZmlnLm1vZGUsXG4gICAgICAgICAgaGlzdG9yeTogaGlzdG9yeVNuYXBzaG90LFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBnZW5lcmF0b3JSZXN1bHQgPSBhd2FpdCBwaGFzZS5nZW5lcmF0b3Ioe1xuICAgICAgICAgIHJlc3VsdCxcbiAgICAgICAgICBoaXN0b3J5OiBoaXN0b3J5U25hcHNob3QsXG4gICAgICAgICAgbWV0YWRhdGEsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoZ2VuZXJhdG9yUmVzdWx0KSB7XG4gICAgICAgICAgY29uc3QgbmV4dFBoYXNlOiBQaGFzZTxUQ29udGV4dD4gPSAoXG4gICAgICAgICAgICBcImNvbmZpZ1wiIGluIGdlbmVyYXRvclJlc3VsdFxuICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgIG5hbWU6IGdlbmVyYXRvclJlc3VsdC5uYW1lID8/IGAke3BoYXNlLm5hbWV9IOKGkiBnZW5gLFxuICAgICAgICAgICAgICAgICAgY29uZmlnOiBnZW5lcmF0b3JSZXN1bHQuY29uZmlnLFxuICAgICAgICAgICAgICAgICAgZ2VuZXJhdG9yOiBwaGFzZS5nZW5lcmF0b3IsXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgIG5hbWU6IGAke3BoYXNlLm5hbWV9IOKGkiBnZW5gLFxuICAgICAgICAgICAgICAgICAgY29uZmlnOiBnZW5lcmF0b3JSZXN1bHQsXG4gICAgICAgICAgICAgICAgICBnZW5lcmF0b3I6IHBoYXNlLmdlbmVyYXRvcixcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgKSBhcyBhbnk7XG4gICAgICAgICAgcXVldWUucHVzaCh7XG4gICAgICAgICAgICBwaGFzZTogbmV4dFBoYXNlLFxuICAgICAgICAgICAgcGhhc2VOdW1iZXI6ICsrcGhhc2VDb3VudGVyLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5sb2dTdW1tYXJ5KHJlc3VsdHMpO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHJ1blBoYXNlKFxuICAgIHBoYXNlOiBQaGFzZTxUQ29udGV4dD4sXG4gICAgY29udGV4dDogVENvbnRleHRcbiAgKTogUHJvbWlzZTxQaGFzZVJlc3VsdDxUQ29udGV4dD4+IHtcbiAgICBhd2FpdCB0aGlzLnJ1bldhcm11cChwaGFzZSwgY29udGV4dCk7XG4gICAgY29uc3Qgc2VnbWVudHMgPSB0aGlzLmJ1aWxkU2VnbWVudEluZGljZXMoXG4gICAgICBwaGFzZS5jb25maWcuaXRlcmF0aW9ucyxcbiAgICAgIHBoYXNlLmNvbmZpZy5idXJzdFxuICAgICk7XG4gICAgY29uc3QgY29sbGVjdGVkOiBJdGVyYXRpb25NZXRyaWNbXSA9IFtdO1xuXG4gICAgZm9yIChcbiAgICAgIGxldCBzZWdtZW50SW5kZXggPSAwO1xuICAgICAgc2VnbWVudEluZGV4IDwgc2VnbWVudHMubGVuZ3RoO1xuICAgICAgc2VnbWVudEluZGV4ICs9IDFcbiAgICApIHtcbiAgICAgIGNvbnN0IGluZGljZXMgPSBzZWdtZW50c1tzZWdtZW50SW5kZXhdO1xuICAgICAgaWYgKCFpbmRpY2VzLmxlbmd0aCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgZGVidWdMb2coXG4gICAgICAgIGBbUGVyZlJ1bm5lcl0gUGhhc2UgXCIke3BoYXNlLm5hbWV9XCIgZXhlY3V0aW5nIHNlZ21lbnQgJHtzZWdtZW50SW5kZXggKyAxfS8ke1xuICAgICAgICAgIHNlZ21lbnRzLmxlbmd0aFxuICAgICAgICB9IChpdGVyYXRpb25zICR7aW5kaWNlc1swXX0tJHtpbmRpY2VzW2luZGljZXMubGVuZ3RoIC0gMV19KWBcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IG1ldHJpY3MgPSBhd2FpdCB0aGlzLmV4ZWN1dGVTZWdtZW50KFxuICAgICAgICB0aGlzLnNjZW5hcmlvLmhhbmRsZXIsXG4gICAgICAgIHBoYXNlLmNvbmZpZyxcbiAgICAgICAgY29udGV4dCxcbiAgICAgICAgaW5kaWNlc1xuICAgICAgKTtcbiAgICAgIGNvbGxlY3RlZC5wdXNoKC4uLm1ldHJpY3MpO1xuXG4gICAgICBjb25zdCBidXJzdEludGVydmFsID0gcGhhc2UuY29uZmlnLmJ1cnN0Py5pbnRlcnZhbE1zO1xuICAgICAgaWYgKGJ1cnN0SW50ZXJ2YWwgJiYgc2VnbWVudEluZGV4IDwgc2VnbWVudHMubGVuZ3RoIC0gMSkge1xuICAgICAgICBhd2FpdCBkZWxheShidXJzdEludGVydmFsKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBzb3J0ZWQgPSBbLi4uY29sbGVjdGVkXS5zb3J0KChhLCBiKSA9PiBhLml0ZXJhdGlvbiAtIGIuaXRlcmF0aW9uKTtcbiAgICBjb25zdCBhZ2dyZWdhdGVkID0gdGhpcy5hZ2dyZWdhdGVNZXRyaWNzKHNvcnRlZCk7XG5cbiAgICBpZiAocGhhc2UuY29uZmlnLnBhdXNlQWZ0ZXJNcykge1xuICAgICAgYXdhaXQgZGVsYXkocGhhc2UuY29uZmlnLnBhdXNlQWZ0ZXJNcyk7XG4gICAgfVxuXG4gICAgaWYgKGFnZ3JlZ2F0ZWQuZmFpbHVyZUNvdW50ID4gMCAmJiB0aGlzLnNjZW5hcmlvLmZhaWxPbkVycm9yICE9PSBmYWxzZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgUGhhc2UgJHtwaGFzZS5uYW1lfSByZWNvcmRlZCAke2FnZ3JlZ2F0ZWQuZmFpbHVyZUNvdW50fSBmYWlsdXJlc2BcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHBoYXNlLFxuICAgICAgY29uZmlnOiBwaGFzZS5jb25maWcsXG4gICAgICBpdGVyYXRpb25NZXRyaWNzOiBzb3J0ZWQsXG4gICAgICBhZ2dyZWdhdGVkLFxuICAgICAgY29udGV4dCxcbiAgICAgIHNlZ21lbnRDb3VudDogc2VnbWVudHMubGVuZ3RoLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcnVuV2FybXVwKFxuICAgIHBoYXNlOiBQaGFzZTxUQ29udGV4dD4sXG4gICAgY29udGV4dDogVENvbnRleHRcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgd2FybXVwID0gcGhhc2UuY29uZmlnLndhcm11cDtcbiAgICBpZiAoIXdhcm11cD8uaXRlcmF0aW9ucykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGhhbmRsZXIgPSB3YXJtdXAuaGFuZGxlciA/PyB0aGlzLnNjZW5hcmlvLmhhbmRsZXI7XG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHdhcm11cC5pdGVyYXRpb25zOyBpbmRleCArPSAxKSB7XG4gICAgICBhd2FpdCBoYW5kbGVyKHtcbiAgICAgICAgaXRlcmF0aW9uOiBpbmRleCxcbiAgICAgICAgY29uZmlnOiBwaGFzZS5jb25maWcsXG4gICAgICAgIGxvYWRGYWN0b3I6IHRoaXMuY29tcHV0ZUxvYWRGYWN0b3IocGhhc2UuY29uZmlnLCBpbmRleCksXG4gICAgICAgIGNvbnRleHQsXG4gICAgICB9KTtcbiAgICAgIGlmICh3YXJtdXAuZGVsYXlCZXR3ZWVuSXRlcmF0aW9uc01zICYmIGluZGV4IDwgd2FybXVwLml0ZXJhdGlvbnMgLSAxKSB7XG4gICAgICAgIGF3YWl0IGRlbGF5KHdhcm11cC5kZWxheUJldHdlZW5JdGVyYXRpb25zTXMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBjb21wdXRlTG9hZEZhY3RvcihcbiAgICBjb25maWc6IFBoYXNlQ29uZmlnPFRDb250ZXh0PixcbiAgICBpdGVyYXRpb246IG51bWJlclxuICApOiBudW1iZXIge1xuICAgIGNvbnN0IGJhc2UgPSBjb25maWcubG9hZFN0YXJ0ID8/IDE7XG4gICAgY29uc3Qgc3RlcCA9IGNvbmZpZy5sb2FkU3RlcCA/PyAwO1xuICAgIGNvbnN0IG11bHRpcGxpZXIgPSBjb25maWcubG9hZE11bHRpcGxpZXIgPz8gMTtcbiAgICByZXR1cm4gKGJhc2UgKyBzdGVwICogaXRlcmF0aW9uKSAqIG11bHRpcGxpZXI7XG4gIH1cblxuICBwcm90ZWN0ZWQgYnVpbGRTZWdtZW50SW5kaWNlcyhcbiAgICBpdGVyYXRpb25zOiBudW1iZXIsXG4gICAgYnVyc3Q/OiBQaGFzZUJ1cnN0Q29uZmlnXG4gICk6IG51bWJlcltdW10ge1xuICAgIGNvbnN0IHRvdGFsID0gTWF0aC5tYXgoMCwgaXRlcmF0aW9ucyk7XG4gICAgaWYgKHRvdGFsID09PSAwKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgY29uc3QgY2h1bmsgPVxuICAgICAgYnVyc3Q/LnNpemUgJiYgYnVyc3Quc2l6ZSA+IDAgPyBNYXRoLm1pbihidXJzdC5zaXplLCB0b3RhbCkgOiB0b3RhbDtcbiAgICBjb25zdCBzZWdtZW50czogbnVtYmVyW11bXSA9IFtdO1xuXG4gICAgZm9yIChsZXQgY3Vyc29yID0gMDsgY3Vyc29yIDwgdG90YWw7IGN1cnNvciArPSBjaHVuaykge1xuICAgICAgY29uc3QgZW5kID0gTWF0aC5taW4odG90YWwsIGN1cnNvciArIGNodW5rKTtcbiAgICAgIHNlZ21lbnRzLnB1c2goXG4gICAgICAgIEFycmF5LmZyb20oeyBsZW5ndGg6IGVuZCAtIGN1cnNvciB9LCAoXywgaWR4KSA9PiBjdXJzb3IgKyBpZHgpXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBzZWdtZW50cztcbiAgfVxuXG4gIHByb3RlY3RlZCBtZXJnZUNvbnRleHQocGhhc2U6IFBoYXNlPFRDb250ZXh0Pik6IFRDb250ZXh0IHtcbiAgICBjb25zdCBiYXNlQ29udGV4dCA9IHRoaXMuc2NlbmFyaW8uYmFzZUNvbnRleHQgPz8gKHt9IGFzIFRDb250ZXh0KTtcbiAgICBjb25zdCBwaGFzZUNvbnRleHQgPSBwaGFzZS5jb25maWcuY29udGV4dCA/PyAoe30gYXMgVENvbnRleHQpO1xuICAgIHJldHVybiB0aGlzLm1lcmdlQ29udGV4dHMoYmFzZUNvbnRleHQsIHBoYXNlQ29udGV4dCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWVyZ2VDb250ZXh0cyhhOiBUQ29udGV4dCwgYjogUGFydGlhbDxUQ29udGV4dD4pOiBUQ29udGV4dCB7XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIGEsIGIpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGV4ZWN1dGVTZWdtZW50KFxuICAgIGhhbmRsZXI6IFBlcmZvcm1hbmNlSGFuZGxlcjxUQ29udGV4dD4sXG4gICAgY29uZmlnOiBQaGFzZUNvbmZpZzxUQ29udGV4dD4sXG4gICAgY29udGV4dDogVENvbnRleHQsXG4gICAgaW5kaWNlczogbnVtYmVyW11cbiAgKTogUHJvbWlzZTxJdGVyYXRpb25NZXRyaWNbXT4ge1xuICAgIGlmICghaW5kaWNlcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLm1vZGUgPT09IFwiY29uY3VycmVudFwiKSB7XG4gICAgICByZXR1cm4gdGhpcy5jb2xsZWN0Q29uY3VycmVudChoYW5kbGVyLCBjb25maWcsIGNvbnRleHQsIGluZGljZXMpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNvbGxlY3RTZXF1ZW50aWFsKGhhbmRsZXIsIGNvbmZpZywgY29udGV4dCwgaW5kaWNlcyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgY29sbGVjdFNlcXVlbnRpYWwoXG4gICAgaGFuZGxlcjogUGVyZm9ybWFuY2VIYW5kbGVyPFRDb250ZXh0PixcbiAgICBjb25maWc6IFBoYXNlQ29uZmlnPFRDb250ZXh0PixcbiAgICBjb250ZXh0OiBUQ29udGV4dCxcbiAgICBpbmRpY2VzOiBudW1iZXJbXVxuICApOiBQcm9taXNlPEl0ZXJhdGlvbk1ldHJpY1tdPiB7XG4gICAgY29uc3QgbWV0cmljczogSXRlcmF0aW9uTWV0cmljW10gPSBbXTtcbiAgICBjb25zdCBkZWxheUJldHdlZW4gPSBjb25maWcuZGVsYXlCZXR3ZWVuSXRlcmF0aW9uc01zO1xuXG4gICAgZm9yIChsZXQgaWR4ID0gMDsgaWR4IDwgaW5kaWNlcy5sZW5ndGg7IGlkeCArPSAxKSB7XG4gICAgICBtZXRyaWNzLnB1c2goXG4gICAgICAgIGF3YWl0IHRoaXMucnVuSXRlcmF0aW9uKGhhbmRsZXIsIGNvbmZpZywgY29udGV4dCwgaW5kaWNlc1tpZHhdKVxuICAgICAgKTtcbiAgICAgIGlmIChkZWxheUJldHdlZW4gJiYgaWR4IDwgaW5kaWNlcy5sZW5ndGggLSAxKSB7XG4gICAgICAgIGF3YWl0IGRlbGF5KGRlbGF5QmV0d2Vlbik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG1ldHJpY3M7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgY29sbGVjdENvbmN1cnJlbnQoXG4gICAgaGFuZGxlcjogUGVyZm9ybWFuY2VIYW5kbGVyPFRDb250ZXh0PixcbiAgICBjb25maWc6IFBoYXNlQ29uZmlnPFRDb250ZXh0PixcbiAgICBjb250ZXh0OiBUQ29udGV4dCxcbiAgICBpbmRpY2VzOiBudW1iZXJbXVxuICApOiBQcm9taXNlPEl0ZXJhdGlvbk1ldHJpY1tdPiB7XG4gICAgY29uc3QgY29uY3VycmVuY3kgPSBNYXRoLm1heChcbiAgICAgIDEsXG4gICAgICBNYXRoLm1pbihjb25maWcuY29uY3VycmVuY3kgPz8gaW5kaWNlcy5sZW5ndGgsIGluZGljZXMubGVuZ3RoKVxuICAgICk7XG4gICAgY29uc3QgbWV0cmljczogSXRlcmF0aW9uTWV0cmljW10gPSBbXTtcbiAgICBsZXQgcG9pbnRlciA9IDA7XG5cbiAgICBjb25zdCB3b3JrZXIgPSBhc3luYyAoKSA9PiB7XG4gICAgICB3aGlsZSAocG9pbnRlciA8IGluZGljZXMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGl0ZXJhdGlvbiA9IGluZGljZXNbcG9pbnRlcl07XG4gICAgICAgIHBvaW50ZXIgKz0gMTtcbiAgICAgICAgbWV0cmljcy5wdXNoKFxuICAgICAgICAgIGF3YWl0IHRoaXMucnVuSXRlcmF0aW9uKGhhbmRsZXIsIGNvbmZpZywgY29udGV4dCwgaXRlcmF0aW9uKVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChBcnJheS5mcm9tKHsgbGVuZ3RoOiBjb25jdXJyZW5jeSB9LCAoKSA9PiB3b3JrZXIoKSkpO1xuICAgIHJldHVybiBtZXRyaWNzO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHJ1bkl0ZXJhdGlvbihcbiAgICBoYW5kbGVyOiBQZXJmb3JtYW5jZUhhbmRsZXI8VENvbnRleHQ+LFxuICAgIGNvbmZpZzogUGhhc2VDb25maWc8VENvbnRleHQ+LFxuICAgIGNvbnRleHQ6IFRDb250ZXh0LFxuICAgIGl0ZXJhdGlvbjogbnVtYmVyXG4gICk6IFByb21pc2U8SXRlcmF0aW9uTWV0cmljPiB7XG4gICAgY29uc3QgbG9hZEZhY3RvciA9IHRoaXMuY29tcHV0ZUxvYWRGYWN0b3IoY29uZmlnLCBpdGVyYXRpb24pO1xuICAgIGNvbnN0IHN0b3B3YXRjaCA9IG5ldyBTdG9wV2F0Y2godHJ1ZSk7XG4gICAgbGV0IHN1Y2Nlc3MgPSB0cnVlO1xuICAgIGxldCBtZXRhOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZDtcblxuICAgIGRlYnVnTG9nKFxuICAgICAgYFtQZXJmUnVubmVyXSBJdGVyYXRpb24gJHtpdGVyYXRpb259IChwaGFzZT0ke2NvbmZpZy5tZXRhZGF0YT8ucGhhc2VOYW1lID8/IFwibi9hXCJ9LCBsb2FkPSR7bG9hZEZhY3Rvci50b0ZpeGVkKFxuICAgICAgICAyXG4gICAgICApfSkgc3RhcnRpbmdgXG4gICAgKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgaGFuZGxlcih7IGl0ZXJhdGlvbiwgY29uZmlnLCBsb2FkRmFjdG9yLCBjb250ZXh0IH0pO1xuICAgICAgaWYgKHR5cGVvZiByZXN1bHQ/LnN1Y2Nlc3MgPT09IFwiYm9vbGVhblwiKSB7XG4gICAgICAgIHN1Y2Nlc3MgPSByZXN1bHQuc3VjY2VzcztcbiAgICAgIH1cbiAgICAgIG1ldGEgPSByZXN1bHQ/Lm1ldGE7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHN1Y2Nlc3MgPSBmYWxzZTtcbiAgICAgIG1ldGEgPSB7IGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcikgfTtcbiAgICB9XG5cbiAgICBjb25zdCBkdXJhdGlvbk1zID0gc3RvcHdhdGNoLnN0b3AoKTtcbiAgICBkZWJ1Z0xvZyhcbiAgICAgIGBbUGVyZlJ1bm5lcl0gSXRlcmF0aW9uICR7aXRlcmF0aW9ufSBjb21wbGV0ZSBpbiAke2R1cmF0aW9uTXMudG9GaXhlZCgyKX1tcywgc3VjY2Vzcz0ke3N1Y2Nlc3N9YFxuICAgICk7XG4gICAgcmV0dXJuIHsgaXRlcmF0aW9uLCBkdXJhdGlvbk1zLCBzdWNjZXNzLCBtZXRhLCBsb2FkRmFjdG9yIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYWdncmVnYXRlTWV0cmljcyhtZXRyaWNzOiBJdGVyYXRpb25NZXRyaWNbXSk6IEFnZ3JlZ2F0ZWRNZXRyaWNzIHtcbiAgICBpZiAobWV0cmljcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHRvdGFsRHVyYXRpb25NczogMCxcbiAgICAgICAgbWluTXM6IDAsXG4gICAgICAgIG1heE1zOiAwLFxuICAgICAgICBhdmVyYWdlTXM6IDAsXG4gICAgICAgIHN1Y2Nlc3NDb3VudDogMCxcbiAgICAgICAgZmFpbHVyZUNvdW50OiAwLFxuICAgICAgICBsb2FkU3RhcnQ6IDAsXG4gICAgICAgIGxvYWRFbmQ6IDAsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHRvdGFsRHVyYXRpb25NcyA9IG1ldHJpY3MucmVkdWNlKFxuICAgICAgKGFjYywgbWV0cmljKSA9PiBhY2MgKyBtZXRyaWMuZHVyYXRpb25NcyxcbiAgICAgIDBcbiAgICApO1xuICAgIGNvbnN0IG1pbk1zID0gTWF0aC5taW4oLi4ubWV0cmljcy5tYXAoKG1ldHJpYykgPT4gbWV0cmljLmR1cmF0aW9uTXMpKTtcbiAgICBjb25zdCBtYXhNcyA9IE1hdGgubWF4KC4uLm1ldHJpY3MubWFwKChtZXRyaWMpID0+IG1ldHJpYy5kdXJhdGlvbk1zKSk7XG4gICAgY29uc3QgYXZlcmFnZU1zID0gdG90YWxEdXJhdGlvbk1zIC8gbWV0cmljcy5sZW5ndGg7XG4gICAgY29uc3Qgc3VjY2Vzc0NvdW50ID0gbWV0cmljcy5maWx0ZXIoKG1ldHJpYykgPT4gbWV0cmljLnN1Y2Nlc3MpLmxlbmd0aDtcbiAgICBjb25zdCBmYWlsdXJlQ291bnQgPSBtZXRyaWNzLmxlbmd0aCAtIHN1Y2Nlc3NDb3VudDtcbiAgICBjb25zdCBsb2FkU3RhcnQgPSBtZXRyaWNzWzBdPy5sb2FkRmFjdG9yID8/IDA7XG4gICAgY29uc3QgbG9hZEVuZCA9IG1ldHJpY3NbbWV0cmljcy5sZW5ndGggLSAxXT8ubG9hZEZhY3RvciA/PyBsb2FkU3RhcnQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdG90YWxEdXJhdGlvbk1zLFxuICAgICAgbWluTXMsXG4gICAgICBtYXhNcyxcbiAgICAgIGF2ZXJhZ2VNcyxcbiAgICAgIHN1Y2Nlc3NDb3VudCxcbiAgICAgIGZhaWx1cmVDb3VudCxcbiAgICAgIGxvYWRTdGFydCxcbiAgICAgIGxvYWRFbmQsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBsb2dTdW1tYXJ5KHJlc3VsdHM6IFBoYXNlUmVzdWx0PFRDb250ZXh0PltdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFyZXN1bHRzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWRlcnMgPSBbXG4gICAgICBcIlBoYXNlXCIsXG4gICAgICBcIk1vZGVcIixcbiAgICAgIFwiSXRlcmF0aW9uc1wiLFxuICAgICAgXCJUb3RhbCBtc1wiLFxuICAgICAgXCJBdmcgbXNcIixcbiAgICAgIFwiTWluIG1zXCIsXG4gICAgICBcIk1heCBtc1wiLFxuICAgICAgXCJTdWNjZXNzXCIsXG4gICAgICBcIkZhaWx1cmVzXCIsXG4gICAgICBcIkxvYWQgcmFuZ2VcIixcbiAgICBdO1xuXG4gICAgY29uc3Qgcm93cyA9IHJlc3VsdHMubWFwKChyZXN1bHQpID0+IFtcbiAgICAgIHJlc3VsdC5waGFzZS5uYW1lLFxuICAgICAgcmVzdWx0LmNvbmZpZy5tb2RlLFxuICAgICAgcmVzdWx0LmNvbmZpZy5pdGVyYXRpb25zLnRvU3RyaW5nKCksXG4gICAgICByZXN1bHQuYWdncmVnYXRlZC50b3RhbER1cmF0aW9uTXMudG9GaXhlZCgyKSxcbiAgICAgIHJlc3VsdC5hZ2dyZWdhdGVkLmF2ZXJhZ2VNcy50b0ZpeGVkKDIpLFxuICAgICAgcmVzdWx0LmFnZ3JlZ2F0ZWQubWluTXMudG9GaXhlZCgyKSxcbiAgICAgIHJlc3VsdC5hZ2dyZWdhdGVkLm1heE1zLnRvRml4ZWQoMiksXG4gICAgICByZXN1bHQuYWdncmVnYXRlZC5zdWNjZXNzQ291bnQudG9TdHJpbmcoKSxcbiAgICAgIHJlc3VsdC5hZ2dyZWdhdGVkLmZhaWx1cmVDb3VudC50b1N0cmluZygpLFxuICAgICAgYCR7cmVzdWx0LmFnZ3JlZ2F0ZWQubG9hZFN0YXJ0LnRvRml4ZWQoMil9IOKGkiAke3Jlc3VsdC5hZ2dyZWdhdGVkLmxvYWRFbmQudG9GaXhlZCgyKX1gLFxuICAgIF0pO1xuXG4gICAgY29uc29sZS5sb2coXG4gICAgICBmb3JtYXRUYWJsZShcbiAgICAgICAgYFBlcmZvcm1hbmNlIHN1bW1hcnkgZm9yICR7dGhpcy5zY2VuYXJpby5uYW1lfWAsXG4gICAgICAgIGhlYWRlcnMsXG4gICAgICAgIHJvd3NcbiAgICAgIClcbiAgICApO1xuXG4gICAgaWYgKHRoaXMuc2hvdWxkUmVuZGVyQ2FudmFzKCkpIHtcbiAgICAgIGNvbnN0IGNoYXJ0UGF0aCA9XG4gICAgICAgIHRoaXMuc2NlbmFyaW8uY2FudmFzT3V0cHV0UGF0aCA/P1xuICAgICAgICBwYXRoLmpvaW4oXG4gICAgICAgICAgcHJvY2Vzcy5jd2QoKSxcbiAgICAgICAgICBcIndvcmtkb2NzXCIsXG4gICAgICAgICAgXCJyZXBvcnRzXCIsXG4gICAgICAgICAgXCJwZXJmb3JtYW5jZS1ydW5uZXIucG5nXCJcbiAgICAgICAgKTtcbiAgICAgIGF3YWl0IHJlbmRlck1ldHJpY3NUYWJsZVRvQ2FudmFzKFxuICAgICAgICBoZWFkZXJzLFxuICAgICAgICByb3dzLFxuICAgICAgICB0aGlzLnNjZW5hcmlvLmNhbnZhc09wdGlvbnMgPz8gZGVmYXVsdENhbnZhc09wdGlvbnMsXG4gICAgICAgIGNoYXJ0UGF0aFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgc2hvdWxkUmVuZGVyQ2FudmFzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnNjZW5hcmlvLmVuYWJsZUNhbnZhcyA/PyBCb29sZWFuKHRoaXMuc2NlbmFyaW8uY2FudmFzT3B0aW9ucyk7XG4gIH1cbn1cbiIsImltcG9ydCB7IENvbW1hbmQgfSBmcm9tIFwiLi4vY29tbWFuZFwiO1xuaW1wb3J0IHsgQ29tbWFuZE9wdGlvbnMgfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IERlZmF1bHRDb21tYW5kT3B0aW9ucywgRGVmYXVsdENvbW1hbmRWYWx1ZXMgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQge1xuICBjb3B5RmlsZSxcbiAgZGVsZXRlUGF0aCxcbiAgZ2V0QWxsRmlsZXMsXG4gIGdldFBhY2thZ2UsXG4gIHBhdGNoRmlsZSxcbiAgcmVuYW1lRmlsZSxcbiAgcnVuQ29tbWFuZCxcbiAgZ2V0RmlsZVNpemVaaXBwZWQsXG4gIGxpc3ROb2RlTW9kdWxlc1BhY2thZ2VzLFxufSBmcm9tIFwiLi4vLi4vdXRpbHNcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBJbnB1dE9wdGlvbnMsIE91dHB1dE9wdGlvbnMsIHJvbGx1cCwgUm9sbHVwQnVpbGQgfSBmcm9tIFwicm9sbHVwXCI7XG5pbXBvcnQgdHlwZXNjcmlwdCBmcm9tIFwiQHJvbGx1cC9wbHVnaW4tdHlwZXNjcmlwdFwiO1xuaW1wb3J0IGNvbW1vbmpzIGZyb20gXCJAcm9sbHVwL3BsdWdpbi1jb21tb25qc1wiO1xuaW1wb3J0IHsgbm9kZVJlc29sdmUgfSBmcm9tIFwiQHJvbGx1cC9wbHVnaW4tbm9kZS1yZXNvbHZlXCI7XG5pbXBvcnQganNvbiBmcm9tIFwiQHJvbGx1cC9wbHVnaW4tanNvblwiO1xuaW1wb3J0IHsgYnVpbHRpbk1vZHVsZXMgfSBmcm9tIFwibW9kdWxlXCI7XG5pbXBvcnQgeyBMb2dnaW5nQ29uZmlnLCBMb2dMZXZlbCB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG4vLyBkZWNsYXJlIG9wdGlvbmFsIHRlcnNlciBtb2R1bGUgdG8gc2F0aXNmeSBUeXBlU2NyaXB0IHdoZW4gdHlwZXMgYXJlbid0IGluc3RhbGxlZFxuZGVjbGFyZSBtb2R1bGUgXCJAcm9sbHVwL3BsdWdpbi10ZXJzZXJcIjtcblxuaW1wb3J0ICogYXMgdHMgZnJvbSBcInR5cGVzY3JpcHRcIjtcbmltcG9ydCB7IERpYWdub3N0aWMsIEVtaXRSZXN1bHQsIE1vZHVsZUtpbmQsIFNvdXJjZUZpbGUgfSBmcm9tIFwidHlwZXNjcmlwdFwiO1xuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VMaXN0KGlucHV0Pzogc3RyaW5nIHwgc3RyaW5nW10pOiBzdHJpbmdbXSB7XG4gIGlmICghaW5wdXQpIHJldHVybiBbXTtcbiAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpKVxuICAgIHJldHVybiBpbnB1dC5tYXAoKGkpID0+IGAke2l9YC50cmltKCkpLmZpbHRlcihCb29sZWFuKTtcbiAgcmV0dXJuIGAke2lucHV0fWBcbiAgICAuc3BsaXQoXCIsXCIpXG4gICAgLm1hcCgocCkgPT4gcC50cmltKCkpXG4gICAgLmZpbHRlcihCb29sZWFuKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhY2thZ2VUb0dsb2JhbChuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAvLyBSZW1vdmUgc2NvcGUgYW5kIHNwbGl0IGJ5IG5vbi1hbHBoYW51bWVyaWMgY2hhcnMsIHRoZW4gY2FtZWxDYXNlXG4gIGNvbnN0IHdpdGhvdXRTY29wZSA9IG5hbWUucmVwbGFjZSgvXkAvLCBcIlwiKTtcbiAgY29uc3QgcGFydHMgPSB3aXRob3V0U2NvcGUuc3BsaXQoL1svXFwtXy5dKy8pLmZpbHRlcihCb29sZWFuKTtcbiAgcmV0dXJuIHBhcnRzXG4gICAgLm1hcCgocCwgaSkgPT5cbiAgICAgIGkgPT09IDBcbiAgICAgICAgPyBwLnJlcGxhY2UoL1teYS16QS1aMC05XS9nLCBcIlwiKVxuICAgICAgICA6IGAke3AuY2hhckF0KDApLnRvVXBwZXJDYXNlKCl9JHtwLnNsaWNlKDEpfWBcbiAgICApXG4gICAgLmpvaW4oXCJcIik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQYWNrYWdlRGVwZW5kZW5jaWVzKCk6IHN0cmluZ1tdIHtcbiAgLy8gVHJ5IHRoZSBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5IGZpcnN0XG4gIGxldCBwa2c6IGFueTtcbiAgdHJ5IHtcbiAgICBwa2cgPSBnZXRQYWNrYWdlKHByb2Nlc3MuY3dkKCkpIGFzIGFueTtcbiAgfSBjYXRjaCB7XG4gICAgcGtnID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLy8gSWYgbm8gZGVwZW5kZW5jaWVzIGZvdW5kIGluIGN3ZCwgdHJ5IHRoZSBwYWNrYWdlIG5leHQgdG8gdGhpcyBzb3VyY2UgZmlsZSAoZmFsbGJhY2sgZm9yIHRlc3RzKVxuICB0cnkge1xuICAgIGNvbnN0IGhhc0RlcHMgPVxuICAgICAgcGtnICYmXG4gICAgICAoT2JqZWN0LmtleXMocGtnLmRlcGVuZGVuY2llcyB8fCB7fSkubGVuZ3RoID4gMCB8fFxuICAgICAgICBPYmplY3Qua2V5cyhwa2cuZGV2RGVwZW5kZW5jaWVzIHx8IHt9KS5sZW5ndGggPiAwIHx8XG4gICAgICAgIE9iamVjdC5rZXlzKHBrZy5wZWVyRGVwZW5kZW5jaWVzIHx8IHt9KS5sZW5ndGggPiAwKTtcbiAgICBpZiAoIWhhc0RlcHMpIHtcbiAgICAgIGNvbnN0IGZhbGxiYWNrRGlyID0gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgXCIuLi8uLi8uLlwiKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIHBrZyA9IGdldFBhY2thZ2UoZmFsbGJhY2tEaXIpIGFzIGFueTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBpZ25vcmUgYW5kIGtlZXAgcGtnIGFzLWlzXG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIHtcbiAgICAvLyBpZ25vcmVcbiAgfVxuXG4gIGNvbnN0IGRlcHMgPSBPYmplY3Qua2V5cygocGtnICYmIHBrZy5kZXBlbmRlbmNpZXMpIHx8IHt9KTtcbiAgY29uc3QgcGVlciA9IE9iamVjdC5rZXlzKChwa2cgJiYgcGtnLnBlZXJEZXBlbmRlbmNpZXMpIHx8IHt9KTtcbiAgY29uc3QgZGV2ID0gT2JqZWN0LmtleXMoKHBrZyAmJiBwa2cuZGV2RGVwZW5kZW5jaWVzKSB8fCB7fSk7XG4gIHJldHVybiBBcnJheS5mcm9tKG5ldyBTZXQoWy4uLmRlcHMsIC4uLnBlZXIsIC4uLmRldl0pKTtcbn1cblxuY29uc3QgVkVSU0lPTl9TVFJJTkcgPSBcIiMjVkVSU0lPTiMjXCI7XG5jb25zdCBQQUNLQUdFX1NUUklORyA9IFwiIyNQQUNLQUdFIyNcIjtcbmNvbnN0IFBBQ0tBR0VfU0laRV9TVFJJTkcgPSBcIiMjUEFDS0FHRV9TSVpFIyNcIjtcblxuZW51bSBNb2RlcyB7XG4gIENKUyA9IFwiY29tbW9uanNcIixcbiAgRVNNID0gXCJlczIwMjJcIixcbn1cblxuZW51bSBCdWlsZE1vZGUge1xuICBCVUlMRCA9IFwiYnVpbGRcIixcbiAgQlVORExFID0gXCJidW5kbGVcIixcbiAgQUxMID0gXCJhbGxcIixcbn1cblxuY29uc3Qgb3B0aW9ucyA9IHtcbiAgcHJvZDoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBkZXY6IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgYnVpbGRNb2RlOiB7XG4gICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICBkZWZhdWx0OiBCdWlsZE1vZGUuQUxMLFxuICB9LFxuICBpbmNsdWRlczoge1xuICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgZGVmYXVsdDogXCJcIixcbiAgfSxcbiAgZXh0ZXJuYWxzOiB7XG4gICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICBkZWZhdWx0OiBcIlwiLFxuICB9LFxuICBkb2NzOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG4gIGNvbW1hbmRzOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG4gIGVudHJ5OiB7XG4gICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICBkZWZhdWx0OiBcIi4vc3JjL2luZGV4LnRzXCIsXG4gIH0sXG4gIGJhbm5lcjoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxufTtcblxuY29uc3QgY2pzMlRyYW5zZm9ybWVyID0gKGV4dCA9IFwiLmNqc1wiKSA9PiB7XG4gIGNvbnN0IGxvZyA9IEJ1aWxkU2NyaXB0cy5sb2cuZm9yKGNqczJUcmFuc2Zvcm1lcik7XG4gIGNvbnN0IHJlc29sdXRpb25DYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG5cbiAgcmV0dXJuICh0cmFuc2Zvcm1hdGlvbkNvbnRleHQ6IHRzLlRyYW5zZm9ybWF0aW9uQ29udGV4dCkgPT4ge1xuICAgIHJldHVybiAoc291cmNlRmlsZTogdHMuU291cmNlRmlsZSkgPT4ge1xuICAgICAgY29uc3Qgc291cmNlRGlyID0gcGF0aC5kaXJuYW1lKHNvdXJjZUZpbGUuZmlsZU5hbWUpO1xuXG4gICAgICBmdW5jdGlvbiByZXNvbHZlUGF0aChpbXBvcnRQYXRoOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgY2FjaGVLZXkgPSBKU09OLnN0cmluZ2lmeShbc291cmNlRGlyLCBpbXBvcnRQYXRoXSk7XG4gICAgICAgIGNvbnN0IGNhY2hlZFZhbHVlID0gcmVzb2x1dGlvbkNhY2hlLmdldChjYWNoZUtleSk7XG4gICAgICAgIGlmIChjYWNoZWRWYWx1ZSAhPSBudWxsKSByZXR1cm4gY2FjaGVkVmFsdWU7XG5cbiAgICAgICAgbGV0IHJlc29sdmVkUGF0aCA9IGltcG9ydFBhdGg7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmVzb2x2ZWRQYXRoID0gcGF0aC5yZXNvbHZlKHNvdXJjZURpciwgcmVzb2x2ZWRQYXRoICsgXCIudHNcIik7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcmVzb2x2ZSBwYXRoICR7aW1wb3J0UGF0aH06ICR7ZXJyb3J9YCk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHN0YXQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgc3RhdCA9IGZzLnN0YXRTeW5jKHJlc29sdmVkUGF0aCk7XG4gICAgICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgbG9nLnZlcmJvc2UoXG4gICAgICAgICAgICAgIGBUZXN0aW5nIGV4aXN0ZW5jZSBvZiBwYXRoICR7cmVzb2x2ZWRQYXRofSBhcyBhIGZvbGRlciBkZWZhdWx0aW5nIHRvIGluZGV4IGZpbGVgXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgc3RhdCA9IGZzLnN0YXRTeW5jKHJlc29sdmVkUGF0aC5yZXBsYWNlKC9cXC50cyQvZ20sIFwiXCIpKTtcbiAgICAgICAgICB9IGNhdGNoIChlMjogdW5rbm93bikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICBgRmFpbGVkIHRvIHJlc29sdmUgcGF0aCAke2ltcG9ydFBhdGh9OiAke2V9LCAke2UyfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzdGF0LmlzRGlyZWN0b3J5KCkpXG4gICAgICAgICAgcmVzb2x2ZWRQYXRoID0gcmVzb2x2ZWRQYXRoLnJlcGxhY2UoL1xcLnRzJC9nbSwgXCIvaW5kZXgudHNcIik7XG5cbiAgICAgICAgaWYgKHBhdGguaXNBYnNvbHV0ZShyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgY29uc3QgZXh0ZW5zaW9uID1cbiAgICAgICAgICAgICgvXFwudHN4PyQvLmV4ZWMocGF0aC5iYXNlbmFtZShyZXNvbHZlZFBhdGgpKSB8fCBbXSlbMF0gfHwgdm9pZCAwO1xuXG4gICAgICAgICAgcmVzb2x2ZWRQYXRoID1cbiAgICAgICAgICAgIFwiLi9cIiArXG4gICAgICAgICAgICBwYXRoLnJlbGF0aXZlKFxuICAgICAgICAgICAgICBzb3VyY2VEaXIsXG4gICAgICAgICAgICAgIHBhdGgucmVzb2x2ZShcbiAgICAgICAgICAgICAgICBwYXRoLmRpcm5hbWUocmVzb2x2ZWRQYXRoKSxcbiAgICAgICAgICAgICAgICBwYXRoLmJhc2VuYW1lKHJlc29sdmVkUGF0aCwgZXh0ZW5zaW9uKSArIGV4dFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzb2x1dGlvbkNhY2hlLnNldChjYWNoZUtleSwgcmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgcmV0dXJuIHJlc29sdmVkUGF0aDtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gdmlzaXROb2RlKG5vZGU6IHRzLk5vZGUpOiB0cy5WaXNpdFJlc3VsdDx0cy5Ob2RlPiB7XG4gICAgICAgIGlmIChzaG91bGRNdXRhdGVNb2R1bGVTcGVjaWZpZXIobm9kZSkpIHtcbiAgICAgICAgICBpZiAodHMuaXNJbXBvcnREZWNsYXJhdGlvbihub2RlKSkge1xuICAgICAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID0gcmVzb2x2ZVBhdGgobm9kZS5tb2R1bGVTcGVjaWZpZXIudGV4dCk7XG4gICAgICAgICAgICBjb25zdCBuZXdNb2R1bGVTcGVjaWZpZXIgPVxuICAgICAgICAgICAgICB0cmFuc2Zvcm1hdGlvbkNvbnRleHQuZmFjdG9yeS5jcmVhdGVTdHJpbmdMaXRlcmFsKHJlc29sdmVkUGF0aCk7XG4gICAgICAgICAgICByZXR1cm4gdHJhbnNmb3JtYXRpb25Db250ZXh0LmZhY3RvcnkudXBkYXRlSW1wb3J0RGVjbGFyYXRpb24oXG4gICAgICAgICAgICAgIG5vZGUsXG4gICAgICAgICAgICAgIG5vZGUubW9kaWZpZXJzLFxuICAgICAgICAgICAgICBub2RlLmltcG9ydENsYXVzZSxcbiAgICAgICAgICAgICAgbmV3TW9kdWxlU3BlY2lmaWVyLFxuICAgICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmICh0cy5pc0V4cG9ydERlY2xhcmF0aW9uKG5vZGUpKSB7XG4gICAgICAgICAgICBjb25zdCByZXNvbHZlZFBhdGggPSByZXNvbHZlUGF0aChub2RlLm1vZHVsZVNwZWNpZmllci50ZXh0KTtcbiAgICAgICAgICAgIGNvbnN0IG5ld01vZHVsZVNwZWNpZmllciA9XG4gICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uQ29udGV4dC5mYWN0b3J5LmNyZWF0ZVN0cmluZ0xpdGVyYWwocmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgICAgIHJldHVybiB0cmFuc2Zvcm1hdGlvbkNvbnRleHQuZmFjdG9yeS51cGRhdGVFeHBvcnREZWNsYXJhdGlvbihcbiAgICAgICAgICAgICAgbm9kZSxcbiAgICAgICAgICAgICAgbm9kZS5tb2RpZmllcnMsXG4gICAgICAgICAgICAgIG5vZGUuaXNUeXBlT25seSxcbiAgICAgICAgICAgICAgbm9kZS5leHBvcnRDbGF1c2UsXG4gICAgICAgICAgICAgIG5ld01vZHVsZVNwZWNpZmllcixcbiAgICAgICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cy52aXNpdEVhY2hDaGlsZChub2RlLCB2aXNpdE5vZGUsIHRyYW5zZm9ybWF0aW9uQ29udGV4dCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHNob3VsZE11dGF0ZU1vZHVsZVNwZWNpZmllcihub2RlOiB0cy5Ob2RlKTogbm9kZSBpcyAoXG4gICAgICAgIHwgdHMuSW1wb3J0RGVjbGFyYXRpb25cbiAgICAgICAgfCB0cy5FeHBvcnREZWNsYXJhdGlvblxuICAgICAgKSAmIHtcbiAgICAgICAgbW9kdWxlU3BlY2lmaWVyOiB0cy5TdHJpbmdMaXRlcmFsO1xuICAgICAgfSB7XG4gICAgICAgIGlmICghdHMuaXNJbXBvcnREZWNsYXJhdGlvbihub2RlKSAmJiAhdHMuaXNFeHBvcnREZWNsYXJhdGlvbihub2RlKSlcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgaWYgKG5vZGUubW9kdWxlU3BlY2lmaWVyID09PSB1bmRlZmluZWQpIHJldHVybiBmYWxzZTtcbiAgICAgICAgLy8gb25seSB3aGVuIG1vZHVsZSBzcGVjaWZpZXIgaXMgdmFsaWRcbiAgICAgICAgaWYgKCF0cy5pc1N0cmluZ0xpdGVyYWwobm9kZS5tb2R1bGVTcGVjaWZpZXIpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIC8vIG9ubHkgd2hlbiBwYXRoIGlzIHJlbGF0aXZlXG4gICAgICAgIGlmIChcbiAgICAgICAgICAhbm9kZS5tb2R1bGVTcGVjaWZpZXIudGV4dC5zdGFydHNXaXRoKFwiLi9cIikgJiZcbiAgICAgICAgICAhbm9kZS5tb2R1bGVTcGVjaWZpZXIudGV4dC5zdGFydHNXaXRoKFwiLi4vXCIpXG4gICAgICAgIClcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIC8vIG9ubHkgd2hlbiBtb2R1bGUgc3BlY2lmaWVyIGhhcyBubyBleHRlbnNpb25cbiAgICAgICAgaWYgKHBhdGguZXh0bmFtZShub2RlLm1vZHVsZVNwZWNpZmllci50ZXh0KSAhPT0gXCJcIikgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRzLnZpc2l0Tm9kZShzb3VyY2VGaWxlLCB2aXNpdE5vZGUpIGFzIFNvdXJjZUZpbGU7XG4gICAgfTtcbiAgfTtcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgY29tbWFuZC1saW5lIHNjcmlwdCBmb3IgYnVpbGRpbmcgYW5kIGJ1bmRsaW5nIFR5cGVTY3JpcHQgcHJvamVjdHMuXG4gKiBAc3VtbWFyeSBUaGlzIGNsYXNzIHByb3ZpZGVzIGEgY29tcHJlaGVuc2l2ZSBidWlsZCBzY3JpcHQgdGhhdCBoYW5kbGVzIFR5cGVTY3JpcHQgY29tcGlsYXRpb24sXG4gKiBidW5kbGluZyB3aXRoIFJvbGx1cCwgYW5kIGRvY3VtZW50YXRpb24gZ2VuZXJhdGlvbi4gSXQgc3VwcG9ydHMgZGlmZmVyZW50IGJ1aWxkIG1vZGVzXG4gKiAoZGV2ZWxvcG1lbnQsIHByb2R1Y3Rpb24pLCBtb2R1bGUgZm9ybWF0cyAoQ0pTLCBFU00pLCBhbmQgY2FuIGJlIGV4dGVuZGVkIHdpdGggY3VzdG9tXG4gKiBjb25maWd1cmF0aW9ucy5cbiAqIEBjbGFzcyBCdWlsZFNjcmlwdHNcbiAqL1xuZXhwb3J0IGNsYXNzIEJ1aWxkU2NyaXB0cyBleHRlbmRzIENvbW1hbmQ8XG4gIENvbW1hbmRPcHRpb25zPHR5cGVvZiBvcHRpb25zPixcbiAgdm9pZFxuPiB7XG4gIHByaXZhdGUgcmVwbGFjZW1lbnRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gIHByaXZhdGUgcmVhZG9ubHkgcGtnVmVyc2lvbjogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IHBrZ05hbWU6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihcbiAgICAgIFwiQnVpbGRTY3JpcHRzXCIsXG4gICAgICBPYmplY3QuYXNzaWduKHt9LCBEZWZhdWx0Q29tbWFuZE9wdGlvbnMsIG9wdGlvbnMpIGFzIENvbW1hbmRPcHRpb25zPFxuICAgICAgICB0eXBlb2Ygb3B0aW9uc1xuICAgICAgPlxuICAgICk7XG4gICAgY29uc3QgcGtnID0gZ2V0UGFja2FnZSgpIGFzIHsgbmFtZTogc3RyaW5nOyB2ZXJzaW9uOiBzdHJpbmcgfTtcbiAgICBjb25zdCB7IG5hbWUsIHZlcnNpb24gfSA9IHBrZztcbiAgICB0aGlzLnBrZ05hbWUgPSBuYW1lLmluY2x1ZGVzKFwiQFwiKSA/IG5hbWUuc3BsaXQoXCIvXCIpWzFdIDogbmFtZTtcbiAgICB0aGlzLnBrZ1ZlcnNpb24gPSB2ZXJzaW9uO1xuICAgIHRoaXMucmVwbGFjZW1lbnRzW1ZFUlNJT05fU1RSSU5HXSA9IHRoaXMucGtnVmVyc2lvbjtcbiAgICB0aGlzLnJlcGxhY2VtZW50c1tQQUNLQUdFX1NUUklOR10gPSBuYW1lO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQYXRjaGVzIGZpbGVzIHdpdGggdmVyc2lvbiBhbmQgcGFja2FnZSBuYW1lLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCByZWFkcyBhbGwgZmlsZXMgaW4gYSBkaXJlY3RvcnksIGZpbmRzIHBsYWNlaG9sZGVycyBmb3IgdmVyc2lvblxuICAgKiBhbmQgcGFja2FnZSBuYW1lLCBhbmQgcmVwbGFjZXMgdGhlbSB3aXRoIHRoZSBhY3R1YWwgdmFsdWVzIGZyb20gcGFja2FnZS5qc29uLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcCAtIFRoZSBwYXRoIHRvIHRoZSBkaXJlY3RvcnkgY29udGFpbmluZyB0aGUgZmlsZXMgdG8gcGF0Y2guXG4gICAqL1xuICBwYXRjaEZpbGVzKHA6IHN0cmluZykge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnBhdGNoRmlsZXMpO1xuICAgIGNvbnN0IHsgbmFtZSwgdmVyc2lvbiB9ID0gZ2V0UGFja2FnZSgpIGFzIGFueTtcbiAgICBsb2cuaW5mbyhgUGF0Y2hpbmcgJHtuYW1lfSAke3ZlcnNpb259IG1vZHVsZSBpbiAke3B9Li4uYCk7XG4gICAgY29uc3Qgc3RhdCA9IGZzLnN0YXRTeW5jKHApO1xuICAgIGlmIChzdGF0LmlzRGlyZWN0b3J5KCkpXG4gICAgICBmcy5yZWFkZGlyU3luYyhwLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUsIHJlY3Vyc2l2ZTogdHJ1ZSB9KVxuICAgICAgICAuZmlsdGVyKChwKSA9PiBwLmlzRmlsZSgpKVxuICAgICAgICAuZm9yRWFjaCgoZmlsZSkgPT5cbiAgICAgICAgICBwYXRjaEZpbGUoXG4gICAgICAgICAgICBwYXRoLmpvaW4oZmlsZS5wYXJlbnRQYXRoLCBmaWxlLm5hbWUpLFxuICAgICAgICAgICAgT2JqZWN0LmVudHJpZXModGhpcy5yZXBsYWNlbWVudHMpLnJlZHVjZShcbiAgICAgICAgICAgICAgKGFjYzogUmVjb3JkPHN0cmluZywgYW55PiwgW2tleSwgdmFsXSkgPT4ge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgICAgICAgICAgICBjYXNlIFZFUlNJT05fU1RSSU5HOlxuICAgICAgICAgICAgICAgICAgICBsb2cuZGVidWcoXCJGb3VuZCBWRVJTSU9OIHN0cmluZyB0byByZXBsYWNlXCIpO1xuICAgICAgICAgICAgICAgICAgICBhY2NbYFZFUlNJT04gPSBcIiR7VkVSU0lPTl9TVFJJTkd9XCI7YF0gPVxuICAgICAgICAgICAgICAgICAgICAgIGBWRVJTSU9OID0gXCIke3ZhbH1cIjtgO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgIGNhc2UgUEFDS0FHRV9TVFJJTkc6XG4gICAgICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIkZvdW5kIFBBQ0tBR0VfTkFNRSBzdHJpbmcgdG8gcmVwbGFjZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgYWNjW2BQQUNLQUdFX05BTUUgPSBcIiR7UEFDS0FHRV9TVFJJTkd9XCI7YF0gPVxuICAgICAgICAgICAgICAgICAgICAgIGBQQUNLQUdFX05BTUUgPSBcIiR7dmFsfVwiO2A7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgYWNjW2tleV0gPSB2YWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHt9XG4gICAgICAgICAgICApXG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgIGxvZy52ZXJib3NlKGBNb2R1bGUgJHtuYW1lfSAke3ZlcnNpb259IHBhdGNoZWQgaW4gJHtwfS4uLmApO1xuICB9XG5cbiAgcHJpdmF0ZSByZXBvcnREaWFnbm9zdGljcyhcbiAgICBkaWFnbm9zdGljczogRGlhZ25vc3RpY1tdLFxuICAgIGxvZ0xldmVsOiBMb2dMZXZlbFxuICApOiBzdHJpbmcge1xuICAgIGNvbnN0IG1zZyA9IHRoaXMuZm9ybWF0RGlhZ25vc3RpY3MoZGlhZ25vc3RpY3MpO1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmxvZ1tsb2dMZXZlbF0obXNnKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBjb25zb2xlLndhcm4oYEZhaWxlZCB0byBnZXQgbG9nZ2VyIGZvciAke2xvZ0xldmVsfWApO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gICAgcmV0dXJuIG1zZztcbiAgfVxuXG4gIC8vIEZvcm1hdCBkaWFnbm9zdGljcyBpbnRvIGEgc2luZ2xlIHN0cmluZyBmb3IgdGhyb3dpbmcgb3IgbG9nZ2luZ1xuICBwcml2YXRlIGZvcm1hdERpYWdub3N0aWNzKGRpYWdub3N0aWNzOiBEaWFnbm9zdGljW10pOiBzdHJpbmcge1xuICAgIHJldHVybiBkaWFnbm9zdGljc1xuICAgICAgLm1hcCgoZGlhZ25vc3RpYykgPT4ge1xuICAgICAgICBsZXQgbWVzc2FnZSA9IFwiXCI7XG4gICAgICAgIGlmIChkaWFnbm9zdGljLmZpbGUgJiYgZGlhZ25vc3RpYy5zdGFydCkge1xuICAgICAgICAgIGNvbnN0IHsgbGluZSwgY2hhcmFjdGVyIH0gPVxuICAgICAgICAgICAgZGlhZ25vc3RpYy5maWxlLmdldExpbmVBbmRDaGFyYWN0ZXJPZlBvc2l0aW9uKGRpYWdub3N0aWMuc3RhcnQpO1xuICAgICAgICAgIG1lc3NhZ2UgKz0gYCR7ZGlhZ25vc3RpYy5maWxlLmZpbGVOYW1lfSAoJHtsaW5lICsgMX0sJHtjaGFyYWN0ZXIgKyAxfSlgO1xuICAgICAgICB9XG4gICAgICAgIG1lc3NhZ2UgKz1cbiAgICAgICAgICBcIjogXCIgKyB0cy5mbGF0dGVuRGlhZ25vc3RpY01lc3NhZ2VUZXh0KGRpYWdub3N0aWMubWVzc2FnZVRleHQsIFwiXFxuXCIpO1xuICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgIH0pXG4gICAgICAuam9pbihcIlxcblwiKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZENvbmZpZ0ZpbGUoY29uZmlnRmlsZU5hbWU6IHN0cmluZykge1xuICAgIC8vIFJlYWQgY29uZmlnIGZpbGVcbiAgICBjb25zdCBjb25maWdGaWxlVGV4dCA9IGZzLnJlYWRGaWxlU3luYyhjb25maWdGaWxlTmFtZSkudG9TdHJpbmcoKTtcblxuICAgIC8vIFBhcnNlIEpTT04sIGFmdGVyIHJlbW92aW5nIGNvbW1lbnRzLiBKdXN0IGZhbmNpZXIgSlNPTi5wYXJzZVxuICAgIGNvbnN0IHJlc3VsdCA9IHRzLnBhcnNlQ29uZmlnRmlsZVRleHRUb0pzb24oY29uZmlnRmlsZU5hbWUsIGNvbmZpZ0ZpbGVUZXh0KTtcbiAgICBjb25zdCBjb25maWdPYmplY3QgPSByZXN1bHQuY29uZmlnO1xuICAgIGlmICghY29uZmlnT2JqZWN0KSB7XG4gICAgICB0aGlzLnJlcG9ydERpYWdub3N0aWNzKFtyZXN1bHQuZXJyb3IhXSwgTG9nTGV2ZWwuZXJyb3IpO1xuICAgIH1cblxuICAgIC8vIEV4dHJhY3QgY29uZmlnIGluZnJvbWF0aW9uXG4gICAgY29uc3QgY29uZmlnUGFyc2VSZXN1bHQgPSB0cy5wYXJzZUpzb25Db25maWdGaWxlQ29udGVudChcbiAgICAgIGNvbmZpZ09iamVjdCxcbiAgICAgIHRzLnN5cyxcbiAgICAgIHBhdGguZGlybmFtZShjb25maWdGaWxlTmFtZSlcbiAgICApO1xuICAgIGlmIChjb25maWdQYXJzZVJlc3VsdC5lcnJvcnMubGVuZ3RoID4gMClcbiAgICAgIHRoaXMucmVwb3J0RGlhZ25vc3RpY3MoY29uZmlnUGFyc2VSZXN1bHQuZXJyb3JzLCBMb2dMZXZlbC5lcnJvcik7XG5cbiAgICByZXR1cm4gY29uZmlnUGFyc2VSZXN1bHQ7XG4gIH1cblxuICBwcml2YXRlIGV2YWxEaWFnbm9zdGljcyhkaWFnbm9zdGljczogRGlhZ25vc3RpY1tdKSB7XG4gICAgaWYgKGRpYWdub3N0aWNzICYmIGRpYWdub3N0aWNzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGVycm9ycyA9IGRpYWdub3N0aWNzLmZpbHRlcihcbiAgICAgICAgKGQpID0+IGQuY2F0ZWdvcnkgPT09IHRzLkRpYWdub3N0aWNDYXRlZ29yeS5FcnJvclxuICAgICAgKTtcbiAgICAgIGNvbnN0IHdhcm5pbmdzID0gZGlhZ25vc3RpY3MuZmlsdGVyKFxuICAgICAgICAoZCkgPT4gZC5jYXRlZ29yeSA9PT0gdHMuRGlhZ25vc3RpY0NhdGVnb3J5Lldhcm5pbmdcbiAgICAgICk7XG4gICAgICBjb25zdCBzdWdnZXN0aW9ucyA9IGRpYWdub3N0aWNzLmZpbHRlcihcbiAgICAgICAgKGQpID0+IGQuY2F0ZWdvcnkgPT09IHRzLkRpYWdub3N0aWNDYXRlZ29yeS5TdWdnZXN0aW9uXG4gICAgICApO1xuICAgICAgY29uc3QgbWVzc2FnZXMgPSBkaWFnbm9zdGljcy5maWx0ZXIoXG4gICAgICAgIChkKSA9PiBkLmNhdGVnb3J5ID09PSB0cy5EaWFnbm9zdGljQ2F0ZWdvcnkuTWVzc2FnZVxuICAgICAgKTtcbiAgICAgIC8vIExvZyBkaWFnbm9zdGljcyB0byBjb25zb2xlXG5cbiAgICAgIGlmICh3YXJuaW5ncy5sZW5ndGgpIHRoaXMucmVwb3J0RGlhZ25vc3RpY3Mod2FybmluZ3MsIExvZ0xldmVsLndhcm4pO1xuICAgICAgaWYgKGVycm9ycy5sZW5ndGgpIHtcbiAgICAgICAgdGhpcy5yZXBvcnREaWFnbm9zdGljcyhkaWFnbm9zdGljcyBhcyBEaWFnbm9zdGljW10sIExvZ0xldmVsLmVycm9yKTtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBUeXBlU2NyaXB0IHJlcG9ydGVkICR7ZGlhZ25vc3RpY3MubGVuZ3RofSBkaWFnbm9zdGljKHMpIGR1cmluZyBjaGVjazsgYWJvcnRpbmcuYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgaWYgKHN1Z2dlc3Rpb25zLmxlbmd0aClcbiAgICAgICAgdGhpcy5yZXBvcnREaWFnbm9zdGljcyhzdWdnZXN0aW9ucywgTG9nTGV2ZWwuaW5mbyk7XG4gICAgICBpZiAobWVzc2FnZXMubGVuZ3RoKSB0aGlzLnJlcG9ydERpYWdub3N0aWNzKG1lc3NhZ2VzLCBMb2dMZXZlbC5pbmZvKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHByZUNoZWNrRGlhZ25vc3RpY3MocHJvZ3JhbTogdHMuUHJvZ3JhbSkge1xuICAgIGNvbnN0IGRpYWdub3N0aWNzID0gdHMuZ2V0UHJlRW1pdERpYWdub3N0aWNzKHByb2dyYW0pO1xuICAgIHRoaXMuZXZhbERpYWdub3N0aWNzKGRpYWdub3N0aWNzIGFzIGFueSk7XG4gIH1cblxuICAvLyBDcmVhdGUgYSBUeXBlU2NyaXB0IHByb2dyYW0gZm9yIHRoZSBjdXJyZW50IHRzY29uZmlnIGFuZCBmYWlsIGlmIHRoZXJlIGFyZSBhbnkgZXJyb3IgZGlhZ25vc3RpY3MuXG4gIHByaXZhdGUgYXN5bmMgY2hlY2tUc0RpYWdub3N0aWNzKFxuICAgIGlzRGV2OiBib29sZWFuLFxuICAgIG1vZGU6IE1vZGVzLFxuICAgIGJ1bmRsZSA9IGZhbHNlXG4gICkge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLmNoZWNrVHNEaWFnbm9zdGljcyk7XG4gICAgbGV0IHRzQ29uZmlnO1xuICAgIHRyeSB7XG4gICAgICB0c0NvbmZpZyA9IHRoaXMucmVhZENvbmZpZ0ZpbGUoXCIuL3RzY29uZmlnLmpzb25cIik7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcGFyc2UgdHNjb25maWcuanNvbjogJHtlfWApO1xuICAgIH1cblxuICAgIGlmIChidW5kbGUpIHtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMubW9kdWxlID0gTW9kdWxlS2luZC5BTUQ7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLm91dERpciA9IFwiZGlzdFwiO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5pc29sYXRlZE1vZHVsZXMgPSBmYWxzZTtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMub3V0RmlsZSA9IHRoaXMucGtnTmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdHNDb25maWcub3B0aW9ucy5vdXREaXIgPSBgbGliJHttb2RlID09PSBNb2Rlcy5FU00gPyBcIi9lc21cIiA6IFwiXCJ9YDtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMubW9kdWxlID1cbiAgICAgICAgbW9kZSA9PT0gTW9kZXMuRVNNID8gTW9kdWxlS2luZC5FUzIwMjIgOiBNb2R1bGVLaW5kLkNvbW1vbkpTO1xuICAgIH1cblxuICAgIC8vIEVuc3VyZSBUeXBlU2NyaXB0IGVtaXRzIGlubGluZSBzb3VyY2UgbWFwcyBmb3IgYm90aCBkZXYgYW5kIHByb2QgKGJ1bmRsZXJzIHdpbGwgY29udHJvbCBleHRlcm5hbCBtYXBzKVxuICAgIC8vIEtlZXAgY29tbWVudHMgaW4gVFMgZW1pdCBieSBkZWZhdWx0OyBidW5kbGluZy9taW5pZmljYXRpb24gd2lsbCBoYW5kbGUgcmVtb3ZhbCB3aGVyZSByZXF1ZXN0ZWQuXG4gICAgLy8gRW1pdCBleHRlcm5hbCBzb3VyY2UgbWFwcyBmcm9tIFR5cGVTY3JpcHQgc28gZWRpdG9ycy9kZWJ1Z2dlcnMgY2FuIGZpbmQgdGhlbS5cbiAgICAvLyBUdXJuIG9mZiBpbmxpbmUgbWFwcy9zb3VyY2VzIHNvIGJ1bmRsZXJzIChSb2xsdXApIGNhbiBjb250cm9sIHdoZXRoZXIgbWFwcyBhcmUgaW5saW5lZCBvciB3cml0dGVuIGV4dGVybmFsbHkuXG4gICAgdHNDb25maWcub3B0aW9ucy5pbmxpbmVTb3VyY2VNYXAgPSBmYWxzZTtcbiAgICB0c0NvbmZpZy5vcHRpb25zLmlubGluZVNvdXJjZXMgPSBmYWxzZTtcbiAgICB0c0NvbmZpZy5vcHRpb25zLnNvdXJjZU1hcCA9IHRydWU7XG5cbiAgICBjb25zdCBwcm9ncmFtID0gdHMuY3JlYXRlUHJvZ3JhbSh0c0NvbmZpZy5maWxlTmFtZXMsIHRzQ29uZmlnLm9wdGlvbnMpO1xuICAgIHRoaXMucHJlQ2hlY2tEaWFnbm9zdGljcyhwcm9ncmFtKTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBUeXBlU2NyaXB0IGNoZWNrcyBwYXNzZWQgKCR7YnVuZGxlID8gXCJidW5kbGVcIiA6IFwibm9ybWFsXCJ9IG1vZGUpLmBcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBidWlsZFRzKGlzRGV2OiBib29sZWFuLCBtb2RlOiBNb2RlcywgYnVuZGxlID0gZmFsc2UpIHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5idWlsZFRzKTtcbiAgICBsb2cuaW5mbyhcbiAgICAgIGBCdWlsZGluZyAke3RoaXMucGtnTmFtZX0gJHt0aGlzLnBrZ1ZlcnNpb259IG1vZHVsZSAoJHttb2RlfSkgaW4gJHtpc0RldiA/IFwiZGV2XCIgOiBcInByb2RcIn0gbW9kZS4uLmBcbiAgICApO1xuICAgIGxldCB0c0NvbmZpZztcbiAgICB0cnkge1xuICAgICAgdHNDb25maWcgPSB0aGlzLnJlYWRDb25maWdGaWxlKFwiLi90c2NvbmZpZy5qc29uXCIpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHBhcnNlIHRzY29uZmlnLmpzb246ICR7ZX1gKTtcbiAgICB9XG5cbiAgICBpZiAoYnVuZGxlKSB7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLm1vZHVsZSA9IE1vZHVsZUtpbmQuQU1EO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5vdXREaXIgPSBcImRpc3RcIjtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMuaXNvbGF0ZWRNb2R1bGVzID0gZmFsc2U7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLm91dEZpbGUgPSB0aGlzLnBrZ05hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMub3V0RGlyID0gYGxpYiR7bW9kZSA9PT0gTW9kZXMuRVNNID8gXCIvZXNtXCIgOiBcIlwifWA7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLm1vZHVsZSA9XG4gICAgICAgIG1vZGUgPT09IE1vZGVzLkVTTSA/IE1vZHVsZUtpbmQuRVMyMDIyIDogTW9kdWxlS2luZC5Db21tb25KUztcbiAgICB9XG5cbiAgICAvLyBBbHdheXMgZW1pdCBpbmxpbmUgc291cmNlIG1hcHMgZnJvbSB0c2MgKGJ1bmRsZXIgd2lsbCBlbWl0IGV4dGVybmFsIG1hcHMgZm9yIHByb2R1Y3Rpb24gYnVuZGxlcykuXG4gICAgLy8gRm9yIGRldiBidWlsZHMgd2Ugd2FudCBUeXBlU2NyaXB0IHRvIGVtaXQgaW5saW5lIHNvdXJjZSBtYXBzIHNvIG5vIHNlcGFyYXRlIC5tYXAgZmlsZXMgYXJlIHByb2R1Y2VkLlxuICAgIC8vIEZvciBwcm9kdWN0aW9uIHdlIGVtaXQgZXh0ZXJuYWwgc291cmNlIG1hcHMgc28gdGhlIGJ1bmRsZXIgY2FuIGZ1cnRoZXIgdHJhbnNmb3JtIGFuZCBlbWl0IHRoZW0uXG4gICAgaWYgKGlzRGV2KSB7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLmlubGluZVNvdXJjZU1hcCA9IHRydWU7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLmlubGluZVNvdXJjZXMgPSB0cnVlO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5zb3VyY2VNYXAgPSBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdHNDb25maWcub3B0aW9ucy5pbmxpbmVTb3VyY2VNYXAgPSBmYWxzZTtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMuaW5saW5lU291cmNlcyA9IGZhbHNlO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5zb3VyY2VNYXAgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIEZvciBwcm9kdWN0aW9uIGJ1aWxkcyB3ZSBzdGlsbCBrZWVwIFR5cGVTY3JpcHQgY29tbWVudHMgKHJlbW92ZUNvbW1lbnRzPWZhbHNlIGluIHRzY29uZmlnKVxuICAgIC8vIEJ1bmRsZXIvdGVyc2VyIHdpbGwgc3RyaXAgY29tbWVudHMgZm9yIHByb2R1Y3Rpb24gYnVuZGxlcyBhcyByZXF1ZXN0ZWQuXG5cbiAgICBjb25zdCBwcm9ncmFtID0gdHMuY3JlYXRlUHJvZ3JhbSh0c0NvbmZpZy5maWxlTmFtZXMsIHRzQ29uZmlnLm9wdGlvbnMpO1xuXG4gICAgY29uc3QgdHJhbnNmb3JtYXRpb25zOiB7IGJlZm9yZT86IGFueVtdIH0gPSB7fTtcbiAgICBpZiAobW9kZSA9PT0gTW9kZXMuQ0pTKSB7XG4gICAgICB0cmFuc2Zvcm1hdGlvbnMuYmVmb3JlID0gW2NqczJUcmFuc2Zvcm1lcihcIi5janNcIildO1xuICAgIH0gZWxzZSBpZiAobW9kZSA9PT0gTW9kZXMuRVNNKSB7XG4gICAgICB0cmFuc2Zvcm1hdGlvbnMuYmVmb3JlID0gW2NqczJUcmFuc2Zvcm1lcihcIi5qc1wiKV07XG4gICAgfVxuXG4gICAgY29uc3QgZW1pdFJlc3VsdDogRW1pdFJlc3VsdCA9IHByb2dyYW0uZW1pdChcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHRyYW5zZm9ybWF0aW9uc1xuICAgICk7XG5cbiAgICBjb25zdCBhbGxEaWFnbm9zdGljcyA9IHRzXG4gICAgICAuZ2V0UHJlRW1pdERpYWdub3N0aWNzKHByb2dyYW0pXG4gICAgICAuY29uY2F0KGVtaXRSZXN1bHQuZGlhZ25vc3RpY3MpO1xuXG4gICAgdGhpcy5ldmFsRGlhZ25vc3RpY3MoYWxsRGlhZ25vc3RpY3MpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBidWlsZChpc0RldjogYm9vbGVhbiwgbW9kZTogTW9kZXMsIGJ1bmRsZSA9IGZhbHNlKSB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuYnVpbGQpO1xuICAgIGF3YWl0IHRoaXMuYnVpbGRUcyhpc0RldiwgbW9kZSwgYnVuZGxlKTtcblxuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYE1vZHVsZSAke3RoaXMucGtnTmFtZX0gJHt0aGlzLnBrZ1ZlcnNpb259ICgke21vZGV9KSBidWlsdCBpbiAke2lzRGV2ID8gXCJkZXZcIiA6IFwicHJvZFwifSBtb2RlLi4uYFxuICAgICk7XG4gICAgaWYgKG1vZGUgPT09IE1vZGVzLkNKUyAmJiAhYnVuZGxlKSB7XG4gICAgICBjb25zdCBmaWxlcyA9IGdldEFsbEZpbGVzKFxuICAgICAgICBcImxpYlwiLFxuICAgICAgICAoZmlsZSkgPT4gZmlsZS5lbmRzV2l0aChcIi5qc1wiKSAmJiAhZmlsZS5pbmNsdWRlcyhcIi9lc20vXCIpXG4gICAgICApO1xuXG4gICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgICAgbG9nLnZlcmJvc2UoYFBhdGNoaW5nICR7ZmlsZX0ncyBjanMgaW1wb3J0cy4uLmApO1xuICAgICAgICBjb25zdCBmID0gZmlsZS5yZXBsYWNlKFwiLmpzXCIsIFwiLmNqc1wiKTtcbiAgICAgICAgYXdhaXQgcmVuYW1lRmlsZShmaWxlLCBmKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENvcGllcyBhc3NldHMgdG8gdGhlIGJ1aWxkIG91dHB1dCBkaXJlY3RvcnkuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGNoZWNrcyBmb3IgdGhlIGV4aXN0ZW5jZSBvZiBhbiAnYXNzZXRzJyBkaXJlY3RvcnkgaW4gdGhlIHNvdXJjZVxuICAgKiBhbmQgY29waWVzIGl0IHRvIHRoZSBhcHByb3ByaWF0ZSBidWlsZCBvdXRwdXQgZGlyZWN0b3J5IChsaWIgb3IgZGlzdCkuXG4gICAqIEBwYXJhbSB7TW9kZXN9IG1vZGUgLSBUaGUgYnVpbGQgbW9kZSAoQ0pTIG9yIEVTTSkuXG4gICAqL1xuICBjb3B5QXNzZXRzKG1vZGU6IE1vZGVzKSB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuY29weUFzc2V0cyk7XG4gICAgbGV0IGhhc0Fzc2V0cyA9IGZhbHNlO1xuICAgIHRyeSB7XG4gICAgICBoYXNBc3NldHMgPSBmcy5zdGF0U3luYyhcIi4vc3JjL2Fzc2V0c1wiKS5pc0RpcmVjdG9yeSgpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHJldHVybiBsb2cudmVyYm9zZShgTm8gYXNzZXRzIGZvdW5kIGluIC4vc3JjL2Fzc2V0cyB0byBjb3B5YCk7XG4gICAgfVxuICAgIGlmIChoYXNBc3NldHMpXG4gICAgICBjb3B5RmlsZShcbiAgICAgICAgXCIuL3NyYy9hc3NldHNcIixcbiAgICAgICAgYC4vJHttb2RlID09PSBNb2Rlcy5DSlMgPyBcImxpYlwiIDogXCJkaXN0XCJ9L2Fzc2V0c2BcbiAgICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJ1bmRsZXMgdGhlIHByb2plY3QgdXNpbmcgUm9sbHVwLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBjb25maWd1cmVzIGFuZCBydW5zIFJvbGx1cCB0byBidW5kbGUgdGhlIHByb2plY3QuIEl0IGhhbmRsZXNcbiAgICogZGlmZmVyZW50IG1vZHVsZSBmb3JtYXRzLCBkZXZlbG9wbWVudCBhbmQgcHJvZHVjdGlvbiBidWlsZHMsIGFuZCBleHRlcm5hbCBkZXBlbmRlbmNpZXMuXG4gICAqIEBwYXJhbSB7TW9kZXN9IG1vZGUgLSBUaGUgbW9kdWxlIGZvcm1hdCAoQ0pTIG9yIEVTTSkuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNEZXYgLSBXaGV0aGVyIGl0J3MgYSBkZXZlbG9wbWVudCBidWlsZC5cbiAgICogQHBhcmFtIHtib29sZWFufSBpc0xpYiAtIFdoZXRoZXIgaXQncyBhIGxpYnJhcnkgYnVpbGQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbZW50cnlGaWxlPVwic3JjL2luZGV4LnRzXCJdIC0gVGhlIGVudHJ5IGZpbGUgZm9yIHRoZSBidW5kbGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbmFtZU92ZXJyaWRlPXRoaXMucGtnTmFtZV0gLSBUaGUgbmFtZSBvZiB0aGUgb3V0cHV0IGJ1bmRsZS5cbiAgICogQHBhcmFtIHtzdHJpbmd8c3RyaW5nW119IFtleHRlcm5hbHNBcmddIC0gQSBsaXN0IG9mIGV4dGVybmFsIGRlcGVuZGVuY2llcy5cbiAgICogQHBhcmFtIHtzdHJpbmd8c3RyaW5nW119IFtpbmNsdWRlQXJnXSAtIEEgbGlzdCBvZiBkZXBlbmRlbmNpZXMgdG8gaW5jbHVkZS5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBidW5kbGUoXG4gICAgbW9kZTogTW9kZXMsXG4gICAgaXNEZXY6IGJvb2xlYW4sXG4gICAgaXNMaWI6IGJvb2xlYW4sXG4gICAgZW50cnlGaWxlOiBzdHJpbmcgPSBcIi4vc3JjL2luZGV4LnRzXCIsXG4gICAgbmFtZU92ZXJyaWRlOiBzdHJpbmcgPSB0aGlzLnBrZ05hbWUsXG4gICAgZXh0ZXJuYWxzQXJnPzogc3RyaW5nIHwgc3RyaW5nW10sXG4gICAgaW5jbHVkZUFyZzogc3RyaW5nIHwgc3RyaW5nW10gPSBbXG4gICAgICBcInByb21wdHNcIixcbiAgICAgIFwic3R5bGVkLXN0cmluZy1idWlsZGVyXCIsXG4gICAgICBcInR5cGVkLW9iamVjdC1hY2N1bXVsYXRvclwiLFxuICAgICAgXCJAZGVjYWYtdHMvbG9nZ2luZ1wiLFxuICAgIF1cbiAgKSB7XG4gICAgLy8gUnVuIGEgVHlwZVNjcmlwdC1vbmx5IGRpYWdub3N0aWMgY2hlY2sgZm9yIHRoZSBidW5kbGluZyBjb25maWd1cmF0aW9uIGFuZCBmYWlsIGZhc3Qgb24gYW55IGVycm9ycy5cbiAgICBhd2FpdCB0aGlzLmNoZWNrVHNEaWFnbm9zdGljcyhpc0RldiwgbW9kZSwgdHJ1ZSk7XG4gICAgY29uc3QgaXNFc20gPSBtb2RlID09PSBNb2Rlcy5FU007XG4gICAgY29uc3QgcGtnTmFtZSA9IHRoaXMucGtnTmFtZTtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZztcblxuICAgIC8vIG5vcm1hbGl6ZSBpbmNsdWRlIGFuZCBleHRlcm5hbHNcbiAgICBjb25zdCBpbmNsdWRlID0gQXJyYXkuZnJvbShcbiAgICAgIG5ldyBTZXQoWy4uLihwYXJzZUxpc3QoaW5jbHVkZUFyZykgYXMgc3RyaW5nW10pXSlcbiAgICApO1xuICAgIGxldCBleHRlcm5hbHNMaXN0ID0gcGFyc2VMaXN0KGV4dGVybmFsc0FyZyk7XG4gICAgaWYgKGV4dGVybmFsc0xpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICAvLyBpZiBubyBleHRlcm5hbHMgc3BlY2lmaWVkLCBsaXN0IHRvcC1sZXZlbCBwYWNrYWdlcyBpbiBub2RlX21vZHVsZXMgKGV4cGFuZCBzY29wZXMpXG4gICAgICB0cnkge1xuICAgICAgICBleHRlcm5hbHNMaXN0ID0gbGlzdE5vZGVNb2R1bGVzUGFja2FnZXMoXG4gICAgICAgICAgcGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIFwibm9kZV9tb2R1bGVzXCIpXG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gZmFsbGJhY2sgdG8gcGFja2FnZS5qc29uIGRlcGVuZGVuY2llcyBpZiBsaXN0aW5nIGZhaWxzIG9yIHlpZWxkcyBub3RoaW5nXG4gICAgICB9XG4gICAgICBpZiAoIWV4dGVybmFsc0xpc3QgfHwgZXh0ZXJuYWxzTGlzdC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgZXh0ZXJuYWxzTGlzdCA9IGdldFBhY2thZ2VEZXBlbmRlbmNpZXMoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBleHQgPSBBcnJheS5mcm9tKFxuICAgICAgbmV3IFNldChbXG4gICAgICAgIC8vIGJ1aWx0aW5zIGFuZCBhbHdheXMgZXh0ZXJuYWwgcnVudGltZSBkZXBzXG4gICAgICAgIC4uLihmdW5jdGlvbiBidWlsdGluTGlzdCgpOiBzdHJpbmdbXSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoYnVpbHRpbk1vZHVsZXMpID8gYnVpbHRpbk1vZHVsZXMgOiBbXVxuICAgICAgICAgICAgKSBhcyBzdHJpbmdbXTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIGZhbGxiYWNrIHRvIGEgcmVhc29uYWJsZSBzdWJzZXQgaWYgYGJ1aWx0aW5Nb2R1bGVzYCBpcyB1bmF2YWlsYWJsZVxuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgXCJmc1wiLFxuICAgICAgICAgICAgICBcInBhdGhcIixcbiAgICAgICAgICAgICAgXCJwcm9jZXNzXCIsXG4gICAgICAgICAgICAgIFwiY2hpbGRfcHJvY2Vzc1wiLFxuICAgICAgICAgICAgICBcInV0aWxcIixcbiAgICAgICAgICAgICAgXCJodHRwc1wiLFxuICAgICAgICAgICAgICBcImh0dHBcIixcbiAgICAgICAgICAgICAgXCJvc1wiLFxuICAgICAgICAgICAgICBcInN0cmVhbVwiLFxuICAgICAgICAgICAgICBcImNyeXB0b1wiLFxuICAgICAgICAgICAgICBcInpsaWJcIixcbiAgICAgICAgICAgICAgXCJuZXRcIixcbiAgICAgICAgICAgICAgXCJ0bHNcIixcbiAgICAgICAgICAgICAgXCJ1cmxcIixcbiAgICAgICAgICAgICAgXCJxdWVyeXN0cmluZ1wiLFxuICAgICAgICAgICAgICBcImFzc2VydFwiLFxuICAgICAgICAgICAgICBcImV2ZW50c1wiLFxuICAgICAgICAgICAgICBcInR0eVwiLFxuICAgICAgICAgICAgICBcImRuc1wiLFxuICAgICAgICAgICAgICBcInF1ZXJ5c3RyaW5nXCIsXG4gICAgICAgICAgICBdO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkoKSxcbiAgICAgICAgLi4uZXh0ZXJuYWxzTGlzdCxcbiAgICAgIF0pXG4gICAgKTtcblxuICAgIC8vIEZvciBwbHVnaW4tdHlwZXNjcmlwdCB3ZSB3YW50IGl0IHRvIGVtaXQgc291cmNlIG1hcHMgKG5vdCBpbmxpbmUpIHNvIFJvbGx1cCBjYW5cbiAgICAvLyBkZWNpZGUgd2hldGhlciB0byBpbmxpbmUgb3IgZW1pdCBleHRlcm5hbCBmaWxlcy4gVGhlIFJvbGx1cCBvdXRwdXQuc291cmNlbWFwXG4gICAgLy8gY29udHJvbHMgZmluYWwgbWFwIHBsYWNlbWVudC4gRG8gTk9UIHNldCBhIG5vbi1zdGFuZGFyZCBgc291cmNlbWFwYCBmaWVsZCBvblxuICAgIC8vIHRoZSByb2xsdXAgaW5wdXQgb3B0aW9ucyAoUm9sbHVwIHdpbGwgcmVqZWN0IGl0KS5cbiAgICBjb25zdCByb2xsdXBTb3VyY2VNYXBPdXRwdXQ6IGZhbHNlIHwgdHJ1ZSB8IFwiaW5saW5lXCIgfCBcImhpZGRlblwiID0gaXNEZXZcbiAgICAgID8gXCJpbmxpbmVcIlxuICAgICAgOiB0cnVlO1xuXG4gICAgY29uc3QgcGx1Z2lucyA9IFtcbiAgICAgIHR5cGVzY3JpcHQoe1xuICAgICAgICBjb21waWxlck9wdGlvbnM6IHtcbiAgICAgICAgICBtb2R1bGU6IFwiZXNuZXh0XCIsXG4gICAgICAgICAgZGVjbGFyYXRpb246IGZhbHNlLFxuICAgICAgICAgIG91dERpcjogaXNMaWIgPyBcImJpblwiIDogXCJkaXN0XCIsXG4gICAgICAgICAgLy8gRm9yIGRldiBidW5kbGVzIGVtaXQgaW5saW5lIHNvdXJjZSBtYXBzIChubyBzZXBhcmF0ZSAubWFwIGZpbGVzKS5cbiAgICAgICAgICAvLyBGb3IgcHJvZCBidW5kbGVzIGVtaXQgZXh0ZXJuYWwgbWFwcyBzbyBSb2xsdXAgY2FuIHdyaXRlIHRoZW0gdG8gZGlzay5cbiAgICAgICAgICBzb3VyY2VNYXA6IGlzRGV2ID8gZmFsc2UgOiB0cnVlLFxuICAgICAgICAgIGlubGluZVNvdXJjZU1hcDogaXNEZXYgPyB0cnVlIDogZmFsc2UsXG4gICAgICAgICAgaW5saW5lU291cmNlczogaXNEZXYgPyB0cnVlIDogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICAgIGluY2x1ZGU6IFtcInNyYy8qKi8qLnRzXCJdLFxuICAgICAgICBleGNsdWRlOiBbXCJub2RlX21vZHVsZXNcIiwgXCIqKi8qLnNwZWMudHNcIl0sXG4gICAgICAgIHRzY29uZmlnOiBcIi4vdHNjb25maWcuanNvblwiLFxuICAgICAgfSksXG4gICAgICBqc29uKCksXG4gICAgXTtcblxuICAgIGlmIChpc0xpYikge1xuICAgICAgcGx1Z2lucy5wdXNoKFxuICAgICAgICBjb21tb25qcyh7XG4gICAgICAgICAgaW5jbHVkZTogW10sXG4gICAgICAgICAgZXhjbHVkZTogZXh0ZXJuYWxzTGlzdCxcbiAgICAgICAgfSksXG4gICAgICAgIG5vZGVSZXNvbHZlKHtcbiAgICAgICAgICByZXNvbHZlT25seTogaW5jbHVkZSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gcHJvZHVjdGlvbiBtaW5pZmljYXRpb246IGFkZCB0ZXJzZXIgbGFzdCBzbyBpdCBzZWVzIHByaW9yIHNvdXJjZSBtYXBzXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRlcnNlck1vZDogYW55ID0gYXdhaXQgaW1wb3J0KFwiQHJvbGx1cC9wbHVnaW4tdGVyc2VyXCIpO1xuICAgICAgY29uc3QgdGVyc2VyRm4gPVxuICAgICAgICAodGVyc2VyTW9kICYmIHRlcnNlck1vZC50ZXJzZXIpIHx8IHRlcnNlck1vZC5kZWZhdWx0IHx8IHRlcnNlck1vZDtcblxuICAgICAgY29uc3QgdGVyc2VyT3B0aW9uc0RldjogYW55ID0ge1xuICAgICAgICBwYXJzZTogeyBlY21hOiAyMDIwIH0sXG4gICAgICAgIGNvbXByZXNzOiBmYWxzZSxcbiAgICAgICAgbWFuZ2xlOiBmYWxzZSxcbiAgICAgICAgZm9ybWF0OiB7XG4gICAgICAgICAgY29tbWVudHM6IGZhbHNlLFxuICAgICAgICAgIGJlYXV0aWZ5OiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdGVyc2VyT3B0aW9uc1Byb2Q6IGFueSA9IHtcbiAgICAgICAgcGFyc2U6IHsgZWNtYTogMjAyMCB9LFxuICAgICAgICBjb21wcmVzczoge1xuICAgICAgICAgIGVjbWE6IDIwMjAsXG4gICAgICAgICAgcGFzc2VzOiA1LFxuICAgICAgICAgIGRyb3BfY29uc29sZTogdHJ1ZSxcbiAgICAgICAgICBkcm9wX2RlYnVnZ2VyOiB0cnVlLFxuICAgICAgICAgIHRvcGxldmVsOiB0cnVlLFxuICAgICAgICAgIG1vZHVsZTogaXNFc20sXG4gICAgICAgICAgdW5zYWZlOiB0cnVlLFxuICAgICAgICAgIHVuc2FmZV9hcnJvd3M6IHRydWUsXG4gICAgICAgICAgdW5zYWZlX2NvbXBzOiB0cnVlLFxuICAgICAgICAgIGNvbGxhcHNlX3ZhcnM6IHRydWUsXG4gICAgICAgICAgcmVkdWNlX2Z1bmNzOiB0cnVlLFxuICAgICAgICAgIHJlZHVjZV92YXJzOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgICBtYW5nbGU6IHtcbiAgICAgICAgICB0b3BsZXZlbDogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgICAgZm9ybWF0OiB7XG4gICAgICAgICAgY29tbWVudHM6IGZhbHNlLFxuICAgICAgICAgIGFzY2lpX29ubHk6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIHRvcGxldmVsOiB0cnVlLFxuICAgICAgfTtcblxuICAgICAgcGx1Z2lucy5wdXNoKHRlcnNlckZuKGlzRGV2ID8gdGVyc2VyT3B0aW9uc0RldiA6IHRlcnNlck9wdGlvbnNQcm9kKSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBpZiB0ZXJzZXIgaXNuJ3QgYXZhaWxhYmxlLCBpZ25vcmVcbiAgICB9XG5cbiAgICBjb25zdCBpbnB1dDogSW5wdXRPcHRpb25zID0ge1xuICAgICAgaW5wdXQ6IGVudHJ5RmlsZSxcbiAgICAgIHBsdWdpbnM6IHBsdWdpbnMsXG4gICAgICBleHRlcm5hbDogZXh0LFxuICAgICAgb253YXJuOiB1bmRlZmluZWQsXG4gICAgICAvLyBlbmFibGUgdHJlZS1zaGFraW5nIGZvciBwcm9kdWN0aW9uIGJ1bmRsZXNcbiAgICAgIHRyZWVzaGFrZTogIWlzRGV2LFxuICAgIH0gYXMgYW55O1xuXG4gICAgLy8gcHJlcGFyZSBvdXRwdXQgZ2xvYmFscyBtYXBwaW5nIGZvciBleHRlcm5hbHNcbiAgICBjb25zdCBnbG9iYWxzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgLy8gaW5jbHVkZSBhbGwgZXh0ZXJuYWxzIGFuZCBidWlsdGlucyAoZXh0KSBzbyBSb2xsdXAgd29uJ3QgZ3Vlc3MgbmFtZXMgZm9yIGJ1aWx0aW5zXG4gICAgZXh0LmZvckVhY2goKGUpID0+IHtcbiAgICAgIGdsb2JhbHNbZV0gPSBwYWNrYWdlVG9HbG9iYWwoZSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBvdXRwdXRzOiBPdXRwdXRPcHRpb25zW10gPSBbXG4gICAgICB7XG4gICAgICAgIGZpbGU6IGAke2lzTGliID8gXCJiaW4vXCIgOiBcImRpc3QvXCJ9JHtuYW1lT3ZlcnJpZGUgPyBuYW1lT3ZlcnJpZGUgOiBgLmJ1bmRsZS4keyFpc0RldiA/IFwibWluXCIgOiBcIlwifWB9JHtpc0VzbSA/IFwiLmpzXCIgOiBcIi5janNcIn1gLFxuICAgICAgICBmb3JtYXQ6IGlzTGliID8gXCJjanNcIiA6IGlzRXNtID8gXCJlc21cIiA6IFwidW1kXCIsXG4gICAgICAgIG5hbWU6IHBrZ05hbWUsXG4gICAgICAgIGVzTW9kdWxlOiBpc0VzbSxcbiAgICAgICAgLy8gb3V0cHV0IHNvdXJjZW1hcDogaW5saW5lIGZvciBkZXYsIGV4dGVybmFsIGZvciBwcm9kXG4gICAgICAgIHNvdXJjZW1hcDogcm9sbHVwU291cmNlTWFwT3V0cHV0LFxuICAgICAgICBnbG9iYWxzOiBnbG9iYWxzLFxuICAgICAgICBleHBvcnRzOiBcImF1dG9cIixcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBidW5kbGUgPSBhd2FpdCByb2xsdXAoaW5wdXQgYXMgYW55KTtcbiAgICAgIC8vIG9ubHkgbG9nIHdhdGNoRmlsZXMgYXQgdmVyYm9zZSBsZXZlbCB0byBhdm9pZCBub2lzeSBjb25zb2xlIG91dHB1dFxuICAgICAgbG9nLnZlcmJvc2UoYnVuZGxlLndhdGNoRmlsZXMpO1xuICAgICAgYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVPdXRwdXRzKGJ1bmRsZTogUm9sbHVwQnVpbGQpIHtcbiAgICAgICAgZm9yIChjb25zdCBvdXRwdXRPcHRpb25zIG9mIG91dHB1dHMpIHtcbiAgICAgICAgICBhd2FpdCBidW5kbGUud3JpdGUob3V0cHV0T3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgYXdhaXQgZ2VuZXJhdGVPdXRwdXRzKGJ1bmRsZSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gYnVuZGxlOiAke2V9YCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBidWlsZEJ5RW52KFxuICAgIGVudHJ5RmlsZTogc3RyaW5nID0gXCIuL3NyYy9pbmRleC50c1wiLFxuICAgIGlzRGV2OiBib29sZWFuLFxuICAgIG1vZGU6IEJ1aWxkTW9kZSA9IEJ1aWxkTW9kZS5BTEwsXG4gICAgaW5jbHVkZXNBcmc/OiBzdHJpbmcgfCBzdHJpbmdbXSxcbiAgICBleHRlcm5hbHNBcmc/OiBzdHJpbmcgfCBzdHJpbmdbXVxuICApIHtcbiAgICAvLyBub3RlOiBpbmNsdWRlcyBhbmQgZXh0ZXJuYWxzIHdpbGwgYmUgcGFzc2VkIHRocm91Z2ggZnJvbSBydW4oKSBpbnRvIHRoaXMgbWV0aG9kIGJ5IGNhbGxlcnNcbiAgICB0cnkge1xuICAgICAgZGVsZXRlUGF0aChcImxpYlwiKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAvLyBkbyBub3RoaW5nXG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBkZWxldGVQYXRoKFwiZGlzdFwiKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAvLyBkbyBub3RoaW5nXG4gICAgfVxuXG4gICAgaWYgKFtCdWlsZE1vZGUuQUxMLCBCdWlsZE1vZGUuQlVJTERdLmluY2x1ZGVzKG1vZGUpKSB7XG4gICAgICBmcy5ta2RpclN5bmMoXCJsaWJcIik7XG4gICAgICBhd2FpdCB0aGlzLmJ1aWxkKGlzRGV2LCBNb2Rlcy5FU00pO1xuICAgICAgYXdhaXQgdGhpcy5idWlsZChpc0RldiwgTW9kZXMuQ0pTKTtcbiAgICAgIHRoaXMucGF0Y2hGaWxlcyhcImxpYlwiKTtcbiAgICB9XG5cbiAgICBpZiAoW0J1aWxkTW9kZS5BTEwsIEJ1aWxkTW9kZS5CVU5ETEVdLmluY2x1ZGVzKG1vZGUpKSB7XG4gICAgICBmcy5ta2RpclN5bmMoXCJkaXN0XCIpO1xuICAgICAgYXdhaXQgdGhpcy5idW5kbGUoXG4gICAgICAgIE1vZGVzLkVTTSxcbiAgICAgICAgaXNEZXYsXG4gICAgICAgIGZhbHNlLFxuICAgICAgICBlbnRyeUZpbGUgfHwgXCIuL3NyYy9pbmRleC50c1wiLFxuICAgICAgICB0aGlzLnBrZ05hbWUsXG4gICAgICAgIGV4dGVybmFsc0FyZyxcbiAgICAgICAgaW5jbHVkZXNBcmdcbiAgICAgICk7XG4gICAgICBhd2FpdCB0aGlzLmJ1bmRsZShcbiAgICAgICAgTW9kZXMuQ0pTLFxuICAgICAgICBpc0RldixcbiAgICAgICAgZmFsc2UsXG4gICAgICAgIGVudHJ5RmlsZSB8fCBcIi4vc3JjL2luZGV4LnRzXCIsXG4gICAgICAgIHRoaXMucGtnTmFtZSxcbiAgICAgICAgZXh0ZXJuYWxzQXJnLFxuICAgICAgICBpbmNsdWRlc0FyZ1xuICAgICAgKTtcbiAgICAgIHRoaXMucGF0Y2hGaWxlcyhcImRpc3RcIik7XG4gICAgfVxuXG4gICAgdGhpcy5jb3B5QXNzZXRzKE1vZGVzLkNKUyk7XG4gICAgdGhpcy5jb3B5QXNzZXRzKE1vZGVzLkVTTSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJ1aWxkcyB0aGUgcHJvamVjdCBmb3IgZGV2ZWxvcG1lbnQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIHJ1bnMgdGhlIGJ1aWxkIHByb2Nlc3Mgd2l0aCBkZXZlbG9wbWVudC1zcGVjaWZpYyBjb25maWd1cmF0aW9ucy5cbiAgICogQHBhcmFtIHtCdWlsZE1vZGV9IFttb2RlPUJ1aWxkTW9kZS5BTExdIC0gVGhlIGJ1aWxkIG1vZGUgKGJ1aWxkLCBidW5kbGUsIG9yIGFsbCkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfHN0cmluZ1tdfSBbaW5jbHVkZXNBcmddIC0gQSBsaXN0IG9mIGRlcGVuZGVuY2llcyB0byBpbmNsdWRlLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xzdHJpbmdbXX0gW2V4dGVybmFsc0FyZ10gLSBBIGxpc3Qgb2YgZXh0ZXJuYWwgZGVwZW5kZW5jaWVzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIGJ1aWxkRGV2KFxuICAgIGVudHJ5RmlsZTogc3RyaW5nID0gXCIuL3NyYy9pbmRleC50c1wiLFxuICAgIG1vZGU6IEJ1aWxkTW9kZSA9IEJ1aWxkTW9kZS5BTEwsXG4gICAgaW5jbHVkZXNBcmc/OiBzdHJpbmcgfCBzdHJpbmdbXSxcbiAgICBleHRlcm5hbHNBcmc/OiBzdHJpbmcgfCBzdHJpbmdbXVxuICApIHtcbiAgICByZXR1cm4gdGhpcy5idWlsZEJ5RW52KGVudHJ5RmlsZSwgdHJ1ZSwgbW9kZSwgaW5jbHVkZXNBcmcsIGV4dGVybmFsc0FyZyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJ1aWxkcyB0aGUgcHJvamVjdCBmb3IgcHJvZHVjdGlvbi5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgcnVucyB0aGUgYnVpbGQgcHJvY2VzcyB3aXRoIHByb2R1Y3Rpb24tc3BlY2lmaWMgY29uZmlndXJhdGlvbnMsXG4gICAqIGluY2x1ZGluZyBtaW5pZmljYXRpb24gYW5kIG90aGVyIG9wdGltaXphdGlvbnMuXG4gICAqIEBwYXJhbSB7QnVpbGRNb2RlfSBbbW9kZT1CdWlsZE1vZGUuQUxMXSAtIFRoZSBidWlsZCBtb2RlIChidWlsZCwgYnVuZGxlLCBvciBhbGwpLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xzdHJpbmdbXX0gW2luY2x1ZGVzQXJnXSAtIEEgbGlzdCBvZiBkZXBlbmRlbmNpZXMgdG8gaW5jbHVkZS5cbiAgICogQHBhcmFtIHtzdHJpbmd8c3RyaW5nW119IFtleHRlcm5hbHNBcmddIC0gQSBsaXN0IG9mIGV4dGVybmFsIGRlcGVuZGVuY2llcy5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBidWlsZFByb2QoXG4gICAgZW50cnlGaWxlOiBzdHJpbmcgPSBcIi4vc3JjL2luZGV4LnRzXCIsXG4gICAgbW9kZTogQnVpbGRNb2RlID0gQnVpbGRNb2RlLkFMTCxcbiAgICBpbmNsdWRlc0FyZz86IHN0cmluZyB8IHN0cmluZ1tdLFxuICAgIGV4dGVybmFsc0FyZz86IHN0cmluZyB8IHN0cmluZ1tdXG4gICkge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkQnlFbnYoZW50cnlGaWxlLCBmYWxzZSwgbW9kZSwgaW5jbHVkZXNBcmcsIGV4dGVybmFsc0FyZyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdlbmVyYXRlcyB0aGUgcHJvamVjdCBkb2N1bWVudGF0aW9uLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCB1c2VzIEpTRG9jIGFuZCBvdGhlciB0b29scyB0byBnZW5lcmF0ZSBIVE1MIGRvY3VtZW50YXRpb24gZm9yIHRoZSBwcm9qZWN0LlxuICAgKiBJdCBhbHNvIHBhdGNoZXMgdGhlIFJFQURNRS5tZCBmaWxlIHdpdGggdmVyc2lvbiBhbmQgcGFja2FnZSBzaXplIGluZm9ybWF0aW9uLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIGJ1aWxkRG9jcygpIHtcbiAgICBhd2FpdCBydW5Db21tYW5kKGBucG0gaW5zdGFsbCBiZXR0ZXItZG9jcyB0YWZmeWRiYCkucHJvbWlzZTtcbiAgICBhd2FpdCBydW5Db21tYW5kKGBucHggbWFya2Rvd24taW5jbHVkZSAuL3dvcmtkb2NzL3JlYWRtZS1tZC5qc29uYCkucHJvbWlzZTtcbiAgICBhd2FpdCBydW5Db21tYW5kKFxuICAgICAgYG5weCBqc2RvYyAtYyAuL3dvcmtkb2NzL2pzZG9jcy5qc29uIC10IC4vbm9kZV9tb2R1bGVzL2JldHRlci1kb2NzYFxuICAgICkucHJvbWlzZTtcbiAgICBhd2FpdCBydW5Db21tYW5kKGBucG0gcmVtb3ZlIGJldHRlci1kb2NzIHRhZmZ5ZGJgKS5wcm9taXNlO1xuICAgIFtcbiAgICAgIHtcbiAgICAgICAgc3JjOiBcIndvcmtkb2NzL2Fzc2V0c1wiLFxuICAgICAgICBkZXN0OiBcIi4vZG9jcy93b3JrZG9jcy9hc3NldHNcIixcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHNyYzogXCJ3b3JrZG9jcy9yZXBvcnRzL2NvdmVyYWdlXCIsXG4gICAgICAgIGRlc3Q6IFwiLi9kb2NzL3dvcmtkb2NzL3JlcG9ydHMvY292ZXJhZ2VcIixcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHNyYzogXCJ3b3JrZG9jcy9yZXBvcnRzL2h0bWxcIixcbiAgICAgICAgZGVzdDogXCIuL2RvY3Mvd29ya2RvY3MvcmVwb3J0cy9odG1sXCIsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBzcmM6IFwid29ya2RvY3MvcmVzb3VyY2VzXCIsXG4gICAgICAgIGRlc3Q6IFwiLi9kb2NzL3dvcmtkb2NzL3Jlc291cmNlc1wiLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgc3JjOiBcIkxJQ0VOU0UubWRcIixcbiAgICAgICAgZGVzdDogXCIuL2RvY3MvTElDRU5TRS5tZFwiLFxuICAgICAgfSxcbiAgICBdLmZvckVhY2goKGYpID0+IHtcbiAgICAgIGNvbnN0IHsgc3JjLCBkZXN0IH0gPSBmO1xuICAgICAgY29weUZpbGUoc3JjLCBkZXN0KTtcbiAgICB9KTtcblxuICAgIC8vIHBhdGNoIC4vUkVBRE1FLm1kIGZpbGUgdG8gcmVwbGFjZSB2ZXJzaW9uL3BhY2thZ2UvcGFja2FnZSBzaXplIHN0cmluZ3NcbiAgICB0cnkge1xuICAgICAgY29uc3Qgc2l6ZUtiID0gYXdhaXQgZ2V0RmlsZVNpemVaaXBwZWQoXG4gICAgICAgIHBhdGgucmVzb2x2ZShwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgXCJkaXN0XCIpKVxuICAgICAgKTtcbiAgICAgIHRoaXMucmVwbGFjZW1lbnRzW1BBQ0tBR0VfU0laRV9TVFJJTkddID0gYCR7c2l6ZUtifSBLQmA7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBpZiB3ZSBjb3VsZG4ndCBjb21wdXRlIHNpemUsIGxlYXZlIHBsYWNlaG9sZGVyIG9yIHNldCB0byB1bmtub3duXG4gICAgICB0aGlzLnJlcGxhY2VtZW50c1tQQUNLQUdFX1NJWkVfU1RSSU5HXSA9IFwidW5rbm93blwiO1xuICAgIH1cblxuICAgIC8vIFBhdGNoIFJFQURNRS5tZCBpbiBwcm9qZWN0IHJvb3RcbiAgICB0cnkge1xuICAgICAgcGF0Y2hGaWxlKFwiLi9SRUFETUUubWRcIiwgdGhpcy5yZXBsYWNlbWVudHMpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLmJ1aWxkRG9jcyBhcyBhbnkpO1xuICAgICAgbG9nLnZlcmJvc2UoYEZhaWxlZCB0byBwYXRjaCBSRUFETUUubWQ6ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcnVuPFI+KFxuICAgIGFuc3dlcnM6IExvZ2dpbmdDb25maWcgJlxuICAgICAgdHlwZW9mIERlZmF1bHRDb21tYW5kVmFsdWVzICYgeyBbayBpbiBrZXlvZiB0eXBlb2Ygb3B0aW9uc106IHVua25vd24gfVxuICApOiBQcm9taXNlPHN0cmluZyB8IHZvaWQgfCBSPiB7XG4gICAgY29uc3QgeyBkZXYsIHByb2QsIGRvY3MsIGJ1aWxkTW9kZSwgaW5jbHVkZXMsIGV4dGVybmFscywgZW50cnkgfSA9XG4gICAgICBhbnN3ZXJzIGFzIGFueTtcbiAgICBpZiAoZGV2KSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5idWlsZERldihcbiAgICAgICAgZW50cnkgfHwgXCIuL3NyYy9pbmRleC50c1wiLFxuICAgICAgICBidWlsZE1vZGUgYXMgQnVpbGRNb2RlLFxuICAgICAgICBpbmNsdWRlcyxcbiAgICAgICAgZXh0ZXJuYWxzXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAocHJvZCkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuYnVpbGRQcm9kKFxuICAgICAgICBlbnRyeSB8fCBcIi4vc3JjL2luZGV4LnRzXCIsXG4gICAgICAgIGJ1aWxkTW9kZSBhcyBCdWlsZE1vZGUsXG4gICAgICAgIGluY2x1ZGVzLFxuICAgICAgICBleHRlcm5hbHNcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChkb2NzKSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5idWlsZERvY3MoKTtcbiAgICB9XG4gIH1cbn1cbiIsIi8qIGlzdGFuYnVsIGlnbm9yZSBmaWxlICovXG5pbXBvcnQgeyBydW5Db21tYW5kIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgeyBOb0NJRkxhZywgU2VtVmVyc2lvbiwgU2VtVmVyc2lvblJlZ2V4IH0gZnJvbSBcIi4uLy4uL3V0aWxzL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgVXNlcklucHV0IH0gZnJvbSBcIi4uLy4uL2lucHV0L2lucHV0XCI7XG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSBcIi4uL2NvbW1hbmRcIjtcbmltcG9ydCB7IERlZmF1bHRDb21tYW5kVmFsdWVzIH0gZnJvbSBcIi4uL2luZGV4XCI7XG5pbXBvcnQgeyBMb2dnaW5nQ29uZmlnIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbmNvbnN0IG9wdGlvbnMgPSB7XG4gIGNpOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbiAgbWVzc2FnZToge1xuICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgc2hvcnQ6IFwibVwiLFxuICB9LFxuICB0YWc6IHtcbiAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgIHNob3J0OiBcInRcIixcbiAgICBkZWZhdWx0OiB1bmRlZmluZWQsXG4gIH0sXG59O1xuXG4vKipcbiAqIEBjbGFzcyBSZWxlYXNlU2NyaXB0XG4gKiBAZXh0ZW5kcyB7Q29tbWFuZH1cbiAqIEBjYXZlZ29yeSBzY3JpcHRzXG4gKiBAZGVzY3JpcHRpb24gQSBjb21tYW5kLWxpbmUgc2NyaXB0IGZvciBtYW5hZ2luZyByZWxlYXNlcyBhbmQgdmVyc2lvbiB1cGRhdGVzLlxuICogQHN1bW1hcnkgVGhpcyBzY3JpcHQgYXV0b21hdGVzIHRoZSBwcm9jZXNzIG9mIGNyZWF0aW5nIGFuZCBwdXNoaW5nIG5ldyByZWxlYXNlcy4gSXQgaGFuZGxlcyB2ZXJzaW9uIHVwZGF0ZXMsXG4gKiBjb21taXQgbWVzc2FnZXMsIGFuZCBvcHRpb25hbGx5IHB1Ymxpc2hlcyB0byBOUE0uIFRoZSBzY3JpcHQgc3VwcG9ydHMgc2VtYW50aWMgdmVyc2lvbmluZyBhbmQgY2FuIHdvcmsgaW4gYm90aCBDSSBhbmQgbm9uLUNJIGVudmlyb25tZW50cy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgdGhlIHNjcmlwdFxuICogQHBhcmFtIHtib29sZWFufSBvcHRpb25zLmNpIC0gV2hldGhlciB0aGUgc2NyaXB0IGlzIHJ1bm5pbmcgaW4gYSBDSSBlbnZpcm9ubWVudCAoZGVmYXVsdDogdHJ1ZSlcbiAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLm1lc3NhZ2UgLSBUaGUgcmVsZWFzZSBtZXNzYWdlIChzaG9ydDogJ20nKVxuICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMudGFnIC0gVGhlIHZlcnNpb24gdGFnIHRvIHVzZSAoc2hvcnQ6ICd0JywgZGVmYXVsdDogdW5kZWZpbmVkKVxuICovXG5leHBvcnQgY2xhc3MgUmVsZWFzZVNjcmlwdCBleHRlbmRzIENvbW1hbmQ8dHlwZW9mIG9wdGlvbnMsIHZvaWQ+IHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoXCJSZWxlYXNlU2NyaXB0XCIsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyB0aGUgdmVyc2lvbiBmb3IgdGhlIHJlbGVhc2UuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIHZhbGlkYXRlcyB0aGUgcHJvdmlkZWQgdGFnIG9yIHByb21wdHMgdGhlIHVzZXIgZm9yIGEgbmV3IG9uZSBpZiBub3QgcHJvdmlkZWQgb3IgaW52YWxpZC5cbiAgICogSXQgYWxzbyBkaXNwbGF5cyB0aGUgbGF0ZXN0IGdpdCB0YWdzIGZvciByZWZlcmVuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YWcgLSBUaGUgdmVyc2lvbiB0YWcgdG8gcHJlcGFyZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSBUaGUgcHJlcGFyZWQgdmVyc2lvbiB0YWdcbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgUiBhcyBSZWxlYXNlU2NyaXB0XG4gICAqICAgcGFydGljaXBhbnQgVCBhcyBUZXN0VmVyc2lvblxuICAgKiAgIHBhcnRpY2lwYW50IFUgYXMgVXNlcklucHV0XG4gICAqICAgcGFydGljaXBhbnQgRyBhcyBHaXRcbiAgICogICBSLT4+VDogdGVzdFZlcnNpb24odGFnKVxuICAgKiAgIGFsdCB0YWcgaXMgdmFsaWRcbiAgICogICAgIFQtLT4+UjogcmV0dXJuIHRhZ1xuICAgKiAgIGVsc2UgdGFnIGlzIGludmFsaWQgb3Igbm90IHByb3ZpZGVkXG4gICAqICAgICBSLT4+RzogTGlzdCBsYXRlc3QgZ2l0IHRhZ3NcbiAgICogICAgIFItPj5VOiBQcm9tcHQgZm9yIG5ldyB0YWdcbiAgICogICAgIFUtLT4+UjogcmV0dXJuIG5ldyB0YWdcbiAgICogICBlbmRcbiAgICovXG4gIGFzeW5jIHByZXBhcmVWZXJzaW9uKHRhZz86IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMucHJlcGFyZVZlcnNpb24pO1xuICAgIHRhZyA9IHRoaXMudGVzdFZlcnNpb24oKHRhZyBhcyBzdHJpbmcpIHx8IFwiXCIpO1xuICAgIGlmICghdGFnKSB7XG4gICAgICBsb2cudmVyYm9zZShcIk5vIHJlbGVhc2UgbWVzc2FnZSBwcm92aWRlZC4gUHJvbXB0aW5nIGZvciBvbmU6XCIpO1xuICAgICAgbG9nLmluZm8oYExpc3RpbmcgbGF0ZXN0IGdpdCB0YWdzOmApO1xuICAgICAgYXdhaXQgcnVuQ29tbWFuZChcImdpdCB0YWcgLS1zb3J0PS10YWdnZXJkYXRlIHwgaGVhZCAtbiA1XCIpLnByb21pc2U7XG4gICAgICByZXR1cm4gYXdhaXQgVXNlcklucHV0Lmluc2lzdEZvclRleHQoXG4gICAgICAgIFwidGFnXCIsXG4gICAgICAgIFwiRW50ZXIgdGhlIG5ldyB0YWcgbnVtYmVyIChhY2NlcHRzIHYqLiouKlstLi4uXSlcIixcbiAgICAgICAgKHZhbCkgPT5cbiAgICAgICAgICAhIXZhbC50b1N0cmluZygpLm1hdGNoKC9edlswLTldK1xcLlswLTldKy5bMC05XSsoLVswLTlhLXpBLVotXSspPyQvKVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRhZztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGVzdHMgaWYgdGhlIHByb3ZpZGVkIHZlcnNpb24gaXMgdmFsaWQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGNoZWNrcyBpZiB0aGUgdmVyc2lvbiBpcyBhIHZhbGlkIHNlbWFudGljIHZlcnNpb24gb3IgYSBwcmVkZWZpbmVkIHVwZGF0ZSB0eXBlIChQQVRDSCwgTUlOT1IsIE1BSk9SKS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHZlcnNpb24gLSBUaGUgdmVyc2lvbiB0byB0ZXN0XG4gICAqIEByZXR1cm5zIHtzdHJpbmcgfCB1bmRlZmluZWR9IFRoZSB2YWxpZGF0ZWQgdmVyc2lvbiBvciB1bmRlZmluZWQgaWYgaW52YWxpZFxuICAgKi9cbiAgdGVzdFZlcnNpb24odmVyc2lvbjogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy50ZXN0VmVyc2lvbik7XG4gICAgdmVyc2lvbiA9IHZlcnNpb24udHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gICAgc3dpdGNoICh2ZXJzaW9uKSB7XG4gICAgICBjYXNlIFNlbVZlcnNpb24uUEFUQ0g6XG4gICAgICBjYXNlIFNlbVZlcnNpb24uTUlOT1I6XG4gICAgICBjYXNlIFNlbVZlcnNpb24uTUFKT1I6XG4gICAgICAgIGxvZy52ZXJib3NlKGBVc2luZyBwcm92aWRlZCBTZW1WZXIgdXBkYXRlOiAke3ZlcnNpb259YCwgMSk7XG4gICAgICAgIHJldHVybiB2ZXJzaW9uO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgbG9nLnZlcmJvc2UoXG4gICAgICAgICAgYFRlc3RpbmcgcHJvdmlkZWQgdmVyc2lvbiBmb3IgU2VtVmVyIGNvbXBhdGliaWxpdHk6ICR7dmVyc2lvbn1gLFxuICAgICAgICAgIDFcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCFuZXcgUmVnRXhwKFNlbVZlcnNpb25SZWdleCkudGVzdCh2ZXJzaW9uKSkge1xuICAgICAgICAgIGxvZy5kZWJ1ZyhgSW52YWxpZCB2ZXJzaW9uIG51bWJlcjogJHt2ZXJzaW9ufWApO1xuICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgbG9nLnZlcmJvc2UoYHZlcnNpb24gYXBwcm92ZWQ6ICR7dmVyc2lvbn1gLCAxKTtcbiAgICAgICAgcmV0dXJuIHZlcnNpb247XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyB0aGUgcmVsZWFzZSBtZXNzYWdlLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBlaXRoZXIgcmV0dXJucyB0aGUgcHJvdmlkZWQgbWVzc2FnZSBvciBwcm9tcHRzIHRoZSB1c2VyIGZvciBhIG5ldyBvbmUgaWYgbm90IHByb3ZpZGVkLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIC0gVGhlIHJlbGVhc2UgbWVzc2FnZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSBUaGUgcHJlcGFyZWQgcmVsZWFzZSBtZXNzYWdlXG4gICAqL1xuICBhc3luYyBwcmVwYXJlTWVzc2FnZShtZXNzYWdlPzogc3RyaW5nKSB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMucHJlcGFyZU1lc3NhZ2UpO1xuICAgIGlmICghbWVzc2FnZSkge1xuICAgICAgbG9nLnZlcmJvc2UoXCJObyByZWxlYXNlIG1lc3NhZ2UgcHJvdmlkZWQuIFByb21wdGluZyBmb3Igb25lXCIpO1xuICAgICAgcmV0dXJuIGF3YWl0IFVzZXJJbnB1dC5pbnNpc3RGb3JUZXh0KFxuICAgICAgICBcIm1lc3NhZ2VcIixcbiAgICAgICAgXCJXaGF0IHNob3VsZCBiZSB0aGUgcmVsZWFzZSBtZXNzYWdlL3RpY2tldD9cIixcbiAgICAgICAgKHZhbCkgPT4gISF2YWwgJiYgdmFsLnRvU3RyaW5nKCkubGVuZ3RoID4gNVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIG1lc3NhZ2U7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJ1bnMgdGhlIHJlbGVhc2Ugc2NyaXB0LlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBvcmNoZXN0cmF0ZXMgdGhlIGVudGlyZSByZWxlYXNlIHByb2Nlc3MsIGluY2x1ZGluZyB2ZXJzaW9uIHByZXBhcmF0aW9uLCBtZXNzYWdlIGNyZWF0aW9uLFxuICAgKiBnaXQgb3BlcmF0aW9ucywgYW5kIG5wbSBwdWJsaXNoaW5nIChpZiBub3QgaW4gQ0kgZW52aXJvbm1lbnQpLlxuICAgKiBAcGFyYW0ge1BhcnNlQXJnc1Jlc3VsdH0gYXJncyAtIFRoZSBwYXJzZWQgY29tbWFuZC1saW5lIGFyZ3VtZW50c1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgUiBhcyBSZWxlYXNlU2NyaXB0XG4gICAqICAgcGFydGljaXBhbnQgViBhcyBQcmVwYXJlVmVyc2lvblxuICAgKiAgIHBhcnRpY2lwYW50IE0gYXMgUHJlcGFyZU1lc3NhZ2VcbiAgICogICBwYXJ0aWNpcGFudCBOIGFzIE5QTVxuICAgKiAgIHBhcnRpY2lwYW50IEcgYXMgR2l0XG4gICAqICAgcGFydGljaXBhbnQgVSBhcyBVc2VySW5wdXRcbiAgICogICBSLT4+VjogcHJlcGFyZVZlcnNpb24odGFnKVxuICAgKiAgIFItPj5NOiBwcmVwYXJlTWVzc2FnZShtZXNzYWdlKVxuICAgKiAgIFItPj5OOiBSdW4gcHJlcGFyZS1yZWxlYXNlIHNjcmlwdFxuICAgKiAgIFItPj5HOiBDaGVjayBnaXQgc3RhdHVzXG4gICAqICAgYWx0IGNoYW5nZXMgZXhpc3RcbiAgICogICAgIFItPj5VOiBBc2sgZm9yIGNvbmZpcm1hdGlvblxuICAgKiAgICAgVS0tPj5SOiBDb25maXJtXG4gICAqICAgICBSLT4+RzogQWRkIGFuZCBjb21taXQgY2hhbmdlc1xuICAgKiAgIGVuZFxuICAgKiAgIFItPj5OOiBVcGRhdGUgbnBtIHZlcnNpb25cbiAgICogICBSLT4+RzogUHVzaCBjaGFuZ2VzIGFuZCB0YWdzXG4gICAqICAgYWx0IG5vdCBDSSBlbnZpcm9ubWVudFxuICAgKiAgICAgUi0+Pk46IFB1Ymxpc2ggdG8gbnBtXG4gICAqICAgZW5kXG4gICAqL1xuICBhc3luYyBydW4oXG4gICAgYXJnczogTG9nZ2luZ0NvbmZpZyAmXG4gICAgICB0eXBlb2YgRGVmYXVsdENvbW1hbmRWYWx1ZXMgJiB7IFtrIGluIGtleW9mIHR5cGVvZiBvcHRpb25zXTogdW5rbm93biB9XG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxldCByZXN1bHQ6IGFueTtcbiAgICBjb25zdCB7IGNpIH0gPSBhcmdzO1xuICAgIGxldCB7IHRhZywgbWVzc2FnZSB9ID0gYXJncztcbiAgICB0YWcgPSBhd2FpdCB0aGlzLnByZXBhcmVWZXJzaW9uKHRhZyBhcyBzdHJpbmcpO1xuICAgIG1lc3NhZ2UgPSBhd2FpdCB0aGlzLnByZXBhcmVNZXNzYWdlKG1lc3NhZ2UgYXMgc3RyaW5nKTtcbiAgICByZXN1bHQgPSBhd2FpdCBydW5Db21tYW5kKGBucG0gcnVuIHByZXBhcmUtcmVsZWFzZSAtLSAke3RhZ30gJHttZXNzYWdlfWAsIHtcbiAgICAgIGN3ZDogcHJvY2Vzcy5jd2QoKSxcbiAgICB9KS5wcm9taXNlO1xuICAgIHJlc3VsdCA9IGF3YWl0IHJ1bkNvbW1hbmQoXCJnaXQgc3RhdHVzIC0tcG9yY2VsYWluXCIpLnByb21pc2U7XG4gICAgYXdhaXQgcmVzdWx0O1xuICAgIGlmIChcbiAgICAgIHJlc3VsdC5sb2dzLmxlbmd0aCAmJlxuICAgICAgKGF3YWl0IFVzZXJJbnB1dC5hc2tDb25maXJtYXRpb24oXG4gICAgICAgIFwiZ2l0LWNoYW5nZXNcIixcbiAgICAgICAgXCJEbyB5b3Ugd2FudCB0byBwdXNoIHRoZSBjaGFuZ2VzIHRvIHRoZSByZW1vdGUgcmVwb3NpdG9yeT9cIixcbiAgICAgICAgdHJ1ZVxuICAgICAgKSlcbiAgICApIHtcbiAgICAgIGF3YWl0IHJ1bkNvbW1hbmQoXCJnaXQgYWRkIC5cIikucHJvbWlzZTtcbiAgICAgIGF3YWl0IHJ1bkNvbW1hbmQoXG4gICAgICAgIGBnaXQgY29tbWl0IC1tIFwiJHt0YWd9IC0gJHttZXNzYWdlfSAtIGFmdGVyIHJlbGVhc2UgcHJlcGFyYXRpb24ke2NpID8gXCJcIiA6IE5vQ0lGTGFnfVwiYFxuICAgICAgKS5wcm9taXNlO1xuICAgIH1cbiAgICBhd2FpdCBydW5Db21tYW5kKFxuICAgICAgYG5wbSB2ZXJzaW9uIFwiJHt0YWd9XCIgLW0gXCIke21lc3NhZ2V9JHtjaSA/IFwiXCIgOiBOb0NJRkxhZ31cImBcbiAgICApLnByb21pc2U7XG4gICAgYXdhaXQgcnVuQ29tbWFuZChcImdpdCBwdXNoIC0tZm9sbG93LXRhZ3NcIikucHJvbWlzZTtcbiAgICBpZiAoIWNpKSB7XG4gICAgICBhd2FpdCBydW5Db21tYW5kKFwiTlBNX1RPS0VOPSQoY2F0IC5ucG10b2tlbikgbnBtIHB1Ymxpc2ggLS1hY2Nlc3MgcHVibGljXCIpXG4gICAgICAgIC5wcm9taXNlO1xuICAgIH1cbiAgfVxufVxuIiwiaW1wb3J0IHsgU3RhbmRhcmRPdXRwdXRXcml0ZXIgfSBmcm9tIFwiLi9TdGFuZGFyZE91dHB1dFdyaXRlclwiO1xuaW1wb3J0IHsgUHJvbWlzZUV4ZWN1dG9yIH0gZnJvbSBcIi4uL3V0aWxzL3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgc3BlY2lhbGl6ZWQgb3V0cHV0IHdyaXRlciB0aGF0IHVzZXMgcmVndWxhciBleHByZXNzaW9ucyB0byBwcm9jZXNzIG91dHB1dC5cbiAqIEBzdW1tYXJ5IFRoaXMgY2xhc3MgZXh0ZW5kcyBTdGFuZGFyZE91dHB1dFdyaXRlciB0byBwcm92aWRlIHJlZ2V4LWJhc2VkIG91dHB1dCBwcm9jZXNzaW5nLlxuICogSXQgYWxsb3dzIGZvciBwYXR0ZXJuIG1hdGNoaW5nIGluIHRoZSBvdXRwdXQgc3RyZWFtIGFuZCBjYW4gdHJpZ2dlciBzcGVjaWZpYyBhY3Rpb25zXG4gKiBiYXNlZCBvbiBtYXRjaGVkIHBhdHRlcm5zLlxuICpcbiAqIEB0ZW1wbGF0ZSBUIC0gVGhlIHR5cGUgb2YgdGhlIHJlc29sdmVkIHZhbHVlLCBkZWZhdWx0aW5nIHRvIHN0cmluZy5cbiAqXG4gKiBAcGFyYW0gY21kIC0gVGhlIGNvbW1hbmQgc3RyaW5nIHRvIGJlIGV4ZWN1dGVkLlxuICogQHBhcmFtIGxvY2sgLSBBIFByb21pc2VFeGVjdXRvciB0byBjb250cm9sIHRoZSBhc3luY2hyb25vdXMgZmxvdy5cbiAqIEBwYXJhbSByZWdleHAgLSBBIHN0cmluZyBvciBSZWdFeHAgdG8gbWF0Y2ggYWdhaW5zdCB0aGUgb3V0cHV0LlxuICogQHBhcmFtIGZsYWdzIC0gT3B0aW9uYWwgZmxhZ3MgZm9yIHRoZSBSZWdFeHAgY29uc3RydWN0b3IsIGRlZmF1bHRzIHRvIFwiZ1wiLlxuICpcbiAqIEBjbGFzc1xuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IFJlZ2V4cE91dHB1dFdyaXRlciB9IGZyb20gJ0BkZWNhZi10cy91dGlscyc7XG4gKiBpbXBvcnQgeyBQcm9taXNlRXhlY3V0b3IgfSBmcm9tICdAZGVjYWYtdHMvdXRpbHMnO1xuICogXG4gKiAvLyBDcmVhdGUgYSBwcm9taXNlIGV4ZWN1dG9yXG4gKiBjb25zdCBleGVjdXRvcjogUHJvbWlzZUV4ZWN1dG9yPHN0cmluZywgRXJyb3I+ID0ge1xuICogICByZXNvbHZlOiAodmFsdWUpID0+IGNvbnNvbGUubG9nKGBSZXNvbHZlZDogJHt2YWx1ZX1gKSxcbiAqICAgcmVqZWN0OiAoZXJyb3IpID0+IGNvbnNvbGUuZXJyb3IoYFJlamVjdGVkOiAke2Vycm9yLm1lc3NhZ2V9YClcbiAqIH07XG4gKiBcbiAqIC8vIENyZWF0ZSBhIHJlZ2V4cCBvdXRwdXQgd3JpdGVyIHRoYXQgbWF0Y2hlcyB2ZXJzaW9uIG51bWJlcnNcbiAqIGNvbnN0IHdyaXRlciA9IG5ldyBSZWdleHBPdXRwdXRXcml0ZXIoJ25vZGUgLS12ZXJzaW9uJywgZXhlY3V0b3IsIC92KFxcZCtcXC5cXGQrXFwuXFxkKykvKTtcbiAqIFxuICogLy8gVXNlIHRoZSB3cml0ZXIgdG8gaGFuZGxlIGNvbW1hbmQgb3V0cHV0XG4gKiB3cml0ZXIuZGF0YSgndjE0LjE3LjAnKTsgIC8vIFRoaXMgd2lsbCBhdXRvbWF0aWNhbGx5IHJlc29sdmUgd2l0aCBcInYxNC4xNy4wXCJcbiAqIGBgYFxuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IFJlZ2V4cE91dHB1dFdyaXRlclxuICogICBwYXJ0aWNpcGFudCBTdGFuZGFyZE91dHB1dFdyaXRlclxuICogICBwYXJ0aWNpcGFudCBMb2dnZXJcbiAqICAgXG4gKiAgIENsaWVudC0+PlJlZ2V4cE91dHB1dFdyaXRlcjogbmV3IFJlZ2V4cE91dHB1dFdyaXRlcihjbWQsIGxvY2ssIHJlZ2V4cCwgZmxhZ3MpXG4gKiAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiBzdXBlcihjbWQsIGxvY2spXG4gKiAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+TG9nZ2VyOiBMb2dnaW5nLmZvcihjbWQpXG4gKiAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlJlZ2V4cE91dHB1dFdyaXRlcjogY29tcGlsZSByZWdleHBcbiAqICAgXG4gKiAgIENsaWVudC0+PlJlZ2V4cE91dHB1dFdyaXRlcjogZGF0YShjaHVuaylcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IHN1cGVyLmRhdGEoY2h1bmspXG4gKiAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+TG9nZ2VyOiBsb2dnZXIuaW5mbyhsb2cpXG4gKiAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlJlZ2V4cE91dHB1dFdyaXRlcjogdGVzdEFuZFJlc29sdmUoY2h1bmspXG4gKiAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlJlZ2V4cE91dHB1dFdyaXRlcjogdGVzdChjaHVuaylcbiAqICAgYWx0IG1hdGNoIGZvdW5kXG4gKiAgICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+UmVnZXhwT3V0cHV0V3JpdGVyOiByZXNvbHZlKG1hdGNoWzBdKVxuICogICAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiByZXNvbHZlKG1hdGNoWzBdKVxuICogICBlbmRcbiAqICAgXG4gKiAgIENsaWVudC0+PlJlZ2V4cE91dHB1dFdyaXRlcjogZXJyb3IoY2h1bmspXG4gKiAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiBzdXBlci5lcnJvcihjaHVuaylcbiAqICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5Mb2dnZXI6IGxvZ2dlci5pbmZvKGxvZylcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+UmVnZXhwT3V0cHV0V3JpdGVyOiB0ZXN0QW5kUmVqZWN0KGNodW5rKVxuICogICBSZWdleHBPdXRwdXRXcml0ZXItPj5SZWdleHBPdXRwdXRXcml0ZXI6IHRlc3QoY2h1bmspXG4gKiAgIGFsdCBtYXRjaCBmb3VuZFxuICogICAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlJlZ2V4cE91dHB1dFdyaXRlcjogcmVqZWN0KG1hdGNoWzBdKVxuICogICAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiByZWplY3QobWF0Y2hbMF0pXG4gKiAgIGVuZFxuICovXG5leHBvcnQgY2xhc3MgUmVnZXhwT3V0cHV0V3JpdGVyIGV4dGVuZHMgU3RhbmRhcmRPdXRwdXRXcml0ZXI8c3RyaW5nPiB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHJlZ3VsYXIgZXhwcmVzc2lvbiB1c2VkIGZvciBtYXRjaGluZyBvdXRwdXQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgcmVhZG9ubHkgcHJvcGVydHkgc3RvcmVzIHRoZSBjb21waWxlZCBSZWdFeHAgdXNlZCBmb3IgcGF0dGVybiBtYXRjaGluZy5cbiAgICovXG4gIHByb3RlY3RlZCByZWFkb25seSByZWdleHA6IFJlZ0V4cDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBjbWQ6IHN0cmluZyxcbiAgICBsb2NrOiBQcm9taXNlRXhlY3V0b3I8c3RyaW5nLCBFcnJvcj4sXG4gICAgcmVnZXhwOiBzdHJpbmcgfCBSZWdFeHAsXG4gICAgZmxhZ3MgPSBcImdcIlxuICApIHtcbiAgICBzdXBlcihjbWQsIGxvY2spO1xuICAgIHRyeSB7XG4gICAgICB0aGlzLnJlZ2V4cCA9XG4gICAgICAgIHR5cGVvZiByZWdleHAgPT09IFwic3RyaW5nXCIgPyBuZXcgUmVnRXhwKHJlZ2V4cCwgZmxhZ3MpIDogcmVnZXhwO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCByZWd1bGFyIGV4cHJlc3Npb246ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRlc3RzIHRoZSBpbnB1dCBkYXRhIGFnYWluc3QgdGhlIHN0b3JlZCByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAqIEBzdW1tYXJ5IEV4ZWN1dGVzIHRoZSByZWd1bGFyIGV4cHJlc3Npb24gb24gdGhlIGlucHV0IGRhdGEgYW5kIHJldHVybnMgdGhlIG1hdGNoIHJlc3VsdC5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBUaGUgc3RyaW5nIHRvIHRlc3QgYWdhaW5zdCB0aGUgcmVndWxhciBleHByZXNzaW9uLlxuICAgKiBAcmV0dXJuIFRoZSByZXN1bHQgb2YgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbiBleGVjdXRpb24sIG9yIHVuZGVmaW5lZCBpZiBhbiBlcnJvciBvY2N1cnMuXG4gICAqL1xuICBwcml2YXRlIHRlc3QoZGF0YTogc3RyaW5nKSB7XG4gICAgdGhpcy5yZWdleHAubGFzdEluZGV4ID0gMDtcbiAgICBsZXQgbWF0Y2g7XG4gICAgdHJ5IHtcbiAgICAgIG1hdGNoID0gdGhpcy5yZWdleHAuZXhlYyhkYXRhKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICByZXR1cm4gY29uc29sZS5kZWJ1ZyhgRmFpbGVkIHRvIHBhcnNlIGNodW5rOiAke2RhdGF9XFxuRXJyb3I6ICR7ZX0gYCk7XG4gICAgfVxuICAgIHJldHVybiBtYXRjaDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGVzdHMgdGhlIGRhdGEgYW5kIHJlc29sdmVzIHRoZSBwcm9taXNlIGlmIGEgbWF0Y2ggaXMgZm91bmQuXG4gICAqIEBzdW1tYXJ5IEV4ZWN1dGVzIHRoZSB0ZXN0IG1ldGhvZCBhbmQgcmVzb2x2ZXMgdGhlIHByb21pc2Ugd2l0aCB0aGUgZmlyc3QgbWF0Y2ggZ3JvdXAgaWYgc3VjY2Vzc2Z1bC5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBUaGUgc3RyaW5nIHRvIHRlc3QgYWdhaW5zdCB0aGUgcmVndWxhciBleHByZXNzaW9uLlxuICAgKi9cbiAgcHJvdGVjdGVkIHRlc3RBbmRSZXNvbHZlKGRhdGE6IHN0cmluZykge1xuICAgIGNvbnN0IG1hdGNoID0gdGhpcy50ZXN0KGRhdGEpO1xuICAgIGlmIChtYXRjaCkgdGhpcy5yZXNvbHZlKG1hdGNoWzBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGVzdHMgdGhlIGRhdGEgYW5kIHJlamVjdHMgdGhlIHByb21pc2UgaWYgYSBtYXRjaCBpcyBmb3VuZC5cbiAgICogQHN1bW1hcnkgRXhlY3V0ZXMgdGhlIHRlc3QgbWV0aG9kIGFuZCByZWplY3RzIHRoZSBwcm9taXNlIHdpdGggdGhlIGZpcnN0IG1hdGNoIGdyb3VwIGlmIHN1Y2Nlc3NmdWwuXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gVGhlIHN0cmluZyB0byB0ZXN0IGFnYWluc3QgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICovXG4gIHByb3RlY3RlZCB0ZXN0QW5kUmVqZWN0KGRhdGE6IHN0cmluZykge1xuICAgIGNvbnN0IG1hdGNoID0gdGhpcy50ZXN0KGRhdGEpO1xuICAgIGlmIChtYXRjaCkgdGhpcy5yZWplY3QobWF0Y2hbMF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgaW5jb21pbmcgZGF0YSBjaHVua3MuXG4gICAqIEBzdW1tYXJ5IENhbGxzIHRoZSBwYXJlbnQgY2xhc3MgZGF0YSBtZXRob2QgYW5kIHRoZW4gdGVzdHMgdGhlIGRhdGEgZm9yIGEgbWF0Y2ggdG8gcG90ZW50aWFsbHkgcmVzb2x2ZSB0aGUgcHJvbWlzZS5cbiAgICpcbiAgICogQHBhcmFtIGNodW5rIC0gVGhlIGRhdGEgY2h1bmsgdG8gcHJvY2Vzcy5cbiAgICovXG4gIG92ZXJyaWRlIGRhdGEoY2h1bms6IGFueSkge1xuICAgIHN1cGVyLmRhdGEoY2h1bmspO1xuICAgIHRoaXMudGVzdEFuZFJlc29sdmUoU3RyaW5nKGNodW5rKSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByb2Nlc3NlcyBpbmNvbWluZyBlcnJvciBjaHVua3MuXG4gICAqIEBzdW1tYXJ5IENhbGxzIHRoZSBwYXJlbnQgY2xhc3MgZXJyb3IgbWV0aG9kIGFuZCB0aGVuIHRlc3RzIHRoZSBkYXRhIGZvciBhIG1hdGNoIHRvIHBvdGVudGlhbGx5IHJlamVjdCB0aGUgcHJvbWlzZS5cbiAgICpcbiAgICogQHBhcmFtIGNodW5rIC0gVGhlIGVycm9yIGNodW5rIHRvIHByb2Nlc3MuXG4gICAqL1xuICBvdmVycmlkZSBlcnJvcihjaHVuazogYW55KSB7XG4gICAgc3VwZXIuZXJyb3IoY2h1bmspO1xuICAgIHRoaXMudGVzdEFuZFJlamVjdChTdHJpbmcoY2h1bmspKTtcbiAgfVxufVxuIiwiZXhwb3J0ICogZnJvbSBcIi4vY2xpXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9pbnB1dFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vb3V0cHV0XCI7XG5leHBvcnQgKiBmcm9tIFwiLi91dGlsc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vd3JpdGVyc1wiO1xuXG4vKipcbiAqIEBtb2R1bGUgdXRpbHNcbiAqIEBkZXNjcmlwdGlvbiBVdGlsaXRpZXMgYW5kIGJ1aWxkaW5nIGJsb2NrcyBmb3IgRGVjYWYtVFMgQ0xJIGFuZCBzY3JpcHRpbmcuXG4gKiBAc3VtbWFyeSBBZ2dyZWdhdGVzIENMSSBjb21tYW5kIGluZnJhc3RydWN0dXJlLCBpbnB1dCBoZWxwZXJzLCBvdXRwdXQgd3JpdGVycywgZmlsZXN5c3RlbS9uZXR3b3JrIHV0aWxpdGllcyxcbiAqIGFuZCBzaGFyZWQgdHlwZXMuIENvbnN1bWVycyB0eXBpY2FsbHkgdXNlIHtAbGluayBDb21tYW5kfSwge0BsaW5rIFVzZXJJbnB1dH0sIHtAbGluayBTdGFuZGFyZE91dHB1dFdyaXRlcn0sXG4gKiB7QGxpbmsgcHJpbnRCYW5uZXJ9LCBhbmQgdXRpbGl0aWVzIGZyb20ge0BsaW5rIG1vZHVsZTp1dGlsc3x1dGlsc30uXG4gKlxuICogVGhpcyBlbnRyeXBvaW50IHJlLWV4cG9ydHMgc3VicGFja2FnZXM6XG4gKiAtIENMSSBmcmFtZXdvcmsgdW5kZXIgYC4vY2xpYCAoY29tbWFuZCBiYXNlLCBvcHRpb25zLCBidWlsdC1pbiBjb21tYW5kcylcbiAqIC0gSW5wdXQgaGVscGVycyB1bmRlciBgLi9pbnB1dGAgKHByb21wdGluZyBhbmQgYXJnIHBhcnNpbmcpXG4gKiAtIE91dHB1dCBoZWxwZXJzIHVuZGVyIGAuL291dHB1dGAgKGJhbm5lciBhbmQgc3R5bGluZylcbiAqIC0gR2VuZXJhbCB1dGlsaXRpZXMgdW5kZXIgYC4vdXRpbHNgIChmcywgaHR0cCwgZXhlYywgdHlwZXMpXG4gKiAtIFdyaXRlcnMgdW5kZXIgYC4vd3JpdGVyc2AgKHN0ZG91dC9zdGRlcnIgcHJvY2Vzc29ycylcbiAqXG4gKiBOb3RlOiBJbmRpdmlkdWFsIGV4cG9ydHMgYXJlIGRvY3VtZW50ZWQgaW4gdGhlaXIgc291cmNlIGZpbGVzLlxuICovXG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlcHJlc2VudHMgdGhlIGN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgbW9kdWxlLlxuICogQHN1bW1hcnkgU3RvcmVzIHRoZSB2ZXJzaW9uIGZvciB0aGUgQGRlY2FmLXRzL3V0aWxzIHBhY2thZ2UuIFRoZSBidWlsZCByZXBsYWNlc1xuICogdGhlIHBsYWNlaG9sZGVyIHdpdGggdGhlIGFjdHVhbCB2ZXJzaW9uIG51bWJlciBhdCBwdWJsaXNoIHRpbWUuXG4gKiBAY29uc3QgVkVSU0lPTlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgY29uc3QgVkVSU0lPTiA9IFwiIyNWRVJTSU9OIyNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVwcmVzZW50cyB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIHRoZSBtb2R1bGUuXG4gKiBAc3VtbWFyeSBTdG9yZXMgdGhlIHZlcnNpb24gZm9yIHRoZSBAZGVjYWYtdHMvdXRpbHMgcGFja2FnZS4gVGhlIGJ1aWxkIHJlcGxhY2VzXG4gKiB0aGUgcGxhY2Vob2xkZXIgd2l0aCB0aGUgYWN0dWFsIHZlcnNpb24gbnVtYmVyIGF0IHB1Ymxpc2ggdGltZS5cbiAqIEBjb25zdCBWRVJTSU9OXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBQQUNLQUdFX05BTUUgPSBcIiMjUEFDS0FHRSMjXCI7XG4iXSwibmFtZXMiOlsiVXNlcklucHV0IiwidGhpcyIsImxvZ2dlciIsIkxvZ2dpbmciLCJmb3IiLCJjb25zdHJ1Y3RvciIsIm5hbWUiLCJ0eXBlIiwic2V0VHlwZSIsInZlcmJvc2UiLCJzZXRNZXNzYWdlIiwidmFsdWUiLCJtZXNzYWdlIiwic2V0SW5pdGlhbCIsImluaXRpYWwiLCJzZXRTdHlsZSIsInN0eWxlIiwic2V0Rm9ybWF0IiwiZm9ybWF0Iiwic2V0VmFsaWRhdGUiLCJ2YWxpZGF0ZSIsInNldE9uU3RhdGUiLCJvblN0YXRlIiwic2V0TWluIiwibWluIiwic2V0TWF4IiwibWF4Iiwic2V0RmxvYXQiLCJmbG9hdCIsInNldFJvdW5kIiwicm91bmQiLCJzZXRJbnN0cnVjdGlvbnMiLCJpbnN0cnVjdGlvbnMiLCJzZXRJbmNyZW1lbnQiLCJpbmNyZW1lbnQiLCJzZXRTZXBhcmF0b3IiLCJzZXBhcmF0b3IiLCJzZXRBY3RpdmUiLCJhY3RpdmUiLCJzZXRJbmFjdGl2ZSIsImluYWN0aXZlIiwic2V0Q2hvaWNlcyIsIkpTT04iLCJzdHJpbmdpZnkiLCJjaG9pY2VzIiwic2V0SGludCIsImhpbnQiLCJzZXRXYXJuIiwid2FybiIsInNldFN1Z2dlc3QiLCJzdWdnZXN0Iiwic2V0TGltaXQiLCJsaW1pdCIsInNldE1hc2siLCJtYXNrIiwic2V0U3Rkb3V0Iiwic3Rkb3V0Iiwic2V0U3RkaW4iLCJzdGRpbiIsImFzayIsInF1ZXN0aW9uIiwibG9nIiwiQXJyYXkiLCJpc0FycmF5IiwiYW5zd2VycyIsIm1hcCIsInEiLCJqb2luIiwicHJvbXB0cyIsImVycm9yIiwiRXJyb3IiLCJhc2tOdW1iZXIiLCJ1c2VySW5wdXQiLCJhc2tUZXh0IiwidW5kZWZpbmVkIiwiYXNrQ29uZmlybWF0aW9uIiwiaW5zaXN0IiwiaW5wdXQiLCJ0ZXN0IiwiZGVmYXVsdENvbmZpcm1hdGlvbiIsInRvU3RyaW5nIiwicmVzdWx0IiwiY291bnQiLCJjb25maXJtYXRpb24iLCJlIiwiaW5mbyIsImluc2lzdEZvclRleHQiLCJpbnNpc3RGb3JOdW1iZXIiLCJwYXJzZUFyZ3MiLCJvcHRpb25zIiwiYXJncyIsInByb2Nlc3MiLCJhcmd2Iiwic2xpY2UiLCJkZWJ1ZyIsIkRlZmF1bHRDb21tYW5kT3B0aW9ucyIsInNob3J0IiwiZGVmYXVsdCIsInZlcnNpb24iLCJoZWxwIiwibG9nTGV2ZWwiLCJsb2dTdHlsZSIsInRpbWVzdGFtcCIsImJhbm5lciIsIkRlZmF1bHRDb21tYW5kVmFsdWVzIiwiT2JqZWN0Iiwia2V5cyIsInJlZHVjZSIsImFjYyIsImtleSIsIkVuY29kaW5nIiwiU2VtVmVyc2lvblJlZ2V4IiwiU2VtVmVyc2lvbiIsIk5vQ0lGTGFnIiwiU2V0dXBTY3JpcHRLZXkiLCJUb2tlbnMiLCJBYm9ydENvZGUiLCJTdGFuZGFyZE91dHB1dFdyaXRlciIsImNtZCIsImxvY2siLCJkYXRhIiwiQnVmZmVyIiwiaXNCdWZmZXIiLCJyZWQiLCJ0ZXh0IiwiY2h1bmsiLCJTdHJpbmciLCJlcnJvcnMiLCJlcnIiLCJleGl0IiwiY29kZSIsImxvZ3MiLCJncmVlbiIsInJlc29sdmUiLCJsIiwidHJpbSIsInJlamVjdCIsImxlbmd0aCIsInBhcnNlQ29tbWFuZCIsImNvbW1hbmQiLCJwYXJ0cyIsInBhcnNlIiwiZmlsdGVyIiwicCIsInJlYXNvbiIsImxvY2tpZnkiLCJmIiwiUHJvbWlzZSIsInBhcmFtcyIsInRoZW4iLCJjYXRjaCIsImNoYWluQWJvcnRDb250cm9sbGVyIiwiYXJndW1lbnQwIiwicmVtYWluZGVyIiwic2lnbmFscyIsImNvbnRyb2xsZXIiLCJBYm9ydFNpZ25hbCIsIkFib3J0Q29udHJvbGxlciIsInNpZ25hbCIsImFib3J0ZWQiLCJoYW5kbGVyIiwiYWJvcnQiLCJhZGRFdmVudExpc3RlbmVyIiwib25jZSIsInNwYXduQ29tbWFuZCIsIm91dHB1dCIsIm9wdHMiLCJzcGF3bklubmVyIiwiYXJneiIsImNoaWxkUHJvY2VzcyIsInNwYXduIiwiY3dkIiwiZW52IiwiYXNzaWduIiwiUEFUSCIsInNoZWxsIiwicGlkIiwibSIsIm1hdGNoIiwiaW5jbHVkZXMiLCJjbWRzIiwic3BsaXQiLCJzcGF3bnMiLCJjb250cm9sbGVycyIsImkiLCJwdXNoIiwicGlwZSIsInJ1bkNvbW1hbmQiLCJvdXRwdXRDb25zdHJ1Y3RvciIsImVycnMiLCJzZXRFbmNvZGluZyIsIm9uIiwic3RkZXJyIiwicHJvbWlzZSIsImFzeW5jIiwiY2IiLCJsb2NhbFJlcXVpcmUiLCJjcmVhdGVSZXF1aXJlIiwiaXNUZXN0RW52aXJvbm1lbnQiLCJOT0RFX0VOViIsIkpFU1RfV09SS0VSX0lEIiwicGF0Y2hTdHJpbmciLCJ2YWx1ZXMiLCJmbGFncyIsImVudHJpZXMiLCJmb3JFYWNoIiwidmFsIiwicmVnZXhwIiwiUmVnRXhwIiwiZXNjYXBlUmVnRXhwIiwicmVwbGFjZSIsInN1YlN0ciIsInBhdGNoRmlsZSIsInBhdGgiLCJmcyIsImV4aXN0c1N5bmMiLCJjb250ZW50IiwicmVhZEZpbGUiLCJ3cml0ZUZpbGUiLCJyZWFkRmlsZVN5bmMiLCJ3cml0ZUZpbGVTeW5jIiwiZ2V0QWxsRmlsZXMiLCJmaWxlcyIsInJlYWRkaXJTeW5jIiwiZW50cnkiLCJmdWxsUGF0aCIsInN0YXQiLCJzdGF0U3luYyIsImlzRmlsZSIsImlzRGlyZWN0b3J5IiwicmVuYW1lRmlsZSIsInNvdXJjZSIsImRlc3QiLCJkZXNjcmlwdG9yU291cmNlIiwiZGVzY3JpcHRvckRlc3QiLCJyZW5hbWVTeW5jIiwiY29weUZpbGUiLCJta2RpclN5bmMiLCJyZWN1cnNpdmUiLCJjcFN5bmMiLCJkZWxldGVQYXRoIiwiZGVzY3JpcHRvciIsInJtU3luYyIsImZvcmNlIiwiZ2V0UGFja2FnZSIsInByb3BlcnR5IiwicGtnIiwic2V0UGFja2FnZUF0dHJpYnV0ZSIsImF0dHIiLCJnZXRQYWNrYWdlVmVyc2lvbiIsImdldERlcGVuZGVuY2llcyIsInBrZ1BhdGgiLCJsb2NrUGF0aCIsIm1hcERlcHMiLCJyZXNvbHZlRGVwZW5kZW5jeVZlcnNpb24iLCJwcm9kIiwiZGVwZW5kZW5jaWVzIiwiZGV2IiwiZGV2RGVwZW5kZW5jaWVzIiwicGVlciIsInBlZXJEZXBlbmRlbmNpZXMiLCJmYWxsYmFjayIsInBhY2thZ2VzIiwidXBkYXRlRGVwZW5kZW5jaWVzIiwiaW5zdGFsbElmTm90QXZhaWxhYmxlIiwiZGVwcyIsImN1cnJlbnQiLCJrbm93biIsIlNldCIsInRvSW5zdGFsbCIsImRlcCIsImhhcyIsImFkZCIsImluc3RhbGxEZXBlbmRlbmNpZXMiLCJkZXZEZXBzIiwiZnJvbSIsInB1c2hUb0dpdCIsImdpdFVzZXIiLCJnaXRFbWFpbCIsIm5vcm1hbGl6ZUltcG9ydCIsImltcG9ydFByb21pc2UiLCJnZXRGaWxlU2l6ZVppcHBlZCIsImRpciIsImNhbmRpZGF0ZXMiLCJzIiwiZW5kc1dpdGgiLCJzbWFsbGVzdCIsInNtYWxsZXN0U2l6ZSIsInNpemUiLCJjIiwiYnVmZmVyIiwiZ3oiLCJ6bGliIiwiZ3ppcFN5bmMiLCJzaXplS2IiLCJOdW1iZXIiLCJ0b0ZpeGVkIiwibGlzdEZvbGRlciIsImJhc2VQYXRoIiwid2l0aEZpbGVUeXBlcyIsIm5hbWVzIiwiZCIsImxpc3ROb2RlTW9kdWxlc1BhY2thZ2VzIiwic3RhcnRzV2l0aCIsInNjb3BlUGF0aCIsInNjb3BlZCIsInNsb2dhbnMiLCJTbG9nYW4iLCJUYWdzIiwiY29sb3JzIiwicHJpbnRCYW5uZXIiLCJnZXRTbG9nYW4iLCJtYXhMZW5ndGgiLCJsaW5lIiwiTWF0aCIsInBhZFN0YXJ0IiwiaW5kZXgiLCJiaW5kIiwiY29uc29sZSIsInJhdyIsImZsb29yIiwicmFuZG9tIiwiQ29tbWFuZCIsIkxvZ2dlZENsYXNzIiwiaW5wdXRzIiwicmVxdWlyZW1lbnRzIiwic3VwZXIiLCJkZWZpbmVQcm9wZXJ0eSIsIndyaXRhYmxlIiwiY2hlY2tSZXF1aXJlbWVudHMiLCJtaXNzaW5nIiwiZnVsbExpc3QiLCJleGVjdXRlIiwiTG9nZ2VkRW52aXJvbm1lbnQiLCJhY2N1bXVsYXRlIiwiY29udGV4dCIsInJ1biIsIkh0dHBDbGllbnQiLCJkb3dubG9hZEZpbGUiLCJ1cmwiLCJyZXF1ZXN0IiwiZW5jb2RlVVJJIiwiaHR0cHMiLCJnZXQiLCJyZXMiLCJzdGF0dXNDb2RlIiwiaGVhZGVycyIsImxvY2F0aW9uIiwiZGVmYXVsdENhbnZhc09wdGlvbnMiLCJ3aWR0aCIsImhlaWdodCIsInBhZGRpbmciLCJiYWNrZ3JvdW5kQ29sb3IiLCJoZWFkZXJGb250Iiwicm93Rm9udCIsImhlYWRlckNvbG9yIiwicm93Q29sb3IiLCJkZWxheSIsIm1zIiwic2V0VGltZW91dCIsInBlcmZEZWJ1Z0VuYWJsZWQiLCJQRVJGX1ZFUkJPU0UiLCJkZWJ1Z0xvZyIsImZvcm1hdFRhYmxlIiwidGl0bGUiLCJyb3dzIiwiY29sdW1uV2lkdGhzIiwiaGVhZGVyIiwicm93IiwiZm9ybWF0Um93IiwicGFkRW5kIiwiaGVhZGVyTGluZSIsImRpdmlkZXIiLCJyZXBlYXQiLCJib2R5IiwiZW5zdXJlRGlyZWN0b3J5IiwidGFyZ2V0UGF0aCIsIm1rZGlyIiwiZGlybmFtZSIsInJlbmRlck1ldHJpY3NUYWJsZVRvQ2FudmFzIiwib3V0cHV0UGF0aCIsImNvbmZpZyIsImNyZWF0ZUNhbnZhcyIsImNhbnZhc01vZHVsZSIsImltcG9ydCIsImNhbnZhcyIsImN0eCIsImdldENvbnRleHQiLCJmaWxsU3R5bGUiLCJmaWxsUmVjdCIsImZvbnQiLCJjb2x1bW5XaWR0aCIsImhlYWRlclkiLCJmaWxsVGV4dCIsInJvd0hlaWdodCIsInJvd0luZGV4IiwieSIsImNlbGwiLCJjZWxsSW5kZXgiLCJ0b0J1ZmZlciIsIlBlcmZvcm1hbmNlUnVubmVyIiwic2NlbmFyaW8iLCJpbml0aWFsaXplIiwicGhhc2VDb3VudGVyIiwicXVldWUiLCJwaGFzZXMiLCJwaGFzZSIsInBoYXNlTnVtYmVyIiwicmVzdWx0cyIsIml0ZW0iLCJzaGlmdCIsIm1lcmdlQ29udGV4dCIsIml0ZXJhdGlvbnMiLCJtb2RlIiwiY29uY3VycmVuY3kiLCJidXJzdCIsInJ1blBoYXNlIiwidG90YWwiLCJhZ2dyZWdhdGVkIiwidG90YWxEdXJhdGlvbk1zIiwiYXZnIiwiYXZlcmFnZU1zIiwiZmFpbHVyZUNvdW50IiwiZ2VuZXJhdG9yIiwiaGlzdG9yeVNuYXBzaG90IiwibWV0YWRhdGEiLCJwaGFzZU5hbWUiLCJpdGVyYXRpb25Db3VudCIsImJ1cnN0U2VnbWVudHMiLCJzZWdtZW50Q291bnQiLCJoaXN0b3J5IiwiZ2VuZXJhdG9yUmVzdWx0IiwibmV4dFBoYXNlIiwibG9nU3VtbWFyeSIsInJ1bldhcm11cCIsInNlZ21lbnRzIiwiYnVpbGRTZWdtZW50SW5kaWNlcyIsImNvbGxlY3RlZCIsInNlZ21lbnRJbmRleCIsImluZGljZXMiLCJtZXRyaWNzIiwiZXhlY3V0ZVNlZ21lbnQiLCJidXJzdEludGVydmFsIiwiaW50ZXJ2YWxNcyIsInNvcnRlZCIsInNvcnQiLCJhIiwiYiIsIml0ZXJhdGlvbiIsImFnZ3JlZ2F0ZU1ldHJpY3MiLCJwYXVzZUFmdGVyTXMiLCJmYWlsT25FcnJvciIsIml0ZXJhdGlvbk1ldHJpY3MiLCJ3YXJtdXAiLCJsb2FkRmFjdG9yIiwiY29tcHV0ZUxvYWRGYWN0b3IiLCJkZWxheUJldHdlZW5JdGVyYXRpb25zTXMiLCJiYXNlIiwibG9hZFN0YXJ0Iiwic3RlcCIsImxvYWRTdGVwIiwibXVsdGlwbGllciIsImxvYWRNdWx0aXBsaWVyIiwiY3Vyc29yIiwiZW5kIiwiXyIsImlkeCIsImJhc2VDb250ZXh0IiwicGhhc2VDb250ZXh0IiwibWVyZ2VDb250ZXh0cyIsImNvbGxlY3RDb25jdXJyZW50IiwiY29sbGVjdFNlcXVlbnRpYWwiLCJkZWxheUJldHdlZW4iLCJydW5JdGVyYXRpb24iLCJwb2ludGVyIiwid29ya2VyIiwiYWxsIiwic3RvcHdhdGNoIiwiU3RvcFdhdGNoIiwic3VjY2VzcyIsIm1ldGEiLCJkdXJhdGlvbk1zIiwic3RvcCIsIm1pbk1zIiwibWF4TXMiLCJzdWNjZXNzQ291bnQiLCJsb2FkRW5kIiwibWV0cmljIiwic2hvdWxkUmVuZGVyQ2FudmFzIiwiY2hhcnRQYXRoIiwiY2FudmFzT3V0cHV0UGF0aCIsImNhbnZhc09wdGlvbnMiLCJlbmFibGVDYW52YXMiLCJCb29sZWFuIiwicGFyc2VMaXN0IiwicGFja2FnZVRvR2xvYmFsIiwid2l0aG91dFNjb3BlIiwiY2hhckF0IiwidG9VcHBlckNhc2UiLCJnZXRQYWNrYWdlRGVwZW5kZW5jaWVzIiwiaGFzRGVwcyIsImZhbGxiYWNrRGlyIiwiX19kaXJuYW1lIiwiVkVSU0lPTl9TVFJJTkciLCJQQUNLQUdFX1NUUklORyIsIlBBQ0tBR0VfU0laRV9TVFJJTkciLCJNb2RlcyIsIkJ1aWxkTW9kZSIsImJ1aWxkTW9kZSIsIkFMTCIsImV4dGVybmFscyIsImRvY3MiLCJjb21tYW5kcyIsImNqczJUcmFuc2Zvcm1lciIsImV4dCIsIkJ1aWxkU2NyaXB0cyIsInJlc29sdXRpb25DYWNoZSIsIk1hcCIsInRyYW5zZm9ybWF0aW9uQ29udGV4dCIsInNvdXJjZUZpbGUiLCJzb3VyY2VEaXIiLCJmaWxlTmFtZSIsInJlc29sdmVQYXRoIiwiaW1wb3J0UGF0aCIsImNhY2hlS2V5IiwiY2FjaGVkVmFsdWUiLCJyZXNvbHZlZFBhdGgiLCJlMiIsImlzQWJzb2x1dGUiLCJleHRlbnNpb24iLCJleGVjIiwiYmFzZW5hbWUiLCJyZWxhdGl2ZSIsInNldCIsInZpc2l0Tm9kZSIsIm5vZGUiLCJzaG91bGRNdXRhdGVNb2R1bGVTcGVjaWZpZXIiLCJ0cyIsImlzSW1wb3J0RGVjbGFyYXRpb24iLCJtb2R1bGVTcGVjaWZpZXIiLCJuZXdNb2R1bGVTcGVjaWZpZXIiLCJmYWN0b3J5IiwiY3JlYXRlU3RyaW5nTGl0ZXJhbCIsInVwZGF0ZUltcG9ydERlY2xhcmF0aW9uIiwibW9kaWZpZXJzIiwiaW1wb3J0Q2xhdXNlIiwiaXNFeHBvcnREZWNsYXJhdGlvbiIsInVwZGF0ZUV4cG9ydERlY2xhcmF0aW9uIiwiaXNUeXBlT25seSIsImV4cG9ydENsYXVzZSIsInZpc2l0RWFjaENoaWxkIiwiaXNTdHJpbmdMaXRlcmFsIiwiZXh0bmFtZSIsInJlcGxhY2VtZW50cyIsInBrZ05hbWUiLCJwa2dWZXJzaW9uIiwicGF0Y2hGaWxlcyIsImZpbGUiLCJwYXJlbnRQYXRoIiwicmVwb3J0RGlhZ25vc3RpY3MiLCJkaWFnbm9zdGljcyIsIm1zZyIsImZvcm1hdERpYWdub3N0aWNzIiwiZGlhZ25vc3RpYyIsInN0YXJ0IiwiY2hhcmFjdGVyIiwiZ2V0TGluZUFuZENoYXJhY3Rlck9mUG9zaXRpb24iLCJmbGF0dGVuRGlhZ25vc3RpY01lc3NhZ2VUZXh0IiwibWVzc2FnZVRleHQiLCJyZWFkQ29uZmlnRmlsZSIsImNvbmZpZ0ZpbGVOYW1lIiwiY29uZmlnRmlsZVRleHQiLCJwYXJzZUNvbmZpZ0ZpbGVUZXh0VG9Kc29uIiwiY29uZmlnT2JqZWN0IiwiTG9nTGV2ZWwiLCJjb25maWdQYXJzZVJlc3VsdCIsInBhcnNlSnNvbkNvbmZpZ0ZpbGVDb250ZW50Iiwic3lzIiwiZXZhbERpYWdub3N0aWNzIiwiY2F0ZWdvcnkiLCJEaWFnbm9zdGljQ2F0ZWdvcnkiLCJ3YXJuaW5ncyIsIldhcm5pbmciLCJzdWdnZXN0aW9ucyIsIlN1Z2dlc3Rpb24iLCJtZXNzYWdlcyIsIk1lc3NhZ2UiLCJwcmVDaGVja0RpYWdub3N0aWNzIiwicHJvZ3JhbSIsImdldFByZUVtaXREaWFnbm9zdGljcyIsImNoZWNrVHNEaWFnbm9zdGljcyIsImlzRGV2IiwiYnVuZGxlIiwidHNDb25maWciLCJtb2R1bGUiLCJNb2R1bGVLaW5kIiwiQU1EIiwib3V0RGlyIiwiaXNvbGF0ZWRNb2R1bGVzIiwib3V0RmlsZSIsIkVTTSIsIkVTMjAyMiIsIkNvbW1vbkpTIiwiaW5saW5lU291cmNlTWFwIiwiaW5saW5lU291cmNlcyIsInNvdXJjZU1hcCIsImNyZWF0ZVByb2dyYW0iLCJmaWxlTmFtZXMiLCJidWlsZFRzIiwidHJhbnNmb3JtYXRpb25zIiwiQ0pTIiwiYmVmb3JlIiwiZW1pdFJlc3VsdCIsImVtaXQiLCJhbGxEaWFnbm9zdGljcyIsImNvbmNhdCIsImJ1aWxkIiwiY29weUFzc2V0cyIsImhhc0Fzc2V0cyIsImlzTGliIiwiZW50cnlGaWxlIiwibmFtZU92ZXJyaWRlIiwiZXh0ZXJuYWxzQXJnIiwiaW5jbHVkZUFyZyIsImlzRXNtIiwiaW5jbHVkZSIsImV4dGVybmFsc0xpc3QiLCJidWlsdGluTGlzdCIsImJ1aWx0aW5Nb2R1bGVzIiwicm9sbHVwU291cmNlTWFwT3V0cHV0IiwicGx1Z2lucyIsInR5cGVzY3JpcHQiLCJjb21waWxlck9wdGlvbnMiLCJkZWNsYXJhdGlvbiIsImV4Y2x1ZGUiLCJ0c2NvbmZpZyIsImpzb24iLCJjb21tb25qcyIsIm5vZGVSZXNvbHZlIiwicmVzb2x2ZU9ubHkiLCJ0ZXJzZXJNb2QiLCJ0ZXJzZXJGbiIsInRlcnNlciIsInRlcnNlck9wdGlvbnNEZXYiLCJlY21hIiwiY29tcHJlc3MiLCJtYW5nbGUiLCJjb21tZW50cyIsImJlYXV0aWZ5IiwidGVyc2VyT3B0aW9uc1Byb2QiLCJwYXNzZXMiLCJkcm9wX2NvbnNvbGUiLCJkcm9wX2RlYnVnZ2VyIiwidG9wbGV2ZWwiLCJ1bnNhZmUiLCJ1bnNhZmVfYXJyb3dzIiwidW5zYWZlX2NvbXBzIiwiY29sbGFwc2VfdmFycyIsInJlZHVjZV9mdW5jcyIsInJlZHVjZV92YXJzIiwiYXNjaWlfb25seSIsImV4dGVybmFsIiwib253YXJuIiwidHJlZXNoYWtlIiwiZ2xvYmFscyIsIm91dHB1dHMiLCJlc01vZHVsZSIsInNvdXJjZW1hcCIsImV4cG9ydHMiLCJyb2xsdXAiLCJ3YXRjaEZpbGVzIiwiZ2VuZXJhdGVPdXRwdXRzIiwib3V0cHV0T3B0aW9ucyIsIndyaXRlIiwiYnVpbGRCeUVudiIsImluY2x1ZGVzQXJnIiwiQlVJTEQiLCJCVU5ETEUiLCJidWlsZERldiIsImJ1aWxkUHJvZCIsImJ1aWxkRG9jcyIsInNyYyIsImNpIiwidGFnIiwiUmVsZWFzZVNjcmlwdCIsInByZXBhcmVWZXJzaW9uIiwidGVzdFZlcnNpb24iLCJ0b0xvd2VyQ2FzZSIsIlBBVENIIiwiTUlOT1IiLCJNQUpPUiIsInByZXBhcmVNZXNzYWdlIiwiUmVnZXhwT3V0cHV0V3JpdGVyIiwibGFzdEluZGV4IiwidGVzdEFuZFJlc29sdmUiLCJ0ZXN0QW5kUmVqZWN0IiwiVkVSU0lPTiIsIlBBQ0tBR0VfTkFNRSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O1VBd0VhQTs7WUFDYUMsS0FBQUMsU0FBU0MsUUFBQUEsUUFBUUMsSUFBSUo7QUFBVztRQXdKeEQsV0FBQUssQ0FBWUM7WUFuSlpMLEtBQUFNLE9BQStEO1lBb0o3RE4sS0FBS0ssT0FBT0E7QUFDZDtRQVNBLE9BQUFFLENBQVFEO1lBQ05QLFVBQVVFLE9BQU9PLFFBQVEsb0JB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RUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFDRTtRQUNGQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFDRTtRQUNGQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFDRTtRQUNGQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFNO09BRVI7UUFDRUQsUUFBUTtRQUNSQyxNQUFN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
|