@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
@@ -0,0 +1,2512 @@
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,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2NvcmUvYXBpL0NvcnJlbGF0aW9uSWRHZW5lcmF0b3IudHMiLCAiLi4vc3JjL2NvcmUvYXBpL0Vycm9ycy9FcnJvck5vcm1hbGl6ZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL0ludGVyY2VwdG9ycy9JbnRlcmNlcHRvck1hbmFnZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL1JlcXVlc3RNYW5hZ2VyLnRzIiwgIi4uL3NyYy9jb3JlL2FwaS9SZXRyeS9SZXRyeUhhbmRsZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL1NpZ25hbHMvU2lnbmFsTWFuYWdlci50cyIsICIuLi9zcmMvY29yZS9hcGkvVXRpbHMvUmVzcG9uc2VQYXJzZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL1V0aWxzL1VybEJ1aWxkZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL0FwaUNsaWVudC50cyIsICIuLi9zcmMvY29yZS9hcGkvY3JlYXRlQXBpQ2xpZW50LnRzIiwgIi4uL3NyYy9jb3JlL2FwaS90eXBlcy9DYW5jZWxUb2tlbi50cyIsICIuLi9zcmMvY29yZS9hcGkvdXNlVmFsaWRhdGlvbkVycm9ycy50cyIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL0F1dGhvcml6ZWRWaWV3L0F1dGhvcml6ZWRWaWV3LnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL0NhbmNlbEJ1dHRvbi9DYW5jZWxCdXR0b24udHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvQ2xlYXJCdXR0b24vQ2xlYXJCdXR0b24udHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvQ29udGFpbmVycy9TaW1wbGVDb250YWluZXIudHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvRmlsdGVyQnV0dG9uL0ZpbHRlckJ1dHRvbi50c3giLCAiLi4vc3JjL2NvcmUvY29tcG9uZW50cy9GaWx0ZXJEaXNwbGF5L0ZpbHRlckNoaXAudHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvRmlsdGVyRGlzcGxheS9GaWx0ZXJEaXNwbGF5LnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL0ZpbHRlcldyYXBwZXIvRmlsdGVyV3JhcHBlci50c3giLCAiLi4vc3JjL2NvcmUvY29tcG9uZW50cy9Gb290ZXIvRm9vdGVyLnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL0xhYmVsVGV4dC9MYWJlbFRleHQudHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvUmVuZGVySWYvUmVuZGVySWYudHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvU2VjdGlvbkJveC9TZWN0aW9uQm94LnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL1NpbXBsZVRhYnMvU2ltcGxlVGFicy50c3giLCAiLi4vc3JjL2NvcmUvY29tcG9uZW50cy9TdWJtaXRCdXR0b24vU3VibWl0QnV0dG9uLnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL1dpdGhSZWYvV2l0aFJlZi50c3giLCAiLi4vc3JjL2NvcmUvY29uZmlnLnRzIiwgIi4uL3NyYy9jb3JlL2hvb2tzL3VzZUFwaUNsaWVudC50cyIsICIuLi9zcmMvY29yZS9ob29rcy91c2VGb3JtRXJyb3JIYW5kbGVyLnRzIiwgIi4uL3NyYy9jb3JlL3V0aWxzL0NhY2hlVXRpbGl0eS9pbmRleC50cyIsICIuLi9zcmMvY29yZS91dGlscy93YXRjaC9jb3JlLnRzIiwgIi4uL3NyYy9jb3JlL3V0aWxzL3dhdGNoL3V0aWxpdGllcy50cyIsICIuLi9zcmMvY29yZS91dGlscy93YXRjaC9pbmRleC50cyIsICIuLi9zcmMvY29yZS91dGlscy9jYWxjdWxhdGVGaWx0ZXJDb3VudC50cyIsICIuLi9zcmMvY29yZS91dGlscy9mb3JtYXQtdGltZS50cyIsICIuLi9zcmMvY29yZS91dGlscy9nZXRFbXB0eU9iamVjdC50cyIsICIuLi9zcmMvY29yZS91dGlscy91c2VTdGFibGVSb3dDb3VudC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IFV0aWxpdGllcyBmb3IgZ2VuZXJhdGluZyBjb3JyZWxhdGlvbiBJRHMgZm9yIGRpc3RyaWJ1dGVkIHJlcXVlc3QgdHJhY2luZy5cbiAqXG4gKiBDb3JyZWxhdGlvbiBJRHMgYXJlIHVuaXF1ZSBpZGVudGlmaWVycyBhdHRhY2hlZCB0byBlYWNoIEFQSSByZXF1ZXN0IHRvIGVuYWJsZVxuICogdHJhY2tpbmcgYW5kIGRlYnVnZ2luZyBhY3Jvc3MgZGlzdHJpYnV0ZWQgc3lzdGVtcywgbWljcm9zZXJ2aWNlcywgYW5kIGxvZyBhZ2dyZWdhdGlvbi5cbiAqXG4gKiBAbW9kdWxlIENvcnJlbGF0aW9uSWRHZW5lcmF0b3JcbiAqL1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIGNyeXB0b2dyYXBoaWNhbGx5IHJhbmRvbSBVVUlEIHY0IHN0cmluZy5cbiAqXG4gKiBQcmVmZXJzIG5hdGl2ZSBgY3J5cHRvLnJhbmRvbVVVSUQoKWAgd2hlbiBhdmFpbGFibGUgKG1vZGVybiBicm93c2VycyBhbmQgTm9kZS5qcyAxOSspLFxuICogZmFsbGluZyBiYWNrIHRvIGEgY29tcGxpYW50IFVVSUQgdjQgaW1wbGVtZW50YXRpb24gdXNpbmcgYE1hdGgucmFuZG9tKClgLlxuICpcbiAqIEBpbnRlcm5hbCBUaGlzIGZ1bmN0aW9uIGlzIG5vdCBleHBvcnRlZCBmcm9tIHRoZSBwdWJsaWMgQVBJXG4gKiBAcmV0dXJucyBBIFVVSUQgdjQgc3RyaW5nIGluIHRoZSBmb3JtYXQgYHh4eHh4eHh4LXh4eHgtNHh4eC15eHh4LXh4eHh4eHh4eHh4eGBcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgdXVpZCA9IGdlbmVyYXRlVVVJRCgpO1xuICogLy8gPT4gXCJhMWIyYzNkNC1lNWY2LTQ3ODktYTAxMi1iM2M0ZDVlNmY3YThcIlxuICogYGBgXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlVVVJRCgpOiBzdHJpbmcge1xuICBpZiAodHlwZW9mIGNyeXB0byAhPT0gJ3VuZGVmaW5lZCcgJiYgY3J5cHRvLnJhbmRvbVVVSUQpIHtcbiAgICByZXR1cm4gY3J5cHRvLnJhbmRvbVVVSUQoKTtcbiAgfVxuXG4gIC8vIEZhbGxiYWNrIFVVSUQgdjQgZ2VuZXJhdG9yXG4gIHJldHVybiAneHh4eHh4eHgteHh4eC00eHh4LXl4eHgteHh4eHh4eHh4eHh4Jy5yZXBsYWNlKC9beHldL2csIGMgPT4ge1xuICAgIGNvbnN0IHIgPSAoTWF0aC5yYW5kb20oKSAqIDE2KSB8IDA7XG4gICAgY29uc3QgdiA9IGMgPT09ICd4JyA/IHIgOiAociAmIDB4MykgfCAweDg7XG5cbiAgICByZXR1cm4gdi50b1N0cmluZygxNik7XG4gIH0pO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBjb3JyZWxhdGlvbiBJRCBmb3IgQVBJIHJlcXVlc3QgdHJhY2tpbmcgYW5kIGRpc3RyaWJ1dGVkIHRyYWNpbmcuXG4gKlxuICogQ29ycmVsYXRpb24gSURzIGhlbHAgdHJhY2sgcmVxdWVzdHMgYWNyb3NzIG11bHRpcGxlIHNlcnZpY2VzIGFuZCBzeXN0ZW1zLiBUaGV5IGFyZVxuICogYXV0b21hdGljYWxseSBhdHRhY2hlZCB0byBvdXRnb2luZyByZXF1ZXN0cyB2aWEgSFRUUCBoZWFkZXJzIChgWC1Db3JyZWxhdGlvbi1JZGAgYW5kXG4gKiBgWC1SZXF1ZXN0LUlkYCkgYW5kIGNhbiBiZSB1c2VkIHRvOlxuICogLSBDb3JyZWxhdGUgbG9ncyBhY3Jvc3MgZGlzdHJpYnV0ZWQgc3lzdGVtc1xuICogLSBUcmFjayByZXF1ZXN0IGZsb3dzIGluIG1pY3Jvc2VydmljZXMgYXJjaGl0ZWN0dXJlc1xuICogLSBEZWJ1ZyBpc3N1ZXMgYnkgdHJhY2luZyBhIHNwZWNpZmljIHJlcXVlc3QncyBqb3VybmV5XG4gKiAtIE1vbml0b3IgcGVyZm9ybWFuY2UgYWNyb3NzIHNlcnZpY2UgYm91bmRhcmllc1xuICpcbiAqIFRoZSBnZW5lcmF0ZWQgSUQgZm9sbG93cyB0aGUgZm9ybWF0OiBge3ByZWZpeH0te3V1aWR9YCBvciBqdXN0IGB7dXVpZH1gIGlmIG5vIHByZWZpeCBpcyBwcm92aWRlZC5cbiAqXG4gKiBAcGFyYW0gcHJlZml4IC0gT3B0aW9uYWwgcHJlZml4IHRvIG5hbWVzcGFjZSBjb3JyZWxhdGlvbiBJRHMgYnkgY29udGV4dCAoZS5nLiwgJ2FwaScsICd3ZWInLCAnbW9iaWxlJylcbiAqIEByZXR1cm5zIEEgY29ycmVsYXRpb24gSUQgc3RyaW5nLCBvcHRpb25hbGx5IHByZWZpeGVkXG4gKiBAcHVibGljXG4gKlxuICogQGV4YW1wbGVcbiAqIEJhc2ljIHVzYWdlOlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgaWQgPSBnZW5lcmF0ZUNvcnJlbGF0aW9uSWQoKTtcbiAqIC8vID0+IFwiYTFiMmMzZDQtZTVmNi00Nzg5LWEwMTItYjNjNGQ1ZTZmN2E4XCJcbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBXaXRoIHByZWZpeCBmb3IgY29udGV4dCBpZGVudGlmaWNhdGlvbjpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHdlYklkID0gZ2VuZXJhdGVDb3JyZWxhdGlvbklkKCd3ZWInKTtcbiAqIC8vID0+IFwid2ViLWExYjJjM2Q0LWU1ZjYtNDc4OS1hMDEyLWIzYzRkNWU2ZjdhOFwiXG4gKlxuICogY29uc3QgYXBpSWQgPSBnZW5lcmF0ZUNvcnJlbGF0aW9uSWQoJ2FwaScpO1xuICogLy8gPT4gXCJhcGktZjFlMmQzYzQtYjVhNi00OTg3LWEwMTItYjNjNGQ1ZTZmN2E4XCJcbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBDb25maWd1cmluZyBpbiBBcGlDbGllbnQ6XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBjbGllbnQgPSBuZXcgQXBpQ2xpZW50KCdodHRwczovL2FwaS5leGFtcGxlLmNvbScpO1xuICogY2xpZW50LnNldENvcnJlbGF0aW9uSWRQcmVmaXgoJ21vYmlsZScpO1xuICogLy8gQWxsIHJlcXVlc3RzIHdpbGwgaGF2ZSBjb3JyZWxhdGlvbiBJRHMgbGlrZSBcIm1vYmlsZS17dXVpZH1cIlxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZUNvcnJlbGF0aW9uSWQocHJlZml4Pzogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgdXVpZCA9IGdlbmVyYXRlVVVJRCgpO1xuXG4gIHJldHVybiBwcmVmaXggPyBgJHtwcmVmaXh9LSR7dXVpZH1gIDogdXVpZDtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IEFwaUVycm9yLCBBcGlFcnJvclR5cGUgfSBmcm9tICcuLi90eXBlcy9BcGlFcnJvcic7XHJcbmltcG9ydCB0eXBlIHsgUmVxdWVzdENvbmZpZyB9IGZyb20gJy4uL3R5cGVzL1JlcXVlc3RDb25maWcnO1xyXG5cclxuLyoqXHJcbiAqIE5vcm1hbGl6ZXMgdmFyaW91cyBlcnJvciB0eXBlcyBpbnRvIGEgY29uc2lzdGVudCwgc3RydWN0dXJlZCBBcGlFcnJvciBmb3JtYXQuXHJcbiAqXHJcbiAqIFRoaXMgaW50ZXJuYWwgY2xhc3MgaGFuZGxlcyB0aGUgY29tcGxleCB0YXNrIG9mIGNvbnZlcnRpbmcgYW55IHR5cGUgb2YgZXJyb3JcclxuICogKG5ldHdvcmsgZXJyb3JzLCBIVFRQIGVycm9ycywgYWJvcnQgZXJyb3JzLCB0aW1lb3V0cywgZXRjLikgaW50byBhIHN0YW5kYXJkaXplZFxyXG4gKiB7QGxpbmsgQXBpRXJyb3J9IHN0cnVjdHVyZSB3aXRoIHByb3BlciBjYXRlZ29yaXphdGlvbiBhbmQgbWV0YWRhdGEuXHJcbiAqXHJcbiAqIEtleSBGZWF0dXJlczpcclxuICogLSAqKkVycm9yIENhdGVnb3JpemF0aW9uKio6IENsYXNzaWZpZXMgZXJyb3JzIGJ5IHR5cGUgKHZhbGlkYXRpb24sIGNsaWVudCwgc2VydmVyLCBuZXR3b3JrLCBldGMuKVxyXG4gKiAtICoqSFRUUCBTdGF0dXMgTWFwcGluZyoqOiBDb252ZXJ0cyBzdGF0dXMgY29kZXMgdG8gaHVtYW4tcmVhZGFibGUgdGl0bGVzXHJcbiAqIC0gKipDb3JyZWxhdGlvbiBJRCBUcmFja2luZyoqOiBQcmVzZXJ2ZXMgb3IgaW5qZWN0cyBjb3JyZWxhdGlvbiBJRHMgZm9yIHRyYWNpbmdcclxuICogLSAqKkFib3J0IERldGVjdGlvbioqOiBJZGVudGlmaWVzIGFuZCBwcm9wZXJseSBoYW5kbGVzIHJlcXVlc3QgY2FuY2VsbGF0aW9uc1xyXG4gKiAtICoqQ29uc2lzdGVudCBTdHJ1Y3R1cmUqKjogRW5zdXJlcyBhbGwgZXJyb3JzIGNvbmZvcm0gdG8gdGhlIEFwaUVycm9yIGludGVyZmFjZVxyXG4gKlxyXG4gKiBAaW50ZXJuYWwgVGhpcyBjbGFzcyBpcyBub3QgZXhwb3J0ZWQgZnJvbSB0aGUgcHVibGljIEFQSVxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEVycm9yTm9ybWFsaXplciB7XHJcbiAgLyoqXHJcbiAgICogTWFwcyBhbiBIVFRQIHN0YXR1cyBjb2RlIHRvIGEgc3RhbmRhcmRpemVkIGVycm9yIHR5cGUgY2F0ZWdvcnkuXHJcbiAgICpcclxuICAgKiBUaGlzIGNhdGVnb3JpemF0aW9uIGhlbHBzIGNvbnN1bWVycyBoYW5kbGUgZGlmZmVyZW50IGVycm9yIGNsYXNzZXMgYXBwcm9wcmlhdGVseTpcclxuICAgKiAtIGB2YWxpZGF0aW9uX2Vycm9yYCAoNDAwKTogQ2xpZW50IHNlbnQgaW52YWxpZCBkYXRhXHJcbiAgICogLSBgY2xpZW50X2Vycm9yYCAoNDAxLTQ5OSk6IENsaWVudC1zaWRlIGlzc3VlcyAoYXV0aCwgcGVybWlzc2lvbnMsIG5vdCBmb3VuZCwgZXRjLilcclxuICAgKiAtIGBzZXJ2ZXJfZXJyb3JgICg1MDAtNTk5KTogU2VydmVyLXNpZGUgZmFpbHVyZXNcclxuICAgKiAtIGB1bmtub3duX2Vycm9yYDogVW5yZWNvZ25pemVkIHN0YXR1cyBjb2Rlc1xyXG4gICAqXHJcbiAgICogQHBhcmFtIHN0YXR1cyAtIEhUVFAgc3RhdHVzIGNvZGUgZnJvbSB0aGUgcmVzcG9uc2VcclxuICAgKiBAcmV0dXJucyBUaGUgZXJyb3IgdHlwZSBjYXRlZ29yeSBhcyBhIHN0cmluZ1xyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBgYGB0eXBlc2NyaXB0XHJcbiAgICogbm9ybWFsaXplci5nZXRFcnJvclR5cGUoNDAwKTsgLy8gPT4gJ3ZhbGlkYXRpb25fZXJyb3InXHJcbiAgICogbm9ybWFsaXplci5nZXRFcnJvclR5cGUoNDA0KTsgLy8gPT4gJ2NsaWVudF9lcnJvcidcclxuICAgKiBub3JtYWxpemVyLmdldEVycm9yVHlwZSg1MDApOyAvLyA9PiAnc2VydmVyX2Vycm9yJ1xyXG4gICAqIG5vcm1hbGl6ZXIuZ2V0RXJyb3JUeXBlKDApOyAgIC8vID0+ICd1bmtub3duX2Vycm9yJ1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIGdldEVycm9yVHlwZShzdGF0dXM6IG51bWJlcik6IEFwaUVycm9yVHlwZSB7XHJcbiAgICBpZiAoc3RhdHVzID49IDQwMCAmJiBzdGF0dXMgPCA1MDApIHtcclxuICAgICAgcmV0dXJuIHN0YXR1cyA9PT0gNDAwID8gJ3ZhbGlkYXRpb25fZXJyb3InIDogJ2NsaWVudF9lcnJvcic7XHJcbiAgICB9IGVsc2UgaWYgKHN0YXR1cyA+PSA1MDApIHtcclxuICAgICAgcmV0dXJuICdzZXJ2ZXJfZXJyb3InO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiAndW5rbm93bl9lcnJvcic7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNYXBzIGFuIEhUVFAgc3RhdHVzIGNvZGUgdG8gYSBodW1hbi1yZWFkYWJsZSBlcnJvciB0aXRsZS5cclxuICAgKlxyXG4gICAqIFByb3ZpZGVzIHVzZXItZnJpZW5kbHkgZXJyb3IgbWVzc2FnZXMgZm9yIGNvbW1vbiBIVFRQIHN0YXR1cyBjb2Rlcy5cclxuICAgKiBGYWxscyBiYWNrIHRvIGEgZ2VuZXJpYyBcIkhUVFAgRXJyb3Ige3N0YXR1c31cIiBmb3JtYXQgZm9yIHVubWFwcGVkIGNvZGVzLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHN0YXR1cyAtIEhUVFAgc3RhdHVzIGNvZGUgZnJvbSB0aGUgcmVzcG9uc2VcclxuICAgKiBAcmV0dXJucyBBIGh1bWFuLXJlYWRhYmxlIGVycm9yIHRpdGxlXHJcbiAgICpcclxuICAgKiBAZXhhbXBsZVxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBub3JtYWxpemVyLmdldEVycm9yVGl0bGUoNDA0KTsgLy8gPT4gJ05vdCBGb3VuZCdcclxuICAgKiBub3JtYWxpemVyLmdldEVycm9yVGl0bGUoNTAwKTsgLy8gPT4gJ0ludGVybmFsIFNlcnZlciBFcnJvcidcclxuICAgKiBub3JtYWxpemVyLmdldEVycm9yVGl0bGUoOTk5KTsgLy8gPT4gJ0hUVFAgRXJyb3IgOTk5J1xyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIGdldEVycm9yVGl0bGUoc3RhdHVzOiBudW1iZXIpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgdGl0bGVzOiBSZWNvcmQ8bnVtYmVyLCBzdHJpbmc+ID0ge1xyXG4gICAgICA0MDA6ICdCYWQgUmVxdWVzdCcsXHJcbiAgICAgIDQwMTogJ1VuYXV0aG9yaXplZCcsXHJcbiAgICAgIDQwMzogJ0ZvcmJpZGRlbicsXHJcbiAgICAgIDQwNDogJ05vdCBGb3VuZCcsXHJcbiAgICAgIDQwNTogJ01ldGhvZCBOb3QgQWxsb3dlZCcsXHJcbiAgICAgIDQwODogJ1JlcXVlc3QgVGltZW91dCcsXHJcbiAgICAgIDQwOTogJ0NvbmZsaWN0JyxcclxuICAgICAgNDIyOiAnVW5wcm9jZXNzYWJsZSBFbnRpdHknLFxyXG4gICAgICA0Mjk6ICdUb28gTWFueSBSZXF1ZXN0cycsXHJcbiAgICAgIDUwMDogJ0ludGVybmFsIFNlcnZlciBFcnJvcicsXHJcbiAgICAgIDUwMjogJ0JhZCBHYXRld2F5JyxcclxuICAgICAgNTAzOiAnU2VydmljZSBVbmF2YWlsYWJsZScsXHJcbiAgICAgIDUwNDogJ0dhdGV3YXkgVGltZW91dCcsXHJcbiAgICB9O1xyXG5cclxuICAgIHJldHVybiB0aXRsZXNbc3RhdHVzXSB8fCBgSFRUUCBFcnJvciAke3N0YXR1c31gO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTm9ybWFsaXplcyBhbnkgZXJyb3IgaW50byBhIGNvbnNpc3RlbnQsIHN0cnVjdHVyZWQgQXBpRXJyb3IgZm9ybWF0LlxyXG4gICAqXHJcbiAgICogVGhpcyBtZXRob2QgaGFuZGxlcyB2YXJpb3VzIGVycm9yIHNjZW5hcmlvcyBhbmQgZW5zdXJlcyB0aGV5IGFsbCBjb25mb3JtIHRvXHJcbiAgICogdGhlIHtAbGluayBBcGlFcnJvcn0gaW50ZXJmYWNlIHdpdGggYXBwcm9wcmlhdGUgY2F0ZWdvcml6YXRpb24gYW5kIG1ldGFkYXRhOlxyXG4gICAqXHJcbiAgICogLSAqKkV4aXN0aW5nIEFwaUVycm9ycyoqOiBFbmhhbmNlcyB3aXRoIG1pc3NpbmcgZmllbGRzICh0cmFjZUlkLCBjb25maWcpXHJcbiAgICogLSAqKkFib3J0RXJyb3JzKio6IE1hcmtzIGFzIGByZXF1ZXN0X2NhbmNlbGxlZGAgd2l0aCBpc0Fib3J0ZWQgZmxhZ1xyXG4gICAqIC0gKipUaW1lb3V0IEVycm9ycyoqOiBDYXRlZ29yaXplcyBhcyBgdGltZW91dF9lcnJvcmAgd2l0aCA0MDggc3RhdHVzXHJcbiAgICogLSAqKk5ldHdvcmsgRXJyb3JzKio6IENhdGVnb3JpemVzIGFzIGBuZXR3b3JrX2Vycm9yYCB3aXRoIDAgc3RhdHVzXHJcbiAgICogLSAqKlVua25vd24gRXJyb3JzKio6IEZhbGxiYWNrIGNhdGVnb3J5IGZvciB1bmV4cGVjdGVkIGVycm9yIHR5cGVzXHJcbiAgICpcclxuICAgKiBBbGwgbm9ybWFsaXplZCBlcnJvcnMgaW5jbHVkZTpcclxuICAgKiAtIGB0eXBlYDogRXJyb3IgY2F0ZWdvcnkgZm9yIHByb2dyYW1tYXRpYyBoYW5kbGluZ1xyXG4gICAqIC0gYHRpdGxlYDogSHVtYW4tcmVhZGFibGUgZXJyb3IgdGl0bGVcclxuICAgKiAtIGBzdGF0dXNgOiBIVFRQIHN0YXR1cyBjb2RlIChvciAwIGZvciBub24tSFRUUCBlcnJvcnMpXHJcbiAgICogLSBgdHJhY2VJZGA6IENvcnJlbGF0aW9uIElEIGZvciBkaXN0cmlidXRlZCB0cmFjaW5nXHJcbiAgICogLSBgaXNBYm9ydGVkYDogQm9vbGVhbiBmbGFnIGluZGljYXRpbmcgaWYgcmVxdWVzdCB3YXMgY2FuY2VsbGVkXHJcbiAgICogLSBgY29uZmlnYDogT3JpZ2luYWwgcmVxdWVzdCBjb25maWd1cmF0aW9uIGZvciBkZWJ1Z2dpbmdcclxuICAgKlxyXG4gICAqIEBwYXJhbSBlcnJvciAtIFRoZSBlcnJvciB0byBub3JtYWxpemUgKGNhbiBiZSBhbnkgdHlwZSlcclxuICAgKiBAcGFyYW0gY29uZmlnIC0gVGhlIHJlcXVlc3QgY29uZmlndXJhdGlvbiB0aGF0IGxlZCB0byB0aGlzIGVycm9yXHJcbiAgICogQHBhcmFtIGNvcnJlbGF0aW9uSWQgLSBPcHRpb25hbCBjb3JyZWxhdGlvbiBJRCBmb3IgdHJhY2luZ1xyXG4gICAqIEByZXR1cm5zIEEgZnVsbHkgc3RydWN0dXJlZCBBcGlFcnJvciBpbnN0YW5jZVxyXG4gICAqXHJcbiAgICogQGV4YW1wbGVcclxuICAgKiBOb3JtYWxpemluZyBhIGZldGNoIEFib3J0RXJyb3I6XHJcbiAgICogYGBgdHlwZXNjcmlwdFxyXG4gICAqIHRyeSB7XHJcbiAgICogICBhd2FpdCBmZXRjaCh1cmwsIHsgc2lnbmFsIH0pO1xyXG4gICAqIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICogICBjb25zdCBhcGlFcnJvciA9IG5vcm1hbGl6ZXIubm9ybWFsaXplRXJyb3IoZXJyb3IsIGNvbmZpZywgJ3JlcS0xMjMnKTtcclxuICAgKiAgIC8vIGFwaUVycm9yLnR5cGUgPT09ICdyZXF1ZXN0X2NhbmNlbGxlZCdcclxuICAgKiAgIC8vIGFwaUVycm9yLmlzQWJvcnRlZCA9PT0gdHJ1ZVxyXG4gICAqIH1cclxuICAgKiBgYGBcclxuICAgKlxyXG4gICAqIEBleGFtcGxlXHJcbiAgICogTm9ybWFsaXppbmcgYSB0aW1lb3V0OlxyXG4gICAqIGBgYHR5cGVzY3JpcHRcclxuICAgKiBjb25zdCB0aW1lb3V0RXJyb3IgPSBuZXcgRXJyb3IoJ1JlcXVlc3QgdGltZW91dCBhZnRlciAzMDAwMG1zJyk7XHJcbiAgICogY29uc3QgYXBpRXJyb3IgPSBub3JtYWxpemVyLm5vcm1hbGl6ZUVycm9yKHRpbWVvdXRFcnJvciwgY29uZmlnKTtcclxuICAgKiAvLyBhcGlFcnJvci50eXBlID09PSAndGltZW91dF9lcnJvcidcclxuICAgKiAvLyBhcGlFcnJvci5zdGF0dXMgPT09IDQwOFxyXG4gICAqIGBgYFxyXG4gICAqL1xyXG4gIG5vcm1hbGl6ZUVycm9yKFxyXG4gICAgZXJyb3I6IHVua25vd24sXHJcbiAgICBjb25maWc6IFJlcXVlc3RDb25maWcsXHJcbiAgICBjb3JyZWxhdGlvbklkPzogc3RyaW5nXHJcbiAgKTogQXBpRXJyb3Ige1xyXG4gICAgLy8gSGFuZGxlIHByaW1pdGl2ZSBlcnJvcnMgKHN0cmluZ3MsIG51bWJlcnMsIGV0Yy4pXHJcbiAgICBpZiAoZXJyb3IgPT09IG51bGwgfHwgZXJyb3IgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihuZXcgRXJyb3IoJ0FuIHVua25vd24gZXJyb3Igb2NjdXJyZWQnKSwge1xyXG4gICAgICAgIHR5cGU6ICd1bmtub3duX2Vycm9yJyxcclxuICAgICAgICB0aXRsZTogJ1Vua25vd24gRXJyb3InLFxyXG4gICAgICAgIHN0YXR1czogMCxcclxuICAgICAgICB0cmFjZUlkOiBjb3JyZWxhdGlvbklkLFxyXG4gICAgICAgIGlzQWJvcnRlZDogZmFsc2UsXHJcbiAgICAgICAgY29uZmlnLFxyXG4gICAgICB9IGFzIEFwaUVycm9yKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBIYW5kbGUgc3RyaW5nIGVycm9yc1xyXG4gICAgaWYgKHR5cGVvZiBlcnJvciA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24obmV3IEVycm9yKGVycm9yKSwge1xyXG4gICAgICAgIHR5cGU6ICd1bmtub3duX2Vycm9yJyxcclxuICAgICAgICB0aXRsZTogJ1Vua25vd24gRXJyb3InLFxyXG4gICAgICAgIHN0YXR1czogMCxcclxuICAgICAgICB0cmFjZUlkOiBjb3JyZWxhdGlvbklkLFxyXG4gICAgICAgIGlzQWJvcnRlZDogZmFsc2UsXHJcbiAgICAgICAgY29uZmlnLFxyXG4gICAgICB9IGFzIEFwaUVycm9yKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBlcnIgPSBlcnJvciBhcyBQYXJ0aWFsPEFwaUVycm9yPiAmIHsgbWVzc2FnZT86IHN0cmluZzsgbmFtZT86IHN0cmluZyB9O1xyXG5cclxuICAgIC8vIElmIGVycm9yIGFscmVhZHkgaGFzIEFwaUVycm9yIHN0cnVjdHVyZSwgZW5oYW5jZSBpdFxyXG4gICAgaWYgKGVyci50eXBlIHx8IGVyci50aXRsZSB8fCBlcnIuZXJyb3JzKSB7XHJcbiAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKFxyXG4gICAgICAgIGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihlcnIubWVzc2FnZSA/PyAnVW5rbm93biBlcnJvcicpLFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIHR5cGU6IGVyci50eXBlLFxyXG4gICAgICAgICAgdGl0bGU6IGVyci50aXRsZSxcclxuICAgICAgICAgIHN0YXR1czogZXJyLnN0YXR1cyxcclxuICAgICAgICAgIHRyYWNlSWQ6IGVyci50cmFjZUlkIHx8IGNvcnJlbGF0aW9uSWQsXHJcbiAgICAgICAgICBlcnJvcnM6IGVyci5lcnJvcnMsXHJcbiAgICAgICAgICBpc0Fib3J0ZWQ6IGVyci5pc0Fib3J0ZWQgfHwgZmFsc2UsXHJcbiAgICAgICAgICBjb25maWcsXHJcbiAgICAgICAgfVxyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChlcnIubmFtZSA9PT0gJ0Fib3J0RXJyb3InIHx8IGVyci5pc0Fib3J0ZWQpIHtcclxuICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24obmV3IEVycm9yKGVyci5tZXNzYWdlID8/ICdSZXF1ZXN0IHdhcyBhYm9ydGVkJyksIHtcclxuICAgICAgICB0eXBlOiAncmVxdWVzdF9jYW5jZWxsZWQnLFxyXG4gICAgICAgIHRpdGxlOiAnUmVxdWVzdCB3YXMgY2FuY2VsbGVkJyxcclxuICAgICAgICBzdGF0dXM6IDAsXHJcbiAgICAgICAgdHJhY2VJZDogY29ycmVsYXRpb25JZCxcclxuICAgICAgICBpc0Fib3J0ZWQ6IHRydWUsXHJcbiAgICAgICAgY29uZmlnLFxyXG4gICAgICB9IGFzIEFwaUVycm9yKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoZXJyLm1lc3NhZ2U/LmluY2x1ZGVzKCd0aW1lb3V0JykpIHtcclxuICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24obmV3IEVycm9yKGVyci5tZXNzYWdlKSwge1xyXG4gICAgICAgIHR5cGU6ICd0aW1lb3V0X2Vycm9yJyxcclxuICAgICAgICB0aXRsZTogJ1JlcXVlc3QgVGltZW91dCcsXHJcbiAgICAgICAgc3RhdHVzOiA0MDgsXHJcbiAgICAgICAgdHJhY2VJZDogY29ycmVsYXRpb25JZCxcclxuICAgICAgICBpc0Fib3J0ZWQ6IHRydWUsXHJcbiAgICAgICAgY29uZmlnLFxyXG4gICAgICB9IGFzIEFwaUVycm9yKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoZXJyLm1lc3NhZ2U/LmluY2x1ZGVzKCduZXR3b3JrJykpIHtcclxuICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24obmV3IEVycm9yKGVyci5tZXNzYWdlID8/ICdOZXR3b3JrIHJlcXVlc3QgZmFpbGVkJyksIHtcclxuICAgICAgICB0eXBlOiAnbmV0d29ya19lcnJvcicsXHJcbiAgICAgICAgdGl0bGU6ICdOZXR3b3JrIEVycm9yJyxcclxuICAgICAgICBzdGF0dXM6IDAsXHJcbiAgICAgICAgdHJhY2VJZDogY29ycmVsYXRpb25JZCxcclxuICAgICAgICBpc0Fib3J0ZWQ6IGZhbHNlLFxyXG4gICAgICAgIGNvbmZpZyxcclxuICAgICAgfSBhcyBBcGlFcnJvcik7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oXHJcbiAgICAgIG5ldyBFcnJvcihlcnIubWVzc2FnZSA/PyAnQW4gdW5rbm93biBlcnJvciBvY2N1cnJlZCcpLFxyXG4gICAgICB7XHJcbiAgICAgICAgdHlwZTogJ3Vua25vd25fZXJyb3InLFxyXG4gICAgICAgIHRpdGxlOiAnVW5rbm93biBFcnJvcicsXHJcbiAgICAgICAgc3RhdHVzOiAwLFxyXG4gICAgICAgIHRyYWNlSWQ6IGNvcnJlbGF0aW9uSWQsXHJcbiAgICAgICAgaXNBYm9ydGVkOiBmYWxzZSxcclxuICAgICAgICBjb25maWcsXHJcbiAgICAgIH0gYXMgQXBpRXJyb3JcclxuICAgICk7XHJcbiAgfVxyXG59XHJcbiIsICJpbXBvcnQgdHlwZSB7IEFwaUVycm9yIH0gZnJvbSAnLi4vdHlwZXMvQXBpRXJyb3InO1xuaW1wb3J0IHR5cGUgeyBFcnJvckludGVyY2VwdG9yIH0gZnJvbSAnLi4vdHlwZXMvRXJyb3JJbnRlcmNlcHRvcic7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3RDb25maWcgfSBmcm9tICcuLi90eXBlcy9SZXF1ZXN0Q29uZmlnJztcbmltcG9ydCB0eXBlIHsgUmVxdWVzdEludGVyY2VwdG9yIH0gZnJvbSAnLi4vdHlwZXMvUmVxdWVzdEludGVyY2VwdG9yJztcbmltcG9ydCB0eXBlIHsgUmVzcG9uc2VJbnRlcmNlcHRvciB9IGZyb20gJy4uL3R5cGVzL1Jlc3BvbnNlSW50ZXJjZXB0b3InO1xuXG5pbXBvcnQgdHlwZSB7IEFwaVJlc3BvbnNlIH0gZnJvbSAnQC90eXBlcyc7XG5cbi8qKlxuICogTWFuYWdlcyB0aGUgcmVnaXN0cmF0aW9uIGFuZCBleGVjdXRpb24gb2YgcmVxdWVzdC9yZXNwb25zZS9lcnJvciBpbnRlcmNlcHRvcnMuXG4gKlxuICogVGhpcyBpbnRlcm5hbCBjbGFzcyBpbXBsZW1lbnRzIHRoZSBpbnRlcmNlcHRvciBwYXR0ZXJuLCBhbGxvd2luZyBtaWRkbGV3YXJlLXN0eWxlXG4gKiBmdW5jdGlvbnMgdG8gYmUgcmVnaXN0ZXJlZCBhbmQgZXhlY3V0ZWQgYXQgZGlmZmVyZW50IHBvaW50cyBpbiB0aGUgcmVxdWVzdCBsaWZlY3ljbGU6XG4gKiAtICoqUmVxdWVzdCBJbnRlcmNlcHRvcnMqKjogTW9kaWZ5IHJlcXVlc3RzIGJlZm9yZSB0aGV5IGFyZSBzZW50XG4gKiAtICoqUmVzcG9uc2UgSW50ZXJjZXB0b3JzKio6IFRyYW5zZm9ybSByZXNwb25zZXMgYmVmb3JlIHRoZXkgYXJlIHJldHVybmVkXG4gKiAtICoqRXJyb3IgSW50ZXJjZXB0b3JzKio6IEhhbmRsZSBvciB0cmFuc2Zvcm0gZXJyb3JzIGJlZm9yZSB0aGV5IGFyZSB0aHJvd25cbiAqXG4gKiBJbnRlcmNlcHRvcnMgYXJlIGV4ZWN1dGVkIHNlcXVlbnRpYWxseSBpbiB0aGUgb3JkZXIgdGhleSB3ZXJlIHJlZ2lzdGVyZWQsXG4gKiBmb3JtaW5nIGEgcHJvY2Vzc2luZyBwaXBlbGluZS4gRWFjaCBpbnRlcmNlcHRvciBjYW46XG4gKiAtIEluc3BlY3QgdGhlIGRhdGEgcGFzc2luZyB0aHJvdWdoXG4gKiAtIFRyYW5zZm9ybSBvciBlbmhhbmNlIHRoZSBkYXRhXG4gKiAtIFNob3J0LWNpcmN1aXQgdGhlIHBpcGVsaW5lIChmb3IgZXJyb3JzKVxuICogLSBQZXJmb3JtIHNpZGUgZWZmZWN0cyAobG9nZ2luZywgbW9uaXRvcmluZywgZXRjLilcbiAqXG4gKiBLZXkgRmVhdHVyZXM6XG4gKiAtICoqU2VxdWVudGlhbCBFeGVjdXRpb24qKjogSW50ZXJjZXB0b3JzIHJ1biBpbiByZWdpc3RyYXRpb24gb3JkZXJcbiAqIC0gKipVbnJlZ2lzdHJhdGlvbiBTdXBwb3J0Kio6IFJldHVybnMgY2xlYW51cCBmdW5jdGlvbiBmb3IgZWFjaCBpbnRlcmNlcHRvclxuICogLSAqKlR5cGUgU2FmZXR5Kio6IEZ1bGx5IHR5cGVkIGludGVyY2VwdG9yIGZ1bmN0aW9ucyB3aXRoIGdlbmVyaWNzXG4gKiAtICoqRXJyb3IgSGFuZGxpbmcqKjogR3JhY2VmdWwgaGFuZGxpbmcgb2YgaW50ZXJjZXB0b3IgZmFpbHVyZXNcbiAqXG4gKiBAaW50ZXJuYWwgVGhpcyBjbGFzcyBpcyBub3QgZXhwb3J0ZWQgZnJvbSB0aGUgcHVibGljIEFQSVxuICpcbiAqIEBleGFtcGxlXG4gKiBDb21tb24gaW50ZXJjZXB0b3IgcGF0dGVybnM6XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBtYW5hZ2VyID0gbmV3IEludGVyY2VwdG9yTWFuYWdlcigpO1xuICpcbiAqIC8vIFJlcXVlc3QgbG9nZ2luZ1xuICogbWFuYWdlci5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoYXN5bmMgKGNvbmZpZykgPT4ge1xuICogICBjb25zb2xlLmxvZygnUmVxdWVzdDonLCBjb25maWcubWV0aG9kLCBjb25maWcudXJsKTtcbiAqICAgcmV0dXJuIGNvbmZpZztcbiAqIH0pO1xuICpcbiAqIC8vIFJlc3BvbnNlIHRyYW5zZm9ybWF0aW9uXG4gKiBtYW5hZ2VyLmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoYXN5bmMgKHJlc3BvbnNlKSA9PiB7XG4gKiAgIGlmIChyZXNwb25zZS5hcGlEYXRhKSB7XG4gKiAgICAgcmVzcG9uc2UuYXBpRGF0YSA9IGNhbWVsQ2FzZUtleXMocmVzcG9uc2UuYXBpRGF0YSk7XG4gKiAgIH1cbiAqICAgcmV0dXJuIHJlc3BvbnNlO1xuICogfSk7XG4gKlxuICogLy8gRXJyb3IgbW9uaXRvcmluZ1xuICogbWFuYWdlci5hZGRFcnJvckludGVyY2VwdG9yKGFzeW5jIChlcnJvcikgPT4ge1xuICogICBpZiAoZXJyb3Iuc3RhdHVzID49IDUwMCkge1xuICogICAgIGF3YWl0IGxvZ1RvTW9uaXRvcmluZyhlcnJvcik7XG4gKiAgIH1cbiAqICAgdGhyb3cgZXJyb3I7IC8vIFJlLXRocm93IHRvIG1haW50YWluIGVycm9yIGZsb3dcbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBJbnRlcmNlcHRvck1hbmFnZXIge1xuICAvKipcbiAgICogQXJyYXkgb2YgcmVnaXN0ZXJlZCByZXF1ZXN0IGludGVyY2VwdG9yc1xuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSByZXF1ZXN0SW50ZXJjZXB0b3JzOiBSZXF1ZXN0SW50ZXJjZXB0b3JbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBBcnJheSBvZiByZWdpc3RlcmVkIHJlc3BvbnNlIGludGVyY2VwdG9yc1xuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSByZXNwb25zZUludGVyY2VwdG9yczogUmVzcG9uc2VJbnRlcmNlcHRvcltdID0gW107XG5cbiAgLyoqXG4gICAqIEFycmF5IG9mIHJlZ2lzdGVyZWQgZXJyb3IgaW50ZXJjZXB0b3JzXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGVycm9ySW50ZXJjZXB0b3JzOiBFcnJvckludGVyY2VwdG9yW10gPSBbXTtcblxuICAvKipcbiAgICogUmVnaXN0ZXJzIGEgcmVxdWVzdCBpbnRlcmNlcHRvciB0byBtb2RpZnkgcmVxdWVzdHMgYmVmb3JlIHRoZXkgYXJlIHNlbnQuXG4gICAqXG4gICAqIFJlcXVlc3QgaW50ZXJjZXB0b3JzIGNhbjpcbiAgICogLSBBZGQgb3IgbW9kaWZ5IGhlYWRlcnNcbiAgICogLSBUcmFuc2Zvcm0gcmVxdWVzdCBib2RpZXNcbiAgICogLSBBZGQgcXVlcnkgcGFyYW1ldGVyc1xuICAgKiAtIEltcGxlbWVudCByZXF1ZXN0IHNpZ25pbmdcbiAgICogLSBMb2cgb3V0Z29pbmcgcmVxdWVzdHNcbiAgICpcbiAgICogQHBhcmFtIGludGVyY2VwdG9yIC0gQXN5bmMgZnVuY3Rpb24gdGhhdCByZWNlaXZlcyBhbmQgcmV0dXJucyBSZXF1ZXN0Q29uZmlnXG4gICAqIEByZXR1cm5zIENsZWFudXAgZnVuY3Rpb24gdG8gdW5yZWdpc3RlciB0aGlzIGludGVyY2VwdG9yXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogLy8gQWRkIGF1dGhlbnRpY2F0aW9uIGhlYWRlclxuICAgKiBjb25zdCB1bnJlZ2lzdGVyID0gbWFuYWdlci5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoYXN5bmMgKGNvbmZpZykgPT4ge1xuICAgKiAgIGNvbnN0IHRva2VuID0gYXdhaXQgZ2V0QXV0aFRva2VuKCk7XG4gICAqICAgY29uZmlnLmhlYWRlcnMgPSBjb25maWcuaGVhZGVycyB8fCBuZXcgSGVhZGVycygpO1xuICAgKiAgIGNvbmZpZy5oZWFkZXJzLnNldCgnQXV0aG9yaXphdGlvbicsIGBCZWFyZXIgJHt0b2tlbn1gKTtcbiAgICogICByZXR1cm4gY29uZmlnO1xuICAgKiB9KTtcbiAgICpcbiAgICogLy8gTGF0ZXIsIHJlbW92ZSB0aGUgaW50ZXJjZXB0b3JcbiAgICogdW5yZWdpc3RlcigpO1xuICAgKiBgYGBcbiAgICovXG4gIGFkZFJlcXVlc3RJbnRlcmNlcHRvcihpbnRlcmNlcHRvcjogUmVxdWVzdEludGVyY2VwdG9yKTogKCkgPT4gdm9pZCB7XG4gICAgdGhpcy5yZXF1ZXN0SW50ZXJjZXB0b3JzLnB1c2goaW50ZXJjZXB0b3IpO1xuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5yZXF1ZXN0SW50ZXJjZXB0b3JzLmluZGV4T2YoaW50ZXJjZXB0b3IpO1xuXG4gICAgICBpZiAoaW5kZXggPiAtMSkgdGhpcy5yZXF1ZXN0SW50ZXJjZXB0b3JzLnNwbGljZShpbmRleCwgMSk7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgYSByZXNwb25zZSBpbnRlcmNlcHRvciB0byB0cmFuc2Zvcm0gcmVzcG9uc2VzIGJlZm9yZSB0aGV5IGFyZSByZXR1cm5lZC5cbiAgICpcbiAgICogUmVzcG9uc2UgaW50ZXJjZXB0b3JzIGNhbjpcbiAgICogLSBUcmFuc2Zvcm0gcmVzcG9uc2UgZGF0YSBmb3JtYXRcbiAgICogLSBFeHRyYWN0IG5lc3RlZCBkYXRhIHN0cnVjdHVyZXNcbiAgICogLSBBZGQgY29tcHV0ZWQgcHJvcGVydGllc1xuICAgKiAtIENhY2hlIHJlc3BvbnNlc1xuICAgKiAtIExvZyBzdWNjZXNzZnVsIHJlc3BvbnNlc1xuICAgKlxuICAgKiBAcGFyYW0gaW50ZXJjZXB0b3IgLSBBc3luYyBmdW5jdGlvbiB0aGF0IHJlY2VpdmVzIGFuZCByZXR1cm5zIEFwaVJlc3BvbnNlXG4gICAqIEByZXR1cm5zIENsZWFudXAgZnVuY3Rpb24gdG8gdW5yZWdpc3RlciB0aGlzIGludGVyY2VwdG9yXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogLy8gRXh0cmFjdCBkYXRhIGZyb20gZW52ZWxvcGVcbiAgICogbWFuYWdlci5hZGRSZXNwb25zZUludGVyY2VwdG9yKGFzeW5jIChyZXNwb25zZSkgPT4ge1xuICAgKiAgIGlmIChyZXNwb25zZS5hcGlEYXRhPy5yZXN1bHQpIHtcbiAgICogICAgIHJlc3BvbnNlLmFwaURhdGEgPSByZXNwb25zZS5hcGlEYXRhLnJlc3VsdDtcbiAgICogICB9XG4gICAqICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgKiB9KTtcbiAgICpcbiAgICogLy8gQWRkIHRpbWVzdGFtcHNcbiAgICogbWFuYWdlci5hZGRSZXNwb25zZUludGVyY2VwdG9yKGFzeW5jIChyZXNwb25zZSkgPT4ge1xuICAgKiAgIHJldHVybiB7XG4gICAqICAgICAuLi5yZXNwb25zZSxcbiAgICogICAgIHJlY2VpdmVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKVxuICAgKiAgIH07XG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoaW50ZXJjZXB0b3I6IFJlc3BvbnNlSW50ZXJjZXB0b3IpOiAoKSA9PiB2b2lkIHtcbiAgICB0aGlzLnJlc3BvbnNlSW50ZXJjZXB0b3JzLnB1c2goaW50ZXJjZXB0b3IpO1xuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5yZXNwb25zZUludGVyY2VwdG9ycy5pbmRleE9mKGludGVyY2VwdG9yKTtcblxuICAgICAgaWYgKGluZGV4ID4gLTEpIHRoaXMucmVzcG9uc2VJbnRlcmNlcHRvcnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhbiBlcnJvciBpbnRlcmNlcHRvciB0byBoYW5kbGUgb3IgdHJhbnNmb3JtIGVycm9ycyBiZWZvcmUgdGhleSBhcmUgdGhyb3duLlxuICAgKlxuICAgKiBFcnJvciBpbnRlcmNlcHRvcnMgY2FuOlxuICAgKiAtIExvZyBlcnJvcnMgdG8gbW9uaXRvcmluZyBzZXJ2aWNlc1xuICAgKiAtIFRyYW5zZm9ybSBlcnJvciBmb3JtYXRzXG4gICAqIC0gSW1wbGVtZW50IHJldHJ5IGxvZ2ljXG4gICAqIC0gU2hvdyB1c2VyIG5vdGlmaWNhdGlvbnNcbiAgICogLSBFeHRyYWN0IHZhbGlkYXRpb24gZXJyb3JzXG4gICAqXG4gICAqICoqTm90ZToqKiBFcnJvciBpbnRlcmNlcHRvcnMgc2hvdWxkIHJlLXRocm93IHRoZSBlcnJvciAob3IgYSB0cmFuc2Zvcm1lZCB2ZXJzaW9uKVxuICAgKiB0byBtYWludGFpbiB0aGUgZXJyb3IgZmxvdy4gVGhlIGZpbmFsIGVycm9yIGlzIGFsd2F5cyB0aHJvd24uXG4gICAqXG4gICAqIEBwYXJhbSBpbnRlcmNlcHRvciAtIEFzeW5jIGZ1bmN0aW9uIHRoYXQgcmVjZWl2ZXMgYW5kIHJldHVybnMgKG9yIHRocm93cykgQXBpRXJyb3JcbiAgICogQHJldHVybnMgQ2xlYW51cCBmdW5jdGlvbiB0byB1bnJlZ2lzdGVyIHRoaXMgaW50ZXJjZXB0b3JcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiAvLyBMb2cgdG8gbW9uaXRvcmluZyBzZXJ2aWNlXG4gICAqIG1hbmFnZXIuYWRkRXJyb3JJbnRlcmNlcHRvcihhc3luYyAoZXJyb3IpID0+IHtcbiAgICogICBpZiAoZXJyb3Iuc3RhdHVzID49IDUwMCkge1xuICAgKiAgICAgYXdhaXQgU2VudHJ5LmNhcHR1cmVFeGNlcHRpb24oZXJyb3IsIHtcbiAgICogICAgICAgZXh0cmE6IHsgdHJhY2VJZDogZXJyb3IudHJhY2VJZCB9XG4gICAqICAgICB9KTtcbiAgICogICB9XG4gICAqICAgdGhyb3cgZXJyb3I7IC8vIFJlLXRocm93IHRvIGNvbnRpbnVlIGVycm9yIGZsb3dcbiAgICogfSk7XG4gICAqXG4gICAqIC8vIFRyYW5zZm9ybSBlcnJvciBtZXNzYWdlc1xuICAgKiBtYW5hZ2VyLmFkZEVycm9ySW50ZXJjZXB0b3IoYXN5bmMgKGVycm9yKSA9PiB7XG4gICAqICAgaWYgKGVycm9yLnN0YXR1cyA9PT0gNDA0KSB7XG4gICAqICAgICBlcnJvci50aXRsZSA9ICdSZXNvdXJjZSBub3QgZm91bmQnO1xuICAgKiAgIH1cbiAgICogICB0aHJvdyBlcnJvcjtcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKi9cbiAgYWRkRXJyb3JJbnRlcmNlcHRvcihpbnRlcmNlcHRvcjogRXJyb3JJbnRlcmNlcHRvcik6ICgpID0+IHZvaWQge1xuICAgIHRoaXMuZXJyb3JJbnRlcmNlcHRvcnMucHVzaChpbnRlcmNlcHRvcik7XG5cbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLmVycm9ySW50ZXJjZXB0b3JzLmluZGV4T2YoaW50ZXJjZXB0b3IpO1xuXG4gICAgICBpZiAoaW5kZXggPiAtMSkgdGhpcy5lcnJvckludGVyY2VwdG9ycy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBhbGwgcmVnaXN0ZXJlZCByZXF1ZXN0IGludGVyY2VwdG9ycyBpbiBzZXF1ZW50aWFsIG9yZGVyLlxuICAgKlxuICAgKiBFYWNoIGludGVyY2VwdG9yIHJlY2VpdmVzIHRoZSBjb25maWcgbW9kaWZpZWQgYnkgdGhlIHByZXZpb3VzIGludGVyY2VwdG9yLFxuICAgKiBmb3JtaW5nIGEgcHJvY2Vzc2luZyBwaXBlbGluZS4gSWYgYW55IGludGVyY2VwdG9yIHRocm93cyBhbiBlcnJvcixcbiAgICogdGhlIHBpcGVsaW5lIHN0b3BzIGFuZCB0aGUgZXJyb3IgcHJvcGFnYXRlcy5cbiAgICpcbiAgICogQHBhcmFtIGNvbmZpZyAtIFRoZSBpbml0aWFsIHJlcXVlc3QgY29uZmlndXJhdGlvblxuICAgKiBAcmV0dXJucyBUaGUgbW9kaWZpZWQgcmVxdWVzdCBjb25maWd1cmF0aW9uIGFmdGVyIGFsbCBpbnRlcmNlcHRvcnNcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBjb25maWcgPSB7IG1ldGhvZDogJ0dFVCcsIHVybDogJy91c2VycycgfTtcbiAgICogY29uc3QgZmluYWxDb25maWcgPSBhd2FpdCBtYW5hZ2VyLmFwcGx5UmVxdWVzdEludGVyY2VwdG9ycyhjb25maWcpO1xuICAgKiAvLyBmaW5hbENvbmZpZyBoYXMgYmVlbiBwcm9jZXNzZWQgYnkgYWxsIHJlZ2lzdGVyZWQgaW50ZXJjZXB0b3JzXG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgYXBwbHlSZXF1ZXN0SW50ZXJjZXB0b3JzKFxuICAgIGNvbmZpZzogUmVxdWVzdENvbmZpZ1xuICApOiBQcm9taXNlPFJlcXVlc3RDb25maWc+IHtcbiAgICBsZXQgbW9kaWZpZWRDb25maWcgPSB7IC4uLmNvbmZpZyB9O1xuXG4gICAgZm9yIChjb25zdCBpbnRlcmNlcHRvciBvZiB0aGlzLnJlcXVlc3RJbnRlcmNlcHRvcnMpIHtcbiAgICAgIG1vZGlmaWVkQ29uZmlnID0gYXdhaXQgaW50ZXJjZXB0b3IobW9kaWZpZWRDb25maWcpO1xuICAgIH1cblxuICAgIHJldHVybiBtb2RpZmllZENvbmZpZztcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBsaWVzIGFsbCByZWdpc3RlcmVkIHJlc3BvbnNlIGludGVyY2VwdG9ycyBpbiBzZXF1ZW50aWFsIG9yZGVyLlxuICAgKlxuICAgKiBFYWNoIGludGVyY2VwdG9yIHJlY2VpdmVzIHRoZSByZXNwb25zZSBtb2RpZmllZCBieSB0aGUgcHJldmlvdXMgaW50ZXJjZXB0b3IsXG4gICAqIGZvcm1pbmcgYSBwcm9jZXNzaW5nIHBpcGVsaW5lLiBJZiBhbnkgaW50ZXJjZXB0b3IgdGhyb3dzIGFuIGVycm9yLFxuICAgKiB0aGUgcGlwZWxpbmUgc3RvcHMgYW5kIHRoZSBlcnJvciBwcm9wYWdhdGVzLlxuICAgKlxuICAgKiBAdGVtcGxhdGUgVCAtIFRoZSB0eXBlIG9mIHRoZSByZXNwb25zZSBkYXRhXG4gICAqIEBwYXJhbSByZXNwb25zZSAtIFRoZSBpbml0aWFsIEFQSSByZXNwb25zZVxuICAgKiBAcmV0dXJucyBUaGUgbW9kaWZpZWQgcmVzcG9uc2UgYWZ0ZXIgYWxsIGludGVyY2VwdG9yc1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHJlc3BvbnNlID0geyBkYXRhOiB7IGlkOiAxLCBuYW1lOiAnSm9obicgfSB9O1xuICAgKiBjb25zdCBmaW5hbFJlc3BvbnNlID0gYXdhaXQgbWFuYWdlci5hcHBseVJlc3BvbnNlSW50ZXJjZXB0b3JzKHJlc3BvbnNlKTtcbiAgICogLy8gZmluYWxSZXNwb25zZSBoYXMgYmVlbiBwcm9jZXNzZWQgYnkgYWxsIHJlZ2lzdGVyZWQgaW50ZXJjZXB0b3JzXG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgYXBwbHlSZXNwb25zZUludGVyY2VwdG9yczxUPihcbiAgICByZXNwb25zZTogQXBpUmVzcG9uc2U8VD5cbiAgKTogUHJvbWlzZTxBcGlSZXNwb25zZTxUPj4ge1xuICAgIGxldCBtb2RpZmllZFJlc3BvbnNlID0gcmVzcG9uc2U7XG5cbiAgICBmb3IgKGNvbnN0IGludGVyY2VwdG9yIG9mIHRoaXMucmVzcG9uc2VJbnRlcmNlcHRvcnMpIHtcbiAgICAgIG1vZGlmaWVkUmVzcG9uc2UgPSBhd2FpdCBpbnRlcmNlcHRvcihtb2RpZmllZFJlc3BvbnNlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbW9kaWZpZWRSZXNwb25zZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBsaWVzIGFsbCByZWdpc3RlcmVkIGVycm9yIGludGVyY2VwdG9ycyBpbiBzZXF1ZW50aWFsIG9yZGVyIGFuZCByZS10aHJvd3MuXG4gICAqXG4gICAqIEVhY2ggaW50ZXJjZXB0b3IgcmVjZWl2ZXMgdGhlIGVycm9yIChwb3RlbnRpYWxseSBtb2RpZmllZCBieSBwcmV2aW91cyBpbnRlcmNlcHRvcnMpLlxuICAgKiBJbnRlcmNlcHRvcnMgY2FuIHRyYW5zZm9ybSB0aGUgZXJyb3IgYmVmb3JlIHJlLXRocm93aW5nIGl0LiBUaGUgZmluYWwgZXJyb3JcbiAgICogaXMgYWx3YXlzIHRocm93biB0byBtYWludGFpbiBlcnJvciBmbG93LlxuICAgKlxuICAgKiBJZiBhbiBpbnRlcmNlcHRvciBpdHNlbGYgdGhyb3dzIGFuIGVycm9yLCB0aGF0IGJlY29tZXMgdGhlIG5ldyBlcnJvciB0byBwcm9jZXNzXG4gICAqIGJ5IHN1YnNlcXVlbnQgaW50ZXJjZXB0b3JzLlxuICAgKlxuICAgKiBAcGFyYW0gZXJyb3IgLSBUaGUgaW5pdGlhbCBBUEkgZXJyb3JcbiAgICogQHJldHVybnMgTmV2ZXIgcmV0dXJucyAoYWx3YXlzIHRocm93cylcbiAgICogQHRocm93cyBUaGUgZmluYWwgZXJyb3IgYWZ0ZXIgYWxsIGludGVyY2VwdG9ycyBoYXZlIHByb2Nlc3NlZCBpdFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIHRyeSB7XG4gICAqICAgYXdhaXQgbWFuYWdlci5hcHBseUVycm9ySW50ZXJjZXB0b3JzKGVycm9yKTtcbiAgICogfSBjYXRjaCAoZmluYWxFcnJvcikge1xuICAgKiAgIC8vIGZpbmFsRXJyb3IgaGFzIGJlZW4gcHJvY2Vzc2VkIGJ5IGFsbCByZWdpc3RlcmVkIGVycm9yIGludGVyY2VwdG9yc1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgYXBwbHlFcnJvckludGVyY2VwdG9ycyhlcnJvcjogQXBpRXJyb3IpOiBQcm9taXNlPG5ldmVyPiB7XG4gICAgbGV0IG1vZGlmaWVkRXJyb3IgPSBlcnJvcjtcblxuICAgIGZvciAoY29uc3QgaW50ZXJjZXB0b3Igb2YgdGhpcy5lcnJvckludGVyY2VwdG9ycykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgbW9kaWZpZWRFcnJvciA9IGF3YWl0IGludGVyY2VwdG9yKG1vZGlmaWVkRXJyb3IpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBtb2RpZmllZEVycm9yID0gZSBhcyBBcGlFcnJvcjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBtb2RpZmllZEVycm9yO1xuICB9XG59XG4iLCAiLyoqXG4gKiBNYW5hZ2VzIGFjdGl2ZSBIVFRQIHJlcXVlc3RzIHdpdGggc3VwcG9ydCBmb3IgY2FuY2VsbGF0aW9uIGFuZCBjb3JyZWxhdGlvbiB0cmFja2luZy5cbiAqXG4gKiBUaGlzIGludGVybmFsIGNsYXNzIG1haW50YWlucyBhIHJlZ2lzdHJ5IG9mIGluLWZsaWdodCByZXF1ZXN0cywgYWxsb3dpbmcgdGhlbSB0byBiZVxuICogY2FuY2VsbGVkIGluZGl2aWR1YWxseSBvciBpbiBidWxrLiBFYWNoIHJlcXVlc3QgaXMgdHJhY2tlZCBieSBhIHVuaXF1ZSBrZXkgYW5kXG4gKiBhc3NvY2lhdGVkIHdpdGggYSBjb3JyZWxhdGlvbiBJRCBmb3IgZGlzdHJpYnV0ZWQgdHJhY2luZy5cbiAqXG4gKiBLZXkgRmVhdHVyZXM6XG4gKiAtICoqUmVxdWVzdCBEZWR1cGxpY2F0aW9uKio6IEF1dG9tYXRpY2FsbHkgY2FuY2VscyBkdXBsaWNhdGUgcmVxdWVzdHMgd2l0aCB0aGUgc2FtZSBrZXlcbiAqIC0gKipDb3JyZWxhdGlvbiBUcmFja2luZyoqOiBNYXBzIHJlcXVlc3Qga2V5cyB0byBjb3JyZWxhdGlvbiBJRHMgZm9yIHRyYWNpbmdcbiAqIC0gKipCdWxrIENhbmNlbGxhdGlvbioqOiBDYW5jZWwgYWxsIHBlbmRpbmcgcmVxdWVzdHMgYXQgb25jZSAodXNlZnVsIGZvciBjbGVhbnVwKVxuICogLSAqKk1lbW9yeSBNYW5hZ2VtZW50Kio6IEF1dG9tYXRpY2FsbHkgY2xlYW5zIHVwIHRyYWNraW5nIGRhdGEgd2hlbiByZXF1ZXN0cyBjb21wbGV0ZVxuICpcbiAqIEBpbnRlcm5hbCBUaGlzIGNsYXNzIGlzIG5vdCBleHBvcnRlZCBmcm9tIHRoZSBwdWJsaWMgQVBJXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IG1hbmFnZXIgPSBuZXcgUmVxdWVzdE1hbmFnZXIoKTtcbiAqIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gKlxuICogLy8gVHJhY2sgYSByZXF1ZXN0XG4gKiBtYW5hZ2VyLmFkZCgnR0VUXy91c2Vycy8xMjMnLCBjb250cm9sbGVyLCAnYXBpLWFiYzEyMycpO1xuICpcbiAqIC8vIENhbmNlbCBzcGVjaWZpYyByZXF1ZXN0XG4gKiBtYW5hZ2VyLmNhbmNlbCgnR0VUXy91c2Vycy8xMjMnKTtcbiAqXG4gKiAvLyBPciBjYW5jZWwgYWxsIHJlcXVlc3RzXG4gKiBtYW5hZ2VyLmNhbmNlbEFsbCgpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBSZXF1ZXN0TWFuYWdlciB7XG4gIC8qKlxuICAgKiBNYXAgb2YgYWN0aXZlIHJlcXVlc3Qga2V5cyB0byB0aGVpciBhYm9ydCBjb250cm9sbGVyc1xuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBhY3RpdmVSZXF1ZXN0czogTWFwPHN0cmluZywgQWJvcnRDb250cm9sbGVyPiA9IG5ldyBNYXAoKTtcblxuICAvKipcbiAgICogTWFwIG9mIHJlcXVlc3Qga2V5cyB0byB0aGVpciBjb3JyZWxhdGlvbiBJRHMgZm9yIHRyYWNpbmdcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgY29ycmVsYXRpb25NYXA6IE1hcDxzdHJpbmcsIHN0cmluZz4gPSBuZXcgTWFwKCk7XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIG5ldyByZXF1ZXN0IGZvciB0cmFja2luZyBhbmQgY2FuY2VsbGF0aW9uIG1hbmFnZW1lbnQuXG4gICAqXG4gICAqIElmIGEgcmVxdWVzdCB3aXRoIHRoZSBzYW1lIGtleSBhbHJlYWR5IGV4aXN0cywgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5XG4gICAqIGNhbmNlbGxlZCBiZWZvcmUgdGhlIG5ldyBvbmUgaXMgcmVnaXN0ZXJlZCAocmVxdWVzdCBkZWR1cGxpY2F0aW9uKS5cbiAgICpcbiAgICogQHBhcmFtIGtleSAtIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgcmVxdWVzdCAodHlwaWNhbGx5IG1ldGhvZCArIFVSTCArIHRpbWVzdGFtcClcbiAgICogQHBhcmFtIGNvbnRyb2xsZXIgLSBBYm9ydENvbnRyb2xsZXIgZm9yIGNhbmNlbGxpbmcgdGhlIHJlcXVlc3RcbiAgICogQHBhcmFtIGNvcnJlbGF0aW9uSWQgLSBDb3JyZWxhdGlvbiBJRCBmb3IgZGlzdHJpYnV0ZWQgdHJhY2luZ1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAqIG1hbmFnZXIuYWRkKCdHRVRfL2FwaS91c2Vyc18xNjk5OTk5OTk5JywgY29udHJvbGxlciwgJ2FwaS1hYmMxMjMnKTtcbiAgICogYGBgXG4gICAqL1xuICBhZGQoa2V5OiBzdHJpbmcsIGNvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlciwgY29ycmVsYXRpb25JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgLy8gQ2FuY2VsIGV4aXN0aW5nIHJlcXVlc3Qgd2l0aCBzYW1lIGtleSBpZiBleGlzdHNcbiAgICB0aGlzLmNhbmNlbChrZXkpO1xuICAgIHRoaXMuYWN0aXZlUmVxdWVzdHMuc2V0KGtleSwgY29udHJvbGxlcik7XG4gICAgdGhpcy5jb3JyZWxhdGlvbk1hcC5zZXQoa2V5LCBjb3JyZWxhdGlvbklkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGEgcmVxdWVzdCBmcm9tIHRyYWNraW5nIHdpdGhvdXQgY2FuY2VsbGluZyBpdC5cbiAgICpcbiAgICogVGhpcyBpcyB0eXBpY2FsbHkgY2FsbGVkIHdoZW4gYSByZXF1ZXN0IGNvbXBsZXRlcyBzdWNjZXNzZnVsbHkgb3IgZmFpbHMuXG4gICAqIFVzZSB7QGxpbmsgY2FuY2VsfSBpbnN0ZWFkIGlmIHlvdSBuZWVkIHRvIGFib3J0IHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcGFyYW0ga2V5IC0gVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSByZXF1ZXN0IHRvIHJlbW92ZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIC8vIENhbGxlZCBhdXRvbWF0aWNhbGx5IGFmdGVyIHJlcXVlc3QgY29tcGxldGVzXG4gICAqIG1hbmFnZXIucmVtb3ZlKCdHRVRfL2FwaS91c2Vyc18xNjk5OTk5OTk5Jyk7XG4gICAqIGBgYFxuICAgKi9cbiAgcmVtb3ZlKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5hY3RpdmVSZXF1ZXN0cy5kZWxldGUoa2V5KTtcbiAgICB0aGlzLmNvcnJlbGF0aW9uTWFwLmRlbGV0ZShrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbmNlbHMgYSBzcGVjaWZpYyByZXF1ZXN0IGFuZCByZW1vdmVzIGl0IGZyb20gdHJhY2tpbmcuXG4gICAqXG4gICAqIElmIHRoZSByZXF1ZXN0IGRvZXNuJ3QgZXhpc3Qgb3Igd2FzIGFscmVhZHkgY2FuY2VsbGVkLCB0aGlzIG9wZXJhdGlvbiBpcyBhIG5vLW9wLlxuICAgKiBUaGUgYXNzb2NpYXRlZCBBYm9ydENvbnRyb2xsZXIncyBzaWduYWwgd2lsbCBiZSB0cmlnZ2VyZWQsIGNhdXNpbmcgYW55IGFjdGl2ZVxuICAgKiBmZXRjaCBvcGVyYXRpb25zIHRvIGFib3J0LlxuICAgKlxuICAgKiBAcGFyYW0ga2V5IC0gVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSByZXF1ZXN0IHRvIGNhbmNlbFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIC8vIFVzZXIgbmF2aWdhdGVzIGF3YXksIGNhbmNlbCB0aGUgcGVuZGluZyByZXF1ZXN0XG4gICAqIG1hbmFnZXIuY2FuY2VsKCdHRVRfL2FwaS91c2Vyc18xNjk5OTk5OTk5Jyk7XG4gICAqIGBgYFxuICAgKi9cbiAgY2FuY2VsKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgY29udHJvbGxlciA9IHRoaXMuYWN0aXZlUmVxdWVzdHMuZ2V0KGtleSk7XG5cbiAgICBpZiAoY29udHJvbGxlcikge1xuICAgICAgY29udHJvbGxlci5hYm9ydCgpO1xuICAgICAgdGhpcy5hY3RpdmVSZXF1ZXN0cy5kZWxldGUoa2V5KTtcbiAgICAgIHRoaXMuY29ycmVsYXRpb25NYXAuZGVsZXRlKGtleSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENhbmNlbHMgYWxsIGFjdGl2ZSByZXF1ZXN0cyBhbmQgY2xlYXJzIGFsbCB0cmFja2luZyBkYXRhLlxuICAgKlxuICAgKiBUaGlzIGlzIHVzZWZ1bCBmb3IgY2xlYW51cCBzY2VuYXJpb3Mgc3VjaCBhczpcbiAgICogLSBVc2VyIGxvZ291dFxuICAgKiAtIENvbXBvbmVudCB1bm1vdW50XG4gICAqIC0gTmF2aWdhdGlvbiB0byBhIGRpZmZlcmVudCBwYXJ0IG9mIHRoZSBhcHBsaWNhdGlvblxuICAgKiAtIEVycm9yIHJlY292ZXJ5IHRoYXQgcmVxdWlyZXMgYSBjbGVhbiBzbGF0ZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIC8vIENhbmNlbCBhbGwgcGVuZGluZyByZXF1ZXN0cyBvbiBsb2dvdXRcbiAgICogZnVuY3Rpb24gaGFuZGxlTG9nb3V0KCkge1xuICAgKiAgIGFwaUNsaWVudC5jYW5jZWxBbGxSZXF1ZXN0cygpO1xuICAgKiAgIC8vIC4uLiByZXN0IG9mIGxvZ291dCBsb2dpY1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgY2FuY2VsQWxsKCk6IHZvaWQge1xuICAgIHRoaXMuYWN0aXZlUmVxdWVzdHMuZm9yRWFjaChjb250cm9sbGVyID0+IGNvbnRyb2xsZXIuYWJvcnQoKSk7XG4gICAgdGhpcy5hY3RpdmVSZXF1ZXN0cy5jbGVhcigpO1xuICAgIHRoaXMuY29ycmVsYXRpb25NYXAuY2xlYXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYSByZXF1ZXN0IHdpdGggdGhlIGdpdmVuIGtleSBpcyBjdXJyZW50bHkgYmVpbmcgdHJhY2tlZC5cbiAgICpcbiAgICogQHBhcmFtIGtleSAtIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgcmVxdWVzdFxuICAgKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlcXVlc3QgaXMgYWN0aXZlLCBgZmFsc2VgIG90aGVyd2lzZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGlmIChtYW5hZ2VyLmhhcygnR0VUXy9hcGkvdXNlcnNfMTY5OTk5OTk5OScpKSB7XG4gICAqICAgY29uc29sZS5sb2coJ1JlcXVlc3QgaXMgc3RpbGwgcGVuZGluZycpO1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgaGFzKGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuYWN0aXZlUmVxdWVzdHMuaGFzKGtleSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBjb3JyZWxhdGlvbiBJRCBmb3IgYSBnaXZlbiByZXF1ZXN0IGtleS5cbiAgICpcbiAgICogQ29ycmVsYXRpb24gSURzIGFyZSB1c2VkIGZvciBkaXN0cmlidXRlZCB0cmFjaW5nIGFuZCByZXF1ZXN0IHRyYWNraW5nXG4gICAqIGFjcm9zcyBzZXJ2aWNlcyBhbmQgbG9ncy5cbiAgICpcbiAgICogQHBhcmFtIGtleSAtIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgcmVxdWVzdFxuICAgKiBAcmV0dXJucyBUaGUgY29ycmVsYXRpb24gSUQgaWYgZm91bmQsIGB1bmRlZmluZWRgIG90aGVyd2lzZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IGNvcnJlbGF0aW9uSWQgPSBtYW5hZ2VyLmdldENvcnJlbGF0aW9uSWQoJ0dFVF8vYXBpL3VzZXJzXzE2OTk5OTk5OTknKTtcbiAgICogaWYgKGNvcnJlbGF0aW9uSWQpIHtcbiAgICogICBjb25zb2xlLmxvZygnVHJhY2UgcmVxdWVzdCB3aXRoIElEOicsIGNvcnJlbGF0aW9uSWQpO1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgZ2V0Q29ycmVsYXRpb25JZChrZXk6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuY29ycmVsYXRpb25NYXAuZ2V0KGtleSk7XG4gIH1cbn1cbiIsICJpbXBvcnQgdHlwZSB7IEFwaUVycm9yIH0gZnJvbSAnLi4vdHlwZXMvQXBpRXJyb3InO1xuXG4vKipcbiAqIEltcGxlbWVudHMgYXV0b21hdGljIHJldHJ5IGxvZ2ljIHdpdGggZXhwb25lbnRpYWwgYmFja29mZiBmb3IgZmFpbGVkIEhUVFAgcmVxdWVzdHMuXG4gKlxuICogVGhpcyBpbnRlcm5hbCBjbGFzcyBoYW5kbGVzIHRyYW5zaWVudCBmYWlsdXJlcyBieSBhdXRvbWF0aWNhbGx5IHJldHJ5aW5nIHJlcXVlc3RzXG4gKiB3aXRoIHByb2dyZXNzaXZlbHkgaW5jcmVhc2luZyBkZWxheXMgYmV0d2VlbiBhdHRlbXB0cy4gVGhlIGV4cG9uZW50aWFsIGJhY2tvZmZcbiAqIHN0cmF0ZWd5IGhlbHBzIHByZXZlbnQgb3ZlcndoZWxtaW5nIGEgc3RydWdnbGluZyBzZXJ2ZXIgd2hpbGUgZ2l2aW5nIHRlbXBvcmFyeVxuICogaXNzdWVzIHRpbWUgdG8gcmVzb2x2ZS5cbiAqXG4gKiBLZXkgRmVhdHVyZXM6XG4gKiAtICoqRXhwb25lbnRpYWwgQmFja29mZioqOiBEb3VibGVzIGRlbGF5IGJldHdlZW4gcmV0cmllcyAoZS5nLiwgMXMsIDJzLCA0cywgOHMpXG4gKiAtICoqU21hcnQgRXJyb3IgRGV0ZWN0aW9uKio6IFNraXBzIHJldHJ5IGZvciBub24tcmV0cnlhYmxlIGVycm9ycyAodmFsaWRhdGlvbiwgYWJvcnRzKVxuICogLSAqKkFib3J0IFN1cHBvcnQqKjogUmVzcGVjdHMgY2FuY2VsbGF0aW9uIHNpZ25hbHMgZHVyaW5nIHJldHJ5IGRlbGF5c1xuICogLSAqKlR5cGUgU2FmZXR5Kio6IEZ1bGx5IGdlbmVyaWMgaW1wbGVtZW50YXRpb24gcHJlc2VydmluZyByZXR1cm4gdHlwZXNcbiAqXG4gKiBSZXRyeSBTdHJhdGVneTpcbiAqIC0gKipSZXRyeWFibGUqKjogTmV0d29yayBlcnJvcnMsIDV4eCBzZXJ2ZXIgZXJyb3JzLCB0aW1lb3V0c1xuICogLSAqKk5vbi1SZXRyeWFibGUqKjogVmFsaWRhdGlvbiBlcnJvcnMgKDQwMCksIEFib3J0RXJyb3JzLCBjYW5jZWxsZWQgcmVxdWVzdHNcbiAqXG4gKiBAaW50ZXJuYWwgVGhpcyBjbGFzcyBpcyBub3QgZXhwb3J0ZWQgZnJvbSB0aGUgcHVibGljIEFQSVxuICpcbiAqIEBleGFtcGxlXG4gKiBSZXRyeSBjb25maWd1cmF0aW9uIGluIEFwaUNsaWVudDpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGNsaWVudCA9IG5ldyBBcGlDbGllbnQoJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJyk7XG4gKlxuICogLy8gUmV0cnkgdXAgdG8gMyB0aW1lcyB3aXRoIDFzIGluaXRpYWwgZGVsYXlcbiAqIGNvbnN0IHsgYXBpRGF0YSB9ID0gYXdhaXQgY2xpZW50LmdldCgnL3VzZXJzJywge1xuICogICByZXRyaWVzOiAzLFxuICogICByZXRyeURlbGF5OiAxMDAwICAvLyAxcywgMnMsIDRzXG4gKiB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgUmV0cnlIYW5kbGVyIHtcbiAgLyoqXG4gICAqIFJldHJpZXMgYSBmYWlsZWQgcmVxdWVzdCB3aXRoIGV4cG9uZW50aWFsIGJhY2tvZmYgc3RyYXRlZ3kuXG4gICAqXG4gICAqIFRoZSByZXRyeSBsb2dpYyB3b3JrcyBhcyBmb2xsb3dzOlxuICAgKiAxLiBBdHRlbXB0cyB0aGUgcmVxdWVzdCBpbW1lZGlhdGVseVxuICAgKiAyLiBPbiBmYWlsdXJlLCBjaGVja3MgaWYgdGhlIGVycm9yIGlzIHJldHJ5YWJsZVxuICAgKiAzLiBJZiByZXRyeWFibGUgYW5kIHJldHJpZXMgcmVtYWluLCB3YWl0cyBmb3IgdGhlIGN1cnJlbnQgZGVsYXlcbiAgICogNC4gRG91YmxlcyB0aGUgZGVsYXkgZm9yIHRoZSBuZXh0IGF0dGVtcHRcbiAgICogNS4gUmVwZWF0cyB1bnRpbCBzdWNjZXNzIG9yIHJldHJpZXMgZXhoYXVzdGVkXG4gICAqXG4gICAqICoqTm9uLVJldHJ5YWJsZSBFcnJvcnM6KipcbiAgICogLSBWYWxpZGF0aW9uIGVycm9ycyAoNDAwKSAtIENsaWVudCBzZW50IGJhZCBkYXRhXG4gICAqIC0gQWJvcnRFcnJvcnMgLSBSZXF1ZXN0IHdhcyBleHBsaWNpdGx5IGNhbmNlbGxlZFxuICAgKiAtIFJlcXVlc3RzIHdpdGggYWJvcnRlZCBzaWduYWxzXG4gICAqXG4gICAqICoqQWJvcnQgSGFuZGxpbmc6KipcbiAgICogSWYgdGhlIHNpZ25hbCBpcyBhYm9ydGVkIGR1cmluZyBhIHJldHJ5IGRlbGF5LCB0aGUgcmV0cnkgaXMgaW1tZWRpYXRlbHlcbiAgICogY2FuY2VsbGVkIGFuZCBhbiBBYm9ydEVycm9yIGlzIHRocm93bi5cbiAgICpcbiAgICogQHRlbXBsYXRlIFQgLSBUaGUgcmV0dXJuIHR5cGUgb2YgdGhlIGZ1bmN0aW9uIGJlaW5nIHJldHJpZWRcbiAgICogQHBhcmFtIGZuIC0gQXN5bmMgZnVuY3Rpb24gdG8gcmV0cnkgb24gZmFpbHVyZVxuICAgKiBAcGFyYW0gcmV0cmllcyAtIE51bWJlciBvZiByZXRyeSBhdHRlbXB0cyByZW1haW5pbmcgKGRlY3JlbWVudHMgZWFjaCByZXRyeSlcbiAgICogQHBhcmFtIGRlbGF5IC0gQ3VycmVudCBkZWxheSBpbiBtaWxsaXNlY29uZHMgYmVmb3JlIG5leHQgcmV0cnlcbiAgICogQHBhcmFtIHNpZ25hbCAtIE9wdGlvbmFsIEFib3J0U2lnbmFsIHRvIGNhbmNlbCByZXRyaWVzXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBmdW5jdGlvbidzIHJlc3VsdCBvbiBzdWNjZXNzXG4gICAqIEB0aHJvd3MgVGhlIGxhc3QgZXJyb3IgZW5jb3VudGVyZWQgaWYgYWxsIHJldHJpZXMgYXJlIGV4aGF1c3RlZFxuICAgKiBAdGhyb3dzIEFib3J0RXJyb3IgaWYgdGhlIHNpZ25hbCBpcyBhYm9ydGVkIGR1cmluZyBleGVjdXRpb24gb3IgZGVsYXlcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogQmFzaWMgcmV0cnkgdXNhZ2U6XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgaGFuZGxlciA9IG5ldyBSZXRyeUhhbmRsZXIoKTtcbiAgICogY29uc3QgZmV0Y2hVc2VyID0gKCkgPT4gZmV0Y2goJy9hcGkvdXNlcnMvMTIzJykudGhlbihyID0+IHIuanNvbigpKTtcbiAgICpcbiAgICogdHJ5IHtcbiAgICogICBjb25zdCB1c2VyID0gYXdhaXQgaGFuZGxlci5yZXRyeVJlcXVlc3QoXG4gICAqICAgICBmZXRjaFVzZXIsXG4gICAqICAgICAzLCAgICAgIC8vIDMgcmV0cmllc1xuICAgKiAgICAgMTAwMCAgICAvLyBTdGFydCB3aXRoIDFzIGRlbGF5XG4gICAqICAgKTtcbiAgICogICBjb25zb2xlLmxvZygnVXNlcjonLCB1c2VyKTtcbiAgICogfSBjYXRjaCAoZXJyb3IpIHtcbiAgICogICBjb25zb2xlLmVycm9yKCdGYWlsZWQgYWZ0ZXIgYWxsIHJldHJpZXM6JywgZXJyb3IpO1xuICAgKiB9XG4gICAqIGBgYFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBXaXRoIGNhbmNlbGxhdGlvbiBzdXBwb3J0OlxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAqIGNvbnN0IHNpZ25hbCA9IGNvbnRyb2xsZXIuc2lnbmFsO1xuICAgKlxuICAgKiAvLyBDYW5jZWwgYWZ0ZXIgNSBzZWNvbmRzXG4gICAqIHNldFRpbWVvdXQoKCkgPT4gY29udHJvbGxlci5hYm9ydCgpLCA1MDAwKTtcbiAgICpcbiAgICogdHJ5IHtcbiAgICogICBhd2FpdCBoYW5kbGVyLnJldHJ5UmVxdWVzdChmZXRjaFVzZXIsIDUsIDEwMDAsIHNpZ25hbCk7XG4gICAqIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAqICAgaWYgKGVycm9yLm5hbWUgPT09ICdBYm9ydEVycm9yJykge1xuICAgKiAgICAgY29uc29sZS5sb2coJ1JldHJ5IGNhbmNlbGxlZCcpO1xuICAgKiAgIH1cbiAgICogfVxuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIHJldHJ5UmVxdWVzdDxUPihcbiAgICBmbjogKCkgPT4gUHJvbWlzZTxUPixcbiAgICByZXRyaWVzOiBudW1iZXIsXG4gICAgZGVsYXk6IG51bWJlcixcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbFxuICApOiBQcm9taXNlPFQ+IHtcbiAgICB0cnkge1xuICAgICAgLy8gQ2hlY2sgaWYgYWxyZWFkeSBhYm9ydGVkXG4gICAgICBpZiAoc2lnbmFsPy5hYm9ydGVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihzaWduYWwucmVhc29uIHx8ICdSZXF1ZXN0IGFib3J0ZWQnKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGF3YWl0IGZuKCk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIGNvbnN0IGVyciA9IGVycm9yIGFzIEFwaUVycm9yO1xuXG4gICAgICAvLyBEb24ndCByZXRyeSBpZiBhYm9ydGVkXG4gICAgICBpZiAoZXJyLm5hbWUgPT09ICdBYm9ydEVycm9yJyB8fCBzaWduYWw/LmFib3J0ZWQpIHtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG5cbiAgICAgIC8vIERvbid0IHJldHJ5IHZhbGlkYXRpb24gZXJyb3JzXG4gICAgICBpZiAoZXJyLnR5cGUgPT09ICd2YWxpZGF0aW9uX2Vycm9yJyB8fCBlcnIuc3RhdHVzID09PSA0MDApIHtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG5cbiAgICAgIGlmIChyZXRyaWVzID09PSAwKSB0aHJvdyBlcnJvcjtcblxuICAgICAgLy8gV2FpdCB3aXRoIGFib3J0IHN1cHBvcnRcbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY29uc3QgdGltZW91dElkID0gc2V0VGltZW91dChyZXNvbHZlLCBkZWxheSk7XG5cbiAgICAgICAgaWYgKHNpZ25hbCkge1xuICAgICAgICAgIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgICAgICAgJ2Fib3J0JyxcbiAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3Ioc2lnbmFsLnJlYXNvbiB8fCAnUmVxdWVzdCBhYm9ydGVkJykpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHsgb25jZTogdHJ1ZSB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiB0aGlzLnJldHJ5UmVxdWVzdChmbiwgcmV0cmllcyAtIDEsIGRlbGF5ICogMiwgc2lnbmFsKTtcbiAgICB9XG4gIH1cbn1cbiIsICIvKipcbiAqIE1hbmFnZXMgQWJvcnRTaWduYWwgY3JlYXRpb24gYW5kIGNvbXBvc2l0aW9uIGZvciByZXF1ZXN0IGNhbmNlbGxhdGlvbiBhbmQgdGltZW91dHMuXG4gKlxuICogVGhpcyBpbnRlcm5hbCBjbGFzcyBwcm92aWRlcyB1dGlsaXRpZXMgZm9yIHdvcmtpbmcgd2l0aCB0aGUgQWJvcnRTaWduYWwgQVBJLFxuICogZW5hYmxpbmcgc29waGlzdGljYXRlZCBjYW5jZWxsYXRpb24gcGF0dGVybnMgYnkgY29tYmluaW5nIG11bHRpcGxlIGNhbmNlbGxhdGlvblxuICogc291cmNlcyBhbmQgY3JlYXRpbmcgdGltZW91dC1iYXNlZCBzaWduYWxzLlxuICpcbiAqIEtleSBGZWF0dXJlczpcbiAqIC0gKipTaWduYWwgQ29tcG9zaXRpb24qKjogQ29tYmluZSBtdWx0aXBsZSBBYm9ydFNpZ25hbHMgaW50byBvbmVcbiAqIC0gKipUaW1lb3V0IFNpZ25hbHMqKjogQ3JlYXRlIHNpZ25hbHMgdGhhdCBhdXRvLWFib3J0IGFmdGVyIGEgZGVsYXlcbiAqIC0gKipFYXJseSBBYm9ydCBEZXRlY3Rpb24qKjogSW1tZWRpYXRlbHkgYWJvcnQgaWYgYW55IHNvdXJjZSBpcyBhbHJlYWR5IGFib3J0ZWRcbiAqIC0gKipSZXNvdXJjZSBDbGVhbnVwKio6IEF1dG9tYXRpYyB0aW1lb3V0IGNsZWFudXAgb24gYWJvcnRcbiAqXG4gKiBVc2UgQ2FzZXM6XG4gKiAtIENvbWJpbmUgdXNlciBjYW5jZWxsYXRpb24gKyB0aW1lb3V0ICsgY29tcG9uZW50IHVubW91bnQgc2lnbmFsc1xuICogLSBDcmVhdGUgcmVxdWVzdCBkZWFkbGluZXNcbiAqIC0gSW1wbGVtZW50IGNhc2NhZGluZyBjYW5jZWxsYXRpb25cbiAqXG4gKiBAaW50ZXJuYWwgVGhpcyBjbGFzcyBpcyBub3QgZXhwb3J0ZWQgZnJvbSB0aGUgcHVibGljIEFQSVxuICpcbiAqIEBleGFtcGxlXG4gKiBDb21iaW5pbmcgbXVsdGlwbGUgY2FuY2VsbGF0aW9uIHNvdXJjZXM6XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBtYW5hZ2VyID0gbmV3IFNpZ25hbE1hbmFnZXIoKTtcbiAqIGNvbnN0IHVzZXJDYW5jZWwgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gKiBjb25zdCB1bm1vdW50U2lnbmFsID0gY29tcG9uZW50VW5tb3VudFNpZ25hbDtcbiAqXG4gKiAvLyBSZXF1ZXN0IHdpbGwgYmUgY2FuY2VsbGVkIGlmIGVpdGhlciB1c2VyIGNsaWNrcyBjYW5jZWwgT1IgY29tcG9uZW50IHVubW91bnRzXG4gKiBjb25zdCBjb21iaW5lZCA9IG1hbmFnZXIuY3JlYXRlQ29tYmluZWRTaWduYWwoW1xuICogICB1c2VyQ2FuY2VsLnNpZ25hbCxcbiAqICAgdW5tb3VudFNpZ25hbFxuICogXSk7XG4gKlxuICogZmV0Y2goJy9hcGkvZGF0YScsIHsgc2lnbmFsOiBjb21iaW5lZC5zaWduYWwgfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIFNpZ25hbE1hbmFnZXIge1xuICAvKipcbiAgICogQ3JlYXRlcyBhIGNvbWJpbmVkIEFib3J0Q29udHJvbGxlciB0aGF0IGFib3J0cyB3aGVuIGFueSBzb3VyY2Ugc2lnbmFsIGFib3J0cy5cbiAgICpcbiAgICogVGhpcyBtZXRob2QgaW1wbGVtZW50cyB0aGUgXCJhbnlcIiBwYXR0ZXJuIGZvciBjYW5jZWxsYXRpb246IHRoZSBjb21iaW5lZCBzaWduYWxcbiAgICogd2lsbCBhYm9ydCBhcyBzb29uIGFzIEFOWSBvZiB0aGUgc291cmNlIHNpZ25hbHMgYWJvcnQuIFRoaXMgaXMgdXNlZnVsIGZvclxuICAgKiBjb29yZGluYXRpbmcgbXVsdGlwbGUgY2FuY2VsbGF0aW9uIGNvbmRpdGlvbnM6XG4gICAqIC0gVXNlciBjbGlja3MgY2FuY2VsIGJ1dHRvblxuICAgKiAtIFJlcXVlc3QgdGltZW91dCBleHBpcmVzXG4gICAqIC0gQ29tcG9uZW50IHVubW91bnRzXG4gICAqIC0gUGFyZW50IHJlcXVlc3QgaXMgY2FuY2VsbGVkXG4gICAqXG4gICAqICoqRWFybHkgQWJvcnQgT3B0aW1pemF0aW9uOioqXG4gICAqIElmIGFueSBzb3VyY2Ugc2lnbmFsIGlzIGFscmVhZHkgYWJvcnRlZCB3aGVuIHRoaXMgbWV0aG9kIGlzIGNhbGxlZCxcbiAgICogdGhlIHJldHVybmVkIGNvbnRyb2xsZXIgaXMgaW1tZWRpYXRlbHkgYWJvcnRlZCB3aXRob3V0IHNldHRpbmcgdXAgbGlzdGVuZXJzLlxuICAgKlxuICAgKiAqKk1lbW9yeSBNYW5hZ2VtZW50OioqXG4gICAqIEV2ZW50IGxpc3RlbmVycyBhcmUgcmVnaXN0ZXJlZCB3aXRoIGB7IG9uY2U6IHRydWUgfWAgdG8gcHJldmVudCBtZW1vcnkgbGVha3MsXG4gICAqIGFzIHRoZXkgYXV0b21hdGljYWxseSBjbGVhbiB1cCBhZnRlciBmaXJpbmcuXG4gICAqXG4gICAqIEBwYXJhbSBzaWduYWxzIC0gQXJyYXkgb2YgQWJvcnRTaWduYWxzIHRvIGNvbWJpbmUgKHVuZGVmaW5lZCB2YWx1ZXMgYXJlIGlnbm9yZWQpXG4gICAqIEByZXR1cm5zIEEgbmV3IEFib3J0Q29udHJvbGxlciB0aGF0IGFib3J0cyB3aGVuIGFueSBzb3VyY2Ugc2lnbmFsIGFib3J0c1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBVc2VyIGNhbmNlbGxhdGlvbiArIHRpbWVvdXQ6XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgdXNlckNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAqIGNvbnN0IHRpbWVvdXQgPSBtYW5hZ2VyLmNyZWF0ZVRpbWVvdXRTaWduYWwoMzAwMDApO1xuICAgKlxuICAgKiBjb25zdCBjb21iaW5lZCA9IG1hbmFnZXIuY3JlYXRlQ29tYmluZWRTaWduYWwoW1xuICAgKiAgIHVzZXJDb250cm9sbGVyLnNpZ25hbCxcbiAgICogICB0aW1lb3V0LnNpZ25hbFxuICAgKiBdKTtcbiAgICpcbiAgICogLy8gUmVxdWVzdCB3aWxsIGJlIGNhbmNlbGxlZCBhZnRlciAzMHMgT1Igd2hlbiB1c2VyIGNsaWNrcyBjYW5jZWxcbiAgICogZmV0Y2goJy9hcGkvZGF0YScsIHsgc2lnbmFsOiBjb21iaW5lZC5zaWduYWwgfSk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBSZWFjdCBjb21wb25lbnQgd2l0aCBjbGVhbnVwOlxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAqICAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICpcbiAgICogICBjb25zdCBjb21iaW5lZCA9IG1hbmFnZXIuY3JlYXRlQ29tYmluZWRTaWduYWwoW1xuICAgKiAgICAgY29udHJvbGxlci5zaWduYWwsXG4gICAqICAgICB1bm1vdW50U2lnbmFsICAvLyBGcm9tIGNvbXBvbmVudCBsaWZlY3ljbGVcbiAgICogICBdKTtcbiAgICpcbiAgICogICBmZXRjaERhdGEoY29tYmluZWQuc2lnbmFsKTtcbiAgICpcbiAgICogICByZXR1cm4gKCkgPT4gY29udHJvbGxlci5hYm9ydCgpOyAvLyBDbGVhbnVwXG4gICAqIH0sIFtdKTtcbiAgICogYGBgXG4gICAqL1xuICBjcmVhdGVDb21iaW5lZFNpZ25hbChcbiAgICBzaWduYWxzOiBBcnJheTxBYm9ydFNpZ25hbCB8IHVuZGVmaW5lZD5cbiAgKTogQWJvcnRDb250cm9sbGVyIHtcbiAgICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuXG4gICAgZm9yIChjb25zdCBzaWduYWwgb2Ygc2lnbmFscykge1xuICAgICAgaWYgKHNpZ25hbCkge1xuICAgICAgICBpZiAoc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgICAgICBjb250cm9sbGVyLmFib3J0KHNpZ25hbC5yZWFzb24pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgJ2Fib3J0JyxcbiAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICBjb250cm9sbGVyLmFib3J0KHNpZ25hbC5yZWFzb24pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBvbmNlOiB0cnVlIH1cbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29udHJvbGxlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIEFib3J0Q29udHJvbGxlciB0aGF0IGF1dG9tYXRpY2FsbHkgYWJvcnRzIGFmdGVyIGEgc3BlY2lmaWVkIHRpbWVvdXQuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGNyZWF0ZXMgYSB0aW1lLWJhc2VkIGNhbmNlbGxhdGlvbiBtZWNoYW5pc20gdXNlZnVsIGZvciBpbXBsZW1lbnRpbmdcbiAgICogcmVxdWVzdCB0aW1lb3V0cyBhbmQgZGVhZGxpbmVzLiBUaGUgc2lnbmFsIHdpbGwgYXV0b21hdGljYWxseSBhYm9ydCBhZnRlciB0aGVcbiAgICogc3BlY2lmaWVkIGR1cmF0aW9uLCBwcm92aWRpbmcgYSBjb25zaXN0ZW50IHRpbWVvdXQgZXhwZXJpZW5jZS5cbiAgICpcbiAgICogKipBdXRvbWF0aWMgQ2xlYW51cDoqKlxuICAgKiBJZiB0aGUgc2lnbmFsIGlzIGFib3J0ZWQgYnkgb3RoZXIgbWVhbnMgYmVmb3JlIHRoZSB0aW1lb3V0IGV4cGlyZXMsIHRoZSBpbnRlcm5hbFxuICAgKiBzZXRUaW1lb3V0IGlzIGF1dG9tYXRpY2FsbHkgY2xlYXJlZCB0byBwcmV2ZW50IG1lbW9yeSBsZWFrcy5cbiAgICpcbiAgICogKipBYm9ydCBSZWFzb246KipcbiAgICogVGhlIGFib3J0IHJlYXNvbiBpbmNsdWRlcyB0aGUgdGltZW91dCBkdXJhdGlvbiBmb3IgZGVidWdnaW5nIHB1cnBvc2VzOlxuICAgKiBgXCJSZXF1ZXN0IHRpbWVvdXQgYWZ0ZXIge3RpbWVvdXR9bXNcImBcbiAgICpcbiAgICogQHBhcmFtIHRpbWVvdXQgLSBUaW1lb3V0IGR1cmF0aW9uIGluIG1pbGxpc2Vjb25kc1xuICAgKiBAcmV0dXJucyBBbiBBYm9ydENvbnRyb2xsZXIgdGhhdCB3aWxsIGFib3J0IGFmdGVyIHRoZSB0aW1lb3V0XG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIFNpbXBsZSByZXF1ZXN0IHRpbWVvdXQ6XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgbWFuYWdlciA9IG5ldyBTaWduYWxNYW5hZ2VyKCk7XG4gICAqIGNvbnN0IHRpbWVvdXQgPSBtYW5hZ2VyLmNyZWF0ZVRpbWVvdXRTaWduYWwoNTAwMCk7IC8vIDUgc2Vjb25kc1xuICAgKlxuICAgKiB0cnkge1xuICAgKiAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goJy9hcGkvc2xvdy1lbmRwb2ludCcsIHtcbiAgICogICAgIHNpZ25hbDogdGltZW91dC5zaWduYWxcbiAgICogICB9KTtcbiAgICogICBjb25zdCBkYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgKiB9IGNhdGNoIChlcnJvcikge1xuICAgKiAgIGlmIChlcnJvci5uYW1lID09PSAnQWJvcnRFcnJvcicpIHtcbiAgICogICAgIGNvbnNvbGUuZXJyb3IoJ1JlcXVlc3QgdGltZWQgb3V0IGFmdGVyIDUgc2Vjb25kcycpO1xuICAgKiAgIH1cbiAgICogfVxuICAgKiBgYGBcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogRGlmZmVyZW50IHRpbWVvdXRzIGZvciBkaWZmZXJlbnQgb3BlcmF0aW9uczpcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiAvLyBTaG9ydCB0aW1lb3V0IGZvciBxdWljayBvcGVyYXRpb25zXG4gICAqIGNvbnN0IHF1aWNrVGltZW91dCA9IG1hbmFnZXIuY3JlYXRlVGltZW91dFNpZ25hbCgyMDAwKTtcbiAgICogYXdhaXQgZmV0Y2goJy9hcGkvaGVhbHRoJywgeyBzaWduYWw6IHF1aWNrVGltZW91dC5zaWduYWwgfSk7XG4gICAqXG4gICAqIC8vIExvbmcgdGltZW91dCBmb3IgaGVhdnkgb3BlcmF0aW9uc1xuICAgKiBjb25zdCBsb25nVGltZW91dCA9IG1hbmFnZXIuY3JlYXRlVGltZW91dFNpZ25hbCg2MDAwMCk7XG4gICAqIGF3YWl0IGZldGNoKCcvYXBpL2V4cG9ydCcsIHsgc2lnbmFsOiBsb25nVGltZW91dC5zaWduYWwgfSk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBNYW51YWwgY2FuY2VsbGF0aW9uIGJlZm9yZSB0aW1lb3V0OlxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHRpbWVvdXQgPSBtYW5hZ2VyLmNyZWF0ZVRpbWVvdXRTaWduYWwoMzAwMDApO1xuICAgKlxuICAgKiAvLyBJZiB1c2VyIGNhbmNlbHMsIHRpbWVvdXQgaXMgYXV0b21hdGljYWxseSBjbGVhbmVkIHVwXG4gICAqIHRpbWVvdXQuYWJvcnQoJ1VzZXIgY2FuY2VsbGVkJyk7XG4gICAqIC8vIEludGVybmFsIHNldFRpbWVvdXQgaXMgY2xlYXJlZCwgbm8gbWVtb3J5IGxlYWtcbiAgICogYGBgXG4gICAqL1xuICBjcmVhdGVUaW1lb3V0U2lnbmFsKHRpbWVvdXQ6IG51bWJlcik6IEFib3J0Q29udHJvbGxlciB7XG4gICAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblxuICAgIGNvbnN0IHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgY29udHJvbGxlci5hYm9ydChgUmVxdWVzdCB0aW1lb3V0IGFmdGVyICR7dGltZW91dH1tc2ApO1xuICAgIH0sIHRpbWVvdXQpO1xuXG4gICAgLy8gQ2xlYW4gdXAgdGltZW91dCB3aGVuIHNpZ25hbCBpcyBhYm9ydGVkXG4gICAgY29udHJvbGxlci5zaWduYWwuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICdhYm9ydCcsXG4gICAgICAoKSA9PiB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0SWQpO1xuICAgICAgfSxcbiAgICAgIHsgb25jZTogdHJ1ZSB9XG4gICAgKTtcblxuICAgIHJldHVybiBjb250cm9sbGVyO1xuICB9XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBSZXNwb25zZURhdGEgfSBmcm9tICcuLi9Nb2RlbHMnO1xuXG4vKipcbiAqIFBhcnNlcyBIVFRQIHJlc3BvbnNlIGJvZGllcyBpbnRvIGFwcHJvcHJpYXRlIEphdmFTY3JpcHQgdHlwZXMgYmFzZWQgb24gQ29udGVudC1UeXBlIGhlYWRlcnMuXG4gKlxuICogVGhpcyBpbnRlcm5hbCBjbGFzcyBoYW5kbGVzIHRoZSBjb21wbGV4aXR5IG9mIGNvbnZlcnRpbmcgdmFyaW91cyBIVFRQIHJlc3BvbnNlIGZvcm1hdHNcbiAqIGludG8gdXNhYmxlIEphdmFTY3JpcHQgZGF0YSBzdHJ1Y3R1cmVzLiBJdCBpbnRlbGxpZ2VudGx5IGRldGVjdHMgdGhlIHJlc3BvbnNlIHR5cGVcbiAqIGFuZCBhcHBsaWVzIHRoZSBhcHByb3ByaWF0ZSBwYXJzaW5nIHN0cmF0ZWd5LlxuICpcbiAqIFN1cHBvcnRlZCBDb250ZW50IFR5cGVzOlxuICogLSAqKmFwcGxpY2F0aW9uL2pzb24qKjogUGFyc2VkIGFzIEpTT04gb2JqZWN0cy9hcnJheXNcbiAqIC0gKip0ZXh0LyoqKiAodGV4dC9wbGFpbiwgdGV4dC9odG1sLCBldGMuKTogUmV0dXJuZWQgYXMgc3RyaW5nXG4gKiAtICoqYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtKio6IFJldHVybmVkIGFzIEJsb2IgZm9yIGJpbmFyeSBkYXRhXG4gKiAtICoqVW5rbm93bi9NaXNzaW5nKio6IEF0dGVtcHRzIEpTT04gcGFyc2UsIGZhbGxzIGJhY2sgdG8gdGV4dFxuICpcbiAqIEtleSBGZWF0dXJlczpcbiAqIC0gKipBdXRvbWF0aWMgRGV0ZWN0aW9uKio6IFVzZXMgQ29udGVudC1UeXBlIGhlYWRlciB0byBkZXRlcm1pbmUgcGFyc2luZyBzdHJhdGVneVxuICogLSAqKkdyYWNlZnVsIEZhbGxiYWNrKio6IEF0dGVtcHRzIEpTT04gcGFyc2luZyBmb3IgdW5rbm93biB0eXBlcywgZmFsbHMgYmFjayB0byB0ZXh0XG4gKiAtICoqQmluYXJ5IFN1cHBvcnQqKjogSGFuZGxlcyBiaW5hcnkgZGF0YSB2aWEgQmxvYlxuICogLSAqKlR5cGUgU2FmZXR5Kio6IFJldHVybnMgdHlwZWQgUmVzcG9uc2VEYXRhIHVuaW9uXG4gKlxuICogQGludGVybmFsIFRoaXMgY2xhc3MgaXMgbm90IGV4cG9ydGVkIGZyb20gdGhlIHB1YmxpYyBBUElcbiAqXG4gKiBAZXhhbXBsZVxuICogUGFyc2luZyBkaWZmZXJlbnQgcmVzcG9uc2UgdHlwZXM6XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBwYXJzZXIgPSBuZXcgUmVzcG9uc2VQYXJzZXIoKTtcbiAqXG4gKiAvLyBKU09OIHJlc3BvbnNlXG4gKiBjb25zdCBqc29uUmVzcG9uc2UgPSBuZXcgUmVzcG9uc2UoJ3tcImlkXCI6IDF9Jywge1xuICogICBoZWFkZXJzOiB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicgfVxuICogfSk7XG4gKiBjb25zdCBkYXRhID0gYXdhaXQgcGFyc2VyLnBhcnNlUmVzcG9uc2UoanNvblJlc3BvbnNlKTtcbiAqIC8vID0+IHsgaWQ6IDEgfVxuICpcbiAqIC8vIFRleHQgcmVzcG9uc2VcbiAqIGNvbnN0IHRleHRSZXNwb25zZSA9IG5ldyBSZXNwb25zZSgnSGVsbG8gV29ybGQnLCB7XG4gKiAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICd0ZXh0L3BsYWluJyB9XG4gKiB9KTtcbiAqIGNvbnN0IHRleHQgPSBhd2FpdCBwYXJzZXIucGFyc2VSZXNwb25zZSh0ZXh0UmVzcG9uc2UpO1xuICogLy8gPT4gXCJIZWxsbyBXb3JsZFwiXG4gKlxuICogLy8gQmluYXJ5IHJlc3BvbnNlXG4gKiBjb25zdCBibG9iUmVzcG9uc2UgPSBuZXcgUmVzcG9uc2UoYmluYXJ5RGF0YSwge1xuICogICBoZWFkZXJzOiB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtJyB9XG4gKiB9KTtcbiAqIGNvbnN0IGJsb2IgPSBhd2FpdCBwYXJzZXIucGFyc2VSZXNwb25zZShibG9iUmVzcG9uc2UpO1xuICogLy8gPT4gQmxvYiB7IC4uLiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIFJlc3BvbnNlUGFyc2VyIHtcbiAgLyoqXG4gICAqIFBhcnNlcyB0aGUgSFRUUCByZXNwb25zZSBib2R5IGludG8gYW4gYXBwcm9wcmlhdGUgSmF2YVNjcmlwdCB0eXBlLlxuICAgKlxuICAgKiBUaGUgcGFyc2luZyBzdHJhdGVneSBpcyBkZXRlcm1pbmVkIGJ5IHRoZSBDb250ZW50LVR5cGUgaGVhZGVyOlxuICAgKiAxLiAqKkpTT04qKiAoYXBwbGljYXRpb24vanNvbik6IENhbGxzIGByZXNwb25zZS5qc29uKClgXG4gICAqIDIuICoqVGV4dCoqICh0ZXh0LyopOiBDYWxscyBgcmVzcG9uc2UudGV4dCgpYFxuICAgKiAzLiAqKkJpbmFyeSoqIChhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0pOiBDYWxscyBgcmVzcG9uc2UuYmxvYigpYFxuICAgKiA0LiAqKlVua25vd24qKjogUmVhZHMgYXMgdGV4dCwgYXR0ZW1wdHMgSlNPTiBwYXJzZSwgZmFsbHMgYmFjayB0byByYXcgdGV4dFxuICAgKlxuICAgKiAqKkZhbGxiYWNrIEJlaGF2aW9yOioqXG4gICAqIEZvciByZXNwb25zZXMgd2l0aG91dCBhIENvbnRlbnQtVHlwZSBoZWFkZXIgb3Igd2l0aCB1bmtub3duIHR5cGVzLCB0aGUgcGFyc2VyXG4gICAqIGF0dGVtcHRzIHRvIHBhcnNlIGFzIEpTT04gZmlyc3QgKGNvbW1vbiBmb3IgQVBJcyB0aGF0IGRvbid0IHNldCBwcm9wZXIgaGVhZGVycykuXG4gICAqIElmIEpTT04gcGFyc2luZyBmYWlscywgaXQgcmV0dXJucyB0aGUgcmF3IHRleHQuXG4gICAqXG4gICAqIEBwYXJhbSByZXNwb25zZSAtIFRoZSBGZXRjaCBBUEkgUmVzcG9uc2Ugb2JqZWN0IHRvIHBhcnNlXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHRoZSBwYXJzZWQgcmVzcG9uc2UgZGF0YVxuICAgKiBAcmV0dXJucyBDYW4gYmU6IEpTT04gb2JqZWN0L2FycmF5LCBzdHJpbmcsIG9yIEJsb2IgZGVwZW5kaW5nIG9uIENvbnRlbnQtVHlwZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBBUEkgcmVzcG9uc2UgcGFyc2luZzpcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKCcvYXBpL3VzZXJzJyk7XG4gICAqIGNvbnN0IGRhdGEgPSBhd2FpdCBwYXJzZXIucGFyc2VSZXNwb25zZShyZXNwb25zZSk7XG4gICAqXG4gICAqIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycpIHtcbiAgICogICBjb25zb2xlLmxvZygnVGV4dCByZXNwb25zZTonLCBkYXRhKTtcbiAgICogfSBlbHNlIGlmIChkYXRhIGluc3RhbmNlb2YgQmxvYikge1xuICAgKiAgIGNvbnNvbGUubG9nKCdCaW5hcnkgcmVzcG9uc2U6JywgZGF0YS5zaXplLCAnYnl0ZXMnKTtcbiAgICogfSBlbHNlIHtcbiAgICogICBjb25zb2xlLmxvZygnSlNPTiByZXNwb25zZTonLCBkYXRhKTtcbiAgICogfVxuICAgKiBgYGBcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogSGFuZGxpbmcgZGlmZmVyZW50IGNvbnRlbnQgdHlwZXM6XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogLy8gQ1NWIGZpbGUgZG93bmxvYWRcbiAgICogY29uc3QgY3N2UmVzcG9uc2UgPSBhd2FpdCBmZXRjaCgnL2FwaS9leHBvcnQuY3N2Jyk7XG4gICAqIGNvbnN0IGJsb2IgPSBhd2FpdCBwYXJzZXIucGFyc2VSZXNwb25zZShjc3ZSZXNwb25zZSk7XG4gICAqIC8vIFJldHVybnMgQmxvYiBmb3IgZG93bmxvYWRcbiAgICpcbiAgICogLy8gSlNPTiBBUElcbiAgICogY29uc3QganNvblJlc3BvbnNlID0gYXdhaXQgZmV0Y2goJy9hcGkvdXNlcnMnKTtcbiAgICogY29uc3QgdXNlcnMgPSBhd2FpdCBwYXJzZXIucGFyc2VSZXNwb25zZShqc29uUmVzcG9uc2UpO1xuICAgKiAvLyBSZXR1cm5zIHBhcnNlZCBKU09OIGFycmF5XG4gICAqXG4gICAqIC8vIFBsYWluIHRleHQgbG9nc1xuICAgKiBjb25zdCBsb2dSZXNwb25zZSA9IGF3YWl0IGZldGNoKCcvYXBpL2xvZ3MnKTtcbiAgICogY29uc3QgbG9ncyA9IGF3YWl0IHBhcnNlci5wYXJzZVJlc3BvbnNlKGxvZ1Jlc3BvbnNlKTtcbiAgICogLy8gUmV0dXJucyBzdHJpbmdcbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBwYXJzZVJlc3BvbnNlKHJlc3BvbnNlOiBSZXNwb25zZSk6IFByb21pc2U8UmVzcG9uc2VEYXRhPiB7XG4gICAgY29uc3QgY29udGVudFR5cGUgPSByZXNwb25zZS5oZWFkZXJzLmdldCgnY29udGVudC10eXBlJyk7XG5cbiAgICBpZiAoY29udGVudFR5cGU/LmluY2x1ZGVzKCdhcHBsaWNhdGlvbi9qc29uJykpIHtcbiAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgfSBlbHNlIGlmIChjb250ZW50VHlwZT8uaW5jbHVkZXMoJ3RleHQvJykpIHtcbiAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KCk7XG4gICAgfSBlbHNlIGlmIChjb250ZW50VHlwZT8uaW5jbHVkZXMoJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbScpKSB7XG4gICAgICByZXR1cm4gcmVzcG9uc2UuYmxvYigpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBUcnkgSlNPTiBmaXJzdCwgZmFsbGJhY2sgdG8gdGV4dFxuICAgICAgY29uc3QgdGV4dCA9IGF3YWl0IHJlc3BvbnNlLnRleHQoKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UodGV4dCkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBRdWVyeVBhcmFtcyB9IGZyb20gJy4uL01vZGVscyc7XG5cbi8qKlxuICogQ29uc3RydWN0cyBmdWxseS1xdWFsaWZpZWQgVVJMcyB3aXRoIHByb3BlciBxdWVyeSBwYXJhbWV0ZXIgZW5jb2RpbmcuXG4gKlxuICogVGhpcyBpbnRlcm5hbCBjbGFzcyBoYW5kbGVzIHRoZSBjb21wbGV4aXR5IG9mIFVSTCBjb25zdHJ1Y3Rpb24sIGNvbWJpbmluZ1xuICogYmFzZSBVUkxzLCBlbmRwb2ludHMsIGFuZCBxdWVyeSBwYXJhbWV0ZXJzIHdpdGggcHJvcGVyIGVuY29kaW5nIGFuZCBhcnJheVxuICogaGFuZGxpbmcuIEl0IHVzZXMgdGhlIG5hdGl2ZSBVUkwgQVBJIGZvciByZWxpYWJsZSBVUkwgY29tcG9zaXRpb24uXG4gKlxuICogS2V5IEZlYXR1cmVzOlxuICogLSAqKlVSTCBDb21wb3NpdGlvbioqOiBTYWZlbHkgY29tYmluZXMgYmFzZSBVUkwgYW5kIGVuZHBvaW50IHBhdGhzXG4gKiAtICoqUXVlcnkgUGFyYW1ldGVyIEVuY29kaW5nKio6IEF1dG9tYXRpYyBlbmNvZGluZyBvZiBzcGVjaWFsIGNoYXJhY3RlcnNcbiAqIC0gKipBcnJheSBTdXBwb3J0Kio6IEhhbmRsZXMgYXJyYXkgcGFyYW1ldGVycyB3aXRoIG11bHRpcGxlIHZhbHVlc1xuICogLSAqKk51bGwvVW5kZWZpbmVkIEZpbHRlcmluZyoqOiBBdXRvbWF0aWNhbGx5IHNraXBzIG51bGwvdW5kZWZpbmVkIHZhbHVlc1xuICogLSAqKlR5cGUgU2FmZXR5Kio6IFN0cm9uZ2x5IHR5cGVkIHF1ZXJ5IHBhcmFtZXRlciB2YWx1ZXNcbiAqXG4gKiBBcnJheSBIYW5kbGluZzpcbiAqIEFycmF5IHBhcmFtZXRlcnMgYXJlIHNlcmlhbGl6ZWQgYnkgYXBwZW5kaW5nIHRoZSBzYW1lIGtleSBtdWx0aXBsZSB0aW1lczpcbiAqIGA/dGFncz1qYXZhc2NyaXB0JnRhZ3M9dHlwZXNjcmlwdCZ0YWdzPXJlYWN0YFxuICpcbiAqIEBpbnRlcm5hbCBUaGlzIGNsYXNzIGlzIG5vdCBleHBvcnRlZCBmcm9tIHRoZSBwdWJsaWMgQVBJXG4gKlxuICogQGV4YW1wbGVcbiAqIEJ1aWxkaW5nIFVSTHMgd2l0aCBxdWVyeSBwYXJhbWV0ZXJzOlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgYnVpbGRlciA9IG5ldyBVcmxCdWlsZGVyKCk7XG4gKlxuICogY29uc3QgdXJsID0gYnVpbGRlci5idWlsZFVSTChcbiAqICAgJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJyxcbiAqICAgJy91c2VycycsXG4gKiAgIHsgYWN0aXZlOiB0cnVlLCByb2xlOiAnYWRtaW4nLCBwYWdlOiAxIH1cbiAqICk7XG4gKiAvLyA9PiBcImh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3VzZXJzP2FjdGl2ZT10cnVlJnJvbGU9YWRtaW4mcGFnZT0xXCJcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgVXJsQnVpbGRlciB7XG4gIC8qKlxuICAgKiBCdWlsZHMgYSBjb21wbGV0ZSBVUkwgYnkgY29tYmluaW5nIGJhc2UgVVJMLCBlbmRwb2ludCwgYW5kIHF1ZXJ5IHBhcmFtZXRlcnMuXG4gICAqXG4gICAqIFRoZSBVUkwgY29uc3RydWN0aW9uIHByb2Nlc3M6XG4gICAqIDEuIENvbWJpbmVzIGBiYXNlVVJMYCBhbmQgYGVuZHBvaW50YCB1c2luZyBVUkwgQVBJXG4gICAqIDIuIEl0ZXJhdGVzIHRocm91Z2ggcXVlcnkgcGFyYW1ldGVyc1xuICAgKiAzLiBTa2lwcyBudWxsL3VuZGVmaW5lZCB2YWx1ZXNcbiAgICogNC4gSGFuZGxlcyBhcnJheXMgYnkgYXBwZW5kaW5nIG11bHRpcGxlIHZhbHVlcyB3aXRoIHNhbWUga2V5XG4gICAqIDUuIENvbnZlcnRzIGFsbCB2YWx1ZXMgdG8gc3RyaW5nc1xuICAgKiA2LiBSZXR1cm5zIGZ1bGx5LXF1YWxpZmllZCBVUkwgc3RyaW5nXG4gICAqXG4gICAqICoqUGF0aCBIYW5kbGluZzoqKlxuICAgKiBUaGUgZW5kcG9pbnQgY2FuIGJlIGVpdGhlciByZWxhdGl2ZSBvciBhYnNvbHV0ZTpcbiAgICogLSBSZWxhdGl2ZTogYC91c2Vyc2AgXHUyMTkyIENvbWJpbmVkIHdpdGggYmFzZVVSTFxuICAgKiAtIEFic29sdXRlOiBgaHR0cHM6Ly9vdGhlci1hcGkuY29tL3VzZXJzYCBcdTIxOTIgVXNlcyBhYnNvbHV0ZSBVUkxcbiAgICpcbiAgICogKipFbmNvZGluZzoqKlxuICAgKiBBbGwgcGFyYW1ldGVyIHZhbHVlcyBhcmUgYXV0b21hdGljYWxseSBVUkwtZW5jb2RlZCBieSB0aGUgVVJMIEFQSSxcbiAgICogc28gc3BlY2lhbCBjaGFyYWN0ZXJzIChzcGFjZXMsICYsID0sIGV0Yy4pIGFyZSBzYWZlbHkgaGFuZGxlZC5cbiAgICpcbiAgICogQHBhcmFtIGJhc2VVUkwgLSBCYXNlIFVSTCBmb3IgdGhlIEFQSSAoZS5nLiwgJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJylcbiAgICogQHBhcmFtIGVuZHBvaW50IC0gQVBJIGVuZHBvaW50IHBhdGggcmVsYXRpdmUgdG8gYmFzZVVSTCAoZS5nLiwgJy91c2Vycy8xMjMnKVxuICAgKiBAcGFyYW0gcGFyYW1zIC0gT3B0aW9uYWwgcXVlcnkgcGFyYW1ldGVycyBhcyBrZXktdmFsdWUgcGFpcnNcbiAgICogQHJldHVybnMgVGhlIGZ1bGx5LXF1YWxpZmllZCBVUkwgc3RyaW5nIHdpdGggZW5jb2RlZCBxdWVyeSBwYXJhbWV0ZXJzXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIEJhc2ljIFVSTCBjb25zdHJ1Y3Rpb246XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgdXJsID0gYnVpbGRlci5idWlsZFVSTChcbiAgICogICAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nLFxuICAgKiAgICcvc2VhcmNoJyxcbiAgICogICB7IHE6ICdoZWxsbyB3b3JsZCcsIGxpbWl0OiAxMCB9XG4gICAqICk7XG4gICAqIC8vID0+IFwiaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20vc2VhcmNoP3E9aGVsbG8rd29ybGQmbGltaXQ9MTBcIlxuICAgKiBgYGBcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogQXJyYXkgcGFyYW1ldGVyczpcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCB1cmwgPSBidWlsZGVyLmJ1aWxkVVJMKFxuICAgKiAgICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsXG4gICAqICAgJy9wb3N0cycsXG4gICAqICAgeyB0YWdzOiBbJ2phdmFzY3JpcHQnLCAndHlwZXNjcmlwdCcsICdyZWFjdCddIH1cbiAgICogKTtcbiAgICogLy8gPT4gXCJodHRwczovL2FwaS5leGFtcGxlLmNvbS9wb3N0cz90YWdzPWphdmFzY3JpcHQmdGFncz10eXBlc2NyaXB0JnRhZ3M9cmVhY3RcIlxuICAgKiBgYGBcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogTnVsbC91bmRlZmluZWQgaGFuZGxpbmc6XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgdXJsID0gYnVpbGRlci5idWlsZFVSTChcbiAgICogICAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nLFxuICAgKiAgICcvdXNlcnMnLFxuICAgKiAgIHtcbiAgICogICAgIG5hbWU6ICdKb2huJyxcbiAgICogICAgIGFnZTogbnVsbCwgICAgICAgIC8vIFNraXBwZWRcbiAgICogICAgIGVtYWlsOiB1bmRlZmluZWQgIC8vIFNraXBwZWRcbiAgICogICB9XG4gICAqICk7XG4gICAqIC8vID0+IFwiaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20vdXNlcnM/bmFtZT1Kb2huXCJcbiAgICogYGBgXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIFNwZWNpYWwgY2hhcmFjdGVycyBlbmNvZGluZzpcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCB1cmwgPSBidWlsZGVyLmJ1aWxkVVJMKFxuICAgKiAgICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsXG4gICAqICAgJy9zZWFyY2gnLFxuICAgKiAgIHsgcTogJ2ZvbyAmIGJhcicsIGNhdGVnb3J5OiAnY29kZS9leGFtcGxlcycgfVxuICAgKiApO1xuICAgKiAvLyA9PiBcImh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3NlYXJjaD9xPWZvbyslMjYrYmFyJmNhdGVnb3J5PWNvZGUlMkZleGFtcGxlc1wiXG4gICAqIGBgYFxuICAgKi9cbiAgYnVpbGRVUkwoYmFzZVVSTDogc3RyaW5nLCBlbmRwb2ludDogc3RyaW5nLCBwYXJhbXM/OiBRdWVyeVBhcmFtcyk6IHN0cmluZyB7XG4gICAgY29uc3QgdXJsID0gbmV3IFVSTChlbmRwb2ludCwgYmFzZVVSTCk7XG5cbiAgICBpZiAocGFyYW1zKSB7XG4gICAgICBPYmplY3Qua2V5cyhwYXJhbXMpLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBwYXJhbXNba2V5XTtcblxuICAgICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCkge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAgICAgdmFsdWUuZm9yRWFjaCh2ID0+IHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKGtleSwgU3RyaW5nKHYpKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKGtleSwgU3RyaW5nKHZhbHVlKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdXJsLnRvU3RyaW5nKCk7XG4gIH1cbn1cbiIsICJpbXBvcnQgeyBnZW5lcmF0ZUNvcnJlbGF0aW9uSWQgfSBmcm9tICcuL0NvcnJlbGF0aW9uSWRHZW5lcmF0b3InO1xuaW1wb3J0IHsgRXJyb3JOb3JtYWxpemVyIH0gZnJvbSAnLi9FcnJvcnMvRXJyb3JOb3JtYWxpemVyJztcbmltcG9ydCB7IEludGVyY2VwdG9yTWFuYWdlciB9IGZyb20gJy4vSW50ZXJjZXB0b3JzL0ludGVyY2VwdG9yTWFuYWdlcic7XG5pbXBvcnQgdHlwZSB7XG4gIExpc3RSZXNwb25zZSxcbiAgUG9zdE1vZGVsLFxuICBRdWVyeVBhcmFtcyxcbiAgUmVzcG9uc2VEYXRhLFxufSBmcm9tICcuL01vZGVscyc7XG5pbXBvcnQgeyBSZXF1ZXN0TWFuYWdlciB9IGZyb20gJy4vUmVxdWVzdE1hbmFnZXInO1xuaW1wb3J0IHsgUmV0cnlIYW5kbGVyIH0gZnJvbSAnLi9SZXRyeS9SZXRyeUhhbmRsZXInO1xuaW1wb3J0IHsgU2lnbmFsTWFuYWdlciB9IGZyb20gJy4vU2lnbmFscy9TaWduYWxNYW5hZ2VyJztcbmltcG9ydCB0eXBlIHsgQXBpRXJyb3IgfSBmcm9tICcuL3R5cGVzL0FwaUVycm9yJztcbmltcG9ydCB0eXBlIHsgRXJyb3JJbnRlcmNlcHRvciB9IGZyb20gJy4vdHlwZXMvRXJyb3JJbnRlcmNlcHRvcic7XG5pbXBvcnQgdHlwZSB7IEVycm9yUmVzcG9uc2VEYXRhIH0gZnJvbSAnLi90eXBlcy9FcnJvclJlc3BvbnNlRGF0YSc7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3RDb25maWcgfSBmcm9tICcuL3R5cGVzL1JlcXVlc3RDb25maWcnO1xuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0SW50ZXJjZXB0b3IgfSBmcm9tICcuL3R5cGVzL1JlcXVlc3RJbnRlcmNlcHRvcic7XG5pbXBvcnQgdHlwZSB7IFJlc3BvbnNlSW50ZXJjZXB0b3IgfSBmcm9tICcuL3R5cGVzL1Jlc3BvbnNlSW50ZXJjZXB0b3InO1xuaW1wb3J0IHsgUmVzcG9uc2VQYXJzZXIgfSBmcm9tICcuL1V0aWxzL1Jlc3BvbnNlUGFyc2VyJztcbmltcG9ydCB7IFVybEJ1aWxkZXIgfSBmcm9tICcuL1V0aWxzL1VybEJ1aWxkZXInO1xuXG5pbXBvcnQgdHlwZSB7IEFwaVJlc3BvbnNlIH0gZnJvbSAnQC90eXBlcyc7XG5cbi8qKlxuICogRW50ZXJwcmlzZS1ncmFkZSBBUEkgY2xpZW50IHdpdGggYWR2YW5jZWQgZmVhdHVyZXMgZm9yIHByb2R1Y3Rpb24gYXBwbGljYXRpb25zLlxuICpcbiAqIFRoaXMgY2xpZW50IHByb3ZpZGVzIGEgcm9idXN0LCB0eXBlLXNhZmUgYWJzdHJhY3Rpb24gb3ZlciB0aGUgRmV0Y2ggQVBJIHdpdGg6XG4gKiAtIENvbXByZWhlbnNpdmUgcmVxdWVzdC9yZXNwb25zZS9lcnJvciBpbnRlcmNlcHRvciBzeXN0ZW1cbiAqIC0gQXV0b21hdGljIHJldHJ5IGxvZ2ljIHdpdGggZXhwb25lbnRpYWwgYmFja29mZlxuICogLSBSZXF1ZXN0IGNvcnJlbGF0aW9uIElEIHRyYWNraW5nIGZvciBkaXN0cmlidXRlZCB0cmFjaW5nXG4gKiAtIFRva2VuLWJhc2VkIGF1dGhlbnRpY2F0aW9uIHdpdGggYXV0b21hdGljIGhlYWRlciBpbmplY3Rpb25cbiAqIC0gUmVxdWVzdCBjYW5jZWxsYXRpb24gYW5kIHRpbWVvdXQgbWFuYWdlbWVudFxuICogLSBUeXBlLXNhZmUgZXJyb3IgaGFuZGxpbmcgd2l0aCBzdHJ1Y3R1cmVkIGVycm9yIHJlc3BvbnNlc1xuICogLSBSZWFjdCBRdWVyeSBpbnRlZ3JhdGlvbiBzdXBwb3J0XG4gKlxuICogQXJjaGl0ZWN0dXJlIFByaW5jaXBsZXM6XG4gKiAtICoqVHlwZSBTYWZldHkqKjogRnVsbCBUeXBlU2NyaXB0IGluZmVyZW5jZSB3aXRoIG5vIGBhbnlgIHR5cGVzXG4gKiAtICoqRXh0ZW5zaWJpbGl0eSoqOiBJbnRlcmNlcHRvciBwYXR0ZXJuIGFsbG93cyBmb3IgZmxleGlibGUgbWlkZGxld2FyZVxuICogLSAqKk9ic2VydmFiaWxpdHkqKjogQnVpbHQtaW4gY29ycmVsYXRpb24gSURzIGZvciByZXF1ZXN0IHRyYWNpbmdcbiAqIC0gKipSZXNpbGllbmNlKio6IEF1dG9tYXRpYyByZXRyaWVzLCB0aW1lb3V0cywgYW5kIGdyYWNlZnVsIGVycm9yIGhhbmRsaW5nXG4gKiAtICoqUGVyZm9ybWFuY2UqKjogUmVxdWVzdCBkZWR1cGxpY2F0aW9uIGFuZCBjYW5jZWxsYXRpb24gc3VwcG9ydFxuICogLSAqKk1vZHVsYXJpdHkqKjogT3JnYW5pemVkIGludG8gZm9jdXNlZCwgc2luZ2xlLXJlc3BvbnNpYmlsaXR5IG1vZHVsZXNcbiAqXG4gKiBAZXhhbXBsZVxuICogQmFzaWMgdXNhZ2U6XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBjbGllbnQgPSBuZXcgQXBpQ2xpZW50KCdodHRwczovL2FwaS5leGFtcGxlLmNvbScsIDMwMDAwKTtcbiAqIGNsaWVudC5zZXRBdXRoVG9rZW4oJ3lvdXItand0LXRva2VuJyk7XG4gKlxuICogLy8gVHlwZS1zYWZlIEdFVCByZXF1ZXN0XG4gKiBjb25zdCB7IGFwaURhdGEsIGVycm9yIH0gPSBhd2FpdCBjbGllbnQuZ2V0PFVzZXI+KCcvdXNlcnMvMTIzJyk7XG4gKiBpZiAoZXJyb3IpIHtcbiAqICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGZldGNoIHVzZXI6JywgZXJyb3IpO1xuICogfSBlbHNlIHtcbiAqICAgY29uc29sZS5sb2coJ1VzZXIgZGF0YTonLCBkYXRhKTtcbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBXaXRoIFJlYWN0IFF1ZXJ5OlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgcXVlcnlDbGllbnQgPSBuZXcgUXVlcnlDbGllbnQoKTtcbiAqIGNvbnN0IGFwaUNsaWVudCA9IG5ldyBBcGlDbGllbnQocHJvY2Vzcy5lbnYuQVBJX0JBU0VfVVJMKTtcbiAqXG4gKiAvLyBBZGQgbG9nZ2luZyBpbnRlcmNlcHRvclxuICogYXBpQ2xpZW50LmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoYXN5bmMgKHJlc3BvbnNlKSA9PiB7XG4gKiAgIGNvbnNvbGUubG9nKCdSZXNwb25zZSByZWNlaXZlZDonLCByZXNwb25zZSk7XG4gKiAgIHJldHVybiByZXNwb25zZTtcbiAqIH0pO1xuICpcbiAqIC8vIFVzZSBpbiBxdWVyaWVzXG4gKiBjb25zdCB7IGFwaURhdGEgfSA9IHVzZVF1ZXJ5KHtcbiAqICAgcXVlcnlLZXk6IFsndXNlcnMnLCB1c2VySWRdLFxuICogICBxdWVyeUZuOiAoKSA9PiBhcGlDbGllbnQuZ2V0PFVzZXI+KGAvdXNlcnMvJHt1c2VySWR9YClcbiAqIH0pO1xuICogYGBgXG4gKlxuICogQGV4YW1wbGVcbiAqIEFkdmFuY2VkIGVycm9yIGhhbmRsaW5nOlxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gT3B0aW9uIDE6IEVycm9ycyB0aHJvd24gKGRlZmF1bHQpXG4gKiB0cnkge1xuICogICBjb25zdCB7IGFwaURhdGEgfSA9IGF3YWl0IGNsaWVudC5nZXQ8VXNlcj4oJy91c2Vycy8xMjMnKTtcbiAqICAgY29uc29sZS5sb2coZGF0YSk7XG4gKiB9IGNhdGNoIChlcnJvcikge1xuICogICBpZiAoZXJyb3Iuc3RhdHVzID09PSA0MDQpIHtcbiAqICAgICBjb25zb2xlLmxvZygnVXNlciBub3QgZm91bmQnKTtcbiAqICAgfVxuICogfVxuICpcbiAqIC8vIE9wdGlvbiAyOiBFcnJvcnMgcmV0dXJuZWQgaW4gcmVzcG9uc2VcbiAqIGNvbnN0IHsgYXBpRGF0YSwgZXJyb3IgfSA9IGF3YWl0IGNsaWVudC5nZXQ8VXNlcj4oJy91c2Vycy8xMjMnLCB7XG4gKiAgIHRocm93RXJyb3JzOiBmYWxzZVxuICogfSk7XG4gKiBpZiAoZXJyb3IpIHtcbiAqICAgY29uc29sZS5lcnJvcignUmVxdWVzdCBmYWlsZWQ6JywgZXJyb3IpO1xuICogfVxuICogYGBgXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgQXBpQ2xpZW50IHtcbiAgcHJpdmF0ZSByZWFkb25seSBiYXNlVVJMOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdFRpbWVvdXQ6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBpbnRlcmNlcHRvck1hbmFnZXI6IEludGVyY2VwdG9yTWFuYWdlciA9XG4gICAgbmV3IEludGVyY2VwdG9yTWFuYWdlcigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHNpZ25hbE1hbmFnZXI6IFNpZ25hbE1hbmFnZXIgPSBuZXcgU2lnbmFsTWFuYWdlcigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGVycm9yTm9ybWFsaXplcjogRXJyb3JOb3JtYWxpemVyID0gbmV3IEVycm9yTm9ybWFsaXplcigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHJlc3BvbnNlUGFyc2VyOiBSZXNwb25zZVBhcnNlciA9IG5ldyBSZXNwb25zZVBhcnNlcigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHVybEJ1aWxkZXI6IFVybEJ1aWxkZXIgPSBuZXcgVXJsQnVpbGRlcigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHJldHJ5SGFuZGxlcjogUmV0cnlIYW5kbGVyID0gbmV3IFJldHJ5SGFuZGxlcigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHJlcXVlc3RNYW5hZ2VyOiBSZXF1ZXN0TWFuYWdlciA9IG5ldyBSZXF1ZXN0TWFuYWdlcigpO1xuICBwcml2YXRlIGF1dGhUb2tlbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgY29ycmVsYXRpb25JZFByZWZpeDogc3RyaW5nID0gJ2FwaSc7XG4gIHByaXZhdGUgaW5jbHVkZUNvcnJlbGF0aW9uSWQ6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IEFQSSBjbGllbnQgaW5zdGFuY2VcbiAgICogQHBhcmFtIGJhc2VVUkwgLSBCYXNlIFVSTCBmb3IgYWxsIEFQSSByZXF1ZXN0cyAoZGVmYXVsdDogZW1wdHkgc3RyaW5nIGZvciByZWxhdGl2ZSBVUkxzKVxuICAgKiBAcGFyYW0gZGVmYXVsdFRpbWVvdXQgLSBEZWZhdWx0IHJlcXVlc3QgdGltZW91dCBpbiBtaWxsaXNlY29uZHMgKGRlZmF1bHQ6IDMwMDAwKVxuICAgKi9cbiAgY29uc3RydWN0b3IoYmFzZVVSTDogc3RyaW5nID0gJycsIGRlZmF1bHRUaW1lb3V0OiBudW1iZXIgPSAzMDAwMCkge1xuICAgIHRoaXMuYmFzZVVSTCA9IGJhc2VVUkw7XG4gICAgdGhpcy5kZWZhdWx0VGltZW91dCA9IGRlZmF1bHRUaW1lb3V0O1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHByZWZpeCBmb3IgYXV0by1nZW5lcmF0ZWQgY29ycmVsYXRpb24gSURzXG4gICAqIEBwYXJhbSBwcmVmaXggLSBUaGUgcHJlZml4IHRvIHVzZSBmb3IgY29ycmVsYXRpb24gSURzIChlLmcuLCAnYXBpJywgJ3dlYicsICdtb2JpbGUnKVxuICAgKi9cbiAgc2V0Q29ycmVsYXRpb25JZFByZWZpeChwcmVmaXg6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuY29ycmVsYXRpb25JZFByZWZpeCA9IHByZWZpeDtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGVzIG9yIGRpc2FibGVzIGF1dG9tYXRpYyBjb3JyZWxhdGlvbiBJRCBnZW5lcmF0aW9uXG4gICAqIEBwYXJhbSBpbmNsdWRlIC0gV2hldGhlciB0byBpbmNsdWRlIGNvcnJlbGF0aW9uIElEcyBpbiByZXF1ZXN0c1xuICAgKi9cbiAgc2V0SW5jbHVkZUNvcnJlbGF0aW9uSWQoaW5jbHVkZTogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuaW5jbHVkZUNvcnJlbGF0aW9uSWQgPSBpbmNsdWRlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIHJlcXVlc3QgaW50ZXJjZXB0b3IgdG8gbW9kaWZ5IHJlcXVlc3RzIGJlZm9yZSB0aGV5J3JlIHNlbnRcbiAgICogQHBhcmFtIGludGVyY2VwdG9yIC0gRnVuY3Rpb24gdG8gaW50ZXJjZXB0IGFuZCBwb3RlbnRpYWxseSBtb2RpZnkgcmVxdWVzdCBjb25maWdcbiAgICogQHJldHVybnMgRnVuY3Rpb24gdG8gdW5yZWdpc3RlciB0aGlzIGludGVyY2VwdG9yXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgdW5yZWdpc3RlciA9IGNsaWVudC5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoYXN5bmMgKGNvbmZpZykgPT4ge1xuICAgKiAgIGNvbmZpZy5oZWFkZXJzID0gY29uZmlnLmhlYWRlcnMgfHwgbmV3IEhlYWRlcnMoKTtcbiAgICogICBjb25maWcuaGVhZGVycy5zZXQoJ1gtQ2xpZW50LVZlcnNpb24nLCAnMS4wLjAnKTtcbiAgICogICByZXR1cm4gY29uZmlnO1xuICAgKiB9KTtcbiAgICpcbiAgICogLy8gTGF0ZXIsIHRvIHJlbW92ZSB0aGUgaW50ZXJjZXB0b3I6XG4gICAqIHVucmVnaXN0ZXIoKTtcbiAgICogYGBgXG4gICAqL1xuICBhZGRSZXF1ZXN0SW50ZXJjZXB0b3IoaW50ZXJjZXB0b3I6IFJlcXVlc3RJbnRlcmNlcHRvcik6ICgpID0+IHZvaWQge1xuICAgIHJldHVybiB0aGlzLmludGVyY2VwdG9yTWFuYWdlci5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoaW50ZXJjZXB0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIHJlc3BvbnNlIGludGVyY2VwdG9yIHRvIG1vZGlmeSByZXNwb25zZXMgYmVmb3JlIHRoZXkncmUgcmV0dXJuZWRcbiAgICogQHBhcmFtIGludGVyY2VwdG9yIC0gRnVuY3Rpb24gdG8gaW50ZXJjZXB0IGFuZCBwb3RlbnRpYWxseSBtb2RpZnkgcmVzcG9uc2VzXG4gICAqIEByZXR1cm5zIEZ1bmN0aW9uIHRvIHVucmVnaXN0ZXIgdGhpcyBpbnRlcmNlcHRvclxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNsaWVudC5hZGRSZXNwb25zZUludGVyY2VwdG9yKGFzeW5jIChyZXNwb25zZSkgPT4ge1xuICAgKiAgIC8vIFRyYW5zZm9ybSBkYXRhIGZvcm1hdFxuICAgKiAgIGlmIChyZXNwb25zZS5hcGlEYXRhKSB7XG4gICAqICAgICByZXNwb25zZS5hcGlEYXRhID0gY2FtZWxDYXNlS2V5cyhyZXNwb25zZS5hcGlEYXRhKTtcbiAgICogICB9XG4gICAqICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBhZGRSZXNwb25zZUludGVyY2VwdG9yKGludGVyY2VwdG9yOiBSZXNwb25zZUludGVyY2VwdG9yKTogKCkgPT4gdm9pZCB7XG4gICAgcmV0dXJuIHRoaXMuaW50ZXJjZXB0b3JNYW5hZ2VyLmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoaW50ZXJjZXB0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhbiBlcnJvciBpbnRlcmNlcHRvciB0byBoYW5kbGUgb3IgdHJhbnNmb3JtIGVycm9yc1xuICAgKiBAcGFyYW0gaW50ZXJjZXB0b3IgLSBGdW5jdGlvbiB0byBpbnRlcmNlcHQgYW5kIHBvdGVudGlhbGx5IG1vZGlmeSBlcnJvcnNcbiAgICogQHJldHVybnMgRnVuY3Rpb24gdG8gdW5yZWdpc3RlciB0aGlzIGludGVyY2VwdG9yXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY2xpZW50LmFkZEVycm9ySW50ZXJjZXB0b3IoYXN5bmMgKGVycm9yKSA9PiB7XG4gICAqICAgLy8gTG9nIGVycm9ycyB0byBtb25pdG9yaW5nIHNlcnZpY2VcbiAgICogICBpZiAoZXJyb3Iuc3RhdHVzID49IDUwMCkge1xuICAgKiAgICAgYXdhaXQgbW9uaXRvcmluZ1NlcnZpY2UubG9nRXJyb3IoZXJyb3IpO1xuICAgKiAgIH1cbiAgICogICByZXR1cm4gZXJyb3I7IC8vIFJlLXRocm93IHRoZSBlcnJvclxuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBhZGRFcnJvckludGVyY2VwdG9yKGludGVyY2VwdG9yOiBFcnJvckludGVyY2VwdG9yKTogKCkgPT4gdm9pZCB7XG4gICAgcmV0dXJuIHRoaXMuaW50ZXJjZXB0b3JNYW5hZ2VyLmFkZEVycm9ySW50ZXJjZXB0b3IoaW50ZXJjZXB0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIGF1dGhlbnRpY2F0aW9uIHRva2VuIGZvciBzdWJzZXF1ZW50IHJlcXVlc3RzXG4gICAqIEBwYXJhbSB0b2tlbiAtIEpXVCB0b2tlbiBvciBudWxsIHRvIGNsZWFyIGF1dGhlbnRpY2F0aW9uXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogLy8gU2V0IHRva2VuIGFmdGVyIGxvZ2luXG4gICAqIGNsaWVudC5zZXRBdXRoVG9rZW4obG9naW5SZXNwb25zZS5hY2Nlc3NUb2tlbik7XG4gICAqXG4gICAqIC8vIENsZWFyIHRva2VuIG9uIGxvZ291dFxuICAgKiBjbGllbnQuc2V0QXV0aFRva2VuKG51bGwpO1xuICAgKiBgYGBcbiAgICovXG4gIHNldEF1dGhUb2tlbih0b2tlbjogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIHRoaXMuYXV0aFRva2VuID0gdG9rZW47XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBjdXJyZW50IGF1dGhlbnRpY2F0aW9uIHRva2VuXG4gICAqIEByZXR1cm5zIFRoZSBjdXJyZW50IGF1dGggdG9rZW4gb3IgbnVsbCBpZiBub3Qgc2V0XG4gICAqL1xuICBnZXRBdXRoVG9rZW4oKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuYXV0aFRva2VuO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbmNlbHMgYSBzcGVjaWZpYyByZXF1ZXN0IGJ5IGl0cyBrZXlcbiAgICogQHBhcmFtIGtleSAtIFRoZSB1bmlxdWUga2V5IGlkZW50aWZ5aW5nIHRoZSByZXF1ZXN0IHRvIGNhbmNlbFxuICAgKi9cbiAgY2FuY2VsUmVxdWVzdChrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMucmVxdWVzdE1hbmFnZXIuY2FuY2VsKGtleSk7XG4gIH1cblxuICAvKipcbiAgICogQ2FuY2VscyBhbGwgcGVuZGluZyByZXF1ZXN0c1xuICAgKiBVc2VmdWwgZm9yIGNsZWFudXAgb24gbmF2aWdhdGlvbiBvciBjb21wb25lbnQgdW5tb3VudFxuICAgKi9cbiAgY2FuY2VsQWxsUmVxdWVzdHMoKTogdm9pZCB7XG4gICAgdGhpcy5yZXF1ZXN0TWFuYWdlci5jYW5jZWxBbGwoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb3JlIHJlcXVlc3QgbWV0aG9kIHRoYXQgaGFuZGxlcyBhbGwgSFRUUCBvcGVyYXRpb25zXG4gICAqIEB0ZW1wbGF0ZSBUIC0gVGhlIGV4cGVjdGVkIHJlc3BvbnNlIGRhdGEgdHlwZVxuICAgKiBAcGFyYW0gZW5kcG9pbnQgLSBBUEkgZW5kcG9pbnQgcmVsYXRpdmUgdG8gYmFzZVVSTFxuICAgKiBAcGFyYW0gY29uZmlnIC0gUmVxdWVzdCBjb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gQXBpUmVzcG9uc2Ugd2l0aCBkYXRhIG9yIGVycm9yXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQucmVxdWVzdDxVc2VyPignL3VzZXJzLzEyMycsIHtcbiAgICogICBtZXRob2Q6ICdHRVQnLFxuICAgKiAgIHRpbWVvdXQ6IDUwMDAsXG4gICAqICAgdGhyb3dFcnJvcnM6IGZhbHNlXG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIHJlcXVlc3Q8VCA9IFJlc3BvbnNlRGF0YT4oXG4gICAgZW5kcG9pbnQ6IHN0cmluZyxcbiAgICBjb25maWc6IFJlcXVlc3RDb25maWcgPSB7fVxuICApOiBQcm9taXNlPEFwaVJlc3BvbnNlPFQsIEFwaUVycm9yPj4ge1xuICAgIC8vIEdlbmVyYXRlIGNvcnJlbGF0aW9uIElEXG4gICAgY29uc3QgY29ycmVsYXRpb25JZCA9XG4gICAgICBjb25maWcuY29ycmVsYXRpb25JZCB8fFxuICAgICAgKCFjb25maWcuc2tpcENvcnJlbGF0aW9uSWQgJiYgdGhpcy5pbmNsdWRlQ29ycmVsYXRpb25JZFxuICAgICAgICA/IGdlbmVyYXRlQ29ycmVsYXRpb25JZCh0aGlzLmNvcnJlbGF0aW9uSWRQcmVmaXgpXG4gICAgICAgIDogdW5kZWZpbmVkKTtcbiAgICAvLyBHZW5lcmF0ZSByZXF1ZXN0IGtleSBmb3IgdHJhY2tpbmdcbiAgICBjb25zdCByZXF1ZXN0S2V5ID0gYCR7Y29uZmlnLm1ldGhvZCB8fCAnR0VUJ31fJHtlbmRwb2ludH1fJHtEYXRlLm5vdygpfWA7XG5cbiAgICAvLyBDcmVhdGUgbWFzdGVyIGNvbnRyb2xsZXIgZm9yIHRoaXMgcmVxdWVzdFxuICAgIGNvbnN0IG1hc3RlckNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgICB0cnkge1xuICAgICAgLy8gQ29tYmluZSBhbGwgYWJvcnQgc2lnbmFsc1xuICAgICAgY29uc3Qgc2lnbmFsczogQXJyYXk8QWJvcnRTaWduYWwgfCB1bmRlZmluZWQ+ID0gW1xuICAgICAgICBjb25maWcuc2lnbmFsLFxuICAgICAgICBjb25maWcuY2FuY2VsVG9rZW4/LnNpZ25hbCxcbiAgICAgICAgbWFzdGVyQ29udHJvbGxlci5zaWduYWwsXG4gICAgICBdO1xuXG4gICAgICAvLyBBZGQgdGltZW91dCBzaWduYWwgaWYgY29uZmlndXJlZFxuICAgICAgY29uc3QgdGltZW91dCA9IGNvbmZpZy50aW1lb3V0IHx8IHRoaXMuZGVmYXVsdFRpbWVvdXQ7XG4gICAgICBjb25zdCB0aW1lb3V0Q29udHJvbGxlciA9IHRoaXMuc2lnbmFsTWFuYWdlci5jcmVhdGVUaW1lb3V0U2lnbmFsKHRpbWVvdXQpO1xuXG4gICAgICBzaWduYWxzLnB1c2godGltZW91dENvbnRyb2xsZXIuc2lnbmFsKTtcblxuICAgICAgLy8gQ3JlYXRlIGNvbWJpbmVkIHNpZ25hbFxuICAgICAgY29uc3QgY29tYmluZWRDb250cm9sbGVyID1cbiAgICAgICAgdGhpcy5zaWduYWxNYW5hZ2VyLmNyZWF0ZUNvbWJpbmVkU2lnbmFsKHNpZ25hbHMpO1xuXG4gICAgICAvLyBUcmFjayB0aGlzIHJlcXVlc3RcbiAgICAgIGlmIChjb3JyZWxhdGlvbklkKSB7XG4gICAgICAgIHRoaXMucmVxdWVzdE1hbmFnZXIuYWRkKHJlcXVlc3RLZXksIG1hc3RlckNvbnRyb2xsZXIsIGNvcnJlbGF0aW9uSWQpO1xuICAgICAgfVxuXG4gICAgICAvLyBBcHBseSByZXF1ZXN0IGludGVyY2VwdG9yc1xuICAgICAgY29uc3QgZmluYWxDb25maWcgPVxuICAgICAgICBhd2FpdCB0aGlzLmludGVyY2VwdG9yTWFuYWdlci5hcHBseVJlcXVlc3RJbnRlcmNlcHRvcnMoe1xuICAgICAgICAgIC4uLmNvbmZpZyxcbiAgICAgICAgICBzaWduYWw6IGNvbWJpbmVkQ29udHJvbGxlci5zaWduYWwsXG4gICAgICAgICAgY29ycmVsYXRpb25JZCxcbiAgICAgICAgfSk7XG5cbiAgICAgIC8vIEJ1aWxkIGZ1bGwgVVJMXG4gICAgICBjb25zdCB1cmwgPSB0aGlzLnVybEJ1aWxkZXIuYnVpbGRVUkwoXG4gICAgICAgIHRoaXMuYmFzZVVSTCxcbiAgICAgICAgZW5kcG9pbnQsXG4gICAgICAgIGZpbmFsQ29uZmlnLnBhcmFtcyBhcyBRdWVyeVBhcmFtc1xuICAgICAgKTtcblxuICAgICAgLy8gQWRkIGRlZmF1bHQgaGVhZGVyc1xuICAgICAgY29uc3QgaGVhZGVycyA9IG5ldyBIZWFkZXJzKGZpbmFsQ29uZmlnLmhlYWRlcnMpO1xuXG4gICAgICAvLyBBZGQgY29ycmVsYXRpb24gSUQgaGVhZGVyXG4gICAgICBpZiAoY29ycmVsYXRpb25JZCkge1xuICAgICAgICBoZWFkZXJzLnNldCgnWC1Db3JyZWxhdGlvbi1JZCcsIGNvcnJlbGF0aW9uSWQpO1xuICAgICAgICBoZWFkZXJzLnNldCgnWC1SZXF1ZXN0LUlkJywgY29ycmVsYXRpb25JZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEFkZCBhdXRoIGhlYWRlciBpZiB0b2tlbiBleGlzdHNcbiAgICAgIGlmICh0aGlzLmF1dGhUb2tlbiAmJiAhZmluYWxDb25maWcuc2tpcEF1dGhSZWZyZXNoKSB7XG4gICAgICAgIGhlYWRlcnMuc2V0KCdBdXRob3JpemF0aW9uJywgYEJlYXJlciAke3RoaXMuYXV0aFRva2VufWApO1xuICAgICAgfVxuXG4gICAgICAvLyBTZXQgY29udGVudC10eXBlIGZvciBKU09OIHBheWxvYWRzXG5cbiAgICAgIGxldCBmZXRjaEJvZHk6IEJvZHlJbml0IHwgbnVsbCB8IHVuZGVmaW5lZCA9IGZpbmFsQ29uZmlnLmJvZHkgYXNcbiAgICAgICAgfCBCb2R5SW5pdFxuICAgICAgICB8IG51bGxcbiAgICAgICAgfCB1bmRlZmluZWQ7XG5cbiAgICAgIGlmIChcbiAgICAgICAgZmluYWxDb25maWcuYm9keSAmJlxuICAgICAgICB0eXBlb2YgZmluYWxDb25maWcuYm9keSA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgIShmaW5hbENvbmZpZy5ib2R5IGluc3RhbmNlb2YgRm9ybURhdGEpICYmXG4gICAgICAgICEoZmluYWxDb25maWcuYm9keSBpbnN0YW5jZW9mIEJsb2IpICYmXG4gICAgICAgICEoZmluYWxDb25maWcuYm9keSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSAmJlxuICAgICAgICAhKGZpbmFsQ29uZmlnLmJvZHkgaW5zdGFuY2VvZiBVUkxTZWFyY2hQYXJhbXMpICYmXG4gICAgICAgICEoZmluYWxDb25maWcuYm9keSBpbnN0YW5jZW9mIFJlYWRhYmxlU3RyZWFtKVxuICAgICAgKSB7XG4gICAgICAgIGhlYWRlcnMuc2V0KCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vanNvbicpO1xuICAgICAgICBmZXRjaEJvZHkgPSBKU09OLnN0cmluZ2lmeShmaW5hbENvbmZpZy5ib2R5KTtcbiAgICAgIH1cblxuICAgICAgZmluYWxDb25maWcuaGVhZGVycyA9IGhlYWRlcnM7XG5cbiAgICAgIC8vIENyZWF0ZSBmZXRjaCBwcm9taXNlXG4gICAgICBjb25zdCBmZXRjaFByb21pc2UgPSBhc3luYyAoKTogUHJvbWlzZTxBcGlSZXNwb25zZTxULCBBcGlFcnJvcj4+ID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHVybCwge1xuICAgICAgICAgICAgLi4uZmluYWxDb25maWcsXG4gICAgICAgICAgICBib2R5OiBmZXRjaEJvZHksXG4gICAgICAgICAgICBzaWduYWw6IGNvbWJpbmVkQ29udHJvbGxlci5zaWduYWwsXG4gICAgICAgICAgfSBhcyBSZXF1ZXN0SW5pdCk7XG5cbiAgICAgICAgICAvLyBQYXJzZSByZXNwb25zZSBkYXRhXG4gICAgICAgICAgY29uc3QgcmVzcG9uc2VEYXRhID1cbiAgICAgICAgICAgIGF3YWl0IHRoaXMucmVzcG9uc2VQYXJzZXIucGFyc2VSZXNwb25zZShyZXNwb25zZSk7XG5cbiAgICAgICAgICAvLyBIYW5kbGUgZXJyb3IgcmVzcG9uc2VzXG4gICAgICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgLy8gQ2FzdCB0byBFcnJvclJlc3BvbnNlRGF0YSBmb3Igc3RydWN0dXJlZCBlcnJvciByZXNwb25zZXMgZnJvbSBiYWNrZW5kXG4gICAgICAgICAgICBjb25zdCBlcnJvckRhdGEgPSByZXNwb25zZURhdGEgYXMgRXJyb3JSZXNwb25zZURhdGE7XG5cbiAgICAgICAgICAgIGNvbnN0IGVycm9yOiBBcGlFcnJvciA9IE9iamVjdC5hc3NpZ24oXG4gICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICBlcnJvckRhdGEudGl0bGUgfHxcbiAgICAgICAgICAgICAgICAgIGBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfTogJHtyZXNwb25zZS5zdGF0dXNUZXh0fWBcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR5cGU6XG4gICAgICAgICAgICAgICAgICBlcnJvckRhdGEudHlwZSB8fFxuICAgICAgICAgICAgICAgICAgdGhpcy5lcnJvck5vcm1hbGl6ZXIuZ2V0RXJyb3JUeXBlKHJlc3BvbnNlLnN0YXR1cyksXG4gICAgICAgICAgICAgICAgdGl0bGU6XG4gICAgICAgICAgICAgICAgICBlcnJvckRhdGEudGl0bGUgfHxcbiAgICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JOb3JtYWxpemVyLmdldEVycm9yVGl0bGUocmVzcG9uc2Uuc3RhdHVzKSxcbiAgICAgICAgICAgICAgICBzdGF0dXM6IHJlc3BvbnNlLnN0YXR1cyxcbiAgICAgICAgICAgICAgICB0cmFjZUlkOiBlcnJvckRhdGEudHJhY2VJZCB8fCBjb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIGVycm9yczogZXJyb3JEYXRhLmVycm9ycyxcbiAgICAgICAgICAgICAgICBpc0Fib3J0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGNvbmZpZzogZmluYWxDb25maWcsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHdlIHNob3VsZCB0aHJvdyBvciByZXR1cm4gZXJyb3IgaW4gcmVzcG9uc2VcbiAgICAgICAgICAgIGlmIChmaW5hbENvbmZpZy50aHJvd0Vycm9ycyAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyBSZXR1cm4gZXJyb3IgaW4gQXBpUmVzcG9uc2UuZXJyb3IgZmllbGRcbiAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuaW50ZXJjZXB0b3JNYW5hZ2VyLmFwcGx5UmVzcG9uc2VJbnRlcmNlcHRvcnMoe1xuICAgICAgICAgICAgICAgIGVycm9yLFxuICAgICAgICAgICAgICB9IGFzIEFwaVJlc3BvbnNlPFQsIEFwaUVycm9yPik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gRm9ybWF0IHN1Y2Nlc3NmdWwgcmVzcG9uc2VcbiAgICAgICAgICBjb25zdCBhcGlSZXNwb25zZTogQXBpUmVzcG9uc2U8VD4gPSB7XG4gICAgICAgICAgICBkYXRhOiByZXNwb25zZURhdGEgYXMgVCxcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgLy8gQXBwbHkgcmVzcG9uc2UgaW50ZXJjZXB0b3JzXG4gICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuaW50ZXJjZXB0b3JNYW5hZ2VyLmFwcGx5UmVzcG9uc2VJbnRlcmNlcHRvcnMoXG4gICAgICAgICAgICBhcGlSZXNwb25zZVxuICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgICAgLy8gSGFuZGxlIGFib3J0IGVycm9yc1xuICAgICAgICAgIGlmICgoZXJyb3IgYXMgRXJyb3IpLm5hbWUgPT09ICdBYm9ydEVycm9yJykge1xuICAgICAgICAgICAgY29uc3QgYWJvcnRFcnJvciA9IE9iamVjdC5hc3NpZ24oXG4gICAgICAgICAgICAgIG5ldyBFcnJvcigoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2UgfHwgJ1JlcXVlc3QgYWJvcnRlZCcpLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ3JlcXVlc3RfY2FuY2VsbGVkJyxcbiAgICAgICAgICAgICAgICB0aXRsZTogJ1JlcXVlc3Qgd2FzIGNhbmNlbGxlZCcsXG4gICAgICAgICAgICAgICAgc3RhdHVzOiAwLFxuICAgICAgICAgICAgICAgIHRyYWNlSWQ6IGNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgaXNBYm9ydGVkOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNvbmZpZzogZmluYWxDb25maWcsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHdlIHNob3VsZCB0aHJvdyBvciByZXR1cm4gZXJyb3IgaW4gcmVzcG9uc2VcbiAgICAgICAgICAgIGlmIChmaW5hbENvbmZpZy50aHJvd0Vycm9ycyAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgdGhyb3cgYWJvcnRFcnJvcjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIC8vIFJldHVybiBlcnJvciBpbiBBcGlSZXNwb25zZS5lcnJvciBmaWVsZFxuICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5pbnRlcmNlcHRvck1hbmFnZXIuYXBwbHlSZXNwb25zZUludGVyY2VwdG9ycyh7XG4gICAgICAgICAgICAgICAgZXJyb3I6IGFib3J0RXJyb3IsXG4gICAgICAgICAgICAgIH0gYXMgQXBpUmVzcG9uc2U8VCwgQXBpRXJyb3I+KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgLy8gSGFuZGxlIHJldHJpZXMgaWYgY29uZmlndXJlZFxuICAgICAgaWYgKGZpbmFsQ29uZmlnLnJldHJpZXMgJiYgZmluYWxDb25maWcucmV0cmllcyA+IDApIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMucmV0cnlIYW5kbGVyLnJldHJ5UmVxdWVzdChcbiAgICAgICAgICBmZXRjaFByb21pc2UsXG4gICAgICAgICAgZmluYWxDb25maWcucmV0cmllcyxcbiAgICAgICAgICBmaW5hbENvbmZpZy5yZXRyeURlbGF5IHx8IDEwMDAsXG4gICAgICAgICAgY29tYmluZWRDb250cm9sbGVyLnNpZ25hbFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gYXdhaXQgZmV0Y2hQcm9taXNlKCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIEhhbmRsZSBlcnJvcnNcbiAgICAgIGNvbnN0IGFwaUVycm9yOiBBcGlFcnJvciA9IHRoaXMuZXJyb3JOb3JtYWxpemVyLm5vcm1hbGl6ZUVycm9yKFxuICAgICAgICBlcnJvcixcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBjb3JyZWxhdGlvbklkXG4gICAgICApO1xuXG4gICAgICAvLyBDaGVjayBpZiB3ZSBzaG91bGQgdGhyb3cgb3IgcmV0dXJuIGVycm9yIGluIHJlc3BvbnNlXG4gICAgICBpZiAoY29uZmlnLnRocm93RXJyb3JzICE9PSBmYWxzZSkge1xuICAgICAgICBhd2FpdCB0aGlzLmludGVyY2VwdG9yTWFuYWdlci5hcHBseUVycm9ySW50ZXJjZXB0b3JzKGFwaUVycm9yKTtcbiAgICAgICAgLy8gVGhpcyBsaW5lIHdpbGwgbmV2ZXIgYmUgcmVhY2hlZCBhcyBhcHBseUVycm9ySW50ZXJjZXB0b3JzIGFsd2F5cyB0aHJvd3MsXG4gICAgICAgIC8vIGJ1dCBUeXBlU2NyaXB0IHJlcXVpcmVzIGEgcmV0dXJuIHN0YXRlbWVudFxuICAgICAgICB0aHJvdyBhcGlFcnJvcjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFJldHVybiBlcnJvciBpbiBBcGlSZXNwb25zZS5lcnJvciBmaWVsZFxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGVycm9yOiBhcGlFcnJvcixcbiAgICAgICAgfSBhcyBBcGlSZXNwb25zZTxULCBBcGlFcnJvcj47XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIC8vIENsZWFuIHVwIHJlcXVlc3QgdHJhY2tpbmdcbiAgICAgIHRoaXMucmVxdWVzdE1hbmFnZXIucmVtb3ZlKHJlcXVlc3RLZXkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyBhIEdFVCByZXF1ZXN0XG4gICAqIEB0ZW1wbGF0ZSBUIC0gVGhlIGV4cGVjdGVkIHJlc3BvbnNlIGRhdGEgdHlwZVxuICAgKiBAcGFyYW0gZW5kcG9pbnQgLSBBUEkgZW5kcG9pbnRcbiAgICogQHBhcmFtIGNvbmZpZyAtIE9wdGlvbmFsIHJlcXVlc3QgY29uZmlndXJhdGlvblxuICAgKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byBBcGlSZXNwb25zZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHsgYXBpRGF0YSwgZXJyb3IgfSA9IGF3YWl0IGNsaWVudC5nZXQ8VXNlcltdPignL3VzZXJzJywge1xuICAgKiAgIHBhcmFtczogeyBhY3RpdmU6IHRydWUgfSxcbiAgICogICB0aW1lb3V0OiA1MDAwXG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGdldDxUID0gUmVzcG9uc2VEYXRhPihcbiAgICBlbmRwb2ludDogc3RyaW5nLFxuICAgIGNvbmZpZz86IFJlcXVlc3RDb25maWdcbiAgKTogUHJvbWlzZTxBcGlSZXNwb25zZTxULCBBcGlFcnJvcj4+IHtcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0PFQ+KGVuZHBvaW50LCB7IC4uLmNvbmZpZywgbWV0aG9kOiAnR0VUJyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyBhIFBPU1QgcmVxdWVzdFxuICAgKiBAdGVtcGxhdGUgVCAtIFRoZSBleHBlY3RlZCByZXNwb25zZSBkYXRhIHR5cGVcbiAgICogQHRlbXBsYXRlIFREYXRhIC0gVGhlIHJlcXVlc3QgYm9keSBkYXRhIHR5cGVcbiAgICogQHBhcmFtIGVuZHBvaW50IC0gQVBJIGVuZHBvaW50XG4gICAqIEBwYXJhbSBkYXRhIC0gUmVxdWVzdCBib2R5IGRhdGFcbiAgICogQHBhcmFtIGNvbmZpZyAtIE9wdGlvbmFsIHJlcXVlc3QgY29uZmlndXJhdGlvblxuICAgKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byBBcGlSZXNwb25zZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHsgYXBpRGF0YSwgZXJyb3IgfSA9IGF3YWl0IGNsaWVudC5wb3N0PFVzZXIsIENyZWF0ZVVzZXJEdG8+KCcvdXNlcnMnLCB7XG4gICAqICAgbmFtZTogJ0pvaG4gRG9lJyxcbiAgICogICBlbWFpbDogJ2pvaG5AZXhhbXBsZS5jb20nXG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIHBvc3Q8XG4gICAgVCA9IFJlc3BvbnNlRGF0YSxcbiAgICBURGF0YSBleHRlbmRzIEJvZHlJbml0IHwgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCBudWxsID0gUmVjb3JkPFxuICAgICAgc3RyaW5nLFxuICAgICAgdW5rbm93blxuICAgID4sXG4gID4oXG4gICAgZW5kcG9pbnQ6IHN0cmluZyxcbiAgICBkYXRhPzogVERhdGEsXG4gICAgY29uZmlnPzogUmVxdWVzdENvbmZpZ1xuICApOiBQcm9taXNlPEFwaVJlc3BvbnNlPFQsIEFwaUVycm9yPj4ge1xuICAgIHJldHVybiB0aGlzLnJlcXVlc3Q8VD4oZW5kcG9pbnQsIHsgLi4uY29uZmlnLCBtZXRob2Q6ICdQT1NUJywgYm9keTogZGF0YSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyBhIFBVVCByZXF1ZXN0XG4gICAqIEB0ZW1wbGF0ZSBUIC0gVGhlIGV4cGVjdGVkIHJlc3BvbnNlIGRhdGEgdHlwZVxuICAgKiBAdGVtcGxhdGUgVERhdGEgLSBUaGUgcmVxdWVzdCBib2R5IGRhdGEgdHlwZVxuICAgKiBAcGFyYW0gZW5kcG9pbnQgLSBBUEkgZW5kcG9pbnRcbiAgICogQHBhcmFtIGRhdGEgLSBSZXF1ZXN0IGJvZHkgZGF0YVxuICAgKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgcmVxdWVzdCBjb25maWd1cmF0aW9uXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIEFwaVJlc3BvbnNlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgeyBhcGlEYXRhLCBlcnJvciB9ID0gYXdhaXQgY2xpZW50LnB1dDxVc2VyLCBVcGRhdGVVc2VyRHRvPihcbiAgICogICAnL3VzZXJzLzEyMycsXG4gICAqICAgeyBuYW1lOiAnSmFuZSBEb2UnIH1cbiAgICogKTtcbiAgICogYGBgXG4gICAqL1xuICBwdXQ8XG4gICAgVCA9IFJlc3BvbnNlRGF0YSxcbiAgICBURGF0YSBleHRlbmRzIEJvZHlJbml0IHwgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCBudWxsID0gUmVjb3JkPFxuICAgICAgc3RyaW5nLFxuICAgICAgdW5rbm93blxuICAgID4sXG4gID4oXG4gICAgZW5kcG9pbnQ6IHN0cmluZyxcbiAgICBkYXRhPzogVERhdGEsXG4gICAgY29uZmlnPzogUmVxdWVzdENvbmZpZ1xuICApOiBQcm9taXNlPEFwaVJlc3BvbnNlPFQsIEFwaUVycm9yPj4ge1xuICAgIHJldHVybiB0aGlzLnJlcXVlc3Q8VD4oZW5kcG9pbnQsIHsgLi4uY29uZmlnLCBtZXRob2Q6ICdQVVQnLCBib2R5OiBkYXRhIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIGEgUEFUQ0ggcmVxdWVzdFxuICAgKiBAdGVtcGxhdGUgVCAtIFRoZSBleHBlY3RlZCByZXNwb25zZSBkYXRhIHR5cGVcbiAgICogQHRlbXBsYXRlIFREYXRhIC0gVGhlIHJlcXVlc3QgYm9keSBkYXRhIHR5cGVcbiAgICogQHBhcmFtIGVuZHBvaW50IC0gQVBJIGVuZHBvaW50XG4gICAqIEBwYXJhbSBkYXRhIC0gUmVxdWVzdCBib2R5IGRhdGFcbiAgICogQHBhcmFtIGNvbmZpZyAtIE9wdGlvbmFsIHJlcXVlc3QgY29uZmlndXJhdGlvblxuICAgKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byBBcGlSZXNwb25zZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHsgYXBpRGF0YSwgZXJyb3IgfSA9IGF3YWl0IGNsaWVudC5wYXRjaDxVc2VyPihcbiAgICogICAnL3VzZXJzLzEyMycsXG4gICAqICAgeyBzdGF0dXM6ICdhY3RpdmUnIH1cbiAgICogKTtcbiAgICogYGBgXG4gICAqL1xuICBwYXRjaDxcbiAgICBUID0gUmVzcG9uc2VEYXRhLFxuICAgIFREYXRhIGV4dGVuZHMgQm9keUluaXQgfCBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IG51bGwgPSBSZWNvcmQ8XG4gICAgICBzdHJpbmcsXG4gICAgICB1bmtub3duXG4gICAgPixcbiAgPihcbiAgICBlbmRwb2ludDogc3RyaW5nLFxuICAgIGRhdGE/OiBURGF0YSxcbiAgICBjb25maWc/OiBSZXF1ZXN0Q29uZmlnXG4gICk6IFByb21pc2U8QXBpUmVzcG9uc2U8VCwgQXBpRXJyb3I+PiB7XG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdDxUPihlbmRwb2ludCwge1xuICAgICAgLi4uY29uZmlnLFxuICAgICAgbWV0aG9kOiAnUEFUQ0gnLFxuICAgICAgYm9keTogZGF0YSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyBhIERFTEVURSByZXF1ZXN0XG4gICAqIEB0ZW1wbGF0ZSBUIC0gVGhlIGV4cGVjdGVkIHJlc3BvbnNlIGRhdGEgdHlwZVxuICAgKiBAcGFyYW0gZW5kcG9pbnQgLSBBUEkgZW5kcG9pbnRcbiAgICogQHBhcmFtIGNvbmZpZyAtIE9wdGlvbmFsIHJlcXVlc3QgY29uZmlndXJhdGlvblxuICAgKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byBBcGlSZXNwb25zZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHsgZXJyb3IgfSA9IGF3YWl0IGNsaWVudC5kZWxldGUoJy91c2Vycy8xMjMnKTtcbiAgICogaWYgKCFlcnJvcikge1xuICAgKiAgIGNvbnNvbGUubG9nKCdVc2VyIGRlbGV0ZWQgc3VjY2Vzc2Z1bGx5Jyk7XG4gICAqIH1cbiAgICogYGBgXG4gICAqL1xuICBkZWxldGU8VCA9IFJlc3BvbnNlRGF0YT4oXG4gICAgZW5kcG9pbnQ6IHN0cmluZyxcbiAgICBjb25maWc/OiBSZXF1ZXN0Q29uZmlnXG4gICk6IFByb21pc2U8QXBpUmVzcG9uc2U8VCwgQXBpRXJyb3I+PiB7XG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdDxUPihlbmRwb2ludCwgeyAuLi5jb25maWcsIG1ldGhvZDogJ0RFTEVURScgfSk7XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybXMgYSBmaWx0ZXJlZCBsaXN0IHJlcXVlc3Qgd2l0aCBwYWdpbmF0aW9uIGFuZCBzb3J0aW5nXG4gICAqIEB0ZW1wbGF0ZSBUTGlzdE1vZGVsIC0gVGhlIHR5cGUgb2YgaW5kaXZpZHVhbCBsaXN0IGl0ZW1zXG4gICAqIEB0ZW1wbGF0ZSBURmlsdGVyIC0gVGhlIGZpbHRlciBjcml0ZXJpYSB0eXBlXG4gICAqIEBwYXJhbSB1cmwgLSBBUEkgZW5kcG9pbnRcbiAgICogQHBhcmFtIGRhdGEgLSBQYWdpbmF0aW9uIGFuZCBmaWx0ZXIgZGF0YVxuICAgKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgcmVxdWVzdCBjb25maWd1cmF0aW9uXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIHBhZ2luYXRlZCBsaXN0IHJlc3BvbnNlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgeyBhcGlEYXRhLCBlcnJvciB9ID0gYXdhaXQgY2xpZW50LmZpbHRlcjxVc2VyLCBVc2VyRmlsdGVyPihcbiAgICogICAnL3VzZXJzL2ZpbHRlcicsXG4gICAqICAge1xuICAgKiAgICAgcGFnZU9mZnNldDogMCxcbiAgICogICAgIHBhZ2VTaXplOiAyMCxcbiAgICogICAgIHNvcnRGaWVsZDogJ2NyZWF0ZWRBdCcsXG4gICAqICAgICBzb3J0T3JkZXI6ICdkZXNjJyxcbiAgICogICAgIGZpbHRlck1vZGVsOiB7IHN0YXR1czogJ2FjdGl2ZScgfVxuICAgKiAgIH1cbiAgICogKTtcbiAgICpcbiAgICogaWYgKGFwaURhdGEpIHtcbiAgICogICBjb25zb2xlLmxvZyhgRm91bmQgJHthcGlEYXRhLlRvdGFsfSB1c2Vyc2ApO1xuICAgKiAgIGNvbnNvbGUubG9nKCdVc2VyczonLCBhcGlEYXRhLkRhdGEpO1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgZmlsdGVyPFRMaXN0TW9kZWwsIFRGaWx0ZXIgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgZGF0YTogUG9zdE1vZGVsPFRGaWx0ZXI+LFxuICAgIGNvbmZpZz86IFJlcXVlc3RDb25maWdcbiAgKTogUHJvbWlzZTxBcGlSZXNwb25zZTxMaXN0UmVzcG9uc2U8VExpc3RNb2RlbD4sIEFwaUVycm9yPj4ge1xuICAgIC8vIE1lcmdlIGJvZHk6IHsgLi4ucG9zdE1vZGVsLCAuLi5wb3N0TW9kZWwuZmlsdGVyTW9kZWwgfVxuICAgIGNvbnN0IG1lcmdlZERhdGEgPSB7IC4uLmRhdGEsIC4uLmRhdGEuZmlsdGVyTW9kZWwgfTtcblxuICAgIHJldHVybiB0aGlzLnJlcXVlc3Q8TGlzdFJlc3BvbnNlPFRMaXN0TW9kZWw+Pih1cmwsIHtcbiAgICAgIC4uLmNvbmZpZyxcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgYm9keTogbWVyZ2VkRGF0YSxcbiAgICB9KTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGZpbGVvdmVydmlldyBGYWN0b3J5IGZ1bmN0aW9ucyBmb3IgY3JlYXRpbmcgYW5kIG1hbmFnaW5nIEFwaUNsaWVudCBpbnN0YW5jZXMuXG4gKlxuICogUHJvdmlkZXMgY29udmVuaWVudCBmYWN0b3J5IG1ldGhvZHMgZm9yIGNyZWF0aW5nIHByZS1jb25maWd1cmVkIEFwaUNsaWVudCBpbnN0YW5jZXNcbiAqIHdpdGggc2Vuc2libGUgZGVmYXVsdHMgYW5kIGF1dG9tYXRpYyB0b2tlbiBtYW5hZ2VtZW50IGZyb20gbG9jYWxTdG9yYWdlLlxuICpcbiAqIEBtb2R1bGUgY3JlYXRlQXBpQ2xpZW50XG4gKi9cblxuaW1wb3J0IHsgQXBpQ2xpZW50IH0gZnJvbSAnLi9BcGlDbGllbnQnO1xuaW1wb3J0IHR5cGUgeyBFcnJvckludGVyY2VwdG9yIH0gZnJvbSAnLi90eXBlcy9FcnJvckludGVyY2VwdG9yJztcbmltcG9ydCB0eXBlIHsgUmVxdWVzdEludGVyY2VwdG9yIH0gZnJvbSAnLi90eXBlcy9SZXF1ZXN0SW50ZXJjZXB0b3InO1xuaW1wb3J0IHR5cGUgeyBSZXNwb25zZUludGVyY2VwdG9yIH0gZnJvbSAnLi90eXBlcy9SZXNwb25zZUludGVyY2VwdG9yJztcblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIGNyZWF0aW5nIGFuIEFwaUNsaWVudCBpbnN0YW5jZS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXBpQ2xpZW50Q29uZmlnIHtcbiAgLyoqXG4gICAqIEJhc2UgVVJMIGZvciBhbGwgQVBJIHJlcXVlc3RzLlxuICAgKiBAZXhhbXBsZSAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nXG4gICAqL1xuICBiYXNlVVJMPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEZWZhdWx0IHRpbWVvdXQgZm9yIHJlcXVlc3RzIGluIG1pbGxpc2Vjb25kcy5cbiAgICogQGRlZmF1bHQgMzAwMDBcbiAgICovXG4gIHRpbWVvdXQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFByZWZpeCBmb3IgYXV0by1nZW5lcmF0ZWQgY29ycmVsYXRpb24gSURzIChlLmcuLCAnYXBpJywgJ3dlYicsICdtb2JpbGUnKS5cbiAgICogQGRlZmF1bHQgJ2FwaSdcbiAgICovXG4gIGNvcnJlbGF0aW9uSWRQcmVmaXg/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gYXV0b21hdGljYWxseSBnZW5lcmF0ZSBhbmQgaW5jbHVkZSBjb3JyZWxhdGlvbiBJRHMgaW4gcmVxdWVzdHMuXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIGluY2x1ZGVDb3JyZWxhdGlvbklkPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogSW5pdGlhbCBhdXRoZW50aWNhdGlvbiB0b2tlbiB0byBzZXQgb24gdGhlIGNsaWVudC5cbiAgICogQGRlZmF1bHQgdW5kZWZpbmVkXG4gICAqL1xuICBhdXRoVG9rZW4/OiBzdHJpbmcgfCBudWxsO1xuXG4gIC8qKlxuICAgKiBBcnJheSBvZiByZXF1ZXN0IGludGVyY2VwdG9ycyB0byByZWdpc3RlciBkdXJpbmcgY2xpZW50IGNyZWF0aW9uLlxuICAgKiBAZGVmYXVsdCBbXVxuICAgKi9cbiAgcmVxdWVzdEludGVyY2VwdG9ycz86IFJlcXVlc3RJbnRlcmNlcHRvcltdO1xuXG4gIC8qKlxuICAgKiBBcnJheSBvZiByZXNwb25zZSBpbnRlcmNlcHRvcnMgdG8gcmVnaXN0ZXIgZHVyaW5nIGNsaWVudCBjcmVhdGlvbi5cbiAgICogQGRlZmF1bHQgW11cbiAgICovXG4gIHJlc3BvbnNlSW50ZXJjZXB0b3JzPzogUmVzcG9uc2VJbnRlcmNlcHRvcltdO1xuXG4gIC8qKlxuICAgKiBBcnJheSBvZiBlcnJvciBpbnRlcmNlcHRvcnMgdG8gcmVnaXN0ZXIgZHVyaW5nIGNsaWVudCBjcmVhdGlvbi5cbiAgICogQGRlZmF1bHQgW11cbiAgICovXG4gIGVycm9ySW50ZXJjZXB0b3JzPzogRXJyb3JJbnRlcmNlcHRvcltdO1xufVxuXG4vKipcbiAqIEdsb2JhbCBzaW5nbGV0b24gQXBpQ2xpZW50IGluc3RhbmNlLlxuICogQGludGVybmFsXG4gKi9cbmxldCBnbG9iYWxBcGlDbGllbnQ6IEFwaUNsaWVudCB8IG51bGwgPSBudWxsO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgQXBpQ2xpZW50IGluc3RhbmNlIHdpdGggc2Vuc2libGUgZGVmYXVsdHMgYW5kIGF1dG9tYXRpYyB0b2tlbiBtYW5hZ2VtZW50LlxuICpcbiAqIFRoaXMgZmFjdG9yeSBmdW5jdGlvbjpcbiAqIC0gQ29uZmlndXJlcyB0aGUgYmFzZSBVUkwgZnJvbSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgb3IgY29uZmlnXG4gKiAtIFNldHMgdXAgYXV0b21hdGljIGF1dGhlbnRpY2F0aW9uIHRva2VuIGluamVjdGlvbiBmcm9tIGxvY2FsU3RvcmFnZSAoJ3NlcnZpY2VUb2tlbicga2V5KVxuICogLSBDb25maWd1cmVzIGNvcnJlbGF0aW9uIElEIGdlbmVyYXRpb25cbiAqIC0gUmVnaXN0ZXJzIHByb3ZpZGVkIGludGVyY2VwdG9yc1xuICpcbiAqICoqTm90ZToqKiBFYWNoIGNhbGwgY3JlYXRlcyBhIE5FVyBpbnN0YW5jZS4gVXNlIHtAbGluayBnZXRHbG9iYWxBcGlDbGllbnR9IGZvciBzaW5nbGV0b24gYmVoYXZpb3IuXG4gKlxuICogQHBhcmFtIGNvbmZpZyAtIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgdGhlIEFQSSBjbGllbnRcbiAqIEByZXR1cm5zIEEgZnVsbHkgY29uZmlndXJlZCBBcGlDbGllbnQgaW5zdGFuY2VcbiAqIEBwdWJsaWNcbiAqXG4gKiBAZXhhbXBsZVxuICogQmFzaWMgdXNhZ2Ugd2l0aCBkZWZhdWx0czpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGNsaWVudCA9IGNyZWF0ZUFwaUNsaWVudCgpO1xuICogLy8gVXNlcyBWSVRFX0FQSV9VUkwsIDMwcyB0aW1lb3V0LCBhdXRvIHRva2VuIGZyb20gbG9jYWxTdG9yYWdlXG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogQ3VzdG9tIGNvbmZpZ3VyYXRpb246XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBjbGllbnQgPSBjcmVhdGVBcGlDbGllbnQoe1xuICogICBiYXNlVVJMOiAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nLFxuICogICB0aW1lb3V0OiA2MDAwMCxcbiAqICAgY29ycmVsYXRpb25JZFByZWZpeDogJ3dlYicsXG4gKiAgIHJlcXVlc3RJbnRlcmNlcHRvcnM6IFtcbiAqICAgICBhc3luYyAoY29uZmlnKSA9PiB7XG4gKiAgICAgICBjb25zb2xlLmxvZygnTWFraW5nIHJlcXVlc3Q6JywgY29uZmlnLnVybCk7XG4gKiAgICAgICByZXR1cm4gY29uZmlnO1xuICogICAgIH1cbiAqICAgXVxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogV2l0aCBSZWFjdCBRdWVyeTpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGFwaUNsaWVudCA9IGNyZWF0ZUFwaUNsaWVudCh7XG4gKiAgIGJhc2VVUkw6IHByb2Nlc3MuZW52LlJFQUNUX0FQUF9BUElfVVJMXG4gKiB9KTtcbiAqXG4gKiBjb25zdCBxdWVyeUNsaWVudCA9IG5ldyBRdWVyeUNsaWVudCgpO1xuICpcbiAqIGZ1bmN0aW9uIFVzZXJQcm9maWxlKHsgdXNlcklkIH0pIHtcbiAqICAgY29uc3QgeyBkYXRhOiByZXNwb25zZSB9ID0gdXNlUXVlcnkoe1xuICogICAgIHF1ZXJ5S2V5OiBbJ3VzZXInLCB1c2VySWRdLFxuICogICAgIHF1ZXJ5Rm46ICgpID0+IGFwaUNsaWVudC5nZXQoYC91c2Vycy8ke3VzZXJJZH1gKVxuICogICB9KTtcbiAqICAgY29uc3QgdXNlciA9IHJlc3BvbnNlPy5hcGlEYXRhOyAvLyBBY2Nlc3MgdGhlIGFjdHVhbCBkYXRhXG4gKiAgIC8vIC4uLlxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVBcGlDbGllbnQoY29uZmlnOiBBcGlDbGllbnRDb25maWcgPSB7fSk6IEFwaUNsaWVudCB7XG4gIGNvbnN0IHtcbiAgICBiYXNlVVJMID0gJycsXG4gICAgdGltZW91dCA9IDMwMDAwLFxuICAgIGNvcnJlbGF0aW9uSWRQcmVmaXggPSAnd2ViJyxcbiAgICBpbmNsdWRlQ29ycmVsYXRpb25JZCA9IHRydWUsXG4gICAgcmVxdWVzdEludGVyY2VwdG9ycyA9IFtdLFxuICAgIHJlc3BvbnNlSW50ZXJjZXB0b3JzID0gW10sXG4gICAgZXJyb3JJbnRlcmNlcHRvcnMgPSBbXSxcbiAgfSA9IGNvbmZpZztcblxuICBjb25zdCBjbGllbnQgPSBuZXcgQXBpQ2xpZW50KGJhc2VVUkwsIHRpbWVvdXQpO1xuXG4gIGNsaWVudC5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoY29uZmlnID0+IHtcbiAgICBjb25zdCB0b2tlbiA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdzZXJ2aWNlVG9rZW4nKTtcblxuICAgIGlmICh0b2tlbiAmJiAhY29uZmlnLnNraXBBdXRoUmVmcmVzaCkge1xuICAgICAgY29uZmlnLmhlYWRlcnMgPSB7XG4gICAgICAgIC4uLmNvbmZpZy5oZWFkZXJzLFxuICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7dG9rZW59YCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmZpZztcbiAgfSk7XG5cbiAgLy8gQ29uZmlndXJlIGNvcnJlbGF0aW9uIElEXG4gIGNsaWVudC5zZXRDb3JyZWxhdGlvbklkUHJlZml4KGNvcnJlbGF0aW9uSWRQcmVmaXgpO1xuICBjbGllbnQuc2V0SW5jbHVkZUNvcnJlbGF0aW9uSWQoaW5jbHVkZUNvcnJlbGF0aW9uSWQpO1xuXG4gIC8vIC8vIFNldCBhdXRoIHRva2VuIGlmIHByb3ZpZGVkXG4gIC8vIGlmIChhdXRoVG9rZW4gIT09IHVuZGVmaW5lZCkge1xuICAvLyAgIGNsaWVudC5zZXRBdXRoVG9rZW4oYXV0aFRva2VuKTtcbiAgLy8gfVxuXG4gIC8vIEFkZCBpbnRlcmNlcHRvcnNcbiAgcmVxdWVzdEludGVyY2VwdG9ycy5mb3JFYWNoKGludGVyY2VwdG9yID0+IHtcbiAgICBjbGllbnQuYWRkUmVxdWVzdEludGVyY2VwdG9yKGludGVyY2VwdG9yKTtcbiAgfSk7XG5cbiAgcmVzcG9uc2VJbnRlcmNlcHRvcnMuZm9yRWFjaChpbnRlcmNlcHRvciA9PiB7XG4gICAgY2xpZW50LmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoaW50ZXJjZXB0b3IpO1xuICB9KTtcblxuICBlcnJvckludGVyY2VwdG9ycy5mb3JFYWNoKGludGVyY2VwdG9yID0+IHtcbiAgICBjbGllbnQuYWRkRXJyb3JJbnRlcmNlcHRvcihpbnRlcmNlcHRvcik7XG4gIH0pO1xuXG4gIHJldHVybiBjbGllbnQ7XG59XG5cbi8qKlxuICogR2V0cyBvciBjcmVhdGVzIGEgZ2xvYmFsIHNpbmdsZXRvbiBBcGlDbGllbnQgaW5zdGFuY2UuXG4gKlxuICogVGhpcyBmdW5jdGlvbiBpbXBsZW1lbnRzIHRoZSBzaW5nbGV0b24gcGF0dGVybiBmb3IgQXBpQ2xpZW50LiBJdCBjcmVhdGVzIHRoZSBjbGllbnRcbiAqIG9uIGZpcnN0IGNhbGwgYW5kIHJldHVybnMgdGhlIHNhbWUgaW5zdGFuY2Ugb24gc3Vic2VxdWVudCBjYWxscy4gVGhpcyBpcyB1c2VmdWwgZm9yOlxuICogLSBTaGFyaW5nIHRoZSBzYW1lIGNsaWVudCBhY3Jvc3MgeW91ciBlbnRpcmUgYXBwbGljYXRpb25cbiAqIC0gQXZvaWRpbmcgbXVsdGlwbGUgaW5zdGFuY2VzIHdpdGggZGlmZmVyZW50IGNvbmZpZ3VyYXRpb25zXG4gKiAtIENvbnNpc3RlbnQgaW50ZXJjZXB0b3IgYmVoYXZpb3IgYXBwLXdpZGVcbiAqXG4gKiAqKkltcG9ydGFudDoqKiBUaGUgY29uZmlnIHBhcmFtZXRlciBpcyBvbmx5IHVzZWQgb24gdGhlIEZJUlNUIGNhbGwuIFN1YnNlcXVlbnQgY2FsbHNcbiAqIGlnbm9yZSB0aGUgY29uZmlnIGFuZCByZXR1cm4gdGhlIGV4aXN0aW5nIGluc3RhbmNlLiBVc2Uge0BsaW5rIHJlc2V0R2xvYmFsQXBpQ2xpZW50fVxuICogZmlyc3QgaWYgeW91IG5lZWQgdG8gcmVjcmVhdGUgd2l0aCBkaWZmZXJlbnQgY29uZmlnLlxuICpcbiAqIEBwYXJhbSBjb25maWcgLSBDb25maWd1cmF0aW9uIG9wdGlvbnMgKG9ubHkgdXNlZCBvbiBmaXJzdCBjYWxsKVxuICogQHJldHVybnMgVGhlIGdsb2JhbCBBcGlDbGllbnQgc2luZ2xldG9uIGluc3RhbmNlXG4gKiBAcHVibGljXG4gKlxuICogQGV4YW1wbGVcbiAqIEluIHlvdXIgYXBwIGluaXRpYWxpemF0aW9uOlxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gc3JjL2xpYi9hcGkudHNcbiAqIGV4cG9ydCBjb25zdCBhcGlDbGllbnQgPSBnZXRHbG9iYWxBcGlDbGllbnQoe1xuICogICBiYXNlVVJMOiAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nLFxuICogICB0aW1lb3V0OiAzMDAwMFxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogSW1wb3J0IGFuZCB1c2UgdGhyb3VnaG91dCB5b3VyIGFwcDpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIHNyYy9mZWF0dXJlcy91c2Vycy9hcGkudHNcbiAqIGltcG9ydCB7IGdldEdsb2JhbEFwaUNsaWVudCB9IGZyb20gJ0BnbndlYnNvZnQvdWknO1xuICpcbiAqIGNvbnN0IGNsaWVudCA9IGdldEdsb2JhbEFwaUNsaWVudCgpOyAvLyBSZXR1cm5zIHNhbWUgaW5zdGFuY2VcbiAqXG4gKiBleHBvcnQgYXN5bmMgZnVuY3Rpb24gZmV0Y2hVc2VycygpIHtcbiAqICAgY29uc3QgeyBhcGlEYXRhIH0gPSBhd2FpdCBjbGllbnQuZ2V0KCcvdXNlcnMnKTtcbiAqICAgcmV0dXJuIGFwaURhdGE7XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogUmVzZXR0aW5nIGZvciB0ZXN0czpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGFmdGVyRWFjaCgoKSA9PiB7XG4gKiAgIHJlc2V0R2xvYmFsQXBpQ2xpZW50KCk7XG4gKiB9KTtcbiAqXG4gKiB0ZXN0KCdjcmVhdGVzIGZyZXNoIGNsaWVudCcsICgpID0+IHtcbiAqICAgY29uc3QgY2xpZW50ID0gZ2V0R2xvYmFsQXBpQ2xpZW50KHsgYmFzZVVSTDogJ2h0dHA6Ly90ZXN0LmxvY2FsJyB9KTtcbiAqICAgLy8gTmV3IGluc3RhbmNlIHdpdGggdGVzdCBjb25maWdcbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRHbG9iYWxBcGlDbGllbnQoY29uZmlnPzogQXBpQ2xpZW50Q29uZmlnKTogQXBpQ2xpZW50IHtcbiAgaWYgKCFnbG9iYWxBcGlDbGllbnQpIHtcbiAgICBnbG9iYWxBcGlDbGllbnQgPSBjcmVhdGVBcGlDbGllbnQoY29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBnbG9iYWxBcGlDbGllbnQ7XG59XG5cbi8qKlxuICogUmVwbGFjZXMgdGhlIGdsb2JhbCBzaW5nbGV0b24gQXBpQ2xpZW50IHdpdGggYSBjdXN0b20gaW5zdGFuY2UuXG4gKlxuICogVXNlIHRoaXMgd2hlbiB5b3UgbmVlZCBmaW5lLWdyYWluZWQgY29udHJvbCBvdmVyIHRoZSBnbG9iYWwgY2xpZW50IGluc3RhbmNlLFxuICogc3VjaCBhcyBpbiB0ZXN0aW5nIHNjZW5hcmlvcyBvciB3aGVuIHlvdSd2ZSBtYW51YWxseSBjcmVhdGVkIGEgY2xpZW50IHdpdGhcbiAqIHNwZWNpZmljIGNvbmZpZ3VyYXRpb24uXG4gKlxuICogQHBhcmFtIGNsaWVudCAtIFRoZSBBcGlDbGllbnQgaW5zdGFuY2UgdG8gdXNlIGFzIHRoZSBnbG9iYWwgc2luZ2xldG9uXG4gKiBAcHVibGljXG4gKlxuICogQGV4YW1wbGVcbiAqIFRlc3Rpbmcgd2l0aCBhIG1vY2sgY2xpZW50OlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgbW9ja0NsaWVudCA9IG5ldyBBcGlDbGllbnQoJ2h0dHA6Ly90ZXN0LmxvY2FsJyk7XG4gKiBtb2NrQ2xpZW50LmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoYXN5bmMgKHJlc3BvbnNlKSA9PiB7XG4gKiAgIC8vIE1vY2sgcmVzcG9uc2UgZGF0YVxuICogICByZXR1cm4geyBkYXRhOiBtb2NrRGF0YSB9O1xuICogfSk7XG4gKlxuICogc2V0R2xvYmFsQXBpQ2xpZW50KG1vY2tDbGllbnQpO1xuICogYGBgXG4gKlxuICogQGV4YW1wbGVcbiAqIEFkdmFuY2VkIGNvbmZpZ3VyYXRpb246XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBjbGllbnQgPSBuZXcgQXBpQ2xpZW50KCdodHRwczovL2FwaS5leGFtcGxlLmNvbScsIDYwMDAwKTtcbiAqIGNsaWVudC5zZXRDb3JyZWxhdGlvbklkUHJlZml4KCdjdXN0b20nKTtcbiAqIGNsaWVudC5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoY3VzdG9tSW50ZXJjZXB0b3IpO1xuICpcbiAqIHNldEdsb2JhbEFwaUNsaWVudChjbGllbnQpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRHbG9iYWxBcGlDbGllbnQoY2xpZW50OiBBcGlDbGllbnQpOiB2b2lkIHtcbiAgZ2xvYmFsQXBpQ2xpZW50ID0gY2xpZW50O1xufVxuXG4vKipcbiAqIFJlc2V0cyB0aGUgZ2xvYmFsIEFwaUNsaWVudCBzaW5nbGV0b24gdG8gbnVsbC5cbiAqXG4gKiBBZnRlciBjYWxsaW5nIHRoaXMsIHRoZSBuZXh0IGNhbGwgdG8ge0BsaW5rIGdldEdsb2JhbEFwaUNsaWVudH0gd2lsbCBjcmVhdGVcbiAqIGEgZnJlc2ggaW5zdGFuY2UuIFRoaXMgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCBpbjpcbiAqIC0gVGVzdCBjbGVhbnVwIHRvIGVuc3VyZSB0ZXN0IGlzb2xhdGlvblxuICogLSBBcHBsaWNhdGlvbiBsb2dvdXQgdG8gY2xlYXIgYW55IGNhY2hlZCBzdGF0ZVxuICogLSBIb3QgbW9kdWxlIHJlbG9hZGluZyBkdXJpbmcgZGV2ZWxvcG1lbnRcbiAqXG4gKiBAcHVibGljXG4gKlxuICogQGV4YW1wbGVcbiAqIFRlc3QgY2xlYW51cDpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGFmdGVyRWFjaCgoKSA9PiB7XG4gKiAgIHJlc2V0R2xvYmFsQXBpQ2xpZW50KCk7XG4gKiB9KTtcbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBMb2dvdXQgZmxvdzpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGZ1bmN0aW9uIGhhbmRsZUxvZ291dCgpIHtcbiAqICAgLy8gQ2xlYXIgYXV0aGVudGljYXRpb25cbiAqICAgbG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oJ3NlcnZpY2VUb2tlbicpO1xuICpcbiAqICAgLy8gQ2FuY2VsIGFsbCBwZW5kaW5nIHJlcXVlc3RzIGFuZCByZXNldCBjbGllbnRcbiAqICAgY29uc3QgY2xpZW50ID0gZ2V0R2xvYmFsQXBpQ2xpZW50KCk7XG4gKiAgIGNsaWVudC5jYW5jZWxBbGxSZXF1ZXN0cygpO1xuICogICByZXNldEdsb2JhbEFwaUNsaWVudCgpO1xuICpcbiAqICAgLy8gUmVkaXJlY3QgdG8gbG9naW5cbiAqICAgbmF2aWdhdGUoJy9sb2dpbicpO1xuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNldEdsb2JhbEFwaUNsaWVudCgpOiB2b2lkIHtcbiAgZ2xvYmFsQXBpQ2xpZW50ID0gbnVsbDtcbn1cbiIsICIvLyBDYW5jZWxUb2tlbiBpbXBsZW1lbnRhdGlvblxyXG5leHBvcnQgY2xhc3MgQ2FuY2VsVG9rZW4ge1xyXG4gIHByaXZhdGUgYWJvcnRDb250cm9sbGVyOiBBYm9ydENvbnRyb2xsZXI7XHJcbiAgcHJpdmF0ZSBjYW5jZWxQcm9taXNlOiBQcm9taXNlPHZvaWQ+O1xyXG4gIHByaXZhdGUgY2FuY2VsUmVzb2x2ZT86ICgpID0+IHZvaWQ7XHJcblxyXG4gIGNvbnN0cnVjdG9yKCkge1xyXG4gICAgdGhpcy5hYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XHJcbiAgICB0aGlzLmNhbmNlbFByb21pc2UgPSBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcclxuICAgICAgdGhpcy5jYW5jZWxSZXNvbHZlID0gcmVzb2x2ZTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHNpZ25hbCgpOiBBYm9ydFNpZ25hbCB7XHJcbiAgICByZXR1cm4gdGhpcy5hYm9ydENvbnRyb2xsZXIuc2lnbmFsO1xyXG4gIH1cclxuXHJcbiAgY2FuY2VsKHJlYXNvbj86IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5hYm9ydENvbnRyb2xsZXIuYWJvcnQocmVhc29uKTtcclxuICAgIHRoaXMuY2FuY2VsUmVzb2x2ZT8uKCk7XHJcbiAgfVxyXG5cclxuICBnZXQgaXNDYW5jZWxsZWQoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5hYm9ydENvbnRyb2xsZXIuc2lnbmFsLmFib3J0ZWQ7XHJcbiAgfVxyXG5cclxuICB0aHJvd0lmQ2FuY2VsbGVkKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuaXNDYW5jZWxsZWQpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZXF1ZXN0IGNhbmNlbGxlZCcpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc3RhdGljIHNvdXJjZSgpOiB7IHRva2VuOiBDYW5jZWxUb2tlbjsgY2FuY2VsOiAocmVhc29uPzogc3RyaW5nKSA9PiB2b2lkIH0ge1xyXG4gICAgY29uc3QgdG9rZW4gPSBuZXcgQ2FuY2VsVG9rZW4oKTtcclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICB0b2tlbixcclxuICAgICAgY2FuY2VsOiAocmVhc29uPzogc3RyaW5nKSA9PiB0b2tlbi5jYW5jZWwocmVhc29uKSxcclxuICAgIH07XHJcbiAgfVxyXG59XHJcbiIsICIvLyBSZWFjdCBIb29rcyB3aXRoIEFwaVJlc3BvbnNlIGZvcm1hdFxyXG5pbXBvcnQgeyB1c2VDYWxsYmFjayB9IGZyb20gJ3JlYWN0JztcclxuXHJcbmltcG9ydCB0eXBlIHsgQXBpRXJyb3IgfSBmcm9tICcuL3R5cGVzJztcclxuXHJcbi8vIEV4cG9ydCBmYWN0b3J5IG1ldGhvZHMgYW5kIHR5cGVzXHJcbmV4cG9ydCB7XHJcbiAgY3JlYXRlQXBpQ2xpZW50LFxyXG4gIGdldEdsb2JhbEFwaUNsaWVudCxcclxuICBzZXRHbG9iYWxBcGlDbGllbnQsXHJcbiAgcmVzZXRHbG9iYWxBcGlDbGllbnQsXHJcbn0gZnJvbSAnLi9jcmVhdGVBcGlDbGllbnQnO1xyXG5cclxuZXhwb3J0IHR5cGUgeyBBcGlDbGllbnRDb25maWcgfSBmcm9tICcuL2NyZWF0ZUFwaUNsaWVudCc7XHJcblxyXG5leHBvcnQgeyBBcGlDbGllbnQgfSBmcm9tICcuL0FwaUNsaWVudCc7XHJcblxyXG4vLyBIZWxwZXIgaG9vayBmb3IgZm9ybSB2YWxpZGF0aW9uIGVycm9yc1xyXG5leHBvcnQgZnVuY3Rpb24gdXNlVmFsaWRhdGlvbkVycm9ycyhlcnJvcjogQXBpRXJyb3IgfCBudWxsKSB7XHJcbiAgY29uc3QgZ2V0RmllbGRFcnJvciA9IHVzZUNhbGxiYWNrKFxyXG4gICAgKGZpZWxkOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsID0+IHtcclxuICAgICAgaWYgKCFlcnJvcj8uZXJyb3JzIHx8ICFlcnJvci5lcnJvcnNbZmllbGRdKSByZXR1cm4gbnVsbDtcclxuXHJcbiAgICAgIGNvbnN0IGZpZWxkRXJyb3IgPSBlcnJvci5lcnJvcnNbZmllbGRdO1xyXG5cclxuICAgICAgaWYgKHR5cGVvZiBmaWVsZEVycm9yID09PSAnc3RyaW5nJykgcmV0dXJuIGZpZWxkRXJyb3I7XHJcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGZpZWxkRXJyb3IpKSByZXR1cm4gZmllbGRFcnJvclswXTtcclxuICAgICAgaWYgKHR5cGVvZiBmaWVsZEVycm9yID09PSAnb2JqZWN0JyAmJiAnbWVzc2FnZScgaW4gZmllbGRFcnJvcikge1xyXG4gICAgICAgIHJldHVybiBmaWVsZEVycm9yLm1lc3NhZ2U7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfSxcclxuICAgIFtlcnJvcl1cclxuICApO1xyXG5cclxuICBjb25zdCBoYXNGaWVsZEVycm9yID0gdXNlQ2FsbGJhY2soXHJcbiAgICAoZmllbGQ6IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xyXG4gICAgICByZXR1cm4gISFnZXRGaWVsZEVycm9yKGZpZWxkKTtcclxuICAgIH0sXHJcbiAgICBbZ2V0RmllbGRFcnJvcl1cclxuICApO1xyXG5cclxuICBjb25zdCBnZXRBbGxFcnJvcnMgPSB1c2VDYWxsYmFjaygoKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9PiB7XHJcbiAgICBpZiAoIWVycm9yPy5lcnJvcnMpIHJldHVybiB7fTtcclxuXHJcbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcclxuXHJcbiAgICBPYmplY3QuZW50cmllcyhlcnJvci5lcnJvcnMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xyXG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgIHJlc3VsdFtrZXldID0gdmFsdWU7XHJcbiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcclxuICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlLmpvaW4oJywgJyk7XHJcbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAmJiAnbWVzc2FnZScgaW4gdmFsdWUpIHtcclxuICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlLm1lc3NhZ2U7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfSwgW2Vycm9yXSk7XHJcblxyXG4gIHJldHVybiB7XHJcbiAgICBnZXRGaWVsZEVycm9yLFxyXG4gICAgaGFzRmllbGRFcnJvcixcclxuICAgIGdldEFsbEVycm9ycyxcclxuICAgIGhhc0Vycm9yczogZXJyb3I/LmVycm9ycyxcclxuICB9O1xyXG59XHJcbiIsICJpbXBvcnQgdHlwZSB7IFByb3BzV2l0aENoaWxkcmVuIH0gZnJvbSAncmVhY3QnO1xuXG50eXBlIEF1dGhvcml6ZWRWaWV3UHJvcHMgPSBQcm9wc1dpdGhDaGlsZHJlbiAmIHtcbiAgc2hvdzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCBjb25zdCBBdXRob3JpemVkVmlldyA9ICh7IGNoaWxkcmVuLCBzaG93IH06IEF1dGhvcml6ZWRWaWV3UHJvcHMpID0+IHtcbiAgaWYgKCFzaG93KSByZXR1cm4gPD48Lz47XG5cbiAgcmV0dXJuIDw+e2NoaWxkcmVufTwvPjtcbn07XG4iLCAiaW1wb3J0IHR5cGUgeyBCdXR0b25Qcm9wcyB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xuaW1wb3J0IHsgQnV0dG9uIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgY29uc3QgQ2FuY2VsQnV0dG9uOiBSZWFjdC5GQzxCdXR0b25Qcm9wcz4gPSAoe1xuICBjaGlsZHJlbiA9ICdDYW5jZWwnLFxuICB2YXJpYW50ID0gJ291dGxpbmVkJyxcbiAgc3gsXG4gIC4uLnJlc3Rcbn0pID0+IChcbiAgPEJ1dHRvbiB2YXJpYW50PXt2YXJpYW50fSBzeD17eyB3aWR0aDogJzZyZW0nLCAuLi5zeCB9fSB7Li4ucmVzdH0+XG4gICAge2NoaWxkcmVufVxuICA8L0J1dHRvbj5cbik7XG4iLCAiaW1wb3J0IHR5cGUgeyBTeFByb3BzIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgeyBCdXR0b24gfSBmcm9tICdAbXVpL21hdGVyaWFsJztcblxuLyoqXG4gKiBQcm9wcyBmb3IgdGhlIENsZWFyQnV0dG9uIGNvbXBvbmVudC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmludGVyZmFjZSBDbGVhckJ1dHRvblByb3BzIHtcbiAgLyoqXG4gICAqIEluZGljYXRlcyBpZiBhIGZvcm0gb3Igb3BlcmF0aW9uIGlzIGN1cnJlbnRseSBiZWluZyBzdWJtaXR0ZWQuXG4gICAqIFdoZW4gdHJ1ZSwgdGhlIGJ1dHRvbiBpcyBkaXNhYmxlZCB0byBwcmV2ZW50IG11bHRpcGxlIGNsZWFyIGFjdGlvbnMuXG4gICAqL1xuICBpc1N1Ym1pdHRpbmc6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBleGVjdXRlZCB3aGVuIHRoZSBjbGVhciBidXR0b24gaXMgY2xpY2tlZC5cbiAgICogU2hvdWxkIGhhbmRsZSB0aGUgY2xlYXJpbmcgbG9naWMgKGUuZy4sIGZvcm0gcmVzZXQsIGRhdGEgY2xlYXJpbmcpLlxuICAgKi9cbiAgaGFuZGxlQ2xlYXI6ICgpID0+IHZvaWQ7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBNVUkgc3ggcHJvcCBmb3IgY3VzdG9tIHN0eWxpbmcuXG4gICAqIEBleGFtcGxlIHsgbXQ6IDIsIGNvbG9yOiAnd2FybmluZy5tYWluJyB9XG4gICAqL1xuICBzeD86IFN4UHJvcHM7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBsb2NhbFN0b3JhZ2Uga2V5IHRvIHJlbW92ZSB3aGVuIGNsZWFyaW5nLlxuICAgKiBJZiBwcm92aWRlZCwgdGhlIGNvcnJlc3BvbmRpbmcgbG9jYWxTdG9yYWdlIGl0ZW0gd2lsbCBiZSByZW1vdmVkIG9uIGNsaWNrLlxuICAgKiBAZXhhbXBsZSBcInVzZXItcHJlZmVyZW5jZXNcIiBvciBcImZvcm0tZGF0YVwiXG4gICAqL1xuICBzdG9yZUtleT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBTdGFuZGFyZGl6ZWQgY2xlYXIgYnV0dG9uIGNvbXBvbmVudCB3aXRoIGxvY2FsU3RvcmFnZSBpbnRlZ3JhdGlvbi5cbiAqXG4gKiBUaGlzIGNvbXBvbmVudCBwcm92aWRlcyBhIGNvbnNpc3RlbnQgY2xlYXIgYnV0dG9uIGltcGxlbWVudGF0aW9uIHRoYXQgaGFuZGxlc1xuICogYm90aCBjYWxsYmFjayBleGVjdXRpb24gYW5kIG9wdGlvbmFsIGxvY2FsU3RvcmFnZSBjbGVhbnVwLiBJdCBhdXRvbWF0aWNhbGx5XG4gKiBkaXNhYmxlcyBkdXJpbmcgZm9ybSBzdWJtaXNzaW9ucyBhbmQgY2FuIGNsZWFyIHN0b3JlZCBkYXRhIHdoZW4gbmVlZGVkLlxuICpcbiAqIEBleGFtcGxlXG4gKiBCYXNpYyB1c2FnZTpcbiAqIGBgYHRzeFxuICogPENsZWFyQnV0dG9uXG4gKiAgIGlzU3VibWl0dGluZz17aXNMb2FkaW5nfVxuICogICBoYW5kbGVDbGVhcj17KCkgPT4gZm9ybS5yZXNldCgpfVxuICogLz5cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBXaXRoIGxvY2FsU3RvcmFnZSBjbGVhbnVwOlxuICogYGBgdHN4XG4gKiA8Q2xlYXJCdXR0b25cbiAqICAgaXNTdWJtaXR0aW5nPXtmb3JtLmZvcm1TdGF0ZS5pc1N1Ym1pdHRpbmd9XG4gKiAgIGhhbmRsZUNsZWFyPXsoKSA9PiBzZXRGaWx0ZXJzKHt9KX1cbiAqICAgc3RvcmVLZXk9XCJ1c2VyLWZpbHRlcnNcIlxuICogLz5cbiAqIGBgYFxuICpcbiAqIEBwYXJhbSBwcm9wcyAtIENvbXBvbmVudCBwcm9wcyBmb3IgY2xlYXIgYnV0dG9uIGNvbmZpZ3VyYXRpb25cbiAqIEByZXR1cm5zIE1VSSBCdXR0b24gY29tcG9uZW50IGNvbmZpZ3VyZWQgYXMgYSBjbGVhciBidXR0b25cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBDbGVhckJ1dHRvbiA9ICh7XG4gIGlzU3VibWl0dGluZyxcbiAgaGFuZGxlQ2xlYXIsXG4gIHN4LFxuICBzdG9yZUtleSxcbn06IENsZWFyQnV0dG9uUHJvcHMpID0+IHtcbiAgY29uc3Qgb25DbGljayA9ICgpID0+IHtcbiAgICBoYW5kbGVDbGVhcigpO1xuICAgIGlmIChzdG9yZUtleSAhPSBudWxsKSB7XG4gICAgICBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShzdG9yZUtleSk7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiAoXG4gICAgPEJ1dHRvblxuICAgICAgdmFyaWFudD1cIm91dGxpbmVkXCJcbiAgICAgIG9uQ2xpY2s9e29uQ2xpY2t9XG4gICAgICBkaXNhYmxlZD17aXNTdWJtaXR0aW5nfVxuICAgICAgc3g9e3N4fVxuICAgID5cbiAgICAgIENsZWFyXG4gICAgPC9CdXR0b24+XG4gICk7XG59O1xuIiwgImltcG9ydCB7IENvbnRhaW5lciwgdHlwZSBTeFByb3BzIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XHJcbmltcG9ydCB0eXBlIHsgUmVhY3ROb2RlIH0gZnJvbSAncmVhY3QnO1xyXG5cclxuaW50ZXJmYWNlIFNpbXBsZUNvbnRhaW5lclByb3BzIHtcclxuICBjaGlsZHJlbjogUmVhY3ROb2RlO1xyXG4gIGNsYXNzTmFtZT86IHN0cmluZztcclxuICBzeD86IFN4UHJvcHM7XHJcbn1cclxuXHJcbmV4cG9ydCBjb25zdCBTaW1wbGVDb250YWluZXIgPSAoe1xyXG4gIGNoaWxkcmVuLFxyXG4gIGNsYXNzTmFtZSxcclxuICBzeCxcclxufTogU2ltcGxlQ29udGFpbmVyUHJvcHMpID0+IChcclxuICA8Q29udGFpbmVyIGNsYXNzTmFtZT17Y2xhc3NOYW1lfSBzeD17eyAuLi5zeCB9fT5cclxuICAgIHtjaGlsZHJlbn1cclxuICA8L0NvbnRhaW5lcj5cclxuKTtcclxuIiwgImltcG9ydCBGaWx0ZXJBbHRJY29uIGZyb20gJ0BtdWkvaWNvbnMtbWF0ZXJpYWwvRmlsdGVyQWx0JztcbmltcG9ydCB7IExvYWRpbmdCdXR0b24gfSBmcm9tICdAbXVpL2xhYic7XG5pbXBvcnQgdHlwZSB7IFN4UHJvcHMgfSBmcm9tICdAbXVpL21hdGVyaWFsJztcbmltcG9ydCB7IEJhZGdlIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5cbi8qKlxuICogUHJvcHMgZm9yIHRoZSBGaWx0ZXJCdXR0b24gY29tcG9uZW50LlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuaW50ZXJmYWNlIEZpbHRlckJ1dHRvblByb3BzIHtcbiAgLyoqXG4gICAqIEluZGljYXRlcyBpZiBhIGZpbHRlciBvcGVyYXRpb24gaXMgY3VycmVudGx5IGJlaW5nIHByb2Nlc3NlZC5cbiAgICogV2hlbiB0cnVlLCBzaG93cyBsb2FkaW5nIHNwaW5uZXIgYW5kIGRpc2FibGVzIHRoZSBidXR0b24uXG4gICAqL1xuICBpc1N1Ym1pdHRpbmc6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBDb250cm9scyBidXR0b24gdmlzaWJpbGl0eSBhbmQgZW5hYmxlZCBzdGF0ZS5cbiAgICogV2hlbiBmYWxzZSwgdGhlIGJ1dHRvbiBpcyBkaXNhYmxlZC5cbiAgICogQGRlZmF1bHRWYWx1ZSB0cnVlXG4gICAqL1xuICBzaG93PzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIEN1c3RvbSB0ZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi5cbiAgICogQGRlZmF1bHRWYWx1ZSBcIkZpbHRlclwiXG4gICAqIEBleGFtcGxlIFwiQXBwbHkgRmlsdGVyc1wiIG9yIFwiU2VhcmNoXCJcbiAgICovXG4gIHRpdGxlPzogc3RyaW5nO1xuICAvKipcbiAgICogQ3VzdG9tIGljb24gdG8gZGlzcGxheSBpbnN0ZWFkIG9mIHRoZSBkZWZhdWx0IGZpbHRlciBpY29uLlxuICAgKiBAZXhhbXBsZSA8U2VhcmNoSWNvbiAvPlxuICAgKi9cbiAgaWNvbj86IFJlYWN0LlJlYWN0Tm9kZTtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIE1VSSBzeCBwcm9wIGZvciBjdXN0b20gYnV0dG9uIHN0eWxpbmcuXG4gICAqIEBleGFtcGxlIHsgbXQ6IDIsIG1pbldpZHRoOiAxMjAgfVxuICAgKi9cbiAgc3g/OiBTeFByb3BzO1xuICAvKipcbiAgICogT3B0aW9uYWwgTVVJIHN4IHByb3AgZm9yIGN1c3RvbSBpY29uIHN0eWxpbmcuXG4gICAqIEBleGFtcGxlIHsgY29sb3I6ICdwcmltYXJ5Lm1haW4nLCBmb250U2l6ZTogMTggfVxuICAgKi9cbiAgaWNvblN4PzogU3hQcm9wcztcbn1cblxuLyoqXG4gKiBGaWx0ZXIgYnV0dG9uIGNvbXBvbmVudCB3aXRoIGxvYWRpbmcgc3RhdGVzIGFuZCBjdXN0b21pemFibGUgYXBwZWFyYW5jZS5cbiAqXG4gKiBUaGlzIGNvbXBvbmVudCBwcm92aWRlcyBhIHN0YW5kYXJkaXplZCBmaWx0ZXIvc3VibWl0IGJ1dHRvbiB3aXRoIGludGVncmF0ZWQgbG9hZGluZ1xuICogc3RhdGVzLCBpY29uIHN1cHBvcnQsIGFuZCBiYWRnZSBzdHlsaW5nLiBJdCdzIGRlc2lnbmVkIGZvciB1c2UgaW4gZmlsdGVyIGZvcm1zXG4gKiBhbmQgc2VhcmNoIGludGVyZmFjZXMgd2hlcmUgdXNlcnMgbmVlZCB0byBhcHBseSBmaWx0ZXJpbmcgY3JpdGVyaWEuXG4gKlxuICogQGV4YW1wbGVcbiAqIEJhc2ljIHVzYWdlOlxuICogYGBgdHN4XG4gKiA8RmlsdGVyQnV0dG9uXG4gKiAgIGlzU3VibWl0dGluZz17aXNMb2FkaW5nfVxuICogICBzaG93PXtoYXNGaWx0ZXJzfVxuICogLz5cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBDdXN0b20gdGl0bGUgYW5kIGljb246XG4gKiBgYGB0c3hcbiAqIDxGaWx0ZXJCdXR0b25cbiAqICAgaXNTdWJtaXR0aW5nPXtmb3JtLmZvcm1TdGF0ZS5pc1N1Ym1pdHRpbmd9XG4gKiAgIHRpdGxlPVwiQXBwbHkgU2VhcmNoXCJcbiAqICAgaWNvbj17PFNlYXJjaEljb24gLz59XG4gKiAgIHNob3c9e3RydWV9XG4gKiAvPlxuICogYGBgXG4gKlxuICogQGV4YW1wbGVcbiAqIFdpdGggY3VzdG9tIHN0eWxpbmc6XG4gKiBgYGB0c3hcbiAqIDxGaWx0ZXJCdXR0b25cbiAqICAgaXNTdWJtaXR0aW5nPXtpc1Byb2Nlc3Npbmd9XG4gKiAgIHRpdGxlPVwiRmlsdGVyIFJlc3VsdHNcIlxuICogICBzeD17eyBtaW5XaWR0aDogMTUwLCBtdDogMiB9fVxuICogICBpY29uU3g9e3sgZm9udFNpemU6IDIwIH19XG4gKiAvPlxuICogYGBgXG4gKlxuICogQHBhcmFtIHByb3BzIC0gQ29tcG9uZW50IHByb3BzIGZvciBmaWx0ZXIgYnV0dG9uIGNvbmZpZ3VyYXRpb25cbiAqIEByZXR1cm5zIE1VSSBMb2FkaW5nQnV0dG9uIGNvbXBvbmVudCBjb25maWd1cmVkIGFzIGEgZmlsdGVyIGJ1dHRvblxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IEZpbHRlckJ1dHRvbiA9ICh7XG4gIGlzU3VibWl0dGluZyxcbiAgc2hvdyxcbiAgdGl0bGUsXG4gIGljb24sXG4gIHN4LFxuICBpY29uU3gsXG59OiBGaWx0ZXJCdXR0b25Qcm9wcykgPT4ge1xuICByZXR1cm4gKFxuICAgIDxMb2FkaW5nQnV0dG9uXG4gICAgICB0eXBlPVwic3VibWl0XCJcbiAgICAgIHZhcmlhbnQ9XCJjb250YWluZWRcIlxuICAgICAgbG9hZGluZz17aXNTdWJtaXR0aW5nfVxuICAgICAgZGlzYWJsZWQ9eyFzaG93fVxuICAgICAgZGlzYWJsZVJpcHBsZVxuICAgICAgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgIHN4PXt7XG4gICAgICAgIGRpc3BsYXk6ICdmbGV4JyxcbiAgICAgICAgYWxpZ25JdGVtczogJ2NlbnRlcicsXG4gICAgICAgIC4uLnN4LFxuICAgICAgfX1cbiAgICAgIHN0YXJ0SWNvbj17XG4gICAgICAgIDxCYWRnZSBjb2xvcj1cImVycm9yXCIgdmFyaWFudD1cInN0YW5kYXJkXCI+XG4gICAgICAgICAge2ljb24gPyBpY29uIDogPEZpbHRlckFsdEljb24gd2lkdGg9XCIyMFwiIGhlaWdodD1cIjIwXCIgc3g9e2ljb25TeH0gLz59XG4gICAgICAgIDwvQmFkZ2U+XG4gICAgICB9XG4gICAgPlxuICAgICAge3RpdGxlPy50cmltKCkgPT09ICcnIHx8ICF0aXRsZSA/ICdGaWx0ZXInIDogdGl0bGV9XG4gICAgPC9Mb2FkaW5nQnV0dG9uPlxuICApO1xufTtcbiIsICJpbXBvcnQgQ2hpcCBmcm9tICdAbXVpL21hdGVyaWFsL0NoaXAnO1xyXG5pbXBvcnQgeyBtZW1vIH0gZnJvbSAncmVhY3QnO1xyXG5cclxuLy8gSW5kaXZpZHVhbCBjaGlwIGNvbXBvbmVudCB0byBwcmV2ZW50IHVubmVjZXNzYXJ5IHJlcmVuZGVycyBvZiBzaWJsaW5nIGNoaXBzXHJcbmV4cG9ydCBjb25zdCBGaWx0ZXJDaGlwID0gbWVtbyhcclxuICAoe1xyXG4gICAgZmllbGRLZXksXHJcbiAgICBmaWx0ZXIsXHJcbiAgICBvbkRlbGV0ZSxcclxuICB9OiB7XHJcbiAgICBmaWVsZEtleTogc3RyaW5nO1xyXG4gICAgZmlsdGVyOiB7IExhYmVsOiBzdHJpbmc7IFZhbHVlOiB1bmtub3duIH07XHJcbiAgICBvbkRlbGV0ZT86ICgpID0+IHZvaWQ7XHJcbiAgfSkgPT4ge1xyXG4gICAgY29uc3QgaGFzVmFsdWUgPVxyXG4gICAgICBmaWx0ZXIuVmFsdWUgIT09IG51bGwgJiZcclxuICAgICAgZmlsdGVyLlZhbHVlICE9PSB1bmRlZmluZWQgJiZcclxuICAgICAgZmlsdGVyLlZhbHVlICE9PSAnJztcclxuICAgIGNvbnN0IGxhYmVsID0gYCR7ZmllbGRLZXkucmVwbGFjZSgnUEsnLCAnJyl9OiAke2ZpbHRlci5MYWJlbH1gO1xyXG5cclxuICAgIHJldHVybiAoXHJcbiAgICAgIDxDaGlwXHJcbiAgICAgICAga2V5PXtmaWVsZEtleX1cclxuICAgICAgICBsYWJlbD17bGFiZWx9XHJcbiAgICAgICAgdmFyaWFudD17aGFzVmFsdWUgPyAnZmlsbGVkJyA6ICdvdXRsaW5lZCd9XHJcbiAgICAgICAgc2l6ZT1cInNtYWxsXCJcclxuICAgICAgICBvbkRlbGV0ZT17aGFzVmFsdWUgPyBvbkRlbGV0ZSA6IHVuZGVmaW5lZH1cclxuICAgICAgLz5cclxuICAgICk7XHJcbiAgfVxyXG4pO1xyXG5cclxuRmlsdGVyQ2hpcC5kaXNwbGF5TmFtZSA9ICdGaWx0ZXJDaGlwJztcclxuIiwgImltcG9ydCB7IENhcmQsIENhcmRDb250ZW50LCBUeXBvZ3JhcGh5LCBCb3ggfSBmcm9tICdAbXVpL21hdGVyaWFsJztcclxuaW1wb3J0IHsgbWVtbywgdXNlTWVtbyB9IGZyb20gJ3JlYWN0JztcclxuXHJcbmltcG9ydCB7IEZpbHRlckNoaXAgfSBmcm9tICcuL0ZpbHRlckNoaXAnO1xyXG5cclxuaW50ZXJmYWNlIEZpbHRlckRpc3BsYXlQcm9wczxURmlsdGVyTW9kZWw+IHtcclxuICBmcmllbmRseUZpbHRlcjogUmVjb3JkPHN0cmluZywgeyBMYWJlbDogc3RyaW5nOyBWYWx1ZTogdW5rbm93biB9PjtcclxuICBvbkZyaWVuZGx5RmlsdGVyQ2hhbmdlPzogKGZpZWxkS2V5OiBrZXlvZiBURmlsdGVyTW9kZWwpID0+IHZvaWQ7XHJcbn1cclxuXHJcbmV4cG9ydCBjb25zdCBQcm9ncmFtc0ZpbHRlckRpc3BsYXkgPSBtZW1vKFxyXG4gIDxURmlsdGVyTW9kZWwgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXHJcbiAgICBwcm9wczogRmlsdGVyRGlzcGxheVByb3BzPFRGaWx0ZXJNb2RlbD5cclxuICApID0+IHtcclxuICAgIGNvbnN0IHsgZnJpZW5kbHlGaWx0ZXIsIG9uRnJpZW5kbHlGaWx0ZXJDaGFuZ2UgfSA9IHByb3BzO1xyXG5cclxuICAgIC8vIE1lbW9pemUgZGVsZXRlIGhhbmRsZXJzIHRvIHByZXZlbnQgcmVjcmVhdGlvblxyXG4gICAgY29uc3QgZGVsZXRlSGFuZGxlcnMgPSB1c2VNZW1vKCgpID0+IHtcclxuICAgICAgaWYgKCFvbkZyaWVuZGx5RmlsdGVyQ2hhbmdlKSByZXR1cm4ge307XHJcblxyXG4gICAgICBjb25zdCBoYW5kbGVyczogUmVjb3JkPHN0cmluZywgKCkgPT4gdm9pZD4gPSB7fTtcclxuXHJcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGZyaWVuZGx5RmlsdGVyKSkge1xyXG4gICAgICAgIGhhbmRsZXJzW2tleV0gPSAoKSA9PiBvbkZyaWVuZGx5RmlsdGVyQ2hhbmdlKGtleSBhcyBrZXlvZiBURmlsdGVyTW9kZWwpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICByZXR1cm4gaGFuZGxlcnM7XHJcbiAgICB9LCBbb25GcmllbmRseUZpbHRlckNoYW5nZSwgZnJpZW5kbHlGaWx0ZXJdKTtcclxuXHJcbiAgICAvLyBNZW1vaXplIGNoaXAgbGlzdCB0byBwcmV2ZW50IHVubmVjZXNzYXJ5IHJlY2FsY3VsYXRpb25zXHJcbiAgICBjb25zdCBjaGlwTGlzdCA9IHVzZU1lbW8oKCkgPT4ge1xyXG4gICAgICByZXR1cm4gT2JqZWN0LmVudHJpZXMoZnJpZW5kbHlGaWx0ZXIpLm1hcCgoW2tleSwgZmlsdGVyXSkgPT4gKFxyXG4gICAgICAgIDxGaWx0ZXJDaGlwXHJcbiAgICAgICAgICBrZXk9e2tleX1cclxuICAgICAgICAgIGZpZWxkS2V5PXtrZXl9XHJcbiAgICAgICAgICBmaWx0ZXI9e2ZpbHRlciBhcyB7IExhYmVsOiBzdHJpbmc7IFZhbHVlOiB1bmtub3duIH19XHJcbiAgICAgICAgICBvbkRlbGV0ZT17ZGVsZXRlSGFuZGxlcnNba2V5XX1cclxuICAgICAgICAvPlxyXG4gICAgICApKTtcclxuICAgIH0sIFtmcmllbmRseUZpbHRlciwgZGVsZXRlSGFuZGxlcnNdKTtcclxuXHJcbiAgICByZXR1cm4gKFxyXG4gICAgICA8Q2FyZCBzeD17eyBtYjogMiB9fT5cclxuICAgICAgICA8Q2FyZENvbnRlbnQ+XHJcbiAgICAgICAgICA8VHlwb2dyYXBoeSB2YXJpYW50PVwiaDZcIiBndXR0ZXJCb3R0b20+XHJcbiAgICAgICAgICAgIEFjdGl2ZSBGaWx0ZXJzXHJcbiAgICAgICAgICA8L1R5cG9ncmFwaHk+XHJcbiAgICAgICAgICA8Qm94IGRpc3BsYXk9XCJmbGV4XCIgZ2FwPXsxfSBmbGV4V3JhcD1cIndyYXBcIj5cclxuICAgICAgICAgICAge2NoaXBMaXN0fVxyXG4gICAgICAgICAgPC9Cb3g+XHJcbiAgICAgICAgPC9DYXJkQ29udGVudD5cclxuICAgICAgPC9DYXJkPlxyXG4gICAgKTtcclxuICB9XHJcbik7XHJcblxyXG5Qcm9ncmFtc0ZpbHRlckRpc3BsYXkuZGlzcGxheU5hbWUgPSAnRmlsdGVyRGlzcGxheSc7XHJcblxyXG5leHBvcnQgdHlwZSB7IEZpbHRlckRpc3BsYXlQcm9wcyB9O1xyXG4iLCAiaW1wb3J0IE1hbmFnZVNlYXJjaEljb24gZnJvbSAnQG11aS9pY29ucy1tYXRlcmlhbC9NYW5hZ2VTZWFyY2gnO1xuaW1wb3J0IHR5cGUgeyBTeFByb3BzIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQge1xuICBCb3gsXG4gIENhcmQsXG4gIENhcmRDb250ZW50LFxuICBDYXJkSGVhZGVyLFxuICBEaXZpZGVyLFxuICBHcmlkLFxuICBUeXBvZ3JhcGh5LFxuICB1c2VUaGVtZSxcbn0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgdHlwZSB7IFByb3BzV2l0aENoaWxkcmVuLCBSZWFjdE5vZGUgfSBmcm9tICdyZWFjdCc7XG5cbi8qKlxuICogUHJvcHMgZm9yIHRoZSBGaWx0ZXJXcmFwcGVyIGNvbXBvbmVudC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbnR5cGUgRmlsdGVyV3JhcHBlclByb3BzID0gUHJvcHNXaXRoQ2hpbGRyZW48e1xuICAvKipcbiAgICogVGl0bGUgdGV4dCBkaXNwbGF5ZWQgaW4gdGhlIGNhcmQgaGVhZGVyLlxuICAgKiBAZGVmYXVsdFZhbHVlIFwiRmlsdGVyXCJcbiAgICogQGV4YW1wbGUgXCJTZWFyY2ggQ3JpdGVyaWFcIiBvciBcIkFkdmFuY2VkIEZpbHRlcnNcIlxuICAgKi9cbiAgdGl0bGU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBOdW1iZXIgb2YgYWN0aXZlIGZpbHRlcnMgdG8gZGlzcGxheSBpbiB0aGUgaGVhZGVyLlxuICAgKiBPbmx5IHNob3duIHdoZW4gc2hvd0NvdW50IGlzIHRydWUuXG4gICAqIEBleGFtcGxlIDMgZm9yIFwiRmlsdGVyICgzKVwiXG4gICAqL1xuICBmaWx0ZXJDb3VudD86IG51bWJlcjtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIE1VSSBzeCBwcm9wIGZvciBjdXN0b20gY2FyZCBzdHlsaW5nLlxuICAgKiBAZXhhbXBsZSB7IG10OiAyLCBib3hTaGFkb3c6IDIgfVxuICAgKi9cbiAgY2FyZFN4PzogU3hQcm9wcztcbiAgLyoqXG4gICAqIE9wdGlvbmFsIE1VSSBzeCBwcm9wIGZvciBjdXN0b20gdGl0bGUgdGV4dCBzdHlsaW5nLlxuICAgKiBAZXhhbXBsZSB7IGZvbnRTaXplOiAxOCwgZm9udFdlaWdodDogJ2JvbGQnIH1cbiAgICovXG4gIHRleHRTeD86IFN4UHJvcHM7XG4gIC8qKlxuICAgKiBDdXN0b20gaWNvbiB0byBkaXNwbGF5IGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgc2VhcmNoIGljb24uXG4gICAqIEBleGFtcGxlIDxGaWx0ZXJMaXN0SWNvbiAvPlxuICAgKi9cbiAgaWNvbj86IFJlYWN0Tm9kZTtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIE1VSSBzeCBwcm9wIGZvciBjdXN0b20gaWNvbiBzdHlsaW5nLlxuICAgKiBAZXhhbXBsZSB7IGNvbG9yOiAnc2Vjb25kYXJ5Lm1haW4nLCBmb250U2l6ZTogMjQgfVxuICAgKi9cbiAgaWNvblN4PzogU3hQcm9wcztcbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZGlzcGxheSB0aGUgZmlsdGVyIGNvdW50IGluIHRoZSBoZWFkZXIuXG4gICAqIEBkZWZhdWx0VmFsdWUgZmFsc2VcbiAgICovXG4gIHNob3dDb3VudD86IGJvb2xlYW47XG59PjtcblxuLyoqXG4gKiBDYXJkLWJhc2VkIHdyYXBwZXIgY29tcG9uZW50IGZvciBvcmdhbml6aW5nIGZpbHRlciBjb250cm9scyBhbmQgZm9ybSBlbGVtZW50cy5cbiAqXG4gKiBUaGlzIGNvbXBvbmVudCBwcm92aWRlcyBhIGNvbnNpc3RlbnQgbGF5b3V0IGZvciBmaWx0ZXIgaW50ZXJmYWNlcyB3aXRoIGEgaGVhZGVyLFxuICogb3B0aW9uYWwgZmlsdGVyIGNvdW50IGRpc3BsYXksIGFuZCBhIGdyaWQtYmFzZWQgY29udGVudCBhcmVhLiBJdCdzIGRlc2lnbmVkIHRvXG4gKiBjb250YWluIGZvcm0gY29udHJvbHMgYW5kIGZpbHRlciBlbGVtZW50cyBpbiBhIHZpc3VhbGx5IG9yZ2FuaXplZCBtYW5uZXIuXG4gKlxuICogQGV4YW1wbGVcbiAqIEJhc2ljIHVzYWdlOlxuICogYGBgdHN4XG4gKiA8RmlsdGVyV3JhcHBlcj5cbiAqICAgPEdyaWQgaXRlbSB4cz17MTJ9IG1kPXs2fT5cbiAqICAgICA8VGV4dEZpZWxkIGxhYmVsPVwiU2VhcmNoXCIgLz5cbiAqICAgPC9HcmlkPlxuICogICA8R3JpZCBpdGVtIHhzPXsxMn0gbWQ9ezZ9PlxuICogICAgIDxTZWxlY3QgbGFiZWw9XCJDYXRlZ29yeVwiIC8+XG4gKiAgIDwvR3JpZD5cbiAqIDwvRmlsdGVyV3JhcHBlcj5cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBXaXRoIGN1c3RvbSB0aXRsZSBhbmQgY291bnQ6XG4gKiBgYGB0c3hcbiAqIDxGaWx0ZXJXcmFwcGVyXG4gKiAgIHRpdGxlPVwiQWR2YW5jZWQgU2VhcmNoXCJcbiAqICAgZmlsdGVyQ291bnQ9e2FjdGl2ZUZpbHRlcnMubGVuZ3RofVxuICogICBzaG93Q291bnQ9e3RydWV9XG4gKiA+XG4gKiAgIHtmaWx0ZXJDb250cm9sc31cbiAqIDwvRmlsdGVyV3JhcHBlcj5cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBXaXRoIGN1c3RvbSBzdHlsaW5nOlxuICogYGBgdHN4XG4gKiA8RmlsdGVyV3JhcHBlclxuICogICB0aXRsZT1cIlByb2R1Y3QgRmlsdGVyc1wiXG4gKiAgIGljb249ezxGaWx0ZXJMaXN0SWNvbiAvPn1cbiAqICAgY2FyZFN4PXt7IG10OiAzLCBib3JkZXJSYWRpdXM6IDIgfX1cbiAqICAgdGV4dFN4PXt7IGNvbG9yOiAnc2Vjb25kYXJ5Lm1haW4nIH19XG4gKiA+XG4gKiAgIHtjaGlsZHJlbn1cbiAqIDwvRmlsdGVyV3JhcHBlcj5cbiAqIGBgYFxuICpcbiAqIEBwYXJhbSBwcm9wcyAtIENvbXBvbmVudCBwcm9wcyBpbmNsdWRpbmcgY2hpbGRyZW4gYW5kIHN0eWxpbmcgb3B0aW9uc1xuICogQHJldHVybnMgTVVJIENhcmQgY29tcG9uZW50IHdpdGggc3RydWN0dXJlZCBmaWx0ZXIgbGF5b3V0XG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgRmlsdGVyV3JhcHBlciA9ICh7XG4gIGNoaWxkcmVuLFxuICB0aXRsZSxcbiAgZmlsdGVyQ291bnQsXG4gIGNhcmRTeCxcbiAgdGV4dFN4LFxuICBpY29uLFxuICBpY29uU3gsXG4gIHNob3dDb3VudCxcbn06IEZpbHRlcldyYXBwZXJQcm9wcykgPT4ge1xuICBjb25zdCB0aGVtZSA9IHVzZVRoZW1lKCk7XG5cbiAgcmV0dXJuIChcbiAgICA8Q2FyZFxuICAgICAgc3g9e3tcbiAgICAgICAgcG9zaXRpb246ICdyZWxhdGl2ZScsXG4gICAgICAgIGJvcmRlclJhZGl1czogJzBweCcsXG4gICAgICAgIG1iOiAyLFxuICAgICAgICAuLi5jYXJkU3gsXG4gICAgICB9fVxuICAgID5cbiAgICAgIDxDYXJkSGVhZGVyXG4gICAgICAgIHN4PXt7XG4gICAgICAgICAgZGlzcGxheTogJ2ZsZXgnLFxuICAgICAgICAgIGZsZXhXcmFwOiAnd3JhcCcsXG4gICAgICAgICAgcDogJzFyZW0nLFxuICAgICAgICAgICcuTXVpQ2FyZEhlYWRlci1hY3Rpb24nOiB7XG4gICAgICAgICAgICBtYXJnaW46IDAsXG4gICAgICAgICAgICBhbGlnblNlbGY6ICdjZW50ZXInLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYWxpZ25JdGVtczogJ2NlbnRlcicsXG4gICAgICAgIH19XG4gICAgICAgIHRpdGxlPXtcbiAgICAgICAgICA8Qm94IHN4PXt7IGRpc3BsYXk6ICdmbGV4JywgYWxpZ25JdGVtczogJ2NlbnRlcicsIGdhcDogMC41IH19PlxuICAgICAgICAgICAge2ljb24gPyAoXG4gICAgICAgICAgICAgIGljb25cbiAgICAgICAgICAgICkgOiAoXG4gICAgICAgICAgICAgIDxNYW5hZ2VTZWFyY2hJY29uXG4gICAgICAgICAgICAgICAgc3g9e3tcbiAgICAgICAgICAgICAgICAgIGhlaWdodDogJzIuNXJlbScsXG4gICAgICAgICAgICAgICAgICBjb2xvcjogdGhlbWUucGFsZXR0ZS5wcmltYXJ5Lm1haW4sXG4gICAgICAgICAgICAgICAgICAuLi5pY29uU3gsXG4gICAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICl9XG4gICAgICAgICAgICA8VHlwb2dyYXBoeVxuICAgICAgICAgICAgICB2YXJpYW50PVwiaDVcIlxuICAgICAgICAgICAgICBzeD17e1xuICAgICAgICAgICAgICAgIGZvbnRXZWlnaHQ6ICdib2xkJyxcbiAgICAgICAgICAgICAgICBjb2xvcjogdGhlbWUucGFsZXR0ZS5wcmltYXJ5Lm1haW4sXG4gICAgICAgICAgICAgICAgLi4udGV4dFN4LFxuICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7dGl0bGUgPyB0aXRsZSA6ICdGaWx0ZXInfXsnICd9XG4gICAgICAgICAgICAgIHtzaG93Q291bnQgPyBgKCR7ZmlsdGVyQ291bnQgPyBmaWx0ZXJDb3VudCA6IDB9KWAgOiA8PjwvPn1cbiAgICAgICAgICAgIDwvVHlwb2dyYXBoeT5cbiAgICAgICAgICA8L0JveD5cbiAgICAgICAgfVxuICAgICAgPjwvQ2FyZEhlYWRlcj5cbiAgICAgIDxEaXZpZGVyIC8+XG4gICAgICA8Q2FyZENvbnRlbnQgc3g9e3sgcHk6IDIgfX0+XG4gICAgICAgIDxHcmlkIGNvbnRhaW5lciBzcGFjaW5nPXsyfT5cbiAgICAgICAgICB7Y2hpbGRyZW59XG4gICAgICAgIDwvR3JpZD5cbiAgICAgIDwvQ2FyZENvbnRlbnQ+XG4gICAgPC9DYXJkPlxuICApO1xufTtcbiIsICIvLyBjb3JlL2NvbXBvbmVudHMvRm9vdGVyL2luZGV4LnRzeFxyXG5pbXBvcnQgeyBCb3gsIFR5cG9ncmFwaHkgfSBmcm9tICdAbXVpL21hdGVyaWFsJztcclxuaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcclxuXHJcbmV4cG9ydCBjb25zdCBGb290ZXI6IFJlYWN0LkZDID0gKCkgPT4ge1xyXG4gIGNvbnN0IGN1cnJlbnRZZWFyID0gbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpO1xyXG5cclxuICByZXR1cm4gKFxyXG4gICAgPEJveFxyXG4gICAgICBjb21wb25lbnQ9XCJmb290ZXJcIlxyXG4gICAgICBzeD17e1xyXG4gICAgICAgIHB5OiAyLFxyXG4gICAgICAgIHB4OiA0LFxyXG4gICAgICAgIG10OiAnYXV0bycsXHJcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiB0aGVtZSA9PlxyXG4gICAgICAgICAgdGhlbWUucGFsZXR0ZS5tb2RlID09PSAnbGlnaHQnXHJcbiAgICAgICAgICAgID8gdGhlbWUucGFsZXR0ZS5ncmV5WzIwMF1cclxuICAgICAgICAgICAgOiB0aGVtZS5wYWxldHRlLmdyZXlbODAwXSxcclxuICAgICAgfX1cclxuICAgID5cclxuICAgICAgPFR5cG9ncmFwaHkgdmFyaWFudD1cImJvZHkyXCIgY29sb3I9XCJ0ZXh0LnNlY29uZGFyeVwiIGFsaWduPVwiY2VudGVyXCI+XHJcbiAgICAgICAge2BcdTAwQTkgQ29weXJpZ2h0ICR7Y3VycmVudFllYXJ9IEdOLiBBbGwgcmlnaHRzIHJlc2VydmVkIGJ5IFBhcnVsIFVuaXZlcnNpdHkuYH1cclxuICAgICAgPC9UeXBvZ3JhcGh5PlxyXG4gICAgPC9Cb3g+XHJcbiAgKTtcclxufTtcclxuIiwgImltcG9ydCB0eXBlIHsgU3hQcm9wcyB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xuaW1wb3J0IHsgR3JpZCwgVG9vbHRpcCwgVHlwb2dyYXBoeSB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xuXG4vKipcbiAqIFByb3BzIGZvciB0aGUgTGFiZWxUZXh0IGNvbXBvbmVudC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmludGVyZmFjZSBMYWJlbFRleHRQcm9wcyB7XG4gIC8qKlxuICAgKiBMYWJlbCB0ZXh0IHRvIGRpc3BsYXkgb24gdGhlIGxlZnQgc2lkZS5cbiAgICogQGV4YW1wbGUgXCJOYW1lXCIgb3IgXCJFbWFpbCBBZGRyZXNzXCJcbiAgICovXG4gIGxhYmVsOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBWYWx1ZSBjb250ZW50IHRvIGRpc3BsYXkgb24gdGhlIHJpZ2h0IHNpZGUuXG4gICAqIENhbiBiZSB0ZXh0LCBudW1iZXJzLCBvciBSZWFjdCBlbGVtZW50cy5cbiAgICogQGV4YW1wbGUgXCJKb2huIERvZVwiIG9yIDxMaW5rPlZpZXcgRGV0YWlsczwvTGluaz5cbiAgICovXG4gIHZhbHVlOiBSZWFjdC5SZWFjdE5vZGU7XG4gIC8qKlxuICAgKiBDdXN0b20gZ3JpZCBzaXppbmcgZm9yIGxhYmVsIGFuZCB2YWx1ZSBzZWN0aW9ucy5cbiAgICogQGRlZmF1bHRWYWx1ZSB7IGxhYmVsU2l6ZTogeyB4czogNiwgc206IDYsIG1kOiA2IH0sIHZhbHVlU2l6ZTogeyB4czogMTIsIHNtOiA2LCBtZDogNiB9IH1cbiAgICovXG4gIGdyaWRTaXplPzoge1xuICAgIC8qKiBHcmlkIHNpemUgY29uZmlndXJhdGlvbiBmb3IgdGhlIGxhYmVsIHNlY3Rpb24gKi9cbiAgICBsYWJlbFNpemU6IHsgeHM6IG51bWJlcjsgc206IG51bWJlcjsgbWQ6IG51bWJlciB9O1xuICAgIC8qKiBHcmlkIHNpemUgY29uZmlndXJhdGlvbiBmb3IgdGhlIHZhbHVlIHNlY3Rpb24gKi9cbiAgICB2YWx1ZVNpemU6IHsgeHM6IG51bWJlcjsgc206IG51bWJlcjsgbWQ6IG51bWJlciB9O1xuICB9O1xuICAvKipcbiAgICogR3JpZCBzaXplIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBlbnRpcmUgY29udGFpbmVyLlxuICAgKiBAZGVmYXVsdFZhbHVlIHsgeHM6IDEyLCBzbTogNiwgbWQ6IDYgfVxuICAgKi9cbiAgY29udGFpbmVyU2l6ZT86IHsgeHM6IG51bWJlcjsgc206IG51bWJlcjsgbWQ6IG51bWJlciB9O1xuICAvKipcbiAgICogT3B0aW9uYWwgTVVJIHN4IHByb3AgZm9yIGN1c3RvbSBsYWJlbCBzdHlsaW5nLlxuICAgKiBAZXhhbXBsZSB7IGZvbnRXZWlnaHQ6ICdib2xkJywgY29sb3I6ICdwcmltYXJ5Lm1haW4nIH1cbiAgICovXG4gIGxhYmVsU3g/OiBTeFByb3BzO1xuICAvKipcbiAgICogT3B0aW9uYWwgTVVJIHN4IHByb3AgZm9yIGN1c3RvbSB2YWx1ZSBzdHlsaW5nLlxuICAgKiBAZXhhbXBsZSB7IGNvbG9yOiAndGV4dC5zZWNvbmRhcnknLCBmb250U3R5bGU6ICdpdGFsaWMnIH1cbiAgICovXG4gIHZhbHVlU3g/OiBTeFByb3BzO1xufVxuXG4vKipcbiAqIFJlc3BvbnNpdmUgbGFiZWwtdmFsdWUgZGlzcGxheSBjb21wb25lbnQgd2l0aCBob3ZlciBlZmZlY3RzIGFuZCB0ZXh0IHRydW5jYXRpb24uXG4gKlxuICogVGhpcyBjb21wb25lbnQgY3JlYXRlcyBhIGNvbnNpc3RlbnQgbGFiZWwtdmFsdWUgcGFpciBsYXlvdXQgdGhhdCBhZGFwdHMgdG8gZGlmZmVyZW50XG4gKiBzY3JlZW4gc2l6ZXMuIEl0IGluY2x1ZGVzIGhvdmVyIGVmZmVjdHMsIHRleHQgdHJ1bmNhdGlvbiB3aXRoIHRvb2x0aXBzLCBhbmRcbiAqIGN1c3RvbWl6YWJsZSBncmlkIHNpemluZyBmb3IgZmxleGlibGUgbGF5b3V0cy5cbiAqXG4gKiBAZXhhbXBsZVxuICogQmFzaWMgdXNhZ2U6XG4gKiBgYGB0c3hcbiAqIDxMYWJlbFRleHRcbiAqICAgbGFiZWw9XCJGdWxsIE5hbWVcIlxuICogICB2YWx1ZT1cIkpvaG4gRG9lXCJcbiAqIC8+XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogV2l0aCBSZWFjdCBlbGVtZW50IHZhbHVlOlxuICogYGBgdHN4XG4gKiA8TGFiZWxUZXh0XG4gKiAgIGxhYmVsPVwiUHJvZmlsZVwiXG4gKiAgIHZhbHVlPXs8TGluayBocmVmPVwiL3Byb2ZpbGVcIj5WaWV3IFByb2ZpbGU8L0xpbms+fVxuICogLz5cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBDdXN0b20gZ3JpZCBzaXppbmc6XG4gKiBgYGB0c3hcbiAqIDxMYWJlbFRleHRcbiAqICAgbGFiZWw9XCJEZXNjcmlwdGlvblwiXG4gKiAgIHZhbHVlPXtsb25nRGVzY3JpcHRpb259XG4gKiAgIGdyaWRTaXplPXt7XG4gKiAgICAgbGFiZWxTaXplOiB7IHhzOiAxMiwgc206IDMsIG1kOiAyIH0sXG4gKiAgICAgdmFsdWVTaXplOiB7IHhzOiAxMiwgc206IDksIG1kOiAxMCB9XG4gKiAgIH19XG4gKiAgIGNvbnRhaW5lclNpemU9e3sgeHM6IDEyLCBzbTogMTIsIG1kOiAxMiB9fVxuICogLz5cbiAqIGBgYFxuICpcbiAqIEBwYXJhbSBwcm9wcyAtIENvbXBvbmVudCBwcm9wcyBmb3IgbGFiZWwtdmFsdWUgY29uZmlndXJhdGlvblxuICogQHJldHVybnMgR3JpZC1iYXNlZCBsYXlvdXQgd2l0aCBsYWJlbCBhbmQgdmFsdWUgc2VjdGlvbnNcbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBMYWJlbFRleHQgPSAoe1xuICBsYWJlbCxcbiAgdmFsdWUsXG4gIGdyaWRTaXplLFxuICBjb250YWluZXJTaXplLFxuICBsYWJlbFN4LFxuICB2YWx1ZVN4LFxufTogTGFiZWxUZXh0UHJvcHMpID0+IHtcbiAgY29uc3QgZGVmYXVsdEdyaWRTaXplID0ge1xuICAgIGxhYmVsU2l6ZTogeyB4czogNiwgc206IDYsIG1kOiA2IH0sXG4gICAgdmFsdWVTaXplOiB7IHhzOiAxMiwgc206IDYsIG1kOiA2IH0sXG4gIH07XG4gIGNvbnN0IGRlZmF1bHRDb250YWluZXJTaXplID0geyB4czogMTIsIHNtOiA2LCBtZDogNiB9O1xuICBjb25zdCBzaXplID0gZ3JpZFNpemUgfHwgZGVmYXVsdEdyaWRTaXplO1xuICBjb25zdCBjb250YWluZXIgPSBjb250YWluZXJTaXplIHx8IGRlZmF1bHRDb250YWluZXJTaXplO1xuXG4gIHJldHVybiAoXG4gICAgPEdyaWRcbiAgICAgIHNpemU9e2NvbnRhaW5lcn1cbiAgICAgIHN4PXt7XG4gICAgICAgIGRpc3BsYXk6ICdmbGV4JyxcbiAgICAgICAgZmxleERpcmVjdGlvbjogeyB4czogJ2NvbHVtbicsIHNtOiAncm93JywgbWQ6ICdyb3cnIH0sXG4gICAgICAgICcmOmhvdmVyJzogeyBiZ2NvbG9yOiAnI2VmZWZlZicsIG92ZXJmbG93OiAnaGlkZGVuJyB9LFxuICAgICAgfX1cbiAgICA+XG4gICAgICA8R3JpZFxuICAgICAgICBzaXplPXtzaXplLmxhYmVsU2l6ZX1cbiAgICAgICAgc3g9e3tcbiAgICAgICAgICBwYWRkaW5nOiAnNXB4JyxcbiAgICAgICAgICBmb250U2l6ZTogJzE0cHgnLFxuICAgICAgICAgIHRleHRBbGlnbjogeyB4czogJ2xlZnQnLCBzbTogJ3JpZ2h0JywgbWQ6ICdyaWdodCcgfSxcbiAgICAgICAgICAuLi5sYWJlbFN4LFxuICAgICAgICB9fVxuICAgICAgPlxuICAgICAgICB7bGFiZWx9IDpcbiAgICAgIDwvR3JpZD5cbiAgICAgIDxHcmlkXG4gICAgICAgIHNpemU9e3NpemUudmFsdWVTaXplfVxuICAgICAgICBzeD17eyBwYWRkaW5nOiAnNXB4JywgZGlzcGxheTogJ2ZsZXgnLCBmbGV4V3JhcDogJ3dyYXAnIH19XG4gICAgICA+XG4gICAgICAgIDxUb29sdGlwIHRpdGxlPXt2YWx1ZX0gYXJyb3c+XG4gICAgICAgICAgPFR5cG9ncmFwaHlcbiAgICAgICAgICAgIHN4PXt7XG4gICAgICAgICAgICAgIGZvbnRTaXplOiAnMTRweCcsXG4gICAgICAgICAgICAgIHdvcmRCcmVhazogJ2JyZWFrLXdvcmQnLFxuICAgICAgICAgICAgICBvdmVyZmxvdzogJ2hpZGRlbicsXG4gICAgICAgICAgICAgIGRpc3BsYXk6ICctd2Via2l0LWJveCcsXG4gICAgICAgICAgICAgIHRleHRPdmVyZmxvdzogJ2VsbGlwc2lzJyxcbiAgICAgICAgICAgICAgV2Via2l0TGluZUNsYW1wOiAyLFxuICAgICAgICAgICAgICBXZWJraXRCb3hPcmllbnQ6ICd2ZXJ0aWNhbCcsXG4gICAgICAgICAgICAgIC4uLnZhbHVlU3gsXG4gICAgICAgICAgICAgIGNvbG9yOiAnIzA3OGRlZScsXG4gICAgICAgICAgICB9fVxuICAgICAgICAgID5cbiAgICAgICAgICAgIHt2YWx1ZSA/IHZhbHVlIDogJy0nfVxuICAgICAgICAgIDwvVHlwb2dyYXBoeT5cbiAgICAgICAgPC9Ub29sdGlwPlxuICAgICAgPC9HcmlkPlxuICAgIDwvR3JpZD5cbiAgKTtcbn07XG4iLCAiaW1wb3J0IHR5cGUgeyBQcm9wc1dpdGhDaGlsZHJlbiB9IGZyb20gJ3JlYWN0JztcclxuXHJcbmludGVyZmFjZSBSZW5kZXJJZlByb3BzIHtcclxuICBzaG93OiBib29sZWFuO1xyXG59XHJcblxyXG5leHBvcnQgY29uc3QgUmVuZGVySWYgPSAoe1xyXG4gIHNob3csXHJcbiAgY2hpbGRyZW4sXHJcbn06IFByb3BzV2l0aENoaWxkcmVuPFJlbmRlcklmUHJvcHM+KSA9PiB7XHJcbiAgcmV0dXJuIHNob3cgPyA8PntjaGlsZHJlbn08Lz4gOiBudWxsO1xyXG59O1xyXG4iLCAiaW1wb3J0IHR5cGUgeyBTeFByb3BzLCBUaGVtZSB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xyXG5pbXBvcnQgeyBCb3gsIERpdmlkZXIsIEdyaWQsIFN0YWNrLCBUeXBvZ3JhcGh5IH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XHJcbmltcG9ydCB0eXBlIHsgUHJvcHNXaXRoQ2hpbGRyZW4sIFJlYWN0Tm9kZSB9IGZyb20gJ3JlYWN0JztcclxuaW1wb3J0IHsgbWVtbywgdXNlTWVtbyB9IGZyb20gJ3JlYWN0JztcclxuXHJcbi8vIFNlY3Rpb24gYm94IGNvbmZpZ3VyYXRpb25cclxuZXhwb3J0IGludGVyZmFjZSBTZWN0aW9uQm94UHJvcHMgZXh0ZW5kcyBQcm9wc1dpdGhDaGlsZHJlbiB7XHJcbiAgdGl0bGU6IHN0cmluZztcclxuICBzcGFjaW5nPzogbnVtYmVyO1xyXG4gIGNvbnRhaW5lclN4PzogU3hQcm9wczxUaGVtZT47XHJcbiAgdGl0bGVTeD86IFN4UHJvcHM8VGhlbWU+O1xyXG4gIHZhcmlhbnQ/OiAnZGVmYXVsdCcgfCAnZm9ybScgfCAnaW5mbycgfCAnd2FybmluZycgfCAnZXJyb3InO1xyXG4gIGljb24/OiBSZWFjdE5vZGU7XHJcbiAgYWN0aW9ucz86IFJlYWN0Tm9kZTtcclxuICBjb2xsYXBzaWJsZT86IGJvb2xlYW47XHJcbiAgZGVmYXVsdEV4cGFuZGVkPzogYm9vbGVhbjtcclxufVxyXG5cclxuLy8gVGhlbWUgY29uZmlndXJhdGlvbiBmb3Igc2VjdGlvbiB2YXJpYW50c1xyXG5jb25zdCBnZXRTZWN0aW9uVGhlbWUgPSAodmFyaWFudDogU2VjdGlvbkJveFByb3BzWyd2YXJpYW50J10gPSAnZGVmYXVsdCcpID0+IHtcclxuICBjb25zdCB0aGVtZXMgPSB7XHJcbiAgICBkZWZhdWx0OiB7XHJcbiAgICAgIGJnY29sb3I6ICcjZmFlYmQ3JyxcclxuICAgICAgY29sb3I6ICcjOTI1ZDIxJyxcclxuICAgIH0sXHJcbiAgICBmb3JtOiB7XHJcbiAgICAgIGJnY29sb3I6ICcjY2RjZWQxJyxcclxuICAgICAgY29sb3I6ICdibGFjaycsXHJcbiAgICB9LFxyXG4gICAgaW5mbzoge1xyXG4gICAgICBiZ2NvbG9yOiAnI2UzZjJmZCcsXHJcbiAgICAgIGNvbG9yOiAnIzE5NzZkMicsXHJcbiAgICB9LFxyXG4gICAgd2FybmluZzoge1xyXG4gICAgICBiZ2NvbG9yOiAnI2ZmZjNlMCcsXHJcbiAgICAgIGNvbG9yOiAnI2Y1N2MwMCcsXHJcbiAgICB9LFxyXG4gICAgZXJyb3I6IHtcclxuICAgICAgYmdjb2xvcjogJyNmZmViZWUnLFxyXG4gICAgICBjb2xvcjogJyNkMzJmMmYnLFxyXG4gICAgfSxcclxuICB9O1xyXG5cclxuICByZXR1cm4gdGhlbWVzW3ZhcmlhbnRdO1xyXG59O1xyXG5cclxuLy8gTWVtb2l6ZWQgU2VjdGlvbkJveCBjb21wb25lbnQgZm9yIHBlcmZvcm1hbmNlXHJcbmV4cG9ydCBjb25zdCBTZWN0aW9uQm94ID0gbWVtbzxTZWN0aW9uQm94UHJvcHM+KFxyXG4gICh7XHJcbiAgICB0aXRsZSxcclxuICAgIGNoaWxkcmVuLFxyXG4gICAgc3BhY2luZyA9IDAsXHJcbiAgICBjb250YWluZXJTeCxcclxuICAgIHRpdGxlU3gsXHJcbiAgICB2YXJpYW50ID0gJ2RlZmF1bHQnLFxyXG4gICAgaWNvbixcclxuICAgIGFjdGlvbnMsXHJcbiAgfSkgPT4ge1xyXG4gICAgY29uc3QgdGhlbWVDb2xvcnMgPSB1c2VNZW1vKCgpID0+IGdldFNlY3Rpb25UaGVtZSh2YXJpYW50KSwgW3ZhcmlhbnRdKTtcclxuXHJcbiAgICBjb25zdCBoZWFkZXJTeCA9IHVzZU1lbW8oXHJcbiAgICAgICgpID0+ICh7XHJcbiAgICAgICAgcHg6IDEuNSxcclxuICAgICAgICBweTogMC4xLFxyXG4gICAgICAgIHdpZHRoOiAnZml0LWNvbnRlbnQnLFxyXG4gICAgICAgIC4uLnRoZW1lQ29sb3JzLFxyXG4gICAgICAgIC4uLnRpdGxlU3gsXHJcbiAgICAgIH0pLFxyXG4gICAgICBbdGhlbWVDb2xvcnMsIHRpdGxlU3hdXHJcbiAgICApO1xyXG5cclxuICAgIGNvbnN0IGNvbnRlbnRTeCA9IHVzZU1lbW8oXHJcbiAgICAgICgpID0+ICh7XHJcbiAgICAgICAgcGFkZGluZzogJzE2cHgnLFxyXG4gICAgICAgIC4uLmNvbnRhaW5lclN4LFxyXG4gICAgICB9KSxcclxuICAgICAgW2NvbnRhaW5lclN4XVxyXG4gICAgKTtcclxuXHJcbiAgICByZXR1cm4gKFxyXG4gICAgICA8PlxyXG4gICAgICAgIDxCb3ggc3g9e3sgZGlzcGxheTogJ2ZsZXgnLCBmbGV4RGlyZWN0aW9uOiAnY29sdW1uJywgd2lkdGg6ICcxMDAlJyB9fT5cclxuICAgICAgICAgIDxTdGFja1xyXG4gICAgICAgICAgICBkaXJlY3Rpb249XCJyb3dcIlxyXG4gICAgICAgICAgICBqdXN0aWZ5Q29udGVudD1cInNwYWNlLWJldHdlZW5cIlxyXG4gICAgICAgICAgICBhbGlnbkl0ZW1zPVwiY2VudGVyXCJcclxuICAgICAgICAgICAgc3g9e2hlYWRlclN4fVxyXG4gICAgICAgICAgPlxyXG4gICAgICAgICAgICA8U3RhY2sgZGlyZWN0aW9uPVwicm93XCIgYWxpZ25JdGVtcz1cImNlbnRlclwiIHNwYWNpbmc9ezF9PlxyXG4gICAgICAgICAgICAgIHtpY29ufVxyXG4gICAgICAgICAgICAgIDxUeXBvZ3JhcGh5IHN4PXt7IGZvbnRTaXplOiAnMTVweCcsIGZvbnRXZWlnaHQ6IDQwMCB9fT5cclxuICAgICAgICAgICAgICAgIHt0aXRsZX1cclxuICAgICAgICAgICAgICA8L1R5cG9ncmFwaHk+XHJcbiAgICAgICAgICAgIDwvU3RhY2s+XHJcbiAgICAgICAgICAgIHthY3Rpb25zfVxyXG4gICAgICAgICAgPC9TdGFjaz5cclxuICAgICAgICAgIDxEaXZpZGVyIC8+XHJcbiAgICAgICAgPC9Cb3g+XHJcbiAgICAgICAgPEdyaWQgY29udGFpbmVyIHNwYWNpbmc9e3NwYWNpbmd9IHN4PXtjb250ZW50U3h9PlxyXG4gICAgICAgICAge2NoaWxkcmVufVxyXG4gICAgICAgIDwvR3JpZD5cclxuICAgICAgPC8+XHJcbiAgICApO1xyXG4gIH1cclxuKTtcclxuIiwgImltcG9ydCB7IFRhYkNvbnRleHQgfSBmcm9tICdAbXVpL2xhYic7XHJcbmltcG9ydCB0eXBlIHsgU3hQcm9wcyB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xyXG5pbXBvcnQgeyBCb3gsIFRhYiwgVGFicyB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xyXG5pbXBvcnQgdHlwZSB7IFByb3BzV2l0aENoaWxkcmVuIH0gZnJvbSAncmVhY3QnO1xyXG5pbXBvcnQgUmVhY3QsIHsgdXNlU3RhdGUgfSBmcm9tICdyZWFjdCc7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFRhYkl0ZW0ge1xyXG4gIGxhYmVsOiBzdHJpbmc7XHJcbiAgdmFsdWU6IG51bWJlcjtcclxuICBwZXJtaXNzaW9uPzogYm9vbGVhbjtcclxufVxyXG5cclxuaW50ZXJmYWNlIEN1c3RvbVRhYnNQcm9wcyB7XHJcbiAgdGFiczogVGFiSXRlbVtdO1xyXG4gIGRlZmF1bHRWYWx1ZT86IG51bWJlcjtcclxuICBvblRhYkNoYW5nZT86IChuZXdWYWx1ZTogbnVtYmVyKSA9PiB2b2lkO1xyXG4gIHRhYlN4PzogU3hQcm9wcztcclxuICB0YWJzU3g/OiBTeFByb3BzO1xyXG59XHJcblxyXG5leHBvcnQgY29uc3QgU2ltcGxlVGFicyA9ICh7XHJcbiAgdGFicyxcclxuICBkZWZhdWx0VmFsdWUgPSAxLFxyXG4gIG9uVGFiQ2hhbmdlLFxyXG4gIGNoaWxkcmVuLFxyXG4gIHRhYlN4LFxyXG4gIHRhYnNTeCxcclxufTogQ3VzdG9tVGFic1Byb3BzICYgUHJvcHNXaXRoQ2hpbGRyZW4pID0+IHtcclxuICBjb25zdCBbdmFsdWUsIHNldFZhbHVlXSA9IHVzZVN0YXRlPG51bWJlcj4oZGVmYXVsdFZhbHVlKTtcclxuXHJcbiAgY29uc3QgaGFuZGxlQ2hhbmdlID0gKGV2ZW50OiBSZWFjdC5TeW50aGV0aWNFdmVudCwgbmV3VmFsdWU6IG51bWJlcikgPT4ge1xyXG4gICAgc2V0VmFsdWUobmV3VmFsdWUpO1xyXG4gICAgaWYgKG9uVGFiQ2hhbmdlKSBvblRhYkNoYW5nZShuZXdWYWx1ZSk7XHJcbiAgfTtcclxuXHJcbiAgcmV0dXJuIChcclxuICAgIDxUYWJDb250ZXh0IHZhbHVlPXt2YWx1ZX0+XHJcbiAgICAgIDxCb3ggc3g9e3sgYm9yZGVyQm90dG9tOiAxLCBib3JkZXJDb2xvcjogJ2RpdmlkZXInLCB3aWR0aDogJzEwMCUnIH19PlxyXG4gICAgICAgIDxUYWJzXHJcbiAgICAgICAgICB2YWx1ZT17dmFsdWV9XHJcbiAgICAgICAgICBvbkNoYW5nZT17aGFuZGxlQ2hhbmdlfVxyXG4gICAgICAgICAgc3g9e3sgcHg6IDIsIHB5OiAwLCAuLi50YWJzU3ggfX1cclxuICAgICAgICA+XHJcbiAgICAgICAgICB7dGFicy5tYXAodGFiID0+IChcclxuICAgICAgICAgICAgPFRhYlxyXG4gICAgICAgICAgICAgIGtleT17dGFiLnZhbHVlfVxyXG4gICAgICAgICAgICAgIGxhYmVsPXt0YWIubGFiZWx9XHJcbiAgICAgICAgICAgICAgdmFsdWU9e3RhYi52YWx1ZX1cclxuICAgICAgICAgICAgICBkaXNhYmxlZD17dGFiLnBlcm1pc3Npb24gPT09IGZhbHNlfVxyXG4gICAgICAgICAgICAgIHN4PXt7IGZvbnRTaXplOiAnMXJlbScsIC4uLnRhYlN4IH19XHJcbiAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICApKX1cclxuICAgICAgICA8L1RhYnM+XHJcbiAgICAgIDwvQm94PlxyXG5cclxuICAgICAge2NoaWxkcmVufVxyXG4gICAgPC9UYWJDb250ZXh0PlxyXG4gICk7XHJcbn07XHJcbiIsICJpbXBvcnQgdHlwZSB7IExvYWRpbmdCdXR0b25Qcm9wcyB9IGZyb20gJ0BtdWkvbGFiJztcclxuaW1wb3J0IHsgTG9hZGluZ0J1dHRvbiB9IGZyb20gJ0BtdWkvbGFiJztcclxuaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcclxuXHJcbnR5cGUgU3VibWl0QnV0dG9uUHJvcHMgPSBPbWl0PFxyXG4gIExvYWRpbmdCdXR0b25Qcm9wcyxcclxuICAnY2hpbGRyZW4nIHwgJ3ZhcmlhbnQnIHwgJ2NvbG9yJyB8ICd0eXBlJ1xyXG4+O1xyXG5cclxuZXhwb3J0IGNvbnN0IFN1Ym1pdEJ1dHRvbjogUmVhY3QuRkM8U3VibWl0QnV0dG9uUHJvcHM+ID0gKHtcclxuICBsb2FkaW5nID0gZmFsc2UsXHJcbiAgLi4ucmVzdFxyXG59KSA9PiAoXHJcbiAgPExvYWRpbmdCdXR0b25cclxuICAgIGxvYWRpbmc9e2xvYWRpbmd9XHJcbiAgICB2YXJpYW50PVwiY29udGFpbmVkXCJcclxuICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICB0eXBlPVwic3VibWl0XCJcclxuICAgIHsuLi5yZXN0fVxyXG4gICAgc3g9e3sgZm9udFdlaWdodDogNDAwIH19XHJcbiAgPlxyXG4gICAgU3VibWl0XHJcbiAgPC9Mb2FkaW5nQnV0dG9uPlxyXG4pO1xyXG4iLCAiaW1wb3J0IHR5cGUgUmVhY3QgZnJvbSAncmVhY3QnO1xyXG5pbXBvcnQgeyBmb3J3YXJkUmVmIH0gZnJvbSAncmVhY3QnO1xyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4vLyBTaGFyZWQgdHlwZXNcclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5leHBvcnQgaW50ZXJmYWNlIERhdGFNb2RhbEJ1dHRvbnMge1xyXG4gIG9uU3VibWl0PzogKCkgPT4gdm9pZDtcclxuICBvbkNhbmNlbD86ICgpID0+IHZvaWQ7XHJcbiAgaXNQZW5kaW5nPzogYm9vbGVhbjtcclxuICBpc1N1Y2Nlc3M/OiBib29sZWFuO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIERhdGFNb2RhbENvbXBvbmVudFByb3BzPFREYXRhPiB7XHJcbiAgZGF0YT86IFREYXRhO1xyXG4gIGlzRWRpdGluZz86IGJvb2xlYW47XHJcbiAgcmVmPzogUmVhY3QuUmVmPERhdGFNb2RhbEJ1dHRvbnM+OyAvLyBcdUQ4M0RcdURDNDggcHV0IHJlZiBpbnRvIHByb3BzXHJcbn1cclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuLy8gUHJvamVjdC1zcGVjaWZpYyBIT0NcclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5leHBvcnQgZnVuY3Rpb24gd2l0aERhdGFNb2RhbDxURGF0YT4oXHJcbiAgY29tcG9uZW50OiAoXHJcbiAgICBwcm9wczogRGF0YU1vZGFsQ29tcG9uZW50UHJvcHM8VERhdGE+XHJcbiAgKSA9PiBSZWFjdC5SZWFjdEVsZW1lbnQgfCBudWxsXHJcbikge1xyXG4gIHJldHVybiBmb3J3YXJkUmVmPERhdGFNb2RhbEJ1dHRvbnMsIERhdGFNb2RhbENvbXBvbmVudFByb3BzPFREYXRhPj4oXHJcbiAgICAocHJvcHMsIHJlZikgPT4gY29tcG9uZW50KHsgLi4ucHJvcHMsIHJlZiB9KVxyXG4gICk7XHJcbn1cclxuIiwgImV4cG9ydCBpbnRlcmZhY2UgQ29uZmlnVmFsdWUge1xyXG4gIGFwaUJhc2VVcmw6IHN0cmluZztcclxuICBkZWZhdWx0UGFnZVNpemU6IG51bWJlcjtcclxufVxyXG5cclxuZXhwb3J0IGNvbnN0IENvbmZpZzogQ29uZmlnVmFsdWUgPSB7XHJcbiAgZGVmYXVsdFBhZ2VTaXplOiAyMCxcclxuICBhcGlCYXNlVXJsOiAnaHR0cDovL2xvY2FsaG9zdDo1MTQzJyxcclxuICAvLyBhcGlCYXNlVXJsOiAnaHR0cDovLzE5Mi4xNjguMS4yNDY6NTE0MycsXHJcbn07XHJcblxyXG5leHBvcnQgY29uc3QgZGF0ZVRpbWVQYXR0ZXJucyA9IHtcclxuICBkYXRlVGltZTogJ0REIE1NTSBZWVlZIGg6bW0gQScsIC8vIDE3IEFwciAyMDIyIDEyOjAwIGFtXHJcbiAgZGF0ZTogJ0REIE1NTSBZWVlZJywgLy8gMTcgQXByIDIwMjJcclxuICBtb250aF95ZWFyX3Nob3J0X2Zvcm1hdDogJ01NTSBZWVlZJyxcclxuICBtb250aF95ZWFyX2Z1bGxfZm9ybWF0OiAnTU1NTSBZWVlZJyxcclxuICB5ZWFyOiAnWVlZWScsXHJcbiAgdGltZTogJ2g6bW0gYScsIC8vIDEyOjAwIGFtXHJcbiAgc3BsaXQ6IHtcclxuICAgIGRhdGVUaW1lOiAnREQvTU0vWVlZWSBoOm1tIEEnLCAvLyAxNy8wNC8yMDIyIDEyOjAwIGFtXHJcbiAgICBkYXRlOiAnREQvTU0vWVlZWScsIC8vIDE3LzA0LzIwMjJcclxuICB9LFxyXG4gIHBhcmFtQ2FzZToge1xyXG4gICAgZGF0ZVRpbWU6ICdERC1NTS1ZWVlZIGg6bW0gQScsIC8vIDE3LTA0LTIwMjIgMTI6MDAgYW1cclxuICAgIGRhdGU6ICdERC1NTS1ZWVlZJywgLy8gMTctMDQtMjAyMlxyXG4gICAgZGF0ZVJldmVyc2U6ICdZWVlZLU1NLUREJywgLy8gMjAyMi0wNC0xNyBmb3IgY29tcGFyZSBkYXRlXHJcbiAgICBNb250aFllYXI6ICdNTU0tWVlZWScsXHJcbiAgfSxcclxufTtcclxuIiwgImltcG9ydCB7IHVzZU1lbW8gfSBmcm9tICdyZWFjdCc7XHJcblxyXG5pbXBvcnQgeyBjcmVhdGVBcGlDbGllbnQgfSBmcm9tICcuLi9hcGkvY3JlYXRlQXBpQ2xpZW50JztcclxuaW1wb3J0IHR5cGUgeyBBcGlDbGllbnRDb25maWcgfSBmcm9tICcuLi9hcGkvY3JlYXRlQXBpQ2xpZW50JztcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiB1c2VBcGlDbGllbnQoY29uZmlnOiBBcGlDbGllbnRDb25maWcgPSB7fSkge1xyXG4gIHJldHVybiB1c2VNZW1vKFxyXG4gICAgKCkgPT4gY3JlYXRlQXBpQ2xpZW50KGNvbmZpZyksXHJcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVhY3QtaG9va3MvZXhoYXVzdGl2ZS1kZXBzXHJcbiAgICBbXHJcbiAgICAgIGNvbmZpZy5iYXNlVVJMLFxyXG4gICAgICBjb25maWcudGltZW91dCxcclxuICAgICAgY29uZmlnLmNvcnJlbGF0aW9uSWRQcmVmaXgsXHJcbiAgICAgIGNvbmZpZy5pbmNsdWRlQ29ycmVsYXRpb25JZCxcclxuICAgICAgY29uZmlnLmF1dGhUb2tlbixcclxuICAgICAgY29uZmlnLnJlcXVlc3RJbnRlcmNlcHRvcnMsXHJcbiAgICAgIGNvbmZpZy5yZXNwb25zZUludGVyY2VwdG9ycyxcclxuICAgICAgY29uZmlnLmVycm9ySW50ZXJjZXB0b3JzLFxyXG4gICAgXVxyXG4gICk7XHJcbn1cclxuIiwgImltcG9ydCB0eXBlIHsgVmFsaWRhdGlvbkVycm9ycyB9IGZyb20gJ0BnbndlYnNvZnQvdWknO1xyXG5pbXBvcnQgeyB1c2VDYWxsYmFjayB9IGZyb20gJ3JlYWN0JztcclxuaW1wb3J0IHR5cGUgeyBVc2VGb3JtU2V0RXJyb3IsIEZpZWxkVmFsdWVzLCBQYXRoIH0gZnJvbSAncmVhY3QtaG9vay1mb3JtJztcclxuaW1wb3J0IHsgdG9hc3QgfSBmcm9tICdzb25uZXInO1xyXG5cclxuaW1wb3J0IHR5cGUgeyBBcGlFcnJvciB9IGZyb20gJy4uL2FwaS90eXBlcyc7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFN1Y2Nlc3NNZXNzYWdlIHtcclxuICBjcmVhdGU6IHN0cmluZztcclxuICB1cGRhdGU6IHN0cmluZztcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBFcnJvck1lc3NhZ2Uge1xyXG4gIG5vQ2hhbmdlczogc3RyaW5nO1xyXG4gIGdlbmVyYWw6IHN0cmluZztcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBVc2VGb3JtRXJyb3JIYW5kbGVyT3B0aW9uczxURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcz4ge1xyXG4gIHNldEVycm9yPzogVXNlRm9ybVNldEVycm9yPFRGaWVsZFZhbHVlcz47XHJcbiAgc3VjY2Vzc01lc3NhZ2U/OiBTdWNjZXNzTWVzc2FnZTtcclxuICBlcnJvck1lc3NhZ2U/OiBFcnJvck1lc3NhZ2U7XHJcbn1cclxuXHJcbmV4cG9ydCB0eXBlIFN1Y2Nlc3NIYW5kbGVyID0gKFxyXG4gIGlzRWRpdGluZzogYm9vbGVhbixcclxuICByb3dzQWZmZWN0ZWQ/OiBudW1iZXJcclxuKSA9PiBib29sZWFuO1xyXG5cclxuZXhwb3J0IHR5cGUgRXJyb3JIYW5kbGVyID0gKHByb2Nlc3NlZEVycm9yOiBBcGlFcnJvcikgPT4gdm9pZDtcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgVXNlRm9ybUVycm9ySGFuZGxlclJldHVybiB7XHJcbiAgaGFuZGxlU3VjY2VzczogU3VjY2Vzc0hhbmRsZXI7XHJcbiAgaGFuZGxlRXJyb3I6IEVycm9ySGFuZGxlcjtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBVc2VEZWxldGVIYW5kbGVyT3B0aW9ucyB7XHJcbiAgc3VjY2Vzc01lc3NhZ2U/OiBzdHJpbmc7XHJcbiAgZXJyb3JNZXNzYWdlPzogc3RyaW5nO1xyXG59XHJcblxyXG4vKipcclxuICogSG9vayB0byBoYW5kbGUgQVBJIGVycm9ycyBpbiBmb3JtcyB3aXRoIHN0YW5kYXJkaXplZCBlcnJvciBoYW5kbGluZyBhbmQgdG9hc3QgbWVzc2FnZXNcclxuICovXHJcbmV4cG9ydCBjb25zdCB1c2VGb3JtRXJyb3JIYW5kbGVyID0gPFRGaWVsZFZhbHVlcyBleHRlbmRzIEZpZWxkVmFsdWVzPih7XHJcbiAgc2V0RXJyb3IsXHJcbiAgc3VjY2Vzc01lc3NhZ2UgPSB7XHJcbiAgICBjcmVhdGU6ICdDcmVhdGVkIHN1Y2Nlc3NmdWxseScsXHJcbiAgICB1cGRhdGU6ICdVcGRhdGVkIHN1Y2Nlc3NmdWxseScsXHJcbiAgfSxcclxuICBlcnJvck1lc3NhZ2UgPSB7XHJcbiAgICBub0NoYW5nZXM6ICdObyBjaGFuZ2VzIHdlcmUgbWFkZScsXHJcbiAgICBnZW5lcmFsOiAnRmFpbGVkIHRvIHNhdmUuIFBsZWFzZSB0cnkgYWdhaW4uJyxcclxuICB9LFxyXG59OiBVc2VGb3JtRXJyb3JIYW5kbGVyT3B0aW9uczxURmllbGRWYWx1ZXM+KTogVXNlRm9ybUVycm9ySGFuZGxlclJldHVybiA9PiB7XHJcbiAgY29uc3QgZ2V0RmllbGRFcnJvciA9IHVzZUNhbGxiYWNrKFxyXG4gICAgKFxyXG4gICAgICBmaWVsZHM6IFZhbGlkYXRpb25FcnJvcnMgfCB1bmRlZmluZWQsXHJcbiAgICAgIGZpZWxkTmFtZTogc3RyaW5nXHJcbiAgICApOiBzdHJpbmcgfCB1bmRlZmluZWQgPT4ge1xyXG4gICAgICBpZiAoIWZpZWxkcyB8fCAhZmllbGRzW2ZpZWxkTmFtZV0pIHJldHVybiB1bmRlZmluZWQ7XHJcblxyXG4gICAgICBjb25zdCBmaWVsZEVycm9yID0gZmllbGRzW2ZpZWxkTmFtZV07XHJcblxyXG4gICAgICBpZiAodHlwZW9mIGZpZWxkRXJyb3IgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgcmV0dXJuIGZpZWxkRXJyb3I7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGZpZWxkRXJyb3IpKSB7XHJcbiAgICAgICAgcmV0dXJuIGZpZWxkRXJyb3Iuam9pbignLCAnKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHR5cGVvZiBmaWVsZEVycm9yID09PSAnb2JqZWN0JyAmJiAnbWVzc2FnZScgaW4gZmllbGRFcnJvcikge1xyXG4gICAgICAgIHJldHVybiBmaWVsZEVycm9yLm1lc3NhZ2U7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgICB9LFxyXG4gICAgW11cclxuICApO1xyXG5cclxuICBjb25zdCBoYW5kbGVTdWNjZXNzID0gdXNlQ2FsbGJhY2soXHJcbiAgICAoaXNFZGl0aW5nOiBib29sZWFuLCByb3dzQWZmZWN0ZWQ/OiBudW1iZXIpID0+IHtcclxuICAgICAgaWYgKHJvd3NBZmZlY3RlZCAhPT0gdW5kZWZpbmVkICYmIHJvd3NBZmZlY3RlZCA+IDApIHtcclxuICAgICAgICB0b2FzdC5zdWNjZXNzKFxyXG4gICAgICAgICAgaXNFZGl0aW5nID8gc3VjY2Vzc01lc3NhZ2UudXBkYXRlIDogc3VjY2Vzc01lc3NhZ2UuY3JlYXRlXHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgIH0gZWxzZSBpZiAocm93c0FmZmVjdGVkID09PSAwKSB7XHJcbiAgICAgICAgdG9hc3QuZXJyb3IoZXJyb3JNZXNzYWdlLm5vQ2hhbmdlcyk7XHJcblxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gSWYgcm93c0FmZmVjdGVkIGlzIHVuZGVmaW5lZCwgYXNzdW1lIHN1Y2Nlc3NcclxuICAgICAgdG9hc3Quc3VjY2Vzcyhpc0VkaXRpbmcgPyBzdWNjZXNzTWVzc2FnZS51cGRhdGUgOiBzdWNjZXNzTWVzc2FnZS5jcmVhdGUpO1xyXG5cclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9LFxyXG4gICAgW3N1Y2Nlc3NNZXNzYWdlLCBlcnJvck1lc3NhZ2VdXHJcbiAgKTtcclxuXHJcbiAgY29uc3QgaGFuZGxlRXJyb3IgPSB1c2VDYWxsYmFjayhcclxuICAgIChwcm9jZXNzZWRFcnJvcjogQXBpRXJyb3IpID0+IHtcclxuICAgICAgaWYgKFxyXG4gICAgICAgIHByb2Nlc3NlZEVycm9yLnR5cGUgPT09ICd2YWxpZGF0aW9uX2Vycm9yJyAmJlxyXG4gICAgICAgIHByb2Nlc3NlZEVycm9yLmVycm9ycyAmJlxyXG4gICAgICAgIHNldEVycm9yXHJcbiAgICAgICkge1xyXG4gICAgICAgIC8vIFNldCBmaWVsZC1zcGVjaWZpYyBlcnJvcnMgdXNpbmcgcmVhY3QtaG9vay1mb3JtJ3Mgc2V0RXJyb3IgKG9ubHkgaWYgc2V0RXJyb3IgaXMgcHJvdmlkZWQpXHJcbiAgICAgICAgT2JqZWN0LmtleXMocHJvY2Vzc2VkRXJyb3IuZXJyb3JzKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XHJcbiAgICAgICAgICBjb25zdCBmaWVsZEVycm9yID0gZ2V0RmllbGRFcnJvcihwcm9jZXNzZWRFcnJvci5lcnJvcnMsIGZpZWxkTmFtZSk7XHJcblxyXG4gICAgICAgICAgaWYgKGZpZWxkRXJyb3IpIHtcclxuICAgICAgICAgICAgc2V0RXJyb3IoZmllbGROYW1lIGFzIFBhdGg8VEZpZWxkVmFsdWVzPiwge1xyXG4gICAgICAgICAgICAgIHR5cGU6ICdzZXJ2ZXInLFxyXG4gICAgICAgICAgICAgIG1lc3NhZ2U6IGZpZWxkRXJyb3IsXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICAvLyBTaG93IGdlbmVyYWwgdmFsaWRhdGlvbiBlcnJvciB0b2FzdFxyXG4gICAgICAgIHRvYXN0LmVycm9yKFxyXG4gICAgICAgICAgcHJvY2Vzc2VkRXJyb3IudGl0bGUgfHwgJ1BsZWFzZSBjaGVjayB0aGUgZm9ybSBmb3IgdmFsaWRhdGlvbiBlcnJvcnMnXHJcbiAgICAgICAgKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICAvLyBTaG93IGdlbmVyYWwgZXJyb3IgdG9hc3QgZm9yIG5vbi12YWxpZGF0aW9uIGVycm9ycyBvciB3aGVuIHNldEVycm9yIGlzIG5vdCBhdmFpbGFibGVcclxuICAgICAgICB0b2FzdC5lcnJvcihwcm9jZXNzZWRFcnJvci50aXRsZSB8fCBlcnJvck1lc3NhZ2UuZ2VuZXJhbCk7XHJcbiAgICAgIH1cclxuICAgIH0sXHJcbiAgICBbZXJyb3JNZXNzYWdlLmdlbmVyYWwsIGdldEZpZWxkRXJyb3IsIHNldEVycm9yXVxyXG4gICk7XHJcblxyXG4gIHJldHVybiB7XHJcbiAgICBoYW5kbGVTdWNjZXNzLFxyXG4gICAgaGFuZGxlRXJyb3IsXHJcbiAgfTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBDb252ZW5pZW5jZSBob29rIGZvciBkZWxldGUgb3BlcmF0aW9ucyB0aGF0IGRvbid0IG5lZWQgZm9ybSBmaWVsZCB2YWxpZGF0aW9uXHJcbiAqIFVzZXMgdXNlRm9ybUVycm9ySGFuZGxlciBpbnRlcm5hbGx5IGJ1dCB3aXRoIHNpbXBsaWZpZWQgb3B0aW9uc1xyXG4gKi9cclxuZXhwb3J0IGNvbnN0IHVzZURlbGV0ZUhhbmRsZXIgPSAoe1xyXG4gIHN1Y2Nlc3NNZXNzYWdlID0gJ0RlbGV0ZWQgc3VjY2Vzc2Z1bGx5JyxcclxuICBlcnJvck1lc3NhZ2UgPSAnRmFpbGVkIHRvIGRlbGV0ZS4gUGxlYXNlIHRyeSBhZ2Fpbi4nLFxyXG59OiBVc2VEZWxldGVIYW5kbGVyT3B0aW9ucyA9IHt9KTogVXNlRm9ybUVycm9ySGFuZGxlclJldHVybiA9PiB7XHJcbiAgcmV0dXJuIHVzZUZvcm1FcnJvckhhbmRsZXIoe1xyXG4gICAgc3VjY2Vzc01lc3NhZ2U6IHtcclxuICAgICAgY3JlYXRlOiBzdWNjZXNzTWVzc2FnZSwgLy8gTm90IHVzZWQgZm9yIGRlbGV0ZSwgYnV0IHJlcXVpcmVkIGZvciB0eXBlXHJcbiAgICAgIHVwZGF0ZTogc3VjY2Vzc01lc3NhZ2UsXHJcbiAgICB9LFxyXG4gICAgZXJyb3JNZXNzYWdlOiB7XHJcbiAgICAgIG5vQ2hhbmdlczogJ05vIGNoYW5nZXMgd2VyZSBtYWRlJywgLy8gTm90IHR5cGljYWxseSB1c2VkIGZvciBkZWxldGVcclxuICAgICAgZ2VuZXJhbDogZXJyb3JNZXNzYWdlLFxyXG4gICAgfSxcclxuICAgIC8vIHNldEVycm9yIGlzIG9taXR0ZWQgKHVuZGVmaW5lZCkgZm9yIGRlbGV0ZSBvcGVyYXRpb25zXHJcbiAgfSk7XHJcbn07XHJcbiIsICJpbXBvcnQgdHlwZSB7IFF1ZXJ5Q2xpZW50LCBRdWVyeUtleSB9IGZyb20gJ0B0YW5zdGFjay9yZWFjdC1xdWVyeSc7XHJcbmltcG9ydCB7IHVzZVF1ZXJ5Q2xpZW50IH0gZnJvbSAnQHRhbnN0YWNrL3JlYWN0LXF1ZXJ5JztcclxuaW1wb3J0IHsgdXNlTWVtbyB9IGZyb20gJ3JlYWN0JztcclxuXHJcbi8vIE1pbmltYWwgdHlwZS1zYWZlIGNhY2hlIHV0aWxpdHkgZm9yIHF1ZXJ5IGtleSBmYWN0b3JpZXNcclxuZXhwb3J0IGNsYXNzIENhY2hlVXRpbGl0eSB7XHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBxdWVyeUNsaWVudDogUXVlcnlDbGllbnQpIHt9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCBjYWNoZWQgZGF0YSB1c2luZyBvbmx5IHRoZSBxdWVyeUtleSBmcm9tIHF1ZXJ5IGZhY3RvcnlcclxuICAgKi9cclxuICBnZXRDYWNoZWREYXRhPFQ+KHF1ZXJ5S2V5OiBRdWVyeUtleSk6IFQgfCB1bmRlZmluZWQge1xyXG4gICAgcmV0dXJuIHRoaXMucXVlcnlDbGllbnQuZ2V0UXVlcnlEYXRhPFQ+KHF1ZXJ5S2V5KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCBjYWNoZWQgZGF0YSB3aXRoIHRyYW5zZm9ybWF0aW9uIHVzaW5nIHNlbGVjdCBmdW5jdGlvblxyXG4gICAqL1xyXG4gIGdldENhY2hlZERhdGFXaXRoU2VsZWN0PFQsIFI+KFxyXG4gICAgcXVlcnlLZXk6IFF1ZXJ5S2V5LFxyXG4gICAgc2VsZWN0OiAoZGF0YTogVCkgPT4gUlxyXG4gICk6IFIgfCB1bmRlZmluZWQge1xyXG4gICAgY29uc3QgY2FjaGVkRGF0YSA9IHRoaXMucXVlcnlDbGllbnQuZ2V0UXVlcnlEYXRhPFQ+KHF1ZXJ5S2V5KTtcclxuXHJcbiAgICBpZiAoY2FjaGVkRGF0YSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHNlbGVjdChjYWNoZWREYXRhKTtcclxuICB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiB1c2VDYWNoZVV0aWxpdHkoKTogQ2FjaGVVdGlsaXR5IHtcclxuICBjb25zdCBxdWVyeUNsaWVudCA9IHVzZVF1ZXJ5Q2xpZW50KCk7XHJcblxyXG4gIHJldHVybiB1c2VNZW1vKCgpID0+IG5ldyBDYWNoZVV0aWxpdHkocXVlcnlDbGllbnQpLCBbcXVlcnlDbGllbnRdKTtcclxufVxyXG4iLCAiaW1wb3J0IHR5cGUge1xyXG4gIENvbnRyb2wsXHJcbiAgRGVlcFBhcnRpYWxTa2lwQXJyYXlLZXksXHJcbiAgRmllbGRWYWx1ZXMsXHJcbiAgUGF0aCxcclxuICBQYXRoVmFsdWUsXHJcbn0gZnJvbSAncmVhY3QtaG9vay1mb3JtJztcclxuaW1wb3J0IHsgdXNlV2F0Y2ggfSBmcm9tICdyZWFjdC1ob29rLWZvcm0nO1xyXG5cclxuLyoqXHJcbiAqIENvcmUgd2F0Y2ggZnVuY3Rpb25zIGZvciBSZWFjdCBIb29rIEZvcm1cclxuICogVGhlc2UgYXJlIHRoZSBwcmltYXJ5IGJ1aWxkaW5nIGJsb2NrcyBmb3IgZm9ybSB3YXRjaGluZ1xyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBVdGlsaXR5IHR5cGUgdG8gZW5zdXJlIGFycmF5IGVsZW1lbnRzIGFyZSBhbGwgUGF0aDxUPlxyXG4gKi9cclxuZXhwb3J0IHR5cGUgUGF0aEFycmF5PFQgZXh0ZW5kcyBGaWVsZFZhbHVlcz4gPSBSZWFkb25seUFycmF5PFBhdGg8VD4+O1xyXG5cclxuLyoqXHJcbiAqIEhvb2sgdG8gd2F0Y2ggZW50aXJlIGZvcm0gLSByZXR1cm5zIGFsbCBmb3JtIHZhbHVlc1xyXG4gKi9cclxuZXhwb3J0IGNvbnN0IHVzZVdhdGNoRm9ybSA9IDxURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcz4oXHJcbiAgY29udHJvbDogQ29udHJvbDxURmllbGRWYWx1ZXM+XHJcbik6IERlZXBQYXJ0aWFsU2tpcEFycmF5S2V5PFRGaWVsZFZhbHVlcz4gPT4gdXNlV2F0Y2goeyBjb250cm9sIH0pO1xyXG5cclxuLyoqXHJcbiAqIEhvb2sgdG8gd2F0Y2ggc2luZ2xlIGZpZWxkIGJ5IHBhdGggLSBzdXBwb3J0cyBhbnkgbmVzdGVkIHBhdGhcclxuICovXHJcbmV4cG9ydCBjb25zdCB1c2VXYXRjaEZpZWxkID0gPFxyXG4gIFRGaWVsZFZhbHVlcyBleHRlbmRzIEZpZWxkVmFsdWVzLFxyXG4gIFROYW1lIGV4dGVuZHMgUGF0aDxURmllbGRWYWx1ZXM+LFxyXG4+KFxyXG4gIGNvbnRyb2w6IENvbnRyb2w8VEZpZWxkVmFsdWVzPixcclxuICBuYW1lOiBUTmFtZVxyXG4pOiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZT4gPT4gdXNlV2F0Y2goeyBjb250cm9sLCBuYW1lIH0pO1xyXG5cclxuLyoqXHJcbiAqIEhvb2sgdG8gd2F0Y2ggbXVsdGlwbGUgZmllbGRzIGJ5IHBhdGhzIC0gcmV0dXJucyBhcnJheSBvZiB2YWx1ZXNcclxuICovXHJcbmV4cG9ydCBjb25zdCB1c2VXYXRjaEZpZWxkcyA9IDxcclxuICBURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcyxcclxuICBUTmFtZXMgZXh0ZW5kcyBSZWFkb25seUFycmF5PFBhdGg8VEZpZWxkVmFsdWVzPj4sXHJcbj4oXHJcbiAgY29udHJvbDogQ29udHJvbDxURmllbGRWYWx1ZXM+LFxyXG4gIG5hbWVzOiBUTmFtZXNcclxuKTogQXJyYXk8UGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgVE5hbWVzW251bWJlcl0+PiA9PlxyXG4gIHVzZVdhdGNoKHsgY29udHJvbCwgbmFtZTogbmFtZXMgfSkgYXMgQXJyYXk8XHJcbiAgICBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZXNbbnVtYmVyXT5cclxuICA+O1xyXG4iLCAiaW1wb3J0IHsgdXNlRWZmZWN0LCB1c2VNZW1vLCB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0JztcclxuaW1wb3J0IHR5cGUgeyBDb250cm9sLCBGaWVsZFZhbHVlcywgUGF0aCwgUGF0aFZhbHVlIH0gZnJvbSAncmVhY3QtaG9vay1mb3JtJztcclxuaW1wb3J0IHsgdXNlV2F0Y2ggfSBmcm9tICdyZWFjdC1ob29rLWZvcm0nO1xyXG5cclxuLyoqXHJcbiAqIFV0aWxpdHkgd2F0Y2ggZnVuY3Rpb25zIGZvciBSZWFjdCBIb29rIEZvcm1cclxuICogRW5oYW5jZWQgZnVuY3Rpb25hbGl0eSBmb3Igc3BlY2lmaWMgdXNlIGNhc2VzXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFdhdGNoIGZpZWxkIHdpdGggdHJhbnNmb3JtYXRpb24vc2VsZWN0b3JcclxuICovXHJcbmV4cG9ydCBjb25zdCB1c2VXYXRjaFRyYW5zZm9ybSA9IDxcclxuICBURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcyxcclxuICBUTmFtZSBleHRlbmRzIFBhdGg8VEZpZWxkVmFsdWVzPixcclxuICBUT3V0cHV0LFxyXG4+KFxyXG4gIGNvbnRyb2w6IENvbnRyb2w8VEZpZWxkVmFsdWVzPixcclxuICBuYW1lOiBUTmFtZSxcclxuICB0cmFuc2Zvcm06ICh2YWx1ZTogUGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgVE5hbWU+KSA9PiBUT3V0cHV0XHJcbik6IFRPdXRwdXQgPT4ge1xyXG4gIGNvbnN0IHZhbHVlID0gdXNlV2F0Y2goeyBjb250cm9sLCBuYW1lIH0pO1xyXG5cclxuICByZXR1cm4gdXNlTWVtbygoKSA9PiB0cmFuc2Zvcm0odmFsdWUpLCBbdmFsdWUsIHRyYW5zZm9ybV0pO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFdhdGNoIGZpZWxkIHdpdGggZGVmYXVsdCBmYWxsYmFjayB2YWx1ZVxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IHVzZVdhdGNoRGVmYXVsdCA9IDxcclxuICBURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcyxcclxuICBUTmFtZSBleHRlbmRzIFBhdGg8VEZpZWxkVmFsdWVzPixcclxuPihcclxuICBjb250cm9sOiBDb250cm9sPFRGaWVsZFZhbHVlcz4sXHJcbiAgbmFtZTogVE5hbWUsXHJcbiAgZGVmYXVsdFZhbHVlOiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZT5cclxuKTogUGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgVE5hbWU+ID0+IHtcclxuICBjb25zdCB2YWx1ZSA9IHVzZVdhdGNoKHsgY29udHJvbCwgbmFtZSB9KTtcclxuXHJcbiAgcmV0dXJuIHZhbHVlID8/IGRlZmF1bHRWYWx1ZTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBXYXRjaCBmaWVsZCBhcyBib29sZWFuIHdpdGggZ3VhcmFudGVlZCBib29sZWFuIHJldHVyblxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IHVzZVdhdGNoQm9vbGVhbiA9IDxcclxuICBURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcyxcclxuICBUTmFtZSBleHRlbmRzIFBhdGg8VEZpZWxkVmFsdWVzPixcclxuPihcclxuICBjb250cm9sOiBDb250cm9sPFRGaWVsZFZhbHVlcz4sXHJcbiAgbmFtZTogVE5hbWUsXHJcbiAgZGVmYXVsdFZhbHVlID0gZmFsc2VcclxuKTogYm9vbGVhbiA9PiB7XHJcbiAgY29uc3QgdmFsdWUgPSB1c2VXYXRjaCh7IGNvbnRyb2wsIG5hbWUgfSk7XHJcblxyXG4gIHJldHVybiBCb29sZWFuKHZhbHVlID8/IGRlZmF1bHRWYWx1ZSk7XHJcbn07XHJcblxyXG4vKipcclxuICogV2F0Y2ggbXVsdGlwbGUgZmllbGRzIGFuZCByZXR1cm4gYW4gb2JqZWN0IHdpdGggZmllbGQgcGF0aHMgYXMga2V5c1xyXG4gKi9cclxuZXhwb3J0IGNvbnN0IHVzZVdhdGNoQmF0Y2ggPSA8XHJcbiAgVEZpZWxkVmFsdWVzIGV4dGVuZHMgRmllbGRWYWx1ZXMsXHJcbiAgVEZpZWxkcyBleHRlbmRzIFJlYWRvbmx5QXJyYXk8UGF0aDxURmllbGRWYWx1ZXM+PixcclxuPihcclxuICBjb250cm9sOiBDb250cm9sPFRGaWVsZFZhbHVlcz4sXHJcbiAgZmllbGRzOiBURmllbGRzXHJcbik6IHsgW0sgaW4gVEZpZWxkc1tudW1iZXJdXTogUGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgSz4gfSA9PiB7XHJcbiAgY29uc3QgdmFsdWVzID0gdXNlV2F0Y2goeyBjb250cm9sLCBuYW1lOiBmaWVsZHMgfSk7XHJcblxyXG4gIHJldHVybiB1c2VNZW1vKCgpID0+IHtcclxuICAgIGNvbnN0IHJlc3VsdCA9IHt9IGFzIHsgW0sgaW4gVEZpZWxkc1tudW1iZXJdXTogUGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgSz4gfTtcclxuXHJcbiAgICBmaWVsZHMuZm9yRWFjaCgoZmllbGQsIGluZGV4KSA9PiB7XHJcbiAgICAgIHJlc3VsdFtmaWVsZCBhcyBURmllbGRzW251bWJlcl1dID0gdmFsdWVzW2luZGV4XTtcclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfSwgW3ZhbHVlcywgZmllbGRzXSk7XHJcbn07XHJcblxyXG4vKipcclxuICogV2F0Y2ggZmllbGQgY29uZGl0aW9uYWxseSBiYXNlZCBvbiBib29sZWFuIGZsYWdcclxuICovXHJcbmV4cG9ydCBjb25zdCB1c2VXYXRjaENvbmRpdGlvbmFsID0gPFxyXG4gIFRGaWVsZFZhbHVlcyBleHRlbmRzIEZpZWxkVmFsdWVzLFxyXG4gIFROYW1lIGV4dGVuZHMgUGF0aDxURmllbGRWYWx1ZXM+LFxyXG4+KFxyXG4gIGNvbnRyb2w6IENvbnRyb2w8VEZpZWxkVmFsdWVzPixcclxuICBuYW1lOiBUTmFtZSxcclxuICBzaG91bGRXYXRjaDogYm9vbGVhbixcclxuICBmYWxsYmFjaz86IFBhdGhWYWx1ZTxURmllbGRWYWx1ZXMsIFROYW1lPlxyXG4pOiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZT4gfCB1bmRlZmluZWQgPT4ge1xyXG4gIGNvbnN0IGFjdGl2ZVZhbHVlID0gdXNlV2F0Y2goe1xyXG4gICAgY29udHJvbCxcclxuICAgIG5hbWUsXHJcbiAgICBkaXNhYmxlZDogIXNob3VsZFdhdGNoLFxyXG4gIH0pO1xyXG5cclxuICByZXR1cm4gc2hvdWxkV2F0Y2ggPyBhY3RpdmVWYWx1ZSA6IGZhbGxiYWNrO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFdhdGNoIGZpZWxkIHdpdGggZGVib3VuY2VkIHVwZGF0ZXNcclxuICovXHJcbmV4cG9ydCBjb25zdCB1c2VXYXRjaERlYm91bmNlZCA9IDxcclxuICBURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcyxcclxuICBUTmFtZSBleHRlbmRzIFBhdGg8VEZpZWxkVmFsdWVzPixcclxuPihcclxuICBjb250cm9sOiBDb250cm9sPFRGaWVsZFZhbHVlcz4sXHJcbiAgbmFtZTogVE5hbWUsXHJcbiAgZGVsYXkgPSAzMDBcclxuKTogUGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgVE5hbWU+ID0+IHtcclxuICBjb25zdCB2YWx1ZSA9IHVzZVdhdGNoKHsgY29udHJvbCwgbmFtZSB9KTtcclxuICBjb25zdCBbZGVib3VuY2VkVmFsdWUsIHNldERlYm91bmNlZFZhbHVlXSA9XHJcbiAgICB1c2VTdGF0ZTxQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZT4+KHZhbHVlKTtcclxuXHJcbiAgdXNlRWZmZWN0KCgpID0+IHtcclxuICAgIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgIHNldERlYm91bmNlZFZhbHVlKHZhbHVlKTtcclxuICAgIH0sIGRlbGF5KTtcclxuXHJcbiAgICByZXR1cm4gKCkgPT4gY2xlYXJUaW1lb3V0KHRpbWVyKTtcclxuICB9LCBbdmFsdWUsIGRlbGF5XSk7XHJcblxyXG4gIHJldHVybiBkZWJvdW5jZWRWYWx1ZTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBXYXRjaCBmaWVsZCB3aXRoIG1lbW9pemVkIHNlbGVjdG9yIGZ1bmN0aW9uXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgdXNlV2F0Y2hTZWxlY3RvciA9IDxcclxuICBURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcyxcclxuICBUTmFtZSBleHRlbmRzIFBhdGg8VEZpZWxkVmFsdWVzPixcclxuICBUT3V0cHV0LFxyXG4+KFxyXG4gIGNvbnRyb2w6IENvbnRyb2w8VEZpZWxkVmFsdWVzPixcclxuICBuYW1lOiBUTmFtZSxcclxuICBzZWxlY3RvcjogKHZhbHVlOiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZT4pID0+IFRPdXRwdXQsXHJcbiAgZGVwczogUmVhY3QuRGVwZW5kZW5jeUxpc3QgPSBbXVxyXG4pOiBUT3V0cHV0ID0+IHtcclxuICBjb25zdCB2YWx1ZSA9IHVzZVdhdGNoKHsgY29udHJvbCwgbmFtZSB9KTtcclxuXHJcbiAgcmV0dXJuIHVzZU1lbW8oXHJcbiAgICAoKSA9PiBzZWxlY3Rvcih2YWx1ZSksXHJcbiAgICBbdmFsdWUsIHNlbGVjdG9yLCAuLi5kZXBzXSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHJlYWN0LWhvb2tzL2V4aGF1c3RpdmUtZGVwc1xyXG4gICk7XHJcbn07XHJcbiIsICIvKipcclxuICogRW5oYW5jZWQgVHlwZVNjcmlwdCB1dGlsaXRpZXMgZm9yIFJlYWN0IEhvb2sgRm9ybSdzIHVzZVdhdGNoXHJcbiAqXHJcbiAqIFRoaXMgbW9kdWxlIHByb3ZpZGVzIGEgY29tcHJlaGVuc2l2ZSBzZXQgb2YgdHlwZS1zYWZlIHdhdGNoIGZ1bmN0aW9uc1xyXG4gKiB3aXRoIGJldHRlciBlcmdvbm9taWNzIGFuZCBhZGRpdGlvbmFsIGZ1bmN0aW9uYWxpdHkuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIGBgYHR5cGVzY3JpcHRcclxuICogaW1wb3J0IHsgdXNlV2F0Y2hGaWVsZCwgdXNlV2F0Y2hCb29sZWFuLCB0eXBlZFdhdGNoIH0gZnJvbSAnc3JjL3V0aWxzL3dhdGNoJztcclxuICpcclxuICogLy8gRGlyZWN0IHVzYWdlIChpbnNpZGUgUmVhY3QgY29tcG9uZW50cylcclxuICogY29uc3QgZW1haWwgPSB1c2VXYXRjaEZpZWxkKGNvbnRyb2wsICd1c2VyLmVtYWlsJyk7XHJcbiAqIGNvbnN0IGlzQWRtaW4gPSB1c2VXYXRjaEJvb2xlYW4oY29udHJvbCwgJ3VzZXIuaXNBZG1pbicpO1xyXG4gKlxyXG4gKiAvLyBPYmplY3QtYmFzZWQgdXNhZ2UgKGluc2lkZSBSZWFjdCBjb21wb25lbnRzKVxyXG4gKiBjb25zdCBlbWFpbCA9IHR5cGVkV2F0Y2guZmllbGQoY29udHJvbCwgJ3VzZXIuZW1haWwnKTtcclxuICogY29uc3QgaXNBZG1pbiA9IHR5cGVkV2F0Y2guYm9vbGVhbihjb250cm9sLCAndXNlci5pc0FkbWluJyk7XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbi8vIENvcmUgZnVuY3Rpb25zXHJcbmV4cG9ydCB7IHVzZVdhdGNoRmllbGQsIHVzZVdhdGNoRmllbGRzLCB1c2VXYXRjaEZvcm0gfSBmcm9tICcuL2NvcmUnO1xyXG5cclxuLy8gVXRpbGl0eSBmdW5jdGlvbnNcclxuZXhwb3J0IHtcclxuICB1c2VXYXRjaEJhdGNoLFxyXG4gIHVzZVdhdGNoQm9vbGVhbixcclxuICB1c2VXYXRjaENvbmRpdGlvbmFsLFxyXG4gIHVzZVdhdGNoRGVib3VuY2VkLFxyXG4gIHVzZVdhdGNoRGVmYXVsdCxcclxuICB1c2VXYXRjaFNlbGVjdG9yLFxyXG4gIHVzZVdhdGNoVHJhbnNmb3JtLFxyXG59IGZyb20gJy4vdXRpbGl0aWVzJztcclxuXHJcbmV4cG9ydCB0eXBlIHsgUGF0aEFycmF5IH0gZnJvbSAnLi9jb3JlJztcclxuXHJcbi8vIEltcG9ydCBhbGwgZnVuY3Rpb25zIGZvciBkZWZhdWx0IGV4cG9ydFxyXG5pbXBvcnQgeyB1c2VXYXRjaEZpZWxkLCB1c2VXYXRjaEZpZWxkcywgdXNlV2F0Y2hGb3JtIH0gZnJvbSAnLi9jb3JlJztcclxuaW1wb3J0IHtcclxuICB1c2VXYXRjaEJhdGNoLFxyXG4gIHVzZVdhdGNoQm9vbGVhbixcclxuICB1c2VXYXRjaENvbmRpdGlvbmFsLFxyXG4gIHVzZVdhdGNoRGVib3VuY2VkLFxyXG4gIHVzZVdhdGNoRGVmYXVsdCxcclxuICB1c2VXYXRjaFNlbGVjdG9yLFxyXG4gIHVzZVdhdGNoVHJhbnNmb3JtLFxyXG59IGZyb20gJy4vdXRpbGl0aWVzJztcclxuXHJcbi8qKlxyXG4gKiBPcmdhbml6ZWQgdXRpbGl0aWVzIGJ5IHVzZSBjYXNlXHJcbiAqIFByb3ZpZGVzIGEgY29udmVuaWVudCBvYmplY3QtYmFzZWQgQVBJIGZvciBhbGwgd2F0Y2ggZnVuY3Rpb25zXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgdHlwZWRXYXRjaCA9IHtcclxuICAvLyA9PT0gQ09SRSBGVU5DVElPTlMgPT09XHJcbiAgLyoqIFdhdGNoIGVudGlyZSBmb3JtICovXHJcbiAgZm9ybTogdXNlV2F0Y2hGb3JtLFxyXG4gIC8qKiBXYXRjaCBzaW5nbGUgZmllbGQgKi9cclxuICBmaWVsZDogdXNlV2F0Y2hGaWVsZCxcclxuICAvKiogV2F0Y2ggbXVsdGlwbGUgZmllbGRzICovXHJcbiAgZmllbGRzOiB1c2VXYXRjaEZpZWxkcyxcclxuXHJcbiAgLy8gPT09IFVUSUxJVFkgRlVOQ1RJT05TID09PVxyXG4gIC8qKiBXYXRjaCB3aXRoIHRyYW5zZm9ybWF0aW9uICovXHJcbiAgdHJhbnNmb3JtOiB1c2VXYXRjaFRyYW5zZm9ybSxcclxuICAvKiogV2F0Y2ggd2l0aCBkZWZhdWx0IHZhbHVlICovXHJcbiAgd2l0aERlZmF1bHQ6IHVzZVdhdGNoRGVmYXVsdCxcclxuICAvKiogV2F0Y2ggYXMgYm9vbGVhbiAqL1xyXG4gIGJvb2xlYW46IHVzZVdhdGNoQm9vbGVhbixcclxuICAvKiogV2F0Y2ggbXVsdGlwbGUgd2l0aCBjdXN0b20ga2V5cyAqL1xyXG4gIGJhdGNoOiB1c2VXYXRjaEJhdGNoLFxyXG4gIC8qKiBXYXRjaCBjb25kaXRpb25hbGx5ICovXHJcbiAgY29uZGl0aW9uYWw6IHVzZVdhdGNoQ29uZGl0aW9uYWwsXHJcbiAgLyoqIFdhdGNoIHdpdGggZGVib3VuY2luZyAqL1xyXG4gIGRlYm91bmNlZDogdXNlV2F0Y2hEZWJvdW5jZWQsXHJcbiAgLyoqIFdhdGNoIHdpdGggc2VsZWN0b3IgKi9cclxuICBzZWxlY3RvcjogdXNlV2F0Y2hTZWxlY3RvcixcclxufSBhcyBjb25zdDtcclxuIiwgImV4cG9ydCBjb25zdCBjYWxjdWxhdGVGaWx0ZXJDb3VudCA9IChtb2RlbDogb2JqZWN0KTogbnVtYmVyID0+XHJcbiAgT2JqZWN0LnZhbHVlcyhtb2RlbCkuZmlsdGVyKFxyXG4gICAgdiA9PiB2ICE9PSBudWxsICYmIHYgIT09IHVuZGVmaW5lZCAmJiBTdHJpbmcodikudHJpbSgpICE9PSAnJ1xyXG4gICkubGVuZ3RoO1xyXG4iLCAiaW1wb3J0IHR5cGUgeyBEYXlqcywgT3BVbml0VHlwZSB9IGZyb20gJ2RheWpzJztcclxuaW1wb3J0IGRheWpzIGZyb20gJ2RheWpzJztcclxuaW1wb3J0IGR1cmF0aW9uIGZyb20gJ2RheWpzL3BsdWdpbi9kdXJhdGlvbic7XHJcbmltcG9ydCByZWxhdGl2ZVRpbWUgZnJvbSAnZGF5anMvcGx1Z2luL3JlbGF0aXZlVGltZSc7XHJcblxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4vKipcclxuICogQERvY3NcclxuICogaHR0cHM6Ly9kYXkuanMub3JnL2RvY3MvZW4vZGlzcGxheS9mb3JtYXRcclxuICovXHJcblxyXG4vKipcclxuICogRGVmYXVsdCB0aW1lem9uZXNcclxuICogaHR0cHM6Ly9kYXkuanMub3JnL2RvY3MvZW4vdGltZXpvbmUvc2V0LWRlZmF1bHQtdGltZXpvbmUjZG9jc05hdlxyXG4gKlxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBVVENcclxuICogaHR0cHM6Ly9kYXkuanMub3JnL2RvY3MvZW4vcGx1Z2luL3V0Y1xyXG4gKiBAaW5zdGFsbFxyXG4gKiBpbXBvcnQgdXRjIGZyb20gJ2RheWpzL3BsdWdpbi91dGMnO1xyXG4gKiBkYXlqcy5leHRlbmQodXRjKTtcclxuICogQHVzYWdlXHJcbiAqIGRheWpzKCkudXRjKCkuZm9ybWF0KClcclxuICpcclxuICovXHJcblxyXG5kYXlqcy5leHRlbmQoZHVyYXRpb24pO1xyXG5kYXlqcy5leHRlbmQocmVsYXRpdmVUaW1lKTtcclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbmV4cG9ydCB0eXBlIERhdGVQaWNrZXJGb3JtYXQgPVxyXG4gIHwgRGF5anNcclxuICB8IERhdGVcclxuICB8IHN0cmluZ1xyXG4gIHwgbnVtYmVyXHJcbiAgfCBudWxsXHJcbiAgfCB1bmRlZmluZWQ7XHJcblxyXG5leHBvcnQgY29uc3QgZm9ybWF0UGF0dGVybnMgPSB7XHJcbiAgZGF0ZVRpbWU6ICdERCBNTU0gWVlZWSBoOm1tIEEnLCAvLyAxNyBBcHIgMjAyMiAxMjowMCBhbVxyXG4gIGRhdGU6ICdERCBNTU0gWVlZWScsIC8vIDE3IEFwciAyMDIyXHJcbiAgbW9udGhfeWVhcl9zaG9ydF9mb3JtYXQ6ICdNTU0gWVlZWScsXHJcbiAgbW9udGhfeWVhcl9mdWxsX2Zvcm1hdDogJ01NTU0gWVlZWScsXHJcbiAgeWVhcjogJ1lZWVknLFxyXG4gIHRpbWU6ICdoOm1tIGEnLCAvLyAxMjowMCBhbVxyXG4gIHNwbGl0OiB7XHJcbiAgICBkYXRlVGltZTogJ0REL01NL1lZWVkgaDptbSBBJywgLy8gMTcvMDQvMjAyMiAxMjowMCBhbVxyXG4gICAgZGF0ZTogJ0REL01NL1lZWVknLCAvLyAxNy8wNC8yMDIyXHJcbiAgfSxcclxuICBwYXJhbUNhc2U6IHtcclxuICAgIGRhdGVUaW1lOiAnREQtTU0tWVlZWSBoOm1tIEEnLCAvLyAxNy0wNC0yMDIyIDEyOjAwIGFtXHJcbiAgICBkYXRlOiAnREQtTU0tWVlZWScsIC8vIDE3LTA0LTIwMjJcclxuICAgIGRhdGVSZXZlcnNlOiAnWVlZWS1NTS1ERCcsIC8vIDIwMjItMDQtMTcgZm9yIGNvbXBhcmUgZGF0ZVxyXG4gICAgTW9udGhZZWFyOiAnTU1NLVlZWVknLFxyXG4gIH0sXHJcbn07XHJcblxyXG5jb25zdCBpc1ZhbGlkRGF0ZSA9IChkYXRlOiBEYXRlUGlja2VyRm9ybWF0KSA9PlxyXG4gIGRhdGUgIT09IG51bGwgJiYgZGF0ZSAhPT0gdW5kZWZpbmVkICYmIGRheWpzKGRhdGUpLmlzVmFsaWQoKTtcclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiB0b2RheSh0ZW1wbGF0ZT86IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgcmV0dXJuIGRheWpzKG5ldyBEYXRlKCkpLnN0YXJ0T2YoJ2RheScpLmZvcm1hdCh0ZW1wbGF0ZSk7XHJcbn1cclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbi8qKlxyXG4gKiBAb3V0cHV0IDE3IEFwciAyMDIyIDEyOjAwIGFtXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZkRhdGVUaW1lKGRhdGU6IERhdGVQaWNrZXJGb3JtYXQsIHRlbXBsYXRlPzogc3RyaW5nKTogc3RyaW5nIHtcclxuICBpZiAoIWlzVmFsaWREYXRlKGRhdGUpKSB7XHJcbiAgICByZXR1cm4gJ0ludmFsaWQgZGF0ZSc7XHJcbiAgfVxyXG5cclxuICByZXR1cm4gZGF5anMoZGF0ZSkuZm9ybWF0KHRlbXBsYXRlID8/IGZvcm1hdFBhdHRlcm5zLmRhdGVUaW1lKTtcclxufVxyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuLyoqXHJcbiAqIEBvdXRwdXQgMTcgQXByIDIwMjJcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmRGF0ZShkYXRlOiBEYXRlUGlja2VyRm9ybWF0LCB0ZW1wbGF0ZT86IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgaWYgKCFpc1ZhbGlkRGF0ZShkYXRlKSkge1xyXG4gICAgcmV0dXJuICdJbnZhbGlkIGRhdGUnO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIGRheWpzKGRhdGUpLmZvcm1hdCh0ZW1wbGF0ZSA/PyBmb3JtYXRQYXR0ZXJucy5kYXRlKTtcclxufVxyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuLyoqXHJcbiAqIEBvdXRwdXQgMTI6MDAgYW1cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmVGltZShkYXRlOiBEYXRlUGlja2VyRm9ybWF0LCB0ZW1wbGF0ZT86IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgaWYgKCFpc1ZhbGlkRGF0ZShkYXRlKSkge1xyXG4gICAgcmV0dXJuICdJbnZhbGlkIGRhdGUnO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIGRheWpzKGRhdGUpLmZvcm1hdCh0ZW1wbGF0ZSA/PyBmb3JtYXRQYXR0ZXJucy50aW1lKTtcclxufVxyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuLyoqXHJcbiAqIEBvdXRwdXQgMTcxMzI1MDEwMFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGZUaW1lc3RhbXAoZGF0ZTogRGF0ZVBpY2tlckZvcm1hdCk6IG51bWJlciB8ICdJbnZhbGlkIGRhdGUnIHtcclxuICBpZiAoIWlzVmFsaWREYXRlKGRhdGUpKSB7XHJcbiAgICByZXR1cm4gJ0ludmFsaWQgZGF0ZSc7XHJcbiAgfVxyXG5cclxuICByZXR1cm4gZGF5anMoZGF0ZSkudmFsdWVPZigpO1xyXG59XHJcblxyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4vKipcclxuICogQG91dHB1dCBhIGZldyBzZWNvbmRzLCAyIHllYXJzXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZlRvTm93KGRhdGU6IERhdGVQaWNrZXJGb3JtYXQpOiBzdHJpbmcge1xyXG4gIGlmICghaXNWYWxpZERhdGUoZGF0ZSkpIHtcclxuICAgIHJldHVybiAnSW52YWxpZCBkYXRlJztcclxuICB9XHJcblxyXG4gIHJldHVybiBkYXlqcyhkYXRlKS50b05vdyh0cnVlKTtcclxufVxyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuLyoqXHJcbiAqIEBvdXRwdXQgYm9vbGVhblxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGZJc0JldHdlZW4oXHJcbiAgaW5wdXREYXRlOiBEYXRlUGlja2VyRm9ybWF0LFxyXG4gIHN0YXJ0RGF0ZTogRGF0ZVBpY2tlckZvcm1hdCxcclxuICBlbmREYXRlOiBEYXRlUGlja2VyRm9ybWF0XHJcbik6IGJvb2xlYW4ge1xyXG4gIGlmIChcclxuICAgICFpc1ZhbGlkRGF0ZShpbnB1dERhdGUpIHx8XHJcbiAgICAhaXNWYWxpZERhdGUoc3RhcnREYXRlKSB8fFxyXG4gICAgIWlzVmFsaWREYXRlKGVuZERhdGUpXHJcbiAgKSB7XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBjb25zdCBmb3JtYXR0ZWRJbnB1dERhdGUgPSBmVGltZXN0YW1wKGlucHV0RGF0ZSk7XHJcbiAgY29uc3QgZm9ybWF0dGVkU3RhcnREYXRlID0gZlRpbWVzdGFtcChzdGFydERhdGUpO1xyXG4gIGNvbnN0IGZvcm1hdHRlZEVuZERhdGUgPSBmVGltZXN0YW1wKGVuZERhdGUpO1xyXG5cclxuICBpZiAoXHJcbiAgICBmb3JtYXR0ZWRJbnB1dERhdGUgPT09ICdJbnZhbGlkIGRhdGUnIHx8XHJcbiAgICBmb3JtYXR0ZWRTdGFydERhdGUgPT09ICdJbnZhbGlkIGRhdGUnIHx8XHJcbiAgICBmb3JtYXR0ZWRFbmREYXRlID09PSAnSW52YWxpZCBkYXRlJ1xyXG4gICkge1xyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIChcclxuICAgIGZvcm1hdHRlZElucHV0RGF0ZSA+PSBmb3JtYXR0ZWRTdGFydERhdGUgJiZcclxuICAgIGZvcm1hdHRlZElucHV0RGF0ZSA8PSBmb3JtYXR0ZWRFbmREYXRlXHJcbiAgKTtcclxufVxyXG5cclxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuLyoqXHJcbiAqIEBvdXRwdXQgYm9vbGVhblxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGZJc0FmdGVyKFxyXG4gIHN0YXJ0RGF0ZTogRGF0ZVBpY2tlckZvcm1hdCxcclxuICBlbmREYXRlOiBEYXRlUGlja2VyRm9ybWF0XHJcbik6IGJvb2xlYW4ge1xyXG4gIGlmICghaXNWYWxpZERhdGUoc3RhcnREYXRlKSB8fCAhaXNWYWxpZERhdGUoZW5kRGF0ZSkpIHtcclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIHJldHVybiBkYXlqcyhzdGFydERhdGUpLmlzQWZ0ZXIoZW5kRGF0ZSk7XHJcbn1cclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbi8qKlxyXG4gKiBAb3V0cHV0IGJvb2xlYW5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmSXNTYW1lKFxyXG4gIHN0YXJ0RGF0ZTogRGF0ZVBpY2tlckZvcm1hdCxcclxuICBlbmREYXRlOiBEYXRlUGlja2VyRm9ybWF0LFxyXG4gIHVuaXRUb0NvbXBhcmU/OiBPcFVuaXRUeXBlXHJcbik6IGJvb2xlYW4ge1xyXG4gIGlmICghaXNWYWxpZERhdGUoc3RhcnREYXRlKSB8fCAhaXNWYWxpZERhdGUoZW5kRGF0ZSkpIHtcclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIHJldHVybiBkYXlqcyhzdGFydERhdGUpLmlzU2FtZShlbmREYXRlLCB1bml0VG9Db21wYXJlID8/ICd5ZWFyJyk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAb3V0cHV0XHJcbiAqIFNhbWUgZGF5OiAyNiBBcHIgMjAyNFxyXG4gKiBTYW1lIG1vbnRoOiAyNSAtIDI2IEFwciAyMDI0XHJcbiAqIFNhbWUgbW9udGg6IDI1IC0gMjYgQXByIDIwMjRcclxuICogU2FtZSB5ZWFyOiAyNSBBcHIgLSAyNiBNYXkgMjAyNFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGZEYXRlUmFuZ2VTaG9ydExhYmVsKFxyXG4gIHN0YXJ0RGF0ZTogRGF0ZVBpY2tlckZvcm1hdCxcclxuICBlbmREYXRlOiBEYXRlUGlja2VyRm9ybWF0LFxyXG4gIGluaXRpYWw/OiBib29sZWFuXHJcbik6IHN0cmluZyB7XHJcbiAgaWYgKFxyXG4gICAgIWlzVmFsaWREYXRlKHN0YXJ0RGF0ZSkgfHxcclxuICAgICFpc1ZhbGlkRGF0ZShlbmREYXRlKSB8fFxyXG4gICAgZklzQWZ0ZXIoc3RhcnREYXRlLCBlbmREYXRlKVxyXG4gICkge1xyXG4gICAgcmV0dXJuICdJbnZhbGlkIGRhdGUnO1xyXG4gIH1cclxuXHJcbiAgbGV0IGxhYmVsID0gYCR7ZkRhdGUoc3RhcnREYXRlKX0gLSAke2ZEYXRlKGVuZERhdGUpfWA7XHJcblxyXG4gIGlmIChpbml0aWFsKSB7XHJcbiAgICByZXR1cm4gbGFiZWw7XHJcbiAgfVxyXG5cclxuICBjb25zdCBpc1NhbWVZZWFyID0gZklzU2FtZShzdGFydERhdGUsIGVuZERhdGUsICd5ZWFyJyk7XHJcbiAgY29uc3QgaXNTYW1lTW9udGggPSBmSXNTYW1lKHN0YXJ0RGF0ZSwgZW5kRGF0ZSwgJ21vbnRoJyk7XHJcbiAgY29uc3QgaXNTYW1lRGF5ID0gZklzU2FtZShzdGFydERhdGUsIGVuZERhdGUsICdkYXknKTtcclxuXHJcbiAgaWYgKGlzU2FtZVllYXIgJiYgIWlzU2FtZU1vbnRoKSB7XHJcbiAgICBsYWJlbCA9IGAke2ZEYXRlKHN0YXJ0RGF0ZSwgJ0REIE1NTScpfSAtICR7ZkRhdGUoZW5kRGF0ZSl9YDtcclxuICB9IGVsc2UgaWYgKGlzU2FtZVllYXIgJiYgaXNTYW1lTW9udGggJiYgIWlzU2FtZURheSkge1xyXG4gICAgbGFiZWwgPSBgJHtmRGF0ZShzdGFydERhdGUsICdERCcpfSAtICR7ZkRhdGUoZW5kRGF0ZSl9YDtcclxuICB9IGVsc2UgaWYgKGlzU2FtZVllYXIgJiYgaXNTYW1lTW9udGggJiYgaXNTYW1lRGF5KSB7XHJcbiAgICBsYWJlbCA9IGAke2ZEYXRlKGVuZERhdGUpfWA7XHJcbiAgfVxyXG5cclxuICByZXR1cm4gbGFiZWw7XHJcbn1cclxuXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbi8qKlxyXG4gKiBAb3V0cHV0IDIwMjQtMDUtMjhUMDU6NTU6MzErMDA6MDBcclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgRHVyYXRpb25Qcm9wcyB7XHJcbiAgeWVhcnM/OiBudW1iZXI7XHJcbiAgbW9udGhzPzogbnVtYmVyO1xyXG4gIGRheXM/OiBudW1iZXI7XHJcbiAgaG91cnM/OiBudW1iZXI7XHJcbiAgbWludXRlcz86IG51bWJlcjtcclxuICBzZWNvbmRzPzogbnVtYmVyO1xyXG4gIG1pbGxpc2Vjb25kcz86IG51bWJlcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGZBZGQoe1xyXG4gIHllYXJzID0gMCxcclxuICBtb250aHMgPSAwLFxyXG4gIGRheXMgPSAwLFxyXG4gIGhvdXJzID0gMCxcclxuICBtaW51dGVzID0gMCxcclxuICBzZWNvbmRzID0gMCxcclxuICBtaWxsaXNlY29uZHMgPSAwLFxyXG59OiBEdXJhdGlvblByb3BzKSB7XHJcbiAgY29uc3QgcmVzdWx0ID0gZGF5anMoKVxyXG4gICAgLmFkZChcclxuICAgICAgZGF5anMuZHVyYXRpb24oe1xyXG4gICAgICAgIHllYXJzLFxyXG4gICAgICAgIG1vbnRocyxcclxuICAgICAgICBkYXlzLFxyXG4gICAgICAgIGhvdXJzLFxyXG4gICAgICAgIG1pbnV0ZXMsXHJcbiAgICAgICAgc2Vjb25kcyxcclxuICAgICAgICBtaWxsaXNlY29uZHMsXHJcbiAgICAgIH0pXHJcbiAgICApXHJcbiAgICAuZm9ybWF0KCk7XHJcblxyXG4gIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAb3V0cHV0IDIwMjQtMDUtMjhUMDU6NTU6MzErMDA6MDBcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBmU3ViKHtcclxuICB5ZWFycyA9IDAsXHJcbiAgbW9udGhzID0gMCxcclxuICBkYXlzID0gMCxcclxuICBob3VycyA9IDAsXHJcbiAgbWludXRlcyA9IDAsXHJcbiAgc2Vjb25kcyA9IDAsXHJcbiAgbWlsbGlzZWNvbmRzID0gMCxcclxufTogRHVyYXRpb25Qcm9wcykge1xyXG4gIGNvbnN0IHJlc3VsdCA9IGRheWpzKClcclxuICAgIC5zdWJ0cmFjdChcclxuICAgICAgZGF5anMuZHVyYXRpb24oe1xyXG4gICAgICAgIHllYXJzLFxyXG4gICAgICAgIG1vbnRocyxcclxuICAgICAgICBkYXlzLFxyXG4gICAgICAgIGhvdXJzLFxyXG4gICAgICAgIG1pbnV0ZXMsXHJcbiAgICAgICAgc2Vjb25kcyxcclxuICAgICAgICBtaWxsaXNlY29uZHMsXHJcbiAgICAgIH0pXHJcbiAgICApXHJcbiAgICAuZm9ybWF0KCk7XHJcblxyXG4gIHJldHVybiByZXN1bHQ7XHJcbn1cclxuIiwgInR5cGUgRW1wdHlWYWx1ZTxUPiA9IFQgZXh0ZW5kcyBudW1iZXJcclxuICA/IDBcclxuICA6IFQgZXh0ZW5kcyBzdHJpbmdcclxuICAgID8gbnVsbFxyXG4gICAgOiBUIGV4dGVuZHMgYm9vbGVhblxyXG4gICAgICA/IG51bGxcclxuICAgICAgOiBUIGV4dGVuZHMgRGF0ZVxyXG4gICAgICAgID8gbnVsbFxyXG4gICAgICAgIDogVCBleHRlbmRzIG9iamVjdFxyXG4gICAgICAgICAgPyBudWxsXHJcbiAgICAgICAgICA6IG51bGw7XHJcblxyXG50eXBlIEVtcHR5T2JqZWN0PFQgZXh0ZW5kcyBvYmplY3Q+ID0ge1xyXG4gIFtLIGluIGtleW9mIFRdOiBFbXB0eVZhbHVlPFRbS10+O1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGdldEVtcHR5T2JqZWN0PFQgZXh0ZW5kcyBvYmplY3Q+KFxyXG4gIGRhdGE6IFQsXHJcbiAgZGVmYXVsdFZhbHVlczogUGFydGlhbDxUPiA9IHt9XHJcbik6IEVtcHR5T2JqZWN0PFQ+ICYgUGFydGlhbDxUPiB7XHJcbiAgY29uc3Qgb2JqID0ge30gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XHJcblxyXG4gIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGRhdGEpIGFzIEFycmF5PGtleW9mIFQ+KSB7XHJcbiAgICBjb25zdCB2YWx1ZSA9IGRhdGFba2V5XTtcclxuICAgIGNvbnN0IHR5cGUgPSB0eXBlb2YgdmFsdWU7XHJcblxyXG4gICAgaWYgKHR5cGUgPT09ICdudW1iZXInKSB7XHJcbiAgICAgIG9ialtrZXkgYXMgc3RyaW5nXSA9IDA7XHJcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdzdHJpbmcnIHx8IHR5cGUgPT09ICdib29sZWFuJykge1xyXG4gICAgICBvYmpba2V5IGFzIHN0cmluZ10gPSBudWxsO1xyXG4gICAgfSBlbHNlIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcclxuICAgICAgb2JqW2tleSBhcyBzdHJpbmddID0gbnVsbDtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIG9ialtrZXkgYXMgc3RyaW5nXSA9IG51bGw7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4geyAuLi5vYmosIC4uLmRlZmF1bHRWYWx1ZXMgfSBhcyBFbXB0eU9iamVjdDxUPiAmIFBhcnRpYWw8VD47XHJcbn1cclxuIiwgImltcG9ydCB7IHVzZVJlZiwgdXNlTWVtbyB9IGZyb20gJ3JlYWN0JztcclxuXHJcbi8qKlxyXG4gKiBIb29rIHRvIG1haW50YWluIHN0YWJsZSByb3cgY291bnQgZm9yIGRhdGEgZ3JpZHMgZHVyaW5nIGxvYWRpbmcgc3RhdGVzLlxyXG4gKiBQcmV2ZW50cyBwYWdpbmF0aW9uIGp1bXBpbmcgYnkgcHJlc2VydmluZyB0aGUgbGFzdCBrbm93biB0b3RhbCBjb3VudC5cclxuICpcclxuICogQHBhcmFtIGN1cnJlbnRUb3RhbCAtIEN1cnJlbnQgdG90YWwgZnJvbSBBUEkgcmVzcG9uc2VcclxuICogQHJldHVybnMgU3RhYmxlIHJvdyBjb3VudCB0aGF0IHBlcnNpc3RzIGR1cmluZyBsb2FkaW5nXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gdXNlU3RhYmxlUm93Q291bnQoY3VycmVudFRvdGFsOiBudW1iZXIgfCB1bmRlZmluZWQpOiBudW1iZXIge1xyXG4gIGNvbnN0IHJvd0NvdW50UmVmID0gdXNlUmVmKGN1cnJlbnRUb3RhbCB8fCAwKTtcclxuXHJcbiAgY29uc3Qgc3RhYmxlUm93Q291bnQgPSB1c2VNZW1vKCgpID0+IHtcclxuICAgIGlmIChjdXJyZW50VG90YWwgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICByb3dDb3VudFJlZi5jdXJyZW50ID0gY3VycmVudFRvdGFsO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiByb3dDb3VudFJlZi5jdXJyZW50O1xyXG4gIH0sIFtjdXJyZW50VG90YWxdKTtcclxuXHJcbiAgcmV0dXJuIHN0YWJsZVJvd0NvdW50O1xyXG59XHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUF3QkEsU0FBUyxlQUF1QjtBQUM5QixNQUFJLE9BQU8sV0FBVyxlQUFlLE9BQU8sWUFBWTtBQUN0RCxXQUFPLE9BQU8sV0FBVztBQUFBLEVBQzNCO0FBR0EsU0FBTyx1Q0FBdUMsUUFBUSxTQUFTLE9BQUs7QUFDbEUsVUFBTSxJQUFLLEtBQUssT0FBTyxJQUFJLEtBQU07QUFDakMsVUFBTSxJQUFJLE1BQU0sTUFBTSxJQUFLLElBQUksSUFBTztBQUV0QyxXQUFPLEVBQUUsU0FBUyxFQUFFO0FBQUEsRUFDdEIsQ0FBQztBQUNI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U3pCLFNBQVMsa0JBQWtCLGNBQTBDO0FBQzFFLFFBQU0sY0FBYyxPQUFPLGdCQUFnQixDQUFDO0FBRTVDLFFBQU0saUJBQWlCQSxTQUFRLE1BQU07QUFDbkMsUUFBSSxpQkFBaUIsUUFBVztBQUM5QixrQkFBWSxVQUFVO0FBQUEsSUFDeEI7QUFFQSxXQUFPLFlBQVk7QUFBQSxFQUNyQixHQUFHLENBQUMsWUFBWSxDQUFDO0FBRWpCLFNBQU87QUFDVDsiLAogICJuYW1lcyI6IFsiY29uZmlnIiwgImpzeCIsICJCdXR0b24iLCAianN4IiwgImpzeCIsICJqc3giLCAianN4IiwgIm1lbW8iLCAianN4IiwgIm1lbW8iLCAiQm94IiwgIkNhcmQiLCAiQ2FyZENvbnRlbnQiLCAiVHlwb2dyYXBoeSIsICJGcmFnbWVudCIsICJqc3giLCAianN4cyIsICJCb3giLCAiVHlwb2dyYXBoeSIsICJqc3giLCAiR3JpZCIsICJUeXBvZ3JhcGh5IiwgImpzeCIsICJqc3hzIiwgIkZyYWdtZW50IiwgImpzeCIsICJCb3giLCAiRGl2aWRlciIsICJHcmlkIiwgIlR5cG9ncmFwaHkiLCAibWVtbyIsICJ1c2VNZW1vIiwgIkZyYWdtZW50IiwgImpzeCIsICJqc3hzIiwgIkJveCIsICJqc3giLCAianN4cyIsICJMb2FkaW5nQnV0dG9uIiwgImpzeCIsICJ1c2VNZW1vIiwgInVzZU1lbW8iLCAidXNlQ2FsbGJhY2siLCAidXNlTWVtbyIsICJ1c2VNZW1vIiwgInVzZVN0YXRlIiwgInVzZVdhdGNoIiwgInVzZU1lbW8iXQp9Cg==