@gnwebsoft/ui 4.0.3 → 4.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (335) hide show
  1. package/dist/{chunk-DKD73ADK.cjs → chunk-2QTXS736.cjs} +28 -77
  2. package/dist/{chunk-DS524L7W.cjs → chunk-3RZ4JNO3.cjs} +5 -5
  3. package/dist/chunk-HKO2FXDM.js +2232 -0
  4. package/dist/{chunk-M3NVOZ7L.cjs → chunk-IKHMJW5A.cjs} +1 -1
  5. package/dist/chunk-LUW7V5GI.cjs +1 -1
  6. package/dist/chunk-MVPLBJRK.cjs +1 -1
  7. package/dist/chunk-NMJ5V7FQ.js +2512 -0
  8. package/dist/chunk-XN3KVY4J.js +467 -0
  9. package/dist/chunk-XTPFOURJ.cjs +72 -0
  10. package/dist/chunk-Y3QTSDLJ.cjs +1 -1
  11. package/dist/core/api/ApiClient.d.ts +329 -0
  12. package/dist/core/api/ApiClient.d.ts.map +1 -0
  13. package/dist/core/api/CorrelationIdGenerator.d.ts +52 -0
  14. package/dist/core/api/CorrelationIdGenerator.d.ts.map +1 -0
  15. package/dist/core/api/Errors/ErrorNormalizer.d.ts +106 -0
  16. package/dist/core/api/Errors/ErrorNormalizer.d.ts.map +1 -0
  17. package/dist/core/api/Interceptors/InterceptorManager.d.ts +236 -0
  18. package/dist/core/api/Interceptors/InterceptorManager.d.ts.map +1 -0
  19. package/dist/core/api/Models/FilterModel.d.ts +22 -0
  20. package/dist/core/api/Models/FilterModel.d.ts.map +1 -0
  21. package/dist/core/api/Models/QueryParams.d.ts +13 -0
  22. package/dist/core/api/Models/QueryParams.d.ts.map +1 -0
  23. package/dist/core/api/Models/index.d.ts +3 -0
  24. package/dist/core/api/Models/index.d.ts.map +1 -0
  25. package/dist/core/api/RequestManager.d.ts +142 -0
  26. package/dist/core/api/RequestManager.d.ts.map +1 -0
  27. package/dist/core/api/Retry/RetryHandler.d.ts +100 -0
  28. package/dist/core/api/Retry/RetryHandler.d.ts.map +1 -0
  29. package/dist/core/api/Signals/SignalManager.d.ts +153 -0
  30. package/dist/core/api/Signals/SignalManager.d.ts.map +1 -0
  31. package/dist/core/api/Utils/ResponseParser.d.ts +105 -0
  32. package/dist/core/api/Utils/ResponseParser.d.ts.map +1 -0
  33. package/dist/core/api/Utils/UrlBuilder.d.ts +111 -0
  34. package/dist/core/api/Utils/UrlBuilder.d.ts.map +1 -0
  35. package/dist/core/api/createApiClient.d.ts +243 -0
  36. package/dist/core/api/createApiClient.d.ts.map +1 -0
  37. package/dist/core/api/index.d.ts +7 -0
  38. package/dist/core/api/index.d.ts.map +1 -0
  39. package/dist/core/api/types/ApiError.d.ts +17 -0
  40. package/dist/core/api/types/ApiError.d.ts.map +1 -0
  41. package/dist/core/api/types/ApiResponse.d.ts +76 -0
  42. package/dist/core/api/types/ApiResponse.d.ts.map +1 -0
  43. package/dist/core/api/types/CancelToken.d.ts +15 -0
  44. package/dist/core/api/types/CancelToken.d.ts.map +1 -0
  45. package/dist/core/api/types/ErrorInterceptor.d.ts +3 -0
  46. package/dist/core/api/types/ErrorInterceptor.d.ts.map +1 -0
  47. package/dist/core/api/types/ErrorResponseData.d.ts +68 -0
  48. package/dist/core/api/types/ErrorResponseData.d.ts.map +1 -0
  49. package/dist/core/api/types/RequestConfig.d.ts +21 -0
  50. package/dist/core/api/types/RequestConfig.d.ts.map +1 -0
  51. package/dist/core/api/types/RequestInterceptor.d.ts +3 -0
  52. package/dist/core/api/types/RequestInterceptor.d.ts.map +1 -0
  53. package/dist/core/api/types/ResponseInterceptor.d.ts +3 -0
  54. package/dist/core/api/types/ResponseInterceptor.d.ts.map +1 -0
  55. package/dist/core/api/types/ValidationErrors.d.ts +7 -0
  56. package/dist/core/api/types/ValidationErrors.d.ts.map +1 -0
  57. package/dist/core/api/types/index.d.ts +10 -0
  58. package/dist/core/api/types/index.d.ts.map +1 -0
  59. package/dist/core/api/useValidationErrors.d.ts +11 -0
  60. package/dist/core/api/useValidationErrors.d.ts.map +1 -0
  61. package/dist/core/components/AuthorizedView/AuthorizedView.d.ts +7 -0
  62. package/dist/core/components/AuthorizedView/AuthorizedView.d.ts.map +1 -0
  63. package/dist/core/components/AuthorizedView/index.d.ts +2 -0
  64. package/dist/core/components/AuthorizedView/index.d.ts.map +1 -0
  65. package/dist/core/components/CancelButton/CancelButton.d.ts +4 -0
  66. package/dist/core/components/CancelButton/CancelButton.d.ts.map +1 -0
  67. package/dist/core/components/CancelButton/index.d.ts +2 -0
  68. package/dist/core/components/CancelButton/index.d.ts.map +1 -0
  69. package/dist/core/components/ClearButton/ClearButton.d.ts +63 -0
  70. package/dist/core/components/ClearButton/ClearButton.d.ts.map +1 -0
  71. package/dist/core/components/ClearButton/index.d.ts +2 -0
  72. package/dist/core/components/ClearButton/index.d.ts.map +1 -0
  73. package/dist/core/components/Containers/SimpleContainer.d.ts +10 -0
  74. package/dist/core/components/Containers/SimpleContainer.d.ts.map +1 -0
  75. package/dist/core/components/Containers/index.d.ts +2 -0
  76. package/dist/core/components/Containers/index.d.ts.map +1 -0
  77. package/dist/core/components/FilterButton/FilterButton.d.ts +86 -0
  78. package/dist/core/components/FilterButton/FilterButton.d.ts.map +1 -0
  79. package/dist/core/components/FilterButton/index.d.ts +2 -0
  80. package/dist/core/components/FilterButton/index.d.ts.map +1 -0
  81. package/dist/core/components/FilterDisplay/FilterChip.d.ts +9 -0
  82. package/dist/core/components/FilterDisplay/FilterChip.d.ts.map +1 -0
  83. package/dist/core/components/FilterDisplay/FilterDisplay.d.ts +10 -0
  84. package/dist/core/components/FilterDisplay/FilterDisplay.d.ts.map +1 -0
  85. package/dist/core/components/FilterDisplay/index.d.ts +3 -0
  86. package/dist/core/components/FilterDisplay/index.d.ts.map +1 -0
  87. package/dist/core/components/FilterWrapper/FilterWrapper.d.ts +99 -0
  88. package/dist/core/components/FilterWrapper/FilterWrapper.d.ts.map +1 -0
  89. package/dist/core/components/FilterWrapper/index.d.ts +2 -0
  90. package/dist/core/components/FilterWrapper/index.d.ts.map +1 -0
  91. package/dist/core/components/Footer/Footer.d.ts +3 -0
  92. package/dist/core/components/Footer/Footer.d.ts.map +1 -0
  93. package/dist/core/components/Footer/index.d.ts +2 -0
  94. package/dist/core/components/Footer/index.d.ts.map +1 -0
  95. package/dist/core/components/LabelText/LabelText.d.ts +103 -0
  96. package/dist/core/components/LabelText/LabelText.d.ts.map +1 -0
  97. package/dist/core/components/LabelText/index.d.ts +2 -0
  98. package/dist/core/components/LabelText/index.d.ts.map +1 -0
  99. package/dist/core/components/RenderIf/RenderIf.d.ts +7 -0
  100. package/dist/core/components/RenderIf/RenderIf.d.ts.map +1 -0
  101. package/dist/core/components/RenderIf/index.d.ts +2 -0
  102. package/dist/core/components/RenderIf/index.d.ts.map +1 -0
  103. package/dist/core/components/SectionBox/SectionBox.d.ts +15 -0
  104. package/dist/core/components/SectionBox/SectionBox.d.ts.map +1 -0
  105. package/dist/core/components/SectionBox/index.d.ts +2 -0
  106. package/dist/core/components/SectionBox/index.d.ts.map +1 -0
  107. package/dist/core/components/SimpleTabs/SimpleTabs.d.ts +17 -0
  108. package/dist/core/components/SimpleTabs/SimpleTabs.d.ts.map +1 -0
  109. package/dist/core/components/SimpleTabs/index.d.ts +2 -0
  110. package/dist/core/components/SimpleTabs/index.d.ts.map +1 -0
  111. package/dist/core/components/SubmitButton/SubmitButton.d.ts +6 -0
  112. package/dist/core/components/SubmitButton/SubmitButton.d.ts.map +1 -0
  113. package/dist/core/components/SubmitButton/index.d.ts +2 -0
  114. package/dist/core/components/SubmitButton/index.d.ts.map +1 -0
  115. package/dist/core/components/WithRef/WithRef.d.ts +14 -0
  116. package/dist/core/components/WithRef/WithRef.d.ts.map +1 -0
  117. package/dist/core/components/WithRef/index.d.ts +2 -0
  118. package/dist/core/components/WithRef/index.d.ts.map +1 -0
  119. package/dist/core/components/index.d.ts +15 -0
  120. package/dist/core/components/index.d.ts.map +1 -0
  121. package/dist/core/config.d.ts +24 -0
  122. package/dist/core/config.d.ts.map +1 -0
  123. package/dist/core/hooks/index.d.ts +3 -0
  124. package/dist/core/hooks/index.d.ts.map +1 -0
  125. package/dist/core/hooks/makeQuery.d.ts +12 -0
  126. package/dist/core/hooks/makeQuery.d.ts.map +1 -0
  127. package/dist/core/hooks/useApiClient.d.ts +3 -0
  128. package/dist/core/hooks/useApiClient.d.ts.map +1 -0
  129. package/dist/core/hooks/useFormErrorHandler.d.ts +35 -0
  130. package/dist/core/hooks/useFormErrorHandler.d.ts.map +1 -0
  131. package/dist/core/hooks/useListView.d.ts +20 -0
  132. package/dist/core/hooks/useListView.d.ts.map +1 -0
  133. package/dist/core/index.cjs +3 -3
  134. package/dist/core/index.d.ts +9 -0
  135. package/dist/core/index.d.ts.map +1 -0
  136. package/dist/core/index.js +1 -1
  137. package/dist/core/models.d.ts +5 -0
  138. package/dist/core/models.d.ts.map +1 -0
  139. package/dist/core/types/FilterLabel.d.ts +6 -0
  140. package/dist/core/types/FilterLabel.d.ts.map +1 -0
  141. package/dist/core/types/ListModels.d.ts +18 -0
  142. package/dist/core/types/ListModels.d.ts.map +1 -0
  143. package/dist/core/types/OptionsRequest.d.ts +4 -0
  144. package/dist/core/types/OptionsRequest.d.ts.map +1 -0
  145. package/dist/core/types/index.d.ts +4 -0
  146. package/dist/core/types/index.d.ts.map +1 -0
  147. package/dist/core/utils/CacheUtility/index.d.ts +15 -0
  148. package/dist/core/utils/CacheUtility/index.d.ts.map +1 -0
  149. package/dist/core/utils/calculateFilterCount.d.ts +2 -0
  150. package/dist/core/utils/calculateFilterCount.d.ts.map +1 -0
  151. package/dist/core/utils/format-time.d.ts +79 -0
  152. package/dist/core/utils/format-time.d.ts.map +1 -0
  153. package/dist/core/utils/getEmptyObject.d.ts +7 -0
  154. package/dist/core/utils/getEmptyObject.d.ts.map +1 -0
  155. package/dist/core/utils/index.d.ts +7 -0
  156. package/dist/core/utils/index.d.ts.map +1 -0
  157. package/dist/core/utils/useStableRowCount.d.ts +9 -0
  158. package/dist/core/utils/useStableRowCount.d.ts.map +1 -0
  159. package/dist/core/utils/watch/core.d.ts +22 -0
  160. package/dist/core/utils/watch/core.d.ts.map +1 -0
  161. package/dist/core/utils/watch/index.d.ts +49 -0
  162. package/dist/core/utils/watch/index.d.ts.map +1 -0
  163. package/dist/core/utils/watch/utilities.d.ts +34 -0
  164. package/dist/core/utils/watch/utilities.d.ts.map +1 -0
  165. package/dist/hooks/index.cjs +1 -1
  166. package/dist/hooks/index.d.ts +3 -0
  167. package/dist/hooks/index.d.ts.map +1 -0
  168. package/dist/hooks/useTransform/enhanced.d.ts +133 -0
  169. package/dist/hooks/useTransform/enhanced.d.ts.map +1 -0
  170. package/dist/hooks/useTransform/index.d.ts +93 -0
  171. package/dist/hooks/useTransform/index.d.ts.map +1 -0
  172. package/dist/index.cjs +6 -24
  173. package/dist/index.d.ts +6 -0
  174. package/dist/index.d.ts.map +1 -0
  175. package/dist/index.js +4 -22
  176. package/dist/types/AsyncSelectPayload.d.ts +9 -0
  177. package/dist/types/AsyncSelectPayload.d.ts.map +1 -0
  178. package/dist/types/OperationResponse.d.ts +5 -0
  179. package/dist/types/OperationResponse.d.ts.map +1 -0
  180. package/dist/types/OptionItem.d.ts +75 -0
  181. package/dist/types/OptionItem.d.ts.map +1 -0
  182. package/dist/types/api.d.ts +127 -0
  183. package/dist/types/api.d.ts.map +1 -0
  184. package/dist/types/events.d.ts +74 -0
  185. package/dist/types/events.d.ts.map +1 -0
  186. package/dist/types/index.cjs +3 -3
  187. package/dist/types/index.d.ts +17 -0
  188. package/dist/types/index.d.ts.map +1 -0
  189. package/dist/types/index.js +1 -1
  190. package/dist/types/utilities.d.ts +458 -0
  191. package/dist/types/utilities.d.ts.map +1 -0
  192. package/dist/utils/api.d.ts +14 -0
  193. package/dist/utils/api.d.ts.map +1 -0
  194. package/dist/utils/api2.d.ts +14 -0
  195. package/dist/utils/api2.d.ts.map +1 -0
  196. package/dist/utils/flattenObjectKeys.d.ts +63 -0
  197. package/dist/utils/flattenObjectKeys.d.ts.map +1 -0
  198. package/dist/utils/getTimezone.d.ts +4 -0
  199. package/dist/utils/getTimezone.d.ts.map +1 -0
  200. package/dist/utils/handleServerErrors.d.ts +70 -0
  201. package/dist/utils/handleServerErrors.d.ts.map +1 -0
  202. package/dist/utils/index.cjs +3 -3
  203. package/dist/utils/index.d.ts +11 -0
  204. package/dist/utils/index.d.ts.map +1 -0
  205. package/dist/utils/index.js +1 -1
  206. package/dist/utils/propertyExists.d.ts +35 -0
  207. package/dist/utils/propertyExists.d.ts.map +1 -0
  208. package/dist/utils/readValueAsDate.d.ts +4 -0
  209. package/dist/utils/readValueAsDate.d.ts.map +1 -0
  210. package/dist/utils/removeLeadingTrailingSlashes.d.ts +2 -0
  211. package/dist/utils/removeLeadingTrailingSlashes.d.ts.map +1 -0
  212. package/dist/utils/schemaTools.d.ts +82 -0
  213. package/dist/utils/schemaTools.d.ts.map +1 -0
  214. package/dist/utils/typeGuards.d.ts +316 -0
  215. package/dist/utils/typeGuards.d.ts.map +1 -0
  216. package/dist/utils/watch/core.d.ts +22 -0
  217. package/dist/utils/watch/core.d.ts.map +1 -0
  218. package/dist/utils/watch/index.d.ts +49 -0
  219. package/dist/utils/watch/index.d.ts.map +1 -0
  220. package/dist/utils/watch/utilities.d.ts +34 -0
  221. package/dist/utils/watch/utilities.d.ts.map +1 -0
  222. package/dist/wrappers/AsyncMultiSelect/AsyncMultiSelect.d.ts +9 -0
  223. package/dist/wrappers/AsyncMultiSelect/AsyncMultiSelect.d.ts.map +1 -0
  224. package/dist/wrappers/AsyncMultiSelect/index.d.ts +3 -0
  225. package/dist/wrappers/AsyncMultiSelect/index.d.ts.map +1 -0
  226. package/dist/wrappers/AsyncMultiSelect/types.d.ts +19 -0
  227. package/dist/wrappers/AsyncMultiSelect/types.d.ts.map +1 -0
  228. package/dist/wrappers/AsyncMultiSelect2/AsyncMultiSelect2.d.ts +8 -0
  229. package/dist/wrappers/AsyncMultiSelect2/AsyncMultiSelect2.d.ts.map +1 -0
  230. package/dist/wrappers/AsyncMultiSelect2/index.d.ts +3 -0
  231. package/dist/wrappers/AsyncMultiSelect2/index.d.ts.map +1 -0
  232. package/dist/wrappers/AsyncMultiSelect2/types.d.ts +29 -0
  233. package/dist/wrappers/AsyncMultiSelect2/types.d.ts.map +1 -0
  234. package/dist/wrappers/AsyncSelect/index.d.ts +9 -0
  235. package/dist/wrappers/AsyncSelect/index.d.ts.map +1 -0
  236. package/dist/wrappers/AsyncSelect/types.d.ts +19 -0
  237. package/dist/wrappers/AsyncSelect/types.d.ts.map +1 -0
  238. package/dist/wrappers/Button.d.ts +49 -0
  239. package/dist/wrappers/Button.d.ts.map +1 -0
  240. package/dist/wrappers/CheckboxElement/CheckboxElement.d.ts +102 -0
  241. package/dist/wrappers/CheckboxElement/CheckboxElement.d.ts.map +1 -0
  242. package/dist/wrappers/CheckboxElement/index.d.ts +3 -0
  243. package/dist/wrappers/CheckboxElement/index.d.ts.map +1 -0
  244. package/dist/wrappers/CheckboxElement/types.d.ts +76 -0
  245. package/dist/wrappers/CheckboxElement/types.d.ts.map +1 -0
  246. package/dist/wrappers/CheckboxGroup/CheckboxGroup.d.ts +96 -0
  247. package/dist/wrappers/CheckboxGroup/CheckboxGroup.d.ts.map +1 -0
  248. package/dist/wrappers/CheckboxGroup/EnhancedCheckboxGroup.d.ts +49 -0
  249. package/dist/wrappers/CheckboxGroup/EnhancedCheckboxGroup.d.ts.map +1 -0
  250. package/dist/wrappers/CheckboxGroup/enhanced-types.d.ts +171 -0
  251. package/dist/wrappers/CheckboxGroup/enhanced-types.d.ts.map +1 -0
  252. package/dist/wrappers/CheckboxGroup/index.d.ts +3 -0
  253. package/dist/wrappers/CheckboxGroup/index.d.ts.map +1 -0
  254. package/dist/wrappers/CheckboxGroup/types.d.ts +106 -0
  255. package/dist/wrappers/CheckboxGroup/types.d.ts.map +1 -0
  256. package/dist/wrappers/DatePickerElement/DatePickerElement.d.ts +131 -0
  257. package/dist/wrappers/DatePickerElement/DatePickerElement.d.ts.map +1 -0
  258. package/dist/wrappers/DatePickerElement/DatePickerElementCore.d.ts +57 -0
  259. package/dist/wrappers/DatePickerElement/DatePickerElementCore.d.ts.map +1 -0
  260. package/dist/wrappers/DatePickerElement/hooks/index.d.ts +24 -0
  261. package/dist/wrappers/DatePickerElement/hooks/index.d.ts.map +1 -0
  262. package/dist/wrappers/DatePickerElement/hooks/useDatePickerStyles.d.ts +63 -0
  263. package/dist/wrappers/DatePickerElement/hooks/useDatePickerStyles.d.ts.map +1 -0
  264. package/dist/wrappers/DatePickerElement/hooks/useDatePickerValidation.d.ts +79 -0
  265. package/dist/wrappers/DatePickerElement/hooks/useDatePickerValidation.d.ts.map +1 -0
  266. package/dist/wrappers/DatePickerElement/hooks/useDatePickerValue.d.ts +73 -0
  267. package/dist/wrappers/DatePickerElement/hooks/useDatePickerValue.d.ts.map +1 -0
  268. package/dist/wrappers/DatePickerElement/index.d.ts +47 -0
  269. package/dist/wrappers/DatePickerElement/index.d.ts.map +1 -0
  270. package/dist/wrappers/DatePickerElement/types.d.ts +183 -0
  271. package/dist/wrappers/DatePickerElement/types.d.ts.map +1 -0
  272. package/dist/wrappers/DatePickerElement/utils.d.ts +89 -0
  273. package/dist/wrappers/DatePickerElement/utils.d.ts.map +1 -0
  274. package/dist/wrappers/DateTimePickerElement/index.d.ts +1 -0
  275. package/dist/wrappers/DateTimePickerElement/index.d.ts.map +1 -0
  276. package/dist/wrappers/DateTimePickerElement/types.d.ts +1 -0
  277. package/dist/wrappers/DateTimePickerElement/types.d.ts.map +1 -0
  278. package/dist/wrappers/Field/index.d.ts +42 -0
  279. package/dist/wrappers/Field/index.d.ts.map +1 -0
  280. package/dist/wrappers/NumberFieldElement/NumberFieldElement.d.ts +176 -0
  281. package/dist/wrappers/NumberFieldElement/NumberFieldElement.d.ts.map +1 -0
  282. package/dist/wrappers/NumberFieldElement/index.d.ts +3 -0
  283. package/dist/wrappers/NumberFieldElement/index.d.ts.map +1 -0
  284. package/dist/wrappers/OTPInputElement/HelperText.d.ts +8 -0
  285. package/dist/wrappers/OTPInputElement/HelperText.d.ts.map +1 -0
  286. package/dist/wrappers/OTPInputElement/OTPInputElement.d.ts +32 -0
  287. package/dist/wrappers/OTPInputElement/OTPInputElement.d.ts.map +1 -0
  288. package/dist/wrappers/OTPInputElement/index.d.ts +3 -0
  289. package/dist/wrappers/OTPInputElement/index.d.ts.map +1 -0
  290. package/dist/wrappers/PasswordElement/PasswordElement.d.ts +104 -0
  291. package/dist/wrappers/PasswordElement/PasswordElement.d.ts.map +1 -0
  292. package/dist/wrappers/PasswordElement/index.d.ts +2 -0
  293. package/dist/wrappers/PasswordElement/index.d.ts.map +1 -0
  294. package/dist/wrappers/RadioButtonGroup/RadioButtonGroup.d.ts +38 -0
  295. package/dist/wrappers/RadioButtonGroup/RadioButtonGroup.d.ts.map +1 -0
  296. package/dist/wrappers/RadioButtonGroup/index.d.ts +2 -0
  297. package/dist/wrappers/RadioButtonGroup/index.d.ts.map +1 -0
  298. package/dist/wrappers/SelectCascadeElement/SelectCascadeElement.d.ts +22 -0
  299. package/dist/wrappers/SelectCascadeElement/SelectCascadeElement.d.ts.map +1 -0
  300. package/dist/wrappers/SelectCascadeElement/index.d.ts +2 -0
  301. package/dist/wrappers/SelectCascadeElement/index.d.ts.map +1 -0
  302. package/dist/wrappers/SelectElement/SelectElement.d.ts +152 -0
  303. package/dist/wrappers/SelectElement/SelectElement.d.ts.map +1 -0
  304. package/dist/wrappers/SelectElement/index.d.ts +2 -0
  305. package/dist/wrappers/SelectElement/index.d.ts.map +1 -0
  306. package/dist/wrappers/SelectMultiElement/SelectMultiElement.d.ts +21 -0
  307. package/dist/wrappers/SelectMultiElement/SelectMultiElement.d.ts.map +1 -0
  308. package/dist/wrappers/SelectMultiElement/index.d.ts +2 -0
  309. package/dist/wrappers/SelectMultiElement/index.d.ts.map +1 -0
  310. package/dist/wrappers/TextFieldElement/TextFieldElement.d.ts +179 -0
  311. package/dist/wrappers/TextFieldElement/TextFieldElement.d.ts.map +1 -0
  312. package/dist/wrappers/TextFieldElement/index.d.ts +3 -0
  313. package/dist/wrappers/TextFieldElement/index.d.ts.map +1 -0
  314. package/dist/wrappers/TimePickerElement/TimePickerElement.d.ts +30 -0
  315. package/dist/wrappers/TimePickerElement/TimePickerElement.d.ts.map +1 -0
  316. package/dist/wrappers/TimePickerElement/index.d.ts +2 -0
  317. package/dist/wrappers/TimePickerElement/index.d.ts.map +1 -0
  318. package/dist/wrappers/index.cjs +3 -4
  319. package/dist/wrappers/index.d.ts +14 -0
  320. package/dist/wrappers/index.d.ts.map +1 -0
  321. package/dist/wrappers/index.js +1 -2
  322. package/dist/wrappers/types/common.d.ts +87 -0
  323. package/dist/wrappers/types/common.d.ts.map +1 -0
  324. package/dist/wrappers/types/index.d.ts +8 -0
  325. package/dist/wrappers/types/index.d.ts.map +1 -0
  326. package/package.json +4 -8
  327. package/dist/chunk-BXWPG6VW.js +0 -108
  328. package/dist/chunk-EOUSOGZ6.js +0 -2281
  329. package/dist/chunk-EYXPJMEF.cjs +0 -108
  330. package/dist/chunk-GHW77WIM.cjs +0 -72
  331. package/dist/chunk-PUQIPRL2.js +0 -467
  332. package/dist/chunk-YAYXHYKC.js +0 -2512
  333. package/dist/i18n/index.cjs +0 -21
  334. package/dist/i18n/index.js +0 -21
  335. /package/dist/{chunk-MULSVYFT.js → chunk-6GKAC3KH.js} +0 -0
@@ -1,2512 +0,0 @@
1
- // src/core/api/CorrelationIdGenerator.ts
2
- function generateUUID() {
3
- if (typeof crypto !== "undefined" && crypto.randomUUID) {
4
- return crypto.randomUUID();
5
- }
6
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
7
- const r = Math.random() * 16 | 0;
8
- const v = c === "x" ? r : r & 3 | 8;
9
- return v.toString(16);
10
- });
11
- }
12
- function generateCorrelationId(prefix) {
13
- const uuid = generateUUID();
14
- return prefix ? `${prefix}-${uuid}` : uuid;
15
- }
16
-
17
- // src/core/api/Errors/ErrorNormalizer.ts
18
- var ErrorNormalizer = class {
19
- /**
20
- * Maps an HTTP status code to a standardized error type category.
21
- *
22
- * This categorization helps consumers handle different error classes appropriately:
23
- * - `validation_error` (400): Client sent invalid data
24
- * - `client_error` (401-499): Client-side issues (auth, permissions, not found, etc.)
25
- * - `server_error` (500-599): Server-side failures
26
- * - `unknown_error`: Unrecognized status codes
27
- *
28
- * @param status - HTTP status code from the response
29
- * @returns The error type category as a string
30
- *
31
- * @example
32
- * ```typescript
33
- * normalizer.getErrorType(400); // => 'validation_error'
34
- * normalizer.getErrorType(404); // => 'client_error'
35
- * normalizer.getErrorType(500); // => 'server_error'
36
- * normalizer.getErrorType(0); // => 'unknown_error'
37
- * ```
38
- */
39
- getErrorType(status) {
40
- if (status >= 400 && status < 500) {
41
- return status === 400 ? "validation_error" : "client_error";
42
- } else if (status >= 500) {
43
- return "server_error";
44
- }
45
- return "unknown_error";
46
- }
47
- /**
48
- * Maps an HTTP status code to a human-readable error title.
49
- *
50
- * Provides user-friendly error messages for common HTTP status codes.
51
- * Falls back to a generic "HTTP Error {status}" format for unmapped codes.
52
- *
53
- * @param status - HTTP status code from the response
54
- * @returns A human-readable error title
55
- *
56
- * @example
57
- * ```typescript
58
- * normalizer.getErrorTitle(404); // => 'Not Found'
59
- * normalizer.getErrorTitle(500); // => 'Internal Server Error'
60
- * normalizer.getErrorTitle(999); // => 'HTTP Error 999'
61
- * ```
62
- */
63
- getErrorTitle(status) {
64
- const titles = {
65
- 400: "Bad Request",
66
- 401: "Unauthorized",
67
- 403: "Forbidden",
68
- 404: "Not Found",
69
- 405: "Method Not Allowed",
70
- 408: "Request Timeout",
71
- 409: "Conflict",
72
- 422: "Unprocessable Entity",
73
- 429: "Too Many Requests",
74
- 500: "Internal Server Error",
75
- 502: "Bad Gateway",
76
- 503: "Service Unavailable",
77
- 504: "Gateway Timeout"
78
- };
79
- return titles[status] || `HTTP Error ${status}`;
80
- }
81
- /**
82
- * Normalizes any error into a consistent, structured ApiError format.
83
- *
84
- * This method handles various error scenarios and ensures they all conform to
85
- * the {@link ApiError} interface with appropriate categorization and metadata:
86
- *
87
- * - **Existing ApiErrors**: Enhances with missing fields (traceId, config)
88
- * - **AbortErrors**: Marks as `request_cancelled` with isAborted flag
89
- * - **Timeout Errors**: Categorizes as `timeout_error` with 408 status
90
- * - **Network Errors**: Categorizes as `network_error` with 0 status
91
- * - **Unknown Errors**: Fallback category for unexpected error types
92
- *
93
- * All normalized errors include:
94
- * - `type`: Error category for programmatic handling
95
- * - `title`: Human-readable error title
96
- * - `status`: HTTP status code (or 0 for non-HTTP errors)
97
- * - `traceId`: Correlation ID for distributed tracing
98
- * - `isAborted`: Boolean flag indicating if request was cancelled
99
- * - `config`: Original request configuration for debugging
100
- *
101
- * @param error - The error to normalize (can be any type)
102
- * @param config - The request configuration that led to this error
103
- * @param correlationId - Optional correlation ID for tracing
104
- * @returns A fully structured ApiError instance
105
- *
106
- * @example
107
- * Normalizing a fetch AbortError:
108
- * ```typescript
109
- * try {
110
- * await fetch(url, { signal });
111
- * } catch (error) {
112
- * const apiError = normalizer.normalizeError(error, config, 'req-123');
113
- * // apiError.type === 'request_cancelled'
114
- * // apiError.isAborted === true
115
- * }
116
- * ```
117
- *
118
- * @example
119
- * Normalizing a timeout:
120
- * ```typescript
121
- * const timeoutError = new Error('Request timeout after 30000ms');
122
- * const apiError = normalizer.normalizeError(timeoutError, config);
123
- * // apiError.type === 'timeout_error'
124
- * // apiError.status === 408
125
- * ```
126
- */
127
- normalizeError(error, config, correlationId) {
128
- if (error === null || error === void 0) {
129
- return Object.assign(new Error("An unknown error occurred"), {
130
- type: "unknown_error",
131
- title: "Unknown Error",
132
- status: 0,
133
- traceId: correlationId,
134
- isAborted: false,
135
- config
136
- });
137
- }
138
- if (typeof error === "string") {
139
- return Object.assign(new Error(error), {
140
- type: "unknown_error",
141
- title: "Unknown Error",
142
- status: 0,
143
- traceId: correlationId,
144
- isAborted: false,
145
- config
146
- });
147
- }
148
- const err = error;
149
- if (err.type || err.title || err.errors) {
150
- return Object.assign(
151
- error instanceof Error ? error : new Error(err.message ?? "Unknown error"),
152
- {
153
- type: err.type,
154
- title: err.title,
155
- status: err.status,
156
- traceId: err.traceId || correlationId,
157
- errors: err.errors,
158
- isAborted: err.isAborted || false,
159
- config
160
- }
161
- );
162
- }
163
- if (err.name === "AbortError" || err.isAborted) {
164
- return Object.assign(new Error(err.message ?? "Request was aborted"), {
165
- type: "request_cancelled",
166
- title: "Request was cancelled",
167
- status: 0,
168
- traceId: correlationId,
169
- isAborted: true,
170
- config
171
- });
172
- }
173
- if (err.message?.includes("timeout")) {
174
- return Object.assign(new Error(err.message), {
175
- type: "timeout_error",
176
- title: "Request Timeout",
177
- status: 408,
178
- traceId: correlationId,
179
- isAborted: true,
180
- config
181
- });
182
- }
183
- if (err.message?.includes("network")) {
184
- return Object.assign(new Error(err.message ?? "Network request failed"), {
185
- type: "network_error",
186
- title: "Network Error",
187
- status: 0,
188
- traceId: correlationId,
189
- isAborted: false,
190
- config
191
- });
192
- }
193
- return Object.assign(
194
- new Error(err.message ?? "An unknown error occurred"),
195
- {
196
- type: "unknown_error",
197
- title: "Unknown Error",
198
- status: 0,
199
- traceId: correlationId,
200
- isAborted: false,
201
- config
202
- }
203
- );
204
- }
205
- };
206
-
207
- // src/core/api/Interceptors/InterceptorManager.ts
208
- var InterceptorManager = class {
209
- /**
210
- * Array of registered request interceptors
211
- * @private
212
- */
213
- requestInterceptors = [];
214
- /**
215
- * Array of registered response interceptors
216
- * @private
217
- */
218
- responseInterceptors = [];
219
- /**
220
- * Array of registered error interceptors
221
- * @private
222
- */
223
- errorInterceptors = [];
224
- /**
225
- * Registers a request interceptor to modify requests before they are sent.
226
- *
227
- * Request interceptors can:
228
- * - Add or modify headers
229
- * - Transform request bodies
230
- * - Add query parameters
231
- * - Implement request signing
232
- * - Log outgoing requests
233
- *
234
- * @param interceptor - Async function that receives and returns RequestConfig
235
- * @returns Cleanup function to unregister this interceptor
236
- *
237
- * @example
238
- * ```typescript
239
- * // Add authentication header
240
- * const unregister = manager.addRequestInterceptor(async (config) => {
241
- * const token = await getAuthToken();
242
- * config.headers = config.headers || new Headers();
243
- * config.headers.set('Authorization', `Bearer ${token}`);
244
- * return config;
245
- * });
246
- *
247
- * // Later, remove the interceptor
248
- * unregister();
249
- * ```
250
- */
251
- addRequestInterceptor(interceptor) {
252
- this.requestInterceptors.push(interceptor);
253
- return () => {
254
- const index = this.requestInterceptors.indexOf(interceptor);
255
- if (index > -1) this.requestInterceptors.splice(index, 1);
256
- };
257
- }
258
- /**
259
- * Registers a response interceptor to transform responses before they are returned.
260
- *
261
- * Response interceptors can:
262
- * - Transform response data format
263
- * - Extract nested data structures
264
- * - Add computed properties
265
- * - Cache responses
266
- * - Log successful responses
267
- *
268
- * @param interceptor - Async function that receives and returns ApiResponse
269
- * @returns Cleanup function to unregister this interceptor
270
- *
271
- * @example
272
- * ```typescript
273
- * // Extract data from envelope
274
- * manager.addResponseInterceptor(async (response) => {
275
- * if (response.apiData?.result) {
276
- * response.apiData = response.apiData.result;
277
- * }
278
- * return response;
279
- * });
280
- *
281
- * // Add timestamps
282
- * manager.addResponseInterceptor(async (response) => {
283
- * return {
284
- * ...response,
285
- * receivedAt: new Date().toISOString()
286
- * };
287
- * });
288
- * ```
289
- */
290
- addResponseInterceptor(interceptor) {
291
- this.responseInterceptors.push(interceptor);
292
- return () => {
293
- const index = this.responseInterceptors.indexOf(interceptor);
294
- if (index > -1) this.responseInterceptors.splice(index, 1);
295
- };
296
- }
297
- /**
298
- * Registers an error interceptor to handle or transform errors before they are thrown.
299
- *
300
- * Error interceptors can:
301
- * - Log errors to monitoring services
302
- * - Transform error formats
303
- * - Implement retry logic
304
- * - Show user notifications
305
- * - Extract validation errors
306
- *
307
- * **Note:** Error interceptors should re-throw the error (or a transformed version)
308
- * to maintain the error flow. The final error is always thrown.
309
- *
310
- * @param interceptor - Async function that receives and returns (or throws) ApiError
311
- * @returns Cleanup function to unregister this interceptor
312
- *
313
- * @example
314
- * ```typescript
315
- * // Log to monitoring service
316
- * manager.addErrorInterceptor(async (error) => {
317
- * if (error.status >= 500) {
318
- * await Sentry.captureException(error, {
319
- * extra: { traceId: error.traceId }
320
- * });
321
- * }
322
- * throw error; // Re-throw to continue error flow
323
- * });
324
- *
325
- * // Transform error messages
326
- * manager.addErrorInterceptor(async (error) => {
327
- * if (error.status === 404) {
328
- * error.title = 'Resource not found';
329
- * }
330
- * throw error;
331
- * });
332
- * ```
333
- */
334
- addErrorInterceptor(interceptor) {
335
- this.errorInterceptors.push(interceptor);
336
- return () => {
337
- const index = this.errorInterceptors.indexOf(interceptor);
338
- if (index > -1) this.errorInterceptors.splice(index, 1);
339
- };
340
- }
341
- /**
342
- * Applies all registered request interceptors in sequential order.
343
- *
344
- * Each interceptor receives the config modified by the previous interceptor,
345
- * forming a processing pipeline. If any interceptor throws an error,
346
- * the pipeline stops and the error propagates.
347
- *
348
- * @param config - The initial request configuration
349
- * @returns The modified request configuration after all interceptors
350
- *
351
- * @example
352
- * ```typescript
353
- * const config = { method: 'GET', url: '/users' };
354
- * const finalConfig = await manager.applyRequestInterceptors(config);
355
- * // finalConfig has been processed by all registered interceptors
356
- * ```
357
- */
358
- async applyRequestInterceptors(config) {
359
- let modifiedConfig = { ...config };
360
- for (const interceptor of this.requestInterceptors) {
361
- modifiedConfig = await interceptor(modifiedConfig);
362
- }
363
- return modifiedConfig;
364
- }
365
- /**
366
- * Applies all registered response interceptors in sequential order.
367
- *
368
- * Each interceptor receives the response modified by the previous interceptor,
369
- * forming a processing pipeline. If any interceptor throws an error,
370
- * the pipeline stops and the error propagates.
371
- *
372
- * @template T - The type of the response data
373
- * @param response - The initial API response
374
- * @returns The modified response after all interceptors
375
- *
376
- * @example
377
- * ```typescript
378
- * const response = { data: { id: 1, name: 'John' } };
379
- * const finalResponse = await manager.applyResponseInterceptors(response);
380
- * // finalResponse has been processed by all registered interceptors
381
- * ```
382
- */
383
- async applyResponseInterceptors(response) {
384
- let modifiedResponse = response;
385
- for (const interceptor of this.responseInterceptors) {
386
- modifiedResponse = await interceptor(modifiedResponse);
387
- }
388
- return modifiedResponse;
389
- }
390
- /**
391
- * Applies all registered error interceptors in sequential order and re-throws.
392
- *
393
- * Each interceptor receives the error (potentially modified by previous interceptors).
394
- * Interceptors can transform the error before re-throwing it. The final error
395
- * is always thrown to maintain error flow.
396
- *
397
- * If an interceptor itself throws an error, that becomes the new error to process
398
- * by subsequent interceptors.
399
- *
400
- * @param error - The initial API error
401
- * @returns Never returns (always throws)
402
- * @throws The final error after all interceptors have processed it
403
- *
404
- * @example
405
- * ```typescript
406
- * try {
407
- * await manager.applyErrorInterceptors(error);
408
- * } catch (finalError) {
409
- * // finalError has been processed by all registered error interceptors
410
- * }
411
- * ```
412
- */
413
- async applyErrorInterceptors(error) {
414
- let modifiedError = error;
415
- for (const interceptor of this.errorInterceptors) {
416
- try {
417
- modifiedError = await interceptor(modifiedError);
418
- } catch (e) {
419
- modifiedError = e;
420
- }
421
- }
422
- throw modifiedError;
423
- }
424
- };
425
-
426
- // src/core/api/RequestManager.ts
427
- var RequestManager = class {
428
- /**
429
- * Map of active request keys to their abort controllers
430
- * @private
431
- */
432
- activeRequests = /* @__PURE__ */ new Map();
433
- /**
434
- * Map of request keys to their correlation IDs for tracing
435
- * @private
436
- */
437
- correlationMap = /* @__PURE__ */ new Map();
438
- /**
439
- * Registers a new request for tracking and cancellation management.
440
- *
441
- * If a request with the same key already exists, it will be automatically
442
- * cancelled before the new one is registered (request deduplication).
443
- *
444
- * @param key - Unique identifier for the request (typically method + URL + timestamp)
445
- * @param controller - AbortController for cancelling the request
446
- * @param correlationId - Correlation ID for distributed tracing
447
- *
448
- * @example
449
- * ```typescript
450
- * const controller = new AbortController();
451
- * manager.add('GET_/api/users_1699999999', controller, 'api-abc123');
452
- * ```
453
- */
454
- add(key, controller, correlationId) {
455
- this.cancel(key);
456
- this.activeRequests.set(key, controller);
457
- this.correlationMap.set(key, correlationId);
458
- }
459
- /**
460
- * Removes a request from tracking without cancelling it.
461
- *
462
- * This is typically called when a request completes successfully or fails.
463
- * Use {@link cancel} instead if you need to abort the request.
464
- *
465
- * @param key - Unique identifier for the request to remove
466
- *
467
- * @example
468
- * ```typescript
469
- * // Called automatically after request completes
470
- * manager.remove('GET_/api/users_1699999999');
471
- * ```
472
- */
473
- remove(key) {
474
- this.activeRequests.delete(key);
475
- this.correlationMap.delete(key);
476
- }
477
- /**
478
- * Cancels a specific request and removes it from tracking.
479
- *
480
- * If the request doesn't exist or was already cancelled, this operation is a no-op.
481
- * The associated AbortController's signal will be triggered, causing any active
482
- * fetch operations to abort.
483
- *
484
- * @param key - Unique identifier for the request to cancel
485
- *
486
- * @example
487
- * ```typescript
488
- * // User navigates away, cancel the pending request
489
- * manager.cancel('GET_/api/users_1699999999');
490
- * ```
491
- */
492
- cancel(key) {
493
- const controller = this.activeRequests.get(key);
494
- if (controller) {
495
- controller.abort();
496
- this.activeRequests.delete(key);
497
- this.correlationMap.delete(key);
498
- }
499
- }
500
- /**
501
- * Cancels all active requests and clears all tracking data.
502
- *
503
- * This is useful for cleanup scenarios such as:
504
- * - User logout
505
- * - Component unmount
506
- * - Navigation to a different part of the application
507
- * - Error recovery that requires a clean slate
508
- *
509
- * @example
510
- * ```typescript
511
- * // Cancel all pending requests on logout
512
- * function handleLogout() {
513
- * apiClient.cancelAllRequests();
514
- * // ... rest of logout logic
515
- * }
516
- * ```
517
- */
518
- cancelAll() {
519
- this.activeRequests.forEach((controller) => controller.abort());
520
- this.activeRequests.clear();
521
- this.correlationMap.clear();
522
- }
523
- /**
524
- * Checks if a request with the given key is currently being tracked.
525
- *
526
- * @param key - Unique identifier for the request
527
- * @returns `true` if the request is active, `false` otherwise
528
- *
529
- * @example
530
- * ```typescript
531
- * if (manager.has('GET_/api/users_1699999999')) {
532
- * console.log('Request is still pending');
533
- * }
534
- * ```
535
- */
536
- has(key) {
537
- return this.activeRequests.has(key);
538
- }
539
- /**
540
- * Retrieves the correlation ID for a given request key.
541
- *
542
- * Correlation IDs are used for distributed tracing and request tracking
543
- * across services and logs.
544
- *
545
- * @param key - Unique identifier for the request
546
- * @returns The correlation ID if found, `undefined` otherwise
547
- *
548
- * @example
549
- * ```typescript
550
- * const correlationId = manager.getCorrelationId('GET_/api/users_1699999999');
551
- * if (correlationId) {
552
- * console.log('Trace request with ID:', correlationId);
553
- * }
554
- * ```
555
- */
556
- getCorrelationId(key) {
557
- return this.correlationMap.get(key);
558
- }
559
- };
560
-
561
- // src/core/api/Retry/RetryHandler.ts
562
- var RetryHandler = class {
563
- /**
564
- * Retries a failed request with exponential backoff strategy.
565
- *
566
- * The retry logic works as follows:
567
- * 1. Attempts the request immediately
568
- * 2. On failure, checks if the error is retryable
569
- * 3. If retryable and retries remain, waits for the current delay
570
- * 4. Doubles the delay for the next attempt
571
- * 5. Repeats until success or retries exhausted
572
- *
573
- * **Non-Retryable Errors:**
574
- * - Validation errors (400) - Client sent bad data
575
- * - AbortErrors - Request was explicitly cancelled
576
- * - Requests with aborted signals
577
- *
578
- * **Abort Handling:**
579
- * If the signal is aborted during a retry delay, the retry is immediately
580
- * cancelled and an AbortError is thrown.
581
- *
582
- * @template T - The return type of the function being retried
583
- * @param fn - Async function to retry on failure
584
- * @param retries - Number of retry attempts remaining (decrements each retry)
585
- * @param delay - Current delay in milliseconds before next retry
586
- * @param signal - Optional AbortSignal to cancel retries
587
- * @returns Promise resolving to the function's result on success
588
- * @throws The last error encountered if all retries are exhausted
589
- * @throws AbortError if the signal is aborted during execution or delay
590
- *
591
- * @example
592
- * Basic retry usage:
593
- * ```typescript
594
- * const handler = new RetryHandler();
595
- * const fetchUser = () => fetch('/api/users/123').then(r => r.json());
596
- *
597
- * try {
598
- * const user = await handler.retryRequest(
599
- * fetchUser,
600
- * 3, // 3 retries
601
- * 1000 // Start with 1s delay
602
- * );
603
- * console.log('User:', user);
604
- * } catch (error) {
605
- * console.error('Failed after all retries:', error);
606
- * }
607
- * ```
608
- *
609
- * @example
610
- * With cancellation support:
611
- * ```typescript
612
- * const controller = new AbortController();
613
- * const signal = controller.signal;
614
- *
615
- * // Cancel after 5 seconds
616
- * setTimeout(() => controller.abort(), 5000);
617
- *
618
- * try {
619
- * await handler.retryRequest(fetchUser, 5, 1000, signal);
620
- * } catch (error) {
621
- * if (error.name === 'AbortError') {
622
- * console.log('Retry cancelled');
623
- * }
624
- * }
625
- * ```
626
- */
627
- async retryRequest(fn, retries, delay, signal) {
628
- try {
629
- if (signal?.aborted) {
630
- throw new Error(signal.reason || "Request aborted");
631
- }
632
- return await fn();
633
- } catch (error) {
634
- const err = error;
635
- if (err.name === "AbortError" || signal?.aborted) {
636
- throw error;
637
- }
638
- if (err.type === "validation_error" || err.status === 400) {
639
- throw error;
640
- }
641
- if (retries === 0) throw error;
642
- await new Promise((resolve, reject) => {
643
- const timeoutId = setTimeout(resolve, delay);
644
- if (signal) {
645
- signal.addEventListener(
646
- "abort",
647
- () => {
648
- clearTimeout(timeoutId);
649
- reject(new Error(signal.reason || "Request aborted"));
650
- },
651
- { once: true }
652
- );
653
- }
654
- });
655
- return this.retryRequest(fn, retries - 1, delay * 2, signal);
656
- }
657
- }
658
- };
659
-
660
- // src/core/api/Signals/SignalManager.ts
661
- var SignalManager = class {
662
- /**
663
- * Creates a combined AbortController that aborts when any source signal aborts.
664
- *
665
- * This method implements the "any" pattern for cancellation: the combined signal
666
- * will abort as soon as ANY of the source signals abort. This is useful for
667
- * coordinating multiple cancellation conditions:
668
- * - User clicks cancel button
669
- * - Request timeout expires
670
- * - Component unmounts
671
- * - Parent request is cancelled
672
- *
673
- * **Early Abort Optimization:**
674
- * If any source signal is already aborted when this method is called,
675
- * the returned controller is immediately aborted without setting up listeners.
676
- *
677
- * **Memory Management:**
678
- * Event listeners are registered with `{ once: true }` to prevent memory leaks,
679
- * as they automatically clean up after firing.
680
- *
681
- * @param signals - Array of AbortSignals to combine (undefined values are ignored)
682
- * @returns A new AbortController that aborts when any source signal aborts
683
- *
684
- * @example
685
- * User cancellation + timeout:
686
- * ```typescript
687
- * const userController = new AbortController();
688
- * const timeout = manager.createTimeoutSignal(30000);
689
- *
690
- * const combined = manager.createCombinedSignal([
691
- * userController.signal,
692
- * timeout.signal
693
- * ]);
694
- *
695
- * // Request will be cancelled after 30s OR when user clicks cancel
696
- * fetch('/api/data', { signal: combined.signal });
697
- * ```
698
- *
699
- * @example
700
- * React component with cleanup:
701
- * ```typescript
702
- * useEffect(() => {
703
- * const controller = new AbortController();
704
- *
705
- * const combined = manager.createCombinedSignal([
706
- * controller.signal,
707
- * unmountSignal // From component lifecycle
708
- * ]);
709
- *
710
- * fetchData(combined.signal);
711
- *
712
- * return () => controller.abort(); // Cleanup
713
- * }, []);
714
- * ```
715
- */
716
- createCombinedSignal(signals) {
717
- const controller = new AbortController();
718
- for (const signal of signals) {
719
- if (signal) {
720
- if (signal.aborted) {
721
- controller.abort(signal.reason);
722
- break;
723
- }
724
- signal.addEventListener(
725
- "abort",
726
- () => {
727
- controller.abort(signal.reason);
728
- },
729
- { once: true }
730
- );
731
- }
732
- }
733
- return controller;
734
- }
735
- /**
736
- * Creates an AbortController that automatically aborts after a specified timeout.
737
- *
738
- * This method creates a time-based cancellation mechanism useful for implementing
739
- * request timeouts and deadlines. The signal will automatically abort after the
740
- * specified duration, providing a consistent timeout experience.
741
- *
742
- * **Automatic Cleanup:**
743
- * If the signal is aborted by other means before the timeout expires, the internal
744
- * setTimeout is automatically cleared to prevent memory leaks.
745
- *
746
- * **Abort Reason:**
747
- * The abort reason includes the timeout duration for debugging purposes:
748
- * `"Request timeout after {timeout}ms"`
749
- *
750
- * @param timeout - Timeout duration in milliseconds
751
- * @returns An AbortController that will abort after the timeout
752
- *
753
- * @example
754
- * Simple request timeout:
755
- * ```typescript
756
- * const manager = new SignalManager();
757
- * const timeout = manager.createTimeoutSignal(5000); // 5 seconds
758
- *
759
- * try {
760
- * const response = await fetch('/api/slow-endpoint', {
761
- * signal: timeout.signal
762
- * });
763
- * const data = await response.json();
764
- * } catch (error) {
765
- * if (error.name === 'AbortError') {
766
- * console.error('Request timed out after 5 seconds');
767
- * }
768
- * }
769
- * ```
770
- *
771
- * @example
772
- * Different timeouts for different operations:
773
- * ```typescript
774
- * // Short timeout for quick operations
775
- * const quickTimeout = manager.createTimeoutSignal(2000);
776
- * await fetch('/api/health', { signal: quickTimeout.signal });
777
- *
778
- * // Long timeout for heavy operations
779
- * const longTimeout = manager.createTimeoutSignal(60000);
780
- * await fetch('/api/export', { signal: longTimeout.signal });
781
- * ```
782
- *
783
- * @example
784
- * Manual cancellation before timeout:
785
- * ```typescript
786
- * const timeout = manager.createTimeoutSignal(30000);
787
- *
788
- * // If user cancels, timeout is automatically cleaned up
789
- * timeout.abort('User cancelled');
790
- * // Internal setTimeout is cleared, no memory leak
791
- * ```
792
- */
793
- createTimeoutSignal(timeout) {
794
- const controller = new AbortController();
795
- const timeoutId = setTimeout(() => {
796
- controller.abort(`Request timeout after ${timeout}ms`);
797
- }, timeout);
798
- controller.signal.addEventListener(
799
- "abort",
800
- () => {
801
- clearTimeout(timeoutId);
802
- },
803
- { once: true }
804
- );
805
- return controller;
806
- }
807
- };
808
-
809
- // src/core/api/Utils/ResponseParser.ts
810
- var ResponseParser = class {
811
- /**
812
- * Parses the HTTP response body into an appropriate JavaScript type.
813
- *
814
- * The parsing strategy is determined by the Content-Type header:
815
- * 1. **JSON** (application/json): Calls `response.json()`
816
- * 2. **Text** (text/*): Calls `response.text()`
817
- * 3. **Binary** (application/octet-stream): Calls `response.blob()`
818
- * 4. **Unknown**: Reads as text, attempts JSON parse, falls back to raw text
819
- *
820
- * **Fallback Behavior:**
821
- * For responses without a Content-Type header or with unknown types, the parser
822
- * attempts to parse as JSON first (common for APIs that don't set proper headers).
823
- * If JSON parsing fails, it returns the raw text.
824
- *
825
- * @param response - The Fetch API Response object to parse
826
- * @returns Promise resolving to the parsed response data
827
- * @returns Can be: JSON object/array, string, or Blob depending on Content-Type
828
- *
829
- * @example
830
- * API response parsing:
831
- * ```typescript
832
- * const response = await fetch('/api/users');
833
- * const data = await parser.parseResponse(response);
834
- *
835
- * if (typeof data === 'string') {
836
- * console.log('Text response:', data);
837
- * } else if (data instanceof Blob) {
838
- * console.log('Binary response:', data.size, 'bytes');
839
- * } else {
840
- * console.log('JSON response:', data);
841
- * }
842
- * ```
843
- *
844
- * @example
845
- * Handling different content types:
846
- * ```typescript
847
- * // CSV file download
848
- * const csvResponse = await fetch('/api/export.csv');
849
- * const blob = await parser.parseResponse(csvResponse);
850
- * // Returns Blob for download
851
- *
852
- * // JSON API
853
- * const jsonResponse = await fetch('/api/users');
854
- * const users = await parser.parseResponse(jsonResponse);
855
- * // Returns parsed JSON array
856
- *
857
- * // Plain text logs
858
- * const logResponse = await fetch('/api/logs');
859
- * const logs = await parser.parseResponse(logResponse);
860
- * // Returns string
861
- * ```
862
- */
863
- async parseResponse(response) {
864
- const contentType = response.headers.get("content-type");
865
- if (contentType?.includes("application/json")) {
866
- return response.json();
867
- } else if (contentType?.includes("text/")) {
868
- return response.text();
869
- } else if (contentType?.includes("application/octet-stream")) {
870
- return response.blob();
871
- } else {
872
- const text = await response.text();
873
- try {
874
- return JSON.parse(text);
875
- } catch {
876
- return text;
877
- }
878
- }
879
- }
880
- };
881
-
882
- // src/core/api/Utils/UrlBuilder.ts
883
- var UrlBuilder = class {
884
- /**
885
- * Builds a complete URL by combining base URL, endpoint, and query parameters.
886
- *
887
- * The URL construction process:
888
- * 1. Combines `baseURL` and `endpoint` using URL API
889
- * 2. Iterates through query parameters
890
- * 3. Skips null/undefined values
891
- * 4. Handles arrays by appending multiple values with same key
892
- * 5. Converts all values to strings
893
- * 6. Returns fully-qualified URL string
894
- *
895
- * **Path Handling:**
896
- * The endpoint can be either relative or absolute:
897
- * - Relative: `/users` → Combined with baseURL
898
- * - Absolute: `https://other-api.com/users` → Uses absolute URL
899
- *
900
- * **Encoding:**
901
- * All parameter values are automatically URL-encoded by the URL API,
902
- * so special characters (spaces, &, =, etc.) are safely handled.
903
- *
904
- * @param baseURL - Base URL for the API (e.g., 'https://api.example.com')
905
- * @param endpoint - API endpoint path relative to baseURL (e.g., '/users/123')
906
- * @param params - Optional query parameters as key-value pairs
907
- * @returns The fully-qualified URL string with encoded query parameters
908
- *
909
- * @example
910
- * Basic URL construction:
911
- * ```typescript
912
- * const url = builder.buildURL(
913
- * 'https://api.example.com',
914
- * '/search',
915
- * { q: 'hello world', limit: 10 }
916
- * );
917
- * // => "https://api.example.com/search?q=hello+world&limit=10"
918
- * ```
919
- *
920
- * @example
921
- * Array parameters:
922
- * ```typescript
923
- * const url = builder.buildURL(
924
- * 'https://api.example.com',
925
- * '/posts',
926
- * { tags: ['javascript', 'typescript', 'react'] }
927
- * );
928
- * // => "https://api.example.com/posts?tags=javascript&tags=typescript&tags=react"
929
- * ```
930
- *
931
- * @example
932
- * Null/undefined handling:
933
- * ```typescript
934
- * const url = builder.buildURL(
935
- * 'https://api.example.com',
936
- * '/users',
937
- * {
938
- * name: 'John',
939
- * age: null, // Skipped
940
- * email: undefined // Skipped
941
- * }
942
- * );
943
- * // => "https://api.example.com/users?name=John"
944
- * ```
945
- *
946
- * @example
947
- * Special characters encoding:
948
- * ```typescript
949
- * const url = builder.buildURL(
950
- * 'https://api.example.com',
951
- * '/search',
952
- * { q: 'foo & bar', category: 'code/examples' }
953
- * );
954
- * // => "https://api.example.com/search?q=foo+%26+bar&category=code%2Fexamples"
955
- * ```
956
- */
957
- buildURL(baseURL, endpoint, params) {
958
- const url = new URL(endpoint, baseURL);
959
- if (params) {
960
- Object.keys(params).forEach((key) => {
961
- const value = params[key];
962
- if (value !== void 0 && value !== null) {
963
- if (Array.isArray(value)) {
964
- value.forEach((v) => url.searchParams.append(key, String(v)));
965
- } else {
966
- url.searchParams.append(key, String(value));
967
- }
968
- }
969
- });
970
- }
971
- return url.toString();
972
- }
973
- };
974
-
975
- // src/core/api/ApiClient.ts
976
- var ApiClient = class {
977
- baseURL;
978
- defaultTimeout;
979
- interceptorManager = new InterceptorManager();
980
- signalManager = new SignalManager();
981
- errorNormalizer = new ErrorNormalizer();
982
- responseParser = new ResponseParser();
983
- urlBuilder = new UrlBuilder();
984
- retryHandler = new RetryHandler();
985
- requestManager = new RequestManager();
986
- authToken = null;
987
- correlationIdPrefix = "api";
988
- includeCorrelationId = true;
989
- /**
990
- * Creates a new API client instance
991
- * @param baseURL - Base URL for all API requests (default: empty string for relative URLs)
992
- * @param defaultTimeout - Default request timeout in milliseconds (default: 30000)
993
- */
994
- constructor(baseURL = "", defaultTimeout = 3e4) {
995
- this.baseURL = baseURL;
996
- this.defaultTimeout = defaultTimeout;
997
- }
998
- /**
999
- * Sets the prefix for auto-generated correlation IDs
1000
- * @param prefix - The prefix to use for correlation IDs (e.g., 'api', 'web', 'mobile')
1001
- */
1002
- setCorrelationIdPrefix(prefix) {
1003
- this.correlationIdPrefix = prefix;
1004
- }
1005
- /**
1006
- * Enables or disables automatic correlation ID generation
1007
- * @param include - Whether to include correlation IDs in requests
1008
- */
1009
- setIncludeCorrelationId(include) {
1010
- this.includeCorrelationId = include;
1011
- }
1012
- /**
1013
- * Registers a request interceptor to modify requests before they're sent
1014
- * @param interceptor - Function to intercept and potentially modify request config
1015
- * @returns Function to unregister this interceptor
1016
- *
1017
- * @example
1018
- * ```typescript
1019
- * const unregister = client.addRequestInterceptor(async (config) => {
1020
- * config.headers = config.headers || new Headers();
1021
- * config.headers.set('X-Client-Version', '1.0.0');
1022
- * return config;
1023
- * });
1024
- *
1025
- * // Later, to remove the interceptor:
1026
- * unregister();
1027
- * ```
1028
- */
1029
- addRequestInterceptor(interceptor) {
1030
- return this.interceptorManager.addRequestInterceptor(interceptor);
1031
- }
1032
- /**
1033
- * Registers a response interceptor to modify responses before they're returned
1034
- * @param interceptor - Function to intercept and potentially modify responses
1035
- * @returns Function to unregister this interceptor
1036
- *
1037
- * @example
1038
- * ```typescript
1039
- * client.addResponseInterceptor(async (response) => {
1040
- * // Transform data format
1041
- * if (response.apiData) {
1042
- * response.apiData = camelCaseKeys(response.apiData);
1043
- * }
1044
- * return response;
1045
- * });
1046
- * ```
1047
- */
1048
- addResponseInterceptor(interceptor) {
1049
- return this.interceptorManager.addResponseInterceptor(interceptor);
1050
- }
1051
- /**
1052
- * Registers an error interceptor to handle or transform errors
1053
- * @param interceptor - Function to intercept and potentially modify errors
1054
- * @returns Function to unregister this interceptor
1055
- *
1056
- * @example
1057
- * ```typescript
1058
- * client.addErrorInterceptor(async (error) => {
1059
- * // Log errors to monitoring service
1060
- * if (error.status >= 500) {
1061
- * await monitoringService.logError(error);
1062
- * }
1063
- * return error; // Re-throw the error
1064
- * });
1065
- * ```
1066
- */
1067
- addErrorInterceptor(interceptor) {
1068
- return this.interceptorManager.addErrorInterceptor(interceptor);
1069
- }
1070
- /**
1071
- * Sets the authentication token for subsequent requests
1072
- * @param token - JWT token or null to clear authentication
1073
- *
1074
- * @example
1075
- * ```typescript
1076
- * // Set token after login
1077
- * client.setAuthToken(loginResponse.accessToken);
1078
- *
1079
- * // Clear token on logout
1080
- * client.setAuthToken(null);
1081
- * ```
1082
- */
1083
- setAuthToken(token) {
1084
- this.authToken = token;
1085
- }
1086
- /**
1087
- * Retrieves the current authentication token
1088
- * @returns The current auth token or null if not set
1089
- */
1090
- getAuthToken() {
1091
- return this.authToken;
1092
- }
1093
- /**
1094
- * Cancels a specific request by its key
1095
- * @param key - The unique key identifying the request to cancel
1096
- */
1097
- cancelRequest(key) {
1098
- this.requestManager.cancel(key);
1099
- }
1100
- /**
1101
- * Cancels all pending requests
1102
- * Useful for cleanup on navigation or component unmount
1103
- */
1104
- cancelAllRequests() {
1105
- this.requestManager.cancelAll();
1106
- }
1107
- /**
1108
- * Core request method that handles all HTTP operations
1109
- * @template T - The expected response data type
1110
- * @param endpoint - API endpoint relative to baseURL
1111
- * @param config - Request configuration options
1112
- * @returns Promise resolving to ApiResponse with data or error
1113
- *
1114
- * @example
1115
- * ```typescript
1116
- * const response = await client.request<User>('/users/123', {
1117
- * method: 'GET',
1118
- * timeout: 5000,
1119
- * throwErrors: false
1120
- * });
1121
- * ```
1122
- */
1123
- async request(endpoint, config = {}) {
1124
- const correlationId = config.correlationId || (!config.skipCorrelationId && this.includeCorrelationId ? generateCorrelationId(this.correlationIdPrefix) : void 0);
1125
- const requestKey = `${config.method || "GET"}_${endpoint}_${Date.now()}`;
1126
- const masterController = new AbortController();
1127
- try {
1128
- const signals = [
1129
- config.signal,
1130
- config.cancelToken?.signal,
1131
- masterController.signal
1132
- ];
1133
- const timeout = config.timeout || this.defaultTimeout;
1134
- const timeoutController = this.signalManager.createTimeoutSignal(timeout);
1135
- signals.push(timeoutController.signal);
1136
- const combinedController = this.signalManager.createCombinedSignal(signals);
1137
- if (correlationId) {
1138
- this.requestManager.add(requestKey, masterController, correlationId);
1139
- }
1140
- const finalConfig = await this.interceptorManager.applyRequestInterceptors({
1141
- ...config,
1142
- signal: combinedController.signal,
1143
- correlationId
1144
- });
1145
- const url = this.urlBuilder.buildURL(
1146
- this.baseURL,
1147
- endpoint,
1148
- finalConfig.params
1149
- );
1150
- const headers = new Headers(finalConfig.headers);
1151
- if (correlationId) {
1152
- headers.set("X-Correlation-Id", correlationId);
1153
- headers.set("X-Request-Id", correlationId);
1154
- }
1155
- if (this.authToken && !finalConfig.skipAuthRefresh) {
1156
- headers.set("Authorization", `Bearer ${this.authToken}`);
1157
- }
1158
- let fetchBody = finalConfig.body;
1159
- if (finalConfig.body && typeof finalConfig.body === "object" && !(finalConfig.body instanceof FormData) && !(finalConfig.body instanceof Blob) && !(finalConfig.body instanceof ArrayBuffer) && !(finalConfig.body instanceof URLSearchParams) && !(finalConfig.body instanceof ReadableStream)) {
1160
- headers.set("Content-Type", "application/json");
1161
- fetchBody = JSON.stringify(finalConfig.body);
1162
- }
1163
- finalConfig.headers = headers;
1164
- const fetchPromise = async () => {
1165
- try {
1166
- const response = await fetch(url, {
1167
- ...finalConfig,
1168
- body: fetchBody,
1169
- signal: combinedController.signal
1170
- });
1171
- const responseData = await this.responseParser.parseResponse(response);
1172
- if (!response.ok) {
1173
- const errorData = responseData;
1174
- const error = Object.assign(
1175
- new Error(
1176
- errorData.title || `HTTP ${response.status}: ${response.statusText}`
1177
- ),
1178
- {
1179
- type: errorData.type || this.errorNormalizer.getErrorType(response.status),
1180
- title: errorData.title || this.errorNormalizer.getErrorTitle(response.status),
1181
- status: response.status,
1182
- traceId: errorData.traceId || correlationId,
1183
- errors: errorData.errors,
1184
- isAborted: false,
1185
- config: finalConfig
1186
- }
1187
- );
1188
- if (finalConfig.throwErrors !== false) {
1189
- throw error;
1190
- } else {
1191
- return await this.interceptorManager.applyResponseInterceptors({
1192
- error
1193
- });
1194
- }
1195
- }
1196
- const apiResponse = {
1197
- data: responseData
1198
- };
1199
- return await this.interceptorManager.applyResponseInterceptors(
1200
- apiResponse
1201
- );
1202
- } catch (error) {
1203
- if (error.name === "AbortError") {
1204
- const abortError = Object.assign(
1205
- new Error(error.message || "Request aborted"),
1206
- {
1207
- type: "request_cancelled",
1208
- title: "Request was cancelled",
1209
- status: 0,
1210
- traceId: correlationId,
1211
- isAborted: true,
1212
- config: finalConfig
1213
- }
1214
- );
1215
- if (finalConfig.throwErrors !== false) {
1216
- throw abortError;
1217
- } else {
1218
- return await this.interceptorManager.applyResponseInterceptors({
1219
- error: abortError
1220
- });
1221
- }
1222
- }
1223
- throw error;
1224
- }
1225
- };
1226
- if (finalConfig.retries && finalConfig.retries > 0) {
1227
- return await this.retryHandler.retryRequest(
1228
- fetchPromise,
1229
- finalConfig.retries,
1230
- finalConfig.retryDelay || 1e3,
1231
- combinedController.signal
1232
- );
1233
- }
1234
- return await fetchPromise();
1235
- } catch (error) {
1236
- const apiError = this.errorNormalizer.normalizeError(
1237
- error,
1238
- config,
1239
- correlationId
1240
- );
1241
- if (config.throwErrors !== false) {
1242
- await this.interceptorManager.applyErrorInterceptors(apiError);
1243
- throw apiError;
1244
- } else {
1245
- return {
1246
- error: apiError
1247
- };
1248
- }
1249
- } finally {
1250
- this.requestManager.remove(requestKey);
1251
- }
1252
- }
1253
- /**
1254
- * Performs a GET request
1255
- * @template T - The expected response data type
1256
- * @param endpoint - API endpoint
1257
- * @param config - Optional request configuration
1258
- * @returns Promise resolving to ApiResponse
1259
- *
1260
- * @example
1261
- * ```typescript
1262
- * const { apiData, error } = await client.get<User[]>('/users', {
1263
- * params: { active: true },
1264
- * timeout: 5000
1265
- * });
1266
- * ```
1267
- */
1268
- get(endpoint, config) {
1269
- return this.request(endpoint, { ...config, method: "GET" });
1270
- }
1271
- /**
1272
- * Performs a POST request
1273
- * @template T - The expected response data type
1274
- * @template TData - The request body data type
1275
- * @param endpoint - API endpoint
1276
- * @param data - Request body data
1277
- * @param config - Optional request configuration
1278
- * @returns Promise resolving to ApiResponse
1279
- *
1280
- * @example
1281
- * ```typescript
1282
- * const { apiData, error } = await client.post<User, CreateUserDto>('/users', {
1283
- * name: 'John Doe',
1284
- * email: 'john@example.com'
1285
- * });
1286
- * ```
1287
- */
1288
- post(endpoint, data, config) {
1289
- return this.request(endpoint, { ...config, method: "POST", body: data });
1290
- }
1291
- /**
1292
- * Performs a PUT request
1293
- * @template T - The expected response data type
1294
- * @template TData - The request body data type
1295
- * @param endpoint - API endpoint
1296
- * @param data - Request body data
1297
- * @param config - Optional request configuration
1298
- * @returns Promise resolving to ApiResponse
1299
- *
1300
- * @example
1301
- * ```typescript
1302
- * const { apiData, error } = await client.put<User, UpdateUserDto>(
1303
- * '/users/123',
1304
- * { name: 'Jane Doe' }
1305
- * );
1306
- * ```
1307
- */
1308
- put(endpoint, data, config) {
1309
- return this.request(endpoint, { ...config, method: "PUT", body: data });
1310
- }
1311
- /**
1312
- * Performs a PATCH request
1313
- * @template T - The expected response data type
1314
- * @template TData - The request body data type
1315
- * @param endpoint - API endpoint
1316
- * @param data - Request body data
1317
- * @param config - Optional request configuration
1318
- * @returns Promise resolving to ApiResponse
1319
- *
1320
- * @example
1321
- * ```typescript
1322
- * const { apiData, error } = await client.patch<User>(
1323
- * '/users/123',
1324
- * { status: 'active' }
1325
- * );
1326
- * ```
1327
- */
1328
- patch(endpoint, data, config) {
1329
- return this.request(endpoint, {
1330
- ...config,
1331
- method: "PATCH",
1332
- body: data
1333
- });
1334
- }
1335
- /**
1336
- * Performs a DELETE request
1337
- * @template T - The expected response data type
1338
- * @param endpoint - API endpoint
1339
- * @param config - Optional request configuration
1340
- * @returns Promise resolving to ApiResponse
1341
- *
1342
- * @example
1343
- * ```typescript
1344
- * const { error } = await client.delete('/users/123');
1345
- * if (!error) {
1346
- * console.log('User deleted successfully');
1347
- * }
1348
- * ```
1349
- */
1350
- delete(endpoint, config) {
1351
- return this.request(endpoint, { ...config, method: "DELETE" });
1352
- }
1353
- /**
1354
- * Performs a filtered list request with pagination and sorting
1355
- * @template TListModel - The type of individual list items
1356
- * @template TFilter - The filter criteria type
1357
- * @param url - API endpoint
1358
- * @param data - Pagination and filter data
1359
- * @param config - Optional request configuration
1360
- * @returns Promise resolving to paginated list response
1361
- *
1362
- * @example
1363
- * ```typescript
1364
- * const { apiData, error } = await client.filter<User, UserFilter>(
1365
- * '/users/filter',
1366
- * {
1367
- * pageOffset: 0,
1368
- * pageSize: 20,
1369
- * sortField: 'createdAt',
1370
- * sortOrder: 'desc',
1371
- * filterModel: { status: 'active' }
1372
- * }
1373
- * );
1374
- *
1375
- * if (apiData) {
1376
- * console.log(`Found ${apiData.Total} users`);
1377
- * console.log('Users:', apiData.Data);
1378
- * }
1379
- * ```
1380
- */
1381
- filter(url, data, config) {
1382
- const mergedData = { ...data, ...data.filterModel };
1383
- return this.request(url, {
1384
- ...config,
1385
- method: "POST",
1386
- body: mergedData
1387
- });
1388
- }
1389
- };
1390
-
1391
- // src/core/api/createApiClient.ts
1392
- var globalApiClient = null;
1393
- function createApiClient(config = {}) {
1394
- const {
1395
- baseURL = "",
1396
- timeout = 3e4,
1397
- correlationIdPrefix = "web",
1398
- includeCorrelationId = true,
1399
- requestInterceptors = [],
1400
- responseInterceptors = [],
1401
- errorInterceptors = []
1402
- } = config;
1403
- const client = new ApiClient(baseURL, timeout);
1404
- client.addRequestInterceptor((config2) => {
1405
- const token = localStorage.getItem("serviceToken");
1406
- if (token && !config2.skipAuthRefresh) {
1407
- config2.headers = {
1408
- ...config2.headers,
1409
- Authorization: `Bearer ${token}`
1410
- };
1411
- }
1412
- return config2;
1413
- });
1414
- client.setCorrelationIdPrefix(correlationIdPrefix);
1415
- client.setIncludeCorrelationId(includeCorrelationId);
1416
- requestInterceptors.forEach((interceptor) => {
1417
- client.addRequestInterceptor(interceptor);
1418
- });
1419
- responseInterceptors.forEach((interceptor) => {
1420
- client.addResponseInterceptor(interceptor);
1421
- });
1422
- errorInterceptors.forEach((interceptor) => {
1423
- client.addErrorInterceptor(interceptor);
1424
- });
1425
- return client;
1426
- }
1427
- function getGlobalApiClient(config) {
1428
- if (!globalApiClient) {
1429
- globalApiClient = createApiClient(config);
1430
- }
1431
- return globalApiClient;
1432
- }
1433
- function setGlobalApiClient(client) {
1434
- globalApiClient = client;
1435
- }
1436
- function resetGlobalApiClient() {
1437
- globalApiClient = null;
1438
- }
1439
-
1440
- // src/core/api/types/CancelToken.ts
1441
- var CancelToken = class _CancelToken {
1442
- abortController;
1443
- cancelPromise;
1444
- cancelResolve;
1445
- constructor() {
1446
- this.abortController = new AbortController();
1447
- this.cancelPromise = new Promise((resolve) => {
1448
- this.cancelResolve = resolve;
1449
- });
1450
- }
1451
- get signal() {
1452
- return this.abortController.signal;
1453
- }
1454
- cancel(reason) {
1455
- this.abortController.abort(reason);
1456
- this.cancelResolve?.();
1457
- }
1458
- get isCancelled() {
1459
- return this.abortController.signal.aborted;
1460
- }
1461
- throwIfCancelled() {
1462
- if (this.isCancelled) {
1463
- throw new Error("Request cancelled");
1464
- }
1465
- }
1466
- static source() {
1467
- const token = new _CancelToken();
1468
- return {
1469
- token,
1470
- cancel: (reason) => token.cancel(reason)
1471
- };
1472
- }
1473
- };
1474
-
1475
- // src/core/api/useValidationErrors.ts
1476
- import { useCallback } from "react";
1477
- function useValidationErrors(error) {
1478
- const getFieldError = useCallback(
1479
- (field) => {
1480
- if (!error?.errors || !error.errors[field]) return null;
1481
- const fieldError = error.errors[field];
1482
- if (typeof fieldError === "string") return fieldError;
1483
- if (Array.isArray(fieldError)) return fieldError[0];
1484
- if (typeof fieldError === "object" && "message" in fieldError) {
1485
- return fieldError.message;
1486
- }
1487
- return null;
1488
- },
1489
- [error]
1490
- );
1491
- const hasFieldError = useCallback(
1492
- (field) => {
1493
- return !!getFieldError(field);
1494
- },
1495
- [getFieldError]
1496
- );
1497
- const getAllErrors = useCallback(() => {
1498
- if (!error?.errors) return {};
1499
- const result = {};
1500
- Object.entries(error.errors).forEach(([key, value]) => {
1501
- if (typeof value === "string") {
1502
- result[key] = value;
1503
- } else if (Array.isArray(value)) {
1504
- result[key] = value.join(", ");
1505
- } else if (typeof value === "object" && value && "message" in value) {
1506
- result[key] = value.message;
1507
- }
1508
- });
1509
- return result;
1510
- }, [error]);
1511
- return {
1512
- getFieldError,
1513
- hasFieldError,
1514
- getAllErrors,
1515
- hasErrors: error?.errors
1516
- };
1517
- }
1518
-
1519
- // src/core/components/AuthorizedView/AuthorizedView.tsx
1520
- import { Fragment, jsx } from "react/jsx-runtime";
1521
- var AuthorizedView = ({ children, show }) => {
1522
- if (!show) return /* @__PURE__ */ jsx(Fragment, {});
1523
- return /* @__PURE__ */ jsx(Fragment, { children });
1524
- };
1525
-
1526
- // src/core/components/CancelButton/CancelButton.tsx
1527
- import { Button } from "@mui/material";
1528
- import { jsx as jsx2 } from "react/jsx-runtime";
1529
- var CancelButton = ({
1530
- children = "Cancel",
1531
- variant = "outlined",
1532
- sx,
1533
- ...rest
1534
- }) => /* @__PURE__ */ jsx2(Button, { variant, sx: { width: "6rem", ...sx }, ...rest, children });
1535
-
1536
- // src/core/components/ClearButton/ClearButton.tsx
1537
- import { Button as Button2 } from "@mui/material";
1538
- import { jsx as jsx3 } from "react/jsx-runtime";
1539
- var ClearButton = ({
1540
- isSubmitting,
1541
- handleClear,
1542
- sx,
1543
- storeKey
1544
- }) => {
1545
- const onClick = () => {
1546
- handleClear();
1547
- if (storeKey != null) {
1548
- localStorage.removeItem(storeKey);
1549
- }
1550
- };
1551
- return /* @__PURE__ */ jsx3(
1552
- Button2,
1553
- {
1554
- variant: "outlined",
1555
- onClick,
1556
- disabled: isSubmitting,
1557
- sx,
1558
- children: "Clear"
1559
- }
1560
- );
1561
- };
1562
-
1563
- // src/core/components/Containers/SimpleContainer.tsx
1564
- import { Container } from "@mui/material";
1565
- import { jsx as jsx4 } from "react/jsx-runtime";
1566
- var SimpleContainer = ({
1567
- children,
1568
- className,
1569
- sx
1570
- }) => /* @__PURE__ */ jsx4(Container, { className, sx: { ...sx }, children });
1571
-
1572
- // src/core/components/FilterButton/FilterButton.tsx
1573
- import FilterAltIcon from "@mui/icons-material/FilterAlt";
1574
- import { LoadingButton } from "@mui/lab";
1575
- import { Badge } from "@mui/material";
1576
- import { jsx as jsx5 } from "react/jsx-runtime";
1577
- var FilterButton = ({
1578
- isSubmitting,
1579
- show,
1580
- title,
1581
- icon,
1582
- sx,
1583
- iconSx
1584
- }) => {
1585
- return /* @__PURE__ */ jsx5(
1586
- LoadingButton,
1587
- {
1588
- type: "submit",
1589
- variant: "contained",
1590
- loading: isSubmitting,
1591
- disabled: !show,
1592
- disableRipple: true,
1593
- color: "primary",
1594
- sx: {
1595
- display: "flex",
1596
- alignItems: "center",
1597
- ...sx
1598
- },
1599
- startIcon: /* @__PURE__ */ jsx5(Badge, { color: "error", variant: "standard", children: icon ? icon : /* @__PURE__ */ jsx5(FilterAltIcon, { width: "20", height: "20", sx: iconSx }) }),
1600
- children: title?.trim() === "" || !title ? "Filter" : title
1601
- }
1602
- );
1603
- };
1604
-
1605
- // src/core/components/FilterDisplay/FilterChip.tsx
1606
- import Chip from "@mui/material/Chip";
1607
- import { memo } from "react";
1608
- import { jsx as jsx6 } from "react/jsx-runtime";
1609
- var FilterChip = memo(
1610
- ({
1611
- fieldKey,
1612
- filter,
1613
- onDelete
1614
- }) => {
1615
- const hasValue = filter.Value !== null && filter.Value !== void 0 && filter.Value !== "";
1616
- const label = `${fieldKey.replace("PK", "")}: ${filter.Label}`;
1617
- return /* @__PURE__ */ jsx6(
1618
- Chip,
1619
- {
1620
- label,
1621
- variant: hasValue ? "filled" : "outlined",
1622
- size: "small",
1623
- onDelete: hasValue ? onDelete : void 0
1624
- },
1625
- fieldKey
1626
- );
1627
- }
1628
- );
1629
- FilterChip.displayName = "FilterChip";
1630
-
1631
- // src/core/components/FilterDisplay/FilterDisplay.tsx
1632
- import { Card, CardContent, Typography, Box } from "@mui/material";
1633
- import { memo as memo2, useMemo } from "react";
1634
- import { jsx as jsx7, jsxs } from "react/jsx-runtime";
1635
- var ProgramsFilterDisplay = memo2(
1636
- (props) => {
1637
- const { friendlyFilter, onFriendlyFilterChange } = props;
1638
- const deleteHandlers = useMemo(() => {
1639
- if (!onFriendlyFilterChange) return {};
1640
- const handlers = {};
1641
- for (const key of Object.keys(friendlyFilter)) {
1642
- handlers[key] = () => onFriendlyFilterChange(key);
1643
- }
1644
- return handlers;
1645
- }, [onFriendlyFilterChange, friendlyFilter]);
1646
- const chipList = useMemo(() => {
1647
- return Object.entries(friendlyFilter).map(([key, filter]) => /* @__PURE__ */ jsx7(
1648
- FilterChip,
1649
- {
1650
- fieldKey: key,
1651
- filter,
1652
- onDelete: deleteHandlers[key]
1653
- },
1654
- key
1655
- ));
1656
- }, [friendlyFilter, deleteHandlers]);
1657
- return /* @__PURE__ */ jsx7(Card, { sx: { mb: 2 }, children: /* @__PURE__ */ jsxs(CardContent, { children: [
1658
- /* @__PURE__ */ jsx7(Typography, { variant: "h6", gutterBottom: true, children: "Active Filters" }),
1659
- /* @__PURE__ */ jsx7(Box, { display: "flex", gap: 1, flexWrap: "wrap", children: chipList })
1660
- ] }) });
1661
- }
1662
- );
1663
- ProgramsFilterDisplay.displayName = "FilterDisplay";
1664
-
1665
- // src/core/components/FilterWrapper/FilterWrapper.tsx
1666
- import ManageSearchIcon from "@mui/icons-material/ManageSearch";
1667
- import {
1668
- Box as Box2,
1669
- Card as Card2,
1670
- CardContent as CardContent2,
1671
- CardHeader,
1672
- Divider,
1673
- Grid,
1674
- Typography as Typography2,
1675
- useTheme
1676
- } from "@mui/material";
1677
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
1678
- var FilterWrapper = ({
1679
- children,
1680
- title,
1681
- filterCount,
1682
- cardSx,
1683
- textSx,
1684
- icon,
1685
- iconSx,
1686
- showCount
1687
- }) => {
1688
- const theme = useTheme();
1689
- return /* @__PURE__ */ jsxs2(
1690
- Card2,
1691
- {
1692
- sx: {
1693
- position: "relative",
1694
- borderRadius: "0px",
1695
- mb: 2,
1696
- ...cardSx
1697
- },
1698
- children: [
1699
- /* @__PURE__ */ jsx8(
1700
- CardHeader,
1701
- {
1702
- sx: {
1703
- display: "flex",
1704
- flexWrap: "wrap",
1705
- p: "1rem",
1706
- ".MuiCardHeader-action": {
1707
- margin: 0,
1708
- alignSelf: "center"
1709
- },
1710
- alignItems: "center"
1711
- },
1712
- title: /* @__PURE__ */ jsxs2(Box2, { sx: { display: "flex", alignItems: "center", gap: 0.5 }, children: [
1713
- icon ? icon : /* @__PURE__ */ jsx8(
1714
- ManageSearchIcon,
1715
- {
1716
- sx: {
1717
- height: "2.5rem",
1718
- color: theme.palette.primary.main,
1719
- ...iconSx
1720
- }
1721
- }
1722
- ),
1723
- /* @__PURE__ */ jsxs2(
1724
- Typography2,
1725
- {
1726
- variant: "h5",
1727
- sx: {
1728
- fontWeight: "bold",
1729
- color: theme.palette.primary.main,
1730
- ...textSx
1731
- },
1732
- children: [
1733
- title ? title : "Filter",
1734
- " ",
1735
- showCount ? `(${filterCount ? filterCount : 0})` : /* @__PURE__ */ jsx8(Fragment2, {})
1736
- ]
1737
- }
1738
- )
1739
- ] })
1740
- }
1741
- ),
1742
- /* @__PURE__ */ jsx8(Divider, {}),
1743
- /* @__PURE__ */ jsx8(CardContent2, { sx: { py: 2 }, children: /* @__PURE__ */ jsx8(Grid, { container: true, spacing: 2, children }) })
1744
- ]
1745
- }
1746
- );
1747
- };
1748
-
1749
- // src/core/components/Footer/Footer.tsx
1750
- import { Box as Box3, Typography as Typography3 } from "@mui/material";
1751
- import { jsx as jsx9 } from "react/jsx-runtime";
1752
- var Footer = () => {
1753
- const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
1754
- return /* @__PURE__ */ jsx9(
1755
- Box3,
1756
- {
1757
- component: "footer",
1758
- sx: {
1759
- py: 2,
1760
- px: 4,
1761
- mt: "auto",
1762
- backgroundColor: (theme) => theme.palette.mode === "light" ? theme.palette.grey[200] : theme.palette.grey[800]
1763
- },
1764
- children: /* @__PURE__ */ jsx9(Typography3, { variant: "body2", color: "text.secondary", align: "center", children: `\xA9 Copyright ${currentYear} GN. All rights reserved by Parul University.` })
1765
- }
1766
- );
1767
- };
1768
-
1769
- // src/core/components/LabelText/LabelText.tsx
1770
- import { Grid as Grid2, Tooltip, Typography as Typography4 } from "@mui/material";
1771
- import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
1772
- var LabelText = ({
1773
- label,
1774
- value,
1775
- gridSize,
1776
- containerSize,
1777
- labelSx,
1778
- valueSx
1779
- }) => {
1780
- const defaultGridSize = {
1781
- labelSize: { xs: 6, sm: 6, md: 6 },
1782
- valueSize: { xs: 12, sm: 6, md: 6 }
1783
- };
1784
- const defaultContainerSize = { xs: 12, sm: 6, md: 6 };
1785
- const size = gridSize || defaultGridSize;
1786
- const container = containerSize || defaultContainerSize;
1787
- return /* @__PURE__ */ jsxs3(
1788
- Grid2,
1789
- {
1790
- size: container,
1791
- sx: {
1792
- display: "flex",
1793
- flexDirection: { xs: "column", sm: "row", md: "row" },
1794
- "&:hover": { bgcolor: "#efefef", overflow: "hidden" }
1795
- },
1796
- children: [
1797
- /* @__PURE__ */ jsxs3(
1798
- Grid2,
1799
- {
1800
- size: size.labelSize,
1801
- sx: {
1802
- padding: "5px",
1803
- fontSize: "14px",
1804
- textAlign: { xs: "left", sm: "right", md: "right" },
1805
- ...labelSx
1806
- },
1807
- children: [
1808
- label,
1809
- " :"
1810
- ]
1811
- }
1812
- ),
1813
- /* @__PURE__ */ jsx10(
1814
- Grid2,
1815
- {
1816
- size: size.valueSize,
1817
- sx: { padding: "5px", display: "flex", flexWrap: "wrap" },
1818
- children: /* @__PURE__ */ jsx10(Tooltip, { title: value, arrow: true, children: /* @__PURE__ */ jsx10(
1819
- Typography4,
1820
- {
1821
- sx: {
1822
- fontSize: "14px",
1823
- wordBreak: "break-word",
1824
- overflow: "hidden",
1825
- display: "-webkit-box",
1826
- textOverflow: "ellipsis",
1827
- WebkitLineClamp: 2,
1828
- WebkitBoxOrient: "vertical",
1829
- ...valueSx,
1830
- color: "#078dee"
1831
- },
1832
- children: value ? value : "-"
1833
- }
1834
- ) })
1835
- }
1836
- )
1837
- ]
1838
- }
1839
- );
1840
- };
1841
-
1842
- // src/core/components/RenderIf/RenderIf.tsx
1843
- import { Fragment as Fragment3, jsx as jsx11 } from "react/jsx-runtime";
1844
- var RenderIf = ({
1845
- show,
1846
- children
1847
- }) => {
1848
- return show ? /* @__PURE__ */ jsx11(Fragment3, { children }) : null;
1849
- };
1850
-
1851
- // src/core/components/SectionBox/SectionBox.tsx
1852
- import { Box as Box4, Divider as Divider2, Grid as Grid3, Stack, Typography as Typography5 } from "@mui/material";
1853
- import { memo as memo3, useMemo as useMemo2 } from "react";
1854
- import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
1855
- var getSectionTheme = (variant = "default") => {
1856
- const themes = {
1857
- default: {
1858
- bgcolor: "#faebd7",
1859
- color: "#925d21"
1860
- },
1861
- form: {
1862
- bgcolor: "#cdced1",
1863
- color: "black"
1864
- },
1865
- info: {
1866
- bgcolor: "#e3f2fd",
1867
- color: "#1976d2"
1868
- },
1869
- warning: {
1870
- bgcolor: "#fff3e0",
1871
- color: "#f57c00"
1872
- },
1873
- error: {
1874
- bgcolor: "#ffebee",
1875
- color: "#d32f2f"
1876
- }
1877
- };
1878
- return themes[variant];
1879
- };
1880
- var SectionBox = memo3(
1881
- ({
1882
- title,
1883
- children,
1884
- spacing = 0,
1885
- containerSx,
1886
- titleSx,
1887
- variant = "default",
1888
- icon,
1889
- actions
1890
- }) => {
1891
- const themeColors = useMemo2(() => getSectionTheme(variant), [variant]);
1892
- const headerSx = useMemo2(
1893
- () => ({
1894
- px: 1.5,
1895
- py: 0.1,
1896
- width: "fit-content",
1897
- ...themeColors,
1898
- ...titleSx
1899
- }),
1900
- [themeColors, titleSx]
1901
- );
1902
- const contentSx = useMemo2(
1903
- () => ({
1904
- padding: "16px",
1905
- ...containerSx
1906
- }),
1907
- [containerSx]
1908
- );
1909
- return /* @__PURE__ */ jsxs4(Fragment4, { children: [
1910
- /* @__PURE__ */ jsxs4(Box4, { sx: { display: "flex", flexDirection: "column", width: "100%" }, children: [
1911
- /* @__PURE__ */ jsxs4(
1912
- Stack,
1913
- {
1914
- direction: "row",
1915
- justifyContent: "space-between",
1916
- alignItems: "center",
1917
- sx: headerSx,
1918
- children: [
1919
- /* @__PURE__ */ jsxs4(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [
1920
- icon,
1921
- /* @__PURE__ */ jsx12(Typography5, { sx: { fontSize: "15px", fontWeight: 400 }, children: title })
1922
- ] }),
1923
- actions
1924
- ]
1925
- }
1926
- ),
1927
- /* @__PURE__ */ jsx12(Divider2, {})
1928
- ] }),
1929
- /* @__PURE__ */ jsx12(Grid3, { container: true, spacing, sx: contentSx, children })
1930
- ] });
1931
- }
1932
- );
1933
-
1934
- // src/core/components/SimpleTabs/SimpleTabs.tsx
1935
- import { TabContext } from "@mui/lab";
1936
- import { Box as Box5, Tab, Tabs } from "@mui/material";
1937
- import { useState } from "react";
1938
- import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
1939
- var SimpleTabs = ({
1940
- tabs,
1941
- defaultValue = 1,
1942
- onTabChange,
1943
- children,
1944
- tabSx,
1945
- tabsSx
1946
- }) => {
1947
- const [value, setValue] = useState(defaultValue);
1948
- const handleChange = (event, newValue) => {
1949
- setValue(newValue);
1950
- if (onTabChange) onTabChange(newValue);
1951
- };
1952
- return /* @__PURE__ */ jsxs5(TabContext, { value, children: [
1953
- /* @__PURE__ */ jsx13(Box5, { sx: { borderBottom: 1, borderColor: "divider", width: "100%" }, children: /* @__PURE__ */ jsx13(
1954
- Tabs,
1955
- {
1956
- value,
1957
- onChange: handleChange,
1958
- sx: { px: 2, py: 0, ...tabsSx },
1959
- children: tabs.map((tab) => /* @__PURE__ */ jsx13(
1960
- Tab,
1961
- {
1962
- label: tab.label,
1963
- value: tab.value,
1964
- disabled: tab.permission === false,
1965
- sx: { fontSize: "1rem", ...tabSx }
1966
- },
1967
- tab.value
1968
- ))
1969
- }
1970
- ) }),
1971
- children
1972
- ] });
1973
- };
1974
-
1975
- // src/core/components/SubmitButton/SubmitButton.tsx
1976
- import { LoadingButton as LoadingButton2 } from "@mui/lab";
1977
- import { jsx as jsx14 } from "react/jsx-runtime";
1978
- var SubmitButton = ({
1979
- loading = false,
1980
- ...rest
1981
- }) => /* @__PURE__ */ jsx14(
1982
- LoadingButton2,
1983
- {
1984
- loading,
1985
- variant: "contained",
1986
- color: "primary",
1987
- type: "submit",
1988
- ...rest,
1989
- sx: { fontWeight: 400 },
1990
- children: "Submit"
1991
- }
1992
- );
1993
-
1994
- // src/core/components/WithRef/WithRef.tsx
1995
- import { forwardRef } from "react";
1996
- function withDataModal(component) {
1997
- return forwardRef(
1998
- (props, ref) => component({ ...props, ref })
1999
- );
2000
- }
2001
-
2002
- // src/core/config.ts
2003
- var Config = {
2004
- defaultPageSize: 20,
2005
- apiBaseUrl: "http://localhost:5143"
2006
- // apiBaseUrl: 'http://192.168.1.246:5143',
2007
- };
2008
- var dateTimePatterns = {
2009
- dateTime: "DD MMM YYYY h:mm A",
2010
- // 17 Apr 2022 12:00 am
2011
- date: "DD MMM YYYY",
2012
- // 17 Apr 2022
2013
- month_year_short_format: "MMM YYYY",
2014
- month_year_full_format: "MMMM YYYY",
2015
- year: "YYYY",
2016
- time: "h:mm a",
2017
- // 12:00 am
2018
- split: {
2019
- dateTime: "DD/MM/YYYY h:mm A",
2020
- // 17/04/2022 12:00 am
2021
- date: "DD/MM/YYYY"
2022
- // 17/04/2022
2023
- },
2024
- paramCase: {
2025
- dateTime: "DD-MM-YYYY h:mm A",
2026
- // 17-04-2022 12:00 am
2027
- date: "DD-MM-YYYY",
2028
- // 17-04-2022
2029
- dateReverse: "YYYY-MM-DD",
2030
- // 2022-04-17 for compare date
2031
- MonthYear: "MMM-YYYY"
2032
- }
2033
- };
2034
-
2035
- // src/core/hooks/useApiClient.ts
2036
- import { useMemo as useMemo3 } from "react";
2037
- function useApiClient(config = {}) {
2038
- return useMemo3(
2039
- () => createApiClient(config),
2040
- // eslint-disable-next-line react-hooks/exhaustive-deps
2041
- [
2042
- config.baseURL,
2043
- config.timeout,
2044
- config.correlationIdPrefix,
2045
- config.includeCorrelationId,
2046
- config.authToken,
2047
- config.requestInterceptors,
2048
- config.responseInterceptors,
2049
- config.errorInterceptors
2050
- ]
2051
- );
2052
- }
2053
-
2054
- // src/core/hooks/useFormErrorHandler.ts
2055
- import { useCallback as useCallback2 } from "react";
2056
- import { toast } from "sonner";
2057
- var useFormErrorHandler = ({
2058
- setError,
2059
- successMessage = {
2060
- create: "Created successfully",
2061
- update: "Updated successfully"
2062
- },
2063
- errorMessage = {
2064
- noChanges: "No changes were made",
2065
- general: "Failed to save. Please try again."
2066
- }
2067
- }) => {
2068
- const getFieldError = useCallback2(
2069
- (fields, fieldName) => {
2070
- if (!fields || !fields[fieldName]) return void 0;
2071
- const fieldError = fields[fieldName];
2072
- if (typeof fieldError === "string") {
2073
- return fieldError;
2074
- }
2075
- if (Array.isArray(fieldError)) {
2076
- return fieldError.join(", ");
2077
- }
2078
- if (typeof fieldError === "object" && "message" in fieldError) {
2079
- return fieldError.message;
2080
- }
2081
- return void 0;
2082
- },
2083
- []
2084
- );
2085
- const handleSuccess = useCallback2(
2086
- (isEditing, rowsAffected) => {
2087
- if (rowsAffected !== void 0 && rowsAffected > 0) {
2088
- toast.success(
2089
- isEditing ? successMessage.update : successMessage.create
2090
- );
2091
- return true;
2092
- } else if (rowsAffected === 0) {
2093
- toast.error(errorMessage.noChanges);
2094
- return false;
2095
- }
2096
- toast.success(isEditing ? successMessage.update : successMessage.create);
2097
- return true;
2098
- },
2099
- [successMessage, errorMessage]
2100
- );
2101
- const handleError = useCallback2(
2102
- (processedError) => {
2103
- if (processedError.type === "validation_error" && processedError.errors && setError) {
2104
- Object.keys(processedError.errors).forEach((fieldName) => {
2105
- const fieldError = getFieldError(processedError.errors, fieldName);
2106
- if (fieldError) {
2107
- setError(fieldName, {
2108
- type: "server",
2109
- message: fieldError
2110
- });
2111
- }
2112
- });
2113
- toast.error(
2114
- processedError.title || "Please check the form for validation errors"
2115
- );
2116
- } else {
2117
- toast.error(processedError.title || errorMessage.general);
2118
- }
2119
- },
2120
- [errorMessage.general, getFieldError, setError]
2121
- );
2122
- return {
2123
- handleSuccess,
2124
- handleError
2125
- };
2126
- };
2127
- var useDeleteHandler = ({
2128
- successMessage = "Deleted successfully",
2129
- errorMessage = "Failed to delete. Please try again."
2130
- } = {}) => {
2131
- return useFormErrorHandler({
2132
- successMessage: {
2133
- create: successMessage,
2134
- // Not used for delete, but required for type
2135
- update: successMessage
2136
- },
2137
- errorMessage: {
2138
- noChanges: "No changes were made",
2139
- // Not typically used for delete
2140
- general: errorMessage
2141
- }
2142
- // setError is omitted (undefined) for delete operations
2143
- });
2144
- };
2145
-
2146
- // src/core/utils/CacheUtility/index.ts
2147
- import { useQueryClient } from "@tanstack/react-query";
2148
- import { useMemo as useMemo4 } from "react";
2149
- var CacheUtility = class {
2150
- constructor(queryClient) {
2151
- this.queryClient = queryClient;
2152
- }
2153
- /**
2154
- * Get cached data using only the queryKey from query factory
2155
- */
2156
- getCachedData(queryKey) {
2157
- return this.queryClient.getQueryData(queryKey);
2158
- }
2159
- /**
2160
- * Get cached data with transformation using select function
2161
- */
2162
- getCachedDataWithSelect(queryKey, select) {
2163
- const cachedData = this.queryClient.getQueryData(queryKey);
2164
- if (cachedData === void 0) {
2165
- return void 0;
2166
- }
2167
- return select(cachedData);
2168
- }
2169
- };
2170
- function useCacheUtility() {
2171
- const queryClient = useQueryClient();
2172
- return useMemo4(() => new CacheUtility(queryClient), [queryClient]);
2173
- }
2174
-
2175
- // src/core/utils/watch/core.ts
2176
- import { useWatch } from "react-hook-form";
2177
- var useWatchForm = (control) => useWatch({ control });
2178
- var useWatchField = (control, name) => useWatch({ control, name });
2179
- var useWatchFields = (control, names) => useWatch({ control, name: names });
2180
-
2181
- // src/core/utils/watch/utilities.ts
2182
- import { useEffect, useMemo as useMemo5, useState as useState2 } from "react";
2183
- import { useWatch as useWatch2 } from "react-hook-form";
2184
- var useWatchTransform = (control, name, transform) => {
2185
- const value = useWatch2({ control, name });
2186
- return useMemo5(() => transform(value), [value, transform]);
2187
- };
2188
- var useWatchDefault = (control, name, defaultValue) => {
2189
- const value = useWatch2({ control, name });
2190
- return value ?? defaultValue;
2191
- };
2192
- var useWatchBoolean = (control, name, defaultValue = false) => {
2193
- const value = useWatch2({ control, name });
2194
- return Boolean(value ?? defaultValue);
2195
- };
2196
- var useWatchBatch = (control, fields) => {
2197
- const values = useWatch2({ control, name: fields });
2198
- return useMemo5(() => {
2199
- const result = {};
2200
- fields.forEach((field, index) => {
2201
- result[field] = values[index];
2202
- });
2203
- return result;
2204
- }, [values, fields]);
2205
- };
2206
- var useWatchConditional = (control, name, shouldWatch, fallback) => {
2207
- const activeValue = useWatch2({
2208
- control,
2209
- name,
2210
- disabled: !shouldWatch
2211
- });
2212
- return shouldWatch ? activeValue : fallback;
2213
- };
2214
- var useWatchDebounced = (control, name, delay = 300) => {
2215
- const value = useWatch2({ control, name });
2216
- const [debouncedValue, setDebouncedValue] = useState2(value);
2217
- useEffect(() => {
2218
- const timer = setTimeout(() => {
2219
- setDebouncedValue(value);
2220
- }, delay);
2221
- return () => clearTimeout(timer);
2222
- }, [value, delay]);
2223
- return debouncedValue;
2224
- };
2225
- var useWatchSelector = (control, name, selector, deps = []) => {
2226
- const value = useWatch2({ control, name });
2227
- return useMemo5(
2228
- () => selector(value),
2229
- [value, selector, ...deps]
2230
- // eslint-disable-line react-hooks/exhaustive-deps
2231
- );
2232
- };
2233
-
2234
- // src/core/utils/watch/index.ts
2235
- var typedWatch = {
2236
- // === CORE FUNCTIONS ===
2237
- /** Watch entire form */
2238
- form: useWatchForm,
2239
- /** Watch single field */
2240
- field: useWatchField,
2241
- /** Watch multiple fields */
2242
- fields: useWatchFields,
2243
- // === UTILITY FUNCTIONS ===
2244
- /** Watch with transformation */
2245
- transform: useWatchTransform,
2246
- /** Watch with default value */
2247
- withDefault: useWatchDefault,
2248
- /** Watch as boolean */
2249
- boolean: useWatchBoolean,
2250
- /** Watch multiple with custom keys */
2251
- batch: useWatchBatch,
2252
- /** Watch conditionally */
2253
- conditional: useWatchConditional,
2254
- /** Watch with debouncing */
2255
- debounced: useWatchDebounced,
2256
- /** Watch with selector */
2257
- selector: useWatchSelector
2258
- };
2259
-
2260
- // src/core/utils/calculateFilterCount.ts
2261
- var calculateFilterCount = (model) => Object.values(model).filter(
2262
- (v) => v !== null && v !== void 0 && String(v).trim() !== ""
2263
- ).length;
2264
-
2265
- // src/core/utils/format-time.ts
2266
- import dayjs from "dayjs";
2267
- import duration from "dayjs/plugin/duration";
2268
- import relativeTime from "dayjs/plugin/relativeTime";
2269
- dayjs.extend(duration);
2270
- dayjs.extend(relativeTime);
2271
- var formatPatterns = {
2272
- dateTime: "DD MMM YYYY h:mm A",
2273
- // 17 Apr 2022 12:00 am
2274
- date: "DD MMM YYYY",
2275
- // 17 Apr 2022
2276
- month_year_short_format: "MMM YYYY",
2277
- month_year_full_format: "MMMM YYYY",
2278
- year: "YYYY",
2279
- time: "h:mm a",
2280
- // 12:00 am
2281
- split: {
2282
- dateTime: "DD/MM/YYYY h:mm A",
2283
- // 17/04/2022 12:00 am
2284
- date: "DD/MM/YYYY"
2285
- // 17/04/2022
2286
- },
2287
- paramCase: {
2288
- dateTime: "DD-MM-YYYY h:mm A",
2289
- // 17-04-2022 12:00 am
2290
- date: "DD-MM-YYYY",
2291
- // 17-04-2022
2292
- dateReverse: "YYYY-MM-DD",
2293
- // 2022-04-17 for compare date
2294
- MonthYear: "MMM-YYYY"
2295
- }
2296
- };
2297
- var isValidDate = (date) => date !== null && date !== void 0 && dayjs(date).isValid();
2298
- function today(template) {
2299
- return dayjs(/* @__PURE__ */ new Date()).startOf("day").format(template);
2300
- }
2301
- function fDateTime(date, template) {
2302
- if (!isValidDate(date)) {
2303
- return "Invalid date";
2304
- }
2305
- return dayjs(date).format(template ?? formatPatterns.dateTime);
2306
- }
2307
- function fDate(date, template) {
2308
- if (!isValidDate(date)) {
2309
- return "Invalid date";
2310
- }
2311
- return dayjs(date).format(template ?? formatPatterns.date);
2312
- }
2313
- function fTime(date, template) {
2314
- if (!isValidDate(date)) {
2315
- return "Invalid date";
2316
- }
2317
- return dayjs(date).format(template ?? formatPatterns.time);
2318
- }
2319
- function fTimestamp(date) {
2320
- if (!isValidDate(date)) {
2321
- return "Invalid date";
2322
- }
2323
- return dayjs(date).valueOf();
2324
- }
2325
- function fToNow(date) {
2326
- if (!isValidDate(date)) {
2327
- return "Invalid date";
2328
- }
2329
- return dayjs(date).toNow(true);
2330
- }
2331
- function fIsBetween(inputDate, startDate, endDate) {
2332
- if (!isValidDate(inputDate) || !isValidDate(startDate) || !isValidDate(endDate)) {
2333
- return false;
2334
- }
2335
- const formattedInputDate = fTimestamp(inputDate);
2336
- const formattedStartDate = fTimestamp(startDate);
2337
- const formattedEndDate = fTimestamp(endDate);
2338
- if (formattedInputDate === "Invalid date" || formattedStartDate === "Invalid date" || formattedEndDate === "Invalid date") {
2339
- return false;
2340
- }
2341
- return formattedInputDate >= formattedStartDate && formattedInputDate <= formattedEndDate;
2342
- }
2343
- function fIsAfter(startDate, endDate) {
2344
- if (!isValidDate(startDate) || !isValidDate(endDate)) {
2345
- return false;
2346
- }
2347
- return dayjs(startDate).isAfter(endDate);
2348
- }
2349
- function fIsSame(startDate, endDate, unitToCompare) {
2350
- if (!isValidDate(startDate) || !isValidDate(endDate)) {
2351
- return false;
2352
- }
2353
- return dayjs(startDate).isSame(endDate, unitToCompare ?? "year");
2354
- }
2355
- function fDateRangeShortLabel(startDate, endDate, initial) {
2356
- if (!isValidDate(startDate) || !isValidDate(endDate) || fIsAfter(startDate, endDate)) {
2357
- return "Invalid date";
2358
- }
2359
- let label = `${fDate(startDate)} - ${fDate(endDate)}`;
2360
- if (initial) {
2361
- return label;
2362
- }
2363
- const isSameYear = fIsSame(startDate, endDate, "year");
2364
- const isSameMonth = fIsSame(startDate, endDate, "month");
2365
- const isSameDay = fIsSame(startDate, endDate, "day");
2366
- if (isSameYear && !isSameMonth) {
2367
- label = `${fDate(startDate, "DD MMM")} - ${fDate(endDate)}`;
2368
- } else if (isSameYear && isSameMonth && !isSameDay) {
2369
- label = `${fDate(startDate, "DD")} - ${fDate(endDate)}`;
2370
- } else if (isSameYear && isSameMonth && isSameDay) {
2371
- label = `${fDate(endDate)}`;
2372
- }
2373
- return label;
2374
- }
2375
- function fAdd({
2376
- years = 0,
2377
- months = 0,
2378
- days = 0,
2379
- hours = 0,
2380
- minutes = 0,
2381
- seconds = 0,
2382
- milliseconds = 0
2383
- }) {
2384
- const result = dayjs().add(
2385
- dayjs.duration({
2386
- years,
2387
- months,
2388
- days,
2389
- hours,
2390
- minutes,
2391
- seconds,
2392
- milliseconds
2393
- })
2394
- ).format();
2395
- return result;
2396
- }
2397
- function fSub({
2398
- years = 0,
2399
- months = 0,
2400
- days = 0,
2401
- hours = 0,
2402
- minutes = 0,
2403
- seconds = 0,
2404
- milliseconds = 0
2405
- }) {
2406
- const result = dayjs().subtract(
2407
- dayjs.duration({
2408
- years,
2409
- months,
2410
- days,
2411
- hours,
2412
- minutes,
2413
- seconds,
2414
- milliseconds
2415
- })
2416
- ).format();
2417
- return result;
2418
- }
2419
-
2420
- // src/core/utils/getEmptyObject.ts
2421
- function getEmptyObject(data, defaultValues = {}) {
2422
- const obj = {};
2423
- for (const key of Object.keys(data)) {
2424
- const value = data[key];
2425
- const type = typeof value;
2426
- if (type === "number") {
2427
- obj[key] = 0;
2428
- } else if (type === "string" || type === "boolean") {
2429
- obj[key] = null;
2430
- } else if (value instanceof Date) {
2431
- obj[key] = null;
2432
- } else {
2433
- obj[key] = null;
2434
- }
2435
- }
2436
- return { ...obj, ...defaultValues };
2437
- }
2438
-
2439
- // src/core/utils/useStableRowCount.ts
2440
- import { useRef, useMemo as useMemo6 } from "react";
2441
- function useStableRowCount(currentTotal) {
2442
- const rowCountRef = useRef(currentTotal || 0);
2443
- const stableRowCount = useMemo6(() => {
2444
- if (currentTotal !== void 0) {
2445
- rowCountRef.current = currentTotal;
2446
- }
2447
- return rowCountRef.current;
2448
- }, [currentTotal]);
2449
- return stableRowCount;
2450
- }
2451
-
2452
- export {
2453
- generateCorrelationId,
2454
- RequestManager,
2455
- ApiClient,
2456
- createApiClient,
2457
- getGlobalApiClient,
2458
- setGlobalApiClient,
2459
- resetGlobalApiClient,
2460
- CancelToken,
2461
- useValidationErrors,
2462
- AuthorizedView,
2463
- CancelButton,
2464
- ClearButton,
2465
- SimpleContainer,
2466
- FilterButton,
2467
- FilterChip,
2468
- ProgramsFilterDisplay,
2469
- FilterWrapper,
2470
- Footer,
2471
- LabelText,
2472
- RenderIf,
2473
- SectionBox,
2474
- SimpleTabs,
2475
- SubmitButton,
2476
- withDataModal,
2477
- Config,
2478
- dateTimePatterns,
2479
- useApiClient,
2480
- useFormErrorHandler,
2481
- useDeleteHandler,
2482
- CacheUtility,
2483
- useCacheUtility,
2484
- useWatchForm,
2485
- useWatchField,
2486
- useWatchFields,
2487
- useWatchTransform,
2488
- useWatchDefault,
2489
- useWatchBoolean,
2490
- useWatchBatch,
2491
- useWatchConditional,
2492
- useWatchDebounced,
2493
- useWatchSelector,
2494
- typedWatch,
2495
- calculateFilterCount,
2496
- formatPatterns,
2497
- today,
2498
- fDateTime,
2499
- fDate,
2500
- fTime,
2501
- fTimestamp,
2502
- fToNow,
2503
- fIsBetween,
2504
- fIsAfter,
2505
- fIsSame,
2506
- fDateRangeShortLabel,
2507
- fAdd,
2508
- fSub,
2509
- getEmptyObject,
2510
- useStableRowCount
2511
- };
2512
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2NvcmUvYXBpL0NvcnJlbGF0aW9uSWRHZW5lcmF0b3IudHMiLCAiLi4vc3JjL2NvcmUvYXBpL0Vycm9ycy9FcnJvck5vcm1hbGl6ZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL0ludGVyY2VwdG9ycy9JbnRlcmNlcHRvck1hbmFnZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL1JlcXVlc3RNYW5hZ2VyLnRzIiwgIi4uL3NyYy9jb3JlL2FwaS9SZXRyeS9SZXRyeUhhbmRsZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL1NpZ25hbHMvU2lnbmFsTWFuYWdlci50cyIsICIuLi9zcmMvY29yZS9hcGkvVXRpbHMvUmVzcG9uc2VQYXJzZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL1V0aWxzL1VybEJ1aWxkZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL0FwaUNsaWVudC50cyIsICIuLi9zcmMvY29yZS9hcGkvY3JlYXRlQXBpQ2xpZW50LnRzIiwgIi4uL3NyYy9jb3JlL2FwaS90eXBlcy9DYW5jZWxUb2tlbi50cyIsICIuLi9zcmMvY29yZS9hcGkvdXNlVmFsaWRhdGlvbkVycm9ycy50cyIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL0F1dGhvcml6ZWRWaWV3L0F1dGhvcml6ZWRWaWV3LnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL0NhbmNlbEJ1dHRvbi9DYW5jZWxCdXR0b24udHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvQ2xlYXJCdXR0b24vQ2xlYXJCdXR0b24udHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvQ29udGFpbmVycy9TaW1wbGVDb250YWluZXIudHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvRmlsdGVyQnV0dG9uL0ZpbHRlckJ1dHRvbi50c3giLCAiLi4vc3JjL2NvcmUvY29tcG9uZW50cy9GaWx0ZXJEaXNwbGF5L0ZpbHRlckNoaXAudHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvRmlsdGVyRGlzcGxheS9GaWx0ZXJEaXNwbGF5LnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL0ZpbHRlcldyYXBwZXIvRmlsdGVyV3JhcHBlci50c3giLCAiLi4vc3JjL2NvcmUvY29tcG9uZW50cy9Gb290ZXIvRm9vdGVyLnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL0xhYmVsVGV4dC9MYWJlbFRleHQudHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvUmVuZGVySWYvUmVuZGVySWYudHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvU2VjdGlvbkJveC9TZWN0aW9uQm94LnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL1NpbXBsZVRhYnMvU2ltcGxlVGFicy50c3giLCAiLi4vc3JjL2NvcmUvY29tcG9uZW50cy9TdWJtaXRCdXR0b24vU3VibWl0QnV0dG9uLnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL1dpdGhSZWYvV2l0aFJlZi50c3giLCAiLi4vc3JjL2NvcmUvY29uZmlnLnRzIiwgIi4uL3NyYy9jb3JlL2hvb2tzL3VzZUFwaUNsaWVudC50cyIsICIuLi9zcmMvY29yZS9ob29rcy91c2VGb3JtRXJyb3JIYW5kbGVyLnRzIiwgIi4uL3NyYy9jb3JlL3V0aWxzL0NhY2hlVXRpbGl0eS9pbmRleC50cyIsICIuLi9zcmMvY29yZS91dGlscy93YXRjaC9jb3JlLnRzIiwgIi4uL3NyYy9jb3JlL3V0aWxzL3dhdGNoL3V0aWxpdGllcy50cyIsICIuLi9zcmMvY29yZS91dGlscy93YXRjaC9pbmRleC50cyIsICIuLi9zcmMvY29yZS91dGlscy9jYWxjdWxhdGVGaWx0ZXJDb3VudC50cyIsICIuLi9zcmMvY29yZS91dGlscy9mb3JtYXQtdGltZS50cyIsICIuLi9zcmMvY29yZS91dGlscy9nZXRFbXB0eU9iamVjdC50cyIsICIuLi9zcmMvY29yZS91dGlscy91c2VTdGFibGVSb3dDb3VudC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXHJcbiAqIEBmaWxlb3ZlcnZpZXcgVXRpbGl0aWVzIGZvciBnZW5lcmF0aW5nIGNvcnJlbGF0aW9uIElEcyBmb3IgZGlzdHJpYnV0ZWQgcmVxdWVzdCB0cmFjaW5nLlxyXG4gKlxyXG4gKiBDb3JyZWxhdGlvbiBJRHMgYXJlIHVuaXF1ZSBpZGVudGlmaWVycyBhdHRhY2hlZCB0byBlYWNoIEFQSSByZXF1ZXN0IHRvIGVuYWJsZVxyXG4gKiB0cmFja2luZyBhbmQgZGVidWdnaW5nIGFjcm9zcyBkaXN0cmlidXRlZCBzeXN0ZW1zLCBtaWNyb3NlcnZpY2VzLCBhbmQgbG9nIGFnZ3JlZ2F0aW9uLlxyXG4gKlxyXG4gKiBAbW9kdWxlIENvcnJlbGF0aW9uSWRHZW5lcmF0b3JcclxuICovXHJcblxyXG4vKipcclxuICogR2VuZXJhdGVzIGEgY3J5cHRvZ3JhcGhpY2FsbHkgcmFuZG9tIFVVSUQgdjQgc3RyaW5nLlxyXG4gKlxyXG4gKiBQcmVmZXJzIG5hdGl2ZSBgY3J5cHRvLnJhbmRvbVVVSUQoKWAgd2hlbiBhdmFpbGFibGUgKG1vZGVybiBicm93c2VycyBhbmQgTm9kZS5qcyAxOSspLFxyXG4gKiBmYWxsaW5nIGJhY2sgdG8gYSBjb21wbGlhbnQgVVVJRCB2NCBpbXBsZW1lbnRhdGlvbiB1c2luZyBgTWF0aC5yYW5kb20oKWAuXHJcbiAqXHJcbiAqIEBpbnRlcm5hbCBUaGlzIGZ1bmN0aW9uIGlzIG5vdCBleHBvcnRlZCBmcm9tIHRoZSBwdWJsaWMgQVBJXHJcbiAqIEByZXR1cm5zIEEgVVVJRCB2NCBzdHJpbmcgaW4gdGhlIGZvcm1hdCBgeHh4eHh4eHgteHh4eC00eHh4LXl4eHgteHh4eHh4eHh4eHh4YFxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBgYGB0eXBlc2NyaXB0XHJcbiAqIGNvbnN0IHV1aWQgPSBnZW5lcmF0ZVVVSUQoKTtcclxuICogLy8gPT4gXCJhMWIyYzNkNC1lNWY2LTQ3ODktYTAxMi1iM2M0ZDVlNmY3YThcIlxyXG4gKiBgYGBcclxuICovXHJcbmZ1bmN0aW9uIGdlbmVyYXRlVVVJRCgpOiBzdHJpbmcge1xyXG4gIGlmICh0eXBlb2YgY3J5cHRvICE9PSAndW5kZWZpbmVkJyAmJiBjcnlwdG8ucmFuZG9tVVVJRCkge1xyXG4gICAgcmV0dXJuIGNyeXB0by5yYW5kb21VVUlEKCk7XHJcbiAgfVxyXG5cclxuICAvLyBGYWxsYmFjayBVVUlEIHY0IGdlbmVyYXRvclxyXG4gIHJldHVybiAneHh4eHh4eHgteHh4eC00eHh4LXl4eHgteHh4eHh4eHh4eHh4Jy5yZXBsYWNlKC9beHldL2csIGMgPT4ge1xyXG4gICAgY29uc3QgciA9IChNYXRoLnJhbmRvbSgpICogMTYpIHwgMDtcclxuICAgIGNvbnN0IHYgPSBjID09PSAneCcgPyByIDogKHIgJiAweDMpIHwgMHg4O1xyXG5cclxuICAgIHJldHVybiB2LnRvU3RyaW5nKDE2KTtcclxuICB9KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBjb3JyZWxhdGlvbiBJRCBmb3IgQVBJIHJlcXVlc3QgdHJhY2tpbmcgYW5kIGRpc3RyaWJ1dGVkIHRyYWNpbmcuXHJcbiAqXHJcbiAqIENvcnJlbGF0aW9uIElEcyBoZWxwIHRyYWNrIHJlcXVlc3RzIGFjcm9zcyBtdWx0aXBsZSBzZXJ2aWNlcyBhbmQgc3lzdGVtcy4gVGhleSBhcmVcclxuICogYXV0b21hdGljYWxseSBhdHRhY2hlZCB0byBvdXRnb2luZyByZXF1ZXN0cyB2aWEgSFRUUCBoZWFkZXJzIChgWC1Db3JyZWxhdGlvbi1JZGAgYW5kXHJcbiAqIGBYLVJlcXVlc3QtSWRgKSBhbmQgY2FuIGJlIHVzZWQgdG86XHJcbiAqIC0gQ29ycmVsYXRlIGxvZ3MgYWNyb3NzIGRpc3RyaWJ1dGVkIHN5c3RlbXNcclxuICogLSBUcmFjayByZXF1ZXN0IGZsb3dzIGluIG1pY3Jvc2VydmljZXMgYXJjaGl0ZWN0dXJlc1xyXG4gKiAtIERlYnVnIGlzc3VlcyBieSB0cmFjaW5nIGEgc3BlY2lmaWMgcmVxdWVzdCdzIGpvdXJuZXlcclxuICogLSBNb25pdG9yIHBlcmZvcm1hbmNlIGFjcm9zcyBzZXJ2aWNlIGJvdW5kYXJpZXNcclxuICpcclxuICogVGhlIGdlbmVyYXRlZCBJRCBmb2xsb3dzIHRoZSBmb3JtYXQ6IGB7cHJlZml4fS17dXVpZH1gIG9yIGp1c3QgYHt1dWlkfWAgaWYgbm8gcHJlZml4IGlzIHByb3ZpZGVkLlxyXG4gKlxyXG4gKiBAcGFyYW0gcHJlZml4IC0gT3B0aW9uYWwgcHJlZml4IHRvIG5hbWVzcGFjZSBjb3JyZWxhdGlvbiBJRHMgYnkgY29udGV4dCAoZS5nLiwgJ2FwaScsICd3ZWInLCAnbW9iaWxlJylcclxuICogQHJldHVybnMgQSBjb3JyZWxhdGlvbiBJRCBzdHJpbmcsIG9wdGlvbmFsbHkgcHJlZml4ZWRcclxuICogQHB1YmxpY1xyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBCYXNpYyB1c2FnZTpcclxuICogYGBgdHlwZXNjcmlwdFxyXG4gKiBjb25zdCBpZCA9IGdlbmVyYXRlQ29ycmVsYXRpb25JZCgpO1xyXG4gKiAvLyA9PiBcImExYjJjM2Q0LWU1ZjYtNDc4OS1hMDEyLWIzYzRkNWU2ZjdhOFwiXHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBXaXRoIHByZWZpeCBmb3IgY29udGV4dCBpZGVudGlmaWNhdGlvbjpcclxuICogYGBgdHlwZXNjcmlwdFxyXG4gKiBjb25zdCB3ZWJJZCA9IGdlbmVyYXRlQ29ycmVsYXRpb25JZCgnd2ViJyk7XHJcbiAqIC8vID0+IFwid2ViLWExYjJjM2Q0LWU1ZjYtNDc4OS1hMDEyLWIzYzRkNWU2ZjdhOFwiXHJcbiAqXHJcbiAqIGNvbnN0IGFwaUlkID0gZ2VuZXJhdGVDb3JyZWxhdGlvbklkKCdhcGknKTtcclxuICogLy8gPT4gXCJhcGktZjFlMmQzYzQtYjVhNi00OTg3LWEwMTItYjNjNGQ1ZTZmN2E4XCJcclxuICogYGBgXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIENvbmZpZ3VyaW5nIGluIEFwaUNsaWVudDpcclxuICogYGBgdHlwZXNjcmlwdFxyXG4gKiBjb25zdCBjbGllbnQgPSBuZXcgQXBpQ2xpZW50KCdodHRwczovL2FwaS5leGFtcGxlLmNvbScpO1xyXG4gKiBjbGllbnQuc2V0Q29ycmVsYXRpb25JZFByZWZpeCgnbW9iaWxlJyk7XHJcbiAqIC8vIEFsbCByZXF1ZXN0cyB3aWxsIGhhdmUgY29ycmVsYXRpb24gSURzIGxpa2UgXCJtb2JpbGUte3V1aWR9XCJcclxuICogYGBgXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVDb3JyZWxhdGlvbklkKHByZWZpeD86IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgY29uc3QgdXVpZCA9IGdlbmVyYXRlVVVJRCgpO1xyXG5cclxuICByZXR1cm4gcHJlZml4ID8gYCR7cHJlZml4fS0ke3V1aWR9YCA6IHV1aWQ7XHJcbn1cclxuIiwgImltcG9ydCB0eXBlIHsgQXBpRXJyb3IsIEFwaUVycm9yVHlwZSB9IGZyb20gJy4uL3R5cGVzL0FwaUVycm9yJztcclxuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0Q29uZmlnIH0gZnJvbSAnLi4vdHlwZXMvUmVxdWVzdENvbmZpZyc7XHJcblxyXG4vKipcclxuICogTm9ybWFsaXplcyB2YXJpb3VzIGVycm9yIHR5cGVzIGludG8gYSBjb25zaXN0ZW50LCBzdHJ1Y3R1cmVkIEFwaUVycm9yIGZvcm1hdC5cclxuICpcclxuICogVGhpcyBpbnRlcm5hbCBjbGFzcyBoYW5kbGVzIHRoZSBjb21wbGV4IHRhc2sgb2YgY29udmVydGluZyBhbnkgdHlwZSBvZiBlcnJvclxyXG4gKiAobmV0d29yayBlcnJvcnMsIEhUVFAgZXJyb3JzLCBhYm9ydCBlcnJvcnMsIHRpbWVvdXRzLCBldGMuKSBpbnRvIGEgc3RhbmRhcmRpemVkXHJcbiAqIHtAbGluayBBcGlFcnJvcn0gc3RydWN0dXJlIHdpdGggcHJvcGVyIGNhdGVnb3JpemF0aW9uIGFuZCBtZXRhZGF0YS5cclxuICpcclxuICogS2V5IEZlYXR1cmVzOlxyXG4gKiAtICoqRXJyb3IgQ2F0ZWdvcml6YXRpb24qKjogQ2xhc3NpZmllcyBlcnJvcnMgYnkgdHlwZSAodmFsaWRhdGlvbiwgY2xpZW50LCBzZXJ2ZXIsIG5ldHdvcmssIGV0Yy4pXHJcbiAqIC0gKipIVFRQIFN0YXR1cyBNYXBwaW5nKio6IENvbnZlcnRzIHN0YXR1cyBjb2RlcyB0byBodW1hbi1yZWFkYWJsZSB0aXRsZXNcclxuICogLSAqKkNvcnJlbGF0aW9uIElEIFRyYWNraW5nKio6IFByZXNlcnZlcyBvciBpbmplY3RzIGNvcnJlbGF0aW9uIElEcyBmb3IgdHJhY2luZ1xyXG4gKiAtICoqQWJvcnQgRGV0ZWN0aW9uKio6IElkZW50aWZpZXMgYW5kIHByb3Blcmx5IGhhbmRsZXMgcmVxdWVzdCBjYW5jZWxsYXRpb25zXHJcbiAqIC0gKipDb25zaXN0ZW50IFN0cnVjdHVyZSoqOiBFbnN1cmVzIGFsbCBlcnJvcnMgY29uZm9ybSB0byB0aGUgQXBpRXJyb3IgaW50ZXJmYWNlXHJcbiAqXHJcbiAqIEBpbnRlcm5hbCBUaGlzIGNsYXNzIGlzIG5vdCBleHBvcnRlZCBmcm9tIHRoZSBwdWJsaWMgQVBJXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgRXJyb3JOb3JtYWxpemVyIHtcclxuICAvKipcclxuICAgKiBNYXBzIGFuIEhUVFAgc3RhdHVzIGNvZGUgdG8gYSBzdGFuZGFyZGl6ZWQgZXJyb3IgdHlwZSBjYXRlZ29yeS5cclxuICAgKlxyXG4gICAqIFRoaXMgY2F0ZWdvcml6YXRpb24gaGVscHMgY29uc3VtZXJzIGhhbmRsZSBkaWZmZXJlbnQgZXJyb3IgY2xhc3NlcyBhcHByb3ByaWF0ZWx5OlxyXG4gICAqIC0gYHZhbGlkYXRpb25fZXJyb3JgICg0MDApOiBDbGllbnQgc2VudCBpbnZhbGlkIGRhdGFcclxuICAgKiAtIGBjbGllbnRfZXJyb3JgICg0MDEtNDk5KTogQ2xpZW50LXNpZGUgaXNzdWVzIChhdXRoLCBwZXJtaXNzaW9ucywgbm90IGZvdW5kLCBldGMuKVxyXG4gICAqIC0gYHNlcnZlcl9lcnJvcmAgKDUwMC01OTkpOiBTZXJ2ZXItc2lkZSBmYWlsdXJlc1xyXG4gICAqIC0gYHVua25vd25fZXJyb3JgOiBVbnJlY29nbml6ZWQgc3RhdHVzIGNvZGVzXHJcbiAgICpcclxuICAgKiBAcGFyYW0gc3RhdHVzIC0gSFRUUCBzdGF0dXMgY29kZSBmcm9tIHRoZSByZXNwb25zZVxyXG4gICAqIEByZXR1cm5zIFRoZSBlcnJvciB0eXBlIGNhdGVnb3J5IGFzIGEgc3RyaW5nXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBub3JtYWxpemVyLmdldEVycm9yVHlwZSg0MDApOyAvLyA9PiAndmFsaWRhdGlvbl9lcnJvcidcclxuICAgKiBub3JtYWxpemVyLmdldEVycm9yVHlwZSg0MDQpOyAvLyA9PiAnY2xpZW50X2Vycm9yJ1xyXG4gICAqIG5vcm1hbGl6ZXIuZ2V0RXJyb3JUeXBlKDUwMCk7IC8vID0+ICdzZXJ2ZXJfZXJyb3InXHJcbiAgICogbm9ybWFsaXplci5nZXRFcnJvclR5cGUoMCk7ICAgLy8gPT4gJ3Vua25vd25fZXJyb3InXHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgZ2V0RXJyb3JUeXBlKHN0YXR1czogbnVtYmVyKTogQXBpRXJyb3JUeXBlIHtcclxuICAgIGlmIChzdGF0dXMgPj0gNDAwICYmIHN0YXR1cyA8IDUwMCkge1xyXG4gICAgICByZXR1cm4gc3RhdHVzID09PSA0MDAgPyAndmFsaWRhdGlvbl9lcnJvcicgOiAnY2xpZW50X2Vycm9yJztcclxuICAgIH0gZWxzZSBpZiAoc3RhdHVzID49IDUwMCkge1xyXG4gICAgICByZXR1cm4gJ3NlcnZlcl9lcnJvcic7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuICd1bmtub3duX2Vycm9yJztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1hcHMgYW4gSFRUUCBzdGF0dXMgY29kZSB0byBhIGh1bWFuLXJlYWRhYmxlIGVycm9yIHRpdGxlLlxyXG4gICAqXHJcbiAgICogUHJvdmlkZXMgdXNlci1mcmllbmRseSBlcnJvciBtZXNzYWdlcyBmb3IgY29tbW9uIEhUVFAgc3RhdHVzIGNvZGVzLlxyXG4gICAqIEZhbGxzIGJhY2sgdG8gYSBnZW5lcmljIFwiSFRUUCBFcnJvciB7c3RhdHVzfVwiIGZvcm1hdCBmb3IgdW5tYXBwZWQgY29kZXMuXHJcbiAgICpcclxuICAgKiBAcGFyYW0gc3RhdHVzIC0gSFRUUCBzdGF0dXMgY29kZSBmcm9tIHRoZSByZXNwb25zZVxyXG4gICAqIEByZXR1cm5zIEEgaHVtYW4tcmVhZGFibGUgZXJyb3IgdGl0bGVcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIG5vcm1hbGl6ZXIuZ2V0RXJyb3JUaXRsZSg0MDQpOyAvLyA9PiAnTm90IEZvdW5kJ1xyXG4gICAqIG5vcm1hbGl6ZXIuZ2V0RXJyb3JUaXRsZSg1MDApOyAvLyA9PiAnSW50ZXJuYWwgU2VydmVyIEVycm9yJ1xyXG4gICAqIG5vcm1hbGl6ZXIuZ2V0RXJyb3JUaXRsZSg5OTkpOyAvLyA9PiAnSFRUUCBFcnJvciA5OTknXHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgZ2V0RXJyb3JUaXRsZShzdGF0dXM6IG51bWJlcik6IHN0cmluZyB7XHJcbiAgICBjb25zdCB0aXRsZXM6IFJlY29yZDxudW1iZXIsIHN0cmluZz4gPSB7XHJcbiAgICAgIDQwMDogJ0JhZCBSZXF1ZXN0JyxcclxuICAgICAgNDAxOiAnVW5hdXRob3JpemVkJyxcclxuICAgICAgNDAzOiAnRm9yYmlkZGVuJyxcclxuICAgICAgNDA0OiAnTm90IEZvdW5kJyxcclxuICAgICAgNDA1OiAnTWV0aG9kIE5vdCBBbGxvd2VkJyxcclxuICAgICAgNDA4OiAnUmVxdWVzdCBUaW1lb3V0JyxcclxuICAgICAgNDA5OiAnQ29uZmxpY3QnLFxyXG4gICAgICA0MjI6ICdVbnByb2Nlc3NhYmxlIEVudGl0eScsXHJcbiAgICAgIDQyOTogJ1RvbyBNYW55IFJlcXVlc3RzJyxcclxuICAgICAgNTAwOiAnSW50ZXJuYWwgU2VydmVyIEVycm9yJyxcclxuICAgICAgNTAyOiAnQmFkIEdhdGV3YXknLFxyXG4gICAgICA1MDM6ICdTZXJ2aWNlIFVuYXZhaWxhYmxlJyxcclxuICAgICAgNTA0OiAnR2F0ZXdheSBUaW1lb3V0JyxcclxuICAgIH07XHJcblxyXG4gICAgcmV0dXJuIHRpdGxlc1tzdGF0dXNdIHx8IGBIVFRQIEVycm9yICR7c3RhdHVzfWA7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBOb3JtYWxpemVzIGFueSBlcnJvciBpbnRvIGEgY29uc2lzdGVudCwgc3RydWN0dXJlZCBBcGlFcnJvciBmb3JtYXQuXHJcbiAgICpcclxuICAgKiBUaGlzIG1ldGhvZCBoYW5kbGVzIHZhcmlvdXMgZXJyb3Igc2NlbmFyaW9zIGFuZCBlbnN1cmVzIHRoZXkgYWxsIGNvbmZvcm0gdG9cclxuICAgKiB0aGUge0BsaW5rIEFwaUVycm9yfSBpbnRlcmZhY2Ugd2l0aCBhcHByb3ByaWF0ZSBjYXRlZ29yaXphdGlvbiBhbmQgbWV0YWRhdGE6XHJcbiAgICpcclxuICAgKiAtICoqRXhpc3RpbmcgQXBpRXJyb3JzKio6IEVuaGFuY2VzIHdpdGggbWlzc2luZyBmaWVsZHMgKHRyYWNlSWQsIGNvbmZpZylcclxuICAgKiAtICoqQWJvcnRFcnJvcnMqKjogTWFya3MgYXMgYHJlcXVlc3RfY2FuY2VsbGVkYCB3aXRoIGlzQWJvcnRlZCBmbGFnXHJcbiAgICogLSAqKlRpbWVvdXQgRXJyb3JzKio6IENhdGVnb3JpemVzIGFzIGB0aW1lb3V0X2Vycm9yYCB3aXRoIDQwOCBzdGF0dXNcclxuICAgKiAtICoqTmV0d29yayBFcnJvcnMqKjogQ2F0ZWdvcml6ZXMgYXMgYG5ldHdvcmtfZXJyb3JgIHdpdGggMCBzdGF0dXNcclxuICAgKiAtICoqVW5rbm93biBFcnJvcnMqKjogRmFsbGJhY2sgY2F0ZWdvcnkgZm9yIHVuZXhwZWN0ZWQgZXJyb3IgdHlwZXNcclxuICAgKlxyXG4gICAqIEFsbCBub3JtYWxpemVkIGVycm9ycyBpbmNsdWRlOlxyXG4gICAqIC0gYHR5cGVgOiBFcnJvciBjYXRlZ29yeSBmb3IgcHJvZ3JhbW1hdGljIGhhbmRsaW5nXHJcbiAgICogLSBgdGl0bGVgOiBIdW1hbi1yZWFkYWJsZSBlcnJvciB0aXRsZVxyXG4gICAqIC0gYHN0YXR1c2A6IEhUVFAgc3RhdHVzIGNvZGUgKG9yIDAgZm9yIG5vbi1IVFRQIGVycm9ycylcclxuICAgKiAtIGB0cmFjZUlkYDogQ29ycmVsYXRpb24gSUQgZm9yIGRpc3RyaWJ1dGVkIHRyYWNpbmdcclxuICAgKiAtIGBpc0Fib3J0ZWRgOiBCb29sZWFuIGZsYWcgaW5kaWNhdGluZyBpZiByZXF1ZXN0IHdhcyBjYW5jZWxsZWRcclxuICAgKiAtIGBjb25maWdgOiBPcmlnaW5hbCByZXF1ZXN0IGNvbmZpZ3VyYXRpb24gZm9yIGRlYnVnZ2luZ1xyXG4gICAqXHJcbiAgICogQHBhcmFtIGVycm9yIC0gVGhlIGVycm9yIHRvIG5vcm1hbGl6ZSAoY2FuIGJlIGFueSB0eXBlKVxyXG4gICAqIEBwYXJhbSBjb25maWcgLSBUaGUgcmVxdWVzdCBjb25maWd1cmF0aW9uIHRoYXQgbGVkIHRvIHRoaXMgZXJyb3JcclxuICAgKiBAcGFyYW0gY29ycmVsYXRpb25JZCAtIE9wdGlvbmFsIGNvcnJlbGF0aW9uIElEIGZvciB0cmFjaW5nXHJcbiAgICogQHJldHVybnMgQSBmdWxseSBzdHJ1Y3R1cmVkIEFwaUVycm9yIGluc3RhbmNlXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIE5vcm1hbGl6aW5nIGEgZmV0Y2ggQWJvcnRFcnJvcjpcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogdHJ5IHtcclxuICAgKiAgIGF3YWl0IGZldGNoKHVybCwgeyBzaWduYWwgfSk7XHJcbiAgICogfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgKiAgIGNvbnN0IGFwaUVycm9yID0gbm9ybWFsaXplci5ub3JtYWxpemVFcnJvcihlcnJvciwgY29uZmlnLCAncmVxLTEyMycpO1xyXG4gICAqICAgLy8gYXBpRXJyb3IudHlwZSA9PT0gJ3JlcXVlc3RfY2FuY2VsbGVkJ1xyXG4gICAqICAgLy8gYXBpRXJyb3IuaXNBYm9ydGVkID09PSB0cnVlXHJcbiAgICogfVxyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBOb3JtYWxpemluZyBhIHRpbWVvdXQ6XHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IHRpbWVvdXRFcnJvciA9IG5ldyBFcnJvcignUmVxdWVzdCB0aW1lb3V0IGFmdGVyIDMwMDAwbXMnKTtcclxuICAgKiBjb25zdCBhcGlFcnJvciA9IG5vcm1hbGl6ZXIubm9ybWFsaXplRXJyb3IodGltZW91dEVycm9yLCBjb25maWcpO1xyXG4gICAqIC8vIGFwaUVycm9yLnR5cGUgPT09ICd0aW1lb3V0X2Vycm9yJ1xyXG4gICAqIC8vIGFwaUVycm9yLnN0YXR1cyA9PT0gNDA4XHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgbm9ybWFsaXplRXJyb3IoXHJcbiAgICBlcnJvcjogdW5rbm93bixcclxuICAgIGNvbmZpZzogUmVxdWVzdENvbmZpZyxcclxuICAgIGNvcnJlbGF0aW9uSWQ/OiBzdHJpbmdcclxuICApOiBBcGlFcnJvciB7XHJcbiAgICAvLyBIYW5kbGUgcHJpbWl0aXZlIGVycm9ycyAoc3RyaW5ncywgbnVtYmVycywgZXRjLilcclxuICAgIGlmIChlcnJvciA9PT0gbnVsbCB8fCBlcnJvciA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKG5ldyBFcnJvcignQW4gdW5rbm93biBlcnJvciBvY2N1cnJlZCcpLCB7XHJcbiAgICAgICAgdHlwZTogJ3Vua25vd25fZXJyb3InLFxyXG4gICAgICAgIHRpdGxlOiAnVW5rbm93biBFcnJvcicsXHJcbiAgICAgICAgc3RhdHVzOiAwLFxyXG4gICAgICAgIHRyYWNlSWQ6IGNvcnJlbGF0aW9uSWQsXHJcbiAgICAgICAgaXNBYm9ydGVkOiBmYWxzZSxcclxuICAgICAgICBjb25maWcsXHJcbiAgICAgIH0gYXMgQXBpRXJyb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEhhbmRsZSBzdHJpbmcgZXJyb3JzXHJcbiAgICBpZiAodHlwZW9mIGVycm9yID09PSAnc3RyaW5nJykge1xyXG4gICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihuZXcgRXJyb3IoZXJyb3IpLCB7XHJcbiAgICAgICAgdHlwZTogJ3Vua25vd25fZXJyb3InLFxyXG4gICAgICAgIHRpdGxlOiAnVW5rbm93biBFcnJvcicsXHJcbiAgICAgICAgc3RhdHVzOiAwLFxyXG4gICAgICAgIHRyYWNlSWQ6IGNvcnJlbGF0aW9uSWQsXHJcbiAgICAgICAgaXNBYm9ydGVkOiBmYWxzZSxcclxuICAgICAgICBjb25maWcsXHJcbiAgICAgIH0gYXMgQXBpRXJyb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGVyciA9IGVycm9yIGFzIFBhcnRpYWw8QXBpRXJyb3I+ICYgeyBtZXNzYWdlPzogc3RyaW5nOyBuYW1lPzogc3RyaW5nIH07XHJcblxyXG4gICAgLy8gSWYgZXJyb3IgYWxyZWFkeSBoYXMgQXBpRXJyb3Igc3RydWN0dXJlLCBlbmhhbmNlIGl0XHJcbiAgICBpZiAoZXJyLnR5cGUgfHwgZXJyLnRpdGxlIHx8IGVyci5lcnJvcnMpIHtcclxuICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oXHJcbiAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yIDogbmV3IEVycm9yKGVyci5tZXNzYWdlID8/ICdVbmtub3duIGVycm9yJyksXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgdHlwZTogZXJyLnR5cGUsXHJcbiAgICAgICAgICB0aXRsZTogZXJyLnRpdGxlLFxyXG4gICAgICAgICAgc3RhdHVzOiBlcnIuc3RhdHVzLFxyXG4gICAgICAgICAgdHJhY2VJZDogZXJyLnRyYWNlSWQgfHwgY29ycmVsYXRpb25JZCxcclxuICAgICAgICAgIGVycm9yczogZXJyLmVycm9ycyxcclxuICAgICAgICAgIGlzQWJvcnRlZDogZXJyLmlzQWJvcnRlZCB8fCBmYWxzZSxcclxuICAgICAgICAgIGNvbmZpZyxcclxuICAgICAgICB9XHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGVyci5uYW1lID09PSAnQWJvcnRFcnJvcicgfHwgZXJyLmlzQWJvcnRlZCkge1xyXG4gICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihuZXcgRXJyb3IoZXJyLm1lc3NhZ2UgPz8gJ1JlcXVlc3Qgd2FzIGFib3J0ZWQnKSwge1xyXG4gICAgICAgIHR5cGU6ICdyZXF1ZXN0X2NhbmNlbGxlZCcsXHJcbiAgICAgICAgdGl0bGU6ICdSZXF1ZXN0IHdhcyBjYW5jZWxsZWQnLFxyXG4gICAgICAgIHN0YXR1czogMCxcclxuICAgICAgICB0cmFjZUlkOiBjb3JyZWxhdGlvbklkLFxyXG4gICAgICAgIGlzQWJvcnRlZDogdHJ1ZSxcclxuICAgICAgICBjb25maWcsXHJcbiAgICAgIH0gYXMgQXBpRXJyb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChlcnIubWVzc2FnZT8uaW5jbHVkZXMoJ3RpbWVvdXQnKSkge1xyXG4gICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihuZXcgRXJyb3IoZXJyLm1lc3NhZ2UpLCB7XHJcbiAgICAgICAgdHlwZTogJ3RpbWVvdXRfZXJyb3InLFxyXG4gICAgICAgIHRpdGxlOiAnUmVxdWVzdCBUaW1lb3V0JyxcclxuICAgICAgICBzdGF0dXM6IDQwOCxcclxuICAgICAgICB0cmFjZUlkOiBjb3JyZWxhdGlvbklkLFxyXG4gICAgICAgIGlzQWJvcnRlZDogdHJ1ZSxcclxuICAgICAgICBjb25maWcsXHJcbiAgICAgIH0gYXMgQXBpRXJyb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChlcnIubWVzc2FnZT8uaW5jbHVkZXMoJ25ldHdvcmsnKSkge1xyXG4gICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihuZXcgRXJyb3IoZXJyLm1lc3NhZ2UgPz8gJ05ldHdvcmsgcmVxdWVzdCBmYWlsZWQnKSwge1xyXG4gICAgICAgIHR5cGU6ICduZXR3b3JrX2Vycm9yJyxcclxuICAgICAgICB0aXRsZTogJ05ldHdvcmsgRXJyb3InLFxyXG4gICAgICAgIHN0YXR1czogMCxcclxuICAgICAgICB0cmFjZUlkOiBjb3JyZWxhdGlvbklkLFxyXG4gICAgICAgIGlzQWJvcnRlZDogZmFsc2UsXHJcbiAgICAgICAgY29uZmlnLFxyXG4gICAgICB9IGFzIEFwaUVycm9yKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihcclxuICAgICAgbmV3IEVycm9yKGVyci5tZXNzYWdlID8/ICdBbiB1bmtub3duIGVycm9yIG9jY3VycmVkJyksXHJcbiAgICAgIHtcclxuICAgICAgICB0eXBlOiAndW5rbm93bl9lcnJvcicsXHJcbiAgICAgICAgdGl0bGU6ICdVbmtub3duIEVycm9yJyxcclxuICAgICAgICBzdGF0dXM6IDAsXHJcbiAgICAgICAgdHJhY2VJZDogY29ycmVsYXRpb25JZCxcclxuICAgICAgICBpc0Fib3J0ZWQ6IGZhbHNlLFxyXG4gICAgICAgIGNvbmZpZyxcclxuICAgICAgfSBhcyBBcGlFcnJvclxyXG4gICAgKTtcclxuICB9XHJcbn1cclxuIiwgImltcG9ydCB0eXBlIHsgQXBpRXJyb3IgfSBmcm9tICcuLi90eXBlcy9BcGlFcnJvcic7XHJcbmltcG9ydCB0eXBlIHsgRXJyb3JJbnRlcmNlcHRvciB9IGZyb20gJy4uL3R5cGVzL0Vycm9ySW50ZXJjZXB0b3InO1xyXG5pbXBvcnQgdHlwZSB7IFJlcXVlc3RDb25maWcgfSBmcm9tICcuLi90eXBlcy9SZXF1ZXN0Q29uZmlnJztcclxuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0SW50ZXJjZXB0b3IgfSBmcm9tICcuLi90eXBlcy9SZXF1ZXN0SW50ZXJjZXB0b3InO1xyXG5pbXBvcnQgdHlwZSB7IFJlc3BvbnNlSW50ZXJjZXB0b3IgfSBmcm9tICcuLi90eXBlcy9SZXNwb25zZUludGVyY2VwdG9yJztcclxuXHJcbmltcG9ydCB0eXBlIHsgQXBpUmVzcG9uc2UgfSBmcm9tICdAL3R5cGVzJztcclxuXHJcbi8qKlxyXG4gKiBNYW5hZ2VzIHRoZSByZWdpc3RyYXRpb24gYW5kIGV4ZWN1dGlvbiBvZiByZXF1ZXN0L3Jlc3BvbnNlL2Vycm9yIGludGVyY2VwdG9ycy5cclxuICpcclxuICogVGhpcyBpbnRlcm5hbCBjbGFzcyBpbXBsZW1lbnRzIHRoZSBpbnRlcmNlcHRvciBwYXR0ZXJuLCBhbGxvd2luZyBtaWRkbGV3YXJlLXN0eWxlXHJcbiAqIGZ1bmN0aW9ucyB0byBiZSByZWdpc3RlcmVkIGFuZCBleGVjdXRlZCBhdCBkaWZmZXJlbnQgcG9pbnRzIGluIHRoZSByZXF1ZXN0IGxpZmVjeWNsZTpcclxuICogLSAqKlJlcXVlc3QgSW50ZXJjZXB0b3JzKio6IE1vZGlmeSByZXF1ZXN0cyBiZWZvcmUgdGhleSBhcmUgc2VudFxyXG4gKiAtICoqUmVzcG9uc2UgSW50ZXJjZXB0b3JzKio6IFRyYW5zZm9ybSByZXNwb25zZXMgYmVmb3JlIHRoZXkgYXJlIHJldHVybmVkXHJcbiAqIC0gKipFcnJvciBJbnRlcmNlcHRvcnMqKjogSGFuZGxlIG9yIHRyYW5zZm9ybSBlcnJvcnMgYmVmb3JlIHRoZXkgYXJlIHRocm93blxyXG4gKlxyXG4gKiBJbnRlcmNlcHRvcnMgYXJlIGV4ZWN1dGVkIHNlcXVlbnRpYWxseSBpbiB0aGUgb3JkZXIgdGhleSB3ZXJlIHJlZ2lzdGVyZWQsXHJcbiAqIGZvcm1pbmcgYSBwcm9jZXNzaW5nIHBpcGVsaW5lLiBFYWNoIGludGVyY2VwdG9yIGNhbjpcclxuICogLSBJbnNwZWN0IHRoZSBkYXRhIHBhc3NpbmcgdGhyb3VnaFxyXG4gKiAtIFRyYW5zZm9ybSBvciBlbmhhbmNlIHRoZSBkYXRhXHJcbiAqIC0gU2hvcnQtY2lyY3VpdCB0aGUgcGlwZWxpbmUgKGZvciBlcnJvcnMpXHJcbiAqIC0gUGVyZm9ybSBzaWRlIGVmZmVjdHMgKGxvZ2dpbmcsIG1vbml0b3JpbmcsIGV0Yy4pXHJcbiAqXHJcbiAqIEtleSBGZWF0dXJlczpcclxuICogLSAqKlNlcXVlbnRpYWwgRXhlY3V0aW9uKio6IEludGVyY2VwdG9ycyBydW4gaW4gcmVnaXN0cmF0aW9uIG9yZGVyXHJcbiAqIC0gKipVbnJlZ2lzdHJhdGlvbiBTdXBwb3J0Kio6IFJldHVybnMgY2xlYW51cCBmdW5jdGlvbiBmb3IgZWFjaCBpbnRlcmNlcHRvclxyXG4gKiAtICoqVHlwZSBTYWZldHkqKjogRnVsbHkgdHlwZWQgaW50ZXJjZXB0b3IgZnVuY3Rpb25zIHdpdGggZ2VuZXJpY3NcclxuICogLSAqKkVycm9yIEhhbmRsaW5nKio6IEdyYWNlZnVsIGhhbmRsaW5nIG9mIGludGVyY2VwdG9yIGZhaWx1cmVzXHJcbiAqXHJcbiAqIEBpbnRlcm5hbCBUaGlzIGNsYXNzIGlzIG5vdCBleHBvcnRlZCBmcm9tIHRoZSBwdWJsaWMgQVBJXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIENvbW1vbiBpbnRlcmNlcHRvciBwYXR0ZXJuczpcclxuICogYGBgdHlwZXNjcmlwdFxyXG4gKiBjb25zdCBtYW5hZ2VyID0gbmV3IEludGVyY2VwdG9yTWFuYWdlcigpO1xyXG4gKlxyXG4gKiAvLyBSZXF1ZXN0IGxvZ2dpbmdcclxuICogbWFuYWdlci5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoYXN5bmMgKGNvbmZpZykgPT4ge1xyXG4gKiAgIGNvbnNvbGUubG9nKCdSZXF1ZXN0OicsIGNvbmZpZy5tZXRob2QsIGNvbmZpZy51cmwpO1xyXG4gKiAgIHJldHVybiBjb25maWc7XHJcbiAqIH0pO1xyXG4gKlxyXG4gKiAvLyBSZXNwb25zZSB0cmFuc2Zvcm1hdGlvblxyXG4gKiBtYW5hZ2VyLmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoYXN5bmMgKHJlc3BvbnNlKSA9PiB7XHJcbiAqICAgaWYgKHJlc3BvbnNlLmFwaURhdGEpIHtcclxuICogICAgIHJlc3BvbnNlLmFwaURhdGEgPSBjYW1lbENhc2VLZXlzKHJlc3BvbnNlLmFwaURhdGEpO1xyXG4gKiAgIH1cclxuICogICByZXR1cm4gcmVzcG9uc2U7XHJcbiAqIH0pO1xyXG4gKlxyXG4gKiAvLyBFcnJvciBtb25pdG9yaW5nXHJcbiAqIG1hbmFnZXIuYWRkRXJyb3JJbnRlcmNlcHRvcihhc3luYyAoZXJyb3IpID0+IHtcclxuICogICBpZiAoZXJyb3Iuc3RhdHVzID49IDUwMCkge1xyXG4gKiAgICAgYXdhaXQgbG9nVG9Nb25pdG9yaW5nKGVycm9yKTtcclxuICogICB9XHJcbiAqICAgdGhyb3cgZXJyb3I7IC8vIFJlLXRocm93IHRvIG1haW50YWluIGVycm9yIGZsb3dcclxuICogfSk7XHJcbiAqIGBgYFxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEludGVyY2VwdG9yTWFuYWdlciB7XHJcbiAgLyoqXHJcbiAgICogQXJyYXkgb2YgcmVnaXN0ZXJlZCByZXF1ZXN0IGludGVyY2VwdG9yc1xyXG4gICAqIEBwcml2YXRlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSByZWFkb25seSByZXF1ZXN0SW50ZXJjZXB0b3JzOiBSZXF1ZXN0SW50ZXJjZXB0b3JbXSA9IFtdO1xyXG5cclxuICAvKipcclxuICAgKiBBcnJheSBvZiByZWdpc3RlcmVkIHJlc3BvbnNlIGludGVyY2VwdG9yc1xyXG4gICAqIEBwcml2YXRlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSByZWFkb25seSByZXNwb25zZUludGVyY2VwdG9yczogUmVzcG9uc2VJbnRlcmNlcHRvcltdID0gW107XHJcblxyXG4gIC8qKlxyXG4gICAqIEFycmF5IG9mIHJlZ2lzdGVyZWQgZXJyb3IgaW50ZXJjZXB0b3JzXHJcbiAgICogQHByaXZhdGVcclxuICAgKi9cclxuICBwcml2YXRlIHJlYWRvbmx5IGVycm9ySW50ZXJjZXB0b3JzOiBFcnJvckludGVyY2VwdG9yW10gPSBbXTtcclxuXHJcbiAgLyoqXHJcbiAgICogUmVnaXN0ZXJzIGEgcmVxdWVzdCBpbnRlcmNlcHRvciB0byBtb2RpZnkgcmVxdWVzdHMgYmVmb3JlIHRoZXkgYXJlIHNlbnQuXHJcbiAgICpcclxuICAgKiBSZXF1ZXN0IGludGVyY2VwdG9ycyBjYW46XHJcbiAgICogLSBBZGQgb3IgbW9kaWZ5IGhlYWRlcnNcclxuICAgKiAtIFRyYW5zZm9ybSByZXF1ZXN0IGJvZGllc1xyXG4gICAqIC0gQWRkIHF1ZXJ5IHBhcmFtZXRlcnNcclxuICAgKiAtIEltcGxlbWVudCByZXF1ZXN0IHNpZ25pbmdcclxuICAgKiAtIExvZyBvdXRnb2luZyByZXF1ZXN0c1xyXG4gICAqXHJcbiAgICogQHBhcmFtIGludGVyY2VwdG9yIC0gQXN5bmMgZnVuY3Rpb24gdGhhdCByZWNlaXZlcyBhbmQgcmV0dXJucyBSZXF1ZXN0Q29uZmlnXHJcbiAgICogQHJldHVybnMgQ2xlYW51cCBmdW5jdGlvbiB0byB1bnJlZ2lzdGVyIHRoaXMgaW50ZXJjZXB0b3JcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIC8vIEFkZCBhdXRoZW50aWNhdGlvbiBoZWFkZXJcclxuICAgKiBjb25zdCB1bnJlZ2lzdGVyID0gbWFuYWdlci5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoYXN5bmMgKGNvbmZpZykgPT4ge1xyXG4gICAqICAgY29uc3QgdG9rZW4gPSBhd2FpdCBnZXRBdXRoVG9rZW4oKTtcclxuICAgKiAgIGNvbmZpZy5oZWFkZXJzID0gY29uZmlnLmhlYWRlcnMgfHwgbmV3IEhlYWRlcnMoKTtcclxuICAgKiAgIGNvbmZpZy5oZWFkZXJzLnNldCgnQXV0aG9yaXphdGlvbicsIGBCZWFyZXIgJHt0b2tlbn1gKTtcclxuICAgKiAgIHJldHVybiBjb25maWc7XHJcbiAgICogfSk7XHJcbiAgICpcclxuICAgKiAvLyBMYXRlciwgcmVtb3ZlIHRoZSBpbnRlcmNlcHRvclxyXG4gICAqIHVucmVnaXN0ZXIoKTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBhZGRSZXF1ZXN0SW50ZXJjZXB0b3IoaW50ZXJjZXB0b3I6IFJlcXVlc3RJbnRlcmNlcHRvcik6ICgpID0+IHZvaWQge1xyXG4gICAgdGhpcy5yZXF1ZXN0SW50ZXJjZXB0b3JzLnB1c2goaW50ZXJjZXB0b3IpO1xyXG5cclxuICAgIHJldHVybiAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5yZXF1ZXN0SW50ZXJjZXB0b3JzLmluZGV4T2YoaW50ZXJjZXB0b3IpO1xyXG5cclxuICAgICAgaWYgKGluZGV4ID4gLTEpIHRoaXMucmVxdWVzdEludGVyY2VwdG9ycy5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlZ2lzdGVycyBhIHJlc3BvbnNlIGludGVyY2VwdG9yIHRvIHRyYW5zZm9ybSByZXNwb25zZXMgYmVmb3JlIHRoZXkgYXJlIHJldHVybmVkLlxyXG4gICAqXHJcbiAgICogUmVzcG9uc2UgaW50ZXJjZXB0b3JzIGNhbjpcclxuICAgKiAtIFRyYW5zZm9ybSByZXNwb25zZSBkYXRhIGZvcm1hdFxyXG4gICAqIC0gRXh0cmFjdCBuZXN0ZWQgZGF0YSBzdHJ1Y3R1cmVzXHJcbiAgICogLSBBZGQgY29tcHV0ZWQgcHJvcGVydGllc1xyXG4gICAqIC0gQ2FjaGUgcmVzcG9uc2VzXHJcbiAgICogLSBMb2cgc3VjY2Vzc2Z1bCByZXNwb25zZXNcclxuICAgKlxyXG4gICAqIEBwYXJhbSBpbnRlcmNlcHRvciAtIEFzeW5jIGZ1bmN0aW9uIHRoYXQgcmVjZWl2ZXMgYW5kIHJldHVybnMgQXBpUmVzcG9uc2VcclxuICAgKiBAcmV0dXJucyBDbGVhbnVwIGZ1bmN0aW9uIHRvIHVucmVnaXN0ZXIgdGhpcyBpbnRlcmNlcHRvclxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogLy8gRXh0cmFjdCBkYXRhIGZyb20gZW52ZWxvcGVcclxuICAgKiBtYW5hZ2VyLmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoYXN5bmMgKHJlc3BvbnNlKSA9PiB7XHJcbiAgICogICBpZiAocmVzcG9uc2UuYXBpRGF0YT8ucmVzdWx0KSB7XHJcbiAgICogICAgIHJlc3BvbnNlLmFwaURhdGEgPSByZXNwb25zZS5hcGlEYXRhLnJlc3VsdDtcclxuICAgKiAgIH1cclxuICAgKiAgIHJldHVybiByZXNwb25zZTtcclxuICAgKiB9KTtcclxuICAgKlxyXG4gICAqIC8vIEFkZCB0aW1lc3RhbXBzXHJcbiAgICogbWFuYWdlci5hZGRSZXNwb25zZUludGVyY2VwdG9yKGFzeW5jIChyZXNwb25zZSkgPT4ge1xyXG4gICAqICAgcmV0dXJuIHtcclxuICAgKiAgICAgLi4ucmVzcG9uc2UsXHJcbiAgICogICAgIHJlY2VpdmVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKVxyXG4gICAqICAgfTtcclxuICAgKiB9KTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBhZGRSZXNwb25zZUludGVyY2VwdG9yKGludGVyY2VwdG9yOiBSZXNwb25zZUludGVyY2VwdG9yKTogKCkgPT4gdm9pZCB7XHJcbiAgICB0aGlzLnJlc3BvbnNlSW50ZXJjZXB0b3JzLnB1c2goaW50ZXJjZXB0b3IpO1xyXG5cclxuICAgIHJldHVybiAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5yZXNwb25zZUludGVyY2VwdG9ycy5pbmRleE9mKGludGVyY2VwdG9yKTtcclxuXHJcbiAgICAgIGlmIChpbmRleCA+IC0xKSB0aGlzLnJlc3BvbnNlSW50ZXJjZXB0b3JzLnNwbGljZShpbmRleCwgMSk7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVnaXN0ZXJzIGFuIGVycm9yIGludGVyY2VwdG9yIHRvIGhhbmRsZSBvciB0cmFuc2Zvcm0gZXJyb3JzIGJlZm9yZSB0aGV5IGFyZSB0aHJvd24uXHJcbiAgICpcclxuICAgKiBFcnJvciBpbnRlcmNlcHRvcnMgY2FuOlxyXG4gICAqIC0gTG9nIGVycm9ycyB0byBtb25pdG9yaW5nIHNlcnZpY2VzXHJcbiAgICogLSBUcmFuc2Zvcm0gZXJyb3IgZm9ybWF0c1xyXG4gICAqIC0gSW1wbGVtZW50IHJldHJ5IGxvZ2ljXHJcbiAgICogLSBTaG93IHVzZXIgbm90aWZpY2F0aW9uc1xyXG4gICAqIC0gRXh0cmFjdCB2YWxpZGF0aW9uIGVycm9yc1xyXG4gICAqXHJcbiAgICogKipOb3RlOioqIEVycm9yIGludGVyY2VwdG9ycyBzaG91bGQgcmUtdGhyb3cgdGhlIGVycm9yIChvciBhIHRyYW5zZm9ybWVkIHZlcnNpb24pXHJcbiAgICogdG8gbWFpbnRhaW4gdGhlIGVycm9yIGZsb3cuIFRoZSBmaW5hbCBlcnJvciBpcyBhbHdheXMgdGhyb3duLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGludGVyY2VwdG9yIC0gQXN5bmMgZnVuY3Rpb24gdGhhdCByZWNlaXZlcyBhbmQgcmV0dXJucyAob3IgdGhyb3dzKSBBcGlFcnJvclxyXG4gICAqIEByZXR1cm5zIENsZWFudXAgZnVuY3Rpb24gdG8gdW5yZWdpc3RlciB0aGlzIGludGVyY2VwdG9yXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiAvLyBMb2cgdG8gbW9uaXRvcmluZyBzZXJ2aWNlXHJcbiAgICogbWFuYWdlci5hZGRFcnJvckludGVyY2VwdG9yKGFzeW5jIChlcnJvcikgPT4ge1xyXG4gICAqICAgaWYgKGVycm9yLnN0YXR1cyA+PSA1MDApIHtcclxuICAgKiAgICAgYXdhaXQgU2VudHJ5LmNhcHR1cmVFeGNlcHRpb24oZXJyb3IsIHtcclxuICAgKiAgICAgICBleHRyYTogeyB0cmFjZUlkOiBlcnJvci50cmFjZUlkIH1cclxuICAgKiAgICAgfSk7XHJcbiAgICogICB9XHJcbiAgICogICB0aHJvdyBlcnJvcjsgLy8gUmUtdGhyb3cgdG8gY29udGludWUgZXJyb3IgZmxvd1xyXG4gICAqIH0pO1xyXG4gICAqXHJcbiAgICogLy8gVHJhbnNmb3JtIGVycm9yIG1lc3NhZ2VzXHJcbiAgICogbWFuYWdlci5hZGRFcnJvckludGVyY2VwdG9yKGFzeW5jIChlcnJvcikgPT4ge1xyXG4gICAqICAgaWYgKGVycm9yLnN0YXR1cyA9PT0gNDA0KSB7XHJcbiAgICogICAgIGVycm9yLnRpdGxlID0gJ1Jlc291cmNlIG5vdCBmb3VuZCc7XHJcbiAgICogICB9XHJcbiAgICogICB0aHJvdyBlcnJvcjtcclxuICAgKiB9KTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBhZGRFcnJvckludGVyY2VwdG9yKGludGVyY2VwdG9yOiBFcnJvckludGVyY2VwdG9yKTogKCkgPT4gdm9pZCB7XHJcbiAgICB0aGlzLmVycm9ySW50ZXJjZXB0b3JzLnB1c2goaW50ZXJjZXB0b3IpO1xyXG5cclxuICAgIHJldHVybiAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5lcnJvckludGVyY2VwdG9ycy5pbmRleE9mKGludGVyY2VwdG9yKTtcclxuXHJcbiAgICAgIGlmIChpbmRleCA+IC0xKSB0aGlzLmVycm9ySW50ZXJjZXB0b3JzLnNwbGljZShpbmRleCwgMSk7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQXBwbGllcyBhbGwgcmVnaXN0ZXJlZCByZXF1ZXN0IGludGVyY2VwdG9ycyBpbiBzZXF1ZW50aWFsIG9yZGVyLlxyXG4gICAqXHJcbiAgICogRWFjaCBpbnRlcmNlcHRvciByZWNlaXZlcyB0aGUgY29uZmlnIG1vZGlmaWVkIGJ5IHRoZSBwcmV2aW91cyBpbnRlcmNlcHRvcixcclxuICAgKiBmb3JtaW5nIGEgcHJvY2Vzc2luZyBwaXBlbGluZS4gSWYgYW55IGludGVyY2VwdG9yIHRocm93cyBhbiBlcnJvcixcclxuICAgKiB0aGUgcGlwZWxpbmUgc3RvcHMgYW5kIHRoZSBlcnJvciBwcm9wYWdhdGVzLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGNvbmZpZyAtIFRoZSBpbml0aWFsIHJlcXVlc3QgY29uZmlndXJhdGlvblxyXG4gICAqIEByZXR1cm5zIFRoZSBtb2RpZmllZCByZXF1ZXN0IGNvbmZpZ3VyYXRpb24gYWZ0ZXIgYWxsIGludGVyY2VwdG9yc1xyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogY29uc3QgY29uZmlnID0geyBtZXRob2Q6ICdHRVQnLCB1cmw6ICcvdXNlcnMnIH07XHJcbiAgICogY29uc3QgZmluYWxDb25maWcgPSBhd2FpdCBtYW5hZ2VyLmFwcGx5UmVxdWVzdEludGVyY2VwdG9ycyhjb25maWcpO1xyXG4gICAqIC8vIGZpbmFsQ29uZmlnIGhhcyBiZWVuIHByb2Nlc3NlZCBieSBhbGwgcmVnaXN0ZXJlZCBpbnRlcmNlcHRvcnNcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBhc3luYyBhcHBseVJlcXVlc3RJbnRlcmNlcHRvcnMoXHJcbiAgICBjb25maWc6IFJlcXVlc3RDb25maWdcclxuICApOiBQcm9taXNlPFJlcXVlc3RDb25maWc+IHtcclxuICAgIGxldCBtb2RpZmllZENvbmZpZyA9IHsgLi4uY29uZmlnIH07XHJcblxyXG4gICAgZm9yIChjb25zdCBpbnRlcmNlcHRvciBvZiB0aGlzLnJlcXVlc3RJbnRlcmNlcHRvcnMpIHtcclxuICAgICAgbW9kaWZpZWRDb25maWcgPSBhd2FpdCBpbnRlcmNlcHRvcihtb2RpZmllZENvbmZpZyk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG1vZGlmaWVkQ29uZmlnO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQXBwbGllcyBhbGwgcmVnaXN0ZXJlZCByZXNwb25zZSBpbnRlcmNlcHRvcnMgaW4gc2VxdWVudGlhbCBvcmRlci5cclxuICAgKlxyXG4gICAqIEVhY2ggaW50ZXJjZXB0b3IgcmVjZWl2ZXMgdGhlIHJlc3BvbnNlIG1vZGlmaWVkIGJ5IHRoZSBwcmV2aW91cyBpbnRlcmNlcHRvcixcclxuICAgKiBmb3JtaW5nIGEgcHJvY2Vzc2luZyBwaXBlbGluZS4gSWYgYW55IGludGVyY2VwdG9yIHRocm93cyBhbiBlcnJvcixcclxuICAgKiB0aGUgcGlwZWxpbmUgc3RvcHMgYW5kIHRoZSBlcnJvciBwcm9wYWdhdGVzLlxyXG4gICAqXHJcbiAgICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiB0aGUgcmVzcG9uc2UgZGF0YVxyXG4gICAqIEBwYXJhbSByZXNwb25zZSAtIFRoZSBpbml0aWFsIEFQSSByZXNwb25zZVxyXG4gICAqIEByZXR1cm5zIFRoZSBtb2RpZmllZCByZXNwb25zZSBhZnRlciBhbGwgaW50ZXJjZXB0b3JzXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCByZXNwb25zZSA9IHsgZGF0YTogeyBpZDogMSwgbmFtZTogJ0pvaG4nIH0gfTtcclxuICAgKiBjb25zdCBmaW5hbFJlc3BvbnNlID0gYXdhaXQgbWFuYWdlci5hcHBseVJlc3BvbnNlSW50ZXJjZXB0b3JzKHJlc3BvbnNlKTtcclxuICAgKiAvLyBmaW5hbFJlc3BvbnNlIGhhcyBiZWVuIHByb2Nlc3NlZCBieSBhbGwgcmVnaXN0ZXJlZCBpbnRlcmNlcHRvcnNcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBhc3luYyBhcHBseVJlc3BvbnNlSW50ZXJjZXB0b3JzPFQ+KFxyXG4gICAgcmVzcG9uc2U6IEFwaVJlc3BvbnNlPFQ+XHJcbiAgKTogUHJvbWlzZTxBcGlSZXNwb25zZTxUPj4ge1xyXG4gICAgbGV0IG1vZGlmaWVkUmVzcG9uc2UgPSByZXNwb25zZTtcclxuXHJcbiAgICBmb3IgKGNvbnN0IGludGVyY2VwdG9yIG9mIHRoaXMucmVzcG9uc2VJbnRlcmNlcHRvcnMpIHtcclxuICAgICAgbW9kaWZpZWRSZXNwb25zZSA9IGF3YWl0IGludGVyY2VwdG9yKG1vZGlmaWVkUmVzcG9uc2UpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBtb2RpZmllZFJlc3BvbnNlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQXBwbGllcyBhbGwgcmVnaXN0ZXJlZCBlcnJvciBpbnRlcmNlcHRvcnMgaW4gc2VxdWVudGlhbCBvcmRlciBhbmQgcmUtdGhyb3dzLlxyXG4gICAqXHJcbiAgICogRWFjaCBpbnRlcmNlcHRvciByZWNlaXZlcyB0aGUgZXJyb3IgKHBvdGVudGlhbGx5IG1vZGlmaWVkIGJ5IHByZXZpb3VzIGludGVyY2VwdG9ycykuXHJcbiAgICogSW50ZXJjZXB0b3JzIGNhbiB0cmFuc2Zvcm0gdGhlIGVycm9yIGJlZm9yZSByZS10aHJvd2luZyBpdC4gVGhlIGZpbmFsIGVycm9yXHJcbiAgICogaXMgYWx3YXlzIHRocm93biB0byBtYWludGFpbiBlcnJvciBmbG93LlxyXG4gICAqXHJcbiAgICogSWYgYW4gaW50ZXJjZXB0b3IgaXRzZWxmIHRocm93cyBhbiBlcnJvciwgdGhhdCBiZWNvbWVzIHRoZSBuZXcgZXJyb3IgdG8gcHJvY2Vzc1xyXG4gICAqIGJ5IHN1YnNlcXVlbnQgaW50ZXJjZXB0b3JzLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGVycm9yIC0gVGhlIGluaXRpYWwgQVBJIGVycm9yXHJcbiAgICogQHJldHVybnMgTmV2ZXIgcmV0dXJucyAoYWx3YXlzIHRocm93cylcclxuICAgKiBAdGhyb3dzIFRoZSBmaW5hbCBlcnJvciBhZnRlciBhbGwgaW50ZXJjZXB0b3JzIGhhdmUgcHJvY2Vzc2VkIGl0XHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiB0cnkge1xyXG4gICAqICAgYXdhaXQgbWFuYWdlci5hcHBseUVycm9ySW50ZXJjZXB0b3JzKGVycm9yKTtcclxuICAgKiB9IGNhdGNoIChmaW5hbEVycm9yKSB7XHJcbiAgICogICAvLyBmaW5hbEVycm9yIGhhcyBiZWVuIHByb2Nlc3NlZCBieSBhbGwgcmVnaXN0ZXJlZCBlcnJvciBpbnRlcmNlcHRvcnNcclxuICAgKiB9XHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgYXN5bmMgYXBwbHlFcnJvckludGVyY2VwdG9ycyhlcnJvcjogQXBpRXJyb3IpOiBQcm9taXNlPG5ldmVyPiB7XHJcbiAgICBsZXQgbW9kaWZpZWRFcnJvciA9IGVycm9yO1xyXG5cclxuICAgIGZvciAoY29uc3QgaW50ZXJjZXB0b3Igb2YgdGhpcy5lcnJvckludGVyY2VwdG9ycykge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIG1vZGlmaWVkRXJyb3IgPSBhd2FpdCBpbnRlcmNlcHRvcihtb2RpZmllZEVycm9yKTtcclxuICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgIG1vZGlmaWVkRXJyb3IgPSBlIGFzIEFwaUVycm9yO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgdGhyb3cgbW9kaWZpZWRFcnJvcjtcclxuICB9XHJcbn1cclxuIiwgIi8qKlxyXG4gKiBNYW5hZ2VzIGFjdGl2ZSBIVFRQIHJlcXVlc3RzIHdpdGggc3VwcG9ydCBmb3IgY2FuY2VsbGF0aW9uIGFuZCBjb3JyZWxhdGlvbiB0cmFja2luZy5cclxuICpcclxuICogVGhpcyBpbnRlcm5hbCBjbGFzcyBtYWludGFpbnMgYSByZWdpc3RyeSBvZiBpbi1mbGlnaHQgcmVxdWVzdHMsIGFsbG93aW5nIHRoZW0gdG8gYmVcclxuICogY2FuY2VsbGVkIGluZGl2aWR1YWxseSBvciBpbiBidWxrLiBFYWNoIHJlcXVlc3QgaXMgdHJhY2tlZCBieSBhIHVuaXF1ZSBrZXkgYW5kXHJcbiAqIGFzc29jaWF0ZWQgd2l0aCBhIGNvcnJlbGF0aW9uIElEIGZvciBkaXN0cmlidXRlZCB0cmFjaW5nLlxyXG4gKlxyXG4gKiBLZXkgRmVhdHVyZXM6XHJcbiAqIC0gKipSZXF1ZXN0IERlZHVwbGljYXRpb24qKjogQXV0b21hdGljYWxseSBjYW5jZWxzIGR1cGxpY2F0ZSByZXF1ZXN0cyB3aXRoIHRoZSBzYW1lIGtleVxyXG4gKiAtICoqQ29ycmVsYXRpb24gVHJhY2tpbmcqKjogTWFwcyByZXF1ZXN0IGtleXMgdG8gY29ycmVsYXRpb24gSURzIGZvciB0cmFjaW5nXHJcbiAqIC0gKipCdWxrIENhbmNlbGxhdGlvbioqOiBDYW5jZWwgYWxsIHBlbmRpbmcgcmVxdWVzdHMgYXQgb25jZSAodXNlZnVsIGZvciBjbGVhbnVwKVxyXG4gKiAtICoqTWVtb3J5IE1hbmFnZW1lbnQqKjogQXV0b21hdGljYWxseSBjbGVhbnMgdXAgdHJhY2tpbmcgZGF0YSB3aGVuIHJlcXVlc3RzIGNvbXBsZXRlXHJcbiAqXHJcbiAqIEBpbnRlcm5hbCBUaGlzIGNsYXNzIGlzIG5vdCBleHBvcnRlZCBmcm9tIHRoZSBwdWJsaWMgQVBJXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIGBgYHR5cGVzY3JpcHRcclxuICogY29uc3QgbWFuYWdlciA9IG5ldyBSZXF1ZXN0TWFuYWdlcigpO1xyXG4gKiBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xyXG4gKlxyXG4gKiAvLyBUcmFjayBhIHJlcXVlc3RcclxuICogbWFuYWdlci5hZGQoJ0dFVF8vdXNlcnMvMTIzJywgY29udHJvbGxlciwgJ2FwaS1hYmMxMjMnKTtcclxuICpcclxuICogLy8gQ2FuY2VsIHNwZWNpZmljIHJlcXVlc3RcclxuICogbWFuYWdlci5jYW5jZWwoJ0dFVF8vdXNlcnMvMTIzJyk7XHJcbiAqXHJcbiAqIC8vIE9yIGNhbmNlbCBhbGwgcmVxdWVzdHNcclxuICogbWFuYWdlci5jYW5jZWxBbGwoKTtcclxuICogYGBgXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgUmVxdWVzdE1hbmFnZXIge1xyXG4gIC8qKlxyXG4gICAqIE1hcCBvZiBhY3RpdmUgcmVxdWVzdCBrZXlzIHRvIHRoZWlyIGFib3J0IGNvbnRyb2xsZXJzXHJcbiAgICogQHByaXZhdGVcclxuICAgKi9cclxuICBwcml2YXRlIGFjdGl2ZVJlcXVlc3RzOiBNYXA8c3RyaW5nLCBBYm9ydENvbnRyb2xsZXI+ID0gbmV3IE1hcCgpO1xyXG5cclxuICAvKipcclxuICAgKiBNYXAgb2YgcmVxdWVzdCBrZXlzIHRvIHRoZWlyIGNvcnJlbGF0aW9uIElEcyBmb3IgdHJhY2luZ1xyXG4gICAqIEBwcml2YXRlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjb3JyZWxhdGlvbk1hcDogTWFwPHN0cmluZywgc3RyaW5nPiA9IG5ldyBNYXAoKTtcclxuXHJcbiAgLyoqXHJcbiAgICogUmVnaXN0ZXJzIGEgbmV3IHJlcXVlc3QgZm9yIHRyYWNraW5nIGFuZCBjYW5jZWxsYXRpb24gbWFuYWdlbWVudC5cclxuICAgKlxyXG4gICAqIElmIGEgcmVxdWVzdCB3aXRoIHRoZSBzYW1lIGtleSBhbHJlYWR5IGV4aXN0cywgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5XHJcbiAgICogY2FuY2VsbGVkIGJlZm9yZSB0aGUgbmV3IG9uZSBpcyByZWdpc3RlcmVkIChyZXF1ZXN0IGRlZHVwbGljYXRpb24pLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGtleSAtIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgcmVxdWVzdCAodHlwaWNhbGx5IG1ldGhvZCArIFVSTCArIHRpbWVzdGFtcClcclxuICAgKiBAcGFyYW0gY29udHJvbGxlciAtIEFib3J0Q29udHJvbGxlciBmb3IgY2FuY2VsbGluZyB0aGUgcmVxdWVzdFxyXG4gICAqIEBwYXJhbSBjb3JyZWxhdGlvbklkIC0gQ29ycmVsYXRpb24gSUQgZm9yIGRpc3RyaWJ1dGVkIHRyYWNpbmdcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XHJcbiAgICogbWFuYWdlci5hZGQoJ0dFVF8vYXBpL3VzZXJzXzE2OTk5OTk5OTknLCBjb250cm9sbGVyLCAnYXBpLWFiYzEyMycpO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIGFkZChrZXk6IHN0cmluZywgY29udHJvbGxlcjogQWJvcnRDb250cm9sbGVyLCBjb3JyZWxhdGlvbklkOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIC8vIENhbmNlbCBleGlzdGluZyByZXF1ZXN0IHdpdGggc2FtZSBrZXkgaWYgZXhpc3RzXHJcbiAgICB0aGlzLmNhbmNlbChrZXkpO1xyXG4gICAgdGhpcy5hY3RpdmVSZXF1ZXN0cy5zZXQoa2V5LCBjb250cm9sbGVyKTtcclxuICAgIHRoaXMuY29ycmVsYXRpb25NYXAuc2V0KGtleSwgY29ycmVsYXRpb25JZCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZW1vdmVzIGEgcmVxdWVzdCBmcm9tIHRyYWNraW5nIHdpdGhvdXQgY2FuY2VsbGluZyBpdC5cclxuICAgKlxyXG4gICAqIFRoaXMgaXMgdHlwaWNhbGx5IGNhbGxlZCB3aGVuIGEgcmVxdWVzdCBjb21wbGV0ZXMgc3VjY2Vzc2Z1bGx5IG9yIGZhaWxzLlxyXG4gICAqIFVzZSB7QGxpbmsgY2FuY2VsfSBpbnN0ZWFkIGlmIHlvdSBuZWVkIHRvIGFib3J0IHRoZSByZXF1ZXN0LlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGtleSAtIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgcmVxdWVzdCB0byByZW1vdmVcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIC8vIENhbGxlZCBhdXRvbWF0aWNhbGx5IGFmdGVyIHJlcXVlc3QgY29tcGxldGVzXHJcbiAgICogbWFuYWdlci5yZW1vdmUoJ0dFVF8vYXBpL3VzZXJzXzE2OTk5OTk5OTknKTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICByZW1vdmUoa2V5OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMuYWN0aXZlUmVxdWVzdHMuZGVsZXRlKGtleSk7XHJcbiAgICB0aGlzLmNvcnJlbGF0aW9uTWFwLmRlbGV0ZShrZXkpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2FuY2VscyBhIHNwZWNpZmljIHJlcXVlc3QgYW5kIHJlbW92ZXMgaXQgZnJvbSB0cmFja2luZy5cclxuICAgKlxyXG4gICAqIElmIHRoZSByZXF1ZXN0IGRvZXNuJ3QgZXhpc3Qgb3Igd2FzIGFscmVhZHkgY2FuY2VsbGVkLCB0aGlzIG9wZXJhdGlvbiBpcyBhIG5vLW9wLlxyXG4gICAqIFRoZSBhc3NvY2lhdGVkIEFib3J0Q29udHJvbGxlcidzIHNpZ25hbCB3aWxsIGJlIHRyaWdnZXJlZCwgY2F1c2luZyBhbnkgYWN0aXZlXHJcbiAgICogZmV0Y2ggb3BlcmF0aW9ucyB0byBhYm9ydC5cclxuICAgKlxyXG4gICAqIEBwYXJhbSBrZXkgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHJlcXVlc3QgdG8gY2FuY2VsXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiAvLyBVc2VyIG5hdmlnYXRlcyBhd2F5LCBjYW5jZWwgdGhlIHBlbmRpbmcgcmVxdWVzdFxyXG4gICAqIG1hbmFnZXIuY2FuY2VsKCdHRVRfL2FwaS91c2Vyc18xNjk5OTk5OTk5Jyk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgY2FuY2VsKGtleTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBjb250cm9sbGVyID0gdGhpcy5hY3RpdmVSZXF1ZXN0cy5nZXQoa2V5KTtcclxuXHJcbiAgICBpZiAoY29udHJvbGxlcikge1xyXG4gICAgICBjb250cm9sbGVyLmFib3J0KCk7XHJcbiAgICAgIHRoaXMuYWN0aXZlUmVxdWVzdHMuZGVsZXRlKGtleSk7XHJcbiAgICAgIHRoaXMuY29ycmVsYXRpb25NYXAuZGVsZXRlKGtleSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDYW5jZWxzIGFsbCBhY3RpdmUgcmVxdWVzdHMgYW5kIGNsZWFycyBhbGwgdHJhY2tpbmcgZGF0YS5cclxuICAgKlxyXG4gICAqIFRoaXMgaXMgdXNlZnVsIGZvciBjbGVhbnVwIHNjZW5hcmlvcyBzdWNoIGFzOlxyXG4gICAqIC0gVXNlciBsb2dvdXRcclxuICAgKiAtIENvbXBvbmVudCB1bm1vdW50XHJcbiAgICogLSBOYXZpZ2F0aW9uIHRvIGEgZGlmZmVyZW50IHBhcnQgb2YgdGhlIGFwcGxpY2F0aW9uXHJcbiAgICogLSBFcnJvciByZWNvdmVyeSB0aGF0IHJlcXVpcmVzIGEgY2xlYW4gc2xhdGVcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIC8vIENhbmNlbCBhbGwgcGVuZGluZyByZXF1ZXN0cyBvbiBsb2dvdXRcclxuICAgKiBmdW5jdGlvbiBoYW5kbGVMb2dvdXQoKSB7XHJcbiAgICogICBhcGlDbGllbnQuY2FuY2VsQWxsUmVxdWVzdHMoKTtcclxuICAgKiAgIC8vIC4uLiByZXN0IG9mIGxvZ291dCBsb2dpY1xyXG4gICAqIH1cclxuICAgKiBgYGBcclxuICAgKi9cclxuICBjYW5jZWxBbGwoKTogdm9pZCB7XHJcbiAgICB0aGlzLmFjdGl2ZVJlcXVlc3RzLmZvckVhY2goY29udHJvbGxlciA9PiBjb250cm9sbGVyLmFib3J0KCkpO1xyXG4gICAgdGhpcy5hY3RpdmVSZXF1ZXN0cy5jbGVhcigpO1xyXG4gICAgdGhpcy5jb3JyZWxhdGlvbk1hcC5jbGVhcigpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2hlY2tzIGlmIGEgcmVxdWVzdCB3aXRoIHRoZSBnaXZlbiBrZXkgaXMgY3VycmVudGx5IGJlaW5nIHRyYWNrZWQuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ga2V5IC0gVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSByZXF1ZXN0XHJcbiAgICogQHJldHVybnMgYHRydWVgIGlmIHRoZSByZXF1ZXN0IGlzIGFjdGl2ZSwgYGZhbHNlYCBvdGhlcndpc2VcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGlmIChtYW5hZ2VyLmhhcygnR0VUXy9hcGkvdXNlcnNfMTY5OTk5OTk5OScpKSB7XHJcbiAgICogICBjb25zb2xlLmxvZygnUmVxdWVzdCBpcyBzdGlsbCBwZW5kaW5nJyk7XHJcbiAgICogfVxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIGhhcyhrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuYWN0aXZlUmVxdWVzdHMuaGFzKGtleSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXRyaWV2ZXMgdGhlIGNvcnJlbGF0aW9uIElEIGZvciBhIGdpdmVuIHJlcXVlc3Qga2V5LlxyXG4gICAqXHJcbiAgICogQ29ycmVsYXRpb24gSURzIGFyZSB1c2VkIGZvciBkaXN0cmlidXRlZCB0cmFjaW5nIGFuZCByZXF1ZXN0IHRyYWNraW5nXHJcbiAgICogYWNyb3NzIHNlcnZpY2VzIGFuZCBsb2dzLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGtleSAtIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgcmVxdWVzdFxyXG4gICAqIEByZXR1cm5zIFRoZSBjb3JyZWxhdGlvbiBJRCBpZiBmb3VuZCwgYHVuZGVmaW5lZGAgb3RoZXJ3aXNlXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCBjb3JyZWxhdGlvbklkID0gbWFuYWdlci5nZXRDb3JyZWxhdGlvbklkKCdHRVRfL2FwaS91c2Vyc18xNjk5OTk5OTk5Jyk7XHJcbiAgICogaWYgKGNvcnJlbGF0aW9uSWQpIHtcclxuICAgKiAgIGNvbnNvbGUubG9nKCdUcmFjZSByZXF1ZXN0IHdpdGggSUQ6JywgY29ycmVsYXRpb25JZCk7XHJcbiAgICogfVxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIGdldENvcnJlbGF0aW9uSWQoa2V5OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xyXG4gICAgcmV0dXJuIHRoaXMuY29ycmVsYXRpb25NYXAuZ2V0KGtleSk7XHJcbiAgfVxyXG59XHJcbiIsICJpbXBvcnQgdHlwZSB7IEFwaUVycm9yIH0gZnJvbSAnLi4vdHlwZXMvQXBpRXJyb3InO1xyXG5cclxuLyoqXHJcbiAqIEltcGxlbWVudHMgYXV0b21hdGljIHJldHJ5IGxvZ2ljIHdpdGggZXhwb25lbnRpYWwgYmFja29mZiBmb3IgZmFpbGVkIEhUVFAgcmVxdWVzdHMuXHJcbiAqXHJcbiAqIFRoaXMgaW50ZXJuYWwgY2xhc3MgaGFuZGxlcyB0cmFuc2llbnQgZmFpbHVyZXMgYnkgYXV0b21hdGljYWxseSByZXRyeWluZyByZXF1ZXN0c1xyXG4gKiB3aXRoIHByb2dyZXNzaXZlbHkgaW5jcmVhc2luZyBkZWxheXMgYmV0d2VlbiBhdHRlbXB0cy4gVGhlIGV4cG9uZW50aWFsIGJhY2tvZmZcclxuICogc3RyYXRlZ3kgaGVscHMgcHJldmVudCBvdmVyd2hlbG1pbmcgYSBzdHJ1Z2dsaW5nIHNlcnZlciB3aGlsZSBnaXZpbmcgdGVtcG9yYXJ5XHJcbiAqIGlzc3VlcyB0aW1lIHRvIHJlc29sdmUuXHJcbiAqXHJcbiAqIEtleSBGZWF0dXJlczpcclxuICogLSAqKkV4cG9uZW50aWFsIEJhY2tvZmYqKjogRG91YmxlcyBkZWxheSBiZXR3ZWVuIHJldHJpZXMgKGUuZy4sIDFzLCAycywgNHMsIDhzKVxyXG4gKiAtICoqU21hcnQgRXJyb3IgRGV0ZWN0aW9uKio6IFNraXBzIHJldHJ5IGZvciBub24tcmV0cnlhYmxlIGVycm9ycyAodmFsaWRhdGlvbiwgYWJvcnRzKVxyXG4gKiAtICoqQWJvcnQgU3VwcG9ydCoqOiBSZXNwZWN0cyBjYW5jZWxsYXRpb24gc2lnbmFscyBkdXJpbmcgcmV0cnkgZGVsYXlzXHJcbiAqIC0gKipUeXBlIFNhZmV0eSoqOiBGdWxseSBnZW5lcmljIGltcGxlbWVudGF0aW9uIHByZXNlcnZpbmcgcmV0dXJuIHR5cGVzXHJcbiAqXHJcbiAqIFJldHJ5IFN0cmF0ZWd5OlxyXG4gKiAtICoqUmV0cnlhYmxlKio6IE5ldHdvcmsgZXJyb3JzLCA1eHggc2VydmVyIGVycm9ycywgdGltZW91dHNcclxuICogLSAqKk5vbi1SZXRyeWFibGUqKjogVmFsaWRhdGlvbiBlcnJvcnMgKDQwMCksIEFib3J0RXJyb3JzLCBjYW5jZWxsZWQgcmVxdWVzdHNcclxuICpcclxuICogQGludGVybmFsIFRoaXMgY2xhc3MgaXMgbm90IGV4cG9ydGVkIGZyb20gdGhlIHB1YmxpYyBBUElcclxuICpcclxuICogQGV4YW1wbGVcclxuICogUmV0cnkgY29uZmlndXJhdGlvbiBpbiBBcGlDbGllbnQ6XHJcbiAqIGBgYHR5cGVzY3JpcHRcclxuICogY29uc3QgY2xpZW50ID0gbmV3IEFwaUNsaWVudCgnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nKTtcclxuICpcclxuICogLy8gUmV0cnkgdXAgdG8gMyB0aW1lcyB3aXRoIDFzIGluaXRpYWwgZGVsYXlcclxuICogY29uc3QgeyBhcGlEYXRhIH0gPSBhd2FpdCBjbGllbnQuZ2V0KCcvdXNlcnMnLCB7XHJcbiAqICAgcmV0cmllczogMyxcclxuICogICByZXRyeURlbGF5OiAxMDAwICAvLyAxcywgMnMsIDRzXHJcbiAqIH0pO1xyXG4gKiBgYGBcclxuICovXHJcbmV4cG9ydCBjbGFzcyBSZXRyeUhhbmRsZXIge1xyXG4gIC8qKlxyXG4gICAqIFJldHJpZXMgYSBmYWlsZWQgcmVxdWVzdCB3aXRoIGV4cG9uZW50aWFsIGJhY2tvZmYgc3RyYXRlZ3kuXHJcbiAgICpcclxuICAgKiBUaGUgcmV0cnkgbG9naWMgd29ya3MgYXMgZm9sbG93czpcclxuICAgKiAxLiBBdHRlbXB0cyB0aGUgcmVxdWVzdCBpbW1lZGlhdGVseVxyXG4gICAqIDIuIE9uIGZhaWx1cmUsIGNoZWNrcyBpZiB0aGUgZXJyb3IgaXMgcmV0cnlhYmxlXHJcbiAgICogMy4gSWYgcmV0cnlhYmxlIGFuZCByZXRyaWVzIHJlbWFpbiwgd2FpdHMgZm9yIHRoZSBjdXJyZW50IGRlbGF5XHJcbiAgICogNC4gRG91YmxlcyB0aGUgZGVsYXkgZm9yIHRoZSBuZXh0IGF0dGVtcHRcclxuICAgKiA1LiBSZXBlYXRzIHVudGlsIHN1Y2Nlc3Mgb3IgcmV0cmllcyBleGhhdXN0ZWRcclxuICAgKlxyXG4gICAqICoqTm9uLVJldHJ5YWJsZSBFcnJvcnM6KipcclxuICAgKiAtIFZhbGlkYXRpb24gZXJyb3JzICg0MDApIC0gQ2xpZW50IHNlbnQgYmFkIGRhdGFcclxuICAgKiAtIEFib3J0RXJyb3JzIC0gUmVxdWVzdCB3YXMgZXhwbGljaXRseSBjYW5jZWxsZWRcclxuICAgKiAtIFJlcXVlc3RzIHdpdGggYWJvcnRlZCBzaWduYWxzXHJcbiAgICpcclxuICAgKiAqKkFib3J0IEhhbmRsaW5nOioqXHJcbiAgICogSWYgdGhlIHNpZ25hbCBpcyBhYm9ydGVkIGR1cmluZyBhIHJldHJ5IGRlbGF5LCB0aGUgcmV0cnkgaXMgaW1tZWRpYXRlbHlcclxuICAgKiBjYW5jZWxsZWQgYW5kIGFuIEFib3J0RXJyb3IgaXMgdGhyb3duLlxyXG4gICAqXHJcbiAgICogQHRlbXBsYXRlIFQgLSBUaGUgcmV0dXJuIHR5cGUgb2YgdGhlIGZ1bmN0aW9uIGJlaW5nIHJldHJpZWRcclxuICAgKiBAcGFyYW0gZm4gLSBBc3luYyBmdW5jdGlvbiB0byByZXRyeSBvbiBmYWlsdXJlXHJcbiAgICogQHBhcmFtIHJldHJpZXMgLSBOdW1iZXIgb2YgcmV0cnkgYXR0ZW1wdHMgcmVtYWluaW5nIChkZWNyZW1lbnRzIGVhY2ggcmV0cnkpXHJcbiAgICogQHBhcmFtIGRlbGF5IC0gQ3VycmVudCBkZWxheSBpbiBtaWxsaXNlY29uZHMgYmVmb3JlIG5leHQgcmV0cnlcclxuICAgKiBAcGFyYW0gc2lnbmFsIC0gT3B0aW9uYWwgQWJvcnRTaWduYWwgdG8gY2FuY2VsIHJldHJpZXNcclxuICAgKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgZnVuY3Rpb24ncyByZXN1bHQgb24gc3VjY2Vzc1xyXG4gICAqIEB0aHJvd3MgVGhlIGxhc3QgZXJyb3IgZW5jb3VudGVyZWQgaWYgYWxsIHJldHJpZXMgYXJlIGV4aGF1c3RlZFxyXG4gICAqIEB0aHJvd3MgQWJvcnRFcnJvciBpZiB0aGUgc2lnbmFsIGlzIGFib3J0ZWQgZHVyaW5nIGV4ZWN1dGlvbiBvciBkZWxheVxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBCYXNpYyByZXRyeSB1c2FnZTpcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogY29uc3QgaGFuZGxlciA9IG5ldyBSZXRyeUhhbmRsZXIoKTtcclxuICAgKiBjb25zdCBmZXRjaFVzZXIgPSAoKSA9PiBmZXRjaCgnL2FwaS91c2Vycy8xMjMnKS50aGVuKHIgPT4gci5qc29uKCkpO1xyXG4gICAqXHJcbiAgICogdHJ5IHtcclxuICAgKiAgIGNvbnN0IHVzZXIgPSBhd2FpdCBoYW5kbGVyLnJldHJ5UmVxdWVzdChcclxuICAgKiAgICAgZmV0Y2hVc2VyLFxyXG4gICAqICAgICAzLCAgICAgIC8vIDMgcmV0cmllc1xyXG4gICAqICAgICAxMDAwICAgIC8vIFN0YXJ0IHdpdGggMXMgZGVsYXlcclxuICAgKiAgICk7XHJcbiAgICogICBjb25zb2xlLmxvZygnVXNlcjonLCB1c2VyKTtcclxuICAgKiB9IGNhdGNoIChlcnJvcikge1xyXG4gICAqICAgY29uc29sZS5lcnJvcignRmFpbGVkIGFmdGVyIGFsbCByZXRyaWVzOicsIGVycm9yKTtcclxuICAgKiB9XHJcbiAgICogYGBgXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIFdpdGggY2FuY2VsbGF0aW9uIHN1cHBvcnQ6XHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XHJcbiAgICogY29uc3Qgc2lnbmFsID0gY29udHJvbGxlci5zaWduYWw7XHJcbiAgICpcclxuICAgKiAvLyBDYW5jZWwgYWZ0ZXIgNSBzZWNvbmRzXHJcbiAgICogc2V0VGltZW91dCgoKSA9PiBjb250cm9sbGVyLmFib3J0KCksIDUwMDApO1xyXG4gICAqXHJcbiAgICogdHJ5IHtcclxuICAgKiAgIGF3YWl0IGhhbmRsZXIucmV0cnlSZXF1ZXN0KGZldGNoVXNlciwgNSwgMTAwMCwgc2lnbmFsKTtcclxuICAgKiB9IGNhdGNoIChlcnJvcikge1xyXG4gICAqICAgaWYgKGVycm9yLm5hbWUgPT09ICdBYm9ydEVycm9yJykge1xyXG4gICAqICAgICBjb25zb2xlLmxvZygnUmV0cnkgY2FuY2VsbGVkJyk7XHJcbiAgICogICB9XHJcbiAgICogfVxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIGFzeW5jIHJldHJ5UmVxdWVzdDxUPihcclxuICAgIGZuOiAoKSA9PiBQcm9taXNlPFQ+LFxyXG4gICAgcmV0cmllczogbnVtYmVyLFxyXG4gICAgZGVsYXk6IG51bWJlcixcclxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsXHJcbiAgKTogUHJvbWlzZTxUPiB7XHJcbiAgICB0cnkge1xyXG4gICAgICAvLyBDaGVjayBpZiBhbHJlYWR5IGFib3J0ZWRcclxuICAgICAgaWYgKHNpZ25hbD8uYWJvcnRlZCkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihzaWduYWwucmVhc29uIHx8ICdSZXF1ZXN0IGFib3J0ZWQnKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIGF3YWl0IGZuKCk7XHJcbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xyXG4gICAgICBjb25zdCBlcnIgPSBlcnJvciBhcyBBcGlFcnJvcjtcclxuXHJcbiAgICAgIC8vIERvbid0IHJldHJ5IGlmIGFib3J0ZWRcclxuICAgICAgaWYgKGVyci5uYW1lID09PSAnQWJvcnRFcnJvcicgfHwgc2lnbmFsPy5hYm9ydGVkKSB7XHJcbiAgICAgICAgdGhyb3cgZXJyb3I7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIERvbid0IHJldHJ5IHZhbGlkYXRpb24gZXJyb3JzXHJcbiAgICAgIGlmIChlcnIudHlwZSA9PT0gJ3ZhbGlkYXRpb25fZXJyb3InIHx8IGVyci5zdGF0dXMgPT09IDQwMCkge1xyXG4gICAgICAgIHRocm93IGVycm9yO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAocmV0cmllcyA9PT0gMCkgdGhyb3cgZXJyb3I7XHJcblxyXG4gICAgICAvLyBXYWl0IHdpdGggYWJvcnQgc3VwcG9ydFxyXG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgY29uc3QgdGltZW91dElkID0gc2V0VGltZW91dChyZXNvbHZlLCBkZWxheSk7XHJcblxyXG4gICAgICAgIGlmIChzaWduYWwpIHtcclxuICAgICAgICAgIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKFxyXG4gICAgICAgICAgICAnYWJvcnQnLFxyXG4gICAgICAgICAgICAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XHJcbiAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihzaWduYWwucmVhc29uIHx8ICdSZXF1ZXN0IGFib3J0ZWQnKSk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIHsgb25jZTogdHJ1ZSB9XHJcbiAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcblxyXG4gICAgICByZXR1cm4gdGhpcy5yZXRyeVJlcXVlc3QoZm4sIHJldHJpZXMgLSAxLCBkZWxheSAqIDIsIHNpZ25hbCk7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiIsICIvKipcclxuICogTWFuYWdlcyBBYm9ydFNpZ25hbCBjcmVhdGlvbiBhbmQgY29tcG9zaXRpb24gZm9yIHJlcXVlc3QgY2FuY2VsbGF0aW9uIGFuZCB0aW1lb3V0cy5cclxuICpcclxuICogVGhpcyBpbnRlcm5hbCBjbGFzcyBwcm92aWRlcyB1dGlsaXRpZXMgZm9yIHdvcmtpbmcgd2l0aCB0aGUgQWJvcnRTaWduYWwgQVBJLFxyXG4gKiBlbmFibGluZyBzb3BoaXN0aWNhdGVkIGNhbmNlbGxhdGlvbiBwYXR0ZXJucyBieSBjb21iaW5pbmcgbXVsdGlwbGUgY2FuY2VsbGF0aW9uXHJcbiAqIHNvdXJjZXMgYW5kIGNyZWF0aW5nIHRpbWVvdXQtYmFzZWQgc2lnbmFscy5cclxuICpcclxuICogS2V5IEZlYXR1cmVzOlxyXG4gKiAtICoqU2lnbmFsIENvbXBvc2l0aW9uKio6IENvbWJpbmUgbXVsdGlwbGUgQWJvcnRTaWduYWxzIGludG8gb25lXHJcbiAqIC0gKipUaW1lb3V0IFNpZ25hbHMqKjogQ3JlYXRlIHNpZ25hbHMgdGhhdCBhdXRvLWFib3J0IGFmdGVyIGEgZGVsYXlcclxuICogLSAqKkVhcmx5IEFib3J0IERldGVjdGlvbioqOiBJbW1lZGlhdGVseSBhYm9ydCBpZiBhbnkgc291cmNlIGlzIGFscmVhZHkgYWJvcnRlZFxyXG4gKiAtICoqUmVzb3VyY2UgQ2xlYW51cCoqOiBBdXRvbWF0aWMgdGltZW91dCBjbGVhbnVwIG9uIGFib3J0XHJcbiAqXHJcbiAqIFVzZSBDYXNlczpcclxuICogLSBDb21iaW5lIHVzZXIgY2FuY2VsbGF0aW9uICsgdGltZW91dCArIGNvbXBvbmVudCB1bm1vdW50IHNpZ25hbHNcclxuICogLSBDcmVhdGUgcmVxdWVzdCBkZWFkbGluZXNcclxuICogLSBJbXBsZW1lbnQgY2FzY2FkaW5nIGNhbmNlbGxhdGlvblxyXG4gKlxyXG4gKiBAaW50ZXJuYWwgVGhpcyBjbGFzcyBpcyBub3QgZXhwb3J0ZWQgZnJvbSB0aGUgcHVibGljIEFQSVxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBDb21iaW5pbmcgbXVsdGlwbGUgY2FuY2VsbGF0aW9uIHNvdXJjZXM6XHJcbiAqIGBgYHR5cGVzY3JpcHRcclxuICogY29uc3QgbWFuYWdlciA9IG5ldyBTaWduYWxNYW5hZ2VyKCk7XHJcbiAqIGNvbnN0IHVzZXJDYW5jZWwgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XHJcbiAqIGNvbnN0IHVubW91bnRTaWduYWwgPSBjb21wb25lbnRVbm1vdW50U2lnbmFsO1xyXG4gKlxyXG4gKiAvLyBSZXF1ZXN0IHdpbGwgYmUgY2FuY2VsbGVkIGlmIGVpdGhlciB1c2VyIGNsaWNrcyBjYW5jZWwgT1IgY29tcG9uZW50IHVubW91bnRzXHJcbiAqIGNvbnN0IGNvbWJpbmVkID0gbWFuYWdlci5jcmVhdGVDb21iaW5lZFNpZ25hbChbXHJcbiAqICAgdXNlckNhbmNlbC5zaWduYWwsXHJcbiAqICAgdW5tb3VudFNpZ25hbFxyXG4gKiBdKTtcclxuICpcclxuICogZmV0Y2goJy9hcGkvZGF0YScsIHsgc2lnbmFsOiBjb21iaW5lZC5zaWduYWwgfSk7XHJcbiAqIGBgYFxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFNpZ25hbE1hbmFnZXIge1xyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgYSBjb21iaW5lZCBBYm9ydENvbnRyb2xsZXIgdGhhdCBhYm9ydHMgd2hlbiBhbnkgc291cmNlIHNpZ25hbCBhYm9ydHMuXHJcbiAgICpcclxuICAgKiBUaGlzIG1ldGhvZCBpbXBsZW1lbnRzIHRoZSBcImFueVwiIHBhdHRlcm4gZm9yIGNhbmNlbGxhdGlvbjogdGhlIGNvbWJpbmVkIHNpZ25hbFxyXG4gICAqIHdpbGwgYWJvcnQgYXMgc29vbiBhcyBBTlkgb2YgdGhlIHNvdXJjZSBzaWduYWxzIGFib3J0LiBUaGlzIGlzIHVzZWZ1bCBmb3JcclxuICAgKiBjb29yZGluYXRpbmcgbXVsdGlwbGUgY2FuY2VsbGF0aW9uIGNvbmRpdGlvbnM6XHJcbiAgICogLSBVc2VyIGNsaWNrcyBjYW5jZWwgYnV0dG9uXHJcbiAgICogLSBSZXF1ZXN0IHRpbWVvdXQgZXhwaXJlc1xyXG4gICAqIC0gQ29tcG9uZW50IHVubW91bnRzXHJcbiAgICogLSBQYXJlbnQgcmVxdWVzdCBpcyBjYW5jZWxsZWRcclxuICAgKlxyXG4gICAqICoqRWFybHkgQWJvcnQgT3B0aW1pemF0aW9uOioqXHJcbiAgICogSWYgYW55IHNvdXJjZSBzaWduYWwgaXMgYWxyZWFkeSBhYm9ydGVkIHdoZW4gdGhpcyBtZXRob2QgaXMgY2FsbGVkLFxyXG4gICAqIHRoZSByZXR1cm5lZCBjb250cm9sbGVyIGlzIGltbWVkaWF0ZWx5IGFib3J0ZWQgd2l0aG91dCBzZXR0aW5nIHVwIGxpc3RlbmVycy5cclxuICAgKlxyXG4gICAqICoqTWVtb3J5IE1hbmFnZW1lbnQ6KipcclxuICAgKiBFdmVudCBsaXN0ZW5lcnMgYXJlIHJlZ2lzdGVyZWQgd2l0aCBgeyBvbmNlOiB0cnVlIH1gIHRvIHByZXZlbnQgbWVtb3J5IGxlYWtzLFxyXG4gICAqIGFzIHRoZXkgYXV0b21hdGljYWxseSBjbGVhbiB1cCBhZnRlciBmaXJpbmcuXHJcbiAgICpcclxuICAgKiBAcGFyYW0gc2lnbmFscyAtIEFycmF5IG9mIEFib3J0U2lnbmFscyB0byBjb21iaW5lICh1bmRlZmluZWQgdmFsdWVzIGFyZSBpZ25vcmVkKVxyXG4gICAqIEByZXR1cm5zIEEgbmV3IEFib3J0Q29udHJvbGxlciB0aGF0IGFib3J0cyB3aGVuIGFueSBzb3VyY2Ugc2lnbmFsIGFib3J0c1xyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBVc2VyIGNhbmNlbGxhdGlvbiArIHRpbWVvdXQ6XHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IHVzZXJDb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xyXG4gICAqIGNvbnN0IHRpbWVvdXQgPSBtYW5hZ2VyLmNyZWF0ZVRpbWVvdXRTaWduYWwoMzAwMDApO1xyXG4gICAqXHJcbiAgICogY29uc3QgY29tYmluZWQgPSBtYW5hZ2VyLmNyZWF0ZUNvbWJpbmVkU2lnbmFsKFtcclxuICAgKiAgIHVzZXJDb250cm9sbGVyLnNpZ25hbCxcclxuICAgKiAgIHRpbWVvdXQuc2lnbmFsXHJcbiAgICogXSk7XHJcbiAgICpcclxuICAgKiAvLyBSZXF1ZXN0IHdpbGwgYmUgY2FuY2VsbGVkIGFmdGVyIDMwcyBPUiB3aGVuIHVzZXIgY2xpY2tzIGNhbmNlbFxyXG4gICAqIGZldGNoKCcvYXBpL2RhdGEnLCB7IHNpZ25hbDogY29tYmluZWQuc2lnbmFsIH0pO1xyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBSZWFjdCBjb21wb25lbnQgd2l0aCBjbGVhbnVwOlxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiB1c2VFZmZlY3QoKCkgPT4ge1xyXG4gICAqICAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcclxuICAgKlxyXG4gICAqICAgY29uc3QgY29tYmluZWQgPSBtYW5hZ2VyLmNyZWF0ZUNvbWJpbmVkU2lnbmFsKFtcclxuICAgKiAgICAgY29udHJvbGxlci5zaWduYWwsXHJcbiAgICogICAgIHVubW91bnRTaWduYWwgIC8vIEZyb20gY29tcG9uZW50IGxpZmVjeWNsZVxyXG4gICAqICAgXSk7XHJcbiAgICpcclxuICAgKiAgIGZldGNoRGF0YShjb21iaW5lZC5zaWduYWwpO1xyXG4gICAqXHJcbiAgICogICByZXR1cm4gKCkgPT4gY29udHJvbGxlci5hYm9ydCgpOyAvLyBDbGVhbnVwXHJcbiAgICogfSwgW10pO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIGNyZWF0ZUNvbWJpbmVkU2lnbmFsKFxyXG4gICAgc2lnbmFsczogQXJyYXk8QWJvcnRTaWduYWwgfCB1bmRlZmluZWQ+XHJcbiAgKTogQWJvcnRDb250cm9sbGVyIHtcclxuICAgIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XHJcblxyXG4gICAgZm9yIChjb25zdCBzaWduYWwgb2Ygc2lnbmFscykge1xyXG4gICAgICBpZiAoc2lnbmFsKSB7XHJcbiAgICAgICAgaWYgKHNpZ25hbC5hYm9ydGVkKSB7XHJcbiAgICAgICAgICBjb250cm9sbGVyLmFib3J0KHNpZ25hbC5yZWFzb24pO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBzaWduYWwuYWRkRXZlbnRMaXN0ZW5lcihcclxuICAgICAgICAgICdhYm9ydCcsXHJcbiAgICAgICAgICAoKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnRyb2xsZXIuYWJvcnQoc2lnbmFsLnJlYXNvbik7XHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgICAgeyBvbmNlOiB0cnVlIH1cclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGNvbnRyb2xsZXI7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGVzIGFuIEFib3J0Q29udHJvbGxlciB0aGF0IGF1dG9tYXRpY2FsbHkgYWJvcnRzIGFmdGVyIGEgc3BlY2lmaWVkIHRpbWVvdXQuXHJcbiAgICpcclxuICAgKiBUaGlzIG1ldGhvZCBjcmVhdGVzIGEgdGltZS1iYXNlZCBjYW5jZWxsYXRpb24gbWVjaGFuaXNtIHVzZWZ1bCBmb3IgaW1wbGVtZW50aW5nXHJcbiAgICogcmVxdWVzdCB0aW1lb3V0cyBhbmQgZGVhZGxpbmVzLiBUaGUgc2lnbmFsIHdpbGwgYXV0b21hdGljYWxseSBhYm9ydCBhZnRlciB0aGVcclxuICAgKiBzcGVjaWZpZWQgZHVyYXRpb24sIHByb3ZpZGluZyBhIGNvbnNpc3RlbnQgdGltZW91dCBleHBlcmllbmNlLlxyXG4gICAqXHJcbiAgICogKipBdXRvbWF0aWMgQ2xlYW51cDoqKlxyXG4gICAqIElmIHRoZSBzaWduYWwgaXMgYWJvcnRlZCBieSBvdGhlciBtZWFucyBiZWZvcmUgdGhlIHRpbWVvdXQgZXhwaXJlcywgdGhlIGludGVybmFsXHJcbiAgICogc2V0VGltZW91dCBpcyBhdXRvbWF0aWNhbGx5IGNsZWFyZWQgdG8gcHJldmVudCBtZW1vcnkgbGVha3MuXHJcbiAgICpcclxuICAgKiAqKkFib3J0IFJlYXNvbjoqKlxyXG4gICAqIFRoZSBhYm9ydCByZWFzb24gaW5jbHVkZXMgdGhlIHRpbWVvdXQgZHVyYXRpb24gZm9yIGRlYnVnZ2luZyBwdXJwb3NlczpcclxuICAgKiBgXCJSZXF1ZXN0IHRpbWVvdXQgYWZ0ZXIge3RpbWVvdXR9bXNcImBcclxuICAgKlxyXG4gICAqIEBwYXJhbSB0aW1lb3V0IC0gVGltZW91dCBkdXJhdGlvbiBpbiBtaWxsaXNlY29uZHNcclxuICAgKiBAcmV0dXJucyBBbiBBYm9ydENvbnRyb2xsZXIgdGhhdCB3aWxsIGFib3J0IGFmdGVyIHRoZSB0aW1lb3V0XHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIFNpbXBsZSByZXF1ZXN0IHRpbWVvdXQ6XHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IG1hbmFnZXIgPSBuZXcgU2lnbmFsTWFuYWdlcigpO1xyXG4gICAqIGNvbnN0IHRpbWVvdXQgPSBtYW5hZ2VyLmNyZWF0ZVRpbWVvdXRTaWduYWwoNTAwMCk7IC8vIDUgc2Vjb25kc1xyXG4gICAqXHJcbiAgICogdHJ5IHtcclxuICAgKiAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goJy9hcGkvc2xvdy1lbmRwb2ludCcsIHtcclxuICAgKiAgICAgc2lnbmFsOiB0aW1lb3V0LnNpZ25hbFxyXG4gICAqICAgfSk7XHJcbiAgICogICBjb25zdCBkYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xyXG4gICAqIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICogICBpZiAoZXJyb3IubmFtZSA9PT0gJ0Fib3J0RXJyb3InKSB7XHJcbiAgICogICAgIGNvbnNvbGUuZXJyb3IoJ1JlcXVlc3QgdGltZWQgb3V0IGFmdGVyIDUgc2Vjb25kcycpO1xyXG4gICAqICAgfVxyXG4gICAqIH1cclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogRGlmZmVyZW50IHRpbWVvdXRzIGZvciBkaWZmZXJlbnQgb3BlcmF0aW9uczpcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogLy8gU2hvcnQgdGltZW91dCBmb3IgcXVpY2sgb3BlcmF0aW9uc1xyXG4gICAqIGNvbnN0IHF1aWNrVGltZW91dCA9IG1hbmFnZXIuY3JlYXRlVGltZW91dFNpZ25hbCgyMDAwKTtcclxuICAgKiBhd2FpdCBmZXRjaCgnL2FwaS9oZWFsdGgnLCB7IHNpZ25hbDogcXVpY2tUaW1lb3V0LnNpZ25hbCB9KTtcclxuICAgKlxyXG4gICAqIC8vIExvbmcgdGltZW91dCBmb3IgaGVhdnkgb3BlcmF0aW9uc1xyXG4gICAqIGNvbnN0IGxvbmdUaW1lb3V0ID0gbWFuYWdlci5jcmVhdGVUaW1lb3V0U2lnbmFsKDYwMDAwKTtcclxuICAgKiBhd2FpdCBmZXRjaCgnL2FwaS9leHBvcnQnLCB7IHNpZ25hbDogbG9uZ1RpbWVvdXQuc2lnbmFsIH0pO1xyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBNYW51YWwgY2FuY2VsbGF0aW9uIGJlZm9yZSB0aW1lb3V0OlxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCB0aW1lb3V0ID0gbWFuYWdlci5jcmVhdGVUaW1lb3V0U2lnbmFsKDMwMDAwKTtcclxuICAgKlxyXG4gICAqIC8vIElmIHVzZXIgY2FuY2VscywgdGltZW91dCBpcyBhdXRvbWF0aWNhbGx5IGNsZWFuZWQgdXBcclxuICAgKiB0aW1lb3V0LmFib3J0KCdVc2VyIGNhbmNlbGxlZCcpO1xyXG4gICAqIC8vIEludGVybmFsIHNldFRpbWVvdXQgaXMgY2xlYXJlZCwgbm8gbWVtb3J5IGxlYWtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBjcmVhdGVUaW1lb3V0U2lnbmFsKHRpbWVvdXQ6IG51bWJlcik6IEFib3J0Q29udHJvbGxlciB7XHJcbiAgICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xyXG5cclxuICAgIGNvbnN0IHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICBjb250cm9sbGVyLmFib3J0KGBSZXF1ZXN0IHRpbWVvdXQgYWZ0ZXIgJHt0aW1lb3V0fW1zYCk7XHJcbiAgICB9LCB0aW1lb3V0KTtcclxuXHJcbiAgICAvLyBDbGVhbiB1cCB0aW1lb3V0IHdoZW4gc2lnbmFsIGlzIGFib3J0ZWRcclxuICAgIGNvbnRyb2xsZXIuc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXHJcbiAgICAgICdhYm9ydCcsXHJcbiAgICAgICgpID0+IHtcclxuICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcclxuICAgICAgfSxcclxuICAgICAgeyBvbmNlOiB0cnVlIH1cclxuICAgICk7XHJcblxyXG4gICAgcmV0dXJuIGNvbnRyb2xsZXI7XHJcbiAgfVxyXG59XHJcbiIsICJpbXBvcnQgdHlwZSB7IFJlc3BvbnNlRGF0YSB9IGZyb20gJy4uL01vZGVscyc7XHJcblxyXG4vKipcclxuICogUGFyc2VzIEhUVFAgcmVzcG9uc2UgYm9kaWVzIGludG8gYXBwcm9wcmlhdGUgSmF2YVNjcmlwdCB0eXBlcyBiYXNlZCBvbiBDb250ZW50LVR5cGUgaGVhZGVycy5cclxuICpcclxuICogVGhpcyBpbnRlcm5hbCBjbGFzcyBoYW5kbGVzIHRoZSBjb21wbGV4aXR5IG9mIGNvbnZlcnRpbmcgdmFyaW91cyBIVFRQIHJlc3BvbnNlIGZvcm1hdHNcclxuICogaW50byB1c2FibGUgSmF2YVNjcmlwdCBkYXRhIHN0cnVjdHVyZXMuIEl0IGludGVsbGlnZW50bHkgZGV0ZWN0cyB0aGUgcmVzcG9uc2UgdHlwZVxyXG4gKiBhbmQgYXBwbGllcyB0aGUgYXBwcm9wcmlhdGUgcGFyc2luZyBzdHJhdGVneS5cclxuICpcclxuICogU3VwcG9ydGVkIENvbnRlbnQgVHlwZXM6XHJcbiAqIC0gKiphcHBsaWNhdGlvbi9qc29uKio6IFBhcnNlZCBhcyBKU09OIG9iamVjdHMvYXJyYXlzXHJcbiAqIC0gKip0ZXh0LyoqKiAodGV4dC9wbGFpbiwgdGV4dC9odG1sLCBldGMuKTogUmV0dXJuZWQgYXMgc3RyaW5nXHJcbiAqIC0gKiphcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0qKjogUmV0dXJuZWQgYXMgQmxvYiBmb3IgYmluYXJ5IGRhdGFcclxuICogLSAqKlVua25vd24vTWlzc2luZyoqOiBBdHRlbXB0cyBKU09OIHBhcnNlLCBmYWxscyBiYWNrIHRvIHRleHRcclxuICpcclxuICogS2V5IEZlYXR1cmVzOlxyXG4gKiAtICoqQXV0b21hdGljIERldGVjdGlvbioqOiBVc2VzIENvbnRlbnQtVHlwZSBoZWFkZXIgdG8gZGV0ZXJtaW5lIHBhcnNpbmcgc3RyYXRlZ3lcclxuICogLSAqKkdyYWNlZnVsIEZhbGxiYWNrKio6IEF0dGVtcHRzIEpTT04gcGFyc2luZyBmb3IgdW5rbm93biB0eXBlcywgZmFsbHMgYmFjayB0byB0ZXh0XHJcbiAqIC0gKipCaW5hcnkgU3VwcG9ydCoqOiBIYW5kbGVzIGJpbmFyeSBkYXRhIHZpYSBCbG9iXHJcbiAqIC0gKipUeXBlIFNhZmV0eSoqOiBSZXR1cm5zIHR5cGVkIFJlc3BvbnNlRGF0YSB1bmlvblxyXG4gKlxyXG4gKiBAaW50ZXJuYWwgVGhpcyBjbGFzcyBpcyBub3QgZXhwb3J0ZWQgZnJvbSB0aGUgcHVibGljIEFQSVxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBQYXJzaW5nIGRpZmZlcmVudCByZXNwb25zZSB0eXBlczpcclxuICogYGBgdHlwZXNjcmlwdFxyXG4gKiBjb25zdCBwYXJzZXIgPSBuZXcgUmVzcG9uc2VQYXJzZXIoKTtcclxuICpcclxuICogLy8gSlNPTiByZXNwb25zZVxyXG4gKiBjb25zdCBqc29uUmVzcG9uc2UgPSBuZXcgUmVzcG9uc2UoJ3tcImlkXCI6IDF9Jywge1xyXG4gKiAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9XHJcbiAqIH0pO1xyXG4gKiBjb25zdCBkYXRhID0gYXdhaXQgcGFyc2VyLnBhcnNlUmVzcG9uc2UoanNvblJlc3BvbnNlKTtcclxuICogLy8gPT4geyBpZDogMSB9XHJcbiAqXHJcbiAqIC8vIFRleHQgcmVzcG9uc2VcclxuICogY29uc3QgdGV4dFJlc3BvbnNlID0gbmV3IFJlc3BvbnNlKCdIZWxsbyBXb3JsZCcsIHtcclxuICogICBoZWFkZXJzOiB7ICdDb250ZW50LVR5cGUnOiAndGV4dC9wbGFpbicgfVxyXG4gKiB9KTtcclxuICogY29uc3QgdGV4dCA9IGF3YWl0IHBhcnNlci5wYXJzZVJlc3BvbnNlKHRleHRSZXNwb25zZSk7XHJcbiAqIC8vID0+IFwiSGVsbG8gV29ybGRcIlxyXG4gKlxyXG4gKiAvLyBCaW5hcnkgcmVzcG9uc2VcclxuICogY29uc3QgYmxvYlJlc3BvbnNlID0gbmV3IFJlc3BvbnNlKGJpbmFyeURhdGEsIHtcclxuICogICBoZWFkZXJzOiB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtJyB9XHJcbiAqIH0pO1xyXG4gKiBjb25zdCBibG9iID0gYXdhaXQgcGFyc2VyLnBhcnNlUmVzcG9uc2UoYmxvYlJlc3BvbnNlKTtcclxuICogLy8gPT4gQmxvYiB7IC4uLiB9XHJcbiAqIGBgYFxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFJlc3BvbnNlUGFyc2VyIHtcclxuICAvKipcclxuICAgKiBQYXJzZXMgdGhlIEhUVFAgcmVzcG9uc2UgYm9keSBpbnRvIGFuIGFwcHJvcHJpYXRlIEphdmFTY3JpcHQgdHlwZS5cclxuICAgKlxyXG4gICAqIFRoZSBwYXJzaW5nIHN0cmF0ZWd5IGlzIGRldGVybWluZWQgYnkgdGhlIENvbnRlbnQtVHlwZSBoZWFkZXI6XHJcbiAgICogMS4gKipKU09OKiogKGFwcGxpY2F0aW9uL2pzb24pOiBDYWxscyBgcmVzcG9uc2UuanNvbigpYFxyXG4gICAqIDIuICoqVGV4dCoqICh0ZXh0LyopOiBDYWxscyBgcmVzcG9uc2UudGV4dCgpYFxyXG4gICAqIDMuICoqQmluYXJ5KiogKGFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSk6IENhbGxzIGByZXNwb25zZS5ibG9iKClgXHJcbiAgICogNC4gKipVbmtub3duKio6IFJlYWRzIGFzIHRleHQsIGF0dGVtcHRzIEpTT04gcGFyc2UsIGZhbGxzIGJhY2sgdG8gcmF3IHRleHRcclxuICAgKlxyXG4gICAqICoqRmFsbGJhY2sgQmVoYXZpb3I6KipcclxuICAgKiBGb3IgcmVzcG9uc2VzIHdpdGhvdXQgYSBDb250ZW50LVR5cGUgaGVhZGVyIG9yIHdpdGggdW5rbm93biB0eXBlcywgdGhlIHBhcnNlclxyXG4gICAqIGF0dGVtcHRzIHRvIHBhcnNlIGFzIEpTT04gZmlyc3QgKGNvbW1vbiBmb3IgQVBJcyB0aGF0IGRvbid0IHNldCBwcm9wZXIgaGVhZGVycykuXHJcbiAgICogSWYgSlNPTiBwYXJzaW5nIGZhaWxzLCBpdCByZXR1cm5zIHRoZSByYXcgdGV4dC5cclxuICAgKlxyXG4gICAqIEBwYXJhbSByZXNwb25zZSAtIFRoZSBGZXRjaCBBUEkgUmVzcG9uc2Ugb2JqZWN0IHRvIHBhcnNlXHJcbiAgICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIHBhcnNlZCByZXNwb25zZSBkYXRhXHJcbiAgICogQHJldHVybnMgQ2FuIGJlOiBKU09OIG9iamVjdC9hcnJheSwgc3RyaW5nLCBvciBCbG9iIGRlcGVuZGluZyBvbiBDb250ZW50LVR5cGVcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogQVBJIHJlc3BvbnNlIHBhcnNpbmc6XHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goJy9hcGkvdXNlcnMnKTtcclxuICAgKiBjb25zdCBkYXRhID0gYXdhaXQgcGFyc2VyLnBhcnNlUmVzcG9uc2UocmVzcG9uc2UpO1xyXG4gICAqXHJcbiAgICogaWYgKHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJykge1xyXG4gICAqICAgY29uc29sZS5sb2coJ1RleHQgcmVzcG9uc2U6JywgZGF0YSk7XHJcbiAgICogfSBlbHNlIGlmIChkYXRhIGluc3RhbmNlb2YgQmxvYikge1xyXG4gICAqICAgY29uc29sZS5sb2coJ0JpbmFyeSByZXNwb25zZTonLCBkYXRhLnNpemUsICdieXRlcycpO1xyXG4gICAqIH0gZWxzZSB7XHJcbiAgICogICBjb25zb2xlLmxvZygnSlNPTiByZXNwb25zZTonLCBkYXRhKTtcclxuICAgKiB9XHJcbiAgICogYGBgXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIEhhbmRsaW5nIGRpZmZlcmVudCBjb250ZW50IHR5cGVzOlxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiAvLyBDU1YgZmlsZSBkb3dubG9hZFxyXG4gICAqIGNvbnN0IGNzdlJlc3BvbnNlID0gYXdhaXQgZmV0Y2goJy9hcGkvZXhwb3J0LmNzdicpO1xyXG4gICAqIGNvbnN0IGJsb2IgPSBhd2FpdCBwYXJzZXIucGFyc2VSZXNwb25zZShjc3ZSZXNwb25zZSk7XHJcbiAgICogLy8gUmV0dXJucyBCbG9iIGZvciBkb3dubG9hZFxyXG4gICAqXHJcbiAgICogLy8gSlNPTiBBUElcclxuICAgKiBjb25zdCBqc29uUmVzcG9uc2UgPSBhd2FpdCBmZXRjaCgnL2FwaS91c2VycycpO1xyXG4gICAqIGNvbnN0IHVzZXJzID0gYXdhaXQgcGFyc2VyLnBhcnNlUmVzcG9uc2UoanNvblJlc3BvbnNlKTtcclxuICAgKiAvLyBSZXR1cm5zIHBhcnNlZCBKU09OIGFycmF5XHJcbiAgICpcclxuICAgKiAvLyBQbGFpbiB0ZXh0IGxvZ3NcclxuICAgKiBjb25zdCBsb2dSZXNwb25zZSA9IGF3YWl0IGZldGNoKCcvYXBpL2xvZ3MnKTtcclxuICAgKiBjb25zdCBsb2dzID0gYXdhaXQgcGFyc2VyLnBhcnNlUmVzcG9uc2UobG9nUmVzcG9uc2UpO1xyXG4gICAqIC8vIFJldHVybnMgc3RyaW5nXHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgYXN5bmMgcGFyc2VSZXNwb25zZShyZXNwb25zZTogUmVzcG9uc2UpOiBQcm9taXNlPFJlc3BvbnNlRGF0YT4ge1xyXG4gICAgY29uc3QgY29udGVudFR5cGUgPSByZXNwb25zZS5oZWFkZXJzLmdldCgnY29udGVudC10eXBlJyk7XHJcblxyXG4gICAgaWYgKGNvbnRlbnRUeXBlPy5pbmNsdWRlcygnYXBwbGljYXRpb24vanNvbicpKSB7XHJcbiAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XHJcbiAgICB9IGVsc2UgaWYgKGNvbnRlbnRUeXBlPy5pbmNsdWRlcygndGV4dC8nKSkge1xyXG4gICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xyXG4gICAgfSBlbHNlIGlmIChjb250ZW50VHlwZT8uaW5jbHVkZXMoJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbScpKSB7XHJcbiAgICAgIHJldHVybiByZXNwb25zZS5ibG9iKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBUcnkgSlNPTiBmaXJzdCwgZmFsbGJhY2sgdG8gdGV4dFxyXG4gICAgICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVzcG9uc2UudGV4dCgpO1xyXG5cclxuICAgICAgdHJ5IHtcclxuICAgICAgICByZXR1cm4gSlNPTi5wYXJzZSh0ZXh0KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcclxuICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgcmV0dXJuIHRleHQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwgImltcG9ydCB0eXBlIHsgUXVlcnlQYXJhbXMgfSBmcm9tICcuLi9Nb2RlbHMnO1xyXG5cclxuLyoqXHJcbiAqIENvbnN0cnVjdHMgZnVsbHktcXVhbGlmaWVkIFVSTHMgd2l0aCBwcm9wZXIgcXVlcnkgcGFyYW1ldGVyIGVuY29kaW5nLlxyXG4gKlxyXG4gKiBUaGlzIGludGVybmFsIGNsYXNzIGhhbmRsZXMgdGhlIGNvbXBsZXhpdHkgb2YgVVJMIGNvbnN0cnVjdGlvbiwgY29tYmluaW5nXHJcbiAqIGJhc2UgVVJMcywgZW5kcG9pbnRzLCBhbmQgcXVlcnkgcGFyYW1ldGVycyB3aXRoIHByb3BlciBlbmNvZGluZyBhbmQgYXJyYXlcclxuICogaGFuZGxpbmcuIEl0IHVzZXMgdGhlIG5hdGl2ZSBVUkwgQVBJIGZvciByZWxpYWJsZSBVUkwgY29tcG9zaXRpb24uXHJcbiAqXHJcbiAqIEtleSBGZWF0dXJlczpcclxuICogLSAqKlVSTCBDb21wb3NpdGlvbioqOiBTYWZlbHkgY29tYmluZXMgYmFzZSBVUkwgYW5kIGVuZHBvaW50IHBhdGhzXHJcbiAqIC0gKipRdWVyeSBQYXJhbWV0ZXIgRW5jb2RpbmcqKjogQXV0b21hdGljIGVuY29kaW5nIG9mIHNwZWNpYWwgY2hhcmFjdGVyc1xyXG4gKiAtICoqQXJyYXkgU3VwcG9ydCoqOiBIYW5kbGVzIGFycmF5IHBhcmFtZXRlcnMgd2l0aCBtdWx0aXBsZSB2YWx1ZXNcclxuICogLSAqKk51bGwvVW5kZWZpbmVkIEZpbHRlcmluZyoqOiBBdXRvbWF0aWNhbGx5IHNraXBzIG51bGwvdW5kZWZpbmVkIHZhbHVlc1xyXG4gKiAtICoqVHlwZSBTYWZldHkqKjogU3Ryb25nbHkgdHlwZWQgcXVlcnkgcGFyYW1ldGVyIHZhbHVlc1xyXG4gKlxyXG4gKiBBcnJheSBIYW5kbGluZzpcclxuICogQXJyYXkgcGFyYW1ldGVycyBhcmUgc2VyaWFsaXplZCBieSBhcHBlbmRpbmcgdGhlIHNhbWUga2V5IG11bHRpcGxlIHRpbWVzOlxyXG4gKiBgP3RhZ3M9amF2YXNjcmlwdCZ0YWdzPXR5cGVzY3JpcHQmdGFncz1yZWFjdGBcclxuICpcclxuICogQGludGVybmFsIFRoaXMgY2xhc3MgaXMgbm90IGV4cG9ydGVkIGZyb20gdGhlIHB1YmxpYyBBUElcclxuICpcclxuICogQGV4YW1wbGVcclxuICogQnVpbGRpbmcgVVJMcyB3aXRoIHF1ZXJ5IHBhcmFtZXRlcnM6XHJcbiAqIGBgYHR5cGVzY3JpcHRcclxuICogY29uc3QgYnVpbGRlciA9IG5ldyBVcmxCdWlsZGVyKCk7XHJcbiAqXHJcbiAqIGNvbnN0IHVybCA9IGJ1aWxkZXIuYnVpbGRVUkwoXHJcbiAqICAgJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJyxcclxuICogICAnL3VzZXJzJyxcclxuICogICB7IGFjdGl2ZTogdHJ1ZSwgcm9sZTogJ2FkbWluJywgcGFnZTogMSB9XHJcbiAqICk7XHJcbiAqIC8vID0+IFwiaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20vdXNlcnM/YWN0aXZlPXRydWUmcm9sZT1hZG1pbiZwYWdlPTFcIlxyXG4gKiBgYGBcclxuICovXHJcbmV4cG9ydCBjbGFzcyBVcmxCdWlsZGVyIHtcclxuICAvKipcclxuICAgKiBCdWlsZHMgYSBjb21wbGV0ZSBVUkwgYnkgY29tYmluaW5nIGJhc2UgVVJMLCBlbmRwb2ludCwgYW5kIHF1ZXJ5IHBhcmFtZXRlcnMuXHJcbiAgICpcclxuICAgKiBUaGUgVVJMIGNvbnN0cnVjdGlvbiBwcm9jZXNzOlxyXG4gICAqIDEuIENvbWJpbmVzIGBiYXNlVVJMYCBhbmQgYGVuZHBvaW50YCB1c2luZyBVUkwgQVBJXHJcbiAgICogMi4gSXRlcmF0ZXMgdGhyb3VnaCBxdWVyeSBwYXJhbWV0ZXJzXHJcbiAgICogMy4gU2tpcHMgbnVsbC91bmRlZmluZWQgdmFsdWVzXHJcbiAgICogNC4gSGFuZGxlcyBhcnJheXMgYnkgYXBwZW5kaW5nIG11bHRpcGxlIHZhbHVlcyB3aXRoIHNhbWUga2V5XHJcbiAgICogNS4gQ29udmVydHMgYWxsIHZhbHVlcyB0byBzdHJpbmdzXHJcbiAgICogNi4gUmV0dXJucyBmdWxseS1xdWFsaWZpZWQgVVJMIHN0cmluZ1xyXG4gICAqXHJcbiAgICogKipQYXRoIEhhbmRsaW5nOioqXHJcbiAgICogVGhlIGVuZHBvaW50IGNhbiBiZSBlaXRoZXIgcmVsYXRpdmUgb3IgYWJzb2x1dGU6XHJcbiAgICogLSBSZWxhdGl2ZTogYC91c2Vyc2AgXHUyMTkyIENvbWJpbmVkIHdpdGggYmFzZVVSTFxyXG4gICAqIC0gQWJzb2x1dGU6IGBodHRwczovL290aGVyLWFwaS5jb20vdXNlcnNgIFx1MjE5MiBVc2VzIGFic29sdXRlIFVSTFxyXG4gICAqXHJcbiAgICogKipFbmNvZGluZzoqKlxyXG4gICAqIEFsbCBwYXJhbWV0ZXIgdmFsdWVzIGFyZSBhdXRvbWF0aWNhbGx5IFVSTC1lbmNvZGVkIGJ5IHRoZSBVUkwgQVBJLFxyXG4gICAqIHNvIHNwZWNpYWwgY2hhcmFjdGVycyAoc3BhY2VzLCAmLCA9LCBldGMuKSBhcmUgc2FmZWx5IGhhbmRsZWQuXHJcbiAgICpcclxuICAgKiBAcGFyYW0gYmFzZVVSTCAtIEJhc2UgVVJMIGZvciB0aGUgQVBJIChlLmcuLCAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nKVxyXG4gICAqIEBwYXJhbSBlbmRwb2ludCAtIEFQSSBlbmRwb2ludCBwYXRoIHJlbGF0aXZlIHRvIGJhc2VVUkwgKGUuZy4sICcvdXNlcnMvMTIzJylcclxuICAgKiBAcGFyYW0gcGFyYW1zIC0gT3B0aW9uYWwgcXVlcnkgcGFyYW1ldGVycyBhcyBrZXktdmFsdWUgcGFpcnNcclxuICAgKiBAcmV0dXJucyBUaGUgZnVsbHktcXVhbGlmaWVkIFVSTCBzdHJpbmcgd2l0aCBlbmNvZGVkIHF1ZXJ5IHBhcmFtZXRlcnNcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogQmFzaWMgVVJMIGNvbnN0cnVjdGlvbjpcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogY29uc3QgdXJsID0gYnVpbGRlci5idWlsZFVSTChcclxuICAgKiAgICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsXHJcbiAgICogICAnL3NlYXJjaCcsXHJcbiAgICogICB7IHE6ICdoZWxsbyB3b3JsZCcsIGxpbWl0OiAxMCB9XHJcbiAgICogKTtcclxuICAgKiAvLyA9PiBcImh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3NlYXJjaD9xPWhlbGxvK3dvcmxkJmxpbWl0PTEwXCJcclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogQXJyYXkgcGFyYW1ldGVyczpcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogY29uc3QgdXJsID0gYnVpbGRlci5idWlsZFVSTChcclxuICAgKiAgICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsXHJcbiAgICogICAnL3Bvc3RzJyxcclxuICAgKiAgIHsgdGFnczogWydqYXZhc2NyaXB0JywgJ3R5cGVzY3JpcHQnLCAncmVhY3QnXSB9XHJcbiAgICogKTtcclxuICAgKiAvLyA9PiBcImh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3Bvc3RzP3RhZ3M9amF2YXNjcmlwdCZ0YWdzPXR5cGVzY3JpcHQmdGFncz1yZWFjdFwiXHJcbiAgICogYGBgXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIE51bGwvdW5kZWZpbmVkIGhhbmRsaW5nOlxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCB1cmwgPSBidWlsZGVyLmJ1aWxkVVJMKFxyXG4gICAqICAgJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJyxcclxuICAgKiAgICcvdXNlcnMnLFxyXG4gICAqICAge1xyXG4gICAqICAgICBuYW1lOiAnSm9obicsXHJcbiAgICogICAgIGFnZTogbnVsbCwgICAgICAgIC8vIFNraXBwZWRcclxuICAgKiAgICAgZW1haWw6IHVuZGVmaW5lZCAgLy8gU2tpcHBlZFxyXG4gICAqICAgfVxyXG4gICAqICk7XHJcbiAgICogLy8gPT4gXCJodHRwczovL2FwaS5leGFtcGxlLmNvbS91c2Vycz9uYW1lPUpvaG5cIlxyXG4gICAqIGBgYFxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBTcGVjaWFsIGNoYXJhY3RlcnMgZW5jb2Rpbmc6XHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IHVybCA9IGJ1aWxkZXIuYnVpbGRVUkwoXHJcbiAgICogICAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nLFxyXG4gICAqICAgJy9zZWFyY2gnLFxyXG4gICAqICAgeyBxOiAnZm9vICYgYmFyJywgY2F0ZWdvcnk6ICdjb2RlL2V4YW1wbGVzJyB9XHJcbiAgICogKTtcclxuICAgKiAvLyA9PiBcImh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3NlYXJjaD9xPWZvbyslMjYrYmFyJmNhdGVnb3J5PWNvZGUlMkZleGFtcGxlc1wiXHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgYnVpbGRVUkwoYmFzZVVSTDogc3RyaW5nLCBlbmRwb2ludDogc3RyaW5nLCBwYXJhbXM/OiBRdWVyeVBhcmFtcyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKGVuZHBvaW50LCBiYXNlVVJMKTtcclxuXHJcbiAgICBpZiAocGFyYW1zKSB7XHJcbiAgICAgIE9iamVjdC5rZXlzKHBhcmFtcykuZm9yRWFjaChrZXkgPT4ge1xyXG4gICAgICAgIGNvbnN0IHZhbHVlID0gcGFyYW1zW2tleV07XHJcblxyXG4gICAgICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsKSB7XHJcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcclxuICAgICAgICAgICAgdmFsdWUuZm9yRWFjaCh2ID0+IHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKGtleSwgU3RyaW5nKHYpKSk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChrZXksIFN0cmluZyh2YWx1ZSkpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHVybC50b1N0cmluZygpO1xyXG4gIH1cclxufVxyXG4iLCAiaW1wb3J0IHsgZ2VuZXJhdGVDb3JyZWxhdGlvbklkIH0gZnJvbSAnLi9Db3JyZWxhdGlvbklkR2VuZXJhdG9yJztcclxuaW1wb3J0IHsgRXJyb3JOb3JtYWxpemVyIH0gZnJvbSAnLi9FcnJvcnMvRXJyb3JOb3JtYWxpemVyJztcclxuaW1wb3J0IHsgSW50ZXJjZXB0b3JNYW5hZ2VyIH0gZnJvbSAnLi9JbnRlcmNlcHRvcnMvSW50ZXJjZXB0b3JNYW5hZ2VyJztcclxuaW1wb3J0IHR5cGUge1xyXG4gIExpc3RSZXNwb25zZSxcclxuICBQb3N0TW9kZWwsXHJcbiAgUXVlcnlQYXJhbXMsXHJcbiAgUmVzcG9uc2VEYXRhLFxyXG59IGZyb20gJy4vTW9kZWxzJztcclxuaW1wb3J0IHsgUmVxdWVzdE1hbmFnZXIgfSBmcm9tICcuL1JlcXVlc3RNYW5hZ2VyJztcclxuaW1wb3J0IHsgUmV0cnlIYW5kbGVyIH0gZnJvbSAnLi9SZXRyeS9SZXRyeUhhbmRsZXInO1xyXG5pbXBvcnQgeyBTaWduYWxNYW5hZ2VyIH0gZnJvbSAnLi9TaWduYWxzL1NpZ25hbE1hbmFnZXInO1xyXG5pbXBvcnQgdHlwZSB7IEFwaUVycm9yIH0gZnJvbSAnLi90eXBlcy9BcGlFcnJvcic7XHJcbmltcG9ydCB0eXBlIHsgRXJyb3JJbnRlcmNlcHRvciB9IGZyb20gJy4vdHlwZXMvRXJyb3JJbnRlcmNlcHRvcic7XHJcbmltcG9ydCB0eXBlIHsgRXJyb3JSZXNwb25zZURhdGEgfSBmcm9tICcuL3R5cGVzL0Vycm9yUmVzcG9uc2VEYXRhJztcclxuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0Q29uZmlnIH0gZnJvbSAnLi90eXBlcy9SZXF1ZXN0Q29uZmlnJztcclxuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0SW50ZXJjZXB0b3IgfSBmcm9tICcuL3R5cGVzL1JlcXVlc3RJbnRlcmNlcHRvcic7XHJcbmltcG9ydCB0eXBlIHsgUmVzcG9uc2VJbnRlcmNlcHRvciB9IGZyb20gJy4vdHlwZXMvUmVzcG9uc2VJbnRlcmNlcHRvcic7XHJcbmltcG9ydCB7IFJlc3BvbnNlUGFyc2VyIH0gZnJvbSAnLi9VdGlscy9SZXNwb25zZVBhcnNlcic7XHJcbmltcG9ydCB7IFVybEJ1aWxkZXIgfSBmcm9tICcuL1V0aWxzL1VybEJ1aWxkZXInO1xyXG5cclxuaW1wb3J0IHR5cGUgeyBBcGlSZXNwb25zZSB9IGZyb20gJ0AvdHlwZXMnO1xyXG5cclxuLyoqXHJcbiAqIEVudGVycHJpc2UtZ3JhZGUgQVBJIGNsaWVudCB3aXRoIGFkdmFuY2VkIGZlYXR1cmVzIGZvciBwcm9kdWN0aW9uIGFwcGxpY2F0aW9ucy5cclxuICpcclxuICogVGhpcyBjbGllbnQgcHJvdmlkZXMgYSByb2J1c3QsIHR5cGUtc2FmZSBhYnN0cmFjdGlvbiBvdmVyIHRoZSBGZXRjaCBBUEkgd2l0aDpcclxuICogLSBDb21wcmVoZW5zaXZlIHJlcXVlc3QvcmVzcG9uc2UvZXJyb3IgaW50ZXJjZXB0b3Igc3lzdGVtXHJcbiAqIC0gQXV0b21hdGljIHJldHJ5IGxvZ2ljIHdpdGggZXhwb25lbnRpYWwgYmFja29mZlxyXG4gKiAtIFJlcXVlc3QgY29ycmVsYXRpb24gSUQgdHJhY2tpbmcgZm9yIGRpc3RyaWJ1dGVkIHRyYWNpbmdcclxuICogLSBUb2tlbi1iYXNlZCBhdXRoZW50aWNhdGlvbiB3aXRoIGF1dG9tYXRpYyBoZWFkZXIgaW5qZWN0aW9uXHJcbiAqIC0gUmVxdWVzdCBjYW5jZWxsYXRpb24gYW5kIHRpbWVvdXQgbWFuYWdlbWVudFxyXG4gKiAtIFR5cGUtc2FmZSBlcnJvciBoYW5kbGluZyB3aXRoIHN0cnVjdHVyZWQgZXJyb3IgcmVzcG9uc2VzXHJcbiAqIC0gUmVhY3QgUXVlcnkgaW50ZWdyYXRpb24gc3VwcG9ydFxyXG4gKlxyXG4gKiBBcmNoaXRlY3R1cmUgUHJpbmNpcGxlczpcclxuICogLSAqKlR5cGUgU2FmZXR5Kio6IEZ1bGwgVHlwZVNjcmlwdCBpbmZlcmVuY2Ugd2l0aCBubyBgYW55YCB0eXBlc1xyXG4gKiAtICoqRXh0ZW5zaWJpbGl0eSoqOiBJbnRlcmNlcHRvciBwYXR0ZXJuIGFsbG93cyBmb3IgZmxleGlibGUgbWlkZGxld2FyZVxyXG4gKiAtICoqT2JzZXJ2YWJpbGl0eSoqOiBCdWlsdC1pbiBjb3JyZWxhdGlvbiBJRHMgZm9yIHJlcXVlc3QgdHJhY2luZ1xyXG4gKiAtICoqUmVzaWxpZW5jZSoqOiBBdXRvbWF0aWMgcmV0cmllcywgdGltZW91dHMsIGFuZCBncmFjZWZ1bCBlcnJvciBoYW5kbGluZ1xyXG4gKiAtICoqUGVyZm9ybWFuY2UqKjogUmVxdWVzdCBkZWR1cGxpY2F0aW9uIGFuZCBjYW5jZWxsYXRpb24gc3VwcG9ydFxyXG4gKiAtICoqTW9kdWxhcml0eSoqOiBPcmdhbml6ZWQgaW50byBmb2N1c2VkLCBzaW5nbGUtcmVzcG9uc2liaWxpdHkgbW9kdWxlc1xyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBCYXNpYyB1c2FnZTpcclxuICogYGBgdHlwZXNjcmlwdFxyXG4gKiBjb25zdCBjbGllbnQgPSBuZXcgQXBpQ2xpZW50KCdodHRwczovL2FwaS5leGFtcGxlLmNvbScsIDMwMDAwKTtcclxuICogY2xpZW50LnNldEF1dGhUb2tlbigneW91ci1qd3QtdG9rZW4nKTtcclxuICpcclxuICogLy8gVHlwZS1zYWZlIEdFVCByZXF1ZXN0XHJcbiAqIGNvbnN0IHsgYXBpRGF0YSwgZXJyb3IgfSA9IGF3YWl0IGNsaWVudC5nZXQ8VXNlcj4oJy91c2Vycy8xMjMnKTtcclxuICogaWYgKGVycm9yKSB7XHJcbiAqICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGZldGNoIHVzZXI6JywgZXJyb3IpO1xyXG4gKiB9IGVsc2Uge1xyXG4gKiAgIGNvbnNvbGUubG9nKCdVc2VyIGRhdGE6JywgZGF0YSk7XHJcbiAqIH1cclxuICogYGBgXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIFdpdGggUmVhY3QgUXVlcnk6XHJcbiAqIGBgYHR5cGVzY3JpcHRcclxuICogY29uc3QgcXVlcnlDbGllbnQgPSBuZXcgUXVlcnlDbGllbnQoKTtcclxuICogY29uc3QgYXBpQ2xpZW50ID0gbmV3IEFwaUNsaWVudChwcm9jZXNzLmVudi5BUElfQkFTRV9VUkwpO1xyXG4gKlxyXG4gKiAvLyBBZGQgbG9nZ2luZyBpbnRlcmNlcHRvclxyXG4gKiBhcGlDbGllbnQuYWRkUmVzcG9uc2VJbnRlcmNlcHRvcihhc3luYyAocmVzcG9uc2UpID0+IHtcclxuICogICBjb25zb2xlLmxvZygnUmVzcG9uc2UgcmVjZWl2ZWQ6JywgcmVzcG9uc2UpO1xyXG4gKiAgIHJldHVybiByZXNwb25zZTtcclxuICogfSk7XHJcbiAqXHJcbiAqIC8vIFVzZSBpbiBxdWVyaWVzXHJcbiAqIGNvbnN0IHsgYXBpRGF0YSB9ID0gdXNlUXVlcnkoe1xyXG4gKiAgIHF1ZXJ5S2V5OiBbJ3VzZXJzJywgdXNlcklkXSxcclxuICogICBxdWVyeUZuOiAoKSA9PiBhcGlDbGllbnQuZ2V0PFVzZXI+KGAvdXNlcnMvJHt1c2VySWR9YClcclxuICogfSk7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBBZHZhbmNlZCBlcnJvciBoYW5kbGluZzpcclxuICogYGBgdHlwZXNjcmlwdFxyXG4gKiAvLyBPcHRpb24gMTogRXJyb3JzIHRocm93biAoZGVmYXVsdClcclxuICogdHJ5IHtcclxuICogICBjb25zdCB7IGFwaURhdGEgfSA9IGF3YWl0IGNsaWVudC5nZXQ8VXNlcj4oJy91c2Vycy8xMjMnKTtcclxuICogICBjb25zb2xlLmxvZyhkYXRhKTtcclxuICogfSBjYXRjaCAoZXJyb3IpIHtcclxuICogICBpZiAoZXJyb3Iuc3RhdHVzID09PSA0MDQpIHtcclxuICogICAgIGNvbnNvbGUubG9nKCdVc2VyIG5vdCBmb3VuZCcpO1xyXG4gKiAgIH1cclxuICogfVxyXG4gKlxyXG4gKiAvLyBPcHRpb24gMjogRXJyb3JzIHJldHVybmVkIGluIHJlc3BvbnNlXHJcbiAqIGNvbnN0IHsgYXBpRGF0YSwgZXJyb3IgfSA9IGF3YWl0IGNsaWVudC5nZXQ8VXNlcj4oJy91c2Vycy8xMjMnLCB7XHJcbiAqICAgdGhyb3dFcnJvcnM6IGZhbHNlXHJcbiAqIH0pO1xyXG4gKiBpZiAoZXJyb3IpIHtcclxuICogICBjb25zb2xlLmVycm9yKCdSZXF1ZXN0IGZhaWxlZDonLCBlcnJvcik7XHJcbiAqIH1cclxuICogYGBgXHJcbiAqXHJcbiAqIEBwdWJsaWNcclxuICovXHJcbmV4cG9ydCBjbGFzcyBBcGlDbGllbnQge1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgYmFzZVVSTDogc3RyaW5nO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdFRpbWVvdXQ6IG51bWJlcjtcclxuICBwcml2YXRlIHJlYWRvbmx5IGludGVyY2VwdG9yTWFuYWdlcjogSW50ZXJjZXB0b3JNYW5hZ2VyID1cclxuICAgIG5ldyBJbnRlcmNlcHRvck1hbmFnZXIoKTtcclxuICBwcml2YXRlIHJlYWRvbmx5IHNpZ25hbE1hbmFnZXI6IFNpZ25hbE1hbmFnZXIgPSBuZXcgU2lnbmFsTWFuYWdlcigpO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgZXJyb3JOb3JtYWxpemVyOiBFcnJvck5vcm1hbGl6ZXIgPSBuZXcgRXJyb3JOb3JtYWxpemVyKCk7XHJcbiAgcHJpdmF0ZSByZWFkb25seSByZXNwb25zZVBhcnNlcjogUmVzcG9uc2VQYXJzZXIgPSBuZXcgUmVzcG9uc2VQYXJzZXIoKTtcclxuICBwcml2YXRlIHJlYWRvbmx5IHVybEJ1aWxkZXI6IFVybEJ1aWxkZXIgPSBuZXcgVXJsQnVpbGRlcigpO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgcmV0cnlIYW5kbGVyOiBSZXRyeUhhbmRsZXIgPSBuZXcgUmV0cnlIYW5kbGVyKCk7XHJcbiAgcHJpdmF0ZSByZWFkb25seSByZXF1ZXN0TWFuYWdlcjogUmVxdWVzdE1hbmFnZXIgPSBuZXcgUmVxdWVzdE1hbmFnZXIoKTtcclxuICBwcml2YXRlIGF1dGhUb2tlbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XHJcbiAgcHJpdmF0ZSBjb3JyZWxhdGlvbklkUHJlZml4OiBzdHJpbmcgPSAnYXBpJztcclxuICBwcml2YXRlIGluY2x1ZGVDb3JyZWxhdGlvbklkOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhIG5ldyBBUEkgY2xpZW50IGluc3RhbmNlXHJcbiAgICogQHBhcmFtIGJhc2VVUkwgLSBCYXNlIFVSTCBmb3IgYWxsIEFQSSByZXF1ZXN0cyAoZGVmYXVsdDogZW1wdHkgc3RyaW5nIGZvciByZWxhdGl2ZSBVUkxzKVxyXG4gICAqIEBwYXJhbSBkZWZhdWx0VGltZW91dCAtIERlZmF1bHQgcmVxdWVzdCB0aW1lb3V0IGluIG1pbGxpc2Vjb25kcyAoZGVmYXVsdDogMzAwMDApXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IoYmFzZVVSTDogc3RyaW5nID0gJycsIGRlZmF1bHRUaW1lb3V0OiBudW1iZXIgPSAzMDAwMCkge1xyXG4gICAgdGhpcy5iYXNlVVJMID0gYmFzZVVSTDtcclxuICAgIHRoaXMuZGVmYXVsdFRpbWVvdXQgPSBkZWZhdWx0VGltZW91dDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldHMgdGhlIHByZWZpeCBmb3IgYXV0by1nZW5lcmF0ZWQgY29ycmVsYXRpb24gSURzXHJcbiAgICogQHBhcmFtIHByZWZpeCAtIFRoZSBwcmVmaXggdG8gdXNlIGZvciBjb3JyZWxhdGlvbiBJRHMgKGUuZy4sICdhcGknLCAnd2ViJywgJ21vYmlsZScpXHJcbiAgICovXHJcbiAgc2V0Q29ycmVsYXRpb25JZFByZWZpeChwcmVmaXg6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5jb3JyZWxhdGlvbklkUHJlZml4ID0gcHJlZml4O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRW5hYmxlcyBvciBkaXNhYmxlcyBhdXRvbWF0aWMgY29ycmVsYXRpb24gSUQgZ2VuZXJhdGlvblxyXG4gICAqIEBwYXJhbSBpbmNsdWRlIC0gV2hldGhlciB0byBpbmNsdWRlIGNvcnJlbGF0aW9uIElEcyBpbiByZXF1ZXN0c1xyXG4gICAqL1xyXG4gIHNldEluY2x1ZGVDb3JyZWxhdGlvbklkKGluY2x1ZGU6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIHRoaXMuaW5jbHVkZUNvcnJlbGF0aW9uSWQgPSBpbmNsdWRlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVnaXN0ZXJzIGEgcmVxdWVzdCBpbnRlcmNlcHRvciB0byBtb2RpZnkgcmVxdWVzdHMgYmVmb3JlIHRoZXkncmUgc2VudFxyXG4gICAqIEBwYXJhbSBpbnRlcmNlcHRvciAtIEZ1bmN0aW9uIHRvIGludGVyY2VwdCBhbmQgcG90ZW50aWFsbHkgbW9kaWZ5IHJlcXVlc3QgY29uZmlnXHJcbiAgICogQHJldHVybnMgRnVuY3Rpb24gdG8gdW5yZWdpc3RlciB0aGlzIGludGVyY2VwdG9yXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCB1bnJlZ2lzdGVyID0gY2xpZW50LmFkZFJlcXVlc3RJbnRlcmNlcHRvcihhc3luYyAoY29uZmlnKSA9PiB7XHJcbiAgICogICBjb25maWcuaGVhZGVycyA9IGNvbmZpZy5oZWFkZXJzIHx8IG5ldyBIZWFkZXJzKCk7XHJcbiAgICogICBjb25maWcuaGVhZGVycy5zZXQoJ1gtQ2xpZW50LVZlcnNpb24nLCAnMS4wLjAnKTtcclxuICAgKiAgIHJldHVybiBjb25maWc7XHJcbiAgICogfSk7XHJcbiAgICpcclxuICAgKiAvLyBMYXRlciwgdG8gcmVtb3ZlIHRoZSBpbnRlcmNlcHRvcjpcclxuICAgKiB1bnJlZ2lzdGVyKCk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgYWRkUmVxdWVzdEludGVyY2VwdG9yKGludGVyY2VwdG9yOiBSZXF1ZXN0SW50ZXJjZXB0b3IpOiAoKSA9PiB2b2lkIHtcclxuICAgIHJldHVybiB0aGlzLmludGVyY2VwdG9yTWFuYWdlci5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoaW50ZXJjZXB0b3IpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVnaXN0ZXJzIGEgcmVzcG9uc2UgaW50ZXJjZXB0b3IgdG8gbW9kaWZ5IHJlc3BvbnNlcyBiZWZvcmUgdGhleSdyZSByZXR1cm5lZFxyXG4gICAqIEBwYXJhbSBpbnRlcmNlcHRvciAtIEZ1bmN0aW9uIHRvIGludGVyY2VwdCBhbmQgcG90ZW50aWFsbHkgbW9kaWZ5IHJlc3BvbnNlc1xyXG4gICAqIEByZXR1cm5zIEZ1bmN0aW9uIHRvIHVucmVnaXN0ZXIgdGhpcyBpbnRlcmNlcHRvclxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogY2xpZW50LmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoYXN5bmMgKHJlc3BvbnNlKSA9PiB7XHJcbiAgICogICAvLyBUcmFuc2Zvcm0gZGF0YSBmb3JtYXRcclxuICAgKiAgIGlmIChyZXNwb25zZS5hcGlEYXRhKSB7XHJcbiAgICogICAgIHJlc3BvbnNlLmFwaURhdGEgPSBjYW1lbENhc2VLZXlzKHJlc3BvbnNlLmFwaURhdGEpO1xyXG4gICAqICAgfVxyXG4gICAqICAgcmV0dXJuIHJlc3BvbnNlO1xyXG4gICAqIH0pO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIGFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoaW50ZXJjZXB0b3I6IFJlc3BvbnNlSW50ZXJjZXB0b3IpOiAoKSA9PiB2b2lkIHtcclxuICAgIHJldHVybiB0aGlzLmludGVyY2VwdG9yTWFuYWdlci5hZGRSZXNwb25zZUludGVyY2VwdG9yKGludGVyY2VwdG9yKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlZ2lzdGVycyBhbiBlcnJvciBpbnRlcmNlcHRvciB0byBoYW5kbGUgb3IgdHJhbnNmb3JtIGVycm9yc1xyXG4gICAqIEBwYXJhbSBpbnRlcmNlcHRvciAtIEZ1bmN0aW9uIHRvIGludGVyY2VwdCBhbmQgcG90ZW50aWFsbHkgbW9kaWZ5IGVycm9yc1xyXG4gICAqIEByZXR1cm5zIEZ1bmN0aW9uIHRvIHVucmVnaXN0ZXIgdGhpcyBpbnRlcmNlcHRvclxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogY2xpZW50LmFkZEVycm9ySW50ZXJjZXB0b3IoYXN5bmMgKGVycm9yKSA9PiB7XHJcbiAgICogICAvLyBMb2cgZXJyb3JzIHRvIG1vbml0b3Jpbmcgc2VydmljZVxyXG4gICAqICAgaWYgKGVycm9yLnN0YXR1cyA+PSA1MDApIHtcclxuICAgKiAgICAgYXdhaXQgbW9uaXRvcmluZ1NlcnZpY2UubG9nRXJyb3IoZXJyb3IpO1xyXG4gICAqICAgfVxyXG4gICAqICAgcmV0dXJuIGVycm9yOyAvLyBSZS10aHJvdyB0aGUgZXJyb3JcclxuICAgKiB9KTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBhZGRFcnJvckludGVyY2VwdG9yKGludGVyY2VwdG9yOiBFcnJvckludGVyY2VwdG9yKTogKCkgPT4gdm9pZCB7XHJcbiAgICByZXR1cm4gdGhpcy5pbnRlcmNlcHRvck1hbmFnZXIuYWRkRXJyb3JJbnRlcmNlcHRvcihpbnRlcmNlcHRvcik7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZXRzIHRoZSBhdXRoZW50aWNhdGlvbiB0b2tlbiBmb3Igc3Vic2VxdWVudCByZXF1ZXN0c1xyXG4gICAqIEBwYXJhbSB0b2tlbiAtIEpXVCB0b2tlbiBvciBudWxsIHRvIGNsZWFyIGF1dGhlbnRpY2F0aW9uXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiAvLyBTZXQgdG9rZW4gYWZ0ZXIgbG9naW5cclxuICAgKiBjbGllbnQuc2V0QXV0aFRva2VuKGxvZ2luUmVzcG9uc2UuYWNjZXNzVG9rZW4pO1xyXG4gICAqXHJcbiAgICogLy8gQ2xlYXIgdG9rZW4gb24gbG9nb3V0XHJcbiAgICogY2xpZW50LnNldEF1dGhUb2tlbihudWxsKTtcclxuICAgKiBgYGBcclxuICAgKi9cclxuICBzZXRBdXRoVG9rZW4odG9rZW46IHN0cmluZyB8IG51bGwpOiB2b2lkIHtcclxuICAgIHRoaXMuYXV0aFRva2VuID0gdG9rZW47XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXRyaWV2ZXMgdGhlIGN1cnJlbnQgYXV0aGVudGljYXRpb24gdG9rZW5cclxuICAgKiBAcmV0dXJucyBUaGUgY3VycmVudCBhdXRoIHRva2VuIG9yIG51bGwgaWYgbm90IHNldFxyXG4gICAqL1xyXG4gIGdldEF1dGhUb2tlbigpOiBzdHJpbmcgfCBudWxsIHtcclxuICAgIHJldHVybiB0aGlzLmF1dGhUb2tlbjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENhbmNlbHMgYSBzcGVjaWZpYyByZXF1ZXN0IGJ5IGl0cyBrZXlcclxuICAgKiBAcGFyYW0ga2V5IC0gVGhlIHVuaXF1ZSBrZXkgaWRlbnRpZnlpbmcgdGhlIHJlcXVlc3QgdG8gY2FuY2VsXHJcbiAgICovXHJcbiAgY2FuY2VsUmVxdWVzdChrZXk6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5yZXF1ZXN0TWFuYWdlci5jYW5jZWwoa2V5KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENhbmNlbHMgYWxsIHBlbmRpbmcgcmVxdWVzdHNcclxuICAgKiBVc2VmdWwgZm9yIGNsZWFudXAgb24gbmF2aWdhdGlvbiBvciBjb21wb25lbnQgdW5tb3VudFxyXG4gICAqL1xyXG4gIGNhbmNlbEFsbFJlcXVlc3RzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5yZXF1ZXN0TWFuYWdlci5jYW5jZWxBbGwoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENvcmUgcmVxdWVzdCBtZXRob2QgdGhhdCBoYW5kbGVzIGFsbCBIVFRQIG9wZXJhdGlvbnNcclxuICAgKiBAdGVtcGxhdGUgVCAtIFRoZSBleHBlY3RlZCByZXNwb25zZSBkYXRhIHR5cGVcclxuICAgKiBAcGFyYW0gZW5kcG9pbnQgLSBBUEkgZW5kcG9pbnQgcmVsYXRpdmUgdG8gYmFzZVVSTFxyXG4gICAqIEBwYXJhbSBjb25maWcgLSBSZXF1ZXN0IGNvbmZpZ3VyYXRpb24gb3B0aW9uc1xyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIEFwaVJlc3BvbnNlIHdpdGggZGF0YSBvciBlcnJvclxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQucmVxdWVzdDxVc2VyPignL3VzZXJzLzEyMycsIHtcclxuICAgKiAgIG1ldGhvZDogJ0dFVCcsXHJcbiAgICogICB0aW1lb3V0OiA1MDAwLFxyXG4gICAqICAgdGhyb3dFcnJvcnM6IGZhbHNlXHJcbiAgICogfSk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgYXN5bmMgcmVxdWVzdDxUID0gUmVzcG9uc2VEYXRhPihcclxuICAgIGVuZHBvaW50OiBzdHJpbmcsXHJcbiAgICBjb25maWc6IFJlcXVlc3RDb25maWcgPSB7fVxyXG4gICk6IFByb21pc2U8QXBpUmVzcG9uc2U8VCwgQXBpRXJyb3I+PiB7XHJcbiAgICAvLyBHZW5lcmF0ZSBjb3JyZWxhdGlvbiBJRFxyXG4gICAgY29uc3QgY29ycmVsYXRpb25JZCA9XHJcbiAgICAgIGNvbmZpZy5jb3JyZWxhdGlvbklkIHx8XHJcbiAgICAgICghY29uZmlnLnNraXBDb3JyZWxhdGlvbklkICYmIHRoaXMuaW5jbHVkZUNvcnJlbGF0aW9uSWRcclxuICAgICAgICA/IGdlbmVyYXRlQ29ycmVsYXRpb25JZCh0aGlzLmNvcnJlbGF0aW9uSWRQcmVmaXgpXHJcbiAgICAgICAgOiB1bmRlZmluZWQpO1xyXG4gICAgLy8gR2VuZXJhdGUgcmVxdWVzdCBrZXkgZm9yIHRyYWNraW5nXHJcbiAgICBjb25zdCByZXF1ZXN0S2V5ID0gYCR7Y29uZmlnLm1ldGhvZCB8fCAnR0VUJ31fJHtlbmRwb2ludH1fJHtEYXRlLm5vdygpfWA7XHJcblxyXG4gICAgLy8gQ3JlYXRlIG1hc3RlciBjb250cm9sbGVyIGZvciB0aGlzIHJlcXVlc3RcclxuICAgIGNvbnN0IG1hc3RlckNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XHJcblxyXG4gICAgdHJ5IHtcclxuICAgICAgLy8gQ29tYmluZSBhbGwgYWJvcnQgc2lnbmFsc1xyXG4gICAgICBjb25zdCBzaWduYWxzOiBBcnJheTxBYm9ydFNpZ25hbCB8IHVuZGVmaW5lZD4gPSBbXHJcbiAgICAgICAgY29uZmlnLnNpZ25hbCxcclxuICAgICAgICBjb25maWcuY2FuY2VsVG9rZW4/LnNpZ25hbCxcclxuICAgICAgICBtYXN0ZXJDb250cm9sbGVyLnNpZ25hbCxcclxuICAgICAgXTtcclxuXHJcbiAgICAgIC8vIEFkZCB0aW1lb3V0IHNpZ25hbCBpZiBjb25maWd1cmVkXHJcbiAgICAgIGNvbnN0IHRpbWVvdXQgPSBjb25maWcudGltZW91dCB8fCB0aGlzLmRlZmF1bHRUaW1lb3V0O1xyXG4gICAgICBjb25zdCB0aW1lb3V0Q29udHJvbGxlciA9IHRoaXMuc2lnbmFsTWFuYWdlci5jcmVhdGVUaW1lb3V0U2lnbmFsKHRpbWVvdXQpO1xyXG5cclxuICAgICAgc2lnbmFscy5wdXNoKHRpbWVvdXRDb250cm9sbGVyLnNpZ25hbCk7XHJcblxyXG4gICAgICAvLyBDcmVhdGUgY29tYmluZWQgc2lnbmFsXHJcbiAgICAgIGNvbnN0IGNvbWJpbmVkQ29udHJvbGxlciA9XHJcbiAgICAgICAgdGhpcy5zaWduYWxNYW5hZ2VyLmNyZWF0ZUNvbWJpbmVkU2lnbmFsKHNpZ25hbHMpO1xyXG5cclxuICAgICAgLy8gVHJhY2sgdGhpcyByZXF1ZXN0XHJcbiAgICAgIGlmIChjb3JyZWxhdGlvbklkKSB7XHJcbiAgICAgICAgdGhpcy5yZXF1ZXN0TWFuYWdlci5hZGQocmVxdWVzdEtleSwgbWFzdGVyQ29udHJvbGxlciwgY29ycmVsYXRpb25JZCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIEFwcGx5IHJlcXVlc3QgaW50ZXJjZXB0b3JzXHJcbiAgICAgIGNvbnN0IGZpbmFsQ29uZmlnID1cclxuICAgICAgICBhd2FpdCB0aGlzLmludGVyY2VwdG9yTWFuYWdlci5hcHBseVJlcXVlc3RJbnRlcmNlcHRvcnMoe1xyXG4gICAgICAgICAgLi4uY29uZmlnLFxyXG4gICAgICAgICAgc2lnbmFsOiBjb21iaW5lZENvbnRyb2xsZXIuc2lnbmFsLFxyXG4gICAgICAgICAgY29ycmVsYXRpb25JZCxcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgIC8vIEJ1aWxkIGZ1bGwgVVJMXHJcbiAgICAgIGNvbnN0IHVybCA9IHRoaXMudXJsQnVpbGRlci5idWlsZFVSTChcclxuICAgICAgICB0aGlzLmJhc2VVUkwsXHJcbiAgICAgICAgZW5kcG9pbnQsXHJcbiAgICAgICAgZmluYWxDb25maWcucGFyYW1zIGFzIFF1ZXJ5UGFyYW1zXHJcbiAgICAgICk7XHJcblxyXG4gICAgICAvLyBBZGQgZGVmYXVsdCBoZWFkZXJzXHJcbiAgICAgIGNvbnN0IGhlYWRlcnMgPSBuZXcgSGVhZGVycyhmaW5hbENvbmZpZy5oZWFkZXJzKTtcclxuXHJcbiAgICAgIC8vIEFkZCBjb3JyZWxhdGlvbiBJRCBoZWFkZXJcclxuICAgICAgaWYgKGNvcnJlbGF0aW9uSWQpIHtcclxuICAgICAgICBoZWFkZXJzLnNldCgnWC1Db3JyZWxhdGlvbi1JZCcsIGNvcnJlbGF0aW9uSWQpO1xyXG4gICAgICAgIGhlYWRlcnMuc2V0KCdYLVJlcXVlc3QtSWQnLCBjb3JyZWxhdGlvbklkKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gQWRkIGF1dGggaGVhZGVyIGlmIHRva2VuIGV4aXN0c1xyXG4gICAgICBpZiAodGhpcy5hdXRoVG9rZW4gJiYgIWZpbmFsQ29uZmlnLnNraXBBdXRoUmVmcmVzaCkge1xyXG4gICAgICAgIGhlYWRlcnMuc2V0KCdBdXRob3JpemF0aW9uJywgYEJlYXJlciAke3RoaXMuYXV0aFRva2VufWApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBTZXQgY29udGVudC10eXBlIGZvciBKU09OIHBheWxvYWRzXHJcblxyXG4gICAgICBsZXQgZmV0Y2hCb2R5OiBCb2R5SW5pdCB8IG51bGwgfCB1bmRlZmluZWQgPSBmaW5hbENvbmZpZy5ib2R5IGFzXHJcbiAgICAgICAgfCBCb2R5SW5pdFxyXG4gICAgICAgIHwgbnVsbFxyXG4gICAgICAgIHwgdW5kZWZpbmVkO1xyXG5cclxuICAgICAgaWYgKFxyXG4gICAgICAgIGZpbmFsQ29uZmlnLmJvZHkgJiZcclxuICAgICAgICB0eXBlb2YgZmluYWxDb25maWcuYm9keSA9PT0gJ29iamVjdCcgJiZcclxuICAgICAgICAhKGZpbmFsQ29uZmlnLmJvZHkgaW5zdGFuY2VvZiBGb3JtRGF0YSkgJiZcclxuICAgICAgICAhKGZpbmFsQ29uZmlnLmJvZHkgaW5zdGFuY2VvZiBCbG9iKSAmJlxyXG4gICAgICAgICEoZmluYWxDb25maWcuYm9keSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSAmJlxyXG4gICAgICAgICEoZmluYWxDb25maWcuYm9keSBpbnN0YW5jZW9mIFVSTFNlYXJjaFBhcmFtcykgJiZcclxuICAgICAgICAhKGZpbmFsQ29uZmlnLmJvZHkgaW5zdGFuY2VvZiBSZWFkYWJsZVN0cmVhbSlcclxuICAgICAgKSB7XHJcbiAgICAgICAgaGVhZGVycy5zZXQoJ0NvbnRlbnQtVHlwZScsICdhcHBsaWNhdGlvbi9qc29uJyk7XHJcbiAgICAgICAgZmV0Y2hCb2R5ID0gSlNPTi5zdHJpbmdpZnkoZmluYWxDb25maWcuYm9keSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGZpbmFsQ29uZmlnLmhlYWRlcnMgPSBoZWFkZXJzO1xyXG5cclxuICAgICAgLy8gQ3JlYXRlIGZldGNoIHByb21pc2VcclxuICAgICAgY29uc3QgZmV0Y2hQcm9taXNlID0gYXN5bmMgKCk6IFByb21pc2U8QXBpUmVzcG9uc2U8VCwgQXBpRXJyb3I+PiA9PiB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsLCB7XHJcbiAgICAgICAgICAgIC4uLmZpbmFsQ29uZmlnLFxyXG4gICAgICAgICAgICBib2R5OiBmZXRjaEJvZHksXHJcbiAgICAgICAgICAgIHNpZ25hbDogY29tYmluZWRDb250cm9sbGVyLnNpZ25hbCxcclxuICAgICAgICAgIH0gYXMgUmVxdWVzdEluaXQpO1xyXG5cclxuICAgICAgICAgIC8vIFBhcnNlIHJlc3BvbnNlIGRhdGFcclxuICAgICAgICAgIGNvbnN0IHJlc3BvbnNlRGF0YSA9XHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucmVzcG9uc2VQYXJzZXIucGFyc2VSZXNwb25zZShyZXNwb25zZSk7XHJcblxyXG4gICAgICAgICAgLy8gSGFuZGxlIGVycm9yIHJlc3BvbnNlc1xyXG4gICAgICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xyXG4gICAgICAgICAgICAvLyBDYXN0IHRvIEVycm9yUmVzcG9uc2VEYXRhIGZvciBzdHJ1Y3R1cmVkIGVycm9yIHJlc3BvbnNlcyBmcm9tIGJhY2tlbmRcclxuICAgICAgICAgICAgY29uc3QgZXJyb3JEYXRhID0gcmVzcG9uc2VEYXRhIGFzIEVycm9yUmVzcG9uc2VEYXRhO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgZXJyb3I6IEFwaUVycm9yID0gT2JqZWN0LmFzc2lnbihcclxuICAgICAgICAgICAgICBuZXcgRXJyb3IoXHJcbiAgICAgICAgICAgICAgICBlcnJvckRhdGEudGl0bGUgfHxcclxuICAgICAgICAgICAgICAgICAgYEhUVFAgJHtyZXNwb25zZS5zdGF0dXN9OiAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YFxyXG4gICAgICAgICAgICAgICksXHJcbiAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgdHlwZTpcclxuICAgICAgICAgICAgICAgICAgZXJyb3JEYXRhLnR5cGUgfHxcclxuICAgICAgICAgICAgICAgICAgdGhpcy5lcnJvck5vcm1hbGl6ZXIuZ2V0RXJyb3JUeXBlKHJlc3BvbnNlLnN0YXR1cyksXHJcbiAgICAgICAgICAgICAgICB0aXRsZTpcclxuICAgICAgICAgICAgICAgICAgZXJyb3JEYXRhLnRpdGxlIHx8XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JOb3JtYWxpemVyLmdldEVycm9yVGl0bGUocmVzcG9uc2Uuc3RhdHVzKSxcclxuICAgICAgICAgICAgICAgIHN0YXR1czogcmVzcG9uc2Uuc3RhdHVzLFxyXG4gICAgICAgICAgICAgICAgdHJhY2VJZDogZXJyb3JEYXRhLnRyYWNlSWQgfHwgY29ycmVsYXRpb25JZCxcclxuICAgICAgICAgICAgICAgIGVycm9yczogZXJyb3JEYXRhLmVycm9ycyxcclxuICAgICAgICAgICAgICAgIGlzQWJvcnRlZDogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICBjb25maWc6IGZpbmFsQ29uZmlnLFxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHdlIHNob3VsZCB0aHJvdyBvciByZXR1cm4gZXJyb3IgaW4gcmVzcG9uc2VcclxuICAgICAgICAgICAgaWYgKGZpbmFsQ29uZmlnLnRocm93RXJyb3JzICE9PSBmYWxzZSkge1xyXG4gICAgICAgICAgICAgIHRocm93IGVycm9yO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIC8vIFJldHVybiBlcnJvciBpbiBBcGlSZXNwb25zZS5lcnJvciBmaWVsZFxyXG4gICAgICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmludGVyY2VwdG9yTWFuYWdlci5hcHBseVJlc3BvbnNlSW50ZXJjZXB0b3JzKHtcclxuICAgICAgICAgICAgICAgIGVycm9yLFxyXG4gICAgICAgICAgICAgIH0gYXMgQXBpUmVzcG9uc2U8VCwgQXBpRXJyb3I+KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC8vIEZvcm1hdCBzdWNjZXNzZnVsIHJlc3BvbnNlXHJcbiAgICAgICAgICBjb25zdCBhcGlSZXNwb25zZTogQXBpUmVzcG9uc2U8VD4gPSB7XHJcbiAgICAgICAgICAgIGRhdGE6IHJlc3BvbnNlRGF0YSBhcyBULFxyXG4gICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAvLyBBcHBseSByZXNwb25zZSBpbnRlcmNlcHRvcnNcclxuICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmludGVyY2VwdG9yTWFuYWdlci5hcHBseVJlc3BvbnNlSW50ZXJjZXB0b3JzKFxyXG4gICAgICAgICAgICBhcGlSZXNwb25zZVxyXG4gICAgICAgICAgKTtcclxuICAgICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xyXG4gICAgICAgICAgLy8gSGFuZGxlIGFib3J0IGVycm9yc1xyXG4gICAgICAgICAgaWYgKChlcnJvciBhcyBFcnJvcikubmFtZSA9PT0gJ0Fib3J0RXJyb3InKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGFib3J0RXJyb3IgPSBPYmplY3QuYXNzaWduKFxyXG4gICAgICAgICAgICAgIG5ldyBFcnJvcigoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2UgfHwgJ1JlcXVlc3QgYWJvcnRlZCcpLFxyXG4gICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHR5cGU6ICdyZXF1ZXN0X2NhbmNlbGxlZCcsXHJcbiAgICAgICAgICAgICAgICB0aXRsZTogJ1JlcXVlc3Qgd2FzIGNhbmNlbGxlZCcsXHJcbiAgICAgICAgICAgICAgICBzdGF0dXM6IDAsXHJcbiAgICAgICAgICAgICAgICB0cmFjZUlkOiBjb3JyZWxhdGlvbklkLFxyXG4gICAgICAgICAgICAgICAgaXNBYm9ydGVkOiB0cnVlLFxyXG4gICAgICAgICAgICAgICAgY29uZmlnOiBmaW5hbENvbmZpZyxcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB3ZSBzaG91bGQgdGhyb3cgb3IgcmV0dXJuIGVycm9yIGluIHJlc3BvbnNlXHJcbiAgICAgICAgICAgIGlmIChmaW5hbENvbmZpZy50aHJvd0Vycm9ycyAhPT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICB0aHJvdyBhYm9ydEVycm9yO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIC8vIFJldHVybiBlcnJvciBpbiBBcGlSZXNwb25zZS5lcnJvciBmaWVsZFxyXG4gICAgICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmludGVyY2VwdG9yTWFuYWdlci5hcHBseVJlc3BvbnNlSW50ZXJjZXB0b3JzKHtcclxuICAgICAgICAgICAgICAgIGVycm9yOiBhYm9ydEVycm9yLFxyXG4gICAgICAgICAgICAgIH0gYXMgQXBpUmVzcG9uc2U8VCwgQXBpRXJyb3I+KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIHRocm93IGVycm9yO1xyXG4gICAgICAgIH1cclxuICAgICAgfTtcclxuXHJcbiAgICAgIC8vIEhhbmRsZSByZXRyaWVzIGlmIGNvbmZpZ3VyZWRcclxuICAgICAgaWYgKGZpbmFsQ29uZmlnLnJldHJpZXMgJiYgZmluYWxDb25maWcucmV0cmllcyA+IDApIHtcclxuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5yZXRyeUhhbmRsZXIucmV0cnlSZXF1ZXN0KFxyXG4gICAgICAgICAgZmV0Y2hQcm9taXNlLFxyXG4gICAgICAgICAgZmluYWxDb25maWcucmV0cmllcyxcclxuICAgICAgICAgIGZpbmFsQ29uZmlnLnJldHJ5RGVsYXkgfHwgMTAwMCxcclxuICAgICAgICAgIGNvbWJpbmVkQ29udHJvbGxlci5zaWduYWxcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICByZXR1cm4gYXdhaXQgZmV0Y2hQcm9taXNlKCk7XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAvLyBIYW5kbGUgZXJyb3JzXHJcbiAgICAgIGNvbnN0IGFwaUVycm9yOiBBcGlFcnJvciA9IHRoaXMuZXJyb3JOb3JtYWxpemVyLm5vcm1hbGl6ZUVycm9yKFxyXG4gICAgICAgIGVycm9yLFxyXG4gICAgICAgIGNvbmZpZyxcclxuICAgICAgICBjb3JyZWxhdGlvbklkXHJcbiAgICAgICk7XHJcblxyXG4gICAgICAvLyBDaGVjayBpZiB3ZSBzaG91bGQgdGhyb3cgb3IgcmV0dXJuIGVycm9yIGluIHJlc3BvbnNlXHJcbiAgICAgIGlmIChjb25maWcudGhyb3dFcnJvcnMgIT09IGZhbHNlKSB7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5pbnRlcmNlcHRvck1hbmFnZXIuYXBwbHlFcnJvckludGVyY2VwdG9ycyhhcGlFcnJvcik7XHJcbiAgICAgICAgLy8gVGhpcyBsaW5lIHdpbGwgbmV2ZXIgYmUgcmVhY2hlZCBhcyBhcHBseUVycm9ySW50ZXJjZXB0b3JzIGFsd2F5cyB0aHJvd3MsXHJcbiAgICAgICAgLy8gYnV0IFR5cGVTY3JpcHQgcmVxdWlyZXMgYSByZXR1cm4gc3RhdGVtZW50XHJcbiAgICAgICAgdGhyb3cgYXBpRXJyb3I7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gUmV0dXJuIGVycm9yIGluIEFwaVJlc3BvbnNlLmVycm9yIGZpZWxkXHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgIGVycm9yOiBhcGlFcnJvcixcclxuICAgICAgICB9IGFzIEFwaVJlc3BvbnNlPFQsIEFwaUVycm9yPjtcclxuICAgICAgfVxyXG4gICAgfSBmaW5hbGx5IHtcclxuICAgICAgLy8gQ2xlYW4gdXAgcmVxdWVzdCB0cmFja2luZ1xyXG4gICAgICB0aGlzLnJlcXVlc3RNYW5hZ2VyLnJlbW92ZShyZXF1ZXN0S2V5KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcmZvcm1zIGEgR0VUIHJlcXVlc3RcclxuICAgKiBAdGVtcGxhdGUgVCAtIFRoZSBleHBlY3RlZCByZXNwb25zZSBkYXRhIHR5cGVcclxuICAgKiBAcGFyYW0gZW5kcG9pbnQgLSBBUEkgZW5kcG9pbnRcclxuICAgKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgcmVxdWVzdCBjb25maWd1cmF0aW9uXHJcbiAgICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gQXBpUmVzcG9uc2VcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IHsgYXBpRGF0YSwgZXJyb3IgfSA9IGF3YWl0IGNsaWVudC5nZXQ8VXNlcltdPignL3VzZXJzJywge1xyXG4gICAqICAgcGFyYW1zOiB7IGFjdGl2ZTogdHJ1ZSB9LFxyXG4gICAqICAgdGltZW91dDogNTAwMFxyXG4gICAqIH0pO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIGdldDxUID0gUmVzcG9uc2VEYXRhPihcclxuICAgIGVuZHBvaW50OiBzdHJpbmcsXHJcbiAgICBjb25maWc/OiBSZXF1ZXN0Q29uZmlnXHJcbiAgKTogUHJvbWlzZTxBcGlSZXNwb25zZTxULCBBcGlFcnJvcj4+IHtcclxuICAgIHJldHVybiB0aGlzLnJlcXVlc3Q8VD4oZW5kcG9pbnQsIHsgLi4uY29uZmlnLCBtZXRob2Q6ICdHRVQnIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGVyZm9ybXMgYSBQT1NUIHJlcXVlc3RcclxuICAgKiBAdGVtcGxhdGUgVCAtIFRoZSBleHBlY3RlZCByZXNwb25zZSBkYXRhIHR5cGVcclxuICAgKiBAdGVtcGxhdGUgVERhdGEgLSBUaGUgcmVxdWVzdCBib2R5IGRhdGEgdHlwZVxyXG4gICAqIEBwYXJhbSBlbmRwb2ludCAtIEFQSSBlbmRwb2ludFxyXG4gICAqIEBwYXJhbSBkYXRhIC0gUmVxdWVzdCBib2R5IGRhdGFcclxuICAgKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgcmVxdWVzdCBjb25maWd1cmF0aW9uXHJcbiAgICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gQXBpUmVzcG9uc2VcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IHsgYXBpRGF0YSwgZXJyb3IgfSA9IGF3YWl0IGNsaWVudC5wb3N0PFVzZXIsIENyZWF0ZVVzZXJEdG8+KCcvdXNlcnMnLCB7XHJcbiAgICogICBuYW1lOiAnSm9obiBEb2UnLFxyXG4gICAqICAgZW1haWw6ICdqb2huQGV4YW1wbGUuY29tJ1xyXG4gICAqIH0pO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHBvc3Q8XHJcbiAgICBUID0gUmVzcG9uc2VEYXRhLFxyXG4gICAgVERhdGEgZXh0ZW5kcyBCb2R5SW5pdCB8IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgbnVsbCA9IFJlY29yZDxcclxuICAgICAgc3RyaW5nLFxyXG4gICAgICB1bmtub3duXHJcbiAgICA+LFxyXG4gID4oXHJcbiAgICBlbmRwb2ludDogc3RyaW5nLFxyXG4gICAgZGF0YT86IFREYXRhLFxyXG4gICAgY29uZmlnPzogUmVxdWVzdENvbmZpZ1xyXG4gICk6IFByb21pc2U8QXBpUmVzcG9uc2U8VCwgQXBpRXJyb3I+PiB7XHJcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0PFQ+KGVuZHBvaW50LCB7IC4uLmNvbmZpZywgbWV0aG9kOiAnUE9TVCcsIGJvZHk6IGRhdGEgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQZXJmb3JtcyBhIFBVVCByZXF1ZXN0XHJcbiAgICogQHRlbXBsYXRlIFQgLSBUaGUgZXhwZWN0ZWQgcmVzcG9uc2UgZGF0YSB0eXBlXHJcbiAgICogQHRlbXBsYXRlIFREYXRhIC0gVGhlIHJlcXVlc3QgYm9keSBkYXRhIHR5cGVcclxuICAgKiBAcGFyYW0gZW5kcG9pbnQgLSBBUEkgZW5kcG9pbnRcclxuICAgKiBAcGFyYW0gZGF0YSAtIFJlcXVlc3QgYm9keSBkYXRhXHJcbiAgICogQHBhcmFtIGNvbmZpZyAtIE9wdGlvbmFsIHJlcXVlc3QgY29uZmlndXJhdGlvblxyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIEFwaVJlc3BvbnNlXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCB7IGFwaURhdGEsIGVycm9yIH0gPSBhd2FpdCBjbGllbnQucHV0PFVzZXIsIFVwZGF0ZVVzZXJEdG8+KFxyXG4gICAqICAgJy91c2Vycy8xMjMnLFxyXG4gICAqICAgeyBuYW1lOiAnSmFuZSBEb2UnIH1cclxuICAgKiApO1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIHB1dDxcclxuICAgIFQgPSBSZXNwb25zZURhdGEsXHJcbiAgICBURGF0YSBleHRlbmRzIEJvZHlJbml0IHwgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCBudWxsID0gUmVjb3JkPFxyXG4gICAgICBzdHJpbmcsXHJcbiAgICAgIHVua25vd25cclxuICAgID4sXHJcbiAgPihcclxuICAgIGVuZHBvaW50OiBzdHJpbmcsXHJcbiAgICBkYXRhPzogVERhdGEsXHJcbiAgICBjb25maWc/OiBSZXF1ZXN0Q29uZmlnXHJcbiAgKTogUHJvbWlzZTxBcGlSZXNwb25zZTxULCBBcGlFcnJvcj4+IHtcclxuICAgIHJldHVybiB0aGlzLnJlcXVlc3Q8VD4oZW5kcG9pbnQsIHsgLi4uY29uZmlnLCBtZXRob2Q6ICdQVVQnLCBib2R5OiBkYXRhIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGVyZm9ybXMgYSBQQVRDSCByZXF1ZXN0XHJcbiAgICogQHRlbXBsYXRlIFQgLSBUaGUgZXhwZWN0ZWQgcmVzcG9uc2UgZGF0YSB0eXBlXHJcbiAgICogQHRlbXBsYXRlIFREYXRhIC0gVGhlIHJlcXVlc3QgYm9keSBkYXRhIHR5cGVcclxuICAgKiBAcGFyYW0gZW5kcG9pbnQgLSBBUEkgZW5kcG9pbnRcclxuICAgKiBAcGFyYW0gZGF0YSAtIFJlcXVlc3QgYm9keSBkYXRhXHJcbiAgICogQHBhcmFtIGNvbmZpZyAtIE9wdGlvbmFsIHJlcXVlc3QgY29uZmlndXJhdGlvblxyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIEFwaVJlc3BvbnNlXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCB7IGFwaURhdGEsIGVycm9yIH0gPSBhd2FpdCBjbGllbnQucGF0Y2g8VXNlcj4oXHJcbiAgICogICAnL3VzZXJzLzEyMycsXHJcbiAgICogICB7IHN0YXR1czogJ2FjdGl2ZScgfVxyXG4gICAqICk7XHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgcGF0Y2g8XHJcbiAgICBUID0gUmVzcG9uc2VEYXRhLFxyXG4gICAgVERhdGEgZXh0ZW5kcyBCb2R5SW5pdCB8IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgbnVsbCA9IFJlY29yZDxcclxuICAgICAgc3RyaW5nLFxyXG4gICAgICB1bmtub3duXHJcbiAgICA+LFxyXG4gID4oXHJcbiAgICBlbmRwb2ludDogc3RyaW5nLFxyXG4gICAgZGF0YT86IFREYXRhLFxyXG4gICAgY29uZmlnPzogUmVxdWVzdENvbmZpZ1xyXG4gICk6IFByb21pc2U8QXBpUmVzcG9uc2U8VCwgQXBpRXJyb3I+PiB7XHJcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0PFQ+KGVuZHBvaW50LCB7XHJcbiAgICAgIC4uLmNvbmZpZyxcclxuICAgICAgbWV0aG9kOiAnUEFUQ0gnLFxyXG4gICAgICBib2R5OiBkYXRhLFxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQZXJmb3JtcyBhIERFTEVURSByZXF1ZXN0XHJcbiAgICogQHRlbXBsYXRlIFQgLSBUaGUgZXhwZWN0ZWQgcmVzcG9uc2UgZGF0YSB0eXBlXHJcbiAgICogQHBhcmFtIGVuZHBvaW50IC0gQVBJIGVuZHBvaW50XHJcbiAgICogQHBhcmFtIGNvbmZpZyAtIE9wdGlvbmFsIHJlcXVlc3QgY29uZmlndXJhdGlvblxyXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIEFwaVJlc3BvbnNlXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCB7IGVycm9yIH0gPSBhd2FpdCBjbGllbnQuZGVsZXRlKCcvdXNlcnMvMTIzJyk7XHJcbiAgICogaWYgKCFlcnJvcikge1xyXG4gICAqICAgY29uc29sZS5sb2coJ1VzZXIgZGVsZXRlZCBzdWNjZXNzZnVsbHknKTtcclxuICAgKiB9XHJcbiAgICogYGBgXHJcbiAgICovXHJcbiAgZGVsZXRlPFQgPSBSZXNwb25zZURhdGE+KFxyXG4gICAgZW5kcG9pbnQ6IHN0cmluZyxcclxuICAgIGNvbmZpZz86IFJlcXVlc3RDb25maWdcclxuICApOiBQcm9taXNlPEFwaVJlc3BvbnNlPFQsIEFwaUVycm9yPj4ge1xyXG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdDxUPihlbmRwb2ludCwgeyAuLi5jb25maWcsIG1ldGhvZDogJ0RFTEVURScgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQZXJmb3JtcyBhIGZpbHRlcmVkIGxpc3QgcmVxdWVzdCB3aXRoIHBhZ2luYXRpb24gYW5kIHNvcnRpbmdcclxuICAgKiBAdGVtcGxhdGUgVExpc3RNb2RlbCAtIFRoZSB0eXBlIG9mIGluZGl2aWR1YWwgbGlzdCBpdGVtc1xyXG4gICAqIEB0ZW1wbGF0ZSBURmlsdGVyIC0gVGhlIGZpbHRlciBjcml0ZXJpYSB0eXBlXHJcbiAgICogQHBhcmFtIHVybCAtIEFQSSBlbmRwb2ludFxyXG4gICAqIEBwYXJhbSBkYXRhIC0gUGFnaW5hdGlvbiBhbmQgZmlsdGVyIGRhdGFcclxuICAgKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgcmVxdWVzdCBjb25maWd1cmF0aW9uXHJcbiAgICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gcGFnaW5hdGVkIGxpc3QgcmVzcG9uc2VcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIGNvbnN0IHsgYXBpRGF0YSwgZXJyb3IgfSA9IGF3YWl0IGNsaWVudC5maWx0ZXI8VXNlciwgVXNlckZpbHRlcj4oXHJcbiAgICogICAnL3VzZXJzL2ZpbHRlcicsXHJcbiAgICogICB7XHJcbiAgICogICAgIHBhZ2VPZmZzZXQ6IDAsXHJcbiAgICogICAgIHBhZ2VTaXplOiAyMCxcclxuICAgKiAgICAgc29ydEZpZWxkOiAnY3JlYXRlZEF0JyxcclxuICAgKiAgICAgc29ydE9yZGVyOiAnZGVzYycsXHJcbiAgICogICAgIGZpbHRlck1vZGVsOiB7IHN0YXR1czogJ2FjdGl2ZScgfVxyXG4gICAqICAgfVxyXG4gICAqICk7XHJcbiAgICpcclxuICAgKiBpZiAoYXBpRGF0YSkge1xyXG4gICAqICAgY29uc29sZS5sb2coYEZvdW5kICR7YXBpRGF0YS5Ub3RhbH0gdXNlcnNgKTtcclxuICAgKiAgIGNvbnNvbGUubG9nKCdVc2VyczonLCBhcGlEYXRhLkRhdGEpO1xyXG4gICAqIH1cclxuICAgKiBgYGBcclxuICAgKi9cclxuICBmaWx0ZXI8VExpc3RNb2RlbCwgVEZpbHRlciA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+PihcclxuICAgIHVybDogc3RyaW5nLFxyXG4gICAgZGF0YTogUG9zdE1vZGVsPFRGaWx0ZXI+LFxyXG4gICAgY29uZmlnPzogUmVxdWVzdENvbmZpZ1xyXG4gICk6IFByb21pc2U8QXBpUmVzcG9uc2U8TGlzdFJlc3BvbnNlPFRMaXN0TW9kZWw+LCBBcGlFcnJvcj4+IHtcclxuICAgIC8vIE1lcmdlIGJvZHk6IHsgLi4ucG9zdE1vZGVsLCAuLi5wb3N0TW9kZWwuZmlsdGVyTW9kZWwgfVxyXG4gICAgY29uc3QgbWVyZ2VkRGF0YSA9IHsgLi4uZGF0YSwgLi4uZGF0YS5maWx0ZXJNb2RlbCB9O1xyXG5cclxuICAgIHJldHVybiB0aGlzLnJlcXVlc3Q8TGlzdFJlc3BvbnNlPFRMaXN0TW9kZWw+Pih1cmwsIHtcclxuICAgICAgLi4uY29uZmlnLFxyXG4gICAgICBtZXRob2Q6ICdQT1NUJyxcclxuICAgICAgYm9keTogbWVyZ2VkRGF0YSxcclxuICAgIH0pO1xyXG4gIH1cclxufVxyXG4iLCAiLyoqXHJcbiAqIEBmaWxlb3ZlcnZpZXcgRmFjdG9yeSBmdW5jdGlvbnMgZm9yIGNyZWF0aW5nIGFuZCBtYW5hZ2luZyBBcGlDbGllbnQgaW5zdGFuY2VzLlxyXG4gKlxyXG4gKiBQcm92aWRlcyBjb252ZW5pZW50IGZhY3RvcnkgbWV0aG9kcyBmb3IgY3JlYXRpbmcgcHJlLWNvbmZpZ3VyZWQgQXBpQ2xpZW50IGluc3RhbmNlc1xyXG4gKiB3aXRoIHNlbnNpYmxlIGRlZmF1bHRzIGFuZCBhdXRvbWF0aWMgdG9rZW4gbWFuYWdlbWVudCBmcm9tIGxvY2FsU3RvcmFnZS5cclxuICpcclxuICogQG1vZHVsZSBjcmVhdGVBcGlDbGllbnRcclxuICovXHJcblxyXG5pbXBvcnQgeyBBcGlDbGllbnQgfSBmcm9tICcuL0FwaUNsaWVudCc7XHJcbmltcG9ydCB0eXBlIHsgRXJyb3JJbnRlcmNlcHRvciB9IGZyb20gJy4vdHlwZXMvRXJyb3JJbnRlcmNlcHRvcic7XHJcbmltcG9ydCB0eXBlIHsgUmVxdWVzdEludGVyY2VwdG9yIH0gZnJvbSAnLi90eXBlcy9SZXF1ZXN0SW50ZXJjZXB0b3InO1xyXG5pbXBvcnQgdHlwZSB7IFJlc3BvbnNlSW50ZXJjZXB0b3IgfSBmcm9tICcuL3R5cGVzL1Jlc3BvbnNlSW50ZXJjZXB0b3InO1xyXG5cclxuLyoqXHJcbiAqIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgY3JlYXRpbmcgYW4gQXBpQ2xpZW50IGluc3RhbmNlLlxyXG4gKlxyXG4gKiBAcHVibGljXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEFwaUNsaWVudENvbmZpZyB7XHJcbiAgLyoqXHJcbiAgICogQmFzZSBVUkwgZm9yIGFsbCBBUEkgcmVxdWVzdHMuXHJcbiAgICogQGV4YW1wbGUgJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJ1xyXG4gICAqL1xyXG4gIGJhc2VVUkw/OiBzdHJpbmc7XHJcblxyXG4gIC8qKlxyXG4gICAqIERlZmF1bHQgdGltZW91dCBmb3IgcmVxdWVzdHMgaW4gbWlsbGlzZWNvbmRzLlxyXG4gICAqIEBkZWZhdWx0IDMwMDAwXHJcbiAgICovXHJcbiAgdGltZW91dD86IG51bWJlcjtcclxuXHJcbiAgLyoqXHJcbiAgICogUHJlZml4IGZvciBhdXRvLWdlbmVyYXRlZCBjb3JyZWxhdGlvbiBJRHMgKGUuZy4sICdhcGknLCAnd2ViJywgJ21vYmlsZScpLlxyXG4gICAqIEBkZWZhdWx0ICdhcGknXHJcbiAgICovXHJcbiAgY29ycmVsYXRpb25JZFByZWZpeD86IHN0cmluZztcclxuXHJcbiAgLyoqXHJcbiAgICogV2hldGhlciB0byBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlIGFuZCBpbmNsdWRlIGNvcnJlbGF0aW9uIElEcyBpbiByZXF1ZXN0cy5cclxuICAgKiBAZGVmYXVsdCB0cnVlXHJcbiAgICovXHJcbiAgaW5jbHVkZUNvcnJlbGF0aW9uSWQ/OiBib29sZWFuO1xyXG5cclxuICAvKipcclxuICAgKiBJbml0aWFsIGF1dGhlbnRpY2F0aW9uIHRva2VuIHRvIHNldCBvbiB0aGUgY2xpZW50LlxyXG4gICAqIEBkZWZhdWx0IHVuZGVmaW5lZFxyXG4gICAqL1xyXG4gIGF1dGhUb2tlbj86IHN0cmluZyB8IG51bGw7XHJcblxyXG4gIC8qKlxyXG4gICAqIEFycmF5IG9mIHJlcXVlc3QgaW50ZXJjZXB0b3JzIHRvIHJlZ2lzdGVyIGR1cmluZyBjbGllbnQgY3JlYXRpb24uXHJcbiAgICogQGRlZmF1bHQgW11cclxuICAgKi9cclxuICByZXF1ZXN0SW50ZXJjZXB0b3JzPzogUmVxdWVzdEludGVyY2VwdG9yW107XHJcblxyXG4gIC8qKlxyXG4gICAqIEFycmF5IG9mIHJlc3BvbnNlIGludGVyY2VwdG9ycyB0byByZWdpc3RlciBkdXJpbmcgY2xpZW50IGNyZWF0aW9uLlxyXG4gICAqIEBkZWZhdWx0IFtdXHJcbiAgICovXHJcbiAgcmVzcG9uc2VJbnRlcmNlcHRvcnM/OiBSZXNwb25zZUludGVyY2VwdG9yW107XHJcblxyXG4gIC8qKlxyXG4gICAqIEFycmF5IG9mIGVycm9yIGludGVyY2VwdG9ycyB0byByZWdpc3RlciBkdXJpbmcgY2xpZW50IGNyZWF0aW9uLlxyXG4gICAqIEBkZWZhdWx0IFtdXHJcbiAgICovXHJcbiAgZXJyb3JJbnRlcmNlcHRvcnM/OiBFcnJvckludGVyY2VwdG9yW107XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHbG9iYWwgc2luZ2xldG9uIEFwaUNsaWVudCBpbnN0YW5jZS5cclxuICogQGludGVybmFsXHJcbiAqL1xyXG5sZXQgZ2xvYmFsQXBpQ2xpZW50OiBBcGlDbGllbnQgfCBudWxsID0gbnVsbDtcclxuXHJcbi8qKlxyXG4gKiBDcmVhdGVzIGEgbmV3IEFwaUNsaWVudCBpbnN0YW5jZSB3aXRoIHNlbnNpYmxlIGRlZmF1bHRzIGFuZCBhdXRvbWF0aWMgdG9rZW4gbWFuYWdlbWVudC5cclxuICpcclxuICogVGhpcyBmYWN0b3J5IGZ1bmN0aW9uOlxyXG4gKiAtIENvbmZpZ3VyZXMgdGhlIGJhc2UgVVJMIGZyb20gZW52aXJvbm1lbnQgdmFyaWFibGVzIG9yIGNvbmZpZ1xyXG4gKiAtIFNldHMgdXAgYXV0b21hdGljIGF1dGhlbnRpY2F0aW9uIHRva2VuIGluamVjdGlvbiBmcm9tIGxvY2FsU3RvcmFnZSAoJ3NlcnZpY2VUb2tlbicga2V5KVxyXG4gKiAtIENvbmZpZ3VyZXMgY29ycmVsYXRpb24gSUQgZ2VuZXJhdGlvblxyXG4gKiAtIFJlZ2lzdGVycyBwcm92aWRlZCBpbnRlcmNlcHRvcnNcclxuICpcclxuICogKipOb3RlOioqIEVhY2ggY2FsbCBjcmVhdGVzIGEgTkVXIGluc3RhbmNlLiBVc2Uge0BsaW5rIGdldEdsb2JhbEFwaUNsaWVudH0gZm9yIHNpbmdsZXRvbiBiZWhhdmlvci5cclxuICpcclxuICogQHBhcmFtIGNvbmZpZyAtIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgdGhlIEFQSSBjbGllbnRcclxuICogQHJldHVybnMgQSBmdWxseSBjb25maWd1cmVkIEFwaUNsaWVudCBpbnN0YW5jZVxyXG4gKiBAcHVibGljXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIEJhc2ljIHVzYWdlIHdpdGggZGVmYXVsdHM6XHJcbiAqIGBgYHR5cGVzY3JpcHRcclxuICogY29uc3QgY2xpZW50ID0gY3JlYXRlQXBpQ2xpZW50KCk7XHJcbiAqIC8vIFVzZXMgVklURV9BUElfVVJMLCAzMHMgdGltZW91dCwgYXV0byB0b2tlbiBmcm9tIGxvY2FsU3RvcmFnZVxyXG4gKiBgYGBcclxuICpcclxuICogQGV4YW1wbGVcclxuICogQ3VzdG9tIGNvbmZpZ3VyYXRpb246XHJcbiAqIGBgYHR5cGVzY3JpcHRcclxuICogY29uc3QgY2xpZW50ID0gY3JlYXRlQXBpQ2xpZW50KHtcclxuICogICBiYXNlVVJMOiAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nLFxyXG4gKiAgIHRpbWVvdXQ6IDYwMDAwLFxyXG4gKiAgIGNvcnJlbGF0aW9uSWRQcmVmaXg6ICd3ZWInLFxyXG4gKiAgIHJlcXVlc3RJbnRlcmNlcHRvcnM6IFtcclxuICogICAgIGFzeW5jIChjb25maWcpID0+IHtcclxuICogICAgICAgY29uc29sZS5sb2coJ01ha2luZyByZXF1ZXN0OicsIGNvbmZpZy51cmwpO1xyXG4gKiAgICAgICByZXR1cm4gY29uZmlnO1xyXG4gKiAgICAgfVxyXG4gKiAgIF1cclxuICogfSk7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBXaXRoIFJlYWN0IFF1ZXJ5OlxyXG4gKiBgYGB0eXBlc2NyaXB0XHJcbiAqIGNvbnN0IGFwaUNsaWVudCA9IGNyZWF0ZUFwaUNsaWVudCh7XHJcbiAqICAgYmFzZVVSTDogcHJvY2Vzcy5lbnYuUkVBQ1RfQVBQX0FQSV9VUkxcclxuICogfSk7XHJcbiAqXHJcbiAqIGNvbnN0IHF1ZXJ5Q2xpZW50ID0gbmV3IFF1ZXJ5Q2xpZW50KCk7XHJcbiAqXHJcbiAqIGZ1bmN0aW9uIFVzZXJQcm9maWxlKHsgdXNlcklkIH0pIHtcclxuICogICBjb25zdCB7IGRhdGE6IHJlc3BvbnNlIH0gPSB1c2VRdWVyeSh7XHJcbiAqICAgICBxdWVyeUtleTogWyd1c2VyJywgdXNlcklkXSxcclxuICogICAgIHF1ZXJ5Rm46ICgpID0+IGFwaUNsaWVudC5nZXQoYC91c2Vycy8ke3VzZXJJZH1gKVxyXG4gKiAgIH0pO1xyXG4gKiAgIGNvbnN0IHVzZXIgPSByZXNwb25zZT8uYXBpRGF0YTsgLy8gQWNjZXNzIHRoZSBhY3R1YWwgZGF0YVxyXG4gKiAgIC8vIC4uLlxyXG4gKiB9XHJcbiAqIGBgYFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUFwaUNsaWVudChjb25maWc6IEFwaUNsaWVudENvbmZpZyA9IHt9KTogQXBpQ2xpZW50IHtcclxuICBjb25zdCB7XHJcbiAgICBiYXNlVVJMID0gJycsXHJcbiAgICB0aW1lb3V0ID0gMzAwMDAsXHJcbiAgICBjb3JyZWxhdGlvbklkUHJlZml4ID0gJ3dlYicsXHJcbiAgICBpbmNsdWRlQ29ycmVsYXRpb25JZCA9IHRydWUsXHJcbiAgICByZXF1ZXN0SW50ZXJjZXB0b3JzID0gW10sXHJcbiAgICByZXNwb25zZUludGVyY2VwdG9ycyA9IFtdLFxyXG4gICAgZXJyb3JJbnRlcmNlcHRvcnMgPSBbXSxcclxuICB9ID0gY29uZmlnO1xyXG5cclxuICBjb25zdCBjbGllbnQgPSBuZXcgQXBpQ2xpZW50KGJhc2VVUkwsIHRpbWVvdXQpO1xyXG5cclxuICBjbGllbnQuYWRkUmVxdWVzdEludGVyY2VwdG9yKGNvbmZpZyA9PiB7XHJcbiAgICBjb25zdCB0b2tlbiA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdzZXJ2aWNlVG9rZW4nKTtcclxuXHJcbiAgICBpZiAodG9rZW4gJiYgIWNvbmZpZy5za2lwQXV0aFJlZnJlc2gpIHtcclxuICAgICAgY29uZmlnLmhlYWRlcnMgPSB7XHJcbiAgICAgICAgLi4uY29uZmlnLmhlYWRlcnMsXHJcbiAgICAgICAgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke3Rva2VufWAsXHJcbiAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGNvbmZpZztcclxuICB9KTtcclxuXHJcbiAgLy8gQ29uZmlndXJlIGNvcnJlbGF0aW9uIElEXHJcbiAgY2xpZW50LnNldENvcnJlbGF0aW9uSWRQcmVmaXgoY29ycmVsYXRpb25JZFByZWZpeCk7XHJcbiAgY2xpZW50LnNldEluY2x1ZGVDb3JyZWxhdGlvbklkKGluY2x1ZGVDb3JyZWxhdGlvbklkKTtcclxuXHJcbiAgLy8gLy8gU2V0IGF1dGggdG9rZW4gaWYgcHJvdmlkZWRcclxuICAvLyBpZiAoYXV0aFRva2VuICE9PSB1bmRlZmluZWQpIHtcclxuICAvLyAgIGNsaWVudC5zZXRBdXRoVG9rZW4oYXV0aFRva2VuKTtcclxuICAvLyB9XHJcblxyXG4gIC8vIEFkZCBpbnRlcmNlcHRvcnNcclxuICByZXF1ZXN0SW50ZXJjZXB0b3JzLmZvckVhY2goaW50ZXJjZXB0b3IgPT4ge1xyXG4gICAgY2xpZW50LmFkZFJlcXVlc3RJbnRlcmNlcHRvcihpbnRlcmNlcHRvcik7XHJcbiAgfSk7XHJcblxyXG4gIHJlc3BvbnNlSW50ZXJjZXB0b3JzLmZvckVhY2goaW50ZXJjZXB0b3IgPT4ge1xyXG4gICAgY2xpZW50LmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoaW50ZXJjZXB0b3IpO1xyXG4gIH0pO1xyXG5cclxuICBlcnJvckludGVyY2VwdG9ycy5mb3JFYWNoKGludGVyY2VwdG9yID0+IHtcclxuICAgIGNsaWVudC5hZGRFcnJvckludGVyY2VwdG9yKGludGVyY2VwdG9yKTtcclxuICB9KTtcclxuXHJcbiAgcmV0dXJuIGNsaWVudDtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgb3IgY3JlYXRlcyBhIGdsb2JhbCBzaW5nbGV0b24gQXBpQ2xpZW50IGluc3RhbmNlLlxyXG4gKlxyXG4gKiBUaGlzIGZ1bmN0aW9uIGltcGxlbWVudHMgdGhlIHNpbmdsZXRvbiBwYXR0ZXJuIGZvciBBcGlDbGllbnQuIEl0IGNyZWF0ZXMgdGhlIGNsaWVudFxyXG4gKiBvbiBmaXJzdCBjYWxsIGFuZCByZXR1cm5zIHRoZSBzYW1lIGluc3RhbmNlIG9uIHN1YnNlcXVlbnQgY2FsbHMuIFRoaXMgaXMgdXNlZnVsIGZvcjpcclxuICogLSBTaGFyaW5nIHRoZSBzYW1lIGNsaWVudCBhY3Jvc3MgeW91ciBlbnRpcmUgYXBwbGljYXRpb25cclxuICogLSBBdm9pZGluZyBtdWx0aXBsZSBpbnN0YW5jZXMgd2l0aCBkaWZmZXJlbnQgY29uZmlndXJhdGlvbnNcclxuICogLSBDb25zaXN0ZW50IGludGVyY2VwdG9yIGJlaGF2aW9yIGFwcC13aWRlXHJcbiAqXHJcbiAqICoqSW1wb3J0YW50OioqIFRoZSBjb25maWcgcGFyYW1ldGVyIGlzIG9ubHkgdXNlZCBvbiB0aGUgRklSU1QgY2FsbC4gU3Vic2VxdWVudCBjYWxsc1xyXG4gKiBpZ25vcmUgdGhlIGNvbmZpZyBhbmQgcmV0dXJuIHRoZSBleGlzdGluZyBpbnN0YW5jZS4gVXNlIHtAbGluayByZXNldEdsb2JhbEFwaUNsaWVudH1cclxuICogZmlyc3QgaWYgeW91IG5lZWQgdG8gcmVjcmVhdGUgd2l0aCBkaWZmZXJlbnQgY29uZmlnLlxyXG4gKlxyXG4gKiBAcGFyYW0gY29uZmlnIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zIChvbmx5IHVzZWQgb24gZmlyc3QgY2FsbClcclxuICogQHJldHVybnMgVGhlIGdsb2JhbCBBcGlDbGllbnQgc2luZ2xldG9uIGluc3RhbmNlXHJcbiAqIEBwdWJsaWNcclxuICpcclxuICogQGV4YW1wbGVcclxuICogSW4geW91ciBhcHAgaW5pdGlhbGl6YXRpb246XHJcbiAqIGBgYHR5cGVzY3JpcHRcclxuICogLy8gc3JjL2xpYi9hcGkudHNcclxuICogZXhwb3J0IGNvbnN0IGFwaUNsaWVudCA9IGdldEdsb2JhbEFwaUNsaWVudCh7XHJcbiAqICAgYmFzZVVSTDogJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJyxcclxuICogICB0aW1lb3V0OiAzMDAwMFxyXG4gKiB9KTtcclxuICogYGBgXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIEltcG9ydCBhbmQgdXNlIHRocm91Z2hvdXQgeW91ciBhcHA6XHJcbiAqIGBgYHR5cGVzY3JpcHRcclxuICogLy8gc3JjL2ZlYXR1cmVzL3VzZXJzL2FwaS50c1xyXG4gKiBpbXBvcnQgeyBnZXRHbG9iYWxBcGlDbGllbnQgfSBmcm9tICdAZ253ZWJzb2Z0L3VpJztcclxuICpcclxuICogY29uc3QgY2xpZW50ID0gZ2V0R2xvYmFsQXBpQ2xpZW50KCk7IC8vIFJldHVybnMgc2FtZSBpbnN0YW5jZVxyXG4gKlxyXG4gKiBleHBvcnQgYXN5bmMgZnVuY3Rpb24gZmV0Y2hVc2VycygpIHtcclxuICogICBjb25zdCB7IGFwaURhdGEgfSA9IGF3YWl0IGNsaWVudC5nZXQoJy91c2VycycpO1xyXG4gKiAgIHJldHVybiBhcGlEYXRhO1xyXG4gKiB9XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBSZXNldHRpbmcgZm9yIHRlc3RzOlxyXG4gKiBgYGB0eXBlc2NyaXB0XHJcbiAqIGFmdGVyRWFjaCgoKSA9PiB7XHJcbiAqICAgcmVzZXRHbG9iYWxBcGlDbGllbnQoKTtcclxuICogfSk7XHJcbiAqXHJcbiAqIHRlc3QoJ2NyZWF0ZXMgZnJlc2ggY2xpZW50JywgKCkgPT4ge1xyXG4gKiAgIGNvbnN0IGNsaWVudCA9IGdldEdsb2JhbEFwaUNsaWVudCh7IGJhc2VVUkw6ICdodHRwOi8vdGVzdC5sb2NhbCcgfSk7XHJcbiAqICAgLy8gTmV3IGluc3RhbmNlIHdpdGggdGVzdCBjb25maWdcclxuICogfSk7XHJcbiAqIGBgYFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGdldEdsb2JhbEFwaUNsaWVudChjb25maWc/OiBBcGlDbGllbnRDb25maWcpOiBBcGlDbGllbnQge1xyXG4gIGlmICghZ2xvYmFsQXBpQ2xpZW50KSB7XHJcbiAgICBnbG9iYWxBcGlDbGllbnQgPSBjcmVhdGVBcGlDbGllbnQoY29uZmlnKTtcclxuICB9XHJcblxyXG4gIHJldHVybiBnbG9iYWxBcGlDbGllbnQ7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXBsYWNlcyB0aGUgZ2xvYmFsIHNpbmdsZXRvbiBBcGlDbGllbnQgd2l0aCBhIGN1c3RvbSBpbnN0YW5jZS5cclxuICpcclxuICogVXNlIHRoaXMgd2hlbiB5b3UgbmVlZCBmaW5lLWdyYWluZWQgY29udHJvbCBvdmVyIHRoZSBnbG9iYWwgY2xpZW50IGluc3RhbmNlLFxyXG4gKiBzdWNoIGFzIGluIHRlc3Rpbmcgc2NlbmFyaW9zIG9yIHdoZW4geW91J3ZlIG1hbnVhbGx5IGNyZWF0ZWQgYSBjbGllbnQgd2l0aFxyXG4gKiBzcGVjaWZpYyBjb25maWd1cmF0aW9uLlxyXG4gKlxyXG4gKiBAcGFyYW0gY2xpZW50IC0gVGhlIEFwaUNsaWVudCBpbnN0YW5jZSB0byB1c2UgYXMgdGhlIGdsb2JhbCBzaW5nbGV0b25cclxuICogQHB1YmxpY1xyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBUZXN0aW5nIHdpdGggYSBtb2NrIGNsaWVudDpcclxuICogYGBgdHlwZXNjcmlwdFxyXG4gKiBjb25zdCBtb2NrQ2xpZW50ID0gbmV3IEFwaUNsaWVudCgnaHR0cDovL3Rlc3QubG9jYWwnKTtcclxuICogbW9ja0NsaWVudC5hZGRSZXNwb25zZUludGVyY2VwdG9yKGFzeW5jIChyZXNwb25zZSkgPT4ge1xyXG4gKiAgIC8vIE1vY2sgcmVzcG9uc2UgZGF0YVxyXG4gKiAgIHJldHVybiB7IGRhdGE6IG1vY2tEYXRhIH07XHJcbiAqIH0pO1xyXG4gKlxyXG4gKiBzZXRHbG9iYWxBcGlDbGllbnQobW9ja0NsaWVudCk7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBBZHZhbmNlZCBjb25maWd1cmF0aW9uOlxyXG4gKiBgYGB0eXBlc2NyaXB0XHJcbiAqIGNvbnN0IGNsaWVudCA9IG5ldyBBcGlDbGllbnQoJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJywgNjAwMDApO1xyXG4gKiBjbGllbnQuc2V0Q29ycmVsYXRpb25JZFByZWZpeCgnY3VzdG9tJyk7XHJcbiAqIGNsaWVudC5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoY3VzdG9tSW50ZXJjZXB0b3IpO1xyXG4gKlxyXG4gKiBzZXRHbG9iYWxBcGlDbGllbnQoY2xpZW50KTtcclxuICogYGBgXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gc2V0R2xvYmFsQXBpQ2xpZW50KGNsaWVudDogQXBpQ2xpZW50KTogdm9pZCB7XHJcbiAgZ2xvYmFsQXBpQ2xpZW50ID0gY2xpZW50O1xyXG59XHJcblxyXG4vKipcclxuICogUmVzZXRzIHRoZSBnbG9iYWwgQXBpQ2xpZW50IHNpbmdsZXRvbiB0byBudWxsLlxyXG4gKlxyXG4gKiBBZnRlciBjYWxsaW5nIHRoaXMsIHRoZSBuZXh0IGNhbGwgdG8ge0BsaW5rIGdldEdsb2JhbEFwaUNsaWVudH0gd2lsbCBjcmVhdGVcclxuICogYSBmcmVzaCBpbnN0YW5jZS4gVGhpcyBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIGluOlxyXG4gKiAtIFRlc3QgY2xlYW51cCB0byBlbnN1cmUgdGVzdCBpc29sYXRpb25cclxuICogLSBBcHBsaWNhdGlvbiBsb2dvdXQgdG8gY2xlYXIgYW55IGNhY2hlZCBzdGF0ZVxyXG4gKiAtIEhvdCBtb2R1bGUgcmVsb2FkaW5nIGR1cmluZyBkZXZlbG9wbWVudFxyXG4gKlxyXG4gKiBAcHVibGljXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIFRlc3QgY2xlYW51cDpcclxuICogYGBgdHlwZXNjcmlwdFxyXG4gKiBhZnRlckVhY2goKCkgPT4ge1xyXG4gKiAgIHJlc2V0R2xvYmFsQXBpQ2xpZW50KCk7XHJcbiAqIH0pO1xyXG4gKiBgYGBcclxuICpcclxuICogQGV4YW1wbGVcclxuICogTG9nb3V0IGZsb3c6XHJcbiAqIGBgYHR5cGVzY3JpcHRcclxuICogZnVuY3Rpb24gaGFuZGxlTG9nb3V0KCkge1xyXG4gKiAgIC8vIENsZWFyIGF1dGhlbnRpY2F0aW9uXHJcbiAqICAgbG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oJ3NlcnZpY2VUb2tlbicpO1xyXG4gKlxyXG4gKiAgIC8vIENhbmNlbCBhbGwgcGVuZGluZyByZXF1ZXN0cyBhbmQgcmVzZXQgY2xpZW50XHJcbiAqICAgY29uc3QgY2xpZW50ID0gZ2V0R2xvYmFsQXBpQ2xpZW50KCk7XHJcbiAqICAgY2xpZW50LmNhbmNlbEFsbFJlcXVlc3RzKCk7XHJcbiAqICAgcmVzZXRHbG9iYWxBcGlDbGllbnQoKTtcclxuICpcclxuICogICAvLyBSZWRpcmVjdCB0byBsb2dpblxyXG4gKiAgIG5hdmlnYXRlKCcvbG9naW4nKTtcclxuICogfVxyXG4gKiBgYGBcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiByZXNldEdsb2JhbEFwaUNsaWVudCgpOiB2b2lkIHtcclxuICBnbG9iYWxBcGlDbGllbnQgPSBudWxsO1xyXG59XHJcbiIsICIvLyBDYW5jZWxUb2tlbiBpbXBsZW1lbnRhdGlvblxyXG5leHBvcnQgY2xhc3MgQ2FuY2VsVG9rZW4ge1xyXG4gIHByaXZhdGUgYWJvcnRDb250cm9sbGVyOiBBYm9ydENvbnRyb2xsZXI7XHJcbiAgcHJpdmF0ZSBjYW5jZWxQcm9taXNlOiBQcm9taXNlPHZvaWQ+O1xyXG4gIHByaXZhdGUgY2FuY2VsUmVzb2x2ZT86ICgpID0+IHZvaWQ7XHJcblxyXG4gIGNvbnN0cnVjdG9yKCkge1xyXG4gICAgdGhpcy5hYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XHJcbiAgICB0aGlzLmNhbmNlbFByb21pc2UgPSBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcclxuICAgICAgdGhpcy5jYW5jZWxSZXNvbHZlID0gcmVzb2x2ZTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHNpZ25hbCgpOiBBYm9ydFNpZ25hbCB7XHJcbiAgICByZXR1cm4gdGhpcy5hYm9ydENvbnRyb2xsZXIuc2lnbmFsO1xyXG4gIH1cclxuXHJcbiAgY2FuY2VsKHJlYXNvbj86IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5hYm9ydENvbnRyb2xsZXIuYWJvcnQocmVhc29uKTtcclxuICAgIHRoaXMuY2FuY2VsUmVzb2x2ZT8uKCk7XHJcbiAgfVxyXG5cclxuICBnZXQgaXNDYW5jZWxsZWQoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5hYm9ydENvbnRyb2xsZXIuc2lnbmFsLmFib3J0ZWQ7XHJcbiAgfVxyXG5cclxuICB0aHJvd0lmQ2FuY2VsbGVkKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuaXNDYW5jZWxsZWQpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZXF1ZXN0IGNhbmNlbGxlZCcpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc3RhdGljIHNvdXJjZSgpOiB7IHRva2VuOiBDYW5jZWxUb2tlbjsgY2FuY2VsOiAocmVhc29uPzogc3RyaW5nKSA9PiB2b2lkIH0ge1xyXG4gICAgY29uc3QgdG9rZW4gPSBuZXcgQ2FuY2VsVG9rZW4oKTtcclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICB0b2tlbixcclxuICAgICAgY2FuY2VsOiAocmVhc29uPzogc3RyaW5nKSA9PiB0b2tlbi5jYW5jZWwocmVhc29uKSxcclxuICAgIH07XHJcbiAgfVxyXG59XHJcbiIsICIvLyBSZWFjdCBIb29rcyB3aXRoIEFwaVJlc3BvbnNlIGZvcm1hdFxyXG5pbXBvcnQgeyB1c2VDYWxsYmFjayB9IGZyb20gJ3JlYWN0JztcclxuXHJcbmltcG9ydCB0eXBlIHsgQXBpRXJyb3IgfSBmcm9tICcuL3R5cGVzJztcclxuXHJcbi8vIEV4cG9ydCBmYWN0b3J5IG1ldGhvZHMgYW5kIHR5cGVzXHJcbmV4cG9ydCB7XHJcbiAgY3JlYXRlQXBpQ2xpZW50LFxyXG4gIGdldEdsb2JhbEFwaUNsaWVudCxcclxuICBzZXRHbG9iYWxBcGlDbGllbnQsXHJcbiAgcmVzZXRHbG9iYWxBcGlDbGllbnQsXHJcbn0gZnJvbSAnLi9jcmVhdGVBcGlDbGllbnQnO1xyXG5cclxuZXhwb3J0IHR5cGUgeyBBcGlDbGllbnRDb25maWcgfSBmcm9tICcuL2NyZWF0ZUFwaUNsaWVudCc7XHJcblxyXG5leHBvcnQgeyBBcGlDbGllbnQgfSBmcm9tICcuL0FwaUNsaWVudCc7XHJcblxyXG4vLyBIZWxwZXIgaG9vayBmb3IgZm9ybSB2YWxpZGF0aW9uIGVycm9yc1xyXG5leHBvcnQgZnVuY3Rpb24gdXNlVmFsaWRhdGlvbkVycm9ycyhlcnJvcjogQXBpRXJyb3IgfCBudWxsKSB7XHJcbiAgY29uc3QgZ2V0RmllbGRFcnJvciA9IHVzZUNhbGxiYWNrKFxyXG4gICAgKGZpZWxkOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsID0+IHtcclxuICAgICAgaWYgKCFlcnJvcj8uZXJyb3JzIHx8ICFlcnJvci5lcnJvcnNbZmllbGRdKSByZXR1cm4gbnVsbDtcclxuXHJcbiAgICAgIGNvbnN0IGZpZWxkRXJyb3IgPSBlcnJvci5lcnJvcnNbZmllbGRdO1xyXG5cclxuICAgICAgaWYgKHR5cGVvZiBmaWVsZEVycm9yID09PSAnc3RyaW5nJykgcmV0dXJuIGZpZWxkRXJyb3I7XHJcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGZpZWxkRXJyb3IpKSByZXR1cm4gZmllbGRFcnJvclswXTtcclxuICAgICAgaWYgKHR5cGVvZiBmaWVsZEVycm9yID09PSAnb2JqZWN0JyAmJiAnbWVzc2FnZScgaW4gZmllbGRFcnJvcikge1xyXG4gICAgICAgIHJldHVybiBmaWVsZEVycm9yLm1lc3NhZ2U7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfSxcclxuICAgIFtlcnJvcl1cclxuICApO1xyXG5cclxuICBjb25zdCBoYXNGaWVsZEVycm9yID0gdXNlQ2FsbGJhY2soXHJcbiAgICAoZmllbGQ6IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xyXG4gICAgICByZXR1cm4gISFnZXRGaWVsZEVycm9yKGZpZWxkKTtcclxuICAgIH0sXHJcbiAgICBbZ2V0RmllbGRFcnJvcl1cclxuICApO1xyXG5cclxuICBjb25zdCBnZXRBbGxFcnJvcnMgPSB1c2VDYWxsYmFjaygoKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9PiB7XHJcbiAgICBpZiAoIWVycm9yPy5lcnJvcnMpIHJldHVybiB7fTtcclxuXHJcbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcclxuXHJcbiAgICBPYmplY3QuZW50cmllcyhlcnJvci5lcnJvcnMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xyXG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgIHJlc3VsdFtrZXldID0gdmFsdWU7XHJcbiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcclxuICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlLmpvaW4oJywgJyk7XHJcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAmJiAnbWVzc2FnZScgaW4gdmFsdWUpIHtcclxuICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlLm1lc3NhZ2U7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfSwgW2Vycm9yXSk7XHJcblxyXG4gIHJldHVybiB7XHJcbiAgICBnZXRGaWVsZEVycm9yLFxyXG4gICAgaGFzRmllbGRFcnJvcixcclxuICAgIGdldEFsbEVycm9ycyxcclxuICAgIGhhc0Vycm9yczogZXJyb3I/LmVycm9ycyxcclxuICB9O1xyXG59XHJcbiIsICJpbXBvcnQgdHlwZSB7IFByb3BzV2l0aENoaWxkcmVuIH0gZnJvbSAncmVhY3QnO1xuXG50eXBlIEF1dGhvcml6ZWRWaWV3UHJvcHMgPSBQcm9wc1dpdGhDaGlsZHJlbiAmIHtcbiAgc2hvdzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCBjb25zdCBBdXRob3JpemVkVmlldyA9ICh7IGNoaWxkcmVuLCBzaG93IH06IEF1dGhvcml6ZWRWaWV3UHJvcHMpID0+IHtcbiAgaWYgKCFzaG93KSByZXR1cm4gPD48Lz47XG5cbiAgcmV0dXJuIDw+e2NoaWxkcmVufTwvPjtcbn07XG4iLCAiaW1wb3J0IHR5cGUgeyBCdXR0b25Qcm9wcyB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xuaW1wb3J0IHsgQnV0dG9uIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgY29uc3QgQ2FuY2VsQnV0dG9uOiBSZWFjdC5GQzxCdXR0b25Qcm9wcz4gPSAoe1xuICBjaGlsZHJlbiA9ICdDYW5jZWwnLFxuICB2YXJpYW50ID0gJ291dGxpbmVkJyxcbiAgc3gsXG4gIC4uLnJlc3Rcbn0pID0+IChcbiAgPEJ1dHRvbiB2YXJpYW50PXt2YXJpYW50fSBzeD17eyB3aWR0aDogJzZyZW0nLCAuLi5zeCB9fSB7Li4ucmVzdH0+XG4gICAge2NoaWxkcmVufVxuICA8L0J1dHRvbj5cbik7XG4iLCAiaW1wb3J0IHR5cGUgeyBTeFByb3BzIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgeyBCdXR0b24gfSBmcm9tICdAbXVpL21hdGVyaWFsJztcblxuLyoqXG4gKiBQcm9wcyBmb3IgdGhlIENsZWFyQnV0dG9uIGNvbXBvbmVudC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmludGVyZmFjZSBDbGVhckJ1dHRvblByb3BzIHtcbiAgLyoqXG4gICAqIEluZGljYXRlcyBpZiBhIGZvcm0gb3Igb3BlcmF0aW9uIGlzIGN1cnJlbnRseSBiZWluZyBzdWJtaXR0ZWQuXG4gICAqIFdoZW4gdHJ1ZSwgdGhlIGJ1dHRvbiBpcyBkaXNhYmxlZCB0byBwcmV2ZW50IG11bHRpcGxlIGNsZWFyIGFjdGlvbnMuXG4gICAqL1xuICBpc1N1Ym1pdHRpbmc6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBleGVjdXRlZCB3aGVuIHRoZSBjbGVhciBidXR0b24gaXMgY2xpY2tlZC5cbiAgICogU2hvdWxkIGhhbmRsZSB0aGUgY2xlYXJpbmcgbG9naWMgKGUuZy4sIGZvcm0gcmVzZXQsIGRhdGEgY2xlYXJpbmcpLlxuICAgKi9cbiAgaGFuZGxlQ2xlYXI6ICgpID0+IHZvaWQ7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBNVUkgc3ggcHJvcCBmb3IgY3VzdG9tIHN0eWxpbmcuXG4gICAqIEBleGFtcGxlIHsgbXQ6IDIsIGNvbG9yOiAnd2FybmluZy5tYWluJyB9XG4gICAqL1xuICBzeD86IFN4UHJvcHM7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBsb2NhbFN0b3JhZ2Uga2V5IHRvIHJlbW92ZSB3aGVuIGNsZWFyaW5nLlxuICAgKiBJZiBwcm92aWRlZCwgdGhlIGNvcnJlc3BvbmRpbmcgbG9jYWxTdG9yYWdlIGl0ZW0gd2lsbCBiZSByZW1vdmVkIG9uIGNsaWNrLlxuICAgKiBAZXhhbXBsZSBcInVzZXItcHJlZmVyZW5jZXNcIiBvciBcImZvcm0tZGF0YVwiXG4gICAqL1xuICBzdG9yZUtleT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBTdGFuZGFyZGl6ZWQgY2xlYXIgYnV0dG9uIGNvbXBvbmVudCB3aXRoIGxvY2FsU3RvcmFnZSBpbnRlZ3JhdGlvbi5cbiAqXG4gKiBUaGlzIGNvbXBvbmVudCBwcm92aWRlcyBhIGNvbnNpc3RlbnQgY2xlYXIgYnV0dG9uIGltcGxlbWVudGF0aW9uIHRoYXQgaGFuZGxlc1xuICogYm90aCBjYWxsYmFjayBleGVjdXRpb24gYW5kIG9wdGlvbmFsIGxvY2FsU3RvcmFnZSBjbGVhbnVwLiBJdCBhdXRvbWF0aWNhbGx5XG4gKiBkaXNhYmxlcyBkdXJpbmcgZm9ybSBzdWJtaXNzaW9ucyBhbmQgY2FuIGNsZWFyIHN0b3JlZCBkYXRhIHdoZW4gbmVlZGVkLlxuICpcbiAqIEBleGFtcGxlXG4gKiBCYXNpYyB1c2FnZTpcbiAqIGBgYHRzeFxuICogPENsZWFyQnV0dG9uXG4gKiAgIGlzU3VibWl0dGluZz17aXNMb2FkaW5nfVxuICogICBoYW5kbGVDbGVhcj17KCkgPT4gZm9ybS5yZXNldCgpfVxuICogLz5cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBXaXRoIGxvY2FsU3RvcmFnZSBjbGVhbnVwOlxuICogYGBgdHN4XG4gKiA8Q2xlYXJCdXR0b25cbiAqICAgaXNTdWJtaXR0aW5nPXtmb3JtLmZvcm1TdGF0ZS5pc1N1Ym1pdHRpbmd9XG4gKiAgIGhhbmRsZUNsZWFyPXsoKSA9PiBzZXRGaWx0ZXJzKHt9KX1cbiAqICAgc3RvcmVLZXk9XCJ1c2VyLWZpbHRlcnNcIlxuICogLz5cbiAqIGBgYFxuICpcbiAqIEBwYXJhbSBwcm9wcyAtIENvbXBvbmVudCBwcm9wcyBmb3IgY2xlYXIgYnV0dG9uIGNvbmZpZ3VyYXRpb25cbiAqIEByZXR1cm5zIE1VSSBCdXR0b24gY29tcG9uZW50IGNvbmZpZ3VyZWQgYXMgYSBjbGVhciBidXR0b25cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBDbGVhckJ1dHRvbiA9ICh7XG4gIGlzU3VibWl0dGluZyxcbiAgaGFuZGxlQ2xlYXIsXG4gIHN4LFxuICBzdG9yZUtleSxcbn06IENsZWFyQnV0dG9uUHJvcHMpID0+IHtcbiAgY29uc3Qgb25DbGljayA9ICgpID0+IHtcbiAgICBoYW5kbGVDbGVhcigpO1xuICAgIGlmIChzdG9yZUtleSAhPSBudWxsKSB7XG4gICAgICBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShzdG9yZUtleSk7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiAoXG4gICAgPEJ1dHRvblxuICAgICAgdmFyaWFudD1cIm91dGxpbmVkXCJcbiAgICAgIG9uQ2xpY2s9e29uQ2xpY2t9XG4gICAgICBkaXNhYmxlZD17aXNTdWJtaXR0aW5nfVxuICAgICAgc3g9e3N4fVxuICAgID5cbiAgICAgIENsZWFyXG4gICAgPC9CdXR0b24+XG4gICk7XG59O1xuIiwgImltcG9ydCB7IENvbnRhaW5lciwgdHlwZSBTeFByb3BzIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgdHlwZSB7IFJlYWN0Tm9kZSB9IGZyb20gJ3JlYWN0JztcblxuaW50ZXJmYWNlIFNpbXBsZUNvbnRhaW5lclByb3BzIHtcbiAgY2hpbGRyZW46IFJlYWN0Tm9kZTtcbiAgY2xhc3NOYW1lPzogc3RyaW5nO1xuICBzeD86IFN4UHJvcHM7XG59XG5cbmV4cG9ydCBjb25zdCBTaW1wbGVDb250YWluZXIgPSAoe1xuICBjaGlsZHJlbixcbiAgY2xhc3NOYW1lLFxuICBzeCxcbn06IFNpbXBsZUNvbnRhaW5lclByb3BzKSA9PiAoXG4gIDxDb250YWluZXIgY2xhc3NOYW1lPXtjbGFzc05hbWV9IHN4PXt7IC4uLnN4IH19PlxuICAgIHtjaGlsZHJlbn1cbiAgPC9Db250YWluZXI+XG4pO1xuIiwgImltcG9ydCBGaWx0ZXJBbHRJY29uIGZyb20gJ0BtdWkvaWNvbnMtbWF0ZXJpYWwvRmlsdGVyQWx0JztcbmltcG9ydCB7IExvYWRpbmdCdXR0b24gfSBmcm9tICdAbXVpL2xhYic7XG5pbXBvcnQgdHlwZSB7IFN4UHJvcHMgfSBmcm9tICdAbXVpL21hdGVyaWFsJztcbmltcG9ydCB7IEJhZGdlIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5cbi8qKlxuICogUHJvcHMgZm9yIHRoZSBGaWx0ZXJCdXR0b24gY29tcG9uZW50LlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuaW50ZXJmYWNlIEZpbHRlckJ1dHRvblByb3BzIHtcbiAgLyoqXG4gICAqIEluZGljYXRlcyBpZiBhIGZpbHRlciBvcGVyYXRpb24gaXMgY3VycmVudGx5IGJlaW5nIHByb2Nlc3NlZC5cbiAgICogV2hlbiB0cnVlLCBzaG93cyBsb2FkaW5nIHNwaW5uZXIgYW5kIGRpc2FibGVzIHRoZSBidXR0b24uXG4gICAqL1xuICBpc1N1Ym1pdHRpbmc6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBDb250cm9scyBidXR0b24gdmlzaWJpbGl0eSBhbmQgZW5hYmxlZCBzdGF0ZS5cbiAgICogV2hlbiBmYWxzZSwgdGhlIGJ1dHRvbiBpcyBkaXNhYmxlZC5cbiAgICogQGRlZmF1bHRWYWx1ZSB0cnVlXG4gICAqL1xuICBzaG93PzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIEN1c3RvbSB0ZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi5cbiAgICogQGRlZmF1bHRWYWx1ZSBcIkZpbHRlclwiXG4gICAqIEBleGFtcGxlIFwiQXBwbHkgRmlsdGVyc1wiIG9yIFwiU2VhcmNoXCJcbiAgICovXG4gIHRpdGxlPzogc3RyaW5nO1xuICAvKipcbiAgICogQ3VzdG9tIGljb24gdG8gZGlzcGxheSBpbnN0ZWFkIG9mIHRoZSBkZWZhdWx0IGZpbHRlciBpY29uLlxuICAgKiBAZXhhbXBsZSA8U2VhcmNoSWNvbiAvPlxuICAgKi9cbiAgaWNvbj86IFJlYWN0LlJlYWN0Tm9kZTtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIE1VSSBzeCBwcm9wIGZvciBjdXN0b20gYnV0dG9uIHN0eWxpbmcuXG4gICAqIEBleGFtcGxlIHsgbXQ6IDIsIG1pbldpZHRoOiAxMjAgfVxuICAgKi9cbiAgc3g/OiBTeFByb3BzO1xuICAvKipcbiAgICogT3B0aW9uYWwgTVVJIHN4IHByb3AgZm9yIGN1c3RvbSBpY29uIHN0eWxpbmcuXG4gICAqIEBleGFtcGxlIHsgY29sb3I6ICdwcmltYXJ5Lm1haW4nLCBmb250U2l6ZTogMTggfVxuICAgKi9cbiAgaWNvblN4PzogU3hQcm9wcztcbn1cblxuLyoqXG4gKiBGaWx0ZXIgYnV0dG9uIGNvbXBvbmVudCB3aXRoIGxvYWRpbmcgc3RhdGVzIGFuZCBjdXN0b21pemFibGUgYXBwZWFyYW5jZS5cbiAqXG4gKiBUaGlzIGNvbXBvbmVudCBwcm92aWRlcyBhIHN0YW5kYXJkaXplZCBmaWx0ZXIvc3VibWl0IGJ1dHRvbiB3aXRoIGludGVncmF0ZWQgbG9hZGluZ1xuICogc3RhdGVzLCBpY29uIHN1cHBvcnQsIGFuZCBiYWRnZSBzdHlsaW5nLiBJdCdzIGRlc2lnbmVkIGZvciB1c2UgaW4gZmlsdGVyIGZvcm1zXG4gKiBhbmQgc2VhcmNoIGludGVyZmFjZXMgd2hlcmUgdXNlcnMgbmVlZCB0byBhcHBseSBmaWx0ZXJpbmcgY3JpdGVyaWEuXG4gKlxuICogQGV4YW1wbGVcbiAqIEJhc2ljIHVzYWdlOlxuICogYGBgdHN4XG4gKiA8RmlsdGVyQnV0dG9uXG4gKiAgIGlzU3VibWl0dGluZz17aXNMb2FkaW5nfVxuICogICBzaG93PXtoYXNGaWx0ZXJzfVxuICogLz5cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBDdXN0b20gdGl0bGUgYW5kIGljb246XG4gKiBgYGB0c3hcbiAqIDxGaWx0ZXJCdXR0b25cbiAqICAgaXNTdWJtaXR0aW5nPXtmb3JtLmZvcm1TdGF0ZS5pc1N1Ym1pdHRpbmd9XG4gKiAgIHRpdGxlPVwiQXBwbHkgU2VhcmNoXCJcbiAqICAgaWNvbj17PFNlYXJjaEljb24gLz59XG4gKiAgIHNob3c9e3RydWV9XG4gKiAvPlxuICogYGBgXG4gKlxuICogQGV4YW1wbGVcbiAqIFdpdGggY3VzdG9tIHN0eWxpbmc6XG4gKiBgYGB0c3hcbiAqIDxGaWx0ZXJCdXR0b25cbiAqICAgaXNTdWJtaXR0aW5nPXtpc1Byb2Nlc3Npbmd9XG4gKiAgIHRpdGxlPVwiRmlsdGVyIFJlc3VsdHNcIlxuICogICBzeD17eyBtaW5XaWR0aDogMTUwLCBtdDogMiB9fVxuICogICBpY29uU3g9e3sgZm9udFNpemU6IDIwIH19XG4gKiAvPlxuICogYGBgXG4gKlxuICogQHBhcmFtIHByb3BzIC0gQ29tcG9uZW50IHByb3BzIGZvciBmaWx0ZXIgYnV0dG9uIGNvbmZpZ3VyYXRpb25cbiAqIEByZXR1cm5zIE1VSSBMb2FkaW5nQnV0dG9uIGNvbXBvbmVudCBjb25maWd1cmVkIGFzIGEgZmlsdGVyIGJ1dHRvblxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IEZpbHRlckJ1dHRvbiA9ICh7XG4gIGlzU3VibWl0dGluZyxcbiAgc2hvdyxcbiAgdGl0bGUsXG4gIGljb24sXG4gIHN4LFxuICBpY29uU3gsXG59OiBGaWx0ZXJCdXR0b25Qcm9wcykgPT4ge1xuICByZXR1cm4gKFxuICAgIDxMb2FkaW5nQnV0dG9uXG4gICAgICB0eXBlPVwic3VibWl0XCJcbiAgICAgIHZhcmlhbnQ9XCJjb250YWluZWRcIlxuICAgICAgbG9hZGluZz17aXNTdWJtaXR0aW5nfVxuICAgICAgZGlzYWJsZWQ9eyFzaG93fVxuICAgICAgZGlzYWJsZVJpcHBsZVxuICAgICAgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgIHN4PXt7XG4gICAgICAgIGRpc3BsYXk6ICdmbGV4JyxcbiAgICAgICAgYWxpZ25JdGVtczogJ2NlbnRlcicsXG4gICAgICAgIC4uLnN4LFxuICAgICAgfX1cbiAgICAgIHN0YXJ0SWNvbj17XG4gICAgICAgIDxCYWRnZSBjb2xvcj1cImVycm9yXCIgdmFyaWFudD1cInN0YW5kYXJkXCI+XG4gICAgICAgICAge2ljb24gPyBpY29uIDogPEZpbHRlckFsdEljb24gd2lkdGg9XCIyMFwiIGhlaWdodD1cIjIwXCIgc3g9e2ljb25TeH0gLz59XG4gICAgICAgIDwvQmFkZ2U+XG4gICAgICB9XG4gICAgPlxuICAgICAge3RpdGxlPy50cmltKCkgPT09ICcnIHx8ICF0aXRsZSA/ICdGaWx0ZXInIDogdGl0bGV9XG4gICAgPC9Mb2FkaW5nQnV0dG9uPlxuICApO1xufTtcbiIsICJpbXBvcnQgQ2hpcCBmcm9tICdAbXVpL21hdGVyaWFsL0NoaXAnO1xuaW1wb3J0IHsgbWVtbyB9IGZyb20gJ3JlYWN0JztcblxuLy8gSW5kaXZpZHVhbCBjaGlwIGNvbXBvbmVudCB0byBwcmV2ZW50IHVubmVjZXNzYXJ5IHJlcmVuZGVycyBvZiBzaWJsaW5nIGNoaXBzXG5leHBvcnQgY29uc3QgRmlsdGVyQ2hpcCA9IG1lbW8oXG4gICh7XG4gICAgZmllbGRLZXksXG4gICAgZmlsdGVyLFxuICAgIG9uRGVsZXRlLFxuICB9OiB7XG4gICAgZmllbGRLZXk6IHN0cmluZztcbiAgICBmaWx0ZXI6IHsgTGFiZWw6IHN0cmluZzsgVmFsdWU6IHVua25vd24gfTtcbiAgICBvbkRlbGV0ZT86ICgpID0+IHZvaWQ7XG4gIH0pID0+IHtcbiAgICBjb25zdCBoYXNWYWx1ZSA9XG4gICAgICBmaWx0ZXIuVmFsdWUgIT09IG51bGwgJiZcbiAgICAgIGZpbHRlci5WYWx1ZSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICBmaWx0ZXIuVmFsdWUgIT09ICcnO1xuICAgIGNvbnN0IGxhYmVsID0gYCR7ZmllbGRLZXkucmVwbGFjZSgnUEsnLCAnJyl9OiAke2ZpbHRlci5MYWJlbH1gO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIDxDaGlwXG4gICAgICAgIGtleT17ZmllbGRLZXl9XG4gICAgICAgIGxhYmVsPXtsYWJlbH1cbiAgICAgICAgdmFyaWFudD17aGFzVmFsdWUgPyAnZmlsbGVkJyA6ICdvdXRsaW5lZCd9XG4gICAgICAgIHNpemU9XCJzbWFsbFwiXG4gICAgICAgIG9uRGVsZXRlPXtoYXNWYWx1ZSA/IG9uRGVsZXRlIDogdW5kZWZpbmVkfVxuICAgICAgLz5cbiAgICApO1xuICB9XG4pO1xuXG5GaWx0ZXJDaGlwLmRpc3BsYXlOYW1lID0gJ0ZpbHRlckNoaXAnO1xuIiwgImltcG9ydCB7IENhcmQsIENhcmRDb250ZW50LCBUeXBvZ3JhcGh5LCBCb3ggfSBmcm9tICdAbXVpL21hdGVyaWFsJztcbmltcG9ydCB7IG1lbW8sIHVzZU1lbW8gfSBmcm9tICdyZWFjdCc7XG5cbmltcG9ydCB7IEZpbHRlckNoaXAgfSBmcm9tICcuL0ZpbHRlckNoaXAnO1xuXG5pbnRlcmZhY2UgRmlsdGVyRGlzcGxheVByb3BzPFRGaWx0ZXJNb2RlbD4ge1xuICBmcmllbmRseUZpbHRlcjogUmVjb3JkPHN0cmluZywgeyBMYWJlbDogc3RyaW5nOyBWYWx1ZTogdW5rbm93biB9PjtcbiAgb25GcmllbmRseUZpbHRlckNoYW5nZT86IChmaWVsZEtleToga2V5b2YgVEZpbHRlck1vZGVsKSA9PiB2b2lkO1xufVxuXG5leHBvcnQgY29uc3QgUHJvZ3JhbXNGaWx0ZXJEaXNwbGF5ID0gbWVtbyhcbiAgPFRGaWx0ZXJNb2RlbCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+PihcbiAgICBwcm9wczogRmlsdGVyRGlzcGxheVByb3BzPFRGaWx0ZXJNb2RlbD5cbiAgKSA9PiB7XG4gICAgY29uc3QgeyBmcmllbmRseUZpbHRlciwgb25GcmllbmRseUZpbHRlckNoYW5nZSB9ID0gcHJvcHM7XG5cbiAgICAvLyBNZW1vaXplIGRlbGV0ZSBoYW5kbGVycyB0byBwcmV2ZW50IHJlY3JlYXRpb25cbiAgICBjb25zdCBkZWxldGVIYW5kbGVycyA9IHVzZU1lbW8oKCkgPT4ge1xuICAgICAgaWYgKCFvbkZyaWVuZGx5RmlsdGVyQ2hhbmdlKSByZXR1cm4ge307XG5cbiAgICAgIGNvbnN0IGhhbmRsZXJzOiBSZWNvcmQ8c3RyaW5nLCAoKSA9PiB2b2lkPiA9IHt9O1xuXG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhmcmllbmRseUZpbHRlcikpIHtcbiAgICAgICAgaGFuZGxlcnNba2V5XSA9ICgpID0+IG9uRnJpZW5kbHlGaWx0ZXJDaGFuZ2Uoa2V5IGFzIGtleW9mIFRGaWx0ZXJNb2RlbCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBoYW5kbGVycztcbiAgICB9LCBbb25GcmllbmRseUZpbHRlckNoYW5nZSwgZnJpZW5kbHlGaWx0ZXJdKTtcblxuICAgIC8vIE1lbW9pemUgY2hpcCBsaXN0IHRvIHByZXZlbnQgdW5uZWNlc3NhcnkgcmVjYWxjdWxhdGlvbnNcbiAgICBjb25zdCBjaGlwTGlzdCA9IHVzZU1lbW8oKCkgPT4ge1xuICAgICAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKGZyaWVuZGx5RmlsdGVyKS5tYXAoKFtrZXksIGZpbHRlcl0pID0+IChcbiAgICAgICAgPEZpbHRlckNoaXBcbiAgICAgICAgICBrZXk9e2tleX1cbiAgICAgICAgICBmaWVsZEtleT17a2V5fVxuICAgICAgICAgIGZpbHRlcj17ZmlsdGVyIGFzIHsgTGFiZWw6IHN0cmluZzsgVmFsdWU6IHVua25vd24gfX1cbiAgICAgICAgICBvbkRlbGV0ZT17ZGVsZXRlSGFuZGxlcnNba2V5XX1cbiAgICAgICAgLz5cbiAgICAgICkpO1xuICAgIH0sIFtmcmllbmRseUZpbHRlciwgZGVsZXRlSGFuZGxlcnNdKTtcblxuICAgIHJldHVybiAoXG4gICAgICA8Q2FyZCBzeD17eyBtYjogMiB9fT5cbiAgICAgICAgPENhcmRDb250ZW50PlxuICAgICAgICAgIDxUeXBvZ3JhcGh5IHZhcmlhbnQ9XCJoNlwiIGd1dHRlckJvdHRvbT5cbiAgICAgICAgICAgIEFjdGl2ZSBGaWx0ZXJzXG4gICAgICAgICAgPC9UeXBvZ3JhcGh5PlxuICAgICAgICAgIDxCb3ggZGlzcGxheT1cImZsZXhcIiBnYXA9ezF9IGZsZXhXcmFwPVwid3JhcFwiPlxuICAgICAgICAgICAge2NoaXBMaXN0fVxuICAgICAgICAgIDwvQm94PlxuICAgICAgICA8L0NhcmRDb250ZW50PlxuICAgICAgPC9DYXJkPlxuICAgICk7XG4gIH1cbik7XG5cblByb2dyYW1zRmlsdGVyRGlzcGxheS5kaXNwbGF5TmFtZSA9ICdGaWx0ZXJEaXNwbGF5JztcblxuZXhwb3J0IHR5cGUgeyBGaWx0ZXJEaXNwbGF5UHJvcHMgfTtcbiIsICJpbXBvcnQgTWFuYWdlU2VhcmNoSWNvbiBmcm9tICdAbXVpL2ljb25zLW1hdGVyaWFsL01hbmFnZVNlYXJjaCc7XG5pbXBvcnQgdHlwZSB7IFN4UHJvcHMgfSBmcm9tICdAbXVpL21hdGVyaWFsJztcbmltcG9ydCB7XG4gIEJveCxcbiAgQ2FyZCxcbiAgQ2FyZENvbnRlbnQsXG4gIENhcmRIZWFkZXIsXG4gIERpdmlkZXIsXG4gIEdyaWQsXG4gIFR5cG9ncmFwaHksXG4gIHVzZVRoZW1lLFxufSBmcm9tICdAbXVpL21hdGVyaWFsJztcbmltcG9ydCB0eXBlIHsgUHJvcHNXaXRoQ2hpbGRyZW4sIFJlYWN0Tm9kZSB9IGZyb20gJ3JlYWN0JztcblxuLyoqXG4gKiBQcm9wcyBmb3IgdGhlIEZpbHRlcldyYXBwZXIgY29tcG9uZW50LlxuICpcbiAqIEBwdWJsaWNcbiAqL1xudHlwZSBGaWx0ZXJXcmFwcGVyUHJvcHMgPSBQcm9wc1dpdGhDaGlsZHJlbjx7XG4gIC8qKlxuICAgKiBUaXRsZSB0ZXh0IGRpc3BsYXllZCBpbiB0aGUgY2FyZCBoZWFkZXIuXG4gICAqIEBkZWZhdWx0VmFsdWUgXCJGaWx0ZXJcIlxuICAgKiBAZXhhbXBsZSBcIlNlYXJjaCBDcml0ZXJpYVwiIG9yIFwiQWR2YW5jZWQgRmlsdGVyc1wiXG4gICAqL1xuICB0aXRsZT86IHN0cmluZztcbiAgLyoqXG4gICAqIE51bWJlciBvZiBhY3RpdmUgZmlsdGVycyB0byBkaXNwbGF5IGluIHRoZSBoZWFkZXIuXG4gICAqIE9ubHkgc2hvd24gd2hlbiBzaG93Q291bnQgaXMgdHJ1ZS5cbiAgICogQGV4YW1wbGUgMyBmb3IgXCJGaWx0ZXIgKDMpXCJcbiAgICovXG4gIGZpbHRlckNvdW50PzogbnVtYmVyO1xuICAvKipcbiAgICogT3B0aW9uYWwgTVVJIHN4IHByb3AgZm9yIGN1c3RvbSBjYXJkIHN0eWxpbmcuXG4gICAqIEBleGFtcGxlIHsgbXQ6IDIsIGJveFNoYWRvdzogMiB9XG4gICAqL1xuICBjYXJkU3g/OiBTeFByb3BzO1xuICAvKipcbiAgICogT3B0aW9uYWwgTVVJIHN4IHByb3AgZm9yIGN1c3RvbSB0aXRsZSB0ZXh0IHN0eWxpbmcuXG4gICAqIEBleGFtcGxlIHsgZm9udFNpemU6IDE4LCBmb250V2VpZ2h0OiAnYm9sZCcgfVxuICAgKi9cbiAgdGV4dFN4PzogU3hQcm9wcztcbiAgLyoqXG4gICAqIEN1c3RvbSBpY29uIHRvIGRpc3BsYXkgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBzZWFyY2ggaWNvbi5cbiAgICogQGV4YW1wbGUgPEZpbHRlckxpc3RJY29uIC8+XG4gICAqL1xuICBpY29uPzogUmVhY3ROb2RlO1xuICAvKipcbiAgICogT3B0aW9uYWwgTVVJIHN4IHByb3AgZm9yIGN1c3RvbSBpY29uIHN0eWxpbmcuXG4gICAqIEBleGFtcGxlIHsgY29sb3I6ICdzZWNvbmRhcnkubWFpbicsIGZvbnRTaXplOiAyNCB9XG4gICAqL1xuICBpY29uU3g/OiBTeFByb3BzO1xuICAvKipcbiAgICogV2hldGhlciB0byBkaXNwbGF5IHRoZSBmaWx0ZXIgY291bnQgaW4gdGhlIGhlYWRlci5cbiAgICogQGRlZmF1bHRWYWx1ZSBmYWxzZVxuICAgKi9cbiAgc2hvd0NvdW50PzogYm9vbGVhbjtcbn0+O1xuXG4vKipcbiAqIENhcmQtYmFzZWQgd3JhcHBlciBjb21wb25lbnQgZm9yIG9yZ2FuaXppbmcgZmlsdGVyIGNvbnRyb2xzIGFuZCBmb3JtIGVsZW1lbnRzLlxuICpcbiAqIFRoaXMgY29tcG9uZW50IHByb3ZpZGVzIGEgY29uc2lzdGVudCBsYXlvdXQgZm9yIGZpbHRlciBpbnRlcmZhY2VzIHdpdGggYSBoZWFkZXIsXG4gKiBvcHRpb25hbCBmaWx0ZXIgY291bnQgZGlzcGxheSwgYW5kIGEgZ3JpZC1iYXNlZCBjb250ZW50IGFyZWEuIEl0J3MgZGVzaWduZWQgdG9cbiAqIGNvbnRhaW4gZm9ybSBjb250cm9scyBhbmQgZmlsdGVyIGVsZW1lbnRzIGluIGEgdmlzdWFsbHkgb3JnYW5pemVkIG1hbm5lci5cbiAqXG4gKiBAZXhhbXBsZVxuICogQmFzaWMgdXNhZ2U6XG4gKiBgYGB0c3hcbiAqIDxGaWx0ZXJXcmFwcGVyPlxuICogICA8R3JpZCBpdGVtIHhzPXsxMn0gbWQ9ezZ9PlxuICogICAgIDxUZXh0RmllbGQgbGFiZWw9XCJTZWFyY2hcIiAvPlxuICogICA8L0dyaWQ+XG4gKiAgIDxHcmlkIGl0ZW0geHM9ezEyfSBtZD17Nn0+XG4gKiAgICAgPFNlbGVjdCBsYWJlbD1cIkNhdGVnb3J5XCIgLz5cbiAqICAgPC9HcmlkPlxuICogPC9GaWx0ZXJXcmFwcGVyPlxuICogYGBgXG4gKlxuICogQGV4YW1wbGVcbiAqIFdpdGggY3VzdG9tIHRpdGxlIGFuZCBjb3VudDpcbiAqIGBgYHRzeFxuICogPEZpbHRlcldyYXBwZXJcbiAqICAgdGl0bGU9XCJBZHZhbmNlZCBTZWFyY2hcIlxuICogICBmaWx0ZXJDb3VudD17YWN0aXZlRmlsdGVycy5sZW5ndGh9XG4gKiAgIHNob3dDb3VudD17dHJ1ZX1cbiAqID5cbiAqICAge2ZpbHRlckNvbnRyb2xzfVxuICogPC9GaWx0ZXJXcmFwcGVyPlxuICogYGBgXG4gKlxuICogQGV4YW1wbGVcbiAqIFdpdGggY3VzdG9tIHN0eWxpbmc6XG4gKiBgYGB0c3hcbiAqIDxGaWx0ZXJXcmFwcGVyXG4gKiAgIHRpdGxlPVwiUHJvZHVjdCBGaWx0ZXJzXCJcbiAqICAgaWNvbj17PEZpbHRlckxpc3RJY29uIC8+fVxuICogICBjYXJkU3g9e3sgbXQ6IDMsIGJvcmRlclJhZGl1czogMiB9fVxuICogICB0ZXh0U3g9e3sgY29sb3I6ICdzZWNvbmRhcnkubWFpbicgfX1cbiAqID5cbiAqICAge2NoaWxkcmVufVxuICogPC9GaWx0ZXJXcmFwcGVyPlxuICogYGBgXG4gKlxuICogQHBhcmFtIHByb3BzIC0gQ29tcG9uZW50IHByb3BzIGluY2x1ZGluZyBjaGlsZHJlbiBhbmQgc3R5bGluZyBvcHRpb25zXG4gKiBAcmV0dXJucyBNVUkgQ2FyZCBjb21wb25lbnQgd2l0aCBzdHJ1Y3R1cmVkIGZpbHRlciBsYXlvdXRcbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBGaWx0ZXJXcmFwcGVyID0gKHtcbiAgY2hpbGRyZW4sXG4gIHRpdGxlLFxuICBmaWx0ZXJDb3VudCxcbiAgY2FyZFN4LFxuICB0ZXh0U3gsXG4gIGljb24sXG4gIGljb25TeCxcbiAgc2hvd0NvdW50LFxufTogRmlsdGVyV3JhcHBlclByb3BzKSA9PiB7XG4gIGNvbnN0IHRoZW1lID0gdXNlVGhlbWUoKTtcblxuICByZXR1cm4gKFxuICAgIDxDYXJkXG4gICAgICBzeD17e1xuICAgICAgICBwb3NpdGlvbjogJ3JlbGF0aXZlJyxcbiAgICAgICAgYm9yZGVyUmFkaXVzOiAnMHB4JyxcbiAgICAgICAgbWI6IDIsXG4gICAgICAgIC4uLmNhcmRTeCxcbiAgICAgIH19XG4gICAgPlxuICAgICAgPENhcmRIZWFkZXJcbiAgICAgICAgc3g9e3tcbiAgICAgICAgICBkaXNwbGF5OiAnZmxleCcsXG4gICAgICAgICAgZmxleFdyYXA6ICd3cmFwJyxcbiAgICAgICAgICBwOiAnMXJlbScsXG4gICAgICAgICAgJy5NdWlDYXJkSGVhZGVyLWFjdGlvbic6IHtcbiAgICAgICAgICAgIG1hcmdpbjogMCxcbiAgICAgICAgICAgIGFsaWduU2VsZjogJ2NlbnRlcicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBhbGlnbkl0ZW1zOiAnY2VudGVyJyxcbiAgICAgICAgfX1cbiAgICAgICAgdGl0bGU9e1xuICAgICAgICAgIDxCb3ggc3g9e3sgZGlzcGxheTogJ2ZsZXgnLCBhbGlnbkl0ZW1zOiAnY2VudGVyJywgZ2FwOiAwLjUgfX0+XG4gICAgICAgICAgICB7aWNvbiA/IChcbiAgICAgICAgICAgICAgaWNvblxuICAgICAgICAgICAgKSA6IChcbiAgICAgICAgICAgICAgPE1hbmFnZVNlYXJjaEljb25cbiAgICAgICAgICAgICAgICBzeD17e1xuICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAnMi41cmVtJyxcbiAgICAgICAgICAgICAgICAgIGNvbG9yOiB0aGVtZS5wYWxldHRlLnByaW1hcnkubWFpbixcbiAgICAgICAgICAgICAgICAgIC4uLmljb25TeCxcbiAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgKX1cbiAgICAgICAgICAgIDxUeXBvZ3JhcGh5XG4gICAgICAgICAgICAgIHZhcmlhbnQ9XCJoNVwiXG4gICAgICAgICAgICAgIHN4PXt7XG4gICAgICAgICAgICAgICAgZm9udFdlaWdodDogJ2JvbGQnLFxuICAgICAgICAgICAgICAgIGNvbG9yOiB0aGVtZS5wYWxldHRlLnByaW1hcnkubWFpbixcbiAgICAgICAgICAgICAgICAuLi50ZXh0U3gsXG4gICAgICAgICAgICAgIH19XG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIHt0aXRsZSA/IHRpdGxlIDogJ0ZpbHRlcid9eycgJ31cbiAgICAgICAgICAgICAge3Nob3dDb3VudCA/IGAoJHtmaWx0ZXJDb3VudCA/IGZpbHRlckNvdW50IDogMH0pYCA6IDw+PC8+fVxuICAgICAgICAgICAgPC9UeXBvZ3JhcGh5PlxuICAgICAgICAgIDwvQm94PlxuICAgICAgICB9XG4gICAgICA+PC9DYXJkSGVhZGVyPlxuICAgICAgPERpdmlkZXIgLz5cbiAgICAgIDxDYXJkQ29udGVudCBzeD17eyBweTogMiB9fT5cbiAgICAgICAgPEdyaWQgY29udGFpbmVyIHNwYWNpbmc9ezJ9PlxuICAgICAgICAgIHtjaGlsZHJlbn1cbiAgICAgICAgPC9HcmlkPlxuICAgICAgPC9DYXJkQ29udGVudD5cbiAgICA8L0NhcmQ+XG4gICk7XG59O1xuIiwgIi8vIGNvcmUvY29tcG9uZW50cy9Gb290ZXIvaW5kZXgudHN4XG5pbXBvcnQgeyBCb3gsIFR5cG9ncmFwaHkgfSBmcm9tICdAbXVpL21hdGVyaWFsJztcbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBjb25zdCBGb290ZXI6IFJlYWN0LkZDID0gKCkgPT4ge1xuICBjb25zdCBjdXJyZW50WWVhciA9IG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKTtcblxuICByZXR1cm4gKFxuICAgIDxCb3hcbiAgICAgIGNvbXBvbmVudD1cImZvb3RlclwiXG4gICAgICBzeD17e1xuICAgICAgICBweTogMixcbiAgICAgICAgcHg6IDQsXG4gICAgICAgIG10OiAnYXV0bycsXG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogdGhlbWUgPT5cbiAgICAgICAgICB0aGVtZS5wYWxldHRlLm1vZGUgPT09ICdsaWdodCdcbiAgICAgICAgICAgID8gdGhlbWUucGFsZXR0ZS5ncmV5WzIwMF1cbiAgICAgICAgICAgIDogdGhlbWUucGFsZXR0ZS5ncmV5WzgwMF0sXG4gICAgICB9fVxuICAgID5cbiAgICAgIDxUeXBvZ3JhcGh5IHZhcmlhbnQ9XCJib2R5MlwiIGNvbG9yPVwidGV4dC5zZWNvbmRhcnlcIiBhbGlnbj1cImNlbnRlclwiPlxuICAgICAgICB7YFx1MDBBOSBDb3B5cmlnaHQgJHtjdXJyZW50WWVhcn0gR04uIEFsbCByaWdodHMgcmVzZXJ2ZWQgYnkgUGFydWwgVW5pdmVyc2l0eS5gfVxuICAgICAgPC9UeXBvZ3JhcGh5PlxuICAgIDwvQm94PlxuICApO1xufTtcbiIsICJpbXBvcnQgdHlwZSB7IFN4UHJvcHMgfSBmcm9tICdAbXVpL21hdGVyaWFsJztcbmltcG9ydCB7IEdyaWQsIFRvb2x0aXAsIFR5cG9ncmFwaHkgfSBmcm9tICdAbXVpL21hdGVyaWFsJztcblxuLyoqXG4gKiBQcm9wcyBmb3IgdGhlIExhYmVsVGV4dCBjb21wb25lbnQuXG4gKlxuICogQHB1YmxpY1xuICovXG5pbnRlcmZhY2UgTGFiZWxUZXh0UHJvcHMge1xuICAvKipcbiAgICogTGFiZWwgdGV4dCB0byBkaXNwbGF5IG9uIHRoZSBsZWZ0IHNpZGUuXG4gICAqIEBleGFtcGxlIFwiTmFtZVwiIG9yIFwiRW1haWwgQWRkcmVzc1wiXG4gICAqL1xuICBsYWJlbDogc3RyaW5nO1xuICAvKipcbiAgICogVmFsdWUgY29udGVudCB0byBkaXNwbGF5IG9uIHRoZSByaWdodCBzaWRlLlxuICAgKiBDYW4gYmUgdGV4dCwgbnVtYmVycywgb3IgUmVhY3QgZWxlbWVudHMuXG4gICAqIEBleGFtcGxlIFwiSm9obiBEb2VcIiBvciA8TGluaz5WaWV3IERldGFpbHM8L0xpbms+XG4gICAqL1xuICB2YWx1ZTogUmVhY3QuUmVhY3ROb2RlO1xuICAvKipcbiAgICogQ3VzdG9tIGdyaWQgc2l6aW5nIGZvciBsYWJlbCBhbmQgdmFsdWUgc2VjdGlvbnMuXG4gICAqIEBkZWZhdWx0VmFsdWUgeyBsYWJlbFNpemU6IHsgeHM6IDYsIHNtOiA2LCBtZDogNiB9LCB2YWx1ZVNpemU6IHsgeHM6IDEyLCBzbTogNiwgbWQ6IDYgfSB9XG4gICAqL1xuICBncmlkU2l6ZT86IHtcbiAgICAvKiogR3JpZCBzaXplIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBsYWJlbCBzZWN0aW9uICovXG4gICAgbGFiZWxTaXplOiB7IHhzOiBudW1iZXI7IHNtOiBudW1iZXI7IG1kOiBudW1iZXIgfTtcbiAgICAvKiogR3JpZCBzaXplIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSB2YWx1ZSBzZWN0aW9uICovXG4gICAgdmFsdWVTaXplOiB7IHhzOiBudW1iZXI7IHNtOiBudW1iZXI7IG1kOiBudW1iZXIgfTtcbiAgfTtcbiAgLyoqXG4gICAqIEdyaWQgc2l6ZSBjb25maWd1cmF0aW9uIGZvciB0aGUgZW50aXJlIGNvbnRhaW5lci5cbiAgICogQGRlZmF1bHRWYWx1ZSB7IHhzOiAxMiwgc206IDYsIG1kOiA2IH1cbiAgICovXG4gIGNvbnRhaW5lclNpemU/OiB7IHhzOiBudW1iZXI7IHNtOiBudW1iZXI7IG1kOiBudW1iZXIgfTtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIE1VSSBzeCBwcm9wIGZvciBjdXN0b20gbGFiZWwgc3R5bGluZy5cbiAgICogQGV4YW1wbGUgeyBmb250V2VpZ2h0OiAnYm9sZCcsIGNvbG9yOiAncHJpbWFyeS5tYWluJyB9XG4gICAqL1xuICBsYWJlbFN4PzogU3hQcm9wcztcbiAgLyoqXG4gICAqIE9wdGlvbmFsIE1VSSBzeCBwcm9wIGZvciBjdXN0b20gdmFsdWUgc3R5bGluZy5cbiAgICogQGV4YW1wbGUgeyBjb2xvcjogJ3RleHQuc2Vjb25kYXJ5JywgZm9udFN0eWxlOiAnaXRhbGljJyB9XG4gICAqL1xuICB2YWx1ZVN4PzogU3hQcm9wcztcbn1cblxuLyoqXG4gKiBSZXNwb25zaXZlIGxhYmVsLXZhbHVlIGRpc3BsYXkgY29tcG9uZW50IHdpdGggaG92ZXIgZWZmZWN0cyBhbmQgdGV4dCB0cnVuY2F0aW9uLlxuICpcbiAqIFRoaXMgY29tcG9uZW50IGNyZWF0ZXMgYSBjb25zaXN0ZW50IGxhYmVsLXZhbHVlIHBhaXIgbGF5b3V0IHRoYXQgYWRhcHRzIHRvIGRpZmZlcmVudFxuICogc2NyZWVuIHNpemVzLiBJdCBpbmNsdWRlcyBob3ZlciBlZmZlY3RzLCB0ZXh0IHRydW5jYXRpb24gd2l0aCB0b29sdGlwcywgYW5kXG4gKiBjdXN0b21pemFibGUgZ3JpZCBzaXppbmcgZm9yIGZsZXhpYmxlIGxheW91dHMuXG4gKlxuICogQGV4YW1wbGVcbiAqIEJhc2ljIHVzYWdlOlxuICogYGBgdHN4XG4gKiA8TGFiZWxUZXh0XG4gKiAgIGxhYmVsPVwiRnVsbCBOYW1lXCJcbiAqICAgdmFsdWU9XCJKb2huIERvZVwiXG4gKiAvPlxuICogYGBgXG4gKlxuICogQGV4YW1wbGVcbiAqIFdpdGggUmVhY3QgZWxlbWVudCB2YWx1ZTpcbiAqIGBgYHRzeFxuICogPExhYmVsVGV4dFxuICogICBsYWJlbD1cIlByb2ZpbGVcIlxuICogICB2YWx1ZT17PExpbmsgaHJlZj1cIi9wcm9maWxlXCI+VmlldyBQcm9maWxlPC9MaW5rPn1cbiAqIC8+XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogQ3VzdG9tIGdyaWQgc2l6aW5nOlxuICogYGBgdHN4XG4gKiA8TGFiZWxUZXh0XG4gKiAgIGxhYmVsPVwiRGVzY3JpcHRpb25cIlxuICogICB2YWx1ZT17bG9uZ0Rlc2NyaXB0aW9ufVxuICogICBncmlkU2l6ZT17e1xuICogICAgIGxhYmVsU2l6ZTogeyB4czogMTIsIHNtOiAzLCBtZDogMiB9LFxuICogICAgIHZhbHVlU2l6ZTogeyB4czogMTIsIHNtOiA5LCBtZDogMTAgfVxuICogICB9fVxuICogICBjb250YWluZXJTaXplPXt7IHhzOiAxMiwgc206IDEyLCBtZDogMTIgfX1cbiAqIC8+XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0gcHJvcHMgLSBDb21wb25lbnQgcHJvcHMgZm9yIGxhYmVsLXZhbHVlIGNvbmZpZ3VyYXRpb25cbiAqIEByZXR1cm5zIEdyaWQtYmFzZWQgbGF5b3V0IHdpdGggbGFiZWwgYW5kIHZhbHVlIHNlY3Rpb25zXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgTGFiZWxUZXh0ID0gKHtcbiAgbGFiZWwsXG4gIHZhbHVlLFxuICBncmlkU2l6ZSxcbiAgY29udGFpbmVyU2l6ZSxcbiAgbGFiZWxTeCxcbiAgdmFsdWVTeCxcbn06IExhYmVsVGV4dFByb3BzKSA9PiB7XG4gIGNvbnN0IGRlZmF1bHRHcmlkU2l6ZSA9IHtcbiAgICBsYWJlbFNpemU6IHsgeHM6IDYsIHNtOiA2LCBtZDogNiB9LFxuICAgIHZhbHVlU2l6ZTogeyB4czogMTIsIHNtOiA2LCBtZDogNiB9LFxuICB9O1xuICBjb25zdCBkZWZhdWx0Q29udGFpbmVyU2l6ZSA9IHsgeHM6IDEyLCBzbTogNiwgbWQ6IDYgfTtcbiAgY29uc3Qgc2l6ZSA9IGdyaWRTaXplIHx8IGRlZmF1bHRHcmlkU2l6ZTtcbiAgY29uc3QgY29udGFpbmVyID0gY29udGFpbmVyU2l6ZSB8fCBkZWZhdWx0Q29udGFpbmVyU2l6ZTtcblxuICByZXR1cm4gKFxuICAgIDxHcmlkXG4gICAgICBzaXplPXtjb250YWluZXJ9XG4gICAgICBzeD17e1xuICAgICAgICBkaXNwbGF5OiAnZmxleCcsXG4gICAgICAgIGZsZXhEaXJlY3Rpb246IHsgeHM6ICdjb2x1bW4nLCBzbTogJ3JvdycsIG1kOiAncm93JyB9LFxuICAgICAgICAnJjpob3Zlcic6IHsgYmdjb2xvcjogJyNlZmVmZWYnLCBvdmVyZmxvdzogJ2hpZGRlbicgfSxcbiAgICAgIH19XG4gICAgPlxuICAgICAgPEdyaWRcbiAgICAgICAgc2l6ZT17c2l6ZS5sYWJlbFNpemV9XG4gICAgICAgIHN4PXt7XG4gICAgICAgICAgcGFkZGluZzogJzVweCcsXG4gICAgICAgICAgZm9udFNpemU6ICcxNHB4JyxcbiAgICAgICAgICB0ZXh0QWxpZ246IHsgeHM6ICdsZWZ0Jywgc206ICdyaWdodCcsIG1kOiAncmlnaHQnIH0sXG4gICAgICAgICAgLi4ubGFiZWxTeCxcbiAgICAgICAgfX1cbiAgICAgID5cbiAgICAgICAge2xhYmVsfSA6XG4gICAgICA8L0dyaWQ+XG4gICAgICA8R3JpZFxuICAgICAgICBzaXplPXtzaXplLnZhbHVlU2l6ZX1cbiAgICAgICAgc3g9e3sgcGFkZGluZzogJzVweCcsIGRpc3BsYXk6ICdmbGV4JywgZmxleFdyYXA6ICd3cmFwJyB9fVxuICAgICAgPlxuICAgICAgICA8VG9vbHRpcCB0aXRsZT17dmFsdWV9IGFycm93PlxuICAgICAgICAgIDxUeXBvZ3JhcGh5XG4gICAgICAgICAgICBzeD17e1xuICAgICAgICAgICAgICBmb250U2l6ZTogJzE0cHgnLFxuICAgICAgICAgICAgICB3b3JkQnJlYWs6ICdicmVhay13b3JkJyxcbiAgICAgICAgICAgICAgb3ZlcmZsb3c6ICdoaWRkZW4nLFxuICAgICAgICAgICAgICBkaXNwbGF5OiAnLXdlYmtpdC1ib3gnLFxuICAgICAgICAgICAgICB0ZXh0T3ZlcmZsb3c6ICdlbGxpcHNpcycsXG4gICAgICAgICAgICAgIFdlYmtpdExpbmVDbGFtcDogMixcbiAgICAgICAgICAgICAgV2Via2l0Qm94T3JpZW50OiAndmVydGljYWwnLFxuICAgICAgICAgICAgICAuLi52YWx1ZVN4LFxuICAgICAgICAgICAgICBjb2xvcjogJyMwNzhkZWUnLFxuICAgICAgICAgICAgfX1cbiAgICAgICAgICA+XG4gICAgICAgICAgICB7dmFsdWUgPyB2YWx1ZSA6ICctJ31cbiAgICAgICAgICA8L1R5cG9ncmFwaHk+XG4gICAgICAgIDwvVG9vbHRpcD5cbiAgICAgIDwvR3JpZD5cbiAgICA8L0dyaWQ+XG4gICk7XG59O1xuIiwgImltcG9ydCB0eXBlIHsgUHJvcHNXaXRoQ2hpbGRyZW4gfSBmcm9tICdyZWFjdCc7XG5cbmludGVyZmFjZSBSZW5kZXJJZlByb3BzIHtcbiAgc2hvdzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNvbnN0IFJlbmRlcklmID0gKHtcbiAgc2hvdyxcbiAgY2hpbGRyZW4sXG59OiBQcm9wc1dpdGhDaGlsZHJlbjxSZW5kZXJJZlByb3BzPikgPT4ge1xuICByZXR1cm4gc2hvdyA/IDw+e2NoaWxkcmVufTwvPiA6IG51bGw7XG59O1xuIiwgImltcG9ydCB0eXBlIHsgU3hQcm9wcywgVGhlbWUgfSBmcm9tICdAbXVpL21hdGVyaWFsJztcbmltcG9ydCB7IEJveCwgRGl2aWRlciwgR3JpZCwgU3RhY2ssIFR5cG9ncmFwaHkgfSBmcm9tICdAbXVpL21hdGVyaWFsJztcbmltcG9ydCB0eXBlIHsgUHJvcHNXaXRoQ2hpbGRyZW4sIFJlYWN0Tm9kZSB9IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7IG1lbW8sIHVzZU1lbW8gfSBmcm9tICdyZWFjdCc7XG5cbi8vIFNlY3Rpb24gYm94IGNvbmZpZ3VyYXRpb25cbmV4cG9ydCBpbnRlcmZhY2UgU2VjdGlvbkJveFByb3BzIGV4dGVuZHMgUHJvcHNXaXRoQ2hpbGRyZW4ge1xuICB0aXRsZTogc3RyaW5nO1xuICBzcGFjaW5nPzogbnVtYmVyO1xuICBjb250YWluZXJTeD86IFN4UHJvcHM8VGhlbWU+O1xuICB0aXRsZVN4PzogU3hQcm9wczxUaGVtZT47XG4gIHZhcmlhbnQ/OiAnZGVmYXVsdCcgfCAnZm9ybScgfCAnaW5mbycgfCAnd2FybmluZycgfCAnZXJyb3InO1xuICBpY29uPzogUmVhY3ROb2RlO1xuICBhY3Rpb25zPzogUmVhY3ROb2RlO1xuICBjb2xsYXBzaWJsZT86IGJvb2xlYW47XG4gIGRlZmF1bHRFeHBhbmRlZD86IGJvb2xlYW47XG59XG5cbi8vIFRoZW1lIGNvbmZpZ3VyYXRpb24gZm9yIHNlY3Rpb24gdmFyaWFudHNcbmNvbnN0IGdldFNlY3Rpb25UaGVtZSA9ICh2YXJpYW50OiBTZWN0aW9uQm94UHJvcHNbJ3ZhcmlhbnQnXSA9ICdkZWZhdWx0JykgPT4ge1xuICBjb25zdCB0aGVtZXMgPSB7XG4gICAgZGVmYXVsdDoge1xuICAgICAgYmdjb2xvcjogJyNmYWViZDcnLFxuICAgICAgY29sb3I6ICcjOTI1ZDIxJyxcbiAgICB9LFxuICAgIGZvcm06IHtcbiAgICAgIGJnY29sb3I6ICcjY2RjZWQxJyxcbiAgICAgIGNvbG9yOiAnYmxhY2snLFxuICAgIH0sXG4gICAgaW5mbzoge1xuICAgICAgYmdjb2xvcjogJyNlM2YyZmQnLFxuICAgICAgY29sb3I6ICcjMTk3NmQyJyxcbiAgICB9LFxuICAgIHdhcm5pbmc6IHtcbiAgICAgIGJnY29sb3I6ICcjZmZmM2UwJyxcbiAgICAgIGNvbG9yOiAnI2Y1N2MwMCcsXG4gICAgfSxcbiAgICBlcnJvcjoge1xuICAgICAgYmdjb2xvcjogJyNmZmViZWUnLFxuICAgICAgY29sb3I6ICcjZDMyZjJmJyxcbiAgICB9LFxuICB9O1xuXG4gIHJldHVybiB0aGVtZXNbdmFyaWFudF07XG59O1xuXG4vLyBNZW1vaXplZCBTZWN0aW9uQm94IGNvbXBvbmVudCBmb3IgcGVyZm9ybWFuY2VcbmV4cG9ydCBjb25zdCBTZWN0aW9uQm94ID0gbWVtbzxTZWN0aW9uQm94UHJvcHM+KFxuICAoe1xuICAgIHRpdGxlLFxuICAgIGNoaWxkcmVuLFxuICAgIHNwYWNpbmcgPSAwLFxuICAgIGNvbnRhaW5lclN4LFxuICAgIHRpdGxlU3gsXG4gICAgdmFyaWFudCA9ICdkZWZhdWx0JyxcbiAgICBpY29uLFxuICAgIGFjdGlvbnMsXG4gIH0pID0+IHtcbiAgICBjb25zdCB0aGVtZUNvbG9ycyA9IHVzZU1lbW8oKCkgPT4gZ2V0U2VjdGlvblRoZW1lKHZhcmlhbnQpLCBbdmFyaWFudF0pO1xuXG4gICAgY29uc3QgaGVhZGVyU3ggPSB1c2VNZW1vKFxuICAgICAgKCkgPT4gKHtcbiAgICAgICAgcHg6IDEuNSxcbiAgICAgICAgcHk6IDAuMSxcbiAgICAgICAgd2lkdGg6ICdmaXQtY29udGVudCcsXG4gICAgICAgIC4uLnRoZW1lQ29sb3JzLFxuICAgICAgICAuLi50aXRsZVN4LFxuICAgICAgfSksXG4gICAgICBbdGhlbWVDb2xvcnMsIHRpdGxlU3hdXG4gICAgKTtcblxuICAgIGNvbnN0IGNvbnRlbnRTeCA9IHVzZU1lbW8oXG4gICAgICAoKSA9PiAoe1xuICAgICAgICBwYWRkaW5nOiAnMTZweCcsXG4gICAgICAgIC4uLmNvbnRhaW5lclN4LFxuICAgICAgfSksXG4gICAgICBbY29udGFpbmVyU3hdXG4gICAgKTtcblxuICAgIHJldHVybiAoXG4gICAgICA8PlxuICAgICAgICA8Qm94IHN4PXt7IGRpc3BsYXk6ICdmbGV4JywgZmxleERpcmVjdGlvbjogJ2NvbHVtbicsIHdpZHRoOiAnMTAwJScgfX0+XG4gICAgICAgICAgPFN0YWNrXG4gICAgICAgICAgICBkaXJlY3Rpb249XCJyb3dcIlxuICAgICAgICAgICAganVzdGlmeUNvbnRlbnQ9XCJzcGFjZS1iZXR3ZWVuXCJcbiAgICAgICAgICAgIGFsaWduSXRlbXM9XCJjZW50ZXJcIlxuICAgICAgICAgICAgc3g9e2hlYWRlclN4fVxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxTdGFjayBkaXJlY3Rpb249XCJyb3dcIiBhbGlnbkl0ZW1zPVwiY2VudGVyXCIgc3BhY2luZz17MX0+XG4gICAgICAgICAgICAgIHtpY29ufVxuICAgICAgICAgICAgICA8VHlwb2dyYXBoeSBzeD17eyBmb250U2l6ZTogJzE1cHgnLCBmb250V2VpZ2h0OiA0MDAgfX0+XG4gICAgICAgICAgICAgICAge3RpdGxlfVxuICAgICAgICAgICAgICA8L1R5cG9ncmFwaHk+XG4gICAgICAgICAgICA8L1N0YWNrPlxuICAgICAgICAgICAge2FjdGlvbnN9XG4gICAgICAgICAgPC9TdGFjaz5cbiAgICAgICAgICA8RGl2aWRlciAvPlxuICAgICAgICA8L0JveD5cbiAgICAgICAgPEdyaWQgY29udGFpbmVyIHNwYWNpbmc9e3NwYWNpbmd9IHN4PXtjb250ZW50U3h9PlxuICAgICAgICAgIHtjaGlsZHJlbn1cbiAgICAgICAgPC9HcmlkPlxuICAgICAgPC8+XG4gICAgKTtcbiAgfVxuKTtcbiIsICJpbXBvcnQgeyBUYWJDb250ZXh0IH0gZnJvbSAnQG11aS9sYWInO1xuaW1wb3J0IHR5cGUgeyBTeFByb3BzIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgeyBCb3gsIFRhYiwgVGFicyB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xuaW1wb3J0IHR5cGUgeyBQcm9wc1dpdGhDaGlsZHJlbiB9IGZyb20gJ3JlYWN0JztcbmltcG9ydCBSZWFjdCwgeyB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IGludGVyZmFjZSBUYWJJdGVtIHtcbiAgbGFiZWw6IHN0cmluZztcbiAgdmFsdWU6IG51bWJlcjtcbiAgcGVybWlzc2lvbj86IGJvb2xlYW47XG59XG5cbmludGVyZmFjZSBDdXN0b21UYWJzUHJvcHMge1xuICB0YWJzOiBUYWJJdGVtW107XG4gIGRlZmF1bHRWYWx1ZT86IG51bWJlcjtcbiAgb25UYWJDaGFuZ2U/OiAobmV3VmFsdWU6IG51bWJlcikgPT4gdm9pZDtcbiAgdGFiU3g/OiBTeFByb3BzO1xuICB0YWJzU3g/OiBTeFByb3BzO1xufVxuXG5leHBvcnQgY29uc3QgU2ltcGxlVGFicyA9ICh7XG4gIHRhYnMsXG4gIGRlZmF1bHRWYWx1ZSA9IDEsXG4gIG9uVGFiQ2hhbmdlLFxuICBjaGlsZHJlbixcbiAgdGFiU3gsXG4gIHRhYnNTeCxcbn06IEN1c3RvbVRhYnNQcm9wcyAmIFByb3BzV2l0aENoaWxkcmVuKSA9PiB7XG4gIGNvbnN0IFt2YWx1ZSwgc2V0VmFsdWVdID0gdXNlU3RhdGU8bnVtYmVyPihkZWZhdWx0VmFsdWUpO1xuXG4gIGNvbnN0IGhhbmRsZUNoYW5nZSA9IChldmVudDogUmVhY3QuU3ludGhldGljRXZlbnQsIG5ld1ZhbHVlOiBudW1iZXIpID0+IHtcbiAgICBzZXRWYWx1ZShuZXdWYWx1ZSk7XG4gICAgaWYgKG9uVGFiQ2hhbmdlKSBvblRhYkNoYW5nZShuZXdWYWx1ZSk7XG4gIH07XG5cbiAgcmV0dXJuIChcbiAgICA8VGFiQ29udGV4dCB2YWx1ZT17dmFsdWV9PlxuICAgICAgPEJveCBzeD17eyBib3JkZXJCb3R0b206IDEsIGJvcmRlckNvbG9yOiAnZGl2aWRlcicsIHdpZHRoOiAnMTAwJScgfX0+XG4gICAgICAgIDxUYWJzXG4gICAgICAgICAgdmFsdWU9e3ZhbHVlfVxuICAgICAgICAgIG9uQ2hhbmdlPXtoYW5kbGVDaGFuZ2V9XG4gICAgICAgICAgc3g9e3sgcHg6IDIsIHB5OiAwLCAuLi50YWJzU3ggfX1cbiAgICAgICAgPlxuICAgICAgICAgIHt0YWJzLm1hcCh0YWIgPT4gKFxuICAgICAgICAgICAgPFRhYlxuICAgICAgICAgICAgICBrZXk9e3RhYi52YWx1ZX1cbiAgICAgICAgICAgICAgbGFiZWw9e3RhYi5sYWJlbH1cbiAgICAgICAgICAgICAgdmFsdWU9e3RhYi52YWx1ZX1cbiAgICAgICAgICAgICAgZGlzYWJsZWQ9e3RhYi5wZXJtaXNzaW9uID09PSBmYWxzZX1cbiAgICAgICAgICAgICAgc3g9e3sgZm9udFNpemU6ICcxcmVtJywgLi4udGFiU3ggfX1cbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgKSl9XG4gICAgICAgIDwvVGFicz5cbiAgICAgIDwvQm94PlxuXG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC9UYWJDb250ZXh0PlxuICApO1xufTtcbiIsICJpbXBvcnQgdHlwZSB7IExvYWRpbmdCdXR0b25Qcm9wcyB9IGZyb20gJ0BtdWkvbGFiJztcbmltcG9ydCB7IExvYWRpbmdCdXR0b24gfSBmcm9tICdAbXVpL2xhYic7XG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuXG50eXBlIFN1Ym1pdEJ1dHRvblByb3BzID0gT21pdDxcbiAgTG9hZGluZ0J1dHRvblByb3BzLFxuICAnY2hpbGRyZW4nIHwgJ3ZhcmlhbnQnIHwgJ2NvbG9yJyB8ICd0eXBlJ1xuPjtcblxuZXhwb3J0IGNvbnN0IFN1Ym1pdEJ1dHRvbjogUmVhY3QuRkM8U3VibWl0QnV0dG9uUHJvcHM+ID0gKHtcbiAgbG9hZGluZyA9IGZhbHNlLFxuICAuLi5yZXN0XG59KSA9PiAoXG4gIDxMb2FkaW5nQnV0dG9uXG4gICAgbG9hZGluZz17bG9hZGluZ31cbiAgICB2YXJpYW50PVwiY29udGFpbmVkXCJcbiAgICBjb2xvcj1cInByaW1hcnlcIlxuICAgIHR5cGU9XCJzdWJtaXRcIlxuICAgIHsuLi5yZXN0fVxuICAgIHN4PXt7IGZvbnRXZWlnaHQ6IDQwMCB9fVxuICA+XG4gICAgU3VibWl0XG4gIDwvTG9hZGluZ0J1dHRvbj5cbik7XG4iLCAiaW1wb3J0IHR5cGUgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IHsgZm9yd2FyZFJlZiB9IGZyb20gJ3JlYWN0JztcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gU2hhcmVkIHR5cGVzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5leHBvcnQgaW50ZXJmYWNlIERhdGFNb2RhbEJ1dHRvbnMge1xuICBvblN1Ym1pdD86ICgpID0+IHZvaWQ7XG4gIG9uQ2FuY2VsPzogKCkgPT4gdm9pZDtcbiAgaXNQZW5kaW5nPzogYm9vbGVhbjtcbiAgaXNTdWNjZXNzPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEYXRhTW9kYWxDb21wb25lbnRQcm9wczxURGF0YT4ge1xuICBkYXRhPzogVERhdGE7XG4gIGlzRWRpdGluZz86IGJvb2xlYW47XG4gIHJlZj86IFJlYWN0LlJlZjxEYXRhTW9kYWxCdXR0b25zPjsgLy8gXHVEODNEXHVEQzQ4IHB1dCByZWYgaW50byBwcm9wc1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBQcm9qZWN0LXNwZWNpZmljIEhPQ1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZXhwb3J0IGZ1bmN0aW9uIHdpdGhEYXRhTW9kYWw8VERhdGE+KFxuICBjb21wb25lbnQ6IChcbiAgICBwcm9wczogRGF0YU1vZGFsQ29tcG9uZW50UHJvcHM8VERhdGE+XG4gICkgPT4gUmVhY3QuUmVhY3RFbGVtZW50IHwgbnVsbFxuKSB7XG4gIHJldHVybiBmb3J3YXJkUmVmPERhdGFNb2RhbEJ1dHRvbnMsIERhdGFNb2RhbENvbXBvbmVudFByb3BzPFREYXRhPj4oXG4gICAgKHByb3BzLCByZWYpID0+IGNvbXBvbmVudCh7IC4uLnByb3BzLCByZWYgfSlcbiAgKTtcbn1cbiIsICJleHBvcnQgaW50ZXJmYWNlIENvbmZpZ1ZhbHVlIHtcbiAgYXBpQmFzZVVybDogc3RyaW5nO1xuICBkZWZhdWx0UGFnZVNpemU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGNvbnN0IENvbmZpZzogQ29uZmlnVmFsdWUgPSB7XG4gIGRlZmF1bHRQYWdlU2l6ZTogMjAsXG4gIGFwaUJhc2VVcmw6ICdodHRwOi8vbG9jYWxob3N0OjUxNDMnLFxuICAvLyBhcGlCYXNlVXJsOiAnaHR0cDovLzE5Mi4xNjguMS4yNDY6NTE0MycsXG59O1xuXG5leHBvcnQgY29uc3QgZGF0ZVRpbWVQYXR0ZXJucyA9IHtcbiAgZGF0ZVRpbWU6ICdERCBNTU0gWVlZWSBoOm1tIEEnLCAvLyAxNyBBcHIgMjAyMiAxMjowMCBhbVxuICBkYXRlOiAnREQgTU1NIFlZWVknLCAvLyAxNyBBcHIgMjAyMlxuICBtb250aF95ZWFyX3Nob3J0X2Zvcm1hdDogJ01NTSBZWVlZJyxcbiAgbW9udGhfeWVhcl9mdWxsX2Zvcm1hdDogJ01NTU0gWVlZWScsXG4gIHllYXI6ICdZWVlZJyxcbiAgdGltZTogJ2g6bW0gYScsIC8vIDEyOjAwIGFtXG4gIHNwbGl0OiB7XG4gICAgZGF0ZVRpbWU6ICdERC9NTS9ZWVlZIGg6bW0gQScsIC8vIDE3LzA0LzIwMjIgMTI6MDAgYW1cbiAgICBkYXRlOiAnREQvTU0vWVlZWScsIC8vIDE3LzA0LzIwMjJcbiAgfSxcbiAgcGFyYW1DYXNlOiB7XG4gICAgZGF0ZVRpbWU6ICdERC1NTS1ZWVlZIGg6bW0gQScsIC8vIDE3LTA0LTIwMjIgMTI6MDAgYW1cbiAgICBkYXRlOiAnREQtTU0tWVlZWScsIC8vIDE3LTA0LTIwMjJcbiAgICBkYXRlUmV2ZXJzZTogJ1lZWVktTU0tREQnLCAvLyAyMDIyLTA0LTE3IGZvciBjb21wYXJlIGRhdGVcbiAgICBNb250aFllYXI6ICdNTU0tWVlZWScsXG4gIH0sXG59O1xuIiwgImltcG9ydCB7IHVzZU1lbW8gfSBmcm9tICdyZWFjdCc7XG5cbmltcG9ydCB7IGNyZWF0ZUFwaUNsaWVudCB9IGZyb20gJy4uL2FwaS9jcmVhdGVBcGlDbGllbnQnO1xuaW1wb3J0IHR5cGUgeyBBcGlDbGllbnRDb25maWcgfSBmcm9tICcuLi9hcGkvY3JlYXRlQXBpQ2xpZW50JztcblxuZXhwb3J0IGZ1bmN0aW9uIHVzZUFwaUNsaWVudChjb25maWc6IEFwaUNsaWVudENvbmZpZyA9IHt9KSB7XG4gIHJldHVybiB1c2VNZW1vKFxuICAgICgpID0+IGNyZWF0ZUFwaUNsaWVudChjb25maWcpLFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSByZWFjdC1ob29rcy9leGhhdXN0aXZlLWRlcHNcbiAgICBbXG4gICAgICBjb25maWcuYmFzZVVSTCxcbiAgICAgIGNvbmZpZy50aW1lb3V0LFxuICAgICAgY29uZmlnLmNvcnJlbGF0aW9uSWRQcmVmaXgsXG4gICAgICBjb25maWcuaW5jbHVkZUNvcnJlbGF0aW9uSWQsXG4gICAgICBjb25maWcuYXV0aFRva2VuLFxuICAgICAgY29uZmlnLnJlcXVlc3RJbnRlcmNlcHRvcnMsXG4gICAgICBjb25maWcucmVzcG9uc2VJbnRlcmNlcHRvcnMsXG4gICAgICBjb25maWcuZXJyb3JJbnRlcmNlcHRvcnMsXG4gICAgXVxuICApO1xufVxuIiwgImltcG9ydCB0eXBlIHsgVmFsaWRhdGlvbkVycm9ycyB9IGZyb20gJ0BnbndlYnNvZnQvdWknO1xuaW1wb3J0IHsgdXNlQ2FsbGJhY2sgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgdHlwZSB7IFVzZUZvcm1TZXRFcnJvciwgRmllbGRWYWx1ZXMsIFBhdGggfSBmcm9tICdyZWFjdC1ob29rLWZvcm0nO1xuaW1wb3J0IHsgdG9hc3QgfSBmcm9tICdzb25uZXInO1xuXG5pbXBvcnQgdHlwZSB7IEFwaUVycm9yIH0gZnJvbSAnLi4vYXBpL3R5cGVzJztcblxuZXhwb3J0IGludGVyZmFjZSBTdWNjZXNzTWVzc2FnZSB7XG4gIGNyZWF0ZTogc3RyaW5nO1xuICB1cGRhdGU6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFcnJvck1lc3NhZ2Uge1xuICBub0NoYW5nZXM6IHN0cmluZztcbiAgZ2VuZXJhbDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFVzZUZvcm1FcnJvckhhbmRsZXJPcHRpb25zPFRGaWVsZFZhbHVlcyBleHRlbmRzIEZpZWxkVmFsdWVzPiB7XG4gIHNldEVycm9yPzogVXNlRm9ybVNldEVycm9yPFRGaWVsZFZhbHVlcz47XG4gIHN1Y2Nlc3NNZXNzYWdlPzogU3VjY2Vzc01lc3NhZ2U7XG4gIGVycm9yTWVzc2FnZT86IEVycm9yTWVzc2FnZTtcbn1cblxuZXhwb3J0IHR5cGUgU3VjY2Vzc0hhbmRsZXIgPSAoXG4gIGlzRWRpdGluZzogYm9vbGVhbixcbiAgcm93c0FmZmVjdGVkPzogbnVtYmVyXG4pID0+IGJvb2xlYW47XG5cbmV4cG9ydCB0eXBlIEVycm9ySGFuZGxlciA9IChwcm9jZXNzZWRFcnJvcjogQXBpRXJyb3IpID0+IHZvaWQ7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXNlRm9ybUVycm9ySGFuZGxlclJldHVybiB7XG4gIGhhbmRsZVN1Y2Nlc3M6IFN1Y2Nlc3NIYW5kbGVyO1xuICBoYW5kbGVFcnJvcjogRXJyb3JIYW5kbGVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFVzZURlbGV0ZUhhbmRsZXJPcHRpb25zIHtcbiAgc3VjY2Vzc01lc3NhZ2U/OiBzdHJpbmc7XG4gIGVycm9yTWVzc2FnZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBIb29rIHRvIGhhbmRsZSBBUEkgZXJyb3JzIGluIGZvcm1zIHdpdGggc3RhbmRhcmRpemVkIGVycm9yIGhhbmRsaW5nIGFuZCB0b2FzdCBtZXNzYWdlc1xuICovXG5leHBvcnQgY29uc3QgdXNlRm9ybUVycm9ySGFuZGxlciA9IDxURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcz4oe1xuICBzZXRFcnJvcixcbiAgc3VjY2Vzc01lc3NhZ2UgPSB7XG4gICAgY3JlYXRlOiAnQ3JlYXRlZCBzdWNjZXNzZnVsbHknLFxuICAgIHVwZGF0ZTogJ1VwZGF0ZWQgc3VjY2Vzc2Z1bGx5JyxcbiAgfSxcbiAgZXJyb3JNZXNzYWdlID0ge1xuICAgIG5vQ2hhbmdlczogJ05vIGNoYW5nZXMgd2VyZSBtYWRlJyxcbiAgICBnZW5lcmFsOiAnRmFpbGVkIHRvIHNhdmUuIFBsZWFzZSB0cnkgYWdhaW4uJyxcbiAgfSxcbn06IFVzZUZvcm1FcnJvckhhbmRsZXJPcHRpb25zPFRGaWVsZFZhbHVlcz4pOiBVc2VGb3JtRXJyb3JIYW5kbGVyUmV0dXJuID0+IHtcbiAgY29uc3QgZ2V0RmllbGRFcnJvciA9IHVzZUNhbGxiYWNrKFxuICAgIChcbiAgICAgIGZpZWxkczogVmFsaWRhdGlvbkVycm9ycyB8IHVuZGVmaW5lZCxcbiAgICAgIGZpZWxkTmFtZTogc3RyaW5nXG4gICAgKTogc3RyaW5nIHwgdW5kZWZpbmVkID0+IHtcbiAgICAgIGlmICghZmllbGRzIHx8ICFmaWVsZHNbZmllbGROYW1lXSkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgICAgY29uc3QgZmllbGRFcnJvciA9IGZpZWxkc1tmaWVsZE5hbWVdO1xuXG4gICAgICBpZiAodHlwZW9mIGZpZWxkRXJyb3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBmaWVsZEVycm9yO1xuICAgICAgfVxuXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShmaWVsZEVycm9yKSkge1xuICAgICAgICByZXR1cm4gZmllbGRFcnJvci5qb2luKCcsICcpO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIGZpZWxkRXJyb3IgPT09ICdvYmplY3QnICYmICdtZXNzYWdlJyBpbiBmaWVsZEVycm9yKSB7XG4gICAgICAgIHJldHVybiBmaWVsZEVycm9yLm1lc3NhZ2U7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfSxcbiAgICBbXVxuICApO1xuXG4gIGNvbnN0IGhhbmRsZVN1Y2Nlc3MgPSB1c2VDYWxsYmFjayhcbiAgICAoaXNFZGl0aW5nOiBib29sZWFuLCByb3dzQWZmZWN0ZWQ/OiBudW1iZXIpID0+IHtcbiAgICAgIGlmIChyb3dzQWZmZWN0ZWQgIT09IHVuZGVmaW5lZCAmJiByb3dzQWZmZWN0ZWQgPiAwKSB7XG4gICAgICAgIHRvYXN0LnN1Y2Nlc3MoXG4gICAgICAgICAgaXNFZGl0aW5nID8gc3VjY2Vzc01lc3NhZ2UudXBkYXRlIDogc3VjY2Vzc01lc3NhZ2UuY3JlYXRlXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKHJvd3NBZmZlY3RlZCA9PT0gMCkge1xuICAgICAgICB0b2FzdC5lcnJvcihlcnJvck1lc3NhZ2Uubm9DaGFuZ2VzKTtcblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIC8vIElmIHJvd3NBZmZlY3RlZCBpcyB1bmRlZmluZWQsIGFzc3VtZSBzdWNjZXNzXG4gICAgICB0b2FzdC5zdWNjZXNzKGlzRWRpdGluZyA/IHN1Y2Nlc3NNZXNzYWdlLnVwZGF0ZSA6IHN1Y2Nlc3NNZXNzYWdlLmNyZWF0ZSk7XG5cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG4gICAgW3N1Y2Nlc3NNZXNzYWdlLCBlcnJvck1lc3NhZ2VdXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlRXJyb3IgPSB1c2VDYWxsYmFjayhcbiAgICAocHJvY2Vzc2VkRXJyb3I6IEFwaUVycm9yKSA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgIHByb2Nlc3NlZEVycm9yLnR5cGUgPT09ICd2YWxpZGF0aW9uX2Vycm9yJyAmJlxuICAgICAgICBwcm9jZXNzZWRFcnJvci5lcnJvcnMgJiZcbiAgICAgICAgc2V0RXJyb3JcbiAgICAgICkge1xuICAgICAgICAvLyBTZXQgZmllbGQtc3BlY2lmaWMgZXJyb3JzIHVzaW5nIHJlYWN0LWhvb2stZm9ybSdzIHNldEVycm9yIChvbmx5IGlmIHNldEVycm9yIGlzIHByb3ZpZGVkKVxuICAgICAgICBPYmplY3Qua2V5cyhwcm9jZXNzZWRFcnJvci5lcnJvcnMpLmZvckVhY2goZmllbGROYW1lID0+IHtcbiAgICAgICAgICBjb25zdCBmaWVsZEVycm9yID0gZ2V0RmllbGRFcnJvcihwcm9jZXNzZWRFcnJvci5lcnJvcnMsIGZpZWxkTmFtZSk7XG5cbiAgICAgICAgICBpZiAoZmllbGRFcnJvcikge1xuICAgICAgICAgICAgc2V0RXJyb3IoZmllbGROYW1lIGFzIFBhdGg8VEZpZWxkVmFsdWVzPiwge1xuICAgICAgICAgICAgICB0eXBlOiAnc2VydmVyJyxcbiAgICAgICAgICAgICAgbWVzc2FnZTogZmllbGRFcnJvcixcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gU2hvdyBnZW5lcmFsIHZhbGlkYXRpb24gZXJyb3IgdG9hc3RcbiAgICAgICAgdG9hc3QuZXJyb3IoXG4gICAgICAgICAgcHJvY2Vzc2VkRXJyb3IudGl0bGUgfHwgJ1BsZWFzZSBjaGVjayB0aGUgZm9ybSBmb3IgdmFsaWRhdGlvbiBlcnJvcnMnXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBTaG93IGdlbmVyYWwgZXJyb3IgdG9hc3QgZm9yIG5vbi12YWxpZGF0aW9uIGVycm9ycyBvciB3aGVuIHNldEVycm9yIGlzIG5vdCBhdmFpbGFibGVcbiAgICAgICAgdG9hc3QuZXJyb3IocHJvY2Vzc2VkRXJyb3IudGl0bGUgfHwgZXJyb3JNZXNzYWdlLmdlbmVyYWwpO1xuICAgICAgfVxuICAgIH0sXG4gICAgW2Vycm9yTWVzc2FnZS5nZW5lcmFsLCBnZXRGaWVsZEVycm9yLCBzZXRFcnJvcl1cbiAgKTtcblxuICByZXR1cm4ge1xuICAgIGhhbmRsZVN1Y2Nlc3MsXG4gICAgaGFuZGxlRXJyb3IsXG4gIH07XG59O1xuXG4vKipcbiAqIENvbnZlbmllbmNlIGhvb2sgZm9yIGRlbGV0ZSBvcGVyYXRpb25zIHRoYXQgZG9uJ3QgbmVlZCBmb3JtIGZpZWxkIHZhbGlkYXRpb25cbiAqIFVzZXMgdXNlRm9ybUVycm9ySGFuZGxlciBpbnRlcm5hbGx5IGJ1dCB3aXRoIHNpbXBsaWZpZWQgb3B0aW9uc1xuICovXG5leHBvcnQgY29uc3QgdXNlRGVsZXRlSGFuZGxlciA9ICh7XG4gIHN1Y2Nlc3NNZXNzYWdlID0gJ0RlbGV0ZWQgc3VjY2Vzc2Z1bGx5JyxcbiAgZXJyb3JNZXNzYWdlID0gJ0ZhaWxlZCB0byBkZWxldGUuIFBsZWFzZSB0cnkgYWdhaW4uJyxcbn06IFVzZURlbGV0ZUhhbmRsZXJPcHRpb25zID0ge30pOiBVc2VGb3JtRXJyb3JIYW5kbGVyUmV0dXJuID0+IHtcbiAgcmV0dXJuIHVzZUZvcm1FcnJvckhhbmRsZXIoe1xuICAgIHN1Y2Nlc3NNZXNzYWdlOiB7XG4gICAgICBjcmVhdGU6IHN1Y2Nlc3NNZXNzYWdlLCAvLyBOb3QgdXNlZCBmb3IgZGVsZXRlLCBidXQgcmVxdWlyZWQgZm9yIHR5cGVcbiAgICAgIHVwZGF0ZTogc3VjY2Vzc01lc3NhZ2UsXG4gICAgfSxcbiAgICBlcnJvck1lc3NhZ2U6IHtcbiAgICAgIG5vQ2hhbmdlczogJ05vIGNoYW5nZXMgd2VyZSBtYWRlJywgLy8gTm90IHR5cGljYWxseSB1c2VkIGZvciBkZWxldGVcbiAgICAgIGdlbmVyYWw6IGVycm9yTWVzc2FnZSxcbiAgICB9LFxuICAgIC8vIHNldEVycm9yIGlzIG9taXR0ZWQgKHVuZGVmaW5lZCkgZm9yIGRlbGV0ZSBvcGVyYXRpb25zXG4gIH0pO1xufTtcbiIsICJpbXBvcnQgdHlwZSB7IFF1ZXJ5Q2xpZW50LCBRdWVyeUtleSB9IGZyb20gJ0B0YW5zdGFjay9yZWFjdC1xdWVyeSc7XG5pbXBvcnQgeyB1c2VRdWVyeUNsaWVudCB9IGZyb20gJ0B0YW5zdGFjay9yZWFjdC1xdWVyeSc7XG5pbXBvcnQgeyB1c2VNZW1vIH0gZnJvbSAncmVhY3QnO1xuXG4vLyBNaW5pbWFsIHR5cGUtc2FmZSBjYWNoZSB1dGlsaXR5IGZvciBxdWVyeSBrZXkgZmFjdG9yaWVzXG5leHBvcnQgY2xhc3MgQ2FjaGVVdGlsaXR5IHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBxdWVyeUNsaWVudDogUXVlcnlDbGllbnQpIHt9XG5cbiAgLyoqXG4gICAqIEdldCBjYWNoZWQgZGF0YSB1c2luZyBvbmx5IHRoZSBxdWVyeUtleSBmcm9tIHF1ZXJ5IGZhY3RvcnlcbiAgICovXG4gIGdldENhY2hlZERhdGE8VD4ocXVlcnlLZXk6IFF1ZXJ5S2V5KTogVCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlDbGllbnQuZ2V0UXVlcnlEYXRhPFQ+KHF1ZXJ5S2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY2FjaGVkIGRhdGEgd2l0aCB0cmFuc2Zvcm1hdGlvbiB1c2luZyBzZWxlY3QgZnVuY3Rpb25cbiAgICovXG4gIGdldENhY2hlZERhdGFXaXRoU2VsZWN0PFQsIFI+KFxuICAgIHF1ZXJ5S2V5OiBRdWVyeUtleSxcbiAgICBzZWxlY3Q6IChkYXRhOiBUKSA9PiBSXG4gICk6IFIgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGNhY2hlZERhdGEgPSB0aGlzLnF1ZXJ5Q2xpZW50LmdldFF1ZXJ5RGF0YTxUPihxdWVyeUtleSk7XG5cbiAgICBpZiAoY2FjaGVkRGF0YSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiBzZWxlY3QoY2FjaGVkRGF0YSk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVzZUNhY2hlVXRpbGl0eSgpOiBDYWNoZVV0aWxpdHkge1xuICBjb25zdCBxdWVyeUNsaWVudCA9IHVzZVF1ZXJ5Q2xpZW50KCk7XG5cbiAgcmV0dXJuIHVzZU1lbW8oKCkgPT4gbmV3IENhY2hlVXRpbGl0eShxdWVyeUNsaWVudCksIFtxdWVyeUNsaWVudF0pO1xufVxuIiwgImltcG9ydCB0eXBlIHtcbiAgQ29udHJvbCxcbiAgRGVlcFBhcnRpYWxTa2lwQXJyYXlLZXksXG4gIEZpZWxkVmFsdWVzLFxuICBQYXRoLFxuICBQYXRoVmFsdWUsXG59IGZyb20gJ3JlYWN0LWhvb2stZm9ybSc7XG5pbXBvcnQgeyB1c2VXYXRjaCB9IGZyb20gJ3JlYWN0LWhvb2stZm9ybSc7XG5cbi8qKlxuICogQ29yZSB3YXRjaCBmdW5jdGlvbnMgZm9yIFJlYWN0IEhvb2sgRm9ybVxuICogVGhlc2UgYXJlIHRoZSBwcmltYXJ5IGJ1aWxkaW5nIGJsb2NrcyBmb3IgZm9ybSB3YXRjaGluZ1xuICovXG5cbi8qKlxuICogVXRpbGl0eSB0eXBlIHRvIGVuc3VyZSBhcnJheSBlbGVtZW50cyBhcmUgYWxsIFBhdGg8VD5cbiAqL1xuZXhwb3J0IHR5cGUgUGF0aEFycmF5PFQgZXh0ZW5kcyBGaWVsZFZhbHVlcz4gPSBSZWFkb25seUFycmF5PFBhdGg8VD4+O1xuXG4vKipcbiAqIEhvb2sgdG8gd2F0Y2ggZW50aXJlIGZvcm0gLSByZXR1cm5zIGFsbCBmb3JtIHZhbHVlc1xuICovXG5leHBvcnQgY29uc3QgdXNlV2F0Y2hGb3JtID0gPFRGaWVsZFZhbHVlcyBleHRlbmRzIEZpZWxkVmFsdWVzPihcbiAgY29udHJvbDogQ29udHJvbDxURmllbGRWYWx1ZXM+XG4pOiBEZWVwUGFydGlhbFNraXBBcnJheUtleTxURmllbGRWYWx1ZXM+ID0+IHVzZVdhdGNoKHsgY29udHJvbCB9KTtcblxuLyoqXG4gKiBIb29rIHRvIHdhdGNoIHNpbmdsZSBmaWVsZCBieSBwYXRoIC0gc3VwcG9ydHMgYW55IG5lc3RlZCBwYXRoXG4gKi9cbmV4cG9ydCBjb25zdCB1c2VXYXRjaEZpZWxkID0gPFxuICBURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcyxcbiAgVE5hbWUgZXh0ZW5kcyBQYXRoPFRGaWVsZFZhbHVlcz4sXG4+KFxuICBjb250cm9sOiBDb250cm9sPFRGaWVsZFZhbHVlcz4sXG4gIG5hbWU6IFROYW1lXG4pOiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZT4gPT4gdXNlV2F0Y2goeyBjb250cm9sLCBuYW1lIH0pO1xuXG4vKipcbiAqIEhvb2sgdG8gd2F0Y2ggbXVsdGlwbGUgZmllbGRzIGJ5IHBhdGhzIC0gcmV0dXJucyBhcnJheSBvZiB2YWx1ZXNcbiAqL1xuZXhwb3J0IGNvbnN0IHVzZVdhdGNoRmllbGRzID0gPFxuICBURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcyxcbiAgVE5hbWVzIGV4dGVuZHMgUmVhZG9ubHlBcnJheTxQYXRoPFRGaWVsZFZhbHVlcz4+LFxuPihcbiAgY29udHJvbDogQ29udHJvbDxURmllbGRWYWx1ZXM+LFxuICBuYW1lczogVE5hbWVzXG4pOiBBcnJheTxQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZXNbbnVtYmVyXT4+ID0+XG4gIHVzZVdhdGNoKHsgY29udHJvbCwgbmFtZTogbmFtZXMgfSkgYXMgQXJyYXk8XG4gICAgUGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgVE5hbWVzW251bWJlcl0+XG4gID47XG4iLCAiaW1wb3J0IHsgdXNlRWZmZWN0LCB1c2VNZW1vLCB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0JztcbmltcG9ydCB0eXBlIHsgQ29udHJvbCwgRmllbGRWYWx1ZXMsIFBhdGgsIFBhdGhWYWx1ZSB9IGZyb20gJ3JlYWN0LWhvb2stZm9ybSc7XG5pbXBvcnQgeyB1c2VXYXRjaCB9IGZyb20gJ3JlYWN0LWhvb2stZm9ybSc7XG5cbi8qKlxuICogVXRpbGl0eSB3YXRjaCBmdW5jdGlvbnMgZm9yIFJlYWN0IEhvb2sgRm9ybVxuICogRW5oYW5jZWQgZnVuY3Rpb25hbGl0eSBmb3Igc3BlY2lmaWMgdXNlIGNhc2VzXG4gKi9cblxuLyoqXG4gKiBXYXRjaCBmaWVsZCB3aXRoIHRyYW5zZm9ybWF0aW9uL3NlbGVjdG9yXG4gKi9cbmV4cG9ydCBjb25zdCB1c2VXYXRjaFRyYW5zZm9ybSA9IDxcbiAgVEZpZWxkVmFsdWVzIGV4dGVuZHMgRmllbGRWYWx1ZXMsXG4gIFROYW1lIGV4dGVuZHMgUGF0aDxURmllbGRWYWx1ZXM+LFxuICBUT3V0cHV0LFxuPihcbiAgY29udHJvbDogQ29udHJvbDxURmllbGRWYWx1ZXM+LFxuICBuYW1lOiBUTmFtZSxcbiAgdHJhbnNmb3JtOiAodmFsdWU6IFBhdGhWYWx1ZTxURmllbGRWYWx1ZXMsIFROYW1lPikgPT4gVE91dHB1dFxuKTogVE91dHB1dCA9PiB7XG4gIGNvbnN0IHZhbHVlID0gdXNlV2F0Y2goeyBjb250cm9sLCBuYW1lIH0pO1xuXG4gIHJldHVybiB1c2VNZW1vKCgpID0+IHRyYW5zZm9ybSh2YWx1ZSksIFt2YWx1ZSwgdHJhbnNmb3JtXSk7XG59O1xuXG4vKipcbiAqIFdhdGNoIGZpZWxkIHdpdGggZGVmYXVsdCBmYWxsYmFjayB2YWx1ZVxuICovXG5leHBvcnQgY29uc3QgdXNlV2F0Y2hEZWZhdWx0ID0gPFxuICBURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcyxcbiAgVE5hbWUgZXh0ZW5kcyBQYXRoPFRGaWVsZFZhbHVlcz4sXG4+KFxuICBjb250cm9sOiBDb250cm9sPFRGaWVsZFZhbHVlcz4sXG4gIG5hbWU6IFROYW1lLFxuICBkZWZhdWx0VmFsdWU6IFBhdGhWYWx1ZTxURmllbGRWYWx1ZXMsIFROYW1lPlxuKTogUGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgVE5hbWU+ID0+IHtcbiAgY29uc3QgdmFsdWUgPSB1c2VXYXRjaCh7IGNvbnRyb2wsIG5hbWUgfSk7XG5cbiAgcmV0dXJuIHZhbHVlID8/IGRlZmF1bHRWYWx1ZTtcbn07XG5cbi8qKlxuICogV2F0Y2ggZmllbGQgYXMgYm9vbGVhbiB3aXRoIGd1YXJhbnRlZWQgYm9vbGVhbiByZXR1cm5cbiAqL1xuZXhwb3J0IGNvbnN0IHVzZVdhdGNoQm9vbGVhbiA9IDxcbiAgVEZpZWxkVmFsdWVzIGV4dGVuZHMgRmllbGRWYWx1ZXMsXG4gIFROYW1lIGV4dGVuZHMgUGF0aDxURmllbGRWYWx1ZXM+LFxuPihcbiAgY29udHJvbDogQ29udHJvbDxURmllbGRWYWx1ZXM+LFxuICBuYW1lOiBUTmFtZSxcbiAgZGVmYXVsdFZhbHVlID0gZmFsc2Vcbik6IGJvb2xlYW4gPT4ge1xuICBjb25zdCB2YWx1ZSA9IHVzZVdhdGNoKHsgY29udHJvbCwgbmFtZSB9KTtcblxuICByZXR1cm4gQm9vbGVhbih2YWx1ZSA/PyBkZWZhdWx0VmFsdWUpO1xufTtcblxuLyoqXG4gKiBXYXRjaCBtdWx0aXBsZSBmaWVsZHMgYW5kIHJldHVybiBhbiBvYmplY3Qgd2l0aCBmaWVsZCBwYXRocyBhcyBrZXlzXG4gKi9cbmV4cG9ydCBjb25zdCB1c2VXYXRjaEJhdGNoID0gPFxuICBURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcyxcbiAgVEZpZWxkcyBleHRlbmRzIFJlYWRvbmx5QXJyYXk8UGF0aDxURmllbGRWYWx1ZXM+Pixcbj4oXG4gIGNvbnRyb2w6IENvbnRyb2w8VEZpZWxkVmFsdWVzPixcbiAgZmllbGRzOiBURmllbGRzXG4pOiB7IFtLIGluIFRGaWVsZHNbbnVtYmVyXV06IFBhdGhWYWx1ZTxURmllbGRWYWx1ZXMsIEs+IH0gPT4ge1xuICBjb25zdCB2YWx1ZXMgPSB1c2VXYXRjaCh7IGNvbnRyb2wsIG5hbWU6IGZpZWxkcyB9KTtcblxuICByZXR1cm4gdXNlTWVtbygoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0ge30gYXMgeyBbSyBpbiBURmllbGRzW251bWJlcl1dOiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBLPiB9O1xuXG4gICAgZmllbGRzLmZvckVhY2goKGZpZWxkLCBpbmRleCkgPT4ge1xuICAgICAgcmVzdWx0W2ZpZWxkIGFzIFRGaWVsZHNbbnVtYmVyXV0gPSB2YWx1ZXNbaW5kZXhdO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSwgW3ZhbHVlcywgZmllbGRzXSk7XG59O1xuXG4vKipcbiAqIFdhdGNoIGZpZWxkIGNvbmRpdGlvbmFsbHkgYmFzZWQgb24gYm9vbGVhbiBmbGFnXG4gKi9cbmV4cG9ydCBjb25zdCB1c2VXYXRjaENvbmRpdGlvbmFsID0gPFxuICBURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcyxcbiAgVE5hbWUgZXh0ZW5kcyBQYXRoPFRGaWVsZFZhbHVlcz4sXG4+KFxuICBjb250cm9sOiBDb250cm9sPFRGaWVsZFZhbHVlcz4sXG4gIG5hbWU6IFROYW1lLFxuICBzaG91bGRXYXRjaDogYm9vbGVhbixcbiAgZmFsbGJhY2s/OiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZT5cbik6IFBhdGhWYWx1ZTxURmllbGRWYWx1ZXMsIFROYW1lPiB8IHVuZGVmaW5lZCA9PiB7XG4gIGNvbnN0IGFjdGl2ZVZhbHVlID0gdXNlV2F0Y2goe1xuICAgIGNvbnRyb2wsXG4gICAgbmFtZSxcbiAgICBkaXNhYmxlZDogIXNob3VsZFdhdGNoLFxuICB9KTtcblxuICByZXR1cm4gc2hvdWxkV2F0Y2ggPyBhY3RpdmVWYWx1ZSA6IGZhbGxiYWNrO1xufTtcblxuLyoqXG4gKiBXYXRjaCBmaWVsZCB3aXRoIGRlYm91bmNlZCB1cGRhdGVzXG4gKi9cbmV4cG9ydCBjb25zdCB1c2VXYXRjaERlYm91bmNlZCA9IDxcbiAgVEZpZWxkVmFsdWVzIGV4dGVuZHMgRmllbGRWYWx1ZXMsXG4gIFROYW1lIGV4dGVuZHMgUGF0aDxURmllbGRWYWx1ZXM+LFxuPihcbiAgY29udHJvbDogQ29udHJvbDxURmllbGRWYWx1ZXM+LFxuICBuYW1lOiBUTmFtZSxcbiAgZGVsYXkgPSAzMDBcbik6IFBhdGhWYWx1ZTxURmllbGRWYWx1ZXMsIFROYW1lPiA9PiB7XG4gIGNvbnN0IHZhbHVlID0gdXNlV2F0Y2goeyBjb250cm9sLCBuYW1lIH0pO1xuICBjb25zdCBbZGVib3VuY2VkVmFsdWUsIHNldERlYm91bmNlZFZhbHVlXSA9XG4gICAgdXNlU3RhdGU8UGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgVE5hbWU+Pih2YWx1ZSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgc2V0RGVib3VuY2VkVmFsdWUodmFsdWUpO1xuICAgIH0sIGRlbGF5KTtcblxuICAgIHJldHVybiAoKSA9PiBjbGVhclRpbWVvdXQodGltZXIpO1xuICB9LCBbdmFsdWUsIGRlbGF5XSk7XG5cbiAgcmV0dXJuIGRlYm91bmNlZFZhbHVlO1xufTtcblxuLyoqXG4gKiBXYXRjaCBmaWVsZCB3aXRoIG1lbW9pemVkIHNlbGVjdG9yIGZ1bmN0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCB1c2VXYXRjaFNlbGVjdG9yID0gPFxuICBURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcyxcbiAgVE5hbWUgZXh0ZW5kcyBQYXRoPFRGaWVsZFZhbHVlcz4sXG4gIFRPdXRwdXQsXG4+KFxuICBjb250cm9sOiBDb250cm9sPFRGaWVsZFZhbHVlcz4sXG4gIG5hbWU6IFROYW1lLFxuICBzZWxlY3RvcjogKHZhbHVlOiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZT4pID0+IFRPdXRwdXQsXG4gIGRlcHM6IFJlYWN0LkRlcGVuZGVuY3lMaXN0ID0gW11cbik6IFRPdXRwdXQgPT4ge1xuICBjb25zdCB2YWx1ZSA9IHVzZVdhdGNoKHsgY29udHJvbCwgbmFtZSB9KTtcblxuICByZXR1cm4gdXNlTWVtbyhcbiAgICAoKSA9PiBzZWxlY3Rvcih2YWx1ZSksXG4gICAgW3ZhbHVlLCBzZWxlY3RvciwgLi4uZGVwc10gLy8gZXNsaW50LWRpc2FibGUtbGluZSByZWFjdC1ob29rcy9leGhhdXN0aXZlLWRlcHNcbiAgKTtcbn07XG4iLCAiLyoqXG4gKiBFbmhhbmNlZCBUeXBlU2NyaXB0IHV0aWxpdGllcyBmb3IgUmVhY3QgSG9vayBGb3JtJ3MgdXNlV2F0Y2hcbiAqXG4gKiBUaGlzIG1vZHVsZSBwcm92aWRlcyBhIGNvbXByZWhlbnNpdmUgc2V0IG9mIHR5cGUtc2FmZSB3YXRjaCBmdW5jdGlvbnNcbiAqIHdpdGggYmV0dGVyIGVyZ29ub21pY3MgYW5kIGFkZGl0aW9uYWwgZnVuY3Rpb25hbGl0eS5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgdXNlV2F0Y2hGaWVsZCwgdXNlV2F0Y2hCb29sZWFuLCB0eXBlZFdhdGNoIH0gZnJvbSAnc3JjL3V0aWxzL3dhdGNoJztcbiAqXG4gKiAvLyBEaXJlY3QgdXNhZ2UgKGluc2lkZSBSZWFjdCBjb21wb25lbnRzKVxuICogY29uc3QgZW1haWwgPSB1c2VXYXRjaEZpZWxkKGNvbnRyb2wsICd1c2VyLmVtYWlsJyk7XG4gKiBjb25zdCBpc0FkbWluID0gdXNlV2F0Y2hCb29sZWFuKGNvbnRyb2wsICd1c2VyLmlzQWRtaW4nKTtcbiAqXG4gKiAvLyBPYmplY3QtYmFzZWQgdXNhZ2UgKGluc2lkZSBSZWFjdCBjb21wb25lbnRzKVxuICogY29uc3QgZW1haWwgPSB0eXBlZFdhdGNoLmZpZWxkKGNvbnRyb2wsICd1c2VyLmVtYWlsJyk7XG4gKiBjb25zdCBpc0FkbWluID0gdHlwZWRXYXRjaC5ib29sZWFuKGNvbnRyb2wsICd1c2VyLmlzQWRtaW4nKTtcbiAqIGBgYFxuICovXG5cbi8vIENvcmUgZnVuY3Rpb25zXG5leHBvcnQgeyB1c2VXYXRjaEZpZWxkLCB1c2VXYXRjaEZpZWxkcywgdXNlV2F0Y2hGb3JtIH0gZnJvbSAnLi9jb3JlJztcblxuLy8gVXRpbGl0eSBmdW5jdGlvbnNcbmV4cG9ydCB7XG4gIHVzZVdhdGNoQmF0Y2gsXG4gIHVzZVdhdGNoQm9vbGVhbixcbiAgdXNlV2F0Y2hDb25kaXRpb25hbCxcbiAgdXNlV2F0Y2hEZWJvdW5jZWQsXG4gIHVzZVdhdGNoRGVmYXVsdCxcbiAgdXNlV2F0Y2hTZWxlY3RvcixcbiAgdXNlV2F0Y2hUcmFuc2Zvcm0sXG59IGZyb20gJy4vdXRpbGl0aWVzJztcblxuZXhwb3J0IHR5cGUgeyBQYXRoQXJyYXkgfSBmcm9tICcuL2NvcmUnO1xuXG4vLyBJbXBvcnQgYWxsIGZ1bmN0aW9ucyBmb3IgZGVmYXVsdCBleHBvcnRcbmltcG9ydCB7IHVzZVdhdGNoRmllbGQsIHVzZVdhdGNoRmllbGRzLCB1c2VXYXRjaEZvcm0gfSBmcm9tICcuL2NvcmUnO1xuaW1wb3J0IHtcbiAgdXNlV2F0Y2hCYXRjaCxcbiAgdXNlV2F0Y2hCb29sZWFuLFxuICB1c2VXYXRjaENvbmRpdGlvbmFsLFxuICB1c2VXYXRjaERlYm91bmNlZCxcbiAgdXNlV2F0Y2hEZWZhdWx0LFxuICB1c2VXYXRjaFNlbGVjdG9yLFxuICB1c2VXYXRjaFRyYW5zZm9ybSxcbn0gZnJvbSAnLi91dGlsaXRpZXMnO1xuXG4vKipcbiAqIE9yZ2FuaXplZCB1dGlsaXRpZXMgYnkgdXNlIGNhc2VcbiAqIFByb3ZpZGVzIGEgY29udmVuaWVudCBvYmplY3QtYmFzZWQgQVBJIGZvciBhbGwgd2F0Y2ggZnVuY3Rpb25zXG4gKi9cbmV4cG9ydCBjb25zdCB0eXBlZFdhdGNoID0ge1xuICAvLyA9PT0gQ09SRSBGVU5DVElPTlMgPT09XG4gIC8qKiBXYXRjaCBlbnRpcmUgZm9ybSAqL1xuICBmb3JtOiB1c2VXYXRjaEZvcm0sXG4gIC8qKiBXYXRjaCBzaW5nbGUgZmllbGQgKi9cbiAgZmllbGQ6IHVzZVdhdGNoRmllbGQsXG4gIC8qKiBXYXRjaCBtdWx0aXBsZSBmaWVsZHMgKi9cbiAgZmllbGRzOiB1c2VXYXRjaEZpZWxkcyxcblxuICAvLyA9PT0gVVRJTElUWSBGVU5DVElPTlMgPT09XG4gIC8qKiBXYXRjaCB3aXRoIHRyYW5zZm9ybWF0aW9uICovXG4gIHRyYW5zZm9ybTogdXNlV2F0Y2hUcmFuc2Zvcm0sXG4gIC8qKiBXYXRjaCB3aXRoIGRlZmF1bHQgdmFsdWUgKi9cbiAgd2l0aERlZmF1bHQ6IHVzZVdhdGNoRGVmYXVsdCxcbiAgLyoqIFdhdGNoIGFzIGJvb2xlYW4gKi9cbiAgYm9vbGVhbjogdXNlV2F0Y2hCb29sZWFuLFxuICAvKiogV2F0Y2ggbXVsdGlwbGUgd2l0aCBjdXN0b20ga2V5cyAqL1xuICBiYXRjaDogdXNlV2F0Y2hCYXRjaCxcbiAgLyoqIFdhdGNoIGNvbmRpdGlvbmFsbHkgKi9cbiAgY29uZGl0aW9uYWw6IHVzZVdhdGNoQ29uZGl0aW9uYWwsXG4gIC8qKiBXYXRjaCB3aXRoIGRlYm91bmNpbmcgKi9cbiAgZGVib3VuY2VkOiB1c2VXYXRjaERlYm91bmNlZCxcbiAgLyoqIFdhdGNoIHdpdGggc2VsZWN0b3IgKi9cbiAgc2VsZWN0b3I6IHVzZVdhdGNoU2VsZWN0b3IsXG59IGFzIGNvbnN0O1xuIiwgImV4cG9ydCBjb25zdCBjYWxjdWxhdGVGaWx0ZXJDb3VudCA9IChtb2RlbDogb2JqZWN0KTogbnVtYmVyID0+XG4gIE9iamVjdC52YWx1ZXMobW9kZWwpLmZpbHRlcihcbiAgICB2ID0+IHYgIT09IG51bGwgJiYgdiAhPT0gdW5kZWZpbmVkICYmIFN0cmluZyh2KS50cmltKCkgIT09ICcnXG4gICkubGVuZ3RoO1xuIiwgImltcG9ydCB0eXBlIHsgRGF5anMsIE9wVW5pdFR5cGUgfSBmcm9tICdkYXlqcyc7XG5pbXBvcnQgZGF5anMgZnJvbSAnZGF5anMnO1xuaW1wb3J0IGR1cmF0aW9uIGZyb20gJ2RheWpzL3BsdWdpbi9kdXJhdGlvbic7XG5pbXBvcnQgcmVsYXRpdmVUaW1lIGZyb20gJ2RheWpzL3BsdWdpbi9yZWxhdGl2ZVRpbWUnO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQERvY3NcbiAqIGh0dHBzOi8vZGF5LmpzLm9yZy9kb2NzL2VuL2Rpc3BsYXkvZm9ybWF0XG4gKi9cblxuLyoqXG4gKiBEZWZhdWx0IHRpbWV6b25lc1xuICogaHR0cHM6Ly9kYXkuanMub3JnL2RvY3MvZW4vdGltZXpvbmUvc2V0LWRlZmF1bHQtdGltZXpvbmUjZG9jc05hdlxuICpcbiAqL1xuXG4vKipcbiAqIFVUQ1xuICogaHR0cHM6Ly9kYXkuanMub3JnL2RvY3MvZW4vcGx1Z2luL3V0Y1xuICogQGluc3RhbGxcbiAqIGltcG9ydCB1dGMgZnJvbSAnZGF5anMvcGx1Z2luL3V0Yyc7XG4gKiBkYXlqcy5leHRlbmQodXRjKTtcbiAqIEB1c2FnZVxuICogZGF5anMoKS51dGMoKS5mb3JtYXQoKVxuICpcbiAqL1xuXG5kYXlqcy5leHRlbmQoZHVyYXRpb24pO1xuZGF5anMuZXh0ZW5kKHJlbGF0aXZlVGltZSk7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZXhwb3J0IHR5cGUgRGF0ZVBpY2tlckZvcm1hdCA9XG4gIHwgRGF5anNcbiAgfCBEYXRlXG4gIHwgc3RyaW5nXG4gIHwgbnVtYmVyXG4gIHwgbnVsbFxuICB8IHVuZGVmaW5lZDtcblxuZXhwb3J0IGNvbnN0IGZvcm1hdFBhdHRlcm5zID0ge1xuICBkYXRlVGltZTogJ0REIE1NTSBZWVlZIGg6bW0gQScsIC8vIDE3IEFwciAyMDIyIDEyOjAwIGFtXG4gIGRhdGU6ICdERCBNTU0gWVlZWScsIC8vIDE3IEFwciAyMDIyXG4gIG1vbnRoX3llYXJfc2hvcnRfZm9ybWF0OiAnTU1NIFlZWVknLFxuICBtb250aF95ZWFyX2Z1bGxfZm9ybWF0OiAnTU1NTSBZWVlZJyxcbiAgeWVhcjogJ1lZWVknLFxuICB0aW1lOiAnaDptbSBhJywgLy8gMTI6MDAgYW1cbiAgc3BsaXQ6IHtcbiAgICBkYXRlVGltZTogJ0REL01NL1lZWVkgaDptbSBBJywgLy8gMTcvMDQvMjAyMiAxMjowMCBhbVxuICAgIGRhdGU6ICdERC9NTS9ZWVlZJywgLy8gMTcvMDQvMjAyMlxuICB9LFxuICBwYXJhbUNhc2U6IHtcbiAgICBkYXRlVGltZTogJ0RELU1NLVlZWVkgaDptbSBBJywgLy8gMTctMDQtMjAyMiAxMjowMCBhbVxuICAgIGRhdGU6ICdERC1NTS1ZWVlZJywgLy8gMTctMDQtMjAyMlxuICAgIGRhdGVSZXZlcnNlOiAnWVlZWS1NTS1ERCcsIC8vIDIwMjItMDQtMTcgZm9yIGNvbXBhcmUgZGF0ZVxuICAgIE1vbnRoWWVhcjogJ01NTS1ZWVlZJyxcbiAgfSxcbn07XG5cbmNvbnN0IGlzVmFsaWREYXRlID0gKGRhdGU6IERhdGVQaWNrZXJGb3JtYXQpID0+XG4gIGRhdGUgIT09IG51bGwgJiYgZGF0ZSAhPT0gdW5kZWZpbmVkICYmIGRheWpzKGRhdGUpLmlzVmFsaWQoKTtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5leHBvcnQgZnVuY3Rpb24gdG9kYXkodGVtcGxhdGU/OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gZGF5anMobmV3IERhdGUoKSkuc3RhcnRPZignZGF5JykuZm9ybWF0KHRlbXBsYXRlKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEBvdXRwdXQgMTcgQXByIDIwMjIgMTI6MDAgYW1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZEYXRlVGltZShkYXRlOiBEYXRlUGlja2VyRm9ybWF0LCB0ZW1wbGF0ZT86IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmICghaXNWYWxpZERhdGUoZGF0ZSkpIHtcbiAgICByZXR1cm4gJ0ludmFsaWQgZGF0ZSc7XG4gIH1cblxuICByZXR1cm4gZGF5anMoZGF0ZSkuZm9ybWF0KHRlbXBsYXRlID8/IGZvcm1hdFBhdHRlcm5zLmRhdGVUaW1lKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEBvdXRwdXQgMTcgQXByIDIwMjJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZEYXRlKGRhdGU6IERhdGVQaWNrZXJGb3JtYXQsIHRlbXBsYXRlPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKCFpc1ZhbGlkRGF0ZShkYXRlKSkge1xuICAgIHJldHVybiAnSW52YWxpZCBkYXRlJztcbiAgfVxuXG4gIHJldHVybiBkYXlqcyhkYXRlKS5mb3JtYXQodGVtcGxhdGUgPz8gZm9ybWF0UGF0dGVybnMuZGF0ZSk7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBAb3V0cHV0IDEyOjAwIGFtXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmVGltZShkYXRlOiBEYXRlUGlja2VyRm9ybWF0LCB0ZW1wbGF0ZT86IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmICghaXNWYWxpZERhdGUoZGF0ZSkpIHtcbiAgICByZXR1cm4gJ0ludmFsaWQgZGF0ZSc7XG4gIH1cblxuICByZXR1cm4gZGF5anMoZGF0ZSkuZm9ybWF0KHRlbXBsYXRlID8/IGZvcm1hdFBhdHRlcm5zLnRpbWUpO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQG91dHB1dCAxNzEzMjUwMTAwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmVGltZXN0YW1wKGRhdGU6IERhdGVQaWNrZXJGb3JtYXQpOiBudW1iZXIgfCAnSW52YWxpZCBkYXRlJyB7XG4gIGlmICghaXNWYWxpZERhdGUoZGF0ZSkpIHtcbiAgICByZXR1cm4gJ0ludmFsaWQgZGF0ZSc7XG4gIH1cblxuICByZXR1cm4gZGF5anMoZGF0ZSkudmFsdWVPZigpO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQG91dHB1dCBhIGZldyBzZWNvbmRzLCAyIHllYXJzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmVG9Ob3coZGF0ZTogRGF0ZVBpY2tlckZvcm1hdCk6IHN0cmluZyB7XG4gIGlmICghaXNWYWxpZERhdGUoZGF0ZSkpIHtcbiAgICByZXR1cm4gJ0ludmFsaWQgZGF0ZSc7XG4gIH1cblxuICByZXR1cm4gZGF5anMoZGF0ZSkudG9Ob3codHJ1ZSk7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBAb3V0cHV0IGJvb2xlYW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZJc0JldHdlZW4oXG4gIGlucHV0RGF0ZTogRGF0ZVBpY2tlckZvcm1hdCxcbiAgc3RhcnREYXRlOiBEYXRlUGlja2VyRm9ybWF0LFxuICBlbmREYXRlOiBEYXRlUGlja2VyRm9ybWF0XG4pOiBib29sZWFuIHtcbiAgaWYgKFxuICAgICFpc1ZhbGlkRGF0ZShpbnB1dERhdGUpIHx8XG4gICAgIWlzVmFsaWREYXRlKHN0YXJ0RGF0ZSkgfHxcbiAgICAhaXNWYWxpZERhdGUoZW5kRGF0ZSlcbiAgKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgZm9ybWF0dGVkSW5wdXREYXRlID0gZlRpbWVzdGFtcChpbnB1dERhdGUpO1xuICBjb25zdCBmb3JtYXR0ZWRTdGFydERhdGUgPSBmVGltZXN0YW1wKHN0YXJ0RGF0ZSk7XG4gIGNvbnN0IGZvcm1hdHRlZEVuZERhdGUgPSBmVGltZXN0YW1wKGVuZERhdGUpO1xuXG4gIGlmIChcbiAgICBmb3JtYXR0ZWRJbnB1dERhdGUgPT09ICdJbnZhbGlkIGRhdGUnIHx8XG4gICAgZm9ybWF0dGVkU3RhcnREYXRlID09PSAnSW52YWxpZCBkYXRlJyB8fFxuICAgIGZvcm1hdHRlZEVuZERhdGUgPT09ICdJbnZhbGlkIGRhdGUnXG4gICkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgZm9ybWF0dGVkSW5wdXREYXRlID49IGZvcm1hdHRlZFN0YXJ0RGF0ZSAmJlxuICAgIGZvcm1hdHRlZElucHV0RGF0ZSA8PSBmb3JtYXR0ZWRFbmREYXRlXG4gICk7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBAb3V0cHV0IGJvb2xlYW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZJc0FmdGVyKFxuICBzdGFydERhdGU6IERhdGVQaWNrZXJGb3JtYXQsXG4gIGVuZERhdGU6IERhdGVQaWNrZXJGb3JtYXRcbik6IGJvb2xlYW4ge1xuICBpZiAoIWlzVmFsaWREYXRlKHN0YXJ0RGF0ZSkgfHwgIWlzVmFsaWREYXRlKGVuZERhdGUpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIGRheWpzKHN0YXJ0RGF0ZSkuaXNBZnRlcihlbmREYXRlKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEBvdXRwdXQgYm9vbGVhblxuICovXG5leHBvcnQgZnVuY3Rpb24gZklzU2FtZShcbiAgc3RhcnREYXRlOiBEYXRlUGlja2VyRm9ybWF0LFxuICBlbmREYXRlOiBEYXRlUGlja2VyRm9ybWF0LFxuICB1bml0VG9Db21wYXJlPzogT3BVbml0VHlwZVxuKTogYm9vbGVhbiB7XG4gIGlmICghaXNWYWxpZERhdGUoc3RhcnREYXRlKSB8fCAhaXNWYWxpZERhdGUoZW5kRGF0ZSkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gZGF5anMoc3RhcnREYXRlKS5pc1NhbWUoZW5kRGF0ZSwgdW5pdFRvQ29tcGFyZSA/PyAneWVhcicpO1xufVxuXG4vKipcbiAqIEBvdXRwdXRcbiAqIFNhbWUgZGF5OiAyNiBBcHIgMjAyNFxuICogU2FtZSBtb250aDogMjUgLSAyNiBBcHIgMjAyNFxuICogU2FtZSBtb250aDogMjUgLSAyNiBBcHIgMjAyNFxuICogU2FtZSB5ZWFyOiAyNSBBcHIgLSAyNiBNYXkgMjAyNFxuICovXG5leHBvcnQgZnVuY3Rpb24gZkRhdGVSYW5nZVNob3J0TGFiZWwoXG4gIHN0YXJ0RGF0ZTogRGF0ZVBpY2tlckZvcm1hdCxcbiAgZW5kRGF0ZTogRGF0ZVBpY2tlckZvcm1hdCxcbiAgaW5pdGlhbD86IGJvb2xlYW5cbik6IHN0cmluZyB7XG4gIGlmIChcbiAgICAhaXNWYWxpZERhdGUoc3RhcnREYXRlKSB8fFxuICAgICFpc1ZhbGlkRGF0ZShlbmREYXRlKSB8fFxuICAgIGZJc0FmdGVyKHN0YXJ0RGF0ZSwgZW5kRGF0ZSlcbiAgKSB7XG4gICAgcmV0dXJuICdJbnZhbGlkIGRhdGUnO1xuICB9XG5cbiAgbGV0IGxhYmVsID0gYCR7ZkRhdGUoc3RhcnREYXRlKX0gLSAke2ZEYXRlKGVuZERhdGUpfWA7XG5cbiAgaWYgKGluaXRpYWwpIHtcbiAgICByZXR1cm4gbGFiZWw7XG4gIH1cblxuICBjb25zdCBpc1NhbWVZZWFyID0gZklzU2FtZShzdGFydERhdGUsIGVuZERhdGUsICd5ZWFyJyk7XG4gIGNvbnN0IGlzU2FtZU1vbnRoID0gZklzU2FtZShzdGFydERhdGUsIGVuZERhdGUsICdtb250aCcpO1xuICBjb25zdCBpc1NhbWVEYXkgPSBmSXNTYW1lKHN0YXJ0RGF0ZSwgZW5kRGF0ZSwgJ2RheScpO1xuXG4gIGlmIChpc1NhbWVZZWFyICYmICFpc1NhbWVNb250aCkge1xuICAgIGxhYmVsID0gYCR7ZkRhdGUoc3RhcnREYXRlLCAnREQgTU1NJyl9IC0gJHtmRGF0ZShlbmREYXRlKX1gO1xuICB9IGVsc2UgaWYgKGlzU2FtZVllYXIgJiYgaXNTYW1lTW9udGggJiYgIWlzU2FtZURheSkge1xuICAgIGxhYmVsID0gYCR7ZkRhdGUoc3RhcnREYXRlLCAnREQnKX0gLSAke2ZEYXRlKGVuZERhdGUpfWA7XG4gIH0gZWxzZSBpZiAoaXNTYW1lWWVhciAmJiBpc1NhbWVNb250aCAmJiBpc1NhbWVEYXkpIHtcbiAgICBsYWJlbCA9IGAke2ZEYXRlKGVuZERhdGUpfWA7XG4gIH1cblxuICByZXR1cm4gbGFiZWw7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBAb3V0cHV0IDIwMjQtMDUtMjhUMDU6NTU6MzErMDA6MDBcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEdXJhdGlvblByb3BzIHtcbiAgeWVhcnM/OiBudW1iZXI7XG4gIG1vbnRocz86IG51bWJlcjtcbiAgZGF5cz86IG51bWJlcjtcbiAgaG91cnM/OiBudW1iZXI7XG4gIG1pbnV0ZXM/OiBudW1iZXI7XG4gIHNlY29uZHM/OiBudW1iZXI7XG4gIG1pbGxpc2Vjb25kcz86IG51bWJlcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZBZGQoe1xuICB5ZWFycyA9IDAsXG4gIG1vbnRocyA9IDAsXG4gIGRheXMgPSAwLFxuICBob3VycyA9IDAsXG4gIG1pbnV0ZXMgPSAwLFxuICBzZWNvbmRzID0gMCxcbiAgbWlsbGlzZWNvbmRzID0gMCxcbn06IER1cmF0aW9uUHJvcHMpIHtcbiAgY29uc3QgcmVzdWx0ID0gZGF5anMoKVxuICAgIC5hZGQoXG4gICAgICBkYXlqcy5kdXJhdGlvbih7XG4gICAgICAgIHllYXJzLFxuICAgICAgICBtb250aHMsXG4gICAgICAgIGRheXMsXG4gICAgICAgIGhvdXJzLFxuICAgICAgICBtaW51dGVzLFxuICAgICAgICBzZWNvbmRzLFxuICAgICAgICBtaWxsaXNlY29uZHMsXG4gICAgICB9KVxuICAgIClcbiAgICAuZm9ybWF0KCk7XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBAb3V0cHV0IDIwMjQtMDUtMjhUMDU6NTU6MzErMDA6MDBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZTdWIoe1xuICB5ZWFycyA9IDAsXG4gIG1vbnRocyA9IDAsXG4gIGRheXMgPSAwLFxuICBob3VycyA9IDAsXG4gIG1pbnV0ZXMgPSAwLFxuICBzZWNvbmRzID0gMCxcbiAgbWlsbGlzZWNvbmRzID0gMCxcbn06IER1cmF0aW9uUHJvcHMpIHtcbiAgY29uc3QgcmVzdWx0ID0gZGF5anMoKVxuICAgIC5zdWJ0cmFjdChcbiAgICAgIGRheWpzLmR1cmF0aW9uKHtcbiAgICAgICAgeWVhcnMsXG4gICAgICAgIG1vbnRocyxcbiAgICAgICAgZGF5cyxcbiAgICAgICAgaG91cnMsXG4gICAgICAgIG1pbnV0ZXMsXG4gICAgICAgIHNlY29uZHMsXG4gICAgICAgIG1pbGxpc2Vjb25kcyxcbiAgICAgIH0pXG4gICAgKVxuICAgIC5mb3JtYXQoKTtcblxuICByZXR1cm4gcmVzdWx0O1xufVxuIiwgInR5cGUgRW1wdHlWYWx1ZTxUPiA9IFQgZXh0ZW5kcyBudW1iZXJcbiAgPyAwXG4gIDogVCBleHRlbmRzIHN0cmluZ1xuICAgID8gbnVsbFxuICAgIDogVCBleHRlbmRzIGJvb2xlYW5cbiAgICAgID8gbnVsbFxuICAgICAgOiBUIGV4dGVuZHMgRGF0ZVxuICAgICAgICA/IG51bGxcbiAgICAgICAgOiBUIGV4dGVuZHMgb2JqZWN0XG4gICAgICAgICAgPyBudWxsXG4gICAgICAgICAgOiBudWxsO1xuXG50eXBlIEVtcHR5T2JqZWN0PFQgZXh0ZW5kcyBvYmplY3Q+ID0ge1xuICBbSyBpbiBrZXlvZiBUXTogRW1wdHlWYWx1ZTxUW0tdPjtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRFbXB0eU9iamVjdDxUIGV4dGVuZHMgb2JqZWN0PihcbiAgZGF0YTogVCxcbiAgZGVmYXVsdFZhbHVlczogUGFydGlhbDxUPiA9IHt9XG4pOiBFbXB0eU9iamVjdDxUPiAmIFBhcnRpYWw8VD4ge1xuICBjb25zdCBvYmogPSB7fSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhkYXRhKSBhcyBBcnJheTxrZXlvZiBUPikge1xuICAgIGNvbnN0IHZhbHVlID0gZGF0YVtrZXldO1xuICAgIGNvbnN0IHR5cGUgPSB0eXBlb2YgdmFsdWU7XG5cbiAgICBpZiAodHlwZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIG9ialtrZXkgYXMgc3RyaW5nXSA9IDA7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJyB8fCB0eXBlID09PSAnYm9vbGVhbicpIHtcbiAgICAgIG9ialtrZXkgYXMgc3RyaW5nXSA9IG51bGw7XG4gICAgfSBlbHNlIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgIG9ialtrZXkgYXMgc3RyaW5nXSA9IG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIG9ialtrZXkgYXMgc3RyaW5nXSA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgLi4ub2JqLCAuLi5kZWZhdWx0VmFsdWVzIH0gYXMgRW1wdHlPYmplY3Q8VD4gJiBQYXJ0aWFsPFQ+O1xufVxuIiwgImltcG9ydCB7IHVzZVJlZiwgdXNlTWVtbyB9IGZyb20gJ3JlYWN0JztcblxuLyoqXG4gKiBIb29rIHRvIG1haW50YWluIHN0YWJsZSByb3cgY291bnQgZm9yIGRhdGEgZ3JpZHMgZHVyaW5nIGxvYWRpbmcgc3RhdGVzLlxuICogUHJldmVudHMgcGFnaW5hdGlvbiBqdW1waW5nIGJ5IHByZXNlcnZpbmcgdGhlIGxhc3Qga25vd24gdG90YWwgY291bnQuXG4gKlxuICogQHBhcmFtIGN1cnJlbnRUb3RhbCAtIEN1cnJlbnQgdG90YWwgZnJvbSBBUEkgcmVzcG9uc2VcbiAqIEByZXR1cm5zIFN0YWJsZSByb3cgY291bnQgdGhhdCBwZXJzaXN0cyBkdXJpbmcgbG9hZGluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlU3RhYmxlUm93Q291bnQoY3VycmVudFRvdGFsOiBudW1iZXIgfCB1bmRlZmluZWQpOiBudW1iZXIge1xuICBjb25zdCByb3dDb3VudFJlZiA9IHVzZVJlZihjdXJyZW50VG90YWwgfHwgMCk7XG5cbiAgY29uc3Qgc3RhYmxlUm93Q291bnQgPSB1c2VNZW1vKCgpID0+IHtcbiAgICBpZiAoY3VycmVudFRvdGFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJvd0NvdW50UmVmLmN1cnJlbnQgPSBjdXJyZW50VG90YWw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJvd0NvdW50UmVmLmN1cnJlbnQ7XG4gIH0sIFtjdXJyZW50VG90YWxdKTtcblxuICByZXR1cm4gc3RhYmxlUm93Q291bnQ7XG59XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBd0JBLFNBQVMsZUFBdUI7QUFDOUIsTUFBSSxPQUFPLFdBQVcsZUFBZSxPQUFPLFlBQVk7QUFDdEQsV0FBTyxPQUFPLFdBQVc7QUFBQSxFQUMzQjtBQUdBLFNBQU8sdUNBQXVDLFFBQVEsU0FBUyxPQUFLO0FBQ2xFLFVBQU0sSUFBSyxLQUFLLE9BQU8sSUFBSSxLQUFNO0FBQ2pDLFVBQU0sSUFBSSxNQUFNLE1BQU0sSUFBSyxJQUFJLElBQU87QUFFdEMsV0FBTyxFQUFFLFNBQVMsRUFBRTtBQUFBLEVBQ3RCLENBQUM7QUFDSDtBQTRDTyxTQUFTLHNCQUFzQixRQUF5QjtBQUM3RCxRQUFNLE9BQU8sYUFBYTtBQUUxQixTQUFPLFNBQVMsR0FBRyxNQUFNLElB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U0FBUSxNQUFNO0FBQ25DLFFBQUksaUJBQWlCLFFBQVc7QUFDOUIsa0JBQVksVUFBVTtBQUFBLElBQ3hCO0FBRUEsV0FBTyxZQUFZO0FBQUEsRUFDckIsR0FBRyxDQUFDLFlBQVksQ0FBQztBQUVqQixTQUFPO0FBQ1Q7IiwKICAibmFtZXMiOiBbImNvbmZpZyIsICJqc3giLCAiQnV0dG9uIiwgImpzeCIsICJqc3giLCAianN4IiwgImpzeCIsICJtZW1vIiwgImpzeCIsICJtZW1vIiwgIkJveCIsICJDYXJkIiwgIkNhcmRDb250ZW50IiwgIlR5cG9ncmFwaHkiLCAiRnJhZ21lbnQiLCAianN4IiwgImpzeHMiLCAiQm94IiwgIlR5cG9ncmFwaHkiLCAianN4IiwgIkdyaWQiLCAiVHlwb2dyYXBoeSIsICJqc3giLCAianN4cyIsICJGcmFnbWVudCIsICJqc3giLCAiQm94IiwgIkRpdmlkZXIiLCAiR3JpZCIsICJUeXBvZ3JhcGh5IiwgIm1lbW8iLCAidXNlTWVtbyIsICJGcmFnbWVudCIsICJqc3giLCAianN4cyIsICJCb3giLCAianN4IiwgImpzeHMiLCAiTG9hZGluZ0J1dHRvbiIsICJqc3giLCAidXNlTWVtbyIsICJ1c2VNZW1vIiwgInVzZUNhbGxiYWNrIiwgInVzZU1lbW8iLCAidXNlTWVtbyIsICJ1c2VTdGF0ZSIsICJ1c2VXYXRjaCIsICJ1c2VNZW1vIl0KfQo=