@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.
- package/dist/NewOrgConfig-C5YL4Y62.cjs +20 -0
- package/dist/NewOrgConfig-CRyIfb_l.js +15 -0
- package/dist/SystemSettingsContext-Cb9YHln8.cjs +20 -0
- package/dist/SystemSettingsContext-D3mmGGcv.js +13 -0
- package/dist/TrackComponentVisibleEvent-C7c_rHFW.cjs +59 -0
- package/dist/TrackComponentVisibleEvent-DXTEBjGM.js +52 -0
- package/dist/amplitudeContext-CB_F-nJY.d.cts +52 -0
- package/dist/amplitudeContext-Cak6ijMq.js +287 -0
- package/dist/amplitudeContext-DFYBDc0h.d.ts +52 -0
- package/dist/amplitudeContext-sTEsPaVG.cjs +309 -0
- package/dist/api-DSFlctlc.cjs +269 -0
- package/dist/api-JTNjuOfc.js +190 -0
- package/dist/{app-CjsQ2_n-.js → app-D_upYeqF.js} +6 -6
- package/dist/{app-CnKRZ9RW.cjs → app-KXTMPa4s.cjs} +8 -8
- package/dist/application/models/graphql/index.cjs +2 -1
- package/dist/application/models/graphql/index.d.ts +1 -1
- package/dist/application/models/graphql/index.js +2 -1
- package/dist/application/models/guards/api/index.cjs +2 -1
- package/dist/application/models/guards/api/index.d.ts +2 -2
- package/dist/application/models/guards/api/index.js +2 -1
- package/dist/application/models/index.cjs +11 -9
- package/dist/application/models/index.d.cts +8 -4
- package/dist/application/models/index.d.ts +11 -7
- package/dist/application/models/index.js +10 -7
- package/dist/application/models/utilityTypes/index.cjs +1 -1
- package/dist/application/models/utilityTypes/index.d.ts +1 -1
- package/dist/application/models/utilityTypes/index.js +1 -1
- package/dist/application/models/variantInfo/index.cjs +1 -1
- package/dist/application/models/variantInfo/index.d.cts +1 -1
- package/dist/application/models/variantInfo/index.d.ts +1 -1
- package/dist/application/models/variantInfo/index.js +1 -1
- package/dist/application/utils/index.cjs +28 -22
- package/dist/application/utils/index.d.cts +12 -8
- package/dist/application/utils/index.d.ts +16 -12
- package/dist/application/utils/index.js +19 -13
- package/dist/{atomStore-B4jIaDPd.cjs → atomStore-DEZyFCNz.cjs} +1 -1
- package/dist/{atomStore-D8pjE1vL.js → atomStore-DnPEioF4.js} +1 -1
- package/dist/atoms/app/index.cjs +13 -9
- package/dist/atoms/app/index.d.cts +15 -11
- package/dist/atoms/app/index.d.ts +18 -14
- package/dist/atoms/app/index.js +13 -9
- package/dist/atoms/atomStore/index.cjs +2 -2
- package/dist/atoms/atomStore/index.d.cts +1 -1
- package/dist/atoms/atomStore/index.js +2 -2
- package/dist/atoms/chat/index.cjs +34 -28
- package/dist/atoms/chat/index.d.cts +35 -31
- package/dist/atoms/chat/index.d.ts +38 -34
- package/dist/atoms/chat/index.js +20 -14
- package/dist/atoms/globalSearch/index.cjs +1 -1
- package/dist/atoms/globalSearch/index.d.cts +5 -5
- package/dist/atoms/globalSearch/index.d.ts +5 -5
- package/dist/atoms/globalSearch/index.js +1 -1
- package/dist/atoms/org/index.cjs +6 -14
- package/dist/atoms/org/index.d.cts +27 -32
- package/dist/atoms/org/index.d.ts +30 -35
- package/dist/atoms/org/index.js +5 -11
- package/dist/atoms/search/index.cjs +44 -34
- package/dist/atoms/search/index.d.cts +9 -4
- package/dist/atoms/search/index.d.ts +12 -7
- package/dist/atoms/search/index.js +26 -16
- package/dist/atoms/search/types.cjs +5 -0
- package/dist/atoms/search/types.d.cts +2 -0
- package/dist/atoms/search/types.d.ts +2 -0
- package/dist/atoms/search/types.js +3 -0
- package/dist/cdnContext-BMjVfBft.cjs +53 -0
- package/dist/cdnContext-DgsJ00Tb.js +38 -0
- package/dist/{chat-CV6MXeID.js → chat-B4lkFIxz.js} +1 -1
- package/dist/chat-D1Eat8Ih.cjs +394 -0
- package/dist/chat-DPJGdUkz.js +258 -0
- package/dist/{chat-BubCW1as.cjs → chat-zA-K4tR_.cjs} +1 -1
- package/dist/chatElementDisplayLocation-9SW40Dd3.d.cts +25 -0
- package/dist/chatElementDisplayLocation-C1tRM5OD.d.ts +25 -0
- package/dist/chatSearch-B5jMnCYX.js +315 -0
- package/dist/chatSearch-DWMiyWN0.cjs +444 -0
- package/dist/chatState-BisPJd5g.cjs +120 -0
- package/dist/chatState-BrmBYY8l.js +34 -0
- package/dist/commerce-api-CxDIfeME.cjs +318 -0
- package/dist/commerce-api-DagLj3D_.js +311 -0
- package/dist/{components-B4T3Uzth.js → components-B1edduHz.js} +1 -1
- package/dist/{components-Cw9WjA6g.cjs → components-g0G58Kat.cjs} +1 -1
- package/dist/config/locators/components/chat/index.cjs +1 -1
- package/dist/config/locators/components/chat/index.d.cts +1 -1
- package/dist/config/locators/components/chat/index.d.ts +1 -1
- package/dist/config/locators/components/chat/index.js +1 -1
- package/dist/config/locators/components/chat/variants/index.d.cts +1 -1
- package/dist/config/locators/components/chat/variants/index.d.ts +1 -1
- package/dist/config/locators/components/index.cjs +1 -1
- package/dist/config/locators/components/index.d.cts +1 -1
- package/dist/config/locators/components/index.d.ts +1 -1
- package/dist/config/locators/components/index.js +1 -1
- package/dist/config/locators/components/search/index.d.cts +1 -1
- package/dist/config/locators/components/search/index.d.ts +1 -1
- package/dist/config/locators/index.cjs +42 -22
- package/dist/config/locators/index.d.cts +2 -2
- package/dist/config/locators/index.d.ts +3 -3
- package/dist/config/locators/index.js +25 -5
- package/dist/contexts/amplitudeContext/index.cjs +21 -0
- package/dist/contexts/amplitudeContext/index.d.cts +2 -0
- package/dist/contexts/amplitudeContext/index.d.ts +2 -0
- package/dist/contexts/amplitudeContext/index.js +19 -0
- package/dist/contexts/cdnContext/index.cjs +7 -0
- package/dist/contexts/cdnContext/index.d.cts +15 -0
- package/dist/contexts/cdnContext/index.d.ts +15 -0
- package/dist/contexts/cdnContext/index.js +6 -0
- package/dist/contexts/chatContext/index.cjs +329 -0
- package/dist/contexts/chatContext/index.d.cts +15 -0
- package/dist/contexts/chatContext/index.d.ts +15 -0
- package/dist/contexts/chatContext/index.js +322 -0
- package/dist/contexts/enviveConfigContext/index.cjs +7 -0
- package/dist/contexts/enviveConfigContext/index.d.cts +30 -0
- package/dist/contexts/enviveConfigContext/index.d.ts +30 -0
- package/dist/contexts/enviveConfigContext/index.js +6 -0
- package/dist/contexts/enviveCssContext/index.cjs +65 -0
- package/dist/contexts/enviveCssContext/index.d.cts +10 -0
- package/dist/contexts/enviveCssContext/index.d.ts +10 -0
- package/dist/contexts/enviveCssContext/index.js +62 -0
- package/dist/contexts/featureFlagContext/index.cjs +107 -0
- package/dist/contexts/featureFlagContext/index.d.cts +20 -0
- package/dist/contexts/featureFlagContext/index.d.ts +20 -0
- package/dist/contexts/featureFlagContext/index.js +103 -0
- package/dist/contexts/featureFlagServiceContext/index.cjs +6 -0
- package/dist/contexts/featureFlagServiceContext/index.d.cts +5 -0
- package/dist/contexts/featureFlagServiceContext/index.d.ts +5 -0
- package/dist/contexts/featureFlagServiceContext/index.js +5 -0
- package/dist/contexts/graphqlContext/index.cjs +15 -0
- package/dist/contexts/graphqlContext/index.d.cts +12 -0
- package/dist/contexts/graphqlContext/index.d.ts +12 -0
- package/dist/contexts/graphqlContext/index.js +14 -0
- package/dist/contexts/localStorageContext/index.cjs +6 -0
- package/dist/contexts/localStorageContext/index.d.cts +30 -0
- package/dist/contexts/localStorageContext/index.d.ts +30 -0
- package/dist/contexts/localStorageContext/index.js +4 -0
- package/dist/contexts/newOrgConfigContext/index.cjs +19 -0
- package/dist/contexts/newOrgConfigContext/index.d.cts +30 -0
- package/dist/contexts/newOrgConfigContext/index.d.ts +30 -0
- package/dist/contexts/newOrgConfigContext/index.js +18 -0
- package/dist/contexts/searchContext/index.cjs +23 -0
- package/dist/contexts/searchContext/index.d.cts +16 -0
- package/dist/contexts/searchContext/index.d.ts +16 -0
- package/dist/contexts/searchContext/index.js +22 -0
- package/dist/contexts/sessionStorageContext/index.cjs +5 -0
- package/dist/contexts/sessionStorageContext/index.d.cts +15 -0
- package/dist/contexts/sessionStorageContext/index.d.ts +15 -0
- package/dist/contexts/sessionStorageContext/index.js +4 -0
- package/dist/contexts/shopifyUrlContext/index.cjs +5 -0
- package/dist/contexts/shopifyUrlContext/index.d.cts +20 -0
- package/dist/contexts/shopifyUrlContext/index.d.ts +20 -0
- package/dist/contexts/shopifyUrlContext/index.js +4 -0
- package/dist/contexts/systemSettingsContext/index.cjs +8 -0
- package/dist/contexts/systemSettingsContext/index.d.cts +36 -0
- package/dist/contexts/systemSettingsContext/index.d.ts +36 -0
- package/dist/contexts/systemSettingsContext/index.js +6 -0
- package/dist/contexts/types.cjs +7 -0
- package/dist/contexts/types.d.cts +4 -0
- package/dist/contexts/types.d.ts +4 -0
- package/dist/contexts/types.js +3 -0
- package/dist/contexts/userIdentityContext/index.cjs +26 -0
- package/dist/contexts/userIdentityContext/index.d.cts +2 -0
- package/dist/contexts/userIdentityContext/index.d.ts +2 -0
- package/dist/contexts/userIdentityContext/index.js +25 -0
- package/dist/domObserver-B6cRGTny.js +285 -0
- package/dist/domObserver-DQZwhPrc.cjs +304 -0
- package/dist/enviveConfig-BJZ4zTJo.js +62 -0
- package/dist/enviveConfig-DdBrcGSQ.cjs +130 -0
- package/dist/enviveConfigContext-78orE_uH.cjs +60 -0
- package/dist/enviveConfigContext-jBCCWQH9.js +45 -0
- package/dist/events/index.cjs +1 -1
- package/dist/events/index.d.ts +1 -1
- package/dist/events/index.js +1 -1
- package/dist/{events-BrLpaNxh.js → events-BHJJjPDN.js} +1 -1
- package/dist/{events-DwT6cEwI.cjs → events-B_fJZf9E.cjs} +1 -1
- package/dist/featureFlagServiceContext-ChL7DJ53.cjs +56 -0
- package/dist/featureFlagServiceContext-D1PzHsEs.d.ts +23 -0
- package/dist/featureFlagServiceContext-DQwlCTde.d.cts +23 -0
- package/dist/featureFlagServiceContext-DzFfmb1Z.js +42 -0
- package/dist/featureGates-Blx10fwB.js +27 -0
- package/dist/featureGates-DcZNrUma.cjs +33 -0
- package/dist/frontendConfig-DrvrQSm8.d.ts +857 -0
- package/dist/frontendConfig-wg41mBok.d.cts +857 -0
- package/dist/{globalSearch-BFvEg53C.cjs → globalSearch-Bnjlxtr5.cjs} +1 -1
- package/dist/{globalSearch-B6THR7Jx.js → globalSearch-CRWUqnjq.js} +1 -1
- package/dist/graphql-B9HhDXYt.cjs +53 -0
- package/dist/graphql-W7GMIHUu.js +36 -0
- package/dist/graphqlConfig-Bn-HLHsh.cjs +39 -0
- package/dist/graphqlConfig-DtZm_YaH.js +14 -0
- package/dist/graphqlContext-BJg7B--J.js +96 -0
- package/dist/graphqlContext-DI-_VRmb.cjs +111 -0
- package/dist/hooks/AmplitudeOperations/index.cjs +21 -0
- package/dist/hooks/AmplitudeOperations/index.d.cts +12 -0
- package/dist/hooks/AmplitudeOperations/index.d.ts +12 -0
- package/dist/hooks/AmplitudeOperations/index.js +21 -0
- package/dist/hooks/AppDetails/index.cjs +18 -0
- package/dist/hooks/AppDetails/index.d.cts +26 -0
- package/dist/hooks/AppDetails/index.d.ts +26 -0
- package/dist/hooks/AppDetails/index.js +18 -0
- package/dist/hooks/BlockBackButton/index.cjs +29 -0
- package/dist/hooks/BlockBackButton/index.d.cts +5 -0
- package/dist/hooks/BlockBackButton/index.d.ts +5 -0
- package/dist/hooks/BlockBackButton/index.js +27 -0
- package/dist/hooks/CdnOperations/index.cjs +24 -0
- package/dist/hooks/CdnOperations/index.d.cts +7 -0
- package/dist/hooks/CdnOperations/index.d.ts +7 -0
- package/dist/hooks/CdnOperations/index.js +22 -0
- package/dist/hooks/ChatToggle/index.cjs +63 -0
- package/dist/hooks/ChatToggle/index.d.cts +12 -0
- package/dist/hooks/ChatToggle/index.d.ts +12 -0
- package/dist/hooks/ChatToggle/index.js +61 -0
- package/dist/hooks/ChatToggleAnalytics/index.cjs +37 -0
- package/dist/hooks/ChatToggleAnalytics/index.d.cts +9 -0
- package/dist/hooks/ChatToggleAnalytics/index.d.ts +9 -0
- package/dist/hooks/ChatToggleAnalytics/index.js +35 -0
- package/dist/hooks/CustomerSupportHandoff/index.cjs +36 -0
- package/dist/hooks/CustomerSupportHandoff/index.d.cts +16 -0
- package/dist/hooks/CustomerSupportHandoff/index.d.ts +16 -0
- package/dist/hooks/CustomerSupportHandoff/index.js +34 -0
- package/dist/hooks/Debounce/index.cjs +3 -0
- package/dist/hooks/Debounce/index.d.cts +5 -0
- package/dist/hooks/Debounce/index.d.ts +5 -0
- package/dist/hooks/Debounce/index.js +3 -0
- package/dist/hooks/ElementObserver/index.cjs +179 -0
- package/dist/hooks/ElementObserver/index.d.cts +29 -0
- package/dist/hooks/ElementObserver/index.d.ts +29 -0
- package/dist/hooks/ElementObserver/index.js +177 -0
- package/dist/hooks/GrabAndScroll/index.cjs +99 -0
- package/dist/hooks/GrabAndScroll/index.d.cts +14 -0
- package/dist/hooks/GrabAndScroll/index.d.ts +14 -0
- package/dist/hooks/GrabAndScroll/index.js +97 -0
- package/dist/hooks/GraphQLConfig/index.cjs +16 -0
- package/dist/hooks/GraphQLConfig/index.d.cts +15 -0
- package/dist/hooks/GraphQLConfig/index.d.ts +15 -0
- package/dist/hooks/GraphQLConfig/index.js +15 -0
- package/dist/hooks/IdentifyUser/index.cjs +59 -0
- package/dist/hooks/IdentifyUser/index.d.cts +10 -0
- package/dist/hooks/IdentifyUser/index.d.ts +10 -0
- package/dist/hooks/IdentifyUser/index.js +57 -0
- package/dist/hooks/ImageResolver/index.cjs +54 -0
- package/dist/hooks/ImageResolver/index.d.cts +7 -0
- package/dist/hooks/ImageResolver/index.d.ts +7 -0
- package/dist/hooks/ImageResolver/index.js +52 -0
- package/dist/hooks/Intersection/index.cjs +3 -0
- package/dist/hooks/Intersection/index.d.cts +7 -0
- package/dist/hooks/Intersection/index.d.ts +7 -0
- package/dist/hooks/Intersection/index.js +3 -0
- package/dist/hooks/IsSmallScreen/index.cjs +22 -0
- package/dist/hooks/IsSmallScreen/index.d.cts +5 -0
- package/dist/hooks/IsSmallScreen/index.d.ts +5 -0
- package/dist/hooks/IsSmallScreen/index.js +20 -0
- package/dist/hooks/LocalStorageOperations/index.cjs +79 -0
- package/dist/hooks/LocalStorageOperations/index.d.cts +17 -0
- package/dist/hooks/LocalStorageOperations/index.d.ts +17 -0
- package/dist/hooks/LocalStorageOperations/index.js +74 -0
- package/dist/hooks/MessageFilter/index.cjs +53 -0
- package/dist/hooks/MessageFilter/index.d.cts +29 -0
- package/dist/hooks/MessageFilter/index.d.ts +29 -0
- package/dist/hooks/MessageFilter/index.js +53 -0
- package/dist/hooks/MessageScrollObserver/index.cjs +36 -0
- package/dist/hooks/MessageScrollObserver/index.d.cts +5 -0
- package/dist/hooks/MessageScrollObserver/index.d.ts +5 -0
- package/dist/hooks/MessageScrollObserver/index.js +34 -0
- package/dist/hooks/NewOrgConfig/index.cjs +19 -0
- package/dist/hooks/NewOrgConfig/index.d.cts +22 -0
- package/dist/hooks/NewOrgConfig/index.d.ts +22 -0
- package/dist/hooks/NewOrgConfig/index.js +19 -0
- package/dist/hooks/Search/index.cjs +324 -0
- package/dist/hooks/Search/index.d.cts +66 -0
- package/dist/hooks/Search/index.d.ts +66 -0
- package/dist/hooks/Search/index.js +321 -0
- package/dist/hooks/SearchOperations/index.cjs +101 -0
- package/dist/hooks/SearchOperations/index.d.cts +22 -0
- package/dist/hooks/SearchOperations/index.d.ts +22 -0
- package/dist/hooks/SearchOperations/index.js +98 -0
- package/dist/hooks/SessionStorageOperations/index.cjs +30 -0
- package/dist/hooks/SessionStorageOperations/index.d.cts +8 -0
- package/dist/hooks/SessionStorageOperations/index.d.ts +8 -0
- package/dist/hooks/SessionStorageOperations/index.js +28 -0
- package/dist/hooks/ShopifyUrlOperations/index.cjs +53 -0
- package/dist/hooks/ShopifyUrlOperations/index.d.cts +23 -0
- package/dist/hooks/ShopifyUrlOperations/index.d.ts +23 -0
- package/dist/hooks/ShopifyUrlOperations/index.js +49 -0
- package/dist/hooks/SnapCalculator/index.cjs +29 -0
- package/dist/hooks/SnapCalculator/index.d.cts +12 -0
- package/dist/hooks/SnapCalculator/index.d.ts +12 -0
- package/dist/hooks/SnapCalculator/index.js +27 -0
- package/dist/hooks/SystemSettingsContext/index.cjs +7 -0
- package/dist/hooks/SystemSettingsContext/index.d.cts +22 -0
- package/dist/hooks/SystemSettingsContext/index.d.ts +22 -0
- package/dist/hooks/SystemSettingsContext/index.js +7 -0
- package/dist/hooks/TrackComponentVisibleEvent/index.cjs +21 -0
- package/dist/hooks/TrackComponentVisibleEvent/index.d.cts +18 -0
- package/dist/hooks/TrackComponentVisibleEvent/index.d.ts +18 -0
- package/dist/hooks/TrackComponentVisibleEvent/index.js +21 -0
- package/dist/hooks/UpdateAnalyticsProps/index.cjs +61 -0
- package/dist/hooks/UpdateAnalyticsProps/index.d.cts +9 -0
- package/dist/hooks/UpdateAnalyticsProps/index.d.ts +9 -0
- package/dist/hooks/UpdateAnalyticsProps/index.js +58 -0
- package/dist/index-BCLaqnc2.d.cts +689 -0
- package/dist/{index-ylUiJvnr.d.ts → index-BS7-_CW4.d.ts} +1 -1
- package/dist/index-Bmub8e38.d.cts +1 -1
- package/dist/index-Bs0QtkSu.d.ts +689 -0
- package/dist/index-CESxqFso.d.cts +1 -1
- package/dist/index-CKeS9dud.d.ts +28 -0
- package/dist/index-CiWEYzXl.d.cts +1 -1
- package/dist/index-CyXULMyI.d.cts +186 -0
- package/dist/index-Cz10TYQA.d.cts +28 -0
- package/dist/{index-B0NW9KTj.d.cts → index-D46Rd0io.d.cts} +1 -1
- package/dist/{index-C6KdON7d.d.ts → index-D8ThXrqI.d.ts} +1 -1
- package/dist/{index-PGF8BvxQ.d.ts → index-D9VegTU-.d.ts} +1 -1
- package/dist/{index-DOii3C6b.d.ts → index-DBqgBV9N.d.ts} +1 -1
- package/dist/{index-Cqg6ltII.d.ts → index-DNUKSg6R.d.ts} +1 -1
- package/dist/{index-BDPWBU3h.d.cts → index-DO0s5KNA.d.cts} +1 -1
- package/dist/{index-CcIG01PJ.d.ts → index-DuyZQOE1.d.ts} +2 -2
- package/dist/{index-Byb45OPg.d.cts → index-REhT-Pls.d.cts} +1 -1
- package/dist/index-fKJB9EFb.d.ts +186 -0
- package/dist/interceptors/index.cjs +2 -1
- package/dist/interceptors/index.d.cts +9 -10
- package/dist/interceptors/index.d.ts +12 -13
- package/dist/interceptors/index.js +2 -1
- package/dist/interceptors/types.cjs +1 -0
- package/dist/interceptors/types.d.cts +12 -0
- package/dist/interceptors/types.d.ts +12 -0
- package/dist/interceptors/types.js +3 -0
- package/dist/localStorageContext-6OrGDFid.js +95 -0
- package/dist/localStorageContext-Bld0OWmG.cjs +115 -0
- package/dist/logger-CSL2jqI9.cjs +26 -0
- package/dist/logger-D5MFf3nW.js +20 -0
- package/dist/{models-BkXg5eIP.cjs → models-Dn8Emdzc.js} +219 -458
- package/dist/models-ZpQcRZQK.cjs +1536 -0
- package/dist/newOrgConfigAtom--tewb_G0.js +8 -0
- package/dist/newOrgConfigAtom-DkSi45_Q.cjs +15 -0
- package/dist/newOrgConfigContext-B3aeblfE.cjs +68 -0
- package/dist/newOrgConfigContext-B5mzHKTG.js +53 -0
- package/dist/{nodeSelector-BxrS2S_k.d.ts → nodeSelector-DybpVr-i.d.ts} +1 -1
- package/dist/{nodeSelector-Dm4S-10n.d.cts → nodeSelector-XsUa5vNH.d.cts} +1 -1
- package/dist/org-B2uRkPt3.js +12 -0
- package/dist/org-ClUxpHPZ.cjs +43 -0
- package/dist/{orgAnalyticsConfig-BJ2A1RZ-.cjs → orgAnalyticsConfig-CuWXijsr.cjs} +1 -1
- package/dist/{orgAnalyticsConfig-ClrFy2qH.js → orgAnalyticsConfig-DOceTdNp.js} +1 -1
- package/dist/search-BIomqYy6.d.ts +20 -0
- package/dist/search-B_Hg-Es2.d.cts +20 -0
- package/dist/search-Bn4x-3TG.js +126 -0
- package/dist/search-DsQm_pAi.cjs +205 -0
- package/dist/{search-filter-types-fZf91Pdw.d.ts → search-filter-types-B5xcaEit.d.ts} +1 -1
- package/dist/{search-filter-types-DosbseF3.d.cts → search-filter-types-Byd0lEUa.d.cts} +1 -1
- package/dist/searchContext-Cn-pCoDy.cjs +145 -0
- package/dist/searchContext-fQDGSvUF.js +129 -0
- package/dist/searchServiceAdapter-BSPZOg1r.js +16 -0
- package/dist/searchServiceAdapter-DrjFCiw8.cjs +34 -0
- package/dist/sessionStorageContext-C5MUl2zf.js +52 -0
- package/dist/sessionStorageContext-CXE7iHtP.cjs +66 -0
- package/dist/shopifyUrlContext-7ppKx1jJ.cjs +75 -0
- package/dist/shopifyUrlContext-BSYWsoX9.js +61 -0
- package/dist/spiffyWidgets-CdxRcXhW.d.ts +20 -0
- package/dist/spiffyWidgets-DxGuuuCG.d.cts +20 -0
- package/dist/systemSettingsContext-BdAe_3Ll.cjs +60 -0
- package/dist/systemSettingsContext-Cjyo2o3N.js +39 -0
- package/dist/{test-types-CgVJtwUr.d.cts → test-types-DQB1JqOf.d.cts} +1 -1
- package/dist/{test-types-C9b_OdfO.d.ts → test-types-ZuRAYwox.d.ts} +1 -1
- package/dist/types/index.cjs +33 -5
- package/dist/types/index.d.cts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +30 -3
- package/dist/types-BCz-hOvv.d.ts +51 -0
- package/dist/types-BwNrLPSZ.cjs +106 -0
- package/dist/types-D3uOF0Oy.js +76 -0
- package/dist/types-DIk0FLwd.js +30 -0
- package/dist/types-DNLkuGWZ.cjs +48 -0
- package/dist/types-DzwBmZHy.d.cts +10 -0
- package/dist/types-Eip78dWv.d.cts +51 -0
- package/dist/types-YvACLe2e.d.ts +10 -0
- package/dist/types.d.cts +15 -0
- package/dist/types.d.ts +15 -0
- package/dist/unsupportedProductExceptions--t7AQFou.js +20 -0
- package/dist/unsupportedProductExceptions-Dak4AD-t.cjs +32 -0
- package/dist/urlsParser-BV5yF8sa.cjs +78 -0
- package/dist/urlsParser-DUgV_Qy9.js +42 -0
- package/dist/useAmplitudeOperations-C6Osqkso.js +34 -0
- package/dist/useAmplitudeOperations-Cco_B3A5.cjs +41 -0
- package/dist/useAppDetails-CGqtN6sJ.cjs +38 -0
- package/dist/useAppDetails-DwX2Rhed.js +30 -0
- package/dist/useDebounce-BJqnCBcl.cjs +26 -0
- package/dist/useDebounce-Ce31ph7m.js +19 -0
- package/dist/useGraphQLConfig-ByOZb3oZ.js +63 -0
- package/dist/useGraphQLConfig-DItL4BgM.cjs +76 -0
- package/dist/useIntersection-Czeo04jt.js +21 -0
- package/dist/useIntersection-DnZNLcnu.cjs +28 -0
- package/dist/{useMessageInterceptor-B87e3yu3.cjs → useMessageInterceptor-C9p9No1n.cjs} +3 -3
- package/dist/{useMessageInterceptor-Bb7YRaWk.js → useMessageInterceptor-tntd2rvB.js} +2 -2
- package/dist/userIdentityContext-C1HzZFb2.cjs +125 -0
- package/dist/userIdentityContext-CDfosvOO.js +109 -0
- package/dist/userIdentityContext-DBXoLrFu.d.cts +20 -0
- package/dist/userIdentityContext-W1OWF3cG.d.ts +20 -0
- package/dist/utilityTypes-CWJZb9BZ.js +1 -0
- package/dist/utilityTypes-YGiMSyV7.cjs +0 -0
- package/dist/utils-BA5HXmkL.cjs +74 -0
- package/dist/utils-BTDw2aMx.cjs +715 -0
- package/dist/utils-C7S9YiFp.js +54 -0
- package/dist/utils-CF13DfA1.js +606 -0
- package/dist/variantInfo-58JLeDJb.js +1 -0
- package/dist/variantInfo-DRFLcGc7.cjs +0 -0
- package/package.json +179 -7
- package/src/application/models/index.ts +0 -1
- package/src/application/utils/analyticsUtils.ts +1 -1
- package/src/atoms/amplitude/amplitudeTrackEventAtom.ts +1 -1
- package/src/atoms/app/index.ts +1 -1
- package/src/atoms/chat/chatState.ts +1 -1
- package/src/atoms/chat/replies.ts +1 -1
- package/src/atoms/org/graphqlConfig.ts +1 -39
- package/src/atoms/org/index.ts +0 -1
- package/src/atoms/org/newOrgConfigAtom.ts +2 -6
- package/src/contexts/{amplitudeContext.tsx → amplitudeContext/amplitudeContext.tsx} +1 -2
- package/src/contexts/amplitudeContext/index.ts +1 -0
- package/src/contexts/{cdnContext.tsx → cdnContext/cdnContext.tsx} +1 -1
- package/src/contexts/cdnContext/index.ts +1 -0
- package/src/contexts/{chatContext.tsx → chatContext/chatContext.tsx} +3 -3
- package/src/contexts/chatContext/index.ts +1 -0
- package/src/contexts/{enviveConfigContext.tsx → enviveConfigContext/enviveConfigContext.tsx} +1 -1
- package/src/contexts/enviveConfigContext/index.ts +1 -0
- package/src/contexts/{enviveCssContext.tsx → enviveCssContext/enviveCssContext.tsx} +1 -1
- package/src/contexts/enviveCssContext/index.ts +1 -0
- package/src/contexts/{featureFlagContext.tsx → featureFlagContext/featureFlagContext.tsx} +1 -1
- package/src/contexts/featureFlagContext/index.ts +1 -0
- package/src/contexts/featureFlagServiceContext/index.ts +1 -0
- package/src/contexts/graphqlContext/index.ts +1 -0
- package/src/contexts/localStorageContext/index.ts +1 -0
- package/src/contexts/{localStorageContext.tsx → localStorageContext/localStorageContext.tsx} +2 -2
- package/src/contexts/newOrgConfigContext/index.ts +1 -0
- package/src/contexts/newOrgConfigContext/newOrgConfigContext.tsx +70 -0
- package/src/contexts/searchContext/index.ts +1 -0
- package/src/contexts/{searchContext.tsx → searchContext/searchContext.tsx} +5 -5
- package/src/contexts/sessionStorageContext/index.ts +1 -0
- package/src/contexts/{sessionStorageContext.tsx → sessionStorageContext/sessionStorageContext.tsx} +1 -1
- package/src/contexts/shopifyUrlContext/index.ts +1 -0
- package/src/contexts/systemSettingsContext/index.ts +1 -0
- package/src/contexts/userIdentityContext/index.ts +1 -0
- package/src/events/registerAnalyticsListeners.ts +2 -2
- package/src/favicon.ico +0 -0
- package/src/hooks/AmplitudeOperations/index.ts +1 -0
- package/src/hooks/{useAmplitudeOperations.ts → AmplitudeOperations/useAmplitudeOperations.ts} +1 -1
- package/src/hooks/AppDetails/index.ts +1 -0
- package/src/hooks/{useAppDetails.ts → AppDetails/useAppDetails.ts} +1 -3
- package/src/hooks/BlockBackButton/index.ts +1 -0
- package/src/hooks/CdnOperations/index.ts +1 -0
- package/src/hooks/{useCdnOperations.ts → CdnOperations/useCdnOperations.ts} +1 -1
- package/src/hooks/ChatToggle/index.ts +1 -0
- package/src/hooks/{useChatToggle.ts → ChatToggle/useChatToggle.ts} +1 -1
- package/src/hooks/ChatToggleAnalytics/index.ts +1 -0
- package/src/hooks/{useChatToggleAnalytics.ts → ChatToggleAnalytics/useChatToggleAnalytics.ts} +1 -1
- package/src/hooks/CustomerSupportHandoff/index.ts +1 -0
- package/src/hooks/Debounce/index.ts +1 -0
- package/src/hooks/ElementObserver/index.ts +1 -0
- package/src/hooks/GrabAndScroll/index.ts +1 -0
- package/src/hooks/GraphQLConfig/index.ts +1 -0
- package/src/hooks/{useGraphQLConfig.ts → GraphQLConfig/useGraphQLConfig.ts} +1 -1
- package/src/hooks/IdentifyUser/index.ts +1 -0
- package/src/hooks/{useIdentifyUser.ts → IdentifyUser/useIdentifyUser.ts} +1 -1
- package/src/hooks/ImageResolver/index.ts +1 -0
- package/src/hooks/Intersection/index.ts +1 -0
- package/src/hooks/IsSmallScreen/index.ts +1 -0
- package/src/hooks/LocalStorageOperations/index.ts +1 -0
- package/src/hooks/{useLocalStorageOperations.ts → LocalStorageOperations/useLocalStorageOperations.ts} +2 -2
- package/src/hooks/MessageFilter/index.ts +1 -0
- package/src/hooks/MessageScrollObserver/index.ts +1 -0
- package/src/hooks/NewOrgConfig/index.ts +1 -0
- package/src/hooks/{useNewOrgConfig.ts → NewOrgConfig/useNewOrgConfig.ts} +1 -1
- package/src/hooks/Search/index.ts +1 -0
- package/src/hooks/{useSearch.tsx → Search/useSearch.tsx} +5 -4
- package/src/hooks/SearchOperations/index.ts +1 -0
- package/src/hooks/SessionStorageOperations/index.ts +1 -0
- package/src/hooks/{useSessionStorageOperations.ts → SessionStorageOperations/useSessionStorageOperations.ts} +1 -1
- package/src/hooks/ShopifyUrlOperations/index.ts +1 -0
- package/src/hooks/{useShopifyUrlOperations.ts → ShopifyUrlOperations/useShopifyUrlOperations.ts} +1 -1
- package/src/hooks/SnapCalculator/index.ts +1 -0
- package/src/hooks/SystemSettingsContext/index.ts +1 -0
- package/src/hooks/SystemSettingsContext/useSystemSettingsContext.ts +14 -0
- package/src/hooks/TrackComponentVisibleEvent/index.ts +1 -0
- package/src/hooks/{useTrackComponentVisibleEvent.ts → TrackComponentVisibleEvent/useTrackComponentVisibleEvent.ts} +2 -2
- package/src/hooks/UpdateAnalyticsProps/index.ts +1 -0
- package/src/hooks/{useUpdateAnalyticsProps.ts → UpdateAnalyticsProps/useUpdateAnalyticsProps.ts} +1 -1
- package/dist/amplitudeContext-CHzas7Cf.d.cts +0 -52
- package/dist/amplitudeContext-D-7fmVh1.cjs +0 -356
- package/dist/amplitudeContext-hY3caPC6.js +0 -322
- package/dist/amplitudeContext-tJ4y-SzX.d.ts +0 -52
- package/dist/api-DjeZXxl_.js +0 -207
- package/dist/api-_JaUnIUj.cjs +0 -292
- package/dist/bandolier-DYEz4-8C.js +0 -1229
- package/dist/bandolier-o_-xrbOV.cjs +0 -1229
- package/dist/carpe-CsG5jCcl.cjs +0 -607
- package/dist/carpe-DONk00bZ.js +0 -605
- package/dist/cdnUtils-32v8bDX9.cjs +0 -16
- package/dist/cdnUtils-E4tLBt2g.js +0 -11
- package/dist/chat-CO7cRkaq.cjs +0 -506
- package/dist/chat-hcRc4RRd.js +0 -285
- package/dist/contexts/index.cjs +0 -57
- package/dist/contexts/index.d.cts +0 -10
- package/dist/contexts/index.d.ts +0 -10
- package/dist/contexts/index.js +0 -23
- package/dist/contexts-B4ihTBsV.cjs +0 -2980
- package/dist/contexts-DGlr7M1o.js +0 -2596
- package/dist/coterie-CKB93qfz.cjs +0 -239
- package/dist/coterie-DHcj2fRE.js +0 -239
- package/dist/custservice-types-Dy0kc9TW.cjs +0 -35
- package/dist/custservice-types-mnIunabv.js +0 -23
- package/dist/default-BnB4p0Se.cjs +0 -234
- package/dist/default-D6f5Dyt7.js +0 -199
- package/dist/default-ZKkE5zT4.cjs +0 -4
- package/dist/default-legGZJwI.js +0 -4
- package/dist/divIds-2dJlU3z8.cjs +0 -117
- package/dist/divIds-BUrN2vY-.js +0 -21
- package/dist/dreamlandBaby-BiRYYFav.js +0 -346
- package/dist/dreamlandBaby-zuvmfzfD.cjs +0 -346
- package/dist/embedded-BJLWIriJ.js +0 -23
- package/dist/embedded-Dl79TJLC.cjs +0 -131
- package/dist/entrypoints-Bs3pn6EV.js +0 -7
- package/dist/entrypoints-Dqi5pzWH.cjs +0 -19
- package/dist/enviveConfig-BccuzS2a.cjs +0 -240
- package/dist/enviveConfig-CzhTz8Aa.js +0 -152
- package/dist/fiveCbd-DwTTwC2j.cjs +0 -613
- package/dist/fiveCbd-Dz2NouOF.js +0 -613
- package/dist/forLoveAndLemons-DqSdyD6S.js +0 -665
- package/dist/forLoveAndLemons-Ud6mPrV3.cjs +0 -667
- package/dist/graphql-BNW60InJ.cjs +0 -128
- package/dist/graphql-CjB8wHzm.js +0 -74
- package/dist/graphqlConfig-CYt6tWII.js +0 -30
- package/dist/graphqlConfig-DicykC-o.cjs +0 -61
- package/dist/greenpan-B_EbPkSP.js +0 -397
- package/dist/greenpan-kPE4fJgd.cjs +0 -397
- package/dist/grooveLife-Ckuir319.js +0 -342
- package/dist/grooveLife-DKSEQp1F.cjs +0 -342
- package/dist/homegrownCannabis-BVPa2pqe.js +0 -410
- package/dist/homegrownCannabis-BwIAkxuA.cjs +0 -410
- package/dist/hooks/index.cjs +0 -63
- package/dist/hooks/index.d.cts +0 -314
- package/dist/hooks/index.d.ts +0 -314
- package/dist/hooks/index.js +0 -23
- package/dist/index-BMPtlgac.d.ts +0 -191
- package/dist/index-C7pGDl1A.d.ts +0 -1609
- package/dist/index-C9lgsCWp.d.cts +0 -203
- package/dist/index-Cc-wBCn6.d.ts +0 -203
- package/dist/index-DTu2X-YS.d.cts +0 -1609
- package/dist/index-OEifcBsm.d.cts +0 -191
- package/dist/jackArcher-B39OEIj6.cjs +0 -727
- package/dist/jackArcher-BwkWGybC.js +0 -727
- package/dist/jordanCraig-CxRH_jLi.js +0 -1786
- package/dist/jordanCraig-RwmWw-jM.cjs +0 -1786
- package/dist/kindredBravely-D78VwL20.cjs +0 -490
- package/dist/kindredBravely-DQDpAzdl.js +0 -490
- package/dist/kutFromTheKloth-TcXQkIti.js +0 -369
- package/dist/kutFromTheKloth-dXRrNti0.cjs +0 -369
- package/dist/larryAndSerges-Bh5XEXsZ.js +0 -262
- package/dist/larryAndSerges-COdBzOzu.cjs +0 -262
- package/dist/leapsAndRebounds-BbXnqkl5.cjs +0 -360
- package/dist/leapsAndRebounds-mjCaH1k-.js +0 -360
- package/dist/longevityrx-DdV3v26F.cjs +0 -320
- package/dist/longevityrx-DfPDfvAt.js +0 -320
- package/dist/lookOptic-DgXFGBPP.cjs +0 -282
- package/dist/lookOptic-FgVW1afF.js +0 -282
- package/dist/mantraBrand-C5gVm3rk.cjs +0 -750
- package/dist/mantraBrand-uV8HCDR8.js +0 -750
- package/dist/medterra-BtDpr1Hw.cjs +0 -583
- package/dist/medterra-DgzE7-mj.js +0 -583
- package/dist/modells-CJjsxOIR.js +0 -484
- package/dist/modells-Ck5KbRFj.cjs +0 -484
- package/dist/models-UZ6HszfZ.js +0 -1281
- package/dist/org-C2RrBVQR.cjs +0 -81
- package/dist/org-xMytX--e.js +0 -38
- package/dist/pressedFloral-Bteoboms.js +0 -661
- package/dist/pressedFloral-CexgV-xy.cjs +0 -661
- package/dist/search-BMOAmrmY.js +0 -459
- package/dist/search-Df0Ifneg.cjs +0 -672
- package/dist/skinPerfection-BGzq9lq-.cjs +0 -334
- package/dist/skinPerfection-BlvcEcUE.js +0 -334
- package/dist/snapSupplements-CbbGzAgO.cjs +0 -285
- package/dist/snapSupplements-kcsPAOm9.js +0 -285
- package/dist/socialProofClasses-Db8gzsfi.cjs +0 -40
- package/dist/socialProofClasses-kwDvwLOZ.js +0 -10
- package/dist/spanx-B4WFA_rI.js +0 -661
- package/dist/spanx-BWoE4F8b.cjs +0 -663
- package/dist/spanxStaging-BOrOjhXn.js +0 -845
- package/dist/spanxStaging-BfdfIug4.cjs +0 -848
- package/dist/suggestionBarV2-types-IMMOmCir.js +0 -10
- package/dist/suggestionBarV2-types-nnGNgFvR.cjs +0 -16
- package/dist/supergoop-22dd5_BS.js +0 -323
- package/dist/supergoop-B-a4cku2.cjs +0 -323
- package/dist/types--pr1GQQx.js +0 -154
- package/dist/types-BVSyY3Hk.cjs +0 -196
- package/dist/uniqueVintage-CJXiNNe7.js +0 -1211
- package/dist/uniqueVintage-D0jzJWlo.cjs +0 -1213
- package/dist/userIdentityContext-BPqvVIg0.d.cts +0 -20
- package/dist/userIdentityContext-wbCRmlzp.d.ts +0 -20
- package/dist/utils-C9ZSCx12.js +0 -888
- package/dist/utils-D5HO61hG.cjs +0 -1016
- package/dist/venaCbd-Bhhu_qUf.cjs +0 -365
- package/dist/venaCbd-CanovPS_.js +0 -365
- package/dist/westonJonBoucher-BC0x1ktI.cjs +0 -422
- package/dist/westonJonBoucher-BUu1_wP1.js +0 -422
- package/dist/wineEnthusiast-BlCryfil.cjs +0 -940
- package/dist/wineEnthusiast-Ck1x5iJq.js +0 -940
- package/dist/wolfMattress-D9Mjq-HP.js +0 -372
- package/dist/wolfMattress-JssghhC-.cjs +0 -372
- package/dist/wolfTactical-C6exYhL7.cjs +0 -349
- package/dist/wolfTactical-CnV3KQdI.js +0 -349
- package/src/application/models/supportedOrgs.ts +0 -161
- package/src/atoms/org/orgPageConfig.ts +0 -42
- package/src/contexts/index.ts +0 -16
- package/src/contexts/newOrgConfigContext.tsx +0 -104
- package/src/contexts/orgConfigContext.tsx +0 -106
- package/src/hooks/index.ts +0 -27
- package/src/hooks/useSystemSettingsContext.ts +0 -12
- package/src/merchants/bandolier/bandolier.ts +0 -1371
- package/src/merchants/carpe/carpe.ts +0 -653
- package/src/merchants/coterie/coterie.ts +0 -277
- package/src/merchants/default.ts +0 -196
- package/src/merchants/dreamlandBaby/dreamlandBaby.ts +0 -381
- package/src/merchants/fiveCbd/fiveCbd.ts +0 -691
- package/src/merchants/forLoveAndLemons/forLoveAndLemons.ts +0 -751
- package/src/merchants/greenpan/greenpan.ts +0 -434
- package/src/merchants/grooveLife/grooveLife.ts +0 -392
- package/src/merchants/homegrownCannabis/homegrownCannabis.ts +0 -474
- package/src/merchants/init-merchant.sh +0 -53
- package/src/merchants/jackArcher/jackArcher.ts +0 -989
- package/src/merchants/jordanCraig/jordanCraig.ts +0 -1927
- package/src/merchants/kindredBravely/kindredBravely.ts +0 -538
- package/src/merchants/kutFromTheKloth/kutFromTheKloth.ts +0 -421
- package/src/merchants/larryAndSerges/larryAndSerges.ts +0 -318
- package/src/merchants/leapsAndRebounds/leapsAndRebounds.ts +0 -424
- package/src/merchants/longevityrx/longevityrx.ts +0 -374
- package/src/merchants/lookOptic/lookOptic.ts +0 -323
- package/src/merchants/mantraBrand/mantraBrand.ts +0 -844
- package/src/merchants/medterra/medterra.ts +0 -673
- package/src/merchants/modells/modells.ts +0 -543
- package/src/merchants/pressedFloral/pressedFloral.ts +0 -728
- package/src/merchants/skinPerfection/skinPerfection.ts +0 -385
- package/src/merchants/snapSupplements/snapSupplements.ts +0 -328
- package/src/merchants/spanx/spanx.ts +0 -810
- package/src/merchants/spanx/spanxStaging.ts +0 -936
- package/src/merchants/supergoop/supergoop.ts +0 -375
- package/src/merchants/uniqueVintage/uniqueVintage.ts +0 -1314
- package/src/merchants/venaCbd/venaCbd.ts +0 -407
- package/src/merchants/westonJonBoucher/westonJonBoucher.ts +0 -473
- package/src/merchants/wineEnthusiast/wineEnthusiast.ts +0 -990
- package/src/merchants/wolfMattress/wolfMattress.ts +0 -411
- package/src/merchants/wolfTactical/wolfTactical.ts +0 -383
- /package/dist/{atomStore-KSoFS3Jj.cjs → AmplitudeOperations-CgIVPUlr.cjs} +0 -0
- /package/dist/{atomStore-CZnUUsrr.js → AmplitudeOperations-YpyaR7Mp.js} +0 -0
- /package/dist/{locators-fBXS_pxP.js → atomStore-C2OI76yN.js} +0 -0
- /package/dist/{locators-0YYZu9n4.cjs → atomStore-DWmT1six.cjs} +0 -0
- /package/dist/{utilityTypes-8sETsYPk.js → types-DQoXDiso.js} +0 -0
- /package/dist/{utilityTypes-COShxVir.cjs → types-o3zWarRp.cjs} +0 -0
- /package/dist/{variantInfo-orXoPBCU.cjs → types.cjs} +0 -0
- /package/dist/{variantInfo-DbVxA1yE.js → types.js} +0 -0
- /package/src/contexts/{featureFlagServiceContext.tsx → featureFlagServiceContext/featureFlagServiceContext.tsx} +0 -0
- /package/src/contexts/{graphqlContext.tsx → graphqlContext/graphqlContext.tsx} +0 -0
- /package/src/contexts/{shopifyUrlContext.tsx → shopifyUrlContext/shopifyUrlContext.tsx} +0 -0
- /package/src/contexts/{systemSettingsContext.tsx → systemSettingsContext/systemSettingsContext.tsx} +0 -0
- /package/src/contexts/{userIdentityContext.tsx → userIdentityContext/userIdentityContext.tsx} +0 -0
- /package/src/hooks/{useBlockBackButton.ts → BlockBackButton/useBlockBackButton.ts} +0 -0
- /package/src/hooks/{useCustomerSupportHandoff.ts → CustomerSupportHandoff/useCustomerSupportHandoff.ts} +0 -0
- /package/src/hooks/{useDebounce.ts → Debounce/useDebounce.ts} +0 -0
- /package/src/hooks/{useElementObserver.ts → ElementObserver/useElementObserver.ts} +0 -0
- /package/src/hooks/{useGrabAndScroll.ts → GrabAndScroll/useGrabAndScroll.ts} +0 -0
- /package/src/hooks/{useImageResolver.ts → ImageResolver/useImageResolver.ts} +0 -0
- /package/src/hooks/{useIntersection.ts → Intersection/useIntersection.ts} +0 -0
- /package/src/hooks/{useIsSmallScreen.ts → IsSmallScreen/useIsSmallScreen.ts} +0 -0
- /package/src/hooks/{useMessageFilter.ts → MessageFilter/useMessageFilter.ts} +0 -0
- /package/src/hooks/{useMessageScrollObserver.ts → MessageScrollObserver/useMessageScrollObserver.ts} +0 -0
- /package/src/hooks/{useSearchOperations.ts → SearchOperations/useSearchOperations.ts} +0 -0
- /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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
|