@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.
Files changed (171) hide show
  1. package/README.md +1 -1
  2. package/dist/utils.cjs +2561 -2
  3. package/dist/utils.js +2602 -2
  4. package/lib/assets/slogans.cjs +1 -1
  5. package/lib/bin/build-scripts.cjs +1 -1
  6. package/lib/bin/tag-release.cjs +1 -1
  7. package/lib/cli/command.cjs +1 -1
  8. package/lib/cli/commands/build-scripts.cjs +74 -14
  9. package/lib/cli/commands/build-scripts.d.ts +62 -2
  10. package/lib/cli/commands/index.cjs +1 -1
  11. package/lib/cli/commands/tag-release.cjs +1 -1
  12. package/lib/cli/constants.cjs +1 -1
  13. package/lib/cli/index.cjs +1 -1
  14. package/lib/cli/types.cjs +1 -1
  15. package/lib/esm/assets/slogans.js +1 -1
  16. package/lib/esm/bin/build-scripts.js +1 -1
  17. package/lib/esm/bin/tag-release.js +1 -1
  18. package/lib/esm/cli/command.js +1 -1
  19. package/lib/esm/cli/commands/build-scripts.d.ts +62 -2
  20. package/lib/esm/cli/commands/build-scripts.js +74 -14
  21. package/lib/esm/cli/commands/index.js +1 -1
  22. package/lib/esm/cli/commands/tag-release.js +1 -1
  23. package/lib/esm/cli/constants.js +1 -1
  24. package/lib/esm/cli/index.js +1 -1
  25. package/lib/esm/cli/types.js +1 -1
  26. package/lib/esm/index.d.ts +1 -1
  27. package/lib/esm/index.js +2 -2
  28. package/lib/esm/input/index.js +1 -1
  29. package/lib/esm/input/input.js +1 -1
  30. package/lib/esm/input/types.js +1 -1
  31. package/lib/esm/output/common.js +1 -1
  32. package/lib/esm/output/index.js +1 -1
  33. package/lib/esm/tests/Consumer.d.ts +106 -0
  34. package/lib/esm/tests/Consumer.js +79 -1
  35. package/lib/esm/tests/ProducerChildProcess.js +1 -1
  36. package/lib/esm/tests/TestReporter.d.ts +3 -0
  37. package/lib/esm/tests/TestReporter.js +20 -2
  38. package/lib/esm/tests/index.d.ts +3 -1
  39. package/lib/esm/tests/index.js +4 -2
  40. package/lib/esm/tests/jestPerformanceRunner.d.ts +7 -0
  41. package/lib/esm/tests/jestPerformanceRunner.js +15 -0
  42. package/lib/esm/tests/utils.d.ts +5 -0
  43. package/lib/esm/tests/utils.js +33 -0
  44. package/lib/esm/utils/constants.js +1 -1
  45. package/lib/esm/utils/fs.d.ts +1 -1
  46. package/lib/esm/utils/fs.js +76 -29
  47. package/lib/esm/utils/http.js +1 -1
  48. package/lib/esm/utils/index.d.ts +1 -0
  49. package/lib/esm/utils/index.js +2 -1
  50. package/lib/esm/utils/md.js +1 -1
  51. package/lib/esm/utils/performanceRunner.d.ts +126 -0
  52. package/lib/esm/utils/performanceRunner.js +344 -0
  53. package/lib/esm/utils/timeout.js +1 -1
  54. package/lib/esm/utils/types.js +1 -1
  55. package/lib/esm/utils/utils.js +1 -1
  56. package/lib/esm/writers/OutputWriter.js +1 -1
  57. package/lib/esm/writers/RegexpOutputWriter.js +1 -1
  58. package/lib/esm/writers/StandardOutputWriter.js +11 -4
  59. package/lib/esm/writers/index.js +1 -1
  60. package/lib/esm/writers/types.js +1 -1
  61. package/lib/index.cjs +2 -2
  62. package/lib/index.d.ts +1 -1
  63. package/lib/input/index.cjs +1 -1
  64. package/lib/input/input.cjs +1 -1
  65. package/lib/input/types.cjs +1 -1
  66. package/lib/output/common.cjs +1 -1
  67. package/lib/output/index.cjs +1 -1
  68. package/lib/tests/Consumer.cjs +79 -1
  69. package/lib/tests/Consumer.d.ts +106 -0
  70. package/lib/tests/ProducerChildProcess.cjs +1 -1
  71. package/lib/tests/TestReporter.cjs +20 -2
  72. package/lib/tests/TestReporter.d.ts +3 -0
  73. package/lib/tests/index.cjs +4 -2
  74. package/lib/tests/index.d.ts +3 -1
  75. package/lib/tests/jestPerformanceRunner.cjs +19 -0
  76. package/lib/tests/jestPerformanceRunner.d.ts +7 -0
  77. package/lib/tests/utils.cjs +36 -0
  78. package/lib/tests/utils.d.ts +5 -0
  79. package/lib/utils/constants.cjs +1 -1
  80. package/lib/utils/fs.cjs +76 -29
  81. package/lib/utils/fs.d.ts +1 -1
  82. package/lib/utils/http.cjs +1 -1
  83. package/lib/utils/index.cjs +2 -1
  84. package/lib/utils/index.d.ts +1 -0
  85. package/lib/utils/md.cjs +1 -1
  86. package/lib/utils/performanceRunner.cjs +384 -0
  87. package/lib/utils/performanceRunner.d.ts +126 -0
  88. package/lib/utils/timeout.cjs +1 -1
  89. package/lib/utils/types.cjs +1 -1
  90. package/lib/utils/utils.cjs +1 -1
  91. package/lib/writers/OutputWriter.cjs +1 -1
  92. package/lib/writers/RegexpOutputWriter.cjs +1 -1
  93. package/lib/writers/StandardOutputWriter.cjs +11 -4
  94. package/lib/writers/index.cjs +1 -1
  95. package/lib/writers/types.cjs +1 -1
  96. package/package.json +17 -10
  97. package/workdocs/assets/slogans.json +802 -0
  98. package/dist/utils.cjs.map +0 -1
  99. package/dist/utils.js.map +0 -1
  100. package/lib/assets/slogans.js.map +0 -1
  101. package/lib/bin/build-scripts.js.map +0 -1
  102. package/lib/bin/tag-release.js.map +0 -1
  103. package/lib/cli/command.js.map +0 -1
  104. package/lib/cli/commands/build-scripts.js.map +0 -1
  105. package/lib/cli/commands/index.js.map +0 -1
  106. package/lib/cli/commands/tag-release.js.map +0 -1
  107. package/lib/cli/constants.js.map +0 -1
  108. package/lib/cli/index.js.map +0 -1
  109. package/lib/cli/types.js.map +0 -1
  110. package/lib/esm/assets/slogans.js.map +0 -1
  111. package/lib/esm/bin/build-scripts.js.map +0 -1
  112. package/lib/esm/bin/tag-release.js.map +0 -1
  113. package/lib/esm/cli/command.js.map +0 -1
  114. package/lib/esm/cli/commands/build-scripts.js.map +0 -1
  115. package/lib/esm/cli/commands/index.js.map +0 -1
  116. package/lib/esm/cli/commands/tag-release.js.map +0 -1
  117. package/lib/esm/cli/constants.js.map +0 -1
  118. package/lib/esm/cli/index.js.map +0 -1
  119. package/lib/esm/cli/types.js.map +0 -1
  120. package/lib/esm/index.js.map +0 -1
  121. package/lib/esm/input/index.js.map +0 -1
  122. package/lib/esm/input/input.js.map +0 -1
  123. package/lib/esm/input/types.js.map +0 -1
  124. package/lib/esm/output/common.js.map +0 -1
  125. package/lib/esm/output/index.js.map +0 -1
  126. package/lib/esm/tests/Consumer.js.map +0 -1
  127. package/lib/esm/tests/ProducerChildProcess.js.map +0 -1
  128. package/lib/esm/tests/TestReporter.js.map +0 -1
  129. package/lib/esm/tests/index.js.map +0 -1
  130. package/lib/esm/utils/constants.js.map +0 -1
  131. package/lib/esm/utils/fs.js.map +0 -1
  132. package/lib/esm/utils/http.js.map +0 -1
  133. package/lib/esm/utils/index.js.map +0 -1
  134. package/lib/esm/utils/md.js.map +0 -1
  135. package/lib/esm/utils/tests.d.ts +0 -1
  136. package/lib/esm/utils/tests.js +0 -2
  137. package/lib/esm/utils/tests.js.map +0 -1
  138. package/lib/esm/utils/timeout.js.map +0 -1
  139. package/lib/esm/utils/types.js.map +0 -1
  140. package/lib/esm/utils/utils.js.map +0 -1
  141. package/lib/esm/writers/OutputWriter.js.map +0 -1
  142. package/lib/esm/writers/RegexpOutputWriter.js.map +0 -1
  143. package/lib/esm/writers/StandardOutputWriter.js.map +0 -1
  144. package/lib/esm/writers/index.js.map +0 -1
  145. package/lib/esm/writers/types.js.map +0 -1
  146. package/lib/index.js.map +0 -1
  147. package/lib/input/index.js.map +0 -1
  148. package/lib/input/input.js.map +0 -1
  149. package/lib/input/types.js.map +0 -1
  150. package/lib/output/common.js.map +0 -1
  151. package/lib/output/index.js.map +0 -1
  152. package/lib/tests/Consumer.js.map +0 -1
  153. package/lib/tests/ProducerChildProcess.js.map +0 -1
  154. package/lib/tests/TestReporter.js.map +0 -1
  155. package/lib/tests/index.js.map +0 -1
  156. package/lib/utils/constants.js.map +0 -1
  157. package/lib/utils/fs.js.map +0 -1
  158. package/lib/utils/http.js.map +0 -1
  159. package/lib/utils/index.js.map +0 -1
  160. package/lib/utils/md.js.map +0 -1
  161. package/lib/utils/tests.cjs +0 -18
  162. package/lib/utils/tests.d.ts +0 -1
  163. package/lib/utils/tests.js.map +0 -1
  164. package/lib/utils/timeout.js.map +0 -1
  165. package/lib/utils/types.js.map +0 -1
  166. package/lib/utils/utils.js.map +0 -1
  167. package/lib/writers/OutputWriter.js.map +0 -1
  168. package/lib/writers/RegexpOutputWriter.js.map +0 -1
  169. package/lib/writers/StandardOutputWriter.js.map +0 -1
  170. package/lib/writers/index.js.map +0 -1
  171. 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
- //# sourceMappingURL=utils.cjs.map
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 = [ "", "", "", "", "", "", "", "", "" ];
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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