@decaf-ts/mcp-server 0.4.1 → 0.4.6

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 (538) hide show
  1. package/LICENSE.md +31 -0
  2. package/dist/mcp-server.cjs +2 -2328
  3. package/dist/mcp-server.cjs.map +1 -0
  4. package/dist/mcp-server.js +2 -0
  5. package/dist/mcp-server.js.map +1 -0
  6. package/lib/bin/cli.cjs +7 -35
  7. package/lib/bin/cli.d.ts +0 -24
  8. package/lib/bin/cli.js.map +1 -0
  9. package/lib/builders/builder.cjs +91 -0
  10. package/lib/builders/builder.d.ts +25 -0
  11. package/lib/builders/builder.js.map +1 -0
  12. package/lib/{mcp/resources → builders}/index.cjs +5 -2
  13. package/lib/builders/index.d.ts +4 -0
  14. package/lib/builders/index.js.map +1 -0
  15. package/lib/builders/prompt-builder.cjs +76 -0
  16. package/lib/builders/prompt-builder.d.ts +12 -0
  17. package/lib/builders/prompt-builder.js.map +1 -0
  18. package/lib/builders/resource-builder.cjs +83 -0
  19. package/lib/builders/resource-builder.d.ts +14 -0
  20. package/lib/builders/resource-builder.js.map +1 -0
  21. package/lib/builders/tool-builder.cjs +104 -0
  22. package/lib/builders/tool-builder.d.ts +16 -0
  23. package/lib/builders/tool-builder.js.map +1 -0
  24. package/lib/constants.cjs +28 -30
  25. package/lib/constants.d.ts +19 -24
  26. package/lib/constants.js.map +1 -0
  27. package/lib/environment.cjs +32 -0
  28. package/lib/environment.d.ts +71 -0
  29. package/lib/environment.js.map +1 -0
  30. package/lib/esm/bin/cli.d.ts +0 -24
  31. package/lib/esm/bin/cli.js +7 -35
  32. package/lib/esm/bin/cli.js.map +1 -0
  33. package/lib/esm/builders/builder.d.ts +25 -0
  34. package/lib/esm/builders/builder.js +86 -0
  35. package/lib/esm/builders/builder.js.map +1 -0
  36. package/lib/esm/builders/index.d.ts +4 -0
  37. package/lib/esm/builders/index.js +5 -0
  38. package/lib/esm/builders/index.js.map +1 -0
  39. package/lib/esm/builders/prompt-builder.d.ts +12 -0
  40. package/lib/esm/builders/prompt-builder.js +72 -0
  41. package/lib/esm/builders/prompt-builder.js.map +1 -0
  42. package/lib/esm/builders/resource-builder.d.ts +14 -0
  43. package/lib/esm/builders/resource-builder.js +79 -0
  44. package/lib/esm/builders/resource-builder.js.map +1 -0
  45. package/lib/esm/builders/tool-builder.d.ts +16 -0
  46. package/lib/esm/builders/tool-builder.js +100 -0
  47. package/lib/esm/builders/tool-builder.js.map +1 -0
  48. package/lib/esm/constants.d.ts +19 -24
  49. package/lib/esm/constants.js +27 -29
  50. package/lib/esm/constants.js.map +1 -0
  51. package/lib/esm/environment.d.ts +71 -0
  52. package/lib/esm/environment.js +29 -0
  53. package/lib/esm/environment.js.map +1 -0
  54. package/lib/esm/index.d.ts +3 -10
  55. package/lib/esm/index.js +4 -11
  56. package/lib/esm/index.js.map +1 -0
  57. package/lib/esm/mcp-server.d.ts +10 -0
  58. package/lib/esm/mcp-server.js +189 -0
  59. package/lib/esm/mcp-server.js.map +1 -0
  60. package/lib/esm/modules/template-module/index.d.ts +6 -0
  61. package/lib/esm/modules/template-module/index.js +4 -0
  62. package/lib/esm/modules/template-module/index.js.map +1 -0
  63. package/lib/esm/prompts/code/constants.d.ts +1 -0
  64. package/lib/esm/prompts/code/constants.js +2 -0
  65. package/lib/esm/prompts/code/constants.js.map +1 -0
  66. package/lib/esm/prompts/code/design-patterns/builder.d.ts +2 -0
  67. package/lib/esm/prompts/code/design-patterns/builder.js +118 -0
  68. package/lib/esm/prompts/code/design-patterns/builder.js.map +1 -0
  69. package/lib/esm/prompts/code/design-patterns/constants.d.ts +1 -0
  70. package/lib/esm/prompts/code/design-patterns/constants.js +3 -0
  71. package/lib/esm/prompts/code/design-patterns/constants.js.map +1 -0
  72. package/lib/esm/prompts/example-prompt/index.d.ts +2 -0
  73. package/lib/esm/prompts/example-prompt/index.js +18 -0
  74. package/lib/esm/prompts/example-prompt/index.js.map +1 -0
  75. package/lib/esm/prompts/index.d.ts +2 -0
  76. package/lib/esm/prompts/index.js +26 -0
  77. package/lib/esm/prompts/index.js.map +1 -0
  78. package/lib/esm/prompts/interactive-jsdoc/index.d.ts +2 -0
  79. package/lib/esm/prompts/interactive-jsdoc/index.js +18 -0
  80. package/lib/esm/prompts/interactive-jsdoc/index.js.map +1 -0
  81. package/lib/esm/prompts/jsdocs/class-prompt.d.ts +2 -0
  82. package/lib/esm/prompts/jsdocs/class-prompt.js +52 -0
  83. package/lib/esm/prompts/jsdocs/class-prompt.js.map +1 -0
  84. package/lib/esm/prompts/jsdocs/const-prompt.d.ts +2 -0
  85. package/lib/esm/prompts/jsdocs/const-prompt.js +24 -0
  86. package/lib/esm/prompts/jsdocs/const-prompt.js.map +1 -0
  87. package/lib/esm/prompts/jsdocs/constants.d.ts +4 -0
  88. package/lib/esm/prompts/jsdocs/constants.js +46 -0
  89. package/lib/esm/prompts/jsdocs/constants.js.map +1 -0
  90. package/lib/esm/prompts/jsdocs/decorator-prompt.d.ts +2 -0
  91. package/lib/esm/prompts/jsdocs/decorator-prompt.js +42 -0
  92. package/lib/esm/prompts/jsdocs/decorator-prompt.js.map +1 -0
  93. package/lib/esm/prompts/jsdocs/enum-prompt.d.ts +2 -0
  94. package/lib/esm/prompts/jsdocs/enum-prompt.js +24 -0
  95. package/lib/esm/prompts/jsdocs/enum-prompt.js.map +1 -0
  96. package/lib/esm/prompts/jsdocs/function-prompt.d.ts +2 -0
  97. package/lib/esm/prompts/jsdocs/function-prompt.js +43 -0
  98. package/lib/esm/prompts/jsdocs/function-prompt.js.map +1 -0
  99. package/lib/esm/prompts/jsdocs/interface-prompt.d.ts +2 -0
  100. package/lib/esm/prompts/jsdocs/interface-prompt.js +24 -0
  101. package/lib/esm/prompts/jsdocs/interface-prompt.js.map +1 -0
  102. package/lib/esm/prompts/jsdocs/types-prompt.d.ts +2 -0
  103. package/lib/esm/prompts/jsdocs/types-prompt.js +24 -0
  104. package/lib/esm/prompts/jsdocs/types-prompt.js.map +1 -0
  105. package/lib/esm/resources/example-resource/index.d.ts +2 -0
  106. package/lib/esm/resources/example-resource/index.js +19 -0
  107. package/lib/esm/resources/example-resource/index.js.map +1 -0
  108. package/lib/esm/resources/index.d.ts +2 -0
  109. package/lib/esm/resources/index.js +4 -0
  110. package/lib/esm/resources/index.js.map +1 -0
  111. package/lib/esm/resources/repo-metadata/index.d.ts +2 -0
  112. package/lib/esm/resources/repo-metadata/index.js +25 -0
  113. package/lib/esm/resources/repo-metadata/index.js.map +1 -0
  114. package/lib/esm/tools/ast/ts-ast-tool.d.ts +2 -0
  115. package/lib/esm/tools/ast/ts-ast-tool.js +67 -0
  116. package/lib/esm/tools/ast/ts-ast-tool.js.map +1 -0
  117. package/lib/esm/tools/ast/types.d.ts +105 -0
  118. package/lib/esm/tools/ast/types.js +33 -0
  119. package/lib/esm/tools/ast/types.js.map +1 -0
  120. package/lib/esm/tools/ast/utils.d.ts +5 -0
  121. package/lib/esm/tools/ast/utils.js +58 -0
  122. package/lib/esm/tools/ast/utils.js.map +1 -0
  123. package/lib/esm/tools/ast-jsdoc-tools/apply.d.ts +6 -0
  124. package/lib/esm/tools/ast-jsdoc-tools/apply.js +29 -0
  125. package/lib/esm/tools/ast-jsdoc-tools/apply.js.map +1 -0
  126. package/lib/esm/tools/ast-jsdoc-tools/cli.js +33 -0
  127. package/lib/esm/tools/ast-jsdoc-tools/cli.js.map +1 -0
  128. package/lib/esm/tools/ast-jsdoc-tools/enumerator.d.ts +1 -0
  129. package/lib/esm/tools/ast-jsdoc-tools/enumerator.js +25 -0
  130. package/lib/esm/tools/ast-jsdoc-tools/enumerator.js.map +1 -0
  131. package/lib/esm/tools/ast-jsdoc-tools/fileRunner.d.ts +11 -0
  132. package/lib/esm/tools/ast-jsdoc-tools/fileRunner.js +29 -0
  133. package/lib/esm/tools/ast-jsdoc-tools/fileRunner.js.map +1 -0
  134. package/lib/esm/tools/ast-jsdoc-tools/formatter.d.ts +6 -0
  135. package/lib/esm/tools/ast-jsdoc-tools/formatter.js +18 -0
  136. package/lib/esm/tools/ast-jsdoc-tools/formatter.js.map +1 -0
  137. package/lib/esm/tools/ast-jsdoc-tools/generator.d.ts +12 -0
  138. package/lib/esm/tools/ast-jsdoc-tools/generator.js +55 -0
  139. package/lib/esm/tools/ast-jsdoc-tools/generator.js.map +1 -0
  140. package/lib/esm/tools/ast-jsdoc-tools/index.d.ts +7 -0
  141. package/lib/esm/tools/ast-jsdoc-tools/index.js +29 -0
  142. package/lib/esm/tools/ast-jsdoc-tools/index.js.map +1 -0
  143. package/lib/esm/tools/ast-jsdoc-tools/interactive.d.ts +1 -0
  144. package/lib/esm/tools/ast-jsdoc-tools/interactive.js +7 -0
  145. package/lib/esm/tools/ast-jsdoc-tools/interactive.js.map +1 -0
  146. package/lib/esm/tools/ast-jsdoc-tools/parser.d.ts +13 -0
  147. package/lib/esm/tools/ast-jsdoc-tools/parser.js +71 -0
  148. package/lib/esm/tools/ast-jsdoc-tools/parser.js.map +1 -0
  149. package/lib/esm/tools/ast-jsdoc-tools/patch.d.ts +2 -0
  150. package/lib/esm/tools/ast-jsdoc-tools/patch.js +23 -0
  151. package/lib/esm/tools/ast-jsdoc-tools/patch.js.map +1 -0
  152. package/lib/esm/tools/ast-jsdoc-tools/prompts/loader.d.ts +10 -0
  153. package/lib/esm/tools/ast-jsdoc-tools/prompts/loader.js +26 -0
  154. package/lib/esm/tools/ast-jsdoc-tools/prompts/loader.js.map +1 -0
  155. package/lib/esm/tools/ast-jsdoc-tools/repoRunner.d.ts +16 -0
  156. package/lib/esm/tools/ast-jsdoc-tools/repoRunner.js +61 -0
  157. package/lib/esm/tools/ast-jsdoc-tools/repoRunner.js.map +1 -0
  158. package/lib/esm/tools/ast-jsdoc-tools/tools/jsdoc-generator.d.ts +5 -0
  159. package/lib/esm/tools/ast-jsdoc-tools/tools/jsdoc-generator.js +78 -0
  160. package/lib/esm/tools/ast-jsdoc-tools/tools/jsdoc-generator.js.map +1 -0
  161. package/lib/esm/tools/ast-jsdoc-tools/utils/conflict-detector.d.ts +5 -0
  162. package/lib/esm/tools/ast-jsdoc-tools/utils/conflict-detector.js +30 -0
  163. package/lib/esm/tools/ast-jsdoc-tools/utils/conflict-detector.js.map +1 -0
  164. package/lib/esm/tools/ast-jsdoc-tools/utils/context-schema.d.ts +7 -0
  165. package/lib/esm/tools/ast-jsdoc-tools/utils/context-schema.js +29 -0
  166. package/lib/esm/tools/ast-jsdoc-tools/utils/context-schema.js.map +1 -0
  167. package/lib/esm/tools/ast-jsdoc-tools/utils/heuristics.d.ts +2 -0
  168. package/lib/esm/tools/ast-jsdoc-tools/utils/heuristics.js +31 -0
  169. package/lib/esm/tools/ast-jsdoc-tools/utils/heuristics.js.map +1 -0
  170. package/lib/esm/tools/ast-jsdoc-tools/utils/ts-project.d.ts +12 -0
  171. package/lib/esm/tools/ast-jsdoc-tools/utils/ts-project.js +21 -0
  172. package/lib/esm/tools/ast-jsdoc-tools/utils/ts-project.js.map +1 -0
  173. package/lib/esm/tools/example-tool/index.d.ts +2 -0
  174. package/lib/esm/tools/example-tool/index.js +29 -0
  175. package/lib/esm/tools/example-tool/index.js.map +1 -0
  176. package/lib/esm/tools/file-summarizer/index.d.ts +2 -0
  177. package/lib/esm/tools/file-summarizer/index.js +29 -0
  178. package/lib/esm/tools/file-summarizer/index.js.map +1 -0
  179. package/lib/esm/tools/index.d.ts +2 -0
  180. package/lib/esm/tools/index.js +6 -0
  181. package/lib/esm/tools/index.js.map +1 -0
  182. package/lib/esm/tools/jsdoc/ts-jsdoc-element-tool.d.ts +2 -0
  183. package/lib/esm/tools/jsdoc/ts-jsdoc-element-tool.js +84 -0
  184. package/lib/esm/tools/jsdoc/ts-jsdoc-element-tool.js.map +1 -0
  185. package/lib/esm/tools/jsdoc/utils.d.ts +5 -0
  186. package/lib/esm/tools/jsdoc/utils.js +53 -0
  187. package/lib/esm/tools/jsdoc/utils.js.map +1 -0
  188. package/lib/esm/tools/testing/ts-jest-list-tests.d.ts +2 -0
  189. package/lib/esm/tools/testing/ts-jest-list-tests.js +53 -0
  190. package/lib/esm/tools/testing/ts-jest-list-tests.js.map +1 -0
  191. package/lib/esm/types.d.ts +56 -47
  192. package/lib/esm/types.js +1 -1
  193. package/lib/esm/types.js.map +1 -0
  194. package/lib/esm/utils/banner.d.ts +3 -0
  195. package/lib/esm/utils/banner.js +107 -0
  196. package/lib/esm/utils/banner.js.map +1 -0
  197. package/lib/esm/version.d.ts +2 -0
  198. package/lib/esm/version.js +5 -0
  199. package/lib/esm/version.js.map +1 -0
  200. package/lib/index.cjs +4 -11
  201. package/lib/index.d.ts +3 -10
  202. package/lib/index.js.map +1 -0
  203. package/lib/mcp-server.cjs +226 -0
  204. package/lib/mcp-server.d.ts +10 -0
  205. package/lib/mcp-server.js.map +1 -0
  206. package/lib/modules/template-module/index.cjs +7 -0
  207. package/lib/modules/template-module/index.d.ts +6 -0
  208. package/lib/modules/template-module/index.js.map +1 -0
  209. package/lib/prompts/code/constants.cjs +5 -0
  210. package/lib/prompts/code/constants.d.ts +1 -0
  211. package/lib/prompts/code/constants.js.map +1 -0
  212. package/lib/prompts/code/design-patterns/builder.cjs +121 -0
  213. package/lib/prompts/code/design-patterns/builder.d.ts +2 -0
  214. package/lib/prompts/code/design-patterns/builder.js.map +1 -0
  215. package/lib/prompts/code/design-patterns/constants.cjs +6 -0
  216. package/lib/prompts/code/design-patterns/constants.d.ts +1 -0
  217. package/lib/prompts/code/design-patterns/constants.js.map +1 -0
  218. package/lib/prompts/example-prompt/index.cjs +21 -0
  219. package/lib/prompts/example-prompt/index.d.ts +2 -0
  220. package/lib/prompts/example-prompt/index.js.map +1 -0
  221. package/lib/prompts/index.cjs +29 -0
  222. package/lib/prompts/index.d.ts +2 -0
  223. package/lib/prompts/index.js.map +1 -0
  224. package/lib/prompts/interactive-jsdoc/index.cjs +21 -0
  225. package/lib/prompts/interactive-jsdoc/index.d.ts +2 -0
  226. package/lib/prompts/interactive-jsdoc/index.js.map +1 -0
  227. package/lib/prompts/jsdocs/class-prompt.cjs +55 -0
  228. package/lib/prompts/jsdocs/class-prompt.d.ts +2 -0
  229. package/lib/prompts/jsdocs/class-prompt.js.map +1 -0
  230. package/lib/prompts/jsdocs/const-prompt.cjs +27 -0
  231. package/lib/prompts/jsdocs/const-prompt.d.ts +2 -0
  232. package/lib/prompts/jsdocs/const-prompt.js.map +1 -0
  233. package/lib/prompts/jsdocs/constants.cjs +49 -0
  234. package/lib/prompts/jsdocs/constants.d.ts +4 -0
  235. package/lib/prompts/jsdocs/constants.js.map +1 -0
  236. package/lib/prompts/jsdocs/decorator-prompt.cjs +45 -0
  237. package/lib/prompts/jsdocs/decorator-prompt.d.ts +2 -0
  238. package/lib/prompts/jsdocs/decorator-prompt.js.map +1 -0
  239. package/lib/prompts/jsdocs/enum-prompt.cjs +27 -0
  240. package/lib/prompts/jsdocs/enum-prompt.d.ts +2 -0
  241. package/lib/prompts/jsdocs/enum-prompt.js.map +1 -0
  242. package/lib/prompts/jsdocs/function-prompt.cjs +46 -0
  243. package/lib/prompts/jsdocs/function-prompt.d.ts +2 -0
  244. package/lib/prompts/jsdocs/function-prompt.js.map +1 -0
  245. package/lib/prompts/jsdocs/interface-prompt.cjs +27 -0
  246. package/lib/prompts/jsdocs/interface-prompt.d.ts +2 -0
  247. package/lib/prompts/jsdocs/interface-prompt.js.map +1 -0
  248. package/lib/prompts/jsdocs/types-prompt.cjs +27 -0
  249. package/lib/prompts/jsdocs/types-prompt.d.ts +2 -0
  250. package/lib/prompts/jsdocs/types-prompt.js.map +1 -0
  251. package/lib/resources/example-resource/index.cjs +22 -0
  252. package/lib/resources/example-resource/index.d.ts +2 -0
  253. package/lib/resources/example-resource/index.js.map +1 -0
  254. package/lib/resources/index.cjs +7 -0
  255. package/lib/resources/index.d.ts +2 -0
  256. package/lib/resources/index.js.map +1 -0
  257. package/lib/resources/repo-metadata/index.cjs +28 -0
  258. package/lib/resources/repo-metadata/index.d.ts +2 -0
  259. package/lib/resources/repo-metadata/index.js.map +1 -0
  260. package/lib/tools/ast/ts-ast-tool.cjs +70 -0
  261. package/lib/tools/ast/ts-ast-tool.d.ts +2 -0
  262. package/lib/tools/ast/ts-ast-tool.js.map +1 -0
  263. package/lib/tools/ast/types.cjs +36 -0
  264. package/lib/tools/ast/types.d.ts +105 -0
  265. package/lib/tools/ast/types.js.map +1 -0
  266. package/lib/tools/ast/utils.cjs +65 -0
  267. package/lib/tools/ast/utils.d.ts +5 -0
  268. package/lib/tools/ast/utils.js.map +1 -0
  269. package/lib/tools/ast-jsdoc-tools/apply.cjs +36 -0
  270. package/lib/tools/ast-jsdoc-tools/apply.d.ts +6 -0
  271. package/lib/tools/ast-jsdoc-tools/apply.js.map +1 -0
  272. package/lib/tools/ast-jsdoc-tools/cli.cjs +38 -0
  273. package/lib/tools/ast-jsdoc-tools/cli.js.map +1 -0
  274. package/lib/tools/ast-jsdoc-tools/enumerator.cjs +31 -0
  275. package/lib/tools/ast-jsdoc-tools/enumerator.d.ts +1 -0
  276. package/lib/tools/ast-jsdoc-tools/enumerator.js.map +1 -0
  277. package/lib/tools/ast-jsdoc-tools/fileRunner.cjs +35 -0
  278. package/lib/tools/ast-jsdoc-tools/fileRunner.d.ts +11 -0
  279. package/lib/tools/ast-jsdoc-tools/fileRunner.js.map +1 -0
  280. package/lib/tools/ast-jsdoc-tools/formatter.cjs +21 -0
  281. package/lib/tools/ast-jsdoc-tools/formatter.d.ts +6 -0
  282. package/lib/tools/ast-jsdoc-tools/formatter.js.map +1 -0
  283. package/lib/tools/ast-jsdoc-tools/generator.cjs +58 -0
  284. package/lib/tools/ast-jsdoc-tools/generator.d.ts +12 -0
  285. package/lib/tools/ast-jsdoc-tools/generator.js.map +1 -0
  286. package/lib/tools/ast-jsdoc-tools/index.cjs +33 -0
  287. package/lib/tools/ast-jsdoc-tools/index.d.ts +7 -0
  288. package/lib/tools/ast-jsdoc-tools/index.js.map +1 -0
  289. package/lib/tools/ast-jsdoc-tools/interactive.cjs +10 -0
  290. package/lib/tools/ast-jsdoc-tools/interactive.d.ts +1 -0
  291. package/lib/tools/ast-jsdoc-tools/interactive.js.map +1 -0
  292. package/lib/tools/ast-jsdoc-tools/parser.cjs +77 -0
  293. package/lib/tools/ast-jsdoc-tools/parser.d.ts +13 -0
  294. package/lib/tools/ast-jsdoc-tools/parser.js.map +1 -0
  295. package/lib/tools/ast-jsdoc-tools/patch.cjs +29 -0
  296. package/lib/tools/ast-jsdoc-tools/patch.d.ts +2 -0
  297. package/lib/tools/ast-jsdoc-tools/patch.js.map +1 -0
  298. package/lib/tools/ast-jsdoc-tools/prompts/loader.cjs +32 -0
  299. package/lib/tools/ast-jsdoc-tools/prompts/loader.d.ts +10 -0
  300. package/lib/tools/ast-jsdoc-tools/prompts/loader.js.map +1 -0
  301. package/lib/tools/ast-jsdoc-tools/repoRunner.cjs +67 -0
  302. package/lib/tools/ast-jsdoc-tools/repoRunner.d.ts +16 -0
  303. package/lib/tools/ast-jsdoc-tools/repoRunner.js.map +1 -0
  304. package/lib/tools/ast-jsdoc-tools/tools/jsdoc-generator.cjs +81 -0
  305. package/lib/tools/ast-jsdoc-tools/tools/jsdoc-generator.d.ts +5 -0
  306. package/lib/tools/ast-jsdoc-tools/tools/jsdoc-generator.js.map +1 -0
  307. package/lib/tools/ast-jsdoc-tools/utils/conflict-detector.cjs +33 -0
  308. package/lib/tools/ast-jsdoc-tools/utils/conflict-detector.d.ts +5 -0
  309. package/lib/tools/ast-jsdoc-tools/utils/conflict-detector.js.map +1 -0
  310. package/lib/tools/ast-jsdoc-tools/utils/context-schema.cjs +32 -0
  311. package/lib/tools/ast-jsdoc-tools/utils/context-schema.d.ts +7 -0
  312. package/lib/tools/ast-jsdoc-tools/utils/context-schema.js.map +1 -0
  313. package/lib/tools/ast-jsdoc-tools/utils/heuristics.cjs +34 -0
  314. package/lib/tools/ast-jsdoc-tools/utils/heuristics.d.ts +2 -0
  315. package/lib/tools/ast-jsdoc-tools/utils/heuristics.js.map +1 -0
  316. package/lib/tools/ast-jsdoc-tools/utils/ts-project.cjs +57 -0
  317. package/lib/tools/ast-jsdoc-tools/utils/ts-project.d.ts +12 -0
  318. package/lib/tools/ast-jsdoc-tools/utils/ts-project.js.map +1 -0
  319. package/lib/tools/example-tool/index.cjs +32 -0
  320. package/lib/tools/example-tool/index.d.ts +2 -0
  321. package/lib/tools/example-tool/index.js.map +1 -0
  322. package/lib/tools/file-summarizer/index.cjs +32 -0
  323. package/lib/tools/file-summarizer/index.d.ts +2 -0
  324. package/lib/tools/file-summarizer/index.js.map +1 -0
  325. package/lib/tools/index.cjs +9 -0
  326. package/lib/tools/index.d.ts +2 -0
  327. package/lib/tools/index.js.map +1 -0
  328. package/lib/tools/jsdoc/ts-jsdoc-element-tool.cjs +87 -0
  329. package/lib/tools/jsdoc/ts-jsdoc-element-tool.d.ts +2 -0
  330. package/lib/tools/jsdoc/ts-jsdoc-element-tool.js.map +1 -0
  331. package/lib/tools/jsdoc/utils.cjs +60 -0
  332. package/lib/tools/jsdoc/utils.d.ts +5 -0
  333. package/lib/tools/jsdoc/utils.js.map +1 -0
  334. package/lib/tools/testing/ts-jest-list-tests.cjs +56 -0
  335. package/lib/tools/testing/ts-jest-list-tests.d.ts +2 -0
  336. package/lib/tools/testing/ts-jest-list-tests.js.map +1 -0
  337. package/lib/types.cjs +1 -1
  338. package/lib/types.d.ts +56 -47
  339. package/lib/types.js.map +1 -0
  340. package/lib/utils/banner.cjs +114 -0
  341. package/lib/utils/banner.d.ts +3 -0
  342. package/lib/utils/banner.js.map +1 -0
  343. package/lib/version.cjs +8 -0
  344. package/lib/version.d.ts +2 -0
  345. package/lib/version.js.map +1 -0
  346. package/package.json +14 -63
  347. package/dist/mcp-server.esm.cjs +0 -2300
  348. package/lib/McpWrapper.cjs +0 -189
  349. package/lib/McpWrapper.d.ts +0 -101
  350. package/lib/bin/validate-modules.cjs +0 -24
  351. package/lib/esm/McpWrapper.d.ts +0 -101
  352. package/lib/esm/McpWrapper.js +0 -182
  353. package/lib/esm/bin/validate-modules.js +0 -22
  354. package/lib/esm/mcp/aggregateModules.d.ts +0 -26
  355. package/lib/esm/mcp/aggregateModules.js +0 -185
  356. package/lib/esm/mcp/code.d.ts +0 -23
  357. package/lib/esm/mcp/code.js +0 -70
  358. package/lib/esm/mcp/decorator-tools.d.ts +0 -118
  359. package/lib/esm/mcp/decorator-tools.js +0 -237
  360. package/lib/esm/mcp/fastmcp-wiring.d.ts +0 -14
  361. package/lib/esm/mcp/fastmcp-wiring.js +0 -56
  362. package/lib/esm/mcp/index.d.ts +0 -9
  363. package/lib/esm/mcp/index.js +0 -29
  364. package/lib/esm/mcp/mcp-module.d.ts +0 -11
  365. package/lib/esm/mcp/mcp-module.js +0 -31
  366. package/lib/esm/mcp/moduleRegistry.d.ts +0 -14
  367. package/lib/esm/mcp/moduleRegistry.js +0 -47
  368. package/lib/esm/mcp/prompts/index.d.ts +0 -4
  369. package/lib/esm/mcp/prompts/index.js +0 -7
  370. package/lib/esm/mcp/prompts/prompts.d.ts +0 -22
  371. package/lib/esm/mcp/prompts/prompts.js +0 -203
  372. package/lib/esm/mcp/resources/index.d.ts +0 -1
  373. package/lib/esm/mcp/resources/index.js +0 -2
  374. package/lib/esm/mcp/resources/resources.d.ts +0 -2
  375. package/lib/esm/mcp/resources/resources.js +0 -69
  376. package/lib/esm/mcp/schemas.d.ts +0 -53
  377. package/lib/esm/mcp/schemas.js +0 -97
  378. package/lib/esm/mcp/templates/codex-templates.d.ts +0 -3
  379. package/lib/esm/mcp/templates/codex-templates.js +0 -33
  380. package/lib/esm/mcp/templates/index.d.ts +0 -71
  381. package/lib/esm/mcp/templates/index.js +0 -66
  382. package/lib/esm/mcp/templates/resource-templates.d.ts +0 -3
  383. package/lib/esm/mcp/templates/resource-templates.js +0 -60
  384. package/lib/esm/mcp/templates/workspace-templates.d.ts +0 -3
  385. package/lib/esm/mcp/templates/workspace-templates.js +0 -66
  386. package/lib/esm/mcp/tools/codex-tools.d.ts +0 -5
  387. package/lib/esm/mcp/tools/codex-tools.js +0 -244
  388. package/lib/esm/mcp/tools/generateMcpModule.d.ts +0 -9
  389. package/lib/esm/mcp/tools/generateMcpModule.js +0 -133
  390. package/lib/esm/mcp/tools/index.d.ts +0 -219
  391. package/lib/esm/mcp/tools/index.js +0 -27
  392. package/lib/esm/mcp/tools/tools.d.ts +0 -10
  393. package/lib/esm/mcp/tools/tools.js +0 -275
  394. package/lib/esm/mcp/types.d.ts +0 -66
  395. package/lib/esm/mcp/types.js +0 -2
  396. package/lib/esm/mcp/utils.d.ts +0 -3
  397. package/lib/esm/mcp/utils.js +0 -46
  398. package/lib/esm/mcp/validation/index.d.ts +0 -13
  399. package/lib/esm/mcp/validation/index.js +0 -116
  400. package/lib/esm/mcp/validation/scaffoldModule.d.ts +0 -9
  401. package/lib/esm/mcp/validation/scaffoldModule.js +0 -88
  402. package/lib/esm/mcp/workspace.d.ts +0 -9
  403. package/lib/esm/mcp/workspace.js +0 -73
  404. package/lib/esm/metadata.d.ts +0 -9
  405. package/lib/esm/metadata.js +0 -22
  406. package/lib/esm/modules/_template/index.d.ts +0 -32
  407. package/lib/esm/modules/_template/index.js +0 -16
  408. package/lib/esm/modules/_template/prompts/index.d.ts +0 -6
  409. package/lib/esm/modules/_template/prompts/index.js +0 -9
  410. package/lib/esm/modules/_template/resources/index.d.ts +0 -6
  411. package/lib/esm/modules/_template/resources/index.js +0 -9
  412. package/lib/esm/modules/_template/templates/index.d.ts +0 -7
  413. package/lib/esm/modules/_template/templates/index.js +0 -10
  414. package/lib/esm/modules/_template/tools/index.d.ts +0 -6
  415. package/lib/esm/modules/_template/tools/index.js +0 -15
  416. package/lib/esm/modules/decoration/index.d.ts +0 -46
  417. package/lib/esm/modules/decoration/index.js +0 -10
  418. package/lib/esm/modules/decoration/prompts/index.d.ts +0 -1
  419. package/lib/esm/modules/decoration/prompts/index.js +0 -2
  420. package/lib/esm/modules/decoration/resources/index.d.ts +0 -7
  421. package/lib/esm/modules/decoration/resources/index.js +0 -10
  422. package/lib/esm/modules/decoration/templates/index.d.ts +0 -6
  423. package/lib/esm/modules/decoration/templates/index.js +0 -9
  424. package/lib/esm/modules/decoration/tools/index.d.ts +0 -26
  425. package/lib/esm/modules/decoration/tools/index.js +0 -7
  426. package/lib/esm/modules/index.d.ts +0 -2
  427. package/lib/esm/modules/index.js +0 -17
  428. package/lib/esm/modules/mcp/decoration-assist.d.ts +0 -4
  429. package/lib/esm/modules/mcp/decoration-assist.js +0 -6
  430. package/lib/esm/modules/mcp/index.d.ts +0 -6
  431. package/lib/esm/modules/mcp/index.js +0 -16
  432. package/lib/esm/modules/mcp/prompts/index.d.ts +0 -2
  433. package/lib/esm/modules/mcp/prompts/index.js +0 -9
  434. package/lib/esm/modules/mcp/resources/index.d.ts +0 -2
  435. package/lib/esm/modules/mcp/resources/index.js +0 -24
  436. package/lib/esm/modules/mcp/templates/index.d.ts +0 -2
  437. package/lib/esm/modules/mcp/templates/index.js +0 -28
  438. package/lib/esm/modules/mcp/tools/index.d.ts +0 -6
  439. package/lib/esm/modules/mcp/tools/index.js +0 -15
  440. package/lib/esm/utils/modulePaths.d.ts +0 -6
  441. package/lib/esm/utils/modulePaths.js +0 -33
  442. package/lib/esm/utils/moduleValidator.d.ts +0 -14
  443. package/lib/esm/utils/moduleValidator.js +0 -176
  444. package/lib/esm/utils.d.ts +0 -61
  445. package/lib/esm/utils.js +0 -86
  446. package/lib/mcp/aggregateModules.cjs +0 -225
  447. package/lib/mcp/aggregateModules.d.ts +0 -26
  448. package/lib/mcp/code.cjs +0 -81
  449. package/lib/mcp/code.d.ts +0 -23
  450. package/lib/mcp/decorator-tools.cjs +0 -243
  451. package/lib/mcp/decorator-tools.d.ts +0 -118
  452. package/lib/mcp/fastmcp-wiring.cjs +0 -59
  453. package/lib/mcp/fastmcp-wiring.d.ts +0 -14
  454. package/lib/mcp/index.cjs +0 -57
  455. package/lib/mcp/index.d.ts +0 -9
  456. package/lib/mcp/mcp-module.cjs +0 -46
  457. package/lib/mcp/mcp-module.d.ts +0 -11
  458. package/lib/mcp/moduleRegistry.cjs +0 -52
  459. package/lib/mcp/moduleRegistry.d.ts +0 -14
  460. package/lib/mcp/prompts/index.cjs +0 -25
  461. package/lib/mcp/prompts/index.d.ts +0 -4
  462. package/lib/mcp/prompts/prompts.cjs +0 -217
  463. package/lib/mcp/prompts/prompts.d.ts +0 -22
  464. package/lib/mcp/resources/index.d.ts +0 -1
  465. package/lib/mcp/resources/resources.cjs +0 -72
  466. package/lib/mcp/resources/resources.d.ts +0 -2
  467. package/lib/mcp/schemas.cjs +0 -100
  468. package/lib/mcp/schemas.d.ts +0 -53
  469. package/lib/mcp/templates/codex-templates.cjs +0 -40
  470. package/lib/mcp/templates/codex-templates.d.ts +0 -3
  471. package/lib/mcp/templates/index.cjs +0 -76
  472. package/lib/mcp/templates/index.d.ts +0 -71
  473. package/lib/mcp/templates/resource-templates.cjs +0 -67
  474. package/lib/mcp/templates/resource-templates.d.ts +0 -3
  475. package/lib/mcp/templates/workspace-templates.cjs +0 -70
  476. package/lib/mcp/templates/workspace-templates.d.ts +0 -3
  477. package/lib/mcp/tools/codex-tools.cjs +0 -250
  478. package/lib/mcp/tools/codex-tools.d.ts +0 -5
  479. package/lib/mcp/tools/generateMcpModule.cjs +0 -139
  480. package/lib/mcp/tools/generateMcpModule.d.ts +0 -9
  481. package/lib/mcp/tools/index.cjs +0 -30
  482. package/lib/mcp/tools/index.d.ts +0 -219
  483. package/lib/mcp/tools/tools.cjs +0 -317
  484. package/lib/mcp/tools/tools.d.ts +0 -10
  485. package/lib/mcp/types.cjs +0 -3
  486. package/lib/mcp/types.d.ts +0 -66
  487. package/lib/mcp/utils.cjs +0 -54
  488. package/lib/mcp/utils.d.ts +0 -3
  489. package/lib/mcp/validation/index.cjs +0 -123
  490. package/lib/mcp/validation/index.d.ts +0 -13
  491. package/lib/mcp/validation/scaffoldModule.cjs +0 -94
  492. package/lib/mcp/validation/scaffoldModule.d.ts +0 -9
  493. package/lib/mcp/workspace.cjs +0 -119
  494. package/lib/mcp/workspace.d.ts +0 -9
  495. package/lib/metadata.cjs +0 -25
  496. package/lib/metadata.d.ts +0 -9
  497. package/lib/modules/_template/index.cjs +0 -23
  498. package/lib/modules/_template/index.d.ts +0 -32
  499. package/lib/modules/_template/prompts/index.cjs +0 -12
  500. package/lib/modules/_template/prompts/index.d.ts +0 -6
  501. package/lib/modules/_template/resources/index.cjs +0 -12
  502. package/lib/modules/_template/resources/index.d.ts +0 -6
  503. package/lib/modules/_template/templates/index.cjs +0 -13
  504. package/lib/modules/_template/templates/index.d.ts +0 -7
  505. package/lib/modules/_template/tools/index.cjs +0 -18
  506. package/lib/modules/_template/tools/index.d.ts +0 -6
  507. package/lib/modules/decoration/index.cjs +0 -17
  508. package/lib/modules/decoration/index.d.ts +0 -46
  509. package/lib/modules/decoration/prompts/index.cjs +0 -5
  510. package/lib/modules/decoration/prompts/index.d.ts +0 -1
  511. package/lib/modules/decoration/resources/index.cjs +0 -13
  512. package/lib/modules/decoration/resources/index.d.ts +0 -7
  513. package/lib/modules/decoration/templates/index.cjs +0 -12
  514. package/lib/modules/decoration/templates/index.d.ts +0 -6
  515. package/lib/modules/decoration/tools/index.cjs +0 -10
  516. package/lib/modules/decoration/tools/index.d.ts +0 -26
  517. package/lib/modules/index.cjs +0 -20
  518. package/lib/modules/index.d.ts +0 -2
  519. package/lib/modules/mcp/decoration-assist.cjs +0 -13
  520. package/lib/modules/mcp/decoration-assist.d.ts +0 -4
  521. package/lib/modules/mcp/index.cjs +0 -23
  522. package/lib/modules/mcp/index.d.ts +0 -6
  523. package/lib/modules/mcp/prompts/index.cjs +0 -12
  524. package/lib/modules/mcp/prompts/index.d.ts +0 -2
  525. package/lib/modules/mcp/resources/index.cjs +0 -27
  526. package/lib/modules/mcp/resources/index.d.ts +0 -2
  527. package/lib/modules/mcp/templates/index.cjs +0 -31
  528. package/lib/modules/mcp/templates/index.d.ts +0 -2
  529. package/lib/modules/mcp/tools/index.cjs +0 -18
  530. package/lib/modules/mcp/tools/index.d.ts +0 -6
  531. package/lib/utils/modulePaths.cjs +0 -43
  532. package/lib/utils/modulePaths.d.ts +0 -6
  533. package/lib/utils/moduleValidator.cjs +0 -184
  534. package/lib/utils/moduleValidator.d.ts +0 -14
  535. package/lib/utils.cjs +0 -129
  536. package/lib/utils.d.ts +0 -61
  537. /package/lib/{bin/validate-modules.d.ts → esm/tools/ast-jsdoc-tools/cli.d.ts} +0 -0
  538. /package/lib/{esm/bin/validate-modules.d.ts → tools/ast-jsdoc-tools/cli.d.ts} +0 -0
@@ -1,2328 +1,2 @@
1
- (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('fs'), require('path'), require('child_process'), require('zod'), require('diff'), require('@decaf-ts/decoration'), require('url'), require('node:fs'), require('node:path'), require('fastmcp'), require('@decaf-ts/logging')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'fs', 'path', 'child_process', 'zod', 'diff', '@decaf-ts/decoration', 'url', 'node:fs', 'node:path', 'fastmcp', '@decaf-ts/logging'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["mcp-server"] = {}, global.fs, global.path, global.child_process, global.zod, global.diff, global.decoration, global.url, global.fs$1, global.path$1, global.fastmcp, global.logging));
5
- })(this, (function (exports, fs, path, child_process, zod, diff, decoration, url, fs$1, path$1, fastmcp, logging) { 'use strict';
6
-
7
- /**
8
- * @description The filename that identifies Decaf CLI modules
9
- * @summary The standard filename for CLI module files where each library must export a single CliModule function
10
- *
11
- * @const MCP_FILE_NAME
12
- * @memberOf module:MCP
13
- */
14
- const MCP_FILE_NAME = "mcp-module";
15
- const WORKSPACE_ROOT_ENV = "MCP_WORKSPACE_ROOT";
16
- const PROMPT_DIRECTORIES = [".code/prompts", ".codex/prompts"];
17
- const DEFAULT_PROMPT_NAME = "doc";
18
- const CLIENT_INTEGRATIONS = [
19
- {
20
- id: "vscode",
21
- display: "Visual Studio Code",
22
- instructions: "When interacting from Visual Studio Code, prefer the vscode://workspace/{path} resource template to fetch file contents and use the apply-code-change tool to commit edits with previewable diffs.",
23
- },
24
- {
25
- id: "cursor",
26
- display: "Cursor",
27
- instructions: "Cursor clients can retrieve and update files through the cursor://workspace/{path} resource template. Always validate patches in dryRun mode before applying permanent changes.",
28
- },
29
- {
30
- id: "copilot",
31
- display: "GitHub Copilot",
32
- instructions: "Use the copilot://workspace/{path} resource template to stream file content into Copilot chat sessions. Prefer returning unified diffs to maintain alignment with Copilot's diff visualization.",
33
- },
34
- ];
35
-
36
- let workspaceRoot = initializeWorkspaceRoot();
37
- let userErrorCtor;
38
- class WorkspaceError extends Error {
39
- constructor(message) {
40
- super(message);
41
- this.name = "WorkspaceError";
42
- }
43
- }
44
- function initializeWorkspaceRoot() {
45
- const configured = process.env[WORKSPACE_ROOT_ENV];
46
- if (configured && configured.trim().length > 0) {
47
- return path.resolve(configured.trim());
48
- }
49
- return process.cwd();
50
- }
51
- async function getUserErrorCtor() {
52
- if (!userErrorCtor) {
53
- try {
54
- const mod = await import('fastmcp');
55
- userErrorCtor = mod
56
- .UserError;
57
- }
58
- catch {
59
- userErrorCtor = class MCPUserError extends Error {
60
- constructor(message) {
61
- super(message);
62
- this.name = "MCPUserError";
63
- }
64
- };
65
- }
66
- }
67
- return userErrorCtor;
68
- }
69
- async function throwUserError(message) {
70
- const Ctor = await getUserErrorCtor();
71
- throw new Ctor(message);
72
- }
73
- function setWorkspaceRoot(root) {
74
- workspaceRoot = path.resolve(root);
75
- }
76
- function getWorkspaceRoot() {
77
- return workspaceRoot;
78
- }
79
- function resolveInWorkspace(root, targetPath) {
80
- const resolved = path.isAbsolute(targetPath)
81
- ? path.normalize(targetPath)
82
- : path.resolve(root, targetPath);
83
- const relative = path.relative(root, resolved);
84
- if (relative.startsWith("..") || path.isAbsolute(relative)) {
85
- throw new WorkspaceError(`Path ${targetPath} escapes the workspace root at ${root}`);
86
- }
87
- return resolved;
88
- }
89
- async function readWorkspaceFile(root, target) {
90
- try {
91
- const absolute = resolveInWorkspace(root, target);
92
- return fs.readFileSync(absolute, "utf8");
93
- }
94
- catch (error) {
95
- if (error instanceof WorkspaceError) {
96
- await throwUserError(error.message);
97
- }
98
- /* istanbul ignore next */
99
- throw error;
100
- }
101
- }
102
- function __resetWorkspaceRoot(root) {
103
- setWorkspaceRoot(root);
104
- }
105
-
106
- const prompts = [];
107
- // Read registered module packages from a runtime global set by modules/index
108
- // This avoids importing moduleRegistry at module-eval time which creates circular imports.
109
- function getRegisteredModulePackages() {
110
- return globalThis.__DECAF_MODULE_PACKAGES__ ?? [];
111
- }
112
- const OBJECT_PROMPT_DEPENDENCIES = {
113
- module: ["doc", "module"],
114
- file: ["doc", "file"],
115
- class: ["doc", "class"],
116
- function: ["doc", "function"],
117
- interface: ["doc", "interface"],
118
- decorator: ["doc", "decorator"],
119
- constant: ["doc", "constant"],
120
- "bulk-docs": ["bulk-docs"],
121
- "bulk-tests": ["bulk-tests"],
122
- "update-readme": ["update-readme"],
123
- "repo-setup": ["repo-setup"],
124
- "release-notes": ["release-notes"],
125
- "mcp-module": ["mcp-module"],
126
- };
127
- function getObjectPromptDependencies() {
128
- return OBJECT_PROMPT_DEPENDENCIES;
129
- }
130
- function buildDocPrompts() {
131
- const root = getWorkspaceRoot();
132
- const fileBasedPrompts = discoverDocPrompts(root).map((prompt) => ({
133
- name: `doc/${prompt.name}`,
134
- description: prompt.description,
135
- load: async () => prompt.content,
136
- }));
137
- const integrationPrompts = CLIENT_INTEGRATIONS.map((integration) => ({
138
- name: `integration/${integration.id}`,
139
- description: `${integration.display} integration guidance`,
140
- load: async () => `You are coordinating with ${integration.display}. ${integration.instructions}\n\nTools available:\n- document-code\n- apply-code-change\n\nEnsure responses include actionable steps for the client.`,
141
- }));
142
- return [...fileBasedPrompts, ...integrationPrompts];
143
- }
144
- function summarizePromptContent(prompt, headingPrefix) {
145
- return [`## ${headingPrefix}`, "", prompt.content.trim()].join("\n");
146
- }
147
- function buildObjectPrompts() {
148
- const root = getWorkspaceRoot();
149
- const discovered = discoverDocPrompts(root);
150
- const promptByName = new Map();
151
- for (const prompt of discovered) {
152
- promptByName.set(prompt.name, prompt);
153
- }
154
- const outputs = [];
155
- for (const [objectType, dependencies] of Object.entries(OBJECT_PROMPT_DEPENDENCIES)) {
156
- const existing = dependencies
157
- .map((name) => promptByName.get(name))
158
- .filter((prompt) => Boolean(prompt));
159
- if (!existing.length)
160
- continue;
161
- outputs.push({
162
- name: `codex/${objectType}`,
163
- description: `Guidance derived from .codex prompts for ${objectType} tasks.`,
164
- load: async () => {
165
- const sections = existing.map((prompt) => summarizePromptContent(prompt, toTitleCase(prompt.name)));
166
- return [`# Codex guidance for ${objectType}`, "", ...sections].join("\n");
167
- },
168
- });
169
- }
170
- return outputs.sort((a, b) => a.name.localeCompare(b.name));
171
- }
172
- function toInputPrompt(asset) {
173
- const provenance = asset.provenance ? ` (module: ${asset.provenance})` : "";
174
- return {
175
- name: asset.id,
176
- description: `${asset.description ?? asset.title}${provenance}`,
177
- load: async () => asset.load(),
178
- };
179
- }
180
- function buildModulePrompts() {
181
- const pkgs = getRegisteredModulePackages();
182
- const assets = pkgs.flatMap((p) => p.prompts ?? []);
183
- return assets.map(toInputPrompt);
184
- }
185
- function refreshPrompts(repoPath) {
186
- const docPrompts = buildDocPrompts();
187
- const objectPrompts = buildObjectPrompts();
188
- const repoPrompts = [];
189
- const modulePrompts = buildModulePrompts();
190
- prompts.splice(0, prompts.length, ...docPrompts, ...objectPrompts, ...repoPrompts, ...modulePrompts);
191
- return prompts;
192
- }
193
- function discoverDocPrompts(root) {
194
- const discovered = [];
195
- for (const directory of PROMPT_DIRECTORIES) {
196
- const promptDir = path.join(root, directory);
197
- // debug logging to help tests diagnose prompt discovery
198
- console.debug("[discoverDocPrompts] checking", promptDir);
199
- if (!fs.existsSync(promptDir) || !fs.statSync(promptDir).isDirectory()) {
200
- continue;
201
- }
202
- for (const entry of fs.readdirSync(promptDir)) {
203
- const fullPath = path.join(promptDir, entry);
204
- if (!fs.statSync(fullPath).isFile())
205
- continue;
206
- const name = path.parse(entry).name;
207
- const content = fs.readFileSync(fullPath, "utf8");
208
- const title = toTitleCase(name.replace(/[-_]/g, " "));
209
- const description = extractDescription(content, fullPath);
210
- discovered.push({
211
- name,
212
- title,
213
- description,
214
- content,
215
- absolutePath: fullPath,
216
- });
217
- }
218
- }
219
- const unique = new Map();
220
- for (const prompt of discovered) {
221
- if (!unique.has(prompt.name)) {
222
- unique.set(prompt.name, prompt);
223
- }
224
- }
225
- return Array.from(unique.values()).sort((a, b) => a.name.localeCompare(b.name));
226
- }
227
- function selectPrompt(promptList, requestedName) {
228
- const direct = promptList.find((prompt) => prompt.name === requestedName);
229
- if (direct)
230
- return direct;
231
- const fallback = promptList.find((prompt) => prompt.name === DEFAULT_PROMPT_NAME);
232
- if (fallback)
233
- return fallback;
234
- if (!promptList.length) {
235
- throw new Error("No documentation prompts available");
236
- }
237
- return promptList[0];
238
- }
239
- function buildDocumentationPayload({ filePath, fileContent, prompt, includePrompt, includeCode, includeMetadata, additionalContext, }) {
240
- const sections = [];
241
- if (includeMetadata) {
242
- sections.push(`# Documentation Request\n- prompt: ${prompt.name}\n- file: ${filePath}`);
243
- }
244
- if (includePrompt) {
245
- sections.push(`## Prompt Guidance (${prompt.title})\n\n${prompt.content.trim()}`);
246
- }
247
- if (additionalContext?.trim()) {
248
- sections.push(`## Additional Context\n\n${additionalContext.trim()}`);
249
- }
250
- if (includeCode) {
251
- sections.push(`## Source\n\n\`\`\`${inferLanguageFromPath(filePath)}\n${fileContent}\n\`\`\``);
252
- }
253
- return {
254
- content: [
255
- {
256
- type: "text",
257
- text: sections.join("\n\n"),
258
- },
259
- ],
260
- };
261
- }
262
- function extractDescription(content, filePath) {
263
- const firstLine = content
264
- .split(/\r?\n/)
265
- .map((line) => line.trim())
266
- .find((line) => line.length > 0);
267
- return (firstLine?.slice(0, 240) ??
268
- `Documentation prompt loaded from ${path.basename(filePath)}`);
269
- }
270
- function toTitleCase(value) {
271
- return value
272
- .split(/\s+/)
273
- .filter(Boolean)
274
- .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
275
- .join(" ");
276
- }
277
- function inferLanguageFromPath(filePath) {
278
- const extension = path.extname(filePath).toLowerCase();
279
- switch (extension) {
280
- case ".ts":
281
- case ".tsx":
282
- return "ts";
283
- case ".js":
284
- case ".jsx":
285
- return "js";
286
- case ".json":
287
- return "json";
288
- case ".md":
289
- return "md";
290
- default:
291
- return "text";
292
- }
293
- }
294
-
295
- var prompts$1 = /*#__PURE__*/Object.freeze({
296
- __proto__: null,
297
- DEFAULT_PROMPT_NAME: DEFAULT_PROMPT_NAME,
298
- buildDocPrompts: buildDocPrompts,
299
- buildDocumentationPayload: buildDocumentationPayload,
300
- buildObjectPrompts: buildObjectPrompts,
301
- discoverDocPrompts: discoverDocPrompts,
302
- getObjectPromptDependencies: getObjectPromptDependencies,
303
- prompts: prompts,
304
- refreshPrompts: refreshPrompts,
305
- selectPrompt: selectPrompt
306
- });
307
-
308
- const promptList = prompts;
309
- function loadPrompts(repoPath) {
310
- return refreshPrompts();
311
- }
312
-
313
- class ModuleRegistry {
314
- constructor(packages = []) {
315
- this.packages = packages;
316
- }
317
- setPackages(pkgs) {
318
- this.packages = Array.isArray(pkgs) ? pkgs : [];
319
- }
320
- listPackages() {
321
- return this.packages;
322
- }
323
- listPrompts() {
324
- return this.collectAssets("prompts");
325
- }
326
- listResources() {
327
- return this.collectAssets("resources");
328
- }
329
- listTemplates() {
330
- return this.collectAssets("templates");
331
- }
332
- listTools() {
333
- return this.collectAssets("tools");
334
- }
335
- collectAssets(key) {
336
- const seen = new Map();
337
- const aggregated = [];
338
- for (const pkg of this.packages) {
339
- if (pkg.status === "disabled")
340
- continue;
341
- for (const asset of pkg[key]) {
342
- const maybeName = asset.name;
343
- const assetKey = (asset && (asset.id ?? maybeName)) || JSON.stringify(asset);
344
- if (seen.has(assetKey)) {
345
- const conflict = seen.get(assetKey);
346
- throw new Error(`Duplicate ${key} id '${assetKey}' from modules ${conflict} and ${pkg.name}`);
347
- }
348
- seen.set(assetKey, pkg.name);
349
- aggregated.push({ ...asset, provenance: pkg.name });
350
- }
351
- }
352
- return aggregated;
353
- }
354
- }
355
- const moduleRegistry = new ModuleRegistry();
356
-
357
- const analyzeRepoSchema = zod.z
358
- .object({
359
- repoPath: zod.z
360
- .string()
361
- .min(1, "repoPath is required")
362
- .describe("Relative or absolute path to the target repository inside this monorepo, e.g. './decoration'."),
363
- includeTests: zod.z
364
- .boolean()
365
- .default(true)
366
- .describe("If true, analyze the tests directory (if present) to derive expected behaviors."),
367
- includeDocs: zod.z
368
- .boolean()
369
- .default(true)
370
- .describe("If true, analyze README.md and docs directories to extract documented features."),
371
- })
372
- .strict()
373
- .describe("Analyze a local repository (e.g. ./decoration) to extract APIs, features, tests, and documentation cues.");
374
- const enumerateCapabilitiesSchema = zod.z
375
- .object({
376
- repoPath: zod.z
377
- .string()
378
- .min(1, "repoPath is required")
379
- .describe("Relative or absolute path to the target repository to enumerate developer-facing capabilities."),
380
- })
381
- .strict()
382
- .describe("Enumerate the complete set of capabilities a developer is expected to use from the given repository.");
383
- const planFeatureSchema = zod.z
384
- .object({
385
- feature: zod.z
386
- .string()
387
- .min(5, "feature must describe the goal clearly")
388
- .describe("Natural-language description of a developer's requested feature or task to implement using the repository and available MCP tools."),
389
- repoPath: zod.z
390
- .string()
391
- .default("./decoration")
392
- .describe("Target repository path providing the library to use, e.g. './decoration'."),
393
- })
394
- .strict()
395
- .describe("Plan which MCP tools to use and in what sequence to implement a requested feature using the repository.");
396
- const documentCodeSchema = zod.z
397
- .object({
398
- filePath: zod.z.string().min(1, "filePath is required"),
399
- promptName: zod.z.string().optional(),
400
- includePrompt: zod.z.boolean().default(true),
401
- includeCode: zod.z.boolean().default(true),
402
- includeMetadata: zod.z.boolean().default(true),
403
- additionalContext: zod.z.string().optional(),
404
- encoding: zod.z.string().default("utf8"),
405
- })
406
- .strict();
407
- const codeChangeSchema = zod.z
408
- .object({
409
- filePath: zod.z.string().min(1, "filePath is required"),
410
- patch: zod.z.string().min(1, "patch is required"),
411
- dryRun: zod.z.boolean().default(false),
412
- showDiff: zod.z.boolean().default(true),
413
- diffContext: zod.z.number().int().min(0).max(100).default(3),
414
- encoding: zod.z.string().default("utf8"),
415
- })
416
- .strict();
417
- const OBJECT_TYPES = [
418
- "module",
419
- "file",
420
- "class",
421
- "function",
422
- "interface",
423
- "decorator",
424
- "constant",
425
- ];
426
- const documentObjectSchema = zod.z
427
- .object({
428
- basePath: zod.z.string().min(1, "basePath is required"),
429
- objectType: zod.z.enum(OBJECT_TYPES),
430
- targetFile: zod.z.string().optional(),
431
- includeContent: zod.z.boolean().default(false),
432
- })
433
- .strict();
434
- const coverageTaskSchema = zod.z
435
- .object({
436
- basePath: zod.z.string().min(1, "basePath is required"),
437
- coverage: zod.z
438
- .number()
439
- .min(0)
440
- .max(100)
441
- .default(90)
442
- .describe("Target coverage percentage"),
443
- dryRun: zod.z.boolean().default(false),
444
- })
445
- .strict();
446
- const readmeImprovementSchema = zod.z
447
- .object({
448
- basePath: zod.z.string().min(1, "basePath is required"),
449
- includeExamples: zod.z.boolean().default(true),
450
- })
451
- .strict();
452
-
453
- function readFileSafe(filePath, encoding = "utf8") {
454
- try {
455
- return fs.readFileSync(filePath, { encoding });
456
- }
457
- catch {
458
- return undefined;
459
- }
460
- }
461
- function listFilesRecursive(root, matcher) {
462
- const out = [];
463
- const stack = [root];
464
- while (stack.length) {
465
- const cur = stack.pop();
466
- const stat = fs.statSync(cur);
467
- if (stat.isDirectory()) {
468
- for (const f of fs.readdirSync(cur))
469
- stack.push(path.join(cur, f));
470
- }
471
- else if (!matcher || matcher(cur)) {
472
- out.push(cur);
473
- }
474
- }
475
- return out.sort();
476
- }
477
- function deriveCapabilities(analysis) {
478
- const cap = new Set();
479
- // heuristics: if decorators like Decoration, flavouredAs, extend, override appear, add capabilities
480
- const allDecs = new Set();
481
- for (const k of Object.keys(analysis.api)) {
482
- for (const d of analysis.api[k].decorators)
483
- allDecs.add(d);
484
- for (const e of analysis.api[k].exports)
485
- if (/Decoration|decorate|Builder|Flavour/i.test(e))
486
- cap.add("use-decoration-api");
487
- }
488
- if ([...allDecs].some((d) => /override|extend/i.test(d)))
489
- cap.add("override-and-extend-decorations");
490
- if (Object.keys(analysis.tests).length > 0)
491
- cap.add("validate-with-tests");
492
- if (analysis.readme)
493
- cap.add("follow-readme-guides");
494
- return [...cap].sort();
495
- }
496
-
497
- // Analysis helpers (minimal yet effective, text-based to avoid heavy AST deps)
498
- function isSourceFile(p) {
499
- return /\.(ts|tsx|js|jsx)$/.test(p) && !p.endsWith(".d.ts");
500
- }
501
- function isTestFile(p) {
502
- return /(\.test\.|\.spec\.)/.test(p);
503
- }
504
- function extractExports(fileContent) {
505
- const names = new Set();
506
- const exportRe = /(export\s+(?:default\s+)?(?:class|function|const|let|var|interface|type|enum)\s+)([A-Za-z0-9_]+)/g;
507
- const namedRe = /export\s*\{([^}]+)\}/g;
508
- let m;
509
- while ((m = exportRe.exec(fileContent)))
510
- names.add(m[2]);
511
- while ((m = namedRe.exec(fileContent))) {
512
- m[1]
513
- .split(",")
514
- .map((s) => s.trim().split(" as ")[0].trim())
515
- .forEach((n) => {
516
- if (n)
517
- names.add(n);
518
- });
519
- }
520
- return [...names].sort();
521
- }
522
- function extractDecorators(fileContent) {
523
- const decs = new Set();
524
- const decRe = /@([A-Za-z_][A-Za-z0-9_]*)/g;
525
- let m;
526
- while ((m = decRe.exec(fileContent)))
527
- decs.add(m[1]);
528
- return [...decs].sort();
529
- }
530
- function summarizeReadme(readme) {
531
- if (!readme)
532
- return undefined;
533
- const lines = readme.split(/\r?\n/).filter(Boolean);
534
- const title = lines.find((l) => /^#\s+/.test(l))?.replace(/^#\s+/, "") || "README";
535
- const bullets = lines.filter((l) => /^[-*]\s+/.test(l)).slice(0, 20);
536
- return { title, bullets };
537
- }
538
- function analyzeRepo(root) {
539
- const src = path.join(root, "src");
540
- const testDir = path.join(root, "tests");
541
- const readmePath = path.join(root, "README.md");
542
- const readme = readFileSafe(readmePath);
543
- const files = fs.existsSync(src) ? listFilesRecursive(src, isSourceFile) : [];
544
- const testFiles = fs.existsSync(testDir)
545
- ? listFilesRecursive(testDir, (f) => isSourceFile(f) && isTestFile(f))
546
- : [];
547
- const api = {};
548
- for (const f of files) {
549
- const content = readFileSafe(f) || "";
550
- api[path.relative(root, f)] = {
551
- exports: extractExports(content),
552
- decorators: extractDecorators(content),
553
- };
554
- }
555
- const tests = {};
556
- for (const f of testFiles) {
557
- const content = readFileSafe(f) || "";
558
- const mentions = Array.from(new Set([...extractExports(content), ...extractDecorators(content)])).sort();
559
- tests[path.relative(root, f)] = { mentions };
560
- }
561
- return { files, testFiles, api, tests, readme: summarizeReadme(readme) };
562
- }
563
-
564
- function relativeFiles(root, files) {
565
- return files.map((file) => path.relative(root, file)).sort();
566
- }
567
- function collectPromptSections(names) {
568
- const root = getWorkspaceRoot();
569
- const promptIndex = new Map(discoverDocPrompts(root).map((prompt) => [prompt.name, prompt]));
570
- return names
571
- .map((name) => promptIndex.get(name))
572
- .filter((prompt) => Boolean(prompt))
573
- .map((prompt) => ({
574
- name: prompt.name,
575
- title: prompt.title,
576
- description: prompt.description,
577
- content: prompt.content,
578
- absolutePath: prompt.absolutePath,
579
- }));
580
- }
581
- function parseTaskLines(content) {
582
- return content
583
- .split(/\r?\n/)
584
- .map((line) => line.trim())
585
- .filter((line) => /^task\s+\d+/i.test(line));
586
- }
587
- function computeCoverageFromFinal(coveragePath) {
588
- const payload = JSON.parse(fs.readFileSync(coveragePath, "utf8"));
589
- const totals = {
590
- statements: { covered: 0, total: 0 },
591
- functions: { covered: 0, total: 0 },
592
- branches: { covered: 0, total: 0 },
593
- };
594
- const files = Object.entries(payload).map(([filePath, info]) => {
595
- const statementCounts = Object.values(info.s);
596
- const functionCounts = Object.values(info.f);
597
- const branchCounts = Object.values(info.b).flatMap((value) => Array.isArray(value) ? value : [value]);
598
- const statementTotal = statementCounts.length;
599
- const functionTotal = functionCounts.length;
600
- const branchTotal = branchCounts.length;
601
- const statementCovered = statementCounts.filter((count) => count > 0).length;
602
- const functionCovered = functionCounts.filter((count) => count > 0).length;
603
- const branchCovered = branchCounts.filter((count) => count > 0).length;
604
- totals.statements.covered += statementCovered;
605
- totals.statements.total += statementTotal;
606
- totals.functions.covered += functionCovered;
607
- totals.functions.total += functionTotal;
608
- totals.branches.covered += branchCovered;
609
- totals.branches.total += branchTotal;
610
- const pct = (covered, total) => total === 0 ? 100 : Number(((covered / total) * 100).toFixed(2));
611
- return {
612
- path: filePath,
613
- statements: pct(statementCovered, statementTotal),
614
- functions: pct(functionCovered, functionTotal),
615
- branches: pct(branchCovered, branchTotal),
616
- };
617
- });
618
- const pct = (covered, total) => total === 0 ? 100 : Number(((covered / total) * 100).toFixed(2));
619
- return {
620
- totals: {
621
- statements: {
622
- ...totals.statements,
623
- pct: pct(totals.statements.covered, totals.statements.total),
624
- },
625
- functions: {
626
- ...totals.functions,
627
- pct: pct(totals.functions.covered, totals.functions.total),
628
- },
629
- branches: {
630
- ...totals.branches,
631
- pct: pct(totals.branches.covered, totals.branches.total),
632
- },
633
- },
634
- files,
635
- };
636
- }
637
- function normalizePromptSections(sections) {
638
- return sections.map((section) => ({
639
- name: section.name,
640
- title: section.title,
641
- tasks: parseTaskLines(section.content),
642
- content: section.content,
643
- }));
644
- }
645
- async function resolveRepoRoot(basePath) {
646
- const root = getWorkspaceRoot();
647
- try {
648
- return resolveInWorkspace(root, basePath);
649
- }
650
- catch (error) {
651
- if (error instanceof WorkspaceError) {
652
- await throwUserError(error.message);
653
- }
654
- throw error;
655
- }
656
- }
657
- const documentObjectTool = {
658
- name: "document-object",
659
- description: "Create a documentation plan for a specific object type using .codex prompts and repository analysis.",
660
- parameters: documentObjectSchema,
661
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
662
- execute: async (input, _context) => {
663
- const args = documentObjectSchema.parse(input);
664
- const repoRoot = await resolveRepoRoot(args.basePath);
665
- const dependencies = getObjectPromptDependencies()[args.objectType] ?? [];
666
- if (!dependencies.length) {
667
- await throwUserError(`No prompt guidance configured for object type ${args.objectType}`);
668
- }
669
- const sections = normalizePromptSections(collectPromptSections(dependencies));
670
- const srcDir = path.join(repoRoot, "src");
671
- const testDir = path.join(repoRoot, "tests");
672
- const sourceFiles = fs.existsSync(srcDir)
673
- ? listFilesRecursive(srcDir, isSourceFile)
674
- : [];
675
- const testFiles = fs.existsSync(testDir)
676
- ? listFilesRecursive(testDir, (file) => isSourceFile(file) && isTestFile(file))
677
- : [];
678
- let targetFileContent;
679
- if (args.targetFile) {
680
- try {
681
- const absolute = resolveInWorkspace(repoRoot, args.targetFile);
682
- targetFileContent = readFileSafe(absolute) ?? undefined;
683
- }
684
- catch (error) {
685
- if (error instanceof WorkspaceError) {
686
- await throwUserError(error.message);
687
- }
688
- throw error;
689
- }
690
- }
691
- const payload = {
692
- basePath: path.relative(getWorkspaceRoot(), repoRoot) || ".",
693
- objectType: args.objectType,
694
- targetFile: args.targetFile,
695
- guidance: sections,
696
- files: {
697
- source: relativeFiles(repoRoot, sourceFiles),
698
- tests: relativeFiles(repoRoot, testFiles),
699
- },
700
- targetFileContent: args.includeContent ? targetFileContent : undefined,
701
- };
702
- return {
703
- content: [
704
- {
705
- type: "text",
706
- text: JSON.stringify(payload, null, 2),
707
- },
708
- ],
709
- };
710
- },
711
- };
712
- const coverageEnforcerTool = {
713
- name: "ensure-test-coverage",
714
- description: "Run the configured coverage command and report whether the target percentage is met, highlighting weak files.",
715
- parameters: coverageTaskSchema,
716
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
717
- execute: async (input, _context) => {
718
- const args = coverageTaskSchema.parse(input);
719
- const repoRoot = await resolveRepoRoot(args.basePath);
720
- if (!args.dryRun) {
721
- const env = {
722
- ...process.env,
723
- USE_WATCHMAN: "false",
724
- WATCHMAN_DISABLE: "1",
725
- JEST_DISABLE_WATCHMAN: "1",
726
- };
727
- const result = child_process.spawnSync("npm", ["run", "coverage", "--", "--watchman=false", "--runInBand"], { cwd: repoRoot, env, encoding: "utf8" });
728
- if (result.status !== 0) {
729
- const message = result.stderr || result.stdout || "Coverage command failed";
730
- await throwUserError(message.trim());
731
- }
732
- }
733
- const coveragePath = path.join(repoRoot, "workdocs", "reports", "coverage", "coverage-final.json");
734
- if (!fs.existsSync(coveragePath)) {
735
- await throwUserError(`Coverage report not found at ${path.relative(repoRoot, coveragePath)}`);
736
- }
737
- const summary = computeCoverageFromFinal(coveragePath);
738
- const meetsThreshold = summary.totals.statements.pct >= args.coverage &&
739
- summary.totals.functions.pct >= args.coverage &&
740
- summary.totals.branches.pct >= args.coverage;
741
- const weakest = [...summary.files]
742
- .sort((a, b) => a.statements - b.statements)
743
- .slice(0, 10);
744
- const guidance = normalizePromptSections(collectPromptSections(["bulk-tests"]));
745
- const payload = {
746
- basePath: path.relative(getWorkspaceRoot(), repoRoot) || ".",
747
- target: args.coverage,
748
- meetsThreshold,
749
- totals: summary.totals,
750
- weakest,
751
- guidance,
752
- };
753
- return {
754
- content: [
755
- {
756
- type: "text",
757
- text: JSON.stringify(payload, null, 2),
758
- },
759
- ],
760
- };
761
- },
762
- };
763
- const readmeImprovementTool = {
764
- name: "improve-readme",
765
- description: "Summarize required steps to refresh README and workdocs content using .codex guidance and repository analysis.",
766
- parameters: readmeImprovementSchema,
767
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
768
- execute: async (input, _context) => {
769
- const args = readmeImprovementSchema.parse(input);
770
- const repoRoot = await resolveRepoRoot(args.basePath);
771
- const analysis = analyzeRepo(repoRoot);
772
- const modules = analysis.files
773
- .filter((file) => /index\.ts$/.test(file))
774
- .map((file) => path.relative(repoRoot, file));
775
- const promptSections = normalizePromptSections(collectPromptSections(["update-readme", "doc", "module"]));
776
- const testExamples = Object.keys(analysis.tests ?? {});
777
- const examples = args.includeExamples ? testExamples.slice(0, 20) : [];
778
- const payload = {
779
- basePath: path.relative(getWorkspaceRoot(), repoRoot) || ".",
780
- summary: {
781
- modules,
782
- totalSourceFiles: analysis.files.length,
783
- totalTestFiles: analysis.testFiles.length,
784
- hasReadme: Boolean(analysis.readme),
785
- },
786
- guidance: promptSections,
787
- suggestedExamples: examples,
788
- };
789
- return {
790
- content: [
791
- {
792
- type: "text",
793
- text: JSON.stringify(payload, null, 2),
794
- },
795
- ],
796
- };
797
- },
798
- };
799
-
800
- function escapeRegExp(value) {
801
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
802
- }
803
- function formatDecorator(spec) {
804
- const args = (spec.args || []).map((arg) => JSON.stringify(arg)).join(", ");
805
- return `@${spec.name}(${args})`;
806
- }
807
- function ensureDirectory(filePath) {
808
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
809
- }
810
- function collectDecoratorNames(classDecorators, properties) {
811
- const names = new Set();
812
- names.add("model");
813
- for (const decorator of classDecorators || []) {
814
- names.add(decorator.name);
815
- }
816
- for (const property of properties || []) {
817
- for (const decorator of property.decorators || []) {
818
- names.add(decorator.name);
819
- }
820
- }
821
- return names;
822
- }
823
- function ensureImport(content, importsFrom, decorators) {
824
- /* istanbul ignore next */
825
- if (!decorators.size)
826
- return content;
827
- const importRegex = new RegExp(`import\\s+\\{([^}]+)\\}\\s+from\\s+["']${escapeRegExp(importsFrom)}["'];`);
828
- const match = content.match(importRegex);
829
- const sorted = Array.from(decorators).sort();
830
- if (match) {
831
- const existing = match[1]
832
- .split(",")
833
- .map((name) => name.trim())
834
- .filter(Boolean);
835
- const merged = Array.from(new Set([...existing, ...sorted])).sort();
836
- return content.replace(importRegex, `import { ${merged.join(", ")} } from "${importsFrom}";`);
837
- }
838
- const importLine = `import { ${sorted.join(", ")} } from "${importsFrom}";`;
839
- return `${importLine}\n\n${content}`;
840
- }
841
- function addPropertyBlock(property) {
842
- const decorators = (property.decorators || [])
843
- .map(formatDecorator)
844
- .join("\n ");
845
- const decoratorBlock = decorators ? ` ${decorators}\n` : "";
846
- return `${decoratorBlock} ${property.name}: ${property.type};`;
847
- }
848
- function removePropertyBlock(content, propertyName) {
849
- const lines = content.split(/\r?\n/);
850
- const result = [];
851
- for (let i = 0; i < lines.length; i++) {
852
- const line = lines[i];
853
- if (line.trim().startsWith(`@`) &&
854
- lines[i + 1]?.includes(`${propertyName}:`)) {
855
- continue;
856
- }
857
- if (line.includes(`${propertyName}:`)) {
858
- // skip this line and any trailing blank line
859
- continue;
860
- }
861
- result.push(line);
862
- }
863
- return result.join("\n");
864
- }
865
- function insertDecorator(content, decorator, target) {
866
- const decoratorLine = formatDecorator(decorator);
867
- if (target.kind === "class") {
868
- const classRegex = /(export\s+class\s+[^\s{]+\s*\{)/;
869
- if (content.includes(decoratorLine))
870
- return content;
871
- return content.replace(classRegex, `${decoratorLine}\n$1`);
872
- }
873
- if (!target.name)
874
- return content;
875
- const propertyRegex = new RegExp(`(^\\s*)(?:@.*\\n\\1)*${escapeRegExp(target.name)}:`, "m");
876
- const match = propertyRegex.exec(content);
877
- if (!match)
878
- return content;
879
- const indent = match[1] || " ";
880
- if (content.includes(`${indent}${decoratorLine}`))
881
- return content;
882
- return (content.slice(0, match.index) +
883
- `${indent}${decoratorLine}\n` +
884
- content.slice(match.index));
885
- }
886
- function removeDecorator(content, decoratorName, target) {
887
- const decoratorRegex = new RegExp(`^\\s*@${escapeRegExp(decoratorName)}\\([^)]*\\)`, "m");
888
- if (target.kind === "class") {
889
- return content.replace(decoratorRegex, "");
890
- }
891
- if (target.name) {
892
- const pattern = new RegExp(`(^\\s*@${escapeRegExp(decoratorName)}\\([^)]*\\)\\s*$\\n)(?=\\s*${escapeRegExp(target.name)}:)`, "m");
893
- return content.replace(pattern, "");
894
- }
895
- return content;
896
- }
897
- function writeIfChanged(filePath, content) {
898
- ensureDirectory(filePath);
899
- fs.writeFileSync(filePath, content);
900
- }
901
- const decoratorTools = {
902
- createOrUpdateModelTool: {
903
- name: "create-or-update-model",
904
- description: "Create or update a validation-ready model class",
905
- execute: async (args) => {
906
- if (!args.overwrite && fs.existsSync(args.filePath)) {
907
- throw new Error(`File already exists at ${args.filePath}`);
908
- }
909
- const decorators = collectDecoratorNames(args.classDecorators, args.properties);
910
- let content = `@model()`;
911
- for (const decorator of args.classDecorators || []) {
912
- content += `\n${formatDecorator(decorator)}`;
913
- }
914
- const properties = (args.properties || [])
915
- .map(addPropertyBlock)
916
- .join("\n\n");
917
- content += `\nexport class ${args.className} {\n${properties ? `${properties}\n` : ""}}\n`;
918
- content = ensureImport(content, args.importsFrom, decorators);
919
- writeIfChanged(args.filePath, content);
920
- return { filePath: args.filePath };
921
- },
922
- },
923
- addAttributeTool: {
924
- name: "add-attribute",
925
- description: "Add a decorated attribute to an existing model",
926
- execute: async (args) => {
927
- if (!fs.existsSync(args.filePath)) {
928
- throw new Error(`Model file not found at ${args.filePath}`);
929
- }
930
- let content = fs.readFileSync(args.filePath, "utf8");
931
- if (content.includes(`${args.attribute.name}:`)) {
932
- return { filePath: args.filePath };
933
- }
934
- const decorators = collectDecoratorNames(undefined, [args.attribute]);
935
- content = ensureImport(content, args.importsFrom, decorators);
936
- const insertionPoint = content.lastIndexOf("}");
937
- const block = addPropertyBlock(args.attribute);
938
- const before = content.slice(0, insertionPoint).replace(/\s*$/, "");
939
- const after = content.slice(insertionPoint);
940
- const updated = `${before}\n${block}\n${after}`;
941
- writeIfChanged(args.filePath, updated);
942
- return { filePath: args.filePath };
943
- },
944
- },
945
- removeAttributeTool: {
946
- name: "remove-attribute",
947
- description: "Remove an attribute from a model class",
948
- execute: async (args) => {
949
- if (!fs.existsSync(args.filePath))
950
- return { filePath: args.filePath };
951
- const content = fs.readFileSync(args.filePath, "utf8");
952
- const updated = removePropertyBlock(content, args.attributeName);
953
- writeIfChanged(args.filePath, updated);
954
- return { filePath: args.filePath };
955
- },
956
- },
957
- applyDecoratorTool: {
958
- name: "apply-decorator",
959
- description: "Apply a decorator to a class or property",
960
- execute: async (args) => {
961
- if (!fs.existsSync(args.filePath)) {
962
- throw new Error(`Model file not found at ${args.filePath}`);
963
- }
964
- let content = fs.readFileSync(args.filePath, "utf8");
965
- const decorators = new Set([args.decorator.name]);
966
- content = ensureImport(content, args.importsFrom, decorators);
967
- content = insertDecorator(content, args.decorator, args.target);
968
- writeIfChanged(args.filePath, content);
969
- return { filePath: args.filePath };
970
- },
971
- },
972
- removeDecoratorTool: {
973
- name: "remove-decorator",
974
- description: "Remove a decorator from a class or property",
975
- execute: async (args) => {
976
- if (!fs.existsSync(args.filePath))
977
- return { filePath: args.filePath };
978
- let content = fs.readFileSync(args.filePath, "utf8");
979
- content = removeDecorator(content, args.decoratorName, args.target);
980
- writeIfChanged(args.filePath, content);
981
- return { filePath: args.filePath };
982
- },
983
- },
984
- scaffoldValidatorTool: {
985
- name: "scaffold-validator",
986
- description: "Scaffold a validator class and optional decorator",
987
- execute: async (args) => {
988
- const classFile = path.join(args.validatorsDir, `${args.name}.ts`);
989
- ensureDirectory(classFile);
990
- const classContent = `export class ${args.name} {\n validate(value: unknown): boolean {\n return value !== undefined;\n }\n}\n`;
991
- fs.writeFileSync(classFile, classContent);
992
- let decoratorFile;
993
- if (args.decoratorDir) {
994
- decoratorFile = path.join(args.decoratorDir, `${args.name}Decorator.ts`);
995
- ensureDirectory(decoratorFile);
996
- fs.writeFileSync(decoratorFile, `export function ${args.name}Decorator() {\n return () => void 0;\n}\n`);
997
- }
998
- return { classFile, decoratorFile };
999
- },
1000
- },
1001
- scaffoldSerializerTool: {
1002
- name: "scaffold-serializer",
1003
- description: "Scaffold a serializer class and optional registry",
1004
- execute: async (args) => {
1005
- const classFile = path.join(args.dir, `${args.name}.ts`);
1006
- ensureDirectory(classFile);
1007
- fs.writeFileSync(classFile, `export class ${args.name} {\n serialize(value: unknown): string {\n return JSON.stringify(value);\n }\n}\n`);
1008
- let registerFile;
1009
- if (args.registerDir) {
1010
- registerFile = path.join(args.registerDir, `${args.name}Register.ts`);
1011
- ensureDirectory(registerFile);
1012
- fs.writeFileSync(registerFile, `export function register${args.name}() {\n return ${args.setDefault ? "'default'" : "'optional'"};\n}\n`);
1013
- }
1014
- return { classFile, registerFile };
1015
- },
1016
- },
1017
- scaffoldHashingTool: {
1018
- name: "scaffold-hashing",
1019
- description: "Scaffold a hashing function and optional registry",
1020
- execute: async (args) => {
1021
- const functionFile = path.join(args.dir, `${args.name}.ts`);
1022
- ensureDirectory(functionFile);
1023
- fs.writeFileSync(functionFile, `export function ${args.name}(value: string): string {\n return value.split('').reverse().join('');\n}\n`);
1024
- let registerFile;
1025
- if (args.registerDir) {
1026
- registerFile = path.join(args.registerDir, `${args.name}Register.ts`);
1027
- ensureDirectory(registerFile);
1028
- fs.writeFileSync(registerFile, `export function register${args.name}() {\n return ${args.setDefault ? "'default'" : "'optional'"};\n}\n`);
1029
- }
1030
- return { functionFile, registerFile };
1031
- },
1032
- },
1033
- };
1034
-
1035
- function buildAnalyzeRepositoryTool() {
1036
- return {
1037
- name: "analyze-repository",
1038
- description: "Analyze a local repository's source, tests, and docs to extract exported APIs, decorators, and test mentions.",
1039
- parameters: analyzeRepoSchema,
1040
- execute: async (input) => {
1041
- let repoRoot = path.resolve(process.cwd(), input.repoPath);
1042
- if (!fs.existsSync(repoRoot)) {
1043
- // try resolving from monorepo root (parent of current cwd)
1044
- const alt = path.resolve(process.cwd(), "..", input.repoPath);
1045
- if (fs.existsSync(alt))
1046
- repoRoot = alt;
1047
- }
1048
- if (!fs.existsSync(repoRoot)) {
1049
- // if input was absolute and still not found, try ../<basename>
1050
- const alt2 = path.resolve(process.cwd(), "..", path.basename(input.repoPath));
1051
- if (fs.existsSync(alt2))
1052
- repoRoot = alt2;
1053
- }
1054
- if (!fs.existsSync(repoRoot))
1055
- throw new Error(`Repository not found at ${repoRoot}`);
1056
- const result = analyzeRepo(repoRoot);
1057
- return {
1058
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1059
- };
1060
- },
1061
- };
1062
- }
1063
- function buildEnumerateCapabilitiesTool() {
1064
- return {
1065
- name: "enumerate-capabilities",
1066
- description: "Enumerate developer-facing capabilities of the given repository, inferred from code, tests, and docs.",
1067
- parameters: enumerateCapabilitiesSchema,
1068
- execute: async (input) => {
1069
- let repoRoot = path.resolve(process.cwd(), input.repoPath);
1070
- if (!fs.existsSync(repoRoot)) {
1071
- const alt = path.resolve(process.cwd(), "..", input.repoPath);
1072
- if (fs.existsSync(alt))
1073
- repoRoot = alt;
1074
- }
1075
- if (!fs.existsSync(repoRoot)) {
1076
- const alt2 = path.resolve(process.cwd(), "..", path.basename(input.repoPath));
1077
- if (fs.existsSync(alt2))
1078
- repoRoot = alt2;
1079
- }
1080
- if (!fs.existsSync(repoRoot))
1081
- throw new Error(`Repository not found at ${repoRoot}`);
1082
- const analysis = analyzeRepo(repoRoot);
1083
- const capabilities = deriveCapabilities(analysis);
1084
- return {
1085
- content: [
1086
- {
1087
- type: "text",
1088
- text: JSON.stringify({
1089
- capabilities,
1090
- analysisSummary: {
1091
- files: analysis.files.length,
1092
- testFiles: analysis.testFiles.length,
1093
- readme: analysis.readme?.title,
1094
- },
1095
- }, null, 2),
1096
- },
1097
- ],
1098
- };
1099
- },
1100
- };
1101
- }
1102
- function buildPlanFeatureTool() {
1103
- return {
1104
- name: "plan-feature-implementation",
1105
- description: "Given a feature request, select appropriate MCP tools (including existing and new ones) and produce an execution plan.",
1106
- parameters: planFeatureSchema,
1107
- execute: async (input) => {
1108
- const steps = [];
1109
- let i = 1;
1110
- steps.push({
1111
- step: i++,
1112
- action: "Analyze repository to enumerate APIs and decorators",
1113
- tool: "analyze-repository",
1114
- arguments: { repoPath: input.repoPath },
1115
- rationale: "Understand available building blocks.",
1116
- });
1117
- steps.push({
1118
- step: i++,
1119
- action: "List capabilities expected for developers",
1120
- tool: "enumerate-capabilities",
1121
- arguments: { repoPath: input.repoPath },
1122
- rationale: "Align the plan with supported capabilities.",
1123
- });
1124
- // Suggest existing generic tools from mcp-module
1125
- steps.push({
1126
- step: i++,
1127
- action: "Select documentation prompt and gather relevant source file(s)",
1128
- tool: "document-code",
1129
- arguments: { filePath: "<target-file>" },
1130
- rationale: "Provide context and instructions for changes.",
1131
- });
1132
- steps.push({
1133
- step: i++,
1134
- action: "Apply code changes using unified diff patch",
1135
- tool: "apply-code-change",
1136
- arguments: {
1137
- filePath: "<target-file>",
1138
- patch: "<unified-diff>",
1139
- dryRun: true,
1140
- },
1141
- rationale: "Validate changes safely before committing.",
1142
- });
1143
- steps.push({
1144
- step: i++,
1145
- action: "Commit code changes",
1146
- tool: "apply-code-change",
1147
- arguments: {
1148
- filePath: "<target-file>",
1149
- patch: "<unified-diff>",
1150
- dryRun: false,
1151
- },
1152
- rationale: "Persist the update.",
1153
- });
1154
- // If decoration-related terms present, suggest decorator tools
1155
- if (/decorat|flavour|override|extend|builder/i.test(input.feature)) {
1156
- steps.unshift({
1157
- step: 0,
1158
- action: "Use decorator tooling to insert/remove/modify decorators",
1159
- tool: "decorator-tools",
1160
- arguments: { action: "help" },
1161
- rationale: "Leverage specialized utilities for decoration patterns.",
1162
- });
1163
- steps.forEach((s, idx) => (s.step = idx + 1));
1164
- }
1165
- return {
1166
- content: [
1167
- {
1168
- type: "text",
1169
- text: JSON.stringify({
1170
- plan: steps,
1171
- notes: "Replace placeholder arguments like <target-file> and <unified-diff> based on the analysis output.",
1172
- }, null, 2),
1173
- },
1174
- ],
1175
- };
1176
- },
1177
- };
1178
- }
1179
- const documentCodeTool = {
1180
- annotations: {
1181
- idempotentHint: true,
1182
- openWorldHint: false,
1183
- readOnlyHint: true,
1184
- title: "Document Source File",
1185
- },
1186
- description: "Generate documentation guidance for a file by combining repository prompts with the target source code.",
1187
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1188
- execute: async (input, _context) => {
1189
- const args = documentCodeSchema.parse(input);
1190
- const root = getWorkspaceRoot();
1191
- let filePath;
1192
- try {
1193
- filePath = resolveInWorkspace(root, args.filePath);
1194
- }
1195
- catch (error) {
1196
- if (error instanceof WorkspaceError) {
1197
- return throwUserError(error.message);
1198
- }
1199
- /* istanbul ignore next */
1200
- throw error;
1201
- }
1202
- if (!fs.existsSync(filePath)) {
1203
- return throwUserError(`Cannot document missing file at ${args.filePath}`);
1204
- }
1205
- const fileContent = fs.readFileSync(filePath, {
1206
- encoding: args.encoding,
1207
- });
1208
- // dynamically import prompt helpers
1209
- const promptMod = await Promise.resolve().then(function () { return prompts$1; });
1210
- const { discoverDocPrompts, selectPrompt, DEFAULT_PROMPT_NAME, buildDocumentationPayload, } = promptMod;
1211
- const prompts = discoverDocPrompts(root);
1212
- if (!prompts.length) {
1213
- return throwUserError("No documentation prompts found under .code/prompts or .codex/prompts");
1214
- }
1215
- const prompt = selectPrompt(prompts, args.promptName ?? DEFAULT_PROMPT_NAME);
1216
- return buildDocumentationPayload({
1217
- filePath: args.filePath,
1218
- fileContent,
1219
- prompt,
1220
- includeCode: args.includeCode,
1221
- includePrompt: args.includePrompt,
1222
- includeMetadata: args.includeMetadata,
1223
- additionalContext: args.additionalContext,
1224
- });
1225
- },
1226
- name: "document-code",
1227
- parameters: documentCodeSchema,
1228
- };
1229
- const applyCodeChangeTool = {
1230
- annotations: {
1231
- destructiveHint: true,
1232
- idempotentHint: false,
1233
- openWorldHint: false,
1234
- readOnlyHint: false,
1235
- title: "Apply Code Patch",
1236
- },
1237
- description: "Apply a unified diff patch to a workspace file with optional dry-run validation and diff preview.",
1238
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1239
- execute: async (input, _context) => {
1240
- const args = codeChangeSchema.parse(input);
1241
- const root = getWorkspaceRoot();
1242
- let filePath;
1243
- try {
1244
- filePath = resolveInWorkspace(root, args.filePath);
1245
- }
1246
- catch (error) {
1247
- if (error instanceof WorkspaceError) {
1248
- return throwUserError(error.message);
1249
- }
1250
- throw error;
1251
- }
1252
- const original = fs.existsSync(filePath)
1253
- ? fs.readFileSync(filePath, args.encoding)
1254
- : "";
1255
- let patched;
1256
- try {
1257
- patched = diff.applyPatch(original, args.patch);
1258
- }
1259
- catch (error) {
1260
- return throwUserError(`Failed to apply provided patch to ${args.filePath}: ${error instanceof Error ? error.message : error}`);
1261
- }
1262
- /* istanbul ignore next */
1263
- if (patched === false) {
1264
- return throwUserError(`Failed to apply provided patch to ${args.filePath}`);
1265
- }
1266
- if (!args.dryRun) {
1267
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
1268
- fs.writeFileSync(filePath, patched, {
1269
- encoding: args.encoding,
1270
- });
1271
- }
1272
- if (!args.showDiff) {
1273
- return `Patch ${args.dryRun ? "validated" : "applied"} for ${args.filePath}`;
1274
- }
1275
- const preview = diff.createTwoFilesPatch(args.filePath, args.filePath, original, patched, undefined, undefined, { context: args.diffContext });
1276
- return {
1277
- content: [
1278
- {
1279
- type: "text",
1280
- text: `Patch ${args.dryRun ? "validated" : "applied"} for ${args.filePath}`,
1281
- },
1282
- {
1283
- type: "text",
1284
- text: ["```diff", preview.trim(), "```"].join("\n"),
1285
- },
1286
- ],
1287
- };
1288
- },
1289
- name: "apply-code-change",
1290
- parameters: codeChangeSchema,
1291
- };
1292
- const analyticTools = [
1293
- buildAnalyzeRepositoryTool(),
1294
- buildEnumerateCapabilitiesTool(),
1295
- buildPlanFeatureTool(),
1296
- ];
1297
- const toolList$1 = [
1298
- ...analyticTools,
1299
- documentCodeTool,
1300
- applyCodeChangeTool,
1301
- ];
1302
-
1303
- const codexToolList = [
1304
- documentObjectTool,
1305
- coverageEnforcerTool,
1306
- readmeImprovementTool,
1307
- ];
1308
- const moduleToolList = moduleRegistry
1309
- .listTools()
1310
- .map((asset) => asset.tool);
1311
- const toolList = [...toolList$1, ...codexToolList, ...moduleToolList];
1312
- const [analyzeRepositoryTool, enumerateCapabilitiesTool, planFeatureTool, documentCodeToolRef, applyCodeChangeToolRef,] = toolList$1;
1313
- const tools = {
1314
- analyzeRepositoryTool,
1315
- enumerateCapabilitiesTool,
1316
- planFeatureTool,
1317
- documentCodeTool: documentCodeToolRef,
1318
- applyCodeChangeTool: applyCodeChangeToolRef,
1319
- documentObjectTool,
1320
- coverageEnforcerTool,
1321
- readmeImprovementTool,
1322
- ...decoratorTools,
1323
- };
1324
-
1325
- function toResource(asset) {
1326
- return {
1327
- name: asset.id,
1328
- uri: asset.uri,
1329
- description: asset.description ?? asset.title,
1330
- mimeType: asset.mimeType,
1331
- load: async () => {
1332
- const res = await asset.load();
1333
- // asset.load may return a ContentResult or a Promise of ContentResult; ensure we return ResourceResult-like object
1334
- if (res?.content) {
1335
- const cr = res;
1336
- // If ContentResult, convert to simple text result expected by Resource.load consumers
1337
- return {
1338
- text: Array.isArray(cr.content)
1339
- ? cr.content.map((c) => c.text).join("\n")
1340
- : String(cr),
1341
- };
1342
- }
1343
- // fallback for objects with text
1344
- return res;
1345
- },
1346
- };
1347
- }
1348
- function buildModuleResources() {
1349
- return moduleRegistry.listResources().map(toResource);
1350
- }
1351
- const resources = [
1352
- {
1353
- name: "codex-prompt-index",
1354
- uri: "codex://prompts/index",
1355
- description: "Enumerate available .codex prompt files with titles and descriptions.",
1356
- mimeType: "application/json",
1357
- load: async () => {
1358
- const root = getWorkspaceRoot();
1359
- const prompts = discoverDocPrompts(root).map((prompt) => ({
1360
- name: prompt.name,
1361
- title: prompt.title,
1362
- description: prompt.description,
1363
- path: prompt.absolutePath,
1364
- }));
1365
- return {
1366
- text: JSON.stringify({ prompts }, null, 2),
1367
- mimeType: "application/json",
1368
- };
1369
- },
1370
- },
1371
- {
1372
- name: "codex-object-prompts",
1373
- uri: "codex://prompts/objects",
1374
- description: "Provides the resolved prompt content for each documented object workflow.",
1375
- mimeType: "application/json",
1376
- load: async () => {
1377
- const entries = await Promise.all(buildObjectPrompts().map(async (prompt) => ({
1378
- name: prompt.name,
1379
- description: prompt.description,
1380
- content: await prompt.load({}),
1381
- })));
1382
- return {
1383
- text: JSON.stringify({ prompts: entries }, null, 2),
1384
- mimeType: "application/json",
1385
- };
1386
- },
1387
- },
1388
- ...buildModuleResources(),
1389
- ];
1390
-
1391
- const codexPromptTemplates = [];
1392
- function buildCodexPromptTemplates() {
1393
- const root = getWorkspaceRoot();
1394
- const templates = [
1395
- {
1396
- name: "codex-prompt",
1397
- description: "Load a .codex prompt file by name (without extension) as markdown.",
1398
- uriTemplate: "codex-prompt://{name}",
1399
- mimeType: "text/markdown",
1400
- arguments: [
1401
- {
1402
- name: "name",
1403
- description: "Name of the prompt file inside .codex/prompts (without .md).",
1404
- required: true,
1405
- },
1406
- ],
1407
- load: async ({ name }) => {
1408
- const promptPath = resolveInWorkspace(root, path.join(".codex", "prompts", `${name}.md`));
1409
- if (!fs.existsSync(promptPath)) {
1410
- throw new Error(`Prompt .codex/prompts/${name}.md not found`);
1411
- }
1412
- const text = fs.readFileSync(promptPath, "utf8");
1413
- return { text, uri: `codex-prompt:///${name}` };
1414
- },
1415
- },
1416
- ];
1417
- codexPromptTemplates.splice(0, codexPromptTemplates.length, ...templates);
1418
- return codexPromptTemplates;
1419
- }
1420
-
1421
- const decorationResourceTemplates = [];
1422
- function makeLoader(type) {
1423
- return async ({ path: relative }) => {
1424
- const root = getWorkspaceRoot();
1425
- const target = path.join(type, relative);
1426
- const text = await readWorkspaceFile(root, target);
1427
- return { text };
1428
- };
1429
- }
1430
- function buildDecorationResourceTemplates() {
1431
- const templates = [
1432
- {
1433
- name: "read-code-from-source",
1434
- description: "Read a file from the <base_path>/src tree by relative path.",
1435
- mimeType: "text/plain",
1436
- uriTemplate: "from-source://src/{path}",
1437
- arguments: [
1438
- {
1439
- name: "path",
1440
- description: "Path under <base_path>/src to load, e.g. 'decoration/types.ts'",
1441
- required: true,
1442
- },
1443
- ],
1444
- load: makeLoader("src"),
1445
- },
1446
- {
1447
- name: "read-test-from-source",
1448
- description: "Read a file from the <base_path>/tests tree by relative path.",
1449
- mimeType: "text/plain",
1450
- uriTemplate: "from-source://tests/{path}",
1451
- arguments: [
1452
- {
1453
- name: "path",
1454
- description: "Path under <base_path>/tests to load, e.g. 'decoration/tests/types.test.ts'",
1455
- required: true,
1456
- },
1457
- ],
1458
- load: makeLoader("tests"),
1459
- },
1460
- {
1461
- name: "read-doc-from-source",
1462
- description: "Read a file from the <base_path>/workdocs tree by relative path.",
1463
- mimeType: "text/plain",
1464
- uriTemplate: "from-source://workdocs/{path}",
1465
- arguments: [
1466
- {
1467
- name: "path",
1468
- description: "Path under <base_path>/workdocs to load, e.g. 'decoration/workdocs/tutorials/for-developers.md'",
1469
- required: true,
1470
- },
1471
- ],
1472
- load: makeLoader("workdocs"),
1473
- },
1474
- ];
1475
- decorationResourceTemplates.splice(0, decorationResourceTemplates.length, ...templates);
1476
- return decorationResourceTemplates;
1477
- }
1478
-
1479
- const workspaceResourceTemplates = [];
1480
- function buildWorkspaceResourceTemplates() {
1481
- const root = getWorkspaceRoot();
1482
- const sharedArguments = [
1483
- {
1484
- name: "path",
1485
- description: "Path relative to the workspace root",
1486
- required: true,
1487
- },
1488
- ];
1489
- const templates = [
1490
- {
1491
- name: "vscode-workspace-file",
1492
- description: "Expose workspace files to Visual Studio Code via vscode:// URIs",
1493
- uriTemplate: "vscode://workspace/{path}",
1494
- mimeType: "text/plain",
1495
- arguments: sharedArguments,
1496
- load: async (args) => {
1497
- try {
1498
- const text = await readWorkspaceFile(root, args.path);
1499
- return { text: String(text) };
1500
- }
1501
- catch (err) {
1502
- // propagate as-is for tests to assert errors
1503
- throw err;
1504
- }
1505
- },
1506
- },
1507
- {
1508
- name: "cursor-workspace-file",
1509
- description: "Expose workspace files to Cursor via cursor:// URIs",
1510
- uriTemplate: "cursor://workspace/{path}",
1511
- mimeType: "text/plain",
1512
- arguments: sharedArguments,
1513
- load: async (args) => {
1514
- try {
1515
- const text = await readWorkspaceFile(root, args.path);
1516
- return { text: String(text) };
1517
- }
1518
- catch (err) {
1519
- throw err;
1520
- }
1521
- },
1522
- },
1523
- {
1524
- name: "copilot-workspace-file",
1525
- description: "Expose workspace files to GitHub Copilot via copilot:// URIs",
1526
- uriTemplate: "copilot://workspace/{path}",
1527
- mimeType: "text/plain",
1528
- arguments: sharedArguments,
1529
- load: async (args) => {
1530
- try {
1531
- const text = await readWorkspaceFile(root, args.path);
1532
- return { text: String(text) };
1533
- }
1534
- catch (err) {
1535
- throw err;
1536
- }
1537
- },
1538
- },
1539
- ];
1540
- workspaceResourceTemplates.splice(0, workspaceResourceTemplates.length, ...templates);
1541
- return workspaceResourceTemplates;
1542
- }
1543
-
1544
- function buildResourceTemplates() {
1545
- const moduleTemplates = moduleRegistry.listTemplates().map((template) => ({
1546
- name: template.id,
1547
- description: template.description ?? template.title,
1548
- mimeType: "text/markdown",
1549
- uriTemplate: `module-template://${template.id}`,
1550
- arguments: (template.placeholders ?? []).map((name) => ({
1551
- name,
1552
- description: `Value for ${name}`,
1553
- required: true,
1554
- })),
1555
- load: async () => ({
1556
- text: typeof template.content === "string"
1557
- ? template.content
1558
- : `# ${template.description ?? template.title ?? template.id}\n\nNo template content available for ${template.id}`,
1559
- }),
1560
- }));
1561
- const all = [
1562
- ...buildWorkspaceResourceTemplates(),
1563
- ...buildCodexPromptTemplates(),
1564
- ...buildDecorationResourceTemplates(),
1565
- ...moduleTemplates,
1566
- ];
1567
- // Normalise all loaders to always return { text: string }
1568
- function normaliseResult(res) {
1569
- if (res == null)
1570
- return { text: "" };
1571
- if (typeof res === "string")
1572
- return { text: res };
1573
- if (typeof res.text === "string")
1574
- return res;
1575
- // handle legacy ContentResult shapes with content or content array
1576
- if (Array.isArray(res.content)) {
1577
- const parts = res.content
1578
- .map((c) => (c && typeof c.text === "string" ? c.text : String(c)))
1579
- .join("\n");
1580
- return { text: parts };
1581
- }
1582
- if (res.content && typeof res.content.text === "string") {
1583
- return { text: res.content.text };
1584
- }
1585
- // fallback: stringify
1586
- try {
1587
- return { text: JSON.stringify(res) };
1588
- }
1589
- catch {
1590
- return { text: String(res) };
1591
- }
1592
- }
1593
- return all.map((t) => ({
1594
- ...t,
1595
- load: async (args) => {
1596
- const raw = await t.load(args);
1597
- return normaliseResult(raw);
1598
- },
1599
- }));
1600
- }
1601
- const templateList = buildResourceTemplates();
1602
-
1603
- /**
1604
- * @const VERSION
1605
- * @name VERSION
1606
- * @description Represents the current version of the ts-workspace module.
1607
- * @summary The actual version number is replaced during the build process.
1608
- * @type {string}
1609
- */
1610
- const VERSION$1 = "0.4.0";
1611
- const PACKAGE_NAME$1 = "##PACKAGE_NAME##";
1612
- try {
1613
- decoration.Metadata.registerLibrary(PACKAGE_NAME$1, VERSION$1);
1614
- }
1615
- catch (error) {
1616
- if (error instanceof Error && error.message.includes("already")) ;
1617
- else {
1618
- throw error;
1619
- }
1620
- }
1621
-
1622
- function enrich(mcp) {
1623
- const promptEntries = loadPrompts();
1624
- for (const prompt of promptEntries) {
1625
- mcp.addPrompt(prompt);
1626
- }
1627
- for (const tool of toolList) {
1628
- mcp.addTool(tool);
1629
- }
1630
- const templates = buildResourceTemplates();
1631
- for (const template of templates) {
1632
- mcp.addResourceTemplate(template);
1633
- }
1634
- for (const resource of resources) {
1635
- const addResource = mcp.addResource;
1636
- if (typeof addResource === "function") {
1637
- addResource.call(mcp, resource);
1638
- }
1639
- }
1640
- return mcp;
1641
- }
1642
- const PACKAGE_NAME = PACKAGE_NAME$1;
1643
- const VERSION = VERSION$1;
1644
-
1645
- // New: validation entrypoint for module structure
1646
- const REQUIRED_SUBFOLDERS = ["prompts", "resources", "templates", "tools"];
1647
- function findModuleDirs(repoRoot) {
1648
- const modulesPath = path.resolve(repoRoot, "src", "modules");
1649
- if (!fs.existsSync(modulesPath) || !fs.statSync(modulesPath).isDirectory()) {
1650
- return [];
1651
- }
1652
- return fs
1653
- .readdirSync(modulesPath, { withFileTypes: true })
1654
- .filter((d) => d.isDirectory())
1655
- .map((d) => path.join(modulesPath, d.name));
1656
- }
1657
- function hasIndexExport(folderPath) {
1658
- const candidates = [
1659
- "index.ts",
1660
- "index.tsx",
1661
- "index.js",
1662
- "index.cjs",
1663
- "index.mjs",
1664
- ];
1665
- for (const c of candidates) {
1666
- if (fs.existsSync(path.join(folderPath, c)))
1667
- return true;
1668
- }
1669
- return false;
1670
- }
1671
- function validateModules(repoRoot) {
1672
- const dirs = findModuleDirs(repoRoot);
1673
- const issues = [];
1674
- for (const moduleDir of dirs) {
1675
- const moduleName = path.basename(moduleDir);
1676
- for (const sub of REQUIRED_SUBFOLDERS) {
1677
- const subPath = path.join(moduleDir, sub);
1678
- if (!fs.existsSync(subPath) || !fs.statSync(subPath).isDirectory()) {
1679
- issues.push({
1680
- module: moduleName,
1681
- path: subPath,
1682
- type: "missing-folder",
1683
- detail: `Required folder '${sub}' is missing in module '${moduleName}'`,
1684
- });
1685
- continue;
1686
- }
1687
- // If folder exists, check for index export
1688
- if (!hasIndexExport(subPath)) {
1689
- issues.push({
1690
- module: moduleName,
1691
- path: subPath,
1692
- type: "missing-export",
1693
- detail: `No index export found in '${subPath}'. Expected one of index.ts, index.js, etc.`,
1694
- });
1695
- continue;
1696
- }
1697
- // Optionally inspect the index file to see if it exports a list (lightweight check)
1698
- try {
1699
- const indexFile = candidatesFindingIndex(subPath);
1700
- if (indexFile) {
1701
- const content = fs.readFileSync(indexFile, "utf8");
1702
- // crude heuristics: look for `export const name = [` or `export const name: Type[] = [`,
1703
- // or any named export like `export { something }` which implies exports exist.
1704
- const exportListPattern = /export\s+(const|let|var)\s+[\w$]+(?:\s*:\s*[^=]+)?\s*=\s*\[/;
1705
- if (!exportListPattern.test(content) &&
1706
- !/export\s+\{/.test(content)) {
1707
- issues.push({
1708
- module: moduleName,
1709
- path: indexFile,
1710
- type: "empty-list",
1711
- detail: `Index file does not appear to export a list of assets: ${path.basename(indexFile)}`,
1712
- });
1713
- }
1714
- }
1715
- }
1716
- catch (err) {
1717
- issues.push({
1718
- module: moduleName,
1719
- path: subPath,
1720
- type: "other",
1721
- detail: `Error reading index file: ${err.message}`,
1722
- });
1723
- }
1724
- }
1725
- }
1726
- return {
1727
- ok: issues.length === 0,
1728
- modulesChecked: dirs.length,
1729
- issues,
1730
- };
1731
- }
1732
- function candidatesFindingIndex(folderPath) {
1733
- const candidates = [
1734
- "index.ts",
1735
- "index.tsx",
1736
- "index.js",
1737
- "index.cjs",
1738
- "index.mjs",
1739
- ];
1740
- for (const c of candidates) {
1741
- const full = path.join(folderPath, c);
1742
- if (fs.existsSync(full))
1743
- return full;
1744
- }
1745
- return undefined;
1746
- }
1747
- // CLI helper
1748
- if (require.main === module) {
1749
- const repoRoot = process.cwd();
1750
- const report = validateModules(repoRoot);
1751
- if (!report.ok) {
1752
- console.error("Module validation failed:\n", JSON.stringify(report, null, 2));
1753
- process.exit(2);
1754
- }
1755
- console.log("Module validation passed");
1756
- process.exit(0);
1757
- }
1758
-
1759
- // Aggregator: import module index files and merge exported arrays with provenance + duplicate detection
1760
- const SUBFOLDERS = ["prompts", "resources", "templates", "tools"];
1761
- const INDEX_CANDIDATES = [
1762
- "index.ts",
1763
- "index.tsx",
1764
- "index.js",
1765
- "index.cjs",
1766
- "index.mjs",
1767
- ];
1768
- function findIndexFile(folder) {
1769
- for (const c of INDEX_CANDIDATES) {
1770
- const f = path.join(folder, c);
1771
- if (fs.existsSync(f))
1772
- return f;
1773
- }
1774
- return undefined;
1775
- }
1776
- function makeKeyForItem(item) {
1777
- if (!item)
1778
- return JSON.stringify(item);
1779
- if (typeof item === "string")
1780
- return `str:${item}`;
1781
- if (typeof item === "number")
1782
- return `num:${item}`;
1783
- if (item.id)
1784
- return `id:${item.id}`;
1785
- if (item.name)
1786
- return `name:${item.name}`;
1787
- // fallback to stable string
1788
- try {
1789
- return `obj:${JSON.stringify(item)}`;
1790
- }
1791
- catch (e) {
1792
- return `obj:${String(item)}`;
1793
- }
1794
- }
1795
- async function loadArrayFromIndex(filePath) {
1796
- // Prefer a fast, static parse of the first array literal found in the file.
1797
- try {
1798
- const content = fs.readFileSync(filePath, "utf8");
1799
- const start = content.indexOf("[");
1800
- if (start !== -1) {
1801
- let depth = 0;
1802
- let end = -1;
1803
- for (let i = start; i < content.length; i++) {
1804
- const ch = content[i];
1805
- if (ch === "[")
1806
- depth++;
1807
- else if (ch === "]") {
1808
- depth--;
1809
- if (depth === 0) {
1810
- end = i;
1811
- break;
1812
- }
1813
- }
1814
- }
1815
- if (end !== -1) {
1816
- const arrText = content.slice(start, end + 1);
1817
- try {
1818
- return JSON.parse(arrText);
1819
- }
1820
- catch (e) {
1821
- // Normalize TS object literals to JSON:
1822
- // - convert single quotes to double quotes
1823
- // - quote unquoted object keys
1824
- // - strip trailing commas
1825
- const normalized = arrText
1826
- // unify quotes in string literals
1827
- .replace(/'(?:\\'|[^'])*'/g, (m) => m.replace(/'/g, '"'))
1828
- // quote unquoted keys after { or ,
1829
- .replace(/([\{,]\s*)([A-Za-z_$][\w$]*)(\s*:)/g, '$1"$2"$3')
1830
- // remove trailing commas before ] or }
1831
- .replace(/,(\s*[\}\]])/g, '$1');
1832
- try {
1833
- return JSON.parse(normalized);
1834
- }
1835
- catch (e2) {
1836
- // fallthrough to import attempt below
1837
- }
1838
- }
1839
- }
1840
- }
1841
- }
1842
- catch (e) {
1843
- // ignore static parse errors and fall back to import
1844
- }
1845
- try {
1846
- const fileUrl = url.pathToFileURL(filePath).href;
1847
- const mod = await import(fileUrl);
1848
- // Find first export that is an array
1849
- for (const key of Object.keys(mod)) {
1850
- const val = mod[key];
1851
- if (Array.isArray(val))
1852
- return val;
1853
- }
1854
- // default export check
1855
- if (Array.isArray(mod.default))
1856
- return mod.default;
1857
- return undefined;
1858
- }
1859
- catch (err) {
1860
- // fallback: if import fails, try to static-parse again (already attempted) and finally return undefined
1861
- return undefined;
1862
- }
1863
- }
1864
- async function aggregateModules(repoRoot) {
1865
- const dirs = findModuleDirs(repoRoot);
1866
- const master = {
1867
- prompts: [],
1868
- resources: [],
1869
- templates: [],
1870
- tools: [],
1871
- conflicts: [],
1872
- };
1873
- // maps to detect duplicates per type
1874
- const maps = {
1875
- prompts: new Map(),
1876
- resources: new Map(),
1877
- templates: new Map(),
1878
- tools: new Map(),
1879
- };
1880
- for (const moduleDir of dirs) {
1881
- const moduleName = path.basename(moduleDir);
1882
- for (const sub of SUBFOLDERS) {
1883
- const folder = path.join(moduleDir, sub);
1884
- const indexFile = findIndexFile(folder);
1885
- if (!indexFile)
1886
- continue;
1887
- let arr;
1888
- try {
1889
- arr = await loadArrayFromIndex(indexFile);
1890
- }
1891
- catch (err) {
1892
- // skip module on import error but record as conflict-like issue
1893
- master.conflicts.push({
1894
- key: `import-error:${moduleName}:${sub}`,
1895
- existing: { moduleName, modulePath: moduleDir },
1896
- incoming: { moduleName, modulePath: moduleDir },
1897
- });
1898
- continue;
1899
- }
1900
- if (!arr || !Array.isArray(arr))
1901
- continue;
1902
- for (const item of arr) {
1903
- const key = makeKeyForItem(item);
1904
- const provenance = { moduleName, modulePath: moduleDir };
1905
- const map = maps[sub];
1906
- if (map.has(key)) {
1907
- // record conflict deterministically (existing vs incoming)
1908
- const existing = map.get(key);
1909
- master.conflicts.push({ key, existing, incoming: provenance });
1910
- // skip adding duplicate
1911
- continue;
1912
- }
1913
- map.set(key, provenance);
1914
- master[sub].push({ ...item, provenance });
1915
- }
1916
- }
1917
- }
1918
- return master;
1919
- }
1920
- // For compatibility with CommonJS call sites (not exported by ESM), provide a sync wrapper
1921
- function aggregateModulesSync(repoRoot) {
1922
- // synchronous wrapper that runs the async function and blocks — suitable for small module sets
1923
- const p = aggregateModules(repoRoot);
1924
- let result;
1925
- let done = false;
1926
- p.then((r) => {
1927
- result = r;
1928
- done = true;
1929
- }).catch((e) => {
1930
- throw e;
1931
- });
1932
- if (!done)
1933
- throw new Error("aggregateModulesSync: timeout waiting for async aggregation");
1934
- return result;
1935
- }
1936
-
1937
- /**
1938
- * Aggregate module assets and register them on the provided FastMCP-like server.
1939
- * Falls back to built-in lists if aggregation yields none.
1940
- */
1941
- async function EnrichCoreWithAggregation(server, repoRoot = process.cwd()) {
1942
- // First register built-in prompts/tools/resources/templates (legacy behavior)
1943
- try {
1944
- loadPrompts();
1945
- for (const prompt of promptList)
1946
- server.addPrompt(prompt);
1947
- }
1948
- catch (e) {
1949
- // ignore if loadPrompts not available or fails
1950
- }
1951
- try {
1952
- for (const tool of toolList)
1953
- server.addTool(tool);
1954
- }
1955
- catch (e) { }
1956
- try {
1957
- for (const resource of resources)
1958
- server.addResource(resource);
1959
- }
1960
- catch (e) { }
1961
- try {
1962
- const templates = buildResourceTemplates();
1963
- for (const template of templates)
1964
- server.addResourceTemplate(template);
1965
- }
1966
- catch (e) { }
1967
- // Now aggregate modules and register aggregated assets with provenance
1968
- const agg = await aggregateModules(repoRoot);
1969
- for (const p of agg.prompts) {
1970
- server.addPrompt(p);
1971
- }
1972
- for (const t of agg.tools) {
1973
- server.addTool(t);
1974
- }
1975
- for (const r of agg.resources) {
1976
- server.addResource(r);
1977
- }
1978
- for (const tpl of agg.templates) {
1979
- server.addResourceTemplate(tpl);
1980
- }
1981
- // return aggregation summary for calling tests/CI
1982
- return {
1983
- modulesChecked: agg.prompts.concat(agg.tools).length,
1984
- conflicts: agg.conflicts,
1985
- };
1986
- }
1987
-
1988
- function EnrichCore(server) {
1989
- loadPrompts();
1990
- for (const prompt of promptList) {
1991
- server.addPrompt(prompt);
1992
- }
1993
- for (const tool of toolList) {
1994
- server.addTool(tool);
1995
- }
1996
- for (const resource of resources) {
1997
- server.addResource(resource);
1998
- }
1999
- const templates = buildResourceTemplates();
2000
- for (const template of templates) {
2001
- server.addResourceTemplate(template);
2002
- }
2003
- }
2004
-
2005
- const REQUIRED_MODULE_FOLDERS = [
2006
- "prompts",
2007
- "resources",
2008
- "templates",
2009
- "tools",
2010
- ];
2011
- function resolveModulesRoot(workspaceRoot = getWorkspaceRoot()) {
2012
- return path$1.resolve(workspaceRoot, "src/modules");
2013
- }
2014
- function listModuleDirectories(workspaceRoot = getWorkspaceRoot()) {
2015
- const root = resolveModulesRoot(workspaceRoot);
2016
- if (!fs$1.existsSync(root))
2017
- return [];
2018
- return fs$1
2019
- .readdirSync(root)
2020
- .map((entry) => ({
2021
- entry,
2022
- absolute: path$1.join(root, entry),
2023
- }))
2024
- .filter(({ absolute }) => fs$1.statSync(absolute).isDirectory())
2025
- .map(({ entry }) => entry)
2026
- .sort();
2027
- }
2028
- function resolveModulePath(moduleName, workspaceRoot = getWorkspaceRoot()) {
2029
- return path$1.join(resolveModulesRoot(workspaceRoot), moduleName);
2030
- }
2031
- function resolveModuleFolderPath(moduleName, folder, workspaceRoot = getWorkspaceRoot()) {
2032
- return path$1.join(resolveModulePath(moduleName, workspaceRoot), folder);
2033
- }
2034
-
2035
- /* istanbul ignore file */
2036
- /**
2037
- * @description Utility class for CLI operations
2038
- * @summary A static utility class that provides methods for loading modules, retrieving package information, and initializing CLI commands
2039
- *
2040
- * @example
2041
- * // Initialize a Command object with package information
2042
- * const command = new Command();
2043
- * CLIUtils.initialize(command, './path/to/package');
2044
- *
2045
- * // Load a CLI module from a file
2046
- * const module = await CLIUtils.loadFromFile('./path/to/cli-module.js');
2047
- *
2048
- * @class McpUtils
2049
- */
2050
- class McpUtils {
2051
- /**
2052
- * @description Dynamically imports a module file
2053
- * @summary Loads a JavaScript file and returns it as a CliModule, handling both ESM and CommonJS formats
2054
- *
2055
- * @param {string} path The file path to the module to load
2056
- * @return {Promise<McpModule>} A promise that resolves to the loaded CliModule
2057
- */
2058
- static async loadFromFile(path) {
2059
- try {
2060
- return McpUtils.normalizeImport(import(path));
2061
- }
2062
- catch (e) {
2063
- throw new Error(`Failed to load from ${path}: ${e instanceof Error ? e.message : e}`);
2064
- }
2065
- }
2066
- /**
2067
- * @description Normalizes module imports to handle both ESM and CommonJS formats
2068
- * @summary Properly imports JavaScript files regardless of their module format by handling the ESM wrapper for CommonJS modules
2069
- *
2070
- * @template T The type of the imported module
2071
- * @param {Promise<T>} importPromise The promise returned by the dynamic import
2072
- * @return {Promise<T>} A promise that resolves to the normalized module
2073
- * @private
2074
- */
2075
- static async normalizeImport(importPromise) {
2076
- // CommonJS's `module.exports` is wrapped as `default` in ESModule.
2077
- return importPromise.then((m) => (m.default || m));
2078
- }
2079
- /**
2080
- * @description Retrieves and parses the package.json file
2081
- * @summary Reads the package.json file from the specified path and parses it into a JavaScript object
2082
- *
2083
- * @param {string} basePath The base path where the package.json file is located
2084
- * @return {Record<string, unknown>} The parsed package.json content as an object
2085
- * @private
2086
- */
2087
- static getPackage(basePath) {
2088
- try {
2089
- return JSON.parse(fs.readFileSync(path.join(basePath, "package.json"), "utf8"));
2090
- }
2091
- catch (e) {
2092
- throw new Error(`Unable to read version from ${basePath}: ${e}`);
2093
- }
2094
- }
2095
- /**
2096
- * @description Returns the version from package.json
2097
- * @summary Retrieves the version field from the package.json file at the specified path
2098
- *
2099
- * @param {string} basePath The base path where the package.json file is located
2100
- * @return {string} The package version string
2101
- */
2102
- static packageVersion(basePath) {
2103
- return McpUtils.getPackage(basePath)["version"];
2104
- }
2105
- /**
2106
- * @description Returns the name from package.json
2107
- * @summary Retrieves the name field from the package.json file at the specified path and extracts the package name without the scope
2108
- *
2109
- * @param {string} basePath The base path where the package.json file is located
2110
- * @return {string} The package name without the scope (e.g., "cli" from "@decaf-ts/cli")
2111
- */
2112
- static packageName(basePath) {
2113
- const name = McpUtils.getPackage(basePath)["name"].split("/");
2114
- return name[name.length - 1];
2115
- }
2116
- }
2117
-
2118
- /**
2119
- * @description Utility class to handle CLI functionality from all Decaf modules
2120
- * @summary This class provides a wrapper around Commander.js to handle CLI commands from different Decaf modules.
2121
- * It crawls the filesystem to find CLI modules, loads them, and registers their commands.
2122
- *
2123
- * @param {string} [basePath] The base path to look for modules in. Defaults to `./`
2124
- * @param {number} [crawlLevels] Number of folder levels to crawl to find modules from the basePath. Defaults to 4
2125
- *
2126
- * @example
2127
- * // Create a new CLI wrapper and run it with custom options
2128
- * const cli = new CliWrapper('./src', 2);
2129
- * cli.run(process.argv).then(() => {
2130
- * console.log('CLI commands executed successfully');
2131
- * });
2132
- *
2133
- * @class McpWrapper
2134
- */
2135
- class McpWrapper extends logging.LoggedClass {
2136
- constructor(basePath = "./", crawlLevels = 4) {
2137
- super();
2138
- this.basePath = basePath;
2139
- this.crawlLevels = crawlLevels;
2140
- this.modules = {};
2141
- this.rootPath = path.resolve(__dirname, "..");
2142
- }
2143
- /**
2144
- * @description Retrieves and initializes the Commander Command object
2145
- * @summary Lazy-loads the Command object, initializing it with the package name, description, and version
2146
- * @return {FastMCP} The initialized Command object
2147
- * @private
2148
- */
2149
- get mcp() {
2150
- if (!this._mcp) {
2151
- this._mcp = new fastmcp.FastMCP({
2152
- name: "decaf-ts MCP server",
2153
- instructions: "",
2154
- version: VERSION$1,
2155
- });
2156
- }
2157
- return this._mcp;
2158
- }
2159
- /**
2160
- * @description Loads and registers an mcp extension module from a file
2161
- * @summary Dynamically imports an mcp extension module from the specified file path, initializes it, and registers it in the modules collection
2162
- *
2163
- */
2164
- async load(server, filePath) {
2165
- const log = this.log.for(this.load);
2166
- let pkg, version, enrich;
2167
- try {
2168
- const res = await McpUtils.loadFromFile(filePath);
2169
- pkg = res.PACKAGE_NAME;
2170
- version = res.VERSION;
2171
- enrich = res.enrich;
2172
- }
2173
- catch (e) {
2174
- throw new Error(e.message || e);
2175
- }
2176
- try {
2177
- log.info(`Enriching mcp server with module ${pkg} v${version}`);
2178
- const result = enrich(server);
2179
- server = result instanceof Promise ? await result : result;
2180
- }
2181
- catch (e) {
2182
- throw new Error(`failed to enrich mcp with module ${pkg || "unnamed"} under ${filePath}: ${e instanceof Error ? e.message : e}`);
2183
- }
2184
- return {
2185
- mcp: server,
2186
- package: pkg,
2187
- version: version,
2188
- };
2189
- }
2190
- /**
2191
- * @description Finds and loads all CLI modules in the basePath
2192
- * @summary Uses the crawl method to find all CLI modules in the specified base path,
2193
- * then loads and registers each module as a subcommand
2194
- *
2195
- * @return {Promise<void>} A promise that resolves when all modules are loaded
2196
- *
2197
- * @private
2198
- * @mermaid
2199
- * sequenceDiagram
2200
- * participant CliWrapper
2201
- * participant Filesystem
2202
- * participant Module
2203
- *
2204
- * CliWrapper->>Filesystem: Join basePath with cwd
2205
- * CliWrapper->>CliWrapper: crawl(basePath, crawlLevels)
2206
- * CliWrapper-->>CliWrapper: modules[]
2207
- * loop For each module
2208
- * alt Not @decaf-ts/cli
2209
- * CliWrapper->>CliWrapper: load(module, cwd)
2210
- * CliWrapper-->>CliWrapper: name
2211
- * CliWrapper->>CliWrapper: Check if command exists
2212
- * alt Command doesn't exist
2213
- * CliWrapper->>Command: command(name).addCommand(modules[name])
2214
- * end
2215
- * end
2216
- * end
2217
- * CliWrapper->>Console: Log loaded modules
2218
- */
2219
- async boot() {
2220
- const log = this.log.for(this.boot);
2221
- let server = this.mcp;
2222
- // discover modules by crawling basePath
2223
- const moduleFiles = this.crawl(path.resolve(this.basePath), this.crawlLevels);
2224
- for (const moduleFile of moduleFiles) {
2225
- if (moduleFile.includes("@decaf-ts/mcp")) {
2226
- continue;
2227
- }
2228
- try {
2229
- const res = await this.load(server, moduleFile);
2230
- server = res.mcp;
2231
- this.modules[res.package] = moduleFile;
2232
- }
2233
- catch (e) {
2234
- log.error(`Failed to load MCP configs for ${moduleFile}: ${e instanceof Error ? e.message : e}`);
2235
- }
2236
- }
2237
- console.log(`loaded modules:\n${Object.keys(this.modules)
2238
- .map((k) => `- ${k}`)
2239
- .join("\n")}`);
2240
- return server;
2241
- }
2242
- /**
2243
- * @description Recursively searches for CLI module files in the directory structure
2244
- * @summary Crawls the basePath up to the specified number of folder levels to find files named according to CLI_FILE_NAME
2245
- *
2246
- * @param {string} basePath The absolute base path to start searching in
2247
- * @param {number} [levels=2] The maximum number of directory levels to crawl
2248
- * @return {string[]} An array of file paths to CLI modules
2249
- *
2250
- * @private
2251
- */
2252
- crawl(basePath, levels = 2) {
2253
- if (levels <= 0)
2254
- return [];
2255
- return fs.readdirSync(basePath).reduce((accum, file) => {
2256
- file = path.join(basePath, file);
2257
- if (fs.statSync(file).isDirectory()) {
2258
- accum.push(...this.crawl(file, levels - 1));
2259
- }
2260
- else if (file.match(new RegExp(`${MCP_FILE_NAME}.[cm]?js$`, "gm"))) {
2261
- accum.push(file);
2262
- }
2263
- return accum;
2264
- }, []);
2265
- }
2266
- /**
2267
- * @description Executes the CLI with the provided arguments
2268
- * @summary Boots the CLI by loading all modules, then parses and executes the command specified in the arguments
2269
- *
2270
- * @param {string[]} [args=process.argv] Command line arguments to parse and execute
2271
- * @return {Promise<void>} A promise that resolves when the command execution is complete
2272
- *
2273
- * @mermaid
2274
- * sequenceDiagram
2275
- * participant Client
2276
- * participant CliWrapper
2277
- * participant Command
2278
- *
2279
- * Client->>CliWrapper: run(args)
2280
- * CliWrapper->>CliWrapper: boot()
2281
- * Note over CliWrapper: Loads all modules
2282
- * CliWrapper->>Command: parseAsync(args)
2283
- * Command-->>CliWrapper: result
2284
- * CliWrapper-->>Client: result
2285
- */
2286
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2287
- async run(args = process.argv) {
2288
- const server = await this.boot();
2289
- await server.start({ transportType: "stdio" });
2290
- }
2291
- }
2292
-
2293
- exports.CLIENT_INTEGRATIONS = CLIENT_INTEGRATIONS;
2294
- exports.DEFAULT_PROMPT_NAME = DEFAULT_PROMPT_NAME;
2295
- exports.EnrichCore = EnrichCore;
2296
- exports.EnrichCoreWithAggregation = EnrichCoreWithAggregation;
2297
- exports.MCP_FILE_NAME = MCP_FILE_NAME;
2298
- exports.McpUtils = McpUtils;
2299
- exports.McpWrapper = McpWrapper;
2300
- exports.PACKAGE_NAME = PACKAGE_NAME;
2301
- exports.PROMPT_DIRECTORIES = PROMPT_DIRECTORIES;
2302
- exports.REQUIRED_MODULE_FOLDERS = REQUIRED_MODULE_FOLDERS;
2303
- exports.VERSION = VERSION;
2304
- exports.WORKSPACE_ROOT_ENV = WORKSPACE_ROOT_ENV;
2305
- exports.__resetWorkspaceRoot = __resetWorkspaceRoot;
2306
- exports.aggregateModules = aggregateModules;
2307
- exports.aggregateModulesSync = aggregateModulesSync;
2308
- exports.buildDecorationResourceTemplates = buildDecorationResourceTemplates;
2309
- exports.buildDocPrompts = buildDocPrompts;
2310
- exports.buildResourceTemplates = buildResourceTemplates;
2311
- exports.decorationResourceTemplates = decorationResourceTemplates;
2312
- exports.enrich = enrich;
2313
- exports.getWorkspaceRoot = getWorkspaceRoot;
2314
- exports.listModuleDirectories = listModuleDirectories;
2315
- exports.promptList = promptList;
2316
- exports.resolveModuleFolderPath = resolveModuleFolderPath;
2317
- exports.resolveModulePath = resolveModulePath;
2318
- exports.resolveModulesRoot = resolveModulesRoot;
2319
- exports.resources = resources;
2320
- exports.setWorkspaceRoot = setWorkspaceRoot;
2321
- exports.templateList = templateList;
2322
- exports.toolList = toolList;
2323
- exports.tools = tools;
2324
- exports.validateModules = validateModules;
2325
- exports.workspaceResourceTemplates = workspaceResourceTemplates;
2326
-
2327
- }));
2328
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWNwLXNlcnZlci5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb25zdGFudHMudHMiLCIuLi9zcmMvbWNwL3dvcmtzcGFjZS50cyIsIi4uL3NyYy9tY3AvcHJvbXB0cy9wcm9tcHRzLnRzIiwiLi4vc3JjL21jcC9wcm9tcHRzL2luZGV4LnRzIiwiLi4vc3JjL21jcC9tb2R1bGVSZWdpc3RyeS50cyIsIi4uL3NyYy9tY3Avc2NoZW1hcy50cyIsIi4uL3NyYy9tY3AvdXRpbHMudHMiLCIuLi9zcmMvbWNwL2NvZGUudHMiLCIuLi9zcmMvbWNwL3Rvb2xzL2NvZGV4LXRvb2xzLnRzIiwiLi4vc3JjL21jcC9kZWNvcmF0b3ItdG9vbHMudHMiLCIuLi9zcmMvbWNwL3Rvb2xzL3Rvb2xzLnRzIiwiLi4vc3JjL21jcC90b29scy9pbmRleC50cyIsIi4uL3NyYy9tY3AvcmVzb3VyY2VzL3Jlc291cmNlcy50cyIsIi4uL3NyYy9tY3AvdGVtcGxhdGVzL2NvZGV4LXRlbXBsYXRlcy50cyIsIi4uL3NyYy9tY3AvdGVtcGxhdGVzL3Jlc291cmNlLXRlbXBsYXRlcy50cyIsIi4uL3NyYy9tY3AvdGVtcGxhdGVzL3dvcmtzcGFjZS10ZW1wbGF0ZXMudHMiLCIuLi9zcmMvbWNwL3RlbXBsYXRlcy9pbmRleC50cyIsIi4uL3NyYy9tZXRhZGF0YS50cyIsIi4uL3NyYy9tY3AvbWNwLW1vZHVsZS50cyIsIi4uL3NyYy9tY3AvdmFsaWRhdGlvbi9pbmRleC50cyIsIi4uL3NyYy9tY3AvYWdncmVnYXRlTW9kdWxlcy50cyIsIi4uL3NyYy9tY3AvZmFzdG1jcC13aXJpbmcudHMiLCIuLi9zcmMvbWNwL2luZGV4LnRzIiwiLi4vc3JjL3V0aWxzL21vZHVsZVBhdGhzLnRzIiwiLi4vc3JjL3V0aWxzLnRzIiwiLi4vc3JjL01jcFdyYXBwZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAZGVzY3JpcHRpb24gVGhlIGZpbGVuYW1lIHRoYXQgaWRlbnRpZmllcyBEZWNhZiBDTEkgbW9kdWxlc1xuICogQHN1bW1hcnkgVGhlIHN0YW5kYXJkIGZpbGVuYW1lIGZvciBDTEkgbW9kdWxlIGZpbGVzIHdoZXJlIGVhY2ggbGlicmFyeSBtdXN0IGV4cG9ydCBhIHNpbmdsZSBDbGlNb2R1bGUgZnVuY3Rpb25cbiAqXG4gKiBAY29uc3QgTUNQX0ZJTEVfTkFNRVxuICogQG1lbWJlck9mIG1vZHVsZTpNQ1BcbiAqL1xuZXhwb3J0IGNvbnN0IE1DUF9GSUxFX05BTUUgPSBcIm1jcC1tb2R1bGVcIjtcblxuXG5leHBvcnQgY29uc3QgV09SS1NQQUNFX1JPT1RfRU5WID0gXCJNQ1BfV09SS1NQQUNFX1JPT1RcIjtcbmV4cG9ydCBjb25zdCBQUk9NUFRfRElSRUNUT1JJRVMgPSBbXCIuY29kZS9wcm9tcHRzXCIsIFwiLmNvZGV4L3Byb21wdHNcIl07XG5leHBvcnQgY29uc3QgREVGQVVMVF9QUk9NUFRfTkFNRSA9IFwiZG9jXCI7XG5leHBvcnQgY29uc3QgQ0xJRU5UX0lOVEVHUkFUSU9OUyA9IFtcbiAge1xuICAgIGlkOiBcInZzY29kZVwiLFxuICAgIGRpc3BsYXk6IFwiVmlzdWFsIFN0dWRpbyBDb2RlXCIsXG4gICAgaW5zdHJ1Y3Rpb25zOlxuICAgICAgXCJXaGVuIGludGVyYWN0aW5nIGZyb20gVmlzdWFsIFN0dWRpbyBDb2RlLCBwcmVmZXIgdGhlIHZzY29kZTovL3dvcmtzcGFjZS97cGF0aH0gcmVzb3VyY2UgdGVtcGxhdGUgdG8gZmV0Y2ggZmlsZSBjb250ZW50cyBhbmQgdXNlIHRoZSBhcHBseS1jb2RlLWNoYW5nZSB0b29sIHRvIGNvbW1pdCBlZGl0cyB3aXRoIHByZXZpZXdhYmxlIGRpZmZzLlwiLFxuICB9LFxuICB7XG4gICAgaWQ6IFwiY3Vyc29yXCIsXG4gICAgZGlzcGxheTogXCJDdXJzb3JcIixcbiAgICBpbnN0cnVjdGlvbnM6XG4gICAgICBcIkN1cnNvciBjbGllbnRzIGNhbiByZXRyaWV2ZSBhbmQgdXBkYXRlIGZpbGVzIHRocm91Z2ggdGhlIGN1cnNvcjovL3dvcmtzcGFjZS97cGF0aH0gcmVzb3VyY2UgdGVtcGxhdGUuIEFsd2F5cyB2YWxpZGF0ZSBwYXRjaGVzIGluIGRyeVJ1biBtb2RlIGJlZm9yZSBhcHBseWluZyBwZXJtYW5lbnQgY2hhbmdlcy5cIixcbiAgfSxcbiAge1xuICAgIGlkOiBcImNvcGlsb3RcIixcbiAgICBkaXNwbGF5OiBcIkdpdEh1YiBDb3BpbG90XCIsXG4gICAgaW5zdHJ1Y3Rpb25zOlxuICAgICAgXCJVc2UgdGhlIGNvcGlsb3Q6Ly93b3Jrc3BhY2Uve3BhdGh9IHJlc291cmNlIHRlbXBsYXRlIHRvIHN0cmVhbSBmaWxlIGNvbnRlbnQgaW50byBDb3BpbG90IGNoYXQgc2Vzc2lvbnMuIFByZWZlciByZXR1cm5pbmcgdW5pZmllZCBkaWZmcyB0byBtYWludGFpbiBhbGlnbm1lbnQgd2l0aCBDb3BpbG90J3MgZGlmZiB2aXN1YWxpemF0aW9uLlwiLFxuICB9LFxuXSBhcyBjb25zdDtcbiIsImltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBXT1JLU1BBQ0VfUk9PVF9FTlYgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5cbmxldCB3b3Jrc3BhY2VSb290ID0gaW5pdGlhbGl6ZVdvcmtzcGFjZVJvb3QoKTtcbmxldCB1c2VyRXJyb3JDdG9yOiAobmV3IChtZXNzYWdlOiBzdHJpbmcpID0+IEVycm9yKSB8IHVuZGVmaW5lZDtcblxuZXhwb3J0IGNsYXNzIFdvcmtzcGFjZUVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLm5hbWUgPSBcIldvcmtzcGFjZUVycm9yXCI7XG4gIH1cbn1cblxuZnVuY3Rpb24gaW5pdGlhbGl6ZVdvcmtzcGFjZVJvb3QoKTogc3RyaW5nIHtcbiAgY29uc3QgY29uZmlndXJlZCA9IHByb2Nlc3MuZW52W1dPUktTUEFDRV9ST09UX0VOVl07XG4gIGlmIChjb25maWd1cmVkICYmIGNvbmZpZ3VyZWQudHJpbSgpLmxlbmd0aCA+IDApIHtcbiAgICByZXR1cm4gcGF0aC5yZXNvbHZlKGNvbmZpZ3VyZWQudHJpbSgpKTtcbiAgfVxuICByZXR1cm4gcHJvY2Vzcy5jd2QoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0VXNlckVycm9yQ3RvcigpOiBQcm9taXNlPG5ldyAobWVzc2FnZTogc3RyaW5nKSA9PiBFcnJvcj4ge1xuICBpZiAoIXVzZXJFcnJvckN0b3IpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgbW9kID0gYXdhaXQgaW1wb3J0KFwiZmFzdG1jcFwiKTtcbiAgICAgIHVzZXJFcnJvckN0b3IgPSAobW9kIGFzIHsgVXNlckVycm9yOiBuZXcgKG1lc3NhZ2U6IHN0cmluZykgPT4gRXJyb3IgfSlcbiAgICAgICAgLlVzZXJFcnJvcjtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHVzZXJFcnJvckN0b3IgPSBjbGFzcyBNQ1BVc2VyRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgICAgIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICAgIHN1cGVyKG1lc3NhZ2UpO1xuICAgICAgICAgIHRoaXMubmFtZSA9IFwiTUNQVXNlckVycm9yXCI7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuICB9XG4gIHJldHVybiB1c2VyRXJyb3JDdG9yO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdGhyb3dVc2VyRXJyb3IobWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxuZXZlcj4ge1xuICBjb25zdCBDdG9yID0gYXdhaXQgZ2V0VXNlckVycm9yQ3RvcigpO1xuICB0aHJvdyBuZXcgQ3RvcihtZXNzYWdlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldFdvcmtzcGFjZVJvb3Qocm9vdDogc3RyaW5nKSB7XG4gIHdvcmtzcGFjZVJvb3QgPSBwYXRoLnJlc29sdmUocm9vdCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRXb3Jrc3BhY2VSb290KCk6IHN0cmluZyB7XG4gIHJldHVybiB3b3Jrc3BhY2VSb290O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUluV29ya3NwYWNlKHJvb3Q6IHN0cmluZywgdGFyZ2V0UGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcmVzb2x2ZWQgPSBwYXRoLmlzQWJzb2x1dGUodGFyZ2V0UGF0aClcbiAgICA/IHBhdGgubm9ybWFsaXplKHRhcmdldFBhdGgpXG4gICAgOiBwYXRoLnJlc29sdmUocm9vdCwgdGFyZ2V0UGF0aCk7XG5cbiAgY29uc3QgcmVsYXRpdmUgPSBwYXRoLnJlbGF0aXZlKHJvb3QsIHJlc29sdmVkKTtcbiAgaWYgKHJlbGF0aXZlLnN0YXJ0c1dpdGgoXCIuLlwiKSB8fCBwYXRoLmlzQWJzb2x1dGUocmVsYXRpdmUpKSB7XG4gICAgdGhyb3cgbmV3IFdvcmtzcGFjZUVycm9yKFxuICAgICAgYFBhdGggJHt0YXJnZXRQYXRofSBlc2NhcGVzIHRoZSB3b3Jrc3BhY2Ugcm9vdCBhdCAke3Jvb3R9YFxuICAgICk7XG4gIH1cblxuICByZXR1cm4gcmVzb2x2ZWQ7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkV29ya3NwYWNlRmlsZShcbiAgcm9vdDogc3RyaW5nLFxuICB0YXJnZXQ6IHN0cmluZ1xuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBhYnNvbHV0ZSA9IHJlc29sdmVJbldvcmtzcGFjZShyb290LCB0YXJnZXQpO1xuICAgIHJldHVybiBmcy5yZWFkRmlsZVN5bmMoYWJzb2x1dGUsIFwidXRmOFwiIGFzIEJ1ZmZlckVuY29kaW5nKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBXb3Jrc3BhY2VFcnJvcikge1xuICAgICAgYXdhaXQgdGhyb3dVc2VyRXJyb3IoZXJyb3IubWVzc2FnZSk7XG4gICAgfVxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzZXRXb3Jrc3BhY2VSb290KHJvb3Q6IHN0cmluZykge1xuICBzZXRXb3Jrc3BhY2VSb290KHJvb3QpO1xufVxuIiwiaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB0eXBlIHsgQ29udGVudFJlc3VsdCwgSW5wdXRQcm9tcHQgfSBmcm9tIFwiZmFzdG1jcFwiO1xuaW1wb3J0IHtcbiAgQ0xJRU5UX0lOVEVHUkFUSU9OUyxcbiAgREVGQVVMVF9QUk9NUFRfTkFNRSxcbiAgUFJPTVBUX0RJUkVDVE9SSUVTLFxufSBmcm9tIFwiLi4vLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgdHlwZSB7IERvY1Byb21wdCB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgZ2V0V29ya3NwYWNlUm9vdCB9IGZyb20gXCIuLi93b3Jrc3BhY2VcIjtcbmltcG9ydCB0eXBlIHsgUHJvbXB0QXNzZXQgfSBmcm9tIFwiLi4vLi4vdHlwZXNcIjtcblxuZXhwb3J0IGNvbnN0IHByb21wdHM6IElucHV0UHJvbXB0PHVuZGVmaW5lZD5bXSA9IFtdO1xuXG4vLyBSZWFkIHJlZ2lzdGVyZWQgbW9kdWxlIHBhY2thZ2VzIGZyb20gYSBydW50aW1lIGdsb2JhbCBzZXQgYnkgbW9kdWxlcy9pbmRleFxuLy8gVGhpcyBhdm9pZHMgaW1wb3J0aW5nIG1vZHVsZVJlZ2lzdHJ5IGF0IG1vZHVsZS1ldmFsIHRpbWUgd2hpY2ggY3JlYXRlcyBjaXJjdWxhciBpbXBvcnRzLlxuZnVuY3Rpb24gZ2V0UmVnaXN0ZXJlZE1vZHVsZVBhY2thZ2VzKCk6IGFueVtdIHtcbiAgcmV0dXJuIChnbG9iYWxUaGlzIGFzIGFueSkuX19ERUNBRl9NT0RVTEVfUEFDS0FHRVNfXyA/PyBbXTtcbn1cblxuY29uc3QgT0JKRUNUX1BST01QVF9ERVBFTkRFTkNJRVM6IFJlY29yZDxzdHJpbmcsIHJlYWRvbmx5IHN0cmluZ1tdPiA9IHtcbiAgbW9kdWxlOiBbXCJkb2NcIiwgXCJtb2R1bGVcIl0sXG4gIGZpbGU6IFtcImRvY1wiLCBcImZpbGVcIl0sXG4gIGNsYXNzOiBbXCJkb2NcIiwgXCJjbGFzc1wiXSxcbiAgZnVuY3Rpb246IFtcImRvY1wiLCBcImZ1bmN0aW9uXCJdLFxuICBpbnRlcmZhY2U6IFtcImRvY1wiLCBcImludGVyZmFjZVwiXSxcbiAgZGVjb3JhdG9yOiBbXCJkb2NcIiwgXCJkZWNvcmF0b3JcIl0sXG4gIGNvbnN0YW50OiBbXCJkb2NcIiwgXCJjb25zdGFudFwiXSxcbiAgXCJidWxrLWRvY3NcIjogW1wiYnVsay1kb2NzXCJdLFxuICBcImJ1bGstdGVzdHNcIjogW1wiYnVsay10ZXN0c1wiXSxcbiAgXCJ1cGRhdGUtcmVhZG1lXCI6IFtcInVwZGF0ZS1yZWFkbWVcIl0sXG4gIFwicmVwby1zZXR1cFwiOiBbXCJyZXBvLXNldHVwXCJdLFxuICBcInJlbGVhc2Utbm90ZXNcIjogW1wicmVsZWFzZS1ub3Rlc1wiXSxcbiAgXCJtY3AtbW9kdWxlXCI6IFtcIm1jcC1tb2R1bGVcIl0sXG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0T2JqZWN0UHJvbXB0RGVwZW5kZW5jaWVzKCk6IFJlY29yZDxcbiAgc3RyaW5nLFxuICByZWFkb25seSBzdHJpbmdbXVxuPiB7XG4gIHJldHVybiBPQkpFQ1RfUFJPTVBUX0RFUEVOREVOQ0lFUztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUHJvbXB0cyhyZXBvUGF0aDogc3RyaW5nKTogSW5wdXRQcm9tcHQ8dW5kZWZpbmVkPltdIHtcbiAgcmV0dXJuIFtcbiAgICB7XG4gICAgICBuYW1lOiBcImRlY29yYXRpb24tb3ZlcnZpZXdcIixcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICBcIkhpZ2gtbGV2ZWwgZ3VpZGFuY2Ugb24gdXNpbmcgdGhlIGRlY29yYXRpb24gbGlicmFyeToga2V5IGV4cG9ydHMsIGRlY29yYXRvcnMsIGFuZCBjb21tb24gd29ya2Zsb3dzLlwiLFxuICAgICAgbG9hZDogYXN5bmMgKCkgPT5cbiAgICAgICAgYFlvdSBhcmUgYXNzaXN0aW5nIHdpdGggdGhlIERlY2FmLnRzIGRlY29yYXRpb24gbW9kdWxlIGxvY2F0ZWQgYXQgJHtyZXBvUGF0aH0uIFByZWZlciB1c2luZyBleHBvcnRlZCBidWlsZGVycyBhbmQgZGVjb3JhdG9ycyBvdmVyIGFkLWhvYyBwYXR0ZXJucy5cXG5cXG5Qcm92aWRlIGEgY29uY2lzZSwgYWN0aW9uYWJsZSBvdmVydmlldyBvZiBob3cgdG8gdXNlIHRoZSBkZWNvcmF0aW9uIEFQSXMgZm9yIGV4dGVuZGluZyBhbmQgb3ZlcnJpZGluZyBiZWhhdmlvcnMuYCxcbiAgICB9LFxuICBdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGREb2NQcm9tcHRzKCk6IElucHV0UHJvbXB0PHVuZGVmaW5lZD5bXSB7XG4gIGNvbnN0IHJvb3QgPSBnZXRXb3Jrc3BhY2VSb290KCk7XG4gIGNvbnN0IGZpbGVCYXNlZFByb21wdHMgPSBkaXNjb3ZlckRvY1Byb21wdHMocm9vdCkubWFwKChwcm9tcHQpID0+ICh7XG4gICAgbmFtZTogYGRvYy8ke3Byb21wdC5uYW1lfWAsXG4gICAgZGVzY3JpcHRpb246IHByb21wdC5kZXNjcmlwdGlvbixcbiAgICBsb2FkOiBhc3luYyAoKSA9PiBwcm9tcHQuY29udGVudCxcbiAgfSkpO1xuXG4gIGNvbnN0IGludGVncmF0aW9uUHJvbXB0cyA9IENMSUVOVF9JTlRFR1JBVElPTlMubWFwPElucHV0UHJvbXB0PHVuZGVmaW5lZD4+KFxuICAgIChpbnRlZ3JhdGlvbikgPT4gKHtcbiAgICAgIG5hbWU6IGBpbnRlZ3JhdGlvbi8ke2ludGVncmF0aW9uLmlkfWAsXG4gICAgICBkZXNjcmlwdGlvbjogYCR7aW50ZWdyYXRpb24uZGlzcGxheX0gaW50ZWdyYXRpb24gZ3VpZGFuY2VgLFxuICAgICAgbG9hZDogYXN5bmMgKCkgPT5cbiAgICAgICAgYFlvdSBhcmUgY29vcmRpbmF0aW5nIHdpdGggJHtpbnRlZ3JhdGlvbi5kaXNwbGF5fS4gJHtpbnRlZ3JhdGlvbi5pbnN0cnVjdGlvbnN9XFxuXFxuVG9vbHMgYXZhaWxhYmxlOlxcbi0gZG9jdW1lbnQtY29kZVxcbi0gYXBwbHktY29kZS1jaGFuZ2VcXG5cXG5FbnN1cmUgcmVzcG9uc2VzIGluY2x1ZGUgYWN0aW9uYWJsZSBzdGVwcyBmb3IgdGhlIGNsaWVudC5gLFxuICAgIH0pXG4gICk7XG5cbiAgcmV0dXJuIFsuLi5maWxlQmFzZWRQcm9tcHRzLCAuLi5pbnRlZ3JhdGlvblByb21wdHNdO1xufVxuXG5mdW5jdGlvbiBzdW1tYXJpemVQcm9tcHRDb250ZW50KFxuICBwcm9tcHQ6IERvY1Byb21wdCxcbiAgaGVhZGluZ1ByZWZpeDogc3RyaW5nXG4pOiBzdHJpbmcge1xuICByZXR1cm4gW2AjIyAke2hlYWRpbmdQcmVmaXh9YCwgXCJcIiwgcHJvbXB0LmNvbnRlbnQudHJpbSgpXS5qb2luKFwiXFxuXCIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRPYmplY3RQcm9tcHRzKCk6IElucHV0UHJvbXB0PHVuZGVmaW5lZD5bXSB7XG4gIGNvbnN0IHJvb3QgPSBnZXRXb3Jrc3BhY2VSb290KCk7XG4gIGNvbnN0IGRpc2NvdmVyZWQgPSBkaXNjb3ZlckRvY1Byb21wdHMocm9vdCk7XG4gIGNvbnN0IHByb21wdEJ5TmFtZSA9IG5ldyBNYXA8c3RyaW5nLCBEb2NQcm9tcHQ+KCk7XG4gIGZvciAoY29uc3QgcHJvbXB0IG9mIGRpc2NvdmVyZWQpIHtcbiAgICBwcm9tcHRCeU5hbWUuc2V0KHByb21wdC5uYW1lLCBwcm9tcHQpO1xuICB9XG5cbiAgY29uc3Qgb3V0cHV0czogSW5wdXRQcm9tcHQ8dW5kZWZpbmVkPltdID0gW107XG4gIGZvciAoY29uc3QgW29iamVjdFR5cGUsIGRlcGVuZGVuY2llc10gb2YgT2JqZWN0LmVudHJpZXMoXG4gICAgT0JKRUNUX1BST01QVF9ERVBFTkRFTkNJRVNcbiAgKSkge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gZGVwZW5kZW5jaWVzXG4gICAgICAubWFwKChuYW1lKSA9PiBwcm9tcHRCeU5hbWUuZ2V0KG5hbWUpKVxuICAgICAgLmZpbHRlcigocHJvbXB0KTogcHJvbXB0IGlzIERvY1Byb21wdCA9PiBCb29sZWFuKHByb21wdCkpO1xuICAgIGlmICghZXhpc3RpbmcubGVuZ3RoKSBjb250aW51ZTtcblxuICAgIG91dHB1dHMucHVzaCh7XG4gICAgICBuYW1lOiBgY29kZXgvJHtvYmplY3RUeXBlfWAsXG4gICAgICBkZXNjcmlwdGlvbjogYEd1aWRhbmNlIGRlcml2ZWQgZnJvbSAuY29kZXggcHJvbXB0cyBmb3IgJHtvYmplY3RUeXBlfSB0YXNrcy5gLFxuICAgICAgbG9hZDogYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBzZWN0aW9ucyA9IGV4aXN0aW5nLm1hcCgocHJvbXB0KSA9PlxuICAgICAgICAgIHN1bW1hcml6ZVByb21wdENvbnRlbnQocHJvbXB0LCB0b1RpdGxlQ2FzZShwcm9tcHQubmFtZSkpXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBbYCMgQ29kZXggZ3VpZGFuY2UgZm9yICR7b2JqZWN0VHlwZX1gLCBcIlwiLCAuLi5zZWN0aW9uc10uam9pbihcbiAgICAgICAgICBcIlxcblwiXG4gICAgICAgICk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIG91dHB1dHMuc29ydCgoYSwgYikgPT4gYS5uYW1lLmxvY2FsZUNvbXBhcmUoYi5uYW1lKSk7XG59XG5cbmZ1bmN0aW9uIHRvSW5wdXRQcm9tcHQoYXNzZXQ6IFByb21wdEFzc2V0KTogSW5wdXRQcm9tcHQ8dW5kZWZpbmVkPiB7XG4gIGNvbnN0IHByb3ZlbmFuY2UgPSBhc3NldC5wcm92ZW5hbmNlID8gYCAobW9kdWxlOiAke2Fzc2V0LnByb3ZlbmFuY2V9KWAgOiBcIlwiO1xuICByZXR1cm4ge1xuICAgIG5hbWU6IGFzc2V0LmlkLFxuICAgIGRlc2NyaXB0aW9uOiBgJHthc3NldC5kZXNjcmlwdGlvbiA/PyBhc3NldC50aXRsZX0ke3Byb3ZlbmFuY2V9YCxcbiAgICBsb2FkOiBhc3luYyAoKSA9PiBhc3NldC5sb2FkKCksXG4gIH07XG59XG5cbmZ1bmN0aW9uIGJ1aWxkTW9kdWxlUHJvbXB0cygpOiBJbnB1dFByb21wdDx1bmRlZmluZWQ+W10ge1xuICBjb25zdCBwa2dzID0gZ2V0UmVnaXN0ZXJlZE1vZHVsZVBhY2thZ2VzKCk7XG4gIGNvbnN0IGFzc2V0czogUHJvbXB0QXNzZXRbXSA9IHBrZ3MuZmxhdE1hcCgocDogYW55KSA9PiBwLnByb21wdHMgPz8gW10pO1xuICByZXR1cm4gYXNzZXRzLm1hcCh0b0lucHV0UHJvbXB0KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlZnJlc2hQcm9tcHRzKHJlcG9QYXRoPzogc3RyaW5nKTogSW5wdXRQcm9tcHQ8dW5kZWZpbmVkPltdIHtcbiAgY29uc3QgZG9jUHJvbXB0cyA9IGJ1aWxkRG9jUHJvbXB0cygpO1xuICBjb25zdCBvYmplY3RQcm9tcHRzID0gYnVpbGRPYmplY3RQcm9tcHRzKCk7XG4gIGNvbnN0IHJlcG9Qcm9tcHRzID0gcmVwb1BhdGggPyBidWlsZFByb21wdHMocmVwb1BhdGgpIDogW107XG4gIGNvbnN0IG1vZHVsZVByb21wdHMgPSBidWlsZE1vZHVsZVByb21wdHMoKTtcbiAgcHJvbXB0cy5zcGxpY2UoXG4gICAgMCxcbiAgICBwcm9tcHRzLmxlbmd0aCxcbiAgICAuLi5kb2NQcm9tcHRzLFxuICAgIC4uLm9iamVjdFByb21wdHMsXG4gICAgLi4ucmVwb1Byb21wdHMsXG4gICAgLi4ubW9kdWxlUHJvbXB0c1xuICApO1xuICByZXR1cm4gcHJvbXB0cztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRpc2NvdmVyRG9jUHJvbXB0cyhyb290OiBzdHJpbmcpOiBEb2NQcm9tcHRbXSB7XG4gIGNvbnN0IGRpc2NvdmVyZWQ6IERvY1Byb21wdFtdID0gW107XG5cbiAgZm9yIChjb25zdCBkaXJlY3Rvcnkgb2YgUFJPTVBUX0RJUkVDVE9SSUVTKSB7XG4gICAgY29uc3QgcHJvbXB0RGlyID0gcGF0aC5qb2luKHJvb3QsIGRpcmVjdG9yeSk7XG4gICAgLy8gZGVidWcgbG9nZ2luZyB0byBoZWxwIHRlc3RzIGRpYWdub3NlIHByb21wdCBkaXNjb3ZlcnlcblxuICAgIGNvbnNvbGUuZGVidWcoXCJbZGlzY292ZXJEb2NQcm9tcHRzXSBjaGVja2luZ1wiLCBwcm9tcHREaXIpO1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhwcm9tcHREaXIpIHx8ICFmcy5zdGF0U3luYyhwcm9tcHREaXIpLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgZW50cnkgb2YgZnMucmVhZGRpclN5bmMocHJvbXB0RGlyKSkge1xuICAgICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4ocHJvbXB0RGlyLCBlbnRyeSk7XG4gICAgICBpZiAoIWZzLnN0YXRTeW5jKGZ1bGxQYXRoKS5pc0ZpbGUoKSkgY29udGludWU7XG5cbiAgICAgIGNvbnN0IG5hbWUgPSBwYXRoLnBhcnNlKGVudHJ5KS5uYW1lO1xuICAgICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhmdWxsUGF0aCwgXCJ1dGY4XCIpO1xuICAgICAgY29uc3QgdGl0bGUgPSB0b1RpdGxlQ2FzZShuYW1lLnJlcGxhY2UoL1stX10vZywgXCIgXCIpKTtcbiAgICAgIGNvbnN0IGRlc2NyaXB0aW9uID0gZXh0cmFjdERlc2NyaXB0aW9uKGNvbnRlbnQsIGZ1bGxQYXRoKTtcblxuICAgICAgZGlzY292ZXJlZC5wdXNoKHtcbiAgICAgICAgbmFtZSxcbiAgICAgICAgdGl0bGUsXG4gICAgICAgIGRlc2NyaXB0aW9uLFxuICAgICAgICBjb250ZW50LFxuICAgICAgICBhYnNvbHV0ZVBhdGg6IGZ1bGxQYXRoLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgdW5pcXVlID0gbmV3IE1hcDxzdHJpbmcsIERvY1Byb21wdD4oKTtcbiAgZm9yIChjb25zdCBwcm9tcHQgb2YgZGlzY292ZXJlZCkge1xuICAgIGlmICghdW5pcXVlLmhhcyhwcm9tcHQubmFtZSkpIHtcbiAgICAgIHVuaXF1ZS5zZXQocHJvbXB0Lm5hbWUsIHByb21wdCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEFycmF5LmZyb20odW5pcXVlLnZhbHVlcygpKS5zb3J0KChhLCBiKSA9PlxuICAgIGEubmFtZS5sb2NhbGVDb21wYXJlKGIubmFtZSlcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNlbGVjdFByb21wdChcbiAgcHJvbXB0TGlzdDogRG9jUHJvbXB0W10sXG4gIHJlcXVlc3RlZE5hbWU6IHN0cmluZ1xuKTogRG9jUHJvbXB0IHtcbiAgY29uc3QgZGlyZWN0ID0gcHJvbXB0TGlzdC5maW5kKChwcm9tcHQpID0+IHByb21wdC5uYW1lID09PSByZXF1ZXN0ZWROYW1lKTtcbiAgaWYgKGRpcmVjdCkgcmV0dXJuIGRpcmVjdDtcblxuICBjb25zdCBmYWxsYmFjayA9IHByb21wdExpc3QuZmluZChcbiAgICAocHJvbXB0KSA9PiBwcm9tcHQubmFtZSA9PT0gREVGQVVMVF9QUk9NUFRfTkFNRVxuICApO1xuICBpZiAoZmFsbGJhY2spIHJldHVybiBmYWxsYmFjaztcblxuICBpZiAoIXByb21wdExpc3QubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gZG9jdW1lbnRhdGlvbiBwcm9tcHRzIGF2YWlsYWJsZVwiKTtcbiAgfVxuXG4gIHJldHVybiBwcm9tcHRMaXN0WzBdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGREb2N1bWVudGF0aW9uUGF5bG9hZCh7XG4gIGZpbGVQYXRoLFxuICBmaWxlQ29udGVudCxcbiAgcHJvbXB0LFxuICBpbmNsdWRlUHJvbXB0LFxuICBpbmNsdWRlQ29kZSxcbiAgaW5jbHVkZU1ldGFkYXRhLFxuICBhZGRpdGlvbmFsQ29udGV4dCxcbn06IHtcbiAgZmlsZVBhdGg6IHN0cmluZztcbiAgZmlsZUNvbnRlbnQ6IHN0cmluZztcbiAgcHJvbXB0OiBEb2NQcm9tcHQ7XG4gIGluY2x1ZGVQcm9tcHQ6IGJvb2xlYW47XG4gIGluY2x1ZGVDb2RlOiBib29sZWFuO1xuICBpbmNsdWRlTWV0YWRhdGE6IGJvb2xlYW47XG4gIGFkZGl0aW9uYWxDb250ZXh0Pzogc3RyaW5nO1xufSk6IENvbnRlbnRSZXN1bHQge1xuICBjb25zdCBzZWN0aW9uczogc3RyaW5nW10gPSBbXTtcblxuICBpZiAoaW5jbHVkZU1ldGFkYXRhKSB7XG4gICAgc2VjdGlvbnMucHVzaChcbiAgICAgIGAjIERvY3VtZW50YXRpb24gUmVxdWVzdFxcbi0gcHJvbXB0OiAke3Byb21wdC5uYW1lfVxcbi0gZmlsZTogJHtmaWxlUGF0aH1gXG4gICAgKTtcbiAgfVxuXG4gIGlmIChpbmNsdWRlUHJvbXB0KSB7XG4gICAgc2VjdGlvbnMucHVzaChcbiAgICAgIGAjIyBQcm9tcHQgR3VpZGFuY2UgKCR7cHJvbXB0LnRpdGxlfSlcXG5cXG4ke3Byb21wdC5jb250ZW50LnRyaW0oKX1gXG4gICAgKTtcbiAgfVxuXG4gIGlmIChhZGRpdGlvbmFsQ29udGV4dD8udHJpbSgpKSB7XG4gICAgc2VjdGlvbnMucHVzaChgIyMgQWRkaXRpb25hbCBDb250ZXh0XFxuXFxuJHthZGRpdGlvbmFsQ29udGV4dC50cmltKCl9YCk7XG4gIH1cblxuICBpZiAoaW5jbHVkZUNvZGUpIHtcbiAgICBzZWN0aW9ucy5wdXNoKFxuICAgICAgYCMjIFNvdXJjZVxcblxcblxcYFxcYFxcYCR7aW5mZXJMYW5ndWFnZUZyb21QYXRoKGZpbGVQYXRoKX1cXG4ke2ZpbGVDb250ZW50fVxcblxcYFxcYFxcYGBcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBjb250ZW50OiBbXG4gICAgICB7XG4gICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICB0ZXh0OiBzZWN0aW9ucy5qb2luKFwiXFxuXFxuXCIpLFxuICAgICAgfSxcbiAgICBdLFxuICB9IHNhdGlzZmllcyBDb250ZW50UmVzdWx0O1xufVxuXG5mdW5jdGlvbiBleHRyYWN0RGVzY3JpcHRpb24oY29udGVudDogc3RyaW5nLCBmaWxlUGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgZmlyc3RMaW5lID0gY29udGVudFxuICAgIC5zcGxpdCgvXFxyP1xcbi8pXG4gICAgLm1hcCgobGluZSkgPT4gbGluZS50cmltKCkpXG4gICAgLmZpbmQoKGxpbmUpID0+IGxpbmUubGVuZ3RoID4gMCk7XG5cbiAgcmV0dXJuIChcbiAgICBmaXJzdExpbmU/LnNsaWNlKDAsIDI0MCkgPz9cbiAgICBgRG9jdW1lbnRhdGlvbiBwcm9tcHQgbG9hZGVkIGZyb20gJHtwYXRoLmJhc2VuYW1lKGZpbGVQYXRoKX1gXG4gICk7XG59XG5cbmZ1bmN0aW9uIHRvVGl0bGVDYXNlKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gdmFsdWVcbiAgICAuc3BsaXQoL1xccysvKVxuICAgIC5maWx0ZXIoQm9vbGVhbilcbiAgICAubWFwKChwYXJ0KSA9PiBwYXJ0LmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgcGFydC5zbGljZSgxKS50b0xvd2VyQ2FzZSgpKVxuICAgIC5qb2luKFwiIFwiKTtcbn1cblxuZnVuY3Rpb24gaW5mZXJMYW5ndWFnZUZyb21QYXRoKGZpbGVQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBleHRlbnNpb24gPSBwYXRoLmV4dG5hbWUoZmlsZVBhdGgpLnRvTG93ZXJDYXNlKCk7XG4gIHN3aXRjaCAoZXh0ZW5zaW9uKSB7XG4gICAgY2FzZSBcIi50c1wiOlxuICAgIGNhc2UgXCIudHN4XCI6XG4gICAgICByZXR1cm4gXCJ0c1wiO1xuICAgIGNhc2UgXCIuanNcIjpcbiAgICBjYXNlIFwiLmpzeFwiOlxuICAgICAgcmV0dXJuIFwianNcIjtcbiAgICBjYXNlIFwiLmpzb25cIjpcbiAgICAgIHJldHVybiBcImpzb25cIjtcbiAgICBjYXNlIFwiLm1kXCI6XG4gICAgICByZXR1cm4gXCJtZFwiO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gXCJ0ZXh0XCI7XG4gIH1cbn1cblxuZXhwb3J0IHsgREVGQVVMVF9QUk9NUFRfTkFNRSB9O1xuZXhwb3J0IHR5cGUgeyBEb2NQcm9tcHQgfTtcbiIsImV4cG9ydCAqIGZyb20gXCIuL3Byb21wdHNcIjtcbmltcG9ydCB7IElucHV0UHJvbXB0IH0gZnJvbSBcImZhc3RtY3BcIjtcbmltcG9ydCB7IHByb21wdHMsIHJlZnJlc2hQcm9tcHRzIH0gZnJvbSBcIi4vcHJvbXB0c1wiO1xuXG5leHBvcnQgY29uc3QgcHJvbXB0TGlzdDogSW5wdXRQcm9tcHQ8dW5kZWZpbmVkPltdID0gcHJvbXB0cztcblxuZXhwb3J0IGZ1bmN0aW9uIGxvYWRQcm9tcHRzKHJlcG9QYXRoPzogc3RyaW5nKTogSW5wdXRQcm9tcHQ8dW5kZWZpbmVkPltdIHtcbiAgcmV0dXJuIHJlZnJlc2hQcm9tcHRzKHJlcG9QYXRoKTtcbn1cbiIsImltcG9ydCB0eXBlIHtcbiAgTW9kdWxlRXhwb3J0UGFja2FnZSxcbiAgUHJvbXB0QXNzZXQsXG4gIFJlc291cmNlQXNzZXQsXG4gIFRlbXBsYXRlQXNzZXQsXG4gIFRvb2xBc3NldCxcbn0gZnJvbSBcIi4uL3R5cGVzXCI7XG5cbnR5cGUgQXNzZXRLZXkgPSBcInByb21wdHNcIiB8IFwicmVzb3VyY2VzXCIgfCBcInRlbXBsYXRlc1wiIHwgXCJ0b29sc1wiO1xuXG5leHBvcnQgY2xhc3MgTW9kdWxlUmVnaXN0cnkge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHBhY2thZ2VzOiBNb2R1bGVFeHBvcnRQYWNrYWdlW10gPSBbXSkge31cblxuICBzZXRQYWNrYWdlcyhwa2dzOiBNb2R1bGVFeHBvcnRQYWNrYWdlW10pIHtcbiAgICB0aGlzLnBhY2thZ2VzID0gQXJyYXkuaXNBcnJheShwa2dzKSA/IHBrZ3MgOiBbXTtcbiAgfVxuXG4gIGxpc3RQYWNrYWdlcygpOiBNb2R1bGVFeHBvcnRQYWNrYWdlW10ge1xuICAgIHJldHVybiB0aGlzLnBhY2thZ2VzO1xuICB9XG5cbiAgbGlzdFByb21wdHMoKTogUHJvbXB0QXNzZXRbXSB7XG4gICAgcmV0dXJuIHRoaXMuY29sbGVjdEFzc2V0cyhcInByb21wdHNcIik7XG4gIH1cblxuICBsaXN0UmVzb3VyY2VzKCk6IFJlc291cmNlQXNzZXRbXSB7XG4gICAgcmV0dXJuIHRoaXMuY29sbGVjdEFzc2V0cyhcInJlc291cmNlc1wiKTtcbiAgfVxuXG4gIGxpc3RUZW1wbGF0ZXMoKTogVGVtcGxhdGVBc3NldFtdIHtcbiAgICByZXR1cm4gdGhpcy5jb2xsZWN0QXNzZXRzKFwidGVtcGxhdGVzXCIpO1xuICB9XG5cbiAgbGlzdFRvb2xzKCk6IFRvb2xBc3NldFtdIHtcbiAgICByZXR1cm4gdGhpcy5jb2xsZWN0QXNzZXRzKFwidG9vbHNcIik7XG4gIH1cblxuICBwcml2YXRlIGNvbGxlY3RBc3NldHM8XG4gICAgVCBleHRlbmRzIFByb21wdEFzc2V0IHwgUmVzb3VyY2VBc3NldCB8IFRlbXBsYXRlQXNzZXQgfCBUb29sQXNzZXQsXG4gID4oa2V5OiBBc3NldEtleSk6IFRbXSB7XG4gICAgY29uc3Qgc2VlbiA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gICAgY29uc3QgYWdncmVnYXRlZDogVFtdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IHBrZyBvZiB0aGlzLnBhY2thZ2VzKSB7XG4gICAgICBpZiAocGtnLnN0YXR1cyA9PT0gXCJkaXNhYmxlZFwiKSBjb250aW51ZTtcbiAgICAgIGZvciAoY29uc3QgYXNzZXQgb2YgKHBrZyBhcyBhbnkpW2tleV0gYXMgVFtdKSB7XG4gICAgICAgIGNvbnN0IG1heWJlTmFtZSA9IChhc3NldCBhcyBhbnkpLm5hbWUgYXMgc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBhc3NldEtleSA9XG4gICAgICAgICAgKGFzc2V0ICYmIChhc3NldC5pZCA/PyBtYXliZU5hbWUpKSB8fCBKU09OLnN0cmluZ2lmeShhc3NldCk7XG4gICAgICAgIGlmIChzZWVuLmhhcyhhc3NldEtleSkpIHtcbiAgICAgICAgICBjb25zdCBjb25mbGljdCA9IHNlZW4uZ2V0KGFzc2V0S2V5KTtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgRHVwbGljYXRlICR7a2V5fSBpZCAnJHthc3NldEtleX0nIGZyb20gbW9kdWxlcyAke2NvbmZsaWN0fSBhbmQgJHtwa2cubmFtZX1gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBzZWVuLnNldChhc3NldEtleSwgcGtnLm5hbWUpO1xuICAgICAgICBhZ2dyZWdhdGVkLnB1c2goeyAuLi5hc3NldCwgcHJvdmVuYW5jZTogcGtnLm5hbWUgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGFnZ3JlZ2F0ZWQ7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IG1vZHVsZVJlZ2lzdHJ5ID0gbmV3IE1vZHVsZVJlZ2lzdHJ5KCk7XG5cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3Rlck1vZHVsZVBhY2thZ2VzKHBrZ3M6IE1vZHVsZUV4cG9ydFBhY2thZ2VbXSkge1xuICBtb2R1bGVSZWdpc3RyeS5zZXRQYWNrYWdlcyhwa2dzKTtcbn1cbiIsImltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5cbmV4cG9ydCBjb25zdCBhbmFseXplUmVwb1NjaGVtYSA9IHpcbiAgLm9iamVjdCh7XG4gICAgcmVwb1BhdGg6IHpcbiAgICAgIC5zdHJpbmcoKVxuICAgICAgLm1pbigxLCBcInJlcG9QYXRoIGlzIHJlcXVpcmVkXCIpXG4gICAgICAuZGVzY3JpYmUoXG4gICAgICAgIFwiUmVsYXRpdmUgb3IgYWJzb2x1dGUgcGF0aCB0byB0aGUgdGFyZ2V0IHJlcG9zaXRvcnkgaW5zaWRlIHRoaXMgbW9ub3JlcG8sIGUuZy4gJy4vZGVjb3JhdGlvbicuXCJcbiAgICAgICksXG4gICAgaW5jbHVkZVRlc3RzOiB6XG4gICAgICAuYm9vbGVhbigpXG4gICAgICAuZGVmYXVsdCh0cnVlKVxuICAgICAgLmRlc2NyaWJlKFxuICAgICAgICBcIklmIHRydWUsIGFuYWx5emUgdGhlIHRlc3RzIGRpcmVjdG9yeSAoaWYgcHJlc2VudCkgdG8gZGVyaXZlIGV4cGVjdGVkIGJlaGF2aW9ycy5cIlxuICAgICAgKSxcbiAgICBpbmNsdWRlRG9jczogelxuICAgICAgLmJvb2xlYW4oKVxuICAgICAgLmRlZmF1bHQodHJ1ZSlcbiAgICAgIC5kZXNjcmliZShcbiAgICAgICAgXCJJZiB0cnVlLCBhbmFseXplIFJFQURNRS5tZCBhbmQgZG9jcyBkaXJlY3RvcmllcyB0byBleHRyYWN0IGRvY3VtZW50ZWQgZmVhdHVyZXMuXCJcbiAgICAgICksXG4gIH0pXG4gIC5zdHJpY3QoKVxuICAuZGVzY3JpYmUoXG4gICAgXCJBbmFseXplIGEgbG9jYWwgcmVwb3NpdG9yeSAoZS5nLiAuL2RlY29yYXRpb24pIHRvIGV4dHJhY3QgQVBJcywgZmVhdHVyZXMsIHRlc3RzLCBhbmQgZG9jdW1lbnRhdGlvbiBjdWVzLlwiXG4gICk7XG5cbmV4cG9ydCBjb25zdCBlbnVtZXJhdGVDYXBhYmlsaXRpZXNTY2hlbWEgPSB6XG4gIC5vYmplY3Qoe1xuICAgIHJlcG9QYXRoOiB6XG4gICAgICAuc3RyaW5nKClcbiAgICAgIC5taW4oMSwgXCJyZXBvUGF0aCBpcyByZXF1aXJlZFwiKVxuICAgICAgLmRlc2NyaWJlKFxuICAgICAgICBcIlJlbGF0aXZlIG9yIGFic29sdXRlIHBhdGggdG8gdGhlIHRhcmdldCByZXBvc2l0b3J5IHRvIGVudW1lcmF0ZSBkZXZlbG9wZXItZmFjaW5nIGNhcGFiaWxpdGllcy5cIlxuICAgICAgKSxcbiAgfSlcbiAgLnN0cmljdCgpXG4gIC5kZXNjcmliZShcbiAgICBcIkVudW1lcmF0ZSB0aGUgY29tcGxldGUgc2V0IG9mIGNhcGFiaWxpdGllcyBhIGRldmVsb3BlciBpcyBleHBlY3RlZCB0byB1c2UgZnJvbSB0aGUgZ2l2ZW4gcmVwb3NpdG9yeS5cIlxuICApO1xuXG5leHBvcnQgY29uc3QgcGxhbkZlYXR1cmVTY2hlbWEgPSB6XG4gIC5vYmplY3Qoe1xuICAgIGZlYXR1cmU6IHpcbiAgICAgIC5zdHJpbmcoKVxuICAgICAgLm1pbig1LCBcImZlYXR1cmUgbXVzdCBkZXNjcmliZSB0aGUgZ29hbCBjbGVhcmx5XCIpXG4gICAgICAuZGVzY3JpYmUoXG4gICAgICAgIFwiTmF0dXJhbC1sYW5ndWFnZSBkZXNjcmlwdGlvbiBvZiBhIGRldmVsb3BlcidzIHJlcXVlc3RlZCBmZWF0dXJlIG9yIHRhc2sgdG8gaW1wbGVtZW50IHVzaW5nIHRoZSByZXBvc2l0b3J5IGFuZCBhdmFpbGFibGUgTUNQIHRvb2xzLlwiXG4gICAgICApLFxuICAgIHJlcG9QYXRoOiB6XG4gICAgICAuc3RyaW5nKClcbiAgICAgIC5kZWZhdWx0KFwiLi9kZWNvcmF0aW9uXCIpXG4gICAgICAuZGVzY3JpYmUoXG4gICAgICAgIFwiVGFyZ2V0IHJlcG9zaXRvcnkgcGF0aCBwcm92aWRpbmcgdGhlIGxpYnJhcnkgdG8gdXNlLCBlLmcuICcuL2RlY29yYXRpb24nLlwiXG4gICAgICApLFxuICB9KVxuICAuc3RyaWN0KClcbiAgLmRlc2NyaWJlKFxuICAgIFwiUGxhbiB3aGljaCBNQ1AgdG9vbHMgdG8gdXNlIGFuZCBpbiB3aGF0IHNlcXVlbmNlIHRvIGltcGxlbWVudCBhIHJlcXVlc3RlZCBmZWF0dXJlIHVzaW5nIHRoZSByZXBvc2l0b3J5LlwiXG4gICk7XG5cbmV4cG9ydCBjb25zdCBkb2N1bWVudENvZGVTY2hlbWEgPSB6XG4gIC5vYmplY3Qoe1xuICAgIGZpbGVQYXRoOiB6LnN0cmluZygpLm1pbigxLCBcImZpbGVQYXRoIGlzIHJlcXVpcmVkXCIpLFxuICAgIHByb21wdE5hbWU6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgICBpbmNsdWRlUHJvbXB0OiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuICAgIGluY2x1ZGVDb2RlOiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuICAgIGluY2x1ZGVNZXRhZGF0YTogei5ib29sZWFuKCkuZGVmYXVsdCh0cnVlKSxcbiAgICBhZGRpdGlvbmFsQ29udGV4dDogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICAgIGVuY29kaW5nOiB6LnN0cmluZygpLmRlZmF1bHQoXCJ1dGY4XCIpLFxuICB9KVxuICAuc3RyaWN0KCk7XG5cbmV4cG9ydCBjb25zdCBjb2RlQ2hhbmdlU2NoZW1hID0gelxuICAub2JqZWN0KHtcbiAgICBmaWxlUGF0aDogei5zdHJpbmcoKS5taW4oMSwgXCJmaWxlUGF0aCBpcyByZXF1aXJlZFwiKSxcbiAgICBwYXRjaDogei5zdHJpbmcoKS5taW4oMSwgXCJwYXRjaCBpcyByZXF1aXJlZFwiKSxcbiAgICBkcnlSdW46IHouYm9vbGVhbigpLmRlZmF1bHQoZmFsc2UpLFxuICAgIHNob3dEaWZmOiB6LmJvb2xlYW4oKS5kZWZhdWx0KHRydWUpLFxuICAgIGRpZmZDb250ZXh0OiB6Lm51bWJlcigpLmludCgpLm1pbigwKS5tYXgoMTAwKS5kZWZhdWx0KDMpLFxuICAgIGVuY29kaW5nOiB6LnN0cmluZygpLmRlZmF1bHQoXCJ1dGY4XCIpLFxuICB9KVxuICAuc3RyaWN0KCk7XG5cbmNvbnN0IE9CSkVDVF9UWVBFUyA9IFtcbiAgXCJtb2R1bGVcIixcbiAgXCJmaWxlXCIsXG4gIFwiY2xhc3NcIixcbiAgXCJmdW5jdGlvblwiLFxuICBcImludGVyZmFjZVwiLFxuICBcImRlY29yYXRvclwiLFxuICBcImNvbnN0YW50XCIsXG5dIGFzIGNvbnN0O1xuXG5leHBvcnQgY29uc3QgZG9jdW1lbnRPYmplY3RTY2hlbWEgPSB6XG4gIC5vYmplY3Qoe1xuICAgIGJhc2VQYXRoOiB6LnN0cmluZygpLm1pbigxLCBcImJhc2VQYXRoIGlzIHJlcXVpcmVkXCIpLFxuICAgIG9iamVjdFR5cGU6IHouZW51bShPQkpFQ1RfVFlQRVMpLFxuICAgIHRhcmdldEZpbGU6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgICBpbmNsdWRlQ29udGVudDogei5ib29sZWFuKCkuZGVmYXVsdChmYWxzZSksXG4gIH0pXG4gIC5zdHJpY3QoKTtcblxuZXhwb3J0IGNvbnN0IGNvdmVyYWdlVGFza1NjaGVtYSA9IHpcbiAgLm9iamVjdCh7XG4gICAgYmFzZVBhdGg6IHouc3RyaW5nKCkubWluKDEsIFwiYmFzZVBhdGggaXMgcmVxdWlyZWRcIiksXG4gICAgY292ZXJhZ2U6IHpcbiAgICAgIC5udW1iZXIoKVxuICAgICAgLm1pbigwKVxuICAgICAgLm1heCgxMDApXG4gICAgICAuZGVmYXVsdCg5MClcbiAgICAgIC5kZXNjcmliZShcIlRhcmdldCBjb3ZlcmFnZSBwZXJjZW50YWdlXCIpLFxuICAgIGRyeVJ1bjogei5ib29sZWFuKCkuZGVmYXVsdChmYWxzZSksXG4gIH0pXG4gIC5zdHJpY3QoKTtcblxuZXhwb3J0IGNvbnN0IHJlYWRtZUltcHJvdmVtZW50U2NoZW1hID0gelxuICAub2JqZWN0KHtcbiAgICBiYXNlUGF0aDogei5zdHJpbmcoKS5taW4oMSwgXCJiYXNlUGF0aCBpcyByZXF1aXJlZFwiKSxcbiAgICBpbmNsdWRlRXhhbXBsZXM6IHouYm9vbGVhbigpLmRlZmF1bHQodHJ1ZSksXG4gIH0pXG4gIC5zdHJpY3QoKTtcbiIsImltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkRmlsZVNhZmUoXG4gIGZpbGVQYXRoOiBzdHJpbmcsXG4gIGVuY29kaW5nOiBCdWZmZXJFbmNvZGluZyA9IFwidXRmOFwiXG4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICB0cnkge1xuICAgIHJldHVybiBmcy5yZWFkRmlsZVN5bmMoZmlsZVBhdGgsIHsgZW5jb2RpbmcgfSk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RGaWxlc1JlY3Vyc2l2ZShcbiAgcm9vdDogc3RyaW5nLFxuICBtYXRjaGVyPzogKHA6IHN0cmluZykgPT4gYm9vbGVhblxuKTogc3RyaW5nW10ge1xuICBjb25zdCBvdXQ6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IHN0YWNrOiBzdHJpbmdbXSA9IFtyb290XTtcbiAgd2hpbGUgKHN0YWNrLmxlbmd0aCkge1xuICAgIGNvbnN0IGN1ciA9IHN0YWNrLnBvcCgpITtcbiAgICBjb25zdCBzdGF0ID0gZnMuc3RhdFN5bmMoY3VyKTtcbiAgICBpZiAoc3RhdC5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBmb3IgKGNvbnN0IGYgb2YgZnMucmVhZGRpclN5bmMoY3VyKSkgc3RhY2sucHVzaChwYXRoLmpvaW4oY3VyLCBmKSk7XG4gICAgfSBlbHNlIGlmICghbWF0Y2hlciB8fCBtYXRjaGVyKGN1cikpIHtcbiAgICAgIG91dC5wdXNoKGN1cik7XG4gICAgfVxuICB9XG4gIHJldHVybiBvdXQuc29ydCgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVyaXZlQ2FwYWJpbGl0aWVzKGFuYWx5c2lzOiBhbnkpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IGNhcCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAvLyBoZXVyaXN0aWNzOiBpZiBkZWNvcmF0b3JzIGxpa2UgRGVjb3JhdGlvbiwgZmxhdm91cmVkQXMsIGV4dGVuZCwgb3ZlcnJpZGUgYXBwZWFyLCBhZGQgY2FwYWJpbGl0aWVzXG4gIGNvbnN0IGFsbERlY3MgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgZm9yIChjb25zdCBrIG9mIE9iamVjdC5rZXlzKGFuYWx5c2lzLmFwaSkpIHtcbiAgICBmb3IgKGNvbnN0IGQgb2YgYW5hbHlzaXMuYXBpW2tdLmRlY29yYXRvcnMpIGFsbERlY3MuYWRkKGQpO1xuICAgIGZvciAoY29uc3QgZSBvZiBhbmFseXNpcy5hcGlba10uZXhwb3J0cylcbiAgICAgIGlmICgvRGVjb3JhdGlvbnxkZWNvcmF0ZXxCdWlsZGVyfEZsYXZvdXIvaS50ZXN0KGUpKVxuICAgICAgICBjYXAuYWRkKFwidXNlLWRlY29yYXRpb24tYXBpXCIpO1xuICB9XG4gIGlmIChbLi4uYWxsRGVjc10uc29tZSgoZCkgPT4gL292ZXJyaWRlfGV4dGVuZC9pLnRlc3QoZCkpKVxuICAgIGNhcC5hZGQoXCJvdmVycmlkZS1hbmQtZXh0ZW5kLWRlY29yYXRpb25zXCIpO1xuICBpZiAoT2JqZWN0LmtleXMoYW5hbHlzaXMudGVzdHMpLmxlbmd0aCA+IDApIGNhcC5hZGQoXCJ2YWxpZGF0ZS13aXRoLXRlc3RzXCIpO1xuICBpZiAoYW5hbHlzaXMucmVhZG1lKSBjYXAuYWRkKFwiZm9sbG93LXJlYWRtZS1ndWlkZXNcIik7XG4gIHJldHVybiBbLi4uY2FwXS5zb3J0KCk7XG59XG5cbiIsIi8vIEFuYWx5c2lzIGhlbHBlcnMgKG1pbmltYWwgeWV0IGVmZmVjdGl2ZSwgdGV4dC1iYXNlZCB0byBhdm9pZCBoZWF2eSBBU1QgZGVwcylcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgeyBsaXN0RmlsZXNSZWN1cnNpdmUsIHJlYWRGaWxlU2FmZSB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1NvdXJjZUZpbGUocDogc3RyaW5nKSB7XG4gIHJldHVybiAvXFwuKHRzfHRzeHxqc3xqc3gpJC8udGVzdChwKSAmJiAhcC5lbmRzV2l0aChcIi5kLnRzXCIpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGlzVGVzdEZpbGUocDogc3RyaW5nKSB7XG4gIHJldHVybiAvKFxcLnRlc3RcXC58XFwuc3BlY1xcLikvLnRlc3QocCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0RXhwb3J0cyhmaWxlQ29udGVudDogc3RyaW5nKTogc3RyaW5nW10ge1xuICBjb25zdCBuYW1lcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBjb25zdCBleHBvcnRSZSA9XG4gICAgLyhleHBvcnRcXHMrKD86ZGVmYXVsdFxccyspPyg/OmNsYXNzfGZ1bmN0aW9ufGNvbnN0fGxldHx2YXJ8aW50ZXJmYWNlfHR5cGV8ZW51bSlcXHMrKShbQS1aYS16MC05X10rKS9nO1xuICBjb25zdCBuYW1lZFJlID0gL2V4cG9ydFxccypcXHsoW159XSspXFx9L2c7XG4gIGxldCBtOiBSZWdFeHBFeGVjQXJyYXkgfCBudWxsO1xuICB3aGlsZSAoKG0gPSBleHBvcnRSZS5leGVjKGZpbGVDb250ZW50KSkpIG5hbWVzLmFkZChtWzJdKTtcbiAgd2hpbGUgKChtID0gbmFtZWRSZS5leGVjKGZpbGVDb250ZW50KSkpIHtcbiAgICBtWzFdXG4gICAgICAuc3BsaXQoXCIsXCIpXG4gICAgICAubWFwKChzKSA9PiBzLnRyaW0oKS5zcGxpdChcIiBhcyBcIilbMF0udHJpbSgpKVxuICAgICAgLmZvckVhY2goKG4pID0+IHtcbiAgICAgICAgaWYgKG4pIG5hbWVzLmFkZChuKTtcbiAgICAgIH0pO1xuICB9XG4gIHJldHVybiBbLi4ubmFtZXNdLnNvcnQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3REZWNvcmF0b3JzKGZpbGVDb250ZW50OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IGRlY3MgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgY29uc3QgZGVjUmUgPSAvQChbQS1aYS16X11bQS1aYS16MC05X10qKS9nO1xuICBsZXQgbTogUmVnRXhwRXhlY0FycmF5IHwgbnVsbDtcbiAgd2hpbGUgKChtID0gZGVjUmUuZXhlYyhmaWxlQ29udGVudCkpKSBkZWNzLmFkZChtWzFdKTtcbiAgcmV0dXJuIFsuLi5kZWNzXS5zb3J0KCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdW1tYXJpemVSZWFkbWUocmVhZG1lPzogc3RyaW5nKSB7XG4gIGlmICghcmVhZG1lKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCBsaW5lcyA9IHJlYWRtZS5zcGxpdCgvXFxyP1xcbi8pLmZpbHRlcihCb29sZWFuKTtcbiAgY29uc3QgdGl0bGUgPVxuICAgIGxpbmVzLmZpbmQoKGwpID0+IC9eI1xccysvLnRlc3QobCkpPy5yZXBsYWNlKC9eI1xccysvLCBcIlwiKSB8fCBcIlJFQURNRVwiO1xuICBjb25zdCBidWxsZXRzID0gbGluZXMuZmlsdGVyKChsKSA9PiAvXlstKl1cXHMrLy50ZXN0KGwpKS5zbGljZSgwLCAyMCk7XG4gIHJldHVybiB7IHRpdGxlLCBidWxsZXRzIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhbmFseXplUmVwbyhyb290OiBzdHJpbmcpIHtcbiAgY29uc3Qgc3JjID0gcGF0aC5qb2luKHJvb3QsIFwic3JjXCIpO1xuICBjb25zdCB0ZXN0RGlyID0gcGF0aC5qb2luKHJvb3QsIFwidGVzdHNcIik7XG4gIGNvbnN0IHJlYWRtZVBhdGggPSBwYXRoLmpvaW4ocm9vdCwgXCJSRUFETUUubWRcIik7XG4gIGNvbnN0IHJlYWRtZSA9IHJlYWRGaWxlU2FmZShyZWFkbWVQYXRoKTtcblxuICBjb25zdCBmaWxlcyA9IGZzLmV4aXN0c1N5bmMoc3JjKSA/IGxpc3RGaWxlc1JlY3Vyc2l2ZShzcmMsIGlzU291cmNlRmlsZSkgOiBbXTtcbiAgY29uc3QgdGVzdEZpbGVzID0gZnMuZXhpc3RzU3luYyh0ZXN0RGlyKVxuICAgID8gbGlzdEZpbGVzUmVjdXJzaXZlKHRlc3REaXIsIChmKSA9PiBpc1NvdXJjZUZpbGUoZikgJiYgaXNUZXN0RmlsZShmKSlcbiAgICA6IFtdO1xuXG4gIGNvbnN0IGFwaTogUmVjb3JkPHN0cmluZywgeyBleHBvcnRzOiBzdHJpbmdbXTsgZGVjb3JhdG9yczogc3RyaW5nW10gfT4gPSB7fTtcbiAgZm9yIChjb25zdCBmIG9mIGZpbGVzKSB7XG4gICAgY29uc3QgY29udGVudCA9IHJlYWRGaWxlU2FmZShmKSB8fCBcIlwiO1xuICAgIGFwaVtwYXRoLnJlbGF0aXZlKHJvb3QsIGYpXSA9IHtcbiAgICAgIGV4cG9ydHM6IGV4dHJhY3RFeHBvcnRzKGNvbnRlbnQpLFxuICAgICAgZGVjb3JhdG9yczogZXh0cmFjdERlY29yYXRvcnMoY29udGVudCksXG4gICAgfTtcbiAgfVxuICBjb25zdCB0ZXN0czogUmVjb3JkPHN0cmluZywgeyBtZW50aW9uczogc3RyaW5nW10gfT4gPSB7fTtcbiAgZm9yIChjb25zdCBmIG9mIHRlc3RGaWxlcykge1xuICAgIGNvbnN0IGNvbnRlbnQgPSByZWFkRmlsZVNhZmUoZikgfHwgXCJcIjtcbiAgICBjb25zdCBtZW50aW9ucyA9IEFycmF5LmZyb20oXG4gICAgICBuZXcgU2V0KFsuLi5leHRyYWN0RXhwb3J0cyhjb250ZW50KSwgLi4uZXh0cmFjdERlY29yYXRvcnMoY29udGVudCldKVxuICAgICkuc29ydCgpO1xuICAgIHRlc3RzW3BhdGgucmVsYXRpdmUocm9vdCwgZildID0geyBtZW50aW9ucyB9O1xuICB9XG4gIHJldHVybiB7IGZpbGVzLCB0ZXN0RmlsZXMsIGFwaSwgdGVzdHMsIHJlYWRtZTogc3VtbWFyaXplUmVhZG1lKHJlYWRtZSkgfTtcbn1cbiIsImltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBzcGF3blN5bmMgfSBmcm9tIFwiY2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHR5cGUgeyBDb250ZW50UmVzdWx0LCBUb29sIH0gZnJvbSBcImZhc3RtY3BcIjtcbmltcG9ydCB7XG4gIGRvY3VtZW50T2JqZWN0U2NoZW1hLFxuICBjb3ZlcmFnZVRhc2tTY2hlbWEsXG4gIHJlYWRtZUltcHJvdmVtZW50U2NoZW1hLFxufSBmcm9tIFwiLi4vc2NoZW1hc1wiO1xuaW1wb3J0IHtcbiAgRG9jdW1lbnRPYmplY3RBcmdzLFxuICBDb3ZlcmFnZVRhc2tBcmdzLFxuICBSZWFkbWVJbXByb3ZlbWVudEFyZ3MsXG59IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHtcbiAgZ2V0V29ya3NwYWNlUm9vdCxcbiAgcmVzb2x2ZUluV29ya3NwYWNlLFxuICB0aHJvd1VzZXJFcnJvcixcbiAgV29ya3NwYWNlRXJyb3IsXG59IGZyb20gXCIuLi93b3Jrc3BhY2VcIjtcbmltcG9ydCB7XG4gIGRpc2NvdmVyRG9jUHJvbXB0cyxcbiAgZ2V0T2JqZWN0UHJvbXB0RGVwZW5kZW5jaWVzLFxufSBmcm9tIFwiLi4vcHJvbXB0cy9wcm9tcHRzXCI7XG5pbXBvcnQgdHlwZSB7IERvY1Byb21wdCB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgbGlzdEZpbGVzUmVjdXJzaXZlLCByZWFkRmlsZVNhZmUgfSBmcm9tIFwiLi4vdXRpbHNcIjtcbmltcG9ydCB7IGFuYWx5emVSZXBvLCBpc1NvdXJjZUZpbGUsIGlzVGVzdEZpbGUgfSBmcm9tIFwiLi4vY29kZVwiO1xuXG50eXBlIFByb21wdFNlY3Rpb24gPSB7XG4gIG5hbWU6IHN0cmluZztcbiAgdGl0bGU6IHN0cmluZztcbiAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgY29udGVudDogc3RyaW5nO1xuICBhYnNvbHV0ZVBhdGg/OiBzdHJpbmc7XG59O1xuXG5mdW5jdGlvbiByZWxhdGl2ZUZpbGVzKHJvb3Q6IHN0cmluZywgZmlsZXM6IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuICByZXR1cm4gZmlsZXMubWFwKChmaWxlKSA9PiBwYXRoLnJlbGF0aXZlKHJvb3QsIGZpbGUpKS5zb3J0KCk7XG59XG5cbmZ1bmN0aW9uIGNvbGxlY3RQcm9tcHRTZWN0aW9ucyhuYW1lczogcmVhZG9ubHkgc3RyaW5nW10pOiBQcm9tcHRTZWN0aW9uW10ge1xuICBjb25zdCByb290ID0gZ2V0V29ya3NwYWNlUm9vdCgpO1xuICBjb25zdCBwcm9tcHRJbmRleCA9IG5ldyBNYXA8c3RyaW5nLCBEb2NQcm9tcHQ+KFxuICAgIGRpc2NvdmVyRG9jUHJvbXB0cyhyb290KS5tYXAoKHByb21wdCkgPT4gW3Byb21wdC5uYW1lLCBwcm9tcHRdKVxuICApO1xuICByZXR1cm4gbmFtZXNcbiAgICAubWFwKChuYW1lKSA9PiBwcm9tcHRJbmRleC5nZXQobmFtZSkpXG4gICAgLmZpbHRlcigocHJvbXB0KTogcHJvbXB0IGlzIERvY1Byb21wdCA9PiBCb29sZWFuKHByb21wdCkpXG4gICAgLm1hcCgocHJvbXB0KSA9PiAoe1xuICAgICAgbmFtZTogcHJvbXB0Lm5hbWUsXG4gICAgICB0aXRsZTogcHJvbXB0LnRpdGxlLFxuICAgICAgZGVzY3JpcHRpb246IHByb21wdC5kZXNjcmlwdGlvbixcbiAgICAgIGNvbnRlbnQ6IHByb21wdC5jb250ZW50LFxuICAgICAgYWJzb2x1dGVQYXRoOiBwcm9tcHQuYWJzb2x1dGVQYXRoLFxuICAgIH0pKTtcbn1cblxuZnVuY3Rpb24gcGFyc2VUYXNrTGluZXMoY29udGVudDogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gY29udGVudFxuICAgIC5zcGxpdCgvXFxyP1xcbi8pXG4gICAgLm1hcCgobGluZSkgPT4gbGluZS50cmltKCkpXG4gICAgLmZpbHRlcigobGluZSkgPT4gL150YXNrXFxzK1xcZCsvaS50ZXN0KGxpbmUpKTtcbn1cblxuZnVuY3Rpb24gY29tcHV0ZUNvdmVyYWdlRnJvbUZpbmFsKGNvdmVyYWdlUGF0aDogc3RyaW5nKSB7XG4gIGNvbnN0IHBheWxvYWQgPSBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhjb3ZlcmFnZVBhdGgsIFwidXRmOFwiKSkgYXMgUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICB7XG4gICAgICBzOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+O1xuICAgICAgZjogUmVjb3JkPHN0cmluZywgbnVtYmVyPjtcbiAgICAgIGI6IFJlY29yZDxzdHJpbmcsIG51bWJlciB8IG51bWJlcltdPjtcbiAgICB9XG4gID47XG5cbiAgY29uc3QgdG90YWxzID0ge1xuICAgIHN0YXRlbWVudHM6IHsgY292ZXJlZDogMCwgdG90YWw6IDAgfSxcbiAgICBmdW5jdGlvbnM6IHsgY292ZXJlZDogMCwgdG90YWw6IDAgfSxcbiAgICBicmFuY2hlczogeyBjb3ZlcmVkOiAwLCB0b3RhbDogMCB9LFxuICB9O1xuXG4gIGNvbnN0IGZpbGVzID0gT2JqZWN0LmVudHJpZXMocGF5bG9hZCkubWFwKChbZmlsZVBhdGgsIGluZm9dKSA9PiB7XG4gICAgY29uc3Qgc3RhdGVtZW50Q291bnRzID0gT2JqZWN0LnZhbHVlcyhpbmZvLnMpO1xuICAgIGNvbnN0IGZ1bmN0aW9uQ291bnRzID0gT2JqZWN0LnZhbHVlcyhpbmZvLmYpO1xuICAgIGNvbnN0IGJyYW5jaENvdW50cyA9IE9iamVjdC52YWx1ZXMoaW5mby5iKS5mbGF0TWFwKCh2YWx1ZSkgPT5cbiAgICAgIEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbdmFsdWVdXG4gICAgKTtcblxuICAgIGNvbnN0IHN0YXRlbWVudFRvdGFsID0gc3RhdGVtZW50Q291bnRzLmxlbmd0aDtcbiAgICBjb25zdCBmdW5jdGlvblRvdGFsID0gZnVuY3Rpb25Db3VudHMubGVuZ3RoO1xuICAgIGNvbnN0IGJyYW5jaFRvdGFsID0gYnJhbmNoQ291bnRzLmxlbmd0aDtcblxuICAgIGNvbnN0IHN0YXRlbWVudENvdmVyZWQgPSBzdGF0ZW1lbnRDb3VudHMuZmlsdGVyKFxuICAgICAgKGNvdW50KSA9PiBjb3VudCA+IDBcbiAgICApLmxlbmd0aDtcbiAgICBjb25zdCBmdW5jdGlvbkNvdmVyZWQgPSBmdW5jdGlvbkNvdW50cy5maWx0ZXIoKGNvdW50KSA9PiBjb3VudCA+IDApLmxlbmd0aDtcbiAgICBjb25zdCBicmFuY2hDb3ZlcmVkID0gYnJhbmNoQ291bnRzLmZpbHRlcigoY291bnQpID0+IGNvdW50ID4gMCkubGVuZ3RoO1xuXG4gICAgdG90YWxzLnN0YXRlbWVudHMuY292ZXJlZCArPSBzdGF0ZW1lbnRDb3ZlcmVkO1xuICAgIHRvdGFscy5zdGF0ZW1lbnRzLnRvdGFsICs9IHN0YXRlbWVudFRvdGFsO1xuICAgIHRvdGFscy5mdW5jdGlvbnMuY292ZXJlZCArPSBmdW5jdGlvbkNvdmVyZWQ7XG4gICAgdG90YWxzLmZ1bmN0aW9ucy50b3RhbCArPSBmdW5jdGlvblRvdGFsO1xuICAgIHRvdGFscy5icmFuY2hlcy5jb3ZlcmVkICs9IGJyYW5jaENvdmVyZWQ7XG4gICAgdG90YWxzLmJyYW5jaGVzLnRvdGFsICs9IGJyYW5jaFRvdGFsO1xuXG4gICAgY29uc3QgcGN0ID0gKGNvdmVyZWQ6IG51bWJlciwgdG90YWw6IG51bWJlcikgPT5cbiAgICAgIHRvdGFsID09PSAwID8gMTAwIDogTnVtYmVyKCgoY292ZXJlZCAvIHRvdGFsKSAqIDEwMCkudG9GaXhlZCgyKSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGF0aDogZmlsZVBhdGgsXG4gICAgICBzdGF0ZW1lbnRzOiBwY3Qoc3RhdGVtZW50Q292ZXJlZCwgc3RhdGVtZW50VG90YWwpLFxuICAgICAgZnVuY3Rpb25zOiBwY3QoZnVuY3Rpb25Db3ZlcmVkLCBmdW5jdGlvblRvdGFsKSxcbiAgICAgIGJyYW5jaGVzOiBwY3QoYnJhbmNoQ292ZXJlZCwgYnJhbmNoVG90YWwpLFxuICAgIH07XG4gIH0pO1xuXG4gIGNvbnN0IHBjdCA9IChjb3ZlcmVkOiBudW1iZXIsIHRvdGFsOiBudW1iZXIpID0+XG4gICAgdG90YWwgPT09IDAgPyAxMDAgOiBOdW1iZXIoKChjb3ZlcmVkIC8gdG90YWwpICogMTAwKS50b0ZpeGVkKDIpKTtcblxuICByZXR1cm4ge1xuICAgIHRvdGFsczoge1xuICAgICAgc3RhdGVtZW50czoge1xuICAgICAgICAuLi50b3RhbHMuc3RhdGVtZW50cyxcbiAgICAgICAgcGN0OiBwY3QodG90YWxzLnN0YXRlbWVudHMuY292ZXJlZCwgdG90YWxzLnN0YXRlbWVudHMudG90YWwpLFxuICAgICAgfSxcbiAgICAgIGZ1bmN0aW9uczoge1xuICAgICAgICAuLi50b3RhbHMuZnVuY3Rpb25zLFxuICAgICAgICBwY3Q6IHBjdCh0b3RhbHMuZnVuY3Rpb25zLmNvdmVyZWQsIHRvdGFscy5mdW5jdGlvbnMudG90YWwpLFxuICAgICAgfSxcbiAgICAgIGJyYW5jaGVzOiB7XG4gICAgICAgIC4uLnRvdGFscy5icmFuY2hlcyxcbiAgICAgICAgcGN0OiBwY3QodG90YWxzLmJyYW5jaGVzLmNvdmVyZWQsIHRvdGFscy5icmFuY2hlcy50b3RhbCksXG4gICAgICB9LFxuICAgIH0sXG4gICAgZmlsZXMsXG4gIH07XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVByb21wdFNlY3Rpb25zKHNlY3Rpb25zOiBQcm9tcHRTZWN0aW9uW10pIHtcbiAgcmV0dXJuIHNlY3Rpb25zLm1hcCgoc2VjdGlvbikgPT4gKHtcbiAgICBuYW1lOiBzZWN0aW9uLm5hbWUsXG4gICAgdGl0bGU6IHNlY3Rpb24udGl0bGUsXG4gICAgdGFza3M6IHBhcnNlVGFza0xpbmVzKHNlY3Rpb24uY29udGVudCksXG4gICAgY29udGVudDogc2VjdGlvbi5jb250ZW50LFxuICB9KSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVSZXBvUm9vdChiYXNlUGF0aDogc3RyaW5nKSB7XG4gIGNvbnN0IHJvb3QgPSBnZXRXb3Jrc3BhY2VSb290KCk7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHJlc29sdmVJbldvcmtzcGFjZShyb290LCBiYXNlUGF0aCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKGVycm9yIGluc3RhbmNlb2YgV29ya3NwYWNlRXJyb3IpIHtcbiAgICAgIGF3YWl0IHRocm93VXNlckVycm9yKGVycm9yLm1lc3NhZ2UpO1xuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgZG9jdW1lbnRPYmplY3RUb29sOiBUb29sPHVuZGVmaW5lZCwgdHlwZW9mIGRvY3VtZW50T2JqZWN0U2NoZW1hPiA9XG4gIHtcbiAgICBuYW1lOiBcImRvY3VtZW50LW9iamVjdFwiLFxuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgXCJDcmVhdGUgYSBkb2N1bWVudGF0aW9uIHBsYW4gZm9yIGEgc3BlY2lmaWMgb2JqZWN0IHR5cGUgdXNpbmcgLmNvZGV4IHByb21wdHMgYW5kIHJlcG9zaXRvcnkgYW5hbHlzaXMuXCIsXG4gICAgcGFyYW1ldGVyczogZG9jdW1lbnRPYmplY3RTY2hlbWEsXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIGV4ZWN1dGU6IGFzeW5jIChpbnB1dCwgX2NvbnRleHQpOiBQcm9taXNlPENvbnRlbnRSZXN1bHQ+ID0+IHtcbiAgICAgIGNvbnN0IGFyZ3MgPSBkb2N1bWVudE9iamVjdFNjaGVtYS5wYXJzZShpbnB1dCBhcyBEb2N1bWVudE9iamVjdEFyZ3MpO1xuICAgICAgY29uc3QgcmVwb1Jvb3QgPSBhd2FpdCByZXNvbHZlUmVwb1Jvb3QoYXJncy5iYXNlUGF0aCk7XG5cbiAgICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9IGdldE9iamVjdFByb21wdERlcGVuZGVuY2llcygpW2FyZ3Mub2JqZWN0VHlwZV0gPz8gW107XG4gICAgICBpZiAoIWRlcGVuZGVuY2llcy5sZW5ndGgpIHtcbiAgICAgICAgYXdhaXQgdGhyb3dVc2VyRXJyb3IoXG4gICAgICAgICAgYE5vIHByb21wdCBndWlkYW5jZSBjb25maWd1cmVkIGZvciBvYmplY3QgdHlwZSAke2FyZ3Mub2JqZWN0VHlwZX1gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNlY3Rpb25zID0gbm9ybWFsaXplUHJvbXB0U2VjdGlvbnMoXG4gICAgICAgIGNvbGxlY3RQcm9tcHRTZWN0aW9ucyhkZXBlbmRlbmNpZXMpXG4gICAgICApO1xuXG4gICAgICBjb25zdCBzcmNEaXIgPSBwYXRoLmpvaW4ocmVwb1Jvb3QsIFwic3JjXCIpO1xuICAgICAgY29uc3QgdGVzdERpciA9IHBhdGguam9pbihyZXBvUm9vdCwgXCJ0ZXN0c1wiKTtcblxuICAgICAgY29uc3Qgc291cmNlRmlsZXMgPSBmcy5leGlzdHNTeW5jKHNyY0RpcilcbiAgICAgICAgPyBsaXN0RmlsZXNSZWN1cnNpdmUoc3JjRGlyLCBpc1NvdXJjZUZpbGUpXG4gICAgICAgIDogW107XG4gICAgICBjb25zdCB0ZXN0RmlsZXMgPSBmcy5leGlzdHNTeW5jKHRlc3REaXIpXG4gICAgICAgID8gbGlzdEZpbGVzUmVjdXJzaXZlKFxuICAgICAgICAgICAgdGVzdERpcixcbiAgICAgICAgICAgIChmaWxlKSA9PiBpc1NvdXJjZUZpbGUoZmlsZSkgJiYgaXNUZXN0RmlsZShmaWxlKVxuICAgICAgICAgIClcbiAgICAgICAgOiBbXTtcblxuICAgICAgbGV0IHRhcmdldEZpbGVDb250ZW50OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICBpZiAoYXJncy50YXJnZXRGaWxlKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgYWJzb2x1dGUgPSByZXNvbHZlSW5Xb3Jrc3BhY2UocmVwb1Jvb3QsIGFyZ3MudGFyZ2V0RmlsZSk7XG4gICAgICAgICAgdGFyZ2V0RmlsZUNvbnRlbnQgPSByZWFkRmlsZVNhZmUoYWJzb2x1dGUpID8/IHVuZGVmaW5lZDtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBXb3Jrc3BhY2VFcnJvcikge1xuICAgICAgICAgICAgYXdhaXQgdGhyb3dVc2VyRXJyb3IoZXJyb3IubWVzc2FnZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgIGJhc2VQYXRoOiBwYXRoLnJlbGF0aXZlKGdldFdvcmtzcGFjZVJvb3QoKSwgcmVwb1Jvb3QpIHx8IFwiLlwiLFxuICAgICAgICBvYmplY3RUeXBlOiBhcmdzLm9iamVjdFR5cGUsXG4gICAgICAgIHRhcmdldEZpbGU6IGFyZ3MudGFyZ2V0RmlsZSxcbiAgICAgICAgZ3VpZGFuY2U6IHNlY3Rpb25zLFxuICAgICAgICBmaWxlczoge1xuICAgICAgICAgIHNvdXJjZTogcmVsYXRpdmVGaWxlcyhyZXBvUm9vdCwgc291cmNlRmlsZXMpLFxuICAgICAgICAgIHRlc3RzOiByZWxhdGl2ZUZpbGVzKHJlcG9Sb290LCB0ZXN0RmlsZXMpLFxuICAgICAgICB9LFxuICAgICAgICB0YXJnZXRGaWxlQ29udGVudDogYXJncy5pbmNsdWRlQ29udGVudCA/IHRhcmdldEZpbGVDb250ZW50IDogdW5kZWZpbmVkLFxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogSlNPTi5zdHJpbmdpZnkocGF5bG9hZCwgbnVsbCwgMiksXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0gc2F0aXNmaWVzIENvbnRlbnRSZXN1bHQ7XG4gICAgfSxcbiAgfTtcblxuZXhwb3J0IGNvbnN0IGNvdmVyYWdlRW5mb3JjZXJUb29sOiBUb29sPHVuZGVmaW5lZCwgdHlwZW9mIGNvdmVyYWdlVGFza1NjaGVtYT4gPVxuICB7XG4gICAgbmFtZTogXCJlbnN1cmUtdGVzdC1jb3ZlcmFnZVwiLFxuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgXCJSdW4gdGhlIGNvbmZpZ3VyZWQgY292ZXJhZ2UgY29tbWFuZCBhbmQgcmVwb3J0IHdoZXRoZXIgdGhlIHRhcmdldCBwZXJjZW50YWdlIGlzIG1ldCwgaGlnaGxpZ2h0aW5nIHdlYWsgZmlsZXMuXCIsXG4gICAgcGFyYW1ldGVyczogY292ZXJhZ2VUYXNrU2NoZW1hLFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICBleGVjdXRlOiBhc3luYyAoaW5wdXQsIF9jb250ZXh0KTogUHJvbWlzZTxDb250ZW50UmVzdWx0PiA9PiB7XG4gICAgICBjb25zdCBhcmdzID0gY292ZXJhZ2VUYXNrU2NoZW1hLnBhcnNlKGlucHV0IGFzIENvdmVyYWdlVGFza0FyZ3MpO1xuICAgICAgY29uc3QgcmVwb1Jvb3QgPSBhd2FpdCByZXNvbHZlUmVwb1Jvb3QoYXJncy5iYXNlUGF0aCk7XG5cbiAgICAgIGlmICghYXJncy5kcnlSdW4pIHtcbiAgICAgICAgY29uc3QgZW52ID0ge1xuICAgICAgICAgIC4uLnByb2Nlc3MuZW52LFxuICAgICAgICAgIFVTRV9XQVRDSE1BTjogXCJmYWxzZVwiLFxuICAgICAgICAgIFdBVENITUFOX0RJU0FCTEU6IFwiMVwiLFxuICAgICAgICAgIEpFU1RfRElTQUJMRV9XQVRDSE1BTjogXCIxXCIsXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHNwYXduU3luYyhcbiAgICAgICAgICBcIm5wbVwiLFxuICAgICAgICAgIFtcInJ1blwiLCBcImNvdmVyYWdlXCIsIFwiLS1cIiwgXCItLXdhdGNobWFuPWZhbHNlXCIsIFwiLS1ydW5JbkJhbmRcIl0sXG4gICAgICAgICAgeyBjd2Q6IHJlcG9Sb290LCBlbnYsIGVuY29kaW5nOiBcInV0ZjhcIiB9XG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKHJlc3VsdC5zdGF0dXMgIT09IDApIHtcbiAgICAgICAgICBjb25zdCBtZXNzYWdlID1cbiAgICAgICAgICAgIHJlc3VsdC5zdGRlcnIgfHwgcmVzdWx0LnN0ZG91dCB8fCBcIkNvdmVyYWdlIGNvbW1hbmQgZmFpbGVkXCI7XG4gICAgICAgICAgYXdhaXQgdGhyb3dVc2VyRXJyb3IobWVzc2FnZS50cmltKCkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvdmVyYWdlUGF0aCA9IHBhdGguam9pbihcbiAgICAgICAgcmVwb1Jvb3QsXG4gICAgICAgIFwid29ya2RvY3NcIixcbiAgICAgICAgXCJyZXBvcnRzXCIsXG4gICAgICAgIFwiY292ZXJhZ2VcIixcbiAgICAgICAgXCJjb3ZlcmFnZS1maW5hbC5qc29uXCJcbiAgICAgICk7XG5cbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhjb3ZlcmFnZVBhdGgpKSB7XG4gICAgICAgIGF3YWl0IHRocm93VXNlckVycm9yKFxuICAgICAgICAgIGBDb3ZlcmFnZSByZXBvcnQgbm90IGZvdW5kIGF0ICR7cGF0aC5yZWxhdGl2ZShyZXBvUm9vdCwgY292ZXJhZ2VQYXRoKX1gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN1bW1hcnkgPSBjb21wdXRlQ292ZXJhZ2VGcm9tRmluYWwoY292ZXJhZ2VQYXRoKTtcbiAgICAgIGNvbnN0IG1lZXRzVGhyZXNob2xkID1cbiAgICAgICAgc3VtbWFyeS50b3RhbHMuc3RhdGVtZW50cy5wY3QgPj0gYXJncy5jb3ZlcmFnZSAmJlxuICAgICAgICBzdW1tYXJ5LnRvdGFscy5mdW5jdGlvbnMucGN0ID49IGFyZ3MuY292ZXJhZ2UgJiZcbiAgICAgICAgc3VtbWFyeS50b3RhbHMuYnJhbmNoZXMucGN0ID49IGFyZ3MuY292ZXJhZ2U7XG5cbiAgICAgIGNvbnN0IHdlYWtlc3QgPSBbLi4uc3VtbWFyeS5maWxlc11cbiAgICAgICAgLnNvcnQoKGEsIGIpID0+IGEuc3RhdGVtZW50cyAtIGIuc3RhdGVtZW50cylcbiAgICAgICAgLnNsaWNlKDAsIDEwKTtcblxuICAgICAgY29uc3QgZ3VpZGFuY2UgPSBub3JtYWxpemVQcm9tcHRTZWN0aW9ucyhcbiAgICAgICAgY29sbGVjdFByb21wdFNlY3Rpb25zKFtcImJ1bGstdGVzdHNcIl0pXG4gICAgICApO1xuXG4gICAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgICBiYXNlUGF0aDogcGF0aC5yZWxhdGl2ZShnZXRXb3Jrc3BhY2VSb290KCksIHJlcG9Sb290KSB8fCBcIi5cIixcbiAgICAgICAgdGFyZ2V0OiBhcmdzLmNvdmVyYWdlLFxuICAgICAgICBtZWV0c1RocmVzaG9sZCxcbiAgICAgICAgdG90YWxzOiBzdW1tYXJ5LnRvdGFscyxcbiAgICAgICAgd2Vha2VzdCxcbiAgICAgICAgZ3VpZGFuY2UsXG4gICAgICB9O1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgICB0ZXh0OiBKU09OLnN0cmluZ2lmeShwYXlsb2FkLCBudWxsLCAyKSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSBzYXRpc2ZpZXMgQ29udGVudFJlc3VsdDtcbiAgICB9LFxuICB9O1xuXG5leHBvcnQgY29uc3QgcmVhZG1lSW1wcm92ZW1lbnRUb29sOiBUb29sPFxuICB1bmRlZmluZWQsXG4gIHR5cGVvZiByZWFkbWVJbXByb3ZlbWVudFNjaGVtYVxuPiA9IHtcbiAgbmFtZTogXCJpbXByb3ZlLXJlYWRtZVwiLFxuICBkZXNjcmlwdGlvbjpcbiAgICBcIlN1bW1hcml6ZSByZXF1aXJlZCBzdGVwcyB0byByZWZyZXNoIFJFQURNRSBhbmQgd29ya2RvY3MgY29udGVudCB1c2luZyAuY29kZXggZ3VpZGFuY2UgYW5kIHJlcG9zaXRvcnkgYW5hbHlzaXMuXCIsXG4gIHBhcmFtZXRlcnM6IHJlYWRtZUltcHJvdmVtZW50U2NoZW1hLFxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIGV4ZWN1dGU6IGFzeW5jIChpbnB1dCwgX2NvbnRleHQpOiBQcm9taXNlPENvbnRlbnRSZXN1bHQ+ID0+IHtcbiAgICBjb25zdCBhcmdzID0gcmVhZG1lSW1wcm92ZW1lbnRTY2hlbWEucGFyc2UoaW5wdXQgYXMgUmVhZG1lSW1wcm92ZW1lbnRBcmdzKTtcbiAgICBjb25zdCByZXBvUm9vdCA9IGF3YWl0IHJlc29sdmVSZXBvUm9vdChhcmdzLmJhc2VQYXRoKTtcblxuICAgIGNvbnN0IGFuYWx5c2lzID0gYW5hbHl6ZVJlcG8ocmVwb1Jvb3QpO1xuICAgIGNvbnN0IG1vZHVsZXMgPSBhbmFseXNpcy5maWxlc1xuICAgICAgLmZpbHRlcigoZmlsZSkgPT4gL2luZGV4XFwudHMkLy50ZXN0KGZpbGUpKVxuICAgICAgLm1hcCgoZmlsZSkgPT4gcGF0aC5yZWxhdGl2ZShyZXBvUm9vdCwgZmlsZSkpO1xuXG4gICAgY29uc3QgcHJvbXB0U2VjdGlvbnMgPSBub3JtYWxpemVQcm9tcHRTZWN0aW9ucyhcbiAgICAgIGNvbGxlY3RQcm9tcHRTZWN0aW9ucyhbXCJ1cGRhdGUtcmVhZG1lXCIsIFwiZG9jXCIsIFwibW9kdWxlXCJdKVxuICAgICk7XG5cbiAgICBjb25zdCB0ZXN0RXhhbXBsZXMgPSBPYmplY3Qua2V5cyhhbmFseXNpcy50ZXN0cyA/PyB7fSk7XG4gICAgY29uc3QgZXhhbXBsZXMgPSBhcmdzLmluY2x1ZGVFeGFtcGxlcyA/IHRlc3RFeGFtcGxlcy5zbGljZSgwLCAyMCkgOiBbXTtcblxuICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICBiYXNlUGF0aDogcGF0aC5yZWxhdGl2ZShnZXRXb3Jrc3BhY2VSb290KCksIHJlcG9Sb290KSB8fCBcIi5cIixcbiAgICAgIHN1bW1hcnk6IHtcbiAgICAgICAgbW9kdWxlcyxcbiAgICAgICAgdG90YWxTb3VyY2VGaWxlczogYW5hbHlzaXMuZmlsZXMubGVuZ3RoLFxuICAgICAgICB0b3RhbFRlc3RGaWxlczogYW5hbHlzaXMudGVzdEZpbGVzLmxlbmd0aCxcbiAgICAgICAgaGFzUmVhZG1lOiBCb29sZWFuKGFuYWx5c2lzLnJlYWRtZSksXG4gICAgICB9LFxuICAgICAgZ3VpZGFuY2U6IHByb21wdFNlY3Rpb25zLFxuICAgICAgc3VnZ2VzdGVkRXhhbXBsZXM6IGV4YW1wbGVzLFxuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW1xuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgdGV4dDogSlNPTi5zdHJpbmdpZnkocGF5bG9hZCwgbnVsbCwgMiksXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0gc2F0aXNmaWVzIENvbnRlbnRSZXN1bHQ7XG4gIH0sXG59O1xuIiwiaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcblxuZXhwb3J0IHR5cGUgRGVjb3JhdG9yU3BlYyA9IHtcbiAgbmFtZTogc3RyaW5nO1xuICBhcmdzPzogdW5rbm93bltdO1xufTtcblxuZXhwb3J0IHR5cGUgQXR0cmlidXRlU3BlYyA9IHtcbiAgbmFtZTogc3RyaW5nO1xuICB0eXBlOiBzdHJpbmc7XG4gIGRlY29yYXRvcnM/OiBEZWNvcmF0b3JTcGVjW107XG59O1xuXG5mdW5jdGlvbiBlc2NhcGVSZWdFeHAodmFsdWU6IHN0cmluZykge1xuICByZXR1cm4gdmFsdWUucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xcXVxcXFxdL2csIFwiXFxcXCQmXCIpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXREZWNvcmF0b3Ioc3BlYzogRGVjb3JhdG9yU3BlYyk6IHN0cmluZyB7XG4gIGNvbnN0IGFyZ3MgPSAoc3BlYy5hcmdzIHx8IFtdKS5tYXAoKGFyZykgPT4gSlNPTi5zdHJpbmdpZnkoYXJnKSkuam9pbihcIiwgXCIpO1xuICByZXR1cm4gYEAke3NwZWMubmFtZX0oJHthcmdzfSlgO1xufVxuXG5mdW5jdGlvbiBlbnN1cmVEaXJlY3RvcnkoZmlsZVBhdGg6IHN0cmluZykge1xuICBmcy5ta2RpclN5bmMocGF0aC5kaXJuYW1lKGZpbGVQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG59XG5cbmZ1bmN0aW9uIGNvbGxlY3REZWNvcmF0b3JOYW1lcyhcbiAgY2xhc3NEZWNvcmF0b3JzOiBEZWNvcmF0b3JTcGVjW10gfCB1bmRlZmluZWQsXG4gIHByb3BlcnRpZXM6IEF0dHJpYnV0ZVNwZWNbXSB8IHVuZGVmaW5lZFxuKSB7XG4gIGNvbnN0IG5hbWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIG5hbWVzLmFkZChcIm1vZGVsXCIpO1xuICBmb3IgKGNvbnN0IGRlY29yYXRvciBvZiBjbGFzc0RlY29yYXRvcnMgfHwgW10pIHtcbiAgICBuYW1lcy5hZGQoZGVjb3JhdG9yLm5hbWUpO1xuICB9XG4gIGZvciAoY29uc3QgcHJvcGVydHkgb2YgcHJvcGVydGllcyB8fCBbXSkge1xuICAgIGZvciAoY29uc3QgZGVjb3JhdG9yIG9mIHByb3BlcnR5LmRlY29yYXRvcnMgfHwgW10pIHtcbiAgICAgIG5hbWVzLmFkZChkZWNvcmF0b3IubmFtZSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBuYW1lcztcbn1cblxuZnVuY3Rpb24gZW5zdXJlSW1wb3J0KFxuICBjb250ZW50OiBzdHJpbmcsXG4gIGltcG9ydHNGcm9tOiBzdHJpbmcsXG4gIGRlY29yYXRvcnM6IFNldDxzdHJpbmc+XG4pIHtcbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgaWYgKCFkZWNvcmF0b3JzLnNpemUpIHJldHVybiBjb250ZW50O1xuICBjb25zdCBpbXBvcnRSZWdleCA9IG5ldyBSZWdFeHAoXG4gICAgYGltcG9ydFxcXFxzK1xcXFx7KFtefV0rKVxcXFx9XFxcXHMrZnJvbVxcXFxzK1tcIiddJHtlc2NhcGVSZWdFeHAoaW1wb3J0c0Zyb20pfVtcIiddO2BcbiAgKTtcbiAgY29uc3QgbWF0Y2ggPSBjb250ZW50Lm1hdGNoKGltcG9ydFJlZ2V4KTtcbiAgY29uc3Qgc29ydGVkID0gQXJyYXkuZnJvbShkZWNvcmF0b3JzKS5zb3J0KCk7XG5cbiAgaWYgKG1hdGNoKSB7XG4gICAgY29uc3QgZXhpc3RpbmcgPSBtYXRjaFsxXVxuICAgICAgLnNwbGl0KFwiLFwiKVxuICAgICAgLm1hcCgobmFtZSkgPT4gbmFtZS50cmltKCkpXG4gICAgICAuZmlsdGVyKEJvb2xlYW4pO1xuICAgIGNvbnN0IG1lcmdlZCA9IEFycmF5LmZyb20obmV3IFNldChbLi4uZXhpc3RpbmcsIC4uLnNvcnRlZF0pKS5zb3J0KCk7XG4gICAgcmV0dXJuIGNvbnRlbnQucmVwbGFjZShcbiAgICAgIGltcG9ydFJlZ2V4LFxuICAgICAgYGltcG9ydCB7ICR7bWVyZ2VkLmpvaW4oXCIsIFwiKX0gfSBmcm9tIFwiJHtpbXBvcnRzRnJvbX1cIjtgXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IGltcG9ydExpbmUgPSBgaW1wb3J0IHsgJHtzb3J0ZWQuam9pbihcIiwgXCIpfSB9IGZyb20gXCIke2ltcG9ydHNGcm9tfVwiO2A7XG4gIHJldHVybiBgJHtpbXBvcnRMaW5lfVxcblxcbiR7Y29udGVudH1gO1xufVxuXG5mdW5jdGlvbiBhZGRQcm9wZXJ0eUJsb2NrKHByb3BlcnR5OiBBdHRyaWJ1dGVTcGVjKSB7XG4gIGNvbnN0IGRlY29yYXRvcnMgPSAocHJvcGVydHkuZGVjb3JhdG9ycyB8fCBbXSlcbiAgICAubWFwKGZvcm1hdERlY29yYXRvcilcbiAgICAuam9pbihcIlxcbiAgXCIpO1xuICBjb25zdCBkZWNvcmF0b3JCbG9jayA9IGRlY29yYXRvcnMgPyBgICAke2RlY29yYXRvcnN9XFxuYCA6IFwiXCI7XG4gIHJldHVybiBgJHtkZWNvcmF0b3JCbG9ja30gICR7cHJvcGVydHkubmFtZX06ICR7cHJvcGVydHkudHlwZX07YDtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHlCbG9jayhjb250ZW50OiBzdHJpbmcsIHByb3BlcnR5TmFtZTogc3RyaW5nKSB7XG4gIGNvbnN0IGxpbmVzID0gY29udGVudC5zcGxpdCgvXFxyP1xcbi8pO1xuICBjb25zdCByZXN1bHQ6IHN0cmluZ1tdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBsaW5lID0gbGluZXNbaV07XG4gICAgaWYgKFxuICAgICAgbGluZS50cmltKCkuc3RhcnRzV2l0aChgQGApICYmXG4gICAgICBsaW5lc1tpICsgMV0/LmluY2x1ZGVzKGAke3Byb3BlcnR5TmFtZX06YClcbiAgICApIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAobGluZS5pbmNsdWRlcyhgJHtwcm9wZXJ0eU5hbWV9OmApKSB7XG4gICAgICAvLyBza2lwIHRoaXMgbGluZSBhbmQgYW55IHRyYWlsaW5nIGJsYW5rIGxpbmVcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICByZXN1bHQucHVzaChsaW5lKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0LmpvaW4oXCJcXG5cIik7XG59XG5cbmZ1bmN0aW9uIGluc2VydERlY29yYXRvcihcbiAgY29udGVudDogc3RyaW5nLFxuICBkZWNvcmF0b3I6IERlY29yYXRvclNwZWMsXG4gIHRhcmdldDoge1xuICAgIGtpbmQ6IFwiY2xhc3NcIiB8IFwicHJvcGVydHlcIjtcbiAgICBuYW1lPzogc3RyaW5nO1xuICB9XG4pIHtcbiAgY29uc3QgZGVjb3JhdG9yTGluZSA9IGZvcm1hdERlY29yYXRvcihkZWNvcmF0b3IpO1xuICBpZiAodGFyZ2V0LmtpbmQgPT09IFwiY2xhc3NcIikge1xuICAgIGNvbnN0IGNsYXNzUmVnZXggPSAvKGV4cG9ydFxccytjbGFzc1xccytbXlxcc3tdK1xccypcXHspLztcbiAgICBpZiAoY29udGVudC5pbmNsdWRlcyhkZWNvcmF0b3JMaW5lKSkgcmV0dXJuIGNvbnRlbnQ7XG4gICAgcmV0dXJuIGNvbnRlbnQucmVwbGFjZShjbGFzc1JlZ2V4LCBgJHtkZWNvcmF0b3JMaW5lfVxcbiQxYCk7XG4gIH1cbiAgaWYgKCF0YXJnZXQubmFtZSkgcmV0dXJuIGNvbnRlbnQ7XG4gIGNvbnN0IHByb3BlcnR5UmVnZXggPSBuZXcgUmVnRXhwKFxuICAgIGAoXlxcXFxzKikoPzpALipcXFxcblxcXFwxKSoke2VzY2FwZVJlZ0V4cCh0YXJnZXQubmFtZSl9OmAsXG4gICAgXCJtXCJcbiAgKTtcbiAgY29uc3QgbWF0Y2ggPSBwcm9wZXJ0eVJlZ2V4LmV4ZWMoY29udGVudCk7XG4gIGlmICghbWF0Y2gpIHJldHVybiBjb250ZW50O1xuICBjb25zdCBpbmRlbnQgPSBtYXRjaFsxXSB8fCBcIiAgXCI7XG4gIGlmIChjb250ZW50LmluY2x1ZGVzKGAke2luZGVudH0ke2RlY29yYXRvckxpbmV9YCkpIHJldHVybiBjb250ZW50O1xuICByZXR1cm4gKFxuICAgIGNvbnRlbnQuc2xpY2UoMCwgbWF0Y2guaW5kZXgpICtcbiAgICBgJHtpbmRlbnR9JHtkZWNvcmF0b3JMaW5lfVxcbmAgK1xuICAgIGNvbnRlbnQuc2xpY2UobWF0Y2guaW5kZXgpXG4gICk7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZURlY29yYXRvcihcbiAgY29udGVudDogc3RyaW5nLFxuICBkZWNvcmF0b3JOYW1lOiBzdHJpbmcsXG4gIHRhcmdldDoge1xuICAgIGtpbmQ6IFwiY2xhc3NcIiB8IFwicHJvcGVydHlcIjtcbiAgICBuYW1lPzogc3RyaW5nO1xuICB9XG4pIHtcbiAgY29uc3QgZGVjb3JhdG9yUmVnZXggPSBuZXcgUmVnRXhwKFxuICAgIGBeXFxcXHMqQCR7ZXNjYXBlUmVnRXhwKGRlY29yYXRvck5hbWUpfVxcXFwoW14pXSpcXFxcKWAsXG4gICAgXCJtXCJcbiAgKTtcbiAgaWYgKHRhcmdldC5raW5kID09PSBcImNsYXNzXCIpIHtcbiAgICByZXR1cm4gY29udGVudC5yZXBsYWNlKGRlY29yYXRvclJlZ2V4LCBcIlwiKTtcbiAgfVxuICBpZiAodGFyZ2V0Lm5hbWUpIHtcbiAgICBjb25zdCBwYXR0ZXJuID0gbmV3IFJlZ0V4cChcbiAgICAgIGAoXlxcXFxzKkAke2VzY2FwZVJlZ0V4cChkZWNvcmF0b3JOYW1lKX1cXFxcKFteKV0qXFxcXClcXFxccyokXFxcXG4pKD89XFxcXHMqJHtlc2NhcGVSZWdFeHAodGFyZ2V0Lm5hbWUpfTopYCxcbiAgICAgIFwibVwiXG4gICAgKTtcbiAgICByZXR1cm4gY29udGVudC5yZXBsYWNlKHBhdHRlcm4sIFwiXCIpO1xuICB9XG4gIHJldHVybiBjb250ZW50O1xufVxuXG5mdW5jdGlvbiB3cml0ZUlmQ2hhbmdlZChmaWxlUGF0aDogc3RyaW5nLCBjb250ZW50OiBzdHJpbmcpIHtcbiAgZW5zdXJlRGlyZWN0b3J5KGZpbGVQYXRoKTtcbiAgZnMud3JpdGVGaWxlU3luYyhmaWxlUGF0aCwgY29udGVudCk7XG59XG5cbmV4cG9ydCBjb25zdCBkZWNvcmF0b3JUb29scyA9IHtcbiAgY3JlYXRlT3JVcGRhdGVNb2RlbFRvb2w6IHtcbiAgICBuYW1lOiBcImNyZWF0ZS1vci11cGRhdGUtbW9kZWxcIixcbiAgICBkZXNjcmlwdGlvbjogXCJDcmVhdGUgb3IgdXBkYXRlIGEgdmFsaWRhdGlvbi1yZWFkeSBtb2RlbCBjbGFzc1wiLFxuICAgIGV4ZWN1dGU6IGFzeW5jIChhcmdzOiB7XG4gICAgICBmaWxlUGF0aDogc3RyaW5nO1xuICAgICAgY2xhc3NOYW1lOiBzdHJpbmc7XG4gICAgICBjbGFzc0RlY29yYXRvcnM/OiBEZWNvcmF0b3JTcGVjW107XG4gICAgICBwcm9wZXJ0aWVzOiBBdHRyaWJ1dGVTcGVjW107XG4gICAgICBpbXBvcnRzRnJvbTogc3RyaW5nO1xuICAgICAgb3ZlcndyaXRlPzogYm9vbGVhbjtcbiAgICB9KSA9PiB7XG4gICAgICBpZiAoIWFyZ3Mub3ZlcndyaXRlICYmIGZzLmV4aXN0c1N5bmMoYXJncy5maWxlUGF0aCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGaWxlIGFscmVhZHkgZXhpc3RzIGF0ICR7YXJncy5maWxlUGF0aH1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGRlY29yYXRvcnMgPSBjb2xsZWN0RGVjb3JhdG9yTmFtZXMoXG4gICAgICAgIGFyZ3MuY2xhc3NEZWNvcmF0b3JzLFxuICAgICAgICBhcmdzLnByb3BlcnRpZXNcbiAgICAgICk7XG4gICAgICBsZXQgY29udGVudCA9IGBAbW9kZWwoKWA7XG4gICAgICBmb3IgKGNvbnN0IGRlY29yYXRvciBvZiBhcmdzLmNsYXNzRGVjb3JhdG9ycyB8fCBbXSkge1xuICAgICAgICBjb250ZW50ICs9IGBcXG4ke2Zvcm1hdERlY29yYXRvcihkZWNvcmF0b3IpfWA7XG4gICAgICB9XG4gICAgICBjb25zdCBwcm9wZXJ0aWVzID0gKGFyZ3MucHJvcGVydGllcyB8fCBbXSlcbiAgICAgICAgLm1hcChhZGRQcm9wZXJ0eUJsb2NrKVxuICAgICAgICAuam9pbihcIlxcblxcblwiKTtcbiAgICAgIGNvbnRlbnQgKz0gYFxcbmV4cG9ydCBjbGFzcyAke2FyZ3MuY2xhc3NOYW1lfSB7XFxuJHtwcm9wZXJ0aWVzID8gYCR7cHJvcGVydGllc31cXG5gIDogXCJcIn19XFxuYDtcbiAgICAgIGNvbnRlbnQgPSBlbnN1cmVJbXBvcnQoY29udGVudCwgYXJncy5pbXBvcnRzRnJvbSwgZGVjb3JhdG9ycyk7XG4gICAgICB3cml0ZUlmQ2hhbmdlZChhcmdzLmZpbGVQYXRoLCBjb250ZW50KTtcbiAgICAgIHJldHVybiB7IGZpbGVQYXRoOiBhcmdzLmZpbGVQYXRoIH07XG4gICAgfSxcbiAgfSxcbiAgYWRkQXR0cmlidXRlVG9vbDoge1xuICAgIG5hbWU6IFwiYWRkLWF0dHJpYnV0ZVwiLFxuICAgIGRlc2NyaXB0aW9uOiBcIkFkZCBhIGRlY29yYXRlZCBhdHRyaWJ1dGUgdG8gYW4gZXhpc3RpbmcgbW9kZWxcIixcbiAgICBleGVjdXRlOiBhc3luYyAoYXJnczoge1xuICAgICAgZmlsZVBhdGg6IHN0cmluZztcbiAgICAgIGNsYXNzTmFtZTogc3RyaW5nO1xuICAgICAgYXR0cmlidXRlOiBBdHRyaWJ1dGVTcGVjO1xuICAgICAgaW1wb3J0c0Zyb206IHN0cmluZztcbiAgICB9KSA9PiB7XG4gICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoYXJncy5maWxlUGF0aCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBNb2RlbCBmaWxlIG5vdCBmb3VuZCBhdCAke2FyZ3MuZmlsZVBhdGh9YCk7XG4gICAgICB9XG4gICAgICBsZXQgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhhcmdzLmZpbGVQYXRoLCBcInV0ZjhcIik7XG4gICAgICBpZiAoY29udGVudC5pbmNsdWRlcyhgJHthcmdzLmF0dHJpYnV0ZS5uYW1lfTpgKSkge1xuICAgICAgICByZXR1cm4geyBmaWxlUGF0aDogYXJncy5maWxlUGF0aCB9O1xuICAgICAgfVxuICAgICAgY29uc3QgZGVjb3JhdG9ycyA9IGNvbGxlY3REZWNvcmF0b3JOYW1lcyh1bmRlZmluZWQsIFthcmdzLmF0dHJpYnV0ZV0pO1xuICAgICAgY29udGVudCA9IGVuc3VyZUltcG9ydChjb250ZW50LCBhcmdzLmltcG9ydHNGcm9tLCBkZWNvcmF0b3JzKTtcbiAgICAgIGNvbnN0IGluc2VydGlvblBvaW50ID0gY29udGVudC5sYXN0SW5kZXhPZihcIn1cIik7XG4gICAgICBjb25zdCBibG9jayA9IGFkZFByb3BlcnR5QmxvY2soYXJncy5hdHRyaWJ1dGUpO1xuICAgICAgY29uc3QgYmVmb3JlID0gY29udGVudC5zbGljZSgwLCBpbnNlcnRpb25Qb2ludCkucmVwbGFjZSgvXFxzKiQvLCBcIlwiKTtcbiAgICAgIGNvbnN0IGFmdGVyID0gY29udGVudC5zbGljZShpbnNlcnRpb25Qb2ludCk7XG4gICAgICBjb25zdCB1cGRhdGVkID0gYCR7YmVmb3JlfVxcbiR7YmxvY2t9XFxuJHthZnRlcn1gO1xuICAgICAgd3JpdGVJZkNoYW5nZWQoYXJncy5maWxlUGF0aCwgdXBkYXRlZCk7XG4gICAgICByZXR1cm4geyBmaWxlUGF0aDogYXJncy5maWxlUGF0aCB9O1xuICAgIH0sXG4gIH0sXG4gIHJlbW92ZUF0dHJpYnV0ZVRvb2w6IHtcbiAgICBuYW1lOiBcInJlbW92ZS1hdHRyaWJ1dGVcIixcbiAgICBkZXNjcmlwdGlvbjogXCJSZW1vdmUgYW4gYXR0cmlidXRlIGZyb20gYSBtb2RlbCBjbGFzc1wiLFxuICAgIGV4ZWN1dGU6IGFzeW5jIChhcmdzOiB7XG4gICAgICBmaWxlUGF0aDogc3RyaW5nO1xuICAgICAgY2xhc3NOYW1lOiBzdHJpbmc7XG4gICAgICBhdHRyaWJ1dGVOYW1lOiBzdHJpbmc7XG4gICAgfSkgPT4ge1xuICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKGFyZ3MuZmlsZVBhdGgpKSByZXR1cm4geyBmaWxlUGF0aDogYXJncy5maWxlUGF0aCB9O1xuICAgICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhhcmdzLmZpbGVQYXRoLCBcInV0ZjhcIik7XG4gICAgICBjb25zdCB1cGRhdGVkID0gcmVtb3ZlUHJvcGVydHlCbG9jayhjb250ZW50LCBhcmdzLmF0dHJpYnV0ZU5hbWUpO1xuICAgICAgd3JpdGVJZkNoYW5nZWQoYXJncy5maWxlUGF0aCwgdXBkYXRlZCk7XG4gICAgICByZXR1cm4geyBmaWxlUGF0aDogYXJncy5maWxlUGF0aCB9O1xuICAgIH0sXG4gIH0sXG4gIGFwcGx5RGVjb3JhdG9yVG9vbDoge1xuICAgIG5hbWU6IFwiYXBwbHktZGVjb3JhdG9yXCIsXG4gICAgZGVzY3JpcHRpb246IFwiQXBwbHkgYSBkZWNvcmF0b3IgdG8gYSBjbGFzcyBvciBwcm9wZXJ0eVwiLFxuICAgIGV4ZWN1dGU6IGFzeW5jIChhcmdzOiB7XG4gICAgICBmaWxlUGF0aDogc3RyaW5nO1xuICAgICAgY2xhc3NOYW1lOiBzdHJpbmc7XG4gICAgICB0YXJnZXQ6IHsga2luZDogXCJjbGFzc1wiIHwgXCJwcm9wZXJ0eVwiOyBuYW1lPzogc3RyaW5nIH07XG4gICAgICBkZWNvcmF0b3I6IERlY29yYXRvclNwZWM7XG4gICAgICBpbXBvcnRzRnJvbTogc3RyaW5nO1xuICAgIH0pID0+IHtcbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhhcmdzLmZpbGVQYXRoKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE1vZGVsIGZpbGUgbm90IGZvdW5kIGF0ICR7YXJncy5maWxlUGF0aH1gKTtcbiAgICAgIH1cbiAgICAgIGxldCBjb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKGFyZ3MuZmlsZVBhdGgsIFwidXRmOFwiKTtcbiAgICAgIGNvbnN0IGRlY29yYXRvcnMgPSBuZXcgU2V0PHN0cmluZz4oW2FyZ3MuZGVjb3JhdG9yLm5hbWVdKTtcbiAgICAgIGNvbnRlbnQgPSBlbnN1cmVJbXBvcnQoY29udGVudCwgYXJncy5pbXBvcnRzRnJvbSwgZGVjb3JhdG9ycyk7XG4gICAgICBjb250ZW50ID0gaW5zZXJ0RGVjb3JhdG9yKGNvbnRlbnQsIGFyZ3MuZGVjb3JhdG9yLCBhcmdzLnRhcmdldCk7XG4gICAgICB3cml0ZUlmQ2hhbmdlZChhcmdzLmZpbGVQYXRoLCBjb250ZW50KTtcbiAgICAgIHJldHVybiB7IGZpbGVQYXRoOiBhcmdzLmZpbGVQYXRoIH07XG4gICAgfSxcbiAgfSxcbiAgcmVtb3ZlRGVjb3JhdG9yVG9vbDoge1xuICAgIG5hbWU6IFwicmVtb3ZlLWRlY29yYXRvclwiLFxuICAgIGRlc2NyaXB0aW9uOiBcIlJlbW92ZSBhIGRlY29yYXRvciBmcm9tIGEgY2xhc3Mgb3IgcHJvcGVydHlcIixcbiAgICBleGVjdXRlOiBhc3luYyAoYXJnczoge1xuICAgICAgZmlsZVBhdGg6IHN0cmluZztcbiAgICAgIGNsYXNzTmFtZTogc3RyaW5nO1xuICAgICAgdGFyZ2V0OiB7IGtpbmQ6IFwiY2xhc3NcIiB8IFwicHJvcGVydHlcIjsgbmFtZT86IHN0cmluZyB9O1xuICAgICAgZGVjb3JhdG9yTmFtZTogc3RyaW5nO1xuICAgIH0pID0+IHtcbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhhcmdzLmZpbGVQYXRoKSkgcmV0dXJuIHsgZmlsZVBhdGg6IGFyZ3MuZmlsZVBhdGggfTtcbiAgICAgIGxldCBjb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKGFyZ3MuZmlsZVBhdGgsIFwidXRmOFwiKTtcbiAgICAgIGNvbnRlbnQgPSByZW1vdmVEZWNvcmF0b3IoY29udGVudCwgYXJncy5kZWNvcmF0b3JOYW1lLCBhcmdzLnRhcmdldCk7XG4gICAgICB3cml0ZUlmQ2hhbmdlZChhcmdzLmZpbGVQYXRoLCBjb250ZW50KTtcbiAgICAgIHJldHVybiB7IGZpbGVQYXRoOiBhcmdzLmZpbGVQYXRoIH07XG4gICAgfSxcbiAgfSxcbiAgc2NhZmZvbGRWYWxpZGF0b3JUb29sOiB7XG4gICAgbmFtZTogXCJzY2FmZm9sZC12YWxpZGF0b3JcIixcbiAgICBkZXNjcmlwdGlvbjogXCJTY2FmZm9sZCBhIHZhbGlkYXRvciBjbGFzcyBhbmQgb3B0aW9uYWwgZGVjb3JhdG9yXCIsXG4gICAgZXhlY3V0ZTogYXN5bmMgKGFyZ3M6IHtcbiAgICAgIHZhbGlkYXRvcnNEaXI6IHN0cmluZztcbiAgICAgIGRlY29yYXRvckRpcj86IHN0cmluZztcbiAgICAgIG5hbWU6IHN0cmluZztcbiAgICB9KSA9PiB7XG4gICAgICBjb25zdCBjbGFzc0ZpbGUgPSBwYXRoLmpvaW4oYXJncy52YWxpZGF0b3JzRGlyLCBgJHthcmdzLm5hbWV9LnRzYCk7XG4gICAgICBlbnN1cmVEaXJlY3RvcnkoY2xhc3NGaWxlKTtcbiAgICAgIGNvbnN0IGNsYXNzQ29udGVudCA9IGBleHBvcnQgY2xhc3MgJHthcmdzLm5hbWV9IHtcXG4gIHZhbGlkYXRlKHZhbHVlOiB1bmtub3duKTogYm9vbGVhbiB7XFxuICAgIHJldHVybiB2YWx1ZSAhPT0gdW5kZWZpbmVkO1xcbiAgfVxcbn1cXG5gO1xuICAgICAgZnMud3JpdGVGaWxlU3luYyhjbGFzc0ZpbGUsIGNsYXNzQ29udGVudCk7XG4gICAgICBsZXQgZGVjb3JhdG9yRmlsZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgaWYgKGFyZ3MuZGVjb3JhdG9yRGlyKSB7XG4gICAgICAgIGRlY29yYXRvckZpbGUgPSBwYXRoLmpvaW4oXG4gICAgICAgICAgYXJncy5kZWNvcmF0b3JEaXIsXG4gICAgICAgICAgYCR7YXJncy5uYW1lfURlY29yYXRvci50c2BcbiAgICAgICAgKTtcbiAgICAgICAgZW5zdXJlRGlyZWN0b3J5KGRlY29yYXRvckZpbGUpO1xuICAgICAgICBmcy53cml0ZUZpbGVTeW5jKFxuICAgICAgICAgIGRlY29yYXRvckZpbGUsXG4gICAgICAgICAgYGV4cG9ydCBmdW5jdGlvbiAke2FyZ3MubmFtZX1EZWNvcmF0b3IoKSB7XFxuICByZXR1cm4gKCkgPT4gdm9pZCAwO1xcbn1cXG5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4geyBjbGFzc0ZpbGUsIGRlY29yYXRvckZpbGUgfTtcbiAgICB9LFxuICB9LFxuICBzY2FmZm9sZFNlcmlhbGl6ZXJUb29sOiB7XG4gICAgbmFtZTogXCJzY2FmZm9sZC1zZXJpYWxpemVyXCIsXG4gICAgZGVzY3JpcHRpb246IFwiU2NhZmZvbGQgYSBzZXJpYWxpemVyIGNsYXNzIGFuZCBvcHRpb25hbCByZWdpc3RyeVwiLFxuICAgIGV4ZWN1dGU6IGFzeW5jIChhcmdzOiB7XG4gICAgICBkaXI6IHN0cmluZztcbiAgICAgIG5hbWU6IHN0cmluZztcbiAgICAgIHJlZ2lzdGVyRGlyPzogc3RyaW5nO1xuICAgICAgc2V0RGVmYXVsdD86IGJvb2xlYW47XG4gICAgfSkgPT4ge1xuICAgICAgY29uc3QgY2xhc3NGaWxlID0gcGF0aC5qb2luKGFyZ3MuZGlyLCBgJHthcmdzLm5hbWV9LnRzYCk7XG4gICAgICBlbnN1cmVEaXJlY3RvcnkoY2xhc3NGaWxlKTtcbiAgICAgIGZzLndyaXRlRmlsZVN5bmMoXG4gICAgICAgIGNsYXNzRmlsZSxcbiAgICAgICAgYGV4cG9ydCBjbGFzcyAke2FyZ3MubmFtZX0ge1xcbiAgc2VyaWFsaXplKHZhbHVlOiB1bmtub3duKTogc3RyaW5nIHtcXG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcXG4gIH1cXG59XFxuYFxuICAgICAgKTtcbiAgICAgIGxldCByZWdpc3RlckZpbGU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgIGlmIChhcmdzLnJlZ2lzdGVyRGlyKSB7XG4gICAgICAgIHJlZ2lzdGVyRmlsZSA9IHBhdGguam9pbihhcmdzLnJlZ2lzdGVyRGlyLCBgJHthcmdzLm5hbWV9UmVnaXN0ZXIudHNgKTtcbiAgICAgICAgZW5zdXJlRGlyZWN0b3J5KHJlZ2lzdGVyRmlsZSk7XG4gICAgICAgIGZzLndyaXRlRmlsZVN5bmMoXG4gICAgICAgICAgcmVnaXN0ZXJGaWxlLFxuICAgICAgICAgIGBleHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXIke2FyZ3MubmFtZX0oKSB7XFxuICByZXR1cm4gJHthcmdzLnNldERlZmF1bHQgPyBcIidkZWZhdWx0J1wiIDogXCInb3B0aW9uYWwnXCJ9O1xcbn1cXG5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4geyBjbGFzc0ZpbGUsIHJlZ2lzdGVyRmlsZSB9O1xuICAgIH0sXG4gIH0sXG4gIHNjYWZmb2xkSGFzaGluZ1Rvb2w6IHtcbiAgICBuYW1lOiBcInNjYWZmb2xkLWhhc2hpbmdcIixcbiAgICBkZXNjcmlwdGlvbjogXCJTY2FmZm9sZCBhIGhhc2hpbmcgZnVuY3Rpb24gYW5kIG9wdGlvbmFsIHJlZ2lzdHJ5XCIsXG4gICAgZXhlY3V0ZTogYXN5bmMgKGFyZ3M6IHtcbiAgICAgIGRpcjogc3RyaW5nO1xuICAgICAgbmFtZTogc3RyaW5nO1xuICAgICAgcmVnaXN0ZXJEaXI/OiBzdHJpbmc7XG4gICAgICBzZXREZWZhdWx0PzogYm9vbGVhbjtcbiAgICB9KSA9PiB7XG4gICAgICBjb25zdCBmdW5jdGlvbkZpbGUgPSBwYXRoLmpvaW4oYXJncy5kaXIsIGAke2FyZ3MubmFtZX0udHNgKTtcbiAgICAgIGVuc3VyZURpcmVjdG9yeShmdW5jdGlvbkZpbGUpO1xuICAgICAgZnMud3JpdGVGaWxlU3luYyhcbiAgICAgICAgZnVuY3Rpb25GaWxlLFxuICAgICAgICBgZXhwb3J0IGZ1bmN0aW9uICR7YXJncy5uYW1lfSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcXG4gIHJldHVybiB2YWx1ZS5zcGxpdCgnJykucmV2ZXJzZSgpLmpvaW4oJycpO1xcbn1cXG5gXG4gICAgICApO1xuICAgICAgbGV0IHJlZ2lzdGVyRmlsZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgaWYgKGFyZ3MucmVnaXN0ZXJEaXIpIHtcbiAgICAgICAgcmVnaXN0ZXJGaWxlID0gcGF0aC5qb2luKGFyZ3MucmVnaXN0ZXJEaXIsIGAke2FyZ3MubmFtZX1SZWdpc3Rlci50c2ApO1xuICAgICAgICBlbnN1cmVEaXJlY3RvcnkocmVnaXN0ZXJGaWxlKTtcbiAgICAgICAgZnMud3JpdGVGaWxlU3luYyhcbiAgICAgICAgICByZWdpc3RlckZpbGUsXG4gICAgICAgICAgYGV4cG9ydCBmdW5jdGlvbiByZWdpc3RlciR7YXJncy5uYW1lfSgpIHtcXG4gIHJldHVybiAke2FyZ3Muc2V0RGVmYXVsdCA/IFwiJ2RlZmF1bHQnXCIgOiBcIidvcHRpb25hbCdcIn07XFxufVxcbmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7IGZ1bmN0aW9uRmlsZSwgcmVnaXN0ZXJGaWxlIH07XG4gICAgfSxcbiAgfSxcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCB0eXBlIERlY29yYXRvclRvb2xzID0gdHlwZW9mIGRlY29yYXRvclRvb2xzO1xuIiwiaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IENvbnRlbnRSZXN1bHQsIFRvb2wgfSBmcm9tIFwiZmFzdG1jcFwiO1xuaW1wb3J0IHsgYXBwbHlQYXRjaCwgY3JlYXRlVHdvRmlsZXNQYXRjaCB9IGZyb20gXCJkaWZmXCI7XG5pbXBvcnQge1xuICBhbmFseXplUmVwb1NjaGVtYSxcbiAgY29kZUNoYW5nZVNjaGVtYSxcbiAgZG9jdW1lbnRDb2RlU2NoZW1hLFxuICBlbnVtZXJhdGVDYXBhYmlsaXRpZXNTY2hlbWEsXG4gIHBsYW5GZWF0dXJlU2NoZW1hLFxufSBmcm9tIFwiLi4vc2NoZW1hc1wiO1xuaW1wb3J0IHsgYW5hbHl6ZVJlcG8gfSBmcm9tIFwiLi4vY29kZVwiO1xuaW1wb3J0IHsgZGVyaXZlQ2FwYWJpbGl0aWVzIH0gZnJvbSBcIi4uL3V0aWxzXCI7XG5pbXBvcnQge1xuICBnZXRXb3Jrc3BhY2VSb290LFxuICByZXNvbHZlSW5Xb3Jrc3BhY2UsXG4gIHRocm93VXNlckVycm9yLFxuICBXb3Jrc3BhY2VFcnJvcixcbn0gZnJvbSBcIi4uL3dvcmtzcGFjZVwiO1xuLy8gTk9URTogcHJvbXB0IGhlbHBlcnMgKGJ1aWxkRG9jdW1lbnRhdGlvblBheWxvYWQsIGRpc2NvdmVyRG9jUHJvbXB0cywgc2VsZWN0UHJvbXB0LCBERUZBVUxUX1BST01QVF9OQU1FKVxuLy8gYXJlIGltcG9ydGVkIGR5bmFtaWNhbGx5IGluc2lkZSBkb2N1bWVudENvZGVUb29sLmV4ZWN1dGUgdG8gYXZvaWQgY3JlYXRpbmcgYSBzdGF0aWMgY2lyY3VsYXIgaW1wb3J0XG4vLyBhdCBtb2R1bGUgbG9hZCB0aW1lIChtb2R1bGVSZWdpc3RyeSAtPiBtb2R1bGVzIC0+IGRlY29yYXRpb24gdG9vbHMgLT4gbWNwL3Rvb2xzIC0+IHByb21wdHMpLlxuLy8gVGhleSB3aWxsIGJlIGxvYWRlZCB3aGVuIHRoZSB0b29sIGV4ZWN1dGVzLlxuaW1wb3J0IHR5cGUgeyBBcHBseUNvZGVDaGFuZ2VBcmdzLCBEb2N1bWVudENvZGVBcmdzIH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZEFuYWx5emVSZXBvc2l0b3J5VG9vbCgpOiBUb29sPFxuICB1bmRlZmluZWQsXG4gIHR5cGVvZiBhbmFseXplUmVwb1NjaGVtYVxuPiB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogXCJhbmFseXplLXJlcG9zaXRvcnlcIixcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgIFwiQW5hbHl6ZSBhIGxvY2FsIHJlcG9zaXRvcnkncyBzb3VyY2UsIHRlc3RzLCBhbmQgZG9jcyB0byBleHRyYWN0IGV4cG9ydGVkIEFQSXMsIGRlY29yYXRvcnMsIGFuZCB0ZXN0IG1lbnRpb25zLlwiLFxuICAgIHBhcmFtZXRlcnM6IGFuYWx5emVSZXBvU2NoZW1hLFxuICAgIGV4ZWN1dGU6IGFzeW5jIChpbnB1dCkgPT4ge1xuICAgICAgbGV0IHJlcG9Sb290ID0gcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIGlucHV0LnJlcG9QYXRoKTtcbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhyZXBvUm9vdCkpIHtcbiAgICAgICAgLy8gdHJ5IHJlc29sdmluZyBmcm9tIG1vbm9yZXBvIHJvb3QgKHBhcmVudCBvZiBjdXJyZW50IGN3ZClcbiAgICAgICAgY29uc3QgYWx0ID0gcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIFwiLi5cIiwgaW5wdXQucmVwb1BhdGgpO1xuICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhhbHQpKSByZXBvUm9vdCA9IGFsdDtcbiAgICAgIH1cbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhyZXBvUm9vdCkpIHtcbiAgICAgICAgLy8gaWYgaW5wdXQgd2FzIGFic29sdXRlIGFuZCBzdGlsbCBub3QgZm91bmQsIHRyeSAuLi88YmFzZW5hbWU+XG4gICAgICAgIGNvbnN0IGFsdDIgPSBwYXRoLnJlc29sdmUoXG4gICAgICAgICAgcHJvY2Vzcy5jd2QoKSxcbiAgICAgICAgICBcIi4uXCIsXG4gICAgICAgICAgcGF0aC5iYXNlbmFtZShpbnB1dC5yZXBvUGF0aClcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGZzLmV4aXN0c1N5bmMoYWx0MikpIHJlcG9Sb290ID0gYWx0MjtcbiAgICAgIH1cbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhyZXBvUm9vdCkpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgUmVwb3NpdG9yeSBub3QgZm91bmQgYXQgJHtyZXBvUm9vdH1gKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGFuYWx5emVSZXBvKHJlcG9Sb290KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFt7IHR5cGU6IFwidGV4dFwiLCB0ZXh0OiBKU09OLnN0cmluZ2lmeShyZXN1bHQsIG51bGwsIDIpIH1dLFxuICAgICAgfTtcbiAgICB9LFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRFbnVtZXJhdGVDYXBhYmlsaXRpZXNUb29sKCk6IFRvb2w8XG4gIHVuZGVmaW5lZCxcbiAgdHlwZW9mIGVudW1lcmF0ZUNhcGFiaWxpdGllc1NjaGVtYVxuPiB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogXCJlbnVtZXJhdGUtY2FwYWJpbGl0aWVzXCIsXG4gICAgZGVzY3JpcHRpb246XG4gICAgICBcIkVudW1lcmF0ZSBkZXZlbG9wZXItZmFjaW5nIGNhcGFiaWxpdGllcyBvZiB0aGUgZ2l2ZW4gcmVwb3NpdG9yeSwgaW5mZXJyZWQgZnJvbSBjb2RlLCB0ZXN0cywgYW5kIGRvY3MuXCIsXG4gICAgcGFyYW1ldGVyczogZW51bWVyYXRlQ2FwYWJpbGl0aWVzU2NoZW1hLFxuICAgIGV4ZWN1dGU6IGFzeW5jIChpbnB1dCkgPT4ge1xuICAgICAgbGV0IHJlcG9Sb290ID0gcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIGlucHV0LnJlcG9QYXRoKTtcbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhyZXBvUm9vdCkpIHtcbiAgICAgICAgY29uc3QgYWx0ID0gcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIFwiLi5cIiwgaW5wdXQucmVwb1BhdGgpO1xuICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhhbHQpKSByZXBvUm9vdCA9IGFsdDtcbiAgICAgIH1cbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhyZXBvUm9vdCkpIHtcbiAgICAgICAgY29uc3QgYWx0MiA9IHBhdGgucmVzb2x2ZShcbiAgICAgICAgICBwcm9jZXNzLmN3ZCgpLFxuICAgICAgICAgIFwiLi5cIixcbiAgICAgICAgICBwYXRoLmJhc2VuYW1lKGlucHV0LnJlcG9QYXRoKVxuICAgICAgICApO1xuICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhhbHQyKSkgcmVwb1Jvb3QgPSBhbHQyO1xuICAgICAgfVxuICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKHJlcG9Sb290KSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZXBvc2l0b3J5IG5vdCBmb3VuZCBhdCAke3JlcG9Sb290fWApO1xuICAgICAgY29uc3QgYW5hbHlzaXMgPSBhbmFseXplUmVwbyhyZXBvUm9vdCk7XG4gICAgICBjb25zdCBjYXBhYmlsaXRpZXMgPSBkZXJpdmVDYXBhYmlsaXRpZXMoYW5hbHlzaXMpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBjYXBhYmlsaXRpZXMsXG4gICAgICAgICAgICAgICAgYW5hbHlzaXNTdW1tYXJ5OiB7XG4gICAgICAgICAgICAgICAgICBmaWxlczogYW5hbHlzaXMuZmlsZXMubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgdGVzdEZpbGVzOiBhbmFseXNpcy50ZXN0RmlsZXMubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgcmVhZG1lOiBhbmFseXNpcy5yZWFkbWU/LnRpdGxlLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICAgIDJcbiAgICAgICAgICAgICksXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfSxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUGxhbkZlYXR1cmVUb29sKCk6IFRvb2w8XG4gIHVuZGVmaW5lZCxcbiAgdHlwZW9mIHBsYW5GZWF0dXJlU2NoZW1hXG4+IHtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBcInBsYW4tZmVhdHVyZS1pbXBsZW1lbnRhdGlvblwiLFxuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgXCJHaXZlbiBhIGZlYXR1cmUgcmVxdWVzdCwgc2VsZWN0IGFwcHJvcHJpYXRlIE1DUCB0b29scyAoaW5jbHVkaW5nIGV4aXN0aW5nIGFuZCBuZXcgb25lcykgYW5kIHByb2R1Y2UgYW4gZXhlY3V0aW9uIHBsYW4uXCIsXG4gICAgcGFyYW1ldGVyczogcGxhbkZlYXR1cmVTY2hlbWEsXG4gICAgZXhlY3V0ZTogYXN5bmMgKGlucHV0KSA9PiB7XG4gICAgICBjb25zdCBzdGVwczogQXJyYXk8e1xuICAgICAgICBzdGVwOiBudW1iZXI7XG4gICAgICAgIGFjdGlvbjogc3RyaW5nO1xuICAgICAgICB0b29sPzogc3RyaW5nO1xuICAgICAgICBhcmd1bWVudHM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgICAgICByYXRpb25hbGU6IHN0cmluZztcbiAgICAgIH0+ID0gW107XG4gICAgICBsZXQgaSA9IDE7XG4gICAgICBzdGVwcy5wdXNoKHtcbiAgICAgICAgc3RlcDogaSsrLFxuICAgICAgICBhY3Rpb246IFwiQW5hbHl6ZSByZXBvc2l0b3J5IHRvIGVudW1lcmF0ZSBBUElzIGFuZCBkZWNvcmF0b3JzXCIsXG4gICAgICAgIHRvb2w6IFwiYW5hbHl6ZS1yZXBvc2l0b3J5XCIsXG4gICAgICAgIGFyZ3VtZW50czogeyByZXBvUGF0aDogaW5wdXQucmVwb1BhdGggfSxcbiAgICAgICAgcmF0aW9uYWxlOiBcIlVuZGVyc3RhbmQgYXZhaWxhYmxlIGJ1aWxkaW5nIGJsb2Nrcy5cIixcbiAgICAgIH0pO1xuICAgICAgc3RlcHMucHVzaCh7XG4gICAgICAgIHN0ZXA6IGkrKyxcbiAgICAgICAgYWN0aW9uOiBcIkxpc3QgY2FwYWJpbGl0aWVzIGV4cGVjdGVkIGZvciBkZXZlbG9wZXJzXCIsXG4gICAgICAgIHRvb2w6IFwiZW51bWVyYXRlLWNhcGFiaWxpdGllc1wiLFxuICAgICAgICBhcmd1bWVudHM6IHsgcmVwb1BhdGg6IGlucHV0LnJlcG9QYXRoIH0sXG4gICAgICAgIHJhdGlvbmFsZTogXCJBbGlnbiB0aGUgcGxhbiB3aXRoIHN1cHBvcnRlZCBjYXBhYmlsaXRpZXMuXCIsXG4gICAgICB9KTtcbiAgICAgIC8vIFN1Z2dlc3QgZXhpc3RpbmcgZ2VuZXJpYyB0b29scyBmcm9tIG1jcC1tb2R1bGVcbiAgICAgIHN0ZXBzLnB1c2goe1xuICAgICAgICBzdGVwOiBpKyssXG4gICAgICAgIGFjdGlvbjpcbiAgICAgICAgICBcIlNlbGVjdCBkb2N1bWVudGF0aW9uIHByb21wdCBhbmQgZ2F0aGVyIHJlbGV2YW50IHNvdXJjZSBmaWxlKHMpXCIsXG4gICAgICAgIHRvb2w6IFwiZG9jdW1lbnQtY29kZVwiLFxuICAgICAgICBhcmd1bWVudHM6IHsgZmlsZVBhdGg6IFwiPHRhcmdldC1maWxlPlwiIH0sXG4gICAgICAgIHJhdGlvbmFsZTogXCJQcm92aWRlIGNvbnRleHQgYW5kIGluc3RydWN0aW9ucyBmb3IgY2hhbmdlcy5cIixcbiAgICAgIH0pO1xuICAgICAgc3RlcHMucHVzaCh7XG4gICAgICAgIHN0ZXA6IGkrKyxcbiAgICAgICAgYWN0aW9uOiBcIkFwcGx5IGNvZGUgY2hhbmdlcyB1c2luZyB1bmlmaWVkIGRpZmYgcGF0Y2hcIixcbiAgICAgICAgdG9vbDogXCJhcHBseS1jb2RlLWNoYW5nZVwiLFxuICAgICAgICBhcmd1bWVudHM6IHtcbiAgICAgICAgICBmaWxlUGF0aDogXCI8dGFyZ2V0LWZpbGU+XCIsXG4gICAgICAgICAgcGF0Y2g6IFwiPHVuaWZpZWQtZGlmZj5cIixcbiAgICAgICAgICBkcnlSdW46IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIHJhdGlvbmFsZTogXCJWYWxpZGF0ZSBjaGFuZ2VzIHNhZmVseSBiZWZvcmUgY29tbWl0dGluZy5cIixcbiAgICAgIH0pO1xuICAgICAgc3RlcHMucHVzaCh7XG4gICAgICAgIHN0ZXA6IGkrKyxcbiAgICAgICAgYWN0aW9uOiBcIkNvbW1pdCBjb2RlIGNoYW5nZXNcIixcbiAgICAgICAgdG9vbDogXCJhcHBseS1jb2RlLWNoYW5nZVwiLFxuICAgICAgICBhcmd1bWVudHM6IHtcbiAgICAgICAgICBmaWxlUGF0aDogXCI8dGFyZ2V0LWZpbGU+XCIsXG4gICAgICAgICAgcGF0Y2g6IFwiPHVuaWZpZWQtZGlmZj5cIixcbiAgICAgICAgICBkcnlSdW46IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgICByYXRpb25hbGU6IFwiUGVyc2lzdCB0aGUgdXBkYXRlLlwiLFxuICAgICAgfSk7XG4gICAgICAvLyBJZiBkZWNvcmF0aW9uLXJlbGF0ZWQgdGVybXMgcHJlc2VudCwgc3VnZ2VzdCBkZWNvcmF0b3IgdG9vbHNcbiAgICAgIGlmICgvZGVjb3JhdHxmbGF2b3VyfG92ZXJyaWRlfGV4dGVuZHxidWlsZGVyL2kudGVzdChpbnB1dC5mZWF0dXJlKSkge1xuICAgICAgICBzdGVwcy51bnNoaWZ0KHtcbiAgICAgICAgICBzdGVwOiAwLFxuICAgICAgICAgIGFjdGlvbjogXCJVc2UgZGVjb3JhdG9yIHRvb2xpbmcgdG8gaW5zZXJ0L3JlbW92ZS9tb2RpZnkgZGVjb3JhdG9yc1wiLFxuICAgICAgICAgIHRvb2w6IFwiZGVjb3JhdG9yLXRvb2xzXCIsXG4gICAgICAgICAgYXJndW1lbnRzOiB7IGFjdGlvbjogXCJoZWxwXCIgfSxcbiAgICAgICAgICByYXRpb25hbGU6IFwiTGV2ZXJhZ2Ugc3BlY2lhbGl6ZWQgdXRpbGl0aWVzIGZvciBkZWNvcmF0aW9uIHBhdHRlcm5zLlwiLFxuICAgICAgICB9KTtcbiAgICAgICAgc3RlcHMuZm9yRWFjaCgocywgaWR4KSA9PiAocy5zdGVwID0gaWR4ICsgMSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBwbGFuOiBzdGVwcyxcbiAgICAgICAgICAgICAgICBub3RlczpcbiAgICAgICAgICAgICAgICAgIFwiUmVwbGFjZSBwbGFjZWhvbGRlciBhcmd1bWVudHMgbGlrZSA8dGFyZ2V0LWZpbGU+IGFuZCA8dW5pZmllZC1kaWZmPiBiYXNlZCBvbiB0aGUgYW5hbHlzaXMgb3V0cHV0LlwiLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgICAyXG4gICAgICAgICAgICApLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH0sXG4gIH07XG59XG5cbmV4cG9ydCBjb25zdCBkb2N1bWVudENvZGVUb29sOiBUb29sPHVuZGVmaW5lZCwgdHlwZW9mIGRvY3VtZW50Q29kZVNjaGVtYT4gPSB7XG4gIGFubm90YXRpb25zOiB7XG4gICAgaWRlbXBvdGVudEhpbnQ6IHRydWUsXG4gICAgb3BlbldvcmxkSGludDogZmFsc2UsXG4gICAgcmVhZE9ubHlIaW50OiB0cnVlLFxuICAgIHRpdGxlOiBcIkRvY3VtZW50IFNvdXJjZSBGaWxlXCIsXG4gIH0sXG4gIGRlc2NyaXB0aW9uOlxuICAgIFwiR2VuZXJhdGUgZG9jdW1lbnRhdGlvbiBndWlkYW5jZSBmb3IgYSBmaWxlIGJ5IGNvbWJpbmluZyByZXBvc2l0b3J5IHByb21wdHMgd2l0aCB0aGUgdGFyZ2V0IHNvdXJjZSBjb2RlLlwiLFxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIGV4ZWN1dGU6IGFzeW5jIChpbnB1dCwgX2NvbnRleHQpOiBQcm9taXNlPENvbnRlbnRSZXN1bHQ+ID0+IHtcbiAgICBjb25zdCBhcmdzID0gZG9jdW1lbnRDb2RlU2NoZW1hLnBhcnNlKGlucHV0IGFzIERvY3VtZW50Q29kZUFyZ3MpO1xuICAgIGNvbnN0IHJvb3QgPSBnZXRXb3Jrc3BhY2VSb290KCk7XG4gICAgbGV0IGZpbGVQYXRoOiBzdHJpbmc7XG4gICAgdHJ5IHtcbiAgICAgIGZpbGVQYXRoID0gcmVzb2x2ZUluV29ya3NwYWNlKHJvb3QsIGFyZ3MuZmlsZVBhdGgpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBXb3Jrc3BhY2VFcnJvcikge1xuICAgICAgICByZXR1cm4gdGhyb3dVc2VyRXJyb3IoZXJyb3IubWVzc2FnZSk7XG4gICAgICB9XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuXG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKGZpbGVQYXRoKSkge1xuICAgICAgcmV0dXJuIHRocm93VXNlckVycm9yKGBDYW5ub3QgZG9jdW1lbnQgbWlzc2luZyBmaWxlIGF0ICR7YXJncy5maWxlUGF0aH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBmaWxlQ29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhmaWxlUGF0aCwge1xuICAgICAgZW5jb2Rpbmc6IGFyZ3MuZW5jb2RpbmcgYXMgQnVmZmVyRW5jb2RpbmcsXG4gICAgfSk7XG4gICAgLy8gZHluYW1pY2FsbHkgaW1wb3J0IHByb21wdCBoZWxwZXJzXG4gICAgY29uc3QgcHJvbXB0TW9kID0gYXdhaXQgaW1wb3J0KFwiLi4vcHJvbXB0cy9wcm9tcHRzXCIpO1xuICAgIGNvbnN0IHtcbiAgICAgIGRpc2NvdmVyRG9jUHJvbXB0cyxcbiAgICAgIHNlbGVjdFByb21wdCxcbiAgICAgIERFRkFVTFRfUFJPTVBUX05BTUUsXG4gICAgICBidWlsZERvY3VtZW50YXRpb25QYXlsb2FkLFxuICAgIH0gPSBwcm9tcHRNb2Q7XG4gICAgY29uc3QgcHJvbXB0cyA9IGRpc2NvdmVyRG9jUHJvbXB0cyhyb290KTtcblxuICAgIGlmICghcHJvbXB0cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiB0aHJvd1VzZXJFcnJvcihcbiAgICAgICAgXCJObyBkb2N1bWVudGF0aW9uIHByb21wdHMgZm91bmQgdW5kZXIgLmNvZGUvcHJvbXB0cyBvciAuY29kZXgvcHJvbXB0c1wiXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHByb21wdCA9IHNlbGVjdFByb21wdChcbiAgICAgIHByb21wdHMsXG4gICAgICBhcmdzLnByb21wdE5hbWUgPz8gREVGQVVMVF9QUk9NUFRfTkFNRVxuICAgICk7XG5cbiAgICByZXR1cm4gYnVpbGREb2N1bWVudGF0aW9uUGF5bG9hZCh7XG4gICAgICBmaWxlUGF0aDogYXJncy5maWxlUGF0aCxcbiAgICAgIGZpbGVDb250ZW50LFxuICAgICAgcHJvbXB0LFxuICAgICAgaW5jbHVkZUNvZGU6IGFyZ3MuaW5jbHVkZUNvZGUsXG4gICAgICBpbmNsdWRlUHJvbXB0OiBhcmdzLmluY2x1ZGVQcm9tcHQsXG4gICAgICBpbmNsdWRlTWV0YWRhdGE6IGFyZ3MuaW5jbHVkZU1ldGFkYXRhLFxuICAgICAgYWRkaXRpb25hbENvbnRleHQ6IGFyZ3MuYWRkaXRpb25hbENvbnRleHQsXG4gICAgfSk7XG4gIH0sXG4gIG5hbWU6IFwiZG9jdW1lbnQtY29kZVwiLFxuICBwYXJhbWV0ZXJzOiBkb2N1bWVudENvZGVTY2hlbWEsXG59O1xuXG5leHBvcnQgY29uc3QgYXBwbHlDb2RlQ2hhbmdlVG9vbDogVG9vbDx1bmRlZmluZWQsIHR5cGVvZiBjb2RlQ2hhbmdlU2NoZW1hPiA9IHtcbiAgYW5ub3RhdGlvbnM6IHtcbiAgICBkZXN0cnVjdGl2ZUhpbnQ6IHRydWUsXG4gICAgaWRlbXBvdGVudEhpbnQ6IGZhbHNlLFxuICAgIG9wZW5Xb3JsZEhpbnQ6IGZhbHNlLFxuICAgIHJlYWRPbmx5SGludDogZmFsc2UsXG4gICAgdGl0bGU6IFwiQXBwbHkgQ29kZSBQYXRjaFwiLFxuICB9LFxuICBkZXNjcmlwdGlvbjpcbiAgICBcIkFwcGx5IGEgdW5pZmllZCBkaWZmIHBhdGNoIHRvIGEgd29ya3NwYWNlIGZpbGUgd2l0aCBvcHRpb25hbCBkcnktcnVuIHZhbGlkYXRpb24gYW5kIGRpZmYgcHJldmlldy5cIixcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBleGVjdXRlOiBhc3luYyAoaW5wdXQsIF9jb250ZXh0KTogUHJvbWlzZTxzdHJpbmcgfCBDb250ZW50UmVzdWx0PiA9PiB7XG4gICAgY29uc3QgYXJncyA9IGNvZGVDaGFuZ2VTY2hlbWEucGFyc2UoaW5wdXQgYXMgQXBwbHlDb2RlQ2hhbmdlQXJncyk7XG4gICAgY29uc3Qgcm9vdCA9IGdldFdvcmtzcGFjZVJvb3QoKTtcbiAgICBsZXQgZmlsZVBhdGg6IHN0cmluZztcbiAgICB0cnkge1xuICAgICAgZmlsZVBhdGggPSByZXNvbHZlSW5Xb3Jrc3BhY2Uocm9vdCwgYXJncy5maWxlUGF0aCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFdvcmtzcGFjZUVycm9yKSB7XG4gICAgICAgIHJldHVybiB0aHJvd1VzZXJFcnJvcihlcnJvci5tZXNzYWdlKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cblxuICAgIGNvbnN0IG9yaWdpbmFsID0gZnMuZXhpc3RzU3luYyhmaWxlUGF0aClcbiAgICAgID8gZnMucmVhZEZpbGVTeW5jKGZpbGVQYXRoLCBhcmdzLmVuY29kaW5nIGFzIEJ1ZmZlckVuY29kaW5nKVxuICAgICAgOiBcIlwiO1xuXG4gICAgbGV0IHBhdGNoZWQ6IHN0cmluZyB8IGZhbHNlO1xuICAgIHRyeSB7XG4gICAgICBwYXRjaGVkID0gYXBwbHlQYXRjaChvcmlnaW5hbCwgYXJncy5wYXRjaCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiB0aHJvd1VzZXJFcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byBhcHBseSBwcm92aWRlZCBwYXRjaCB0byAke2FyZ3MuZmlsZVBhdGh9OiAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogZXJyb3J9YFxuICAgICAgKTtcbiAgICB9XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICBpZiAocGF0Y2hlZCA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybiB0aHJvd1VzZXJFcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byBhcHBseSBwcm92aWRlZCBwYXRjaCB0byAke2FyZ3MuZmlsZVBhdGh9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoIWFyZ3MuZHJ5UnVuKSB7XG4gICAgICBmcy5ta2RpclN5bmMocGF0aC5kaXJuYW1lKGZpbGVQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICBmcy53cml0ZUZpbGVTeW5jKGZpbGVQYXRoLCBwYXRjaGVkLCB7XG4gICAgICAgIGVuY29kaW5nOiBhcmdzLmVuY29kaW5nIGFzIEJ1ZmZlckVuY29kaW5nLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKCFhcmdzLnNob3dEaWZmKSB7XG4gICAgICByZXR1cm4gYFBhdGNoICR7YXJncy5kcnlSdW4gPyBcInZhbGlkYXRlZFwiIDogXCJhcHBsaWVkXCJ9IGZvciAke2FyZ3MuZmlsZVBhdGh9YDtcbiAgICB9XG5cbiAgICBjb25zdCBwcmV2aWV3ID0gY3JlYXRlVHdvRmlsZXNQYXRjaChcbiAgICAgIGFyZ3MuZmlsZVBhdGgsXG4gICAgICBhcmdzLmZpbGVQYXRoLFxuICAgICAgb3JpZ2luYWwsXG4gICAgICBwYXRjaGVkLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgeyBjb250ZXh0OiBhcmdzLmRpZmZDb250ZXh0IH1cbiAgICApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGBQYXRjaCAke2FyZ3MuZHJ5UnVuID8gXCJ2YWxpZGF0ZWRcIiA6IFwiYXBwbGllZFwifSBmb3IgJHthcmdzLmZpbGVQYXRofWAsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICB0ZXh0OiBbXCJgYGBkaWZmXCIsIHByZXZpZXcudHJpbSgpLCBcImBgYFwiXS5qb2luKFwiXFxuXCIpLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9IHNhdGlzZmllcyBDb250ZW50UmVzdWx0O1xuICB9LFxuICBuYW1lOiBcImFwcGx5LWNvZGUtY2hhbmdlXCIsXG4gIHBhcmFtZXRlcnM6IGNvZGVDaGFuZ2VTY2hlbWEsXG59O1xuXG50eXBlIEFueVRvb2wgPSBUb29sPHVuZGVmaW5lZCwgYW55PjtcblxuY29uc3QgYW5hbHl0aWNUb29sczogQW55VG9vbFtdID0gW1xuICBidWlsZEFuYWx5emVSZXBvc2l0b3J5VG9vbCgpLFxuICBidWlsZEVudW1lcmF0ZUNhcGFiaWxpdGllc1Rvb2woKSxcbiAgYnVpbGRQbGFuRmVhdHVyZVRvb2woKSxcbl07XG5cbmV4cG9ydCBjb25zdCB0b29sTGlzdDogQW55VG9vbFtdID0gW1xuICAuLi5hbmFseXRpY1Rvb2xzLFxuICBkb2N1bWVudENvZGVUb29sLFxuICBhcHBseUNvZGVDaGFuZ2VUb29sLFxuXTtcbiIsImltcG9ydCB7IG1vZHVsZVJlZ2lzdHJ5IH0gZnJvbSBcIi4uL21vZHVsZVJlZ2lzdHJ5XCI7XG5pbXBvcnQge1xuICBjb3ZlcmFnZUVuZm9yY2VyVG9vbCxcbiAgZG9jdW1lbnRPYmplY3RUb29sLFxuICByZWFkbWVJbXByb3ZlbWVudFRvb2wsXG59IGZyb20gXCIuL2NvZGV4LXRvb2xzXCI7XG5pbXBvcnQgeyBkZWNvcmF0b3JUb29scyB9IGZyb20gXCIuLi9kZWNvcmF0b3ItdG9vbHNcIjtcbmNvbnN0IGNvZGV4VG9vbExpc3QgPSBbXG4gIGRvY3VtZW50T2JqZWN0VG9vbCxcbiAgY292ZXJhZ2VFbmZvcmNlclRvb2wsXG4gIHJlYWRtZUltcHJvdmVtZW50VG9vbCxcbl07XG5cbmltcG9ydCB7IHRvb2xMaXN0IGFzIGNvcmVUb29sTGlzdCB9IGZyb20gXCIuL3Rvb2xzXCI7XG5cbmNvbnN0IG1vZHVsZVRvb2xMaXN0ID0gbW9kdWxlUmVnaXN0cnlcbiAgLmxpc3RUb29scygpXG4gIC5tYXAoKGFzc2V0KSA9PiBhc3NldC50b29sIGFzIGFueSk7XG5cbmV4cG9ydCBjb25zdCB0b29sTGlzdCA9IFsuLi5jb3JlVG9vbExpc3QsIC4uLmNvZGV4VG9vbExpc3QsIC4uLm1vZHVsZVRvb2xMaXN0XTtcbmNvbnN0IFtcbiAgYW5hbHl6ZVJlcG9zaXRvcnlUb29sLFxuICBlbnVtZXJhdGVDYXBhYmlsaXRpZXNUb29sLFxuICBwbGFuRmVhdHVyZVRvb2wsXG4gIGRvY3VtZW50Q29kZVRvb2xSZWYsXG4gIGFwcGx5Q29kZUNoYW5nZVRvb2xSZWYsXG5dID0gY29yZVRvb2xMaXN0O1xuXG5leHBvcnQgY29uc3QgdG9vbHMgPSB7XG4gIGFuYWx5emVSZXBvc2l0b3J5VG9vbCxcbiAgZW51bWVyYXRlQ2FwYWJpbGl0aWVzVG9vbCxcbiAgcGxhbkZlYXR1cmVUb29sLFxuICBkb2N1bWVudENvZGVUb29sOiBkb2N1bWVudENvZGVUb29sUmVmLFxuICBhcHBseUNvZGVDaGFuZ2VUb29sOiBhcHBseUNvZGVDaGFuZ2VUb29sUmVmLFxuICBkb2N1bWVudE9iamVjdFRvb2wsXG4gIGNvdmVyYWdlRW5mb3JjZXJUb29sLFxuICByZWFkbWVJbXByb3ZlbWVudFRvb2wsXG4gIC4uLmRlY29yYXRvclRvb2xzLFxufTtcbmV4cG9ydCB7IGRlY29yYXRvclRvb2xzIH07XG4iLCJpbXBvcnQgdHlwZSB7IFJlc291cmNlIH0gZnJvbSBcImZhc3RtY3BcIjtcbmltcG9ydCB0eXBlIHsgUmVzb3VyY2VBc3NldCB9IGZyb20gXCIuLi8uLi90eXBlc1wiO1xuaW1wb3J0IHsgbW9kdWxlUmVnaXN0cnkgfSBmcm9tIFwiLi4vbW9kdWxlUmVnaXN0cnlcIjtcbmltcG9ydCB7IGdldFdvcmtzcGFjZVJvb3QgfSBmcm9tIFwiLi4vd29ya3NwYWNlXCI7XG5pbXBvcnQgeyBidWlsZE9iamVjdFByb21wdHMsIGRpc2NvdmVyRG9jUHJvbXB0cyB9IGZyb20gXCIuLi9wcm9tcHRzL3Byb21wdHNcIjtcblxuZnVuY3Rpb24gdG9SZXNvdXJjZShhc3NldDogUmVzb3VyY2VBc3NldCk6IFJlc291cmNlPHVuZGVmaW5lZD4ge1xuICByZXR1cm4ge1xuICAgIG5hbWU6IGFzc2V0LmlkLFxuICAgIHVyaTogYXNzZXQudXJpLFxuICAgIGRlc2NyaXB0aW9uOiBhc3NldC5kZXNjcmlwdGlvbiA/PyBhc3NldC50aXRsZSxcbiAgICBtaW1lVHlwZTogYXNzZXQubWltZVR5cGUsXG4gICAgbG9hZDogYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYXNzZXQubG9hZCgpO1xuICAgICAgLy8gYXNzZXQubG9hZCBtYXkgcmV0dXJuIGEgQ29udGVudFJlc3VsdCBvciBhIFByb21pc2Ugb2YgQ29udGVudFJlc3VsdDsgZW5zdXJlIHdlIHJldHVybiBSZXNvdXJjZVJlc3VsdC1saWtlIG9iamVjdFxuICAgICAgaWYgKChyZXMgYXMgYW55KT8uY29udGVudCkge1xuICAgICAgICBjb25zdCBjciA9IHJlcyBhcyBhbnk7XG4gICAgICAgIC8vIElmIENvbnRlbnRSZXN1bHQsIGNvbnZlcnQgdG8gc2ltcGxlIHRleHQgcmVzdWx0IGV4cGVjdGVkIGJ5IFJlc291cmNlLmxvYWQgY29uc3VtZXJzXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdGV4dDogQXJyYXkuaXNBcnJheShjci5jb250ZW50KVxuICAgICAgICAgICAgPyBjci5jb250ZW50Lm1hcCgoYzogYW55KSA9PiBjLnRleHQpLmpvaW4oXCJcXG5cIilcbiAgICAgICAgICAgIDogU3RyaW5nKGNyKSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIC8vIGZhbGxiYWNrIGZvciBvYmplY3RzIHdpdGggdGV4dFxuICAgICAgcmV0dXJuIHJlcyBhcyBhbnkgYXMgeyB0ZXh0OiBzdHJpbmcgfTtcbiAgICB9LFxuICB9O1xufVxuXG5mdW5jdGlvbiBidWlsZE1vZHVsZVJlc291cmNlcygpOiBSZXNvdXJjZTx1bmRlZmluZWQ+W10ge1xuICByZXR1cm4gbW9kdWxlUmVnaXN0cnkubGlzdFJlc291cmNlcygpLm1hcCh0b1Jlc291cmNlKTtcbn1cblxuZXhwb3J0IGNvbnN0IHJlc291cmNlczogUmVzb3VyY2U8dW5kZWZpbmVkPltdID0gW1xuICB7XG4gICAgbmFtZTogXCJjb2RleC1wcm9tcHQtaW5kZXhcIixcbiAgICB1cmk6IFwiY29kZXg6Ly9wcm9tcHRzL2luZGV4XCIsXG4gICAgZGVzY3JpcHRpb246XG4gICAgICBcIkVudW1lcmF0ZSBhdmFpbGFibGUgLmNvZGV4IHByb21wdCBmaWxlcyB3aXRoIHRpdGxlcyBhbmQgZGVzY3JpcHRpb25zLlwiLFxuICAgIG1pbWVUeXBlOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICBsb2FkOiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCByb290ID0gZ2V0V29ya3NwYWNlUm9vdCgpO1xuICAgICAgY29uc3QgcHJvbXB0cyA9IGRpc2NvdmVyRG9jUHJvbXB0cyhyb290KS5tYXAoKHByb21wdCkgPT4gKHtcbiAgICAgICAgbmFtZTogcHJvbXB0Lm5hbWUsXG4gICAgICAgIHRpdGxlOiBwcm9tcHQudGl0bGUsXG4gICAgICAgIGRlc2NyaXB0aW9uOiBwcm9tcHQuZGVzY3JpcHRpb24sXG4gICAgICAgIHBhdGg6IHByb21wdC5hYnNvbHV0ZVBhdGgsXG4gICAgICB9KSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0ZXh0OiBKU09OLnN0cmluZ2lmeSh7IHByb21wdHMgfSwgbnVsbCwgMiksXG4gICAgICAgIG1pbWVUeXBlOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgIH07XG4gICAgfSxcbiAgfSxcbiAge1xuICAgIG5hbWU6IFwiY29kZXgtb2JqZWN0LXByb21wdHNcIixcbiAgICB1cmk6IFwiY29kZXg6Ly9wcm9tcHRzL29iamVjdHNcIixcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgIFwiUHJvdmlkZXMgdGhlIHJlc29sdmVkIHByb21wdCBjb250ZW50IGZvciBlYWNoIGRvY3VtZW50ZWQgb2JqZWN0IHdvcmtmbG93LlwiLFxuICAgIG1pbWVUeXBlOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICBsb2FkOiBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBlbnRyaWVzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGJ1aWxkT2JqZWN0UHJvbXB0cygpLm1hcChhc3luYyAocHJvbXB0KSA9PiAoe1xuICAgICAgICAgIG5hbWU6IHByb21wdC5uYW1lLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiBwcm9tcHQuZGVzY3JpcHRpb24sXG4gICAgICAgICAgY29udGVudDogYXdhaXQgcHJvbXB0LmxvYWQoe30gYXMgbmV2ZXIpLFxuICAgICAgICB9KSlcbiAgICAgICk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0ZXh0OiBKU09OLnN0cmluZ2lmeSh7IHByb21wdHM6IGVudHJpZXMgfSwgbnVsbCwgMiksXG4gICAgICAgIG1pbWVUeXBlOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgIH07XG4gICAgfSxcbiAgfSxcbiAgLi4uYnVpbGRNb2R1bGVSZXNvdXJjZXMoKSxcbl07XG4iLCJpbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHsgZ2V0V29ya3NwYWNlUm9vdCwgcmVzb2x2ZUluV29ya3NwYWNlIH0gZnJvbSBcIi4uL3dvcmtzcGFjZVwiO1xuaW1wb3J0IHR5cGUgeyBQcm9tcHRSZXNvdXJjZVRlbXBsYXRlIH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5cbmV4cG9ydCBjb25zdCBjb2RleFByb21wdFRlbXBsYXRlczogUHJvbXB0UmVzb3VyY2VUZW1wbGF0ZVtdID0gW107XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZENvZGV4UHJvbXB0VGVtcGxhdGVzKCk6IFByb21wdFJlc291cmNlVGVtcGxhdGVbXSB7XG4gIGNvbnN0IHJvb3QgPSBnZXRXb3Jrc3BhY2VSb290KCk7XG4gIGNvbnN0IHRlbXBsYXRlczogUHJvbXB0UmVzb3VyY2VUZW1wbGF0ZVtdID0gW1xuICAgIHtcbiAgICAgIG5hbWU6IFwiY29kZXgtcHJvbXB0XCIsXG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJMb2FkIGEgLmNvZGV4IHByb21wdCBmaWxlIGJ5IG5hbWUgKHdpdGhvdXQgZXh0ZW5zaW9uKSBhcyBtYXJrZG93bi5cIixcbiAgICAgIHVyaVRlbXBsYXRlOiBcImNvZGV4LXByb21wdDovL3tuYW1lfVwiLFxuICAgICAgbWltZVR5cGU6IFwidGV4dC9tYXJrZG93blwiLFxuICAgICAgYXJndW1lbnRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcIm5hbWVcIixcbiAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgIFwiTmFtZSBvZiB0aGUgcHJvbXB0IGZpbGUgaW5zaWRlIC5jb2RleC9wcm9tcHRzICh3aXRob3V0IC5tZCkuXCIsXG4gICAgICAgICAgcmVxdWlyZWQ6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgbG9hZDogYXN5bmMgKHsgbmFtZSB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHByb21wdFBhdGggPSByZXNvbHZlSW5Xb3Jrc3BhY2UoXG4gICAgICAgICAgcm9vdCxcbiAgICAgICAgICBwYXRoLmpvaW4oXCIuY29kZXhcIiwgXCJwcm9tcHRzXCIsIGAke25hbWV9Lm1kYClcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKHByb21wdFBhdGgpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBQcm9tcHQgLmNvZGV4L3Byb21wdHMvJHtuYW1lfS5tZCBub3QgZm91bmRgKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB0ZXh0ID0gZnMucmVhZEZpbGVTeW5jKHByb21wdFBhdGgsIFwidXRmOFwiKTtcbiAgICAgICAgcmV0dXJuIHsgdGV4dCwgdXJpOiBgY29kZXgtcHJvbXB0Oi8vLyR7bmFtZX1gIH07XG4gICAgICB9LFxuICAgIH0sXG4gIF07XG5cbiAgY29kZXhQcm9tcHRUZW1wbGF0ZXMuc3BsaWNlKDAsIGNvZGV4UHJvbXB0VGVtcGxhdGVzLmxlbmd0aCwgLi4udGVtcGxhdGVzKTtcbiAgcmV0dXJuIGNvZGV4UHJvbXB0VGVtcGxhdGVzO1xufVxuIiwiaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB0eXBlIHsgRGVjb3JhdGlvblJlc291cmNlVGVtcGxhdGUgfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IGdldFdvcmtzcGFjZVJvb3QsIHJlYWRXb3Jrc3BhY2VGaWxlIH0gZnJvbSBcIi4uL3dvcmtzcGFjZVwiO1xuXG5leHBvcnQgY29uc3QgZGVjb3JhdGlvblJlc291cmNlVGVtcGxhdGVzOiBEZWNvcmF0aW9uUmVzb3VyY2VUZW1wbGF0ZVtdID0gW107XG5cbmZ1bmN0aW9uIG1ha2VMb2FkZXIodHlwZTogXCJzcmNcIiB8IFwidGVzdHNcIiB8IFwid29ya2RvY3NcIikge1xuICByZXR1cm4gYXN5bmMgKHsgcGF0aDogcmVsYXRpdmUgfTogeyBwYXRoOiBzdHJpbmcgfSkgPT4ge1xuICAgIGNvbnN0IHJvb3QgPSBnZXRXb3Jrc3BhY2VSb290KCk7XG4gICAgY29uc3QgdGFyZ2V0ID0gcGF0aC5qb2luKHR5cGUsIHJlbGF0aXZlKTtcbiAgICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVhZFdvcmtzcGFjZUZpbGUocm9vdCwgdGFyZ2V0KTtcbiAgICByZXR1cm4geyB0ZXh0IH07XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZERlY29yYXRpb25SZXNvdXJjZVRlbXBsYXRlcygpOiBEZWNvcmF0aW9uUmVzb3VyY2VUZW1wbGF0ZVtdIHtcbiAgY29uc3QgdGVtcGxhdGVzOiBEZWNvcmF0aW9uUmVzb3VyY2VUZW1wbGF0ZVtdID0gW1xuICAgIHtcbiAgICAgIG5hbWU6IFwicmVhZC1jb2RlLWZyb20tc291cmNlXCIsXG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJSZWFkIGEgZmlsZSBmcm9tIHRoZSA8YmFzZV9wYXRoPi9zcmMgdHJlZSBieSByZWxhdGl2ZSBwYXRoLlwiLFxuICAgICAgbWltZVR5cGU6IFwidGV4dC9wbGFpblwiLFxuICAgICAgdXJpVGVtcGxhdGU6IFwiZnJvbS1zb3VyY2U6Ly9zcmMve3BhdGh9XCIsXG4gICAgICBhcmd1bWVudHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwicGF0aFwiLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgXCJQYXRoIHVuZGVyIDxiYXNlX3BhdGg+L3NyYyB0byBsb2FkLCBlLmcuICdkZWNvcmF0aW9uL3R5cGVzLnRzJ1wiLFxuICAgICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGxvYWQ6IG1ha2VMb2FkZXIoXCJzcmNcIiksXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiBcInJlYWQtdGVzdC1mcm9tLXNvdXJjZVwiLFxuICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgIFwiUmVhZCBhIGZpbGUgZnJvbSB0aGUgPGJhc2VfcGF0aD4vdGVzdHMgdHJlZSBieSByZWxhdGl2ZSBwYXRoLlwiLFxuICAgICAgbWltZVR5cGU6IFwidGV4dC9wbGFpblwiLFxuICAgICAgdXJpVGVtcGxhdGU6IFwiZnJvbS1zb3VyY2U6Ly90ZXN0cy97cGF0aH1cIixcbiAgICAgIGFyZ3VtZW50czogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJwYXRoXCIsXG4gICAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgICBcIlBhdGggdW5kZXIgPGJhc2VfcGF0aD4vdGVzdHMgdG8gbG9hZCwgZS5nLiAnZGVjb3JhdGlvbi90ZXN0cy90eXBlcy50ZXN0LnRzJ1wiLFxuICAgICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGxvYWQ6IG1ha2VMb2FkZXIoXCJ0ZXN0c1wiKSxcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6IFwicmVhZC1kb2MtZnJvbS1zb3VyY2VcIixcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICBcIlJlYWQgYSBmaWxlIGZyb20gdGhlIDxiYXNlX3BhdGg+L3dvcmtkb2NzIHRyZWUgYnkgcmVsYXRpdmUgcGF0aC5cIixcbiAgICAgIG1pbWVUeXBlOiBcInRleHQvcGxhaW5cIixcbiAgICAgIHVyaVRlbXBsYXRlOiBcImZyb20tc291cmNlOi8vd29ya2RvY3Mve3BhdGh9XCIsXG4gICAgICBhcmd1bWVudHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwicGF0aFwiLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgXCJQYXRoIHVuZGVyIDxiYXNlX3BhdGg+L3dvcmtkb2NzIHRvIGxvYWQsIGUuZy4gJ2RlY29yYXRpb24vd29ya2RvY3MvdHV0b3JpYWxzL2Zvci1kZXZlbG9wZXJzLm1kJ1wiLFxuICAgICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGxvYWQ6IG1ha2VMb2FkZXIoXCJ3b3JrZG9jc1wiKSxcbiAgICB9LFxuICBdO1xuXG4gIGRlY29yYXRpb25SZXNvdXJjZVRlbXBsYXRlcy5zcGxpY2UoXG4gICAgMCxcbiAgICBkZWNvcmF0aW9uUmVzb3VyY2VUZW1wbGF0ZXMubGVuZ3RoLFxuICAgIC4uLnRlbXBsYXRlc1xuICApO1xuICByZXR1cm4gZGVjb3JhdGlvblJlc291cmNlVGVtcGxhdGVzO1xufVxuIiwiaW1wb3J0IHsgV29ya3NwYWNlUmVzb3VyY2VUZW1wbGF0ZSB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgZ2V0V29ya3NwYWNlUm9vdCwgcmVhZFdvcmtzcGFjZUZpbGUgfSBmcm9tIFwiLi4vd29ya3NwYWNlXCI7XG5cbmV4cG9ydCBjb25zdCB3b3Jrc3BhY2VSZXNvdXJjZVRlbXBsYXRlczogV29ya3NwYWNlUmVzb3VyY2VUZW1wbGF0ZVtdID0gW107XG5cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFdvcmtzcGFjZVJlc291cmNlVGVtcGxhdGVzKCk6IFdvcmtzcGFjZVJlc291cmNlVGVtcGxhdGVbXSB7XG4gIGNvbnN0IHJvb3QgPSBnZXRXb3Jrc3BhY2VSb290KCk7XG4gIGNvbnN0IHNoYXJlZEFyZ3VtZW50cyA9IFtcbiAgICB7XG4gICAgICBuYW1lOiBcInBhdGhcIixcbiAgICAgIGRlc2NyaXB0aW9uOiBcIlBhdGggcmVsYXRpdmUgdG8gdGhlIHdvcmtzcGFjZSByb290XCIsXG4gICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICB9LFxuICBdIGFzIGNvbnN0O1xuXG4gIGNvbnN0IHRlbXBsYXRlczogV29ya3NwYWNlUmVzb3VyY2VUZW1wbGF0ZVtdID0gW1xuICAgIHtcbiAgICAgIG5hbWU6IFwidnNjb2RlLXdvcmtzcGFjZS1maWxlXCIsXG4gICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgXCJFeHBvc2Ugd29ya3NwYWNlIGZpbGVzIHRvIFZpc3VhbCBTdHVkaW8gQ29kZSB2aWEgdnNjb2RlOi8vIFVSSXNcIixcbiAgICAgIHVyaVRlbXBsYXRlOiBcInZzY29kZTovL3dvcmtzcGFjZS97cGF0aH1cIixcbiAgICAgIG1pbWVUeXBlOiBcInRleHQvcGxhaW5cIixcbiAgICAgIGFyZ3VtZW50czogc2hhcmVkQXJndW1lbnRzLFxuICAgICAgbG9hZDogYXN5bmMgKGFyZ3M6IHsgcGF0aDogc3RyaW5nIH0pID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVhZFdvcmtzcGFjZUZpbGUocm9vdCwgYXJncy5wYXRoKTtcbiAgICAgICAgICByZXR1cm4geyB0ZXh0OiBTdHJpbmcodGV4dCkgfTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgLy8gcHJvcGFnYXRlIGFzLWlzIGZvciB0ZXN0cyB0byBhc3NlcnQgZXJyb3JzXG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogXCJjdXJzb3Itd29ya3NwYWNlLWZpbGVcIixcbiAgICAgIGRlc2NyaXB0aW9uOiBcIkV4cG9zZSB3b3Jrc3BhY2UgZmlsZXMgdG8gQ3Vyc29yIHZpYSBjdXJzb3I6Ly8gVVJJc1wiLFxuICAgICAgdXJpVGVtcGxhdGU6IFwiY3Vyc29yOi8vd29ya3NwYWNlL3twYXRofVwiLFxuICAgICAgbWltZVR5cGU6IFwidGV4dC9wbGFpblwiLFxuICAgICAgYXJndW1lbnRzOiBzaGFyZWRBcmd1bWVudHMsXG4gICAgICBsb2FkOiBhc3luYyAoYXJnczogeyBwYXRoOiBzdHJpbmcgfSkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHRleHQgPSBhd2FpdCByZWFkV29ya3NwYWNlRmlsZShyb290LCBhcmdzLnBhdGgpO1xuICAgICAgICAgIHJldHVybiB7IHRleHQ6IFN0cmluZyh0ZXh0KSB9O1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiBcImNvcGlsb3Qtd29ya3NwYWNlLWZpbGVcIixcbiAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICBcIkV4cG9zZSB3b3Jrc3BhY2UgZmlsZXMgdG8gR2l0SHViIENvcGlsb3QgdmlhIGNvcGlsb3Q6Ly8gVVJJc1wiLFxuICAgICAgdXJpVGVtcGxhdGU6IFwiY29waWxvdDovL3dvcmtzcGFjZS97cGF0aH1cIixcbiAgICAgIG1pbWVUeXBlOiBcInRleHQvcGxhaW5cIixcbiAgICAgIGFyZ3VtZW50czogc2hhcmVkQXJndW1lbnRzLFxuICAgICAgbG9hZDogYXN5bmMgKGFyZ3M6IHsgcGF0aDogc3RyaW5nIH0pID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVhZFdvcmtzcGFjZUZpbGUocm9vdCwgYXJncy5wYXRoKTtcbiAgICAgICAgICByZXR1cm4geyB0ZXh0OiBTdHJpbmcodGV4dCkgfTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG4gIF07XG5cbiAgd29ya3NwYWNlUmVzb3VyY2VUZW1wbGF0ZXMuc3BsaWNlKFxuICAgIDAsXG4gICAgd29ya3NwYWNlUmVzb3VyY2VUZW1wbGF0ZXMubGVuZ3RoLFxuICAgIC4uLnRlbXBsYXRlc1xuICApO1xuICByZXR1cm4gd29ya3NwYWNlUmVzb3VyY2VUZW1wbGF0ZXM7XG59XG5cbiIsImltcG9ydCB7IGJ1aWxkQ29kZXhQcm9tcHRUZW1wbGF0ZXMgfSBmcm9tIFwiLi9jb2RleC10ZW1wbGF0ZXNcIjtcbmltcG9ydCB7IGJ1aWxkRGVjb3JhdGlvblJlc291cmNlVGVtcGxhdGVzIH0gZnJvbSBcIi4vcmVzb3VyY2UtdGVtcGxhdGVzXCI7XG5pbXBvcnQgeyBidWlsZFdvcmtzcGFjZVJlc291cmNlVGVtcGxhdGVzIH0gZnJvbSBcIi4vd29ya3NwYWNlLXRlbXBsYXRlc1wiO1xuaW1wb3J0IHsgbW9kdWxlUmVnaXN0cnkgfSBmcm9tIFwiLi4vbW9kdWxlUmVnaXN0cnlcIjtcblxuZXhwb3J0IHtcbiAgYnVpbGRDb2RleFByb21wdFRlbXBsYXRlcyxcbiAgY29kZXhQcm9tcHRUZW1wbGF0ZXMsXG59IGZyb20gXCIuL2NvZGV4LXRlbXBsYXRlc1wiO1xuZXhwb3J0IHtcbiAgYnVpbGREZWNvcmF0aW9uUmVzb3VyY2VUZW1wbGF0ZXMsXG4gIGRlY29yYXRpb25SZXNvdXJjZVRlbXBsYXRlcyxcbn0gZnJvbSBcIi4vcmVzb3VyY2UtdGVtcGxhdGVzXCI7XG5leHBvcnQge1xuICBidWlsZFdvcmtzcGFjZVJlc291cmNlVGVtcGxhdGVzLFxuICB3b3Jrc3BhY2VSZXNvdXJjZVRlbXBsYXRlcyxcbn0gZnJvbSBcIi4vd29ya3NwYWNlLXRlbXBsYXRlc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRSZXNvdXJjZVRlbXBsYXRlcygpIHtcbiAgY29uc3QgbW9kdWxlVGVtcGxhdGVzID0gbW9kdWxlUmVnaXN0cnkubGlzdFRlbXBsYXRlcygpLm1hcCgodGVtcGxhdGUpID0+ICh7XG4gICAgbmFtZTogdGVtcGxhdGUuaWQsXG4gICAgZGVzY3JpcHRpb246IHRlbXBsYXRlLmRlc2NyaXB0aW9uID8/IHRlbXBsYXRlLnRpdGxlLFxuICAgIG1pbWVUeXBlOiBcInRleHQvbWFya2Rvd25cIixcbiAgICB1cmlUZW1wbGF0ZTogYG1vZHVsZS10ZW1wbGF0ZTovLyR7dGVtcGxhdGUuaWR9YCxcbiAgICBhcmd1bWVudHM6ICh0ZW1wbGF0ZS5wbGFjZWhvbGRlcnMgPz8gW10pLm1hcCgobmFtZSkgPT4gKHtcbiAgICAgIG5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogYFZhbHVlIGZvciAke25hbWV9YCxcbiAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgIH0pKSxcbiAgICBsb2FkOiBhc3luYyAoKSA9PiAoe1xuICAgICAgdGV4dDpcbiAgICAgICAgdHlwZW9mICh0ZW1wbGF0ZSBhcyBhbnkpLmNvbnRlbnQgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICA/ICh0ZW1wbGF0ZSBhcyBhbnkpLmNvbnRlbnRcbiAgICAgICAgICA6IGAjICR7dGVtcGxhdGUuZGVzY3JpcHRpb24gPz8gdGVtcGxhdGUudGl0bGUgPz8gdGVtcGxhdGUuaWR9XFxuXFxuTm8gdGVtcGxhdGUgY29udGVudCBhdmFpbGFibGUgZm9yICR7dGVtcGxhdGUuaWR9YCxcbiAgICB9KSxcbiAgfSkpO1xuXG4gIGNvbnN0IGFsbCA9IFtcbiAgICAuLi5idWlsZFdvcmtzcGFjZVJlc291cmNlVGVtcGxhdGVzKCksXG4gICAgLi4uYnVpbGRDb2RleFByb21wdFRlbXBsYXRlcygpLFxuICAgIC4uLmJ1aWxkRGVjb3JhdGlvblJlc291cmNlVGVtcGxhdGVzKCksXG4gICAgLi4ubW9kdWxlVGVtcGxhdGVzLFxuICBdO1xuXG4gIC8vIE5vcm1hbGlzZSBhbGwgbG9hZGVycyB0byBhbHdheXMgcmV0dXJuIHsgdGV4dDogc3RyaW5nIH1cbiAgZnVuY3Rpb24gbm9ybWFsaXNlUmVzdWx0KHJlczogYW55KSB7XG4gICAgaWYgKHJlcyA9PSBudWxsKSByZXR1cm4geyB0ZXh0OiBcIlwiIH07XG4gICAgaWYgKHR5cGVvZiByZXMgPT09IFwic3RyaW5nXCIpIHJldHVybiB7IHRleHQ6IHJlcyB9O1xuICAgIGlmICh0eXBlb2YgcmVzLnRleHQgPT09IFwic3RyaW5nXCIpIHJldHVybiByZXM7XG4gICAgLy8gaGFuZGxlIGxlZ2FjeSBDb250ZW50UmVzdWx0IHNoYXBlcyB3aXRoIGNvbnRlbnQgb3IgY29udGVudCBhcnJheVxuICAgIGlmIChBcnJheS5pc0FycmF5KHJlcy5jb250ZW50KSkge1xuICAgICAgY29uc3QgcGFydHMgPSByZXMuY29udGVudFxuICAgICAgICAubWFwKChjOiBhbnkpID0+IChjICYmIHR5cGVvZiBjLnRleHQgPT09IFwic3RyaW5nXCIgPyBjLnRleHQgOiBTdHJpbmcoYykpKVxuICAgICAgICAuam9pbihcIlxcblwiKTtcbiAgICAgIHJldHVybiB7IHRleHQ6IHBhcnRzIH07XG4gICAgfVxuICAgIGlmIChyZXMuY29udGVudCAmJiB0eXBlb2YgcmVzLmNvbnRlbnQudGV4dCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgcmV0dXJuIHsgdGV4dDogcmVzLmNvbnRlbnQudGV4dCB9O1xuICAgIH1cbiAgICAvLyBmYWxsYmFjazogc3RyaW5naWZ5XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB7IHRleHQ6IEpTT04uc3RyaW5naWZ5KHJlcykgfTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiB7IHRleHQ6IFN0cmluZyhyZXMpIH07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGFsbC5tYXAoKHQpID0+ICh7XG4gICAgLi4udCxcbiAgICBsb2FkOiBhc3luYyAoYXJnczogYW55KSA9PiB7XG4gICAgICBjb25zdCByYXcgPSBhd2FpdCAodC5sb2FkIGFzIGFueSkoYXJncyk7XG4gICAgICByZXR1cm4gbm9ybWFsaXNlUmVzdWx0KHJhdyk7XG4gICAgfSxcbiAgfSkpO1xufVxuXG5leHBvcnQgY29uc3QgdGVtcGxhdGVMaXN0ID0gYnVpbGRSZXNvdXJjZVRlbXBsYXRlcygpO1xuIiwiaW1wb3J0IHsgTWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRpb25cIjtcblxuLyoqXG4gKiBAY29uc3QgVkVSU0lPTlxuICogQG5hbWUgVkVSU0lPTlxuICogQGRlc2NyaXB0aW9uIFJlcHJlc2VudHMgdGhlIGN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgdHMtd29ya3NwYWNlIG1vZHVsZS5cbiAqIEBzdW1tYXJ5IFRoZSBhY3R1YWwgdmVyc2lvbiBudW1iZXIgaXMgcmVwbGFjZWQgZHVyaW5nIHRoZSBidWlsZCBwcm9jZXNzLlxuICogQHR5cGUge3N0cmluZ31cbiAqL1xuZXhwb3J0IGNvbnN0IFZFUlNJT04gPSBcIiMjVkVSU0lPTiMjXCI7XG5leHBvcnQgY29uc3QgUEFDS0FHRV9OQU1FID0gXCIjI1BBQ0tBR0VfTkFNRSMjXCI7XG5cbnRyeSB7XG4gIE1ldGFkYXRhLnJlZ2lzdGVyTGlicmFyeShQQUNLQUdFX05BTUUsIFZFUlNJT04pO1xufSBjYXRjaCAoZXJyb3IpIHtcbiAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgJiYgZXJyb3IubWVzc2FnZS5pbmNsdWRlcyhcImFscmVhZHlcIikpIHtcbiAgICAvLyBJZ25vcmUgZHVwbGljYXRlIHJlZ2lzdHJhdGlvbiBkdXJpbmcgdGVzdHMvYnVuZGxpbmcgY2hlY2tzLlxuICB9IGVsc2Uge1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG4iLCJpbXBvcnQgdHlwZSB7IEZhc3RNQ1AgfSBmcm9tIFwiZmFzdG1jcFwiO1xuaW1wb3J0IHsgUEFDS0FHRV9OQU1FIGFzIFBLRywgVkVSU0lPTiBhcyBWIH0gZnJvbSBcIi4uL21ldGFkYXRhXCI7XG5pbXBvcnQgeyBsb2FkUHJvbXB0cywgcHJvbXB0TGlzdCB9IGZyb20gXCIuL3Byb21wdHNcIjtcbmltcG9ydCB7IHJlc291cmNlcyB9IGZyb20gXCIuL3Jlc291cmNlc1wiO1xuaW1wb3J0IHtcbiAgYnVpbGREZWNvcmF0aW9uUmVzb3VyY2VUZW1wbGF0ZXMsXG4gIGJ1aWxkUmVzb3VyY2VUZW1wbGF0ZXMsXG4gIGRlY29yYXRpb25SZXNvdXJjZVRlbXBsYXRlcyxcbiAgdGVtcGxhdGVMaXN0LFxuICB3b3Jrc3BhY2VSZXNvdXJjZVRlbXBsYXRlcyxcbn0gZnJvbSBcIi4vdGVtcGxhdGVzXCI7XG5pbXBvcnQgeyB0b29sTGlzdCwgdG9vbHMgfSBmcm9tIFwiLi90b29sc1wiO1xuaW1wb3J0IHtcbiAgX19yZXNldFdvcmtzcGFjZVJvb3QsXG4gIGdldFdvcmtzcGFjZVJvb3QsXG4gIHNldFdvcmtzcGFjZVJvb3QsXG59IGZyb20gXCIuL3dvcmtzcGFjZVwiO1xuXG5leHBvcnQgZnVuY3Rpb24gZW5yaWNoKG1jcDogRmFzdE1DUCk6IEZhc3RNQ1Age1xuICBjb25zdCBwcm9tcHRFbnRyaWVzID0gbG9hZFByb21wdHMoKTtcbiAgZm9yIChjb25zdCBwcm9tcHQgb2YgcHJvbXB0RW50cmllcykge1xuICAgIG1jcC5hZGRQcm9tcHQocHJvbXB0IGFzIGFueSk7XG4gIH1cblxuICBmb3IgKGNvbnN0IHRvb2wgb2YgdG9vbExpc3QpIHtcbiAgICBtY3AuYWRkVG9vbCh0b29sIGFzIGFueSk7XG4gIH1cblxuICBjb25zdCB0ZW1wbGF0ZXMgPSBidWlsZFJlc291cmNlVGVtcGxhdGVzKCk7XG4gIGZvciAoY29uc3QgdGVtcGxhdGUgb2YgdGVtcGxhdGVzKSB7XG4gICAgbWNwLmFkZFJlc291cmNlVGVtcGxhdGUodGVtcGxhdGUgYXMgYW55KTtcbiAgfVxuXG4gIGZvciAoY29uc3QgcmVzb3VyY2Ugb2YgcmVzb3VyY2VzKSB7XG4gICAgY29uc3QgYWRkUmVzb3VyY2UgPSAoXG4gICAgICBtY3AgYXMgdW5rbm93biBhcyB7IGFkZFJlc291cmNlPzogKHJlczogdW5rbm93bikgPT4gdm9pZCB9XG4gICAgKS5hZGRSZXNvdXJjZTtcbiAgICBpZiAodHlwZW9mIGFkZFJlc291cmNlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIGFkZFJlc291cmNlLmNhbGwobWNwLCByZXNvdXJjZSBhcyBhbnkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtY3A7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGVucmljaDtcbmV4cG9ydCBjb25zdCBQQUNLQUdFX05BTUUgPSBQS0c7XG5leHBvcnQgY29uc3QgVkVSU0lPTiA9IFY7XG5cbmV4cG9ydCB7XG4gIHRvb2xzLFxuICB0b29sTGlzdCxcbiAgYnVpbGREZWNvcmF0aW9uUmVzb3VyY2VUZW1wbGF0ZXMsXG4gIGJ1aWxkUmVzb3VyY2VUZW1wbGF0ZXMsXG4gIGRlY29yYXRpb25SZXNvdXJjZVRlbXBsYXRlcyxcbiAgcHJvbXB0TGlzdCxcbiAgcmVzb3VyY2VzLFxuICB0ZW1wbGF0ZUxpc3QsXG4gIHdvcmtzcGFjZVJlc291cmNlVGVtcGxhdGVzLFxuICBnZXRXb3Jrc3BhY2VSb290LFxuICBzZXRXb3Jrc3BhY2VSb290LFxuICBfX3Jlc2V0V29ya3NwYWNlUm9vdCxcbn07XG4iLCIvLyBOZXc6IHZhbGlkYXRpb24gZW50cnlwb2ludCBmb3IgbW9kdWxlIHN0cnVjdHVyZVxuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcblxuZXhwb3J0IHR5cGUgVmFsaWRhdGlvbklzc3VlID0ge1xuICBtb2R1bGU6IHN0cmluZztcbiAgcGF0aDogc3RyaW5nO1xuICB0eXBlOlxuICAgIHwgXCJtaXNzaW5nLWZvbGRlclwiXG4gICAgfCBcIm1pc3NpbmctZXhwb3J0XCJcbiAgICB8IFwiZW1wdHktbGlzdFwiXG4gICAgfCBcImRpc2FibGVkXCJcbiAgICB8IFwib3RoZXJcIjtcbiAgZGV0YWlsPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IHR5cGUgVmFsaWRhdGlvblJlcG9ydCA9IHtcbiAgb2s6IGJvb2xlYW47XG4gIG1vZHVsZXNDaGVja2VkOiBudW1iZXI7XG4gIGlzc3VlczogVmFsaWRhdGlvbklzc3VlW107XG59O1xuXG5jb25zdCBSRVFVSVJFRF9TVUJGT0xERVJTID0gW1wicHJvbXB0c1wiLCBcInJlc291cmNlc1wiLCBcInRlbXBsYXRlc1wiLCBcInRvb2xzXCJdO1xuXG5leHBvcnQgZnVuY3Rpb24gZmluZE1vZHVsZURpcnMocmVwb1Jvb3Q6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgbW9kdWxlc1BhdGggPSBwYXRoLnJlc29sdmUocmVwb1Jvb3QsIFwic3JjXCIsIFwibW9kdWxlc1wiKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKG1vZHVsZXNQYXRoKSB8fCAhZnMuc3RhdFN5bmMobW9kdWxlc1BhdGgpLmlzRGlyZWN0b3J5KCkpIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgcmV0dXJuIGZzXG4gICAgLnJlYWRkaXJTeW5jKG1vZHVsZXNQYXRoLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSlcbiAgICAuZmlsdGVyKChkKSA9PiBkLmlzRGlyZWN0b3J5KCkpXG4gICAgLm1hcCgoZCkgPT4gcGF0aC5qb2luKG1vZHVsZXNQYXRoLCBkLm5hbWUpKTtcbn1cblxuZnVuY3Rpb24gaGFzSW5kZXhFeHBvcnQoZm9sZGVyUGF0aDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IGNhbmRpZGF0ZXMgPSBbXG4gICAgXCJpbmRleC50c1wiLFxuICAgIFwiaW5kZXgudHN4XCIsXG4gICAgXCJpbmRleC5qc1wiLFxuICAgIFwiaW5kZXguY2pzXCIsXG4gICAgXCJpbmRleC5tanNcIixcbiAgXTtcbiAgZm9yIChjb25zdCBjIG9mIGNhbmRpZGF0ZXMpIHtcbiAgICBpZiAoZnMuZXhpc3RzU3luYyhwYXRoLmpvaW4oZm9sZGVyUGF0aCwgYykpKSByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZU1vZHVsZXMocmVwb1Jvb3Q6IHN0cmluZyk6IFZhbGlkYXRpb25SZXBvcnQge1xuICBjb25zdCBkaXJzID0gZmluZE1vZHVsZURpcnMocmVwb1Jvb3QpO1xuICBjb25zdCBpc3N1ZXM6IFZhbGlkYXRpb25Jc3N1ZVtdID0gW107XG5cbiAgZm9yIChjb25zdCBtb2R1bGVEaXIgb2YgZGlycykge1xuICAgIGNvbnN0IG1vZHVsZU5hbWUgPSBwYXRoLmJhc2VuYW1lKG1vZHVsZURpcik7XG4gICAgZm9yIChjb25zdCBzdWIgb2YgUkVRVUlSRURfU1VCRk9MREVSUykge1xuICAgICAgY29uc3Qgc3ViUGF0aCA9IHBhdGguam9pbihtb2R1bGVEaXIsIHN1Yik7XG4gICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoc3ViUGF0aCkgfHwgIWZzLnN0YXRTeW5jKHN1YlBhdGgpLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgaXNzdWVzLnB1c2goe1xuICAgICAgICAgIG1vZHVsZTogbW9kdWxlTmFtZSxcbiAgICAgICAgICBwYXRoOiBzdWJQYXRoLFxuICAgICAgICAgIHR5cGU6IFwibWlzc2luZy1mb2xkZXJcIixcbiAgICAgICAgICBkZXRhaWw6IGBSZXF1aXJlZCBmb2xkZXIgJyR7c3VifScgaXMgbWlzc2luZyBpbiBtb2R1bGUgJyR7bW9kdWxlTmFtZX0nYCxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgLy8gSWYgZm9sZGVyIGV4aXN0cywgY2hlY2sgZm9yIGluZGV4IGV4cG9ydFxuICAgICAgaWYgKCFoYXNJbmRleEV4cG9ydChzdWJQYXRoKSkge1xuICAgICAgICBpc3N1ZXMucHVzaCh7XG4gICAgICAgICAgbW9kdWxlOiBtb2R1bGVOYW1lLFxuICAgICAgICAgIHBhdGg6IHN1YlBhdGgsXG4gICAgICAgICAgdHlwZTogXCJtaXNzaW5nLWV4cG9ydFwiLFxuICAgICAgICAgIGRldGFpbDogYE5vIGluZGV4IGV4cG9ydCBmb3VuZCBpbiAnJHtzdWJQYXRofScuIEV4cGVjdGVkIG9uZSBvZiBpbmRleC50cywgaW5kZXguanMsIGV0Yy5gLFxuICAgICAgICB9KTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICAvLyBPcHRpb25hbGx5IGluc3BlY3QgdGhlIGluZGV4IGZpbGUgdG8gc2VlIGlmIGl0IGV4cG9ydHMgYSBsaXN0IChsaWdodHdlaWdodCBjaGVjaylcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGluZGV4RmlsZSA9IGNhbmRpZGF0ZXNGaW5kaW5nSW5kZXgoc3ViUGF0aCk7XG4gICAgICAgIGlmIChpbmRleEZpbGUpIHtcbiAgICAgICAgICBjb25zdCBjb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKGluZGV4RmlsZSwgXCJ1dGY4XCIpO1xuICAgICAgICAgIC8vIGNydWRlIGhldXJpc3RpY3M6IGxvb2sgZm9yIGBleHBvcnQgY29uc3QgbmFtZSA9IFtgIG9yIGBleHBvcnQgY29uc3QgbmFtZTogVHlwZVtdID0gW2AsXG4gICAgICAgICAgLy8gb3IgYW55IG5hbWVkIGV4cG9ydCBsaWtlIGBleHBvcnQgeyBzb21ldGhpbmcgfWAgd2hpY2ggaW1wbGllcyBleHBvcnRzIGV4aXN0LlxuICAgICAgICAgIGNvbnN0IGV4cG9ydExpc3RQYXR0ZXJuID1cbiAgICAgICAgICAgIC9leHBvcnRcXHMrKGNvbnN0fGxldHx2YXIpXFxzK1tcXHckXSsoPzpcXHMqOlxccypbXj1dKyk/XFxzKj1cXHMqXFxbLztcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAhZXhwb3J0TGlzdFBhdHRlcm4udGVzdChjb250ZW50KSAmJlxuICAgICAgICAgICAgIS9leHBvcnRcXHMrXFx7Ly50ZXN0KGNvbnRlbnQpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBpc3N1ZXMucHVzaCh7XG4gICAgICAgICAgICAgIG1vZHVsZTogbW9kdWxlTmFtZSxcbiAgICAgICAgICAgICAgcGF0aDogaW5kZXhGaWxlLFxuICAgICAgICAgICAgICB0eXBlOiBcImVtcHR5LWxpc3RcIixcbiAgICAgICAgICAgICAgZGV0YWlsOiBgSW5kZXggZmlsZSBkb2VzIG5vdCBhcHBlYXIgdG8gZXhwb3J0IGEgbGlzdCBvZiBhc3NldHM6ICR7cGF0aC5iYXNlbmFtZShpbmRleEZpbGUpfWAsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgIGlzc3Vlcy5wdXNoKHtcbiAgICAgICAgICBtb2R1bGU6IG1vZHVsZU5hbWUsXG4gICAgICAgICAgcGF0aDogc3ViUGF0aCxcbiAgICAgICAgICB0eXBlOiBcIm90aGVyXCIsXG4gICAgICAgICAgZGV0YWlsOiBgRXJyb3IgcmVhZGluZyBpbmRleCBmaWxlOiAke2Vyci5tZXNzYWdlfWAsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgb2s6IGlzc3Vlcy5sZW5ndGggPT09IDAsXG4gICAgbW9kdWxlc0NoZWNrZWQ6IGRpcnMubGVuZ3RoLFxuICAgIGlzc3VlcyxcbiAgfTtcbn1cblxuZnVuY3Rpb24gY2FuZGlkYXRlc0ZpbmRpbmdJbmRleChmb2xkZXJQYXRoOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBjYW5kaWRhdGVzID0gW1xuICAgIFwiaW5kZXgudHNcIixcbiAgICBcImluZGV4LnRzeFwiLFxuICAgIFwiaW5kZXguanNcIixcbiAgICBcImluZGV4LmNqc1wiLFxuICAgIFwiaW5kZXgubWpzXCIsXG4gIF07XG4gIGZvciAoY29uc3QgYyBvZiBjYW5kaWRhdGVzKSB7XG4gICAgY29uc3QgZnVsbCA9IHBhdGguam9pbihmb2xkZXJQYXRoLCBjKTtcbiAgICBpZiAoZnMuZXhpc3RzU3luYyhmdWxsKSkgcmV0dXJuIGZ1bGw7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLy8gQ0xJIGhlbHBlclxuaWYgKHJlcXVpcmUubWFpbiA9PT0gbW9kdWxlKSB7XG4gIGNvbnN0IHJlcG9Sb290ID0gcHJvY2Vzcy5jd2QoKTtcbiAgY29uc3QgcmVwb3J0ID0gdmFsaWRhdGVNb2R1bGVzKHJlcG9Sb290KTtcbiAgaWYgKCFyZXBvcnQub2spIHtcbiAgICBjb25zb2xlLmVycm9yKFxuICAgICAgXCJNb2R1bGUgdmFsaWRhdGlvbiBmYWlsZWQ6XFxuXCIsXG4gICAgICBKU09OLnN0cmluZ2lmeShyZXBvcnQsIG51bGwsIDIpXG4gICAgKTtcbiAgICBwcm9jZXNzLmV4aXQoMik7XG4gIH1cbiAgY29uc29sZS5sb2coXCJNb2R1bGUgdmFsaWRhdGlvbiBwYXNzZWRcIik7XG4gIHByb2Nlc3MuZXhpdCgwKTtcbn1cbiIsIi8vIEFnZ3JlZ2F0b3I6IGltcG9ydCBtb2R1bGUgaW5kZXggZmlsZXMgYW5kIG1lcmdlIGV4cG9ydGVkIGFycmF5cyB3aXRoIHByb3ZlbmFuY2UgKyBkdXBsaWNhdGUgZGV0ZWN0aW9uXG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHsgcGF0aFRvRmlsZVVSTCB9IGZyb20gXCJ1cmxcIjtcbmltcG9ydCB7IGZpbmRNb2R1bGVEaXJzIH0gZnJvbSBcIi4vdmFsaWRhdGlvblwiO1xuXG5leHBvcnQgdHlwZSBQcm92ZW5hbmNlID0geyBtb2R1bGVOYW1lOiBzdHJpbmc7IG1vZHVsZVBhdGg6IHN0cmluZyB9O1xuZXhwb3J0IHR5cGUgQWdncmVnYXRpb25Db25mbGljdCA9IHtcbiAga2V5OiBzdHJpbmc7XG4gIGV4aXN0aW5nOiBQcm92ZW5hbmNlO1xuICBpbmNvbWluZzogUHJvdmVuYW5jZTtcbn07XG5cbmV4cG9ydCB0eXBlIEFnZ3JlZ2F0aW9uUmVzdWx0PFQgPSBhbnk+ID0ge1xuICBwcm9tcHRzOiBBcnJheTxUICYgeyBwcm92ZW5hbmNlOiBQcm92ZW5hbmNlIH0+O1xuICByZXNvdXJjZXM6IEFycmF5PFQgJiB7IHByb3ZlbmFuY2U6IFByb3ZlbmFuY2UgfT47XG4gIHRlbXBsYXRlczogQXJyYXk8VCAmIHsgcHJvdmVuYW5jZTogUHJvdmVuYW5jZSB9PjtcbiAgdG9vbHM6IEFycmF5PFQgJiB7IHByb3ZlbmFuY2U6IFByb3ZlbmFuY2UgfT47XG4gIGNvbmZsaWN0czogQWdncmVnYXRpb25Db25mbGljdFtdO1xufTtcblxuY29uc3QgU1VCRk9MREVSUyA9IFtcInByb21wdHNcIiwgXCJyZXNvdXJjZXNcIiwgXCJ0ZW1wbGF0ZXNcIiwgXCJ0b29sc1wiXTtcbmNvbnN0IElOREVYX0NBTkRJREFURVMgPSBbXG4gIFwiaW5kZXgudHNcIixcbiAgXCJpbmRleC50c3hcIixcbiAgXCJpbmRleC5qc1wiLFxuICBcImluZGV4LmNqc1wiLFxuICBcImluZGV4Lm1qc1wiLFxuXTtcblxuZnVuY3Rpb24gZmluZEluZGV4RmlsZShmb2xkZXI6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGZvciAoY29uc3QgYyBvZiBJTkRFWF9DQU5ESURBVEVTKSB7XG4gICAgY29uc3QgZiA9IHBhdGguam9pbihmb2xkZXIsIGMpO1xuICAgIGlmIChmcy5leGlzdHNTeW5jKGYpKSByZXR1cm4gZjtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBtYWtlS2V5Rm9ySXRlbShpdGVtOiBhbnkpOiBzdHJpbmcge1xuICBpZiAoIWl0ZW0pIHJldHVybiBKU09OLnN0cmluZ2lmeShpdGVtKTtcbiAgaWYgKHR5cGVvZiBpdGVtID09PSBcInN0cmluZ1wiKSByZXR1cm4gYHN0cjoke2l0ZW19YDtcbiAgaWYgKHR5cGVvZiBpdGVtID09PSBcIm51bWJlclwiKSByZXR1cm4gYG51bToke2l0ZW19YDtcbiAgaWYgKGl0ZW0uaWQpIHJldHVybiBgaWQ6JHtpdGVtLmlkfWA7XG4gIGlmIChpdGVtLm5hbWUpIHJldHVybiBgbmFtZToke2l0ZW0ubmFtZX1gO1xuICAvLyBmYWxsYmFjayB0byBzdGFibGUgc3RyaW5nXG4gIHRyeSB7XG4gICAgcmV0dXJuIGBvYmo6JHtKU09OLnN0cmluZ2lmeShpdGVtKX1gO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGBvYmo6JHtTdHJpbmcoaXRlbSl9YDtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBsb2FkQXJyYXlGcm9tSW5kZXgoXG4gIGZpbGVQYXRoOiBzdHJpbmdcbik6IFByb21pc2U8YW55W10gfCB1bmRlZmluZWQ+IHtcbiAgLy8gUHJlZmVyIGEgZmFzdCwgc3RhdGljIHBhcnNlIG9mIHRoZSBmaXJzdCBhcnJheSBsaXRlcmFsIGZvdW5kIGluIHRoZSBmaWxlLlxuICB0cnkge1xuICAgIGNvbnN0IGNvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmMoZmlsZVBhdGgsIFwidXRmOFwiKTtcbiAgICBjb25zdCBzdGFydCA9IGNvbnRlbnQuaW5kZXhPZihcIltcIik7XG4gICAgaWYgKHN0YXJ0ICE9PSAtMSkge1xuICAgICAgbGV0IGRlcHRoID0gMDtcbiAgICAgIGxldCBlbmQgPSAtMTtcbiAgICAgIGZvciAobGV0IGkgPSBzdGFydDsgaSA8IGNvbnRlbnQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgY2ggPSBjb250ZW50W2ldO1xuICAgICAgICBpZiAoY2ggPT09IFwiW1wiKSBkZXB0aCsrO1xuICAgICAgICBlbHNlIGlmIChjaCA9PT0gXCJdXCIpIHtcbiAgICAgICAgICBkZXB0aC0tO1xuICAgICAgICAgIGlmIChkZXB0aCA9PT0gMCkge1xuICAgICAgICAgICAgZW5kID0gaTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGVuZCAhPT0gLTEpIHtcbiAgICAgICAgY29uc3QgYXJyVGV4dCA9IGNvbnRlbnQuc2xpY2Uoc3RhcnQsIGVuZCArIDEpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBKU09OLnBhcnNlKGFyclRleHQpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgLy8gTm9ybWFsaXplIFRTIG9iamVjdCBsaXRlcmFscyB0byBKU09OOlxuICAgICAgICAgIC8vIC0gY29udmVydCBzaW5nbGUgcXVvdGVzIHRvIGRvdWJsZSBxdW90ZXNcbiAgICAgICAgICAvLyAtIHF1b3RlIHVucXVvdGVkIG9iamVjdCBrZXlzXG4gICAgICAgICAgLy8gLSBzdHJpcCB0cmFpbGluZyBjb21tYXNcbiAgICAgICAgICBjb25zdCBub3JtYWxpemVkID0gYXJyVGV4dFxuICAgICAgICAgICAgLy8gdW5pZnkgcXVvdGVzIGluIHN0cmluZyBsaXRlcmFsc1xuICAgICAgICAgICAgLnJlcGxhY2UoLycoPzpcXFxcJ3xbXiddKSonL2csIChtKSA9PiBtLnJlcGxhY2UoLycvZywgJ1wiJykpXG4gICAgICAgICAgICAvLyBxdW90ZSB1bnF1b3RlZCBrZXlzIGFmdGVyIHsgb3IgLFxuICAgICAgICAgICAgLnJlcGxhY2UoLyhbXFx7LF1cXHMqKShbQS1aYS16XyRdW1xcdyRdKikoXFxzKjopL2csICckMVwiJDJcIiQzJylcbiAgICAgICAgICAgIC8vIHJlbW92ZSB0cmFpbGluZyBjb21tYXMgYmVmb3JlIF0gb3IgfVxuICAgICAgICAgICAgLnJlcGxhY2UoLywoXFxzKltcXH1cXF1dKS9nLCAnJDEnKTtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2Uobm9ybWFsaXplZCk7XG4gICAgICAgICAgfSBjYXRjaCAoZTIpIHtcbiAgICAgICAgICAgIC8vIGZhbGx0aHJvdWdoIHRvIGltcG9ydCBhdHRlbXB0IGJlbG93XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgLy8gaWdub3JlIHN0YXRpYyBwYXJzZSBlcnJvcnMgYW5kIGZhbGwgYmFjayB0byBpbXBvcnRcbiAgfVxuXG4gIHRyeSB7XG4gICAgY29uc3QgZmlsZVVybCA9IHBhdGhUb0ZpbGVVUkwoZmlsZVBhdGgpLmhyZWY7XG4gICAgY29uc3QgbW9kID0gYXdhaXQgaW1wb3J0KGZpbGVVcmwpO1xuICAgIC8vIEZpbmQgZmlyc3QgZXhwb3J0IHRoYXQgaXMgYW4gYXJyYXlcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhtb2QpKSB7XG4gICAgICBjb25zdCB2YWwgPSAobW9kIGFzIGFueSlba2V5XTtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbCkpIHJldHVybiB2YWw7XG4gICAgfVxuICAgIC8vIGRlZmF1bHQgZXhwb3J0IGNoZWNrXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoKG1vZCBhcyBhbnkpLmRlZmF1bHQpKSByZXR1cm4gKG1vZCBhcyBhbnkpLmRlZmF1bHQ7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgLy8gZmFsbGJhY2s6IGlmIGltcG9ydCBmYWlscywgdHJ5IHRvIHN0YXRpYy1wYXJzZSBhZ2FpbiAoYWxyZWFkeSBhdHRlbXB0ZWQpIGFuZCBmaW5hbGx5IHJldHVybiB1bmRlZmluZWRcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhZ2dyZWdhdGVNb2R1bGVzKFxuICByZXBvUm9vdDogc3RyaW5nXG4pOiBQcm9taXNlPEFnZ3JlZ2F0aW9uUmVzdWx0PiB7XG4gIGNvbnN0IGRpcnMgPSBmaW5kTW9kdWxlRGlycyhyZXBvUm9vdCk7XG4gIGNvbnN0IG1hc3RlciA9IHtcbiAgICBwcm9tcHRzOiBbXSBhcyBhbnlbXSxcbiAgICByZXNvdXJjZXM6IFtdIGFzIGFueVtdLFxuICAgIHRlbXBsYXRlczogW10gYXMgYW55W10sXG4gICAgdG9vbHM6IFtdIGFzIGFueVtdLFxuICAgIGNvbmZsaWN0czogW10gYXMgQWdncmVnYXRpb25Db25mbGljdFtdLFxuICB9O1xuXG4gIC8vIG1hcHMgdG8gZGV0ZWN0IGR1cGxpY2F0ZXMgcGVyIHR5cGVcbiAgY29uc3QgbWFwczogUmVjb3JkPHN0cmluZywgTWFwPHN0cmluZywgUHJvdmVuYW5jZT4+ID0ge1xuICAgIHByb21wdHM6IG5ldyBNYXAoKSxcbiAgICByZXNvdXJjZXM6IG5ldyBNYXAoKSxcbiAgICB0ZW1wbGF0ZXM6IG5ldyBNYXAoKSxcbiAgICB0b29sczogbmV3IE1hcCgpLFxuICB9O1xuXG4gIGZvciAoY29uc3QgbW9kdWxlRGlyIG9mIGRpcnMpIHtcbiAgICBjb25zdCBtb2R1bGVOYW1lID0gcGF0aC5iYXNlbmFtZShtb2R1bGVEaXIpO1xuICAgIGZvciAoY29uc3Qgc3ViIG9mIFNVQkZPTERFUlMpIHtcbiAgICAgIGNvbnN0IGZvbGRlciA9IHBhdGguam9pbihtb2R1bGVEaXIsIHN1Yik7XG4gICAgICBjb25zdCBpbmRleEZpbGUgPSBmaW5kSW5kZXhGaWxlKGZvbGRlcik7XG4gICAgICBpZiAoIWluZGV4RmlsZSkgY29udGludWU7XG4gICAgICBsZXQgYXJyOiBhbnlbXSB8IHVuZGVmaW5lZDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGFyciA9IGF3YWl0IGxvYWRBcnJheUZyb21JbmRleChpbmRleEZpbGUpO1xuICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgLy8gc2tpcCBtb2R1bGUgb24gaW1wb3J0IGVycm9yIGJ1dCByZWNvcmQgYXMgY29uZmxpY3QtbGlrZSBpc3N1ZVxuICAgICAgICBtYXN0ZXIuY29uZmxpY3RzLnB1c2goe1xuICAgICAgICAgIGtleTogYGltcG9ydC1lcnJvcjoke21vZHVsZU5hbWV9OiR7c3VifWAsXG4gICAgICAgICAgZXhpc3Rpbmc6IHsgbW9kdWxlTmFtZSwgbW9kdWxlUGF0aDogbW9kdWxlRGlyIH0sXG4gICAgICAgICAgaW5jb21pbmc6IHsgbW9kdWxlTmFtZSwgbW9kdWxlUGF0aDogbW9kdWxlRGlyIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmICghYXJyIHx8ICFBcnJheS5pc0FycmF5KGFycikpIGNvbnRpbnVlO1xuXG4gICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgYXJyKSB7XG4gICAgICAgIGNvbnN0IGtleSA9IG1ha2VLZXlGb3JJdGVtKGl0ZW0pO1xuICAgICAgICBjb25zdCBwcm92ZW5hbmNlID0geyBtb2R1bGVOYW1lLCBtb2R1bGVQYXRoOiBtb2R1bGVEaXIgfTtcbiAgICAgICAgY29uc3QgbWFwID0gbWFwc1tzdWJdO1xuICAgICAgICBpZiAobWFwLmhhcyhrZXkpKSB7XG4gICAgICAgICAgLy8gcmVjb3JkIGNvbmZsaWN0IGRldGVybWluaXN0aWNhbGx5IChleGlzdGluZyB2cyBpbmNvbWluZylcbiAgICAgICAgICBjb25zdCBleGlzdGluZyA9IG1hcC5nZXQoa2V5KSE7XG4gICAgICAgICAgbWFzdGVyLmNvbmZsaWN0cy5wdXNoKHsga2V5LCBleGlzdGluZywgaW5jb21pbmc6IHByb3ZlbmFuY2UgfSk7XG4gICAgICAgICAgLy8gc2tpcCBhZGRpbmcgZHVwbGljYXRlXG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgbWFwLnNldChrZXksIHByb3ZlbmFuY2UpO1xuICAgICAgICAobWFzdGVyIGFzIGFueSlbc3ViXS5wdXNoKHsgLi4uaXRlbSwgcHJvdmVuYW5jZSB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbWFzdGVyO1xufVxuXG4vLyBGb3IgY29tcGF0aWJpbGl0eSB3aXRoIENvbW1vbkpTIGNhbGwgc2l0ZXMgKG5vdCBleHBvcnRlZCBieSBFU00pLCBwcm92aWRlIGEgc3luYyB3cmFwcGVyXG5leHBvcnQgZnVuY3Rpb24gYWdncmVnYXRlTW9kdWxlc1N5bmMocmVwb1Jvb3Q6IHN0cmluZykge1xuICAvLyBzeW5jaHJvbm91cyB3cmFwcGVyIHRoYXQgcnVucyB0aGUgYXN5bmMgZnVuY3Rpb24gYW5kIGJsb2NrcyDigJQgc3VpdGFibGUgZm9yIHNtYWxsIG1vZHVsZSBzZXRzXG4gIGNvbnN0IHAgPSBhZ2dyZWdhdGVNb2R1bGVzKHJlcG9Sb290KTtcbiAgbGV0IHJlc3VsdDogYW55O1xuICBsZXQgZG9uZSA9IGZhbHNlO1xuICBwLnRoZW4oKHIpID0+IHtcbiAgICByZXN1bHQgPSByO1xuICAgIGRvbmUgPSB0cnVlO1xuICB9KS5jYXRjaCgoZSkgPT4ge1xuICAgIHRocm93IGU7XG4gIH0pO1xuICAvLyBzcGluLXdhaXQgKGFjY2VwdGFibGUgaW4gc21hbGwgZGV2IHNjcmlwdHMpXG4gIGNvbnN0IHVudGlsID0gRGF0ZS5ub3coKSArIDUwMDA7XG4gIHdoaWxlICghZG9uZSAmJiBEYXRlLm5vdygpIDwgdW50aWwpIHt9XG4gIGlmICghZG9uZSlcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBcImFnZ3JlZ2F0ZU1vZHVsZXNTeW5jOiB0aW1lb3V0IHdhaXRpbmcgZm9yIGFzeW5jIGFnZ3JlZ2F0aW9uXCJcbiAgICApO1xuICByZXR1cm4gcmVzdWx0IGFzIEFnZ3JlZ2F0aW9uUmVzdWx0O1xufVxuIiwiaW1wb3J0IHsgYWdncmVnYXRlTW9kdWxlcyB9IGZyb20gXCIuL2FnZ3JlZ2F0ZU1vZHVsZXNcIjtcbmltcG9ydCB7IGxvYWRQcm9tcHRzLCBwcm9tcHRMaXN0IH0gZnJvbSBcIi4vcHJvbXB0cy9pbmRleFwiO1xuaW1wb3J0IHsgdG9vbExpc3QgfSBmcm9tIFwiLi90b29scy9pbmRleFwiO1xuaW1wb3J0IHsgcmVzb3VyY2VzIH0gZnJvbSBcIi4vcmVzb3VyY2VzL2luZGV4XCI7XG5pbXBvcnQgeyBidWlsZFJlc291cmNlVGVtcGxhdGVzIH0gZnJvbSBcIi4vdGVtcGxhdGVzL2luZGV4XCI7XG5cbmV4cG9ydCB0eXBlIEZhc3RNQ1BMaWtlID0ge1xuICBhZGRQcm9tcHQ6IChwOiBhbnkpID0+IHZvaWQ7XG4gIGFkZFRvb2w6ICh0OiBhbnkpID0+IHZvaWQ7XG4gIGFkZFJlc291cmNlOiAocjogYW55KSA9PiB2b2lkO1xuICBhZGRSZXNvdXJjZVRlbXBsYXRlOiAodDogYW55KSA9PiB2b2lkO1xufTtcblxuLyoqXG4gKiBBZ2dyZWdhdGUgbW9kdWxlIGFzc2V0cyBhbmQgcmVnaXN0ZXIgdGhlbSBvbiB0aGUgcHJvdmlkZWQgRmFzdE1DUC1saWtlIHNlcnZlci5cbiAqIEZhbGxzIGJhY2sgdG8gYnVpbHQtaW4gbGlzdHMgaWYgYWdncmVnYXRpb24geWllbGRzIG5vbmUuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBFbnJpY2hDb3JlV2l0aEFnZ3JlZ2F0aW9uKFxuICBzZXJ2ZXI6IEZhc3RNQ1BMaWtlLFxuICByZXBvUm9vdCA9IHByb2Nlc3MuY3dkKClcbikge1xuICAvLyBGaXJzdCByZWdpc3RlciBidWlsdC1pbiBwcm9tcHRzL3Rvb2xzL3Jlc291cmNlcy90ZW1wbGF0ZXMgKGxlZ2FjeSBiZWhhdmlvcilcbiAgdHJ5IHtcbiAgICBsb2FkUHJvbXB0cygpO1xuICAgIGZvciAoY29uc3QgcHJvbXB0IG9mIHByb21wdExpc3QpIHNlcnZlci5hZGRQcm9tcHQocHJvbXB0IGFzIGFueSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBpZ25vcmUgaWYgbG9hZFByb21wdHMgbm90IGF2YWlsYWJsZSBvciBmYWlsc1xuICB9XG5cbiAgdHJ5IHtcbiAgICBmb3IgKGNvbnN0IHRvb2wgb2YgdG9vbExpc3QpIHNlcnZlci5hZGRUb29sKHRvb2wgYXMgYW55KTtcbiAgfSBjYXRjaCAoZSkge31cblxuICB0cnkge1xuICAgIGZvciAoY29uc3QgcmVzb3VyY2Ugb2YgcmVzb3VyY2VzKSBzZXJ2ZXIuYWRkUmVzb3VyY2UocmVzb3VyY2UgYXMgYW55KTtcbiAgfSBjYXRjaCAoZSkge31cblxuICB0cnkge1xuICAgIGNvbnN0IHRlbXBsYXRlcyA9IGJ1aWxkUmVzb3VyY2VUZW1wbGF0ZXMoKTtcbiAgICBmb3IgKGNvbnN0IHRlbXBsYXRlIG9mIHRlbXBsYXRlcylcbiAgICAgIHNlcnZlci5hZGRSZXNvdXJjZVRlbXBsYXRlKHRlbXBsYXRlIGFzIGFueSk7XG4gIH0gY2F0Y2ggKGUpIHt9XG5cbiAgLy8gTm93IGFnZ3JlZ2F0ZSBtb2R1bGVzIGFuZCByZWdpc3RlciBhZ2dyZWdhdGVkIGFzc2V0cyB3aXRoIHByb3ZlbmFuY2VcbiAgY29uc3QgYWdnID0gYXdhaXQgYWdncmVnYXRlTW9kdWxlcyhyZXBvUm9vdCk7XG5cbiAgZm9yIChjb25zdCBwIG9mIGFnZy5wcm9tcHRzKSB7XG4gICAgc2VydmVyLmFkZFByb21wdChwKTtcbiAgfVxuICBmb3IgKGNvbnN0IHQgb2YgYWdnLnRvb2xzKSB7XG4gICAgc2VydmVyLmFkZFRvb2wodCk7XG4gIH1cbiAgZm9yIChjb25zdCByIG9mIGFnZy5yZXNvdXJjZXMpIHtcbiAgICBzZXJ2ZXIuYWRkUmVzb3VyY2Uocik7XG4gIH1cbiAgZm9yIChjb25zdCB0cGwgb2YgYWdnLnRlbXBsYXRlcykge1xuICAgIHNlcnZlci5hZGRSZXNvdXJjZVRlbXBsYXRlKHRwbCk7XG4gIH1cblxuICAvLyByZXR1cm4gYWdncmVnYXRpb24gc3VtbWFyeSBmb3IgY2FsbGluZyB0ZXN0cy9DSVxuICByZXR1cm4ge1xuICAgIG1vZHVsZXNDaGVja2VkOiBhZ2cucHJvbXB0cy5jb25jYXQoYWdnLnRvb2xzKS5sZW5ndGgsXG4gICAgY29uZmxpY3RzOiBhZ2cuY29uZmxpY3RzLFxuICB9O1xufVxuIiwiaW1wb3J0IHsgRmFzdE1DUCB9IGZyb20gXCJmYXN0bWNwXCI7XG5pbXBvcnQgeyBsb2FkUHJvbXB0cywgcHJvbXB0TGlzdCB9IGZyb20gXCIuL3Byb21wdHMvaW5kZXhcIjtcbmltcG9ydCB7IHRvb2xMaXN0IH0gZnJvbSBcIi4vdG9vbHMvaW5kZXhcIjtcbmltcG9ydCB7IHJlc291cmNlcyB9IGZyb20gXCIuL3Jlc291cmNlcy9pbmRleFwiO1xuaW1wb3J0IHsgYnVpbGRSZXNvdXJjZVRlbXBsYXRlcyB9IGZyb20gXCIuL3RlbXBsYXRlcy9pbmRleFwiO1xuXG5leHBvcnQgKiBmcm9tIFwiLi9tY3AtbW9kdWxlXCI7XG5leHBvcnQgeyBkZWZhdWx0IH0gZnJvbSBcIi4vbWNwLW1vZHVsZVwiO1xuXG5leHBvcnQgeyB2YWxpZGF0ZU1vZHVsZXMgfSBmcm9tIFwiLi92YWxpZGF0aW9uXCI7XG5leHBvcnQgeyBhZ2dyZWdhdGVNb2R1bGVzLCBhZ2dyZWdhdGVNb2R1bGVzU3luYyB9IGZyb20gXCIuL2FnZ3JlZ2F0ZU1vZHVsZXNcIjtcbmV4cG9ydCB7IEVucmljaENvcmVXaXRoQWdncmVnYXRpb24gfSBmcm9tIFwiLi9mYXN0bWNwLXdpcmluZ1wiO1xuXG4vLyByZS1leHBvcnQgaGVscGVycyB1c2VkIGJ5IHRlc3RzIGFuZCBvdGhlciBtb2R1bGVzXG5leHBvcnQgeyBidWlsZERvY1Byb21wdHMgfSBmcm9tIFwiLi9wcm9tcHRzL2luZGV4XCI7XG5leHBvcnQgeyBidWlsZFJlc291cmNlVGVtcGxhdGVzIH0gZnJvbSBcIi4vdGVtcGxhdGVzL2luZGV4XCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBFbnJpY2hDb3JlKHNlcnZlcjogRmFzdE1DUCkge1xuICBsb2FkUHJvbXB0cygpO1xuICBmb3IgKGNvbnN0IHByb21wdCBvZiBwcm9tcHRMaXN0KSB7XG4gICAgc2VydmVyLmFkZFByb21wdChwcm9tcHQgYXMgYW55KTtcbiAgfVxuICBmb3IgKGNvbnN0IHRvb2wgb2YgdG9vbExpc3QpIHtcbiAgICBzZXJ2ZXIuYWRkVG9vbCh0b29sIGFzIGFueSk7XG4gIH1cbiAgZm9yIChjb25zdCByZXNvdXJjZSBvZiByZXNvdXJjZXMpIHtcbiAgICBzZXJ2ZXIuYWRkUmVzb3VyY2UocmVzb3VyY2UgYXMgYW55KTtcbiAgfVxuICBjb25zdCB0ZW1wbGF0ZXMgPSBidWlsZFJlc291cmNlVGVtcGxhdGVzKCk7XG4gIGZvciAoY29uc3QgdGVtcGxhdGUgb2YgdGVtcGxhdGVzKSB7XG4gICAgc2VydmVyLmFkZFJlc291cmNlVGVtcGxhdGUodGVtcGxhdGUgYXMgYW55KTtcbiAgfVxufVxuIiwiaW1wb3J0IGZzIGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBnZXRXb3Jrc3BhY2VSb290IH0gZnJvbSBcIi4uL21jcC93b3Jrc3BhY2VcIjtcblxuZXhwb3J0IGNvbnN0IFJFUVVJUkVEX01PRFVMRV9GT0xERVJTID0gW1xuICBcInByb21wdHNcIixcbiAgXCJyZXNvdXJjZXNcIixcbiAgXCJ0ZW1wbGF0ZXNcIixcbiAgXCJ0b29sc1wiLFxuXSBhcyBjb25zdDtcblxuZXhwb3J0IHR5cGUgTW9kdWxlRm9sZGVyID0gKHR5cGVvZiBSRVFVSVJFRF9NT0RVTEVfRk9MREVSUylbbnVtYmVyXTtcblxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVNb2R1bGVzUm9vdCh3b3Jrc3BhY2VSb290ID0gZ2V0V29ya3NwYWNlUm9vdCgpKTogc3RyaW5nIHtcbiAgcmV0dXJuIHBhdGgucmVzb2x2ZSh3b3Jrc3BhY2VSb290LCBcInNyYy9tb2R1bGVzXCIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbGlzdE1vZHVsZURpcmVjdG9yaWVzKHdvcmtzcGFjZVJvb3QgPSBnZXRXb3Jrc3BhY2VSb290KCkpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHJvb3QgPSByZXNvbHZlTW9kdWxlc1Jvb3Qod29ya3NwYWNlUm9vdCk7XG4gIGlmICghZnMuZXhpc3RzU3luYyhyb290KSkgcmV0dXJuIFtdO1xuXG4gIHJldHVybiBmc1xuICAgIC5yZWFkZGlyU3luYyhyb290KVxuICAgIC5tYXAoKGVudHJ5KSA9PiAoe1xuICAgICAgZW50cnksXG4gICAgICBhYnNvbHV0ZTogcGF0aC5qb2luKHJvb3QsIGVudHJ5KSxcbiAgICB9KSlcbiAgICAuZmlsdGVyKCh7IGFic29sdXRlIH0pID0+IGZzLnN0YXRTeW5jKGFic29sdXRlKS5pc0RpcmVjdG9yeSgpKVxuICAgIC5tYXAoKHsgZW50cnkgfSkgPT4gZW50cnkpXG4gICAgLnNvcnQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVNb2R1bGVQYXRoKFxuICBtb2R1bGVOYW1lOiBzdHJpbmcsXG4gIHdvcmtzcGFjZVJvb3QgPSBnZXRXb3Jrc3BhY2VSb290KClcbik6IHN0cmluZyB7XG4gIHJldHVybiBwYXRoLmpvaW4ocmVzb2x2ZU1vZHVsZXNSb290KHdvcmtzcGFjZVJvb3QpLCBtb2R1bGVOYW1lKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVNb2R1bGVGb2xkZXJQYXRoKFxuICBtb2R1bGVOYW1lOiBzdHJpbmcsXG4gIGZvbGRlcjogTW9kdWxlRm9sZGVyLFxuICB3b3Jrc3BhY2VSb290ID0gZ2V0V29ya3NwYWNlUm9vdCgpXG4pOiBzdHJpbmcge1xuICByZXR1cm4gcGF0aC5qb2luKHJlc29sdmVNb2R1bGVQYXRoKG1vZHVsZU5hbWUsIHdvcmtzcGFjZVJvb3QpLCBmb2xkZXIpO1xufVxuIiwiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgeyBNY3BNb2R1bGUgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBVdGlsaXR5IGNsYXNzIGZvciBDTEkgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgQSBzdGF0aWMgdXRpbGl0eSBjbGFzcyB0aGF0IHByb3ZpZGVzIG1ldGhvZHMgZm9yIGxvYWRpbmcgbW9kdWxlcywgcmV0cmlldmluZyBwYWNrYWdlIGluZm9ybWF0aW9uLCBhbmQgaW5pdGlhbGl6aW5nIENMSSBjb21tYW5kc1xuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBJbml0aWFsaXplIGEgQ29tbWFuZCBvYmplY3Qgd2l0aCBwYWNrYWdlIGluZm9ybWF0aW9uXG4gKiBjb25zdCBjb21tYW5kID0gbmV3IENvbW1hbmQoKTtcbiAqIENMSVV0aWxzLmluaXRpYWxpemUoY29tbWFuZCwgJy4vcGF0aC90by9wYWNrYWdlJyk7XG4gKlxuICogLy8gTG9hZCBhIENMSSBtb2R1bGUgZnJvbSBhIGZpbGVcbiAqIGNvbnN0IG1vZHVsZSA9IGF3YWl0IENMSVV0aWxzLmxvYWRGcm9tRmlsZSgnLi9wYXRoL3RvL2NsaS1tb2R1bGUuanMnKTtcbiAqXG4gKiBAY2xhc3MgTWNwVXRpbHNcbiAqL1xuZXhwb3J0IGNsYXNzIE1jcFV0aWxzIHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEeW5hbWljYWxseSBpbXBvcnRzIGEgbW9kdWxlIGZpbGVcbiAgICogQHN1bW1hcnkgTG9hZHMgYSBKYXZhU2NyaXB0IGZpbGUgYW5kIHJldHVybnMgaXQgYXMgYSBDbGlNb2R1bGUsIGhhbmRsaW5nIGJvdGggRVNNIGFuZCBDb21tb25KUyBmb3JtYXRzXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIFRoZSBmaWxlIHBhdGggdG8gdGhlIG1vZHVsZSB0byBsb2FkXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TWNwTW9kdWxlPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGxvYWRlZCBDbGlNb2R1bGVcbiAgICovXG4gIHN0YXRpYyBhc3luYyBsb2FkRnJvbUZpbGUocGF0aDogc3RyaW5nKTogUHJvbWlzZTxNY3BNb2R1bGU+IHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIE1jcFV0aWxzLm5vcm1hbGl6ZUltcG9ydChpbXBvcnQocGF0aCkpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byBsb2FkIGZyb20gJHtwYXRofTogJHtlIGluc3RhbmNlb2YgRXJyb3IgPyBlLm1lc3NhZ2UgOiBlfWBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBOb3JtYWxpemVzIG1vZHVsZSBpbXBvcnRzIHRvIGhhbmRsZSBib3RoIEVTTSBhbmQgQ29tbW9uSlMgZm9ybWF0c1xuICAgKiBAc3VtbWFyeSBQcm9wZXJseSBpbXBvcnRzIEphdmFTY3JpcHQgZmlsZXMgcmVnYXJkbGVzcyBvZiB0aGVpciBtb2R1bGUgZm9ybWF0IGJ5IGhhbmRsaW5nIHRoZSBFU00gd3JhcHBlciBmb3IgQ29tbW9uSlMgbW9kdWxlc1xuICAgKlxuICAgKiBAdGVtcGxhdGUgVCBUaGUgdHlwZSBvZiB0aGUgaW1wb3J0ZWQgbW9kdWxlXG4gICAqIEBwYXJhbSB7UHJvbWlzZTxUPn0gaW1wb3J0UHJvbWlzZSBUaGUgcHJvbWlzZSByZXR1cm5lZCBieSB0aGUgZHluYW1pYyBpbXBvcnRcbiAgICogQHJldHVybiB7UHJvbWlzZTxUPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIG5vcm1hbGl6ZWQgbW9kdWxlXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgbm9ybWFsaXplSW1wb3J0PFQ+KGltcG9ydFByb21pc2U6IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+IHtcbiAgICAvLyBDb21tb25KUydzIGBtb2R1bGUuZXhwb3J0c2AgaXMgd3JhcHBlZCBhcyBgZGVmYXVsdGAgaW4gRVNNb2R1bGUuXG4gICAgcmV0dXJuIGltcG9ydFByb21pc2UudGhlbihcbiAgICAgIChtOiB1bmtub3duKSA9PiAoKG0gYXMgeyBkZWZhdWx0OiBUIH0pLmRlZmF1bHQgfHwgbSkgYXMgVFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhbmQgcGFyc2VzIHRoZSBwYWNrYWdlLmpzb24gZmlsZVxuICAgKiBAc3VtbWFyeSBSZWFkcyB0aGUgcGFja2FnZS5qc29uIGZpbGUgZnJvbSB0aGUgc3BlY2lmaWVkIHBhdGggYW5kIHBhcnNlcyBpdCBpbnRvIGEgSmF2YVNjcmlwdCBvYmplY3RcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGJhc2VQYXRoIFRoZSBiYXNlIHBhdGggd2hlcmUgdGhlIHBhY2thZ2UuanNvbiBmaWxlIGlzIGxvY2F0ZWRcbiAgICogQHJldHVybiB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59IFRoZSBwYXJzZWQgcGFja2FnZS5qc29uIGNvbnRlbnQgYXMgYW4gb2JqZWN0XG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBnZXRQYWNrYWdlKGJhc2VQYXRoOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBKU09OLnBhcnNlKFxuICAgICAgICBmcy5yZWFkRmlsZVN5bmMocGF0aC5qb2luKGJhc2VQYXRoLCBcInBhY2thZ2UuanNvblwiKSwgXCJ1dGY4XCIpXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIHJlYWQgdmVyc2lvbiBmcm9tICR7YmFzZVBhdGh9OiAke2V9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXR1cm5zIHRoZSB2ZXJzaW9uIGZyb20gcGFja2FnZS5qc29uXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyB0aGUgdmVyc2lvbiBmaWVsZCBmcm9tIHRoZSBwYWNrYWdlLmpzb24gZmlsZSBhdCB0aGUgc3BlY2lmaWVkIHBhdGhcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGJhc2VQYXRoIFRoZSBiYXNlIHBhdGggd2hlcmUgdGhlIHBhY2thZ2UuanNvbiBmaWxlIGlzIGxvY2F0ZWRcbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgcGFja2FnZSB2ZXJzaW9uIHN0cmluZ1xuICAgKi9cbiAgc3RhdGljIHBhY2thZ2VWZXJzaW9uKGJhc2VQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBNY3BVdGlscy5nZXRQYWNrYWdlKGJhc2VQYXRoKVtcInZlcnNpb25cIl0gYXMgc3RyaW5nO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXR1cm5zIHRoZSBuYW1lIGZyb20gcGFja2FnZS5qc29uXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyB0aGUgbmFtZSBmaWVsZCBmcm9tIHRoZSBwYWNrYWdlLmpzb24gZmlsZSBhdCB0aGUgc3BlY2lmaWVkIHBhdGggYW5kIGV4dHJhY3RzIHRoZSBwYWNrYWdlIG5hbWUgd2l0aG91dCB0aGUgc2NvcGVcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGJhc2VQYXRoIFRoZSBiYXNlIHBhdGggd2hlcmUgdGhlIHBhY2thZ2UuanNvbiBmaWxlIGlzIGxvY2F0ZWRcbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgcGFja2FnZSBuYW1lIHdpdGhvdXQgdGhlIHNjb3BlIChlLmcuLCBcImNsaVwiIGZyb20gXCJAZGVjYWYtdHMvY2xpXCIpXG4gICAqL1xuICBzdGF0aWMgcGFja2FnZU5hbWUoYmFzZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgbmFtZSA9IChNY3BVdGlscy5nZXRQYWNrYWdlKGJhc2VQYXRoKVtcIm5hbWVcIl0gYXMgc3RyaW5nKS5zcGxpdChcIi9cIik7XG4gICAgcmV0dXJuIG5hbWVbbmFtZS5sZW5ndGggLSAxXTtcbiAgfVxufVxuXG5leHBvcnQgKiBmcm9tIFwiLi91dGlscy9tb2R1bGVQYXRoc1wiO1xuIiwiaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IE1DUF9GSUxFX05BTUUgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IE1jcFV0aWxzIH0gZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCB7IEZhc3RNQ1AgfSBmcm9tIFwiZmFzdG1jcFwiO1xuaW1wb3J0IHsgTG9nZ2VkQ2xhc3MgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcbmltcG9ydCB7IFZFUlNJT04gfSBmcm9tIFwiLi9tZXRhZGF0YVwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBVdGlsaXR5IGNsYXNzIHRvIGhhbmRsZSBDTEkgZnVuY3Rpb25hbGl0eSBmcm9tIGFsbCBEZWNhZiBtb2R1bGVzXG4gKiBAc3VtbWFyeSBUaGlzIGNsYXNzIHByb3ZpZGVzIGEgd3JhcHBlciBhcm91bmQgQ29tbWFuZGVyLmpzIHRvIGhhbmRsZSBDTEkgY29tbWFuZHMgZnJvbSBkaWZmZXJlbnQgRGVjYWYgbW9kdWxlcy5cbiAqIEl0IGNyYXdscyB0aGUgZmlsZXN5c3RlbSB0byBmaW5kIENMSSBtb2R1bGVzLCBsb2FkcyB0aGVtLCBhbmQgcmVnaXN0ZXJzIHRoZWlyIGNvbW1hbmRzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBbYmFzZVBhdGhdIFRoZSBiYXNlIHBhdGggdG8gbG9vayBmb3IgbW9kdWxlcyBpbi4gRGVmYXVsdHMgdG8gYC4vYFxuICogQHBhcmFtIHtudW1iZXJ9IFtjcmF3bExldmVsc10gTnVtYmVyIG9mIGZvbGRlciBsZXZlbHMgdG8gY3Jhd2wgdG8gZmluZCBtb2R1bGVzIGZyb20gdGhlIGJhc2VQYXRoLiBEZWZhdWx0cyB0byA0XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIENyZWF0ZSBhIG5ldyBDTEkgd3JhcHBlciBhbmQgcnVuIGl0IHdpdGggY3VzdG9tIG9wdGlvbnNcbiAqIGNvbnN0IGNsaSA9IG5ldyBDbGlXcmFwcGVyKCcuL3NyYycsIDIpO1xuICogY2xpLnJ1bihwcm9jZXNzLmFyZ3YpLnRoZW4oKCkgPT4ge1xuICogICBjb25zb2xlLmxvZygnQ0xJIGNvbW1hbmRzIGV4ZWN1dGVkIHN1Y2Nlc3NmdWxseScpO1xuICogfSk7XG4gKlxuICogQGNsYXNzIE1jcFdyYXBwZXJcbiAqL1xuZXhwb3J0IGNsYXNzIE1jcFdyYXBwZXIgZXh0ZW5kcyBMb2dnZWRDbGFzcyB7XG4gIHByaXZhdGUgX21jcD86IEZhc3RNQ1A7XG4gIHByaXZhdGUgbW9kdWxlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBwcml2YXRlIHJlYWRvbmx5IHJvb3RQYXRoOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBiYXNlUGF0aDogc3RyaW5nID0gXCIuL1wiLFxuICAgIHByaXZhdGUgY3Jhd2xMZXZlbHMgPSA0XG4gICkge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5yb290UGF0aCA9IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsIFwiLi5cIik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhbmQgaW5pdGlhbGl6ZXMgdGhlIENvbW1hbmRlciBDb21tYW5kIG9iamVjdFxuICAgKiBAc3VtbWFyeSBMYXp5LWxvYWRzIHRoZSBDb21tYW5kIG9iamVjdCwgaW5pdGlhbGl6aW5nIGl0IHdpdGggdGhlIHBhY2thZ2UgbmFtZSwgZGVzY3JpcHRpb24sIGFuZCB2ZXJzaW9uXG4gICAqIEByZXR1cm4ge0Zhc3RNQ1B9IFRoZSBpbml0aWFsaXplZCBDb21tYW5kIG9iamVjdFxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBnZXQgbWNwKCkge1xuICAgIGlmICghdGhpcy5fbWNwKSB7XG4gICAgICB0aGlzLl9tY3AgPSBuZXcgRmFzdE1DUCh7XG4gICAgICAgIG5hbWU6IFwiZGVjYWYtdHMgTUNQIHNlcnZlclwiLFxuICAgICAgICBpbnN0cnVjdGlvbnM6IFwiXCIsXG4gICAgICAgIHZlcnNpb246IFZFUlNJT04gYXMgYW55LFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9tY3A7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExvYWRzIGFuZCByZWdpc3RlcnMgYW4gbWNwIGV4dGVuc2lvbiBtb2R1bGUgZnJvbSBhIGZpbGVcbiAgICogQHN1bW1hcnkgRHluYW1pY2FsbHkgaW1wb3J0cyBhbiBtY3AgZXh0ZW5zaW9uIG1vZHVsZSBmcm9tIHRoZSBzcGVjaWZpZWQgZmlsZSBwYXRoLCBpbml0aWFsaXplcyBpdCwgYW5kIHJlZ2lzdGVycyBpdCBpbiB0aGUgbW9kdWxlcyBjb2xsZWN0aW9uXG4gICAqXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGxvYWQoXG4gICAgc2VydmVyOiBGYXN0TUNQLFxuICAgIGZpbGVQYXRoOiBzdHJpbmdcbiAgKTogUHJvbWlzZTx7IG1jcDogRmFzdE1DUDsgcGFja2FnZTogc3RyaW5nOyB2ZXJzaW9uOiBzdHJpbmcgfT4ge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLmxvYWQpO1xuXG4gICAgbGV0IHBrZzogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmcsIGVucmljaDogYW55O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBNY3BVdGlscy5sb2FkRnJvbUZpbGUoZmlsZVBhdGgpO1xuICAgICAgcGtnID0gcmVzLlBBQ0tBR0VfTkFNRTtcbiAgICAgIHZlcnNpb24gPSByZXMuVkVSU0lPTjtcbiAgICAgIGVucmljaCA9IHJlcy5lbnJpY2g7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKChlIGFzIGFueSkubWVzc2FnZSB8fCAoZSBhcyBhbnkpKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGxvZy5pbmZvKGBFbnJpY2hpbmcgbWNwIHNlcnZlciB3aXRoIG1vZHVsZSAke3BrZ30gdiR7dmVyc2lvbn1gKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGVucmljaChzZXJ2ZXIpO1xuICAgICAgc2VydmVyID0gcmVzdWx0IGluc3RhbmNlb2YgUHJvbWlzZSA/IGF3YWl0IHJlc3VsdCA6IHJlc3VsdDtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBmYWlsZWQgdG8gZW5yaWNoIG1jcCB3aXRoIG1vZHVsZSAke3BrZyB8fCBcInVubmFtZWRcIn0gdW5kZXIgJHtmaWxlUGF0aH06ICR7ZSBpbnN0YW5jZW9mIEVycm9yID8gZS5tZXNzYWdlIDogZX1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgbWNwOiBzZXJ2ZXIsXG4gICAgICBwYWNrYWdlOiBwa2csXG4gICAgICB2ZXJzaW9uOiB2ZXJzaW9uLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEZpbmRzIGFuZCBsb2FkcyBhbGwgQ0xJIG1vZHVsZXMgaW4gdGhlIGJhc2VQYXRoXG4gICAqIEBzdW1tYXJ5IFVzZXMgdGhlIGNyYXdsIG1ldGhvZCB0byBmaW5kIGFsbCBDTEkgbW9kdWxlcyBpbiB0aGUgc3BlY2lmaWVkIGJhc2UgcGF0aCxcbiAgICogdGhlbiBsb2FkcyBhbmQgcmVnaXN0ZXJzIGVhY2ggbW9kdWxlIGFzIGEgc3ViY29tbWFuZFxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCBtb2R1bGVzIGFyZSBsb2FkZWRcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2xpV3JhcHBlclxuICAgKiAgIHBhcnRpY2lwYW50IEZpbGVzeXN0ZW1cbiAgICogICBwYXJ0aWNpcGFudCBNb2R1bGVcbiAgICpcbiAgICogICBDbGlXcmFwcGVyLT4+RmlsZXN5c3RlbTogSm9pbiBiYXNlUGF0aCB3aXRoIGN3ZFxuICAgKiAgIENsaVdyYXBwZXItPj5DbGlXcmFwcGVyOiBjcmF3bChiYXNlUGF0aCwgY3Jhd2xMZXZlbHMpXG4gICAqICAgQ2xpV3JhcHBlci0tPj5DbGlXcmFwcGVyOiBtb2R1bGVzW11cbiAgICogICBsb29wIEZvciBlYWNoIG1vZHVsZVxuICAgKiAgICAgYWx0IE5vdCBAZGVjYWYtdHMvY2xpXG4gICAqICAgICAgIENsaVdyYXBwZXItPj5DbGlXcmFwcGVyOiBsb2FkKG1vZHVsZSwgY3dkKVxuICAgKiAgICAgICBDbGlXcmFwcGVyLS0+PkNsaVdyYXBwZXI6IG5hbWVcbiAgICogICAgICAgQ2xpV3JhcHBlci0+PkNsaVdyYXBwZXI6IENoZWNrIGlmIGNvbW1hbmQgZXhpc3RzXG4gICAqICAgICAgIGFsdCBDb21tYW5kIGRvZXNuJ3QgZXhpc3RcbiAgICogICAgICAgICBDbGlXcmFwcGVyLT4+Q29tbWFuZDogY29tbWFuZChuYW1lKS5hZGRDb21tYW5kKG1vZHVsZXNbbmFtZV0pXG4gICAqICAgICAgIGVuZFxuICAgKiAgICAgZW5kXG4gICAqICAgZW5kXG4gICAqICAgQ2xpV3JhcHBlci0+PkNvbnNvbGU6IExvZyBsb2FkZWQgbW9kdWxlc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBib290KCkge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLmJvb3QpO1xuICAgIGxldCBzZXJ2ZXIgPSB0aGlzLm1jcDtcbiAgICAvLyBkaXNjb3ZlciBtb2R1bGVzIGJ5IGNyYXdsaW5nIGJhc2VQYXRoXG4gICAgY29uc3QgbW9kdWxlRmlsZXMgPSB0aGlzLmNyYXdsKFxuICAgICAgcGF0aC5yZXNvbHZlKHRoaXMuYmFzZVBhdGgpLFxuICAgICAgdGhpcy5jcmF3bExldmVsc1xuICAgICk7XG4gICAgZm9yIChjb25zdCBtb2R1bGVGaWxlIG9mIG1vZHVsZUZpbGVzKSB7XG4gICAgICBpZiAobW9kdWxlRmlsZS5pbmNsdWRlcyhcIkBkZWNhZi10cy9tY3BcIikpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLmxvYWQoc2VydmVyLCBtb2R1bGVGaWxlKTtcbiAgICAgICAgc2VydmVyID0gcmVzLm1jcDtcbiAgICAgICAgdGhpcy5tb2R1bGVzW3Jlcy5wYWNrYWdlXSA9IG1vZHVsZUZpbGU7XG4gICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgIGxvZy5lcnJvcihcbiAgICAgICAgICBgRmFpbGVkIHRvIGxvYWQgTUNQIGNvbmZpZ3MgZm9yICR7bW9kdWxlRmlsZX06ICR7ZSBpbnN0YW5jZW9mIEVycm9yID8gZS5tZXNzYWdlIDogZX1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKFxuICAgICAgYGxvYWRlZCBtb2R1bGVzOlxcbiR7T2JqZWN0LmtleXModGhpcy5tb2R1bGVzKVxuICAgICAgICAubWFwKChrKSA9PiBgLSAke2t9YClcbiAgICAgICAgLmpvaW4oXCJcXG5cIil9YFxuICAgICk7XG4gICAgcmV0dXJuIHNlcnZlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVjdXJzaXZlbHkgc2VhcmNoZXMgZm9yIENMSSBtb2R1bGUgZmlsZXMgaW4gdGhlIGRpcmVjdG9yeSBzdHJ1Y3R1cmVcbiAgICogQHN1bW1hcnkgQ3Jhd2xzIHRoZSBiYXNlUGF0aCB1cCB0byB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiBmb2xkZXIgbGV2ZWxzIHRvIGZpbmQgZmlsZXMgbmFtZWQgYWNjb3JkaW5nIHRvIENMSV9GSUxFX05BTUVcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGJhc2VQYXRoIFRoZSBhYnNvbHV0ZSBiYXNlIHBhdGggdG8gc3RhcnQgc2VhcmNoaW5nIGluXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbbGV2ZWxzPTJdIFRoZSBtYXhpbXVtIG51bWJlciBvZiBkaXJlY3RvcnkgbGV2ZWxzIHRvIGNyYXdsXG4gICAqIEByZXR1cm4ge3N0cmluZ1tdfSBBbiBhcnJheSBvZiBmaWxlIHBhdGhzIHRvIENMSSBtb2R1bGVzXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGNyYXdsKGJhc2VQYXRoOiBzdHJpbmcsIGxldmVsczogbnVtYmVyID0gMikge1xuICAgIGlmIChsZXZlbHMgPD0gMCkgcmV0dXJuIFtdO1xuICAgIHJldHVybiBmcy5yZWFkZGlyU3luYyhiYXNlUGF0aCkucmVkdWNlKChhY2N1bTogc3RyaW5nW10sIGZpbGUpID0+IHtcbiAgICAgIGZpbGUgPSBwYXRoLmpvaW4oYmFzZVBhdGgsIGZpbGUpO1xuICAgICAgaWYgKGZzLnN0YXRTeW5jKGZpbGUpLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgYWNjdW0ucHVzaCguLi50aGlzLmNyYXdsKGZpbGUsIGxldmVscyAtIDEpKTtcbiAgICAgIH0gZWxzZSBpZiAoZmlsZS5tYXRjaChuZXcgUmVnRXhwKGAke01DUF9GSUxFX05BTUV9LltjbV0/anMkYCwgXCJnbVwiKSkpIHtcbiAgICAgICAgYWNjdW0ucHVzaChmaWxlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhY2N1bTtcbiAgICB9LCBbXSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIHRoZSBDTEkgd2l0aCB0aGUgcHJvdmlkZWQgYXJndW1lbnRzXG4gICAqIEBzdW1tYXJ5IEJvb3RzIHRoZSBDTEkgYnkgbG9hZGluZyBhbGwgbW9kdWxlcywgdGhlbiBwYXJzZXMgYW5kIGV4ZWN1dGVzIHRoZSBjb21tYW5kIHNwZWNpZmllZCBpbiB0aGUgYXJndW1lbnRzXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IFthcmdzPXByb2Nlc3MuYXJndl0gQ29tbWFuZCBsaW5lIGFyZ3VtZW50cyB0byBwYXJzZSBhbmQgZXhlY3V0ZVxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBjb21tYW5kIGV4ZWN1dGlvbiBpcyBjb21wbGV0ZVxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAgICogICBwYXJ0aWNpcGFudCBDbGlXcmFwcGVyXG4gICAqICAgcGFydGljaXBhbnQgQ29tbWFuZFxuICAgKlxuICAgKiAgIENsaWVudC0+PkNsaVdyYXBwZXI6IHJ1bihhcmdzKVxuICAgKiAgIENsaVdyYXBwZXItPj5DbGlXcmFwcGVyOiBib290KClcbiAgICogICBOb3RlIG92ZXIgQ2xpV3JhcHBlcjogTG9hZHMgYWxsIG1vZHVsZXNcbiAgICogICBDbGlXcmFwcGVyLT4+Q29tbWFuZDogcGFyc2VBc3luYyhhcmdzKVxuICAgKiAgIENvbW1hbmQtLT4+Q2xpV3JhcHBlcjogcmVzdWx0XG4gICAqICAgQ2xpV3JhcHBlci0tPj5DbGllbnQ6IHJlc3VsdFxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBhc3luYyBydW4oYXJnczogc3RyaW5nW10gPSBwcm9jZXNzLmFyZ3YpIHtcbiAgICBjb25zdCBzZXJ2ZXIgPSBhd2FpdCB0aGlzLmJvb3QoKTtcbiAgICBhd2FpdCBzZXJ2ZXIuc3RhcnQoeyB0cmFuc3BvcnRUeXBlOiBcInN0ZGlvXCIgfSk7XG4gIH1cbn1cbiJdLCJuYW1lcyI6WyJ6Iiwic3Bhd25TeW5jIiwiYXBwbHlQYXRjaCIsImNyZWF0ZVR3b0ZpbGVzUGF0Y2giLCJ0b29sTGlzdCIsImNvcmVUb29sTGlzdCIsIlZFUlNJT04iLCJQQUNLQUdFX05BTUUiLCJNZXRhZGF0YSIsIlBLRyIsIlYiLCJwYXRoVG9GaWxlVVJMIiwicGF0aCIsImZzIiwiTG9nZ2VkQ2xhc3MiLCJGYXN0TUNQIl0sIm1hcHBpbmdzIjoiOzs7Ozs7SUFBQTs7Ozs7O0lBTUc7QUFDSSxVQUFNLGFBQWEsR0FBRztBQUd0QixVQUFNLGtCQUFrQixHQUFHO1VBQ3JCLGtCQUFrQixHQUFHLENBQUMsZUFBZSxFQUFFLGdCQUFnQjtBQUM3RCxVQUFNLG1CQUFtQixHQUFHO0FBQzVCLFVBQU0sbUJBQW1CLEdBQUc7SUFDakMsSUFBQTtJQUNFLFFBQUEsRUFBRSxFQUFFLFFBQVE7SUFDWixRQUFBLE9BQU8sRUFBRSxvQkFBb0I7SUFDN0IsUUFBQSxZQUFZLEVBQ1Ysb01BQW9NO0lBQ3ZNLEtBQUE7SUFDRCxJQUFBO0lBQ0UsUUFBQSxFQUFFLEVBQUUsUUFBUTtJQUNaLFFBQUEsT0FBTyxFQUFFLFFBQVE7SUFDakIsUUFBQSxZQUFZLEVBQ1YsaUxBQWlMO0lBQ3BMLEtBQUE7SUFDRCxJQUFBO0lBQ0UsUUFBQSxFQUFFLEVBQUUsU0FBUztJQUNiLFFBQUEsT0FBTyxFQUFFLGdCQUFnQjtJQUN6QixRQUFBLFlBQVksRUFDVixpTUFBaU07SUFDcE0sS0FBQTs7O0lDM0JILElBQUksYUFBYSxHQUFHLHVCQUF1QixFQUFF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
1
+ var e,t;e=this,t=function(e,t,r,n,o,s,i,a,c,d,l,m,u,p,h,g,f){"use strict";function y(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var b,S,v,w=y(c),x=y(d);(e=>{e[e.NONE=0]="NONE",e[e.BASIC=1]="BASIC",e[e.ADVANCED=2]="ADVANCED",e[e.HIGH=3]="HIGH"})(b||(b={})),(e=>{e[e.NONE=0]="NONE",e[e.LOW=1]="LOW",e[e.MEDIUM=2]="MEDIUM",e[e.HIGH=3]="HIGH"})(S||(S={})),(e=>{e[e.FREE=0]="FREE",e[e.LOW=1]="LOW",e[e.MEDIUM=2]="MEDIUM",e[e.HIGH=3]="HIGH"})(v||(v={}));class T extends r.Model{constructor(e){super(e),r.Model.fromObject(this,e)}log(e){const{sessionId:t,requestId:r,authInfo:o}=e||{};let s="string"==typeof t&&t.length>0?n.Logging.for(t).for(this):n.Logging.for(this);return o&&o.clientId&&(s=s.for(o.clientId)),r&&(s=s.for(r.toString())),s}setDescription(e){return this.description=e,this}setName(e){return this.name=e,this}setTitle(e){return this.title=e,this}}t.__decorate([r.required(),t.__metadata("design:type",String)],T.prototype,"description",void 0),t.__decorate([r.required(),t.__metadata("design:type",String)],T.prototype,"name",void 0),t.__decorate([r.required(),t.__metadata("design:type",String)],T.prototype,"title",void 0);class N extends T{constructor(e){super(e),this.reasoning=b.NONE,this.effort=S.NONE,this.cost=v.FREE}setReasoning(e){return this.reasoning=e,this}setEffort(e){return this.effort=e,this}setCost(e){return this.cost=e,this}}t.__decorate([r.required(),t.__metadata("design:type",Number)],N.prototype,"reasoning",void 0),t.__decorate([r.required(),t.__metadata("design:type",Number)],N.prototype,"effort",void 0),t.__decorate([r.required(),t.__metadata("design:type",Number)],N.prototype,"cost",void 0);class _ extends N{setCb(e){return this.cb=e,this}setArgsSchema(e){return this.argsSchema=e,this}constructor(e){super(e)}static get builder(){return new _}build(e){const t=this.hasErrors();if(t)throw Error(t.toString());try{return e.registerPrompt(this.name,{title:this.title,description:this.description,argsSchema:this.argsSchema},async(e,t)=>{const r=this.log(t);e=e||{},r.verbose(`Executing prompt ${this.name} with args: ${JSON.stringify(e)}`),e._meta=Object.assign(e._meta||{},{usage:{reasoning:this.reasoning,effort:this.effort,cost:this.cost}});const n=await Promise.resolve(this.cb(e,t));return r.verbose(`Prompt ${this.name} executed successfully.`),r.debug("Prompt execution meta: "+JSON.stringify(n._meta)),n})}catch(e){throw n.Logging.for(this).error("Failed to register prompt "+this.name,e),e}}}t.__decorate([r.required(),t.__metadata("design:type",Object)],_.prototype,"cb",void 0),t.__decorate([r.required(),t.__metadata("design:type",Object)],_.prototype,"argsSchema",void 0);class E extends T{setCb(e){return this.cb=e,this}setConfig(e){return this.config=e,this}setUriOtTemplate(e){return this.uriOrTemplate=e,this}constructor(e){super(e)}static get builder(){return new E}build(e){const t=this.hasErrors();if(t)throw Error(t.toString());try{const t="string"==typeof this.uriOrTemplate&&this.uriOrTemplate.includes("{")?new s.ResourceTemplate(new o.UriTemplate(this.uriOrTemplate),{list:void 0}):this.uriOrTemplate,r=Object.assign(this.config,{_meta:{}}),n=async(e,t)=>{const r=this.log(t);r.verbose(`Requesting resource ${this.name} from ${e.toString()}`);const n=await Promise.resolve(this.cb(e,t));return r.verbose(`Resource ${this.name} retrieved successfully.`),r.debug("Resource retrieval meta: "+JSON.stringify(n._meta)),n};return e.resource(this.name,t,r,n)}catch(e){throw n.Logging.for(this).error("Error registering resource "+this.name,e),e}}}t.__decorate([r.required(),t.__metadata("design:type",String)],E.prototype,"uriOrTemplate",void 0),t.__decorate([r.required(),t.__metadata("design:type",Function)],E.prototype,"cb",void 0),t.__decorate([r.required(),t.__metadata("design:type",Object)],E.prototype,"config",void 0);class O extends N{setAnnotations(e){return this.annotations=Object.assign(this.annotations,e),this}setCb(e){return this.cb=e,this}setInputSchema(e){return this.inputSchema=e,this}setOutputSchema(e){return this.outputSchema=e,this}constructor(e){super(e),this.annotations={readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}}static get builder(){return new O}build(e){const t=this.hasErrors();if(t)throw Error(t.toString());try{return e.registerTool(this.name,{title:this.title,description:this.description,inputSchema:this.inputSchema,outputSchema:this.outputSchema,annotations:this.annotations,_meta:{usage:{reasoning:this.reasoning,effort:this.effort,cost:this.cost}}},async(e,t)=>{const r=this.log(t);r.verbose(`Executing tool ${this.name} with args: ${JSON.stringify(e)}`),t._meta=Object.assign(t._meta||{},{usage:{reasoning:this.reasoning,effort:this.effort,cost:this.cost}});const n=await Promise.resolve(this.cb(e,t));return r.verbose(`Tool ${this.name} executed successfully.`),r.debug("Tool execution meta: "+JSON.stringify(n._meta)),n})}catch(e){throw n.Logging.for(this).error("Error building tool",e),e}}}t.__decorate([r.required(),t.__metadata("design:type",Object)],O.prototype,"annotations",void 0),t.__decorate([r.required(),t.__metadata("design:type",Object)],O.prototype,"cb",void 0),t.__decorate([r.type(Object.name),r.required(),t.__metadata("design:type",Object)],O.prototype,"inputSchema",void 0),t.__decorate([r.type(Object.name),t.__metadata("design:type",Object)],O.prototype,"outputSchema",void 0);const D=["\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"];let j=null;async function A(e){const t=j||(j=new m.Project({tsConfigFilePath:void 0,skipAddingFilesFromTsConfig:!0}),j),r=t.addSourceFileAtPathIfExists(e)||t.createSourceFile(e,void 0,{overwrite:!1});try{await Promise.race([t.resolveSourceFileDependencies(),new Promise(e=>setTimeout(e,2e3))])}catch(e){}const n=r.getExportedDeclarations();return{astObjects:Array.from(n.entries()).flatMap(([t,r])=>r.map(r=>{const n="function"==typeof r.getStartLineNumber?r.getStartLineNumber():0,o="function"==typeof r.getEndLineNumber?r.getEndLineNumber():0,s="function"==typeof r.getKindName?(r.getKindName()+"").toLowerCase():"unknown",i="function"==typeof r.getStartLinePos?r.getStartLinePos():0;return{id:`${e}::${t}`,name:t,kind:s,location:{filePath:e,startLine:n,startColumn:i,endLine:o,endColumn:0},isExported:!0}}))}}const C="ts.ast.extract",P="AST Extraction Tool for TypeScript",I=l.z.object({filePath:l.z.string().describe("The path to the TypeScript file to analyze.")}).describe(`the input schema for the ${C} tool`);l.z.object({}).describe(`the output schema for the ${C} tool`);const $=O.builder.setName(C).setTitle(P).setDescription("Extracts and analyzes the Abstract Syntax Tree (AST) of TypeScript code to provide insights into its structure and components.").setInputSchema(I).setAnnotations({title:P,readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}).setCb(async(e,t)=>{const{filePath:r}=e,n=await Promise.race([A(r),new Promise(e=>setTimeout(()=>e(null),1500))]);if(!n||!n.astObjects)return{content:[{type:"text",text:"No AST objects or analysis timed out"}],structuredContent:{astObjects:[]}};const o=n.astObjects.map(e=>({id:e.id,name:e.name,kind:e.kind||"unknown",location:e.location,isExported:!!e.isExported,signature:e.signature,parentId:e.parentId,children:e.children,decorators:e.decorators,contextHints:e.contextHints||[]}));return{content:[{type:"text",text:`Found ${o.length} AST objects`}],structuredContent:{astObjects:o}}}),k=O.builder.setName("example-tool").setTitle("Example: Reverse String Tool").setDescription("Reverses the provided `text` input and returns the result.").setInputSchema(l.z.object({text:l.z.string()})).setCb(async(e,t)=>{const r=((e?.text??"")+"").split("").reverse().join("");return{content:[{type:"text",text:r}],structuredContent:{result:r}}}).setReasoning(b.NONE).setEffort(S.NONE).setCost(v.FREE),R=O.builder.setName("ast.jsdoc").setTitle("AST \u2192 JSDoc Tool").setDescription("Generate suggested JSDoc comments for TypeScript AST objects (MVP stub).").setInputSchema(l.z.object({filePath:l.z.string()})).setCb(async(e,t)=>{const r=[{type:"text",text:"Not implemented (stub)"}];return{content:r,structuredContent:{content:r}}}).setReasoning(b.BASIC).setEffort(S.LOW).setCost(v.FREE),q=[$,k,O.builder.setName("file.summarizer").setTitle("File Summarizer").setDescription("Produce a short structured summary for a TypeScript file.").setInputSchema(l.z.object({filePath:l.z.string()})).setCb(async(e,t)=>{if(!(e?.filePath??e?.path))return{content:[{type:"text",text:""}]};const r=await(async()=>({astObjects:[]}))().catch(()=>null),n=r&&r.astObjects||[],o=n.map(e=>e.name||e.id||e.kind).slice(0,20),s=`Found ${n.length} AST objects. Top names: ${o.join(", ")}`;return{content:[{type:"text",text:s}],structuredContent:{summary:s},_meta:{count:n.length}}}).setReasoning(b.NONE).setEffort(S.NONE).setCost(v.FREE),R];var z=Object.freeze({__proto__:null,Tools:q});const J="You're a senior TypeScript developer writing JSDoc documentation for a class to be used with better-docs. Given the module code:\nGenerate a JSDoc comment block for a TypeScript module file using better-docs formatting:",M="document the target code, always including the @description tag with a short description of the target, and a@summary tag with a more detailed one.\n Include @interface and @typeDef an @template tags when appropriate.\n Include detailed @description for all properties.\n For methods, include @description and @summary tags as defined for the target. also document every argument, including its type definition, and return type, referencing @template tags when necessary.\n\n The order of tags (when applicable) should be as follows:\n1 - @description;\n2 - @summary;\n3 - @template;\n4 - @param;\n5 - @return;\n6 - @interface or @typeDef followed by the interface or type name;\n8 - @memberOf referencing the appropriate module using the appropriate syntax\n\nOutput only the completed JSDoc comment block for the type or interface.\nrefer to the module it belongs with @memberOf this the `@memberOf module:<module_name>` syntax\nnever omit or change any code\nif the element is already documented, only restructure, correct, or add to the documentation. NEVER remove existing information",L="document the target code, always including the @description tag with a short description of the target, and a@summary tag with a more detailed one.\nInclude @const and @typeDef tags when appropriate.\nInclude detailed @description for all properties.\n- For enums, include @enum and @readonly, and add inline documentation for each member\n- For object-like constants:\n - Create a @typedef with @property for each key\n - Reference it in the constant using @type\n - Alternatively, document each key inline if small\n\nThe order of tags (when applicable) should be as follows:\n1 - @description;\n2 - @summary;\n3 - @template;\n4 - @property;\n6 - @const followed by the const or enum name;\n8 - @memberOf referencing the appropriate module using the appropriate syntax\n\nRespond with the JSDoc comment block(s) for both the typedef and the constant or enum.\nrefer to the module it belongs with @memberOf this the `@memberOf module:<module_name>` syntax\nnever omit or change any code\nif the element is already documented, only restructure, correct, or add to the documentation. NEVER remove existing information",F="NOTES:\n - when document a function/method parameters, and there is a template type involved, ALWAYS reference it using the @template tag;\n - when documenting a function type as a parameter, ALWAYS use the function(type1,type2):return_type syntax;\n ",H=l.z.object({}),B=_.builder.setName("ts.jsdoc.class").setTitle("Class JSDocs Prompt").setDescription("Generate JSDoc comments for a TypeScript class according to a curated template and prompt.").setArgsSchema(H).setReasoning(b.BASIC).setCb((e,t)=>({messages:[{role:"user",content:{type:"text",text:`${J}\ndocument the entire class and each of its functions including always including the @description tag with a short description of the target, and a@summary tag with a more detailed one.\nInclude @class tags when applicable.\ninclude @param tags in the class documentation and its type definitions\nInclude detailed @description for all properties.\nInclude @template tags when necessary.\nDo NOT document the constructor, but include the constructor arguments as @param in the class documentation\nFor methods and functions:\n- include @description and @summary tags as defined for the target. also document every argument, including its type definition, and return type, referencing @template tags when necessary.\n- create a usage example under the @example tag on the class documentation\n- create mermaid sequence diagrams under the @mermaid tag;\n\nThe order of tags (when applicable) should be as follows:\n1 - @description;\n2 - @summary;\n3 - @template;\n4 - @param;\n5 - @return;\n6 - @class\n7 - @example\n8 - @mermaid;\n\nignore @mermaid for methods with less that 15 lines and constructors.\nRespond only with the full JSDoc comment block for the class and its methods.\nNEVER user @memberOf in the class or any of it's methods\nif the element is already documented, only restructure, correct, or add to the documentation. NEVER remove existing information\nnever omit or change any code, including the constructor\n${F}`}}],_meta:{}})),G=l.z.object({}),U=_.builder.setName("ts.jsdoc.const").setTitle("Const JSDocs Prompt").setDescription("Generate JSDoc comments for a TypeScript constant according to a curated template and prompt.").setArgsSchema(G).setCb((e,t)=>({messages:[{role:"user",content:{type:"text",text:`${J}\n${L}\n${F}`}}]})),V=l.z.object({}),W=_.builder.setName("ts.jsdoc.decorator").setTitle("Decorator JSDocs Prompt").setDescription("Generate JSDoc comments for a TypeScript Decorator according to a curated template and prompt.").setArgsSchema(V).setCb((e,t)=>({messages:[{role:"user",content:{type:"text",text:`${J}\ndocument the target code, always including the @description tag with a short description of the target, and a@summary tag with a more detailed one.\nInclude @function an @template tags when appropriate.\nInclude detailed @description for all properties.\nFor methods, include @description and @summary tags as defined for the target. also document every argument, including its type definition, and return type, referencing @template tags when necessary.\ncreate mermaid sequence diagrams under the @mermaid tag;\n\nThe order of tags (when applicable) should be as follows:\n1 - @description;\n2 - @summary;\n3 - @template;\n4 - @param including type definitions;\n5 - @return;\n6 - @function followed by the interface or type name;\n7 - @mermaid with the sequence diagram for the function if it has over 10 lines\n8 - @category one of: "Decorators", "Class Decorators", "Method Decorators", "Property Decorators", "Parameter Decorators"\nOutput only the full JSDoc comment block for the function.\nDO NOT refer to the module it belongs with @memberOf\nnever omit or change any code\nif the element is already documented, only restructure, correct, or add to the documentation. NEVER remove existing information\n${F}`}}]})),K=l.z.object({}),Y=_.builder.setName("ts.jsdoc.enum").setTitle("Enum JSDocs Prompt").setDescription("Generate JSDoc comments for a TypeScript enum according to a curated template and prompt.").setArgsSchema(K).setCb((e,t)=>({messages:[{role:"user",content:{type:"text",text:`${J}\n${L}\n${F}`}}]})),Q=l.z.object({}),X=_.builder.setName("ts.jsdoc.function").setTitle("Function JSDocs Prompt").setDescription("Generate JSDoc comments for a TypeScript function according to a curated template and prompt.").setArgsSchema(Q).setCb((e,t)=>({messages:[{role:"user",content:{type:"text",text:`${J}\ndocument the target code, always including the @description tag with a short description of the target, and a@summary tag with a more detailed one.\nInclude @function an @template tags when appropriate.\nInclude detailed @description for all properties.\nFor methods, include @description and @summary tags as defined for the target. also document every argument, including its type definition, and return type, referencing @template tags when necessary.\ncreate mermaid sequence diagrams under the @mermaid tag;\n\nThe order of tags (when applicable) should be as follows:\n1 - @description;\n2 - @summary;\n3 - @template;\n4 - @param including type definitions;\n5 - @return;\n6 - @function followed by the interface or type name;\n7 - @mermaid with the sequence diagram for the function if ithas over 10 lines\n8 - @memberOf referencing the appropriate module using the appropriate syntax\n\nOutput only the full JSDoc comment block for the function.\nrefer to the module it belongs with @memberOf this the \`@memberOf module:<module_name>\` syntax\nnever omit or change any code\nif the element is already documented, only restructure, correct, or add to the documentation. NEVER remove existing information\n${F}`}}]})),Z=l.z.object({}),ee=_.builder.setName("ts.jsdoc.interface").setTitle("Interface JSDocs Prompt").setDescription("Generate JSDoc comments for a TypeScript interface according to a curated template and prompt.").setArgsSchema(Z).setCb((e,t)=>({messages:[{role:"user",content:{type:"text",text:`${J}\n${M}\n${F}`}}]})),te=l.z.object({}),re=_.builder.setName("ts.jsdoc.type").setTitle("Type JSDocs Prompt").setDescription("Generate JSDoc comments for a TypeScript type according to a curated template and prompt.").setArgsSchema(te).setCb((e,t)=>({messages:[{role:"user",content:{type:"text",text:`${J}\n${M}\n${F}`}}]})),ne=l.z.object({className:l.z.string().describe("the class name to turn into a builder")}),oe=_.builder.setName("ts.code.dp.builder").setTitle("Typescript builder design patter prompt").setDescription("for a class, with a defined set of properties, scafold a builder design pattern").setArgsSchema(ne).setReasoning(b.BASIC).setCb((e,t)=>(e.className=n.toPascalCase(e.className),{messages:[{role:"user",content:{type:"text",text:`You're a senior TypeScript developer writing typescript code.You're a senior TypeScript developer writing typescript code.\nTransform the selected class into a builder design pattern implementation in Typescript.\nuse @decaf-ts validation decorators to enforce the validation of your builder.\n\n- must extend the Model Class from @decaf-ts/decorator-validation;\n- each property must be marked as protected;\n- each property must have a setter method that returns 'this' for chaining;\n- the build() method must validate the properties using hasErrors() method from Model class;\n- if validation fails, throw an error with the validation errors;\n- if validation passes, return an instance of the original class with the set properties;\n- optionally (but do so by default) add the static builder and from methods from the example;\n- if the clasee already follows the pattern but has properties without decoration or without setters, simple add them;\n\nexample:\n\noriginal class:\n\`\`\`typescript\nexport class ${e.className} {\n description!: string;\n name!: string = "default name";\n title!: string;\n age?: string;\n dateOfBirth!: Date;\n}}\n\`\`\` \n\nresulting builder pattern implementation:\n\`\`\`typescript\nexport class ${e.className}Builder extends Model {\n\n @minlength(10\n @required()\n protected description!: string;\n \n @required()\n protected name!: string = "default value;\n \n @required()\n protected title!: string;\n \n @min(18)\n protected age?: string;\n \n @date()\n protected dateOfBirth!: Date;\n\n protected constructor(arg?: ModelArg<${e.className}Builder>>) {\n super(arg);\n Model.fromModel(this, arg);\n }\n\n setDescription(value: string) {\n this.description = value;\n return this;\n }\n\n setName(value: string) {\n this.name = value;\n return this;\n }\n\n setTitle(value: string) {\n this.title = value;\n return this;\n }\n setAge(value: number) {\n this.age = value;\n return this;\n }\n setDate(value: Date) {\n this.age = value;\n return this;\n }\n \n build(...args: any[]): ${e.className}Builder | Promise<${e.className}Builder> {\n const errs = this.hasErrors();\n if (errs) throw new Error(errs.toString());\n \n return // code that builds OBJ here\n }\n \n static get builder(): ${e.className}Builder {\n return new ${e.className}Builder(); // static method to get a new builder instance\n }\n \n static from<K extends keyof ${e.className}Builder>(obj: K, ${e.className}Builder[K]): ${e.className}Builder {\n return new ${e.className}Builder(); // static method to create a builder from an object\n }\n}\n\`\`\` \n\n`}}],_meta:{}})),se=l.z.object({text:l.z.string().optional()}),ie=_.builder.setName("example.prompt.echo").setTitle("Example: Echo Prompt").setDescription("Returns a short prompt containing the provided `text` as a user message.").setArgsSchema(se).setReasoning(b.BASIC).setCb((e,t)=>({messages:[{role:"user",content:{type:"text",text:e?.text??"(no text provided)"}}],_meta:{}})),ae=l.z.object({code:l.z.string().optional(),astObject:l.z.any().optional()}),ce=[B,U,W,Y,X,ee,re,oe,ie,_.builder.setName("interactive.jsdoc.assistant").setTitle("Interactive JSDoc Assistant").setDescription("Produce a ready-to-insert JSDoc block for a provided code snippet or AST object.").setArgsSchema(ae).setReasoning(b.BASIC).setCb((e,t)=>({messages:[{role:"user",content:{type:"text",text:"Generate a complete JSDoc comment block for the following code. Respond only with the full JSDoc block.\n\n"+(e?.code??"")}}],_meta:{}}))],de=[E.builder.setName("example.resource.hello").setTitle("Example: Hello Resource").setDescription("A tiny example resource that returns a simple payload for any URI.").setUriOtTemplate("example://hello/{name}").setConfig({description:"Example resource",_meta:{usage:{reasoning:b.NONE,effort:S.NONE,cost:v.FREE}}}).setCb(async(e,t)=>({content:{type:"text",text:"hello from example resource"},_meta:{}})),E.builder.setName("repo.metadata").setTitle("Repository Metadata Resource").setDescription("Expose basic repository metadata such as package.json and lint rules.").setUriOtTemplate("repo://metadata/{file}").setConfig({description:"Repository metadata resource",_meta:{usage:{reasoning:b.NONE,effort:S.NONE,cost:v.FREE}}}).setCb(async(e,t)=>{const r=e.pathname.replace(/^\//,"")||"package.json";try{const e=c.resolve(process.cwd(),r),t=await u.readFile(e,{encoding:"utf8"}),n=JSON.parse(t);return{content:{type:"json",data:JSON.stringify(n)},_meta:{}}}catch(e){return{content:{type:"text",text:""},_meta:{}}}})],le="##VERSION##",me="##PACKAGE##";f.Metadata.registerLibrary(me,le);const ue={mcpId:me,name:"Official Decaf-TS MCP Server",title:"Official Decaf-TS MCP Server",description:"Provides precise coding assistance for the decaf-ts framework",version:le,websiteUrl:"https://decaf-ts.github.io",repositoryUrl:"https://github.com/decaf-ts",license:"AGPL-3.0",contacts:[{name:"Decaf-TS",url:"https://decaf-ts.github.io"}],tags:"server,official,decaf-ts",metadata:{},icons:[{src:"workdocs/assets/favicon.svg",mimeType:"image/svg+xml",sizes:"any"}]},pe=n.LoggedEnvironment.accumulate(ue);class he extends n.LoggedClass{get client(){if(!this._mcp)throw Error("Mcp server requires Mcp client");return this._mcp}constructor(){super()}async load(){try{const e=await Promise.all(de.map(e=>e.build(this.client)));this.log.verbose(`Loaded ${e.length} resources`);const t=await Promise.all(ce.map(e=>e.build(this.client)));this.log.verbose(`Loaded ${t.length} prompts`);const r=await Promise.all(q.map(e=>e.build(this.client)));this.log.verbose(`Loaded ${r.length} tools`);try{const e=await Promise.resolve().then(()=>z),t=Object.values(e).filter(e=>e&&"function"==typeof e.build).filter(e=>!q.includes(e));if(t.length>0){const e=await Promise.all(t.map(e=>e.build(this.client)));this.log.verbose(`Loaded ${e.length} exported builders from tools module`)}}catch(e){this.log.verbose("No additional exported builders loaded from tools module: "+e)}}catch(e){throw this.log.error("Error loading core MCP components",e),e}}async boot(e="stdio"){const t=this.log;this.log.for(this.boot).info("McpServer booting..."),((e=n.Logging.get())=>{let t;try{t=(()=>{let e,t=__dirname;try{for(;t&&t!==w.default.parse(t).root;){const r=w.default.join(t,"node_modules");if(x.default.existsSync(r)&&x.default.statSync(r).isDirectory()){e=r;break}const n=w.default.dirname(t);if(n===t)break;t=n}}catch{}const r=[];if(e){const t=w.default.join(e,"@decaf-ts");try{if(x.default.existsSync(t)&&x.default.statSync(t).isDirectory()){const e=x.default.readdirSync(t);for(const n of e){const e=w.default.join(t,n);try{const t=w.default.join(e,"workdocs","assets","slogans.json");if(x.default.existsSync(t)&&x.default.statSync(t).isFile()){const e=x.default.readFileSync(t,"utf-8"),n=JSON.parse(e);if(Array.isArray(n))for(const e of n)"string"==typeof e&&e.trim().length>0&&r.push(e.trim())}}catch{}}}}catch{}}return 0===r.length?"Decaf: strongly brewed TypeScript.":r[Math.floor(Math.random()*r.length)]})()}catch{t="Decaf: strongly brewed TypeScript."}const r="# \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"),o=r.reduce((e,t)=>Math.max(e,t.length),0);r.push("# "+t.padStart(o-3)),r.forEach((t,r)=>{const n=D[r%D.length]||"",o=e?e.info.bind(e):(()=>{}).bind();try{o(a.style(t||"").raw(n).text)}catch{o((t||"")+"")}})})(this.log);const r=((Array.isArray(pe.icons)?pe.icons:[pe.icons])||[]).map(e=>{const t="string"==typeof e?.src?e.src:(e?.src??"")+"",r="string"==typeof e?.mimeType?e.mimeType:(e?.mimeType??"")+"";let n=[];return Array.isArray(e?.sizes)?n=e.sizes.map(e=>e+""):"string"==typeof e?.sizes&&(n=(e.sizes+"").split(",").map(e=>e.trim())),{src:t,mimeType:r,sizes:n}}),o=pe.contacts;let s;if(null!=o)if(Array.isArray(o))s=o.map(e=>({name:"string"==typeof e?.name?e.name:(e?.name??"")+"",email:"string"==typeof e?.email?e.email:e?.email?e.email+"":void 0,url:"string"==typeof e?.url?e.url:e?.url?e.url+"":void 0}));else if("object"==typeof o){const e=Object.keys(o||{}).filter(e=>/^[0-9]+$/.test(e)).sort((e,t)=>Number(e)-Number(t));if(e.length>0)s=e.map(e=>{const t=o[e];return{name:"string"==typeof t?.name?t.name:(t?.name??"")+"",email:"string"==typeof t?.email?t.email:t?.email?t.email+"":void 0,url:"string"==typeof t?.url?t.url:t?.url?t.url+"":void 0}});else if("number"==typeof o.length){const e=Number(o.length)||0;s=[];for(let t=0;e>t;t++){const e=o[t];s.push({name:"string"==typeof e?.name?e.name:(e?.name??"")+"",email:"string"==typeof e?.email?e.email:e?.email?e.email+"":void 0,url:"string"==typeof e?.url?e.url:e?.url?e.url+"":void 0})}}else s=Object.keys(o).filter(e=>"length"!==e).map(e=>{const t=o[e];return{name:"string"==typeof t?.name?t.name:(t?.name??"")+"",email:"string"==typeof t?.email?t.email:t?.email?t.email+"":void 0,url:"string"==typeof t?.url?t.url:t?.url?t.url+"":void 0}})}const c={id:pe.mcpId,name:pe.name,title:pe.title,description:pe.description,websiteUrl:pe.websiteUrl,repositoryUrl:pe.repositoryUrl,version:pe.version,license:pe.license,contacts:s,tags:pe.tags?pe.tags.split(","):void 0,metadata:pe.metadata,icons:r};this._mcp=new i.McpServer(c,{instructions:"You are an AI assistant designed to help users with programming tasks related to the Decaf-TS framework. \nProvide clear, concise, and accurate information.\nIf you don't know the answer, admit it rather than making up information.\nAlways prioritize the user's intent and provide helpful suggestions when appropriate.\n",capabilities:{logging:{},completions:{},resources:{},tools:{},prompts:{}}});try{await this.load()}catch(e){throw this.log.error("Error loading resources/prompts/tools: "+e),e}if("string"==typeof e)switch(e){case"stdio":e=new h.StdioServerTransport;break;case"http":e=new p.StreamableHTTPServerTransport({sessionIdGenerator:()=>g.v4(),onsessioninitialized:e=>t.verbose("Session initialized: "+e),onsessionclosed:e=>t.verbose("Session closed: "+e),enableJsonResponse:!0,eventStore:void 0,allowedHosts:["*"],allowedOrigins:["*"],enableDnsRebindingProtection:!0});break;default:throw Error("Invalid transport type: "+e)}return this.client.connect(e)}}e.Builder=T,e.McpServer=he,e.PACKAGE_NAME=me,e.PromptBuilder=_,e.ResourceBuilder=E,e.ToolBuilder=O,e.UsableBuilder=N,e.VERSION=le},"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("tslib"),require("@decaf-ts/decorator-validation"),require("@decaf-ts/logging"),require("@modelcontextprotocol/sdk/shared/uriTemplate"),require("@modelcontextprotocol/sdk/server/mcp"),require("@modelcontextprotocol/sdk/server/mcp.js"),require("styled-string-builder"),require("path"),require("fs"),require("zod"),require("ts-morph"),require("fs/promises"),require("@modelcontextprotocol/sdk/server/streamableHttp"),require("@modelcontextprotocol/sdk/server/stdio"),require("uuid"),require("@decaf-ts/decoration")):"function"==typeof define&&define.amd?define(["exports","tslib","@decaf-ts/decorator-validation","@decaf-ts/logging","@modelcontextprotocol/sdk/shared/uriTemplate","@modelcontextprotocol/sdk/server/mcp","@modelcontextprotocol/sdk/server/mcp.js","styled-string-builder","path","fs","zod","ts-morph","fs/promises","@modelcontextprotocol/sdk/server/streamableHttp","@modelcontextprotocol/sdk/server/stdio","uuid","@decaf-ts/decoration"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["mcp-server"]={},e.tslib,e.decafTsDecoratorValidation,e.decafTsLogging,e.uriTemplate,e.mcp,e.mcp_js,e.styledStringBuilder,e.path,e.fs,e.zod,e.tsMorph,e.fsPromises,e.streamableHttp,e.stdio,e.uuid,e.decafTsDecoration);
2
+ //# sourceMappingURL=mcp-server.cjs.map