@envive-ai/react-hooks 0.1.6 → 0.1.7

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 (667) hide show
  1. package/dist/NewOrgConfig-C5YL4Y62.cjs +20 -0
  2. package/dist/NewOrgConfig-CRyIfb_l.js +15 -0
  3. package/dist/SystemSettingsContext-Cb9YHln8.cjs +20 -0
  4. package/dist/SystemSettingsContext-D3mmGGcv.js +13 -0
  5. package/dist/TrackComponentVisibleEvent-C7c_rHFW.cjs +59 -0
  6. package/dist/TrackComponentVisibleEvent-DXTEBjGM.js +52 -0
  7. package/dist/amplitudeContext-CB_F-nJY.d.cts +52 -0
  8. package/dist/amplitudeContext-Cak6ijMq.js +287 -0
  9. package/dist/amplitudeContext-DFYBDc0h.d.ts +52 -0
  10. package/dist/amplitudeContext-sTEsPaVG.cjs +309 -0
  11. package/dist/api-DSFlctlc.cjs +269 -0
  12. package/dist/api-JTNjuOfc.js +190 -0
  13. package/dist/{app-CjsQ2_n-.js → app-D_upYeqF.js} +6 -6
  14. package/dist/{app-CnKRZ9RW.cjs → app-KXTMPa4s.cjs} +8 -8
  15. package/dist/application/models/graphql/index.cjs +2 -1
  16. package/dist/application/models/graphql/index.d.ts +1 -1
  17. package/dist/application/models/graphql/index.js +2 -1
  18. package/dist/application/models/guards/api/index.cjs +2 -1
  19. package/dist/application/models/guards/api/index.d.ts +2 -2
  20. package/dist/application/models/guards/api/index.js +2 -1
  21. package/dist/application/models/index.cjs +11 -9
  22. package/dist/application/models/index.d.cts +8 -4
  23. package/dist/application/models/index.d.ts +11 -7
  24. package/dist/application/models/index.js +10 -7
  25. package/dist/application/models/utilityTypes/index.cjs +1 -1
  26. package/dist/application/models/utilityTypes/index.d.ts +1 -1
  27. package/dist/application/models/utilityTypes/index.js +1 -1
  28. package/dist/application/models/variantInfo/index.cjs +1 -1
  29. package/dist/application/models/variantInfo/index.d.cts +1 -1
  30. package/dist/application/models/variantInfo/index.d.ts +1 -1
  31. package/dist/application/models/variantInfo/index.js +1 -1
  32. package/dist/application/utils/index.cjs +28 -22
  33. package/dist/application/utils/index.d.cts +12 -8
  34. package/dist/application/utils/index.d.ts +16 -12
  35. package/dist/application/utils/index.js +19 -13
  36. package/dist/{atomStore-B4jIaDPd.cjs → atomStore-DEZyFCNz.cjs} +1 -1
  37. package/dist/{atomStore-D8pjE1vL.js → atomStore-DnPEioF4.js} +1 -1
  38. package/dist/atoms/app/index.cjs +13 -9
  39. package/dist/atoms/app/index.d.cts +15 -11
  40. package/dist/atoms/app/index.d.ts +18 -14
  41. package/dist/atoms/app/index.js +13 -9
  42. package/dist/atoms/atomStore/index.cjs +2 -2
  43. package/dist/atoms/atomStore/index.d.cts +1 -1
  44. package/dist/atoms/atomStore/index.js +2 -2
  45. package/dist/atoms/chat/index.cjs +34 -28
  46. package/dist/atoms/chat/index.d.cts +35 -31
  47. package/dist/atoms/chat/index.d.ts +38 -34
  48. package/dist/atoms/chat/index.js +20 -14
  49. package/dist/atoms/globalSearch/index.cjs +1 -1
  50. package/dist/atoms/globalSearch/index.d.cts +5 -5
  51. package/dist/atoms/globalSearch/index.d.ts +5 -5
  52. package/dist/atoms/globalSearch/index.js +1 -1
  53. package/dist/atoms/org/index.cjs +6 -14
  54. package/dist/atoms/org/index.d.cts +27 -32
  55. package/dist/atoms/org/index.d.ts +30 -35
  56. package/dist/atoms/org/index.js +5 -11
  57. package/dist/atoms/search/index.cjs +44 -34
  58. package/dist/atoms/search/index.d.cts +9 -4
  59. package/dist/atoms/search/index.d.ts +12 -7
  60. package/dist/atoms/search/index.js +26 -16
  61. package/dist/atoms/search/types.cjs +5 -0
  62. package/dist/atoms/search/types.d.cts +2 -0
  63. package/dist/atoms/search/types.d.ts +2 -0
  64. package/dist/atoms/search/types.js +3 -0
  65. package/dist/cdnContext-BMjVfBft.cjs +53 -0
  66. package/dist/cdnContext-DgsJ00Tb.js +38 -0
  67. package/dist/{chat-CV6MXeID.js → chat-B4lkFIxz.js} +1 -1
  68. package/dist/chat-D1Eat8Ih.cjs +394 -0
  69. package/dist/chat-DPJGdUkz.js +258 -0
  70. package/dist/{chat-BubCW1as.cjs → chat-zA-K4tR_.cjs} +1 -1
  71. package/dist/chatElementDisplayLocation-9SW40Dd3.d.cts +25 -0
  72. package/dist/chatElementDisplayLocation-C1tRM5OD.d.ts +25 -0
  73. package/dist/chatSearch-B5jMnCYX.js +315 -0
  74. package/dist/chatSearch-DWMiyWN0.cjs +444 -0
  75. package/dist/chatState-BisPJd5g.cjs +120 -0
  76. package/dist/chatState-BrmBYY8l.js +34 -0
  77. package/dist/commerce-api-CxDIfeME.cjs +318 -0
  78. package/dist/commerce-api-DagLj3D_.js +311 -0
  79. package/dist/{components-B4T3Uzth.js → components-B1edduHz.js} +1 -1
  80. package/dist/{components-Cw9WjA6g.cjs → components-g0G58Kat.cjs} +1 -1
  81. package/dist/config/locators/components/chat/index.cjs +1 -1
  82. package/dist/config/locators/components/chat/index.d.cts +1 -1
  83. package/dist/config/locators/components/chat/index.d.ts +1 -1
  84. package/dist/config/locators/components/chat/index.js +1 -1
  85. package/dist/config/locators/components/chat/variants/index.d.cts +1 -1
  86. package/dist/config/locators/components/chat/variants/index.d.ts +1 -1
  87. package/dist/config/locators/components/index.cjs +1 -1
  88. package/dist/config/locators/components/index.d.cts +1 -1
  89. package/dist/config/locators/components/index.d.ts +1 -1
  90. package/dist/config/locators/components/index.js +1 -1
  91. package/dist/config/locators/components/search/index.d.cts +1 -1
  92. package/dist/config/locators/components/search/index.d.ts +1 -1
  93. package/dist/config/locators/index.cjs +42 -22
  94. package/dist/config/locators/index.d.cts +2 -2
  95. package/dist/config/locators/index.d.ts +3 -3
  96. package/dist/config/locators/index.js +25 -5
  97. package/dist/contexts/amplitudeContext/index.cjs +21 -0
  98. package/dist/contexts/amplitudeContext/index.d.cts +2 -0
  99. package/dist/contexts/amplitudeContext/index.d.ts +2 -0
  100. package/dist/contexts/amplitudeContext/index.js +19 -0
  101. package/dist/contexts/cdnContext/index.cjs +7 -0
  102. package/dist/contexts/cdnContext/index.d.cts +15 -0
  103. package/dist/contexts/cdnContext/index.d.ts +15 -0
  104. package/dist/contexts/cdnContext/index.js +6 -0
  105. package/dist/contexts/chatContext/index.cjs +329 -0
  106. package/dist/contexts/chatContext/index.d.cts +15 -0
  107. package/dist/contexts/chatContext/index.d.ts +15 -0
  108. package/dist/contexts/chatContext/index.js +322 -0
  109. package/dist/contexts/enviveConfigContext/index.cjs +7 -0
  110. package/dist/contexts/enviveConfigContext/index.d.cts +30 -0
  111. package/dist/contexts/enviveConfigContext/index.d.ts +30 -0
  112. package/dist/contexts/enviveConfigContext/index.js +6 -0
  113. package/dist/contexts/enviveCssContext/index.cjs +65 -0
  114. package/dist/contexts/enviveCssContext/index.d.cts +10 -0
  115. package/dist/contexts/enviveCssContext/index.d.ts +10 -0
  116. package/dist/contexts/enviveCssContext/index.js +62 -0
  117. package/dist/contexts/featureFlagContext/index.cjs +107 -0
  118. package/dist/contexts/featureFlagContext/index.d.cts +20 -0
  119. package/dist/contexts/featureFlagContext/index.d.ts +20 -0
  120. package/dist/contexts/featureFlagContext/index.js +103 -0
  121. package/dist/contexts/featureFlagServiceContext/index.cjs +6 -0
  122. package/dist/contexts/featureFlagServiceContext/index.d.cts +5 -0
  123. package/dist/contexts/featureFlagServiceContext/index.d.ts +5 -0
  124. package/dist/contexts/featureFlagServiceContext/index.js +5 -0
  125. package/dist/contexts/graphqlContext/index.cjs +15 -0
  126. package/dist/contexts/graphqlContext/index.d.cts +12 -0
  127. package/dist/contexts/graphqlContext/index.d.ts +12 -0
  128. package/dist/contexts/graphqlContext/index.js +14 -0
  129. package/dist/contexts/localStorageContext/index.cjs +6 -0
  130. package/dist/contexts/localStorageContext/index.d.cts +30 -0
  131. package/dist/contexts/localStorageContext/index.d.ts +30 -0
  132. package/dist/contexts/localStorageContext/index.js +4 -0
  133. package/dist/contexts/newOrgConfigContext/index.cjs +19 -0
  134. package/dist/contexts/newOrgConfigContext/index.d.cts +30 -0
  135. package/dist/contexts/newOrgConfigContext/index.d.ts +30 -0
  136. package/dist/contexts/newOrgConfigContext/index.js +18 -0
  137. package/dist/contexts/searchContext/index.cjs +23 -0
  138. package/dist/contexts/searchContext/index.d.cts +16 -0
  139. package/dist/contexts/searchContext/index.d.ts +16 -0
  140. package/dist/contexts/searchContext/index.js +22 -0
  141. package/dist/contexts/sessionStorageContext/index.cjs +5 -0
  142. package/dist/contexts/sessionStorageContext/index.d.cts +15 -0
  143. package/dist/contexts/sessionStorageContext/index.d.ts +15 -0
  144. package/dist/contexts/sessionStorageContext/index.js +4 -0
  145. package/dist/contexts/shopifyUrlContext/index.cjs +5 -0
  146. package/dist/contexts/shopifyUrlContext/index.d.cts +20 -0
  147. package/dist/contexts/shopifyUrlContext/index.d.ts +20 -0
  148. package/dist/contexts/shopifyUrlContext/index.js +4 -0
  149. package/dist/contexts/systemSettingsContext/index.cjs +8 -0
  150. package/dist/contexts/systemSettingsContext/index.d.cts +36 -0
  151. package/dist/contexts/systemSettingsContext/index.d.ts +36 -0
  152. package/dist/contexts/systemSettingsContext/index.js +6 -0
  153. package/dist/contexts/types.cjs +7 -0
  154. package/dist/contexts/types.d.cts +4 -0
  155. package/dist/contexts/types.d.ts +4 -0
  156. package/dist/contexts/types.js +3 -0
  157. package/dist/contexts/userIdentityContext/index.cjs +26 -0
  158. package/dist/contexts/userIdentityContext/index.d.cts +2 -0
  159. package/dist/contexts/userIdentityContext/index.d.ts +2 -0
  160. package/dist/contexts/userIdentityContext/index.js +25 -0
  161. package/dist/domObserver-B6cRGTny.js +285 -0
  162. package/dist/domObserver-DQZwhPrc.cjs +304 -0
  163. package/dist/enviveConfig-BJZ4zTJo.js +62 -0
  164. package/dist/enviveConfig-DdBrcGSQ.cjs +130 -0
  165. package/dist/enviveConfigContext-78orE_uH.cjs +60 -0
  166. package/dist/enviveConfigContext-jBCCWQH9.js +45 -0
  167. package/dist/events/index.cjs +1 -1
  168. package/dist/events/index.d.ts +1 -1
  169. package/dist/events/index.js +1 -1
  170. package/dist/{events-BrLpaNxh.js → events-BHJJjPDN.js} +1 -1
  171. package/dist/{events-DwT6cEwI.cjs → events-B_fJZf9E.cjs} +1 -1
  172. package/dist/featureFlagServiceContext-ChL7DJ53.cjs +56 -0
  173. package/dist/featureFlagServiceContext-D1PzHsEs.d.ts +23 -0
  174. package/dist/featureFlagServiceContext-DQwlCTde.d.cts +23 -0
  175. package/dist/featureFlagServiceContext-DzFfmb1Z.js +42 -0
  176. package/dist/featureGates-Blx10fwB.js +27 -0
  177. package/dist/featureGates-DcZNrUma.cjs +33 -0
  178. package/dist/frontendConfig-DrvrQSm8.d.ts +857 -0
  179. package/dist/frontendConfig-wg41mBok.d.cts +857 -0
  180. package/dist/{globalSearch-BFvEg53C.cjs → globalSearch-Bnjlxtr5.cjs} +1 -1
  181. package/dist/{globalSearch-B6THR7Jx.js → globalSearch-CRWUqnjq.js} +1 -1
  182. package/dist/graphql-B9HhDXYt.cjs +53 -0
  183. package/dist/graphql-W7GMIHUu.js +36 -0
  184. package/dist/graphqlConfig-Bn-HLHsh.cjs +39 -0
  185. package/dist/graphqlConfig-DtZm_YaH.js +14 -0
  186. package/dist/graphqlContext-BJg7B--J.js +96 -0
  187. package/dist/graphqlContext-DI-_VRmb.cjs +111 -0
  188. package/dist/hooks/AmplitudeOperations/index.cjs +21 -0
  189. package/dist/hooks/AmplitudeOperations/index.d.cts +12 -0
  190. package/dist/hooks/AmplitudeOperations/index.d.ts +12 -0
  191. package/dist/hooks/AmplitudeOperations/index.js +21 -0
  192. package/dist/hooks/AppDetails/index.cjs +18 -0
  193. package/dist/hooks/AppDetails/index.d.cts +26 -0
  194. package/dist/hooks/AppDetails/index.d.ts +26 -0
  195. package/dist/hooks/AppDetails/index.js +18 -0
  196. package/dist/hooks/BlockBackButton/index.cjs +29 -0
  197. package/dist/hooks/BlockBackButton/index.d.cts +5 -0
  198. package/dist/hooks/BlockBackButton/index.d.ts +5 -0
  199. package/dist/hooks/BlockBackButton/index.js +27 -0
  200. package/dist/hooks/CdnOperations/index.cjs +24 -0
  201. package/dist/hooks/CdnOperations/index.d.cts +7 -0
  202. package/dist/hooks/CdnOperations/index.d.ts +7 -0
  203. package/dist/hooks/CdnOperations/index.js +22 -0
  204. package/dist/hooks/ChatToggle/index.cjs +63 -0
  205. package/dist/hooks/ChatToggle/index.d.cts +12 -0
  206. package/dist/hooks/ChatToggle/index.d.ts +12 -0
  207. package/dist/hooks/ChatToggle/index.js +61 -0
  208. package/dist/hooks/ChatToggleAnalytics/index.cjs +37 -0
  209. package/dist/hooks/ChatToggleAnalytics/index.d.cts +9 -0
  210. package/dist/hooks/ChatToggleAnalytics/index.d.ts +9 -0
  211. package/dist/hooks/ChatToggleAnalytics/index.js +35 -0
  212. package/dist/hooks/CustomerSupportHandoff/index.cjs +36 -0
  213. package/dist/hooks/CustomerSupportHandoff/index.d.cts +16 -0
  214. package/dist/hooks/CustomerSupportHandoff/index.d.ts +16 -0
  215. package/dist/hooks/CustomerSupportHandoff/index.js +34 -0
  216. package/dist/hooks/Debounce/index.cjs +3 -0
  217. package/dist/hooks/Debounce/index.d.cts +5 -0
  218. package/dist/hooks/Debounce/index.d.ts +5 -0
  219. package/dist/hooks/Debounce/index.js +3 -0
  220. package/dist/hooks/ElementObserver/index.cjs +179 -0
  221. package/dist/hooks/ElementObserver/index.d.cts +29 -0
  222. package/dist/hooks/ElementObserver/index.d.ts +29 -0
  223. package/dist/hooks/ElementObserver/index.js +177 -0
  224. package/dist/hooks/GrabAndScroll/index.cjs +99 -0
  225. package/dist/hooks/GrabAndScroll/index.d.cts +14 -0
  226. package/dist/hooks/GrabAndScroll/index.d.ts +14 -0
  227. package/dist/hooks/GrabAndScroll/index.js +97 -0
  228. package/dist/hooks/GraphQLConfig/index.cjs +16 -0
  229. package/dist/hooks/GraphQLConfig/index.d.cts +15 -0
  230. package/dist/hooks/GraphQLConfig/index.d.ts +15 -0
  231. package/dist/hooks/GraphQLConfig/index.js +15 -0
  232. package/dist/hooks/IdentifyUser/index.cjs +59 -0
  233. package/dist/hooks/IdentifyUser/index.d.cts +10 -0
  234. package/dist/hooks/IdentifyUser/index.d.ts +10 -0
  235. package/dist/hooks/IdentifyUser/index.js +57 -0
  236. package/dist/hooks/ImageResolver/index.cjs +54 -0
  237. package/dist/hooks/ImageResolver/index.d.cts +7 -0
  238. package/dist/hooks/ImageResolver/index.d.ts +7 -0
  239. package/dist/hooks/ImageResolver/index.js +52 -0
  240. package/dist/hooks/Intersection/index.cjs +3 -0
  241. package/dist/hooks/Intersection/index.d.cts +7 -0
  242. package/dist/hooks/Intersection/index.d.ts +7 -0
  243. package/dist/hooks/Intersection/index.js +3 -0
  244. package/dist/hooks/IsSmallScreen/index.cjs +22 -0
  245. package/dist/hooks/IsSmallScreen/index.d.cts +5 -0
  246. package/dist/hooks/IsSmallScreen/index.d.ts +5 -0
  247. package/dist/hooks/IsSmallScreen/index.js +20 -0
  248. package/dist/hooks/LocalStorageOperations/index.cjs +79 -0
  249. package/dist/hooks/LocalStorageOperations/index.d.cts +17 -0
  250. package/dist/hooks/LocalStorageOperations/index.d.ts +17 -0
  251. package/dist/hooks/LocalStorageOperations/index.js +74 -0
  252. package/dist/hooks/MessageFilter/index.cjs +53 -0
  253. package/dist/hooks/MessageFilter/index.d.cts +29 -0
  254. package/dist/hooks/MessageFilter/index.d.ts +29 -0
  255. package/dist/hooks/MessageFilter/index.js +53 -0
  256. package/dist/hooks/MessageScrollObserver/index.cjs +36 -0
  257. package/dist/hooks/MessageScrollObserver/index.d.cts +5 -0
  258. package/dist/hooks/MessageScrollObserver/index.d.ts +5 -0
  259. package/dist/hooks/MessageScrollObserver/index.js +34 -0
  260. package/dist/hooks/NewOrgConfig/index.cjs +19 -0
  261. package/dist/hooks/NewOrgConfig/index.d.cts +22 -0
  262. package/dist/hooks/NewOrgConfig/index.d.ts +22 -0
  263. package/dist/hooks/NewOrgConfig/index.js +19 -0
  264. package/dist/hooks/Search/index.cjs +324 -0
  265. package/dist/hooks/Search/index.d.cts +66 -0
  266. package/dist/hooks/Search/index.d.ts +66 -0
  267. package/dist/hooks/Search/index.js +321 -0
  268. package/dist/hooks/SearchOperations/index.cjs +101 -0
  269. package/dist/hooks/SearchOperations/index.d.cts +22 -0
  270. package/dist/hooks/SearchOperations/index.d.ts +22 -0
  271. package/dist/hooks/SearchOperations/index.js +98 -0
  272. package/dist/hooks/SessionStorageOperations/index.cjs +30 -0
  273. package/dist/hooks/SessionStorageOperations/index.d.cts +8 -0
  274. package/dist/hooks/SessionStorageOperations/index.d.ts +8 -0
  275. package/dist/hooks/SessionStorageOperations/index.js +28 -0
  276. package/dist/hooks/ShopifyUrlOperations/index.cjs +53 -0
  277. package/dist/hooks/ShopifyUrlOperations/index.d.cts +23 -0
  278. package/dist/hooks/ShopifyUrlOperations/index.d.ts +23 -0
  279. package/dist/hooks/ShopifyUrlOperations/index.js +49 -0
  280. package/dist/hooks/SnapCalculator/index.cjs +29 -0
  281. package/dist/hooks/SnapCalculator/index.d.cts +12 -0
  282. package/dist/hooks/SnapCalculator/index.d.ts +12 -0
  283. package/dist/hooks/SnapCalculator/index.js +27 -0
  284. package/dist/hooks/SystemSettingsContext/index.cjs +7 -0
  285. package/dist/hooks/SystemSettingsContext/index.d.cts +22 -0
  286. package/dist/hooks/SystemSettingsContext/index.d.ts +22 -0
  287. package/dist/hooks/SystemSettingsContext/index.js +7 -0
  288. package/dist/hooks/TrackComponentVisibleEvent/index.cjs +21 -0
  289. package/dist/hooks/TrackComponentVisibleEvent/index.d.cts +18 -0
  290. package/dist/hooks/TrackComponentVisibleEvent/index.d.ts +18 -0
  291. package/dist/hooks/TrackComponentVisibleEvent/index.js +21 -0
  292. package/dist/hooks/UpdateAnalyticsProps/index.cjs +61 -0
  293. package/dist/hooks/UpdateAnalyticsProps/index.d.cts +9 -0
  294. package/dist/hooks/UpdateAnalyticsProps/index.d.ts +9 -0
  295. package/dist/hooks/UpdateAnalyticsProps/index.js +58 -0
  296. package/dist/index-BCLaqnc2.d.cts +689 -0
  297. package/dist/{index-ylUiJvnr.d.ts → index-BS7-_CW4.d.ts} +1 -1
  298. package/dist/index-Bmub8e38.d.cts +1 -1
  299. package/dist/index-Bs0QtkSu.d.ts +689 -0
  300. package/dist/index-CESxqFso.d.cts +1 -1
  301. package/dist/index-CKeS9dud.d.ts +28 -0
  302. package/dist/index-CiWEYzXl.d.cts +1 -1
  303. package/dist/index-CyXULMyI.d.cts +186 -0
  304. package/dist/index-Cz10TYQA.d.cts +28 -0
  305. package/dist/{index-B0NW9KTj.d.cts → index-D46Rd0io.d.cts} +1 -1
  306. package/dist/{index-C6KdON7d.d.ts → index-D8ThXrqI.d.ts} +1 -1
  307. package/dist/{index-PGF8BvxQ.d.ts → index-D9VegTU-.d.ts} +1 -1
  308. package/dist/{index-DOii3C6b.d.ts → index-DBqgBV9N.d.ts} +1 -1
  309. package/dist/{index-Cqg6ltII.d.ts → index-DNUKSg6R.d.ts} +1 -1
  310. package/dist/{index-BDPWBU3h.d.cts → index-DO0s5KNA.d.cts} +1 -1
  311. package/dist/{index-CcIG01PJ.d.ts → index-DuyZQOE1.d.ts} +2 -2
  312. package/dist/{index-Byb45OPg.d.cts → index-REhT-Pls.d.cts} +1 -1
  313. package/dist/index-fKJB9EFb.d.ts +186 -0
  314. package/dist/interceptors/index.cjs +2 -1
  315. package/dist/interceptors/index.d.cts +9 -10
  316. package/dist/interceptors/index.d.ts +12 -13
  317. package/dist/interceptors/index.js +2 -1
  318. package/dist/interceptors/types.cjs +1 -0
  319. package/dist/interceptors/types.d.cts +12 -0
  320. package/dist/interceptors/types.d.ts +12 -0
  321. package/dist/interceptors/types.js +3 -0
  322. package/dist/localStorageContext-6OrGDFid.js +95 -0
  323. package/dist/localStorageContext-Bld0OWmG.cjs +115 -0
  324. package/dist/logger-CSL2jqI9.cjs +26 -0
  325. package/dist/logger-D5MFf3nW.js +20 -0
  326. package/dist/{models-BkXg5eIP.cjs → models-Dn8Emdzc.js} +219 -458
  327. package/dist/models-ZpQcRZQK.cjs +1536 -0
  328. package/dist/newOrgConfigAtom--tewb_G0.js +8 -0
  329. package/dist/newOrgConfigAtom-DkSi45_Q.cjs +15 -0
  330. package/dist/newOrgConfigContext-B3aeblfE.cjs +68 -0
  331. package/dist/newOrgConfigContext-B5mzHKTG.js +53 -0
  332. package/dist/{nodeSelector-BxrS2S_k.d.ts → nodeSelector-DybpVr-i.d.ts} +1 -1
  333. package/dist/{nodeSelector-Dm4S-10n.d.cts → nodeSelector-XsUa5vNH.d.cts} +1 -1
  334. package/dist/org-B2uRkPt3.js +12 -0
  335. package/dist/org-ClUxpHPZ.cjs +43 -0
  336. package/dist/{orgAnalyticsConfig-BJ2A1RZ-.cjs → orgAnalyticsConfig-CuWXijsr.cjs} +1 -1
  337. package/dist/{orgAnalyticsConfig-ClrFy2qH.js → orgAnalyticsConfig-DOceTdNp.js} +1 -1
  338. package/dist/search-BIomqYy6.d.ts +20 -0
  339. package/dist/search-B_Hg-Es2.d.cts +20 -0
  340. package/dist/search-Bn4x-3TG.js +126 -0
  341. package/dist/search-DsQm_pAi.cjs +205 -0
  342. package/dist/{search-filter-types-fZf91Pdw.d.ts → search-filter-types-B5xcaEit.d.ts} +1 -1
  343. package/dist/{search-filter-types-DosbseF3.d.cts → search-filter-types-Byd0lEUa.d.cts} +1 -1
  344. package/dist/searchContext-Cn-pCoDy.cjs +145 -0
  345. package/dist/searchContext-fQDGSvUF.js +129 -0
  346. package/dist/searchServiceAdapter-BSPZOg1r.js +16 -0
  347. package/dist/searchServiceAdapter-DrjFCiw8.cjs +34 -0
  348. package/dist/sessionStorageContext-C5MUl2zf.js +52 -0
  349. package/dist/sessionStorageContext-CXE7iHtP.cjs +66 -0
  350. package/dist/shopifyUrlContext-7ppKx1jJ.cjs +75 -0
  351. package/dist/shopifyUrlContext-BSYWsoX9.js +61 -0
  352. package/dist/spiffyWidgets-CdxRcXhW.d.ts +20 -0
  353. package/dist/spiffyWidgets-DxGuuuCG.d.cts +20 -0
  354. package/dist/systemSettingsContext-BdAe_3Ll.cjs +60 -0
  355. package/dist/systemSettingsContext-Cjyo2o3N.js +39 -0
  356. package/dist/{test-types-CgVJtwUr.d.cts → test-types-DQB1JqOf.d.cts} +1 -1
  357. package/dist/{test-types-C9b_OdfO.d.ts → test-types-ZuRAYwox.d.ts} +1 -1
  358. package/dist/types/index.cjs +33 -5
  359. package/dist/types/index.d.cts +2 -2
  360. package/dist/types/index.d.ts +2 -2
  361. package/dist/types/index.js +30 -3
  362. package/dist/types-BCz-hOvv.d.ts +51 -0
  363. package/dist/types-BwNrLPSZ.cjs +106 -0
  364. package/dist/types-D3uOF0Oy.js +76 -0
  365. package/dist/types-DIk0FLwd.js +30 -0
  366. package/dist/types-DNLkuGWZ.cjs +48 -0
  367. package/dist/types-DzwBmZHy.d.cts +10 -0
  368. package/dist/types-Eip78dWv.d.cts +51 -0
  369. package/dist/types-YvACLe2e.d.ts +10 -0
  370. package/dist/types.d.cts +15 -0
  371. package/dist/types.d.ts +15 -0
  372. package/dist/unsupportedProductExceptions--t7AQFou.js +20 -0
  373. package/dist/unsupportedProductExceptions-Dak4AD-t.cjs +32 -0
  374. package/dist/urlsParser-BV5yF8sa.cjs +78 -0
  375. package/dist/urlsParser-DUgV_Qy9.js +42 -0
  376. package/dist/useAmplitudeOperations-C6Osqkso.js +34 -0
  377. package/dist/useAmplitudeOperations-Cco_B3A5.cjs +41 -0
  378. package/dist/useAppDetails-CGqtN6sJ.cjs +38 -0
  379. package/dist/useAppDetails-DwX2Rhed.js +30 -0
  380. package/dist/useDebounce-BJqnCBcl.cjs +26 -0
  381. package/dist/useDebounce-Ce31ph7m.js +19 -0
  382. package/dist/useGraphQLConfig-ByOZb3oZ.js +63 -0
  383. package/dist/useGraphQLConfig-DItL4BgM.cjs +76 -0
  384. package/dist/useIntersection-Czeo04jt.js +21 -0
  385. package/dist/useIntersection-DnZNLcnu.cjs +28 -0
  386. package/dist/{useMessageInterceptor-B87e3yu3.cjs → useMessageInterceptor-C9p9No1n.cjs} +3 -3
  387. package/dist/{useMessageInterceptor-Bb7YRaWk.js → useMessageInterceptor-tntd2rvB.js} +2 -2
  388. package/dist/userIdentityContext-C1HzZFb2.cjs +125 -0
  389. package/dist/userIdentityContext-CDfosvOO.js +109 -0
  390. package/dist/userIdentityContext-DBXoLrFu.d.cts +20 -0
  391. package/dist/userIdentityContext-W1OWF3cG.d.ts +20 -0
  392. package/dist/utilityTypes-CWJZb9BZ.js +1 -0
  393. package/dist/utilityTypes-YGiMSyV7.cjs +0 -0
  394. package/dist/utils-BA5HXmkL.cjs +74 -0
  395. package/dist/utils-BTDw2aMx.cjs +715 -0
  396. package/dist/utils-C7S9YiFp.js +54 -0
  397. package/dist/utils-CF13DfA1.js +606 -0
  398. package/dist/variantInfo-58JLeDJb.js +1 -0
  399. package/dist/variantInfo-DRFLcGc7.cjs +0 -0
  400. package/package.json +179 -7
  401. package/src/application/models/index.ts +0 -1
  402. package/src/application/utils/analyticsUtils.ts +1 -1
  403. package/src/atoms/amplitude/amplitudeTrackEventAtom.ts +1 -1
  404. package/src/atoms/app/index.ts +1 -1
  405. package/src/atoms/chat/chatState.ts +1 -1
  406. package/src/atoms/chat/replies.ts +1 -1
  407. package/src/atoms/org/graphqlConfig.ts +1 -39
  408. package/src/atoms/org/index.ts +0 -1
  409. package/src/atoms/org/newOrgConfigAtom.ts +2 -6
  410. package/src/contexts/{amplitudeContext.tsx → amplitudeContext/amplitudeContext.tsx} +1 -2
  411. package/src/contexts/amplitudeContext/index.ts +1 -0
  412. package/src/contexts/{cdnContext.tsx → cdnContext/cdnContext.tsx} +1 -1
  413. package/src/contexts/cdnContext/index.ts +1 -0
  414. package/src/contexts/{chatContext.tsx → chatContext/chatContext.tsx} +3 -3
  415. package/src/contexts/chatContext/index.ts +1 -0
  416. package/src/contexts/{enviveConfigContext.tsx → enviveConfigContext/enviveConfigContext.tsx} +1 -1
  417. package/src/contexts/enviveConfigContext/index.ts +1 -0
  418. package/src/contexts/{enviveCssContext.tsx → enviveCssContext/enviveCssContext.tsx} +1 -1
  419. package/src/contexts/enviveCssContext/index.ts +1 -0
  420. package/src/contexts/{featureFlagContext.tsx → featureFlagContext/featureFlagContext.tsx} +1 -1
  421. package/src/contexts/featureFlagContext/index.ts +1 -0
  422. package/src/contexts/featureFlagServiceContext/index.ts +1 -0
  423. package/src/contexts/graphqlContext/index.ts +1 -0
  424. package/src/contexts/localStorageContext/index.ts +1 -0
  425. package/src/contexts/{localStorageContext.tsx → localStorageContext/localStorageContext.tsx} +2 -2
  426. package/src/contexts/newOrgConfigContext/index.ts +1 -0
  427. package/src/contexts/newOrgConfigContext/newOrgConfigContext.tsx +70 -0
  428. package/src/contexts/searchContext/index.ts +1 -0
  429. package/src/contexts/{searchContext.tsx → searchContext/searchContext.tsx} +5 -5
  430. package/src/contexts/sessionStorageContext/index.ts +1 -0
  431. package/src/contexts/{sessionStorageContext.tsx → sessionStorageContext/sessionStorageContext.tsx} +1 -1
  432. package/src/contexts/shopifyUrlContext/index.ts +1 -0
  433. package/src/contexts/systemSettingsContext/index.ts +1 -0
  434. package/src/contexts/userIdentityContext/index.ts +1 -0
  435. package/src/events/registerAnalyticsListeners.ts +2 -2
  436. package/src/favicon.ico +0 -0
  437. package/src/hooks/AmplitudeOperations/index.ts +1 -0
  438. package/src/hooks/{useAmplitudeOperations.ts → AmplitudeOperations/useAmplitudeOperations.ts} +1 -1
  439. package/src/hooks/AppDetails/index.ts +1 -0
  440. package/src/hooks/{useAppDetails.ts → AppDetails/useAppDetails.ts} +1 -3
  441. package/src/hooks/BlockBackButton/index.ts +1 -0
  442. package/src/hooks/CdnOperations/index.ts +1 -0
  443. package/src/hooks/{useCdnOperations.ts → CdnOperations/useCdnOperations.ts} +1 -1
  444. package/src/hooks/ChatToggle/index.ts +1 -0
  445. package/src/hooks/{useChatToggle.ts → ChatToggle/useChatToggle.ts} +1 -1
  446. package/src/hooks/ChatToggleAnalytics/index.ts +1 -0
  447. package/src/hooks/{useChatToggleAnalytics.ts → ChatToggleAnalytics/useChatToggleAnalytics.ts} +1 -1
  448. package/src/hooks/CustomerSupportHandoff/index.ts +1 -0
  449. package/src/hooks/Debounce/index.ts +1 -0
  450. package/src/hooks/ElementObserver/index.ts +1 -0
  451. package/src/hooks/GrabAndScroll/index.ts +1 -0
  452. package/src/hooks/GraphQLConfig/index.ts +1 -0
  453. package/src/hooks/{useGraphQLConfig.ts → GraphQLConfig/useGraphQLConfig.ts} +1 -1
  454. package/src/hooks/IdentifyUser/index.ts +1 -0
  455. package/src/hooks/{useIdentifyUser.ts → IdentifyUser/useIdentifyUser.ts} +1 -1
  456. package/src/hooks/ImageResolver/index.ts +1 -0
  457. package/src/hooks/Intersection/index.ts +1 -0
  458. package/src/hooks/IsSmallScreen/index.ts +1 -0
  459. package/src/hooks/LocalStorageOperations/index.ts +1 -0
  460. package/src/hooks/{useLocalStorageOperations.ts → LocalStorageOperations/useLocalStorageOperations.ts} +2 -2
  461. package/src/hooks/MessageFilter/index.ts +1 -0
  462. package/src/hooks/MessageScrollObserver/index.ts +1 -0
  463. package/src/hooks/NewOrgConfig/index.ts +1 -0
  464. package/src/hooks/{useNewOrgConfig.ts → NewOrgConfig/useNewOrgConfig.ts} +1 -1
  465. package/src/hooks/Search/index.ts +1 -0
  466. package/src/hooks/{useSearch.tsx → Search/useSearch.tsx} +5 -4
  467. package/src/hooks/SearchOperations/index.ts +1 -0
  468. package/src/hooks/SessionStorageOperations/index.ts +1 -0
  469. package/src/hooks/{useSessionStorageOperations.ts → SessionStorageOperations/useSessionStorageOperations.ts} +1 -1
  470. package/src/hooks/ShopifyUrlOperations/index.ts +1 -0
  471. package/src/hooks/{useShopifyUrlOperations.ts → ShopifyUrlOperations/useShopifyUrlOperations.ts} +1 -1
  472. package/src/hooks/SnapCalculator/index.ts +1 -0
  473. package/src/hooks/SystemSettingsContext/index.ts +1 -0
  474. package/src/hooks/SystemSettingsContext/useSystemSettingsContext.ts +14 -0
  475. package/src/hooks/TrackComponentVisibleEvent/index.ts +1 -0
  476. package/src/hooks/{useTrackComponentVisibleEvent.ts → TrackComponentVisibleEvent/useTrackComponentVisibleEvent.ts} +2 -2
  477. package/src/hooks/UpdateAnalyticsProps/index.ts +1 -0
  478. package/src/hooks/{useUpdateAnalyticsProps.ts → UpdateAnalyticsProps/useUpdateAnalyticsProps.ts} +1 -1
  479. package/dist/amplitudeContext-CHzas7Cf.d.cts +0 -52
  480. package/dist/amplitudeContext-D-7fmVh1.cjs +0 -356
  481. package/dist/amplitudeContext-hY3caPC6.js +0 -322
  482. package/dist/amplitudeContext-tJ4y-SzX.d.ts +0 -52
  483. package/dist/api-DjeZXxl_.js +0 -207
  484. package/dist/api-_JaUnIUj.cjs +0 -292
  485. package/dist/bandolier-DYEz4-8C.js +0 -1229
  486. package/dist/bandolier-o_-xrbOV.cjs +0 -1229
  487. package/dist/carpe-CsG5jCcl.cjs +0 -607
  488. package/dist/carpe-DONk00bZ.js +0 -605
  489. package/dist/cdnUtils-32v8bDX9.cjs +0 -16
  490. package/dist/cdnUtils-E4tLBt2g.js +0 -11
  491. package/dist/chat-CO7cRkaq.cjs +0 -506
  492. package/dist/chat-hcRc4RRd.js +0 -285
  493. package/dist/contexts/index.cjs +0 -57
  494. package/dist/contexts/index.d.cts +0 -10
  495. package/dist/contexts/index.d.ts +0 -10
  496. package/dist/contexts/index.js +0 -23
  497. package/dist/contexts-B4ihTBsV.cjs +0 -2980
  498. package/dist/contexts-DGlr7M1o.js +0 -2596
  499. package/dist/coterie-CKB93qfz.cjs +0 -239
  500. package/dist/coterie-DHcj2fRE.js +0 -239
  501. package/dist/custservice-types-Dy0kc9TW.cjs +0 -35
  502. package/dist/custservice-types-mnIunabv.js +0 -23
  503. package/dist/default-BnB4p0Se.cjs +0 -234
  504. package/dist/default-D6f5Dyt7.js +0 -199
  505. package/dist/default-ZKkE5zT4.cjs +0 -4
  506. package/dist/default-legGZJwI.js +0 -4
  507. package/dist/divIds-2dJlU3z8.cjs +0 -117
  508. package/dist/divIds-BUrN2vY-.js +0 -21
  509. package/dist/dreamlandBaby-BiRYYFav.js +0 -346
  510. package/dist/dreamlandBaby-zuvmfzfD.cjs +0 -346
  511. package/dist/embedded-BJLWIriJ.js +0 -23
  512. package/dist/embedded-Dl79TJLC.cjs +0 -131
  513. package/dist/entrypoints-Bs3pn6EV.js +0 -7
  514. package/dist/entrypoints-Dqi5pzWH.cjs +0 -19
  515. package/dist/enviveConfig-BccuzS2a.cjs +0 -240
  516. package/dist/enviveConfig-CzhTz8Aa.js +0 -152
  517. package/dist/fiveCbd-DwTTwC2j.cjs +0 -613
  518. package/dist/fiveCbd-Dz2NouOF.js +0 -613
  519. package/dist/forLoveAndLemons-DqSdyD6S.js +0 -665
  520. package/dist/forLoveAndLemons-Ud6mPrV3.cjs +0 -667
  521. package/dist/graphql-BNW60InJ.cjs +0 -128
  522. package/dist/graphql-CjB8wHzm.js +0 -74
  523. package/dist/graphqlConfig-CYt6tWII.js +0 -30
  524. package/dist/graphqlConfig-DicykC-o.cjs +0 -61
  525. package/dist/greenpan-B_EbPkSP.js +0 -397
  526. package/dist/greenpan-kPE4fJgd.cjs +0 -397
  527. package/dist/grooveLife-Ckuir319.js +0 -342
  528. package/dist/grooveLife-DKSEQp1F.cjs +0 -342
  529. package/dist/homegrownCannabis-BVPa2pqe.js +0 -410
  530. package/dist/homegrownCannabis-BwIAkxuA.cjs +0 -410
  531. package/dist/hooks/index.cjs +0 -63
  532. package/dist/hooks/index.d.cts +0 -314
  533. package/dist/hooks/index.d.ts +0 -314
  534. package/dist/hooks/index.js +0 -23
  535. package/dist/index-BMPtlgac.d.ts +0 -191
  536. package/dist/index-C7pGDl1A.d.ts +0 -1609
  537. package/dist/index-C9lgsCWp.d.cts +0 -203
  538. package/dist/index-Cc-wBCn6.d.ts +0 -203
  539. package/dist/index-DTu2X-YS.d.cts +0 -1609
  540. package/dist/index-OEifcBsm.d.cts +0 -191
  541. package/dist/jackArcher-B39OEIj6.cjs +0 -727
  542. package/dist/jackArcher-BwkWGybC.js +0 -727
  543. package/dist/jordanCraig-CxRH_jLi.js +0 -1786
  544. package/dist/jordanCraig-RwmWw-jM.cjs +0 -1786
  545. package/dist/kindredBravely-D78VwL20.cjs +0 -490
  546. package/dist/kindredBravely-DQDpAzdl.js +0 -490
  547. package/dist/kutFromTheKloth-TcXQkIti.js +0 -369
  548. package/dist/kutFromTheKloth-dXRrNti0.cjs +0 -369
  549. package/dist/larryAndSerges-Bh5XEXsZ.js +0 -262
  550. package/dist/larryAndSerges-COdBzOzu.cjs +0 -262
  551. package/dist/leapsAndRebounds-BbXnqkl5.cjs +0 -360
  552. package/dist/leapsAndRebounds-mjCaH1k-.js +0 -360
  553. package/dist/longevityrx-DdV3v26F.cjs +0 -320
  554. package/dist/longevityrx-DfPDfvAt.js +0 -320
  555. package/dist/lookOptic-DgXFGBPP.cjs +0 -282
  556. package/dist/lookOptic-FgVW1afF.js +0 -282
  557. package/dist/mantraBrand-C5gVm3rk.cjs +0 -750
  558. package/dist/mantraBrand-uV8HCDR8.js +0 -750
  559. package/dist/medterra-BtDpr1Hw.cjs +0 -583
  560. package/dist/medterra-DgzE7-mj.js +0 -583
  561. package/dist/modells-CJjsxOIR.js +0 -484
  562. package/dist/modells-Ck5KbRFj.cjs +0 -484
  563. package/dist/models-UZ6HszfZ.js +0 -1281
  564. package/dist/org-C2RrBVQR.cjs +0 -81
  565. package/dist/org-xMytX--e.js +0 -38
  566. package/dist/pressedFloral-Bteoboms.js +0 -661
  567. package/dist/pressedFloral-CexgV-xy.cjs +0 -661
  568. package/dist/search-BMOAmrmY.js +0 -459
  569. package/dist/search-Df0Ifneg.cjs +0 -672
  570. package/dist/skinPerfection-BGzq9lq-.cjs +0 -334
  571. package/dist/skinPerfection-BlvcEcUE.js +0 -334
  572. package/dist/snapSupplements-CbbGzAgO.cjs +0 -285
  573. package/dist/snapSupplements-kcsPAOm9.js +0 -285
  574. package/dist/socialProofClasses-Db8gzsfi.cjs +0 -40
  575. package/dist/socialProofClasses-kwDvwLOZ.js +0 -10
  576. package/dist/spanx-B4WFA_rI.js +0 -661
  577. package/dist/spanx-BWoE4F8b.cjs +0 -663
  578. package/dist/spanxStaging-BOrOjhXn.js +0 -845
  579. package/dist/spanxStaging-BfdfIug4.cjs +0 -848
  580. package/dist/suggestionBarV2-types-IMMOmCir.js +0 -10
  581. package/dist/suggestionBarV2-types-nnGNgFvR.cjs +0 -16
  582. package/dist/supergoop-22dd5_BS.js +0 -323
  583. package/dist/supergoop-B-a4cku2.cjs +0 -323
  584. package/dist/types--pr1GQQx.js +0 -154
  585. package/dist/types-BVSyY3Hk.cjs +0 -196
  586. package/dist/uniqueVintage-CJXiNNe7.js +0 -1211
  587. package/dist/uniqueVintage-D0jzJWlo.cjs +0 -1213
  588. package/dist/userIdentityContext-BPqvVIg0.d.cts +0 -20
  589. package/dist/userIdentityContext-wbCRmlzp.d.ts +0 -20
  590. package/dist/utils-C9ZSCx12.js +0 -888
  591. package/dist/utils-D5HO61hG.cjs +0 -1016
  592. package/dist/venaCbd-Bhhu_qUf.cjs +0 -365
  593. package/dist/venaCbd-CanovPS_.js +0 -365
  594. package/dist/westonJonBoucher-BC0x1ktI.cjs +0 -422
  595. package/dist/westonJonBoucher-BUu1_wP1.js +0 -422
  596. package/dist/wineEnthusiast-BlCryfil.cjs +0 -940
  597. package/dist/wineEnthusiast-Ck1x5iJq.js +0 -940
  598. package/dist/wolfMattress-D9Mjq-HP.js +0 -372
  599. package/dist/wolfMattress-JssghhC-.cjs +0 -372
  600. package/dist/wolfTactical-C6exYhL7.cjs +0 -349
  601. package/dist/wolfTactical-CnV3KQdI.js +0 -349
  602. package/src/application/models/supportedOrgs.ts +0 -161
  603. package/src/atoms/org/orgPageConfig.ts +0 -42
  604. package/src/contexts/index.ts +0 -16
  605. package/src/contexts/newOrgConfigContext.tsx +0 -104
  606. package/src/contexts/orgConfigContext.tsx +0 -106
  607. package/src/hooks/index.ts +0 -27
  608. package/src/hooks/useSystemSettingsContext.ts +0 -12
  609. package/src/merchants/bandolier/bandolier.ts +0 -1371
  610. package/src/merchants/carpe/carpe.ts +0 -653
  611. package/src/merchants/coterie/coterie.ts +0 -277
  612. package/src/merchants/default.ts +0 -196
  613. package/src/merchants/dreamlandBaby/dreamlandBaby.ts +0 -381
  614. package/src/merchants/fiveCbd/fiveCbd.ts +0 -691
  615. package/src/merchants/forLoveAndLemons/forLoveAndLemons.ts +0 -751
  616. package/src/merchants/greenpan/greenpan.ts +0 -434
  617. package/src/merchants/grooveLife/grooveLife.ts +0 -392
  618. package/src/merchants/homegrownCannabis/homegrownCannabis.ts +0 -474
  619. package/src/merchants/init-merchant.sh +0 -53
  620. package/src/merchants/jackArcher/jackArcher.ts +0 -989
  621. package/src/merchants/jordanCraig/jordanCraig.ts +0 -1927
  622. package/src/merchants/kindredBravely/kindredBravely.ts +0 -538
  623. package/src/merchants/kutFromTheKloth/kutFromTheKloth.ts +0 -421
  624. package/src/merchants/larryAndSerges/larryAndSerges.ts +0 -318
  625. package/src/merchants/leapsAndRebounds/leapsAndRebounds.ts +0 -424
  626. package/src/merchants/longevityrx/longevityrx.ts +0 -374
  627. package/src/merchants/lookOptic/lookOptic.ts +0 -323
  628. package/src/merchants/mantraBrand/mantraBrand.ts +0 -844
  629. package/src/merchants/medterra/medterra.ts +0 -673
  630. package/src/merchants/modells/modells.ts +0 -543
  631. package/src/merchants/pressedFloral/pressedFloral.ts +0 -728
  632. package/src/merchants/skinPerfection/skinPerfection.ts +0 -385
  633. package/src/merchants/snapSupplements/snapSupplements.ts +0 -328
  634. package/src/merchants/spanx/spanx.ts +0 -810
  635. package/src/merchants/spanx/spanxStaging.ts +0 -936
  636. package/src/merchants/supergoop/supergoop.ts +0 -375
  637. package/src/merchants/uniqueVintage/uniqueVintage.ts +0 -1314
  638. package/src/merchants/venaCbd/venaCbd.ts +0 -407
  639. package/src/merchants/westonJonBoucher/westonJonBoucher.ts +0 -473
  640. package/src/merchants/wineEnthusiast/wineEnthusiast.ts +0 -990
  641. package/src/merchants/wolfMattress/wolfMattress.ts +0 -411
  642. package/src/merchants/wolfTactical/wolfTactical.ts +0 -383
  643. /package/dist/{atomStore-KSoFS3Jj.cjs → AmplitudeOperations-CgIVPUlr.cjs} +0 -0
  644. /package/dist/{atomStore-CZnUUsrr.js → AmplitudeOperations-YpyaR7Mp.js} +0 -0
  645. /package/dist/{locators-fBXS_pxP.js → atomStore-C2OI76yN.js} +0 -0
  646. /package/dist/{locators-0YYZu9n4.cjs → atomStore-DWmT1six.cjs} +0 -0
  647. /package/dist/{utilityTypes-8sETsYPk.js → types-DQoXDiso.js} +0 -0
  648. /package/dist/{utilityTypes-COShxVir.cjs → types-o3zWarRp.cjs} +0 -0
  649. /package/dist/{variantInfo-orXoPBCU.cjs → types.cjs} +0 -0
  650. /package/dist/{variantInfo-DbVxA1yE.js → types.js} +0 -0
  651. /package/src/contexts/{featureFlagServiceContext.tsx → featureFlagServiceContext/featureFlagServiceContext.tsx} +0 -0
  652. /package/src/contexts/{graphqlContext.tsx → graphqlContext/graphqlContext.tsx} +0 -0
  653. /package/src/contexts/{shopifyUrlContext.tsx → shopifyUrlContext/shopifyUrlContext.tsx} +0 -0
  654. /package/src/contexts/{systemSettingsContext.tsx → systemSettingsContext/systemSettingsContext.tsx} +0 -0
  655. /package/src/contexts/{userIdentityContext.tsx → userIdentityContext/userIdentityContext.tsx} +0 -0
  656. /package/src/hooks/{useBlockBackButton.ts → BlockBackButton/useBlockBackButton.ts} +0 -0
  657. /package/src/hooks/{useCustomerSupportHandoff.ts → CustomerSupportHandoff/useCustomerSupportHandoff.ts} +0 -0
  658. /package/src/hooks/{useDebounce.ts → Debounce/useDebounce.ts} +0 -0
  659. /package/src/hooks/{useElementObserver.ts → ElementObserver/useElementObserver.ts} +0 -0
  660. /package/src/hooks/{useGrabAndScroll.ts → GrabAndScroll/useGrabAndScroll.ts} +0 -0
  661. /package/src/hooks/{useImageResolver.ts → ImageResolver/useImageResolver.ts} +0 -0
  662. /package/src/hooks/{useIntersection.ts → Intersection/useIntersection.ts} +0 -0
  663. /package/src/hooks/{useIsSmallScreen.ts → IsSmallScreen/useIsSmallScreen.ts} +0 -0
  664. /package/src/hooks/{useMessageFilter.ts → MessageFilter/useMessageFilter.ts} +0 -0
  665. /package/src/hooks/{useMessageScrollObserver.ts → MessageScrollObserver/useMessageScrollObserver.ts} +0 -0
  666. /package/src/hooks/{useSearchOperations.ts → SearchOperations/useSearchOperations.ts} +0 -0
  667. /package/src/hooks/{useSnapCalculator.ts → SnapCalculator/useSnapCalculator.ts} +0 -0
@@ -1,2596 +0,0 @@
1
- import { FeatureGates, MessageRole, MessageType, ProductExperiment, SpiffyWidgets, getMerchantOrgIdQuery, transformSnakeToCamel, validateGraphQLOrgId, validateOrgConfigResults, validateResponse, validateSuggestion, validateUserEvent } from "./models-UZ6HszfZ.js";
2
- import { OrgShortName, getOrgInfo } from "./types--pr1GQQx.js";
3
- import { configVersion, parseHref } from "./graphql-CjB8wHzm.js";
4
- import { logger_default } from "./api-DjeZXxl_.js";
5
- import { LocalStorageKeys, baseUrlAtom, cdnUrlAtom, contextSourceAtom, envAtom, orgLevelApiKeyAtom, orgShortNameAtom, reactAppNameAtom, useLocalStorage } from "./enviveConfig-CzhTz8Aa.js";
6
- import { getAtomStore } from "./atomStore-D8pjE1vL.js";
7
- import { chatIdAtom, hasParsedVariantInfoAtom, supportedEventAtom, userIdAtom, variantInfoAtom } from "./app-CjsQ2_n-.js";
8
- import { SpiffyMetricsEventName, useAmplitude, useEnviveConfig } from "./amplitudeContext-hY3caPC6.js";
9
- import { DOMObserver, coreSupportedEventRequestToApiRequest, messageFromFormSubmittedEvent, messageFromQueryEvent, messageFromResponse, messageFromSuggestionEvent, messageRequestToCommerceMessageRequest } from "./utils-C9ZSCx12.js";
10
- import { featureFlagServiceAtom, orgIdAtom } from "./graphqlConfig-CYt6tWII.js";
11
- import { PerfMetricsEvents, chatAtom, chatOnToggleAtom, clearUserEventAtom, createResponsePayload, logPerfMetricAtom, messagesAtom, processUserEventAtom, requestFailureAtom, responseStreamingAtom, suggestionsAtom, suggestionsLoadingAtom, userEventQueueAtom, userEventsAtom, userHasRepliedAtom, userQueueEventCountAtom } from "./chat-hcRc4RRd.js";
12
- import { newOrgConfigAtom } from "./org-xMytX--e.js";
13
- import { ProductSorting, addSearchFilterAtom, chatSearchIsLoadingAtom, chatSearchProductSortingAtom, chatSearchProducts, chatSearchStateAtom, clearSearchFiltersAtom, clearSearchServiceFunction, createFilterOption, filteredSearchProductsAtom, formatFilterDisplayName, handleSearchResultsAtom, performSearchAtom, removeSearchFilterAtom, searchAtom, searchFiltersAtom, searchParamsAtom, searchProductSortingAtom, searchSelectedFiltersAtom, setSearchServiceFunction } from "./search-BMOAmrmY.js";
14
- import { autocompleteStateAtom, isFilterOpenAtom } from "./globalSearch-B6THR7Jx.js";
15
- import { useMessageInterceptor } from "./useMessageInterceptor-Bb7YRaWk.js";
16
- import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
17
- import { useAtom, useAtomValue, useSetAtom } from "jotai";
18
- import { Configuration, ContextEnvEnum, ContextSourceEnum, CustomerServiceApi, DefaultApi, FormType, InferenceApi, PLPAttributeCategory, ResponseCategory, ResponseError, SearchApi, UserEventCategory, V1OrgConfigGetSourceEnum } from "@spiffy-ai/commerce-api-client";
19
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
20
- import { v4 } from "uuid";
21
- import UAParser from "ua-parser-js";
22
-
23
- //#region src/contexts/cdnContext.tsx
24
- const CdnContext = createContext(null);
25
- const CdnProvider = ({ children }) => {
26
- const cdnUrl = useAtomValue(cdnUrlAtom) || "https://cdn.spiffy.ai/other";
27
- const getCdnBasePath = useCallback(() => {
28
- return cdnUrl;
29
- }, [cdnUrl]);
30
- const getAssetURL = useCallback((assetName, orgShortName) => {
31
- return `${getCdnBasePath()}/assets/${orgShortName}/${assetName}`;
32
- }, [getCdnBasePath]);
33
- const value = useMemo(() => ({
34
- cdnUrl,
35
- getCdnBasePath,
36
- getAssetURL
37
- }), [
38
- cdnUrl,
39
- getCdnBasePath,
40
- getAssetURL
41
- ]);
42
- return /* @__PURE__ */ jsx(CdnContext.Provider, {
43
- value,
44
- children
45
- });
46
- };
47
- const useCdn = () => {
48
- const context = useContext(CdnContext);
49
- if (!context) throw new Error("useCdn must be used within a CdnProvider");
50
- return context;
51
- };
52
-
53
- //#endregion
54
- //#region src/types/exceptions/sessionExceptions.ts
55
- var SessionRestartRequired = class extends Error {
56
- constructor() {
57
- super("Session restart required");
58
- this.name = "SessionRestartRequired";
59
- }
60
- };
61
-
62
- //#endregion
63
- //#region src/types/exceptions/unsupportedProductExceptions.ts
64
- var UnsupportedProductException = class extends Error {
65
- constructor() {
66
- super("Unsupported product");
67
- this.name = "UnsupportedProduct";
68
- }
69
- };
70
-
71
- //#endregion
72
- //#region src/application/commerce-api.ts
73
- async function errorResponseBody$1(error) {
74
- try {
75
- return await error.response.json();
76
- } catch {
77
- return {};
78
- }
79
- }
80
- async function throwSessionRestartRequiredIf$1(errorMsg, error) {
81
- if (!(error instanceof ResponseError)) {
82
- logger_default.logInfo(errorMsg, error);
83
- throw error;
84
- }
85
- const errorResponse = await errorResponseBody$1(error);
86
- if (errorResponse?.message?.toLowerCase() === "unsupported product" || errorResponse?.app_code?.toUpperCase() === "PRODUCT_NOT_FOUND") throw new UnsupportedProductException();
87
- else if (errorResponse?.app_code?.toUpperCase() === "RESTART_SESSION" || errorResponse?.sub_code?.toUpperCase() === "NOT_FOUND") {
88
- logger_default.logInfo("Session does not exist. Re-start session", error, error.response, errorResponse);
89
- throw new SessionRestartRequired();
90
- }
91
- logger_default.logInfo(errorMsg, error);
92
- throw error;
93
- }
94
- var CommerceApiClient = class CommerceApiClient {
95
- static {
96
- this.getInstance = () => {
97
- if (!CommerceApiClient.instance) CommerceApiClient.instance = new CommerceApiClient();
98
- return CommerceApiClient.instance;
99
- };
100
- }
101
- constructor(basePath) {
102
- this.suggestionsAbortController = new AbortController();
103
- this.responsesAbortController = new AbortController();
104
- const baseUrl = getAtomStore().get(baseUrlAtom);
105
- const config = new Configuration({
106
- basePath: basePath || baseUrl,
107
- headers: {
108
- "Content-Type": "application/json",
109
- Accept: "application/json"
110
- }
111
- });
112
- this.defaultApi = new DefaultApi(config);
113
- this.inferenceApi = new InferenceApi(config);
114
- this.customerServiceApi = new CustomerServiceApi(config);
115
- }
116
- static {
117
- this.resolveUrl = async (url) => {
118
- const atomStore = getAtomStore();
119
- const orgShortName = atomStore.get(orgShortNameAtom);
120
- const orgId = atomStore.get(orgIdAtom);
121
- const userId = atomStore.get(userIdAtom);
122
- const chatId = atomStore.get(chatIdAtom);
123
- const source = atomStore.get(contextSourceAtom);
124
- const env = atomStore.get(envAtom);
125
- const featureFlagService = atomStore.get(featureFlagServiceAtom);
126
- const context = {
127
- user_id: userId ?? "",
128
- org_id: orgId ?? "",
129
- org_short_name: orgShortName ?? "",
130
- chat_id: chatId ?? "",
131
- source: source ?? ContextSourceEnum.App,
132
- env: env ?? ContextEnvEnum.Dev
133
- };
134
- const featureGates = featureFlagService?.featureFlagService?.getFeatureFlags() || {};
135
- const urlResolvingRequest = {
136
- url,
137
- context,
138
- feature_gates: featureGates
139
- };
140
- return await (await CommerceApiClient.getInstance().inferenceApi.v1UrlResolvingPostRaw({ UrlResolvingRequest: urlResolvingRequest })).raw.json();
141
- };
142
- }
143
- static {
144
- this.reportSession = async (reportRequest) => {
145
- await CommerceApiClient.getInstance().defaultApi.v1ChatsReportSessionIdPost({ ReportSessionRequest: reportRequest });
146
- };
147
- }
148
- static {
149
- this.getNextResponses = async (payload) => {
150
- try {
151
- return (await CommerceApiClient.getInstance().inferenceApi.v1NextResponsesPost({ NextMessageRequest: messageRequestToCommerceMessageRequest(payload) })).map((resp) => validateResponse(resp)).map((resp) => messageFromResponse(resp)).filter((m) => m != null);
152
- } catch (err) {
153
- logger_default.logInfo("Failed to get next responses", err, {
154
- payloadContext: payload?.context,
155
- userEvents: payload?.userEvents
156
- });
157
- await throwSessionRestartRequiredIf$1("Failed to get next responses", err);
158
- return [];
159
- }
160
- };
161
- }
162
- static {
163
- this.getNextResponseStreaming = (payload) => {
164
- async function* generate(inferenceApi, abortController) {
165
- try {
166
- const response = await inferenceApi.v1NextResponsesPostRaw({ NextMessageRequest: messageRequestToCommerceMessageRequest(payload) }, { signal: abortController.signal });
167
- if (!response.raw.body) {
168
- logger_default.logError("[spiffy-ai] No body in the streamed response", void 0, { response: response.raw });
169
- return;
170
- }
171
- const reader = response.raw.body.getReader();
172
- const decoder = new TextDecoder("utf-8");
173
- let partial = "";
174
- const safeParse = (line) => {
175
- try {
176
- return JSON.parse(line);
177
- } catch (err) {
178
- logger_default.logError("[spiffy-ai] Error parsing streamed line", err, {
179
- line,
180
- partial
181
- });
182
- partial = line;
183
- return partial;
184
- }
185
- };
186
- const processChunk = (chunk) => {
187
- return `${partial}${chunk}`.split("\n").map((line) => line.replace(/^data: /, "").trim()).filter((line) => line !== "" && line !== "[DONE]").map(safeParse).filter((v) => v);
188
- };
189
- while (true) {
190
- const { done, value } = await reader.read();
191
- if (done) break;
192
- const chunk = decoder.decode(value);
193
- const parsedLines = processChunk(chunk);
194
- for (const parsedLine of parsedLines) {
195
- const validatedResponse = validateResponse(parsedLine);
196
- if (validatedResponse) yield validatedResponse;
197
- }
198
- }
199
- } catch (error) {
200
- logger_default.logError("[spiffy-ai] Failed to get next streaming responses", error, {
201
- payloadContext: payload?.context,
202
- userEvents: payload?.userEvents
203
- });
204
- await throwSessionRestartRequiredIf$1("Failed to get next streaming responses", error);
205
- }
206
- }
207
- CommerceApiClient.getInstance().responsesAbortController.abort();
208
- CommerceApiClient.getInstance().responsesAbortController = new AbortController();
209
- return generate(CommerceApiClient.getInstance().inferenceApi, CommerceApiClient.getInstance().responsesAbortController);
210
- };
211
- }
212
- static {
213
- this.getNextSuggestions = async (payload) => {
214
- try {
215
- CommerceApiClient.getInstance().suggestionsAbortController.abort();
216
- CommerceApiClient.getInstance().suggestionsAbortController = new AbortController();
217
- return (await CommerceApiClient.getInstance().inferenceApi.v1NextSuggestionsPost({ NextMessageRequest: messageRequestToCommerceMessageRequest(payload) }, { signal: CommerceApiClient.getInstance().suggestionsAbortController.signal })).map((resp) => validateSuggestion(resp)).filter((suggestion) => suggestion != null);
218
- } catch (error) {
219
- logger_default.logInfo("Failed to get suggestions", error, {
220
- payloadContext: payload?.context,
221
- userEvents: payload?.userEvents
222
- });
223
- await throwSessionRestartRequiredIf$1("Failed to get suggestions", error);
224
- return [];
225
- }
226
- };
227
- }
228
- static {
229
- this.getResponses = async (orgId, chatId, userId) => {
230
- let data = {
231
- responses: [],
232
- suggestions: [],
233
- user_events: []
234
- };
235
- const request = {
236
- org_id: orgId,
237
- chat_id: chatId,
238
- user_id: userId
239
- };
240
- try {
241
- data = await CommerceApiClient.getInstance().defaultApi.v1GetSessionMessages(request);
242
- } catch (error) {
243
- await throwSessionRestartRequiredIf$1("Failed to get chat responses", error);
244
- }
245
- const responses = data?.responses?.map((turn) => turn.map((response) => validateResponse(response)).filter((response) => response != null));
246
- const suggestions = data?.suggestions.map((suggestion) => validateSuggestion(suggestion)).filter((suggestion) => suggestion != null);
247
- const userEvents = data?.user_events.map((event) => validateUserEvent(event)).filter((event) => event != null);
248
- const formSubmittedUserEventsFormIds = userEvents.filter((event) => event.category === UserEventCategory.FormSubmitted).map((event) => event.attributes.formResponseId);
249
- const assistantMessages = responses.map((turn) => turn.filter((response) => !(response.category === ResponseCategory.Form && formSubmittedUserEventsFormIds.includes(response.id))).map((response) => messageFromResponse(response)).filter((message) => message != null)).filter((turn) => turn.length > 0);
250
- const userMessages = userEvents.map((event) => {
251
- if ([UserEventCategory.QueryTyped, UserEventCategory.Search].includes(event.category)) return [messageFromQueryEvent(event)];
252
- if (event.category === UserEventCategory.SuggestionClicked) return [messageFromSuggestionEvent(event, suggestions)];
253
- if (event.category === UserEventCategory.FormSubmitted) {
254
- const formResponse = responses.flat().find((response) => response.id === event.attributes.formResponseId && event.attributes.formType !== FormType.Escalation);
255
- if (formResponse && formResponse.category === ResponseCategory.Form) return [messageFromFormSubmittedEvent(event, formResponse.attributes)];
256
- }
257
- return [];
258
- }).filter((message) => message.length > 0);
259
- const sortedMessages = [...assistantMessages, ...userMessages].sort((a, b) => new Date(a[0].createdAt).getTime() - new Date(b[0].createdAt).getTime());
260
- return {
261
- responses,
262
- userEvents,
263
- suggestions,
264
- messages: sortedMessages
265
- };
266
- };
267
- }
268
- static {
269
- this.isSupportedEvent = async (payload) => {
270
- try {
271
- const httpResponseText = await (await CommerceApiClient.getInstance().inferenceApi.v1SupportedEventPostRaw({ SupportedEventRequest: coreSupportedEventRequestToApiRequest(payload) })).raw.text();
272
- const httpResponseJson = JSON.parse(httpResponseText);
273
- return {
274
- ...httpResponseJson,
275
- numberOfReviews: httpResponseJson.num_of_reviews,
276
- merchant_tags: httpResponseJson.merchant_tags || []
277
- };
278
- } catch (err) {
279
- logger_default.logError("Failed to get response for v1SupportedEventPost", { err });
280
- return {
281
- supported: false,
282
- ready: false,
283
- category: void 0,
284
- collections: [],
285
- numberOfReviews: void 0,
286
- top_category: void 0,
287
- merchant_tags: []
288
- };
289
- }
290
- };
291
- }
292
- static {
293
- this.identifyUser = async (spiffyUserId, merchantUserId, uaDetails) => {
294
- try {
295
- await CommerceApiClient.getInstance().defaultApi.v1AnalyticsIdentifyPost({ AnalyticsIdentifyRequest: {
296
- user_id: spiffyUserId,
297
- os_name: uaDetails.os,
298
- os_version: uaDetails.osVersion,
299
- platform: uaDetails.os,
300
- device_id: uaDetails.deviceModel,
301
- device_brand: uaDetails.deviceBrand,
302
- device_manufacturer: uaDetails.deviceManufacturer,
303
- device_model: uaDetails.deviceModel,
304
- user_properties: {
305
- cdp_user_id: merchantUserId,
306
- browser: uaDetails.browser,
307
- browser_version: uaDetails.browserVersion,
308
- user_agent: uaDetails.userAgent
309
- }
310
- } });
311
- } catch (err) {
312
- logger_default.logError("Failed to identify user", err);
313
- }
314
- };
315
- }
316
- static {
317
- this.mapContextSourceToV1OrgConfigGetSource = (source) => {
318
- if (source === void 0) return void 0;
319
- switch (source) {
320
- case ContextSourceEnum.Fork: return V1OrgConfigGetSourceEnum.Fork;
321
- case ContextSourceEnum.Playground: return V1OrgConfigGetSourceEnum.Playground;
322
- case ContextSourceEnum.App: return V1OrgConfigGetSourceEnum.App;
323
- case ContextSourceEnum.Test: return V1OrgConfigGetSourceEnum.Test;
324
- default: return source;
325
- }
326
- };
327
- }
328
- static {
329
- this.getOrgConfig = async (user_id) => {
330
- try {
331
- const atomStore = getAtomStore();
332
- const reactAppName = atomStore.get(reactAppNameAtom);
333
- const contextSource = atomStore.get(contextSourceAtom);
334
- const featureFlagService = atomStore.get(featureFlagServiceAtom);
335
- const request = {
336
- namespace: reactAppName,
337
- user_id,
338
- source: this.mapContextSourceToV1OrgConfigGetSource(contextSource),
339
- include_experiments: Object.values(ProductExperiment),
340
- include_feature_gates: Object.entries(featureFlagService?.featureFlagService?.getFeatureFlags() || {}).filter(([, isEnabled]) => isEnabled).map(([featureGateName]) => featureGateName)
341
- };
342
- const response = await CommerceApiClient.getInstance().defaultApi.v1OrgConfigGet(request);
343
- return validateOrgConfigResults(response);
344
- } catch (err) {
345
- logger_default.logError(`Failed to get org config`, err, { err });
346
- return;
347
- }
348
- };
349
- }
350
- static {
351
- this.addNoteToLatestConversation = async (spiffyUserId, email, customerServiceProvider) => {
352
- logger_default.logInfo(`addNoteToLatestConversation - user_id=${spiffyUserId} email=${email} customer_service_provider=${customerServiceProvider}`);
353
- try {
354
- await CommerceApiClient.getInstance().customerServiceApi.v1CustserviceAddNoteToLatestConversationPost({ AddNoteToLatestConversationRequest: {
355
- spiffy_user_id: spiffyUserId,
356
- email,
357
- customer_service_provider: customerServiceProvider
358
- } });
359
- } catch (err) {
360
- logger_default.logError("Failed to add note to latest conversation", { err });
361
- }
362
- };
363
- }
364
- static {
365
- this.getCustomerServiceApi = () => CommerceApiClient.getInstance().customerServiceApi;
366
- }
367
- };
368
- var commerce_api_default = CommerceApiClient;
369
-
370
- //#endregion
371
- //#region src/hooks/useAmplitudeOperations.ts
372
- const useAmplitudeTracking = () => {
373
- const { trackEvent, isReady } = useAmplitude();
374
- const [loading, setLoading] = useState(false);
375
- const [error, setError] = useState(null);
376
- return {
377
- track: useCallback(async (eventName, eventProps) => {
378
- if (!isReady) return;
379
- setLoading(true);
380
- setError(null);
381
- try {
382
- await trackEvent({
383
- eventName,
384
- eventProps
385
- });
386
- } catch (err) {
387
- setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Tracking failed"));
388
- throw err;
389
- } finally {
390
- setLoading(false);
391
- }
392
- }, [trackEvent, isReady]),
393
- loading,
394
- error,
395
- isReady
396
- };
397
- };
398
-
399
- //#endregion
400
- //#region src/hooks/useBlockBackButton.ts
401
- const useBlockBackButton = (enabled, callback) => {
402
- useEffect(() => {
403
- if (enabled && window) {
404
- if (window.history.scrollRestoration) window.history.scrollRestoration = "manual";
405
- window.history.pushState(null, document.title, window.location.href);
406
- window.onpopstate = (e) => {
407
- e.preventDefault();
408
- window.history.pushState(null, document.title, window.location.href);
409
- callback?.();
410
- };
411
- }
412
- return () => {
413
- if (enabled && window) {
414
- window.history.back();
415
- window.onpopstate = null;
416
- window.history.scrollRestoration = "auto";
417
- }
418
- };
419
- }, [enabled]);
420
- };
421
-
422
- //#endregion
423
- //#region src/hooks/useCdnOperations.ts
424
- const useCdnUrl = () => {
425
- const { cdnUrl } = useCdn();
426
- return cdnUrl;
427
- };
428
- const useCdnBasePath = () => {
429
- const { getCdnBasePath } = useCdn();
430
- return getCdnBasePath();
431
- };
432
- const useAssetUrl = (assetName, orgShortName) => {
433
- const { getAssetURL } = useCdn();
434
- return getAssetURL(assetName, orgShortName);
435
- };
436
-
437
- //#endregion
438
- //#region src/hooks/useChatToggle.ts
439
- const useChatToggle = () => {
440
- const onToggle = useSetAtom(chatOnToggleAtom);
441
- const { isOpen } = useAtomValue(chatAtom);
442
- const { trackEvent } = useAmplitude();
443
- const toggle = (triggerLocation, triggerId) => {
444
- if (!isOpen) trackEvent({
445
- eventName: SpiffyMetricsEventName.ChatComponentExpanded,
446
- eventProps: { message_metadata: {
447
- trigger_location: triggerLocation,
448
- trigger_id: triggerId
449
- } }
450
- });
451
- else trackEvent({
452
- eventName: SpiffyMetricsEventName.ChatComponentCollapsed,
453
- eventProps: { message_metadata: {
454
- trigger_location: triggerLocation,
455
- trigger_id: triggerId
456
- } }
457
- });
458
- onToggle();
459
- };
460
- const openChat = (triggerLocation, triggerId) => {
461
- if (!isOpen) toggle(triggerLocation, triggerId);
462
- };
463
- const closeChat = (triggerLocation, triggerId) => {
464
- if (isOpen) toggle(triggerLocation, triggerId);
465
- };
466
- return {
467
- toggle,
468
- isOpen,
469
- openChat,
470
- closeChat
471
- };
472
- };
473
-
474
- //#endregion
475
- //#region src/hooks/useChatToggleAnalytics.ts
476
- const useChatToggleAnalytics = () => {
477
- const setChatOnToggle = useSetAtom(chatOnToggleAtom);
478
- const { track } = useAmplitudeTracking();
479
- const toggleChat = (triggerLocation) => {
480
- setChatOnToggle(triggerLocation, track);
481
- };
482
- return { toggleChat };
483
- };
484
-
485
- //#endregion
486
- //#region src/hooks/useCustomerSupportHandoff.ts
487
- /**
488
- * Hook to call the `click` method of the merchant's customer support chat widget.
489
- *
490
- * @param onSwitchToAgent a function to override the function returned by the hook. This is mainly to
491
- * preserve backward compatibility for merchants not using Kustomer and will be removed when all
492
- * CS integrations are handled.
493
- *
494
- * @returns a function that searches for the customer support chat widget and calls the `click` method.
495
- */
496
- const useCustomerSupportHandoff = (onSwitchToAgent) => {
497
- const onKustomerSwitch = useCallback(() => {
498
- const kustomerElement = document.getElementById("kustomer-ui-sdk-iframe");
499
- if (kustomerElement == null || !(kustomerElement instanceof HTMLIFrameElement)) {
500
- logger_default.logError("[spiffy-ai] Kustomer iFrame element not found", void 0);
501
- return;
502
- }
503
- const kustomerButton = kustomerElement.contentWindow?.document?.getElementById("rootChatIcon");
504
- if (kustomerButton == null) {
505
- logger_default.logError("[spiffy-ai] Kustomer button not found", void 0);
506
- return;
507
- }
508
- kustomerButton.click();
509
- }, []);
510
- if (onSwitchToAgent != null) return { onSwitch: onSwitchToAgent };
511
- return { onSwitch: onKustomerSwitch };
512
- };
513
-
514
- //#endregion
515
- //#region src/hooks/useDebounce.ts
516
- function useDebounce(value, delay) {
517
- const [debouncedValue, setDebouncedValue] = useState(value);
518
- useEffect(() => {
519
- const handler = setTimeout(() => {
520
- setDebouncedValue(value);
521
- }, delay);
522
- return () => {
523
- clearTimeout(handler);
524
- };
525
- }, [value, delay]);
526
- return debouncedValue;
527
- }
528
-
529
- //#endregion
530
- //#region src/hooks/useElementObserver.ts
531
- const useElementObserver = (selector) => {
532
- const INITIAL_RENDER_STATE = true;
533
- const eoRef = useRef(DOMObserver.add(selector));
534
- const [renderBlocked, setRenderBlocked] = useState(INITIAL_RENDER_STATE);
535
- /**
536
- * Fired every time the HTML element changes.
537
- *
538
- * @param fn
539
- */
540
- const onChange = (fn) => {
541
- eoRef.current?.registerOnChange(fn);
542
- };
543
- /**
544
- * Fired when the HTML element is added to the DOM.
545
- *
546
- * @param fn
547
- */
548
- const onAdd = (fn) => {
549
- eoRef.current?.registerOnAdd(fn);
550
- };
551
- /**
552
- * Fired when the HTML element is removed from the DOM.
553
- *
554
- * @param fn
555
- */
556
- const onRemove = (fn) => {
557
- eoRef.current?.registerOnRemove(fn);
558
- };
559
- /**
560
- * Fired when the class of the HTML element changes.
561
- *
562
- * @param fn
563
- */
564
- const onClassChange = (fn) => {
565
- eoRef.current?.registerOnclassChange(fn);
566
- };
567
- /**
568
- * Fired when a class is added to the HTML element.
569
- *
570
- * @param className
571
- * @param fn
572
- */
573
- const onClassAdded = (className, fn) => {
574
- eoRef.current?.registerOnClassAdded(className, fn);
575
- };
576
- /**
577
- * Fired when a class is removed from the HTML element.
578
- *
579
- * @param className
580
- * @param fn
581
- */
582
- const onClassRemoved = (className, fn) => {
583
- eoRef.current?.registerOnClassRemoved(className, fn);
584
- };
585
- /**
586
- * Fired when a child element is added to the HTML element.
587
- *
588
- * @param fn
589
- */
590
- const onAddChild = (fn) => {
591
- eoRef.current?.registerOnAddChild(fn);
592
- };
593
- /**
594
- * Fired when a child element is removed from the HTML element.
595
- *
596
- * @param fn
597
- */
598
- const onRemoveChild = (fn) => {
599
- eoRef.current?.registerOnRemoveChild(fn);
600
- };
601
- /**
602
- * Allows hooking event listeners to the HTML element, such as `focus`, `blur`, etc.
603
- *
604
- * @param event
605
- * @param fn
606
- */
607
- const onEvent = (event, fn) => {
608
- eoRef.current.registerEvent(event, fn);
609
- };
610
- /**
611
- * Useful when rendering a React.js component inside the HTML element.
612
- *
613
- * @param fn
614
- * @returns
615
- */
616
- const render = (fn) => {
617
- if (!renderBlocked) return eoRef.current.render(fn);
618
- };
619
- /**
620
- * Checks if the element exists in the DOM.
621
- *
622
- * @returns
623
- */
624
- const exists = () => !!eoRef.current.getNode();
625
- /**
626
- * Checks if rendering is unblocked.
627
- *
628
- * @returns
629
- */
630
- const isRendered = () => !renderBlocked;
631
- /**
632
- * Triggers an event for the HTML element.
633
- *
634
- * @param event
635
- */
636
- const fire = (event) => {
637
- eoRef.current.fire(event);
638
- };
639
- /**
640
- * Shows the HTML element.
641
- *
642
- * @returns
643
- */
644
- const show = () => eoRef.current.show();
645
- /**
646
- * Hides the HTML element.
647
- *
648
- * @returns
649
- */
650
- const hide = () => eoRef.current.hide();
651
- /**
652
- * Blocks the rendering of elements.
653
- *
654
- * @returns
655
- */
656
- const blockRendering = () => setRenderBlocked(true);
657
- /**
658
- * Unblocks the rendering of elements.
659
- *
660
- * @returns
661
- */
662
- const unblockRendering = () => setRenderBlocked(false);
663
- /**
664
- * Applies CSS styles to the HTML element.
665
- *
666
- * @param styles
667
- */
668
- const applyStyle = (styles) => {
669
- const node = eoRef?.current?.getNode();
670
- node && Object.assign(node.style, styles);
671
- };
672
- useEffect(() => {
673
- eoRef.current.init();
674
- eoRef.current.registerOnReset(() => setRenderBlocked(INITIAL_RENDER_STATE));
675
- DOMObserver.observe();
676
- return () => DOMObserver.remove(selector);
677
- }, [selector.getPattern()]);
678
- return {
679
- targetNode: eoRef.current.getNode(),
680
- onChange,
681
- onAdd,
682
- onRemove,
683
- onClassChange,
684
- onClassAdded,
685
- onClassRemoved,
686
- onAddChild,
687
- onRemoveChild,
688
- onEvent,
689
- blockRendering,
690
- unblockRendering,
691
- exists,
692
- isRendered,
693
- render,
694
- fire,
695
- show,
696
- hide,
697
- applyStyle
698
- };
699
- };
700
-
701
- //#endregion
702
- //#region src/hooks/useGrabAndScroll.ts
703
- const animateHorizontalScroll = ({ element, duration, targetScroll, multiply = 1, direction, callback, offset = 0 }) => {
704
- const start = element.scrollLeft;
705
- const distance = (targetScroll - start) * multiply;
706
- const startTime = performance.now();
707
- function easeOutSine(x) {
708
- return Math.sin(x * Math.PI / 2);
709
- }
710
- function scrollStep(currentTime) {
711
- const timeElapsed = currentTime - startTime;
712
- const progress = Math.min(timeElapsed / duration, 1);
713
- const easing = easeOutSine(progress);
714
- const step = start + distance * easing;
715
- const canScroll = (direction === "rt" ? element.scrollLeft < step : element.scrollLeft > step) || !direction;
716
- if (step > 0 && canScroll) element.scrollTo(step, 0);
717
- if (timeElapsed < duration) requestAnimationFrame(scrollStep);
718
- else if (element.scrollLeft + offset === element.scrollWidth) callback?.("rt");
719
- else if (element.scrollLeft <= 1) callback?.("lt");
720
- else callback?.("ct");
721
- }
722
- requestAnimationFrame(scrollStep);
723
- };
724
- const useGrabAndScroll = (enabled, chunkWidth, speed = 400, offset = 0) => {
725
- const containerRef = useRef(null);
726
- const [leftArrow, setLeftArrow] = useState(false);
727
- const [rightArrow, setRightArrow] = useState(true);
728
- const handleArrows = (position) => {
729
- switch (position) {
730
- case "lt":
731
- setLeftArrow(false);
732
- setRightArrow(true);
733
- break;
734
- case "rt":
735
- setLeftArrow(true);
736
- setRightArrow(false);
737
- break;
738
- default:
739
- setLeftArrow(true);
740
- setRightArrow(true);
741
- }
742
- };
743
- const animationTrigger = () => {
744
- if (enabled && containerRef.current) {
745
- const dist = (containerRef?.current?.scrollLeft || 0) / chunkWidth;
746
- const targetScroll = chunkWidth * (Math.floor(dist) + (dist % 1 > .5 ? 1 : 0));
747
- animateHorizontalScroll({
748
- element: containerRef.current,
749
- targetScroll,
750
- duration: speed,
751
- offset,
752
- callback: handleArrows
753
- });
754
- }
755
- };
756
- const onNext = (cardsToSlide) => {
757
- if (containerRef.current) {
758
- const targetScroll = containerRef.current.scrollLeft + chunkWidth;
759
- animateHorizontalScroll({
760
- element: containerRef.current,
761
- targetScroll,
762
- duration: speed,
763
- direction: "rt",
764
- multiply: cardsToSlide,
765
- offset,
766
- callback: handleArrows
767
- });
768
- }
769
- };
770
- const onPrevious = (cardsToSlide) => {
771
- if (containerRef.current) {
772
- const targetScroll = containerRef.current.scrollLeft - chunkWidth;
773
- animateHorizontalScroll({
774
- element: containerRef.current,
775
- targetScroll,
776
- duration: speed,
777
- direction: "lt",
778
- multiply: cardsToSlide,
779
- offset,
780
- callback: handleArrows
781
- });
782
- }
783
- };
784
- return {
785
- containerRef,
786
- leftArrow,
787
- rightArrow,
788
- animationTrigger,
789
- onNext,
790
- onPrevious
791
- };
792
- };
793
-
794
- //#endregion
795
- //#region src/contexts/graphqlContext.tsx
796
- const GraphQLContext = createContext(null);
797
- const colorsAndFrontendConfigQuery = () => `
798
- query ($version: String = "${configVersion()}") {
799
- me {
800
- getProductsConfigByVersion(version: $version) {
801
- frontend { values }
802
- colors { values }
803
- }
804
- }
805
- }
806
- `;
807
- const GraphQLProvider = ({ children }) => {
808
- const apiKey = useAtomValue(orgLevelApiKeyAtom);
809
- const baseUrl = useAtomValue(baseUrlAtom);
810
- const isReady = Boolean(apiKey && baseUrl);
811
- const executeQuery = useCallback(async (query, variables) => {
812
- if (!isReady) throw new Error("GraphQL client not ready - missing apiKey or baseUrl");
813
- const response = await fetch(`${baseUrl}/v1/graphql`, {
814
- method: "POST",
815
- headers: {
816
- "Content-Type": "application/json",
817
- Authorization: `Bearer ${apiKey}`
818
- },
819
- body: JSON.stringify({
820
- query,
821
- variables
822
- })
823
- });
824
- if (!response.ok) throw new Error(`GraphQL request failed: ${response.statusText}`);
825
- const result = await response.json();
826
- if (result.errors) throw new Error(`GraphQL errors: ${JSON.stringify(result.errors)}`);
827
- return result.data;
828
- }, [
829
- apiKey,
830
- baseUrl,
831
- isReady
832
- ]);
833
- const getOrgId = useCallback(async () => {
834
- const response = await executeQuery(getMerchantOrgIdQuery);
835
- return validateGraphQLOrgId(response.me.org?.id);
836
- }, [executeQuery]);
837
- const getColorsAndFrontendConfig = useCallback(async () => {
838
- try {
839
- const query = await colorsAndFrontendConfigQuery();
840
- if (!query) throw new Error("Colors and frontend config query is not defined");
841
- const response = await executeQuery(query);
842
- const colorsConfig = response.me.getProductsConfigByVersion?.colors?.values;
843
- const frontendConfig = response.me.getProductsConfigByVersion?.frontend?.values;
844
- const transformedColorConfig = transformSnakeToCamel(colorsConfig);
845
- const transformedFrontendConfig = transformSnakeToCamel(frontendConfig);
846
- return {
847
- colorsConfig: transformedColorConfig,
848
- frontendConfig: transformedFrontendConfig
849
- };
850
- } catch (err) {
851
- logger_default.logError("Error fetching graphql colors and frontend config", err);
852
- return {
853
- colorsConfig: void 0,
854
- frontendConfig: void 0
855
- };
856
- }
857
- }, [executeQuery]);
858
- const value = useMemo(() => ({
859
- executeQuery,
860
- getOrgId,
861
- getColorsAndFrontendConfig,
862
- isReady
863
- }), [
864
- executeQuery,
865
- getOrgId,
866
- getColorsAndFrontendConfig,
867
- isReady
868
- ]);
869
- return /* @__PURE__ */ jsx(GraphQLContext.Provider, {
870
- value,
871
- children
872
- });
873
- };
874
- const useGraphQLClient = () => {
875
- const context = useContext(GraphQLContext);
876
- if (!context) throw new Error("useGraphQLClient must be used within a GraphQLProvider");
877
- return context;
878
- };
879
-
880
- //#endregion
881
- //#region src/hooks/useGraphQLConfig.ts
882
- const useColorsAndFrontendConfig = () => {
883
- const { getColorsAndFrontendConfig, isReady } = useGraphQLClient();
884
- const [data, setData] = useState({});
885
- const [loading, setLoading] = useState(false);
886
- const [error, setError] = useState(null);
887
- const fetchConfig = useCallback(async () => {
888
- if (!isReady) return;
889
- setLoading(true);
890
- setError(null);
891
- try {
892
- const result = await getColorsAndFrontendConfig();
893
- setData(result);
894
- } catch (err) {
895
- setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Unknown error"));
896
- } finally {
897
- setLoading(false);
898
- }
899
- }, [getColorsAndFrontendConfig, isReady]);
900
- useEffect(() => {
901
- fetchConfig();
902
- }, [fetchConfig]);
903
- return {
904
- data,
905
- loading,
906
- error,
907
- refetch: fetchConfig
908
- };
909
- };
910
- const useOrgId = () => {
911
- const { getOrgId, isReady } = useGraphQLClient();
912
- const [orgId, setOrgId] = useState();
913
- const [loading, setLoading] = useState(false);
914
- const [error, setError] = useState(null);
915
- useEffect(() => {
916
- if (!isReady) return;
917
- const fetchOrgId = async () => {
918
- setLoading(true);
919
- setError(null);
920
- try {
921
- const id = await getOrgId();
922
- setOrgId(id);
923
- } catch (err) {
924
- setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Unknown error"));
925
- } finally {
926
- setLoading(false);
927
- }
928
- };
929
- fetchOrgId();
930
- }, [getOrgId, isReady]);
931
- return {
932
- orgId,
933
- loading,
934
- error
935
- };
936
- };
937
-
938
- //#endregion
939
- //#region src/contexts/userIdentityContext.tsx
940
- const getUserAgentDetails = () => {
941
- const result = new UAParser().getResult();
942
- return {
943
- os: result?.os?.name,
944
- osVersion: result?.os?.version,
945
- deviceBrand: result?.device?.vendor,
946
- deviceManufacturer: result?.device?.vendor,
947
- deviceModel: result?.device?.model,
948
- browser: result?.browser?.name,
949
- browserVersion: result?.browser?.version,
950
- userAgent: result?.ua
951
- };
952
- };
953
- const UserIdentityContext = createContext(void 0);
954
- const UserIdentityProvider = ({ children }) => {
955
- const { getItem, setItem, isAvailable: localStorageIsReady } = useLocalStorage();
956
- const [isReady, setIsReady] = useState(false);
957
- useEffect(() => {
958
- setIsReady(localStorageIsReady);
959
- }, [localStorageIsReady]);
960
- const USER_ID_OVERRIDE_KEY = "v1-spiffy-user-id-override";
961
- const USER_ID_DEFAULT_KEY = "v1-spiffy-user-id-default";
962
- const getUserIdOverrideFromLocalStorage = useCallback(() => {
963
- return getItem(USER_ID_OVERRIDE_KEY) ?? void 0;
964
- }, [getItem]);
965
- const getUserIdDefaultFromLocalStorage = useCallback(() => {
966
- return getItem(USER_ID_DEFAULT_KEY) ?? void 0;
967
- }, [getItem]);
968
- const setUserIdDefaultInLocalStorage = useCallback((userId) => {
969
- logger_default.logInfo(`setUserIdDefaultInLocalStorage - Setting user_id=${userId}`);
970
- setItem(USER_ID_DEFAULT_KEY, userId);
971
- return userId;
972
- }, [setItem, USER_ID_DEFAULT_KEY]);
973
- const setUserIdOverrideInLocalStorage = useCallback((userId) => {
974
- logger_default.logInfo(`setUserIdOverrideInLocalStorage - Setting user_id=${userId}`);
975
- setItem(USER_ID_OVERRIDE_KEY, userId);
976
- return userId;
977
- }, [setItem, USER_ID_OVERRIDE_KEY]);
978
- const clearUserIdOverrideInLocalStorage = useCallback(() => {
979
- logger_default.logInfo(`clearUserIdOverrideInLocalStorage - Clearing user_id`);
980
- setItem(USER_ID_OVERRIDE_KEY, "");
981
- }, [setItem, USER_ID_OVERRIDE_KEY]);
982
- const getUserIdOrDefault = useCallback(() => {
983
- const userIdOverride = getUserIdOverrideFromLocalStorage();
984
- if (userIdOverride) return userIdOverride;
985
- const defaultUserId = getUserIdDefaultFromLocalStorage();
986
- if (defaultUserId) return defaultUserId;
987
- return setUserIdDefaultInLocalStorage(`spiffy-user-id-${v4()}`);
988
- }, [
989
- getUserIdOverrideFromLocalStorage,
990
- getUserIdDefaultFromLocalStorage,
991
- setUserIdDefaultInLocalStorage
992
- ]);
993
- const identifyUser = useCallback(async () => {
994
- if (!isReady) {
995
- logger_default.logWarn("[UserIdentityContext] Context not ready, skipping identifyUser", void 0);
996
- return;
997
- }
998
- try {
999
- const cdpUserId = "UNKNOWN_CDP_USER_ID";
1000
- const userId = getUserIdOrDefault();
1001
- const userAgentDetails = getUserAgentDetails();
1002
- await commerce_api_default.identifyUser(userId, cdpUserId, userAgentDetails);
1003
- } catch (error) {
1004
- logger_default.logError("[spiffy-ai] Error identifying user", error);
1005
- }
1006
- }, [isReady, getUserIdOrDefault]);
1007
- const value = useMemo(() => ({
1008
- identifyUser,
1009
- getUserIdOrDefault,
1010
- getUserIdOverrideFromLocalStorage,
1011
- getUserIdDefaultFromLocalStorage,
1012
- setUserIdDefaultInLocalStorage,
1013
- setUserIdOverrideInLocalStorage,
1014
- clearUserIdOverrideInLocalStorage,
1015
- isReady
1016
- }), [
1017
- identifyUser,
1018
- getUserIdOrDefault,
1019
- getUserIdOverrideFromLocalStorage,
1020
- getUserIdDefaultFromLocalStorage,
1021
- setUserIdDefaultInLocalStorage,
1022
- setUserIdOverrideInLocalStorage,
1023
- clearUserIdOverrideInLocalStorage,
1024
- isReady
1025
- ]);
1026
- return /* @__PURE__ */ jsx(UserIdentityContext.Provider, {
1027
- value,
1028
- children
1029
- });
1030
- };
1031
- const useUserIdentity = () => {
1032
- const context = useContext(UserIdentityContext);
1033
- if (!context) throw new Error("useUserIdentity must be used within a UserIdentityProvider");
1034
- return context;
1035
- };
1036
-
1037
- //#endregion
1038
- //#region src/hooks/useIdentifyUser.ts
1039
- const useIdentifyUser = () => {
1040
- const { identifyUser, isReady } = useUserIdentity();
1041
- const [loading, setLoading] = useState(false);
1042
- const [error, setError] = useState(null);
1043
- const executeIdentifyUser = useCallback(async () => {
1044
- if (!isReady) {
1045
- setError(/* @__PURE__ */ new Error("UserIdentityContext not ready."));
1046
- return;
1047
- }
1048
- setLoading(true);
1049
- setError(null);
1050
- try {
1051
- await identifyUser();
1052
- } catch (err) {
1053
- setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Unknown error during user identification."));
1054
- throw err;
1055
- } finally {
1056
- setLoading(false);
1057
- }
1058
- }, [identifyUser, isReady]);
1059
- return {
1060
- loading,
1061
- error,
1062
- executeIdentifyUser,
1063
- isReady
1064
- };
1065
- };
1066
-
1067
- //#endregion
1068
- //#region src/hooks/useImageResolver.ts
1069
- var ImageResolver = class {};
1070
- var MerchantImageResolver = class {
1071
- static {
1072
- this.imageResolverMap = /* @__PURE__ */ new Map();
1073
- }
1074
- static loadMapping() {
1075
- if (this.imageResolverMap.size === 0) {
1076
- this.imageResolverMap.set(OrgShortName.Spanx, new ShopifyImageResolver());
1077
- this.imageResolverMap.set(OrgShortName.SpanxStaging, new ShopifyImageResolver());
1078
- this.imageResolverMap.set(OrgShortName.UniqueVintage, new ShopifyImageResolver());
1079
- }
1080
- return this.imageResolverMap;
1081
- }
1082
- static get(name) {
1083
- return this.loadMapping().get(name);
1084
- }
1085
- };
1086
- var ShopifyImageResolver = class extends ImageResolver {
1087
- resolve(url, size) {
1088
- const pattern = /_\d+x\.jpg/;
1089
- const urlHasPrefix = pattern.test(url);
1090
- const newSizePrefix = `_${size}x.jpg`;
1091
- if (urlHasPrefix) return url.replace(pattern, newSizePrefix);
1092
- return url.replace(".jpg", newSizePrefix);
1093
- }
1094
- };
1095
- const useImageResolver = () => {
1096
- const orgShortName = useAtomValue(orgShortNameAtom);
1097
- const resolve = (image, size) => {
1098
- if (image && size && orgShortName) return MerchantImageResolver.get(orgShortName)?.resolve(image, size) || image;
1099
- return image;
1100
- };
1101
- return { resolve };
1102
- };
1103
-
1104
- //#endregion
1105
- //#region src/hooks/useIntersection.ts
1106
- const useIntersection = (element, rootMargin) => {
1107
- const [isVisible, setIsVisible] = useState(false);
1108
- useEffect(() => {
1109
- const current = element?.current;
1110
- const observer = new IntersectionObserver(([entry]) => {
1111
- setIsVisible(entry.isIntersecting);
1112
- }, { rootMargin });
1113
- if (current) observer?.observe(current);
1114
- return () => {
1115
- if (current) observer.unobserve(current);
1116
- };
1117
- }, []);
1118
- return isVisible;
1119
- };
1120
-
1121
- //#endregion
1122
- //#region src/hooks/useIsSmallScreen.ts
1123
- const useIsSmallScreen = () => {
1124
- const [isSmall, setIsSmall] = useState(false);
1125
- useEffect(() => {
1126
- const mediaQuery = window.matchMedia("(max-width: 479px)");
1127
- setIsSmall(mediaQuery.matches);
1128
- const handleResize = (event) => {
1129
- setIsSmall(event.matches);
1130
- };
1131
- mediaQuery.addEventListener("change", handleResize);
1132
- return () => mediaQuery.removeEventListener("change", handleResize);
1133
- }, []);
1134
- return isSmall;
1135
- };
1136
-
1137
- //#endregion
1138
- //#region src/hooks/useLocalStorageOperations.ts
1139
- const useLocalStorageValue = (key) => {
1140
- const { getItem, setItem, attachListener, detachListener } = useLocalStorage();
1141
- const [value, setValue] = useState(() => getItem(key));
1142
- useEffect(() => {
1143
- const listener = {
1144
- storageKey: key,
1145
- listener: (event) => {
1146
- setValue(event.newValue);
1147
- }
1148
- };
1149
- attachListener(listener);
1150
- return () => detachListener(listener);
1151
- }, [
1152
- key,
1153
- attachListener,
1154
- detachListener
1155
- ]);
1156
- const updateValue = useCallback((newValue) => {
1157
- setItem(key, newValue);
1158
- setValue(newValue);
1159
- }, [key, setItem]);
1160
- return {
1161
- value,
1162
- setValue: updateValue
1163
- };
1164
- };
1165
- const useSpiffyFeatureFlag = () => {
1166
- const { setSpiffyOnFeatureFlag } = useLocalStorage();
1167
- const { value } = useLocalStorageValue(LocalStorageKeys.SpiffyOnOverride);
1168
- const setFlag = useCallback((flag) => {
1169
- setSpiffyOnFeatureFlag(flag);
1170
- }, [setSpiffyOnFeatureFlag]);
1171
- return {
1172
- value: value === "true" ? true : value === "false" ? false : null,
1173
- setFlag
1174
- };
1175
- };
1176
- const useEnviveFeatureFlag = () => {
1177
- const { setItem, getItem } = useLocalStorage();
1178
- const { value } = useLocalStorageValue(LocalStorageKeys.EnviveOnOverride);
1179
- const setFlag = useCallback((flag) => {
1180
- if (flag === true) setItem(LocalStorageKeys.EnviveOnOverride, "true");
1181
- else if (flag === false) setItem(LocalStorageKeys.EnviveOnOverride, "false");
1182
- }, [setItem]);
1183
- return {
1184
- value: value === "true" ? true : value === "false" ? false : null,
1185
- setFlag
1186
- };
1187
- };
1188
- const useLocalStorageListener = (key, callback) => {
1189
- const { attachListener, detachListener } = useLocalStorage();
1190
- useEffect(() => {
1191
- const listener = {
1192
- storageKey: key,
1193
- listener: callback
1194
- };
1195
- attachListener(listener);
1196
- return () => detachListener(listener);
1197
- }, [
1198
- key,
1199
- callback,
1200
- attachListener,
1201
- detachListener
1202
- ]);
1203
- };
1204
-
1205
- //#endregion
1206
- //#region src/hooks/useMessageFilter.ts
1207
- const useMessageFilter = () => {
1208
- const findMessageIndex = ({ msgs, type, role }) => {
1209
- let lastIndex = -1;
1210
- msgs.forEach((subArray, index) => {
1211
- subArray.forEach((obj) => {
1212
- if (obj.type === type || obj.role === role) lastIndex = index;
1213
- });
1214
- });
1215
- return lastIndex;
1216
- };
1217
- const removePreviousDiscussions = (msgs, index) => {
1218
- if (index > -1) {
1219
- const lastMessages = msgs.slice(index);
1220
- return lastMessages.length > 0 ? lastMessages : msgs;
1221
- }
1222
- return msgs;
1223
- };
1224
- const getFilteredMessages = (msgs, skipFilter) => {
1225
- const messageMap = msgs.reduce((acc, msg) => {
1226
- acc[msg[0].id] = msg;
1227
- return acc;
1228
- }, {});
1229
- const deduplicatedMsgs = Object.values(messageMap);
1230
- if (!skipFilter) {
1231
- const idx = findMessageIndex({
1232
- msgs: deduplicatedMsgs,
1233
- type: MessageType.Separator
1234
- });
1235
- return removePreviousDiscussions(deduplicatedMsgs, idx);
1236
- }
1237
- return deduplicatedMsgs;
1238
- };
1239
- return {
1240
- findMessageIndex,
1241
- removePreviousDiscussions,
1242
- getFilteredMessages
1243
- };
1244
- };
1245
-
1246
- //#endregion
1247
- //#region src/hooks/useMessageScrollObserver.ts
1248
- const useMessageScrollObserver = (boxRef, scrollRef, onScrollChange) => {
1249
- const calculateScrollHeight = () => {
1250
- const boxHeight = boxRef?.current?.getBoundingClientRect().height || 0;
1251
- const scrollHeight = scrollRef?.current?.getBoundingClientRect().height || 0;
1252
- return boxHeight - scrollHeight;
1253
- };
1254
- const updateState = () => {
1255
- const scrollHeight = calculateScrollHeight();
1256
- if (scrollHeight > 0) onScrollChange(scrollHeight);
1257
- };
1258
- useEffect(() => {
1259
- let boxRO = null;
1260
- let scrollRO = null;
1261
- if (scrollRef?.current) {
1262
- boxRO = new ResizeObserver(updateState);
1263
- boxRO.observe(scrollRef?.current);
1264
- }
1265
- if (boxRef?.current) {
1266
- scrollRO = new ResizeObserver(updateState);
1267
- scrollRO.observe(boxRef?.current);
1268
- }
1269
- return () => {
1270
- if (scrollRef?.current && boxRO) boxRO.unobserve(scrollRef?.current);
1271
- if (scrollRO && boxRef?.current) scrollRO?.unobserve(boxRef?.current);
1272
- };
1273
- }, []);
1274
- };
1275
-
1276
- //#endregion
1277
- //#region src/contexts/featureFlagServiceContext.tsx
1278
- var FeatureFlagService = class {
1279
- constructor(featureGates) {
1280
- this.isFeatureGateEnabled = (featureGate) => {
1281
- const gateValue = this.featureGates.find((gate) => gate.name === featureGate);
1282
- if (gateValue == null || gateValue.value == null) {
1283
- logger_default.logDebug(`[spiffy-ai] isFeatureGateEnabled featureGate:${featureGate} value is undefined - returning false`);
1284
- return false;
1285
- }
1286
- return gateValue.value;
1287
- };
1288
- this.isClientSessionEnabled = () => {
1289
- return this.featureGates.filter((gate) => gate.name === FeatureGates.IsClientSessionEnabled && gate.value === true).length > 0;
1290
- };
1291
- this.getFeatureFlags = () => {
1292
- return Object.fromEntries(Object.values(FeatureGates).map((featureGate) => [featureGate, this.isFeatureGateEnabled(featureGate)]));
1293
- };
1294
- this.featureGates = featureGates;
1295
- }
1296
- };
1297
- const FeatureFlagServiceContext = createContext(void 0);
1298
- const FeatureFlagServiceProvider = ({ featureGates, children }) => {
1299
- const featureFlagService = useMemo(() => new FeatureFlagService(featureGates), [featureGates]);
1300
- return /* @__PURE__ */ jsx(FeatureFlagServiceContext.Provider, {
1301
- value: { featureFlagService },
1302
- children
1303
- });
1304
- };
1305
- const useFeatureFlagService = () => {
1306
- const context = useContext(FeatureFlagServiceContext);
1307
- if (context === void 0) throw new Error("useFeatureFlagService must be used within a FeatureFlagServiceProvider");
1308
- return context;
1309
- };
1310
-
1311
- //#endregion
1312
- //#region src/contexts/newOrgConfigContext.tsx
1313
- const NewOrgConfigContext = createContext(void 0);
1314
- const NewOrgConfigProvider = ({ children }) => {
1315
- const [oldConfig, setOldConfig] = useState();
1316
- const orgShortName = useAtomValue(orgShortNameAtom);
1317
- const setNewOrgConfig = useSetAtom(newOrgConfigAtom);
1318
- const { data: newConfig, loading, error } = useColorsAndFrontendConfig();
1319
- useEffect(() => {
1320
- if (orgShortName) getOrgInfo(orgShortName).then(setOldConfig);
1321
- }, [orgShortName]);
1322
- const combinedConfig = useMemo(() => {
1323
- if (!oldConfig || !newConfig) return null;
1324
- return {
1325
- ...oldConfig,
1326
- ...newConfig
1327
- };
1328
- }, [oldConfig, newConfig]);
1329
- useEffect(() => {
1330
- const atomStore = getAtomStore();
1331
- if (combinedConfig) {
1332
- atomStore.set(orgIdAtom, "mock-org-id");
1333
- setNewOrgConfig(combinedConfig);
1334
- }
1335
- }, [combinedConfig, setNewOrgConfig]);
1336
- const contextValue = useMemo(() => {
1337
- if (!orgShortName || loading && !oldConfig) return {
1338
- combinedConfig: null,
1339
- loading: true,
1340
- error: null
1341
- };
1342
- if (error) return {
1343
- combinedConfig: null,
1344
- loading: false,
1345
- error
1346
- };
1347
- return {
1348
- combinedConfig,
1349
- loading: false,
1350
- error: null
1351
- };
1352
- }, [
1353
- orgShortName,
1354
- loading,
1355
- error,
1356
- oldConfig,
1357
- combinedConfig
1358
- ]);
1359
- return /* @__PURE__ */ jsx(NewOrgConfigContext.Provider, {
1360
- value: contextValue,
1361
- children: /* @__PURE__ */ jsx(FeatureFlagServiceProvider, {
1362
- featureGates: [],
1363
- children
1364
- })
1365
- });
1366
- };
1367
- const useNewOrgConfigContext = () => {
1368
- const context = useContext(NewOrgConfigContext);
1369
- if (context === void 0) throw new Error("useNewOrgConfigContext must be used within a NewOrgConfigProvider");
1370
- return context;
1371
- };
1372
-
1373
- //#endregion
1374
- //#region src/hooks/useNewOrgConfig.ts
1375
- const useNewOrgConfig = () => {
1376
- const { combinedConfig, loading, error } = useNewOrgConfigContext();
1377
- return {
1378
- ...combinedConfig,
1379
- loading,
1380
- error
1381
- };
1382
- };
1383
-
1384
- //#endregion
1385
- //#region src/hooks/utils.ts
1386
- const isElementPartiallyVisible = (el) => {
1387
- if (!el) return false;
1388
- const rect = el.getBoundingClientRect();
1389
- const windowHeight = window.innerHeight || document.documentElement.clientHeight;
1390
- const windowWidth = window.innerWidth || document.documentElement.clientWidth;
1391
- const verticallyVisible = Math.round(rect.top) < windowHeight && Math.round(rect.bottom) > 0;
1392
- const horizontallyVisible = Math.round(rect.left) < windowWidth && Math.round(rect.right) > 0;
1393
- return verticallyVisible && horizontallyVisible;
1394
- };
1395
- const createAppLoadedEvent = () => ({
1396
- eventId: v4(),
1397
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1398
- category: UserEventCategory.AppLoaded
1399
- });
1400
- const createVisitUserEvent = ({ variantInfo }) => {
1401
- if (variantInfo.variant === "pdp" && variantInfo.productId != null) return {
1402
- eventId: v4(),
1403
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1404
- category: UserEventCategory.PdpVisit,
1405
- attributes: {
1406
- productId: variantInfo.productId,
1407
- parentProductId: variantInfo.parentProductId ?? "",
1408
- url: variantInfo.url ?? ""
1409
- }
1410
- };
1411
- if (variantInfo.variant === "plp" && variantInfo.plpId != null) return {
1412
- eventId: v4(),
1413
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1414
- category: UserEventCategory.PlpVisit,
1415
- attributes: {
1416
- category: PLPAttributeCategory.Id,
1417
- attributes: { id: variantInfo.plpId }
1418
- }
1419
- };
1420
- if (variantInfo.variant === "page_visit") return {
1421
- eventId: v4(),
1422
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1423
- category: UserEventCategory.PageVisit,
1424
- attributes: {
1425
- url: variantInfo.url,
1426
- pageVisitCategory: variantInfo.pageVisitCategory
1427
- }
1428
- };
1429
- };
1430
- const parseTime = (time, timeZone) => {
1431
- const times = time.match(/^([0-1]?\d):([0-5]\d)(AM|PM)$/i);
1432
- const hours = times?.[1];
1433
- const minutes = times?.[2];
1434
- const period = times?.[3];
1435
- if (hours && minutes && period) {
1436
- const date = /* @__PURE__ */ new Date();
1437
- let adjustedHours = 0;
1438
- if (period.toUpperCase() === "PM" && hours !== "12") adjustedHours = parseInt(hours) + 12;
1439
- if (period.toUpperCase() === "AM" && hours !== "12") adjustedHours = parseInt(hours);
1440
- const formattedDate = `${date.toISOString().split("T")[0]}T${String(adjustedHours).padStart(2, "0")}:${minutes}:00`;
1441
- return /* @__PURE__ */ new Date(`${formattedDate}${timeZone}`);
1442
- }
1443
- };
1444
- const isWithinBusinessHours = (startTime, endTime, timeZone) => {
1445
- const start = parseTime(startTime, timeZone);
1446
- let end = parseTime(endTime, timeZone);
1447
- if (!start || !end) return false;
1448
- let now = /* @__PURE__ */ new Date();
1449
- if (end < start) {
1450
- end = new Date(end.getTime() + 1440 * 60 * 1e3);
1451
- now = new Date(now.getTime() + 1440 * 60 * 1e3);
1452
- }
1453
- if (end.getUTCDate() > start.getUTCDate()) {
1454
- const crossingMidnight = new Date(now.getTime() + 1440 * 60 * 1e3);
1455
- return start <= now || crossingMidnight <= end;
1456
- }
1457
- return now >= start && now <= end;
1458
- };
1459
- let SearchResultsState = /* @__PURE__ */ function(SearchResultsState$1) {
1460
- SearchResultsState$1[SearchResultsState$1["Loading"] = 0] = "Loading";
1461
- SearchResultsState$1[SearchResultsState$1["Results"] = 1] = "Results";
1462
- SearchResultsState$1[SearchResultsState$1["NoResults"] = 2] = "NoResults";
1463
- return SearchResultsState$1;
1464
- }({});
1465
- const getSearchResultsState = (isLoadingSearch, searchData) => {
1466
- if (isLoadingSearch) return SearchResultsState.Loading;
1467
- if (searchData) return SearchResultsState.Results;
1468
- return SearchResultsState.NoResults;
1469
- };
1470
-
1471
- //#endregion
1472
- //#region src/hooks/useSearch.tsx
1473
- const useSearch = () => {
1474
- const config = useNewOrgConfig();
1475
- const orgShortName = useAtomValue(orgShortNameAtom);
1476
- const { data: searchData, loading: isLoadingSearch } = useAtomValue(searchAtom);
1477
- const productList = useAtomValue(filteredSearchProductsAtom);
1478
- const performSearch = useSetAtom(performSearchAtom);
1479
- const [{ results: autocompleteResults, isLoading: isLoadingAutocomplete }, setAutocompleteState] = useAtom(autocompleteStateAtom);
1480
- const [{ query }] = useAtom(searchParamsAtom);
1481
- const [isFilterOpen, setIsFilterOpen] = useAtom(isFilterOpenAtom);
1482
- const [selectedFilterOptions] = useAtom(searchSelectedFiltersAtom);
1483
- const addFilter = useSetAtom(addSearchFilterAtom);
1484
- const removeFilter = useSetAtom(removeSearchFilterAtom);
1485
- const [productSorting, setProductSorting] = useAtom(searchProductSortingAtom);
1486
- const clearFilters = useSetAtom(clearSearchFiltersAtom);
1487
- const searchFilters = useAtomValue(searchFiltersAtom);
1488
- const [isDirty, setIsDirty] = useState(true);
1489
- const [focusedIndex, setFocusedIndex] = useState(-1);
1490
- const [focusedOptionId, setFocusedOptionId] = useState(void 0);
1491
- const [searchText, setSearchText] = useState(query || "");
1492
- const searchResultsRef = useRef(null);
1493
- const debouncedSearchText = useDebounce(searchText, 200);
1494
- const searchResultsState = getSearchResultsState(isLoadingSearch, searchData);
1495
- const dynamicFilters = searchData?.filters || [];
1496
- const safeProductCardConfig = config?.frontendConfig?.uiConfigs?.productCardConfig || {
1497
- variant: "minimal",
1498
- hoverVariant: "none",
1499
- layoutVariant: "square"
1500
- };
1501
- const safeMerchantShortName = orgShortName || "";
1502
- const availableDynamicFilters = useMemo(() => {
1503
- return dynamicFilters.filter((dynamicFilterName) => !selectedFilterOptions.some((option) => option.id === `dynamic:${dynamicFilterName}`)).map((dynamicFilterName) => ({
1504
- name: dynamicFilterName,
1505
- displayName: formatFilterDisplayName(dynamicFilterName)
1506
- }));
1507
- }, [dynamicFilters, selectedFilterOptions]);
1508
- const filters = useMemo(() => {
1509
- return [{
1510
- filterId: "sort",
1511
- displayName: "SORT",
1512
- items: [
1513
- {
1514
- filterItemId: String(ProductSorting.FEATURED),
1515
- displayName: "Relevance",
1516
- productCount: 0,
1517
- isSelected: productSorting === ProductSorting.FEATURED
1518
- },
1519
- {
1520
- filterItemId: String(ProductSorting.PRICE_ASC),
1521
- displayName: "Price: Low to High",
1522
- productCount: 0,
1523
- isSelected: productSorting === ProductSorting.PRICE_ASC
1524
- },
1525
- {
1526
- filterItemId: String(ProductSorting.PRICE_DESC),
1527
- displayName: "Price: High to Low",
1528
- productCount: 0,
1529
- isSelected: productSorting === ProductSorting.PRICE_DESC
1530
- }
1531
- ]
1532
- }, ...searchFilters];
1533
- }, [productSorting, searchFilters]);
1534
- const filterButtonText = useMemo(() => {
1535
- const selectedCount = filters.reduce((acc, filter) => {
1536
- if (filter.filterId === "sort") return acc;
1537
- return acc + filter.items.filter((item) => item.isSelected).length;
1538
- }, 0);
1539
- if (selectedCount === 0) return "Filter & Sort";
1540
- return `Filter & Sort (${selectedCount})`;
1541
- }, [filters]);
1542
- const { trackEvent } = useAmplitude();
1543
- const handleToggleDynamicFilter = useCallback(({ filter, dynamicFilterDisplayName }) => {
1544
- trackEvent({
1545
- eventName: SpiffyMetricsEventName.SearchFilterClicked,
1546
- eventProps: {
1547
- filterType: "Dynamic",
1548
- filterValue: filter,
1549
- queryText: searchText
1550
- }
1551
- });
1552
- addFilter(createFilterOption("dynamic", filter, dynamicFilterDisplayName));
1553
- }, [
1554
- addFilter,
1555
- searchText,
1556
- trackEvent
1557
- ]);
1558
- const handleRemoveFilter = useCallback((filter) => {
1559
- removeFilter(filter.id);
1560
- }, [removeFilter]);
1561
- const handleSubmitSearch = useCallback(async () => {
1562
- if (searchText.trim()) {
1563
- trackEvent({
1564
- eventName: SpiffyMetricsEventName.SearchQuerySubmitted,
1565
- eventProps: {
1566
- searchOrigin: SpiffyWidgets.SearchResults,
1567
- queryText: searchText.trim()
1568
- },
1569
- alsoSendToGoogleAnalytics: true
1570
- });
1571
- const url = new URL(window.location.href);
1572
- url.searchParams.set("esq", searchText.trim());
1573
- window.history.pushState({}, "", url);
1574
- performSearch({ query: searchText.trim() });
1575
- }
1576
- }, [
1577
- performSearch,
1578
- searchText,
1579
- trackEvent
1580
- ]);
1581
- const handleAutocompleteSelect = useCallback((suggestion) => {
1582
- setSearchText(suggestion);
1583
- handleSubmitSearch();
1584
- }, [handleSubmitSearch, setSearchText]);
1585
- const handleKeyDown = useCallback((event) => {
1586
- if (event.key === "ArrowDown") {
1587
- event.preventDefault();
1588
- const newIndex = (focusedIndex + 1) % autocompleteResults.length;
1589
- setFocusedIndex(newIndex);
1590
- setFocusedOptionId(`option-${newIndex}`);
1591
- } else if (event.key === "ArrowUp") {
1592
- event.preventDefault();
1593
- const newIndex = (focusedIndex - 1 + autocompleteResults.length) % autocompleteResults.length;
1594
- setFocusedIndex(newIndex);
1595
- setFocusedOptionId(`option-${newIndex}`);
1596
- } else if (event.key === "Enter") if (focusedIndex === -1) {
1597
- event.preventDefault();
1598
- handleSubmitSearch();
1599
- } else {
1600
- event.preventDefault();
1601
- const suggestionText = autocompleteResults[focusedIndex];
1602
- handleAutocompleteSelect(suggestionText);
1603
- }
1604
- else if (event.key === "Escape") {
1605
- event.preventDefault();
1606
- setFocusedIndex(-1);
1607
- setFocusedOptionId(void 0);
1608
- }
1609
- }, [
1610
- autocompleteResults,
1611
- focusedIndex,
1612
- handleAutocompleteSelect,
1613
- handleSubmitSearch
1614
- ]);
1615
- const handleSearchInputChange = (newValue) => {
1616
- if (newValue.length === 1) trackEvent({
1617
- eventName: SpiffyMetricsEventName.SearchInputStarted,
1618
- eventProps: { searchOrigin: SpiffyWidgets.SearchResults }
1619
- });
1620
- setSearchText(newValue);
1621
- setIsDirty(true);
1622
- };
1623
- const handleSelectFilterItem = useCallback(({ filterId, filterItemId, isSelected, displayName }) => {
1624
- if (filterId === "sort") {
1625
- const newSort = filterItemId;
1626
- trackEvent({
1627
- eventName: SpiffyMetricsEventName.SearchSortClicked,
1628
- eventProps: {
1629
- sortType: newSort,
1630
- queryText: searchText
1631
- }
1632
- });
1633
- setProductSorting(newSort);
1634
- } else if (!isSelected) removeFilter(`${filterId}:${filterItemId}`);
1635
- else {
1636
- trackEvent({
1637
- eventName: SpiffyMetricsEventName.SearchFilterClicked,
1638
- eventProps: {
1639
- filterType: "Static",
1640
- filterCategory: filterId,
1641
- filterValue: filterItemId,
1642
- queryText: searchText
1643
- }
1644
- });
1645
- addFilter(createFilterOption(filterId, filterItemId, displayName));
1646
- }
1647
- }, [
1648
- addFilter,
1649
- removeFilter,
1650
- setProductSorting,
1651
- searchText,
1652
- trackEvent
1653
- ]);
1654
- const handleClearAllFilters = useCallback(() => {
1655
- setProductSorting(ProductSorting.FEATURED);
1656
- clearFilters();
1657
- }, [setProductSorting, clearFilters]);
1658
- useTrackComponentVisibleEvent(SpiffyWidgets.SearchResults, searchResultsRef, {}, SpiffyMetricsEventName.SearchComponentVisible);
1659
- useEffect(() => {
1660
- if (productList.length > 0) trackEvent({
1661
- eventName: SpiffyMetricsEventName.SearchResultsViewed,
1662
- eventProps: {
1663
- queryText: searchText,
1664
- resultsCount: productList.length
1665
- }
1666
- });
1667
- }, [
1668
- productList.length,
1669
- searchText,
1670
- trackEvent
1671
- ]);
1672
- useEffect(() => {
1673
- if (query && query !== searchText) setSearchText(query);
1674
- }, [query]);
1675
- useEffect(() => {
1676
- const esq = new URLSearchParams(window.location.search).get("esq");
1677
- if (esq) {
1678
- setSearchText(esq);
1679
- performSearch({ query: esq });
1680
- }
1681
- }, [performSearch]);
1682
- const fetchAutocompleteSuggestions = (_query) => {
1683
- return Promise.resolve([]);
1684
- };
1685
- useEffect(() => {
1686
- if (fetchAutocompleteSuggestions === void 0) return;
1687
- if (!isDirty || debouncedSearchText.length <= 2) {
1688
- setAutocompleteState({
1689
- results: [],
1690
- isLoading: false
1691
- });
1692
- return;
1693
- }
1694
- setAutocompleteState((prev) => ({
1695
- ...prev,
1696
- isLoading: true
1697
- }));
1698
- const fetchData = async () => {
1699
- try {
1700
- const results = await fetchAutocompleteSuggestions?.(debouncedSearchText);
1701
- setAutocompleteState({
1702
- results: results ?? [],
1703
- isLoading: false
1704
- });
1705
- } catch (error) {
1706
- logger_default.logError("Failed to fetch autocomplete suggestions:", error);
1707
- setAutocompleteState({
1708
- results: [],
1709
- isLoading: false
1710
- });
1711
- }
1712
- };
1713
- fetchData();
1714
- }, [
1715
- debouncedSearchText,
1716
- isDirty,
1717
- setAutocompleteState
1718
- ]);
1719
- return {
1720
- searchData,
1721
- searchResponseId: searchData?.searchResponseId ?? "",
1722
- merchantShortName: safeMerchantShortName,
1723
- productCardConfig: safeProductCardConfig,
1724
- productList,
1725
- autocompleteResults,
1726
- searchFilters: filters,
1727
- availableDynamicFilters,
1728
- selectedFilterOptions,
1729
- searchText,
1730
- searchResultsState,
1731
- isLoadingAutocomplete,
1732
- isLoadingSearch,
1733
- isFilterOpen,
1734
- isDirty,
1735
- focusedIndex,
1736
- focusedOptionId,
1737
- filterButtonText,
1738
- onSearchInputChange: handleSearchInputChange,
1739
- onSubmitSearch: handleSubmitSearch,
1740
- onAutocompleteSelect: handleAutocompleteSelect,
1741
- onKeyDown: handleKeyDown,
1742
- onToggleDynamicFilter: handleToggleDynamicFilter,
1743
- onSelectFilterItem: handleSelectFilterItem,
1744
- onRemoveFilter: handleRemoveFilter,
1745
- onClearAllFilters: handleClearAllFilters,
1746
- setIsFilterOpen,
1747
- searchResultsRef
1748
- };
1749
- };
1750
-
1751
- //#endregion
1752
- //#region src/hooks/useAppDetails.ts
1753
- const useAppDetails = () => {
1754
- const { orgId: fetchedOrgId } = useOrgId();
1755
- const orgId = fetchedOrgId ?? "";
1756
- const orgShortName = useAtomValue(orgShortNameAtom) ?? "spiffy-ai";
1757
- const chatId = useAtomValue(chatIdAtom);
1758
- const userId = useAtomValue(userIdAtom);
1759
- const source = useAtomValue(contextSourceAtom) ?? ContextSourceEnum.App;
1760
- const env = useAtomValue(envAtom) ?? ContextEnvEnum.Dev;
1761
- const variantInfo = useAtomValue(variantInfoAtom);
1762
- return {
1763
- orgId,
1764
- orgShortName,
1765
- chatId,
1766
- userId,
1767
- source,
1768
- env,
1769
- variantInfo
1770
- };
1771
- };
1772
-
1773
- //#endregion
1774
- //#region src/contexts/searchContext.tsx
1775
- const transformProductResponses = (products) => products.map((data) => ({
1776
- id: data.id,
1777
- responseId: data.response_id,
1778
- category: ResponseCategory.Product,
1779
- description: data.description,
1780
- imageUrl: data.image_url,
1781
- imageUrls: data.image_urls,
1782
- title: data.title,
1783
- url: data.url,
1784
- originalPrice: data.original_price,
1785
- salePrice: data.sale_price,
1786
- averageRating: data.average_rating,
1787
- numberReviews: data.number_reviews,
1788
- metadata: data.metadata,
1789
- isForGrid: data.is_for_grid,
1790
- colors: data.colors,
1791
- sizes: data.sizes,
1792
- filters: data.filters
1793
- }));
1794
- async function errorResponseBody(error) {
1795
- try {
1796
- return await error.response.json();
1797
- } catch {
1798
- return {};
1799
- }
1800
- }
1801
- async function throwSessionRestartRequiredIf(errorMsg, error) {
1802
- if (!(error instanceof ResponseError)) {
1803
- logger_default.logInfo(errorMsg, error);
1804
- throw error;
1805
- }
1806
- const errorResponse = await errorResponseBody(error);
1807
- if (errorResponse?.message?.toLowerCase() === "unsupported product" || errorResponse?.app_code?.toUpperCase() === "PRODUCT_NOT_FOUND") throw new UnsupportedProductException();
1808
- else if (errorResponse?.app_code?.toUpperCase() === "RESTART_SESSION" || errorResponse?.sub_code?.toUpperCase() === "NOT_FOUND") {
1809
- logger_default.logInfo("Session does not exist. Re-start session", error, error.response, errorResponse);
1810
- throw new SessionRestartRequired();
1811
- }
1812
- logger_default.logInfo(errorMsg, error);
1813
- throw error;
1814
- }
1815
- const SearchContext = createContext(void 0);
1816
- const SearchProvider = ({ children }) => {
1817
- const { orgLevelApiKey, publicKey } = useEnviveConfig();
1818
- const apiKey = orgLevelApiKey || publicKey;
1819
- const appDetails = useAppDetails();
1820
- const baseUrl = useAtomValue(baseUrlAtom);
1821
- const isReady = Boolean(apiKey && appDetails && baseUrl);
1822
- const searchApi = useMemo(() => {
1823
- if (!isReady) return null;
1824
- const config = new Configuration({
1825
- accessToken: apiKey,
1826
- basePath: baseUrl,
1827
- headers: {
1828
- "Content-Type": "application/json",
1829
- Accept: "application/json"
1830
- }
1831
- });
1832
- return new SearchApi(config);
1833
- }, [
1834
- apiKey,
1835
- baseUrl,
1836
- isReady
1837
- ]);
1838
- const searchProducts = useCallback(async (params) => {
1839
- if (!isReady || !searchApi) throw new Error("SearchService not ready - missing dependencies");
1840
- try {
1841
- const { products, filters, search_response_id: searchResponseId } = await searchApi.v1SearchQueryGet({
1842
- query: params.query,
1843
- limit: params.limit,
1844
- org_id: appDetails.orgId,
1845
- user_id: appDetails.userId
1846
- });
1847
- return {
1848
- products: transformProductResponses(products) || [],
1849
- filters: filters || [],
1850
- totalProductCount: products?.length || 0,
1851
- searchResponseId: searchResponseId || ""
1852
- };
1853
- } catch (error) {
1854
- await throwSessionRestartRequiredIf("Failed to search products", error);
1855
- return {
1856
- products: [],
1857
- filters: [],
1858
- totalProductCount: 0,
1859
- searchResponseId: ""
1860
- };
1861
- }
1862
- }, [
1863
- searchApi,
1864
- isReady,
1865
- appDetails
1866
- ]);
1867
- useEffect(() => {
1868
- if (isReady) setSearchServiceFunction(searchProducts);
1869
- else clearSearchServiceFunction();
1870
- return () => {
1871
- clearSearchServiceFunction();
1872
- };
1873
- }, [searchProducts, isReady]);
1874
- const value = useMemo(() => ({
1875
- searchProducts,
1876
- isReady
1877
- }), [searchProducts, isReady]);
1878
- return /* @__PURE__ */ jsx(SearchContext.Provider, {
1879
- value,
1880
- children
1881
- });
1882
- };
1883
- const useSearchService = () => {
1884
- const context = useContext(SearchContext);
1885
- if (!context) throw new Error("useSearchService must be used within a SearchProvider");
1886
- return context;
1887
- };
1888
-
1889
- //#endregion
1890
- //#region src/hooks/useSearchOperations.ts
1891
- const useProductSearch = () => {
1892
- const { searchProducts, isReady } = useSearchService();
1893
- const [data, setData] = useState();
1894
- const [loading, setLoading] = useState(false);
1895
- const [error, setError] = useState(null);
1896
- const search = useCallback(async (params) => {
1897
- if (!isReady) {
1898
- setError(/* @__PURE__ */ new Error("Search service not ready - missing dependencies"));
1899
- return;
1900
- }
1901
- setLoading(true);
1902
- setError(null);
1903
- try {
1904
- const result = await searchProducts(params);
1905
- setData(result);
1906
- } catch (err) {
1907
- setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Unknown search error"));
1908
- } finally {
1909
- setLoading(false);
1910
- }
1911
- }, [searchProducts, isReady]);
1912
- const reset = useCallback(() => {
1913
- setData(void 0);
1914
- setError(null);
1915
- setLoading(false);
1916
- }, []);
1917
- return {
1918
- data,
1919
- loading,
1920
- error,
1921
- search,
1922
- reset,
1923
- isReady
1924
- };
1925
- };
1926
- const useSearchWithQuery = (params) => {
1927
- const { searchProducts, isReady } = useSearchService();
1928
- const [data, setData] = useState();
1929
- const [loading, setLoading] = useState(false);
1930
- const [error, setError] = useState(null);
1931
- const executeSearch = useCallback(async (searchParams) => {
1932
- if (!isReady) return;
1933
- setLoading(true);
1934
- setError(null);
1935
- try {
1936
- const result = await searchProducts(searchParams);
1937
- setData(result);
1938
- } catch (err) {
1939
- setError(err instanceof Error ? err : /* @__PURE__ */ new Error("Unknown search error"));
1940
- } finally {
1941
- setLoading(false);
1942
- }
1943
- }, [searchProducts, isReady]);
1944
- useEffect(() => {
1945
- if (params && isReady) executeSearch(params);
1946
- }, [
1947
- params,
1948
- isReady,
1949
- executeSearch
1950
- ]);
1951
- const refetch = useCallback(() => {
1952
- if (params) executeSearch(params);
1953
- }, [params, executeSearch]);
1954
- return {
1955
- data,
1956
- loading,
1957
- error,
1958
- refetch,
1959
- isReady
1960
- };
1961
- };
1962
-
1963
- //#endregion
1964
- //#region src/contexts/sessionStorageContext.tsx
1965
- const SessionStorageContext = createContext(null);
1966
- const SessionStorageProvider = ({ children }) => {
1967
- const isAvailable = useMemo(() => {
1968
- try {
1969
- return typeof window !== "undefined" && !!window.sessionStorage;
1970
- } catch {
1971
- return false;
1972
- }
1973
- }, []);
1974
- useEffect(() => {
1975
- if (!isAvailable) logger_default.logError("sessionStorage is not available", void 0);
1976
- }, [isAvailable]);
1977
- const setItem = useCallback((key, value$1) => {
1978
- if (!isAvailable) return;
1979
- sessionStorage.setItem(key, value$1);
1980
- window.dispatchEvent(new StorageEvent("storage", {
1981
- key,
1982
- newValue: value$1
1983
- }));
1984
- }, [isAvailable]);
1985
- const getItem = useCallback((key) => {
1986
- if (!isAvailable) return null;
1987
- return sessionStorage.getItem(key);
1988
- }, [isAvailable]);
1989
- const value = useMemo(() => ({
1990
- setItem,
1991
- getItem,
1992
- isAvailable
1993
- }), [
1994
- setItem,
1995
- getItem,
1996
- isAvailable
1997
- ]);
1998
- return /* @__PURE__ */ jsx(SessionStorageContext.Provider, {
1999
- value,
2000
- children
2001
- });
2002
- };
2003
- const useSessionStorage = () => {
2004
- const context = useContext(SessionStorageContext);
2005
- if (!context) throw new Error("useSessionStorage must be used within a SessionStorageProvider");
2006
- return context;
2007
- };
2008
-
2009
- //#endregion
2010
- //#region src/hooks/useSessionStorageOperations.ts
2011
- const useSessionStorageValue = (key) => {
2012
- const { getItem, setItem } = useSessionStorage();
2013
- const [value, setValue] = useState(() => getItem(key));
2014
- useEffect(() => {
2015
- const handleStorageChange = (event) => {
2016
- if (event.key === key) setValue(event.newValue);
2017
- };
2018
- window.addEventListener("storage", handleStorageChange);
2019
- return () => window.removeEventListener("storage", handleStorageChange);
2020
- }, [key, getItem]);
2021
- const updateValue = useCallback((newValue) => {
2022
- setItem(key, newValue);
2023
- setValue(newValue);
2024
- }, [key, setItem]);
2025
- return {
2026
- value,
2027
- setValue: updateValue
2028
- };
2029
- };
2030
-
2031
- //#endregion
2032
- //#region src/contexts/shopifyUrlContext.tsx
2033
- const ShopifyUrlContext = createContext(void 0);
2034
- const ShopifyUrlProvider = ({ children }) => {
2035
- const isReady = true;
2036
- const getTrimmedPathName = useCallback(() => {
2037
- let { pathname } = window.location;
2038
- pathname = pathname.replace("/proxy", "");
2039
- pathname = pathname.replace(/#.*$/, "");
2040
- pathname = pathname.replace(/\/$/, "");
2041
- if (pathname === void 0 || pathname === null || pathname.length === 0) return null;
2042
- return pathname;
2043
- }, []);
2044
- const getPlpOrPdpId = useCallback((extractor) => {
2045
- if (extractor === "shopify-product-variant-id") {
2046
- const variantId = parseHref(window.location.href)?.urlSearchParams?.get("variant");
2047
- if (!variantId) return getPlpOrPdpId("shopify-product-id");
2048
- return variantId;
2049
- }
2050
- const pathSegment = extractor === "shopify-product-id" ? "products" : "collections";
2051
- const tokens = getTrimmedPathName()?.split("/");
2052
- const idIndex = tokens?.findIndex((token) => token === pathSegment);
2053
- if (idIndex !== void 0 && idIndex >= 0 && tokens) return decodeURIComponent(tokens[idIndex + 1]);
2054
- return null;
2055
- }, [getTrimmedPathName]);
2056
- const isOnPdpPage = useCallback(() => {
2057
- return getTrimmedPathName()?.includes("/products") ?? false;
2058
- }, [getTrimmedPathName]);
2059
- const isOnPlpPage = useCallback(() => {
2060
- return (getTrimmedPathName()?.includes("/collections") && !getTrimmedPathName()?.includes("/products")) ?? false;
2061
- }, [getTrimmedPathName]);
2062
- const value = useMemo(() => ({
2063
- getTrimmedPathName,
2064
- getPlpOrPdpId,
2065
- isOnPdpPage,
2066
- isOnPlpPage,
2067
- isReady
2068
- }), [
2069
- getTrimmedPathName,
2070
- getPlpOrPdpId,
2071
- isOnPdpPage,
2072
- isOnPlpPage,
2073
- isReady
2074
- ]);
2075
- return /* @__PURE__ */ jsx(ShopifyUrlContext.Provider, {
2076
- value,
2077
- children
2078
- });
2079
- };
2080
- const useShopifyUrl = () => {
2081
- const context = useContext(ShopifyUrlContext);
2082
- if (!context) throw new Error("useShopifyUrl must be used within a ShopifyUrlProvider");
2083
- return context;
2084
- };
2085
-
2086
- //#endregion
2087
- //#region src/hooks/useShopifyUrlOperations.ts
2088
- const useShopifyUrlOperations = () => {
2089
- const { getTrimmedPathName, getPlpOrPdpId, isOnPdpPage, isOnPlpPage, isReady } = useShopifyUrl();
2090
- return {
2091
- getTrimmedPathName,
2092
- getPlpOrPdpId,
2093
- isOnPdpPage,
2094
- isOnPlpPage,
2095
- isReady
2096
- };
2097
- };
2098
- const useCurrentPageType = () => {
2099
- const { isOnPdpPage, isOnPlpPage, isReady } = useShopifyUrl();
2100
- return {
2101
- getPageType: useCallback(() => {
2102
- if (!isReady) return "unknown";
2103
- if (isOnPdpPage()) return "pdp";
2104
- if (isOnPlpPage()) return "plp";
2105
- return "other";
2106
- }, [
2107
- isReady,
2108
- isOnPdpPage,
2109
- isOnPlpPage
2110
- ]),
2111
- isReady
2112
- };
2113
- };
2114
- const useProductId = (extractor) => {
2115
- const { getPlpOrPdpId, isReady } = useShopifyUrl();
2116
- return {
2117
- productId: useCallback(() => {
2118
- if (!isReady) return null;
2119
- return getPlpOrPdpId(extractor);
2120
- }, [
2121
- isReady,
2122
- getPlpOrPdpId,
2123
- extractor
2124
- ]),
2125
- isReady
2126
- };
2127
- };
2128
-
2129
- //#endregion
2130
- //#region src/hooks/useSnapCalculator.ts
2131
- const useSnapCalculator = (snaps, maxHeight, unit) => {
2132
- const viewportHeightPx = document.documentElement.clientHeight;
2133
- const swipeviewHeightPx = unit === "percent" ? Math.floor(viewportHeightPx * (maxHeight / 100)) : maxHeight;
2134
- const snapsToPixels = useMemo(() => snaps?.map((snap) => Math.abs((unit === "percent" ? Math.floor(swipeviewHeightPx * (snap / 100)) : snap) - swipeviewHeightPx)), [viewportHeightPx]);
2135
- const getPixelToSnap = (pixels) => {
2136
- const snapIdx = snapsToPixels?.indexOf(pixels) || 0;
2137
- return snaps?.[snapIdx] || 0;
2138
- };
2139
- const getSnapToPixel = (snap) => {
2140
- const snapIdx = snaps?.indexOf(snap) || 0;
2141
- return snapsToPixels?.[snapIdx] || 0;
2142
- };
2143
- return {
2144
- viewportHeightPx,
2145
- snapsToPixels,
2146
- swipeviewHeightPx,
2147
- getPixelToSnap,
2148
- getSnapToPixel
2149
- };
2150
- };
2151
-
2152
- //#endregion
2153
- //#region src/hooks/useSystemSettingsContext.ts
2154
- const useSystemSettingsContext = () => {
2155
- const context = useContext(SystemSettingsContext);
2156
- if (!context) throw new Error("useSystemSettingsContext must be used within a SystemSettingsContextProvider");
2157
- return { ...context };
2158
- };
2159
-
2160
- //#endregion
2161
- //#region src/hooks/useTrackComponentVisibleEvent.ts
2162
- /**
2163
- * Tracks a component and logs an event to Amplitude when the component is visible.
2164
- *
2165
- * @param component - The component to track.
2166
- * @param element - The element to track visibility of.
2167
- * @param eventProps - Additional properties to include with the event.
2168
- * @param eventName - The Amplitude event name to track (defaults to ChatComponentVisible).
2169
- */
2170
- const useTrackComponentVisibleEvent = (component, element, eventProps, eventName = SpiffyMetricsEventName.ChatComponentVisible) => {
2171
- const isVisible = useIntersection(element, "0px");
2172
- const hasTrackedEvent = useRef(false);
2173
- const { trackEvent } = useAmplitude();
2174
- const componentProps = (() => {
2175
- if (eventName === SpiffyMetricsEventName.ChatComponentVisible) return {
2176
- chat_component: component,
2177
- ...eventProps
2178
- };
2179
- if (eventName === SpiffyMetricsEventName.SearchComponentVisible) return {
2180
- search_component: component,
2181
- ...eventProps
2182
- };
2183
- return {
2184
- component,
2185
- ...eventProps
2186
- };
2187
- })();
2188
- useEffect(() => {
2189
- if (isVisible && !hasTrackedEvent.current) {
2190
- trackEvent({
2191
- eventName,
2192
- eventProps: componentProps
2193
- });
2194
- hasTrackedEvent.current = true;
2195
- }
2196
- }, [
2197
- isVisible,
2198
- component,
2199
- eventProps,
2200
- eventName,
2201
- componentProps,
2202
- trackEvent
2203
- ]);
2204
- };
2205
-
2206
- //#endregion
2207
- //#region src/hooks/useUpdateAnalyticsProps.ts
2208
- /**
2209
- * Updates the default analytics properties whenever the variant info changes. This hook also
2210
- * triggers any events that should be sent once per page visit.
2211
- */
2212
- const useUpdateAnalyticsProps = () => {
2213
- const variantInfo = useAtomValue(variantInfoAtom);
2214
- const hasInitialized = useRef(false);
2215
- const hasParsedVariantInfo = useAtomValue(hasParsedVariantInfoAtom);
2216
- const { trackEvent, setSupplementalDefaultProps } = useAmplitude();
2217
- useEffect(() => {
2218
- const variantInfoWithPrefix = Object.fromEntries(Object.entries(variantInfo).map(([key, value]) => [`variantInfo.${key}`, value]));
2219
- const defaultEventProperties = {
2220
- page_variant: variantInfo.variant,
2221
- ...variantInfoWithPrefix
2222
- };
2223
- if (variantInfo.variant === "pdp") defaultEventProperties.product_id = variantInfo.productId;
2224
- if (variantInfo.variant === "plp") defaultEventProperties.plp_id = variantInfo.plpId;
2225
- if (variantInfo.variant === "page_visit") {
2226
- defaultEventProperties.page_visit_category = variantInfo.pageVisitCategory;
2227
- defaultEventProperties.page_visit_url = variantInfo.url;
2228
- }
2229
- setSupplementalDefaultProps(defaultEventProperties);
2230
- if (!hasInitialized.current && hasParsedVariantInfo) {
2231
- trackEvent({ eventName: SpiffyMetricsEventName.BundleLoaded });
2232
- hasInitialized.current = true;
2233
- }
2234
- }, [
2235
- variantInfo,
2236
- hasParsedVariantInfo,
2237
- trackEvent,
2238
- setSupplementalDefaultProps
2239
- ]);
2240
- };
2241
-
2242
- //#endregion
2243
- //#region src/contexts/chatContext.tsx
2244
- /**
2245
- * Record the chat assistant response in Amplitude
2246
- *
2247
- * @param startTimeMs The start time of the assistant response
2248
- * @param payload The payload used to generate the response
2249
- */
2250
- const recordAssistantResponse = (startTimeMs, payload, track) => {
2251
- const atomStore = getAtomStore();
2252
- const chatState = atomStore.get(chatAtom);
2253
- const chatSearchState = atomStore.get(chatSearchStateAtom);
2254
- const searchProducts = atomStore.get(chatSearchProducts);
2255
- const searchProductsSort = atomStore.get(chatSearchProductSortingAtom);
2256
- const assistantResponseTimeMs = {
2257
- start: startTimeMs,
2258
- end: Date.now()
2259
- };
2260
- let userQueryProperty;
2261
- if (chatState.replyEventCategory === UserEventCategory.SuggestionClicked && chatState.suggestion) userQueryProperty = chatState.suggestion.content;
2262
- else if (chatState.userQuery && chatState.userQuery.length > 0) userQueryProperty = chatState.userQuery;
2263
- const eventProps = {
2264
- response_time_ms: assistantResponseTimeMs.end - assistantResponseTimeMs.start,
2265
- user_event_type: chatState.replyEventCategory,
2266
- user_query: userQueryProperty
2267
- };
2268
- if (chatState.replyEventCategory === UserEventCategory.FormSubmitted) {
2269
- const lastAssistantTurn = chatState.messages.filter((turn) => turn.length > 0 && turn[0].role === MessageRole.Assistant).pop();
2270
- const formType = payload.userEvents?.find((event) => event.category === UserEventCategory.FormSubmitted)?.attributes.formType;
2271
- const formStatus = lastAssistantTurn?.some((response) => response.type === MessageType.Order);
2272
- eventProps.form_submitted_attributes = {
2273
- form_type: formType,
2274
- status: formStatus ? "success" : "failed"
2275
- };
2276
- }
2277
- if (chatSearchState === "product-page") {
2278
- eventProps.search_products_returned = searchProducts.length;
2279
- eventProps.search_products_sort_type = searchProductsSort;
2280
- }
2281
- track(SpiffyMetricsEventName.ChatAssistantResponse, { eventProps });
2282
- };
2283
- const ChatContext = createContext(void 0);
2284
- const updateMessageState = (message, lastMessage, setMessages) => {
2285
- if (lastMessage == null) {
2286
- setMessages((prev) => [...prev, [message]]);
2287
- return message;
2288
- }
2289
- if (lastMessage.type === MessageType.Text && message.type === MessageType.Text) {
2290
- const newMessage = {
2291
- ...lastMessage,
2292
- metadata: {
2293
- ...lastMessage.metadata,
2294
- content: lastMessage.metadata.content + message.metadata.content
2295
- }
2296
- };
2297
- setMessages((prev) => {
2298
- const lastTurn = prev[prev.length - 1];
2299
- return [...prev.slice(0, prev.length - 1), [...lastTurn.slice(0, lastTurn.length - 1), newMessage]];
2300
- });
2301
- return newMessage;
2302
- }
2303
- setMessages((prev) => [...prev.slice(0, prev.length - 1), [...prev[prev.length - 1], message]]);
2304
- return message;
2305
- };
2306
- const handleStreamingError = (_error, setRequestFailure, setMessages) => {
2307
- setRequestFailure(true);
2308
- setMessages((prev) => [...prev, [{
2309
- id: v4(),
2310
- role: MessageRole.Assistant,
2311
- type: MessageType.Text,
2312
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
2313
- metadata: { content: "I'm sorry! I'm having trouble right now. Please refresh the page or try again in a moment." }
2314
- }]]);
2315
- };
2316
- const processStreamingResponse = async (stream, messageInterceptor, handleSearchResults, setMessages, setSearchIsLoading, chatId) => {
2317
- let lastMessage;
2318
- let hasSearchResults = false;
2319
- for await (const response of stream) try {
2320
- if (messageInterceptor.intercept(response)) return { hasSearchResults };
2321
- const message = messageFromResponse(response);
2322
- if (!message) throw new Error("Failed to transform API response to client message");
2323
- if (message.type === MessageType.ProductSearch) {
2324
- handleSearchResults(message);
2325
- hasSearchResults = true;
2326
- setSearchIsLoading(false);
2327
- }
2328
- lastMessage = updateMessageState(message, lastMessage, setMessages);
2329
- } catch (error) {
2330
- logger_default.logWarn(`[spiffy-ai] Failed to generate responses from stream chat_id=${chatId}`, error, {
2331
- lastResponse: lastMessage,
2332
- response
2333
- });
2334
- }
2335
- return { hasSearchResults };
2336
- };
2337
- const ChatContextProvider = ({ children }) => {
2338
- const logPerfMetric = useSetAtom(logPerfMetricAtom);
2339
- const [widgetInitialized, setWidgetInitialized] = useState(false);
2340
- const setUserHasReplied = useSetAtom(userHasRepliedAtom);
2341
- const [messages, setMessages] = useAtom(messagesAtom);
2342
- const setUserEvents = useSetAtom(userEventsAtom);
2343
- const setSuggestions = useSetAtom(suggestionsAtom);
2344
- const [suggestionsLoading, setSuggestionsLoading] = useAtom(suggestionsLoadingAtom);
2345
- const [responseStreaming, setResponseStreaming] = useAtom(responseStreamingAtom);
2346
- const setRequestFailure = useSetAtom(requestFailureAtom);
2347
- const userEvents = useAtomValue(userEventQueueAtom);
2348
- const userQueueEventCount = useAtomValue(userQueueEventCountAtom);
2349
- const markUserEventsProcessed = useSetAtom(processUserEventAtom);
2350
- const clearUserEventQueue = useSetAtom(clearUserEventAtom);
2351
- const userId = useAtomValue(userIdAtom);
2352
- const chatId = useAtomValue(chatIdAtom);
2353
- const supportedEvent = useAtomValue(supportedEventAtom);
2354
- const orgId = "mock-org-id";
2355
- const variantInfo = useAtomValue(variantInfoAtom);
2356
- const settingsContext = useSystemSettingsContext();
2357
- const messageInterceptor = useMessageInterceptor();
2358
- const handleSearchResults = useSetAtom(handleSearchResultsAtom);
2359
- const setSearchIsLoading = useSetAtom(chatSearchIsLoadingAtom);
2360
- const { track } = useAmplitudeTracking();
2361
- const getStreamingResponses = useCallback(async (payload) => {
2362
- logPerfMetric(PerfMetricsEvents.FirstResponseStarted);
2363
- const stream = commerce_api_default.getNextResponseStreaming(payload);
2364
- try {
2365
- setRequestFailure(false);
2366
- const { hasSearchResults } = await processStreamingResponse(stream, messageInterceptor, handleSearchResults, setMessages, setSearchIsLoading, chatId);
2367
- return { hasSearchResults };
2368
- } catch (e) {
2369
- handleStreamingError(e, setRequestFailure, setMessages);
2370
- throw e;
2371
- } finally {
2372
- logPerfMetric(PerfMetricsEvents.FirstResponseCompleted);
2373
- }
2374
- }, [
2375
- logPerfMetric,
2376
- setRequestFailure,
2377
- messageInterceptor,
2378
- handleSearchResults,
2379
- setMessages,
2380
- setSearchIsLoading,
2381
- chatId
2382
- ]);
2383
- const getSuggestions = useCallback(async () => {
2384
- logPerfMetric(PerfMetricsEvents.FirstSuggestionsStarted);
2385
- setSuggestionsLoading(true);
2386
- setSuggestions([]);
2387
- const payloadWithoutAppLoaded = createResponsePayload({
2388
- userEvents: [],
2389
- generationParams: settingsContext.generationParams
2390
- });
2391
- const response = await commerce_api_default.getNextSuggestions(payloadWithoutAppLoaded);
2392
- setSuggestions(response.sort((a, b) => a.content.length - b.content.length));
2393
- setSuggestionsLoading(false);
2394
- logPerfMetric(PerfMetricsEvents.FirstSuggestionsCompleted);
2395
- }, [
2396
- logPerfMetric,
2397
- setSuggestionsLoading,
2398
- setSuggestions,
2399
- settingsContext.generationParams
2400
- ]);
2401
- const getResponses = useCallback(async (payload) => {
2402
- try {
2403
- const requestPayload = payload ?? createResponsePayload({
2404
- userEvents,
2405
- generationParams: settingsContext.generationParams
2406
- });
2407
- setResponseStreaming(true);
2408
- setSuggestions([]);
2409
- const startTimeMs = Date.now();
2410
- await getStreamingResponses(requestPayload);
2411
- recordAssistantResponse(startTimeMs, requestPayload, track);
2412
- await getSuggestions();
2413
- } catch (error) {
2414
- logger_default.logError("[spiffy-ai] getResponses error", error);
2415
- } finally {
2416
- markUserEventsProcessed(userEvents.map(({ eventId }) => eventId));
2417
- setUserHasReplied(false);
2418
- setResponseStreaming(false);
2419
- }
2420
- }, [
2421
- userEvents,
2422
- settingsContext.generationParams,
2423
- setResponseStreaming,
2424
- setSuggestions,
2425
- getStreamingResponses,
2426
- markUserEventsProcessed,
2427
- getSuggestions,
2428
- setUserHasReplied,
2429
- track
2430
- ]);
2431
- useEffect(() => {
2432
- const processUserEvents = async () => {
2433
- if (responseStreaming || !widgetInitialized) return;
2434
- if (variantInfo.variant === "pdp" && !variantInfo.productId || variantInfo.variant === "plp" && !variantInfo.plpId || variantInfo.variant === "page_visit" && !variantInfo.url) {
2435
- logger_default.logDebug("[spiffy-ai] variantInfo has invalid values, skipping...", {
2436
- variantInfo,
2437
- supportedEvent
2438
- });
2439
- return;
2440
- }
2441
- logger_default.logDebug(`Assistants Turn is_currently_streaming=${responseStreaming} initialized=${widgetInitialized}`);
2442
- try {
2443
- await getResponses();
2444
- logger_default.logInfo(`Assistants Turn [finished]`);
2445
- } catch (error) {
2446
- logger_default.logError("[spiffy-ai] Assistants Turn error", error);
2447
- }
2448
- };
2449
- if (userQueueEventCount > 0) processUserEvents();
2450
- }, [
2451
- getResponses,
2452
- responseStreaming,
2453
- userQueueEventCount,
2454
- widgetInitialized,
2455
- variantInfo,
2456
- supportedEvent
2457
- ]);
2458
- useEffect(() => {
2459
- if (widgetInitialized || responseStreaming) {
2460
- logger_default.logDebug(`[spiffy-ai] initializeWidget [skipped] is_currently_streaming=${responseStreaming} is_initialized=${widgetInitialized}`);
2461
- return;
2462
- }
2463
- const hydrateChat = async () => {
2464
- try {
2465
- logger_default.logDebug(`[spiffy-ai] initializeWidget is_currently_streaming=${responseStreaming} is_initialized=${widgetInitialized}`);
2466
- const { messages: existingMessages, userEvents: userEvents$1 } = await commerce_api_default.getResponses(orgId, chatId, userId);
2467
- setMessages([...existingMessages]);
2468
- setUserEvents([...userEvents$1]);
2469
- getResponses();
2470
- } catch (error) {
2471
- logger_default.logInfo(`Init chat [exception] chat_id=${chatId} error=${error}`, error);
2472
- if (error instanceof SessionRestartRequired) {
2473
- const appLoadedEvent = createAppLoadedEvent();
2474
- const visitEvent = createVisitUserEvent({ variantInfo });
2475
- setMessages([]);
2476
- clearUserEventQueue();
2477
- if (visitEvent) {
2478
- const payload = createResponsePayload({
2479
- userEvents: [appLoadedEvent, visitEvent],
2480
- generationParams: settingsContext.generationParams
2481
- });
2482
- getResponses(payload);
2483
- }
2484
- }
2485
- } finally {
2486
- setWidgetInitialized(true);
2487
- }
2488
- };
2489
- hydrateChat();
2490
- }, []);
2491
- const onFocus = useCallback(async () => {
2492
- try {
2493
- if (!responseStreaming && !suggestionsLoading && orgId) {
2494
- const { messages: existingMessages } = await commerce_api_default.getResponses(orgId, chatId, userId);
2495
- if (existingMessages.length > messages.length) setMessages([...existingMessages]);
2496
- }
2497
- } catch (error) {
2498
- logger_default.logError("[spiffy-ai] onFocus error", error);
2499
- }
2500
- }, [
2501
- responseStreaming,
2502
- suggestionsLoading,
2503
- orgId,
2504
- chatId,
2505
- userId,
2506
- messages.length,
2507
- setMessages
2508
- ]);
2509
- useEffect(() => {
2510
- window.addEventListener("focus", onFocus);
2511
- return () => {
2512
- window.removeEventListener("focus", onFocus);
2513
- };
2514
- }, [onFocus]);
2515
- const chatContext = useMemo(() => ({}), []);
2516
- return /* @__PURE__ */ jsx(ChatContext.Provider, {
2517
- value: chatContext,
2518
- children
2519
- });
2520
- };
2521
-
2522
- //#endregion
2523
- //#region src/contexts/enviveCssContext.tsx
2524
- const EnviveCssProvider = ({ children }) => {
2525
- const { colorsConfig, frontendConfig, loading } = useNewOrgConfig();
2526
- let merchantThemeCss = `* {}`;
2527
- if (colorsConfig && !loading) merchantThemeCss = `
2528
- * {
2529
- --spiffy-colors-text-primary: ${colorsConfig.textPrimary};
2530
- --spiffy-colors-text-secondary: ${colorsConfig.textSecondary};
2531
- --spiffy-colors-text-accent: ${colorsConfig.textAccent};
2532
- --spiffy-colors-text-link: ${colorsConfig.textLink};
2533
- --spiffy-colors-text-light: ${colorsConfig.textLight};
2534
- --spiffy-colors-background-primary: ${colorsConfig.backgroundPrimary};
2535
- --spiffy-colors-background-secondary: ${colorsConfig.backgroundSecondary};
2536
- --spiffy-colors-background-secondary-dark: ${colorsConfig.backgroundSecondaryDark};
2537
- --spiffy-colors-background-tertiary: ${colorsConfig.backgroundTertiary};
2538
- --spiffy-colors-background-dark: ${colorsConfig.backgroundDark};
2539
- --spiffy-colors-background-light: ${colorsConfig.backgroundLight};
2540
- --spiffy-colors-background-saturated: ${colorsConfig.backgroundSaturated};
2541
- --spiffy-colors-border-light: ${colorsConfig.borderLight};
2542
- --spiffy-colors-border-medium: ${colorsConfig.borderMedium};
2543
- --spiffy-colors-border-dark: ${colorsConfig.borderDark};
2544
- --spiffy-colors-border-outline: ${colorsConfig.borderOutline};
2545
- --spiffy-colors-accent-primary: ${colorsConfig.accentPrimary};
2546
- --spiffy-colors-accent-secondary: ${colorsConfig.accentSecondary};
2547
- }`;
2548
- console.log(frontendConfig);
2549
- return /* @__PURE__ */ jsxs(Fragment, { children: [
2550
- frontendConfig ? /* @__PURE__ */ jsx("style", {
2551
- id: "merchant-css-overrides",
2552
- children: `${frontendConfig.merchantOverrideCss}`
2553
- }) : null,
2554
- colorsConfig ? /* @__PURE__ */ jsx("style", {
2555
- id: "merchant-css-colors",
2556
- children: `${merchantThemeCss}`
2557
- }) : null,
2558
- children
2559
- ] });
2560
- };
2561
-
2562
- //#endregion
2563
- //#region src/contexts/systemSettingsContext.tsx
2564
- const getChatModelName = () => {
2565
- const urlObj = new URL(window.location.href);
2566
- const params = new URLSearchParams(urlObj.search);
2567
- return Object.fromEntries(params.entries()).llm_model_name;
2568
- };
2569
- const defaultGenerationParams = {
2570
- stream: true,
2571
- numSuggestions: 3,
2572
- model: getChatModelName()
2573
- };
2574
- const SystemSettingsContext = createContext(void 0);
2575
- const SystemSettingsContextProvider = ({ children, generationParams, showDebugBar }) => {
2576
- const [params, setParams] = useState(() => generationParams ?? defaultGenerationParams);
2577
- const endpointURL = useAtomValue(baseUrlAtom);
2578
- const settingsContextValues = useMemo(() => ({
2579
- generationParams: params,
2580
- showDebugBar,
2581
- setGenerationParams: setParams,
2582
- endpointURL
2583
- }), [
2584
- generationParams,
2585
- endpointURL,
2586
- showDebugBar
2587
- ]);
2588
- return /* @__PURE__ */ jsx(SystemSettingsContext.Provider, {
2589
- value: settingsContextValues,
2590
- children
2591
- });
2592
- };
2593
-
2594
- //#endregion
2595
- export { CdnProvider, ChatContext, ChatContextProvider, EnviveCssProvider, FeatureFlagServiceProvider, GraphQLProvider, NewOrgConfigProvider, SearchProvider, SearchResultsState, SessionStorageProvider, ShopifyUrlProvider, SystemSettingsContext, SystemSettingsContextProvider, UserIdentityProvider, createAppLoadedEvent, createVisitUserEvent, defaultGenerationParams, getSearchResultsState, isElementPartiallyVisible, isWithinBusinessHours, useAmplitudeTracking, useAssetUrl, useBlockBackButton, useCdn, useCdnBasePath, useCdnUrl, useChatToggle, useChatToggleAnalytics, useColorsAndFrontendConfig, useCurrentPageType, useCustomerSupportHandoff, useDebounce, useElementObserver, useEnviveFeatureFlag, useFeatureFlagService, useGrabAndScroll, useGraphQLClient, useIdentifyUser, useImageResolver, useIntersection, useIsSmallScreen, useLocalStorageListener, useLocalStorageValue, useMessageFilter, useMessageScrollObserver, useNewOrgConfig, useNewOrgConfigContext, useOrgId, useProductId, useProductSearch, useSearch, useSearchService, useSearchWithQuery, useSessionStorage, useSessionStorageValue, useShopifyUrl, useShopifyUrlOperations, useSnapCalculator, useSpiffyFeatureFlag, useSystemSettingsContext, useTrackComponentVisibleEvent, useUpdateAnalyticsProps, useUserIdentity };
2596
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dHMtREdscjdNMW8uanMiLCJuYW1lcyI6WyJDZG5Qcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+IiwiZXJyb3JSZXNwb25zZUJvZHkiLCJ0aHJvd1Nlc3Npb25SZXN0YXJ0UmVxdWlyZWRJZiIsImNvbmZpZzogQ29uZmlndXJhdGlvbiIsImNvbnRleHQ6IENvbnRleHQiLCJlcnI6IHVua25vd24iLCJlcnJvcjogdW5rbm93biIsImRhdGE6IFYxR2V0U2Vzc2lvbk1lc3NhZ2VzMjAwUmVzcG9uc2UiLCJyZXNwb25zZXM6IFJlc3BvbnNlW11bXSIsInN1Z2dlc3Rpb25zOiBTdWdnZXN0aW9uW10iLCJ1c2VyRXZlbnRzOiBVc2VyRXZlbnRbXSIsImFzc2lzdGFudE1lc3NhZ2VzOiBNZXNzYWdlW11bXSIsInVzZXJNZXNzYWdlczogTWVzc2FnZVtdW10iLCJyZXF1ZXN0OiBWMU9yZ0NvbmZpZ0dldFJlcXVlc3QiLCJVc2VySWRlbnRpdHlQcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+IiwidXVpZCIsIkNvbW1lcmNlQXBpQ2xpZW50IiwibGlzdGVuZXI6IExvY2FsU3RvcmFnZUV2ZW50TGlzdGVuZXIiLCJGZWF0dXJlRmxhZ1NlcnZpY2VQcm92aWRlcjogUmVhY3QuRkM8XG4gIEZlYXR1cmVGbGFnU2VydmljZVByb3ZpZGVyUHJvcHNcbj4iLCJOZXdPcmdDb25maWdQcm92aWRlcjogUmVhY3QuRkM8TmV3T3JnQ29uZmlnUHJvdmlkZXJQcm9wcz4iLCJ1dWlkIiwiaGFuZGxlU2VsZWN0RmlsdGVySXRlbTogU2VsZWN0RmlsdGVySXRlbSIsImVudml2ZU9yZ1Nob3J0TmFtZUF0b20iLCJlbnZpdmVFbnZBdG9tIiwiU2VhcmNoUHJvdmlkZXI6IFJlYWN0LkZDPHsgY2hpbGRyZW46IFJlYWN0LlJlYWN0Tm9kZSB9PiIsImNvbmZpZzogQ29uZmlndXJhdGlvbiIsIlNlc3Npb25TdG9yYWdlUHJvdmlkZXI6IFJlYWN0LkZDPHtcbiAgY2hpbGRyZW46IFJlYWN0LlJlYWN0Tm9kZTtcbn0+IiwidmFsdWUiLCJTaG9waWZ5VXJsUHJvdmlkZXI6IFJlYWN0LkZDPHsgY2hpbGRyZW46IFJlYWN0LlJlYWN0Tm9kZSB9PiIsImRlZmF1bHRFdmVudFByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IiwidXNlclF1ZXJ5UHJvcGVydHk6IHN0cmluZyB8IHVuZGVmaW5lZCIsImV2ZW50UHJvcHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IiwidXVpZCIsImxhc3RNZXNzYWdlOiBNZXNzYWdlIHwgdW5kZWZpbmVkIiwiZXJyb3I6IHVua25vd24iLCJDb21tZXJjZUFwaUNsaWVudCIsInVzZXJFdmVudHMiLCJFbnZpdmVDc3NQcm92aWRlcjogUmVhY3QuRkM8RW52aXZlQ3NzUHJvdmlkZXJQcm9wcz4iLCJkZWZhdWx0R2VuZXJhdGlvblBhcmFtczogR2VuZXJhdGlvblBhcmFtcyJdLCJzb3VyY2VzIjpbIi4uL3NyYy9jb250ZXh0cy9jZG5Db250ZXh0LnRzeCIsIi4uL3NyYy90eXBlcy9leGNlcHRpb25zL3Nlc3Npb25FeGNlcHRpb25zLnRzIiwiLi4vc3JjL3R5cGVzL2V4Y2VwdGlvbnMvdW5zdXBwb3J0ZWRQcm9kdWN0RXhjZXB0aW9ucy50cyIsIi4uL3NyYy9hcHBsaWNhdGlvbi9jb21tZXJjZS1hcGkudHMiLCIuLi9zcmMvaG9va3MvdXNlQW1wbGl0dWRlT3BlcmF0aW9ucy50cyIsIi4uL3NyYy9ob29rcy91c2VCbG9ja0JhY2tCdXR0b24udHMiLCIuLi9zcmMvaG9va3MvdXNlQ2RuT3BlcmF0aW9ucy50cyIsIi4uL3NyYy9ob29rcy91c2VDaGF0VG9nZ2xlLnRzIiwiLi4vc3JjL2hvb2tzL3VzZUNoYXRUb2dnbGVBbmFseXRpY3MudHMiLCIuLi9zcmMvaG9va3MvdXNlQ3VzdG9tZXJTdXBwb3J0SGFuZG9mZi50cyIsIi4uL3NyYy9ob29rcy91c2VEZWJvdW5jZS50cyIsIi4uL3NyYy9ob29rcy91c2VFbGVtZW50T2JzZXJ2ZXIudHMiLCIuLi9zcmMvaG9va3MvdXNlR3JhYkFuZFNjcm9sbC50cyIsIi4uL3NyYy9jb250ZXh0cy9ncmFwaHFsQ29udGV4dC50c3giLCIuLi9zcmMvaG9va3MvdXNlR3JhcGhRTENvbmZpZy50cyIsIi4uL3NyYy9jb250ZXh0cy91c2VySWRlbnRpdHlDb250ZXh0LnRzeCIsIi4uL3NyYy9ob29rcy91c2VJZGVudGlmeVVzZXIudHMiLCIuLi9zcmMvaG9va3MvdXNlSW1hZ2VSZXNvbHZlci50cyIsIi4uL3NyYy9ob29rcy91c2VJbnRlcnNlY3Rpb24udHMiLCIuLi9zcmMvaG9va3MvdXNlSXNTbWFsbFNjcmVlbi50cyIsIi4uL3NyYy9ob29rcy91c2VMb2NhbFN0b3JhZ2VPcGVyYXRpb25zLnRzIiwiLi4vc3JjL2hvb2tzL3VzZU1lc3NhZ2VGaWx0ZXIudHMiLCIuLi9zcmMvaG9va3MvdXNlTWVzc2FnZVNjcm9sbE9ic2VydmVyLnRzIiwiLi4vc3JjL2NvbnRleHRzL2ZlYXR1cmVGbGFnU2VydmljZUNvbnRleHQudHN4IiwiLi4vc3JjL2NvbnRleHRzL25ld09yZ0NvbmZpZ0NvbnRleHQudHN4IiwiLi4vc3JjL2hvb2tzL3VzZU5ld09yZ0NvbmZpZy50cyIsIi4uL3NyYy9ob29rcy91dGlscy50cyIsIi4uL3NyYy9ob29rcy91c2VTZWFyY2gudHN4IiwiLi4vc3JjL2hvb2tzL3VzZUFwcERldGFpbHMudHMiLCIuLi9zcmMvY29udGV4dHMvc2VhcmNoQ29udGV4dC50c3giLCIuLi9zcmMvaG9va3MvdXNlU2VhcmNoT3BlcmF0aW9ucy50cyIsIi4uL3NyYy9jb250ZXh0cy9zZXNzaW9uU3RvcmFnZUNvbnRleHQudHN4IiwiLi4vc3JjL2hvb2tzL3VzZVNlc3Npb25TdG9yYWdlT3BlcmF0aW9ucy50cyIsIi4uL3NyYy9jb250ZXh0cy9zaG9waWZ5VXJsQ29udGV4dC50c3giLCIuLi9zcmMvaG9va3MvdXNlU2hvcGlmeVVybE9wZXJhdGlvbnMudHMiLCIuLi9zcmMvaG9va3MvdXNlU25hcENhbGN1bGF0b3IudHMiLCIuLi9zcmMvaG9va3MvdXNlU3lzdGVtU2V0dGluZ3NDb250ZXh0LnRzIiwiLi4vc3JjL2hvb2tzL3VzZVRyYWNrQ29tcG9uZW50VmlzaWJsZUV2ZW50LnRzIiwiLi4vc3JjL2hvb2tzL3VzZVVwZGF0ZUFuYWx5dGljc1Byb3BzLnRzIiwiLi4vc3JjL2NvbnRleHRzL2NoYXRDb250ZXh0LnRzeCIsIi4uL3NyYy9jb250ZXh0cy9lbnZpdmVDc3NDb250ZXh0LnRzeCIsIi4uL3NyYy9jb250ZXh0cy9zeXN0ZW1TZXR0aW5nc0NvbnRleHQudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCwgeyBjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0LCB1c2VDYWxsYmFjaywgdXNlTWVtbyB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgdXNlQXRvbVZhbHVlIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQgeyBjZG5VcmxBdG9tIH0gZnJvbSBcIi4uL2F0b21zL2Vudml2ZS9lbnZpdmVDb25maWdcIjtcblxuaW50ZXJmYWNlIENkbkNvbnRleHRUeXBlIHtcbiAgY2RuVXJsOiBzdHJpbmc7XG4gIGdldENkbkJhc2VQYXRoOiAoKSA9PiBzdHJpbmc7XG4gIGdldEFzc2V0VVJMOiAoYXNzZXROYW1lOiBzdHJpbmcsIG9yZ1Nob3J0TmFtZTogc3RyaW5nKSA9PiBzdHJpbmc7XG59XG5cbmNvbnN0IENkbkNvbnRleHQgPSBjcmVhdGVDb250ZXh0PENkbkNvbnRleHRUeXBlIHwgbnVsbD4obnVsbCk7XG5cbmV4cG9ydCBjb25zdCBDZG5Qcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+ID0gKHtcbiAgY2hpbGRyZW4sXG59KSA9PiB7XG4gIGNvbnN0IGNkblVybEF0b21WYWx1ZSA9IHVzZUF0b21WYWx1ZShjZG5VcmxBdG9tKTtcbiAgY29uc3QgY2RuVXJsID0gY2RuVXJsQXRvbVZhbHVlIHx8IFwiaHR0cHM6Ly9jZG4uc3BpZmZ5LmFpL290aGVyXCI7XG5cbiAgY29uc3QgZ2V0Q2RuQmFzZVBhdGggPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgcmV0dXJuIGNkblVybDtcbiAgfSwgW2NkblVybF0pO1xuXG4gIGNvbnN0IGdldEFzc2V0VVJMID0gdXNlQ2FsbGJhY2soXG4gICAgKGFzc2V0TmFtZTogc3RyaW5nLCBvcmdTaG9ydE5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgcmV0dXJuIGAke2dldENkbkJhc2VQYXRoKCl9L2Fzc2V0cy8ke29yZ1Nob3J0TmFtZX0vJHthc3NldE5hbWV9YDtcbiAgICB9LFxuICAgIFtnZXRDZG5CYXNlUGF0aF1cbiAgKTtcblxuICBjb25zdCB2YWx1ZSA9IHVzZU1lbW8oXG4gICAgKCkgPT4gKHtcbiAgICAgIGNkblVybCxcbiAgICAgIGdldENkbkJhc2VQYXRoLFxuICAgICAgZ2V0QXNzZXRVUkwsXG4gICAgfSksXG4gICAgW2NkblVybCwgZ2V0Q2RuQmFzZVBhdGgsIGdldEFzc2V0VVJMXVxuICApO1xuXG4gIHJldHVybiA8Q2RuQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17dmFsdWV9PntjaGlsZHJlbn08L0NkbkNvbnRleHQuUHJvdmlkZXI+O1xufTtcblxuZXhwb3J0IGNvbnN0IHVzZUNkbiA9ICgpID0+IHtcbiAgY29uc3QgY29udGV4dCA9IHVzZUNvbnRleHQoQ2RuQ29udGV4dCk7XG4gIGlmICghY29udGV4dCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcInVzZUNkbiBtdXN0IGJlIHVzZWQgd2l0aGluIGEgQ2RuUHJvdmlkZXJcIik7XG4gIH1cbiAgcmV0dXJuIGNvbnRleHQ7XG59O1xuIiwiZXhwb3J0IGNsYXNzIFNlc3Npb25SZXN0YXJ0UmVxdWlyZWQgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCdTZXNzaW9uIHJlc3RhcnQgcmVxdWlyZWQnKTtcbiAgICB0aGlzLm5hbWUgPSAnU2Vzc2lvblJlc3RhcnRSZXF1aXJlZCc7XG4gIH1cbn1cbiIsImV4cG9ydCBjbGFzcyBVbnN1cHBvcnRlZFByb2R1Y3RFeGNlcHRpb24gZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCdVbnN1cHBvcnRlZCBwcm9kdWN0Jyk7XG4gICAgdGhpcy5uYW1lID0gJ1Vuc3VwcG9ydGVkUHJvZHVjdCc7XG4gIH1cbn0iLCJpbXBvcnQgTG9nZ2VyIGZyb20gXCJzcmMvYXBwbGljYXRpb24vbG9nZ2luZy9sb2dnZXJcIjtcbmltcG9ydCB7XG4gIENvbmZpZ3VyYXRpb24sXG4gIEN1c3RvbWVyU2VydmljZUFwaSxcbiAgRGVmYXVsdEFwaSxcbiAgSW5mZXJlbmNlQXBpLFxuICBSZXBvcnRTZXNzaW9uUmVxdWVzdCxcbiAgUmVzcG9uc2VFcnJvcixcbiAgVXNlckV2ZW50Q2F0ZWdvcnksXG4gIFYxR2V0U2Vzc2lvbk1lc3NhZ2VzMjAwUmVzcG9uc2UsXG4gIFYxT3JnQ29uZmlnR2V0UmVxdWVzdCxcbiAgQ29udGV4dFNvdXJjZUVudW0sXG4gIFYxT3JnQ29uZmlnR2V0U291cmNlRW51bSxcbiAgQ3VzdG9tZXJTZXJ2aWNlUHJvdmlkZXIsXG4gIFJlc3BvbnNlQ2F0ZWdvcnksXG4gIEZvcm1UeXBlLFxufSBmcm9tIFwiQHNwaWZmeS1haS9jb21tZXJjZS1hcGktY2xpZW50XCI7XG5pbXBvcnQgeyB2YWxpZGF0ZVN1Z2dlc3Rpb24gfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy92YWxpZGF0b3JzL3ZhbGlkYXRlU3VnZ2VzdGlvblwiO1xuaW1wb3J0IHsgdmFsaWRhdGVVc2VyRXZlbnQgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy92YWxpZGF0b3JzL3ZhbGlkYXRlVXNlckV2ZW50XCI7XG5pbXBvcnQge1xuICBtZXNzYWdlRnJvbVF1ZXJ5RXZlbnQsXG4gIG1lc3NhZ2VGcm9tUmVzcG9uc2UsXG4gIG1lc3NhZ2VGcm9tU3VnZ2VzdGlvbkV2ZW50LFxufSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL3V0aWxzXCI7XG5pbXBvcnQge1xuICBNZXNzYWdlLFxuICBOZXh0TWVzc2FnZVJlcXVlc3QsXG4gIFJlc3BvbnNlLFxuICBTdWdnZXN0aW9uLFxuICBTdXBwb3J0ZWRFdmVudFJlcXVlc3QsXG4gIFVzZXJFdmVudCxcbn0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHNcIjtcbmltcG9ydCB7IG1lc3NhZ2VSZXF1ZXN0VG9Db21tZXJjZU1lc3NhZ2VSZXF1ZXN0IH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi91dGlscy9uZXh0TWVzc2FnZVJlcXVlc3RUb0FwaVJlcXVlc3RcIjtcbmltcG9ydCB7IHZhbGlkYXRlUmVzcG9uc2UgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy92YWxpZGF0b3JzL3ZhbGlkYXRlUmVzcG9uc2VcIjtcbmltcG9ydCB7IGNvcmVTdXBwb3J0ZWRFdmVudFJlcXVlc3RUb0FwaVJlcXVlc3QgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL3V0aWxzL3N1cHBvcnRlZEV2ZW50UmVxdWVzdFRvQXBpUmVxdWVzdFwiO1xuaW1wb3J0IHsgU2Vzc2lvblJlc3RhcnRSZXF1aXJlZCB9IGZyb20gXCJzcmMvdHlwZXMvZXhjZXB0aW9ucy9zZXNzaW9uRXhjZXB0aW9uc1wiO1xuaW1wb3J0IHsgVW5zdXBwb3J0ZWRQcm9kdWN0RXhjZXB0aW9uIH0gZnJvbSBcInNyYy90eXBlcy9leGNlcHRpb25zL3Vuc3VwcG9ydGVkUHJvZHVjdEV4Y2VwdGlvbnNcIjtcbmltcG9ydCB7IENsaWVudERldGFpbHMgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9jbGllbnREZXRhaWxzXCI7XG5pbXBvcnQgeyBnZXRBdG9tU3RvcmUgfSBmcm9tIFwic3JjL2F0b21zL2F0b21TdG9yZS9hdG9tU3RvcmVcIjtcbmltcG9ydCB7IFByb2R1Y3RFeHBlcmltZW50IH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvcHJvZHVjdEV4cGVyaW1lbnRcIjtcbmltcG9ydCB7IEZlYXR1cmVHYXRlcyB9IGZyb20gXCJzcmMvYXBwbGljYXRpb24vbW9kZWxzL2ZlYXR1cmVHYXRlc1wiO1xuaW1wb3J0IHsgdmFsaWRhdGVPcmdDb25maWdSZXN1bHRzIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvdmFsaWRhdG9ycy92YWxpZGF0ZU9yZ0NvbmZpZ1Jlc3VsdHNcIjtcbmltcG9ydCB7IE9yZ0NvbmZpZyB9IGZyb20gXCJzcmMvYXBwbGljYXRpb24vbW9kZWxzL2FwaS9vcmdDb25maWdSZXN1bHRzXCI7XG5pbXBvcnQgeyBTdXBwb3J0ZWRFdmVudCB9IGZyb20gXCJzcmMvYXRvbXMvYXBwL3ZhcmlhbnRcIjtcbmltcG9ydCB7IG1lc3NhZ2VGcm9tRm9ybVN1Ym1pdHRlZEV2ZW50IH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi91dGlscy9tZXNzYWdlRnJvbUZvcm1TdWJtaXR0ZWRFdmVudFwiO1xuaW1wb3J0IHR5cGUgeyBDb250ZXh0IH0gZnJvbSBcIkBzcGlmZnktYWkvY29tbWVyY2UtYXBpLWNsaWVudC9kaXN0L21vZGVscy9Db250ZXh0XCI7XG5pbXBvcnQgeyBDb250ZXh0RW52RW51bSB9IGZyb20gXCJAc3BpZmZ5LWFpL2NvbW1lcmNlLWFwaS1jbGllbnRcIjsgLy8gSW1wb3J0IENvbnRleHRFbnZFbnVtXG5pbXBvcnQge1xuICBiYXNlVXJsQXRvbSxcbiAgcmVhY3RBcHBOYW1lQXRvbSxcbiAgY29udGV4dFNvdXJjZUF0b20sXG4gIG9yZ1Nob3J0TmFtZUF0b20sXG4gIGVudkF0b20sIC8vIEltcG9ydCBlbnZBdG9tXG59IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuaW1wb3J0IHsgdXNlcklkQXRvbSwgY2hhdElkQXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvYXBwXCI7IC8vIEltcG9ydCB1c2VySWRBdG9tIGFuZCBjaGF0SWRBdG9tXG5pbXBvcnQgeyBvcmdJZEF0b20sIGZlYXR1cmVGbGFnU2VydmljZUF0b20gfSBmcm9tIFwic3JjL2F0b21zL29yZy9ncmFwaHFsQ29uZmlnXCI7IC8vIEltcG9ydCBuZXcgb3JnSWRBdG9tIGFuZCBmZWF0dXJlRmxhZ1NlcnZpY2VBdG9tXG5cbmFzeW5jIGZ1bmN0aW9uIGVycm9yUmVzcG9uc2VCb2R5KGVycm9yOiBSZXNwb25zZUVycm9yKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IGVycm9yLnJlc3BvbnNlLmpzb24oKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHRocm93U2Vzc2lvblJlc3RhcnRSZXF1aXJlZElmKGVycm9yTXNnOiBzdHJpbmcsIGVycm9yOiB1bmtub3duKSB7XG4gIGlmICghKGVycm9yIGluc3RhbmNlb2YgUmVzcG9uc2VFcnJvcikpIHtcbiAgICBMb2dnZXIubG9nSW5mbyhlcnJvck1zZywgZXJyb3IpO1xuICAgIHRocm93IGVycm9yO1xuICB9XG5cbiAgY29uc3QgZXJyb3JSZXNwb25zZSA9IGF3YWl0IGVycm9yUmVzcG9uc2VCb2R5KGVycm9yKTtcbiAgaWYgKFxuICAgIGVycm9yUmVzcG9uc2U/Lm1lc3NhZ2U/LnRvTG93ZXJDYXNlKCkgPT09IFwidW5zdXBwb3J0ZWQgcHJvZHVjdFwiIHx8IC8vIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LiBuZXdlciB2ZXJzaW9ucyBvZiB0aGUgQVBJIHJldHVybiBzdWJfY29kZSBpbnN0ZWFkIG9mIG1lc3NhZ2VcbiAgICBlcnJvclJlc3BvbnNlPy5hcHBfY29kZT8udG9VcHBlckNhc2UoKSA9PT0gXCJQUk9EVUNUX05PVF9GT1VORFwiXG4gICkge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZFByb2R1Y3RFeGNlcHRpb24oKTtcbiAgfSBlbHNlIGlmIChcbiAgICBlcnJvclJlc3BvbnNlPy5hcHBfY29kZT8udG9VcHBlckNhc2UoKSA9PT0gXCJSRVNUQVJUX1NFU1NJT05cIiB8fFxuICAgIGVycm9yUmVzcG9uc2U/LnN1Yl9jb2RlPy50b1VwcGVyQ2FzZSgpID09PSBcIk5PVF9GT1VORFwiIC8vIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LiBuZXcgQVBJIHJlc3BvbnNlcyB3aWxsIGNvbnRhaW4gXCJhcHBfY29kZVwiXG4gICkge1xuICAgIExvZ2dlci5sb2dJbmZvKFxuICAgICAgXCJTZXNzaW9uIGRvZXMgbm90IGV4aXN0LiBSZS1zdGFydCBzZXNzaW9uXCIsXG4gICAgICBlcnJvcixcbiAgICAgIGVycm9yLnJlc3BvbnNlLFxuICAgICAgZXJyb3JSZXNwb25zZVxuICAgICk7XG4gICAgdGhyb3cgbmV3IFNlc3Npb25SZXN0YXJ0UmVxdWlyZWQoKTtcbiAgfVxuXG4gIExvZ2dlci5sb2dJbmZvKGVycm9yTXNnLCBlcnJvcik7XG4gIHRocm93IGVycm9yO1xufVxuXG5jbGFzcyBDb21tZXJjZUFwaUNsaWVudCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdEFwaTogRGVmYXVsdEFwaTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGN1c3RvbWVyU2VydmljZUFwaTogQ3VzdG9tZXJTZXJ2aWNlQXBpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgaW5mZXJlbmNlQXBpOiBJbmZlcmVuY2VBcGk7XG5cbiAgcHJpdmF0ZSBzdGF0aWMgaW5zdGFuY2U6IENvbW1lcmNlQXBpQ2xpZW50IHwgdW5kZWZpbmVkO1xuXG4gIHByaXZhdGUgc3VnZ2VzdGlvbnNBYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgcHJpdmF0ZSByZXNwb25zZXNBYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0SW5zdGFuY2UgPSAoKTogQ29tbWVyY2VBcGlDbGllbnQgPT4ge1xuICAgIGlmICghQ29tbWVyY2VBcGlDbGllbnQuaW5zdGFuY2UpIHtcbiAgICAgIENvbW1lcmNlQXBpQ2xpZW50Lmluc3RhbmNlID0gbmV3IENvbW1lcmNlQXBpQ2xpZW50KCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIENvbW1lcmNlQXBpQ2xpZW50Lmluc3RhbmNlO1xuICB9O1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoYmFzZVBhdGg/OiBzdHJpbmcpIHtcbiAgICBjb25zdCBhdG9tU3RvcmUgPSBnZXRBdG9tU3RvcmUoKTtcbiAgICBjb25zdCBiYXNlVXJsID0gYXRvbVN0b3JlLmdldChiYXNlVXJsQXRvbSk7XG4gICAgY29uc3QgcGF0aCA9IGJhc2VQYXRoIHx8IGJhc2VVcmw7XG4gICAgLy8gQVBJIEtleSBpcyBub3cgaGFuZGxlZCBhdCB0aGUgRW52aXZlQ29uZmlnUHJvdmlkZXIgbGV2ZWxcbiAgICBjb25zdCBjb25maWc6IENvbmZpZ3VyYXRpb24gPSBuZXcgQ29uZmlndXJhdGlvbih7XG4gICAgICBiYXNlUGF0aDogcGF0aCxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgIEFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIHRoaXMuZGVmYXVsdEFwaSA9IG5ldyBEZWZhdWx0QXBpKGNvbmZpZyk7XG4gICAgdGhpcy5pbmZlcmVuY2VBcGkgPSBuZXcgSW5mZXJlbmNlQXBpKGNvbmZpZyk7XG4gICAgdGhpcy5jdXN0b21lclNlcnZpY2VBcGkgPSBuZXcgQ3VzdG9tZXJTZXJ2aWNlQXBpKGNvbmZpZyk7XG4gIH1cblxuICBzdGF0aWMgcmVzb2x2ZVVybCA9IGFzeW5jICh1cmw6IHN0cmluZykgPT4ge1xuICAgIGNvbnN0IGF0b21TdG9yZSA9IGdldEF0b21TdG9yZSgpO1xuICAgIGNvbnN0IG9yZ1Nob3J0TmFtZSA9IGF0b21TdG9yZS5nZXQob3JnU2hvcnROYW1lQXRvbSk7XG4gICAgY29uc3Qgb3JnSWQgPSBhdG9tU3RvcmUuZ2V0KG9yZ0lkQXRvbSk7XG4gICAgY29uc3QgdXNlcklkID0gYXRvbVN0b3JlLmdldCh1c2VySWRBdG9tKTtcbiAgICBjb25zdCBjaGF0SWQgPSBhdG9tU3RvcmUuZ2V0KGNoYXRJZEF0b20pO1xuICAgIGNvbnN0IHNvdXJjZSA9IGF0b21TdG9yZS5nZXQoY29udGV4dFNvdXJjZUF0b20pO1xuICAgIGNvbnN0IGVudiA9IGF0b21TdG9yZS5nZXQoZW52QXRvbSk7XG5cbiAgICBjb25zdCBmZWF0dXJlRmxhZ1NlcnZpY2UgPSBhdG9tU3RvcmUuZ2V0KGZlYXR1cmVGbGFnU2VydmljZUF0b20pO1xuXG4gICAgY29uc3QgY29udGV4dDogQ29udGV4dCA9IHtcbiAgICAgIHVzZXJfaWQ6IHVzZXJJZCA/PyBcIlwiLFxuICAgICAgb3JnX2lkOiBvcmdJZCA/PyBcIlwiLFxuICAgICAgb3JnX3Nob3J0X25hbWU6IG9yZ1Nob3J0TmFtZSA/PyBcIlwiLFxuICAgICAgY2hhdF9pZDogY2hhdElkID8/IFwiXCIsXG4gICAgICBzb3VyY2U6IHNvdXJjZSA/PyBDb250ZXh0U291cmNlRW51bS5BcHAsXG4gICAgICBlbnY6IChlbnYgYXMgQ29udGV4dEVudkVudW0pID8/IENvbnRleHRFbnZFbnVtLkRldiwgLy8gQ2FzdCBlbnYgdG8gQ29udGV4dEVudkVudW1cbiAgICB9O1xuXG4gICAgY29uc3QgZmVhdHVyZUdhdGVzID1cbiAgICAgIGZlYXR1cmVGbGFnU2VydmljZT8uZmVhdHVyZUZsYWdTZXJ2aWNlPy5nZXRGZWF0dXJlRmxhZ3MoKSB8fCB7fTtcbiAgICBjb25zdCB1cmxSZXNvbHZpbmdSZXF1ZXN0ID0ge1xuICAgICAgdXJsLFxuICAgICAgY29udGV4dCxcbiAgICAgIGZlYXR1cmVfZ2F0ZXM6IGZlYXR1cmVHYXRlcyxcbiAgICB9O1xuXG4gICAgY29uc3QgcmF3UmVzcG9uc2UgPVxuICAgICAgYXdhaXQgQ29tbWVyY2VBcGlDbGllbnQuZ2V0SW5zdGFuY2UoKS5pbmZlcmVuY2VBcGkudjFVcmxSZXNvbHZpbmdQb3N0UmF3KHtcbiAgICAgICAgVXJsUmVzb2x2aW5nUmVxdWVzdDogdXJsUmVzb2x2aW5nUmVxdWVzdCxcbiAgICAgIH0pO1xuXG4gICAgY29uc3QgcmVzcG9uc2VCb2R5ID0gYXdhaXQgcmF3UmVzcG9uc2UucmF3Lmpzb24oKTtcblxuICAgIHJldHVybiByZXNwb25zZUJvZHk7XG4gIH07XG5cbiAgc3RhdGljIHJlcG9ydFNlc3Npb24gPSBhc3luYyAoXG4gICAgcmVwb3J0UmVxdWVzdDogUmVwb3J0U2Vzc2lvblJlcXVlc3RcbiAgKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgYXdhaXQgQ29tbWVyY2VBcGlDbGllbnQuZ2V0SW5zdGFuY2UoKS5kZWZhdWx0QXBpLnYxQ2hhdHNSZXBvcnRTZXNzaW9uSWRQb3N0KFxuICAgICAge1xuICAgICAgICBSZXBvcnRTZXNzaW9uUmVxdWVzdDogcmVwb3J0UmVxdWVzdCxcbiAgICAgIH1cbiAgICApO1xuICB9O1xuXG4gIHN0YXRpYyBnZXROZXh0UmVzcG9uc2VzID0gYXN5bmMgKFxuICAgIHBheWxvYWQ6IE5leHRNZXNzYWdlUmVxdWVzdFxuICApOiBQcm9taXNlPE1lc3NhZ2VbXT4gPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9XG4gICAgICAgIGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuaW5mZXJlbmNlQXBpLnYxTmV4dFJlc3BvbnNlc1Bvc3Qoe1xuICAgICAgICAgIE5leHRNZXNzYWdlUmVxdWVzdDogbWVzc2FnZVJlcXVlc3RUb0NvbW1lcmNlTWVzc2FnZVJlcXVlc3QocGF5bG9hZCksXG4gICAgICAgIH0pO1xuICAgICAgY29uc3QgbWVzc2FnZXMgPSByZXNwb25zZVxuICAgICAgICAubWFwKChyZXNwKSA9PiB2YWxpZGF0ZVJlc3BvbnNlKHJlc3ApKVxuICAgICAgICAubWFwKChyZXNwKSA9PiBtZXNzYWdlRnJvbVJlc3BvbnNlKHJlc3ApKTtcblxuICAgICAgcmV0dXJuIG1lc3NhZ2VzLmZpbHRlcigobSk6IG0gaXMgTWVzc2FnZSA9PiBtICE9IG51bGwpO1xuICAgIH0gY2F0Y2ggKGVycjogdW5rbm93bikge1xuICAgICAgTG9nZ2VyLmxvZ0luZm8oXCJGYWlsZWQgdG8gZ2V0IG5leHQgcmVzcG9uc2VzXCIsIGVyciwge1xuICAgICAgICBwYXlsb2FkQ29udGV4dDogcGF5bG9hZD8uY29udGV4dCxcbiAgICAgICAgdXNlckV2ZW50czogcGF5bG9hZD8udXNlckV2ZW50cyxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgdGhyb3dTZXNzaW9uUmVzdGFydFJlcXVpcmVkSWYoXCJGYWlsZWQgdG8gZ2V0IG5leHQgcmVzcG9uc2VzXCIsIGVycik7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICB9O1xuXG4gIHN0YXRpYyBnZXROZXh0UmVzcG9uc2VTdHJlYW1pbmcgPSAoXG4gICAgcGF5bG9hZDogTmV4dE1lc3NhZ2VSZXF1ZXN0XG4gICk6IEFzeW5jR2VuZXJhdG9yPFJlc3BvbnNlLCB2b2lkLCB1bmtub3duPiA9PiB7XG4gICAgYXN5bmMgZnVuY3Rpb24qIGdlbmVyYXRlKFxuICAgICAgaW5mZXJlbmNlQXBpOiBJbmZlcmVuY2VBcGksXG4gICAgICBhYm9ydENvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlclxuICAgICkge1xuICAgICAgLy8gbWFrZSBzdXJlIHN0cmVhbWluZyBpcyBlbmFibGVkXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGluZmVyZW5jZUFwaS52MU5leHRSZXNwb25zZXNQb3N0UmF3KFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIE5leHRNZXNzYWdlUmVxdWVzdDogbWVzc2FnZVJlcXVlc3RUb0NvbW1lcmNlTWVzc2FnZVJlcXVlc3QocGF5bG9hZCksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IHNpZ25hbDogYWJvcnRDb250cm9sbGVyLnNpZ25hbCB9XG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gUmVhZCB0aGUgcmVzcG9uc2UgYXMgYSBzdHJlYW0gb2YgZGF0YVxuICAgICAgICBpZiAoIXJlc3BvbnNlLnJhdy5ib2R5KSB7XG4gICAgICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFxuICAgICAgICAgICAgXCJbc3BpZmZ5LWFpXSBObyBib2R5IGluIHRoZSBzdHJlYW1lZCByZXNwb25zZVwiLFxuICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICByZXNwb25zZTogcmVzcG9uc2UucmF3LFxuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVhZGVyID0gcmVzcG9uc2UucmF3LmJvZHkuZ2V0UmVhZGVyKCk7XG4gICAgICAgIGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoXCJ1dGYtOFwiKTtcblxuICAgICAgICBsZXQgcGFydGlhbCA9IFwiXCI7XG4gICAgICAgIC8vIFRPRE8gdGhpcyBmdW5jdGlvbiBpcyByZWNyZWF0ZWQgZXZlcnkgdGltZSBuZXcgZGF0YSBjb21lcyBmcm9tIHRoZSBzdHJlYW0gLSBkZWZpbmUgaXQgb3V0c2lkZSBvZiB0aGUgZ2VuZXJhdG9yXG4gICAgICAgIGNvbnN0IHNhZmVQYXJzZSA9IChsaW5lOiBzdHJpbmcpOiB1bmtub3duID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UobGluZSk7IC8vIFBhcnNlIHRoZSBKU09OIHN0cmluZ1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFwiW3NwaWZmeS1haV0gRXJyb3IgcGFyc2luZyBzdHJlYW1lZCBsaW5lXCIsIGVyciwge1xuICAgICAgICAgICAgICBsaW5lLFxuICAgICAgICAgICAgICBwYXJ0aWFsLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAvLyBzd2FsbG93IHRoZSBlcnJvciBhbmQgc2V0IHRoZSBwYXJ0aWFsIHRvIG91ciBjdXJyZW50IGNodW5rXG4gICAgICAgICAgICBwYXJ0aWFsID0gbGluZTtcbiAgICAgICAgICAgIHJldHVybiBwYXJ0aWFsO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvLyBUT0RPIHRoaXMgZnVuY3Rpb24gaXMgcmVjcmVhdGVkIGV2ZXJ5IHRpbWUgbmV3IGRhdGEgY29tZXMgZnJvbSB0aGUgc3RyZWFtIC0gZGVmaW5lIGl0IG91dHNpZGUgb2YgdGhlIGdlbmVyYXRvclxuICAgICAgICBjb25zdCBwcm9jZXNzQ2h1bmsgPSAoY2h1bms6IHN0cmluZyk6IHVua25vd25bXSA9PiB7XG4gICAgICAgICAgLy8gbWVyZ2UgdGhlIHBhcnRpYWwgd2l0aCB0aGUgaW5jb21pbmcgY2h1bmtcbiAgICAgICAgICBjb25zdCBsaW5lcyA9IGAke3BhcnRpYWx9JHtjaHVua31gLnNwbGl0KFwiXFxuXCIpO1xuXG4gICAgICAgICAgY29uc3QgcGFyc2VkTGluZXMgPSBsaW5lc1xuICAgICAgICAgICAgLm1hcCgobGluZSkgPT4gbGluZS5yZXBsYWNlKC9eZGF0YTogLywgXCJcIikudHJpbSgpKSAvLyBSZW1vdmUgdGhlIFwiZGF0YTogXCIgcHJlZml4XG4gICAgICAgICAgICAuZmlsdGVyKChsaW5lKSA9PiBsaW5lICE9PSBcIlwiICYmIGxpbmUgIT09IFwiW0RPTkVdXCIpIC8vIFJlbW92ZSBlbXB0eSBsaW5lcyBhbmQgXCJbRE9ORV1cIlxuICAgICAgICAgICAgLm1hcChzYWZlUGFyc2UpXG4gICAgICAgICAgICAuZmlsdGVyKCh2KSA9PiB2KTsgLy8gYW5kIGZpbHRlciBvdXQgdGhlIHVuZGVmaW5lZCB2YWx1ZXNcbiAgICAgICAgICByZXR1cm4gcGFyc2VkTGluZXM7XG4gICAgICAgIH07XG5cbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYXdhaXQtaW4tbG9vcFxuICAgICAgICAgIGNvbnN0IHsgZG9uZSwgdmFsdWUgfSA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XG5cbiAgICAgICAgICBpZiAoZG9uZSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gTWFzc2FnZSBhbmQgcGFyc2UgdGhlIGNodW5rIG9mIGRhdGFcbiAgICAgICAgICBjb25zdCBjaHVuayA9IGRlY29kZXIuZGVjb2RlKHZhbHVlKTtcbiAgICAgICAgICBjb25zdCBwYXJzZWRMaW5lcyA9IHByb2Nlc3NDaHVuayhjaHVuayk7XG5cbiAgICAgICAgICBmb3IgKGNvbnN0IHBhcnNlZExpbmUgb2YgcGFyc2VkTGluZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbGlkYXRlZFJlc3BvbnNlID0gdmFsaWRhdGVSZXNwb25zZShwYXJzZWRMaW5lKTtcblxuICAgICAgICAgICAgaWYgKHZhbGlkYXRlZFJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgIHlpZWxkIHZhbGlkYXRlZFJlc3BvbnNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFxuICAgICAgICAgIFwiW3NwaWZmeS1haV0gRmFpbGVkIHRvIGdldCBuZXh0IHN0cmVhbWluZyByZXNwb25zZXNcIixcbiAgICAgICAgICBlcnJvcixcbiAgICAgICAgICB7XG4gICAgICAgICAgICBwYXlsb2FkQ29udGV4dDogcGF5bG9hZD8uY29udGV4dCxcbiAgICAgICAgICAgIHVzZXJFdmVudHM6IHBheWxvYWQ/LnVzZXJFdmVudHMsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICBhd2FpdCB0aHJvd1Nlc3Npb25SZXN0YXJ0UmVxdWlyZWRJZihcbiAgICAgICAgICBcIkZhaWxlZCB0byBnZXQgbmV4dCBzdHJlYW1pbmcgcmVzcG9uc2VzXCIsXG4gICAgICAgICAgZXJyb3JcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBDb21tZXJjZUFwaUNsaWVudC5nZXRJbnN0YW5jZSgpLnJlc3BvbnNlc0Fib3J0Q29udHJvbGxlci5hYm9ydCgpO1xuICAgIENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkucmVzcG9uc2VzQWJvcnRDb250cm9sbGVyID1cbiAgICAgIG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblxuICAgIHJldHVybiBnZW5lcmF0ZShcbiAgICAgIENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuaW5mZXJlbmNlQXBpLFxuICAgICAgQ29tbWVyY2VBcGlDbGllbnQuZ2V0SW5zdGFuY2UoKS5yZXNwb25zZXNBYm9ydENvbnRyb2xsZXJcbiAgICApO1xuICB9O1xuXG4gIHN0YXRpYyBnZXROZXh0U3VnZ2VzdGlvbnMgPSBhc3luYyAoXG4gICAgcGF5bG9hZDogTmV4dE1lc3NhZ2VSZXF1ZXN0XG4gICk6IFByb21pc2U8U3VnZ2VzdGlvbltdPiA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuc3VnZ2VzdGlvbnNBYm9ydENvbnRyb2xsZXIuYWJvcnQoKTtcbiAgICAgIENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuc3VnZ2VzdGlvbnNBYm9ydENvbnRyb2xsZXIgPVxuICAgICAgICBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlID1cbiAgICAgICAgYXdhaXQgQ29tbWVyY2VBcGlDbGllbnQuZ2V0SW5zdGFuY2UoKS5pbmZlcmVuY2VBcGkudjFOZXh0U3VnZ2VzdGlvbnNQb3N0KFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIE5leHRNZXNzYWdlUmVxdWVzdDogbWVzc2FnZVJlcXVlc3RUb0NvbW1lcmNlTWVzc2FnZVJlcXVlc3QocGF5bG9hZCksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBzaWduYWw6XG4gICAgICAgICAgICAgIENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuc3VnZ2VzdGlvbnNBYm9ydENvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgY29uc3Qgc3VnZ2VzdGlvbnMgPSByZXNwb25zZVxuICAgICAgICAubWFwKChyZXNwKSA9PiB2YWxpZGF0ZVN1Z2dlc3Rpb24ocmVzcCkpXG4gICAgICAgIC5maWx0ZXIoKHN1Z2dlc3Rpb24pOiBzdWdnZXN0aW9uIGlzIFN1Z2dlc3Rpb24gPT4gc3VnZ2VzdGlvbiAhPSBudWxsKTtcblxuICAgICAgcmV0dXJuIHN1Z2dlc3Rpb25zO1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBMb2dnZXIubG9nSW5mbyhcIkZhaWxlZCB0byBnZXQgc3VnZ2VzdGlvbnNcIiwgZXJyb3IsIHtcbiAgICAgICAgcGF5bG9hZENvbnRleHQ6IHBheWxvYWQ/LmNvbnRleHQsXG4gICAgICAgIHVzZXJFdmVudHM6IHBheWxvYWQ/LnVzZXJFdmVudHMsXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgdGhyb3dTZXNzaW9uUmVzdGFydFJlcXVpcmVkSWYoXCJGYWlsZWQgdG8gZ2V0IHN1Z2dlc3Rpb25zXCIsIGVycm9yKTtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEZldGNoZXMgdGhlIGV4aXN0aW5nIGNoYXQgZGF0YSBmb3IgYSBnaXZlbiBzZXNzaW9uIGFuZCB0cmFuc2Zvcm1zIHRoZW0gdG8gcmVjb25zdHJ1Y3QgdGhlIGNoYXQgaGlzdG9yeS5cbiAgICpcbiAgICogQHBhcmFtIG9yZ0lkIFRoZSBvcmdhbml6YXRpb24gSWRcbiAgICogQHBhcmFtIGNoYXRJZCBUaGUgZXhpc3RpbmcgY2hhdCBJZFxuICAgKiBAcGFyYW0gdXNlcklkIFRoZSB1c2VyIElkXG4gICAqXG4gICAqIEByZXR1cm5zIEEgbGlzdCBvZiBtZXNzYWdlcyB0aGF0IHdlcmUgZXhjaGFuZ2VkIGluIHRoZSBjaGF0LCB0aHJvd3MgYW4gZXJyb3IgaWYgdGhlIGNoYXQgc2Vzc2lvbiBoYXMgZXhwaXJlZC5cbiAgICovXG4gIHN0YXRpYyBnZXRSZXNwb25zZXMgPSBhc3luYyAoXG4gICAgb3JnSWQ6IHN0cmluZyxcbiAgICBjaGF0SWQ6IHN0cmluZyxcbiAgICB1c2VySWQ6IHN0cmluZ1xuICApOiBQcm9taXNlPHtcbiAgICByZXNwb25zZXM6IFJlc3BvbnNlW11bXTtcbiAgICB1c2VyRXZlbnRzOiBVc2VyRXZlbnRbXTtcbiAgICBzdWdnZXN0aW9uczogU3VnZ2VzdGlvbltdO1xuICAgIG1lc3NhZ2VzOiBNZXNzYWdlW11bXTtcbiAgfT4gPT4ge1xuICAgIGxldCBkYXRhOiBWMUdldFNlc3Npb25NZXNzYWdlczIwMFJlc3BvbnNlID0ge1xuICAgICAgcmVzcG9uc2VzOiBbXSxcbiAgICAgIHN1Z2dlc3Rpb25zOiBbXSxcbiAgICAgIHVzZXJfZXZlbnRzOiBbXSxcbiAgICB9O1xuICAgIGNvbnN0IHJlcXVlc3QgPSB7XG4gICAgICBvcmdfaWQ6IG9yZ0lkLFxuICAgICAgY2hhdF9pZDogY2hhdElkLFxuICAgICAgdXNlcl9pZDogdXNlcklkLFxuICAgIH07XG4gICAgdHJ5IHtcbiAgICAgIGRhdGEgPVxuICAgICAgICBhd2FpdCBDb21tZXJjZUFwaUNsaWVudC5nZXRJbnN0YW5jZSgpLmRlZmF1bHRBcGkudjFHZXRTZXNzaW9uTWVzc2FnZXMoXG4gICAgICAgICAgcmVxdWVzdFxuICAgICAgICApO1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBhd2FpdCB0aHJvd1Nlc3Npb25SZXN0YXJ0UmVxdWlyZWRJZihcbiAgICAgICAgXCJGYWlsZWQgdG8gZ2V0IGNoYXQgcmVzcG9uc2VzXCIsXG4gICAgICAgIGVycm9yXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3BvbnNlczogUmVzcG9uc2VbXVtdID0gZGF0YT8ucmVzcG9uc2VzPy5tYXAoKHR1cm4pID0+XG4gICAgICB0dXJuXG4gICAgICAgIC5tYXAoKHJlc3BvbnNlKSA9PiB2YWxpZGF0ZVJlc3BvbnNlKHJlc3BvbnNlKSlcbiAgICAgICAgLmZpbHRlcigocmVzcG9uc2UpOiByZXNwb25zZSBpcyBSZXNwb25zZSA9PiByZXNwb25zZSAhPSBudWxsKVxuICAgICk7XG5cbiAgICBjb25zdCBzdWdnZXN0aW9uczogU3VnZ2VzdGlvbltdID0gZGF0YT8uc3VnZ2VzdGlvbnNcbiAgICAgIC5tYXAoKHN1Z2dlc3Rpb24pID0+IHZhbGlkYXRlU3VnZ2VzdGlvbihzdWdnZXN0aW9uKSlcbiAgICAgIC5maWx0ZXIoKHN1Z2dlc3Rpb24pOiBzdWdnZXN0aW9uIGlzIFN1Z2dlc3Rpb24gPT4gc3VnZ2VzdGlvbiAhPSBudWxsKTtcblxuICAgIGNvbnN0IHVzZXJFdmVudHM6IFVzZXJFdmVudFtdID0gZGF0YT8udXNlcl9ldmVudHNcbiAgICAgIC5tYXAoKGV2ZW50KSA9PiB2YWxpZGF0ZVVzZXJFdmVudChldmVudCkpXG4gICAgICAuZmlsdGVyKChldmVudCk6IGV2ZW50IGlzIFVzZXJFdmVudCA9PiBldmVudCAhPSBudWxsKTtcblxuICAgIC8vIGlmIGEgZm9ybSBoYXMgYWxyZWFkeSBiZWVuIHN1Ym1pdHRlZCwgZG9uJ3Qgc2hvdyBpdCBpbiB0aGUgY2hhdCBoaXN0b3J5XG4gICAgY29uc3QgZm9ybVN1Ym1pdHRlZFVzZXJFdmVudHNGb3JtSWRzID0gdXNlckV2ZW50c1xuICAgICAgLmZpbHRlcigoZXZlbnQpID0+IGV2ZW50LmNhdGVnb3J5ID09PSBVc2VyRXZlbnRDYXRlZ29yeS5Gb3JtU3VibWl0dGVkKVxuICAgICAgLm1hcCgoZXZlbnQpID0+IGV2ZW50LmF0dHJpYnV0ZXMuZm9ybVJlc3BvbnNlSWQpO1xuXG4gICAgY29uc3QgYXNzaXN0YW50TWVzc2FnZXM6IE1lc3NhZ2VbXVtdID0gcmVzcG9uc2VzXG4gICAgICAubWFwKCh0dXJuKSA9PlxuICAgICAgICB0dXJuXG4gICAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAgIChyZXNwb25zZSkgPT5cbiAgICAgICAgICAgICAgIShcbiAgICAgICAgICAgICAgICByZXNwb25zZS5jYXRlZ29yeSA9PT0gUmVzcG9uc2VDYXRlZ29yeS5Gb3JtICYmXG4gICAgICAgICAgICAgICAgZm9ybVN1Ym1pdHRlZFVzZXJFdmVudHNGb3JtSWRzLmluY2x1ZGVzKHJlc3BvbnNlLmlkKVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgKVxuICAgICAgICAgIC5tYXAoKHJlc3BvbnNlKSA9PiBtZXNzYWdlRnJvbVJlc3BvbnNlKHJlc3BvbnNlKSlcbiAgICAgICAgICAuZmlsdGVyKChtZXNzYWdlKTogbWVzc2FnZSBpcyBNZXNzYWdlID0+IG1lc3NhZ2UgIT0gbnVsbClcbiAgICAgIClcbiAgICAgIC5maWx0ZXIoKHR1cm4pID0+IHR1cm4ubGVuZ3RoID4gMCk7XG5cbiAgICBjb25zdCB1c2VyTWVzc2FnZXM6IE1lc3NhZ2VbXVtdID0gdXNlckV2ZW50c1xuICAgICAgLm1hcCgoZXZlbnQpID0+IHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIFtVc2VyRXZlbnRDYXRlZ29yeS5RdWVyeVR5cGVkLCBVc2VyRXZlbnRDYXRlZ29yeS5TZWFyY2hdLmluY2x1ZGVzKFxuICAgICAgICAgICAgZXZlbnQuY2F0ZWdvcnlcbiAgICAgICAgICApXG4gICAgICAgICkge1xuICAgICAgICAgIHJldHVybiBbbWVzc2FnZUZyb21RdWVyeUV2ZW50KGV2ZW50KV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQuY2F0ZWdvcnkgPT09IFVzZXJFdmVudENhdGVnb3J5LlN1Z2dlc3Rpb25DbGlja2VkKSB7XG4gICAgICAgICAgcmV0dXJuIFttZXNzYWdlRnJvbVN1Z2dlc3Rpb25FdmVudChldmVudCwgc3VnZ2VzdGlvbnMpXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5jYXRlZ29yeSA9PT0gVXNlckV2ZW50Q2F0ZWdvcnkuRm9ybVN1Ym1pdHRlZCkge1xuICAgICAgICAgIGNvbnN0IGZvcm1SZXNwb25zZSA9IHJlc3BvbnNlc1xuICAgICAgICAgICAgLmZsYXQoKVxuICAgICAgICAgICAgLmZpbmQoXG4gICAgICAgICAgICAgIChyZXNwb25zZSkgPT5cbiAgICAgICAgICAgICAgICByZXNwb25zZS5pZCA9PT0gZXZlbnQuYXR0cmlidXRlcy5mb3JtUmVzcG9uc2VJZCAmJlxuICAgICAgICAgICAgICAgIGV2ZW50LmF0dHJpYnV0ZXMuZm9ybVR5cGUgIT09IEZvcm1UeXBlLkVzY2FsYXRpb25cbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICBpZiAoZm9ybVJlc3BvbnNlICYmIGZvcm1SZXNwb25zZS5jYXRlZ29yeSA9PT0gUmVzcG9uc2VDYXRlZ29yeS5Gb3JtKSB7XG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICBtZXNzYWdlRnJvbUZvcm1TdWJtaXR0ZWRFdmVudChldmVudCwgZm9ybVJlc3BvbnNlLmF0dHJpYnV0ZXMpLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW107XG4gICAgICB9KVxuICAgICAgLmZpbHRlcigobWVzc2FnZSk6IG1lc3NhZ2UgaXMgTWVzc2FnZVtdID0+IG1lc3NhZ2UubGVuZ3RoID4gMCk7XG5cbiAgICAvLyBTb3J0IHRoZSBtZXNzYWdlcyBjaHJvbm9sb2dpY2FsbHkgdG8gcmVjb25zdHJ1Y3QgdGhlIGNoYXQgaGlzdG9yeVxuICAgIGNvbnN0IHNvcnRlZE1lc3NhZ2VzID0gWy4uLmFzc2lzdGFudE1lc3NhZ2VzLCAuLi51c2VyTWVzc2FnZXNdLnNvcnQoXG4gICAgICAoYSwgYikgPT5cbiAgICAgICAgbmV3IERhdGUoYVswXS5jcmVhdGVkQXQpLmdldFRpbWUoKSAtIG5ldyBEYXRlKGJbMF0uY3JlYXRlZEF0KS5nZXRUaW1lKClcbiAgICApO1xuXG4gICAgcmV0dXJuIHsgcmVzcG9uc2VzLCB1c2VyRXZlbnRzLCBzdWdnZXN0aW9ucywgbWVzc2FnZXM6IHNvcnRlZE1lc3NhZ2VzIH07XG4gIH07XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSBwYXlsb2FkXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBzdGF0aWMgaXNTdXBwb3J0ZWRFdmVudCA9IGFzeW5jIChcbiAgICBwYXlsb2FkOiBTdXBwb3J0ZWRFdmVudFJlcXVlc3RcbiAgKTogUHJvbWlzZTxTdXBwb3J0ZWRFdmVudD4gPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByYXdSZXNwb25zZSA9XG4gICAgICAgIGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuaW5mZXJlbmNlQXBpLnYxU3VwcG9ydGVkRXZlbnRQb3N0UmF3KFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIFN1cHBvcnRlZEV2ZW50UmVxdWVzdDpcbiAgICAgICAgICAgICAgY29yZVN1cHBvcnRlZEV2ZW50UmVxdWVzdFRvQXBpUmVxdWVzdChwYXlsb2FkKSxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgIC8vIEdldCB0aGUgYWN0dWFsIEhUVFAgcmVzcG9uc2UgSlNPTlxuICAgICAgY29uc3QgaHR0cFJlc3BvbnNlVGV4dCA9IGF3YWl0IHJhd1Jlc3BvbnNlLnJhdy50ZXh0KCk7XG4gICAgICBjb25zdCBodHRwUmVzcG9uc2VKc29uID0gSlNPTi5wYXJzZShodHRwUmVzcG9uc2VUZXh0KTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uaHR0cFJlc3BvbnNlSnNvbixcbiAgICAgICAgbnVtYmVyT2ZSZXZpZXdzOiBodHRwUmVzcG9uc2VKc29uLm51bV9vZl9yZXZpZXdzLFxuICAgICAgICBtZXJjaGFudF90YWdzOiBodHRwUmVzcG9uc2VKc29uLm1lcmNoYW50X3RhZ3MgfHwgW10sXG4gICAgICB9O1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFwiRmFpbGVkIHRvIGdldCByZXNwb25zZSBmb3IgdjFTdXBwb3J0ZWRFdmVudFBvc3RcIiwge1xuICAgICAgICBlcnIsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN1cHBvcnRlZDogZmFsc2UsXG4gICAgICAgIHJlYWR5OiBmYWxzZSxcbiAgICAgICAgY2F0ZWdvcnk6IHVuZGVmaW5lZCxcbiAgICAgICAgY29sbGVjdGlvbnM6IFtdLFxuICAgICAgICBudW1iZXJPZlJldmlld3M6IHVuZGVmaW5lZCxcbiAgICAgICAgdG9wX2NhdGVnb3J5OiB1bmRlZmluZWQsXG4gICAgICAgIG1lcmNoYW50X3RhZ3M6IFtdLFxuICAgICAgfTtcbiAgICB9XG4gIH07XG5cbiAgc3RhdGljIGlkZW50aWZ5VXNlciA9IGFzeW5jIChcbiAgICBzcGlmZnlVc2VySWQ6IHN0cmluZyxcbiAgICBtZXJjaGFudFVzZXJJZDogc3RyaW5nLFxuICAgIHVhRGV0YWlsczogQ2xpZW50RGV0YWlsc1xuICApOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgQ29tbWVyY2VBcGlDbGllbnQuZ2V0SW5zdGFuY2UoKS5kZWZhdWx0QXBpLnYxQW5hbHl0aWNzSWRlbnRpZnlQb3N0KHtcbiAgICAgICAgQW5hbHl0aWNzSWRlbnRpZnlSZXF1ZXN0OiB7XG4gICAgICAgICAgdXNlcl9pZDogc3BpZmZ5VXNlcklkLFxuICAgICAgICAgIG9zX25hbWU6IHVhRGV0YWlscy5vcyxcbiAgICAgICAgICBvc192ZXJzaW9uOiB1YURldGFpbHMub3NWZXJzaW9uLFxuICAgICAgICAgIHBsYXRmb3JtOiB1YURldGFpbHMub3MsXG4gICAgICAgICAgZGV2aWNlX2lkOiB1YURldGFpbHMuZGV2aWNlTW9kZWwsXG4gICAgICAgICAgZGV2aWNlX2JyYW5kOiB1YURldGFpbHMuZGV2aWNlQnJhbmQsXG4gICAgICAgICAgZGV2aWNlX21hbnVmYWN0dXJlcjogdWFEZXRhaWxzLmRldmljZU1hbnVmYWN0dXJlcixcbiAgICAgICAgICBkZXZpY2VfbW9kZWw6IHVhRGV0YWlscy5kZXZpY2VNb2RlbCxcbiAgICAgICAgICB1c2VyX3Byb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIGNkcF91c2VyX2lkOiBtZXJjaGFudFVzZXJJZCxcbiAgICAgICAgICAgIGJyb3dzZXI6IHVhRGV0YWlscy5icm93c2VyLFxuICAgICAgICAgICAgYnJvd3Nlcl92ZXJzaW9uOiB1YURldGFpbHMuYnJvd3NlclZlcnNpb24sXG4gICAgICAgICAgICB1c2VyX2FnZW50OiB1YURldGFpbHMudXNlckFnZW50LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIExvZ2dlci5sb2dFcnJvcihcIkZhaWxlZCB0byBpZGVudGlmeSB1c2VyXCIsIGVycik7XG4gICAgfVxuICB9O1xuXG4gIHByaXZhdGUgc3RhdGljIG1hcENvbnRleHRTb3VyY2VUb1YxT3JnQ29uZmlnR2V0U291cmNlID0gKFxuICAgIHNvdXJjZTogQ29udGV4dFNvdXJjZUVudW0gfCB1bmRlZmluZWRcbiAgKTogVjFPcmdDb25maWdHZXRTb3VyY2VFbnVtIHwgdW5kZWZpbmVkID0+IHtcbiAgICBpZiAoc291cmNlID09PSB1bmRlZmluZWQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgc3dpdGNoIChzb3VyY2UpIHtcbiAgICAgIGNhc2UgQ29udGV4dFNvdXJjZUVudW0uRm9yazpcbiAgICAgICAgcmV0dXJuIFYxT3JnQ29uZmlnR2V0U291cmNlRW51bS5Gb3JrO1xuICAgICAgY2FzZSBDb250ZXh0U291cmNlRW51bS5QbGF5Z3JvdW5kOlxuICAgICAgICByZXR1cm4gVjFPcmdDb25maWdHZXRTb3VyY2VFbnVtLlBsYXlncm91bmQ7XG4gICAgICBjYXNlIENvbnRleHRTb3VyY2VFbnVtLkFwcDpcbiAgICAgICAgcmV0dXJuIFYxT3JnQ29uZmlnR2V0U291cmNlRW51bS5BcHA7XG4gICAgICBjYXNlIENvbnRleHRTb3VyY2VFbnVtLlRlc3Q6XG4gICAgICAgIHJldHVybiBWMU9yZ0NvbmZpZ0dldFNvdXJjZUVudW0uVGVzdDtcbiAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgLy8gVGhpcyBlbnN1cmVzIHRoYXQgaWYgbmV3IHZhbHVlcyBhcmUgYWRkZWQgdG8gQ29udGV4dFNvdXJjZUVudW0sIHdlIGNhdGNoIGl0XG4gICAgICAgIGNvbnN0IGV4aGF1c3RpdmVDaGVjazogbmV2ZXIgPSBzb3VyY2U7XG4gICAgICAgIHJldHVybiBleGhhdXN0aXZlQ2hlY2s7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIHN0YXRpYyBnZXRPcmdDb25maWcgPSBhc3luYyAoXG4gICAgdXNlcl9pZDogc3RyaW5nXG4gICk6IFByb21pc2U8T3JnQ29uZmlnIHwgdW5kZWZpbmVkPiA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGF0b21TdG9yZSA9IGdldEF0b21TdG9yZSgpO1xuICAgICAgY29uc3QgcmVhY3RBcHBOYW1lID0gYXRvbVN0b3JlLmdldChyZWFjdEFwcE5hbWVBdG9tKTtcbiAgICAgIGNvbnN0IGNvbnRleHRTb3VyY2UgPSBhdG9tU3RvcmUuZ2V0KGNvbnRleHRTb3VyY2VBdG9tKTtcbiAgICAgIGNvbnN0IGZlYXR1cmVGbGFnU2VydmljZSA9IGF0b21TdG9yZS5nZXQoZmVhdHVyZUZsYWdTZXJ2aWNlQXRvbSk7IC8vIEdldCBmZWF0dXJlRmxhZ1NlcnZpY2VcbiAgICAgIGNvbnN0IHJlcXVlc3Q6IFYxT3JnQ29uZmlnR2V0UmVxdWVzdCA9IHtcbiAgICAgICAgbmFtZXNwYWNlOiByZWFjdEFwcE5hbWUsXG4gICAgICAgIHVzZXJfaWQsXG4gICAgICAgIHNvdXJjZTogdGhpcy5tYXBDb250ZXh0U291cmNlVG9WMU9yZ0NvbmZpZ0dldFNvdXJjZShjb250ZXh0U291cmNlKSxcbiAgICAgICAgaW5jbHVkZV9leHBlcmltZW50czogT2JqZWN0LnZhbHVlcyhQcm9kdWN0RXhwZXJpbWVudCksXG4gICAgICAgIGluY2x1ZGVfZmVhdHVyZV9nYXRlczogT2JqZWN0LmVudHJpZXMoXG4gICAgICAgICAgZmVhdHVyZUZsYWdTZXJ2aWNlPy5mZWF0dXJlRmxhZ1NlcnZpY2U/LmdldEZlYXR1cmVGbGFncygpIHx8IHt9XG4gICAgICAgIClcbiAgICAgICAgICAuZmlsdGVyKChbLCBpc0VuYWJsZWRdKSA9PiBpc0VuYWJsZWQpXG4gICAgICAgICAgLm1hcCgoW2ZlYXR1cmVHYXRlTmFtZV0pID0+IGZlYXR1cmVHYXRlTmFtZSksIC8vIFVzZSBmZWF0dXJlRmxhZ1NlcnZpY2VcbiAgICAgIH07XG4gICAgICBjb25zdCByZXNwb25zZSA9XG4gICAgICAgIGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuZGVmYXVsdEFwaS52MU9yZ0NvbmZpZ0dldChcbiAgICAgICAgICByZXF1ZXN0XG4gICAgICAgICk7XG5cbiAgICAgIHJldHVybiB2YWxpZGF0ZU9yZ0NvbmZpZ1Jlc3VsdHMocmVzcG9uc2UpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKGBGYWlsZWQgdG8gZ2V0IG9yZyBjb25maWdgLCBlcnIsIHsgZXJyIH0pO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH07XG5cbiAgc3RhdGljIGFkZE5vdGVUb0xhdGVzdENvbnZlcnNhdGlvbiA9IGFzeW5jIChcbiAgICBzcGlmZnlVc2VySWQ6IHN0cmluZyxcbiAgICBlbWFpbDogc3RyaW5nLFxuICAgIGN1c3RvbWVyU2VydmljZVByb3ZpZGVyOiBDdXN0b21lclNlcnZpY2VQcm92aWRlclxuICApID0+IHtcbiAgICBMb2dnZXIubG9nSW5mbyhcbiAgICAgIGBhZGROb3RlVG9MYXRlc3RDb252ZXJzYXRpb24gLSB1c2VyX2lkPSR7c3BpZmZ5VXNlcklkfSBlbWFpbD0ke2VtYWlsfSBjdXN0b21lcl9zZXJ2aWNlX3Byb3ZpZGVyPSR7Y3VzdG9tZXJTZXJ2aWNlUHJvdmlkZXJ9YFxuICAgICk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmdldEluc3RhbmNlKCkuY3VzdG9tZXJTZXJ2aWNlQXBpLnYxQ3VzdHNlcnZpY2VBZGROb3RlVG9MYXRlc3RDb252ZXJzYXRpb25Qb3N0KFxuICAgICAgICB7XG4gICAgICAgICAgQWRkTm90ZVRvTGF0ZXN0Q29udmVyc2F0aW9uUmVxdWVzdDoge1xuICAgICAgICAgICAgc3BpZmZ5X3VzZXJfaWQ6IHNwaWZmeVVzZXJJZCxcbiAgICAgICAgICAgIGVtYWlsLFxuICAgICAgICAgICAgY3VzdG9tZXJfc2VydmljZV9wcm92aWRlcjogY3VzdG9tZXJTZXJ2aWNlUHJvdmlkZXIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIExvZ2dlci5sb2dFcnJvcihcIkZhaWxlZCB0byBhZGQgbm90ZSB0byBsYXRlc3QgY29udmVyc2F0aW9uXCIsIHsgZXJyIH0pO1xuICAgIH1cbiAgfTtcblxuICBzdGF0aWMgZ2V0Q3VzdG9tZXJTZXJ2aWNlQXBpID0gKCkgPT5cbiAgICBDb21tZXJjZUFwaUNsaWVudC5nZXRJbnN0YW5jZSgpLmN1c3RvbWVyU2VydmljZUFwaTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgQ29tbWVyY2VBcGlDbGllbnQ7XG4iLCJpbXBvcnQgeyB1c2VTdGF0ZSwgdXNlQ2FsbGJhY2sgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7XG4gIFNwaWZmeU1ldHJpY3NFdmVudE5hbWUsXG4gIHVzZUFtcGxpdHVkZSxcbn0gZnJvbSBcInNyYy9jb250ZXh0cy9hbXBsaXR1ZGVDb250ZXh0XCI7XG5cbmV4cG9ydCBjb25zdCB1c2VBbXBsaXR1ZGVUcmFja2luZyA9ICgpID0+IHtcbiAgY29uc3QgeyB0cmFja0V2ZW50LCBpc1JlYWR5IH0gPSB1c2VBbXBsaXR1ZGUoKTtcbiAgY29uc3QgW2xvYWRpbmcsIHNldExvYWRpbmddID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbZXJyb3IsIHNldEVycm9yXSA9IHVzZVN0YXRlPEVycm9yIHwgbnVsbD4obnVsbCk7XG5cbiAgY29uc3QgdHJhY2sgPSB1c2VDYWxsYmFjayhcbiAgICBhc3luYyAoXG4gICAgICBldmVudE5hbWU6IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUsXG4gICAgICBldmVudFByb3BzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgICApID0+IHtcbiAgICAgIGlmICghaXNSZWFkeSkgcmV0dXJuO1xuXG4gICAgICBzZXRMb2FkaW5nKHRydWUpO1xuICAgICAgc2V0RXJyb3IobnVsbCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRyYWNrRXZlbnQoeyBldmVudE5hbWUsIGV2ZW50UHJvcHMgfSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgc2V0RXJyb3IoZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIgOiBuZXcgRXJyb3IoXCJUcmFja2luZyBmYWlsZWRcIikpO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBzZXRMb2FkaW5nKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFt0cmFja0V2ZW50LCBpc1JlYWR5XVxuICApO1xuXG4gIHJldHVybiB7IHRyYWNrLCBsb2FkaW5nLCBlcnJvciwgaXNSZWFkeSB9O1xufTtcbiIsImltcG9ydCB7IHVzZUVmZmVjdCB9IGZyb20gXCJyZWFjdFwiO1xuXG5leHBvcnQgY29uc3QgdXNlQmxvY2tCYWNrQnV0dG9uID0gKGVuYWJsZWQ6IGJvb2xlYW4sIGNhbGxiYWNrOiAoKSA9PiB2b2lkKSA9PiB7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoZW5hYmxlZCAmJiB3aW5kb3cpIHtcblxuICAgICAgaWYgKHdpbmRvdy5oaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uKSB7XG4gICAgICAgIHdpbmRvdy5oaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uID0gXCJtYW51YWxcIlxuICAgICAgfVxuXG4gICAgICB3aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGUobnVsbCwgZG9jdW1lbnQudGl0bGUsIHdpbmRvdy5sb2NhdGlvbi5ocmVmKTtcbiAgICAgIHdpbmRvdy5vbnBvcHN0YXRlID0gKGUpID0+IHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB3aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGUobnVsbCwgZG9jdW1lbnQudGl0bGUsIHdpbmRvdy5sb2NhdGlvbi5ocmVmKTtcbiAgICAgICAgY2FsbGJhY2s/LigpXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBpZiAoZW5hYmxlZCAmJiB3aW5kb3cpIHtcbiAgICAgICAgd2luZG93Lmhpc3RvcnkuYmFjaygpXG4gICAgICAgIHdpbmRvdy5vbnBvcHN0YXRlID0gbnVsbFxuICAgICAgICB3aW5kb3cuaGlzdG9yeS5zY3JvbGxSZXN0b3JhdGlvbiA9IFwiYXV0b1wiO1xuICAgICAgfVxuICAgIH1cbiAgfSwgW2VuYWJsZWRdKVxuXG59IiwiaW1wb3J0IHsgdXNlQ2RuIH0gZnJvbSBcIi4uL2NvbnRleHRzL2NkbkNvbnRleHRcIjtcblxuZXhwb3J0IGNvbnN0IHVzZUNkblVybCA9ICgpID0+IHtcbiAgY29uc3QgeyBjZG5VcmwgfSA9IHVzZUNkbigpO1xuICByZXR1cm4gY2RuVXJsO1xufTtcblxuZXhwb3J0IGNvbnN0IHVzZUNkbkJhc2VQYXRoID0gKCkgPT4ge1xuICBjb25zdCB7IGdldENkbkJhc2VQYXRoIH0gPSB1c2VDZG4oKTtcbiAgcmV0dXJuIGdldENkbkJhc2VQYXRoKCk7XG59O1xuXG5leHBvcnQgY29uc3QgdXNlQXNzZXRVcmwgPSAoYXNzZXROYW1lOiBzdHJpbmcsIG9yZ1Nob3J0TmFtZTogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IHsgZ2V0QXNzZXRVUkwgfSA9IHVzZUNkbigpO1xuICByZXR1cm4gZ2V0QXNzZXRVUkwoYXNzZXROYW1lLCBvcmdTaG9ydE5hbWUpO1xufTtcbiIsImltcG9ydCB7IHVzZUF0b21WYWx1ZSwgdXNlU2V0QXRvbSB9IGZyb20gXCJqb3RhaVwiO1xuaW1wb3J0IHsgQ2hhdEVsZW1lbnREaXNwbGF5TG9jYXRpb24gfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9jaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblwiO1xuaW1wb3J0IHsgY2hhdEF0b20sIGNoYXRPblRvZ2dsZUF0b20gfSBmcm9tIFwic3JjL2F0b21zL2NoYXRcIjtcbmltcG9ydCB7XG4gIFNwaWZmeU1ldHJpY3NFdmVudE5hbWUsXG4gIHVzZUFtcGxpdHVkZSxcbn0gZnJvbSBcInNyYy9jb250ZXh0cy9hbXBsaXR1ZGVDb250ZXh0XCI7XG5cbmV4cG9ydCBjb25zdCB1c2VDaGF0VG9nZ2xlID0gKCkgPT4ge1xuICBjb25zdCBvblRvZ2dsZSA9IHVzZVNldEF0b20oY2hhdE9uVG9nZ2xlQXRvbSk7XG4gIGNvbnN0IHsgaXNPcGVuIH0gPSB1c2VBdG9tVmFsdWUoY2hhdEF0b20pO1xuICBjb25zdCB7IHRyYWNrRXZlbnQgfSA9IHVzZUFtcGxpdHVkZSgpO1xuXG4gIGNvbnN0IHRvZ2dsZSA9IChcbiAgICB0cmlnZ2VyTG9jYXRpb246IENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uLFxuICAgIHRyaWdnZXJJZD86IHN0cmluZ1xuICApID0+IHtcbiAgICBpZiAoIWlzT3Blbikge1xuICAgICAgdHJhY2tFdmVudCh7XG4gICAgICAgIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5DaGF0Q29tcG9uZW50RXhwYW5kZWQsXG4gICAgICAgIGV2ZW50UHJvcHM6IHtcbiAgICAgICAgICBtZXNzYWdlX21ldGFkYXRhOiB7XG4gICAgICAgICAgICB0cmlnZ2VyX2xvY2F0aW9uOiB0cmlnZ2VyTG9jYXRpb24sXG4gICAgICAgICAgICB0cmlnZ2VyX2lkOiB0cmlnZ2VySWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0cmFja0V2ZW50KHtcbiAgICAgICAgZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLkNoYXRDb21wb25lbnRDb2xsYXBzZWQsXG4gICAgICAgIGV2ZW50UHJvcHM6IHtcbiAgICAgICAgICBtZXNzYWdlX21ldGFkYXRhOiB7XG4gICAgICAgICAgICB0cmlnZ2VyX2xvY2F0aW9uOiB0cmlnZ2VyTG9jYXRpb24sXG4gICAgICAgICAgICB0cmlnZ2VyX2lkOiB0cmlnZ2VySWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIG9uVG9nZ2xlKCk7XG4gIH07XG5cbiAgY29uc3Qgb3BlbkNoYXQgPSAoXG4gICAgdHJpZ2dlckxvY2F0aW9uOiBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvbixcbiAgICB0cmlnZ2VySWQ/OiBzdHJpbmdcbiAgKSA9PiB7XG4gICAgaWYgKCFpc09wZW4pIHtcbiAgICAgIHRvZ2dsZSh0cmlnZ2VyTG9jYXRpb24sIHRyaWdnZXJJZCk7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGNsb3NlQ2hhdCA9IChcbiAgICB0cmlnZ2VyTG9jYXRpb246IENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uLFxuICAgIHRyaWdnZXJJZD86IHN0cmluZ1xuICApID0+IHtcbiAgICBpZiAoaXNPcGVuKSB7XG4gICAgICB0b2dnbGUodHJpZ2dlckxvY2F0aW9uLCB0cmlnZ2VySWQpO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4ge1xuICAgIHRvZ2dsZSxcbiAgICBpc09wZW4sXG4gICAgb3BlbkNoYXQsXG4gICAgY2xvc2VDaGF0LFxuICB9O1xufTtcbiIsImltcG9ydCB7IHVzZVNldEF0b20gfSBmcm9tIFwiam90YWlcIjtcbmltcG9ydCB7IGNoYXRPblRvZ2dsZUF0b20gfSBmcm9tIFwic3JjL2F0b21zL2NoYXQvY2hhdFN0YXRlXCI7XG5pbXBvcnQgeyBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvbiB9IGZyb20gXCJzcmMvYXBwbGljYXRpb24vbW9kZWxzL2NoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uXCI7XG5pbXBvcnQgeyB1c2VBbXBsaXR1ZGVUcmFja2luZyB9IGZyb20gXCIuL3VzZUFtcGxpdHVkZU9wZXJhdGlvbnNcIjtcblxuZXhwb3J0IGNvbnN0IHVzZUNoYXRUb2dnbGVBbmFseXRpY3MgPSAoKSA9PiB7XG4gIGNvbnN0IHNldENoYXRPblRvZ2dsZSA9IHVzZVNldEF0b20oY2hhdE9uVG9nZ2xlQXRvbSk7XG4gIGNvbnN0IHsgdHJhY2sgfSA9IHVzZUFtcGxpdHVkZVRyYWNraW5nKCk7XG5cbiAgY29uc3QgdG9nZ2xlQ2hhdCA9ICh0cmlnZ2VyTG9jYXRpb24/OiBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvbikgPT4ge1xuICAgIHNldENoYXRPblRvZ2dsZSh0cmlnZ2VyTG9jYXRpb24sIHRyYWNrKTtcbiAgfTtcblxuICByZXR1cm4geyB0b2dnbGVDaGF0IH07XG59O1xuIiwiaW1wb3J0IExvZ2dlciBmcm9tICdzcmMvYXBwbGljYXRpb24vbG9nZ2luZy9sb2dnZXInO1xuaW1wb3J0IHsgdXNlQ2FsbGJhY2sgfSBmcm9tICdyZWFjdCc7XG5cbi8qKlxuICogSG9vayB0byBjYWxsIHRoZSBgY2xpY2tgIG1ldGhvZCBvZiB0aGUgbWVyY2hhbnQncyBjdXN0b21lciBzdXBwb3J0IGNoYXQgd2lkZ2V0LlxuICpcbiAqIEBwYXJhbSBvblN3aXRjaFRvQWdlbnQgYSBmdW5jdGlvbiB0byBvdmVycmlkZSB0aGUgZnVuY3Rpb24gcmV0dXJuZWQgYnkgdGhlIGhvb2suIFRoaXMgaXMgbWFpbmx5IHRvXG4gKiBwcmVzZXJ2ZSBiYWNrd2FyZCBjb21wYXRpYmlsaXR5IGZvciBtZXJjaGFudHMgbm90IHVzaW5nIEt1c3RvbWVyIGFuZCB3aWxsIGJlIHJlbW92ZWQgd2hlbiBhbGxcbiAqIENTIGludGVncmF0aW9ucyBhcmUgaGFuZGxlZC5cbiAqXG4gKiBAcmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgc2VhcmNoZXMgZm9yIHRoZSBjdXN0b21lciBzdXBwb3J0IGNoYXQgd2lkZ2V0IGFuZCBjYWxscyB0aGUgYGNsaWNrYCBtZXRob2QuXG4gKi9cbmV4cG9ydCBjb25zdCB1c2VDdXN0b21lclN1cHBvcnRIYW5kb2ZmID0gKG9uU3dpdGNoVG9BZ2VudD86ICgpID0+IHZvaWQpID0+IHtcbiAgLy8gVE9ETyBoYW5kbGUgR29yZ2lhc1xuXG4gIGNvbnN0IG9uS3VzdG9tZXJTd2l0Y2ggPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgY29uc3Qga3VzdG9tZXJFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2t1c3RvbWVyLXVpLXNkay1pZnJhbWUnKTtcblxuICAgIGlmIChrdXN0b21lckVsZW1lbnQgPT0gbnVsbCB8fCAhKGt1c3RvbWVyRWxlbWVudCBpbnN0YW5jZW9mIEhUTUxJRnJhbWVFbGVtZW50KSkge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKCdbc3BpZmZ5LWFpXSBLdXN0b21lciBpRnJhbWUgZWxlbWVudCBub3QgZm91bmQnLCB1bmRlZmluZWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGt1c3RvbWVyQnV0dG9uID0ga3VzdG9tZXJFbGVtZW50LmNvbnRlbnRXaW5kb3c/LmRvY3VtZW50Py5nZXRFbGVtZW50QnlJZCgncm9vdENoYXRJY29uJyk7XG5cbiAgICBpZiAoa3VzdG9tZXJCdXR0b24gPT0gbnVsbCkge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKCdbc3BpZmZ5LWFpXSBLdXN0b21lciBidXR0b24gbm90IGZvdW5kJywgdW5kZWZpbmVkKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBrdXN0b21lckJ1dHRvbi5jbGljaygpO1xuICB9LCBbXSk7XG5cbiAgaWYgKG9uU3dpdGNoVG9BZ2VudCAhPSBudWxsKSB7XG4gICAgcmV0dXJuIHsgb25Td2l0Y2g6IG9uU3dpdGNoVG9BZ2VudCB9O1xuICB9XG5cbiAgcmV0dXJuIHsgb25Td2l0Y2g6IG9uS3VzdG9tZXJTd2l0Y2ggfTtcbn07XG4iLCJpbXBvcnQgeyB1c2VTdGF0ZSwgdXNlRWZmZWN0IH0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gdXNlRGVib3VuY2U8VD4odmFsdWU6IFQsIGRlbGF5OiBudW1iZXIpOiBUIHtcbiAgY29uc3QgW2RlYm91bmNlZFZhbHVlLCBzZXREZWJvdW5jZWRWYWx1ZV0gPSB1c2VTdGF0ZTxUPih2YWx1ZSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBoYW5kbGVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBzZXREZWJvdW5jZWRWYWx1ZSh2YWx1ZSk7XG4gICAgfSwgZGVsYXkpO1xuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGNsZWFyVGltZW91dChoYW5kbGVyKTtcbiAgICB9O1xuICB9LCBbdmFsdWUsIGRlbGF5XSk7XG5cbiAgcmV0dXJuIGRlYm91bmNlZFZhbHVlO1xufVxuIiwiaW1wb3J0IHsgUmVhY3RFbGVtZW50LCB1c2VFZmZlY3QsIHVzZVJlZiwgdXNlU3RhdGUgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBET01PYnNlcnZlciB9IGZyb20gJ3NyYy9hcHBsaWNhdGlvbi91dGlscy9kb21PYnNlcnZlcic7XG5pbXBvcnQgeyBFbGVtZW50T2JzZXJ2ZXIgfSBmcm9tICdzcmMvYXBwbGljYXRpb24vdXRpbHMvZWxlbWVudE9ic2VydmVyJztcbmltcG9ydCB7IE1vdXNlRXZlbnRUeXBlcyB9IGZyb20gJ3NyYy9hcHBsaWNhdGlvbi91dGlscy9tb3VzZUV2ZW50VHlwZXMnO1xuaW1wb3J0IHsgTm9kZVNlbGVjdG9yIH0gZnJvbSAnc3JjL2FwcGxpY2F0aW9uL3V0aWxzL25vZGVTZWxlY3Rvcic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWxlbWVudE9ic2VydmVyVXRpbGl0eSB7XG4gIG9uQ2hhbmdlOiAoZm46IChlbDogSFRNTEVsZW1lbnQgfCBudWxsKSA9PiB2b2lkKSA9PiB2b2lkO1xuICBvbkFkZDogKGZuOiAoZWw6IEhUTUxFbGVtZW50IHwgbnVsbCkgPT4gdm9pZCkgPT4gdm9pZDtcbiAgb25SZW1vdmU6IChmbjogKGVsOiBIVE1MRWxlbWVudCB8IG51bGwpID0+IHZvaWQpID0+IHZvaWQ7XG4gIG9uQ2xhc3NDaGFuZ2U6IChmbjogKGNsYXNzZXM/OiBET01Ub2tlbkxpc3QpID0+IHZvaWQpID0+IHZvaWQ7XG4gIG9uQ2xhc3NBZGRlZDogKGNsYXNzTmFtZTogc3RyaW5nLCBmbjogKCkgPT4gdm9pZCkgPT4gdm9pZDtcbiAgb25DbGFzc1JlbW92ZWQ6IChjbGFzc05hbWU6IHN0cmluZywgZm46ICgpID0+IHZvaWQpID0+IHZvaWQ7XG4gIG9uQWRkQ2hpbGQ6IChmbjogKG5vZGVzPzogRE9NVG9rZW5MaXN0KSA9PiB2b2lkKSA9PiB2b2lkO1xuICBvblJlbW92ZUNoaWxkOiAoZm46IChub2Rlcz86IERPTVRva2VuTGlzdCkgPT4gdm9pZCkgPT4gdm9pZDtcbiAgb25FdmVudDogPEsgZXh0ZW5kcyBrZXlvZiBIVE1MRWxlbWVudEV2ZW50TWFwPihcbiAgICBldmVudDogSyxcbiAgICBmbjogRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdCxcbiAgKSA9PiB2b2lkO1xuICBibG9ja1JlbmRlcmluZzogKCkgPT4gdm9pZDtcbiAgdW5ibG9ja1JlbmRlcmluZzogKCkgPT4gdm9pZDtcbiAgZXhpc3RzOiAoKSA9PiBib29sZWFuO1xuICBpc1JlbmRlcmVkOiAoKSA9PiBib29sZWFuO1xuICByZW5kZXI6IChmbjogKCkgPT4gUmVhY3RFbGVtZW50KSA9PiBSZWFjdEVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gIGZpcmU6IChldmVudDogTW91c2VFdmVudFR5cGVzKSA9PiB2b2lkO1xuICBzaG93OiAoKSA9PiB2b2lkO1xuICBoaWRlOiAoKSA9PiB2b2lkO1xuICBhcHBseVN0eWxlOiAoc3R5bGVzOiBSZWFjdC5DU1NQcm9wZXJ0aWVzKSA9PiB2b2lkO1xuICB0YXJnZXROb2RlOiBIVE1MRWxlbWVudCB8IG51bGw7XG59XG5cbi8qXG4gKiBUaGlzIGhvb2sgZW5hYmxlcyB0aGUgY29ubmVjdGlvbiBiZXR3ZWVuIGEgYE11dGF0aW9uT2JzZXJ2ZXJgIGFuZCBhIFJlYWN0LmpzIGNvbXBvbmVudC5cbiAqIEl0IGFic3RyYWN0cyBhbGwgdGhlIG5lY2Vzc2FyeSB2YWxpZGF0aW9ucyBhbmQgaW1wbGVtZW50YXRpb25zIHRvIG1vZGlmeSBIVE1MIGVsZW1lbnRzLFxuICogbW9uaXRvciB0aGVpciBjaGFuZ2VzLCBhbmQgaW50ZXJhY3Qgd2l0aCB0aGVtLiBUaGUgb25seSByZXF1aXJlZCBpbnB1dCBpcyB0aGUgZWxlbWVudCdzIHNlbGVjdG9yLlxuICpcbiAqIEhvdyB0byB1c2UgaXQ6XG4gKlxuICogTGV0J3MgYXNzdW1lIHdlIHdhbnQgdG8gaW50ZXJhY3Qgd2l0aCB0aGUgZm9sbG93aW5nIGVsZW1lbnQ6XG4gKiBgPGRpdiBpZD1cImF3ZXNvbWUtY29udGVudFwiPjxjb250ZW50IC8+PC9kaXY+YFxuICpcbiAqIFRvIGhvb2sgaW50byB0aGF0IGVsZW1lbnQsIHNpbXBseSBkbyB0aGUgZm9sbG93aW5nOlxuICogYGNvbnN0IGVsZW1lbnQgPSB1c2VFbGVtZW50T2JzZXJ2ZXIoU2VsZWN0b3JGYWN0b3J5LmlkKFwiYXdlc29tZS1jb250ZW50XCIpKWBcbiAqXG4gKiBXaXRoIHRoZSBgRWxlbWVudE9ic2VydmVyYCBpbnN0YW5jZSBpbiBoYW5kLCB3ZSBjYW4gaW50ZXJhY3Qgd2l0aCB0aGUgSFRNTCBlbGVtZW50IHdpdGhvdXQgaGF2aW5nXG4gKiB0byBtYW5hZ2UgaXRzIHByZXNlbmNlIGluIHRoZSBET00uIFRoZSBgb25BZGRgIGFuZCBgb25SZW1vdmVgIGZ1bmN0aW9ucyBjYW4gYmUgdXNlZCB0byBkZXRlcm1pbmVcbiAqIHdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgcHJlc2VudCBpbiB0aGUgRE9NIG9yIG5vdCwgYW5kIHRvIGVuc3VyZSBpbnRlcmFjdGlvbiBvY2N1cnMgb25seSB3aGVuIG5lY2Vzc2FyeS5cbiAqXG4gKiBAcGFyYW0gc2VsZWN0b3JcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBjb25zdCB1c2VFbGVtZW50T2JzZXJ2ZXIgPSAoc2VsZWN0b3I6IE5vZGVTZWxlY3Rvcik6IEVsZW1lbnRPYnNlcnZlclV0aWxpdHkgPT4ge1xuICBjb25zdCBJTklUSUFMX1JFTkRFUl9TVEFURSA9IHRydWU7XG4gIGNvbnN0IGVvUmVmID0gdXNlUmVmPEVsZW1lbnRPYnNlcnZlcj4oRE9NT2JzZXJ2ZXIuYWRkKHNlbGVjdG9yKSk7XG4gIGNvbnN0IFtyZW5kZXJCbG9ja2VkLCBzZXRSZW5kZXJCbG9ja2VkXSA9IHVzZVN0YXRlKElOSVRJQUxfUkVOREVSX1NUQVRFKTtcblxuICAvKipcbiAgICogRmlyZWQgZXZlcnkgdGltZSB0aGUgSFRNTCBlbGVtZW50IGNoYW5nZXMuXG4gICAqXG4gICAqIEBwYXJhbSBmblxuICAgKi9cbiAgY29uc3Qgb25DaGFuZ2UgPSAoZm46IChlbDogSFRNTEVsZW1lbnQgfCBudWxsKSA9PiB2b2lkKSA9PiB7XG4gICAgZW9SZWYuY3VycmVudD8ucmVnaXN0ZXJPbkNoYW5nZShmbik7XG4gIH07XG5cbiAgLyoqXG4gICAqIEZpcmVkIHdoZW4gdGhlIEhUTUwgZWxlbWVudCBpcyBhZGRlZCB0byB0aGUgRE9NLlxuICAgKlxuICAgKiBAcGFyYW0gZm5cbiAgICovXG4gIGNvbnN0IG9uQWRkID0gKGZuOiAoZWw6IEhUTUxFbGVtZW50IHwgbnVsbCkgPT4gdm9pZCkgPT4ge1xuICAgIGVvUmVmLmN1cnJlbnQ/LnJlZ2lzdGVyT25BZGQoZm4pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBGaXJlZCB3aGVuIHRoZSBIVE1MIGVsZW1lbnQgaXMgcmVtb3ZlZCBmcm9tIHRoZSBET00uXG4gICAqXG4gICAqIEBwYXJhbSBmblxuICAgKi9cbiAgY29uc3Qgb25SZW1vdmUgPSAoZm46IChlbDogSFRNTEVsZW1lbnQgfCBudWxsKSA9PiB2b2lkKSA9PiB7XG4gICAgZW9SZWYuY3VycmVudD8ucmVnaXN0ZXJPblJlbW92ZShmbik7XG4gIH07XG5cbiAgLyoqXG4gICAqIEZpcmVkIHdoZW4gdGhlIGNsYXNzIG9mIHRoZSBIVE1MIGVsZW1lbnQgY2hhbmdlcy5cbiAgICpcbiAgICogQHBhcmFtIGZuXG4gICAqL1xuICBjb25zdCBvbkNsYXNzQ2hhbmdlID0gKGZuOiAoY2xhc3Nlcz86IERPTVRva2VuTGlzdCkgPT4gdm9pZCkgPT4ge1xuICAgIGVvUmVmLmN1cnJlbnQ/LnJlZ2lzdGVyT25jbGFzc0NoYW5nZShmbik7XG4gIH07XG5cbiAgLyoqXG4gICAqIEZpcmVkIHdoZW4gYSBjbGFzcyBpcyBhZGRlZCB0byB0aGUgSFRNTCBlbGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gY2xhc3NOYW1lXG4gICAqIEBwYXJhbSBmblxuICAgKi9cbiAgY29uc3Qgb25DbGFzc0FkZGVkID0gKGNsYXNzTmFtZTogc3RyaW5nLCBmbjogKCkgPT4gdm9pZCkgPT4ge1xuICAgIGVvUmVmLmN1cnJlbnQ/LnJlZ2lzdGVyT25DbGFzc0FkZGVkKGNsYXNzTmFtZSwgZm4pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBGaXJlZCB3aGVuIGEgY2xhc3MgaXMgcmVtb3ZlZCBmcm9tIHRoZSBIVE1MIGVsZW1lbnQuXG4gICAqXG4gICAqIEBwYXJhbSBjbGFzc05hbWVcbiAgICogQHBhcmFtIGZuXG4gICAqL1xuICBjb25zdCBvbkNsYXNzUmVtb3ZlZCA9IChjbGFzc05hbWU6IHN0cmluZywgZm46ICgpID0+IHZvaWQpID0+IHtcbiAgICBlb1JlZi5jdXJyZW50Py5yZWdpc3Rlck9uQ2xhc3NSZW1vdmVkKGNsYXNzTmFtZSwgZm4pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBGaXJlZCB3aGVuIGEgY2hpbGQgZWxlbWVudCBpcyBhZGRlZCB0byB0aGUgSFRNTCBlbGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gZm5cbiAgICovXG4gIGNvbnN0IG9uQWRkQ2hpbGQgPSAoZm46IChub2Rlcz86IERPTVRva2VuTGlzdCkgPT4gdm9pZCkgPT4ge1xuICAgIGVvUmVmLmN1cnJlbnQ/LnJlZ2lzdGVyT25BZGRDaGlsZChmbik7XG4gIH07XG5cbiAgLyoqXG4gICAqIEZpcmVkIHdoZW4gYSBjaGlsZCBlbGVtZW50IGlzIHJlbW92ZWQgZnJvbSB0aGUgSFRNTCBlbGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0gZm5cbiAgICovXG4gIGNvbnN0IG9uUmVtb3ZlQ2hpbGQgPSAoZm46IChub2Rlcz86IERPTVRva2VuTGlzdCkgPT4gdm9pZCkgPT4ge1xuICAgIGVvUmVmLmN1cnJlbnQ/LnJlZ2lzdGVyT25SZW1vdmVDaGlsZChmbik7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFsbG93cyBob29raW5nIGV2ZW50IGxpc3RlbmVycyB0byB0aGUgSFRNTCBlbGVtZW50LCBzdWNoIGFzIGBmb2N1c2AsIGBibHVyYCwgZXRjLlxuICAgKlxuICAgKiBAcGFyYW0gZXZlbnRcbiAgICogQHBhcmFtIGZuXG4gICAqL1xuICBjb25zdCBvbkV2ZW50ID0gPEsgZXh0ZW5kcyBrZXlvZiBIVE1MRWxlbWVudEV2ZW50TWFwPihcbiAgICBldmVudDogSyxcbiAgICBmbjogRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdCxcbiAgKSA9PiB7XG4gICAgZW9SZWYuY3VycmVudC5yZWdpc3RlckV2ZW50KGV2ZW50LCBmbik7XG4gIH07XG5cbiAgLyoqXG4gICAqIFVzZWZ1bCB3aGVuIHJlbmRlcmluZyBhIFJlYWN0LmpzIGNvbXBvbmVudCBpbnNpZGUgdGhlIEhUTUwgZWxlbWVudC5cbiAgICpcbiAgICogQHBhcmFtIGZuXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBjb25zdCByZW5kZXIgPSAoZm46ICgpID0+IFJlYWN0RWxlbWVudCkgPT4ge1xuICAgIGlmICghcmVuZGVyQmxvY2tlZCkge1xuICAgICAgcmV0dXJuIGVvUmVmLmN1cnJlbnQucmVuZGVyKGZuKTtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgZWxlbWVudCBleGlzdHMgaW4gdGhlIERPTS5cbiAgICpcbiAgICogQHJldHVybnNcbiAgICovXG4gIGNvbnN0IGV4aXN0cyA9ICgpID0+ICEhZW9SZWYuY3VycmVudC5nZXROb2RlKCk7XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiByZW5kZXJpbmcgaXMgdW5ibG9ja2VkLlxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgY29uc3QgaXNSZW5kZXJlZCA9ICgpID0+ICFyZW5kZXJCbG9ja2VkO1xuXG4gIC8qKlxuICAgKiBUcmlnZ2VycyBhbiBldmVudCBmb3IgdGhlIEhUTUwgZWxlbWVudC5cbiAgICpcbiAgICogQHBhcmFtIGV2ZW50XG4gICAqL1xuICBjb25zdCBmaXJlID0gKGV2ZW50OiBNb3VzZUV2ZW50VHlwZXMpID0+IHtcbiAgICBlb1JlZi5jdXJyZW50LmZpcmUoZXZlbnQpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBTaG93cyB0aGUgSFRNTCBlbGVtZW50LlxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgY29uc3Qgc2hvdyA9ICgpID0+IGVvUmVmLmN1cnJlbnQuc2hvdygpO1xuXG4gIC8qKlxuICAgKiBIaWRlcyB0aGUgSFRNTCBlbGVtZW50LlxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgY29uc3QgaGlkZSA9ICgpID0+IGVvUmVmLmN1cnJlbnQuaGlkZSgpO1xuXG4gIC8qKlxuICAgKiBCbG9ja3MgdGhlIHJlbmRlcmluZyBvZiBlbGVtZW50cy5cbiAgICpcbiAgICogQHJldHVybnNcbiAgICovXG4gIGNvbnN0IGJsb2NrUmVuZGVyaW5nID0gKCkgPT4gc2V0UmVuZGVyQmxvY2tlZCh0cnVlKTtcblxuICAvKipcbiAgICogVW5ibG9ja3MgdGhlIHJlbmRlcmluZyBvZiBlbGVtZW50cy5cbiAgICpcbiAgICogQHJldHVybnNcbiAgICovXG4gIGNvbnN0IHVuYmxvY2tSZW5kZXJpbmcgPSAoKSA9PiBzZXRSZW5kZXJCbG9ja2VkKGZhbHNlKTtcblxuICAvKipcbiAgICogQXBwbGllcyBDU1Mgc3R5bGVzIHRvIHRoZSBIVE1MIGVsZW1lbnQuXG4gICAqXG4gICAqIEBwYXJhbSBzdHlsZXNcbiAgICovXG4gIGNvbnN0IGFwcGx5U3R5bGUgPSAoc3R5bGVzOiBSZWFjdC5DU1NQcm9wZXJ0aWVzKSA9PiB7XG4gICAgY29uc3Qgbm9kZSA9IGVvUmVmPy5jdXJyZW50Py5nZXROb2RlKCk7XG4gICAgbm9kZSAmJiBPYmplY3QuYXNzaWduKG5vZGUuc3R5bGUsIHN0eWxlcyk7XG4gIH07XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBlb1JlZi5jdXJyZW50LmluaXQoKTtcbiAgICBlb1JlZi5jdXJyZW50LnJlZ2lzdGVyT25SZXNldCgoKSA9PiBzZXRSZW5kZXJCbG9ja2VkKElOSVRJQUxfUkVOREVSX1NUQVRFKSk7XG4gICAgRE9NT2JzZXJ2ZXIub2JzZXJ2ZSgpO1xuICAgIHJldHVybiAoKSA9PiBET01PYnNlcnZlci5yZW1vdmUoc2VsZWN0b3IpO1xuICB9LCBbc2VsZWN0b3IuZ2V0UGF0dGVybigpXSk7XG5cbiAgcmV0dXJuIHtcbiAgICB0YXJnZXROb2RlOiBlb1JlZi5jdXJyZW50LmdldE5vZGUoKSxcbiAgICBvbkNoYW5nZSxcbiAgICBvbkFkZCxcbiAgICBvblJlbW92ZSxcbiAgICBvbkNsYXNzQ2hhbmdlLFxuICAgIG9uQ2xhc3NBZGRlZCxcbiAgICBvbkNsYXNzUmVtb3ZlZCxcbiAgICBvbkFkZENoaWxkLFxuICAgIG9uUmVtb3ZlQ2hpbGQsXG4gICAgb25FdmVudCxcbiAgICBibG9ja1JlbmRlcmluZyxcbiAgICB1bmJsb2NrUmVuZGVyaW5nLFxuICAgIGV4aXN0cyxcbiAgICBpc1JlbmRlcmVkLFxuICAgIHJlbmRlcixcbiAgICBmaXJlLFxuICAgIHNob3csXG4gICAgaGlkZSxcbiAgICBhcHBseVN0eWxlLFxuICB9IHNhdGlzZmllcyBFbGVtZW50T2JzZXJ2ZXJVdGlsaXR5O1xufTtcbiIsImltcG9ydCB7IHVzZVJlZiwgdXNlU3RhdGUgfSBmcm9tIFwicmVhY3RcIjtcblxudHlwZSBBcnJvd1Bvc2l0aW9uID0gJ2x0JyB8ICdjdCcgfCAncnQnXG5cbmludGVyZmFjZSBBbmltYXRpb25Qcm9wcyB7XG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnRcbiAgICB0YXJnZXRTY3JvbGw6IG51bWJlciBcbiAgICBkdXJhdGlvbjogbnVtYmVyIFxuICAgIGRpcmVjdGlvbj86ICdsdCcgfCAncnQnIFxuICAgIG11bHRpcGx5PzogbnVtYmVyIFxuICAgIG9mZnNldD86IG51bWJlclxuICAgIGNhbGxiYWNrPzogKHBvc2l0aW9uOiBBcnJvd1Bvc2l0aW9uKSA9PiB2b2lkXG59XG5cbmNvbnN0IGFuaW1hdGVIb3Jpem9udGFsU2Nyb2xsID0gKHsgZWxlbWVudCwgZHVyYXRpb24sIHRhcmdldFNjcm9sbCwgbXVsdGlwbHkgPSAxLCBkaXJlY3Rpb24sIGNhbGxiYWNrLCBvZmZzZXQgPSAwIH06IEFuaW1hdGlvblByb3BzKSA9PiB7XG4gICAgY29uc3Qgc3RhcnQgPSBlbGVtZW50LnNjcm9sbExlZnRcbiAgICBjb25zdCBkaXN0YW5jZSA9ICh0YXJnZXRTY3JvbGwgLSBzdGFydCkgKiBtdWx0aXBseTtcbiAgICBjb25zdCBzdGFydFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcblxuICAgIGZ1bmN0aW9uIGVhc2VPdXRTaW5lKHg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICByZXR1cm4gTWF0aC5zaW4oKHggKiBNYXRoLlBJKSAvIDIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNjcm9sbFN0ZXAoY3VycmVudFRpbWU6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCB0aW1lRWxhcHNlZCA9IGN1cnJlbnRUaW1lIC0gc3RhcnRUaW1lO1xuICAgICAgICBjb25zdCBwcm9ncmVzcyA9IE1hdGgubWluKHRpbWVFbGFwc2VkIC8gZHVyYXRpb24sIDEpO1xuICAgICAgICBjb25zdCBlYXNpbmcgPSBlYXNlT3V0U2luZShwcm9ncmVzcyk7XG4gICAgICAgIGNvbnN0IHN0ZXAgPSBzdGFydCArIChkaXN0YW5jZSAqIGVhc2luZylcbiAgICAgICAgY29uc3QgY2FuU2Nyb2xsID0gKGRpcmVjdGlvbiA9PT0gJ3J0JyA/IChlbGVtZW50LnNjcm9sbExlZnQgPCBzdGVwKSA6IChlbGVtZW50LnNjcm9sbExlZnQgPiBzdGVwKSkgfHwgIWRpcmVjdGlvblxuICAgICAgICBcbiAgICAgICAgaWYgKHN0ZXAgPiAwICYmIGNhblNjcm9sbCkge1xuICAgICAgICAgIGVsZW1lbnQuc2Nyb2xsVG8oc3RlcCwgMClcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aW1lRWxhcHNlZCA8IGR1cmF0aW9uKSB7XG4gICAgICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoc2Nyb2xsU3RlcCk7XG4gICAgICAgIH0gXG5cbiAgICAgICAgLy8gRW5kIG9mIHNjcm9sbGluZyBjb250YWluZXJcbiAgICAgICAgZWxzZSBpZiAoKGVsZW1lbnQuc2Nyb2xsTGVmdCArIG9mZnNldCkgPT09IGVsZW1lbnQuc2Nyb2xsV2lkdGgpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrPy4oJ3J0JylcbiAgICAgICAgfSBcbiAgICAgICAgLy8gQmVnaW4gb2Ygc2Nyb2xsaW5nIGNvbnRhaW5lclxuICAgICAgICBlbHNlIGlmIChlbGVtZW50LnNjcm9sbExlZnQgPD0gMSkge1xuICAgICAgICAgICAgY2FsbGJhY2s/LignbHQnKVxuICAgICAgICB9XG4gICAgICAgIC8vIFNvbWV3aGVyZSBpbiB0aGUgbWlkZGxlXG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY2FsbGJhY2s/LignY3QnKVxuICAgICAgICB9XG5cbiAgICB9XG5cbiAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoc2Nyb2xsU3RlcCk7XG59XG5cblxuZXhwb3J0IGNvbnN0IHVzZUdyYWJBbmRTY3JvbGwgPSAoZW5hYmxlZDogYm9vbGVhbiwgY2h1bmtXaWR0aDogbnVtYmVyLCBzcGVlZDogbnVtYmVyID0gNDAwLCBvZmZzZXQ6IG51bWJlciA9IDApID0+IHtcbiAgICBjb25zdCBjb250YWluZXJSZWYgPSB1c2VSZWY8SFRNTERpdkVsZW1lbnQ+KG51bGwpXG4gICAgY29uc3QgWyBsZWZ0QXJyb3csIHNldExlZnRBcnJvdyBdID0gdXNlU3RhdGUoZmFsc2UpXG4gICAgY29uc3QgWyByaWdodEFycm93LCBzZXRSaWdodEFycm93IF0gPSB1c2VTdGF0ZSh0cnVlKVxuXG4gICAgY29uc3QgaGFuZGxlQXJyb3dzID0gKHBvc2l0aW9uOiBBcnJvd1Bvc2l0aW9uKSA9PiB7XG4gICAgICAgIHN3aXRjaCAocG9zaXRpb24pIHtcbiAgICAgICAgICAgIGNhc2UgJ2x0JzpcbiAgICAgICAgICAgICAgICBzZXRMZWZ0QXJyb3coZmFsc2UpXG4gICAgICAgICAgICAgICAgc2V0UmlnaHRBcnJvdyh0cnVlKVxuICAgICAgICAgICAgICAgIGJyZWFrXG5cbiAgICAgICAgICAgIGNhc2UgJ3J0JzpcbiAgICAgICAgICAgICAgICBzZXRMZWZ0QXJyb3codHJ1ZSlcbiAgICAgICAgICAgICAgICBzZXRSaWdodEFycm93KGZhbHNlKVxuICAgICAgICAgICAgICAgIGJyZWFrXG5cbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgc2V0TGVmdEFycm93KHRydWUpXG4gICAgICAgICAgICAgICAgc2V0UmlnaHRBcnJvdyh0cnVlKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgYW5pbWF0aW9uVHJpZ2dlciA9ICgpID0+IHtcbiAgICAgICAgaWYgKGVuYWJsZWQgJiYgY29udGFpbmVyUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IGRpc3QgPSAoY29udGFpbmVyUmVmPy5jdXJyZW50Py5zY3JvbGxMZWZ0IHx8IDApIC8gY2h1bmtXaWR0aFxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0U2Nyb2xsID0gY2h1bmtXaWR0aCAqIChNYXRoLmZsb29yKGRpc3QpICsgKGRpc3QgJSAxID4gMC41ID8gMSA6IDApKVxuICAgICAgICAgICAgYW5pbWF0ZUhvcml6b250YWxTY3JvbGwoe1xuICAgICAgICAgICAgICAgIGVsZW1lbnQ6IGNvbnRhaW5lclJlZi5jdXJyZW50LCBcbiAgICAgICAgICAgICAgICB0YXJnZXRTY3JvbGwsIFxuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiBzcGVlZCxcbiAgICAgICAgICAgICAgICBvZmZzZXQsXG4gICAgICAgICAgICAgICAgY2FsbGJhY2s6IGhhbmRsZUFycm93c1xuICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG9uTmV4dCA9IChjYXJkc1RvU2xpZGU6IG51bWJlcikgPT4ge1xuICAgICAgICBpZiAoY29udGFpbmVyUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldFNjcm9sbCA9IGNvbnRhaW5lclJlZi5jdXJyZW50LnNjcm9sbExlZnQgKyBjaHVua1dpZHRoXG4gICAgICAgICAgICBhbmltYXRlSG9yaXpvbnRhbFNjcm9sbCh7XG4gICAgICAgICAgICAgICAgZWxlbWVudDogY29udGFpbmVyUmVmLmN1cnJlbnQsIFxuICAgICAgICAgICAgICAgIHRhcmdldFNjcm9sbCwgXG4gICAgICAgICAgICAgICAgZHVyYXRpb246IHNwZWVkLCBcbiAgICAgICAgICAgICAgICBkaXJlY3Rpb246ICdydCcsIFxuICAgICAgICAgICAgICAgIG11bHRpcGx5OiBjYXJkc1RvU2xpZGUsXG4gICAgICAgICAgICAgICAgb2Zmc2V0LFxuICAgICAgICAgICAgICAgIGNhbGxiYWNrOiBoYW5kbGVBcnJvd3NcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgY29uc3Qgb25QcmV2aW91cyA9IChjYXJkc1RvU2xpZGU6IG51bWJlcikgPT4ge1xuICAgICAgICBpZiAoY29udGFpbmVyUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldFNjcm9sbCA9IGNvbnRhaW5lclJlZi5jdXJyZW50LnNjcm9sbExlZnQgLSBjaHVua1dpZHRoXG4gICAgICAgICAgICBhbmltYXRlSG9yaXpvbnRhbFNjcm9sbCh7XG4gICAgICAgICAgICAgICAgZWxlbWVudDogY29udGFpbmVyUmVmLmN1cnJlbnQsIFxuICAgICAgICAgICAgICAgIHRhcmdldFNjcm9sbCwgXG4gICAgICAgICAgICAgICAgZHVyYXRpb246IHNwZWVkLCBcbiAgICAgICAgICAgICAgICBkaXJlY3Rpb246ICdsdCcsIFxuICAgICAgICAgICAgICAgIG11bHRpcGx5OiBjYXJkc1RvU2xpZGUsXG4gICAgICAgICAgICAgICAgb2Zmc2V0LFxuICAgICAgICAgICAgICAgIGNhbGxiYWNrOiBoYW5kbGVBcnJvd3NcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBjb250YWluZXJSZWYsXG4gICAgICAgIGxlZnRBcnJvdyxcbiAgICAgICAgcmlnaHRBcnJvdyxcbiAgICAgICAgYW5pbWF0aW9uVHJpZ2dlcixcbiAgICAgICAgb25OZXh0LFxuICAgICAgICBvblByZXZpb3VzXG4gICAgfVxufSIsImltcG9ydCBSZWFjdCwge1xuICBjcmVhdGVDb250ZXh0LFxuICB1c2VDb250ZXh0LFxuICB1c2VDYWxsYmFjayxcbiAgdXNlTWVtbyxcbiAgUmVhY3ROb2RlLFxufSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZUF0b21WYWx1ZSB9IGZyb20gXCJqb3RhaVwiO1xuaW1wb3J0IHsgYmFzZVVybEF0b20sIG9yZ0xldmVsQXBpS2V5QXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuaW1wb3J0IHsgZ2V0TWVyY2hhbnRPcmdJZFF1ZXJ5IH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvZ3JhcGhxbC9xdWVyaWVzL2dldE1lcmNoYW50T3JnSWRRdWVyeVwiO1xuaW1wb3J0IHsgdmFsaWRhdGVHcmFwaFFMT3JnSWQgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy92YWxpZGF0b3JzL3ZhbGlkYXRlR3JhcGhRTE9yZ0lkXCI7XG5pbXBvcnQge1xuICBnZXRNZXJjaGFudENvbG9yc1F1ZXJ5LFxuICBHZXRNZXJjaGFudENvbG9yc1F1ZXJ5RGF0YSxcbiAgZ2V0TWVyY2hhbnRGcm9udGVuZENvbmZpZ1F1ZXJ5LFxuICBHZXRNZXJjaGFudEZyb250ZW5kQ29uZmlnUXVlcnlEYXRhLFxufSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9ncmFwaHFsXCI7XG5pbXBvcnQgeyB2YWxpZGF0ZUdyYXBoUUxDb2xvcnNDb25maWcgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy92YWxpZGF0b3JzL3ZhbGlkYXRlR3JhcGhRTENvbG9yc0NvbmZpZ1wiO1xuaW1wb3J0IHsgdmFsaWRhdGVHcmFwaFFMRnJvbnRlbmRDb25maWcgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy92YWxpZGF0b3JzL3ZhbGlkYXRlR3JhcGhRTEZyb250ZW5kQ29uZmlnXCI7XG5pbXBvcnQgeyBDb2xvck1hcHBpbmcgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9jb2xvcnNDb25maWdcIjtcbmltcG9ydCB7IEZyb250ZW5kQ29uZmlnIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvZnJvbnRlbmRDb25maWdcIjtcbmltcG9ydCBMb2dnZXIgZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9sb2dnaW5nL2xvZ2dlclwiO1xuaW1wb3J0IHsgY29uZmlnVmVyc2lvbiB9IGZyb20gXCJzcmMvdHlwZXMvY29uZmlnLXZlcnNpb25zXCI7XG5pbXBvcnQge1xuICBDYW1lbENhc2VkUHJvcGVydGllc0RlZXAsXG4gIHRyYW5zZm9ybVNuYWtlVG9DYW1lbCxcbn0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHNcIjtcblxuaW50ZXJmYWNlIEJhc2VNZUNvbmZpZ1F1ZXJ5UmVzcG9uc2Uge1xuICBtZToge1xuICAgIG9yZz86IHtcbiAgICAgIGlkOiBzdHJpbmc7XG4gICAgfTtcbiAgICBnZXRQcm9kdWN0c0NvbmZpZ0J5VmVyc2lvbj86IHtcbiAgICAgIGZyb250ZW5kPzoge1xuICAgICAgICB2YWx1ZXM6IENhbWVsQ2FzZWRQcm9wZXJ0aWVzRGVlcDxHZXRNZXJjaGFudEZyb250ZW5kQ29uZmlnUXVlcnlEYXRhPjtcbiAgICAgIH07XG4gICAgICBjb2xvcnM/OiB7IHZhbHVlczogQ2FtZWxDYXNlZFByb3BlcnRpZXNEZWVwPEdldE1lcmNoYW50Q29sb3JzUXVlcnlEYXRhPiB9O1xuICAgIH07XG4gIH07XG59XG5leHBvcnQgdHlwZSBDb2xvcnNDb25maWdSZXNwb25zZSA9IENhbWVsQ2FzZWRQcm9wZXJ0aWVzRGVlcDxDb2xvck1hcHBpbmc+O1xuZXhwb3J0IHR5cGUgRnJvbnRlbmRDb25maWdSZXNwb25zZSA9IENhbWVsQ2FzZWRQcm9wZXJ0aWVzRGVlcDxGcm9udGVuZENvbmZpZz47XG5cbmV4cG9ydCB0eXBlIEdyYXBoUWxDb25maWdWYWx1ZXMgPSB7XG4gIGNvbG9yc0NvbmZpZz86IENvbG9yc0NvbmZpZ1Jlc3BvbnNlO1xuICBmcm9udGVuZENvbmZpZz86IENhbWVsQ2FzZWRQcm9wZXJ0aWVzRGVlcDxGcm9udGVuZENvbmZpZz47XG59O1xuXG5pbnRlcmZhY2UgR3JhcGhRTENvbnRleHRWYWx1ZSB7XG4gIGV4ZWN1dGVRdWVyeTogPFQ+KFxuICAgIHF1ZXJ5OiBzdHJpbmcsXG4gICAgdmFyaWFibGVzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgKSA9PiBQcm9taXNlPFQ+O1xuICBnZXRPcmdJZDogKCkgPT4gUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+O1xuICBnZXRDb2xvcnNBbmRGcm9udGVuZENvbmZpZzogKCkgPT4gUHJvbWlzZTxHcmFwaFFsQ29uZmlnVmFsdWVzPjtcbiAgaXNSZWFkeTogYm9vbGVhbjtcbn1cblxuY29uc3QgR3JhcGhRTENvbnRleHQgPSBjcmVhdGVDb250ZXh0PEdyYXBoUUxDb250ZXh0VmFsdWUgfCBudWxsPihudWxsKTtcblxuY29uc3QgY29sb3JzQW5kRnJvbnRlbmRDb25maWdRdWVyeSA9ICgpID0+IGBcbiAgcXVlcnkgKCR2ZXJzaW9uOiBTdHJpbmcgPSBcIiR7Y29uZmlnVmVyc2lvbigpfVwiKSB7XG4gICAgbWUge1xuICAgICAgZ2V0UHJvZHVjdHNDb25maWdCeVZlcnNpb24odmVyc2lvbjogJHZlcnNpb24pIHtcbiAgICAgICAgZnJvbnRlbmQgeyB2YWx1ZXMgfVxuICAgICAgICBjb2xvcnMgeyB2YWx1ZXMgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuYDtcblxudHlwZSBHcmFwaFFMUHJvdmlkZXJQcm9wcyA9IHtcbiAgY2hpbGRyZW46IFJlYWN0Tm9kZTtcbn07XG5cbmV4cG9ydCBjb25zdCBHcmFwaFFMUHJvdmlkZXIgPSAoeyBjaGlsZHJlbiB9OiBHcmFwaFFMUHJvdmlkZXJQcm9wcykgPT4ge1xuICBjb25zdCBhcGlLZXkgPSB1c2VBdG9tVmFsdWUob3JnTGV2ZWxBcGlLZXlBdG9tKTtcbiAgY29uc3QgYmFzZVVybCA9IHVzZUF0b21WYWx1ZShiYXNlVXJsQXRvbSk7XG5cbiAgY29uc3QgaXNSZWFkeSA9IEJvb2xlYW4oYXBpS2V5ICYmIGJhc2VVcmwpO1xuXG4gIGNvbnN0IGV4ZWN1dGVRdWVyeSA9IHVzZUNhbGxiYWNrKFxuICAgIGFzeW5jIChxdWVyeTogc3RyaW5nLCB2YXJpYWJsZXM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4ge1xuICAgICAgaWYgKCFpc1JlYWR5KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkdyYXBoUUwgY2xpZW50IG5vdCByZWFkeSAtIG1pc3NpbmcgYXBpS2V5IG9yIGJhc2VVcmxcIik7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYCR7YmFzZVVybH0vdjEvZ3JhcGhxbGAsIHtcbiAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiLFxuICAgICAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHthcGlLZXl9YCxcbiAgICAgICAgfSxcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBxdWVyeSwgdmFyaWFibGVzIH0pLFxuICAgICAgfSk7XG5cbiAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBHcmFwaFFMIHJlcXVlc3QgZmFpbGVkOiAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgIGlmIChyZXN1bHQuZXJyb3JzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgR3JhcGhRTCBlcnJvcnM6ICR7SlNPTi5zdHJpbmdpZnkocmVzdWx0LmVycm9ycyl9YCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXN1bHQuZGF0YTtcbiAgICB9LFxuICAgIFthcGlLZXksIGJhc2VVcmwsIGlzUmVhZHldXG4gICk7XG5cbiAgY29uc3QgZ2V0T3JnSWQgPSB1c2VDYWxsYmFjayhhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBleGVjdXRlUXVlcnkoZ2V0TWVyY2hhbnRPcmdJZFF1ZXJ5KTtcbiAgICByZXR1cm4gdmFsaWRhdGVHcmFwaFFMT3JnSWQocmVzcG9uc2UubWUub3JnPy5pZCk7XG4gIH0sIFtleGVjdXRlUXVlcnldKTtcblxuICBjb25zdCBnZXRDb2xvcnNBbmRGcm9udGVuZENvbmZpZyA9XG4gICAgdXNlQ2FsbGJhY2soYXN5bmMgKCk6IFByb21pc2U8R3JhcGhRbENvbmZpZ1ZhbHVlcz4gPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcXVlcnkgPSBhd2FpdCBjb2xvcnNBbmRGcm9udGVuZENvbmZpZ1F1ZXJ5KCk7XG4gICAgICAgIGlmICghcXVlcnkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb2xvcnMgYW5kIGZyb250ZW5kIGNvbmZpZyBxdWVyeSBpcyBub3QgZGVmaW5lZFwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGV4ZWN1dGVRdWVyeShxdWVyeSk7XG4gICAgICAgIGNvbnN0IGNvbG9yc0NvbmZpZyA9XG4gICAgICAgICAgcmVzcG9uc2UubWUuZ2V0UHJvZHVjdHNDb25maWdCeVZlcnNpb24/LmNvbG9ycz8udmFsdWVzO1xuICAgICAgICBjb25zdCBmcm9udGVuZENvbmZpZyA9XG4gICAgICAgICAgcmVzcG9uc2UubWUuZ2V0UHJvZHVjdHNDb25maWdCeVZlcnNpb24/LmZyb250ZW5kPy52YWx1ZXM7XG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybWVkQ29sb3JDb25maWcgPSB0cmFuc2Zvcm1TbmFrZVRvQ2FtZWwoY29sb3JzQ29uZmlnKTtcbiAgICAgICAgY29uc3QgdHJhbnNmb3JtZWRGcm9udGVuZENvbmZpZyA9IHRyYW5zZm9ybVNuYWtlVG9DYW1lbChmcm9udGVuZENvbmZpZyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY29sb3JzQ29uZmlnOiB0cmFuc2Zvcm1lZENvbG9yQ29uZmlnIGFzIENvbG9yc0NvbmZpZ1Jlc3BvbnNlLFxuICAgICAgICAgIGZyb250ZW5kQ29uZmlnOiB0cmFuc2Zvcm1lZEZyb250ZW5kQ29uZmlnIGFzIEZyb250ZW5kQ29uZmlnUmVzcG9uc2UsXG4gICAgICAgIH07XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFxuICAgICAgICAgIFwiRXJyb3IgZmV0Y2hpbmcgZ3JhcGhxbCBjb2xvcnMgYW5kIGZyb250ZW5kIGNvbmZpZ1wiLFxuICAgICAgICAgIGVyclxuICAgICAgICApO1xuICAgICAgICByZXR1cm4geyBjb2xvcnNDb25maWc6IHVuZGVmaW5lZCwgZnJvbnRlbmRDb25maWc6IHVuZGVmaW5lZCB9O1xuICAgICAgfVxuICAgIH0sIFtleGVjdXRlUXVlcnldKTtcblxuICBjb25zdCB2YWx1ZSA9IHVzZU1lbW8oXG4gICAgKCkgPT4gKHtcbiAgICAgIGV4ZWN1dGVRdWVyeSxcbiAgICAgIGdldE9yZ0lkLFxuICAgICAgZ2V0Q29sb3JzQW5kRnJvbnRlbmRDb25maWcsXG4gICAgICBpc1JlYWR5LFxuICAgIH0pLFxuICAgIFtleGVjdXRlUXVlcnksIGdldE9yZ0lkLCBnZXRDb2xvcnNBbmRGcm9udGVuZENvbmZpZywgaXNSZWFkeV1cbiAgKTtcblxuICByZXR1cm4gKFxuICAgIDxHcmFwaFFMQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17dmFsdWV9PntjaGlsZHJlbn08L0dyYXBoUUxDb250ZXh0LlByb3ZpZGVyPlxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHVzZUdyYXBoUUxDbGllbnQgPSAoKSA9PiB7XG4gIGNvbnN0IGNvbnRleHQgPSB1c2VDb250ZXh0KEdyYXBoUUxDb250ZXh0KTtcbiAgaWYgKCFjb250ZXh0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwidXNlR3JhcGhRTENsaWVudCBtdXN0IGJlIHVzZWQgd2l0aGluIGEgR3JhcGhRTFByb3ZpZGVyXCIpO1xuICB9XG4gIHJldHVybiBjb250ZXh0O1xufTtcbiIsImltcG9ydCB7IHVzZUNhbGxiYWNrLCB1c2VFZmZlY3QsIHVzZVN0YXRlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyB1c2VHcmFwaFFMQ2xpZW50IH0gZnJvbSBcInNyYy9jb250ZXh0cy9ncmFwaHFsQ29udGV4dFwiO1xuaW1wb3J0IHsgQ29sb3JNYXBwaW5nIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvY29sb3JzQ29uZmlnXCI7XG5pbXBvcnQgeyBGcm9udGVuZENvbmZpZyB9IGZyb20gXCJzcmMvYXBwbGljYXRpb24vbW9kZWxzL2Zyb250ZW5kQ29uZmlnXCI7XG5pbXBvcnQgeyB0cmFuc2Zvcm1TbmFrZVRvQ2FtZWwgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVsc1wiO1xuXG5leHBvcnQgY29uc3QgdXNlQ29sb3JzQW5kRnJvbnRlbmRDb25maWcgPSAoKSA9PiB7XG4gIGNvbnN0IHsgZ2V0Q29sb3JzQW5kRnJvbnRlbmRDb25maWcsIGlzUmVhZHkgfSA9IHVzZUdyYXBoUUxDbGllbnQoKTtcbiAgY29uc3QgW2RhdGEsIHNldERhdGFdID0gdXNlU3RhdGUoe30pO1xuICBjb25zdCBbbG9hZGluZywgc2V0TG9hZGluZ10gPSB1c2VTdGF0ZShmYWxzZSk7XG4gIGNvbnN0IFtlcnJvciwgc2V0RXJyb3JdID0gdXNlU3RhdGU8RXJyb3IgfCBudWxsPihudWxsKTtcblxuICBjb25zdCBmZXRjaENvbmZpZyA9IHVzZUNhbGxiYWNrKGFzeW5jICgpID0+IHtcbiAgICBpZiAoIWlzUmVhZHkpIHJldHVybjtcblxuICAgIHNldExvYWRpbmcodHJ1ZSk7XG4gICAgc2V0RXJyb3IobnVsbCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZ2V0Q29sb3JzQW5kRnJvbnRlbmRDb25maWcoKTtcbiAgICAgIHNldERhdGEocmVzdWx0KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHNldEVycm9yKGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyIDogbmV3IEVycm9yKFwiVW5rbm93biBlcnJvclwiKSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHNldExvYWRpbmcoZmFsc2UpO1xuICAgIH1cbiAgfSwgW2dldENvbG9yc0FuZEZyb250ZW5kQ29uZmlnLCBpc1JlYWR5XSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBmZXRjaENvbmZpZygpO1xuICB9LCBbZmV0Y2hDb25maWddKTtcblxuICByZXR1cm4geyBkYXRhLCBsb2FkaW5nLCBlcnJvciwgcmVmZXRjaDogZmV0Y2hDb25maWcgfTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VPcmdJZCA9ICgpID0+IHtcbiAgY29uc3QgeyBnZXRPcmdJZCwgaXNSZWFkeSB9ID0gdXNlR3JhcGhRTENsaWVudCgpO1xuICBjb25zdCBbb3JnSWQsIHNldE9yZ0lkXSA9IHVzZVN0YXRlPHN0cmluZyB8IHVuZGVmaW5lZD4oKTtcbiAgY29uc3QgW2xvYWRpbmcsIHNldExvYWRpbmddID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbZXJyb3IsIHNldEVycm9yXSA9IHVzZVN0YXRlPEVycm9yIHwgbnVsbD4obnVsbCk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoIWlzUmVhZHkpIHJldHVybjtcblxuICAgIGNvbnN0IGZldGNoT3JnSWQgPSBhc3luYyAoKSA9PiB7XG4gICAgICBzZXRMb2FkaW5nKHRydWUpO1xuICAgICAgc2V0RXJyb3IobnVsbCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGlkID0gYXdhaXQgZ2V0T3JnSWQoKTtcbiAgICAgICAgc2V0T3JnSWQoaWQpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHNldEVycm9yKGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyIDogbmV3IEVycm9yKFwiVW5rbm93biBlcnJvclwiKSk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBzZXRMb2FkaW5nKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgZmV0Y2hPcmdJZCgpO1xuICB9LCBbZ2V0T3JnSWQsIGlzUmVhZHldKTtcblxuICByZXR1cm4geyBvcmdJZCwgbG9hZGluZywgZXJyb3IgfTtcbn07XG4iLCJpbXBvcnQgUmVhY3QsIHtcbiAgY3JlYXRlQ29udGV4dCxcbiAgdXNlQ2FsbGJhY2ssXG4gIHVzZUNvbnRleHQsXG4gIHVzZU1lbW8sXG4gIHVzZVN0YXRlLFxuICB1c2VFZmZlY3QsXG59IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IFVBUGFyc2VyIGZyb20gXCJ1YS1wYXJzZXItanNcIjtcbmltcG9ydCBMb2dnZXIgZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9sb2dnaW5nL2xvZ2dlclwiO1xuaW1wb3J0IENvbW1lcmNlQXBpQ2xpZW50IGZyb20gXCJzcmMvYXBwbGljYXRpb24vY29tbWVyY2UtYXBpXCI7XG5pbXBvcnQgeyB2NCBhcyB1dWlkIH0gZnJvbSBcInV1aWRcIjtcbmltcG9ydCB7IENsaWVudERldGFpbHMgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9jbGllbnREZXRhaWxzXCI7XG5pbXBvcnQgeyB1c2VMb2NhbFN0b3JhZ2UgfSBmcm9tIFwic3JjL2NvbnRleHRzL2xvY2FsU3RvcmFnZUNvbnRleHRcIjtcblxuLy8gSGVscGVyIGZ1bmN0aW9uIGZyb20gdGhlIG9yaWdpbmFsIHNlcnZpY2VcbmNvbnN0IGdldFVzZXJBZ2VudERldGFpbHMgPSAoKTogQ2xpZW50RGV0YWlscyA9PiB7XG4gIGNvbnN0IHVhUGFyc2VyID0gbmV3IFVBUGFyc2VyKCk7XG4gIGNvbnN0IHJlc3VsdCA9IHVhUGFyc2VyLmdldFJlc3VsdCgpO1xuXG4gIHJldHVybiB7XG4gICAgb3M6IHJlc3VsdD8ub3M/Lm5hbWUsXG4gICAgb3NWZXJzaW9uOiByZXN1bHQ/Lm9zPy52ZXJzaW9uLFxuICAgIGRldmljZUJyYW5kOiByZXN1bHQ/LmRldmljZT8udmVuZG9yLFxuICAgIGRldmljZU1hbnVmYWN0dXJlcjogcmVzdWx0Py5kZXZpY2U/LnZlbmRvcixcbiAgICBkZXZpY2VNb2RlbDogcmVzdWx0Py5kZXZpY2U/Lm1vZGVsLFxuICAgIGJyb3dzZXI6IHJlc3VsdD8uYnJvd3Nlcj8ubmFtZSxcbiAgICBicm93c2VyVmVyc2lvbjogcmVzdWx0Py5icm93c2VyPy52ZXJzaW9uLFxuICAgIHVzZXJBZ2VudDogcmVzdWx0Py51YSxcbiAgfTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXNlcklkZW50aXR5Q29udGV4dFR5cGUge1xuICBpZGVudGlmeVVzZXI6ICgpID0+IFByb21pc2U8dm9pZD47XG4gIGdldFVzZXJJZE9yRGVmYXVsdDogKCkgPT4gc3RyaW5nO1xuICBnZXRVc2VySWRPdmVycmlkZUZyb21Mb2NhbFN0b3JhZ2U6ICgpID0+IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgZ2V0VXNlcklkRGVmYXVsdEZyb21Mb2NhbFN0b3JhZ2U6ICgpID0+IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgc2V0VXNlcklkRGVmYXVsdEluTG9jYWxTdG9yYWdlOiAodXNlcklkOiBzdHJpbmcpID0+IHN0cmluZztcbiAgc2V0VXNlcklkT3ZlcnJpZGVJbkxvY2FsU3RvcmFnZTogKHVzZXJJZDogc3RyaW5nKSA9PiBzdHJpbmc7XG4gIGNsZWFyVXNlcklkT3ZlcnJpZGVJbkxvY2FsU3RvcmFnZTogKCkgPT4gdm9pZDtcbiAgaXNSZWFkeTogYm9vbGVhbjtcbn1cblxuY29uc3QgVXNlcklkZW50aXR5Q29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8VXNlcklkZW50aXR5Q29udGV4dFR5cGUgfCB1bmRlZmluZWQ+KFxuICB1bmRlZmluZWRcbik7XG5cbmV4cG9ydCBjb25zdCBVc2VySWRlbnRpdHlQcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+ID0gKHtcbiAgY2hpbGRyZW4sXG59KSA9PiB7XG4gIGNvbnN0IHtcbiAgICBnZXRJdGVtLFxuICAgIHNldEl0ZW0sXG4gICAgaXNBdmFpbGFibGU6IGxvY2FsU3RvcmFnZUlzUmVhZHksXG4gIH0gPSB1c2VMb2NhbFN0b3JhZ2UoKTtcblxuICBjb25zdCBbaXNSZWFkeSwgc2V0SXNSZWFkeV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAvLyBBc3N1bWluZyBDb21tZXJjZUFwaUNsaWVudCBhbmQgb3RoZXIgZGVwZW5kZW5jaWVzIGFyZSByZWFkeSBpZiBsb2NhbFN0b3JhZ2UgaXMuXG4gICAgLy8gSW4gYSBtb3JlIGNvbXBsZXggc2NlbmFyaW8sIHlvdSBtaWdodCBoYXZlIG1vcmUgY2hlY2tzIGhlcmUuXG4gICAgc2V0SXNSZWFkeShsb2NhbFN0b3JhZ2VJc1JlYWR5KTtcbiAgfSwgW2xvY2FsU3RvcmFnZUlzUmVhZHldKTtcblxuICBjb25zdCBVU0VSX0lEX09WRVJSSURFX0tFWSA9IFwidjEtc3BpZmZ5LXVzZXItaWQtb3ZlcnJpZGVcIjtcbiAgY29uc3QgVVNFUl9JRF9ERUZBVUxUX0tFWSA9IFwidjEtc3BpZmZ5LXVzZXItaWQtZGVmYXVsdFwiO1xuXG4gIGNvbnN0IGdldFVzZXJJZE92ZXJyaWRlRnJvbUxvY2FsU3RvcmFnZSA9IHVzZUNhbGxiYWNrKCgpOlxuICAgIHwgc3RyaW5nXG4gICAgfCB1bmRlZmluZWQgPT4ge1xuICAgIHJldHVybiBnZXRJdGVtKFVTRVJfSURfT1ZFUlJJREVfS0VZKSA/PyB1bmRlZmluZWQ7XG4gIH0sIFtnZXRJdGVtXSk7XG5cbiAgY29uc3QgZ2V0VXNlcklkRGVmYXVsdEZyb21Mb2NhbFN0b3JhZ2UgPSB1c2VDYWxsYmFjaygoKTpcbiAgICB8IHN0cmluZ1xuICAgIHwgdW5kZWZpbmVkID0+IHtcbiAgICByZXR1cm4gZ2V0SXRlbShVU0VSX0lEX0RFRkFVTFRfS0VZKSA/PyB1bmRlZmluZWQ7XG4gIH0sIFtnZXRJdGVtXSk7XG5cbiAgY29uc3Qgc2V0VXNlcklkRGVmYXVsdEluTG9jYWxTdG9yYWdlID0gdXNlQ2FsbGJhY2soXG4gICAgKHVzZXJJZDogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgICAgIExvZ2dlci5sb2dJbmZvKFxuICAgICAgICBgc2V0VXNlcklkRGVmYXVsdEluTG9jYWxTdG9yYWdlIC0gU2V0dGluZyB1c2VyX2lkPSR7dXNlcklkfWBcbiAgICAgICk7XG4gICAgICBzZXRJdGVtKFVTRVJfSURfREVGQVVMVF9LRVksIHVzZXJJZCk7XG4gICAgICAvLyB3aW5kb3cuZGlzcGF0Y2hFdmVudCBpcyBoYW5kbGVkIGJ5IHVzZUxvY2FsU3RvcmFnZSBub3dcbiAgICAgIHJldHVybiB1c2VySWQ7XG4gICAgfSxcbiAgICBbc2V0SXRlbSwgVVNFUl9JRF9ERUZBVUxUX0tFWV1cbiAgKTtcblxuICBjb25zdCBzZXRVc2VySWRPdmVycmlkZUluTG9jYWxTdG9yYWdlID0gdXNlQ2FsbGJhY2soXG4gICAgKHVzZXJJZDogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgICAgIExvZ2dlci5sb2dJbmZvKFxuICAgICAgICBgc2V0VXNlcklkT3ZlcnJpZGVJbkxvY2FsU3RvcmFnZSAtIFNldHRpbmcgdXNlcl9pZD0ke3VzZXJJZH1gXG4gICAgICApO1xuICAgICAgc2V0SXRlbShVU0VSX0lEX09WRVJSSURFX0tFWSwgdXNlcklkKTtcbiAgICAgIC8vIHdpbmRvdy5kaXNwYXRjaEV2ZW50IGlzIGhhbmRsZWQgYnkgdXNlTG9jYWxTdG9yYWdlIG5vd1xuICAgICAgcmV0dXJuIHVzZXJJZDtcbiAgICB9LFxuICAgIFtzZXRJdGVtLCBVU0VSX0lEX09WRVJSSURFX0tFWV1cbiAgKTtcblxuICBjb25zdCBjbGVhclVzZXJJZE92ZXJyaWRlSW5Mb2NhbFN0b3JhZ2UgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgTG9nZ2VyLmxvZ0luZm8oYGNsZWFyVXNlcklkT3ZlcnJpZGVJbkxvY2FsU3RvcmFnZSAtIENsZWFyaW5nIHVzZXJfaWRgKTtcbiAgICAvLyBMb2NhbFN0b3JhZ2VTZXJ2aWNlLmdldExvY2FsU3RvcmFnZSgpPy5yZW1vdmVJdGVtKFVTRVJfSURfT1ZFUlJJREVfS0VZKTtcbiAgICAvLyB3aW5kb3cuZGlzcGF0Y2hFdmVudCBpcyBoYW5kbGVkIGJ5IHVzZUxvY2FsU3RvcmFnZSBub3dcbiAgICBzZXRJdGVtKFVTRVJfSURfT1ZFUlJJREVfS0VZLCBcIlwiKTsgLy8gU2V0IHRvIGVtcHR5IHN0cmluZyB0byBjbGVhclxuICB9LCBbc2V0SXRlbSwgVVNFUl9JRF9PVkVSUklERV9LRVldKTtcblxuICBjb25zdCBnZXRVc2VySWRPckRlZmF1bHQgPSB1c2VDYWxsYmFjaygoKTogc3RyaW5nID0+IHtcbiAgICBjb25zdCB1c2VySWRPdmVycmlkZSA9IGdldFVzZXJJZE92ZXJyaWRlRnJvbUxvY2FsU3RvcmFnZSgpO1xuICAgIGlmICh1c2VySWRPdmVycmlkZSkge1xuICAgICAgcmV0dXJuIHVzZXJJZE92ZXJyaWRlO1xuICAgIH1cblxuICAgIGNvbnN0IGRlZmF1bHRVc2VySWQgPSBnZXRVc2VySWREZWZhdWx0RnJvbUxvY2FsU3RvcmFnZSgpO1xuICAgIGlmIChkZWZhdWx0VXNlcklkKSB7XG4gICAgICByZXR1cm4gZGVmYXVsdFVzZXJJZDtcbiAgICB9XG5cbiAgICByZXR1cm4gc2V0VXNlcklkRGVmYXVsdEluTG9jYWxTdG9yYWdlKGBzcGlmZnktdXNlci1pZC0ke3V1aWQoKX1gKTtcbiAgfSwgW1xuICAgIGdldFVzZXJJZE92ZXJyaWRlRnJvbUxvY2FsU3RvcmFnZSxcbiAgICBnZXRVc2VySWREZWZhdWx0RnJvbUxvY2FsU3RvcmFnZSxcbiAgICBzZXRVc2VySWREZWZhdWx0SW5Mb2NhbFN0b3JhZ2UsXG4gIF0pO1xuXG4gIGNvbnN0IGlkZW50aWZ5VXNlciA9IHVzZUNhbGxiYWNrKGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICBpZiAoIWlzUmVhZHkpIHtcbiAgICAgIExvZ2dlci5sb2dXYXJuKFxuICAgICAgICBcIltVc2VySWRlbnRpdHlDb250ZXh0XSBDb250ZXh0IG5vdCByZWFkeSwgc2tpcHBpbmcgaWRlbnRpZnlVc2VyXCIsXG4gICAgICAgIHVuZGVmaW5lZFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgLy8gVGVtcG9yYXJpbHkgY29tbWVudGVkIG91dCB1bnRpbCBXaW5kb3dEYXRhTGF5ZXJTZXJ2aWNlIGlzIHJlc29sdmVkXG4gICAgICAvLyBjb25zdCBjZHBVc2VySWQgPSBXaW5kb3dEYXRhTGF5ZXJTZXJ2aWNlLmdldEdvb2dsZUFuYWx5dGljc0NsaWVudElkKCk7XG4gICAgICBjb25zdCBjZHBVc2VySWQgPSBcIlVOS05PV05fQ0RQX1VTRVJfSURcIjsgLy8gUGxhY2Vob2xkZXJcbiAgICAgIGNvbnN0IHVzZXJJZCA9IGdldFVzZXJJZE9yRGVmYXVsdCgpO1xuICAgICAgY29uc3QgdXNlckFnZW50RGV0YWlscyA9IGdldFVzZXJBZ2VudERldGFpbHMoKTtcblxuICAgICAgaWYgKCFjZHBVc2VySWQpIHtcbiAgICAgICAgTG9nZ2VyLmxvZ1dhcm4oXG4gICAgICAgICAgXCJbc3BpZmZ5LWFpXSBObyBHQSBDbGllbnQgSUQgZm91bmQsIHNraXBwaW5nIGlkZW50aWZ5VXNlclwiLFxuICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmlkZW50aWZ5VXNlcih1c2VySWQsIGNkcFVzZXJJZCwgdXNlckFnZW50RGV0YWlscyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIExvZ2dlci5sb2dFcnJvcihcIltzcGlmZnktYWldIEVycm9yIGlkZW50aWZ5aW5nIHVzZXJcIiwgZXJyb3IpO1xuICAgIH1cbiAgfSwgW2lzUmVhZHksIGdldFVzZXJJZE9yRGVmYXVsdF0pO1xuXG4gIGNvbnN0IHZhbHVlID0gdXNlTWVtbyhcbiAgICAoKSA9PiAoe1xuICAgICAgaWRlbnRpZnlVc2VyLFxuICAgICAgZ2V0VXNlcklkT3JEZWZhdWx0LFxuICAgICAgZ2V0VXNlcklkT3ZlcnJpZGVGcm9tTG9jYWxTdG9yYWdlLFxuICAgICAgZ2V0VXNlcklkRGVmYXVsdEZyb21Mb2NhbFN0b3JhZ2UsXG4gICAgICBzZXRVc2VySWREZWZhdWx0SW5Mb2NhbFN0b3JhZ2UsXG4gICAgICBzZXRVc2VySWRPdmVycmlkZUluTG9jYWxTdG9yYWdlLFxuICAgICAgY2xlYXJVc2VySWRPdmVycmlkZUluTG9jYWxTdG9yYWdlLFxuICAgICAgaXNSZWFkeSxcbiAgICB9KSxcbiAgICBbXG4gICAgICBpZGVudGlmeVVzZXIsXG4gICAgICBnZXRVc2VySWRPckRlZmF1bHQsXG4gICAgICBnZXRVc2VySWRPdmVycmlkZUZyb21Mb2NhbFN0b3JhZ2UsXG4gICAgICBnZXRVc2VySWREZWZhdWx0RnJvbUxvY2FsU3RvcmFnZSxcbiAgICAgIHNldFVzZXJJZERlZmF1bHRJbkxvY2FsU3RvcmFnZSxcbiAgICAgIHNldFVzZXJJZE92ZXJyaWRlSW5Mb2NhbFN0b3JhZ2UsXG4gICAgICBjbGVhclVzZXJJZE92ZXJyaWRlSW5Mb2NhbFN0b3JhZ2UsXG4gICAgICBpc1JlYWR5LFxuICAgIF1cbiAgKTtcblxuICByZXR1cm4gKFxuICAgIDxVc2VySWRlbnRpdHlDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXt2YWx1ZX0+XG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC9Vc2VySWRlbnRpdHlDb250ZXh0LlByb3ZpZGVyPlxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHVzZVVzZXJJZGVudGl0eSA9ICgpID0+IHtcbiAgY29uc3QgY29udGV4dCA9IHVzZUNvbnRleHQoVXNlcklkZW50aXR5Q29udGV4dCk7XG4gIGlmICghY29udGV4dCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIFwidXNlVXNlcklkZW50aXR5IG11c3QgYmUgdXNlZCB3aXRoaW4gYSBVc2VySWRlbnRpdHlQcm92aWRlclwiXG4gICAgKTtcbiAgfVxuICByZXR1cm4gY29udGV4dDtcbn07XG4iLCJpbXBvcnQgeyB1c2VTdGF0ZSwgdXNlQ2FsbGJhY2sgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZVVzZXJJZGVudGl0eSB9IGZyb20gXCJzcmMvY29udGV4dHMvdXNlcklkZW50aXR5Q29udGV4dFwiO1xuXG5leHBvcnQgY29uc3QgdXNlSWRlbnRpZnlVc2VyID0gKCkgPT4ge1xuICBjb25zdCB7IGlkZW50aWZ5VXNlciwgaXNSZWFkeSB9ID0gdXNlVXNlcklkZW50aXR5KCk7XG4gIGNvbnN0IFtsb2FkaW5nLCBzZXRMb2FkaW5nXSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgY29uc3QgW2Vycm9yLCBzZXRFcnJvcl0gPSB1c2VTdGF0ZTxFcnJvciB8IG51bGw+KG51bGwpO1xuXG4gIGNvbnN0IGV4ZWN1dGVJZGVudGlmeVVzZXIgPSB1c2VDYWxsYmFjayhhc3luYyAoKSA9PiB7XG4gICAgaWYgKCFpc1JlYWR5KSB7XG4gICAgICBzZXRFcnJvcihuZXcgRXJyb3IoXCJVc2VySWRlbnRpdHlDb250ZXh0IG5vdCByZWFkeS5cIikpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHNldExvYWRpbmcodHJ1ZSk7XG4gICAgc2V0RXJyb3IobnVsbCk7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgaWRlbnRpZnlVc2VyKCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBzZXRFcnJvcihcbiAgICAgICAgZXJyIGluc3RhbmNlb2YgRXJyb3JcbiAgICAgICAgICA/IGVyclxuICAgICAgICAgIDogbmV3IEVycm9yKFwiVW5rbm93biBlcnJvciBkdXJpbmcgdXNlciBpZGVudGlmaWNhdGlvbi5cIilcbiAgICAgICk7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHNldExvYWRpbmcoZmFsc2UpO1xuICAgIH1cbiAgfSwgW2lkZW50aWZ5VXNlciwgaXNSZWFkeV0pO1xuXG4gIHJldHVybiB7IGxvYWRpbmcsIGVycm9yLCBleGVjdXRlSWRlbnRpZnlVc2VyLCBpc1JlYWR5IH07XG59O1xuIiwiaW1wb3J0IHsgdXNlQXRvbVZhbHVlIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQgeyBPcmdTaG9ydE5hbWUgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVsc1wiO1xuaW1wb3J0IHsgb3JnU2hvcnROYW1lQXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuYWJzdHJhY3QgY2xhc3MgSW1hZ2VSZXNvbHZlciB7XG4gIGFic3RyYWN0IHJlc29sdmUodXJsOiBzdHJpbmcsIHNpemU6IG51bWJlcik6IHN0cmluZztcbn1cblxuY2xhc3MgTWVyY2hhbnRJbWFnZVJlc29sdmVyIHtcbiAgcHJpdmF0ZSBzdGF0aWMgaW1hZ2VSZXNvbHZlck1hcCA9IG5ldyBNYXA8c3RyaW5nLCBJbWFnZVJlc29sdmVyPigpO1xuXG4gIHByaXZhdGUgc3RhdGljIGxvYWRNYXBwaW5nKCkge1xuICAgIGlmICh0aGlzLmltYWdlUmVzb2x2ZXJNYXAuc2l6ZSA9PT0gMCkge1xuICAgICAgdGhpcy5pbWFnZVJlc29sdmVyTWFwLnNldChPcmdTaG9ydE5hbWUuU3BhbngsIG5ldyBTaG9waWZ5SW1hZ2VSZXNvbHZlcigpKTtcbiAgICAgIHRoaXMuaW1hZ2VSZXNvbHZlck1hcC5zZXQoXG4gICAgICAgIE9yZ1Nob3J0TmFtZS5TcGFueFN0YWdpbmcsXG4gICAgICAgIG5ldyBTaG9waWZ5SW1hZ2VSZXNvbHZlcigpXG4gICAgICApO1xuICAgICAgdGhpcy5pbWFnZVJlc29sdmVyTWFwLnNldChcbiAgICAgICAgT3JnU2hvcnROYW1lLlVuaXF1ZVZpbnRhZ2UsXG4gICAgICAgIG5ldyBTaG9waWZ5SW1hZ2VSZXNvbHZlcigpXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5pbWFnZVJlc29sdmVyTWFwO1xuICB9XG5cbiAgc3RhdGljIGdldChuYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5sb2FkTWFwcGluZygpLmdldChuYW1lKTtcbiAgfVxufVxuXG5jbGFzcyBTaG9waWZ5SW1hZ2VSZXNvbHZlciBleHRlbmRzIEltYWdlUmVzb2x2ZXIge1xuICByZXNvbHZlKHVybDogc3RyaW5nLCBzaXplOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IHBhdHRlcm4gPSAvX1xcZCt4XFwuanBnLztcbiAgICBjb25zdCB1cmxIYXNQcmVmaXggPSBwYXR0ZXJuLnRlc3QodXJsKTtcbiAgICBjb25zdCBuZXdTaXplUHJlZml4ID0gYF8ke3NpemV9eC5qcGdgO1xuICAgIGlmICh1cmxIYXNQcmVmaXgpIHtcbiAgICAgIHJldHVybiB1cmwucmVwbGFjZShwYXR0ZXJuLCBuZXdTaXplUHJlZml4KTtcbiAgICB9XG4gICAgcmV0dXJuIHVybC5yZXBsYWNlKFwiLmpwZ1wiLCBuZXdTaXplUHJlZml4KTtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgdXNlSW1hZ2VSZXNvbHZlciA9ICgpID0+IHtcbiAgY29uc3Qgb3JnU2hvcnROYW1lID0gdXNlQXRvbVZhbHVlKG9yZ1Nob3J0TmFtZUF0b20pO1xuICBjb25zdCByZXNvbHZlID0gKGltYWdlPzogc3RyaW5nLCBzaXplPzogbnVtYmVyKSA9PiB7XG4gICAgaWYgKGltYWdlICYmIHNpemUgJiYgb3JnU2hvcnROYW1lKSB7XG4gICAgICBjb25zdCBuZXdJbWFnZVBhdGggPSBNZXJjaGFudEltYWdlUmVzb2x2ZXIuZ2V0KG9yZ1Nob3J0TmFtZSk/LnJlc29sdmUoXG4gICAgICAgIGltYWdlLFxuICAgICAgICBzaXplXG4gICAgICApO1xuICAgICAgcmV0dXJuIG5ld0ltYWdlUGF0aCB8fCBpbWFnZTtcbiAgICB9XG4gICAgcmV0dXJuIGltYWdlO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgcmVzb2x2ZSxcbiAgfTtcbn07XG4iLCJpbXBvcnQgeyBSZWZPYmplY3QsIHVzZUVmZmVjdCwgdXNlU3RhdGUgfSBmcm9tICdyZWFjdCc7XG5cbi8vIGh0dHBzOi8vcmFzaWxiYWlkYXIubWVkaXVtLmNvbS90cmlnZ2VyLWV2ZW50LXdoZW4tZWxlbWVudC1lbnRlcnMtdmlld3BvcnQtdGhlLXJlYWN0LXdheS0xNjg1MDlkYTJlMjNcbmV4cG9ydCBjb25zdCB1c2VJbnRlcnNlY3Rpb24gPSAoZWxlbWVudDogUmVmT2JqZWN0PEhUTUxFbGVtZW50Piwgcm9vdE1hcmdpbjogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IFtpc1Zpc2libGUsIHNldElzVmlzaWJsZV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBjdXJyZW50ID0gZWxlbWVudD8uY3VycmVudDtcbiAgICBjb25zdCBvYnNlcnZlciA9IG5ldyBJbnRlcnNlY3Rpb25PYnNlcnZlcihcbiAgICAgIChbZW50cnldKSA9PiB7XG4gICAgICAgIHNldElzVmlzaWJsZShlbnRyeS5pc0ludGVyc2VjdGluZyk7XG4gICAgICB9LFxuICAgICAgeyByb290TWFyZ2luIH0sXG4gICAgKTtcblxuICAgIGlmIChjdXJyZW50KSB7XG4gICAgICBvYnNlcnZlcj8ub2JzZXJ2ZShjdXJyZW50KTtcbiAgICB9XG5cbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgaWYgKGN1cnJlbnQpIHtcbiAgICAgICAgb2JzZXJ2ZXIudW5vYnNlcnZlKGN1cnJlbnQpO1xuICAgICAgfVxuICAgIH07XG4gIH0sIFtdKTtcblxuICByZXR1cm4gaXNWaXNpYmxlO1xufTtcbiIsImltcG9ydCB7IHVzZVN0YXRlLCB1c2VFZmZlY3QgfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBjb25zdCB1c2VJc1NtYWxsU2NyZWVuID0gKCkgPT4ge1xuICBjb25zdCBbaXNTbWFsbCwgc2V0SXNTbWFsbF0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBtZWRpYVF1ZXJ5ID0gd2luZG93Lm1hdGNoTWVkaWEoJyhtYXgtd2lkdGg6IDQ3OXB4KScpO1xuXG4gICAgLy8gU2V0IGluaXRpYWwgdmFsdWVcbiAgICBzZXRJc1NtYWxsKG1lZGlhUXVlcnkubWF0Y2hlcyk7XG5cbiAgICAvLyBVcGRhdGUgc3RhdGUgd2hlbiB2aWV3cG9ydCBjaGFuZ2VzXG4gICAgY29uc3QgaGFuZGxlUmVzaXplID0gKGV2ZW50OiBNZWRpYVF1ZXJ5TGlzdEV2ZW50KSA9PiB7XG4gICAgICBzZXRJc1NtYWxsKGV2ZW50Lm1hdGNoZXMpO1xuICAgIH07XG5cbiAgICBtZWRpYVF1ZXJ5LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIGhhbmRsZVJlc2l6ZSk7XG5cbiAgICByZXR1cm4gKCkgPT4gbWVkaWFRdWVyeS5yZW1vdmVFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCBoYW5kbGVSZXNpemUpO1xuICB9LCBbXSk7XG5cbiAgcmV0dXJuIGlzU21hbGw7XG59O1xuIiwiaW1wb3J0IHsgdXNlU3RhdGUsIHVzZUVmZmVjdCwgdXNlQ2FsbGJhY2sgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7XG4gIHVzZUxvY2FsU3RvcmFnZSxcbiAgTG9jYWxTdG9yYWdlS2V5cyxcbn0gZnJvbSBcIi4uL2NvbnRleHRzL2xvY2FsU3RvcmFnZUNvbnRleHRcIjtcbmltcG9ydCB7IExvY2FsU3RvcmFnZUV2ZW50TGlzdGVuZXIgfSBmcm9tIFwiLi4vYXBwbGljYXRpb24vbW9kZWxzL2xvY2FsU3RvcmFnZUV2ZW50TGlzdGVuZXJcIjtcblxuLy8gUmVhY3RpdmUgbG9jYWxTdG9yYWdlIHZhbHVlIGhvb2tcbmV4cG9ydCBjb25zdCB1c2VMb2NhbFN0b3JhZ2VWYWx1ZSA9IChrZXk6IHN0cmluZykgPT4ge1xuICBjb25zdCB7IGdldEl0ZW0sIHNldEl0ZW0sIGF0dGFjaExpc3RlbmVyLCBkZXRhY2hMaXN0ZW5lciB9ID1cbiAgICB1c2VMb2NhbFN0b3JhZ2UoKTtcbiAgY29uc3QgW3ZhbHVlLCBzZXRWYWx1ZV0gPSB1c2VTdGF0ZTxzdHJpbmcgfCBudWxsPigoKSA9PiBnZXRJdGVtKGtleSkpO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgY29uc3QgbGlzdGVuZXI6IExvY2FsU3RvcmFnZUV2ZW50TGlzdGVuZXIgPSB7XG4gICAgICBzdG9yYWdlS2V5OiBrZXksXG4gICAgICBsaXN0ZW5lcjogKGV2ZW50OiBTdG9yYWdlRXZlbnQpID0+IHtcbiAgICAgICAgc2V0VmFsdWUoZXZlbnQubmV3VmFsdWUpO1xuICAgICAgfSxcbiAgICB9O1xuXG4gICAgYXR0YWNoTGlzdGVuZXIobGlzdGVuZXIpO1xuICAgIHJldHVybiAoKSA9PiBkZXRhY2hMaXN0ZW5lcihsaXN0ZW5lcik7XG4gIH0sIFtrZXksIGF0dGFjaExpc3RlbmVyLCBkZXRhY2hMaXN0ZW5lcl0pO1xuXG4gIGNvbnN0IHVwZGF0ZVZhbHVlID0gdXNlQ2FsbGJhY2soXG4gICAgKG5ld1ZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgIHNldEl0ZW0oa2V5LCBuZXdWYWx1ZSk7XG4gICAgICBzZXRWYWx1ZShuZXdWYWx1ZSk7XG4gICAgfSxcbiAgICBba2V5LCBzZXRJdGVtXVxuICApO1xuXG4gIHJldHVybiB7IHZhbHVlLCBzZXRWYWx1ZTogdXBkYXRlVmFsdWUgfTtcbn07XG5cbi8vIEZlYXR1cmUgZmxhZyBob29rIGZvciBTcGlmZnlcbmV4cG9ydCBjb25zdCB1c2VTcGlmZnlGZWF0dXJlRmxhZyA9ICgpID0+IHtcbiAgY29uc3QgeyBzZXRTcGlmZnlPbkZlYXR1cmVGbGFnIH0gPSB1c2VMb2NhbFN0b3JhZ2UoKTtcbiAgY29uc3QgeyB2YWx1ZSB9ID0gdXNlTG9jYWxTdG9yYWdlVmFsdWUoTG9jYWxTdG9yYWdlS2V5cy5TcGlmZnlPbk92ZXJyaWRlKTtcblxuICBjb25zdCBzZXRGbGFnID0gdXNlQ2FsbGJhY2soXG4gICAgKGZsYWc6IGJvb2xlYW4gfCBudWxsKSA9PiB7XG4gICAgICBzZXRTcGlmZnlPbkZlYXR1cmVGbGFnKGZsYWcpO1xuICAgIH0sXG4gICAgW3NldFNwaWZmeU9uRmVhdHVyZUZsYWddXG4gICk7XG5cbiAgcmV0dXJuIHtcbiAgICB2YWx1ZTogdmFsdWUgPT09IFwidHJ1ZVwiID8gdHJ1ZSA6IHZhbHVlID09PSBcImZhbHNlXCIgPyBmYWxzZSA6IG51bGwsXG4gICAgc2V0RmxhZyxcbiAgfTtcbn07XG5cbi8vIEZlYXR1cmUgZmxhZyBob29rIGZvciBFbnZpdmVcbmV4cG9ydCBjb25zdCB1c2VFbnZpdmVGZWF0dXJlRmxhZyA9ICgpID0+IHtcbiAgY29uc3QgeyBzZXRJdGVtLCBnZXRJdGVtIH0gPSB1c2VMb2NhbFN0b3JhZ2UoKTtcbiAgY29uc3QgeyB2YWx1ZSB9ID0gdXNlTG9jYWxTdG9yYWdlVmFsdWUoTG9jYWxTdG9yYWdlS2V5cy5FbnZpdmVPbk92ZXJyaWRlKTtcblxuICBjb25zdCBzZXRGbGFnID0gdXNlQ2FsbGJhY2soXG4gICAgKGZsYWc6IGJvb2xlYW4gfCBudWxsKSA9PiB7XG4gICAgICBpZiAoZmxhZyA9PT0gdHJ1ZSkge1xuICAgICAgICBzZXRJdGVtKExvY2FsU3RvcmFnZUtleXMuRW52aXZlT25PdmVycmlkZSwgXCJ0cnVlXCIpO1xuICAgICAgfSBlbHNlIGlmIChmbGFnID09PSBmYWxzZSkge1xuICAgICAgICBzZXRJdGVtKExvY2FsU3RvcmFnZUtleXMuRW52aXZlT25PdmVycmlkZSwgXCJmYWxzZVwiKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtzZXRJdGVtXVxuICApO1xuXG4gIHJldHVybiB7XG4gICAgdmFsdWU6IHZhbHVlID09PSBcInRydWVcIiA/IHRydWUgOiB2YWx1ZSA9PT0gXCJmYWxzZVwiID8gZmFsc2UgOiBudWxsLFxuICAgIHNldEZsYWcsXG4gIH07XG59O1xuXG4vLyBTdG9yYWdlIGxpc3RlbmVyIGhvb2tcbmV4cG9ydCBjb25zdCB1c2VMb2NhbFN0b3JhZ2VMaXN0ZW5lciA9IChcbiAga2V5OiBzdHJpbmcsXG4gIGNhbGxiYWNrOiAoZXZlbnQ6IFN0b3JhZ2VFdmVudCkgPT4gdm9pZFxuKSA9PiB7XG4gIGNvbnN0IHsgYXR0YWNoTGlzdGVuZXIsIGRldGFjaExpc3RlbmVyIH0gPSB1c2VMb2NhbFN0b3JhZ2UoKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGNvbnN0IGxpc3RlbmVyOiBMb2NhbFN0b3JhZ2VFdmVudExpc3RlbmVyID0ge1xuICAgICAgc3RvcmFnZUtleToga2V5LFxuICAgICAgbGlzdGVuZXI6IGNhbGxiYWNrLFxuICAgIH07XG4gICAgYXR0YWNoTGlzdGVuZXIobGlzdGVuZXIpO1xuICAgIHJldHVybiAoKSA9PiBkZXRhY2hMaXN0ZW5lcihsaXN0ZW5lcik7XG4gIH0sIFtrZXksIGNhbGxiYWNrLCBhdHRhY2hMaXN0ZW5lciwgZGV0YWNoTGlzdGVuZXJdKTtcbn07XG4iLCJpbXBvcnQgeyBNZXNzYWdlLCBNZXNzYWdlUm9sZSwgTWVzc2FnZVR5cGUgfSBmcm9tICdzcmMvYXBwbGljYXRpb24vbW9kZWxzJztcblxudHlwZSBNZXNzYWdlRmluZGVyID0ge1xuICBtc2dzOiBNZXNzYWdlW11bXTtcbiAgdHlwZT86IE1lc3NhZ2VUeXBlO1xuICByb2xlPzogTWVzc2FnZVJvbGU7XG59O1xuXG5leHBvcnQgY29uc3QgdXNlTWVzc2FnZUZpbHRlciA9ICgpID0+IHtcbiAgY29uc3QgZmluZE1lc3NhZ2VJbmRleCA9ICh7IG1zZ3MsIHR5cGUsIHJvbGUgfTogTWVzc2FnZUZpbmRlcikgPT4ge1xuICAgIGxldCBsYXN0SW5kZXggPSAtMTtcbiAgICBtc2dzLmZvckVhY2goKHN1YkFycmF5LCBpbmRleCkgPT4ge1xuICAgICAgc3ViQXJyYXkuZm9yRWFjaCgob2JqKSA9PiB7XG4gICAgICAgIGlmIChvYmoudHlwZSA9PT0gdHlwZSB8fCBvYmoucm9sZSA9PT0gcm9sZSkgbGFzdEluZGV4ID0gaW5kZXg7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gbGFzdEluZGV4O1xuICB9O1xuXG4gIGNvbnN0IHJlbW92ZVByZXZpb3VzRGlzY3Vzc2lvbnMgPSAobXNnczogTWVzc2FnZVtdW10sIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICBpZiAoaW5kZXggPiAtMSkge1xuICAgICAgY29uc3QgbGFzdE1lc3NhZ2VzID0gbXNncy5zbGljZShpbmRleCk7XG4gICAgICByZXR1cm4gbGFzdE1lc3NhZ2VzLmxlbmd0aCA+IDAgPyBsYXN0TWVzc2FnZXMgOiBtc2dzO1xuICAgIH1cbiAgICByZXR1cm4gbXNncztcbiAgfTtcblxuICBjb25zdCBnZXRGaWx0ZXJlZE1lc3NhZ2VzID0gKG1zZ3M6IE1lc3NhZ2VbXVtdLCBza2lwRmlsdGVyPzogYm9vbGVhbikgPT4ge1xuICAgIGNvbnN0IG1lc3NhZ2VNYXAgPSBtc2dzLnJlZHVjZShcbiAgICAgIChhY2MsIG1zZykgPT4ge1xuICAgICAgICBhY2NbbXNnWzBdLmlkXSA9IG1zZztcbiAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgIH0sXG4gICAgICB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBNZXNzYWdlW10+LFxuICAgICk7XG4gICAgY29uc3QgZGVkdXBsaWNhdGVkTXNncyA9IE9iamVjdC52YWx1ZXMobWVzc2FnZU1hcCk7XG4gICAgaWYgKCFza2lwRmlsdGVyKSB7XG4gICAgICBjb25zdCBpZHggPSBmaW5kTWVzc2FnZUluZGV4KHsgbXNnczogZGVkdXBsaWNhdGVkTXNncywgdHlwZTogTWVzc2FnZVR5cGUuU2VwYXJhdG9yIH0pO1xuICAgICAgcmV0dXJuIHJlbW92ZVByZXZpb3VzRGlzY3Vzc2lvbnMoZGVkdXBsaWNhdGVkTXNncywgaWR4KTtcbiAgICB9XG4gICAgcmV0dXJuIGRlZHVwbGljYXRlZE1zZ3M7XG4gIH07XG5cbiAgcmV0dXJuIHtcbiAgICBmaW5kTWVzc2FnZUluZGV4LFxuICAgIHJlbW92ZVByZXZpb3VzRGlzY3Vzc2lvbnMsXG4gICAgZ2V0RmlsdGVyZWRNZXNzYWdlcyxcbiAgfTtcbn07XG4iLCJpbXBvcnQgeyB1c2VFZmZlY3QgfSBmcm9tIFwicmVhY3RcIjtcblxuZXhwb3J0IGNvbnN0IHVzZU1lc3NhZ2VTY3JvbGxPYnNlcnZlciA9IChcbiAgICBib3hSZWY6IFJlYWN0LlJlZk9iamVjdDxIVE1MRGl2RWxlbWVudD4sIFxuICAgIHNjcm9sbFJlZjogUmVhY3QuUmVmT2JqZWN0PEhUTUxEaXZFbGVtZW50PiwgXG4gICAgb25TY3JvbGxDaGFuZ2U6IChwb3NpdGlvbjogbnVtYmVyKSA9PiB2b2lkXG4pID0+IHtcblxuICAgIGNvbnN0IGNhbGN1bGF0ZVNjcm9sbEhlaWdodCA9ICgpID0+IHtcbiAgICAgIGNvbnN0IGJveEhlaWdodCA9IGJveFJlZj8uY3VycmVudD8uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0IHx8IDBcbiAgICAgIGNvbnN0IHNjcm9sbEhlaWdodCA9IHNjcm9sbFJlZj8uY3VycmVudD8uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0IHx8IDBcbiAgICAgIHJldHVybiBib3hIZWlnaHQgLSBzY3JvbGxIZWlnaHRcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVTdGF0ZSA9ICgpID0+IHtcbiAgICAgIGNvbnN0IHNjcm9sbEhlaWdodCA9IGNhbGN1bGF0ZVNjcm9sbEhlaWdodCgpXG4gICAgICBpZiAoc2Nyb2xsSGVpZ2h0ID4gMCkge1xuICAgICAgICBvblNjcm9sbENoYW5nZShzY3JvbGxIZWlnaHQpXG4gICAgICB9XG4gICAgfVxuXG4gICAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAgIGxldCBib3hSTyA9IG51bGw7XG4gICAgICBsZXQgc2Nyb2xsUk8gPSBudWxsO1xuXG4gICAgICBpZiAoc2Nyb2xsUmVmPy5jdXJyZW50KSB7XG4gICAgICAgIGJveFJPID0gbmV3IFJlc2l6ZU9ic2VydmVyKHVwZGF0ZVN0YXRlKTtcbiAgICAgICAgYm94Uk8ub2JzZXJ2ZShzY3JvbGxSZWY/LmN1cnJlbnQpO1xuICAgICAgfVxuICAgICAgXG4gICAgICBpZiAoYm94UmVmPy5jdXJyZW50KSB7XG4gICAgICAgIHNjcm9sbFJPID0gbmV3IFJlc2l6ZU9ic2VydmVyKHVwZGF0ZVN0YXRlKTtcbiAgICAgICAgc2Nyb2xsUk8ub2JzZXJ2ZShib3hSZWY/LmN1cnJlbnQpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICBpZiAoc2Nyb2xsUmVmPy5jdXJyZW50ICYmIGJveFJPKSB7XG4gICAgICAgICAgYm94Uk8udW5vYnNlcnZlKHNjcm9sbFJlZj8uY3VycmVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2Nyb2xsUk8gJiYgYm94UmVmPy5jdXJyZW50KSB7XG4gICAgICAgICAgc2Nyb2xsUk8/LnVub2JzZXJ2ZShib3hSZWY/LmN1cnJlbnQpXG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfSwgW10pO1xuXG59IiwiaW1wb3J0IFJlYWN0LCB7IGNyZWF0ZUNvbnRleHQsIHVzZUNvbnRleHQsIHVzZU1lbW8sIFJlYWN0Tm9kZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgT3JnQ29uZmlnRmVhdHVyZUdhdGUgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9hcGkvb3JnQ29uZmlnUmVzdWx0c1wiO1xuaW1wb3J0IHsgRmVhdHVyZUdhdGVzIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvZmVhdHVyZUdhdGVzXCI7XG5pbXBvcnQgTG9nZ2VyIGZyb20gXCJzcmMvYXBwbGljYXRpb24vbG9nZ2luZy9sb2dnZXJcIjtcblxuLy8gVGhpcyBpcyB0aGUgY2xhc3MgdGhhdCB3YXMgcHJldmlvdXNseSBpbXBsaWNpdGx5IHVzZWQgb3IgZGVmaW5lZCBlbHNld2hlcmVcbmNsYXNzIEZlYXR1cmVGbGFnU2VydmljZSB7XG4gIHByaXZhdGUgZmVhdHVyZUdhdGVzOiBPcmdDb25maWdGZWF0dXJlR2F0ZVtdO1xuXG4gIGNvbnN0cnVjdG9yKGZlYXR1cmVHYXRlczogT3JnQ29uZmlnRmVhdHVyZUdhdGVbXSkge1xuICAgIHRoaXMuZmVhdHVyZUdhdGVzID0gZmVhdHVyZUdhdGVzO1xuICB9XG5cbiAgaXNGZWF0dXJlR2F0ZUVuYWJsZWQgPSAoZmVhdHVyZUdhdGU6IEZlYXR1cmVHYXRlcyk6IGJvb2xlYW4gPT4ge1xuICAgIGNvbnN0IGdhdGVWYWx1ZSA9IHRoaXMuZmVhdHVyZUdhdGVzLmZpbmQoXG4gICAgICAoZ2F0ZSkgPT4gZ2F0ZS5uYW1lID09PSBmZWF0dXJlR2F0ZVxuICAgICk7XG5cbiAgICAvLyBUT0RPOiBBZGQgbG9naWMgZm9yIG92ZXJyaWRlcyAocXVlcnkgcGFyYW1zLCB3aW5kb3csIHN0b3JlZCkgaWYgbmVlZGVkLCBzaW1pbGFyIHRvIHRoZSBvbGQgRmVhdHVyZUZsYWdDb250ZXh0LnRzeFxuICAgIC8vIEZvciBub3csIGRpcmVjdCB2YWx1ZSBmcm9tIGNvbmZpZyBpcyB1c2VkLlxuXG4gICAgaWYgKGdhdGVWYWx1ZSA9PSBudWxsIHx8IGdhdGVWYWx1ZS52YWx1ZSA9PSBudWxsKSB7XG4gICAgICBMb2dnZXIubG9nRGVidWcoXG4gICAgICAgIGBbc3BpZmZ5LWFpXSBpc0ZlYXR1cmVHYXRlRW5hYmxlZCBmZWF0dXJlR2F0ZToke2ZlYXR1cmVHYXRlfSB2YWx1ZSBpcyB1bmRlZmluZWQgLSByZXR1cm5pbmcgZmFsc2VgXG4gICAgICApO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gZ2F0ZVZhbHVlLnZhbHVlO1xuICB9O1xuXG4gIGlzQ2xpZW50U2Vzc2lvbkVuYWJsZWQgPSAoKTogYm9vbGVhbiA9PiB7XG4gICAgY29uc3QgaXNFbmFibGVkID1cbiAgICAgIHRoaXMuZmVhdHVyZUdhdGVzLmZpbHRlcihcbiAgICAgICAgKGdhdGUpID0+XG4gICAgICAgICAgZ2F0ZS5uYW1lID09PSBGZWF0dXJlR2F0ZXMuSXNDbGllbnRTZXNzaW9uRW5hYmxlZCAmJlxuICAgICAgICAgIGdhdGUudmFsdWUgPT09IHRydWVcbiAgICAgICkubGVuZ3RoID4gMDtcbiAgICByZXR1cm4gaXNFbmFibGVkO1xuICB9O1xuXG4gIGdldEZlYXR1cmVGbGFncyA9ICgpOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiA9PiB7XG4gICAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIE9iamVjdC52YWx1ZXMoRmVhdHVyZUdhdGVzKS5tYXAoKGZlYXR1cmVHYXRlOiBGZWF0dXJlR2F0ZXMpID0+IFtcbiAgICAgICAgZmVhdHVyZUdhdGUsXG4gICAgICAgIHRoaXMuaXNGZWF0dXJlR2F0ZUVuYWJsZWQoZmVhdHVyZUdhdGUpLFxuICAgICAgXSlcbiAgICApO1xuICB9O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZlYXR1cmVGbGFnQ29udGV4dFR5cGUge1xuICBmZWF0dXJlRmxhZ1NlcnZpY2U6IEZlYXR1cmVGbGFnU2VydmljZSB8IHVuZGVmaW5lZDtcbn1cblxuY29uc3QgRmVhdHVyZUZsYWdTZXJ2aWNlQ29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8XG4gIEZlYXR1cmVGbGFnQ29udGV4dFR5cGUgfCB1bmRlZmluZWRcbj4odW5kZWZpbmVkKTtcblxuaW50ZXJmYWNlIEZlYXR1cmVGbGFnU2VydmljZVByb3ZpZGVyUHJvcHMge1xuICBmZWF0dXJlR2F0ZXM6IE9yZ0NvbmZpZ0ZlYXR1cmVHYXRlW107XG4gIGNoaWxkcmVuOiBSZWFjdE5vZGU7XG59XG5cbmV4cG9ydCBjb25zdCBGZWF0dXJlRmxhZ1NlcnZpY2VQcm92aWRlcjogUmVhY3QuRkM8XG4gIEZlYXR1cmVGbGFnU2VydmljZVByb3ZpZGVyUHJvcHNcbj4gPSAoeyBmZWF0dXJlR2F0ZXMsIGNoaWxkcmVuIH0pID0+IHtcbiAgY29uc3QgZmVhdHVyZUZsYWdTZXJ2aWNlID0gdXNlTWVtbyhcbiAgICAoKSA9PiBuZXcgRmVhdHVyZUZsYWdTZXJ2aWNlKGZlYXR1cmVHYXRlcyksXG4gICAgW2ZlYXR1cmVHYXRlc11cbiAgKTtcblxuICByZXR1cm4gKFxuICAgIDxGZWF0dXJlRmxhZ1NlcnZpY2VDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXt7IGZlYXR1cmVGbGFnU2VydmljZSB9fT5cbiAgICAgIHtjaGlsZHJlbn1cbiAgICA8L0ZlYXR1cmVGbGFnU2VydmljZUNvbnRleHQuUHJvdmlkZXI+XG4gICk7XG59O1xuXG5leHBvcnQgY29uc3QgdXNlRmVhdHVyZUZsYWdTZXJ2aWNlID0gKCkgPT4ge1xuICBjb25zdCBjb250ZXh0ID0gdXNlQ29udGV4dChGZWF0dXJlRmxhZ1NlcnZpY2VDb250ZXh0KTtcbiAgaWYgKGNvbnRleHQgPT09IHVuZGVmaW5lZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIFwidXNlRmVhdHVyZUZsYWdTZXJ2aWNlIG11c3QgYmUgdXNlZCB3aXRoaW4gYSBGZWF0dXJlRmxhZ1NlcnZpY2VQcm92aWRlclwiXG4gICAgKTtcbiAgfVxuICByZXR1cm4gY29udGV4dDtcbn07XG4iLCJpbXBvcnQgUmVhY3QsIHtcbiAgY3JlYXRlQ29udGV4dCxcbiAgdXNlQ29udGV4dCxcbiAgUmVhY3ROb2RlLFxuICB1c2VTdGF0ZSxcbiAgdXNlRWZmZWN0LFxuICB1c2VNZW1vLFxufSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZUF0b21WYWx1ZSwgdXNlU2V0QXRvbSB9IGZyb20gXCJqb3RhaVwiO1xuaW1wb3J0IHtcbiAgQmFzaWNPcmdJbmZvVHlwZSxcbiAgZ2V0T3JnSW5mbyxcbn0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvc3VwcG9ydGVkT3Jnc1wiO1xuaW1wb3J0IHsgdXNlQ29sb3JzQW5kRnJvbnRlbmRDb25maWcgfSBmcm9tIFwic3JjL2hvb2tzL3VzZUdyYXBoUUxDb25maWdcIjtcbmltcG9ydCB7IG9yZ1Nob3J0TmFtZUF0b20gfSBmcm9tIFwic3JjL2F0b21zL2Vudml2ZS9lbnZpdmVDb25maWdcIjtcbmltcG9ydCB7IGdldEF0b21TdG9yZSB9IGZyb20gXCJzcmMvYXRvbXMvYXRvbVN0b3JlL2F0b21TdG9yZVwiOyAvLyBJbXBvcnQgZ2V0QXRvbVN0b3JlXG5pbXBvcnQgeyBvcmdJZEF0b20gfSBmcm9tIFwic3JjL2F0b21zL29yZy9ncmFwaHFsQ29uZmlnXCI7IC8vIEltcG9ydCBuZXcgYXRvbXNcbmltcG9ydCB7IG5ld09yZ0NvbmZpZ0F0b20gfSBmcm9tIFwic3JjL2F0b21zL29yZy9uZXdPcmdDb25maWdBdG9tXCI7IC8vIEltcG9ydCBuZXdPcmdDb25maWdBdG9tXG5pbXBvcnQgeyBPcmdDb25maWdGZWF0dXJlR2F0ZSB9IGZyb20gXCJzcmMvYXBwbGljYXRpb24vbW9kZWxzL2FwaS9vcmdDb25maWdSZXN1bHRzXCI7IC8vIEltcG9ydCBPcmdDb25maWdGZWF0dXJlR2F0ZVxuaW1wb3J0IHsgRmVhdHVyZUZsYWdTZXJ2aWNlUHJvdmlkZXIgfSBmcm9tIFwic3JjL2NvbnRleHRzL2ZlYXR1cmVGbGFnU2VydmljZUNvbnRleHRcIjsgLy8gSW1wb3J0IEZlYXR1cmVGbGFnU2VydmljZVByb3ZpZGVyXG5pbXBvcnQgeyBDb2xvcnNDb25maWdSZXNwb25zZSwgRnJvbnRlbmRDb25maWdSZXNwb25zZSB9IGZyb20gXCIuL2dyYXBocWxDb250ZXh0XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmV3T3JnQ29uZmlnQ29udGV4dFR5cGUge1xuICBjb21iaW5lZENvbmZpZz86XG4gICAgfCAoQmFzaWNPcmdJbmZvVHlwZSAmIHtcbiAgICAgICAgY29sb3JzQ29uZmlnPzogQ29sb3JzQ29uZmlnUmVzcG9uc2U7XG4gICAgICAgIGZyb250ZW5kQ29uZmlnPzogRnJvbnRlbmRDb25maWdSZXNwb25zZTtcbiAgICAgIH0pXG4gICAgfCBudWxsO1xuICBsb2FkaW5nOiBib29sZWFuO1xuICBlcnJvcjogRXJyb3IgfCBudWxsO1xufVxuXG5jb25zdCBOZXdPcmdDb25maWdDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxOZXdPcmdDb25maWdDb250ZXh0VHlwZSB8IHVuZGVmaW5lZD4oXG4gIHVuZGVmaW5lZFxuKTtcblxuaW50ZXJmYWNlIE5ld09yZ0NvbmZpZ1Byb3ZpZGVyUHJvcHMge1xuICBjaGlsZHJlbjogUmVhY3ROb2RlO1xufVxuXG5leHBvcnQgY29uc3QgTmV3T3JnQ29uZmlnUHJvdmlkZXI6IFJlYWN0LkZDPE5ld09yZ0NvbmZpZ1Byb3ZpZGVyUHJvcHM+ID0gKHtcbiAgY2hpbGRyZW4sXG59KSA9PiB7XG4gIGNvbnN0IFtvbGRDb25maWcsIHNldE9sZENvbmZpZ10gPSB1c2VTdGF0ZTxCYXNpY09yZ0luZm9UeXBlIHwgdW5kZWZpbmVkPigpO1xuICBjb25zdCBvcmdTaG9ydE5hbWUgPSB1c2VBdG9tVmFsdWUob3JnU2hvcnROYW1lQXRvbSk7XG4gIGNvbnN0IHNldE5ld09yZ0NvbmZpZyA9IHVzZVNldEF0b20obmV3T3JnQ29uZmlnQXRvbSk7XG5cbiAgY29uc3QgeyBkYXRhOiBuZXdDb25maWcsIGxvYWRpbmcsIGVycm9yIH0gPSB1c2VDb2xvcnNBbmRGcm9udGVuZENvbmZpZygpO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKG9yZ1Nob3J0TmFtZSkge1xuICAgICAgZ2V0T3JnSW5mbyhvcmdTaG9ydE5hbWUpLnRoZW4oc2V0T2xkQ29uZmlnKTtcbiAgICB9XG4gIH0sIFtvcmdTaG9ydE5hbWVdKTtcblxuICBjb25zdCBjb21iaW5lZENvbmZpZyA9IHVzZU1lbW8oKCkgPT4ge1xuICAgIGlmICghb2xkQ29uZmlnIHx8ICFuZXdDb25maWcpIHJldHVybiBudWxsO1xuICAgIHJldHVybiB7IC4uLm9sZENvbmZpZywgLi4ubmV3Q29uZmlnIH07XG4gIH0sIFtvbGRDb25maWcsIG5ld0NvbmZpZ10pO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgY29uc3QgYXRvbVN0b3JlID0gZ2V0QXRvbVN0b3JlKCk7XG4gICAgaWYgKGNvbWJpbmVkQ29uZmlnKSB7XG4gICAgICAvLyBUT0RPOiBSZXBsYWNlIHdpdGggYWN0dWFsIG9yZ0lkIHdoZW4gYXZhaWxhYmxlIGluIGNvbWJpbmVkQ29uZmlnXG4gICAgICBhdG9tU3RvcmUuc2V0KG9yZ0lkQXRvbSwgXCJtb2NrLW9yZy1pZFwiKTtcblxuICAgICAgc2V0TmV3T3JnQ29uZmlnKGNvbWJpbmVkQ29uZmlnKTtcbiAgICB9XG4gIH0sIFtjb21iaW5lZENvbmZpZywgc2V0TmV3T3JnQ29uZmlnXSk7XG5cbiAgY29uc3QgY29udGV4dFZhbHVlID0gdXNlTWVtbygoKSA9PiB7XG4gICAgaWYgKCFvcmdTaG9ydE5hbWUgfHwgKGxvYWRpbmcgJiYgIW9sZENvbmZpZykpIHtcbiAgICAgIHJldHVybiB7IGNvbWJpbmVkQ29uZmlnOiBudWxsLCBsb2FkaW5nOiB0cnVlLCBlcnJvcjogbnVsbCB9O1xuICAgIH1cblxuICAgIGlmIChlcnJvcikge1xuICAgICAgcmV0dXJuIHsgY29tYmluZWRDb25maWc6IG51bGwsIGxvYWRpbmc6IGZhbHNlLCBlcnJvciB9O1xuICAgIH1cblxuICAgIHJldHVybiB7IGNvbWJpbmVkQ29uZmlnLCBsb2FkaW5nOiBmYWxzZSwgZXJyb3I6IG51bGwgfTtcbiAgfSwgW29yZ1Nob3J0TmFtZSwgbG9hZGluZywgZXJyb3IsIG9sZENvbmZpZywgY29tYmluZWRDb25maWddKTtcblxuICAvLyBUT0RPOiBQcm92aWRlIGFjdHVhbCBmZWF0dXJlR2F0ZXMgd2hlbiBhdmFpbGFibGUgaW4gY29tYmluZWRDb25maWdcbiAgY29uc3QgZmVhdHVyZUdhdGVzOiBPcmdDb25maWdGZWF0dXJlR2F0ZVtdID0gW107XG5cbiAgcmV0dXJuIChcbiAgICA8TmV3T3JnQ29uZmlnQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17Y29udGV4dFZhbHVlfT5cbiAgICAgIDxGZWF0dXJlRmxhZ1NlcnZpY2VQcm92aWRlciBmZWF0dXJlR2F0ZXM9e2ZlYXR1cmVHYXRlc30+XG4gICAgICAgIHtjaGlsZHJlbn1cbiAgICAgIDwvRmVhdHVyZUZsYWdTZXJ2aWNlUHJvdmlkZXI+XG4gICAgPC9OZXdPcmdDb25maWdDb250ZXh0LlByb3ZpZGVyPlxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHVzZU5ld09yZ0NvbmZpZ0NvbnRleHQgPSAoKSA9PiB7XG4gIGNvbnN0IGNvbnRleHQgPSB1c2VDb250ZXh0KE5ld09yZ0NvbmZpZ0NvbnRleHQpO1xuICBpZiAoY29udGV4dCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgXCJ1c2VOZXdPcmdDb25maWdDb250ZXh0IG11c3QgYmUgdXNlZCB3aXRoaW4gYSBOZXdPcmdDb25maWdQcm92aWRlclwiXG4gICAgKTtcbiAgfVxuICByZXR1cm4gY29udGV4dDtcbn07XG4iLCJpbXBvcnQgeyB1c2VOZXdPcmdDb25maWdDb250ZXh0IH0gZnJvbSBcInNyYy9jb250ZXh0cy9uZXdPcmdDb25maWdDb250ZXh0XCI7XG5cbmV4cG9ydCBjb25zdCB1c2VOZXdPcmdDb25maWcgPSAoKSA9PiB7XG4gIGNvbnN0IHsgY29tYmluZWRDb25maWcsIGxvYWRpbmcsIGVycm9yIH0gPSB1c2VOZXdPcmdDb25maWdDb250ZXh0KCk7XG5cbiAgcmV0dXJuIHsgLi4uY29tYmluZWRDb25maWcsIGxvYWRpbmcsIGVycm9yIH07XG59O1xuIiwiaW1wb3J0IHtcbiAgUExQQXR0cmlidXRlQ2F0ZWdvcnksXG4gIFVzZXJFdmVudENhdGVnb3J5LFxufSBmcm9tIFwiQHNwaWZmeS1haS9jb21tZXJjZS1hcGktY2xpZW50XCI7XG5pbXBvcnQgeyBTZWFyY2hSZXN1bHQgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9hcGkvc2VhcmNoXCI7XG5pbXBvcnQgeyBVc2VyRXZlbnQsIFZhcmlhbnRJbmZvIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHNcIjtcbmltcG9ydCB7IHY0IGFzIHV1aWQgfSBmcm9tIFwidXVpZFwiO1xuXG5leHBvcnQgY29uc3QgaXNFbGVtZW50UGFydGlhbGx5VmlzaWJsZSA9IChlbD86IEhUTUxEaXZFbGVtZW50IHwgbnVsbCkgPT4ge1xuICBpZiAoIWVsKSByZXR1cm4gZmFsc2U7XG5cbiAgY29uc3QgcmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICBjb25zdCB3aW5kb3dIZWlnaHQgPVxuICAgIHdpbmRvdy5pbm5lckhlaWdodCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICBjb25zdCB3aW5kb3dXaWR0aCA9IHdpbmRvdy5pbm5lcldpZHRoIHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRXaWR0aDtcbiAgY29uc3QgdmVydGljYWxseVZpc2libGUgPVxuICAgIE1hdGgucm91bmQocmVjdC50b3ApIDwgd2luZG93SGVpZ2h0ICYmIE1hdGgucm91bmQocmVjdC5ib3R0b20pID4gMDtcbiAgY29uc3QgaG9yaXpvbnRhbGx5VmlzaWJsZSA9XG4gICAgTWF0aC5yb3VuZChyZWN0LmxlZnQpIDwgd2luZG93V2lkdGggJiYgTWF0aC5yb3VuZChyZWN0LnJpZ2h0KSA+IDA7XG4gIHJldHVybiB2ZXJ0aWNhbGx5VmlzaWJsZSAmJiBob3Jpem9udGFsbHlWaXNpYmxlO1xufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZUFwcExvYWRlZEV2ZW50ID0gKCk6IFVzZXJFdmVudCA9PiAoe1xuICBldmVudElkOiB1dWlkKCksXG4gIGNyZWF0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICBjYXRlZ29yeTogVXNlckV2ZW50Q2F0ZWdvcnkuQXBwTG9hZGVkLFxufSk7XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVWaXNpdFVzZXJFdmVudCA9ICh7XG4gIHZhcmlhbnRJbmZvLFxufToge1xuICB2YXJpYW50SW5mbzogVmFyaWFudEluZm87XG59KTogVXNlckV2ZW50IHwgdW5kZWZpbmVkID0+IHtcbiAgLy8gdGhpcyBpcyBhIHBkcCB2aXNpdCBldmVudFxuICBpZiAodmFyaWFudEluZm8udmFyaWFudCA9PT0gXCJwZHBcIiAmJiB2YXJpYW50SW5mby5wcm9kdWN0SWQgIT0gbnVsbCkge1xuICAgIHJldHVybiB7XG4gICAgICBldmVudElkOiB1dWlkKCksXG4gICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgIGNhdGVnb3J5OiBVc2VyRXZlbnRDYXRlZ29yeS5QZHBWaXNpdCxcbiAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgcHJvZHVjdElkOiB2YXJpYW50SW5mby5wcm9kdWN0SWQsXG4gICAgICAgIHBhcmVudFByb2R1Y3RJZDogdmFyaWFudEluZm8ucGFyZW50UHJvZHVjdElkID8/IFwiXCIsXG4gICAgICAgIHVybDogdmFyaWFudEluZm8udXJsID8/IFwiXCIsXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvLyB0aGlzIGlzIGEgcGxwIHZpc2l0IGV2ZW50XG4gIGlmICh2YXJpYW50SW5mby52YXJpYW50ID09PSBcInBscFwiICYmIHZhcmlhbnRJbmZvLnBscElkICE9IG51bGwpIHtcbiAgICByZXR1cm4ge1xuICAgICAgZXZlbnRJZDogdXVpZCgpLFxuICAgICAgY3JlYXRlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICBjYXRlZ29yeTogVXNlckV2ZW50Q2F0ZWdvcnkuUGxwVmlzaXQsXG4gICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgIGNhdGVnb3J5OiBQTFBBdHRyaWJ1dGVDYXRlZ29yeS5JZCxcbiAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgIGlkOiB2YXJpYW50SW5mby5wbHBJZCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIGlmICh2YXJpYW50SW5mby52YXJpYW50ID09PSBcInBhZ2VfdmlzaXRcIikge1xuICAgIHJldHVybiB7XG4gICAgICBldmVudElkOiB1dWlkKCksXG4gICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgIGNhdGVnb3J5OiBVc2VyRXZlbnRDYXRlZ29yeS5QYWdlVmlzaXQsXG4gICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgIHVybDogdmFyaWFudEluZm8udXJsLFxuICAgICAgICBwYWdlVmlzaXRDYXRlZ29yeTogdmFyaWFudEluZm8ucGFnZVZpc2l0Q2F0ZWdvcnksXG4gICAgICB9LFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn07XG5cbmNvbnN0IHBhcnNlVGltZSA9ICh0aW1lOiBzdHJpbmcsIHRpbWVab25lOiBzdHJpbmcpID0+IHtcbiAgY29uc3QgdGltZXMgPSB0aW1lLm1hdGNoKC9eKFswLTFdP1xcZCk6KFswLTVdXFxkKShBTXxQTSkkL2kpO1xuICBjb25zdCBob3VycyA9IHRpbWVzPy5bMV07XG4gIGNvbnN0IG1pbnV0ZXMgPSB0aW1lcz8uWzJdO1xuICBjb25zdCBwZXJpb2QgPSB0aW1lcz8uWzNdO1xuXG4gIGlmIChob3VycyAmJiBtaW51dGVzICYmIHBlcmlvZCkge1xuICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSgpO1xuXG4gICAgLy8gQWRqdXN0IGhvdXJzIGZvciBBTS9QTVxuICAgIGxldCBhZGp1c3RlZEhvdXJzID0gMDtcbiAgICBpZiAocGVyaW9kLnRvVXBwZXJDYXNlKCkgPT09IFwiUE1cIiAmJiBob3VycyAhPT0gXCIxMlwiKSB7XG4gICAgICBhZGp1c3RlZEhvdXJzID0gcGFyc2VJbnQoaG91cnMpICsgMTI7XG4gICAgfVxuXG4gICAgaWYgKHBlcmlvZC50b1VwcGVyQ2FzZSgpID09PSBcIkFNXCIgJiYgaG91cnMgIT09IFwiMTJcIikge1xuICAgICAgYWRqdXN0ZWRIb3VycyA9IHBhcnNlSW50KGhvdXJzKTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgdGhlIGRhdGUgc3RyaW5nIHdpdGggdGltZSB6b25lXG4gICAgY29uc3QgZm9ybWF0dGVkRGF0ZSA9IGAke2RhdGUudG9JU09TdHJpbmcoKS5zcGxpdChcIlRcIilbMF19VCR7U3RyaW5nKFxuICAgICAgYWRqdXN0ZWRIb3Vyc1xuICAgICkucGFkU3RhcnQoMiwgXCIwXCIpfToke21pbnV0ZXN9OjAwYDtcbiAgICByZXR1cm4gbmV3IERhdGUoYCR7Zm9ybWF0dGVkRGF0ZX0ke3RpbWVab25lfWApO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgaXNXaXRoaW5CdXNpbmVzc0hvdXJzID0gKFxuICBzdGFydFRpbWU6IHN0cmluZyxcbiAgZW5kVGltZTogc3RyaW5nLFxuICB0aW1lWm9uZTogc3RyaW5nXG4pID0+IHtcbiAgLy8gUGFyc2Ugc3RhcnQgYW5kIGVuZCB0aW1lc1xuICBjb25zdCBzdGFydCA9IHBhcnNlVGltZShzdGFydFRpbWUsIHRpbWVab25lKTtcbiAgbGV0IGVuZCA9IHBhcnNlVGltZShlbmRUaW1lLCB0aW1lWm9uZSk7XG5cbiAgaWYgKCFzdGFydCB8fCAhZW5kKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IG5vdyA9IG5ldyBEYXRlKCk7XG5cbiAgLy8gSWYgdGhlIGVuZCBkYXRlIGlzIGdyZWF0ZXIgdGhhbiB0aGUgc3RhcnQgZGF0ZSwgYWRkIGEgZGF5IHRvIGJvdGggb2YgdGhlbVxuICAvLyBUaGlzIGhhbmRsZXMgY29uZmlndXJhdGlvbnMgc3VjaCBhcyBzdGFydFRpbWUgPSAxMDowMFBNIGFuZCBlbmRUaW1lID0gNzowMEFNXG4gIGlmIChlbmQgPCBzdGFydCkge1xuICAgIGVuZCA9IG5ldyBEYXRlKGVuZC5nZXRUaW1lKCkgKyAyNCAqIDYwICogNjAgKiAxMDAwKTtcbiAgICBub3cgPSBuZXcgRGF0ZShub3cuZ2V0VGltZSgpICsgMjQgKiA2MCAqIDYwICogMTAwMCk7XG4gIH1cblxuICAvLyBJZiB0aGUgZGF0ZSBjb252ZXJzaW9uIHNoaWZ0cyB0aGUgZW5kIGRhdGUgdG8gdGhlIG5leHQgZGF5LCBjb25zaWRlciBjb21wYXJpbmcgaXQgYWNyb3NzIG1pZG5pZ2h0XG4gIGlmIChlbmQuZ2V0VVRDRGF0ZSgpID4gc3RhcnQuZ2V0VVRDRGF0ZSgpKSB7XG4gICAgY29uc3QgY3Jvc3NpbmdNaWRuaWdodCA9IG5ldyBEYXRlKG5vdy5nZXRUaW1lKCkgKyAyNCAqIDYwICogNjAgKiAxMDAwKTtcbiAgICByZXR1cm4gc3RhcnQgPD0gbm93IHx8IGNyb3NzaW5nTWlkbmlnaHQgPD0gZW5kO1xuICB9XG5cbiAgLy8gQ2hlY2sgaWYgdGhlIGN1cnJlbnQgdGltZSBmYWxscyBiZXR3ZWVuIHN0YXJ0IGFuZCBlbmRcbiAgcmV0dXJuIG5vdyA+PSBzdGFydCAmJiBub3cgPD0gZW5kO1xufTtcblxuZXhwb3J0IGVudW0gU2VhcmNoUmVzdWx0c1N0YXRlIHtcbiAgTG9hZGluZyxcbiAgUmVzdWx0cyxcbiAgTm9SZXN1bHRzLFxufVxuXG5leHBvcnQgY29uc3QgZ2V0U2VhcmNoUmVzdWx0c1N0YXRlID0gKFxuICBpc0xvYWRpbmdTZWFyY2g6IGJvb2xlYW4sXG4gIHNlYXJjaERhdGE6IFNlYXJjaFJlc3VsdCB8IG51bGxcbik6IFNlYXJjaFJlc3VsdHNTdGF0ZSA9PiB7XG4gIGlmIChpc0xvYWRpbmdTZWFyY2gpIHtcbiAgICByZXR1cm4gU2VhcmNoUmVzdWx0c1N0YXRlLkxvYWRpbmc7XG4gIH1cbiAgaWYgKHNlYXJjaERhdGEpIHtcbiAgICByZXR1cm4gU2VhcmNoUmVzdWx0c1N0YXRlLlJlc3VsdHM7XG4gIH1cbiAgcmV0dXJuIFNlYXJjaFJlc3VsdHNTdGF0ZS5Ob1Jlc3VsdHM7XG59O1xuIiwiaW1wb3J0IHsgdXNlQXRvbSwgdXNlQXRvbVZhbHVlLCB1c2VTZXRBdG9tIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQgeyB1c2VDYWxsYmFjaywgdXNlRWZmZWN0LCB1c2VNZW1vLCB1c2VSZWYsIHVzZVN0YXRlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyB1c2VEZWJvdW5jZSB9IGZyb20gXCJzcmMvaG9va3MvdXNlRGVib3VuY2VcIjtcbmltcG9ydCB7IHVzZU5ld09yZ0NvbmZpZywgdXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQgfSBmcm9tIFwic3JjL2hvb2tzXCI7XG5pbXBvcnQge1xuICBhZGRTZWFyY2hGaWx0ZXJBdG9tLFxuICBjbGVhclNlYXJjaEZpbHRlcnNBdG9tLFxuICBjcmVhdGVGaWx0ZXJPcHRpb24sXG4gIGZpbHRlcmVkU2VhcmNoUHJvZHVjdHNBdG9tLFxuICBwZXJmb3JtU2VhcmNoQXRvbSxcbiAgcmVtb3ZlU2VhcmNoRmlsdGVyQXRvbSxcbiAgc2VhcmNoQXRvbSxcbiAgc2VhcmNoRmlsdGVyc0F0b20sXG4gIHNlYXJjaFBhcmFtc0F0b20sXG4gIHNlYXJjaFByb2R1Y3RTb3J0aW5nQXRvbSxcbiAgc2VhcmNoU2VsZWN0ZWRGaWx0ZXJzQXRvbSxcbiAgU2VsZWN0ZWRGaWx0ZXJPcHRpb24sXG59IGZyb20gXCJzcmMvYXRvbXMvc2VhcmNoXCI7XG5pbXBvcnQge1xuICBhdXRvY29tcGxldGVTdGF0ZUF0b20sXG4gIGlzRmlsdGVyT3BlbkF0b20sXG59IGZyb20gXCJzcmMvYXRvbXMvZ2xvYmFsU2VhcmNoL2dsb2JhbFNlYXJjaFwiO1xuaW1wb3J0IHsgZm9ybWF0RmlsdGVyRGlzcGxheU5hbWUgfSBmcm9tIFwic3JjL2F0b21zL3NlYXJjaC91dGlsc1wiO1xuaW1wb3J0IHsgUHJvZHVjdFNvcnRpbmcgfSBmcm9tIFwic3JjL2F0b21zL3NlYXJjaC90eXBlc1wiO1xuaW1wb3J0IHtcbiAgU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSxcbiAgdXNlQW1wbGl0dWRlLFxufSBmcm9tIFwic3JjL2NvbnRleHRzL2FtcGxpdHVkZUNvbnRleHRcIjtcbmltcG9ydCB7IFNwaWZmeVdpZGdldHMgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9zcGlmZnlXaWRnZXRzXCI7XG5pbXBvcnQgeyBQcm9kdWN0Q2FyZENvbmZpZyB9IGZyb20gXCJzcmMvY29udGV4dHMvdHlwZXNcIjtcbmltcG9ydCBMb2dnZXIgZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9sb2dnaW5nL2xvZ2dlclwiO1xuaW1wb3J0IHsgU2VhcmNoUmVzdWx0IH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvYXBpL3NlYXJjaFwiO1xuaW1wb3J0IHsgU2VhcmNoUmVzcG9uc2VQcm9kdWN0IH0gZnJvbSBcIkBzcGlmZnktYWkvY29tbWVyY2UtYXBpLWNsaWVudFwiO1xuaW1wb3J0IHtcbiAgU2VhcmNoRmlsdGVyRGF0dW0sXG4gIFNlbGVjdEZpbHRlckl0ZW0sXG59IGZyb20gXCJzcmMvdHlwZXMvc2VhcmNoLWZpbHRlci10eXBlc1wiO1xuaW1wb3J0IHsgZ2V0U2VhcmNoUmVzdWx0c1N0YXRlLCBTZWFyY2hSZXN1bHRzU3RhdGUgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgb3JnU2hvcnROYW1lQXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNlYXJjaFJlc3VsdHNIb2NQcm9wcyB7XG4gIC8vIERhdGFcbiAgc2VhcmNoRGF0YTogU2VhcmNoUmVzdWx0IHwgbnVsbDtcbiAgc2VhcmNoUmVzcG9uc2VJZDogc3RyaW5nO1xuICBtZXJjaGFudFNob3J0TmFtZTogc3RyaW5nO1xuICBwcm9kdWN0Q2FyZENvbmZpZzogUHJvZHVjdENhcmRDb25maWc7XG4gIHByb2R1Y3RMaXN0OiBTZWFyY2hSZXNwb25zZVByb2R1Y3RbXTtcbiAgYXV0b2NvbXBsZXRlUmVzdWx0czogc3RyaW5nW107XG4gIHNlYXJjaEZpbHRlcnM6IFNlYXJjaEZpbHRlckRhdHVtW107XG4gIGF2YWlsYWJsZUR5bmFtaWNGaWx0ZXJzOiB7IG5hbWU6IHN0cmluZzsgZGlzcGxheU5hbWU6IHN0cmluZyB9W107XG4gIHNlbGVjdGVkRmlsdGVyT3B0aW9uczogU2VsZWN0ZWRGaWx0ZXJPcHRpb25bXTtcblxuICAvLyBTdGF0ZVxuICBzZWFyY2hUZXh0OiBzdHJpbmc7XG4gIHNlYXJjaFJlc3VsdHNTdGF0ZTogU2VhcmNoUmVzdWx0c1N0YXRlO1xuICBpc0xvYWRpbmdBdXRvY29tcGxldGU6IGJvb2xlYW47XG4gIGlzTG9hZGluZ1NlYXJjaDogYm9vbGVhbjtcbiAgaXNGaWx0ZXJPcGVuOiBib29sZWFuO1xuICBpc0RpcnR5OiBib29sZWFuO1xuICBmb2N1c2VkSW5kZXg6IG51bWJlcjtcbiAgZm9jdXNlZE9wdGlvbklkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgLy8gVUlcbiAgZmlsdGVyQnV0dG9uVGV4dDogc3RyaW5nO1xuXG4gIC8vIEV2ZW50IEhhbmRsZXJzXG4gIG9uU2VhcmNoSW5wdXRDaGFuZ2U6ICh2YWx1ZTogc3RyaW5nKSA9PiB2b2lkO1xuICBvblN1Ym1pdFNlYXJjaDogKCkgPT4gdm9pZDtcbiAgb25BdXRvY29tcGxldGVTZWxlY3Q6IChzdWdnZXN0aW9uOiBzdHJpbmcpID0+IHZvaWQ7XG4gIG9uS2V5RG93bjogKGV2ZW50OiBSZWFjdC5LZXlib2FyZEV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KSA9PiB2b2lkO1xuICBvblRvZ2dsZUR5bmFtaWNGaWx0ZXI6ICh7XG4gICAgZmlsdGVyLFxuICAgIGR5bmFtaWNGaWx0ZXJEaXNwbGF5TmFtZSxcbiAgfToge1xuICAgIGZpbHRlcjogc3RyaW5nO1xuICAgIGR5bmFtaWNGaWx0ZXJEaXNwbGF5TmFtZTogc3RyaW5nO1xuICB9KSA9PiB2b2lkO1xuICBvblNlbGVjdEZpbHRlckl0ZW06IFNlbGVjdEZpbHRlckl0ZW07XG4gIG9uUmVtb3ZlRmlsdGVyOiAoZmlsdGVyOiBTZWxlY3RlZEZpbHRlck9wdGlvbikgPT4gdm9pZDtcbiAgb25DbGVhckFsbEZpbHRlcnM6ICgpID0+IHZvaWQ7XG4gIHNldElzRmlsdGVyT3BlbjogKGlzRmlsdGVyT3BlbjogYm9vbGVhbikgPT4gdm9pZDtcblxuICAvLyBSZWZzXG4gIHNlYXJjaFJlc3VsdHNSZWY6IFJlYWN0LlJlZk9iamVjdDxIVE1MRGl2RWxlbWVudD47XG59XG5cbmV4cG9ydCBjb25zdCB1c2VTZWFyY2ggPSAoKTogU2VhcmNoUmVzdWx0c0hvY1Byb3BzID0+IHtcbiAgLy8gQXRvbXNcbiAgY29uc3QgY29uZmlnID0gdXNlTmV3T3JnQ29uZmlnKCk7XG4gIGNvbnN0IG9yZ1Nob3J0TmFtZSA9IHVzZUF0b21WYWx1ZShvcmdTaG9ydE5hbWVBdG9tKTtcbiAgY29uc3QgeyBkYXRhOiBzZWFyY2hEYXRhLCBsb2FkaW5nOiBpc0xvYWRpbmdTZWFyY2ggfSA9XG4gICAgdXNlQXRvbVZhbHVlKHNlYXJjaEF0b20pO1xuICBjb25zdCBwcm9kdWN0TGlzdCA9IHVzZUF0b21WYWx1ZShmaWx0ZXJlZFNlYXJjaFByb2R1Y3RzQXRvbSk7XG4gIGNvbnN0IHBlcmZvcm1TZWFyY2ggPSB1c2VTZXRBdG9tKHBlcmZvcm1TZWFyY2hBdG9tKTtcbiAgY29uc3QgW1xuICAgIHsgcmVzdWx0czogYXV0b2NvbXBsZXRlUmVzdWx0cywgaXNMb2FkaW5nOiBpc0xvYWRpbmdBdXRvY29tcGxldGUgfSxcbiAgICBzZXRBdXRvY29tcGxldGVTdGF0ZSxcbiAgXSA9IHVzZUF0b20oYXV0b2NvbXBsZXRlU3RhdGVBdG9tKTtcbiAgY29uc3QgW3sgcXVlcnkgfV0gPSB1c2VBdG9tKHNlYXJjaFBhcmFtc0F0b20pO1xuICBjb25zdCBbaXNGaWx0ZXJPcGVuLCBzZXRJc0ZpbHRlck9wZW5dID0gdXNlQXRvbShpc0ZpbHRlck9wZW5BdG9tKTtcbiAgY29uc3QgW3NlbGVjdGVkRmlsdGVyT3B0aW9uc10gPSB1c2VBdG9tKHNlYXJjaFNlbGVjdGVkRmlsdGVyc0F0b20pO1xuICBjb25zdCBhZGRGaWx0ZXIgPSB1c2VTZXRBdG9tKGFkZFNlYXJjaEZpbHRlckF0b20pO1xuICBjb25zdCByZW1vdmVGaWx0ZXIgPSB1c2VTZXRBdG9tKHJlbW92ZVNlYXJjaEZpbHRlckF0b20pO1xuICBjb25zdCBbcHJvZHVjdFNvcnRpbmcsIHNldFByb2R1Y3RTb3J0aW5nXSA9IHVzZUF0b20oc2VhcmNoUHJvZHVjdFNvcnRpbmdBdG9tKTtcbiAgY29uc3QgY2xlYXJGaWx0ZXJzID0gdXNlU2V0QXRvbShjbGVhclNlYXJjaEZpbHRlcnNBdG9tKTtcbiAgY29uc3Qgc2VhcmNoRmlsdGVycyA9IHVzZUF0b21WYWx1ZShzZWFyY2hGaWx0ZXJzQXRvbSk7XG5cbiAgLy8gU3RhdGVcbiAgY29uc3QgW2lzRGlydHksIHNldElzRGlydHldID0gdXNlU3RhdGUodHJ1ZSk7XG4gIGNvbnN0IFtmb2N1c2VkSW5kZXgsIHNldEZvY3VzZWRJbmRleF0gPSB1c2VTdGF0ZSgtMSk7XG4gIGNvbnN0IFtmb2N1c2VkT3B0aW9uSWQsIHNldEZvY3VzZWRPcHRpb25JZF0gPSB1c2VTdGF0ZTxzdHJpbmcgfCB1bmRlZmluZWQ+KFxuICAgIHVuZGVmaW5lZFxuICApO1xuICBjb25zdCBbc2VhcmNoVGV4dCwgc2V0U2VhcmNoVGV4dF0gPSB1c2VTdGF0ZShxdWVyeSB8fCBcIlwiKTtcblxuICAvLyBSZWZzXG4gIGNvbnN0IHNlYXJjaFJlc3VsdHNSZWYgPSB1c2VSZWY8SFRNTERpdkVsZW1lbnQ+KG51bGwpO1xuXG4gIC8vIERlcml2ZWQgU3RhdGVcbiAgY29uc3QgZGVib3VuY2VkU2VhcmNoVGV4dCA9IHVzZURlYm91bmNlKHNlYXJjaFRleHQsIDIwMCk7XG4gIGNvbnN0IHNlYXJjaFJlc3VsdHNTdGF0ZSA9IGdldFNlYXJjaFJlc3VsdHNTdGF0ZShpc0xvYWRpbmdTZWFyY2gsIHNlYXJjaERhdGEpO1xuXG4gIGNvbnN0IGR5bmFtaWNGaWx0ZXJzID0gc2VhcmNoRGF0YT8uZmlsdGVycyB8fCBbXTtcblxuICAvLyBQcm92aWRlIGZhbGxiYWNrIHZhbHVlcyB3aGVuIG9yZ1VJQ29uZmlnIGlzIG5vdCB5ZXQgYXZhaWxhYmxlXG4gIGNvbnN0IHNhZmVQcm9kdWN0Q2FyZENvbmZpZyA9IGNvbmZpZz8uZnJvbnRlbmRDb25maWc/LnVpQ29uZmlnc1xuICAgID8ucHJvZHVjdENhcmRDb25maWcgfHwge1xuICAgIHZhcmlhbnQ6IFwibWluaW1hbFwiLFxuICAgIGhvdmVyVmFyaWFudDogXCJub25lXCIsXG4gICAgbGF5b3V0VmFyaWFudDogXCJzcXVhcmVcIixcbiAgfTtcbiAgY29uc3Qgc2FmZU1lcmNoYW50U2hvcnROYW1lID0gb3JnU2hvcnROYW1lIHx8IFwiXCI7XG5cbiAgY29uc3QgYXZhaWxhYmxlRHluYW1pY0ZpbHRlcnMgPSB1c2VNZW1vKCgpID0+IHtcbiAgICByZXR1cm4gZHluYW1pY0ZpbHRlcnNcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChkeW5hbWljRmlsdGVyTmFtZSkgPT5cbiAgICAgICAgICAhc2VsZWN0ZWRGaWx0ZXJPcHRpb25zLnNvbWUoXG4gICAgICAgICAgICAob3B0aW9uKSA9PiBvcHRpb24uaWQgPT09IGBkeW5hbWljOiR7ZHluYW1pY0ZpbHRlck5hbWV9YFxuICAgICAgICAgIClcbiAgICAgIClcbiAgICAgIC5tYXAoKGR5bmFtaWNGaWx0ZXJOYW1lKSA9PiAoe1xuICAgICAgICBuYW1lOiBkeW5hbWljRmlsdGVyTmFtZSxcbiAgICAgICAgZGlzcGxheU5hbWU6IGZvcm1hdEZpbHRlckRpc3BsYXlOYW1lKGR5bmFtaWNGaWx0ZXJOYW1lKSxcbiAgICAgIH0pKTtcbiAgfSwgW2R5bmFtaWNGaWx0ZXJzLCBzZWxlY3RlZEZpbHRlck9wdGlvbnNdKTtcblxuICBjb25zdCBmaWx0ZXJzID0gdXNlTWVtbygoKSA9PiB7XG4gICAgY29uc3Qgc29ydE9wdGlvbnMgPSBbXG4gICAgICB7XG4gICAgICAgIGZpbHRlckl0ZW1JZDogU3RyaW5nKFByb2R1Y3RTb3J0aW5nLkZFQVRVUkVEKSxcbiAgICAgICAgZGlzcGxheU5hbWU6IFwiUmVsZXZhbmNlXCIsXG4gICAgICAgIHByb2R1Y3RDb3VudDogMCxcbiAgICAgICAgaXNTZWxlY3RlZDogcHJvZHVjdFNvcnRpbmcgPT09IFByb2R1Y3RTb3J0aW5nLkZFQVRVUkVELFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgZmlsdGVySXRlbUlkOiBTdHJpbmcoUHJvZHVjdFNvcnRpbmcuUFJJQ0VfQVNDKSxcbiAgICAgICAgZGlzcGxheU5hbWU6IFwiUHJpY2U6IExvdyB0byBIaWdoXCIsXG4gICAgICAgIHByb2R1Y3RDb3VudDogMCxcbiAgICAgICAgaXNTZWxlY3RlZDogcHJvZHVjdFNvcnRpbmcgPT09IFByb2R1Y3RTb3J0aW5nLlBSSUNFX0FTQyxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGZpbHRlckl0ZW1JZDogU3RyaW5nKFByb2R1Y3RTb3J0aW5nLlBSSUNFX0RFU0MpLFxuICAgICAgICBkaXNwbGF5TmFtZTogXCJQcmljZTogSGlnaCB0byBMb3dcIixcbiAgICAgICAgcHJvZHVjdENvdW50OiAwLFxuICAgICAgICBpc1NlbGVjdGVkOiBwcm9kdWN0U29ydGluZyA9PT0gUHJvZHVjdFNvcnRpbmcuUFJJQ0VfREVTQyxcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIHJldHVybiBbXG4gICAgICB7IGZpbHRlcklkOiBcInNvcnRcIiwgZGlzcGxheU5hbWU6IFwiU09SVFwiLCBpdGVtczogc29ydE9wdGlvbnMgfSxcbiAgICAgIC4uLnNlYXJjaEZpbHRlcnMsXG4gICAgXSBhcyBTZWFyY2hGaWx0ZXJEYXR1bVtdO1xuICB9LCBbcHJvZHVjdFNvcnRpbmcsIHNlYXJjaEZpbHRlcnNdKTtcblxuICBjb25zdCBmaWx0ZXJCdXR0b25UZXh0ID0gdXNlTWVtbygoKSA9PiB7XG4gICAgY29uc3Qgc2VsZWN0ZWRDb3VudCA9IGZpbHRlcnMucmVkdWNlKChhY2M6IG51bWJlciwgZmlsdGVyKSA9PiB7XG4gICAgICBpZiAoZmlsdGVyLmZpbHRlcklkID09PSBcInNvcnRcIikge1xuICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjYyArIGZpbHRlci5pdGVtcy5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0uaXNTZWxlY3RlZCkubGVuZ3RoO1xuICAgIH0sIDApO1xuICAgIGlmIChzZWxlY3RlZENvdW50ID09PSAwKSB7XG4gICAgICByZXR1cm4gXCJGaWx0ZXIgJiBTb3J0XCI7XG4gICAgfVxuICAgIHJldHVybiBgRmlsdGVyICYgU29ydCAoJHtzZWxlY3RlZENvdW50fSlgO1xuICB9LCBbZmlsdGVyc10pO1xuXG4gIC8vIENhbGxiYWNrc1xuICBjb25zdCB7IHRyYWNrRXZlbnQgfSA9IHVzZUFtcGxpdHVkZSgpO1xuXG4gIGNvbnN0IGhhbmRsZVRvZ2dsZUR5bmFtaWNGaWx0ZXIgPSB1c2VDYWxsYmFjayhcbiAgICAoe1xuICAgICAgZmlsdGVyLFxuICAgICAgZHluYW1pY0ZpbHRlckRpc3BsYXlOYW1lLFxuICAgIH06IHtcbiAgICAgIGZpbHRlcjogc3RyaW5nO1xuICAgICAgZHluYW1pY0ZpbHRlckRpc3BsYXlOYW1lOiBzdHJpbmc7XG4gICAgfSkgPT4ge1xuICAgICAgdHJhY2tFdmVudCh7XG4gICAgICAgIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5TZWFyY2hGaWx0ZXJDbGlja2VkLFxuICAgICAgICBldmVudFByb3BzOiB7XG4gICAgICAgICAgZmlsdGVyVHlwZTogXCJEeW5hbWljXCIsXG4gICAgICAgICAgZmlsdGVyVmFsdWU6IGZpbHRlcixcbiAgICAgICAgICBxdWVyeVRleHQ6IHNlYXJjaFRleHQsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIGFkZEZpbHRlcihcbiAgICAgICAgY3JlYXRlRmlsdGVyT3B0aW9uKFwiZHluYW1pY1wiLCBmaWx0ZXIsIGR5bmFtaWNGaWx0ZXJEaXNwbGF5TmFtZSlcbiAgICAgICk7XG4gICAgfSxcbiAgICBbYWRkRmlsdGVyLCBzZWFyY2hUZXh0LCB0cmFja0V2ZW50XVxuICApO1xuXG4gIGNvbnN0IGhhbmRsZVJlbW92ZUZpbHRlciA9IHVzZUNhbGxiYWNrKFxuICAgIChmaWx0ZXI6IFNlbGVjdGVkRmlsdGVyT3B0aW9uKSA9PiB7XG4gICAgICByZW1vdmVGaWx0ZXIoZmlsdGVyLmlkKTtcbiAgICB9LFxuICAgIFtyZW1vdmVGaWx0ZXJdXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlU3VibWl0U2VhcmNoID0gdXNlQ2FsbGJhY2soYXN5bmMgKCkgPT4ge1xuICAgIGlmIChzZWFyY2hUZXh0LnRyaW0oKSkge1xuICAgICAgdHJhY2tFdmVudCh7XG4gICAgICAgIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5TZWFyY2hRdWVyeVN1Ym1pdHRlZCxcbiAgICAgICAgZXZlbnRQcm9wczoge1xuICAgICAgICAgIHNlYXJjaE9yaWdpbjogU3BpZmZ5V2lkZ2V0cy5TZWFyY2hSZXN1bHRzLFxuICAgICAgICAgIHF1ZXJ5VGV4dDogc2VhcmNoVGV4dC50cmltKCksXG4gICAgICAgIH0sXG4gICAgICAgIGFsc29TZW5kVG9Hb29nbGVBbmFseXRpY3M6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwod2luZG93LmxvY2F0aW9uLmhyZWYpO1xuICAgICAgdXJsLnNlYXJjaFBhcmFtcy5zZXQoXCJlc3FcIiwgc2VhcmNoVGV4dC50cmltKCkpO1xuICAgICAgd2luZG93Lmhpc3RvcnkucHVzaFN0YXRlKHt9LCBcIlwiLCB1cmwpO1xuICAgICAgcGVyZm9ybVNlYXJjaCh7IHF1ZXJ5OiBzZWFyY2hUZXh0LnRyaW0oKSB9KTtcbiAgICB9XG4gIH0sIFtwZXJmb3JtU2VhcmNoLCBzZWFyY2hUZXh0LCB0cmFja0V2ZW50XSk7XG5cbiAgY29uc3QgaGFuZGxlQXV0b2NvbXBsZXRlU2VsZWN0ID0gdXNlQ2FsbGJhY2soXG4gICAgKHN1Z2dlc3Rpb246IHN0cmluZykgPT4ge1xuICAgICAgc2V0U2VhcmNoVGV4dChzdWdnZXN0aW9uKTtcbiAgICAgIGhhbmRsZVN1Ym1pdFNlYXJjaCgpO1xuICAgIH0sXG4gICAgW2hhbmRsZVN1Ym1pdFNlYXJjaCwgc2V0U2VhcmNoVGV4dF1cbiAgKTtcblxuICBjb25zdCBoYW5kbGVLZXlEb3duID0gdXNlQ2FsbGJhY2soXG4gICAgKGV2ZW50OiBSZWFjdC5LZXlib2FyZEV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KSA9PiB7XG4gICAgICBpZiAoZXZlbnQua2V5ID09PSBcIkFycm93RG93blwiKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGNvbnN0IG5ld0luZGV4ID0gKGZvY3VzZWRJbmRleCArIDEpICUgYXV0b2NvbXBsZXRlUmVzdWx0cy5sZW5ndGg7XG4gICAgICAgIHNldEZvY3VzZWRJbmRleChuZXdJbmRleCk7XG4gICAgICAgIHNldEZvY3VzZWRPcHRpb25JZChgb3B0aW9uLSR7bmV3SW5kZXh9YCk7XG4gICAgICB9IGVsc2UgaWYgKGV2ZW50LmtleSA9PT0gXCJBcnJvd1VwXCIpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgY29uc3QgbmV3SW5kZXggPVxuICAgICAgICAgIChmb2N1c2VkSW5kZXggLSAxICsgYXV0b2NvbXBsZXRlUmVzdWx0cy5sZW5ndGgpICVcbiAgICAgICAgICBhdXRvY29tcGxldGVSZXN1bHRzLmxlbmd0aDtcbiAgICAgICAgc2V0Rm9jdXNlZEluZGV4KG5ld0luZGV4KTtcbiAgICAgICAgc2V0Rm9jdXNlZE9wdGlvbklkKGBvcHRpb24tJHtuZXdJbmRleH1gKTtcbiAgICAgIH0gZWxzZSBpZiAoZXZlbnQua2V5ID09PSBcIkVudGVyXCIpIHtcbiAgICAgICAgaWYgKGZvY3VzZWRJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIGhhbmRsZVN1Ym1pdFNlYXJjaCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgY29uc3Qgc3VnZ2VzdGlvblRleHQgPSBhdXRvY29tcGxldGVSZXN1bHRzW2ZvY3VzZWRJbmRleF07XG4gICAgICAgICAgaGFuZGxlQXV0b2NvbXBsZXRlU2VsZWN0KHN1Z2dlc3Rpb25UZXh0KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChldmVudC5rZXkgPT09IFwiRXNjYXBlXCIpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgc2V0Rm9jdXNlZEluZGV4KC0xKTtcbiAgICAgICAgc2V0Rm9jdXNlZE9wdGlvbklkKHVuZGVmaW5lZCk7XG4gICAgICB9XG4gICAgfSxcbiAgICBbXG4gICAgICBhdXRvY29tcGxldGVSZXN1bHRzLFxuICAgICAgZm9jdXNlZEluZGV4LFxuICAgICAgaGFuZGxlQXV0b2NvbXBsZXRlU2VsZWN0LFxuICAgICAgaGFuZGxlU3VibWl0U2VhcmNoLFxuICAgIF1cbiAgKTtcblxuICBjb25zdCBoYW5kbGVTZWFyY2hJbnB1dENoYW5nZSA9IChuZXdWYWx1ZTogc3RyaW5nKSA9PiB7XG4gICAgaWYgKG5ld1ZhbHVlLmxlbmd0aCA9PT0gMSkge1xuICAgICAgdHJhY2tFdmVudCh7XG4gICAgICAgIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5TZWFyY2hJbnB1dFN0YXJ0ZWQsXG4gICAgICAgIGV2ZW50UHJvcHM6IHtcbiAgICAgICAgICBzZWFyY2hPcmlnaW46IFNwaWZmeVdpZGdldHMuU2VhcmNoUmVzdWx0cyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICBzZXRTZWFyY2hUZXh0KG5ld1ZhbHVlKTtcbiAgICBzZXRJc0RpcnR5KHRydWUpO1xuICB9O1xuXG4gIGNvbnN0IGhhbmRsZVNlbGVjdEZpbHRlckl0ZW06IFNlbGVjdEZpbHRlckl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICAoe1xuICAgICAgZmlsdGVySWQsXG4gICAgICBmaWx0ZXJJdGVtSWQsXG4gICAgICBpc1NlbGVjdGVkLFxuICAgICAgZGlzcGxheU5hbWUsXG4gICAgfToge1xuICAgICAgZmlsdGVySWQ6IHN0cmluZztcbiAgICAgIGZpbHRlckl0ZW1JZDogc3RyaW5nO1xuICAgICAgaXNTZWxlY3RlZDogYm9vbGVhbjtcbiAgICAgIGRpc3BsYXlOYW1lOiBzdHJpbmc7XG4gICAgfSkgPT4ge1xuICAgICAgaWYgKGZpbHRlcklkID09PSBcInNvcnRcIikge1xuICAgICAgICBjb25zdCBuZXdTb3J0ID0gZmlsdGVySXRlbUlkIGFzIFByb2R1Y3RTb3J0aW5nO1xuICAgICAgICB0cmFja0V2ZW50KHtcbiAgICAgICAgICBldmVudE5hbWU6IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUuU2VhcmNoU29ydENsaWNrZWQsXG4gICAgICAgICAgZXZlbnRQcm9wczoge1xuICAgICAgICAgICAgc29ydFR5cGU6IG5ld1NvcnQsXG4gICAgICAgICAgICBxdWVyeVRleHQ6IHNlYXJjaFRleHQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIHNldFByb2R1Y3RTb3J0aW5nKG5ld1NvcnQpO1xuICAgICAgfSBlbHNlIGlmICghaXNTZWxlY3RlZCkge1xuICAgICAgICByZW1vdmVGaWx0ZXIoYCR7ZmlsdGVySWR9OiR7ZmlsdGVySXRlbUlkfWApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJhY2tFdmVudCh7XG4gICAgICAgICAgZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLlNlYXJjaEZpbHRlckNsaWNrZWQsXG4gICAgICAgICAgZXZlbnRQcm9wczoge1xuICAgICAgICAgICAgZmlsdGVyVHlwZTogXCJTdGF0aWNcIixcbiAgICAgICAgICAgIGZpbHRlckNhdGVnb3J5OiBmaWx0ZXJJZCxcbiAgICAgICAgICAgIGZpbHRlclZhbHVlOiBmaWx0ZXJJdGVtSWQsXG4gICAgICAgICAgICBxdWVyeVRleHQ6IHNlYXJjaFRleHQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGFkZEZpbHRlcihjcmVhdGVGaWx0ZXJPcHRpb24oZmlsdGVySWQsIGZpbHRlckl0ZW1JZCwgZGlzcGxheU5hbWUpKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFthZGRGaWx0ZXIsIHJlbW92ZUZpbHRlciwgc2V0UHJvZHVjdFNvcnRpbmcsIHNlYXJjaFRleHQsIHRyYWNrRXZlbnRdXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlQ2xlYXJBbGxGaWx0ZXJzID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIHNldFByb2R1Y3RTb3J0aW5nKFByb2R1Y3RTb3J0aW5nLkZFQVRVUkVEKTtcbiAgICBjbGVhckZpbHRlcnMoKTtcbiAgfSwgW3NldFByb2R1Y3RTb3J0aW5nLCBjbGVhckZpbHRlcnNdKTtcblxuICAvLyBTaWRlIEVmZmVjdHNcbiAgdXNlVHJhY2tDb21wb25lbnRWaXNpYmxlRXZlbnQoXG4gICAgU3BpZmZ5V2lkZ2V0cy5TZWFyY2hSZXN1bHRzLFxuICAgIHNlYXJjaFJlc3VsdHNSZWYsXG4gICAge30sXG4gICAgU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5TZWFyY2hDb21wb25lbnRWaXNpYmxlXG4gICk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAocHJvZHVjdExpc3QubGVuZ3RoID4gMCkge1xuICAgICAgdHJhY2tFdmVudCh7XG4gICAgICAgIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5TZWFyY2hSZXN1bHRzVmlld2VkLFxuICAgICAgICBldmVudFByb3BzOiB7XG4gICAgICAgICAgcXVlcnlUZXh0OiBzZWFyY2hUZXh0LFxuICAgICAgICAgIHJlc3VsdHNDb3VudDogcHJvZHVjdExpc3QubGVuZ3RoLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfVxuICB9LCBbcHJvZHVjdExpc3QubGVuZ3RoLCBzZWFyY2hUZXh0LCB0cmFja0V2ZW50XSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAocXVlcnkgJiYgcXVlcnkgIT09IHNlYXJjaFRleHQpIHtcbiAgICAgIHNldFNlYXJjaFRleHQocXVlcnkpO1xuICAgIH1cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVhY3QtaG9va3MvZXhoYXVzdGl2ZS1kZXBzXG4gIH0sIFtxdWVyeV0pO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgY29uc3QgZXNxID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoKS5nZXQoXCJlc3FcIik7XG4gICAgaWYgKGVzcSkge1xuICAgICAgc2V0U2VhcmNoVGV4dChlc3EpO1xuICAgICAgcGVyZm9ybVNlYXJjaCh7IHF1ZXJ5OiBlc3EgfSk7XG4gICAgfVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSByZWFjdC1ob29rcy9leGhhdXN0aXZlLWRlcHNcbiAgfSwgW3BlcmZvcm1TZWFyY2hdKTtcblxuICBjb25zdCBmZXRjaEF1dG9jb21wbGV0ZVN1Z2dlc3Rpb25zID0gKF9xdWVyeTogc3RyaW5nKSA9PiB7XG4gICAgLy8gVE9ETzogaW1wbGVtZW50IGF1dG9jb21wbGV0ZSBzdWdnZXN0aW9uc1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoW10pO1xuICB9O1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKGZldGNoQXV0b2NvbXBsZXRlU3VnZ2VzdGlvbnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaXNEaXJ0eSB8fCBkZWJvdW5jZWRTZWFyY2hUZXh0Lmxlbmd0aCA8PSAyKSB7XG4gICAgICBzZXRBdXRvY29tcGxldGVTdGF0ZSh7IHJlc3VsdHM6IFtdLCBpc0xvYWRpbmc6IGZhbHNlIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHNldEF1dG9jb21wbGV0ZVN0YXRlKChwcmV2KSA9PiAoeyAuLi5wcmV2LCBpc0xvYWRpbmc6IHRydWUgfSkpO1xuXG4gICAgY29uc3QgZmV0Y2hEYXRhID0gYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IGZldGNoQXV0b2NvbXBsZXRlU3VnZ2VzdGlvbnM/LihcbiAgICAgICAgICBkZWJvdW5jZWRTZWFyY2hUZXh0XG4gICAgICAgICk7XG4gICAgICAgIHNldEF1dG9jb21wbGV0ZVN0YXRlKHsgcmVzdWx0czogcmVzdWx0cyA/PyBbXSwgaXNMb2FkaW5nOiBmYWxzZSB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIExvZ2dlci5sb2dFcnJvcihcIkZhaWxlZCB0byBmZXRjaCBhdXRvY29tcGxldGUgc3VnZ2VzdGlvbnM6XCIsIGVycm9yKTtcbiAgICAgICAgc2V0QXV0b2NvbXBsZXRlU3RhdGUoeyByZXN1bHRzOiBbXSwgaXNMb2FkaW5nOiBmYWxzZSB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgZmV0Y2hEYXRhKCk7XG4gIH0sIFtkZWJvdW5jZWRTZWFyY2hUZXh0LCBpc0RpcnR5LCBzZXRBdXRvY29tcGxldGVTdGF0ZV0pO1xuXG4gIHJldHVybiB7XG4gICAgc2VhcmNoRGF0YSxcbiAgICBzZWFyY2hSZXNwb25zZUlkOiBzZWFyY2hEYXRhPy5zZWFyY2hSZXNwb25zZUlkID8/IFwiXCIsXG4gICAgbWVyY2hhbnRTaG9ydE5hbWU6IHNhZmVNZXJjaGFudFNob3J0TmFtZSxcbiAgICBwcm9kdWN0Q2FyZENvbmZpZzogc2FmZVByb2R1Y3RDYXJkQ29uZmlnLFxuICAgIHByb2R1Y3RMaXN0LFxuICAgIGF1dG9jb21wbGV0ZVJlc3VsdHMsXG4gICAgc2VhcmNoRmlsdGVyczogZmlsdGVycyxcbiAgICBhdmFpbGFibGVEeW5hbWljRmlsdGVycyxcbiAgICBzZWxlY3RlZEZpbHRlck9wdGlvbnMsXG4gICAgc2VhcmNoVGV4dCxcbiAgICBzZWFyY2hSZXN1bHRzU3RhdGUsXG4gICAgaXNMb2FkaW5nQXV0b2NvbXBsZXRlLFxuICAgIGlzTG9hZGluZ1NlYXJjaCxcbiAgICBpc0ZpbHRlck9wZW4sXG4gICAgaXNEaXJ0eSxcbiAgICBmb2N1c2VkSW5kZXgsXG4gICAgZm9jdXNlZE9wdGlvbklkLFxuICAgIGZpbHRlckJ1dHRvblRleHQsXG4gICAgb25TZWFyY2hJbnB1dENoYW5nZTogaGFuZGxlU2VhcmNoSW5wdXRDaGFuZ2UsXG4gICAgb25TdWJtaXRTZWFyY2g6IGhhbmRsZVN1Ym1pdFNlYXJjaCxcbiAgICBvbkF1dG9jb21wbGV0ZVNlbGVjdDogaGFuZGxlQXV0b2NvbXBsZXRlU2VsZWN0LFxuICAgIG9uS2V5RG93bjogaGFuZGxlS2V5RG93bixcbiAgICBvblRvZ2dsZUR5bmFtaWNGaWx0ZXI6IGhhbmRsZVRvZ2dsZUR5bmFtaWNGaWx0ZXIsXG4gICAgb25TZWxlY3RGaWx0ZXJJdGVtOiBoYW5kbGVTZWxlY3RGaWx0ZXJJdGVtLFxuICAgIG9uUmVtb3ZlRmlsdGVyOiBoYW5kbGVSZW1vdmVGaWx0ZXIsXG4gICAgb25DbGVhckFsbEZpbHRlcnM6IGhhbmRsZUNsZWFyQWxsRmlsdGVycyxcbiAgICBzZXRJc0ZpbHRlck9wZW4sXG4gICAgc2VhcmNoUmVzdWx0c1JlZixcbiAgfTtcbn07XG4iLCJpbXBvcnQgeyB1c2VBdG9tVmFsdWUgfSBmcm9tIFwiam90YWlcIjtcbmltcG9ydCB7XG4gIENvbnRleHRFbnZFbnVtLFxuICBDb250ZXh0U291cmNlRW51bSxcbn0gZnJvbSBcIkBzcGlmZnktYWkvY29tbWVyY2UtYXBpLWNsaWVudFwiO1xuaW1wb3J0IHsgVmFyaWFudEluZm8gfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVsc1wiO1xuaW1wb3J0IHsgVXNlcklkZW50aXR5Q29udGV4dFR5cGUgfSBmcm9tIFwic3JjL2NvbnRleHRzL3VzZXJJZGVudGl0eUNvbnRleHRcIjtcbmltcG9ydCB7IHZhcmlhbnRJbmZvQXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvYXBwL3ZhcmlhbnRcIjtcbmltcG9ydCB7XG4gIGNvbnRleHRTb3VyY2VBdG9tLFxuICBlbnZBdG9tIGFzIGVudml2ZUVudkF0b20sXG4gIG9yZ1Nob3J0TmFtZUF0b20gYXMgZW52aXZlT3JnU2hvcnROYW1lQXRvbSxcbn0gZnJvbSBcInNyYy9hdG9tcy9lbnZpdmUvZW52aXZlQ29uZmlnXCI7XG5pbXBvcnQgeyBjaGF0SWRBdG9tLCB1c2VySWRBdG9tIH0gZnJvbSBcInNyYy9hdG9tcy9hcHAvaW5kZXhcIjtcbmltcG9ydCB7IHVzZU5ld09yZ0NvbmZpZ0NvbnRleHQgfSBmcm9tIFwic3JjL2NvbnRleHRzL25ld09yZ0NvbmZpZ0NvbnRleHRcIjtcbmltcG9ydCB7IHVzZU9yZ0lkIH0gZnJvbSBcInNyYy9ob29rcy91c2VHcmFwaFFMQ29uZmlnXCI7IC8vIEltcG9ydCB1c2VPcmdJZFxuXG5leHBvcnQgaW50ZXJmYWNlIEFwcERldGFpbHMge1xuICBvcmdJZDogc3RyaW5nO1xuICBvcmdTaG9ydE5hbWU6IHN0cmluZztcbiAgY2hhdElkOiBzdHJpbmc7XG4gIHVzZXJJZDogc3RyaW5nO1xuICBzb3VyY2U6IENvbnRleHRTb3VyY2VFbnVtO1xuICBlbnY6IENvbnRleHRFbnZFbnVtO1xuICB2YXJpYW50SW5mbzogVmFyaWFudEluZm87XG59XG5cbmV4cG9ydCBjb25zdCB1c2VBcHBEZXRhaWxzID0gKCk6IEFwcERldGFpbHMgPT4ge1xuICBjb25zdCB7IG9yZ0lkOiBmZXRjaGVkT3JnSWQgfSA9IHVzZU9yZ0lkKCk7IC8vIEdldCBvcmdJZCBmcm9tIHVzZU9yZ0lkIGhvb2tcbiAgY29uc3Qgb3JnSWQgPSBmZXRjaGVkT3JnSWQgPz8gXCJcIjsgLy8gUHJvdmlkZSBhIGRlZmF1bHQgZW1wdHkgc3RyaW5nIGlmIHVuZGVmaW5lZFxuXG4gIGNvbnN0IG9yZ1Nob3J0TmFtZSA9IHVzZUF0b21WYWx1ZShlbnZpdmVPcmdTaG9ydE5hbWVBdG9tKSA/PyBcInNwaWZmeS1haVwiO1xuICBjb25zdCBjaGF0SWQgPSB1c2VBdG9tVmFsdWUoY2hhdElkQXRvbSk7XG4gIGNvbnN0IHVzZXJJZCA9IHVzZUF0b21WYWx1ZSh1c2VySWRBdG9tKTtcbiAgY29uc3Qgc291cmNlID0gdXNlQXRvbVZhbHVlKGNvbnRleHRTb3VyY2VBdG9tKSA/PyBDb250ZXh0U291cmNlRW51bS5BcHA7XG4gIGNvbnN0IGVudiA9XG4gICAgKHVzZUF0b21WYWx1ZShlbnZpdmVFbnZBdG9tKSBhcyBDb250ZXh0RW52RW51bSkgPz8gQ29udGV4dEVudkVudW0uRGV2OyAvLyBDYXN0IHRvIENvbnRleHRFbnZFbnVtXG4gIGNvbnN0IHZhcmlhbnRJbmZvID0gdXNlQXRvbVZhbHVlKHZhcmlhbnRJbmZvQXRvbSk7XG5cbiAgcmV0dXJuIHtcbiAgICBvcmdJZCxcbiAgICBvcmdTaG9ydE5hbWUsXG4gICAgY2hhdElkLFxuICAgIHVzZXJJZCxcbiAgICBzb3VyY2UsXG4gICAgZW52LFxuICAgIHZhcmlhbnRJbmZvLFxuICB9O1xufTtcbiIsImltcG9ydCBSZWFjdCwge1xuICBjcmVhdGVDb250ZXh0LFxuICB1c2VDb250ZXh0LFxuICB1c2VDYWxsYmFjayxcbiAgdXNlTWVtbyxcbiAgdXNlRWZmZWN0LFxufSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZUF0b21WYWx1ZSB9IGZyb20gXCJqb3RhaVwiO1xuaW1wb3J0IHtcbiAgQ29uZmlndXJhdGlvbixcbiAgUmVzcG9uc2VDYXRlZ29yeSxcbiAgUmVzcG9uc2VFcnJvcixcbiAgU2VhcmNoQXBpLFxufSBmcm9tIFwiQHNwaWZmeS1haS9jb21tZXJjZS1hcGktY2xpZW50XCI7XG5pbXBvcnQgeyBiYXNlVXJsQXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuaW1wb3J0IExvZ2dlciBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL2xvZ2dpbmcvbG9nZ2VyXCI7XG5pbXBvcnQgeyB1c2VBcHBEZXRhaWxzIH0gZnJvbSBcInNyYy9ob29rcy91c2VBcHBEZXRhaWxzXCI7XG5pbXBvcnQgeyB1c2VFbnZpdmVDb25maWcgfSBmcm9tIFwic3JjL2NvbnRleHRzL2Vudml2ZUNvbmZpZ0NvbnRleHRcIjtcbmltcG9ydCB7IFNlc3Npb25SZXN0YXJ0UmVxdWlyZWQgfSBmcm9tIFwic3JjL3R5cGVzL2V4Y2VwdGlvbnMvc2Vzc2lvbkV4Y2VwdGlvbnNcIjtcbmltcG9ydCB7IFVuc3VwcG9ydGVkUHJvZHVjdEV4Y2VwdGlvbiB9IGZyb20gXCJzcmMvdHlwZXMvZXhjZXB0aW9ucy91bnN1cHBvcnRlZFByb2R1Y3RFeGNlcHRpb25zXCI7XG5pbXBvcnQgeyBTZWFyY2hSZXN1bHQsIFNlYXJjaFBhcmFtcyB9IGZyb20gXCIuLi9hcHBsaWNhdGlvbi9tb2RlbHMvYXBpL3NlYXJjaFwiO1xuaW1wb3J0IHtcbiAgc2V0U2VhcmNoU2VydmljZUZ1bmN0aW9uLFxuICBjbGVhclNlYXJjaFNlcnZpY2VGdW5jdGlvbixcbn0gZnJvbSBcIi4uL2F0b21zL3NlYXJjaC9zZWFyY2hTZXJ2aWNlQWRhcHRlclwiO1xuXG5jb25zdCB0cmFuc2Zvcm1Qcm9kdWN0UmVzcG9uc2VzID0gKHByb2R1Y3RzOiBTZWFyY2hSZXN1bHRbXCJwcm9kdWN0c1wiXSkgPT5cbiAgcHJvZHVjdHMubWFwKChkYXRhKSA9PiAoe1xuICAgIGlkOiBkYXRhLmlkLFxuICAgIHJlc3BvbnNlSWQ6IGRhdGEucmVzcG9uc2VfaWQsXG4gICAgY2F0ZWdvcnk6IFJlc3BvbnNlQ2F0ZWdvcnkuUHJvZHVjdCxcbiAgICBkZXNjcmlwdGlvbjogZGF0YS5kZXNjcmlwdGlvbixcbiAgICBpbWFnZVVybDogZGF0YS5pbWFnZV91cmwsXG4gICAgaW1hZ2VVcmxzOiBkYXRhLmltYWdlX3VybHMsXG4gICAgdGl0bGU6IGRhdGEudGl0bGUsXG4gICAgdXJsOiBkYXRhLnVybCxcbiAgICBvcmlnaW5hbFByaWNlOiBkYXRhLm9yaWdpbmFsX3ByaWNlLFxuICAgIHNhbGVQcmljZTogZGF0YS5zYWxlX3ByaWNlLFxuICAgIGF2ZXJhZ2VSYXRpbmc6IGRhdGEuYXZlcmFnZV9yYXRpbmcsXG4gICAgbnVtYmVyUmV2aWV3czogZGF0YS5udW1iZXJfcmV2aWV3cyxcbiAgICBtZXRhZGF0YTogZGF0YS5tZXRhZGF0YSxcbiAgICBpc0ZvckdyaWQ6IGRhdGEuaXNfZm9yX2dyaWQsXG4gICAgY29sb3JzOiBkYXRhLmNvbG9ycyxcbiAgICBzaXplczogZGF0YS5zaXplcyxcbiAgICBmaWx0ZXJzOiBkYXRhLmZpbHRlcnMsXG4gIH0pKTtcblxuYXN5bmMgZnVuY3Rpb24gZXJyb3JSZXNwb25zZUJvZHkoZXJyb3I6IFJlc3BvbnNlRXJyb3IpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgZXJyb3IucmVzcG9uc2UuanNvbigpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4ge307XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gdGhyb3dTZXNzaW9uUmVzdGFydFJlcXVpcmVkSWYoZXJyb3JNc2c6IHN0cmluZywgZXJyb3I6IHVua25vd24pIHtcbiAgaWYgKCEoZXJyb3IgaW5zdGFuY2VvZiBSZXNwb25zZUVycm9yKSkge1xuICAgIExvZ2dlci5sb2dJbmZvKGVycm9yTXNnLCBlcnJvcik7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICBjb25zdCBlcnJvclJlc3BvbnNlID0gYXdhaXQgZXJyb3JSZXNwb25zZUJvZHkoZXJyb3IpO1xuICBpZiAoXG4gICAgZXJyb3JSZXNwb25zZT8ubWVzc2FnZT8udG9Mb3dlckNhc2UoKSA9PT0gXCJ1bnN1cHBvcnRlZCBwcm9kdWN0XCIgfHxcbiAgICBlcnJvclJlc3BvbnNlPy5hcHBfY29kZT8udG9VcHBlckNhc2UoKSA9PT0gXCJQUk9EVUNUX05PVF9GT1VORFwiXG4gICkge1xuICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZFByb2R1Y3RFeGNlcHRpb24oKTtcbiAgfSBlbHNlIGlmIChcbiAgICBlcnJvclJlc3BvbnNlPy5hcHBfY29kZT8udG9VcHBlckNhc2UoKSA9PT0gXCJSRVNUQVJUX1NFU1NJT05cIiB8fFxuICAgIGVycm9yUmVzcG9uc2U/LnN1Yl9jb2RlPy50b1VwcGVyQ2FzZSgpID09PSBcIk5PVF9GT1VORFwiXG4gICkge1xuICAgIExvZ2dlci5sb2dJbmZvKFxuICAgICAgXCJTZXNzaW9uIGRvZXMgbm90IGV4aXN0LiBSZS1zdGFydCBzZXNzaW9uXCIsXG4gICAgICBlcnJvcixcbiAgICAgIGVycm9yLnJlc3BvbnNlLFxuICAgICAgZXJyb3JSZXNwb25zZVxuICAgICk7XG4gICAgdGhyb3cgbmV3IFNlc3Npb25SZXN0YXJ0UmVxdWlyZWQoKTtcbiAgfVxuXG4gIExvZ2dlci5sb2dJbmZvKGVycm9yTXNnLCBlcnJvcik7XG4gIHRocm93IGVycm9yO1xufVxuXG5pbnRlcmZhY2UgU2VhcmNoQ29udGV4dFZhbHVlIHtcbiAgc2VhcmNoUHJvZHVjdHM6IChwYXJhbXM6IFNlYXJjaFBhcmFtcykgPT4gUHJvbWlzZTxTZWFyY2hSZXN1bHQ+O1xuICBpc1JlYWR5OiBib29sZWFuO1xufVxuXG5jb25zdCBTZWFyY2hDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxTZWFyY2hDb250ZXh0VmFsdWUgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG5cbmV4cG9ydCBjb25zdCBTZWFyY2hQcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+ID0gKHtcbiAgY2hpbGRyZW4sXG59KSA9PiB7XG4gIGNvbnN0IHsgb3JnTGV2ZWxBcGlLZXksIHB1YmxpY0tleSB9ID0gdXNlRW52aXZlQ29uZmlnKCk7XG4gIGNvbnN0IGFwaUtleSA9IG9yZ0xldmVsQXBpS2V5IHx8IHB1YmxpY0tleTsgLy8gUmVwbGljYXRlIGFwaUtleUF0b20gbG9naWNcbiAgY29uc3QgYXBwRGV0YWlscyA9IHVzZUFwcERldGFpbHMoKTtcbiAgY29uc3QgYmFzZVVybCA9IHVzZUF0b21WYWx1ZShiYXNlVXJsQXRvbSk7XG5cbiAgY29uc3QgaXNSZWFkeSA9IEJvb2xlYW4oYXBpS2V5ICYmIGFwcERldGFpbHMgJiYgYmFzZVVybCk7XG5cbiAgY29uc3Qgc2VhcmNoQXBpID0gdXNlTWVtbygoKSA9PiB7XG4gICAgaWYgKCFpc1JlYWR5KSByZXR1cm4gbnVsbDtcblxuICAgIGNvbnN0IGNvbmZpZzogQ29uZmlndXJhdGlvbiA9IG5ldyBDb25maWd1cmF0aW9uKHtcbiAgICAgIGFjY2Vzc1Rva2VuOiBhcGlLZXksXG4gICAgICBiYXNlUGF0aDogYmFzZVVybCxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgIEFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIHJldHVybiBuZXcgU2VhcmNoQXBpKGNvbmZpZyk7XG4gIH0sIFthcGlLZXksIGJhc2VVcmwsIGlzUmVhZHldKTtcblxuICBjb25zdCBzZWFyY2hQcm9kdWN0cyA9IHVzZUNhbGxiYWNrKFxuICAgIGFzeW5jIChwYXJhbXM6IFNlYXJjaFBhcmFtcyk6IFByb21pc2U8U2VhcmNoUmVzdWx0PiA9PiB7XG4gICAgICBpZiAoIWlzUmVhZHkgfHwgIXNlYXJjaEFwaSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTZWFyY2hTZXJ2aWNlIG5vdCByZWFkeSAtIG1pc3NpbmcgZGVwZW5kZW5jaWVzXCIpO1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHNlYXJjaEFwaS52MVNlYXJjaFF1ZXJ5R2V0KHtcbiAgICAgICAgICBxdWVyeTogcGFyYW1zLnF1ZXJ5LFxuICAgICAgICAgIGxpbWl0OiBwYXJhbXMubGltaXQsXG4gICAgICAgICAgb3JnX2lkOiBhcHBEZXRhaWxzLm9yZ0lkLFxuICAgICAgICAgIHVzZXJfaWQ6IGFwcERldGFpbHMudXNlcklkLFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3Qge1xuICAgICAgICAgIHByb2R1Y3RzLFxuICAgICAgICAgIGZpbHRlcnMsXG4gICAgICAgICAgc2VhcmNoX3Jlc3BvbnNlX2lkOiBzZWFyY2hSZXNwb25zZUlkLFxuICAgICAgICB9ID0gcmVzcG9uc2U7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBwcm9kdWN0czogdHJhbnNmb3JtUHJvZHVjdFJlc3BvbnNlcyhwcm9kdWN0cykgfHwgW10sXG4gICAgICAgICAgZmlsdGVyczogZmlsdGVycyB8fCBbXSxcbiAgICAgICAgICB0b3RhbFByb2R1Y3RDb3VudDogcHJvZHVjdHM/Lmxlbmd0aCB8fCAwLFxuICAgICAgICAgIHNlYXJjaFJlc3BvbnNlSWQ6IHNlYXJjaFJlc3BvbnNlSWQgfHwgXCJcIixcbiAgICAgICAgfTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGF3YWl0IHRocm93U2Vzc2lvblJlc3RhcnRSZXF1aXJlZElmKFwiRmFpbGVkIHRvIHNlYXJjaCBwcm9kdWN0c1wiLCBlcnJvcik7XG4gICAgICAgIC8vIFRoaXMgcGFydCB3aWxsIG5vdCBiZSByZWFjaGVkIGlmIGFuIGV4Y2VwdGlvbiBpcyB0aHJvd24sIGJ1dCBpdCdzIHJlcXVpcmVkIGZvciB0eXBlIHNhZmV0eVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHByb2R1Y3RzOiBbXSxcbiAgICAgICAgICBmaWx0ZXJzOiBbXSxcbiAgICAgICAgICB0b3RhbFByb2R1Y3RDb3VudDogMCxcbiAgICAgICAgICBzZWFyY2hSZXNwb25zZUlkOiBcIlwiLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0sXG4gICAgW3NlYXJjaEFwaSwgaXNSZWFkeSwgYXBwRGV0YWlsc11cbiAgKTtcblxuICAvLyBSZWdpc3RlciB0aGUgc2VhcmNoIGZ1bmN0aW9uIHdpdGggdGhlIGFkYXB0ZXIgZm9yIHVzZSBpbiBhdG9tc1xuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmIChpc1JlYWR5KSB7XG4gICAgICBzZXRTZWFyY2hTZXJ2aWNlRnVuY3Rpb24oc2VhcmNoUHJvZHVjdHMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjbGVhclNlYXJjaFNlcnZpY2VGdW5jdGlvbigpO1xuICAgIH1cblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBjbGVhclNlYXJjaFNlcnZpY2VGdW5jdGlvbigpO1xuICAgIH07XG4gIH0sIFtzZWFyY2hQcm9kdWN0cywgaXNSZWFkeV0pO1xuXG4gIGNvbnN0IHZhbHVlID0gdXNlTWVtbyhcbiAgICAoKSA9PiAoe1xuICAgICAgc2VhcmNoUHJvZHVjdHMsXG4gICAgICBpc1JlYWR5LFxuICAgIH0pLFxuICAgIFtzZWFyY2hQcm9kdWN0cywgaXNSZWFkeV1cbiAgKTtcblxuICByZXR1cm4gKFxuICAgIDxTZWFyY2hDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXt2YWx1ZX0+e2NoaWxkcmVufTwvU2VhcmNoQ29udGV4dC5Qcm92aWRlcj5cbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VTZWFyY2hTZXJ2aWNlID0gKCkgPT4ge1xuICBjb25zdCBjb250ZXh0ID0gdXNlQ29udGV4dChTZWFyY2hDb250ZXh0KTtcbiAgaWYgKCFjb250ZXh0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwidXNlU2VhcmNoU2VydmljZSBtdXN0IGJlIHVzZWQgd2l0aGluIGEgU2VhcmNoUHJvdmlkZXJcIik7XG4gIH1cbiAgcmV0dXJuIGNvbnRleHQ7XG59O1xuIiwiaW1wb3J0IHsgdXNlU3RhdGUsIHVzZUNhbGxiYWNrLCB1c2VFZmZlY3QgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZVNlYXJjaFNlcnZpY2UgfSBmcm9tIFwic3JjL2NvbnRleHRzL3NlYXJjaENvbnRleHRcIjtcbmltcG9ydCB7IFNlYXJjaFJlc3VsdCwgU2VhcmNoUGFyYW1zIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvYXBpL3NlYXJjaFwiO1xuXG5leHBvcnQgY29uc3QgdXNlUHJvZHVjdFNlYXJjaCA9ICgpID0+IHtcbiAgY29uc3QgeyBzZWFyY2hQcm9kdWN0cywgaXNSZWFkeSB9ID0gdXNlU2VhcmNoU2VydmljZSgpO1xuICBjb25zdCBbZGF0YSwgc2V0RGF0YV0gPSB1c2VTdGF0ZTxTZWFyY2hSZXN1bHQgfCB1bmRlZmluZWQ+KCk7XG4gIGNvbnN0IFtsb2FkaW5nLCBzZXRMb2FkaW5nXSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgY29uc3QgW2Vycm9yLCBzZXRFcnJvcl0gPSB1c2VTdGF0ZTxFcnJvciB8IG51bGw+KG51bGwpO1xuXG4gIGNvbnN0IHNlYXJjaCA9IHVzZUNhbGxiYWNrKFxuICAgIGFzeW5jIChwYXJhbXM6IFNlYXJjaFBhcmFtcykgPT4ge1xuICAgICAgaWYgKCFpc1JlYWR5KSB7XG4gICAgICAgIHNldEVycm9yKG5ldyBFcnJvcihcIlNlYXJjaCBzZXJ2aWNlIG5vdCByZWFkeSAtIG1pc3NpbmcgZGVwZW5kZW5jaWVzXCIpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBzZXRMb2FkaW5nKHRydWUpO1xuICAgICAgc2V0RXJyb3IobnVsbCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNlYXJjaFByb2R1Y3RzKHBhcmFtcyk7XG4gICAgICAgIHNldERhdGEocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBzZXRFcnJvcihcbiAgICAgICAgICBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyciA6IG5ldyBFcnJvcihcIlVua25vd24gc2VhcmNoIGVycm9yXCIpXG4gICAgICAgICk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBzZXRMb2FkaW5nKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtzZWFyY2hQcm9kdWN0cywgaXNSZWFkeV1cbiAgKTtcblxuICBjb25zdCByZXNldCA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICBzZXREYXRhKHVuZGVmaW5lZCk7XG4gICAgc2V0RXJyb3IobnVsbCk7XG4gICAgc2V0TG9hZGluZyhmYWxzZSk7XG4gIH0sIFtdKTtcblxuICByZXR1cm4ge1xuICAgIGRhdGEsXG4gICAgbG9hZGluZyxcbiAgICBlcnJvcixcbiAgICBzZWFyY2gsXG4gICAgcmVzZXQsXG4gICAgaXNSZWFkeSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VTZWFyY2hXaXRoUXVlcnkgPSAocGFyYW1zOiBTZWFyY2hQYXJhbXMgfCBudWxsKSA9PiB7XG4gIGNvbnN0IHsgc2VhcmNoUHJvZHVjdHMsIGlzUmVhZHkgfSA9IHVzZVNlYXJjaFNlcnZpY2UoKTtcbiAgY29uc3QgW2RhdGEsIHNldERhdGFdID0gdXNlU3RhdGU8U2VhcmNoUmVzdWx0IHwgdW5kZWZpbmVkPigpO1xuICBjb25zdCBbbG9hZGluZywgc2V0TG9hZGluZ10gPSB1c2VTdGF0ZShmYWxzZSk7XG4gIGNvbnN0IFtlcnJvciwgc2V0RXJyb3JdID0gdXNlU3RhdGU8RXJyb3IgfCBudWxsPihudWxsKTtcblxuICBjb25zdCBleGVjdXRlU2VhcmNoID0gdXNlQ2FsbGJhY2soXG4gICAgYXN5bmMgKHNlYXJjaFBhcmFtczogU2VhcmNoUGFyYW1zKSA9PiB7XG4gICAgICBpZiAoIWlzUmVhZHkpIHJldHVybjtcblxuICAgICAgc2V0TG9hZGluZyh0cnVlKTtcbiAgICAgIHNldEVycm9yKG51bGwpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzZWFyY2hQcm9kdWN0cyhzZWFyY2hQYXJhbXMpO1xuICAgICAgICBzZXREYXRhKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgc2V0RXJyb3IoXG4gICAgICAgICAgZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIgOiBuZXcgRXJyb3IoXCJVbmtub3duIHNlYXJjaCBlcnJvclwiKVxuICAgICAgICApO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgc2V0TG9hZGluZyhmYWxzZSk7XG4gICAgICB9XG4gICAgfSxcbiAgICBbc2VhcmNoUHJvZHVjdHMsIGlzUmVhZHldXG4gICk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAocGFyYW1zICYmIGlzUmVhZHkpIHtcbiAgICAgIGV4ZWN1dGVTZWFyY2gocGFyYW1zKTtcbiAgICB9XG4gIH0sIFtwYXJhbXMsIGlzUmVhZHksIGV4ZWN1dGVTZWFyY2hdKTtcblxuICBjb25zdCByZWZldGNoID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGlmIChwYXJhbXMpIHtcbiAgICAgIGV4ZWN1dGVTZWFyY2gocGFyYW1zKTtcbiAgICB9XG4gIH0sIFtwYXJhbXMsIGV4ZWN1dGVTZWFyY2hdKTtcblxuICByZXR1cm4ge1xuICAgIGRhdGEsXG4gICAgbG9hZGluZyxcbiAgICBlcnJvcixcbiAgICByZWZldGNoLFxuICAgIGlzUmVhZHksXG4gIH07XG59O1xuIiwiaW1wb3J0IFJlYWN0LCB7XG4gIGNyZWF0ZUNvbnRleHQsXG4gIHVzZUNvbnRleHQsXG4gIHVzZUNhbGxiYWNrLFxuICB1c2VNZW1vLFxuICB1c2VFZmZlY3QsXG59IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IExvZ2dlciBmcm9tIFwiLi4vYXBwbGljYXRpb24vbG9nZ2luZy9sb2dnZXJcIjtcblxuaW50ZXJmYWNlIFNlc3Npb25TdG9yYWdlQ29udGV4dFR5cGUge1xuICBzZXRJdGVtOiAoa2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpID0+IHZvaWQ7XG4gIGdldEl0ZW06IChrZXk6IHN0cmluZykgPT4gc3RyaW5nIHwgbnVsbDtcbiAgaXNBdmFpbGFibGU6IGJvb2xlYW47XG59XG5cbmNvbnN0IFNlc3Npb25TdG9yYWdlQ29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8U2Vzc2lvblN0b3JhZ2VDb250ZXh0VHlwZSB8IG51bGw+KFxuICBudWxsXG4pO1xuXG5leHBvcnQgY29uc3QgU2Vzc2lvblN0b3JhZ2VQcm92aWRlcjogUmVhY3QuRkM8e1xuICBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlO1xufT4gPSAoeyBjaGlsZHJlbiB9KSA9PiB7XG4gIGNvbnN0IGlzQXZhaWxhYmxlID0gdXNlTWVtbygoKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiICYmICEhd2luZG93LnNlc3Npb25TdG9yYWdlO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfSwgW10pO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKCFpc0F2YWlsYWJsZSkge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFwic2Vzc2lvblN0b3JhZ2UgaXMgbm90IGF2YWlsYWJsZVwiLCB1bmRlZmluZWQpO1xuICAgIH1cbiAgfSwgW2lzQXZhaWxhYmxlXSk7XG5cbiAgY29uc3Qgc2V0SXRlbSA9IHVzZUNhbGxiYWNrKFxuICAgIChrZXk6IHN0cmluZywgdmFsdWU6IHN0cmluZykgPT4ge1xuICAgICAgaWYgKCFpc0F2YWlsYWJsZSkgcmV0dXJuO1xuICAgICAgc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbShrZXksIHZhbHVlKTtcbiAgICAgIHdpbmRvdy5kaXNwYXRjaEV2ZW50KFxuICAgICAgICBuZXcgU3RvcmFnZUV2ZW50KFwic3RvcmFnZVwiLCB7IGtleSwgbmV3VmFsdWU6IHZhbHVlIH0pXG4gICAgICApO1xuICAgIH0sXG4gICAgW2lzQXZhaWxhYmxlXVxuICApO1xuXG4gIGNvbnN0IGdldEl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICAoa2V5OiBzdHJpbmcpID0+IHtcbiAgICAgIGlmICghaXNBdmFpbGFibGUpIHJldHVybiBudWxsO1xuICAgICAgcmV0dXJuIHNlc3Npb25TdG9yYWdlLmdldEl0ZW0oa2V5KTtcbiAgICB9LFxuICAgIFtpc0F2YWlsYWJsZV1cbiAgKTtcblxuICBjb25zdCB2YWx1ZSA9IHVzZU1lbW8oXG4gICAgKCkgPT4gKHtcbiAgICAgIHNldEl0ZW0sXG4gICAgICBnZXRJdGVtLFxuICAgICAgaXNBdmFpbGFibGUsXG4gICAgfSksXG4gICAgW3NldEl0ZW0sIGdldEl0ZW0sIGlzQXZhaWxhYmxlXVxuICApO1xuXG4gIHJldHVybiAoXG4gICAgPFNlc3Npb25TdG9yYWdlQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17dmFsdWV9PlxuICAgICAge2NoaWxkcmVufVxuICAgIDwvU2Vzc2lvblN0b3JhZ2VDb250ZXh0LlByb3ZpZGVyPlxuICApO1xufTtcblxuZXhwb3J0IGNvbnN0IHVzZVNlc3Npb25TdG9yYWdlID0gKCkgPT4ge1xuICBjb25zdCBjb250ZXh0ID0gdXNlQ29udGV4dChTZXNzaW9uU3RvcmFnZUNvbnRleHQpO1xuICBpZiAoIWNvbnRleHQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBcInVzZVNlc3Npb25TdG9yYWdlIG11c3QgYmUgdXNlZCB3aXRoaW4gYSBTZXNzaW9uU3RvcmFnZVByb3ZpZGVyXCJcbiAgICApO1xuICB9XG4gIHJldHVybiBjb250ZXh0O1xufTtcbiIsImltcG9ydCB7IHVzZVN0YXRlLCB1c2VFZmZlY3QsIHVzZUNhbGxiYWNrIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyB1c2VTZXNzaW9uU3RvcmFnZSB9IGZyb20gXCIuLi9jb250ZXh0cy9zZXNzaW9uU3RvcmFnZUNvbnRleHRcIjtcblxuZXhwb3J0IGNvbnN0IHVzZVNlc3Npb25TdG9yYWdlVmFsdWUgPSAoa2V5OiBzdHJpbmcpID0+IHtcbiAgY29uc3QgeyBnZXRJdGVtLCBzZXRJdGVtIH0gPSB1c2VTZXNzaW9uU3RvcmFnZSgpO1xuICBjb25zdCBbdmFsdWUsIHNldFZhbHVlXSA9IHVzZVN0YXRlPHN0cmluZyB8IG51bGw+KCgpID0+IGdldEl0ZW0oa2V5KSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBoYW5kbGVTdG9yYWdlQ2hhbmdlID0gKGV2ZW50OiBTdG9yYWdlRXZlbnQpID0+IHtcbiAgICAgIGlmIChldmVudC5rZXkgPT09IGtleSkge1xuICAgICAgICBzZXRWYWx1ZShldmVudC5uZXdWYWx1ZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwic3RvcmFnZVwiLCBoYW5kbGVTdG9yYWdlQ2hhbmdlKTtcbiAgICByZXR1cm4gKCkgPT4gd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJzdG9yYWdlXCIsIGhhbmRsZVN0b3JhZ2VDaGFuZ2UpO1xuICB9LCBba2V5LCBnZXRJdGVtXSk7XG5cbiAgY29uc3QgdXBkYXRlVmFsdWUgPSB1c2VDYWxsYmFjayhcbiAgICAobmV3VmFsdWU6IHN0cmluZykgPT4ge1xuICAgICAgc2V0SXRlbShrZXksIG5ld1ZhbHVlKTtcbiAgICAgIHNldFZhbHVlKG5ld1ZhbHVlKTtcbiAgICB9LFxuICAgIFtrZXksIHNldEl0ZW1dXG4gICk7XG5cbiAgcmV0dXJuIHsgdmFsdWUsIHNldFZhbHVlOiB1cGRhdGVWYWx1ZSB9O1xufTtcbiIsImltcG9ydCBSZWFjdCwgeyBjcmVhdGVDb250ZXh0LCB1c2VDYWxsYmFjaywgdXNlQ29udGV4dCwgdXNlTWVtbyB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgSWRFeHRyYWN0b3IgfSBmcm9tIFwic3JjL2NvbnRleHRzL3R5cGVzXCI7XG5pbXBvcnQgeyBwYXJzZUhyZWYgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL3V0aWxzL3VybHNQYXJzZXJcIjtcblxuaW50ZXJmYWNlIFNob3BpZnlVcmxDb250ZXh0VHlwZSB7XG4gIGdldFRyaW1tZWRQYXRoTmFtZTogKCkgPT4gc3RyaW5nIHwgbnVsbDtcbiAgZ2V0UGxwT3JQZHBJZDogKGV4dHJhY3RvcjogSWRFeHRyYWN0b3IpID0+IHN0cmluZyB8IG51bGw7XG4gIGlzT25QZHBQYWdlOiAoKSA9PiBib29sZWFuO1xuICBpc09uUGxwUGFnZTogKCkgPT4gYm9vbGVhbjtcbiAgaXNSZWFkeTogYm9vbGVhbjtcbn1cblxuY29uc3QgU2hvcGlmeVVybENvbnRleHQgPSBjcmVhdGVDb250ZXh0PFNob3BpZnlVcmxDb250ZXh0VHlwZSB8IHVuZGVmaW5lZD4oXG4gIHVuZGVmaW5lZFxuKTtcblxuZXhwb3J0IGNvbnN0IFNob3BpZnlVcmxQcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+ID0gKHtcbiAgY2hpbGRyZW4sXG59KSA9PiB7XG4gIGNvbnN0IGlzUmVhZHkgPSB0cnVlOyAvLyBObyBleHRlcm5hbCBkZXBlbmRlbmNpZXMsIHNvIGFsd2F5cyByZWFkeVxuXG4gIGNvbnN0IGdldFRyaW1tZWRQYXRoTmFtZSA9IHVzZUNhbGxiYWNrKCgpOiBzdHJpbmcgfCBudWxsID0+IHtcbiAgICBsZXQgeyBwYXRobmFtZSB9ID0gd2luZG93LmxvY2F0aW9uO1xuICAgIC8vIHN0cmlwIG91dCB0aGUgcHJveHkgcGF0aCBzbyBsb2NhbCBkZXYgc3RpbGwgd29ya3NcbiAgICBwYXRobmFtZSA9IHBhdGhuYW1lLnJlcGxhY2UoXCIvcHJveHlcIiwgXCJcIik7XG4gICAgLy8gcmVtb3ZlIHRyYWlsaW5nIGhhc2ggaWYgaXQgZXhpc3RzXG4gICAgcGF0aG5hbWUgPSBwYXRobmFtZS5yZXBsYWNlKC8jLiokLywgXCJcIik7XG4gICAgLy8gcmVtb3ZlIHRyYWlsaW5nIC8sIGllLiBzb21lIFVSTHMgY2FuIGVuZCB3aXRoICcvJyBsaWtlIC9jb2xsZWN0aW9ucy9jYXN0LWlyb24vXG4gICAgcGF0aG5hbWUgPSBwYXRobmFtZS5yZXBsYWNlKC9cXC8kLywgXCJcIik7XG5cbiAgICBpZiAocGF0aG5hbWUgPT09IHVuZGVmaW5lZCB8fCBwYXRobmFtZSA9PT0gbnVsbCB8fCBwYXRobmFtZS5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBwYXRobmFtZTtcbiAgfSwgW10pO1xuXG4gIGNvbnN0IGdldFBscE9yUGRwSWQgPSB1c2VDYWxsYmFjayhcbiAgICAoZXh0cmFjdG9yOiBJZEV4dHJhY3Rvcik6IHN0cmluZyB8IG51bGwgPT4ge1xuICAgICAgaWYgKGV4dHJhY3RvciA9PT0gXCJzaG9waWZ5LXByb2R1Y3QtdmFyaWFudC1pZFwiKSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZEhyZWYgPSBwYXJzZUhyZWYod2luZG93LmxvY2F0aW9uLmhyZWYpO1xuICAgICAgICBjb25zdCB2YXJpYW50SWQgPSBwYXJzZWRIcmVmPy51cmxTZWFyY2hQYXJhbXM/LmdldChcInZhcmlhbnRcIik7XG4gICAgICAgIGlmICghdmFyaWFudElkKSB7XG4gICAgICAgICAgcmV0dXJuIGdldFBscE9yUGRwSWQoXCJzaG9waWZ5LXByb2R1Y3QtaWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhcmlhbnRJZDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcGF0aFNlZ21lbnQgPVxuICAgICAgICBleHRyYWN0b3IgPT09IFwic2hvcGlmeS1wcm9kdWN0LWlkXCIgPyBcInByb2R1Y3RzXCIgOiBcImNvbGxlY3Rpb25zXCI7XG4gICAgICBjb25zdCB0b2tlbnMgPSBnZXRUcmltbWVkUGF0aE5hbWUoKT8uc3BsaXQoXCIvXCIpO1xuICAgICAgY29uc3QgaWRJbmRleCA9IHRva2Vucz8uZmluZEluZGV4KCh0b2tlbikgPT4gdG9rZW4gPT09IHBhdGhTZWdtZW50KTtcbiAgICAgIGlmIChpZEluZGV4ICE9PSB1bmRlZmluZWQgJiYgaWRJbmRleCA+PSAwICYmIHRva2Vucykge1xuICAgICAgICByZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KHRva2Vuc1tpZEluZGV4ICsgMV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSxcbiAgICBbZ2V0VHJpbW1lZFBhdGhOYW1lXVxuICApO1xuXG4gIGNvbnN0IGlzT25QZHBQYWdlID0gdXNlQ2FsbGJhY2soKCk6IGJvb2xlYW4gPT4ge1xuICAgIHJldHVybiBnZXRUcmltbWVkUGF0aE5hbWUoKT8uaW5jbHVkZXMoXCIvcHJvZHVjdHNcIikgPz8gZmFsc2U7XG4gIH0sIFtnZXRUcmltbWVkUGF0aE5hbWVdKTtcblxuICBjb25zdCBpc09uUGxwUGFnZSA9IHVzZUNhbGxiYWNrKCgpOiBib29sZWFuID0+IHtcbiAgICByZXR1cm4gKFxuICAgICAgKGdldFRyaW1tZWRQYXRoTmFtZSgpPy5pbmNsdWRlcyhcIi9jb2xsZWN0aW9uc1wiKSAmJlxuICAgICAgICAhZ2V0VHJpbW1lZFBhdGhOYW1lKCk/LmluY2x1ZGVzKFwiL3Byb2R1Y3RzXCIpKSA/P1xuICAgICAgZmFsc2VcbiAgICApO1xuICB9LCBbZ2V0VHJpbW1lZFBhdGhOYW1lXSk7XG5cbiAgY29uc3QgdmFsdWUgPSB1c2VNZW1vKFxuICAgICgpID0+ICh7XG4gICAgICBnZXRUcmltbWVkUGF0aE5hbWUsXG4gICAgICBnZXRQbHBPclBkcElkLFxuICAgICAgaXNPblBkcFBhZ2UsXG4gICAgICBpc09uUGxwUGFnZSxcbiAgICAgIGlzUmVhZHksXG4gICAgfSksXG4gICAgW2dldFRyaW1tZWRQYXRoTmFtZSwgZ2V0UGxwT3JQZHBJZCwgaXNPblBkcFBhZ2UsIGlzT25QbHBQYWdlLCBpc1JlYWR5XVxuICApO1xuXG4gIHJldHVybiAoXG4gICAgPFNob3BpZnlVcmxDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXt2YWx1ZX0+XG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC9TaG9waWZ5VXJsQ29udGV4dC5Qcm92aWRlcj5cbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VTaG9waWZ5VXJsID0gKCkgPT4ge1xuICBjb25zdCBjb250ZXh0ID0gdXNlQ29udGV4dChTaG9waWZ5VXJsQ29udGV4dCk7XG4gIGlmICghY29udGV4dCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcInVzZVNob3BpZnlVcmwgbXVzdCBiZSB1c2VkIHdpdGhpbiBhIFNob3BpZnlVcmxQcm92aWRlclwiKTtcbiAgfVxuICByZXR1cm4gY29udGV4dDtcbn07XG4iLCJpbXBvcnQgeyB1c2VDYWxsYmFjayB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgdXNlU2hvcGlmeVVybCB9IGZyb20gXCJzcmMvY29udGV4dHMvc2hvcGlmeVVybENvbnRleHRcIjtcbmltcG9ydCB7IElkRXh0cmFjdG9yIH0gZnJvbSBcInNyYy9jb250ZXh0cy90eXBlc1wiO1xuXG5leHBvcnQgY29uc3QgdXNlU2hvcGlmeVVybE9wZXJhdGlvbnMgPSAoKSA9PiB7XG4gIGNvbnN0IHtcbiAgICBnZXRUcmltbWVkUGF0aE5hbWUsXG4gICAgZ2V0UGxwT3JQZHBJZCxcbiAgICBpc09uUGRwUGFnZSxcbiAgICBpc09uUGxwUGFnZSxcbiAgICBpc1JlYWR5LFxuICB9ID0gdXNlU2hvcGlmeVVybCgpO1xuXG4gIHJldHVybiB7XG4gICAgZ2V0VHJpbW1lZFBhdGhOYW1lLFxuICAgIGdldFBscE9yUGRwSWQsXG4gICAgaXNPblBkcFBhZ2UsXG4gICAgaXNPblBscFBhZ2UsXG4gICAgaXNSZWFkeSxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VDdXJyZW50UGFnZVR5cGUgPSAoKSA9PiB7XG4gIGNvbnN0IHsgaXNPblBkcFBhZ2UsIGlzT25QbHBQYWdlLCBpc1JlYWR5IH0gPSB1c2VTaG9waWZ5VXJsKCk7XG5cbiAgY29uc3QgZ2V0UGFnZVR5cGUgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgaWYgKCFpc1JlYWR5KSByZXR1cm4gXCJ1bmtub3duXCI7XG4gICAgaWYgKGlzT25QZHBQYWdlKCkpIHJldHVybiBcInBkcFwiO1xuICAgIGlmIChpc09uUGxwUGFnZSgpKSByZXR1cm4gXCJwbHBcIjtcbiAgICByZXR1cm4gXCJvdGhlclwiO1xuICB9LCBbaXNSZWFkeSwgaXNPblBkcFBhZ2UsIGlzT25QbHBQYWdlXSk7XG5cbiAgcmV0dXJuIHsgZ2V0UGFnZVR5cGUsIGlzUmVhZHkgfTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VQcm9kdWN0SWQgPSAoZXh0cmFjdG9yOiBJZEV4dHJhY3RvcikgPT4ge1xuICBjb25zdCB7IGdldFBscE9yUGRwSWQsIGlzUmVhZHkgfSA9IHVzZVNob3BpZnlVcmwoKTtcblxuICBjb25zdCBwcm9kdWN0SWQgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgaWYgKCFpc1JlYWR5KSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4gZ2V0UGxwT3JQZHBJZChleHRyYWN0b3IpO1xuICB9LCBbaXNSZWFkeSwgZ2V0UGxwT3JQZHBJZCwgZXh0cmFjdG9yXSk7XG5cbiAgcmV0dXJuIHsgcHJvZHVjdElkLCBpc1JlYWR5IH07XG59O1xuIiwiaW1wb3J0IHsgdXNlTWVtbyB9IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IHR5cGUgVW5pdCA9ICdwZXJjZW50JyB8ICdwaXhlbCc7XG5cbmV4cG9ydCBjb25zdCB1c2VTbmFwQ2FsY3VsYXRvciA9IChzbmFwczogbnVtYmVyW10sIG1heEhlaWdodDogbnVtYmVyLCB1bml0OiBVbml0KSA9PiB7XG4gIGNvbnN0IHZpZXdwb3J0SGVpZ2h0UHggPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICBjb25zdCBzd2lwZXZpZXdIZWlnaHRQeCA9XG4gICAgdW5pdCA9PT0gJ3BlcmNlbnQnID8gTWF0aC5mbG9vcih2aWV3cG9ydEhlaWdodFB4ICogKG1heEhlaWdodCAvIDEwMCkpIDogbWF4SGVpZ2h0O1xuXG4gIGNvbnN0IHNuYXBzVG9QaXhlbHMgPSB1c2VNZW1vKFxuICAgICgpID0+XG4gICAgICBzbmFwcz8ubWFwKChzbmFwKSA9PlxuICAgICAgICBNYXRoLmFicyhcbiAgICAgICAgICAodW5pdCA9PT0gJ3BlcmNlbnQnID8gTWF0aC5mbG9vcihzd2lwZXZpZXdIZWlnaHRQeCAqIChzbmFwIC8gMTAwKSkgOiBzbmFwKSAtXG4gICAgICAgICAgICBzd2lwZXZpZXdIZWlnaHRQeCxcbiAgICAgICAgKSxcbiAgICAgICksXG4gICAgW3ZpZXdwb3J0SGVpZ2h0UHhdLFxuICApO1xuXG4gIGNvbnN0IGdldFBpeGVsVG9TbmFwID0gKHBpeGVsczogbnVtYmVyKSA9PiB7XG4gICAgY29uc3Qgc25hcElkeCA9IHNuYXBzVG9QaXhlbHM/LmluZGV4T2YocGl4ZWxzKSB8fCAwO1xuICAgIHJldHVybiBzbmFwcz8uW3NuYXBJZHhdIHx8IDA7XG4gIH07XG5cbiAgY29uc3QgZ2V0U25hcFRvUGl4ZWwgPSAoc25hcDogbnVtYmVyKSA9PiB7XG4gICAgY29uc3Qgc25hcElkeCA9IHNuYXBzPy5pbmRleE9mKHNuYXApIHx8IDA7XG4gICAgcmV0dXJuIHNuYXBzVG9QaXhlbHM/LltzbmFwSWR4XSB8fCAwO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgdmlld3BvcnRIZWlnaHRQeCxcbiAgICBzbmFwc1RvUGl4ZWxzLFxuICAgIHN3aXBldmlld0hlaWdodFB4LFxuICAgIGdldFBpeGVsVG9TbmFwLFxuICAgIGdldFNuYXBUb1BpeGVsLFxuICB9O1xufTtcbiIsImltcG9ydCB7IHVzZUNvbnRleHQgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBTeXN0ZW1TZXR0aW5nc0NvbnRleHQgfSBmcm9tICdzcmMvY29udGV4dHMnO1xuXG5leHBvcnQgY29uc3QgdXNlU3lzdGVtU2V0dGluZ3NDb250ZXh0ID0gKCkgPT4ge1xuICBjb25zdCBjb250ZXh0ID0gdXNlQ29udGV4dChTeXN0ZW1TZXR0aW5nc0NvbnRleHQpO1xuXG4gIGlmICghY29udGV4dCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXNlU3lzdGVtU2V0dGluZ3NDb250ZXh0IG11c3QgYmUgdXNlZCB3aXRoaW4gYSBTeXN0ZW1TZXR0aW5nc0NvbnRleHRQcm92aWRlcicpO1xuICB9XG5cbiAgcmV0dXJuIHsgLi4uY29udGV4dCB9O1xufTtcbiIsImltcG9ydCB7IFJlZk9iamVjdCwgdXNlRWZmZWN0LCB1c2VSZWYgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IFNwaWZmeVdpZGdldHMgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVscy9zcGlmZnlXaWRnZXRzXCI7XG5pbXBvcnQgeyB1c2VJbnRlcnNlY3Rpb24gfSBmcm9tIFwic3JjL2hvb2tzL3VzZUludGVyc2VjdGlvblwiO1xuaW1wb3J0IHtcbiAgU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSxcbiAgdXNlQW1wbGl0dWRlLFxufSBmcm9tIFwic3JjL2NvbnRleHRzL2FtcGxpdHVkZUNvbnRleHRcIjtcblxuLyoqXG4gKiBUcmFja3MgYSBjb21wb25lbnQgYW5kIGxvZ3MgYW4gZXZlbnQgdG8gQW1wbGl0dWRlIHdoZW4gdGhlIGNvbXBvbmVudCBpcyB2aXNpYmxlLlxuICpcbiAqIEBwYXJhbSBjb21wb25lbnQgLSBUaGUgY29tcG9uZW50IHRvIHRyYWNrLlxuICogQHBhcmFtIGVsZW1lbnQgLSBUaGUgZWxlbWVudCB0byB0cmFjayB2aXNpYmlsaXR5IG9mLlxuICogQHBhcmFtIGV2ZW50UHJvcHMgLSBBZGRpdGlvbmFsIHByb3BlcnRpZXMgdG8gaW5jbHVkZSB3aXRoIHRoZSBldmVudC5cbiAqIEBwYXJhbSBldmVudE5hbWUgLSBUaGUgQW1wbGl0dWRlIGV2ZW50IG5hbWUgdG8gdHJhY2sgKGRlZmF1bHRzIHRvIENoYXRDb21wb25lbnRWaXNpYmxlKS5cbiAqL1xuZXhwb3J0IGNvbnN0IHVzZVRyYWNrQ29tcG9uZW50VmlzaWJsZUV2ZW50ID0gKFxuICBjb21wb25lbnQ6IFNwaWZmeVdpZGdldHMsXG4gIGVsZW1lbnQ6IFJlZk9iamVjdDxIVE1MRWxlbWVudD4sXG4gIGV2ZW50UHJvcHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lID0gU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5DaGF0Q29tcG9uZW50VmlzaWJsZVxuKSA9PiB7XG4gIGNvbnN0IGlzVmlzaWJsZSA9IHVzZUludGVyc2VjdGlvbihlbGVtZW50LCBcIjBweFwiKTtcbiAgY29uc3QgaGFzVHJhY2tlZEV2ZW50ID0gdXNlUmVmKGZhbHNlKTtcbiAgY29uc3QgeyB0cmFja0V2ZW50IH0gPSB1c2VBbXBsaXR1ZGUoKTtcblxuICBjb25zdCBjb21wb25lbnRQcm9wcyA9ICgoKSA9PiB7XG4gICAgaWYgKGV2ZW50TmFtZSA9PT0gU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5DaGF0Q29tcG9uZW50VmlzaWJsZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY2hhdF9jb21wb25lbnQ6IGNvbXBvbmVudCxcbiAgICAgICAgLi4uZXZlbnRQcm9wcyxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmIChldmVudE5hbWUgPT09IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUuU2VhcmNoQ29tcG9uZW50VmlzaWJsZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc2VhcmNoX2NvbXBvbmVudDogY29tcG9uZW50LFxuICAgICAgICAuLi5ldmVudFByb3BzLFxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gRGVmYXVsdCBjYXNlIGZvciBvdGhlciBldmVudCB0eXBlc1xuICAgIHJldHVybiB7XG4gICAgICBjb21wb25lbnQ6IGNvbXBvbmVudCxcbiAgICAgIC4uLmV2ZW50UHJvcHMsXG4gICAgfTtcbiAgfSkoKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmIChpc1Zpc2libGUgJiYgIWhhc1RyYWNrZWRFdmVudC5jdXJyZW50KSB7XG4gICAgICB0cmFja0V2ZW50KHtcbiAgICAgICAgZXZlbnROYW1lOiBldmVudE5hbWUsXG4gICAgICAgIGV2ZW50UHJvcHM6IGNvbXBvbmVudFByb3BzLFxuICAgICAgfSk7XG4gICAgICBoYXNUcmFja2VkRXZlbnQuY3VycmVudCA9IHRydWU7XG4gICAgfVxuICB9LCBbaXNWaXNpYmxlLCBjb21wb25lbnQsIGV2ZW50UHJvcHMsIGV2ZW50TmFtZSwgY29tcG9uZW50UHJvcHMsIHRyYWNrRXZlbnRdKTtcbn07XG4iLCJpbXBvcnQgeyB1c2VBdG9tVmFsdWUgfSBmcm9tIFwiam90YWlcIjtcbmltcG9ydCB7IHVzZUVmZmVjdCwgdXNlUmVmIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQge1xuICBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLFxuICB1c2VBbXBsaXR1ZGUsXG59IGZyb20gXCJzcmMvY29udGV4dHMvYW1wbGl0dWRlQ29udGV4dFwiO1xuaW1wb3J0IHtcbiAgaGFzUGFyc2VkVmFyaWFudEluZm9BdG9tLFxuICB2YXJpYW50SW5mb0F0b20sXG59IGZyb20gXCJzcmMvYXRvbXMvYXBwL3ZhcmlhbnRcIjtcblxuLyoqXG4gKiBVcGRhdGVzIHRoZSBkZWZhdWx0IGFuYWx5dGljcyBwcm9wZXJ0aWVzIHdoZW5ldmVyIHRoZSB2YXJpYW50IGluZm8gY2hhbmdlcy4gVGhpcyBob29rIGFsc29cbiAqIHRyaWdnZXJzIGFueSBldmVudHMgdGhhdCBzaG91bGQgYmUgc2VudCBvbmNlIHBlciBwYWdlIHZpc2l0LlxuICovXG5leHBvcnQgY29uc3QgdXNlVXBkYXRlQW5hbHl0aWNzUHJvcHMgPSAoKSA9PiB7XG4gIGNvbnN0IHZhcmlhbnRJbmZvID0gdXNlQXRvbVZhbHVlKHZhcmlhbnRJbmZvQXRvbSk7XG4gIGNvbnN0IGhhc0luaXRpYWxpemVkID0gdXNlUmVmKGZhbHNlKTtcbiAgY29uc3QgaGFzUGFyc2VkVmFyaWFudEluZm8gPSB1c2VBdG9tVmFsdWUoaGFzUGFyc2VkVmFyaWFudEluZm9BdG9tKTtcbiAgY29uc3QgeyB0cmFja0V2ZW50LCBzZXRTdXBwbGVtZW50YWxEZWZhdWx0UHJvcHMgfSA9IHVzZUFtcGxpdHVkZSgpO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgY29uc3QgdmFyaWFudEluZm9XaXRoUHJlZml4ID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgT2JqZWN0LmVudHJpZXModmFyaWFudEluZm8pLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBbXG4gICAgICAgIGB2YXJpYW50SW5mby4ke2tleX1gLFxuICAgICAgICB2YWx1ZSxcbiAgICAgIF0pXG4gICAgKTtcblxuICAgIGNvbnN0IGRlZmF1bHRFdmVudFByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge1xuICAgICAgcGFnZV92YXJpYW50OiB2YXJpYW50SW5mby52YXJpYW50LCAvLyBUT0RPOiBzaG91bGQgYmUgcmVtb3ZlZCBvdmVyIHRpbWUsIGFmdGVyIG1pZ3JhdGlvblxuICAgICAgLi4udmFyaWFudEluZm9XaXRoUHJlZml4LFxuICAgIH07XG5cbiAgICAvLyBUT0RPOiBzaG91bGQgYmUgcmVtb3ZlZCBvdmVyIHRpbWUsIGFmdGVyIG1pZ3JhdGlvblxuICAgIGlmICh2YXJpYW50SW5mby52YXJpYW50ID09PSBcInBkcFwiKSB7XG4gICAgICBkZWZhdWx0RXZlbnRQcm9wZXJ0aWVzLnByb2R1Y3RfaWQgPSB2YXJpYW50SW5mby5wcm9kdWN0SWQ7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogc2hvdWxkIGJlIHJlbW92ZWQgb3ZlciB0aW1lLCBhZnRlciBtaWdyYXRpb25cbiAgICBpZiAodmFyaWFudEluZm8udmFyaWFudCA9PT0gXCJwbHBcIikge1xuICAgICAgZGVmYXVsdEV2ZW50UHJvcGVydGllcy5wbHBfaWQgPSB2YXJpYW50SW5mby5wbHBJZDtcbiAgICB9XG5cbiAgICAvLyBUT0RPOiBzaG91bGQgYmUgcmVtb3ZlZCBvdmVyIHRpbWUsIGFmdGVyIG1pZ3JhdGlvblxuICAgIGlmICh2YXJpYW50SW5mby52YXJpYW50ID09PSBcInBhZ2VfdmlzaXRcIikge1xuICAgICAgZGVmYXVsdEV2ZW50UHJvcGVydGllcy5wYWdlX3Zpc2l0X2NhdGVnb3J5ID1cbiAgICAgICAgdmFyaWFudEluZm8ucGFnZVZpc2l0Q2F0ZWdvcnk7XG4gICAgICBkZWZhdWx0RXZlbnRQcm9wZXJ0aWVzLnBhZ2VfdmlzaXRfdXJsID0gdmFyaWFudEluZm8udXJsO1xuICAgIH1cblxuICAgIHNldFN1cHBsZW1lbnRhbERlZmF1bHRQcm9wcyhkZWZhdWx0RXZlbnRQcm9wZXJ0aWVzKTtcblxuICAgIC8vIHB1dCBhbnkgZXZlbnRzIHRoYXQgc2hvdWxkIGJlIHNlbnQgb25jZSBwZXIgcGFnZSB2aXNpdCBoZXJlXG4gICAgaWYgKCFoYXNJbml0aWFsaXplZC5jdXJyZW50ICYmIGhhc1BhcnNlZFZhcmlhbnRJbmZvKSB7XG4gICAgICB0cmFja0V2ZW50KHtcbiAgICAgICAgZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLkJ1bmRsZUxvYWRlZCxcbiAgICAgIH0pO1xuICAgICAgaGFzSW5pdGlhbGl6ZWQuY3VycmVudCA9IHRydWU7XG4gICAgfVxuICB9LCBbXG4gICAgdmFyaWFudEluZm8sXG4gICAgaGFzUGFyc2VkVmFyaWFudEluZm8sXG4gICAgdHJhY2tFdmVudCxcbiAgICBzZXRTdXBwbGVtZW50YWxEZWZhdWx0UHJvcHMsXG4gIF0pO1xufTtcbiIsImltcG9ydCB7IFVzZXJFdmVudENhdGVnb3J5IH0gZnJvbSBcIkBzcGlmZnktYWkvY29tbWVyY2UtYXBpLWNsaWVudFwiO1xuaW1wb3J0IHsgdXNlQXRvbSwgdXNlQXRvbVZhbHVlLCB1c2VTZXRBdG9tIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQge1xuICBjcmVhdGVDb250ZXh0LFxuICB1c2VFZmZlY3QsXG4gIHVzZVN0YXRlLFxuICBSZWFjdE5vZGUsXG4gIHVzZUNhbGxiYWNrLFxuICB1c2VNZW1vLFxufSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCBDb21tZXJjZUFwaUNsaWVudCBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL2NvbW1lcmNlLWFwaVwiO1xuaW1wb3J0IHsgdjQgYXMgdXVpZCB9IGZyb20gXCJ1dWlkXCI7XG5pbXBvcnQgeyBTZXNzaW9uUmVzdGFydFJlcXVpcmVkIH0gZnJvbSBcInNyYy90eXBlcy9leGNlcHRpb25zL3Nlc3Npb25FeGNlcHRpb25zXCI7XG5pbXBvcnQgTG9nZ2VyIGZyb20gXCJzcmMvYXBwbGljYXRpb24vbG9nZ2luZy9sb2dnZXJcIjtcbmltcG9ydCB7XG4gIE1lc3NhZ2UsXG4gIE1lc3NhZ2VSb2xlLFxuICBNZXNzYWdlVHlwZSxcbiAgTmV4dE1lc3NhZ2VSZXF1ZXN0LFxuICBSZXNwb25zZSxcbn0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHNcIjtcbmltcG9ydCB7IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUgfSBmcm9tIFwic3JjL2NvbnRleHRzL2FtcGxpdHVkZUNvbnRleHRcIjtcbmltcG9ydCB7IG1lc3NhZ2VGcm9tUmVzcG9uc2UgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL3V0aWxzXCI7XG5pbXBvcnQgeyBjaGF0SWRBdG9tLCB1c2VySWRBdG9tLCB2YXJpYW50SW5mb0F0b20gfSBmcm9tIFwic3JjL2F0b21zL2FwcFwiO1xuaW1wb3J0IHtcbiAgbWVzc2FnZXNBdG9tLFxuICByZXF1ZXN0RmFpbHVyZUF0b20sXG4gIHJlc3BvbnNlU3RyZWFtaW5nQXRvbSxcbiAgdXNlckhhc1JlcGxpZWRBdG9tLFxuICBQZXJmTWV0cmljc0V2ZW50cyxcbiAgbG9nUGVyZk1ldHJpY0F0b20sXG4gIHVzZXJFdmVudHNBdG9tLFxuICBzdWdnZXN0aW9uc0xvYWRpbmdBdG9tLFxuICBzdWdnZXN0aW9uc0F0b20sXG59IGZyb20gXCJzcmMvYXRvbXMvY2hhdFwiO1xuaW1wb3J0IHtcbiAgY2hhdFNlYXJjaFByb2R1Y3RTb3J0aW5nQXRvbSxcbiAgY2hhdFNlYXJjaFByb2R1Y3RzLFxuICBjaGF0U2VhcmNoU3RhdGVBdG9tLFxuICBoYW5kbGVTZWFyY2hSZXN1bHRzQXRvbSxcbiAgY2hhdFNlYXJjaElzTG9hZGluZ0F0b20sXG59IGZyb20gXCJzcmMvYXRvbXMvc2VhcmNoL2NoYXRTZWFyY2hcIjtcbmltcG9ydCB7IHVzZVN5c3RlbVNldHRpbmdzQ29udGV4dCB9IGZyb20gXCJzcmMvaG9va3NcIjtcbmltcG9ydCB7IGNyZWF0ZUFwcExvYWRlZEV2ZW50LCBjcmVhdGVWaXNpdFVzZXJFdmVudCB9IGZyb20gXCJzcmMvaG9va3MvdXRpbHNcIjtcbmltcG9ydCB7IHVzZU1lc3NhZ2VJbnRlcmNlcHRvciB9IGZyb20gXCJzcmMvaW50ZXJjZXB0b3JzL3VzZU1lc3NhZ2VJbnRlcmNlcHRvclwiO1xuaW1wb3J0IHsgc3VwcG9ydGVkRXZlbnRBdG9tIH0gZnJvbSBcInNyYy9hdG9tcy9hcHAvdmFyaWFudFwiO1xuaW1wb3J0IHsgY2hhdEF0b20gfSBmcm9tIFwic3JjL2F0b21zL2NoYXRcIjtcbmltcG9ydCB7IGdldEF0b21TdG9yZSB9IGZyb20gXCJzcmMvYXRvbXMvYXRvbVN0b3JlXCI7XG5pbXBvcnQge1xuICBjbGVhclVzZXJFdmVudEF0b20sXG4gIGNyZWF0ZVJlc3BvbnNlUGF5bG9hZCxcbiAgcHJvY2Vzc1VzZXJFdmVudEF0b20sXG4gIHVzZXJFdmVudFF1ZXVlQXRvbSxcbiAgdXNlclF1ZXVlRXZlbnRDb3VudEF0b20sXG59IGZyb20gXCJzcmMvYXRvbXMvY2hhdC9tZXNzYWdlUXVldWVcIjtcbmltcG9ydCB7IHVzZUFtcGxpdHVkZVRyYWNraW5nIH0gZnJvbSBcInNyYy9ob29rcy91c2VBbXBsaXR1ZGVPcGVyYXRpb25zXCI7XG5cbi8qKlxuICogUmVjb3JkIHRoZSBjaGF0IGFzc2lzdGFudCByZXNwb25zZSBpbiBBbXBsaXR1ZGVcbiAqXG4gKiBAcGFyYW0gc3RhcnRUaW1lTXMgVGhlIHN0YXJ0IHRpbWUgb2YgdGhlIGFzc2lzdGFudCByZXNwb25zZVxuICogQHBhcmFtIHBheWxvYWQgVGhlIHBheWxvYWQgdXNlZCB0byBnZW5lcmF0ZSB0aGUgcmVzcG9uc2VcbiAqL1xuY29uc3QgcmVjb3JkQXNzaXN0YW50UmVzcG9uc2UgPSAoXG4gIHN0YXJ0VGltZU1zOiBudW1iZXIsXG4gIHBheWxvYWQ6IE5leHRNZXNzYWdlUmVxdWVzdCxcbiAgdHJhY2s6IChcbiAgICBldmVudE5hbWU6IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUsXG4gICAgZXZlbnRQcm9wcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4gICkgPT4gdm9pZFxuKSA9PiB7XG4gIGNvbnN0IGF0b21TdG9yZSA9IGdldEF0b21TdG9yZSgpO1xuICBjb25zdCBjaGF0U3RhdGUgPSBhdG9tU3RvcmUuZ2V0KGNoYXRBdG9tKTtcbiAgY29uc3QgY2hhdFNlYXJjaFN0YXRlID0gYXRvbVN0b3JlLmdldChjaGF0U2VhcmNoU3RhdGVBdG9tKTtcbiAgY29uc3Qgc2VhcmNoUHJvZHVjdHMgPSBhdG9tU3RvcmUuZ2V0KGNoYXRTZWFyY2hQcm9kdWN0cyk7XG4gIGNvbnN0IHNlYXJjaFByb2R1Y3RzU29ydCA9IGF0b21TdG9yZS5nZXQoY2hhdFNlYXJjaFByb2R1Y3RTb3J0aW5nQXRvbSk7XG4gIGNvbnN0IGFzc2lzdGFudFJlc3BvbnNlVGltZU1zID0geyBzdGFydDogc3RhcnRUaW1lTXMsIGVuZDogRGF0ZS5ub3coKSB9O1xuICBsZXQgdXNlclF1ZXJ5UHJvcGVydHk6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBpZiAoXG4gICAgY2hhdFN0YXRlLnJlcGx5RXZlbnRDYXRlZ29yeSA9PT0gVXNlckV2ZW50Q2F0ZWdvcnkuU3VnZ2VzdGlvbkNsaWNrZWQgJiZcbiAgICBjaGF0U3RhdGUuc3VnZ2VzdGlvblxuICApIHtcbiAgICB1c2VyUXVlcnlQcm9wZXJ0eSA9IGNoYXRTdGF0ZS5zdWdnZXN0aW9uLmNvbnRlbnQ7XG4gIH0gZWxzZSBpZiAoY2hhdFN0YXRlLnVzZXJRdWVyeSAmJiBjaGF0U3RhdGUudXNlclF1ZXJ5Lmxlbmd0aCA+IDApIHtcbiAgICB1c2VyUXVlcnlQcm9wZXJ0eSA9IGNoYXRTdGF0ZS51c2VyUXVlcnk7XG4gIH1cblxuICBjb25zdCBldmVudFByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcbiAgICByZXNwb25zZV90aW1lX21zOlxuICAgICAgYXNzaXN0YW50UmVzcG9uc2VUaW1lTXMuZW5kIC0gYXNzaXN0YW50UmVzcG9uc2VUaW1lTXMuc3RhcnQsXG4gICAgdXNlcl9ldmVudF90eXBlOiBjaGF0U3RhdGUucmVwbHlFdmVudENhdGVnb3J5LFxuICAgIHVzZXJfcXVlcnk6IHVzZXJRdWVyeVByb3BlcnR5LFxuICB9O1xuXG4gIGlmIChjaGF0U3RhdGUucmVwbHlFdmVudENhdGVnb3J5ID09PSBVc2VyRXZlbnRDYXRlZ29yeS5Gb3JtU3VibWl0dGVkKSB7XG4gICAgY29uc3QgbGFzdEFzc2lzdGFudFR1cm4gPSBjaGF0U3RhdGUubWVzc2FnZXNcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgICh0dXJuKSA9PiB0dXJuLmxlbmd0aCA+IDAgJiYgdHVyblswXS5yb2xlID09PSBNZXNzYWdlUm9sZS5Bc3Npc3RhbnRcbiAgICAgIClcbiAgICAgIC5wb3AoKTtcbiAgICBjb25zdCBmb3JtVHlwZSA9IHBheWxvYWQudXNlckV2ZW50cz8uZmluZChcbiAgICAgIChldmVudCkgPT4gZXZlbnQuY2F0ZWdvcnkgPT09IFVzZXJFdmVudENhdGVnb3J5LkZvcm1TdWJtaXR0ZWRcbiAgICApPy5hdHRyaWJ1dGVzLmZvcm1UeXBlO1xuICAgIGNvbnN0IGZvcm1TdGF0dXMgPSBsYXN0QXNzaXN0YW50VHVybj8uc29tZShcbiAgICAgIChyZXNwb25zZSkgPT4gcmVzcG9uc2UudHlwZSA9PT0gTWVzc2FnZVR5cGUuT3JkZXJcbiAgICApO1xuICAgIGV2ZW50UHJvcHMuZm9ybV9zdWJtaXR0ZWRfYXR0cmlidXRlcyA9IHtcbiAgICAgIGZvcm1fdHlwZTogZm9ybVR5cGUsXG4gICAgICBzdGF0dXM6IGZvcm1TdGF0dXMgPyBcInN1Y2Nlc3NcIiA6IFwiZmFpbGVkXCIsXG4gICAgfTtcbiAgfVxuXG4gIGlmIChjaGF0U2VhcmNoU3RhdGUgPT09IFwicHJvZHVjdC1wYWdlXCIpIHtcbiAgICBldmVudFByb3BzLnNlYXJjaF9wcm9kdWN0c19yZXR1cm5lZCA9IHNlYXJjaFByb2R1Y3RzLmxlbmd0aDtcbiAgICBldmVudFByb3BzLnNlYXJjaF9wcm9kdWN0c19zb3J0X3R5cGUgPSBzZWFyY2hQcm9kdWN0c1NvcnQ7XG4gIH1cblxuICB0cmFjayhTcGlmZnlNZXRyaWNzRXZlbnROYW1lLkNoYXRBc3Npc3RhbnRSZXNwb25zZSwge1xuICAgIGV2ZW50UHJvcHMsXG4gIH0pO1xufTtcblxuaW50ZXJmYWNlIENoYXRDb250ZXh0UGFyYW1zIHt9XG5cbmNvbnN0IENoYXRDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxDaGF0Q29udGV4dFBhcmFtcyB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcblxuY29uc3QgdXBkYXRlTWVzc2FnZVN0YXRlID0gKFxuICBtZXNzYWdlOiBNZXNzYWdlLFxuICBsYXN0TWVzc2FnZTogTWVzc2FnZSxcbiAgc2V0TWVzc2FnZXM6ICh1cGRhdGVyOiAocHJldjogTWVzc2FnZVtdW10pID0+IE1lc3NhZ2VbXVtdKSA9PiB2b2lkXG4pOiBNZXNzYWdlID0+IHtcbiAgaWYgKGxhc3RNZXNzYWdlID09IG51bGwpIHtcbiAgICBzZXRNZXNzYWdlcygocHJldikgPT4gWy4uLnByZXYsIFttZXNzYWdlXV0pO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG4gIGlmIChcbiAgICBsYXN0TWVzc2FnZS50eXBlID09PSBNZXNzYWdlVHlwZS5UZXh0ICYmXG4gICAgbWVzc2FnZS50eXBlID09PSBNZXNzYWdlVHlwZS5UZXh0XG4gICkge1xuICAgIGNvbnN0IG5ld01lc3NhZ2UgPSB7XG4gICAgICAuLi5sYXN0TWVzc2FnZSxcbiAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgIC4uLmxhc3RNZXNzYWdlLm1ldGFkYXRhLFxuICAgICAgICBjb250ZW50OiBsYXN0TWVzc2FnZS5tZXRhZGF0YS5jb250ZW50ICsgbWVzc2FnZS5tZXRhZGF0YS5jb250ZW50LFxuICAgICAgfSxcbiAgICB9O1xuICAgIHNldE1lc3NhZ2VzKChwcmV2KSA9PiB7XG4gICAgICBjb25zdCBsYXN0VHVybiA9IHByZXZbcHJldi5sZW5ndGggLSAxXTtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIC4uLnByZXYuc2xpY2UoMCwgcHJldi5sZW5ndGggLSAxKSxcbiAgICAgICAgWy4uLmxhc3RUdXJuLnNsaWNlKDAsIGxhc3RUdXJuLmxlbmd0aCAtIDEpLCBuZXdNZXNzYWdlXSxcbiAgICAgIF07XG4gICAgfSk7XG4gICAgcmV0dXJuIG5ld01lc3NhZ2U7XG4gIH1cbiAgc2V0TWVzc2FnZXMoKHByZXYpID0+IFtcbiAgICAuLi5wcmV2LnNsaWNlKDAsIHByZXYubGVuZ3RoIC0gMSksXG4gICAgWy4uLnByZXZbcHJldi5sZW5ndGggLSAxXSwgbWVzc2FnZV0sXG4gIF0pO1xuICByZXR1cm4gbWVzc2FnZTtcbn07XG5cbmNvbnN0IGhhbmRsZVN0cmVhbWluZ0Vycm9yID0gKFxuICBfZXJyb3I6IHVua25vd24sXG4gIHNldFJlcXVlc3RGYWlsdXJlOiAoZmFpbGVkOiBib29sZWFuKSA9PiB2b2lkLFxuICBzZXRNZXNzYWdlczogKHVwZGF0ZXI6IChwcmV2OiBNZXNzYWdlW11bXSkgPT4gTWVzc2FnZVtdW10pID0+IHZvaWRcbikgPT4ge1xuICBzZXRSZXF1ZXN0RmFpbHVyZSh0cnVlKTtcbiAgc2V0TWVzc2FnZXMoKHByZXYpID0+IFtcbiAgICAuLi5wcmV2LFxuICAgIFtcbiAgICAgIHtcbiAgICAgICAgaWQ6IHV1aWQoKSxcbiAgICAgICAgcm9sZTogTWVzc2FnZVJvbGUuQXNzaXN0YW50LFxuICAgICAgICB0eXBlOiBNZXNzYWdlVHlwZS5UZXh0LFxuICAgICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICBjb250ZW50OlxuICAgICAgICAgICAgXCJJJ20gc29ycnkhIEknbSBoYXZpbmcgdHJvdWJsZSByaWdodCBub3cuIFBsZWFzZSByZWZyZXNoIHRoZSBwYWdlIG9yIHRyeSBhZ2FpbiBpbiBhIG1vbWVudC5cIixcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgXSxcbiAgXSk7XG59O1xuXG5jb25zdCBwcm9jZXNzU3RyZWFtaW5nUmVzcG9uc2UgPSBhc3luYyAoXG4gIHN0cmVhbTogQXN5bmNJdGVyYWJsZTxSZXNwb25zZT4sXG4gIG1lc3NhZ2VJbnRlcmNlcHRvcjoge1xuICAgIGludGVyY2VwdDogKHJlc3BvbnNlPzogUmVzcG9uc2UpID0+IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG4gIH0sXG4gIGhhbmRsZVNlYXJjaFJlc3VsdHM6IChtZXNzYWdlOiBNZXNzYWdlKSA9PiB2b2lkLFxuICBzZXRNZXNzYWdlczogKHVwZGF0ZXI6IChwcmV2OiBNZXNzYWdlW11bXSkgPT4gTWVzc2FnZVtdW10pID0+IHZvaWQsXG4gIHNldFNlYXJjaElzTG9hZGluZzogKGxvYWRpbmc6IGJvb2xlYW4pID0+IHZvaWQsXG4gIGNoYXRJZDogc3RyaW5nXG4pOiBQcm9taXNlPHsgaGFzU2VhcmNoUmVzdWx0czogYm9vbGVhbiB9PiA9PiB7XG4gIGxldCBsYXN0TWVzc2FnZTogTWVzc2FnZSB8IHVuZGVmaW5lZDtcbiAgbGV0IGhhc1NlYXJjaFJlc3VsdHMgPSBmYWxzZTtcblxuICBmb3IgYXdhaXQgKGNvbnN0IHJlc3BvbnNlIG9mIHN0cmVhbSkge1xuICAgIHRyeSB7XG4gICAgICBpZiAobWVzc2FnZUludGVyY2VwdG9yLmludGVyY2VwdChyZXNwb25zZSkpIHtcbiAgICAgICAgcmV0dXJuIHsgaGFzU2VhcmNoUmVzdWx0cyB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtZXNzYWdlID0gbWVzc2FnZUZyb21SZXNwb25zZShyZXNwb25zZSk7XG4gICAgICBpZiAoIW1lc3NhZ2UpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbGVkIHRvIHRyYW5zZm9ybSBBUEkgcmVzcG9uc2UgdG8gY2xpZW50IG1lc3NhZ2VcIik7XG4gICAgICB9XG5cbiAgICAgIGlmIChtZXNzYWdlLnR5cGUgPT09IE1lc3NhZ2VUeXBlLlByb2R1Y3RTZWFyY2gpIHtcbiAgICAgICAgaGFuZGxlU2VhcmNoUmVzdWx0cyhtZXNzYWdlKTtcbiAgICAgICAgaGFzU2VhcmNoUmVzdWx0cyA9IHRydWU7XG4gICAgICAgIHNldFNlYXJjaElzTG9hZGluZyhmYWxzZSk7IC8vIFVwZGF0ZSBzZWFyY2ggbG9hZGluZyBpbW1lZGlhdGVseSB3aGVuIHJlc3VsdHMgYXJlIGRldGVjdGVkXG4gICAgICB9XG5cbiAgICAgIGxhc3RNZXNzYWdlID0gdXBkYXRlTWVzc2FnZVN0YXRlKG1lc3NhZ2UsIGxhc3RNZXNzYWdlISwgc2V0TWVzc2FnZXMpO1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBMb2dnZXIubG9nV2FybihcbiAgICAgICAgYFtzcGlmZnktYWldIEZhaWxlZCB0byBnZW5lcmF0ZSByZXNwb25zZXMgZnJvbSBzdHJlYW0gY2hhdF9pZD0ke2NoYXRJZH1gLFxuICAgICAgICBlcnJvcixcbiAgICAgICAge1xuICAgICAgICAgIGxhc3RSZXNwb25zZTogbGFzdE1lc3NhZ2UsXG4gICAgICAgICAgcmVzcG9uc2UsXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgaGFzU2VhcmNoUmVzdWx0cyB9O1xufTtcblxuY29uc3QgQ2hhdENvbnRleHRQcm92aWRlciA9ICh7IGNoaWxkcmVuIH06IHsgY2hpbGRyZW46IFJlYWN0Tm9kZSB9KSA9PiB7XG4gIGNvbnN0IGxvZ1BlcmZNZXRyaWMgPSB1c2VTZXRBdG9tKGxvZ1BlcmZNZXRyaWNBdG9tKTtcbiAgY29uc3QgW3dpZGdldEluaXRpYWxpemVkLCBzZXRXaWRnZXRJbml0aWFsaXplZF0gPSB1c2VTdGF0ZShmYWxzZSk7XG4gIGNvbnN0IHNldFVzZXJIYXNSZXBsaWVkID0gdXNlU2V0QXRvbSh1c2VySGFzUmVwbGllZEF0b20pO1xuICAvLyBUT0RPOiBjcmVhdGUgYXRvbXMgZm9yIHNldHRpbmcvZ2V0dGluZyB0aGUgbGFzdCBtZXNzYWdlIHR1cm5cbiAgY29uc3QgW21lc3NhZ2VzLCBzZXRNZXNzYWdlc10gPSB1c2VBdG9tPE1lc3NhZ2VbXVtdPihtZXNzYWdlc0F0b20pO1xuICBjb25zdCBzZXRVc2VyRXZlbnRzID0gdXNlU2V0QXRvbSh1c2VyRXZlbnRzQXRvbSk7XG4gIGNvbnN0IHNldFN1Z2dlc3Rpb25zID0gdXNlU2V0QXRvbShzdWdnZXN0aW9uc0F0b20pO1xuICBjb25zdCBbc3VnZ2VzdGlvbnNMb2FkaW5nLCBzZXRTdWdnZXN0aW9uc0xvYWRpbmddID0gdXNlQXRvbTxib29sZWFuPihcbiAgICBzdWdnZXN0aW9uc0xvYWRpbmdBdG9tXG4gICk7XG4gIGNvbnN0IFtyZXNwb25zZVN0cmVhbWluZywgc2V0UmVzcG9uc2VTdHJlYW1pbmddID0gdXNlQXRvbTxib29sZWFuPihcbiAgICByZXNwb25zZVN0cmVhbWluZ0F0b21cbiAgKTtcbiAgY29uc3Qgc2V0UmVxdWVzdEZhaWx1cmUgPSB1c2VTZXRBdG9tKHJlcXVlc3RGYWlsdXJlQXRvbSk7XG4gIGNvbnN0IHVzZXJFdmVudHMgPSB1c2VBdG9tVmFsdWUodXNlckV2ZW50UXVldWVBdG9tKTtcbiAgY29uc3QgdXNlclF1ZXVlRXZlbnRDb3VudCA9IHVzZUF0b21WYWx1ZSh1c2VyUXVldWVFdmVudENvdW50QXRvbSk7XG4gIGNvbnN0IG1hcmtVc2VyRXZlbnRzUHJvY2Vzc2VkID0gdXNlU2V0QXRvbShwcm9jZXNzVXNlckV2ZW50QXRvbSk7XG4gIGNvbnN0IGNsZWFyVXNlckV2ZW50UXVldWUgPSB1c2VTZXRBdG9tKGNsZWFyVXNlckV2ZW50QXRvbSk7XG4gIGNvbnN0IHVzZXJJZCA9IHVzZUF0b21WYWx1ZSh1c2VySWRBdG9tKTtcbiAgY29uc3QgY2hhdElkID0gdXNlQXRvbVZhbHVlKGNoYXRJZEF0b20pO1xuICBjb25zdCBzdXBwb3J0ZWRFdmVudCA9IHVzZUF0b21WYWx1ZShzdXBwb3J0ZWRFdmVudEF0b20pO1xuICAvLyBUT0RPOiBSZXBsYWNlIHdpdGggYWN0dWFsIG9yZ0lkIGZyb20gdXNlRW52aXZlQ29uZmlnIG9yIE5ld09yZ0NvbmZpZ0NvbnRleHQgd2hlbiBhdmFpbGFibGVcbiAgY29uc3Qgb3JnSWQgPSBcIm1vY2stb3JnLWlkXCI7XG5cbiAgY29uc3QgdmFyaWFudEluZm8gPSB1c2VBdG9tVmFsdWUodmFyaWFudEluZm9BdG9tKTtcbiAgY29uc3Qgc2V0dGluZ3NDb250ZXh0ID0gdXNlU3lzdGVtU2V0dGluZ3NDb250ZXh0KCk7XG4gIGNvbnN0IG1lc3NhZ2VJbnRlcmNlcHRvciA9IHVzZU1lc3NhZ2VJbnRlcmNlcHRvcigpO1xuICBjb25zdCBoYW5kbGVTZWFyY2hSZXN1bHRzID0gdXNlU2V0QXRvbShoYW5kbGVTZWFyY2hSZXN1bHRzQXRvbSk7XG4gIGNvbnN0IHNldFNlYXJjaElzTG9hZGluZyA9IHVzZVNldEF0b20oY2hhdFNlYXJjaElzTG9hZGluZ0F0b20pO1xuICBjb25zdCB7IHRyYWNrIH0gPSB1c2VBbXBsaXR1ZGVUcmFja2luZygpO1xuXG4gIGNvbnN0IGdldFN0cmVhbWluZ1Jlc3BvbnNlcyA9IHVzZUNhbGxiYWNrKFxuICAgIGFzeW5jIChcbiAgICAgIHBheWxvYWQ6IE5leHRNZXNzYWdlUmVxdWVzdFxuICAgICk6IFByb21pc2U8eyBoYXNTZWFyY2hSZXN1bHRzOiBib29sZWFuIH0+ID0+IHtcbiAgICAgIGxvZ1BlcmZNZXRyaWMoUGVyZk1ldHJpY3NFdmVudHMuRmlyc3RSZXNwb25zZVN0YXJ0ZWQpO1xuICAgICAgY29uc3Qgc3RyZWFtID0gQ29tbWVyY2VBcGlDbGllbnQuZ2V0TmV4dFJlc3BvbnNlU3RyZWFtaW5nKHBheWxvYWQpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBzZXRSZXF1ZXN0RmFpbHVyZShmYWxzZSk7XG5cbiAgICAgICAgY29uc3QgeyBoYXNTZWFyY2hSZXN1bHRzIH0gPSBhd2FpdCBwcm9jZXNzU3RyZWFtaW5nUmVzcG9uc2UoXG4gICAgICAgICAgc3RyZWFtLFxuICAgICAgICAgIG1lc3NhZ2VJbnRlcmNlcHRvcixcbiAgICAgICAgICBoYW5kbGVTZWFyY2hSZXN1bHRzLFxuICAgICAgICAgIHNldE1lc3NhZ2VzLFxuICAgICAgICAgIHNldFNlYXJjaElzTG9hZGluZyxcbiAgICAgICAgICBjaGF0SWRcbiAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4geyBoYXNTZWFyY2hSZXN1bHRzIH07XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGhhbmRsZVN0cmVhbWluZ0Vycm9yKGUsIHNldFJlcXVlc3RGYWlsdXJlLCBzZXRNZXNzYWdlcyk7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBsb2dQZXJmTWV0cmljKFBlcmZNZXRyaWNzRXZlbnRzLkZpcnN0UmVzcG9uc2VDb21wbGV0ZWQpO1xuICAgICAgfVxuICAgIH0sXG4gICAgW1xuICAgICAgbG9nUGVyZk1ldHJpYyxcbiAgICAgIHNldFJlcXVlc3RGYWlsdXJlLFxuICAgICAgbWVzc2FnZUludGVyY2VwdG9yLFxuICAgICAgaGFuZGxlU2VhcmNoUmVzdWx0cyxcbiAgICAgIHNldE1lc3NhZ2VzLFxuICAgICAgc2V0U2VhcmNoSXNMb2FkaW5nLFxuICAgICAgY2hhdElkLFxuICAgIF1cbiAgKTtcblxuICBjb25zdCBnZXRTdWdnZXN0aW9ucyA9IHVzZUNhbGxiYWNrKGFzeW5jICgpID0+IHtcbiAgICBsb2dQZXJmTWV0cmljKFBlcmZNZXRyaWNzRXZlbnRzLkZpcnN0U3VnZ2VzdGlvbnNTdGFydGVkKTtcbiAgICBzZXRTdWdnZXN0aW9uc0xvYWRpbmcodHJ1ZSk7XG4gICAgc2V0U3VnZ2VzdGlvbnMoW10pO1xuXG4gICAgY29uc3QgcGF5bG9hZFdpdGhvdXRBcHBMb2FkZWQgPSBjcmVhdGVSZXNwb25zZVBheWxvYWQoe1xuICAgICAgdXNlckV2ZW50czogW10sXG4gICAgICBnZW5lcmF0aW9uUGFyYW1zOiBzZXR0aW5nc0NvbnRleHQuZ2VuZXJhdGlvblBhcmFtcyxcbiAgICB9KTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmdldE5leHRTdWdnZXN0aW9ucyhcbiAgICAgIHBheWxvYWRXaXRob3V0QXBwTG9hZGVkXG4gICAgKTtcblxuICAgIC8vIHNvcnQgdGhlIHN1Z2dlc3Rpb25zIGJ5IHNob3J0ZXN0IGxlbmd0aCBzbyB0aGUgcGlsbHMgY2FuIGJlIHN0YWNrZWQgaG9yaXpvbnRhbGx5XG4gICAgc2V0U3VnZ2VzdGlvbnMoXG4gICAgICByZXNwb25zZS5zb3J0KChhLCBiKSA9PiBhLmNvbnRlbnQubGVuZ3RoIC0gYi5jb250ZW50Lmxlbmd0aClcbiAgICApO1xuICAgIHNldFN1Z2dlc3Rpb25zTG9hZGluZyhmYWxzZSk7XG4gICAgbG9nUGVyZk1ldHJpYyhQZXJmTWV0cmljc0V2ZW50cy5GaXJzdFN1Z2dlc3Rpb25zQ29tcGxldGVkKTtcbiAgfSwgW1xuICAgIGxvZ1BlcmZNZXRyaWMsXG4gICAgc2V0U3VnZ2VzdGlvbnNMb2FkaW5nLFxuICAgIHNldFN1Z2dlc3Rpb25zLFxuICAgIHNldHRpbmdzQ29udGV4dC5nZW5lcmF0aW9uUGFyYW1zLFxuICBdKTtcblxuICBjb25zdCBnZXRSZXNwb25zZXMgPSB1c2VDYWxsYmFjayhcbiAgICBhc3luYyAocGF5bG9hZD86IE5leHRNZXNzYWdlUmVxdWVzdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVxdWVzdFBheWxvYWQgPVxuICAgICAgICAgIHBheWxvYWQgPz9cbiAgICAgICAgICBjcmVhdGVSZXNwb25zZVBheWxvYWQoe1xuICAgICAgICAgICAgdXNlckV2ZW50cyxcbiAgICAgICAgICAgIGdlbmVyYXRpb25QYXJhbXM6IHNldHRpbmdzQ29udGV4dC5nZW5lcmF0aW9uUGFyYW1zLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIHNldFJlc3BvbnNlU3RyZWFtaW5nKHRydWUpO1xuICAgICAgICBzZXRTdWdnZXN0aW9ucyhbXSk7XG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZU1zID0gRGF0ZS5ub3coKTtcblxuICAgICAgICBhd2FpdCBnZXRTdHJlYW1pbmdSZXNwb25zZXMocmVxdWVzdFBheWxvYWQpO1xuXG4gICAgICAgIHJlY29yZEFzc2lzdGFudFJlc3BvbnNlKHN0YXJ0VGltZU1zLCByZXF1ZXN0UGF5bG9hZCwgdHJhY2spO1xuICAgICAgICBhd2FpdCBnZXRTdWdnZXN0aW9ucygpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFwiW3NwaWZmeS1haV0gZ2V0UmVzcG9uc2VzIGVycm9yXCIsIGVycm9yKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIC8vIFJlbW92ZSBzZWFyY2ggbG9hZGluZyBtYW5hZ2VtZW50IGZyb20gaGVyZSAtIGl0J3Mgbm93IGhhbmRsZWQgaW5kZXBlbmRlbnRseVxuICAgICAgICAvLyBpbiB0aGUgcHJvY2Vzc1N0cmVhbWluZ1Jlc3BvbnNlIGZ1bmN0aW9uIHdoZW4gc2VhcmNoIHJlc3VsdHMgYXJlIGRldGVjdGVkXG4gICAgICAgIG1hcmtVc2VyRXZlbnRzUHJvY2Vzc2VkKHVzZXJFdmVudHMubWFwKCh7IGV2ZW50SWQgfSkgPT4gZXZlbnRJZCkpO1xuICAgICAgICBzZXRVc2VySGFzUmVwbGllZChmYWxzZSk7XG4gICAgICAgIHNldFJlc3BvbnNlU3RyZWFtaW5nKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtcbiAgICAgIHVzZXJFdmVudHMsXG4gICAgICBzZXR0aW5nc0NvbnRleHQuZ2VuZXJhdGlvblBhcmFtcyxcbiAgICAgIHNldFJlc3BvbnNlU3RyZWFtaW5nLFxuICAgICAgc2V0U3VnZ2VzdGlvbnMsXG4gICAgICBnZXRTdHJlYW1pbmdSZXNwb25zZXMsXG4gICAgICBtYXJrVXNlckV2ZW50c1Byb2Nlc3NlZCxcbiAgICAgIGdldFN1Z2dlc3Rpb25zLFxuICAgICAgc2V0VXNlckhhc1JlcGxpZWQsXG4gICAgICB0cmFjayxcbiAgICBdXG4gICk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBwcm9jZXNzVXNlckV2ZW50cyA9IGFzeW5jICgpID0+IHtcbiAgICAgIGlmIChyZXNwb25zZVN0cmVhbWluZyB8fCAhd2lkZ2V0SW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgICh2YXJpYW50SW5mby52YXJpYW50ID09PSBcInBkcFwiICYmICF2YXJpYW50SW5mby5wcm9kdWN0SWQpIHx8XG4gICAgICAgICh2YXJpYW50SW5mby52YXJpYW50ID09PSBcInBscFwiICYmICF2YXJpYW50SW5mby5wbHBJZCkgfHxcbiAgICAgICAgKHZhcmlhbnRJbmZvLnZhcmlhbnQgPT09IFwicGFnZV92aXNpdFwiICYmICF2YXJpYW50SW5mby51cmwpXG4gICAgICApIHtcbiAgICAgICAgTG9nZ2VyLmxvZ0RlYnVnKFxuICAgICAgICAgIFwiW3NwaWZmeS1haV0gdmFyaWFudEluZm8gaGFzIGludmFsaWQgdmFsdWVzLCBza2lwcGluZy4uLlwiLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhcmlhbnRJbmZvLFxuICAgICAgICAgICAgc3VwcG9ydGVkRXZlbnQsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIExvZ2dlci5sb2dEZWJ1ZyhcbiAgICAgICAgYEFzc2lzdGFudHMgVHVybiBpc19jdXJyZW50bHlfc3RyZWFtaW5nPSR7cmVzcG9uc2VTdHJlYW1pbmd9IGluaXRpYWxpemVkPSR7d2lkZ2V0SW5pdGlhbGl6ZWR9YFxuICAgICAgKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGdldFJlc3BvbnNlcygpO1xuICAgICAgICBMb2dnZXIubG9nSW5mbyhgQXNzaXN0YW50cyBUdXJuIFtmaW5pc2hlZF1gKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgIExvZ2dlci5sb2dFcnJvcihcIltzcGlmZnktYWldIEFzc2lzdGFudHMgVHVybiBlcnJvclwiLCBlcnJvcik7XG4gICAgICB9XG4gICAgfTtcbiAgICBpZiAodXNlclF1ZXVlRXZlbnRDb3VudCA+IDApIHtcbiAgICAgIHByb2Nlc3NVc2VyRXZlbnRzKCk7XG4gICAgfVxuICB9LCBbXG4gICAgZ2V0UmVzcG9uc2VzLFxuICAgIHJlc3BvbnNlU3RyZWFtaW5nLFxuICAgIHVzZXJRdWV1ZUV2ZW50Q291bnQsXG4gICAgd2lkZ2V0SW5pdGlhbGl6ZWQsXG4gICAgdmFyaWFudEluZm8sXG4gICAgc3VwcG9ydGVkRXZlbnQsXG4gIF0pO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKHdpZGdldEluaXRpYWxpemVkIHx8IHJlc3BvbnNlU3RyZWFtaW5nKSB7XG4gICAgICBMb2dnZXIubG9nRGVidWcoXG4gICAgICAgIGBbc3BpZmZ5LWFpXSBpbml0aWFsaXplV2lkZ2V0IFtza2lwcGVkXSBpc19jdXJyZW50bHlfc3RyZWFtaW5nPSR7cmVzcG9uc2VTdHJlYW1pbmd9IGlzX2luaXRpYWxpemVkPSR7d2lkZ2V0SW5pdGlhbGl6ZWR9YFxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBoeWRyYXRlQ2hhdCA9IGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIExvZ2dlci5sb2dEZWJ1ZyhcbiAgICAgICAgICBgW3NwaWZmeS1haV0gaW5pdGlhbGl6ZVdpZGdldCBpc19jdXJyZW50bHlfc3RyZWFtaW5nPSR7cmVzcG9uc2VTdHJlYW1pbmd9IGlzX2luaXRpYWxpemVkPSR7d2lkZ2V0SW5pdGlhbGl6ZWR9YFxuICAgICAgICApO1xuICAgICAgICAvLyBvbiBtb3VudCwgdHJ5IHRvIGdldCB0aGUgcmVzcG9uc2VzIGZyb20gYW4gYWN0aXZlIHNlc3Npb24gaWYgb25lIGV4aXN0c1xuICAgICAgICBpZiAoIW9yZ0lkKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3JnSWQgaXMgbm90IGF2YWlsYWJsZVwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IG1lc3NhZ2VzOiBleGlzdGluZ01lc3NhZ2VzLCB1c2VyRXZlbnRzIH0gPVxuICAgICAgICAgIGF3YWl0IENvbW1lcmNlQXBpQ2xpZW50LmdldFJlc3BvbnNlcyhvcmdJZCwgY2hhdElkLCB1c2VySWQpO1xuICAgICAgICBzZXRNZXNzYWdlcyhbLi4uZXhpc3RpbmdNZXNzYWdlc10pO1xuICAgICAgICBzZXRVc2VyRXZlbnRzKFsuLi51c2VyRXZlbnRzXSk7XG4gICAgICAgIGdldFJlc3BvbnNlcygpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgLy8gbm8gYWN0aXZlIGNoYXQgc2Vzc2lvbiB3YXMgZm91bmQsIHN0YXJ0IGEgbmV3IG9uZVxuICAgICAgICBMb2dnZXIubG9nSW5mbyhcbiAgICAgICAgICBgSW5pdCBjaGF0IFtleGNlcHRpb25dIGNoYXRfaWQ9JHtjaGF0SWR9IGVycm9yPSR7ZXJyb3J9YCxcbiAgICAgICAgICBlcnJvclxuICAgICAgICApO1xuICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTZXNzaW9uUmVzdGFydFJlcXVpcmVkKSB7XG4gICAgICAgICAgY29uc3QgYXBwTG9hZGVkRXZlbnQgPSBjcmVhdGVBcHBMb2FkZWRFdmVudCgpO1xuICAgICAgICAgIGNvbnN0IHZpc2l0RXZlbnQgPSBjcmVhdGVWaXNpdFVzZXJFdmVudCh7IHZhcmlhbnRJbmZvIH0pO1xuICAgICAgICAgIHNldE1lc3NhZ2VzKFtdKTtcbiAgICAgICAgICBjbGVhclVzZXJFdmVudFF1ZXVlKCk7XG4gICAgICAgICAgaWYgKHZpc2l0RXZlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSBjcmVhdGVSZXNwb25zZVBheWxvYWQoe1xuICAgICAgICAgICAgICB1c2VyRXZlbnRzOiBbYXBwTG9hZGVkRXZlbnQsIHZpc2l0RXZlbnRdLFxuICAgICAgICAgICAgICBnZW5lcmF0aW9uUGFyYW1zOiBzZXR0aW5nc0NvbnRleHQuZ2VuZXJhdGlvblBhcmFtcyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZ2V0UmVzcG9uc2VzKHBheWxvYWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgc2V0V2lkZ2V0SW5pdGlhbGl6ZWQodHJ1ZSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGh5ZHJhdGVDaGF0KCk7XG4gIH0sIFtdKTtcblxuICBjb25zdCBvbkZvY3VzID0gdXNlQ2FsbGJhY2soYXN5bmMgKCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBpZiAoIXJlc3BvbnNlU3RyZWFtaW5nICYmICFzdWdnZXN0aW9uc0xvYWRpbmcgJiYgb3JnSWQpIHtcbiAgICAgICAgY29uc3QgeyBtZXNzYWdlczogZXhpc3RpbmdNZXNzYWdlcyB9ID1cbiAgICAgICAgICBhd2FpdCBDb21tZXJjZUFwaUNsaWVudC5nZXRSZXNwb25zZXMob3JnSWQsIGNoYXRJZCwgdXNlcklkKTtcblxuICAgICAgICBpZiAoZXhpc3RpbmdNZXNzYWdlcy5sZW5ndGggPiBtZXNzYWdlcy5sZW5ndGgpIHtcbiAgICAgICAgICBzZXRNZXNzYWdlcyhbLi4uZXhpc3RpbmdNZXNzYWdlc10pO1xuICAgICAgICAgIC8vIFRPRE86IElzIHRoaXMgYnVnIGhhY2sgc3RpbGwgbmVjZXNzYXJ5P1xuICAgICAgICAgIC8vIElmIGl0IGlzLCBjb21lIHVwIHdpdGggYSBiZXR0ZXIgc29sdXRpb24gZm9yIGl0XG4gICAgICAgICAgLy8gfSBlbHNlIGlmIChleGlzdGluZ01lc3NhZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIC8vICAgLy8gaWYgdGhlcmUgd2FzIGFuIGVycm9yIGR1cmluZyB0aGUgaW5pdGlhbGl6YXRpb24gb2YgYSBuZXcgc2Vzc2lvbiwgdGhlIHNlc3Npb24gd291bGQgYmVcbiAgICAgICAgICAvLyAgIC8vIGNyZWF0ZWQgaW4gdGhlIGJhY2tlbmQgYnV0IHdpdGhvdXQgYW55IG1lc3NhZ2VzLiBSZXRyeSB0aGUgbmV4dF9yZXNwb25zZXMgcmVxdWVzdCB3aXRoXG4gICAgICAgICAgLy8gICAvLyB0aGUgY3VycmVudCBzZXQgb2YgcGFyYW1ldGVycyB0byBcImp1bXBzdGFydFwiIHRoZSBzZXNzaW9uXG4gICAgICAgICAgLy8gICB0cmlnZ2VyR2V0UmVzcG9uc2VDYWxsKCdvbkZvY3VzJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFwiW3NwaWZmeS1haV0gb25Gb2N1cyBlcnJvclwiLCBlcnJvcik7XG4gICAgfVxuICB9LCBbXG4gICAgcmVzcG9uc2VTdHJlYW1pbmcsXG4gICAgc3VnZ2VzdGlvbnNMb2FkaW5nLFxuICAgIG9yZ0lkLFxuICAgIGNoYXRJZCxcbiAgICB1c2VySWQsXG4gICAgbWVzc2FnZXMubGVuZ3RoLFxuICAgIHNldE1lc3NhZ2VzLFxuICBdKTtcblxuICAvLyBsaXN0ZW4gZm9yIHBhZ2UgZm9jdXMgdG8gZ2V0IGxhdGVzdCBtZXNzYWdlcyBmcm9tIHRoZSBzZXJ2ZXJcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcImZvY3VzXCIsIG9uRm9jdXMpO1xuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwiZm9jdXNcIiwgb25Gb2N1cyk7XG4gICAgfTtcbiAgfSwgW29uRm9jdXNdKTtcblxuICBjb25zdCBjaGF0Q29udGV4dCA9IHVzZU1lbW8oKCkgPT4gKHt9KSwgW10pO1xuXG4gIHJldHVybiAoXG4gICAgPENoYXRDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXtjaGF0Q29udGV4dH0+e2NoaWxkcmVufTwvQ2hhdENvbnRleHQuUHJvdmlkZXI+XG4gICk7XG59O1xuXG5leHBvcnQgeyBDaGF0Q29udGV4dCwgQ2hhdENvbnRleHRQcm92aWRlciB9O1xuZXhwb3J0IHR5cGUgeyBDaGF0Q29udGV4dFBhcmFtcyB9O1xuIiwiaW1wb3J0IFJlYWN0LCB7IFJlYWN0Tm9kZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgdXNlTmV3T3JnQ29uZmlnIH0gZnJvbSBcInNyYy9ob29rc1wiO1xuXG5pbnRlcmZhY2UgRW52aXZlQ3NzUHJvdmlkZXJQcm9wcyB7XG4gIGNoaWxkcmVuOiBSZWFjdE5vZGU7XG59XG5cbmV4cG9ydCBjb25zdCBFbnZpdmVDc3NQcm92aWRlcjogUmVhY3QuRkM8RW52aXZlQ3NzUHJvdmlkZXJQcm9wcz4gPSAoe1xuICBjaGlsZHJlbixcbn0pID0+IHtcbiAgY29uc3QgeyBjb2xvcnNDb25maWcsIGZyb250ZW5kQ29uZmlnLCBsb2FkaW5nIH0gPSB1c2VOZXdPcmdDb25maWcoKTtcbiAgbGV0IG1lcmNoYW50VGhlbWVDc3MgPSBgKiB7fWA7XG4gIGlmIChjb2xvcnNDb25maWcgJiYgIWxvYWRpbmcpIHtcbiAgICBtZXJjaGFudFRoZW1lQ3NzID0gYFxuKiB7XG4gIC0tc3BpZmZ5LWNvbG9ycy10ZXh0LXByaW1hcnk6ICR7Y29sb3JzQ29uZmlnLnRleHRQcmltYXJ5fTtcbiAgLS1zcGlmZnktY29sb3JzLXRleHQtc2Vjb25kYXJ5OiAke2NvbG9yc0NvbmZpZy50ZXh0U2Vjb25kYXJ5fTtcbiAgLS1zcGlmZnktY29sb3JzLXRleHQtYWNjZW50OiAke2NvbG9yc0NvbmZpZy50ZXh0QWNjZW50fTtcbiAgLS1zcGlmZnktY29sb3JzLXRleHQtbGluazogJHtjb2xvcnNDb25maWcudGV4dExpbmt9O1xuICAtLXNwaWZmeS1jb2xvcnMtdGV4dC1saWdodDogJHtjb2xvcnNDb25maWcudGV4dExpZ2h0fTtcbiAgLS1zcGlmZnktY29sb3JzLWJhY2tncm91bmQtcHJpbWFyeTogJHtjb2xvcnNDb25maWcuYmFja2dyb3VuZFByaW1hcnl9O1xuICAtLXNwaWZmeS1jb2xvcnMtYmFja2dyb3VuZC1zZWNvbmRhcnk6ICR7Y29sb3JzQ29uZmlnLmJhY2tncm91bmRTZWNvbmRhcnl9O1xuICAtLXNwaWZmeS1jb2xvcnMtYmFja2dyb3VuZC1zZWNvbmRhcnktZGFyazogJHtjb2xvcnNDb25maWcuYmFja2dyb3VuZFNlY29uZGFyeURhcmt9O1xuICAtLXNwaWZmeS1jb2xvcnMtYmFja2dyb3VuZC10ZXJ0aWFyeTogJHtjb2xvcnNDb25maWcuYmFja2dyb3VuZFRlcnRpYXJ5fTtcbiAgLS1zcGlmZnktY29sb3JzLWJhY2tncm91bmQtZGFyazogJHtjb2xvcnNDb25maWcuYmFja2dyb3VuZERhcmt9O1xuICAtLXNwaWZmeS1jb2xvcnMtYmFja2dyb3VuZC1saWdodDogJHtjb2xvcnNDb25maWcuYmFja2dyb3VuZExpZ2h0fTtcbiAgLS1zcGlmZnktY29sb3JzLWJhY2tncm91bmQtc2F0dXJhdGVkOiAke2NvbG9yc0NvbmZpZy5iYWNrZ3JvdW5kU2F0dXJhdGVkfTtcbiAgLS1zcGlmZnktY29sb3JzLWJvcmRlci1saWdodDogJHtjb2xvcnNDb25maWcuYm9yZGVyTGlnaHR9O1xuICAtLXNwaWZmeS1jb2xvcnMtYm9yZGVyLW1lZGl1bTogJHtjb2xvcnNDb25maWcuYm9yZGVyTWVkaXVtfTtcbiAgLS1zcGlmZnktY29sb3JzLWJvcmRlci1kYXJrOiAke2NvbG9yc0NvbmZpZy5ib3JkZXJEYXJrfTtcbiAgLS1zcGlmZnktY29sb3JzLWJvcmRlci1vdXRsaW5lOiAke2NvbG9yc0NvbmZpZy5ib3JkZXJPdXRsaW5lfTtcbiAgLS1zcGlmZnktY29sb3JzLWFjY2VudC1wcmltYXJ5OiAke2NvbG9yc0NvbmZpZy5hY2NlbnRQcmltYXJ5fTtcbiAgLS1zcGlmZnktY29sb3JzLWFjY2VudC1zZWNvbmRhcnk6ICR7Y29sb3JzQ29uZmlnLmFjY2VudFNlY29uZGFyeX07XG59YDtcbiAgfVxuICBjb25zb2xlLmxvZyhmcm9udGVuZENvbmZpZyk7XG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIHtmcm9udGVuZENvbmZpZyA/IChcbiAgICAgICAgPHN0eWxlIGlkPVwibWVyY2hhbnQtY3NzLW92ZXJyaWRlc1wiPntgJHtmcm9udGVuZENvbmZpZy5tZXJjaGFudE92ZXJyaWRlQ3NzfWB9PC9zdHlsZT5cbiAgICAgICkgOiBudWxsfVxuICAgICAge2NvbG9yc0NvbmZpZyA/IChcbiAgICAgICAgPHN0eWxlIGlkPVwibWVyY2hhbnQtY3NzLWNvbG9yc1wiPntgJHttZXJjaGFudFRoZW1lQ3NzfWB9PC9zdHlsZT5cbiAgICAgICkgOiBudWxsfVxuXG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC8+XG4gICk7XG59O1xuIiwiaW1wb3J0IHsgdXNlQXRvbVZhbHVlIH0gZnJvbSBcImpvdGFpXCI7XG5pbXBvcnQge1xuICBEaXNwYXRjaCxcbiAgUmVhY3ROb2RlLFxuICBTZXRTdGF0ZUFjdGlvbixcbiAgY3JlYXRlQ29udGV4dCxcbiAgdXNlTWVtbyxcbiAgdXNlU3RhdGUsXG59IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgR2VuZXJhdGlvblBhcmFtcyB9IGZyb20gXCJzcmMvYXBwbGljYXRpb24vbW9kZWxzXCI7XG5pbXBvcnQgeyBiYXNlVXJsQXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuXG4vLyBUT0RPOiBSZWZhY3RvciB0aGlzIHRvIGEgY29tbW9uIHNlcnZpY2UgdGhhdCBoYW5kbGVzIHF1ZXJ5IHBhcmFtcyAoYW5kIHNwaWZmeSB2YXJpYWJsZXMgYWxsIHRvZ2V0aGVyKVxuY29uc3QgZ2V0Q2hhdE1vZGVsTmFtZSA9ICgpID0+IHtcbiAgY29uc3QgdXJsT2JqID0gbmV3IFVSTCh3aW5kb3cubG9jYXRpb24uaHJlZik7XG4gIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXModXJsT2JqLnNlYXJjaCk7XG4gIGNvbnN0IHBhcmFtc09iaiA9IE9iamVjdC5mcm9tRW50cmllcyhwYXJhbXMuZW50cmllcygpKTtcbiAgcmV0dXJuIHBhcmFtc09iai5sbG1fbW9kZWxfbmFtZTtcbn07XG5cbmNvbnN0IGRlZmF1bHRHZW5lcmF0aW9uUGFyYW1zOiBHZW5lcmF0aW9uUGFyYW1zID0ge1xuICBzdHJlYW06IHRydWUsXG4gIG51bVN1Z2dlc3Rpb25zOiAzLFxuICBtb2RlbDogZ2V0Q2hhdE1vZGVsTmFtZSgpLFxufTtcblxuaW50ZXJmYWNlIFN5c3RlbVNldHRpbmdzQ29udGV4dFBhcmFtcyB7XG4gIGdlbmVyYXRpb25QYXJhbXM/OiBHZW5lcmF0aW9uUGFyYW1zO1xuICBzaG93RGVidWdCYXI/OiBib29sZWFuO1xuICBlbmRwb2ludFVSTD86IHN0cmluZztcbiAgc2V0R2VuZXJhdGlvblBhcmFtczogRGlzcGF0Y2g8U2V0U3RhdGVBY3Rpb248R2VuZXJhdGlvblBhcmFtcyB8IHVuZGVmaW5lZD4+O1xufVxuXG5pbnRlcmZhY2UgU3lzdGVtU2V0dGluZ3NDb250ZXh0UHJvdmlkZXJQcm9wcyB7XG4gIGNoaWxkcmVuOiBSZWFjdE5vZGU7XG4gIGdlbmVyYXRpb25QYXJhbXM/OiBHZW5lcmF0aW9uUGFyYW1zO1xuICBzaG93RGVidWdCYXI/OiBib29sZWFuO1xufVxuXG5jb25zdCBTeXN0ZW1TZXR0aW5nc0NvbnRleHQgPSBjcmVhdGVDb250ZXh0PFxuICBTeXN0ZW1TZXR0aW5nc0NvbnRleHRQYXJhbXMgfCB1bmRlZmluZWRcbj4odW5kZWZpbmVkKTtcblxuY29uc3QgU3lzdGVtU2V0dGluZ3NDb250ZXh0UHJvdmlkZXIgPSAoe1xuICBjaGlsZHJlbixcbiAgZ2VuZXJhdGlvblBhcmFtcyxcbiAgc2hvd0RlYnVnQmFyLFxufTogU3lzdGVtU2V0dGluZ3NDb250ZXh0UHJvdmlkZXJQcm9wcykgPT4ge1xuICBjb25zdCBbcGFyYW1zLCBzZXRQYXJhbXNdID0gdXNlU3RhdGU8R2VuZXJhdGlvblBhcmFtcyB8IHVuZGVmaW5lZD4oXG4gICAgKCkgPT4gZ2VuZXJhdGlvblBhcmFtcyA/PyBkZWZhdWx0R2VuZXJhdGlvblBhcmFtc1xuICApO1xuICBjb25zdCBlbmRwb2ludFVSTCA9IHVzZUF0b21WYWx1ZShiYXNlVXJsQXRvbSk7XG4gIGNvbnN0IHNldHRpbmdzQ29udGV4dFZhbHVlcyA9IHVzZU1lbW8oXG4gICAgKCkgPT4gKHtcbiAgICAgIGdlbmVyYXRpb25QYXJhbXM6IHBhcmFtcyxcbiAgICAgIHNob3dEZWJ1Z0JhcixcbiAgICAgIHNldEdlbmVyYXRpb25QYXJhbXM6IHNldFBhcmFtcyxcbiAgICAgIGVuZHBvaW50VVJMLFxuICAgIH0pLFxuICAgIFtnZW5lcmF0aW9uUGFyYW1zLCBlbmRwb2ludFVSTCwgc2hvd0RlYnVnQmFyXVxuICApO1xuXG4gIHJldHVybiAoXG4gICAgPFN5c3RlbVNldHRpbmdzQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17c2V0dGluZ3NDb250ZXh0VmFsdWVzfT5cbiAgICAgIHtjaGlsZHJlbn1cbiAgICA8L1N5c3RlbVNldHRpbmdzQ29udGV4dC5Qcm92aWRlcj5cbiAgKTtcbn07XG5cbmV4cG9ydCB7XG4gIFN5c3RlbVNldHRpbmdzQ29udGV4dFByb3ZpZGVyLFxuICBTeXN0ZW1TZXR0aW5nc0NvbnRleHQsXG4gIGRlZmF1bHRHZW5lcmF0aW9uUGFyYW1zLFxufTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFVQSxNQUFNLGFBQWEsY0FBcUMsS0FBSztBQUU3RCxNQUFhQSxlQUF3RCxFQUNuRSxlQUNJO0NBRUosTUFBTSxTQURrQixhQUFhLFdBQVcsSUFDZDtDQUVsQyxNQUFNLGlCQUFpQixrQkFBa0I7QUFDdkMsU0FBTztJQUNOLENBQUMsT0FBTyxDQUFDO0NBRVosTUFBTSxjQUFjLGFBQ2pCLFdBQW1CLGlCQUF5QjtBQUMzQyxTQUFPLEdBQUcsZ0JBQWdCLENBQUMsVUFBVSxhQUFhLEdBQUc7SUFFdkQsQ0FBQyxlQUFlLENBQ2pCO0NBRUQsTUFBTSxRQUFRLGVBQ0w7RUFDTDtFQUNBO0VBQ0E7RUFD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