@depup/aws-cdk 2.1117.0-depup.0

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 (308) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +16 -0
  3. package/README.md +25 -0
  4. package/THIRD_PARTY_LICENSES +24866 -0
  5. package/bin/cdk +6 -0
  6. package/build-info.json +4 -0
  7. package/changes.json +5 -0
  8. package/db.json.gz +0 -0
  9. package/docs/deploy-architecture.md +194 -0
  10. package/lib/api/aws-auth.d.ts +3 -0
  11. package/lib/api/aws-auth.js +21 -0
  12. package/lib/api/bootstrap/bootstrap-template.yaml +855 -0
  13. package/lib/api/bootstrap.d.ts +1 -0
  14. package/lib/api/bootstrap.js +19 -0
  15. package/lib/api/cloud-assembly.d.ts +5 -0
  16. package/lib/api/cloud-assembly.js +23 -0
  17. package/lib/api/cloudformation.d.ts +1 -0
  18. package/lib/api/cloudformation.js +19 -0
  19. package/lib/api/context.d.ts +1 -0
  20. package/lib/api/context.js +19 -0
  21. package/lib/api/deployments.d.ts +1 -0
  22. package/lib/api/deployments.js +19 -0
  23. package/lib/api/hotswap.d.ts +1 -0
  24. package/lib/api/hotswap.js +19 -0
  25. package/lib/api/index.d.ts +16 -0
  26. package/lib/api/index.js +38 -0
  27. package/lib/api/network-detector.d.ts +1 -0
  28. package/lib/api/network-detector.js +19 -0
  29. package/lib/api/notices.d.ts +1 -0
  30. package/lib/api/notices.js +19 -0
  31. package/lib/api/plugin.d.ts +1 -0
  32. package/lib/api/plugin.js +19 -0
  33. package/lib/api/refactor.d.ts +1 -0
  34. package/lib/api/refactor.js +8 -0
  35. package/lib/api/settings.d.ts +1 -0
  36. package/lib/api/settings.js +19 -0
  37. package/lib/api/tags.d.ts +1 -0
  38. package/lib/api/tags.js +19 -0
  39. package/lib/api-private.d.ts +9 -0
  40. package/lib/api-private.js +29 -0
  41. package/lib/cli/cdk-toolkit.d.ts +699 -0
  42. package/lib/cli/cdk-toolkit.js +1260 -0
  43. package/lib/cli/ci-systems.d.ts +29 -0
  44. package/lib/cli/ci-systems.js +61 -0
  45. package/lib/cli/cli-config.d.ts +10 -0
  46. package/lib/cli/cli-config.js +556 -0
  47. package/lib/cli/cli-type-registry.json +1147 -0
  48. package/lib/cli/cli.d.ts +3 -0
  49. package/lib/cli/cli.js +746 -0
  50. package/lib/cli/convert-to-user-input.d.ts +3 -0
  51. package/lib/cli/convert-to-user-input.js +560 -0
  52. package/lib/cli/display-version.d.ts +11 -0
  53. package/lib/cli/display-version.js +101 -0
  54. package/lib/cli/io-host/cli-io-host.d.ts +191 -0
  55. package/lib/cli/io-host/cli-io-host.js +477 -0
  56. package/lib/cli/io-host/index.d.ts +1 -0
  57. package/lib/cli/io-host/index.js +18 -0
  58. package/lib/cli/parse-command-line-arguments.d.ts +1 -0
  59. package/lib/cli/parse-command-line-arguments.js +1067 -0
  60. package/lib/cli/platform-warnings.d.ts +3 -0
  61. package/lib/cli/platform-warnings.js +44 -0
  62. package/lib/cli/pretty-print-error.d.ts +1 -0
  63. package/lib/cli/pretty-print-error.js +37 -0
  64. package/lib/cli/proxy-agent.d.ts +30 -0
  65. package/lib/cli/proxy-agent.js +52 -0
  66. package/lib/cli/root-dir.d.ts +10 -0
  67. package/lib/cli/root-dir.js +23 -0
  68. package/lib/cli/singleton-plugin-host.d.ts +7 -0
  69. package/lib/cli/singleton-plugin-host.js +11 -0
  70. package/lib/cli/tables.d.ts +1 -0
  71. package/lib/cli/tables.js +10 -0
  72. package/lib/cli/telemetry/collect-telemetry.d.ts +5 -0
  73. package/lib/cli/telemetry/collect-telemetry.js +16 -0
  74. package/lib/cli/telemetry/error.d.ts +15 -0
  75. package/lib/cli/telemetry/error.js +68 -0
  76. package/lib/cli/telemetry/feature-flags.d.ts +96 -0
  77. package/lib/cli/telemetry/feature-flags.js +103 -0
  78. package/lib/cli/telemetry/installation-id.d.ts +5 -0
  79. package/lib/cli/telemetry/installation-id.js +47 -0
  80. package/lib/cli/telemetry/library-version.d.ts +2 -0
  81. package/lib/cli/telemetry/library-version.js +30 -0
  82. package/lib/cli/telemetry/messages.d.ts +43 -0
  83. package/lib/cli/telemetry/messages.js +60 -0
  84. package/lib/cli/telemetry/sanitation.d.ts +100 -0
  85. package/lib/cli/telemetry/sanitation.js +79 -0
  86. package/lib/cli/telemetry/schema.d.ts +85 -0
  87. package/lib/cli/telemetry/schema.js +3 -0
  88. package/lib/cli/telemetry/session.d.ts +67 -0
  89. package/lib/cli/telemetry/session.js +174 -0
  90. package/lib/cli/telemetry/sink/endpoint-sink.d.ts +44 -0
  91. package/lib/cli/telemetry/sink/endpoint-sink.js +105 -0
  92. package/lib/cli/telemetry/sink/file-sink.d.ts +32 -0
  93. package/lib/cli/telemetry/sink/file-sink.js +43 -0
  94. package/lib/cli/telemetry/sink/funnel.d.ts +16 -0
  95. package/lib/cli/telemetry/sink/funnel.js +29 -0
  96. package/lib/cli/telemetry/sink/io-host-sink.d.ts +27 -0
  97. package/lib/cli/telemetry/sink/io-host-sink.js +35 -0
  98. package/lib/cli/telemetry/sink/sink-interface.d.ts +18 -0
  99. package/lib/cli/telemetry/sink/sink-interface.js +3 -0
  100. package/lib/cli/user-configuration.d.ts +104 -0
  101. package/lib/cli/user-configuration.js +334 -0
  102. package/lib/cli/user-input.d.ts +1505 -0
  103. package/lib/cli/user-input.js +3 -0
  104. package/lib/cli/util/ci.d.ts +5 -0
  105. package/lib/cli/util/ci.js +11 -0
  106. package/lib/cli/util/console-formatters.d.ts +18 -0
  107. package/lib/cli/util/console-formatters.js +42 -0
  108. package/lib/cli/util/guess-agent.d.ts +7 -0
  109. package/lib/cli/util/guess-agent.js +32 -0
  110. package/lib/cli/util/npm.d.ts +4 -0
  111. package/lib/cli/util/npm.js +34 -0
  112. package/lib/cli/util/trap-errors.d.ts +6 -0
  113. package/lib/cli/util/trap-errors.js +17 -0
  114. package/lib/cli/util/yargs-helpers.d.ts +22 -0
  115. package/lib/cli/util/yargs-helpers.js +49 -0
  116. package/lib/cli/version.d.ts +3 -0
  117. package/lib/cli/version.js +22 -0
  118. package/lib/commands/context.d.ts +40 -0
  119. package/lib/commands/context.js +158 -0
  120. package/lib/commands/deploy.d.ts +13 -0
  121. package/lib/commands/deploy.js +18 -0
  122. package/lib/commands/docs.d.ts +18 -0
  123. package/lib/commands/docs.js +33 -0
  124. package/lib/commands/doctor.d.ts +4 -0
  125. package/lib/commands/doctor.js +69 -0
  126. package/lib/commands/flags/flags.d.ts +13 -0
  127. package/lib/commands/flags/flags.js +30 -0
  128. package/lib/commands/flags/interactive-handler.d.ts +16 -0
  129. package/lib/commands/flags/interactive-handler.js +71 -0
  130. package/lib/commands/flags/obsolete-flags.d.ts +1 -0
  131. package/lib/commands/flags/obsolete-flags.js +9 -0
  132. package/lib/commands/flags/operations.d.ts +80 -0
  133. package/lib/commands/flags/operations.js +467 -0
  134. package/lib/commands/flags/router.d.ts +18 -0
  135. package/lib/commands/flags/router.js +60 -0
  136. package/lib/commands/flags/types.d.ts +12 -0
  137. package/lib/commands/flags/types.js +12 -0
  138. package/lib/commands/flags/validator.d.ts +22 -0
  139. package/lib/commands/flags/validator.js +95 -0
  140. package/lib/commands/init/index.d.ts +1 -0
  141. package/lib/commands/init/index.js +18 -0
  142. package/lib/commands/init/init-hooks.d.ts +41 -0
  143. package/lib/commands/init/init-hooks.js +85 -0
  144. package/lib/commands/init/init.d.ts +139 -0
  145. package/lib/commands/init/init.js +788 -0
  146. package/lib/commands/init/os.d.ts +8 -0
  147. package/lib/commands/init/os.js +91 -0
  148. package/lib/commands/init/package-manager.d.ts +15 -0
  149. package/lib/commands/init/package-manager.js +14 -0
  150. package/lib/commands/language.d.ts +30 -0
  151. package/lib/commands/language.js +46 -0
  152. package/lib/commands/list-stacks.d.ts +21 -0
  153. package/lib/commands/list-stacks.js +28 -0
  154. package/lib/commands/migrate.d.ts +316 -0
  155. package/lib/commands/migrate.js +801 -0
  156. package/lib/context-providers.d.ts +1 -0
  157. package/lib/context-providers.js +19 -0
  158. package/lib/cxapp/cloud-assembly.d.ts +79 -0
  159. package/lib/cxapp/cloud-assembly.js +109 -0
  160. package/lib/cxapp/cloud-executable.d.ts +51 -0
  161. package/lib/cxapp/cloud-executable.js +123 -0
  162. package/lib/cxapp/environments.d.ts +8 -0
  163. package/lib/cxapp/environments.js +66 -0
  164. package/lib/cxapp/exec.d.ts +14 -0
  165. package/lib/cxapp/exec.js +133 -0
  166. package/lib/cxapp/index.d.ts +4 -0
  167. package/lib/cxapp/index.js +21 -0
  168. package/lib/index.d.ts +2 -0
  169. package/lib/index.js +364043 -0
  170. package/lib/index_bg.wasm +0 -0
  171. package/lib/init-templates/.init-version.json +1 -0
  172. package/lib/init-templates/.no-packagejson-validator +0 -0
  173. package/lib/init-templates/.recommended-feature-flags.json +86 -0
  174. package/lib/init-templates/LICENSE +16 -0
  175. package/lib/init-templates/app/csharp/.template.gitignore +342 -0
  176. package/lib/init-templates/app/csharp/README.md +14 -0
  177. package/lib/init-templates/app/csharp/cdk.template.json +15 -0
  178. package/lib/init-templates/app/csharp/src/%name.PascalCased%/%name.PascalCased%.template.csproj +20 -0
  179. package/lib/init-templates/app/csharp/src/%name.PascalCased%/%name.PascalCased%Stack.template.cs +13 -0
  180. package/lib/init-templates/app/csharp/src/%name.PascalCased%/GlobalSuppressions.cs +1 -0
  181. package/lib/init-templates/app/csharp/src/%name.PascalCased%/Program.template.cs +44 -0
  182. package/lib/init-templates/app/csharp/src/%name.PascalCased%.template.sln +18 -0
  183. package/lib/init-templates/app/fsharp/.template.gitignore +342 -0
  184. package/lib/init-templates/app/fsharp/README.md +18 -0
  185. package/lib/init-templates/app/fsharp/cdk.template.json +14 -0
  186. package/lib/init-templates/app/fsharp/src/%name.PascalCased%/%name.PascalCased%.template.fsproj +25 -0
  187. package/lib/init-templates/app/fsharp/src/%name.PascalCased%/%name.PascalCased%Stack.template.fs +8 -0
  188. package/lib/init-templates/app/fsharp/src/%name.PascalCased%/Program.template.fs +11 -0
  189. package/lib/init-templates/app/fsharp/src/%name.PascalCased%.template.sln +18 -0
  190. package/lib/init-templates/app/go/%name%.template.go +70 -0
  191. package/lib/init-templates/app/go/%name%_test.template.go +26 -0
  192. package/lib/init-templates/app/go/.template.gitignore +19 -0
  193. package/lib/init-templates/app/go/README.md +12 -0
  194. package/lib/init-templates/app/go/cdk.template.json +13 -0
  195. package/lib/init-templates/app/go/go.template.mod +9 -0
  196. package/lib/init-templates/app/info.json +4 -0
  197. package/lib/init-templates/app/java/.template.gitignore +13 -0
  198. package/lib/init-templates/app/java/README.md +18 -0
  199. package/lib/init-templates/app/java/cdk.json +13 -0
  200. package/lib/init-templates/app/java/pom.xml +60 -0
  201. package/lib/init-templates/app/java/src/main/java/com/myorg/%name.PascalCased%App.template.java +42 -0
  202. package/lib/init-templates/app/java/src/main/java/com/myorg/%name.PascalCased%Stack.template.java +24 -0
  203. package/lib/init-templates/app/java/src/test/java/com/myorg/%name.PascalCased%Test.template.java +26 -0
  204. package/lib/init-templates/app/javascript/.template.gitignore +5 -0
  205. package/lib/init-templates/app/javascript/.template.npmignore +3 -0
  206. package/lib/init-templates/app/javascript/README.md +12 -0
  207. package/lib/init-templates/app/javascript/bin/%name%.template.js +21 -0
  208. package/lib/init-templates/app/javascript/cdk.template.json +15 -0
  209. package/lib/init-templates/app/javascript/jest.config.js +4 -0
  210. package/lib/init-templates/app/javascript/lib/%name%-stack.template.js +23 -0
  211. package/lib/init-templates/app/javascript/package.json +20 -0
  212. package/lib/init-templates/app/javascript/test/%name%.test.template.js +17 -0
  213. package/lib/init-templates/app/python/%name.PythonModule%/%name.PythonModule%_stack.template.py +19 -0
  214. package/lib/init-templates/app/python/%name.PythonModule%/__init__.py +0 -0
  215. package/lib/init-templates/app/python/.template.gitignore +10 -0
  216. package/lib/init-templates/app/python/README.template.md +58 -0
  217. package/lib/init-templates/app/python/app.template.py +28 -0
  218. package/lib/init-templates/app/python/cdk.template.json +15 -0
  219. package/lib/init-templates/app/python/requirements-dev.txt +1 -0
  220. package/lib/init-templates/app/python/requirements.txt +2 -0
  221. package/lib/init-templates/app/python/source.bat +13 -0
  222. package/lib/init-templates/app/python/tests/__init__.py +0 -0
  223. package/lib/init-templates/app/python/tests/unit/__init__.py +0 -0
  224. package/lib/init-templates/app/python/tests/unit/test_%name.PythonModule%_stack.template.py +15 -0
  225. package/lib/init-templates/app/typescript/.template.gitignore +8 -0
  226. package/lib/init-templates/app/typescript/.template.npmignore +6 -0
  227. package/lib/init-templates/app/typescript/README.md +14 -0
  228. package/lib/init-templates/app/typescript/bin/%name%.template.ts +20 -0
  229. package/lib/init-templates/app/typescript/cdk.template.json +17 -0
  230. package/lib/init-templates/app/typescript/jest.config.js +9 -0
  231. package/lib/init-templates/app/typescript/lib/%name%-stack.template.ts +16 -0
  232. package/lib/init-templates/app/typescript/package.json +26 -0
  233. package/lib/init-templates/app/typescript/test/%name%.test.template.ts +17 -0
  234. package/lib/init-templates/app/typescript/tsconfig.json +32 -0
  235. package/lib/init-templates/lib/info.json +4 -0
  236. package/lib/init-templates/lib/typescript/.template.gitignore +8 -0
  237. package/lib/init-templates/lib/typescript/.template.npmignore +6 -0
  238. package/lib/init-templates/lib/typescript/README.template.md +12 -0
  239. package/lib/init-templates/lib/typescript/jest.config.js +9 -0
  240. package/lib/init-templates/lib/typescript/lib/index.template.ts +21 -0
  241. package/lib/init-templates/lib/typescript/package.json +24 -0
  242. package/lib/init-templates/lib/typescript/test/%name%.test.template.ts +18 -0
  243. package/lib/init-templates/lib/typescript/tsconfig.json +32 -0
  244. package/lib/init-templates/sample-app/csharp/.template.gitignore +342 -0
  245. package/lib/init-templates/sample-app/csharp/README.template.md +19 -0
  246. package/lib/init-templates/sample-app/csharp/cdk.template.json +15 -0
  247. package/lib/init-templates/sample-app/csharp/src/%name.PascalCased%/%name.PascalCased%.template.csproj +20 -0
  248. package/lib/init-templates/sample-app/csharp/src/%name.PascalCased%/%name.PascalCased%Stack.template.cs +24 -0
  249. package/lib/init-templates/sample-app/csharp/src/%name.PascalCased%/GlobalSuppressions.cs +1 -0
  250. package/lib/init-templates/sample-app/csharp/src/%name.PascalCased%/Program.template.cs +15 -0
  251. package/lib/init-templates/sample-app/csharp/src/%name.PascalCased%.template.sln +18 -0
  252. package/lib/init-templates/sample-app/fsharp/.template.gitignore +342 -0
  253. package/lib/init-templates/sample-app/fsharp/README.template.md +20 -0
  254. package/lib/init-templates/sample-app/fsharp/cdk.template.json +14 -0
  255. package/lib/init-templates/sample-app/fsharp/src/%name.PascalCased%/%name.PascalCased%.template.fsproj +25 -0
  256. package/lib/init-templates/sample-app/fsharp/src/%name.PascalCased%/%name.PascalCased%Stack.template.fs +14 -0
  257. package/lib/init-templates/sample-app/fsharp/src/%name.PascalCased%/Program.template.fs +11 -0
  258. package/lib/init-templates/sample-app/fsharp/src/%name.PascalCased%.template.sln +18 -0
  259. package/lib/init-templates/sample-app/go/%name%.template.go +73 -0
  260. package/lib/init-templates/sample-app/go/%name%_test.template.go +25 -0
  261. package/lib/init-templates/sample-app/go/.template.gitignore +19 -0
  262. package/lib/init-templates/sample-app/go/README.md +12 -0
  263. package/lib/init-templates/sample-app/go/cdk.template.json +13 -0
  264. package/lib/init-templates/sample-app/go/go.template.mod +9 -0
  265. package/lib/init-templates/sample-app/info.json +4 -0
  266. package/lib/init-templates/sample-app/java/.template.gitignore +13 -0
  267. package/lib/init-templates/sample-app/java/README.template.md +19 -0
  268. package/lib/init-templates/sample-app/java/cdk.json +13 -0
  269. package/lib/init-templates/sample-app/java/pom.xml +55 -0
  270. package/lib/init-templates/sample-app/java/src/main/java/com/myorg/%name.PascalCased%App.template.java +13 -0
  271. package/lib/init-templates/sample-app/java/src/main/java/com/myorg/%name.PascalCased%Stack.template.java +29 -0
  272. package/lib/init-templates/sample-app/java/src/test/java/com/myorg/%name.PascalCased%StackTest.template.java +27 -0
  273. package/lib/init-templates/sample-app/javascript/.template.gitignore +5 -0
  274. package/lib/init-templates/sample-app/javascript/.template.npmignore +3 -0
  275. package/lib/init-templates/sample-app/javascript/README.template.md +13 -0
  276. package/lib/init-templates/sample-app/javascript/bin/%name%.template.js +6 -0
  277. package/lib/init-templates/sample-app/javascript/cdk.template.json +15 -0
  278. package/lib/init-templates/sample-app/javascript/jest.config.js +4 -0
  279. package/lib/init-templates/sample-app/javascript/lib/%name%-stack.template.js +25 -0
  280. package/lib/init-templates/sample-app/javascript/package.json +20 -0
  281. package/lib/init-templates/sample-app/javascript/test/%name%.test.template.js +16 -0
  282. package/lib/init-templates/sample-app/javascript/tsconfig.json +34 -0
  283. package/lib/init-templates/sample-app/python/%name.PythonModule%/%name.PythonModule%_stack.template.py +26 -0
  284. package/lib/init-templates/sample-app/python/%name.PythonModule%/__init__.py +0 -0
  285. package/lib/init-templates/sample-app/python/.template.gitignore +22 -0
  286. package/lib/init-templates/sample-app/python/README.template.md +65 -0
  287. package/lib/init-templates/sample-app/python/app.template.py +11 -0
  288. package/lib/init-templates/sample-app/python/cdk.template.json +15 -0
  289. package/lib/init-templates/sample-app/python/requirements-dev.txt +1 -0
  290. package/lib/init-templates/sample-app/python/requirements.txt +2 -0
  291. package/lib/init-templates/sample-app/python/source.bat +13 -0
  292. package/lib/init-templates/sample-app/python/tests/__init__.py +0 -0
  293. package/lib/init-templates/sample-app/python/tests/unit/__init__.py +0 -0
  294. package/lib/init-templates/sample-app/python/tests/unit/test_%name.PythonModule%_stack.template.py +21 -0
  295. package/lib/init-templates/sample-app/typescript/.template.gitignore +8 -0
  296. package/lib/init-templates/sample-app/typescript/.template.npmignore +6 -0
  297. package/lib/init-templates/sample-app/typescript/README.template.md +15 -0
  298. package/lib/init-templates/sample-app/typescript/bin/%name%.template.ts +6 -0
  299. package/lib/init-templates/sample-app/typescript/cdk.template.json +17 -0
  300. package/lib/init-templates/sample-app/typescript/jest.config.js +9 -0
  301. package/lib/init-templates/sample-app/typescript/lib/%name%-stack.template.ts +19 -0
  302. package/lib/init-templates/sample-app/typescript/package.json +26 -0
  303. package/lib/init-templates/sample-app/typescript/test/%name%.test.template.ts +17 -0
  304. package/lib/init-templates/sample-app/typescript/tsconfig.json +32 -0
  305. package/lib/util.d.ts +1 -0
  306. package/lib/util.js +19 -0
  307. package/package.json +170 -0
  308. package/release.txt +2 -0
@@ -0,0 +1,801 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FromScan = exports.CfnTemplateGeneratorProvider = exports.FilterType = exports.ScanStatus = exports.TemplateSourceOptions = void 0;
4
+ exports.generateCdkApp = generateCdkApp;
5
+ exports.generateStack = generateStack;
6
+ exports.readFromPath = readFromPath;
7
+ exports.readFromStack = readFromStack;
8
+ exports.generateTemplate = generateTemplate;
9
+ exports.chunks = chunks;
10
+ exports.setEnvironment = setEnvironment;
11
+ exports.parseSourceOptions = parseSourceOptions;
12
+ exports.printBar = printBar;
13
+ exports.printDots = printDots;
14
+ exports.rewriteLine = rewriteLine;
15
+ exports.writeMigrateJsonFile = writeMigrateJsonFile;
16
+ exports.getMigrateScanType = getMigrateScanType;
17
+ exports.isThereAWarning = isThereAWarning;
18
+ exports.buildGeneratedTemplateOutput = buildGeneratedTemplateOutput;
19
+ exports.buildCfnClient = buildCfnClient;
20
+ exports.appendWarningsToReadme = appendWarningsToReadme;
21
+ /* eslint-disable @typescript-eslint/no-require-imports */
22
+ /* eslint-disable @typescript-eslint/no-var-requires */
23
+ const fs = require("fs");
24
+ const path = require("path");
25
+ const cloud_assembly_api_1 = require("@aws-cdk/cloud-assembly-api");
26
+ const toolkit_lib_1 = require("@aws-cdk/toolkit-lib");
27
+ const cdk_from_cfn = require("cdk-from-cfn");
28
+ const chalk = require("chalk");
29
+ const init_1 = require("./init");
30
+ const cloudformation_1 = require("../api/cloudformation");
31
+ const plugin_1 = require("../api/plugin");
32
+ const util_1 = require("../util");
33
+ const camelCase = require('camelcase');
34
+ const decamelize = require('decamelize');
35
+ /** The list of languages supported by the built-in noctilucent binary. */
36
+ const MIGRATE_SUPPORTED_LANGUAGES = cdk_from_cfn.supported_languages();
37
+ /**
38
+ * Generates a CDK app from a yaml or json template.
39
+ *
40
+ * @param stackName - The name to assign to the stack in the generated app
41
+ * @param stack - The yaml or json template for the stack
42
+ * @param language - The language to generate the CDK app in
43
+ * @param outputPath - The path at which to generate the CDK app
44
+ */
45
+ async function generateCdkApp(ioHelper, stackName, stack, language, outputPath, compress) {
46
+ const resolvedOutputPath = path.join(outputPath ?? process.cwd(), stackName);
47
+ const formattedStackName = decamelize(stackName);
48
+ try {
49
+ fs.rmSync(resolvedOutputPath, { recursive: true, force: true });
50
+ fs.mkdirSync(resolvedOutputPath, { recursive: true });
51
+ const generateOnly = compress;
52
+ await (0, init_1.cliInit)({
53
+ ioHelper,
54
+ type: 'app',
55
+ language,
56
+ canUseNetwork: true,
57
+ generateOnly,
58
+ workDir: resolvedOutputPath,
59
+ stackName,
60
+ migrate: true,
61
+ });
62
+ let stackFileName;
63
+ switch (language) {
64
+ case 'typescript':
65
+ stackFileName = `${resolvedOutputPath}/lib/${formattedStackName}-stack.ts`;
66
+ break;
67
+ case 'java':
68
+ stackFileName = `${resolvedOutputPath}/src/main/java/com/myorg/${camelCase(formattedStackName, { pascalCase: true })}Stack.java`;
69
+ break;
70
+ case 'python':
71
+ stackFileName = `${resolvedOutputPath}/${formattedStackName.replace(/-/g, '_')}/${formattedStackName.replace(/-/g, '_')}_stack.py`;
72
+ break;
73
+ case 'csharp':
74
+ stackFileName = `${resolvedOutputPath}/src/${camelCase(formattedStackName, { pascalCase: true })}/${camelCase(formattedStackName, { pascalCase: true })}Stack.cs`;
75
+ break;
76
+ case 'go':
77
+ stackFileName = `${resolvedOutputPath}/${formattedStackName}.go`;
78
+ break;
79
+ default:
80
+ throw new toolkit_lib_1.ToolkitError('UnsupportedMigrateLanguage', `${language} is not supported by CDK Migrate. Please choose from: ${MIGRATE_SUPPORTED_LANGUAGES.join(', ')}`);
81
+ }
82
+ fs.writeFileSync(stackFileName, stack);
83
+ if (compress) {
84
+ await (0, util_1.zipDirectory)(resolvedOutputPath, `${resolvedOutputPath}.zip`);
85
+ fs.rmSync(resolvedOutputPath, { recursive: true, force: true });
86
+ }
87
+ }
88
+ catch (error) {
89
+ fs.rmSync(resolvedOutputPath, { recursive: true, force: true });
90
+ throw error;
91
+ }
92
+ }
93
+ /**
94
+ * Generates a CDK stack file.
95
+ * @param template - The template to translate into a CDK stack
96
+ * @param stackName - The name to assign to the stack
97
+ * @param language - The language to generate the stack in
98
+ * @returns A string representation of a CDK stack file
99
+ */
100
+ function generateStack(template, stackName, language) {
101
+ const formattedStackName = `${camelCase(decamelize(stackName), { pascalCase: true })}Stack`;
102
+ try {
103
+ return cdk_from_cfn.transmute(template, language, formattedStackName);
104
+ }
105
+ catch (e) {
106
+ throw new toolkit_lib_1.ToolkitError('StackGenerationFailed', `${formattedStackName} could not be generated because ${e.message}`);
107
+ }
108
+ }
109
+ /**
110
+ * Reads and returns a stack template from a local path.
111
+ *
112
+ * @param inputPath - The location of the template
113
+ * @returns A string representation of the template if present, otherwise undefined
114
+ */
115
+ function readFromPath(inputPath) {
116
+ let readFile;
117
+ try {
118
+ readFile = fs.readFileSync(inputPath, 'utf8');
119
+ }
120
+ catch (e) {
121
+ throw new toolkit_lib_1.ToolkitError('InvalidPath', `'${inputPath}' is not a valid path.`);
122
+ }
123
+ if (readFile == '') {
124
+ throw new toolkit_lib_1.ToolkitError('EmptyTemplateFile', `Cloudformation template filepath: '${inputPath}' is an empty file.`);
125
+ }
126
+ return readFile;
127
+ }
128
+ /**
129
+ * Reads and returns a stack template from a deployed CloudFormation stack.
130
+ *
131
+ * @param stackName - The name of the stack
132
+ * @param sdkProvider - The sdk provider for making CloudFormation calls
133
+ * @param environment - The account and region where the stack is deployed
134
+ * @returns A string representation of the template if present, otherwise undefined
135
+ */
136
+ async function readFromStack(stackName, sdkProvider, environment) {
137
+ const cloudFormation = (await sdkProvider.forEnvironment(environment, plugin_1.Mode.ForReading)).sdk.cloudFormation();
138
+ const stack = await cloudformation_1.CloudFormationStack.lookup(cloudFormation, stackName, true);
139
+ if (stack.stackStatus.isDeploySuccess || stack.stackStatus.isRollbackSuccess) {
140
+ return JSON.stringify(await stack.template());
141
+ }
142
+ else {
143
+ throw new toolkit_lib_1.ToolkitError('UnhealthyStackStatus', `Stack '${stackName}' in account ${environment.account} and region ${environment.region} has a status of '${stack.stackStatus.name}' due to '${stack.stackStatus.reason}'. The stack cannot be migrated until it is in a healthy state.`);
144
+ }
145
+ }
146
+ /**
147
+ * Takes in a stack name and account and region and returns a generated cloudformation template using the cloudformation
148
+ * template generator.
149
+ *
150
+ * @param GenerateTemplateOptions - An object containing the stack name, filters, sdkProvider, environment, and newScan flag
151
+ * @returns a generated cloudformation template
152
+ */
153
+ async function generateTemplate(options) {
154
+ const cfn = new CfnTemplateGeneratorProvider(await buildCfnClient(options.sdkProvider, options.environment), options.ioHelper);
155
+ const ioHelper = options.ioHelper;
156
+ const scanId = await findLastSuccessfulScan(cfn, options);
157
+ // if a customer accidentally ctrl-c's out of the command and runs it again, this will continue the progress bar where it left off
158
+ const curScan = await cfn.describeResourceScan(scanId);
159
+ if (curScan.Status == ScanStatus.IN_PROGRESS) {
160
+ await ioHelper.defaults.info('Resource scan in progress. Please wait, this can take 10 minutes or longer.');
161
+ await scanProgressBar(ioHelper, scanId, cfn);
162
+ }
163
+ await displayTimeDiff(ioHelper, new Date(), new Date(curScan.StartTime));
164
+ let resources = await cfn.listResourceScanResources(scanId, options.filters);
165
+ await ioHelper.defaults.info('finding related resources.');
166
+ let relatedResources = await cfn.getResourceScanRelatedResources(scanId, resources);
167
+ await ioHelper.defaults.info(`Found ${relatedResources.length} resources.`);
168
+ await ioHelper.defaults.info('Generating CFN template from scanned resources.');
169
+ const templateArn = (await cfn.createGeneratedTemplate(options.stackName, relatedResources)).GeneratedTemplateId;
170
+ let generatedTemplate = await cfn.describeGeneratedTemplate(templateArn);
171
+ await ioHelper.defaults.info('Please wait, template creation in progress. This may take a couple minutes.');
172
+ while (generatedTemplate.Status !== ScanStatus.COMPLETE && generatedTemplate.Status !== ScanStatus.FAILED) {
173
+ await printDots(`[${generatedTemplate.Status}] Template Creation in Progress`, 400);
174
+ generatedTemplate = await cfn.describeGeneratedTemplate(templateArn);
175
+ }
176
+ await ioHelper.defaults.info('\nTemplate successfully generated!');
177
+ return buildGeneratedTemplateOutput(generatedTemplate, (await cfn.getGeneratedTemplate(templateArn)).TemplateBody, templateArn);
178
+ }
179
+ async function findLastSuccessfulScan(cfn, options) {
180
+ const ioHelper = options.ioHelper;
181
+ let resourceScanSummaries = [];
182
+ const clientRequestToken = `cdk-migrate-${options.environment.account}-${options.environment.region}`;
183
+ if (options.fromScan === FromScan.NEW) {
184
+ await ioHelper.defaults.info(`Starting new scan for account ${options.environment.account} in region ${options.environment.region}`);
185
+ try {
186
+ await cfn.startResourceScan(clientRequestToken);
187
+ resourceScanSummaries = (await cfn.listResourceScans()).ResourceScanSummaries;
188
+ }
189
+ catch (e) {
190
+ // continuing here because if the scan fails on a new-scan it is very likely because there is either already a scan in progress
191
+ // or the customer hit a rate limit. In either case we want to continue with the most recent scan.
192
+ // If this happens to fail for a credential error then that will be caught immediately after anyway.
193
+ await ioHelper.defaults.info(`Scan failed to start due to error '${e.message}', defaulting to latest scan.`);
194
+ }
195
+ }
196
+ else {
197
+ resourceScanSummaries = (await cfn.listResourceScans()).ResourceScanSummaries;
198
+ await cfn.checkForResourceScan(resourceScanSummaries, options, clientRequestToken);
199
+ }
200
+ // get the latest scan, which we know will exist
201
+ resourceScanSummaries = (await cfn.listResourceScans()).ResourceScanSummaries;
202
+ let scanId = resourceScanSummaries[0].ResourceScanId;
203
+ // find the most recent scan that isn't in a failed state in case we didn't start a new one
204
+ for (const summary of resourceScanSummaries) {
205
+ if (summary.Status !== ScanStatus.FAILED) {
206
+ scanId = summary.ResourceScanId;
207
+ break;
208
+ }
209
+ }
210
+ return scanId;
211
+ }
212
+ /**
213
+ * Takes a string of filters in the format of key1=value1,key2=value2 and returns a map of the filters.
214
+ *
215
+ * @param filters - a string of filters in the format of key1=value1,key2=value2
216
+ * @returns a map of the filters
217
+ */
218
+ function parseFilters(filters) {
219
+ if (!filters) {
220
+ return {
221
+ 'resource-identifier': undefined,
222
+ 'resource-type-prefix': undefined,
223
+ 'tag-key': undefined,
224
+ 'tag-value': undefined,
225
+ };
226
+ }
227
+ const filterShorthands = {
228
+ 'identifier': FilterType.RESOURCE_IDENTIFIER,
229
+ 'id': FilterType.RESOURCE_IDENTIFIER,
230
+ 'type': FilterType.RESOURCE_TYPE_PREFIX,
231
+ 'type-prefix': FilterType.RESOURCE_TYPE_PREFIX,
232
+ };
233
+ const filterList = filters.split(',');
234
+ let filterMap = {
235
+ [FilterType.RESOURCE_IDENTIFIER]: undefined,
236
+ [FilterType.RESOURCE_TYPE_PREFIX]: undefined,
237
+ [FilterType.TAG_KEY]: undefined,
238
+ [FilterType.TAG_VALUE]: undefined,
239
+ };
240
+ for (const fil of filterList) {
241
+ const filter = fil.split('=');
242
+ let filterKey = filter[0];
243
+ const filterValue = filter[1];
244
+ // if the key is a shorthand, replace it with the full name
245
+ if (filterKey in filterShorthands) {
246
+ filterKey = filterShorthands[filterKey];
247
+ }
248
+ if (Object.values(FilterType).includes(filterKey)) {
249
+ filterMap[filterKey] = filterValue;
250
+ }
251
+ else {
252
+ throw new toolkit_lib_1.ToolkitError('InvalidFilter', `Invalid filter: ${filterKey}`);
253
+ }
254
+ }
255
+ return filterMap;
256
+ }
257
+ /**
258
+ * Takes a list of any type and breaks it up into chunks of a specified size.
259
+ *
260
+ * @param list - The list to break up
261
+ * @param chunkSize - The size of each chunk
262
+ * @returns A list of lists of the specified size
263
+ */
264
+ function chunks(list, chunkSize) {
265
+ const chunkedList = [];
266
+ for (let i = 0; i < list.length; i += chunkSize) {
267
+ chunkedList.push(list.slice(i, i + chunkSize));
268
+ }
269
+ return chunkedList;
270
+ }
271
+ /**
272
+ * Sets the account and region for making CloudFormation calls.
273
+ * @param account - The account to use
274
+ * @param region - The region to use
275
+ * @returns The environment object
276
+ */
277
+ function setEnvironment(account, region) {
278
+ return {
279
+ account: account ?? cloud_assembly_api_1.UNKNOWN_ACCOUNT,
280
+ region: region ?? cloud_assembly_api_1.UNKNOWN_REGION,
281
+ name: 'cdk-migrate-env',
282
+ };
283
+ }
284
+ /**
285
+ * Enum for the source options for the template
286
+ */
287
+ var TemplateSourceOptions;
288
+ (function (TemplateSourceOptions) {
289
+ TemplateSourceOptions["PATH"] = "path";
290
+ TemplateSourceOptions["STACK"] = "stack";
291
+ TemplateSourceOptions["SCAN"] = "scan";
292
+ })(TemplateSourceOptions || (exports.TemplateSourceOptions = TemplateSourceOptions = {}));
293
+ /**
294
+ * Enum for the status of a resource scan
295
+ */
296
+ var ScanStatus;
297
+ (function (ScanStatus) {
298
+ ScanStatus["IN_PROGRESS"] = "IN_PROGRESS";
299
+ ScanStatus["COMPLETE"] = "COMPLETE";
300
+ ScanStatus["FAILED"] = "FAILED";
301
+ })(ScanStatus || (exports.ScanStatus = ScanStatus = {}));
302
+ var FilterType;
303
+ (function (FilterType) {
304
+ FilterType["RESOURCE_IDENTIFIER"] = "resource-identifier";
305
+ FilterType["RESOURCE_TYPE_PREFIX"] = "resource-type-prefix";
306
+ FilterType["TAG_KEY"] = "tag-key";
307
+ FilterType["TAG_VALUE"] = "tag-value";
308
+ })(FilterType || (exports.FilterType = FilterType = {}));
309
+ /**
310
+ * Validates that exactly one source option has been provided.
311
+ * @param fromPath - The content of the flag `--from-path`
312
+ * @param fromStack - the content of the flag `--from-stack`
313
+ */
314
+ function parseSourceOptions(fromPath, fromStack, stackName) {
315
+ if (fromPath && fromStack) {
316
+ throw new toolkit_lib_1.ToolkitError('ConflictingSourceOptions', 'Only one of `--from-path` or `--from-stack` may be provided.');
317
+ }
318
+ if (!stackName) {
319
+ throw new toolkit_lib_1.ToolkitError('MissingStackName', '`--stack-name` is a required field.');
320
+ }
321
+ if (!fromPath && !fromStack) {
322
+ return { source: TemplateSourceOptions.SCAN };
323
+ }
324
+ if (fromPath) {
325
+ return { source: TemplateSourceOptions.PATH, templatePath: fromPath };
326
+ }
327
+ return { source: TemplateSourceOptions.STACK, stackName: stackName };
328
+ }
329
+ /**
330
+ * Takes a set of resources and removes any with the managedbystack flag set to true.
331
+ *
332
+ * @param resourceList - the list of resources provided by the list scanned resources calls
333
+ * @returns a list of resources not managed by cfn stacks
334
+ */
335
+ function excludeManaged(resourceList) {
336
+ return resourceList
337
+ .filter((r) => !r.ManagedByStack)
338
+ .map((r) => ({
339
+ ResourceType: r.ResourceType,
340
+ ResourceIdentifier: r.ResourceIdentifier,
341
+ }));
342
+ }
343
+ /**
344
+ * Transforms a list of resources into a list of resource identifiers by removing the ManagedByStack flag.
345
+ * Setting the value of the field to undefined effectively removes it from the object.
346
+ *
347
+ * @param resourceList - the list of resources provided by the list scanned resources calls
348
+ * @returns a list of ScannedResourceIdentifier[]
349
+ */
350
+ function resourceIdentifiers(resourceList) {
351
+ const identifiers = [];
352
+ resourceList.forEach((r) => {
353
+ const identifier = {
354
+ ResourceType: r.ResourceType,
355
+ ResourceIdentifier: r.ResourceIdentifier,
356
+ };
357
+ identifiers.push(identifier);
358
+ });
359
+ return identifiers;
360
+ }
361
+ /**
362
+ * Takes a scan id and maintains a progress bar to display the progress of a scan to the user.
363
+ *
364
+ * @param scanId - A string representing the scan id
365
+ * @param cloudFormation - The CloudFormation sdk client to use
366
+ */
367
+ async function scanProgressBar(ioHelper, scanId, cfn) {
368
+ let curProgress = 0.5;
369
+ // we know it's in progress initially since we wouldn't have gotten here if it wasn't
370
+ let curScan = {
371
+ Status: ScanStatus.IN_PROGRESS,
372
+ $metadata: {},
373
+ };
374
+ while (curScan.Status == ScanStatus.IN_PROGRESS) {
375
+ curScan = await cfn.describeResourceScan(scanId);
376
+ curProgress = curScan.PercentageCompleted ?? curProgress;
377
+ printBar(30, curProgress);
378
+ await new Promise((resolve) => setTimeout(resolve, 2000));
379
+ }
380
+ await ioHelper.defaults.info('\n✅ Scan Complete!');
381
+ }
382
+ /**
383
+ * Prints a progress bar to the console. To be used in a while loop to show progress of a long running task.
384
+ * The progress bar deletes the current line on the console and rewrites it with the progress amount.
385
+ *
386
+ * @param width - The width of the progress bar
387
+ * @param progress - The current progress to display as a percentage of 100
388
+ */
389
+ function printBar(width, progress) {
390
+ if (!process.env.MIGRATE_INTEG_TEST) {
391
+ const FULL_BLOCK = '█';
392
+ const PARTIAL_BLOCK = ['', '▏', '▎', '▍', '▌', '▋', '▊', '▉'];
393
+ const fraction = Math.min(progress / 100, 1);
394
+ const innerWidth = Math.max(1, width - 2);
395
+ const chars = innerWidth * fraction;
396
+ const remainder = chars - Math.floor(chars);
397
+ const fullChars = FULL_BLOCK.repeat(Math.floor(chars));
398
+ const partialChar = PARTIAL_BLOCK[Math.floor(remainder * PARTIAL_BLOCK.length)];
399
+ const filler = '·'.repeat(innerWidth - Math.floor(chars) - (partialChar ? 1 : 0));
400
+ const color = chalk.green;
401
+ rewriteLine('[' + color(fullChars + partialChar) + filler + `] (${progress}%)`);
402
+ }
403
+ }
404
+ /**
405
+ * Prints a message to the console with a series periods appended to it. To be used in a while loop to show progress of a long running task.
406
+ * The message deletes the current line and rewrites it several times to display 1-3 periods to show the user that the task is still running.
407
+ *
408
+ * @param message - The message to display
409
+ * @param timeoutx4 - The amount of time to wait before printing the next period
410
+ */
411
+ async function printDots(message, timeoutx4) {
412
+ if (!process.env.MIGRATE_INTEG_TEST) {
413
+ rewriteLine(message + ' .');
414
+ await new Promise((resolve) => setTimeout(resolve, timeoutx4));
415
+ rewriteLine(message + ' ..');
416
+ await new Promise((resolve) => setTimeout(resolve, timeoutx4));
417
+ rewriteLine(message + ' ...');
418
+ await new Promise((resolve) => setTimeout(resolve, timeoutx4));
419
+ rewriteLine(message);
420
+ await new Promise((resolve) => setTimeout(resolve, timeoutx4));
421
+ }
422
+ }
423
+ /**
424
+ * Rewrites the current line on the console and writes a new message to it.
425
+ * This is a helper funciton for printDots and printBar.
426
+ *
427
+ * @param message - The message to display
428
+ */
429
+ function rewriteLine(message) {
430
+ process.stdout.clearLine(0);
431
+ process.stdout.cursorTo(0);
432
+ process.stdout.write(message);
433
+ }
434
+ /**
435
+ * Prints the time difference between two dates in days, hours, and minutes.
436
+ *
437
+ * @param time1 - The first date to compare
438
+ * @param time2 - The second date to compare
439
+ */
440
+ async function displayTimeDiff(ioHelper, time1, time2) {
441
+ const diff = Math.abs(time1.getTime() - time2.getTime());
442
+ const days = Math.floor(diff / (1000 * 60 * 60 * 24));
443
+ const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
444
+ const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
445
+ await ioHelper.defaults.info(`Using the latest successful scan which is ${days} days, ${hours} hours, and ${minutes} minutes old.`);
446
+ }
447
+ /**
448
+ * Writes a migrate.json file to the output directory.
449
+ *
450
+ * @param outputPath - The path to write the migrate.json file to
451
+ * @param stackName - The name of the stack
452
+ * @param generatedOutput - The output of the template generator
453
+ */
454
+ function writeMigrateJsonFile(outputPath, stackName, migrateJson) {
455
+ const outputToJson = {
456
+ '//': 'This file is generated by cdk migrate. It will be automatically deleted after the first successful deployment of this app to the environment of the original resources.',
457
+ 'Source': migrateJson.source,
458
+ 'Resources': migrateJson.resources,
459
+ };
460
+ fs.writeFileSync(`${path.join(outputPath ?? process.cwd(), stackName)}/migrate.json`, JSON.stringify(outputToJson, null, 2));
461
+ }
462
+ /**
463
+ * Takes a string representing the from-scan flag and returns a FromScan enum value.
464
+ *
465
+ * @param scanType - A string representing the from-scan flag
466
+ * @returns A FromScan enum value
467
+ */
468
+ function getMigrateScanType(scanType) {
469
+ switch (scanType) {
470
+ case 'new':
471
+ return FromScan.NEW;
472
+ case 'most-recent':
473
+ return FromScan.MOST_RECENT;
474
+ case '':
475
+ return FromScan.DEFAULT;
476
+ case undefined:
477
+ return FromScan.DEFAULT;
478
+ default:
479
+ throw new toolkit_lib_1.ToolkitError('UnknownScanType', `Unknown scan type: ${scanType}`);
480
+ }
481
+ }
482
+ /**
483
+ * Takes a generatedTemplateOutput objct and returns a boolean representing whether there are any warnings on any rescources.
484
+ *
485
+ * @param generatedTemplateOutput - A GenerateTemplateOutput object
486
+ * @returns A boolean representing whether there are any warnings on any rescources
487
+ */
488
+ function isThereAWarning(generatedTemplateOutput) {
489
+ if (generatedTemplateOutput.resources) {
490
+ for (const resource of generatedTemplateOutput.resources) {
491
+ if (resource.Warnings && resource.Warnings.length > 0) {
492
+ return true;
493
+ }
494
+ }
495
+ }
496
+ return false;
497
+ }
498
+ /**
499
+ * Builds the GenerateTemplateOutput object from the DescribeGeneratedTemplateOutput and the template body.
500
+ *
501
+ * @param generatedTemplateSummary - The output of the describe generated template call
502
+ * @param templateBody - The body of the generated template
503
+ * @returns A GenerateTemplateOutput object
504
+ */
505
+ function buildGeneratedTemplateOutput(generatedTemplateSummary, templateBody, source) {
506
+ const resources = generatedTemplateSummary.Resources;
507
+ const migrateJson = {
508
+ templateBody: templateBody,
509
+ source: source,
510
+ resources: generatedTemplateSummary.Resources.map((r) => ({
511
+ ResourceType: r.ResourceType,
512
+ LogicalResourceId: r.LogicalResourceId,
513
+ ResourceIdentifier: r.ResourceIdentifier,
514
+ })),
515
+ };
516
+ const templateId = generatedTemplateSummary.GeneratedTemplateId;
517
+ return {
518
+ migrateJson: migrateJson,
519
+ resources: resources,
520
+ templateId: templateId,
521
+ };
522
+ }
523
+ /**
524
+ * Builds a CloudFormation sdk client for making requests with the CFN template generator.
525
+ *
526
+ * @param sdkProvider - The sdk provider for making CloudFormation calls
527
+ * @param environment - The account and region where the stack is deployed
528
+ * @returns A CloudFormation sdk client
529
+ */
530
+ async function buildCfnClient(sdkProvider, environment) {
531
+ const sdk = (await sdkProvider.forEnvironment(environment, plugin_1.Mode.ForReading)).sdk;
532
+ sdk.appendCustomUserAgent('cdk-migrate');
533
+ return sdk.cloudFormation();
534
+ }
535
+ /**
536
+ * Appends a list of warnings to a readme file.
537
+ *
538
+ * @param filepath - The path to the readme file
539
+ * @param resources - A list of resources to append warnings for
540
+ */
541
+ function appendWarningsToReadme(filepath, resources) {
542
+ const readme = fs.readFileSync(filepath, 'utf8');
543
+ const lines = readme.split('\n');
544
+ const index = lines.findIndex((line) => line.trim() === 'Enjoy!');
545
+ let linesToAdd = ['\n## Warnings'];
546
+ linesToAdd.push('### Write-only properties');
547
+ linesToAdd.push("Write-only properties are resource property values that can be written to but can't be read by AWS CloudFormation or CDK Migrate. For more information, see [IaC generator and write-only properties](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/generate-IaC-write-only-properties.html).");
548
+ linesToAdd.push('\n');
549
+ linesToAdd.push('Write-only properties discovered during migration are organized here by resource ID and categorized by write-only property type. Resolve write-only properties by providing property values in your CDK app. For guidance, see [Resolve write-only properties](https://docs.aws.amazon.com/cdk/v2/guide/migrate.html#migrate-resources-writeonly).');
550
+ for (const resource of resources) {
551
+ if (resource.Warnings && resource.Warnings.length > 0) {
552
+ linesToAdd.push(`### ${resource.LogicalResourceId}`);
553
+ for (const warning of resource.Warnings) {
554
+ linesToAdd.push(`- **${warning.Type}**: `);
555
+ for (const property of warning.Properties) {
556
+ linesToAdd.push(` - ${property.PropertyPath}: ${property.Description}`);
557
+ }
558
+ }
559
+ }
560
+ }
561
+ lines.splice(index, 0, ...linesToAdd);
562
+ fs.writeFileSync(filepath, lines.join('\n'));
563
+ }
564
+ /**
565
+ * takes a list of resources and returns a list of unique resources based on the resource type and logical resource id.
566
+ *
567
+ * @param resources - A list of resources to deduplicate
568
+ * @returns A list of unique resources
569
+ */
570
+ function deduplicateResources(resources) {
571
+ let uniqueResources = {};
572
+ for (const resource of resources) {
573
+ const key = Object.keys(resource.ResourceIdentifier)[0];
574
+ // Creating our unique identifier using the resource type, the key, and the value of the resource identifier
575
+ // The resource identifier is a combination of a key value pair defined by a resource's schema, and the resource type of the resource.
576
+ const uniqueIdentifer = `${resource.ResourceType}:${key}:${resource.ResourceIdentifier[key]}`;
577
+ uniqueResources[uniqueIdentifer] = resource;
578
+ }
579
+ return Object.values(uniqueResources);
580
+ }
581
+ /**
582
+ * Class for making CloudFormation template generator calls
583
+ */
584
+ class CfnTemplateGeneratorProvider {
585
+ constructor(cfn, ioHelper) {
586
+ this.cfn = cfn;
587
+ this.ioHelper = ioHelper;
588
+ }
589
+ async checkForResourceScan(resourceScanSummaries, options, clientRequestToken) {
590
+ if (!resourceScanSummaries || resourceScanSummaries.length === 0) {
591
+ if (options.fromScan === FromScan.MOST_RECENT) {
592
+ throw new toolkit_lib_1.ToolkitError('NoScansFound', 'No scans found. Please either start a new scan with the `--from-scan` new or do not specify a `--from-scan` option.');
593
+ }
594
+ else {
595
+ await this.ioHelper.defaults.info('No scans found. Initiating a new resource scan.');
596
+ await this.startResourceScan(clientRequestToken);
597
+ }
598
+ }
599
+ }
600
+ /**
601
+ * Retrieves a tokenized list of resources and their associated scan. If a token is present the function
602
+ * will loop through all pages and combine them into a single list of ScannedRelatedResources
603
+ *
604
+ * @param scanId - scan id for the to list resources for
605
+ * @param resources - A list of resources to find related resources for
606
+ */
607
+ async getResourceScanRelatedResources(scanId, resources) {
608
+ let relatedResourceList = resources;
609
+ // break the list of resources into chunks of 100 to avoid hitting the 100 resource limit
610
+ for (const chunk of chunks(resources, 100)) {
611
+ // get the first page of related resources
612
+ const res = await this.cfn.listResourceScanRelatedResources({
613
+ ResourceScanId: scanId,
614
+ Resources: chunk,
615
+ });
616
+ // add the first page to the list
617
+ relatedResourceList.push(...(res.RelatedResources ?? []));
618
+ let nextToken = res.NextToken;
619
+ // if there are more pages, cycle through them and add them to the list before moving on to the next chunk
620
+ while (nextToken) {
621
+ const nextRelatedResources = await this.cfn.listResourceScanRelatedResources({
622
+ ResourceScanId: scanId,
623
+ Resources: resourceIdentifiers(resources),
624
+ NextToken: nextToken,
625
+ });
626
+ nextToken = nextRelatedResources.NextToken;
627
+ relatedResourceList.push(...(nextRelatedResources.RelatedResources ?? []));
628
+ }
629
+ }
630
+ relatedResourceList = deduplicateResources(relatedResourceList);
631
+ // prune the managedbystack flag off of them again.
632
+ return process.env.MIGRATE_INTEG_TEST
633
+ ? resourceIdentifiers(relatedResourceList)
634
+ : resourceIdentifiers(excludeManaged(relatedResourceList));
635
+ }
636
+ /**
637
+ * Kicks off a scan of a customers account, returning the scan id. A scan can take
638
+ * 10 minutes or longer to complete. However this will return a scan id as soon as
639
+ * the scan has begun.
640
+ *
641
+ * @returns A string representing the scan id
642
+ */
643
+ async startResourceScan(requestToken) {
644
+ return (await this.cfn.startResourceScan({
645
+ ClientRequestToken: requestToken,
646
+ })).ResourceScanId;
647
+ }
648
+ /**
649
+ * Gets the most recent scans a customer has completed
650
+ *
651
+ * @returns a list of resource scan summaries
652
+ */
653
+ async listResourceScans() {
654
+ return this.cfn.listResourceScans();
655
+ }
656
+ /**
657
+ * Retrieves a tokenized list of resources from a resource scan. If a token is present, this function
658
+ * will loop through all pages and combine them into a single list of ScannedResource[].
659
+ * Additionally will apply any filters provided by the customer.
660
+ *
661
+ * @param scanId - scan id for the to list resources for
662
+ * @param filters - a string of filters in the format of key1=value1,key2=value2
663
+ * @returns a combined list of all resources from the scan
664
+ */
665
+ async listResourceScanResources(scanId, filters = []) {
666
+ let resourceList = [];
667
+ let resourceScanInputs;
668
+ if (filters.length > 0) {
669
+ await this.ioHelper.defaults.info('Applying filters to resource scan.');
670
+ for (const filter of filters) {
671
+ const filterList = parseFilters(filter);
672
+ resourceScanInputs = {
673
+ ResourceScanId: scanId,
674
+ ResourceIdentifier: filterList[FilterType.RESOURCE_IDENTIFIER],
675
+ ResourceTypePrefix: filterList[FilterType.RESOURCE_TYPE_PREFIX],
676
+ TagKey: filterList[FilterType.TAG_KEY],
677
+ TagValue: filterList[FilterType.TAG_VALUE],
678
+ };
679
+ const resources = await this.cfn.listResourceScanResources(resourceScanInputs);
680
+ resourceList = resourceList.concat(resources.Resources ?? []);
681
+ let nextToken = resources.NextToken;
682
+ // cycle through the pages adding all resources to the list until we run out of pages
683
+ while (nextToken) {
684
+ resourceScanInputs.NextToken = nextToken;
685
+ const nextResources = await this.cfn.listResourceScanResources(resourceScanInputs);
686
+ nextToken = nextResources.NextToken;
687
+ resourceList = resourceList.concat(nextResources.Resources ?? []);
688
+ }
689
+ }
690
+ }
691
+ else {
692
+ await this.ioHelper.defaults.info('No filters provided. Retrieving all resources from scan.');
693
+ resourceScanInputs = {
694
+ ResourceScanId: scanId,
695
+ };
696
+ const resources = await this.cfn.listResourceScanResources(resourceScanInputs);
697
+ resourceList = resourceList.concat(resources.Resources ?? []);
698
+ let nextToken = resources.NextToken;
699
+ // cycle through the pages adding all resources to the list until we run out of pages
700
+ while (nextToken) {
701
+ resourceScanInputs.NextToken = nextToken;
702
+ const nextResources = await this.cfn.listResourceScanResources(resourceScanInputs);
703
+ nextToken = nextResources.NextToken;
704
+ resourceList = resourceList.concat(nextResources.Resources ?? []);
705
+ }
706
+ }
707
+ if (resourceList.length === 0) {
708
+ throw new toolkit_lib_1.ToolkitError('NoResourcesFound', `No resources found with filters ${filters.join(' ')}. Please try again with different filters.`);
709
+ }
710
+ resourceList = deduplicateResources(resourceList);
711
+ return process.env.MIGRATE_INTEG_TEST
712
+ ? resourceIdentifiers(resourceList)
713
+ : resourceIdentifiers(excludeManaged(resourceList));
714
+ }
715
+ /**
716
+ * Retrieves information about a resource scan.
717
+ *
718
+ * @param scanId - scan id for the to list resources for
719
+ * @returns information about the scan
720
+ */
721
+ async describeResourceScan(scanId) {
722
+ return this.cfn.describeResourceScan({
723
+ ResourceScanId: scanId,
724
+ });
725
+ }
726
+ /**
727
+ * Describes the current status of the template being generated.
728
+ *
729
+ * @param templateId - A string representing the template id
730
+ * @returns DescribeGeneratedTemplateOutput an object containing the template status and results
731
+ */
732
+ async describeGeneratedTemplate(templateId) {
733
+ const generatedTemplate = await this.cfn.describeGeneratedTemplate({
734
+ GeneratedTemplateName: templateId,
735
+ });
736
+ if (generatedTemplate.Status == ScanStatus.FAILED) {
737
+ throw new toolkit_lib_1.ToolkitError('TemplateGenerationFailed', generatedTemplate.StatusReason);
738
+ }
739
+ return generatedTemplate;
740
+ }
741
+ /**
742
+ * Retrieves a completed generated cloudformation template from the template generator.
743
+ *
744
+ * @param templateId - A string representing the template id
745
+ * @param cloudFormation - The CloudFormation sdk client to use
746
+ * @returns DescribeGeneratedTemplateOutput an object containing the template status and body
747
+ */
748
+ async getGeneratedTemplate(templateId) {
749
+ return this.cfn.getGeneratedTemplate({
750
+ GeneratedTemplateName: templateId,
751
+ });
752
+ }
753
+ /**
754
+ * Kicks off a template generation for a set of resources.
755
+ *
756
+ * @param stackName - The name of the stack
757
+ * @param resources - A list of resources to generate the template from
758
+ * @returns CreateGeneratedTemplateOutput an object containing the template arn to query on later
759
+ */
760
+ async createGeneratedTemplate(stackName, resources) {
761
+ const createTemplateOutput = await this.cfn.createGeneratedTemplate({
762
+ Resources: resources,
763
+ GeneratedTemplateName: stackName,
764
+ });
765
+ if (createTemplateOutput.GeneratedTemplateId === undefined) {
766
+ throw new toolkit_lib_1.ToolkitError('MissingTemplateArn', 'CreateGeneratedTemplate failed to return an Arn.');
767
+ }
768
+ return createTemplateOutput;
769
+ }
770
+ /**
771
+ * Deletes a generated template from the template generator.
772
+ *
773
+ * @param templateArn - The arn of the template to delete
774
+ * @returns A promise that resolves when the template has been deleted
775
+ */
776
+ async deleteGeneratedTemplate(templateArn) {
777
+ await this.cfn.deleteGeneratedTemplate({
778
+ GeneratedTemplateName: templateArn,
779
+ });
780
+ }
781
+ }
782
+ exports.CfnTemplateGeneratorProvider = CfnTemplateGeneratorProvider;
783
+ /**
784
+ * The possible ways to choose a scan to generate a CDK application from
785
+ */
786
+ var FromScan;
787
+ (function (FromScan) {
788
+ /**
789
+ * Initiate a new resource scan to build the CDK application from.
790
+ */
791
+ FromScan[FromScan["NEW"] = 0] = "NEW";
792
+ /**
793
+ * Use the last successful scan to build the CDK application from. Will fail if no scan is found.
794
+ */
795
+ FromScan[FromScan["MOST_RECENT"] = 1] = "MOST_RECENT";
796
+ /**
797
+ * Starts a scan if none exists, otherwise uses the most recent successful scan to build the CDK application from.
798
+ */
799
+ FromScan[FromScan["DEFAULT"] = 2] = "DEFAULT";
800
+ })(FromScan || (exports.FromScan = FromScan = {}));
801
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm1pZ3JhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBd0NBLHdDQTBEQztBQVNELHNDQU9DO0FBUUQsb0NBV0M7QUFVRCxzQ0FnQkM7QUFTRCw0Q0FzQ0M7QUFpR0Qsd0JBTUM7QUFRRCx3Q0FNQztBQXdDRCxnREFjQztBQWlFRCw0QkFpQkM7QUFTRCw4QkFjQztBQVFELGtDQUlDO0FBeUJELG9EQWNDO0FBUUQsZ0RBYUM7QUFRRCwwQ0FTQztBQVNELG9FQXFCQztBQVNELHdDQUlDO0FBUUQsd0RBMEJDO0FBeG9CRCwwREFBMEQ7QUFDMUQsdURBQXVEO0FBQ3ZELHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUFFN0Isb0VBQThFO0FBQzlFLHNEQUFvRDtBQWFwRCw2Q0FBNkM7QUFDN0MsK0JBQStCO0FBQy9CLGlDQUFpQztBQUVqQywwREFBNEQ7QUFDNUQsMENBQXFDO0FBRXJDLGtDQUF1QztBQUN2QyxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7QUFDdkMsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBQ3pDLDBFQUEwRTtBQUMxRSxNQUFNLDJCQUEyQixHQUFzQixZQUFZLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztBQUUxRjs7Ozs7OztHQU9HO0FBQ0ksS0FBSyxVQUFVLGNBQWMsQ0FDbEMsUUFBa0IsRUFDbEIsU0FBaUIsRUFDakIsS0FBYSxFQUNiLFFBQWdCLEVBQ2hCLFVBQW1CLEVBQ25CLFFBQWtCO0lBRWxCLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzdFLE1BQU0sa0JBQWtCLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRWpELElBQUksQ0FBQztRQUNILEVBQUUsQ0FBQyxNQUFNLENBQUMs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RyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsdUJBQXVCLENBQUM7WUFDbEUsU0FBUyxFQUFFLFNBQVM7WUFDcEIscUJBQXFCLEVBQUUsU0FBUztTQUNqQyxDQUFDLENBQUM7UUFFSCxJQUFJLG9CQUFvQixDQUFDLG1CQUFtQixLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzNELE1BQU0sSUFBSSwwQkFBWSxDQUFDLG9CQUFvQixFQUFFLGtEQUFrRCxDQUFDLENBQUM7UUFDbkcsQ0FBQztRQUNELE9BQU8sb0JBQW9CLENBQUM7SUFDOUIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLHVCQUF1QixDQUFDLFdBQW1CO1FBQy9DLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQztZQUNyQyxxQkFBcUIsRUFBRSxXQUFXO1NBQ25DLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQXZPRCxvRUF1T0M7QUFFRDs7R0FFRztBQUNILElBQVksUUFlWDtBQWZELFdBQVksUUFBUTtJQUNsQjs7T0FFRztJQUNILHFDQUFHLENBQUE7SUFFSDs7T0FFRztJQUNILHFEQUFXLENBQUE7SUFFWDs7T0FFRztJQUNILDZDQUFPLENBQUE7QUFDVCxDQUFDLEVBZlcsUUFBUSx3QkFBUixRQUFRLFFBZW5CIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAqL1xuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlcyAqL1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB0eXBlIHsgRW52aXJvbm1lbnQgfSBmcm9tICdAYXdzLWNkay9jbG91ZC1hc3NlbWJseS1hcGknO1xuaW1wb3J0IHsgVU5LTk9XTl9BQ0NPVU5ULCBVTktOT1dOX1JFR0lPTiB9IGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LWFwaSc7XG5pbXBvcnQgeyBUb29sa2l0RXJyb3IgfSBmcm9tICdAYXdzLWNkay90b29sa2l0LWxpYic7XG5pbXBvcnQgdHlwZSB7XG4gIERlc2NyaWJlR2VuZXJhdGVkVGVtcGxhdGVDb21tYW5kT3V0cHV0LFxuICBEZXNjcmliZVJlc291cmNlU2NhbkNvbW1hbmRPdXRwdXQsXG4gIEdldEdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZE91dHB1dCxcbiAgTGlzdFJlc291cmNlU2NhblJlc291cmNlc0NvbW1hbmRJbnB1dCxcbiAgUmVzb3VyY2VEZWZpbml0aW9uLFxuICBSZXNvdXJjZURldGFpbCxcbiAgUmVzb3VyY2VJZGVudGlmaWVyU3VtbWFyeSxcbiAgUmVzb3VyY2VTY2FuU3VtbWFyeSxcbiAgU2Nhbm5lZFJlc291cmNlLFxuICBTY2FubmVkUmVzb3VyY2VJZGVudGlmaWVyLFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtY2xvdWRmb3JtYXRpb24nO1xuaW1wb3J0ICogYXMgY2RrX2Zyb21fY2ZuIGZyb20gJ2Nkay1mcm9tLWNmbic7XG5pbXBvcnQgKiBhcyBjaGFsayBmcm9tICdjaGFsayc7XG5pbXBvcnQgeyBjbGlJbml0IH0gZnJvbSAnLi9pbml0JztcbmltcG9ydCB0eXBlIHsgSUNsb3VkRm9ybWF0aW9uQ2xpZW50LCBTZGtQcm92aWRlciB9IGZyb20gJy4uL2FwaS9hd3MtYXV0aCc7XG5pbXBvcnQgeyBDbG91ZEZvcm1hdGlvblN0YWNrIH0gZnJvbSAnLi4vYXBpL2Nsb3VkZm9ybWF0aW9uJztcbmltcG9ydCB7IE1vZGUgfSBmcm9tICcuLi9hcGkvcGx1Z2luJztcbmltcG9ydCB0eXBlIHsgSW9IZWxwZXIgfSBmcm9tICcuLi9hcGktcHJpdmF0ZSc7XG5pbXBvcnQgeyB6aXBEaXJlY3RvcnkgfSBmcm9tICcuLi91dGlsJztcbmNvbnN0IGNhbWVsQ2FzZSA9IHJlcXVpcmUoJ2NhbWVsY2FzZScpO1xuY29uc3QgZGVjYW1lbGl6ZSA9IHJlcXVpcmUoJ2RlY2FtZWxpemUnKTtcbi8qKiBUaGUgbGlzdCBvZiBsYW5ndWFnZXMgc3VwcG9ydGVkIGJ5IHRoZSBidWlsdC1pbiBub2N0aWx1Y2VudCBiaW5hcnkuICovXG5jb25zdCBNSUdSQVRFX1NVUFBPUlRFRF9MQU5HVUFHRVM6IHJlYWRvbmx5IHN0cmluZ1tdID0gY2RrX2Zyb21fY2ZuLnN1cHBvcnRlZF9sYW5ndWFnZXMoKTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBDREsgYXBwIGZyb20gYSB5YW1sIG9yIGpzb24gdGVtcGxhdGUuXG4gKlxuICogQHBhcmFtIHN0YWNrTmFtZSAtIFRoZSBuYW1lIHRvIGFzc2lnbiB0byB0aGUgc3RhY2sgaW4gdGhlIGdlbmVyYXRlZCBhcHBcbiAqIEBwYXJhbSBzdGFjayAtIFRoZSB5YW1sIG9yIGpzb24gdGVtcGxhdGUgZm9yIHRoZSBzdGFja1xuICogQHBhcmFtIGxhbmd1YWdlIC0gVGhlIGxhbmd1YWdlIHRvIGdlbmVyYXRlIHRoZSBDREsgYXBwIGluXG4gKiBAcGFyYW0gb3V0cHV0UGF0aCAtIFRoZSBwYXRoIGF0IHdoaWNoIHRvIGdlbmVyYXRlIHRoZSBDREsgYXBwXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZW5lcmF0ZUNka0FwcChcbiAgaW9IZWxwZXI6IElvSGVscGVyLFxuICBzdGFja05hbWU6IHN0cmluZyxcbiAgc3RhY2s6IHN0cmluZyxcbiAgbGFuZ3VhZ2U6IHN0cmluZyxcbiAgb3V0cHV0UGF0aD86IHN0cmluZyxcbiAgY29tcHJlc3M/OiBib29sZWFuLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHJlc29sdmVkT3V0cHV0UGF0aCA9IHBhdGguam9pbihvdXRwdXRQYXRoID8/IHByb2Nlc3MuY3dkKCksIHN0YWNrTmFtZSk7XG4gIGNvbnN0IGZvcm1hdHRlZFN0YWNrTmFtZSA9IGRlY2FtZWxpemUoc3RhY2tOYW1lKTtcblxuICB0cnkge1xuICAgIGZzLnJtU3luYyhyZXNvbHZlZE91dHB1dFBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgICBmcy5ta2RpclN5bmMocmVzb2x2ZWRPdXRwdXRQYXRoLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICBjb25zdCBnZW5lcmF0ZU9ubHkgPSBjb21wcmVzcztcbiAgICBhd2FpdCBjbGlJbml0KHtcbiAgICAgIGlvSGVscGVyLFxuICAgICAgdHlwZTogJ2FwcCcsXG4gICAgICBsYW5ndWFnZSxcbiAgICAgIGNhblVzZU5ldHdvcms6IHRydWUsXG4gICAgICBnZW5lcmF0ZU9ubHksXG4gICAgICB3b3JrRGlyOiByZXNvbHZlZE91dHB1dFBhdGgsXG4gICAgICBzdGFja05hbWUsXG4gICAgICBtaWdyYXRlOiB0cnVlLFxuICAgIH0pO1xuXG4gICAgbGV0IHN0YWNrRmlsZU5hbWU6IHN0cmluZztcbiAgICBzd2l0Y2ggKGxhbmd1YWdlKSB7XG4gICAgICBjYXNlICd0eXBlc2NyaXB0JzpcbiAgICAgICAgc3RhY2tGaWxlTmFtZSA9IGAke3Jlc29sdmVkT3V0cHV0UGF0aH0vbGliLyR7Zm9ybWF0dGVkU3RhY2tOYW1lfS1zdGFjay50c2A7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnamF2YSc6XG4gICAgICAgIHN0YWNrRmlsZU5hbWUgPSBgJHtyZXNvbHZlZE91dHB1dFBhdGh9L3NyYy9tYWluL2phdmEvY29tL215b3JnLyR7Y2FtZWxDYXNlKGZvcm1hdHRlZFN0YWNrTmFtZSwgeyBwYXNjYWxDYXNlOiB0cnVlIH0pfVN0YWNrLmphdmFgO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3B5dGhvbic6XG4gICAgICAgIHN0YWNrRmlsZU5hbWUgPSBgJHtyZXNvbHZlZE91dHB1dFBhdGh9LyR7Zm9ybWF0dGVkU3RhY2tOYW1lLnJlcGxhY2UoLy0vZywgJ18nKX0vJHtmb3JtYXR0ZWRTdGFja05hbWUucmVwbGFjZSgvLS9nLCAnXycpfV9zdGFjay5weWA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnY3NoYXJwJzpcbiAgICAgICAgc3RhY2tGaWxlTmFtZSA9IGAke3Jlc29sdmVkT3V0cHV0UGF0aH0vc3JjLyR7Y2FtZWxDYXNlKGZvcm1hdHRlZFN0YWNrTmFtZSwgeyBwYXNjYWxDYXNlOiB0cnVlIH0pfS8ke2NhbWVsQ2FzZShmb3JtYXR0ZWRTdGFja05hbWUsIHsgcGFzY2FsQ2FzZTogdHJ1ZSB9KX1TdGFjay5jc2A7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnZ28nOlxuICAgICAgICBzdGFja0ZpbGVOYW1lID0gYCR7cmVzb2x2ZWRPdXRwdXRQYXRofS8ke2Zvcm1hdHRlZFN0YWNrTmFtZX0uZ29gO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoXG4gICAgICAgICAgJ1Vuc3VwcG9ydGVkTWlncmF0ZUxhbmd1YWdlJyxcbiAgICAgICAgICBgJHtsYW5ndWFnZX0gaXMgbm90IHN1cHBvcnRlZCBieSBDREsgTWlncmF0ZS4gUGxlYXNlIGNob29zZSBmcm9tOiAke01JR1JBVEVfU1VQUE9SVEVEX0xBTkdVQUdFUy5qb2luKCcsICcpfWAsXG4gICAgICAgICk7XG4gICAgfVxuICAgIGZzLndyaXRlRmlsZVN5bmMoc3RhY2tGaWxlTmFtZSwgc3RhY2spO1xuICAgIGlmIChjb21wcmVzcykge1xuICAgICAgYXdhaXQgemlwRGlyZWN0b3J5KHJlc29sdmVkT3V0cHV0UGF0aCwgYCR7cmVzb2x2ZWRPdXRwdXRQYXRofS56aXBgKTtcbiAgICAgIGZzLnJtU3luYyhyZXNvbHZlZE91dHB1dFBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgZnMucm1TeW5jKHJlc29sdmVkT3V0cHV0UGF0aCwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgQ0RLIHN0YWNrIGZpbGUuXG4gKiBAcGFyYW0gdGVtcGxhdGUgLSBUaGUgdGVtcGxhdGUgdG8gdHJhbnNsYXRlIGludG8gYSBDREsgc3RhY2tcbiAqIEBwYXJhbSBzdGFja05hbWUgLSBUaGUgbmFtZSB0byBhc3NpZ24gdG8gdGhlIHN0YWNrXG4gKiBAcGFyYW0gbGFuZ3VhZ2UgLSBUaGUgbGFuZ3VhZ2UgdG8gZ2VuZXJhdGUgdGhlIHN0YWNrIGluXG4gKiBAcmV0dXJucyBBIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIENESyBzdGFjayBmaWxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZVN0YWNrKHRlbXBsYXRlOiBzdHJpbmcsIHN0YWNrTmFtZTogc3RyaW5nLCBsYW5ndWFnZTogc3RyaW5nKSB7XG4gIGNvbnN0IGZvcm1hdHRlZFN0YWNrTmFtZSA9IGAke2NhbWVsQ2FzZShkZWNhbWVsaXplKHN0YWNrTmFtZSksIHsgcGFzY2FsQ2FzZTogdHJ1ZSB9KX1TdGFja2A7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGNka19mcm9tX2Nmbi50cmFuc211dGUodGVtcGxhdGUsIGxhbmd1YWdlLCBmb3JtYXR0ZWRTdGFja05hbWUpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcignU3RhY2tHZW5lcmF0aW9uRmFpbGVkJywgYCR7Zm9ybWF0dGVkU3RhY2tOYW1lfSBjb3VsZCBub3QgYmUgZ2VuZXJhdGVkIGJlY2F1c2UgJHsoZSBhcyBFcnJvcikubWVzc2FnZX1gKTtcbiAgfVxufVxuXG4vKipcbiAqIFJlYWRzIGFuZCByZXR1cm5zIGEgc3RhY2sgdGVtcGxhdGUgZnJvbSBhIGxvY2FsIHBhdGguXG4gKlxuICogQHBhcmFtIGlucHV0UGF0aCAtIFRoZSBsb2NhdGlvbiBvZiB0aGUgdGVtcGxhdGVcbiAqIEByZXR1cm5zIEEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSB0ZW1wbGF0ZSBpZiBwcmVzZW50LCBvdGhlcndpc2UgdW5kZWZpbmVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkRnJvbVBhdGgoaW5wdXRQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICBsZXQgcmVhZEZpbGU6IHN0cmluZztcbiAgdHJ5IHtcbiAgICByZWFkRmlsZSA9IGZzLnJlYWRGaWxlU3luYyhpbnB1dFBhdGgsICd1dGY4Jyk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKCdJbnZhbGlkUGF0aCcsIGAnJHtpbnB1dFBhdGh9JyBpcyBub3QgYSB2YWxpZCBwYXRoLmApO1xuICB9XG4gIGlmIChyZWFkRmlsZSA9PSAnJykge1xuICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ0VtcHR5VGVtcGxhdGVGaWxlJywgYENsb3VkZm9ybWF0aW9uIHRlbXBsYXRlIGZpbGVwYXRoOiAnJHtpbnB1dFBhdGh9JyBpcyBhbiBlbXB0eSBmaWxlLmApO1xuICB9XG4gIHJldHVybiByZWFkRmlsZTtcbn1cblxuLyoqXG4gKiBSZWFkcyBhbmQgcmV0dXJucyBhIHN0YWNrIHRlbXBsYXRlIGZyb20gYSBkZXBsb3llZCBDbG91ZEZvcm1hdGlvbiBzdGFjay5cbiAqXG4gKiBAcGFyYW0gc3RhY2tOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHN0YWNrXG4gKiBAcGFyYW0gc2RrUHJvdmlkZXIgLSBUaGUgc2RrIHByb3ZpZGVyIGZvciBtYWtpbmcgQ2xvdWRGb3JtYXRpb24gY2FsbHNcbiAqIEBwYXJhbSBlbnZpcm9ubWVudCAtIFRoZSBhY2NvdW50IGFuZCByZWdpb24gd2hlcmUgdGhlIHN0YWNrIGlzIGRlcGxveWVkXG4gKiBAcmV0dXJucyBBIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgdGVtcGxhdGUgaWYgcHJlc2VudCwgb3RoZXJ3aXNlIHVuZGVmaW5lZFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZEZyb21TdGFjayhcbiAgc3RhY2tOYW1lOiBzdHJpbmcsXG4gIHNka1Byb3ZpZGVyOiBTZGtQcm92aWRlcixcbiAgZW52aXJvbm1lbnQ6IEVudmlyb25tZW50LFxuKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgY29uc3QgY2xvdWRGb3JtYXRpb24gPSAoYXdhaXQgc2RrUHJvdmlkZXIuZm9yRW52aXJvbm1lbnQoZW52aXJvbm1lbnQsIE1vZGUuRm9yUmVhZGluZykpLnNkay5jbG91ZEZvcm1hdGlvbigpO1xuXG4gIGNvbnN0IHN0YWNrID0gYXdhaXQgQ2xvdWRGb3JtYXRpb25TdGFjay5sb29rdXAoY2xvdWRGb3JtYXRpb24sIHN0YWNrTmFtZSwgdHJ1ZSk7XG4gIGlmIChzdGFjay5zdGFja1N0YXR1cy5pc0RlcGxveVN1Y2Nlc3MgfHwgc3RhY2suc3RhY2tTdGF0dXMuaXNSb2xsYmFja1N1Y2Nlc3MpIHtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoYXdhaXQgc3RhY2sudGVtcGxhdGUoKSk7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihcbiAgICAgICdVbmhlYWx0aHlTdGFja1N0YXR1cycsXG4gICAgICBgU3RhY2sgJyR7c3RhY2tOYW1lfScgaW4gYWNjb3VudCAke2Vudmlyb25tZW50LmFjY291bnR9IGFuZCByZWdpb24gJHtlbnZpcm9ubWVudC5yZWdpb259IGhhcyBhIHN0YXR1cyBvZiAnJHtzdGFjay5zdGFja1N0YXR1cy5uYW1lfScgZHVlIHRvICcke3N0YWNrLnN0YWNrU3RhdHVzLnJlYXNvbn0nLiBUaGUgc3RhY2sgY2Fubm90IGJlIG1pZ3JhdGVkIHVudGlsIGl0IGlzIGluIGEgaGVhbHRoeSBzdGF0ZS5gLFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBUYWtlcyBpbiBhIHN0YWNrIG5hbWUgYW5kIGFjY291bnQgYW5kIHJlZ2lvbiBhbmQgcmV0dXJucyBhIGdlbmVyYXRlZCBjbG91ZGZvcm1hdGlvbiB0ZW1wbGF0ZSB1c2luZyB0aGUgY2xvdWRmb3JtYXRpb25cbiAqIHRlbXBsYXRlIGdlbmVyYXRvci5cbiAqXG4gKiBAcGFyYW0gR2VuZXJhdGVUZW1wbGF0ZU9wdGlvbnMgLSBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgc3RhY2sgbmFtZSwgZmlsdGVycywgc2RrUHJvdmlkZXIsIGVudmlyb25tZW50LCBhbmQgbmV3U2NhbiBmbGFnXG4gKiBAcmV0dXJucyBhIGdlbmVyYXRlZCBjbG91ZGZvcm1hdGlvbiB0ZW1wbGF0ZVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVUZW1wbGF0ZShvcHRpb25zOiBHZW5lcmF0ZVRlbXBsYXRlT3B0aW9ucyk6IFByb21pc2U8R2VuZXJhdGVUZW1wbGF0ZU91dHB1dD4ge1xuICBjb25zdCBjZm4gPSBuZXcgQ2ZuVGVtcGxhdGVHZW5lcmF0b3JQcm92aWRlcihhd2FpdCBidWlsZENmbkNsaWVudChvcHRpb25zLnNka1Byb3ZpZGVyLCBvcHRpb25zLmVudmlyb25tZW50KSwgb3B0aW9ucy5pb0hlbHBlcik7XG4gIGNvbnN0IGlvSGVscGVyID0gb3B0aW9ucy5pb0hlbHBlcjtcblxuICBjb25zdCBzY2FuSWQgPSBhd2FpdCBmaW5kTGFzdFN1Y2Nlc3NmdWxTY2FuKGNmbiwgb3B0aW9ucyk7XG5cbiAgLy8gaWYgYSBjdXN0b21lciBhY2NpZGVudGFsbHkgY3RybC1jJ3Mgb3V0IG9mIHRoZSBjb21tYW5kIGFuZCBydW5zIGl0IGFnYWluLCB0aGlzIHdpbGwgY29udGludWUgdGhlIHByb2dyZXNzIGJhciB3aGVyZSBpdCBsZWZ0IG9mZlxuICBjb25zdCBjdXJTY2FuID0gYXdhaXQgY2ZuLmRlc2NyaWJlUmVzb3VyY2VTY2FuKHNjYW5JZCk7XG4gIGlmIChjdXJTY2FuLlN0YXR1cyA9PSBTY2FuU3RhdHVzLklOX1BST0dSRVNTKSB7XG4gICAgYXdhaXQgaW9IZWxwZXIuZGVmYXVsdHMuaW5mbygnUmVzb3VyY2Ugc2NhbiBpbiBwcm9ncmVzcy4gUGxlYXNlIHdhaXQsIHRoaXMgY2FuIHRha2UgMTAgbWludXRlcyBvciBsb25nZXIuJyk7XG4gICAgYXdhaXQgc2NhblByb2dyZXNzQmFyKGlvSGVscGVyLCBzY2FuSWQsIGNmbik7XG4gIH1cblxuICBhd2FpdCBkaXNwbGF5VGltZURpZmYoaW9IZWxwZXIsIG5ldyBEYXRlKCksIG5ldyBEYXRlKGN1clNjYW4uU3RhcnRUaW1lISkpO1xuXG4gIGxldCByZXNvdXJjZXM6IFNjYW5uZWRSZXNvdXJjZVtdID0gYXdhaXQgY2ZuLmxpc3RSZXNvdXJjZVNjYW5SZXNvdXJjZXMoc2NhbklkISwgb3B0aW9ucy5maWx0ZXJzKTtcblxuICBhd2FpdCBpb0hlbHBlci5kZWZhdWx0cy5pbmZvKCdmaW5kaW5nIHJlbGF0ZWQgcmVzb3VyY2VzLicpO1xuICBsZXQgcmVsYXRlZFJlc291cmNlcyA9IGF3YWl0IGNmbi5nZXRSZXNvdXJjZVNjYW5SZWxhdGVkUmVzb3VyY2VzKHNjYW5JZCEsIHJlc291cmNlcyk7XG5cbiAgYXdhaXQgaW9IZWxwZXIuZGVmYXVsdHMuaW5mbyhgRm91bmQgJHtyZWxhdGVkUmVzb3VyY2VzLmxlbmd0aH0gcmVzb3VyY2VzLmApO1xuXG4gIGF3YWl0IGlvSGVscGVyLmRlZmF1bHRzLmluZm8oJ0dlbmVyYXRpbmcgQ0ZOIHRlbXBsYXRlIGZyb20gc2Nhbm5lZCByZXNvdXJjZXMuJyk7XG4gIGNvbnN0IHRlbXBsYXRlQXJuID0gKGF3YWl0IGNmbi5jcmVhdGVHZW5lcmF0ZWRUZW1wbGF0ZShvcHRpb25zLnN0YWNrTmFtZSwgcmVsYXRlZFJlc291cmNlcykpLkdlbmVyYXRlZFRlbXBsYXRlSWQhO1xuXG4gIGxldCBnZW5lcmF0ZWRUZW1wbGF0ZSA9IGF3YWl0IGNmbi5kZXNjcmliZUdlbmVyYXRlZFRlbXBsYXRlKHRlbXBsYXRlQXJuKTtcblxuICBhd2FpdCBpb0hlbHBlci5kZWZhdWx0cy5pbmZvKCdQbGVhc2Ugd2FpdCwgdGVtcGxhdGUgY3JlYXRpb24gaW4gcHJvZ3Jlc3MuIFRoaXMgbWF5IHRha2UgYSBjb3VwbGUgbWludXRlcy4nKTtcbiAgd2hpbGUgKGdlbmVyYXRlZFRlbXBsYXRlLlN0YXR1cyAhPT0gU2NhblN0YXR1cy5DT01QTEVURSAmJiBnZW5lcmF0ZWRUZW1wbGF0ZS5TdGF0dXMgIT09IFNjYW5TdGF0dXMuRkFJTEVEKSB7XG4gICAgYXdhaXQgcHJpbnREb3RzKGBbJHtnZW5lcmF0ZWRUZW1wbGF0ZS5TdGF0dXN9XSBUZW1wbGF0ZSBDcmVhdGlvbiBpbiBQcm9ncmVzc2AsIDQwMCk7XG4gICAgZ2VuZXJhdGVkVGVtcGxhdGUgPSBhd2FpdCBjZm4uZGVzY3JpYmVHZW5lcmF0ZWRUZW1wbGF0ZSh0ZW1wbGF0ZUFybik7XG4gIH1cbiAgYXdhaXQgaW9IZWxwZXIuZGVmYXVsdHMuaW5mbygnXFxuVGVtcGxhdGUgc3VjY2Vzc2Z1bGx5IGdlbmVyYXRlZCEnKTtcbiAgcmV0dXJuIGJ1aWxkR2VuZXJhdGVkVGVtcGxhdGVPdXRwdXQoXG4gICAgZ2VuZXJhdGVkVGVtcGxhdGUsXG4gICAgKGF3YWl0IGNmbi5nZXRHZW5lcmF0ZWRUZW1wbGF0ZSh0ZW1wbGF0ZUFybikpLlRlbXBsYXRlQm9keSEsXG4gICAgdGVtcGxhdGVBcm4sXG4gICk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbmRMYXN0U3VjY2Vzc2Z1bFNjYW4oXG4gIGNmbjogQ2ZuVGVtcGxhdGVHZW5lcmF0b3JQcm92aWRlcixcbiAgb3B0aW9uczogR2VuZXJhdGVUZW1wbGF0ZU9wdGlvbnMsXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBpb0hlbHBlciA9IG9wdGlvbnMuaW9IZWxwZXI7XG4gIGxldCByZXNvdXJjZVNjYW5TdW1tYXJpZXM6IFJlc291cmNlU2NhblN1bW1hcnlbXSB8IHVuZGVmaW5lZCA9IFtdO1xuICBjb25zdCBjbGllbnRSZXF1ZXN0VG9rZW4gPSBgY2RrLW1pZ3JhdGUtJHtvcHRpb25zLmVudmlyb25tZW50LmFjY291bnR9LSR7b3B0aW9ucy5lbnZpcm9ubWVudC5yZWdpb259YDtcbiAgaWYgKG9wdGlvbnMuZnJvbVNjYW4gPT09IEZyb21TY2FuLk5FVykge1xuICAgIGF3YWl0IGlvSGVscGVyLmRlZmF1bHRzLmluZm8oYFN0YXJ0aW5nIG5ldyBzY2FuIGZvciBhY2NvdW50ICR7b3B0aW9ucy5lbnZpcm9ubWVudC5hY2NvdW50fSBpbiByZWdpb24gJHtvcHRpb25zLmVudmlyb25tZW50LnJlZ2lvbn1gKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgY2ZuLnN0YXJ0UmVzb3VyY2VTY2FuKGNsaWVudFJlcXVlc3RUb2tlbik7XG4gICAgICByZXNvdXJjZVNjYW5TdW1tYXJpZXMgPSAoYXdhaXQgY2ZuLmxpc3RSZXNvdXJjZVNjYW5zKCkpLlJlc291cmNlU2NhblN1bW1hcmllcztcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBjb250aW51aW5nIGhlcmUgYmVjYXVzZSBpZiB0aGUgc2NhbiBmYWlscyBvbiBhIG5ldy1zY2FuIGl0IGlzIHZlcnkgbGlrZWx5IGJlY2F1c2UgdGhlcmUgaXMgZWl0aGVyIGFscmVhZHkgYSBzY2FuIGluIHByb2dyZXNzXG4gICAgICAvLyBvciB0aGUgY3VzdG9tZXIgaGl0IGEgcmF0ZSBsaW1pdC4gSW4gZWl0aGVyIGNhc2Ugd2Ugd2FudCB0byBjb250aW51ZSB3aXRoIHRoZSBtb3N0IHJlY2VudCBzY2FuLlxuICAgICAgLy8gSWYgdGhpcyBoYXBwZW5zIHRvIGZhaWwgZm9yIGEgY3JlZGVudGlhbCBlcnJvciB0aGVuIHRoYXQgd2lsbCBiZSBjYXVnaHQgaW1tZWRpYXRlbHkgYWZ0ZXIgYW55d2F5LlxuICAgICAgYXdhaXQgaW9IZWxwZXIuZGVmYXVsdHMuaW5mbyhgU2NhbiBmYWlsZWQgdG8gc3RhcnQgZHVlIHRvIGVycm9yICckeyhlIGFzIEVycm9yKS5tZXNzYWdlfScsIGRlZmF1bHRpbmcgdG8gbGF0ZXN0IHNjYW4uYCk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJlc291cmNlU2NhblN1bW1hcmllcyA9IChhd2FpdCBjZm4ubGlzdFJlc291cmNlU2NhbnMoKSkuUmVzb3VyY2VTY2FuU3VtbWFyaWVzO1xuICAgIGF3YWl0IGNmbi5jaGVja0ZvclJlc291cmNlU2NhbihyZXNvdXJjZVNjYW5TdW1tYXJpZXMsIG9wdGlvbnMsIGNsaWVudFJlcXVlc3RUb2tlbik7XG4gIH1cbiAgLy8gZ2V0IHRoZSBsYXRlc3Qgc2Nhbiwgd2hpY2ggd2Uga25vdyB3aWxsIGV4aXN0XG4gIHJlc291cmNlU2NhblN1bW1hcmllcyA9IChhd2FpdCBjZm4ubGlzdFJlc291cmNlU2NhbnMoKSkuUmVzb3VyY2VTY2FuU3VtbWFyaWVzO1xuICBsZXQgc2NhbklkOiBzdHJpbmcgfCB1bmRlZmluZWQgPSByZXNvdXJjZVNjYW5TdW1tYXJpZXMhWzBdLlJlc291cmNlU2NhbklkO1xuXG4gIC8vIGZpbmQgdGhlIG1vc3QgcmVjZW50IHNjYW4gdGhhdCBpc24ndCBpbiBhIGZhaWxlZCBzdGF0ZSBpbiBjYXNlIHdlIGRpZG4ndCBzdGFydCBhIG5ldyBvbmVcbiAgZm9yIChjb25zdCBzdW1tYXJ5IG9mIHJlc291cmNlU2NhblN1bW1hcmllcyEpIHtcbiAgICBpZiAoc3VtbWFyeS5TdGF0dXMgIT09IFNjYW5TdGF0dXMuRkFJTEVEKSB7XG4gICAgICBzY2FuSWQgPSBzdW1tYXJ5LlJlc291cmNlU2NhbklkITtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzY2FuSWQhO1xufVxuXG4vKipcbiAqIFRha2VzIGEgc3RyaW5nIG9mIGZpbHRlcnMgaW4gdGhlIGZvcm1hdCBvZiBrZXkxPXZhbHVlMSxrZXkyPXZhbHVlMiBhbmQgcmV0dXJucyBhIG1hcCBvZiB0aGUgZmlsdGVycy5cbiAqXG4gKiBAcGFyYW0gZmlsdGVycyAtIGEgc3RyaW5nIG9mIGZpbHRlcnMgaW4gdGhlIGZvcm1hdCBvZiBrZXkxPXZhbHVlMSxrZXkyPXZhbHVlMlxuICogQHJldHVybnMgYSBtYXAgb2YgdGhlIGZpbHRlcnNcbiAqL1xuZnVuY3Rpb24gcGFyc2VGaWx0ZXJzKGZpbHRlcnM6IHN0cmluZyk6IHtcbiAgW2tleSBpbiBGaWx0ZXJUeXBlXTogc3RyaW5nIHwgdW5kZWZpbmVkO1xufSB7XG4gIGlmICghZmlsdGVycykge1xuICAgIHJldHVybiB7XG4gICAgICAncmVzb3VyY2UtaWRlbnRpZmllcic6IHVuZGVmaW5lZCxcbiAgICAgICdyZXNvdXJjZS10eXBlLXByZWZpeCc6IHVuZGVmaW5lZCxcbiAgICAgICd0YWcta2V5JzogdW5kZWZpbmVkLFxuICAgICAgJ3RhZy12YWx1ZSc6IHVuZGVmaW5lZCxcbiAgICB9O1xuICB9XG5cbiAgY29uc3QgZmlsdGVyU2hvcnRoYW5kczogeyBba2V5OiBzdHJpbmddOiBGaWx0ZXJUeXBlIH0gPSB7XG4gICAgJ2lkZW50aWZpZXInOiBGaWx0ZXJUeXBlLlJFU09VUkNFX0lERU5USUZJRVIsXG4gICAgJ2lkJzogRmlsdGVyVHlwZS5SRVNPVVJDRV9JREVOVElGSUVSLFxuICAgICd0eXBlJzogRmlsdGVyVHlwZS5SRVNPVVJDRV9UWVBFX1BSRUZJWCxcbiAgICAndHlwZS1wcmVmaXgnOiBGaWx0ZXJUeXBlLlJFU09VUkNFX1RZUEVfUFJFRklYLFxuICB9O1xuXG4gIGNvbnN0IGZpbHRlckxpc3QgPSBmaWx0ZXJzLnNwbGl0KCcsJyk7XG5cbiAgbGV0IGZpbHRlck1hcDogeyBba2V5IGluIEZpbHRlclR5cGVdOiBzdHJpbmcgfCB1bmRlZmluZWQgfSA9IHtcbiAgICBbRmlsdGVyVHlwZS5SRVNPVVJDRV9JREVOVElGSUVSXTogdW5kZWZpbmVkLFxuICAgIFtGaWx0ZXJUeXBlLlJFU09VUkNFX1RZUEVfUFJFRklYXTogdW5kZWZpbmVkLFxuICAgIFtGaWx0ZXJUeXBlLlRBR19LRVldOiB1bmRlZmluZWQsXG4gICAgW0ZpbHRlclR5cGUuVEFHX1ZBTFVFXTogdW5kZWZpbmVkLFxuICB9O1xuXG4gIGZvciAoY29uc3QgZmlsIG9mIGZpbHRlckxpc3QpIHtcbiAgICBjb25zdCBmaWx0ZXIgPSBmaWwuc3BsaXQoJz0nKTtcbiAgICBsZXQgZmlsdGVyS2V5ID0gZmlsdGVyWzBdO1xuICAgIGNvbnN0IGZpbHRlclZhbHVlID0gZmlsdGVyWzFdO1xuICAgIC8vIGlmIHRoZSBrZXkgaXMgYSBzaG9ydGhhbmQsIHJlcGxhY2UgaXQgd2l0aCB0aGUgZnVsbCBuYW1lXG4gICAgaWYgKGZpbHRlcktleSBpbiBmaWx0ZXJTaG9ydGhhbmRzKSB7XG4gICAgICBmaWx0ZXJLZXkgPSBmaWx0ZXJTaG9ydGhhbmRzW2ZpbHRlcktleV07XG4gICAgfVxuICAgIGlmIChPYmplY3QudmFsdWVzKEZpbHRlclR5cGUpLmluY2x1ZGVzKGZpbHRlcktleSBhcyBhbnkpKSB7XG4gICAgICBmaWx0ZXJNYXBbZmlsdGVyS2V5IGFzIGtleW9mIHR5cGVvZiBmaWx0ZXJNYXBdID0gZmlsdGVyVmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ0ludmFsaWRGaWx0ZXInLCBgSW52YWxpZCBmaWx0ZXI6ICR7ZmlsdGVyS2V5fWApO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmlsdGVyTWFwO1xufVxuXG4vKipcbiAqIFRha2VzIGEgbGlzdCBvZiBhbnkgdHlwZSBhbmQgYnJlYWtzIGl0IHVwIGludG8gY2h1bmtzIG9mIGEgc3BlY2lmaWVkIHNpemUuXG4gKlxuICogQHBhcmFtIGxpc3QgLSBUaGUgbGlzdCB0byBicmVhayB1cFxuICogQHBhcmFtIGNodW5rU2l6ZSAtIFRoZSBzaXplIG9mIGVhY2ggY2h1bmtcbiAqIEByZXR1cm5zIEEgbGlzdCBvZiBsaXN0cyBvZiB0aGUgc3BlY2lmaWVkIHNpemVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNodW5rcyhsaXN0OiBhbnlbXSwgY2h1bmtTaXplOiBudW1iZXIpOiBhbnlbXVtdIHtcbiAgY29uc3QgY2h1bmtlZExpc3Q6IGFueVtdW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSArPSBjaHVua1NpemUpIHtcbiAgICBjaHVua2VkTGlzdC5wdXNoKGxpc3Quc2xpY2UoaSwgaSArIGNodW5rU2l6ZSkpO1xuICB9XG4gIHJldHVybiBjaHVua2VkTGlzdDtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBhY2NvdW50IGFuZCByZWdpb24gZm9yIG1ha2luZyBDbG91ZEZvcm1hdGlvbiBjYWxscy5cbiAqIEBwYXJhbSBhY2NvdW50IC0gVGhlIGFjY291bnQgdG8gdXNlXG4gKiBAcGFyYW0gcmVnaW9uIC0gVGhlIHJlZ2lvbiB0byB1c2VcbiAqIEByZXR1cm5zIFRoZSBlbnZpcm9ubWVudCBvYmplY3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldEVudmlyb25tZW50KGFjY291bnQ/OiBzdHJpbmcsIHJlZ2lvbj86IHN0cmluZyk6IEVudmlyb25tZW50IHtcbiAgcmV0dXJuIHtcbiAgICBhY2NvdW50OiBhY2NvdW50ID8/IFVOS05PV05fQUNDT1VOVCxcbiAgICByZWdpb246IHJlZ2lvbiA/PyBVTktOT1dOX1JFR0lPTixcbiAgICBuYW1lOiAnY2RrLW1pZ3JhdGUtZW52JyxcbiAgfTtcbn1cblxuLyoqXG4gKiBFbnVtIGZvciB0aGUgc291cmNlIG9wdGlvbnMgZm9yIHRoZSB0ZW1wbGF0ZVxuICovXG5leHBvcnQgZW51bSBUZW1wbGF0ZVNvdXJjZU9wdGlvbnMge1xuICBQQVRIID0gJ3BhdGgnLFxuICBTVEFDSyA9ICdzdGFjaycsXG4gIFNDQU4gPSAnc2NhbicsXG59XG5cbi8qKlxuICogQW4gb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgc291cmNlIG9mIGEgdGVtcGxhdGUuXG4gKi9cbnR5cGUgVGVtcGxhdGVTb3VyY2UgPVxuICB8IHsgc291cmNlOiBUZW1wbGF0ZVNvdXJjZU9wdGlvbnMuU0NBTiB9XG4gIHwgeyBzb3VyY2U6IFRlbXBsYXRlU291cmNlT3B0aW9ucy5QQVRIOyB0ZW1wbGF0ZVBhdGg6IHN0cmluZyB9XG4gIHwgeyBzb3VyY2U6IFRlbXBsYXRlU291cmNlT3B0aW9ucy5TVEFDSzsgc3RhY2tOYW1lOiBzdHJpbmcgfTtcblxuLyoqXG4gKiBFbnVtIGZvciB0aGUgc3RhdHVzIG9mIGEgcmVzb3VyY2Ugc2NhblxuICovXG5leHBvcnQgZW51bSBTY2FuU3RhdHVzIHtcbiAgSU5fUFJPR1JFU1MgPSAnSU5fUFJPR1JFU1MnLFxuICBDT01QTEVURSA9ICdDT01QTEVURScsXG4gIEZBSUxFRCA9ICdGQUlMRUQnLFxufVxuXG5leHBvcnQgZW51bSBGaWx0ZXJUeXBlIHtcbiAgUkVTT1VSQ0VfSURFTlRJRklFUiA9ICdyZXNvdXJjZS1pZGVudGlmaWVyJyxcbiAgUkVTT1VSQ0VfVFlQRV9QUkVGSVggPSAncmVzb3VyY2UtdHlwZS1wcmVmaXgnLFxuICBUQUdfS0VZID0gJ3RhZy1rZXknLFxuICBUQUdfVkFMVUUgPSAndGFnLXZhbHVlJyxcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgdGhhdCBleGFjdGx5IG9uZSBzb3VyY2Ugb3B0aW9uIGhhcyBiZWVuIHByb3ZpZGVkLlxuICogQHBhcmFtIGZyb21QYXRoIC0gVGhlIGNvbnRlbnQgb2YgdGhlIGZsYWcgYC0tZnJvbS1wYXRoYFxuICogQHBhcmFtIGZyb21TdGFjayAtIHRoZSBjb250ZW50IG9mIHRoZSBmbGFnIGAtLWZyb20tc3RhY2tgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVNvdXJjZU9wdGlvbnMoZnJvbVBhdGg/OiBzdHJpbmcsIGZyb21TdGFjaz86IGJvb2xlYW4sIHN0YWNrTmFtZT86IHN0cmluZyk6IFRlbXBsYXRlU291cmNlIHtcbiAgaWYgKGZyb21QYXRoICYmIGZyb21TdGFjaykge1xuICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ0NvbmZsaWN0aW5nU291cmNlT3B0aW9ucycsICdPbmx5IG9uZSBvZiBgLS1mcm9tLXBhdGhgIG9yIGAtLWZyb20tc3RhY2tgIG1heSBiZSBwcm92aWRlZC4nKTtcbiAgfVxuICBpZiAoIXN0YWNrTmFtZSkge1xuICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ01pc3NpbmdTdGFja05hbWUnLCAnYC0tc3RhY2stbmFtZWAgaXMgYSByZXF1aXJlZCBmaWVsZC4nKTtcbiAgfVxuICBpZiAoIWZyb21QYXRoICYmICFmcm9tU3RhY2spIHtcbiAgICByZXR1cm4geyBzb3VyY2U6IFRlbXBsYXRlU291cmNlT3B0aW9ucy5TQ0FOIH07XG4gIH1cbiAgaWYgKGZyb21QYXRoKSB7XG4gICAgcmV0dXJuIHsgc291cmNlOiBUZW1wbGF0ZVNvdXJjZU9wdGlvbnMuUEFUSCwgdGVtcGxhdGVQYXRoOiBmcm9tUGF0aCB9O1xuICB9XG4gIHJldHVybiB7IHNvdXJjZTogVGVtcGxhdGVTb3VyY2VPcHRpb25zLlNUQUNLLCBzdGFja05hbWU6IHN0YWNrTmFtZSEgfTtcbn1cblxuLyoqXG4gKiBUYWtlcyBhIHNldCBvZiByZXNvdXJjZXMgYW5kIHJlbW92ZXMgYW55IHdpdGggdGhlIG1hbmFnZWRieXN0YWNrIGZsYWcgc2V0IHRvIHRydWUuXG4gKlxuICogQHBhcmFtIHJlc291cmNlTGlzdCAtIHRoZSBsaXN0IG9mIHJlc291cmNlcyBwcm92aWRlZCBieSB0aGUgbGlzdCBzY2FubmVkIHJlc291cmNlcyBjYWxsc1xuICogQHJldHVybnMgYSBsaXN0IG9mIHJlc291cmNlcyBub3QgbWFuYWdlZCBieSBjZm4gc3RhY2tzXG4gKi9cbmZ1bmN0aW9uIGV4Y2x1ZGVNYW5hZ2VkKHJlc291cmNlTGlzdDogU2Nhbm5lZFJlc291cmNlW10pOiBTY2FubmVkUmVzb3VyY2VJZGVudGlmaWVyW10ge1xuICByZXR1cm4gcmVzb3VyY2VMaXN0XG4gICAgLmZpbHRlcigocikgPT4gIXIuTWFuYWdlZEJ5U3RhY2spXG4gICAgLm1hcCgocikgPT4gKHtcbiAgICAgIFJlc291cmNlVHlwZTogci5SZXNvdXJjZVR5cGUhLFxuICAgICAgUmVzb3VyY2VJZGVudGlmaWVyOiByLlJlc291cmNlSWRlbnRpZmllciEsXG4gICAgfSkpO1xufVxuXG4vKipcbiAqIFRyYW5zZm9ybXMgYSBsaXN0IG9mIHJlc291cmNlcyBpbnRvIGEgbGlzdCBvZiByZXNvdXJjZSBpZGVudGlmaWVycyBieSByZW1vdmluZyB0aGUgTWFuYWdlZEJ5U3RhY2sgZmxhZy5cbiAqIFNldHRpbmcgdGhlIHZhbHVlIG9mIHRoZSBmaWVsZCB0byB1bmRlZmluZWQgZWZmZWN0aXZlbHkgcmVtb3ZlcyBpdCBmcm9tIHRoZSBvYmplY3QuXG4gKlxuICogQHBhcmFtIHJlc291cmNlTGlzdCAtIHRoZSBsaXN0IG9mIHJlc291cmNlcyBwcm92aWRlZCBieSB0aGUgbGlzdCBzY2FubmVkIHJlc291cmNlcyBjYWxsc1xuICogQHJldHVybnMgYSBsaXN0IG9mIFNjYW5uZWRSZXNvdXJjZUlkZW50aWZpZXJbXVxuICovXG5mdW5jdGlvbiByZXNvdXJjZUlkZW50aWZpZXJzKHJlc291cmNlTGlzdDogU2Nhbm5lZFJlc291cmNlW10pOiBTY2FubmVkUmVzb3VyY2VJZGVudGlmaWVyW10ge1xuICBjb25zdCBpZGVudGlmaWVyczogU2Nhbm5lZFJlc291cmNlSWRlbnRpZmllcltdID0gW107XG4gIHJlc291cmNlTGlzdC5mb3JFYWNoKChyKSA9PiB7XG4gICAgY29uc3QgaWRlbnRpZmllcjogU2Nhbm5lZFJlc291cmNlSWRlbnRpZmllciA9IHtcbiAgICAgIFJlc291cmNlVHlwZTogci5SZXNvdXJjZVR5cGUhLFxuICAgICAgUmVzb3VyY2VJZGVudGlmaWVyOiByLlJlc291cmNlSWRlbnRpZmllciEsXG4gICAgfTtcbiAgICBpZGVudGlmaWVycy5wdXNoKGlkZW50aWZpZXIpO1xuICB9KTtcbiAgcmV0dXJuIGlkZW50aWZpZXJzO1xufVxuXG4vKipcbiAqIFRha2VzIGEgc2NhbiBpZCBhbmQgbWFpbnRhaW5zIGEgcHJvZ3Jlc3MgYmFyIHRvIGRpc3BsYXkgdGhlIHByb2dyZXNzIG9mIGEgc2NhbiB0byB0aGUgdXNlci5cbiAqXG4gKiBAcGFyYW0gc2NhbklkIC0gQSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBzY2FuIGlkXG4gKiBAcGFyYW0gY2xvdWRGb3JtYXRpb24gLSBUaGUgQ2xvdWRGb3JtYXRpb24gc2RrIGNsaWVudCB0byB1c2VcbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2NhblByb2dyZXNzQmFyKGlvSGVscGVyOiBJb0hlbHBlciwgc2NhbklkOiBzdHJpbmcsIGNmbjogQ2ZuVGVtcGxhdGVHZW5lcmF0b3JQcm92aWRlcikge1xuICBsZXQgY3VyUHJvZ3Jlc3MgPSAwLjU7XG4gIC8vIHdlIGtub3cgaXQncyBpbiBwcm9ncmVzcyBpbml0aWFsbHkgc2luY2Ugd2Ugd291bGRuJ3QgaGF2ZSBnb3R0ZW4gaGVyZSBpZiBpdCB3YXNuJ3RcbiAgbGV0IGN1clNjYW46IERlc2NyaWJlUmVzb3VyY2VTY2FuQ29tbWFuZE91dHB1dCA9IHtcbiAgICBTdGF0dXM6IFNjYW5TdGF0dXMuSU5fUFJPR1JFU1MsXG4gICAgJG1ldGFkYXRhOiB7fSxcbiAgfTtcbiAgd2hpbGUgKGN1clNjYW4uU3RhdHVzID09IFNjYW5TdGF0dXMuSU5fUFJPR1JFU1MpIHtcbiAgICBjdXJTY2FuID0gYXdhaXQgY2ZuLmRlc2NyaWJlUmVzb3VyY2VTY2FuKHNjYW5JZCk7XG4gICAgY3VyUHJvZ3Jlc3MgPSBjdXJTY2FuLlBlcmNlbnRhZ2VDb21wbGV0ZWQgPz8gY3VyUHJvZ3Jlc3M7XG4gICAgcHJpbnRCYXIoMzAsIGN1clByb2dyZXNzKTtcbiAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAyMDAwKSk7XG4gIH1cbiAgYXdhaXQgaW9IZWxwZXIuZGVmYXVsdHMuaW5mbygnXFxu4pyFIFNjYW4gQ29tcGxldGUhJyk7XG59XG5cbi8qKlxuICogUHJpbnRzIGEgcHJvZ3Jlc3MgYmFyIHRvIHRoZSBjb25zb2xlLiBUbyBiZSB1c2VkIGluIGEgd2hpbGUgbG9vcCB0byBzaG93IHByb2dyZXNzIG9mIGEgbG9uZyBydW5uaW5nIHRhc2suXG4gKiBUaGUgcHJvZ3Jlc3MgYmFyIGRlbGV0ZXMgdGhlIGN1cnJlbnQgbGluZSBvbiB0aGUgY29uc29sZSBhbmQgcmV3cml0ZXMgaXQgd2l0aCB0aGUgcHJvZ3Jlc3MgYW1vdW50LlxuICpcbiAqIEBwYXJhbSB3aWR0aCAtIFRoZSB3aWR0aCBvZiB0aGUgcHJvZ3Jlc3MgYmFyXG4gKiBAcGFyYW0gcHJvZ3Jlc3MgLSBUaGUgY3VycmVudCBwcm9ncmVzcyB0byBkaXNwbGF5IGFzIGEgcGVyY2VudGFnZSBvZiAxMDBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByaW50QmFyKHdpZHRoOiBudW1iZXIsIHByb2dyZXNzOiBudW1iZXIpIHtcbiAgaWYgKCFwcm9jZXNzLmVudi5NSUdSQVRFX0lOVEVHX1RFU1QpIHtcbiAgICBjb25zdCBGVUxMX0JMT0NLID0gJ+KWiCc7XG4gICAgY29uc3QgUEFSVElBTF9CTE9DSyA9IFsnJywgJ+KWjycsICfilo4nLCAn4paNJywgJ+KWjCcsICfilosnLCAn4paKJywgJ+KWiSddO1xuICAgIGNvbnN0IGZyYWN0aW9uID0gTWF0aC5taW4ocHJvZ3Jlc3MgLyAxMDAsIDEpO1xuICAgIGNvbnN0IGlubmVyV2lkdGggPSBNYXRoLm1heCgxLCB3aWR0aCAtIDIpO1xuICAgIGNvbnN0IGNoYXJzID0gaW5uZXJXaWR0aCAqIGZyYWN0aW9uO1xuICAgIGNvbnN0IHJlbWFpbmRlciA9IGNoYXJzIC0gTWF0aC5mbG9vcihjaGFycyk7XG5cbiAgICBjb25zdCBmdWxsQ2hhcnMgPSBGVUxMX0JMT0NLLnJlcGVhdChNYXRoLmZsb29yKGNoYXJzKSk7XG4gICAgY29uc3QgcGFydGlhbENoYXIgPSBQQVJUSUFMX0JMT0NLW01hdGguZmxvb3IocmVtYWluZGVyICogUEFSVElBTF9CTE9DSy5sZW5ndGgpXTtcbiAgICBjb25zdCBmaWxsZXIgPSAnwrcnLnJlcGVhdChpbm5lcldpZHRoIC0gTWF0aC5mbG9vcihjaGFycykgLSAocGFydGlhbENoYXIgPyAxIDogMCkpO1xuXG4gICAgY29uc3QgY29sb3IgPSBjaGFsay5ncmVlbjtcblxuICAgIHJld3JpdGVMaW5lKCdbJyArIGNvbG9yKGZ1bGxDaGFycyArIHBhcnRpYWxDaGFyKSArIGZpbGxlciArIGBdICgke3Byb2dyZXNzfSUpYCk7XG4gIH1cbn1cblxuLyoqXG4gKiBQcmludHMgYSBtZXNzYWdlIHRvIHRoZSBjb25zb2xlIHdpdGggYSBzZXJpZXMgcGVyaW9kcyBhcHBlbmRlZCB0byBpdC4gVG8gYmUgdXNlZCBpbiBhIHdoaWxlIGxvb3AgdG8gc2hvdyBwcm9ncmVzcyBvZiBhIGxvbmcgcnVubmluZyB0YXNrLlxuICogVGhlIG1lc3NhZ2UgZGVsZXRlcyB0aGUgY3VycmVudCBsaW5lIGFuZCByZXdyaXRlcyBpdCBzZXZlcmFsIHRpbWVzIHRvIGRpc3BsYXkgMS0zIHBlcmlvZHMgdG8gc2hvdyB0aGUgdXNlciB0aGF0IHRoZSB0YXNrIGlzIHN0aWxsIHJ1bm5pbmcuXG4gKlxuICogQHBhcmFtIG1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byBkaXNwbGF5XG4gKiBAcGFyYW0gdGltZW91dHg0IC0gVGhlIGFtb3VudCBvZiB0aW1lIHRvIHdhaXQgYmVmb3JlIHByaW50aW5nIHRoZSBuZXh0IHBlcmlvZFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJpbnREb3RzKG1lc3NhZ2U6IHN0cmluZywgdGltZW91dHg0OiBudW1iZXIpIHtcbiAgaWYgKCFwcm9jZXNzLmVudi5NSUdSQVRFX0lOVEVHX1RFU1QpIHtcbiAgICByZXdyaXRlTGluZShtZXNzYWdlICsgJyAuJyk7XG4gICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgdGltZW91dHg0KSk7XG5cbiAgICByZXdyaXRlTGluZShtZXNzYWdlICsgJyAuLicpO1xuICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIHRpbWVvdXR4NCkpO1xuXG4gICAgcmV3cml0ZUxpbmUobWVzc2FnZSArICcgLi4uJyk7XG4gICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgdGltZW91dHg0KSk7XG5cbiAgICByZXdyaXRlTGluZShtZXNzYWdlKTtcbiAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCB0aW1lb3V0eDQpKTtcbiAgfVxufVxuXG4vKipcbiAqIFJld3JpdGVzIHRoZSBjdXJyZW50IGxpbmUgb24gdGhlIGNvbnNvbGUgYW5kIHdyaXRlcyBhIG5ldyBtZXNzYWdlIHRvIGl0LlxuICogVGhpcyBpcyBhIGhlbHBlciBmdW5jaXRvbiBmb3IgcHJpbnREb3RzIGFuZCBwcmludEJhci5cbiAqXG4gKiBAcGFyYW0gbWVzc2FnZSAtIFRoZSBtZXNzYWdlIHRvIGRpc3BsYXlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJld3JpdGVMaW5lKG1lc3NhZ2U6IHN0cmluZykge1xuICBwcm9jZXNzLnN0ZG91dC5jbGVhckxpbmUoMCk7XG4gIHByb2Nlc3Muc3Rkb3V0LmN1cnNvclRvKDApO1xuICBwcm9jZXNzLnN0ZG91dC53cml0ZShtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBQcmludHMgdGhlIHRpbWUgZGlmZmVyZW5jZSBiZXR3ZWVuIHR3byBkYXRlcyBpbiBkYXlzLCBob3VycywgYW5kIG1pbnV0ZXMuXG4gKlxuICogQHBhcmFtIHRpbWUxIC0gVGhlIGZpcnN0IGRhdGUgdG8gY29tcGFyZVxuICogQHBhcmFtIHRpbWUyIC0gVGhlIHNlY29uZCBkYXRlIHRvIGNvbXBhcmVcbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGlzcGxheVRpbWVEaWZmKGlvSGVscGVyOiBJb0hlbHBlciwgdGltZTE6IERhdGUsIHRpbWUyOiBEYXRlKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGRpZmYgPSBNYXRoLmFicyh0aW1lMS5nZXRUaW1lKCkgLSB0aW1lMi5nZXRUaW1lKCkpO1xuXG4gIGNvbnN0IGRheXMgPSBNYXRoLmZsb29yKGRpZmYgLyAoMTAwMCAqIDYwICogNjAgKiAyNCkpO1xuICBjb25zdCBob3VycyA9IE1hdGguZmxvb3IoKGRpZmYgJSAoMTAwMCAqIDYwICogNjAgKiAyNCkpIC8gKDEwMDAgKiA2MCAqIDYwKSk7XG4gIGNvbnN0IG1pbnV0ZXMgPSBNYXRoLmZsb29yKChkaWZmICUgKDEwMDAgKiA2MCAqIDYwKSkgLyAoMTAwMCAqIDYwKSk7XG5cbiAgYXdhaXQgaW9IZWxwZXIuZGVmYXVsdHMuaW5mbyhgVXNpbmcgdGhlIGxhdGVzdCBzdWNjZXNzZnVsIHNjYW4gd2hpY2ggaXMgJHtkYXlzfSBkYXlzLCAke2hvdXJzfSBob3VycywgYW5kICR7bWludXRlc30gbWludXRlcyBvbGQuYCk7XG59XG5cbi8qKlxuICogV3JpdGVzIGEgbWlncmF0ZS5qc29uIGZpbGUgdG8gdGhlIG91dHB1dCBkaXJlY3RvcnkuXG4gKlxuICogQHBhcmFtIG91dHB1dFBhdGggLSBUaGUgcGF0aCB0byB3cml0ZSB0aGUgbWlncmF0ZS5qc29uIGZpbGUgdG9cbiAqIEBwYXJhbSBzdGFja05hbWUgLSBUaGUgbmFtZSBvZiB0aGUgc3RhY2tcbiAqIEBwYXJhbSBnZW5lcmF0ZWRPdXRwdXQgLSBUaGUgb3V0cHV0IG9mIHRoZSB0ZW1wbGF0ZSBnZW5lcmF0b3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdyaXRlTWlncmF0ZUpzb25GaWxlKFxuICBvdXRwdXRQYXRoOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIHN0YWNrTmFtZTogc3RyaW5nLFxuICBtaWdyYXRlSnNvbjogTWlncmF0ZUpzb25Gb3JtYXQsXG4pIHtcbiAgY29uc3Qgb3V0cHV0VG9Kc29uID0ge1xuICAgICcvLyc6ICdUaGlzIGZpbGUgaXMgZ2VuZXJhdGVkIGJ5IGNkayBtaWdyYXRlLiBJdCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgZGVsZXRlZCBhZnRlciB0aGUgZmlyc3Qgc3VjY2Vzc2Z1bCBkZXBsb3ltZW50IG9mIHRoaXMgYXBwIHRvIHRoZSBlbnZpcm9ubWVudCBvZiB0aGUgb3JpZ2luYWwgcmVzb3VyY2VzLicsXG4gICAgJ1NvdXJjZSc6IG1pZ3JhdGVKc29uLnNvdXJjZSxcbiAgICAnUmVzb3VyY2VzJzogbWlncmF0ZUpzb24ucmVzb3VyY2VzLFxuICB9O1xuICBmcy53cml0ZUZpbGVTeW5jKFxuICAgIGAke3BhdGguam9pbihvdXRwdXRQYXRoID8/IHByb2Nlc3MuY3dkKCksIHN0YWNrTmFtZSl9L21pZ3JhdGUuanNvbmAsXG4gICAgSlNPTi5zdHJpbmdpZnkob3V0cHV0VG9Kc29uLCBudWxsLCAyKSxcbiAgKTtcbn1cblxuLyoqXG4gKiBUYWtlcyBhIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIGZyb20tc2NhbiBmbGFnIGFuZCByZXR1cm5zIGEgRnJvbVNjYW4gZW51bSB2YWx1ZS5cbiAqXG4gKiBAcGFyYW0gc2NhblR5cGUgLSBBIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIGZyb20tc2NhbiBmbGFnXG4gKiBAcmV0dXJucyBBIEZyb21TY2FuIGVudW0gdmFsdWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1pZ3JhdGVTY2FuVHlwZShzY2FuVHlwZTogc3RyaW5nKSB7XG4gIHN3aXRjaCAoc2NhblR5cGUpIHtcbiAgICBjYXNlICduZXcnOlxuICAgICAgcmV0dXJuIEZyb21TY2FuLk5FVztcbiAgICBjYXNlICdtb3N0LXJlY2VudCc6XG4gICAgICByZXR1cm4gRnJvbVNjYW4uTU9TVF9SRUNFTlQ7XG4gICAgY2FzZSAnJzpcbiAgICAgIHJldHVybiBGcm9tU2Nhbi5ERUZBVUxUO1xuICAgIGNhc2UgdW5kZWZpbmVkOlxuICAgICAgcmV0dXJuIEZyb21TY2FuLkRFRkFVTFQ7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ1Vua25vd25TY2FuVHlwZScsIGBVbmtub3duIHNjYW4gdHlwZTogJHtzY2FuVHlwZX1gKTtcbiAgfVxufVxuXG4vKipcbiAqIFRha2VzIGEgZ2VuZXJhdGVkVGVtcGxhdGVPdXRwdXQgb2JqY3QgYW5kIHJldHVybnMgYSBib29sZWFuIHJlcHJlc2VudGluZyB3aGV0aGVyIHRoZXJlIGFyZSBhbnkgd2FybmluZ3Mgb24gYW55IHJlc2NvdXJjZXMuXG4gKlxuICogQHBhcmFtIGdlbmVyYXRlZFRlbXBsYXRlT3V0cHV0IC0gQSBHZW5lcmF0ZVRlbXBsYXRlT3V0cHV0IG9iamVjdFxuICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB3aGV0aGVyIHRoZXJlIGFyZSBhbnkgd2FybmluZ3Mgb24gYW55IHJlc2NvdXJjZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVGhlcmVBV2FybmluZyhnZW5lcmF0ZWRUZW1wbGF0ZU91dHB1dDogR2VuZXJhdGVUZW1wbGF0ZU91dHB1dCkge1xuICBpZiAoZ2VuZXJhdGVkVGVtcGxhdGVPdXRwdXQucmVzb3VyY2VzKSB7XG4gICAgZm9yIChjb25zdCByZXNvdXJjZSBvZiBnZW5lcmF0ZWRUZW1wbGF0ZU91dHB1dC5yZXNvdXJjZXMpIHtcbiAgICAgIGlmIChyZXNvdXJjZS5XYXJuaW5ncyAmJiByZXNvdXJjZS5XYXJuaW5ncy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogQnVpbGRzIHRoZSBHZW5lcmF0ZVRlbXBsYXRlT3V0cHV0IG9iamVjdCBmcm9tIHRoZSBEZXNjcmliZUdlbmVyYXRlZFRlbXBsYXRlT3V0cHV0IGFuZCB0aGUgdGVtcGxhdGUgYm9keS5cbiAqXG4gKiBAcGFyYW0gZ2VuZXJhdGVkVGVtcGxhdGVTdW1tYXJ5IC0gVGhlIG91dHB1dCBvZiB0aGUgZGVzY3JpYmUgZ2VuZXJhdGVkIHRlbXBsYXRlIGNhbGxcbiAqIEBwYXJhbSB0ZW1wbGF0ZUJvZHkgLSBUaGUgYm9keSBvZiB0aGUgZ2VuZXJhdGVkIHRlbXBsYXRlXG4gKiBAcmV0dXJucyBBIEdlbmVyYXRlVGVtcGxhdGVPdXRwdXQgb2JqZWN0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZEdlbmVyYXRlZFRlbXBsYXRlT3V0cHV0KFxuICBnZW5lcmF0ZWRUZW1wbGF0ZVN1bW1hcnk6IERlc2NyaWJlR2VuZXJhdGVkVGVtcGxhdGVDb21tYW5kT3V0cHV0LFxuICB0ZW1wbGF0ZUJvZHk6IHN0cmluZyxcbiAgc291cmNlOiBzdHJpbmcsXG4pOiBHZW5lcmF0ZVRlbXBsYXRlT3V0cHV0IHtcbiAgY29uc3QgcmVzb3VyY2VzOiBSZXNvdXJjZURldGFpbFtdIHwgdW5kZWZpbmVkID0gZ2VuZXJhdGVkVGVtcGxhdGVTdW1tYXJ5LlJlc291cmNlcztcbiAgY29uc3QgbWlncmF0ZUpzb246IE1pZ3JhdGVKc29uRm9ybWF0ID0ge1xuICAgIHRlbXBsYXRlQm9keTogdGVtcGxhdGVCb2R5LFxuICAgIHNvdXJjZTogc291cmNlLFxuICAgIHJlc291cmNlczogZ2VuZXJhdGVkVGVtcGxhdGVTdW1tYXJ5LlJlc291cmNlcyEubWFwKChyKSA9PiAoe1xuICAgICAgUmVzb3VyY2VUeXBlOiByLlJlc291cmNlVHlwZSEsXG4gICAgICBMb2dpY2FsUmVzb3VyY2VJZDogci5Mb2dpY2FsUmVzb3VyY2VJZCEsXG4gICAgICBSZXNvdXJjZUlkZW50aWZpZXI6IHIuUmVzb3VyY2VJZGVudGlmaWVyISxcbiAgICB9KSksXG4gIH07XG4gIGNvbnN0IHRlbXBsYXRlSWQgPSBnZW5lcmF0ZWRUZW1wbGF0ZVN1bW1hcnkuR2VuZXJhdGVkVGVtcGxhdGVJZCE7XG4gIHJldHVybiB7XG4gICAgbWlncmF0ZUpzb246IG1pZ3JhdGVKc29uLFxuICAgIHJlc291cmNlczogcmVzb3VyY2VzLFxuICAgIHRlbXBsYXRlSWQ6IHRlbXBsYXRlSWQsXG4gIH07XG59XG5cbi8qKlxuICogQnVpbGRzIGEgQ2xvdWRGb3JtYXRpb24gc2RrIGNsaWVudCBmb3IgbWFraW5nIHJlcXVlc3RzIHdpdGggdGhlIENGTiB0ZW1wbGF0ZSBnZW5lcmF0b3IuXG4gKlxuICogQHBhcmFtIHNka1Byb3ZpZGVyIC0gVGhlIHNkayBwcm92aWRlciBmb3IgbWFraW5nIENsb3VkRm9ybWF0aW9uIGNhbGxzXG4gKiBAcGFyYW0gZW52aXJvbm1lbnQgLSBUaGUgYWNjb3VudCBhbmQgcmVnaW9uIHdoZXJlIHRoZSBzdGFjayBpcyBkZXBsb3llZFxuICogQHJldHVybnMgQSBDbG91ZEZvcm1hdGlvbiBzZGsgY2xpZW50XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidWlsZENmbkNsaWVudChzZGtQcm92aWRlcjogU2RrUHJvdmlkZXIsIGVudmlyb25tZW50OiBFbnZpcm9ubWVudCkge1xuICBjb25zdCBzZGsgPSAoYXdhaXQgc2RrUHJvdmlkZXIuZm9yRW52aXJvbm1lbnQoZW52aXJvbm1lbnQsIE1vZGUuRm9yUmVhZGluZykpLnNkaztcbiAgc2RrLmFwcGVuZEN1c3RvbVVzZXJBZ2VudCgnY2RrLW1pZ3JhdGUnKTtcbiAgcmV0dXJuIHNkay5jbG91ZEZvcm1hdGlvbigpO1xufVxuXG4vKipcbiAqIEFwcGVuZHMgYSBsaXN0IG9mIHdhcm5pbmdzIHRvIGEgcmVhZG1lIGZpbGUuXG4gKlxuICogQHBhcmFtIGZpbGVwYXRoIC0gVGhlIHBhdGggdG8gdGhlIHJlYWRtZSBmaWxlXG4gKiBAcGFyYW0gcmVzb3VyY2VzIC0gQSBsaXN0IG9mIHJlc291cmNlcyB0byBhcHBlbmQgd2FybmluZ3MgZm9yXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBlbmRXYXJuaW5nc1RvUmVhZG1lKGZpbGVwYXRoOiBzdHJpbmcsIHJlc291cmNlczogUmVzb3VyY2VEZXRhaWxbXSkge1xuICBjb25zdCByZWFkbWUgPSBmcy5yZWFkRmlsZVN5bmMoZmlsZXBhdGgsICd1dGY4Jyk7XG4gIGNvbnN0IGxpbmVzID0gcmVhZG1lLnNwbGl0KCdcXG4nKTtcbiAgY29uc3QgaW5kZXggPSBsaW5lcy5maW5kSW5kZXgoKGxpbmUpID0+IGxpbmUudHJpbSgpID09PSAnRW5qb3khJyk7XG4gIGxldCBsaW5lc1RvQWRkID0gWydcXG4jIyBXYXJuaW5ncyddO1xuICBsaW5lc1RvQWRkLnB1c2goJyMjIyBXcml0ZS1vbmx5IHByb3BlcnRpZXMnKTtcbiAgbGluZXNUb0FkZC5wdXNoKFxuICAgIFwiV3JpdGUtb25seSBwcm9wZXJ0aWVzIGFyZSByZXNvdXJjZSBwcm9wZXJ0eSB2YWx1ZXMgdGhhdCBjYW4gYmUgd3JpdHRlbiB0byBidXQgY2FuJ3QgYmUgcmVhZCBieSBBV1MgQ2xvdWRGb3JtYXRpb24gb3IgQ0RLIE1pZ3JhdGUuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWUgW0lhQyBnZW5lcmF0b3IgYW5kIHdyaXRlLW9ubHkgcHJvcGVydGllc10oaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvZ2VuZXJhdGUtSWFDLXdyaXRlLW9ubHktcHJvcGVydGllcy5odG1sKS5cIixcbiAgKTtcbiAgbGluZXNUb0FkZC5wdXNoKCdcXG4nKTtcbiAgbGluZXNUb0FkZC5wdXNoKFxuICAgICdXcml0ZS1vbmx5IHByb3BlcnRpZXMgZGlzY292ZXJlZCBkdXJpbmcgbWlncmF0aW9uIGFyZSBvcmdhbml6ZWQgaGVyZSBieSByZXNvdXJjZSBJRCBhbmQgY2F0ZWdvcml6ZWQgYnkgd3JpdGUtb25seSBwcm9wZXJ0eSB0eXBlLiBSZXNvbHZlIHdyaXRlLW9ubHkgcHJvcGVydGllcyBieSBwcm92aWRpbmcgcHJvcGVydHkgdmFsdWVzIGluIHlvdXIgQ0RLIGFwcC4gRm9yIGd1aWRhbmNlLCBzZWUgW1Jlc29sdmUgd3JpdGUtb25seSBwcm9wZXJ0aWVzXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY2RrL3YyL2d1aWRlL21pZ3JhdGUuaHRtbCNtaWdyYXRlLXJlc291cmNlcy13cml0ZW9ubHkpLicsXG4gICk7XG4gIGZvciAoY29uc3QgcmVzb3VyY2Ugb2YgcmVzb3VyY2VzKSB7XG4gICAgaWYgKHJlc291cmNlLldhcm5pbmdzICYmIHJlc291cmNlLldhcm5pbmdzLmxlbmd0aCA+IDApIHtcbiAgICAgIGxpbmVzVG9BZGQucHVzaChgIyMjICR7cmVzb3VyY2UuTG9naWNhbFJlc291cmNlSWR9YCk7XG4gICAgICBmb3IgKGNvbnN0IHdhcm5pbmcgb2YgcmVzb3VyY2UuV2FybmluZ3MpIHtcbiAgICAgICAgbGluZXNUb0FkZC5wdXNoKGAtICoqJHt3YXJuaW5nLlR5cGV9Kio6IGApO1xuICAgICAgICBmb3IgKGNvbnN0IHByb3BlcnR5IG9mIHdhcm5pbmcuUHJvcGVydGllcyEpIHtcbiAgICAgICAgICBsaW5lc1RvQWRkLnB1c2goYCAgLSAke3Byb3BlcnR5LlByb3BlcnR5UGF0aH06ICR7cHJvcGVydHkuRGVzY3JpcHRpb259YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgbGluZXMuc3BsaWNlKGluZGV4LCAwLCAuLi5saW5lc1RvQWRkKTtcbiAgZnMud3JpdGVGaWxlU3luYyhmaWxlcGF0aCwgbGluZXMuam9pbignXFxuJykpO1xufVxuXG4vKipcbiAqIHRha2VzIGEgbGlzdCBvZiByZXNvdXJjZXMgYW5kIHJldHVybnMgYSBsaXN0IG9mIHVuaXF1ZSByZXNvdXJjZXMgYmFzZWQgb24gdGhlIHJlc291cmNlIHR5cGUgYW5kIGxvZ2ljYWwgcmVzb3VyY2UgaWQuXG4gKlxuICogQHBhcmFtIHJlc291cmNlcyAtIEEgbGlzdCBvZiByZXNvdXJjZXMgdG8gZGVkdXBsaWNhdGVcbiAqIEByZXR1cm5zIEEgbGlzdCBvZiB1bmlxdWUgcmVzb3VyY2VzXG4gKi9cbmZ1bmN0aW9uIGRlZHVwbGljYXRlUmVzb3VyY2VzKHJlc291cmNlczogUmVzb3VyY2VEZXRhaWxbXSkge1xuICBsZXQgdW5pcXVlUmVzb3VyY2VzOiB7IFtrZXk6IHN0cmluZ106IFJlc291cmNlRGV0YWlsIH0gPSB7fTtcblxuICBmb3IgKGNvbnN0IHJlc291cmNlIG9mIHJlc291cmNlcykge1xuICAgIGNvbnN0IGtleSA9IE9iamVjdC5rZXlzKHJlc291cmNlLlJlc291cmNlSWRlbnRpZmllciEpWzBdO1xuXG4gICAgLy8gQ3JlYXRpbmcgb3VyIHVuaXF1ZSBpZGVudGlmaWVyIHVzaW5nIHRoZSByZXNvdXJjZSB0eXBlLCB0aGUga2V5LCBhbmQgdGhlIHZhbHVlIG9mIHRoZSByZXNvdXJjZSBpZGVudGlmaWVyXG4gICAgLy8gVGhlIHJlc291cmNlIGlkZW50aWZpZXIgaXMgYSBjb21iaW5hdGlvbiBvZiBhIGtleSB2YWx1ZSBwYWlyIGRlZmluZWQgYnkgYSByZXNvdXJjZSdzIHNjaGVtYSwgYW5kIHRoZSByZXNvdXJjZSB0eXBlIG9mIHRoZSByZXNvdXJjZS5cbiAgICBjb25zdCB1bmlxdWVJZGVudGlmZXIgPSBgJHtyZXNvdXJjZS5SZXNvdXJjZVR5cGV9OiR7a2V5fToke3Jlc291cmNlLlJlc291cmNlSWRlbnRpZmllciFba2V5XX1gO1xuICAgIHVuaXF1ZVJlc291cmNlc1t1bmlxdWVJZGVudGlmZXJdID0gcmVzb3VyY2U7XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LnZhbHVlcyh1bmlxdWVSZXNvdXJjZXMpO1xufVxuXG4vKipcbiAqIENsYXNzIGZvciBtYWtpbmcgQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGUgZ2VuZXJhdG9yIGNhbGxzXG4gKi9cbmV4cG9ydCBjbGFzcyBDZm5UZW1wbGF0ZUdlbmVyYXRvclByb3ZpZGVyIHtcbiAgcHJpdmF0ZSBjZm46IElDbG91ZEZvcm1hdGlvbkNsaWVudDtcbiAgcHJpdmF0ZSBpb0hlbHBlcjogSW9IZWxwZXI7XG4gIGNvbnN0cnVjdG9yKGNmbjogSUNsb3VkRm9ybWF0aW9uQ2xpZW50LCBpb0hlbHBlcjogSW9IZWxwZXIpIHtcbiAgICB0aGlzLmNmbiA9IGNmbjtcbiAgICB0aGlzLmlvSGVscGVyID0gaW9IZWxwZXI7XG4gIH1cblxuICBhc3luYyBjaGVja0ZvclJlc291cmNlU2NhbihcbiAgICByZXNvdXJjZVNjYW5TdW1tYXJpZXM6IFJlc291cmNlU2NhblN1bW1hcnlbXSB8IHVuZGVmaW5lZCxcbiAgICBvcHRpb25zOiBHZW5lcmF0ZVRlbXBsYXRlT3B0aW9ucyxcbiAgICBjbGllbnRSZXF1ZXN0VG9rZW46IHN0cmluZyxcbiAgKSB7XG4gICAgaWYgKCFyZXNvdXJjZVNjYW5TdW1tYXJpZXMgfHwgcmVzb3VyY2VTY2FuU3VtbWFyaWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgaWYgKG9wdGlvbnMuZnJvbVNjYW4gPT09IEZyb21TY2FuLk1PU1RfUkVDRU5UKSB7XG4gICAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoXG4gICAgICAgICAgJ05vU2NhbnNGb3VuZCcsXG4gICAgICAgICAgJ05vIHNjYW5zIGZvdW5kLiBQbGVhc2UgZWl0aGVyIHN0YXJ0IGEgbmV3IHNjYW4gd2l0aCB0aGUgYC0tZnJvbS1zY2FuYCBuZXcgb3IgZG8gbm90IHNwZWNpZnkgYSBgLS1mcm9tLXNjYW5gIG9wdGlvbi4nLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5kZWZhdWx0cy5pbmZvKCdObyBzY2FucyBmb3VuZC4gSW5pdGlhdGluZyBhIG5ldyByZXNvdXJjZSBzY2FuLicpO1xuICAgICAgICBhd2FpdCB0aGlzLnN0YXJ0UmVzb3VyY2VTY2FuKGNsaWVudFJlcXVlc3RUb2tlbik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyBhIHRva2VuaXplZCBsaXN0IG9mIHJlc291cmNlcyBhbmQgdGhlaXIgYXNzb2NpYXRlZCBzY2FuLiBJZiBhIHRva2VuIGlzIHByZXNlbnQgdGhlIGZ1bmN0aW9uXG4gICAqIHdpbGwgbG9vcCB0aHJvdWdoIGFsbCBwYWdlcyBhbmQgY29tYmluZSB0aGVtIGludG8gYSBzaW5nbGUgbGlzdCBvZiBTY2FubmVkUmVsYXRlZFJlc291cmNlc1xuICAgKlxuICAgKiBAcGFyYW0gc2NhbklkIC0gc2NhbiBpZCBmb3IgdGhlIHRvIGxpc3QgcmVzb3VyY2VzIGZvclxuICAgKiBAcGFyYW0gcmVzb3VyY2VzIC0gQSBsaXN0IG9mIHJlc291cmNlcyB0byBmaW5kIHJlbGF0ZWQgcmVzb3VyY2VzIGZvclxuICAgKi9cbiAgYXN5bmMgZ2V0UmVzb3VyY2VTY2FuUmVsYXRlZFJlc291cmNlcyhcbiAgICBzY2FuSWQ6IHN0cmluZyxcbiAgICByZXNvdXJjZXM6IFNjYW5uZWRSZXNvdXJjZVtdLFxuICApOiBQcm9taXNlPFNjYW5uZWRSZXNvdXJjZUlkZW50aWZpZXJbXT4ge1xuICAgIGxldCByZWxhdGVkUmVzb3VyY2VMaXN0ID0gcmVzb3VyY2VzO1xuXG4gICAgLy8gYnJlYWsgdGhlIGxpc3Qgb2YgcmVzb3VyY2VzIGludG8gY2h1bmtzIG9mIDEwMCB0byBhdm9pZCBoaXR0aW5nIHRoZSAxMDAgcmVzb3VyY2UgbGltaXRcbiAgICBmb3IgKGNvbnN0IGNodW5rIG9mIGNodW5rcyhyZXNvdXJjZXMsIDEwMCkpIHtcbiAgICAgIC8vIGdldCB0aGUgZmlyc3QgcGFnZSBvZiByZWxhdGVkIHJlc291cmNlc1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5jZm4ubGlzdFJlc291cmNlU2NhblJlbGF0ZWRSZXNvdXJjZXMoe1xuICAgICAgICBSZXNvdXJjZVNjYW5JZDogc2NhbklkLFxuICAgICAgICBSZXNvdXJjZXM6IGNodW5rLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIGFkZCB0aGUgZmlyc3QgcGFnZSB0byB0aGUgbGlzdFxuICAgICAgcmVsYXRlZFJlc291cmNlTGlzdC5wdXNoKC4uLihyZXMuUmVsYXRlZFJlc291cmNlcyA/PyBbXSkpO1xuICAgICAgbGV0IG5leHRUb2tlbiA9IHJlcy5OZXh0VG9rZW47XG5cbiAgICAgIC8vIGlmIHRoZXJlIGFyZSBtb3JlIHBhZ2VzLCBjeWNsZSB0aHJvdWdoIHRoZW0gYW5kIGFkZCB0aGVtIHRvIHRoZSBsaXN0IGJlZm9yZSBtb3Zpbmcgb24gdG8gdGhlIG5leHQgY2h1bmtcbiAgICAgIHdoaWxlIChuZXh0VG9rZW4pIHtcbiAgICAgICAgY29uc3QgbmV4dFJlbGF0ZWRSZXNvdXJjZXMgPSBhd2FpdCB0aGlzLmNmbi5saXN0UmVzb3VyY2VTY2FuUmVsYXRlZFJlc291cmNlcyh7XG4gICAgICAgICAgUmVzb3VyY2VTY2FuSWQ6IHNjYW5JZCxcbiAgICAgICAgICBSZXNvdXJjZXM6IHJlc291cmNlSWRlbnRpZmllcnMocmVzb3VyY2VzKSxcbiAgICAgICAgICBOZXh0VG9rZW46IG5leHRUb2tlbixcbiAgICAgICAgfSk7XG4gICAgICAgIG5leHRUb2tlbiA9IG5leHRSZWxhdGVkUmVzb3VyY2VzLk5leHRUb2tlbjtcbiAgICAgICAgcmVsYXRlZFJlc291cmNlTGlzdC5wdXNoKC4uLihuZXh0UmVsYXRlZFJlc291cmNlcy5SZWxhdGVkUmVzb3VyY2VzID8/IFtdKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmVsYXRlZFJlc291cmNlTGlzdCA9IGRlZHVwbGljYXRlUmVzb3VyY2VzKHJlbGF0ZWRSZXNvdXJjZUxpc3QpO1xuXG4gICAgLy8gcHJ1bmUgdGhlIG1hbmFnZWRieXN0YWNrIGZsYWcgb2ZmIG9mIHRoZW0gYWdhaW4uXG4gICAgcmV0dXJuIHByb2Nlc3MuZW52Lk1JR1JBVEVfSU5URUdfVEVTVFxuICAgICAgPyByZXNvdXJjZUlkZW50aWZpZXJzKHJlbGF0ZWRSZXNvdXJjZUxpc3QpXG4gICAgICA6IHJlc291cmNlSWRlbnRpZmllcnMoZXhjbHVkZU1hbmFnZWQocmVsYXRlZFJlc291cmNlTGlzdCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEtpY2tzIG9mZiBhIHNjYW4gb2YgYSBjdXN0b21lcnMgYWNjb3VudCwgcmV0dXJuaW5nIHRoZSBzY2FuIGlkLiBBIHNjYW4gY2FuIHRha2VcbiAgICogMTAgbWludXRlcyBvciBsb25nZXIgdG8gY29tcGxldGUuIEhvd2V2ZXIgdGhpcyB3aWxsIHJldHVybiBhIHNjYW4gaWQgYXMgc29vbiBhc1xuICAgKiB0aGUgc2NhbiBoYXMgYmVndW4uXG4gICAqXG4gICAqIEByZXR1cm5zIEEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgc2NhbiBpZFxuICAgKi9cbiAgYXN5bmMgc3RhcnRSZXNvdXJjZVNjYW4ocmVxdWVzdFRva2VuOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gKFxuICAgICAgYXdhaXQgdGhpcy5jZm4uc3RhcnRSZXNvdXJjZVNjYW4oe1xuICAgICAgICBDbGllbnRSZXF1ZXN0VG9rZW46IHJlcXVlc3RUb2tlbixcbiAgICAgIH0pXG4gICAgKS5SZXNvdXJjZVNjYW5JZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBtb3N0IHJlY2VudCBzY2FucyBhIGN1c3RvbWVyIGhhcyBjb21wbGV0ZWRcbiAgICpcbiAgICogQHJldHVybnMgYSBsaXN0IG9mIHJlc291cmNlIHNjYW4gc3VtbWFyaWVzXG4gICAqL1xuICBhc3luYyBsaXN0UmVzb3VyY2VTY2FucygpIHtcbiAgICByZXR1cm4gdGhpcy5jZm4ubGlzdFJlc291cmNlU2NhbnMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgYSB0b2tlbml6ZWQgbGlzdCBvZiByZXNvdXJjZXMgZnJvbSBhIHJlc291cmNlIHNjYW4uIElmIGEgdG9rZW4gaXMgcHJlc2VudCwgdGhpcyBmdW5jdGlvblxuICAgKiB3aWxsIGxvb3AgdGhyb3VnaCBhbGwgcGFnZXMgYW5kIGNvbWJpbmUgdGhlbSBpbnRvIGEgc2luZ2xlIGxpc3Qgb2YgU2Nhbm5lZFJlc291cmNlW10uXG4gICAqIEFkZGl0aW9uYWxseSB3aWxsIGFwcGx5IGFueSBmaWx0ZXJzIHByb3ZpZGVkIGJ5IHRoZSBjdXN0b21lci5cbiAgICpcbiAgICogQHBhcmFtIHNjYW5JZCAtIHNjYW4gaWQgZm9yIHRoZSB0byBsaXN0IHJlc291cmNlcyBmb3JcbiAgICogQHBhcmFtIGZpbHRlcnMgLSBhIHN0cmluZyBvZiBmaWx0ZXJzIGluIHRoZSBmb3JtYXQgb2Yga2V5MT12YWx1ZTEsa2V5Mj12YWx1ZTJcbiAgICogQHJldHVybnMgYSBjb21iaW5lZCBsaXN0IG9mIGFsbCByZXNvdXJjZXMgZnJvbSB0aGUgc2NhblxuICAgKi9cbiAgYXN5bmMgbGlzdFJlc291cmNlU2NhblJlc291cmNlcyhzY2FuSWQ6IHN0cmluZywgZmlsdGVyczogc3RyaW5nW10gPSBbXSk6IFByb21pc2U8U2Nhbm5lZFJlc291cmNlSWRlbnRpZmllcltdPiB7XG4gICAgbGV0IHJlc291cmNlTGlzdDogU2Nhbm5lZFJlc291cmNlW10gPSBbXTtcbiAgICBsZXQgcmVzb3VyY2VTY2FuSW5wdXRzOiBMaXN0UmVzb3VyY2VTY2FuUmVzb3VyY2VzQ29tbWFuZElucHV0O1xuXG4gICAgaWYgKGZpbHRlcnMubGVuZ3RoID4gMCkge1xuICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5kZWZhdWx0cy5pbmZvKCdBcHBseWluZyBmaWx0ZXJzIHRvIHJlc291cmNlIHNjYW4uJyk7XG4gICAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiBmaWx0ZXJzKSB7XG4gICAgICAgIGNvbnN0IGZpbHRlckxpc3QgPSBwYXJzZUZpbHRlcnMoZmlsdGVyKTtcbiAgICAgICAgcmVzb3VyY2VTY2FuSW5wdXRzID0ge1xuICAgICAgICAgIFJlc291cmNlU2NhbklkOiBzY2FuSWQsXG4gICAgICAgICAgUmVzb3VyY2VJZGVudGlmaWVyOiBmaWx0ZXJMaXN0W0ZpbHRlclR5cGUuUkVTT1VSQ0VfSURFTlRJRklFUl0sXG4gICAgICAgICAgUmVzb3VyY2VUeXBlUHJlZml4OiBmaWx0ZXJMaXN0W0ZpbHRlclR5cGUuUkVTT1VSQ0VfVFlQRV9QUkVGSVhdLFxuICAgICAgICAgIFRhZ0tleTogZmlsdGVyTGlzdFtGaWx0ZXJUeXBlLlRBR19LRVldLFxuICAgICAgICAgIFRhZ1ZhbHVlOiBmaWx0ZXJMaXN0W0ZpbHRlclR5cGUuVEFHX1ZBTFVFXSxcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgcmVzb3VyY2VzID0gYXdhaXQgdGhpcy5jZm4ubGlzdFJlc291cmNlU2NhblJlc291cmNlcyhyZXNvdXJjZVNjYW5JbnB1dHMpO1xuICAgICAgICByZXNvdXJjZUxpc3QgPSByZXNvdXJjZUxpc3QuY29uY2F0KHJlc291cmNlcy5SZXNvdXJjZXMgPz8gW10pO1xuICAgICAgICBsZXQgbmV4dFRva2VuID0gcmVzb3VyY2VzLk5leHRUb2tlbjtcblxuICAgICAgICAvLyBjeWNsZSB0aHJvdWdoIHRoZSBwYWdlcyBhZGRpbmcgYWxsIHJlc291cmNlcyB0byB0aGUgbGlzdCB1bnRpbCB3ZSBydW4gb3V0IG9mIHBhZ2VzXG4gICAgICAgIHdoaWxlIChuZXh0VG9rZW4pIHtcbiAgICAgICAgICByZXNvdXJjZVNjYW5JbnB1dHMuTmV4dFRva2VuID0gbmV4dFRva2VuO1xuICAgICAgICAgIGNvbnN0IG5leHRSZXNvdXJjZXMgPSBhd2FpdCB0aGlzLmNmbi5saXN0UmVzb3VyY2VTY2FuUmVzb3VyY2VzKHJlc291cmNlU2NhbklucHV0cyk7XG4gICAgICAgICAgbmV4dFRva2VuID0gbmV4dFJlc291cmNlcy5OZXh0VG9rZW47XG4gICAgICAgICAgcmVzb3VyY2VMaXN0ID0gcmVzb3VyY2VMaXN0IS5jb25jYXQobmV4dFJlc291cmNlcy5SZXNvdXJjZXMgPz8gW10pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIuZGVmYXVsdHMuaW5mbygnTm8gZmlsdGVycyBwcm92aWRlZC4gUmV0cmlldmluZyBhbGwgcmVzb3VyY2VzIGZyb20gc2Nhbi4nKTtcbiAgICAgIHJlc291cmNlU2NhbklucHV0cyA9IHtcbiAgICAgICAgUmVzb3VyY2VTY2FuSWQ6IHNjYW5JZCxcbiAgICAgIH07XG4gICAgICBjb25zdCByZXNvdXJjZXMgPSBhd2FpdCB0aGlzLmNmbi5saXN0UmVzb3VyY2VTY2FuUmVzb3VyY2VzKHJlc291cmNlU2NhbklucHV0cyk7XG4gICAgICByZXNvdXJjZUxpc3QgPSByZXNvdXJjZUxpc3QhLmNvbmNhdChyZXNvdXJjZXMuUmVzb3VyY2VzID8/IFtdKTtcbiAgICAgIGxldCBuZXh0VG9rZW4gPSByZXNvdXJjZXMuTmV4dFRva2VuO1xuXG4gICAgICAvLyBjeWNsZSB0aHJvdWdoIHRoZSBwYWdlcyBhZGRpbmcgYWxsIHJlc291cmNlcyB0byB0aGUgbGlzdCB1bnRpbCB3ZSBydW4gb3V0IG9mIHBhZ2VzXG4gICAgICB3aGlsZSAobmV4dFRva2VuKSB7XG4gICAgICAgIHJlc291cmNlU2NhbklucHV0cy5OZXh0VG9rZW4gPSBuZXh0VG9rZW47XG4gICAgICAgIGNvbnN0IG5leHRSZXNvdXJjZXMgPSBhd2FpdCB0aGlzLmNmbi5saXN0UmVzb3VyY2VTY2FuUmVzb3VyY2VzKHJlc291cmNlU2NhbklucHV0cyk7XG4gICAgICAgIG5leHRUb2tlbiA9IG5leHRSZXNvdXJjZXMuTmV4dFRva2VuO1xuICAgICAgICByZXNvdXJjZUxpc3QgPSByZXNvdXJjZUxpc3QhLmNvbmNhdChuZXh0UmVzb3VyY2VzLlJlc291cmNlcyA/PyBbXSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChyZXNvdXJjZUxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKCdOb1Jlc291cmNlc0ZvdW5kJywgYE5vIHJlc291cmNlcyBmb3VuZCB3aXRoIGZpbHRlcnMgJHtmaWx0ZXJzLmpvaW4oJyAnKX0uIFBsZWFzZSB0cnkgYWdhaW4gd2l0aCBkaWZmZXJlbnQgZmlsdGVycy5gKTtcbiAgICB9XG4gICAgcmVzb3VyY2VMaXN0ID0gZGVkdXBsaWNhdGVSZXNvdXJjZXMocmVzb3VyY2VMaXN0KTtcblxuICAgIHJldHVybiBwcm9jZXNzLmVudi5NSUdSQVRFX0lOVEVHX1RFU1RcbiAgICAgID8gcmVzb3VyY2VJZGVudGlmaWVycyhyZXNvdXJjZUxpc3QpXG4gICAgICA6IHJlc291cmNlSWRlbnRpZmllcnMoZXhjbHVkZU1hbmFnZWQocmVzb3VyY2VMaXN0KSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIGluZm9ybWF0aW9uIGFib3V0IGEgcmVzb3VyY2Ugc2Nhbi5cbiAgICpcbiAgICogQHBhcmFtIHNjYW5JZCAtIHNjYW4gaWQgZm9yIHRoZSB0byBsaXN0IHJlc291cmNlcyBmb3JcbiAgICogQHJldHVybnMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHNjYW5cbiAgICovXG4gIGFzeW5jIGRlc2NyaWJlUmVzb3VyY2VTY2FuKHNjYW5JZDogc3RyaW5nKTogUHJvbWlzZTxEZXNjcmliZVJlc291cmNlU2NhbkNvbW1hbmRPdXRwdXQ+IHtcbiAgICByZXR1cm4gdGhpcy5jZm4uZGVzY3JpYmVSZXNvdXJjZVNjYW4oe1xuICAgICAgUmVzb3VyY2VTY2FuSWQ6IHNjYW5JZCxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXNjcmliZXMgdGhlIGN1cnJlbnQgc3RhdHVzIG9mIHRoZSB0ZW1wbGF0ZSBiZWluZyBnZW5lcmF0ZWQuXG4gICAqXG4gICAqIEBwYXJhbSB0ZW1wbGF0ZUlkIC0gQSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSB0ZW1wbGF0ZSBpZFxuICAgKiBAcmV0dXJucyBEZXNjcmliZUdlbmVyYXRlZFRlbXBsYXRlT3V0cHV0IGFuIG9iamVjdCBjb250YWluaW5nIHRoZSB0ZW1wbGF0ZSBzdGF0dXMgYW5kIHJlc3VsdHNcbiAgICovXG4gIGFzeW5jIGRlc2NyaWJlR2VuZXJhdGVkVGVtcGxhdGUodGVtcGxhdGVJZDogc3RyaW5nKTogUHJvbWlzZTxEZXNjcmliZUdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZE91dHB1dD4ge1xuICAgIGNvbnN0IGdlbmVyYXRlZFRlbXBsYXRlID0gYXdhaXQgdGhpcy5jZm4uZGVzY3JpYmVHZW5lcmF0ZWRUZW1wbGF0ZSh7XG4gICAgICBHZW5lcmF0ZWRUZW1wbGF0ZU5hbWU6IHRlbXBsYXRlSWQsXG4gICAgfSk7XG5cbiAgICBpZiAoZ2VuZXJhdGVkVGVtcGxhdGUuU3RhdHVzID09IFNjYW5TdGF0dXMuRkFJTEVEKSB7XG4gICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKCdUZW1wbGF0ZUdlbmVyYXRpb25GYWlsZWQnLCBnZW5lcmF0ZWRUZW1wbGF0ZS5TdGF0dXNSZWFzb24hKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ2VuZXJhdGVkVGVtcGxhdGU7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIGEgY29tcGxldGVkIGdlbmVyYXRlZCBjbG91ZGZvcm1hdGlvbiB0ZW1wbGF0ZSBmcm9tIHRoZSB0ZW1wbGF0ZSBnZW5lcmF0b3IuXG4gICAqXG4gICAqIEBwYXJhbSB0ZW1wbGF0ZUlkIC0gQSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSB0ZW1wbGF0ZSBpZFxuICAgKiBAcGFyYW0gY2xvdWRGb3JtYXRpb24gLSBUaGUgQ2xvdWRGb3JtYXRpb24gc2RrIGNsaWVudCB0byB1c2VcbiAgICogQHJldHVybnMgRGVzY3JpYmVHZW5lcmF0ZWRUZW1wbGF0ZU91dHB1dCBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgdGVtcGxhdGUgc3RhdHVzIGFuZCBib2R5XG4gICAqL1xuICBhc3luYyBnZXRHZW5lcmF0ZWRUZW1wbGF0ZSh0ZW1wbGF0ZUlkOiBzdHJpbmcpOiBQcm9taXNlPEdldEdlbmVyYXRlZFRlbXBsYXRlQ29tbWFuZE91dHB1dD4ge1xuICAgIHJldHVybiB0aGlzLmNmbi5nZXRHZW5lcmF0ZWRUZW1wbGF0ZSh7XG4gICAgICBHZW5lcmF0ZWRUZW1wbGF0ZU5hbWU6IHRlbXBsYXRlSWQsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogS2lja3Mgb2ZmIGEgdGVtcGxhdGUgZ2VuZXJhdGlvbiBmb3IgYSBzZXQgb2YgcmVzb3VyY2VzLlxuICAgKlxuICAgKiBAcGFyYW0gc3RhY2tOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHN0YWNrXG4gICAqIEBwYXJhbSByZXNvdXJjZXMgLSBBIGxpc3Qgb2YgcmVzb3VyY2VzIHRvIGdlbmVyYXRlIHRoZSB0ZW1wbGF0ZSBmcm9tXG4gICAqIEByZXR1cm5zIENyZWF0ZUdlbmVyYXRlZFRlbXBsYXRlT3V0cHV0IGFuIG9iamVjdCBjb250YWluaW5nIHRoZSB0ZW1wbGF0ZSBhcm4gdG8gcXVlcnkgb24gbGF0ZXJcbiAgICovXG4gIGFzeW5jIGNyZWF0ZUdlbmVyYXRlZFRlbXBsYXRlKHN0YWNrTmFtZTogc3RyaW5nLCByZXNvdXJjZXM6IFJlc291cmNlRGVmaW5pdGlvbltdKSB7XG4gICAgY29uc3QgY3JlYXRlVGVtcGxhdGVPdXRwdXQgPSBhd2FpdCB0aGlzLmNmbi5jcmVhdGVHZW5lcmF0ZWRUZW1wbGF0ZSh7XG4gICAgICBSZXNvdXJjZXM6IHJlc291cmNlcyxcbiAgICAgIEdlbmVyYXRlZFRlbXBsYXRlTmFtZTogc3RhY2tOYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKGNyZWF0ZVRlbXBsYXRlT3V0cHV0LkdlbmVyYXRlZFRlbXBsYXRlSWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcignTWlzc2luZ1RlbXBsYXRlQXJuJywgJ0NyZWF0ZUdlbmVyYXRlZFRlbXBsYXRlIGZhaWxlZCB0byByZXR1cm4gYW4gQXJuLicpO1xuICAgIH1cbiAgICByZXR1cm4gY3JlYXRlVGVtcGxhdGVPdXRwdXQ7XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyBhIGdlbmVyYXRlZCB0ZW1wbGF0ZSBmcm9tIHRoZSB0ZW1wbGF0ZSBnZW5lcmF0b3IuXG4gICAqXG4gICAqIEBwYXJhbSB0ZW1wbGF0ZUFybiAtIFRoZSBhcm4gb2YgdGhlIHRlbXBsYXRlIHRvIGRlbGV0ZVxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSB0ZW1wbGF0ZSBoYXMgYmVlbiBkZWxldGVkXG4gICAqL1xuICBhc3luYyBkZWxldGVHZW5lcmF0ZWRUZW1wbGF0ZSh0ZW1wbGF0ZUFybjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5jZm4uZGVsZXRlR2VuZXJhdGVkVGVtcGxhdGUoe1xuICAgICAgR2VuZXJhdGVkVGVtcGxhdGVOYW1lOiB0ZW1wbGF0ZUFybixcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSBwb3NzaWJsZSB3YXlzIHRvIGNob29zZSBhIHNjYW4gdG8gZ2VuZXJhdGUgYSBDREsgYXBwbGljYXRpb24gZnJvbVxuICovXG5leHBvcnQgZW51bSBGcm9tU2NhbiB7XG4gIC8qKlxuICAgKiBJbml0aWF0ZSBhIG5ldyByZXNvdXJjZSBzY2FuIHRvIGJ1aWxkIHRoZSBDREsgYXBwbGljYXRpb24gZnJvbS5cbiAgICovXG4gIE5FVyxcblxuICAvKipcbiAgICogVXNlIHRoZSBsYXN0IHN1Y2Nlc3NmdWwgc2NhbiB0byBidWlsZCB0aGUgQ0RLIGFwcGxpY2F0aW9uIGZyb20uIFdpbGwgZmFpbCBpZiBubyBzY2FuIGlzIGZvdW5kLlxuICAgKi9cbiAgTU9TVF9SRUNFTlQsXG5cbiAgLyoqXG4gICAqIFN0YXJ0cyBhIHNjYW4gaWYgbm9uZSBleGlzdHMsIG90aGVyd2lzZSB1c2VzIHRoZSBtb3N0IHJlY2VudCBzdWNjZXNzZnVsIHNjYW4gdG8gYnVpbGQgdGhlIENESyBhcHBsaWNhdGlvbiBmcm9tLlxuICAgKi9cbiAgREVGQVVMVCxcbn1cblxuLyoqXG4gKiBJbnRlcmZhY2UgZm9yIHRoZSBvcHRpb25zIG9iamVjdCBwYXNzZWQgdG8gdGhlIGdlbmVyYXRlVGVtcGxhdGUgZnVuY3Rpb25cbiAqXG4gKiBAcGFyYW0gc3RhY2tOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHN0YWNrXG4gKiBAcGFyYW0gZmlsdGVycyAtIEEgbGlzdCBvZiBmaWx0ZXJzIHRvIGFwcGx5IHRvIHRoZSBzY2FuXG4gKiBAcGFyYW0gZnJvbVNjYW4gLSBBbiBlbnVtIHZhbHVlIHNwZWNpZnlpbmcgd2hldGhlciBhIG5ldyBzY2FuIHNob3VsZCBiZSBzdGFydGVkIG9yIHRoZSBtb3N0IHJlY2VudCBzdWNjZXNzZnVsIHNjYW4gc2hvdWxkIGJlIHVzZWRcbiAqIEBwYXJhbSBzZGtQcm92aWRlciAtIFRoZSBzZGsgcHJvdmlkZXIgZm9yIG1ha2luZyBDbG91ZEZvcm1hdGlvbiBjYWxsc1xuICogQHBhcmFtIGVudmlyb25tZW50IC0gVGhlIGFjY291bnQgYW5kIHJlZ2lvbiB3aGVyZSB0aGUgc3RhY2sgaXMgZGVwbG95ZWRcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZW5lcmF0ZVRlbXBsYXRlT3B0aW9ucyB7XG4gIHN0YWNrTmFtZTogc3RyaW5nO1xuICBmaWx0ZXJzPzogc3RyaW5nW107XG4gIGZyb21TY2FuPzogRnJvbVNjYW47XG4gIHNka1Byb3ZpZGVyOiBTZGtQcm92aWRlcjtcbiAgZW52aXJvbm1lbnQ6IEVudmlyb25tZW50O1xuICBpb0hlbHBlcjogSW9IZWxwZXI7XG59XG5cbi8qKlxuICogSW50ZXJmYWNlIGZvciB0aGUgb3V0cHV0IG9mIHRoZSBnZW5lcmF0ZVRlbXBsYXRlIGZ1bmN0aW9uXG4gKlxuICogQHBhcmFtIG1pZ3JhdGVKc29uIC0gVGhlIGdlbmVyYXRlZCBNaWdyYXRlLmpzb24gZmlsZVxuICogQHBhcmFtIHJlc291cmNlcyAtIFRoZSBnZW5lcmF0ZWQgdGVtcGxhdGVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZW5lcmF0ZVRlbXBsYXRlT3V0cHV0IHtcbiAgbWlncmF0ZUpzb246IE1pZ3JhdGVKc29uRm9ybWF0O1xuICByZXNvdXJjZXM/OiBSZXNvdXJjZURldGFpbFtdO1xuICB0ZW1wbGF0ZUlkPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEludGVyZmFjZSBkZWZpbmluZyB0aGUgZm9ybWF0IG9mIHRoZSBnZW5lcmF0ZWQgTWlncmF0ZS5qc29uIGZpbGVcbiAqXG4gKiBAcGFyYW0gVGVtcGxhdGVCb2R5IC0gVGhlIGdlbmVyYXRlZCB0ZW1wbGF0ZVxuICogQHBhcmFtIFNvdXJjZSAtIFRoZSBzb3VyY2Ugb2YgdGhlIHRlbXBsYXRlXG4gKiBAcGFyYW0gUmVzb3VyY2VzIC0gQSBsaXN0IG9mIHJlc291cmNlcyB0aGF0IHdlcmUgdXNlZCB0byBnZW5lcmF0ZSB0aGUgdGVtcGxhdGVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBNaWdyYXRlSnNvbkZvcm1hdCB7XG4gIHRlbXBsYXRlQm9keTogc3RyaW5nO1xuICBzb3VyY2U6IHN0cmluZztcbiAgcmVzb3VyY2VzPzogR2VuZXJhdGVkUmVzb3VyY2VJbXBvcnRJZGVudGlmaWVyW107XG59XG5cbi8qKlxuICogSW50ZXJmYWNlIHJlcHJlc2VudGluZyB0aGUgZm9ybWF0IG9mIGEgcmVzb3VyY2UgaWRlbnRpZmllciByZXF1aXJlZCBmb3IgcmVzb3VyY2UgaW1wb3J0XG4gKlxuICogQHBhcmFtIFJlc291cmNlVHlwZSAtIFRoZSB0eXBlIG9mIHJlc291cmNlXG4gKiBAcGFyYW0gTG9naWNhbFJlc291cmNlSWQgLSBUaGUgbG9naWNhbCBpZCBvZiB0aGUgcmVzb3VyY2VcbiAqIEBwYXJhbSBSZXNvdXJjZUlkZW50aWZpZXIgLSBUaGUgcmVzb3VyY2UgaWRlbnRpZmllciBvZiB0aGUgcmVzb3VyY2VcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZW5lcmF0ZWRSZXNvdXJjZUltcG9ydElkZW50aWZpZXIge1xuICAvLyBjZGsgZGVwbG95IGV4cGVjdHMgdGhlIG1pZ3JhdGUuanNvbiByZXNvdXJjZSBpZGVudGlmaWVycyB0byBiZSBQYXNjYWxDYXNlLCBub3QgY2FtZWxDYXNlLlxuICBSZXNvdXJjZVR5cGU6IHN0cmluZztcbiAgTG9naWNhbFJlc291cmNlSWQ6IHN0cmluZztcbiAgUmVzb3VyY2VJZGVudGlmaWVyOiBSZXNvdXJjZUlkZW50aWZpZXJTdW1tYXJ5O1xufVxuIl19