@envive-ai/react-hooks 0.2.7-arthur-1 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/{TrackComponentVisibleEvent-CXhKOwKQ.js → TrackComponentVisibleEvent-qNE0dIL1.js} +2 -2
  2. package/dist/{TrackComponentVisibleEvent-CgxCqrIt.cjs → TrackComponentVisibleEvent-tDRnrJi3.cjs} +2 -2
  3. package/dist/amplitudeContext-C6LHpqP_.cjs +290 -0
  4. package/dist/amplitudeContext-rEjGf57q.js +268 -0
  5. package/dist/application/utils/index.cjs +2 -2
  6. package/dist/application/utils/index.js +2 -2
  7. package/dist/atoms/app/index.d.cts +7 -7
  8. package/dist/atoms/app/index.d.ts +1 -1
  9. package/dist/atoms/chat/index.cjs +3 -3
  10. package/dist/atoms/chat/index.d.cts +26 -26
  11. package/dist/atoms/chat/index.d.ts +1 -1
  12. package/dist/atoms/chat/index.js +3 -3
  13. package/dist/atoms/globalSearch/index.d.cts +6 -6
  14. package/dist/atoms/globalSearch/index.d.ts +5 -5
  15. package/dist/atoms/org/index.d.cts +16 -16
  16. package/dist/atoms/org/index.d.ts +16 -16
  17. package/dist/atoms/search/index.cjs +5 -5
  18. package/dist/atoms/search/index.js +5 -5
  19. package/dist/atoms/search/utils.d.ts +1 -1
  20. package/dist/{cdnContext-CtrIlAqX.js → cdnContext-B8zWuGGT.js} +1 -1
  21. package/dist/{cdnContext-CaDyQ_5p.cjs → cdnContext-DzifgoNo.cjs} +1 -1
  22. package/dist/{chat-BjhQCyW_.js → chat-DChvXHjz.js} +3 -3
  23. package/dist/{chat-BkPax29G.cjs → chat-L_N0qaqs.cjs} +3 -3
  24. package/dist/{chatSearch-C3N3iIxu.cjs → chatSearch-B5whqPLW.cjs} +3 -3
  25. package/dist/{chatSearch-BsYlFvpv.js → chatSearch-so-qeiEL.js} +3 -3
  26. package/dist/{chatState-CJ52Ag_7.cjs → chatState-D9_aA1_h.cjs} +2 -2
  27. package/dist/{chatState-CXA1vF16.js → chatState-Dl5lyuKC.js} +2 -2
  28. package/dist/{commerce-api-rgj30eEp.js → commerce-api-DEFd5HUH.js} +2 -2
  29. package/dist/{commerce-api-DA1QGGMK.cjs → commerce-api-DqVD4NH8.cjs} +2 -2
  30. package/dist/contexts/amplitudeContext/index.cjs +2 -2
  31. package/dist/contexts/amplitudeContext/index.js +2 -2
  32. package/dist/contexts/cdnContext/index.cjs +1 -1
  33. package/dist/contexts/cdnContext/index.js +1 -1
  34. package/dist/contexts/chatContext/index.cjs +7 -7
  35. package/dist/contexts/chatContext/index.d.ts +4 -4
  36. package/dist/contexts/chatContext/index.js +7 -7
  37. package/dist/contexts/systemSettingsContext/index.d.cts +2 -2
  38. package/dist/contexts/systemSettingsContext/index.d.ts +4 -4
  39. package/dist/contexts/userIdentityContext/index.cjs +4 -4
  40. package/dist/contexts/userIdentityContext/index.js +4 -4
  41. package/dist/frontendConfig-Cawh5iqv.d.ts +1 -1
  42. package/dist/frontendConfig-iZipB5FG.d.cts +1 -1
  43. package/dist/hooks/AmplitudeOperations/index.cjs +3 -3
  44. package/dist/hooks/AmplitudeOperations/index.js +3 -3
  45. package/dist/hooks/CdnOperations/index.cjs +1 -1
  46. package/dist/hooks/CdnOperations/index.js +1 -1
  47. package/dist/hooks/ChatToggle/index.cjs +3 -3
  48. package/dist/hooks/ChatToggle/index.js +3 -3
  49. package/dist/hooks/ChatToggleAnalytics/index.cjs +4 -4
  50. package/dist/hooks/ChatToggleAnalytics/index.js +4 -4
  51. package/dist/hooks/GrabAndScroll/index.d.cts +2 -2
  52. package/dist/hooks/IdentifyUser/index.cjs +4 -4
  53. package/dist/hooks/IdentifyUser/index.js +4 -4
  54. package/dist/hooks/Search/index.cjs +19 -1157
  55. package/dist/hooks/Search/index.js +17 -1156
  56. package/dist/hooks/SystemSettingsContext/index.d.ts +2 -2
  57. package/dist/hooks/TrackComponentVisibleEvent/index.cjs +2 -2
  58. package/dist/hooks/TrackComponentVisibleEvent/index.js +2 -2
  59. package/dist/hooks/UpdateAnalyticsProps/index.cjs +1 -1
  60. package/dist/hooks/UpdateAnalyticsProps/index.js +1 -1
  61. package/dist/{search-Csh2n66W.cjs → search-CneZkauD.cjs} +2 -2
  62. package/dist/{search-DkiqkogN.js → search-DbZeJYdg.js} +2 -2
  63. package/dist/{useAmplitudeOperations-zIRSqmMW.js → useAmplitudeOperations-B9HjVe6G.js} +2 -2
  64. package/dist/{useAmplitudeOperations-Bo6YNbTV.cjs → useAmplitudeOperations-BdvxAzuI.cjs} +2 -2
  65. package/dist/userIdentityContext-CPztaX6-.js +126 -0
  66. package/dist/userIdentityContext-DdySlQBz.cjs +143 -0
  67. package/dist/{utils-C1ErYSoW.js → utils-B4PvsKVY.js} +2 -2
  68. package/dist/{utils-mqfncrhI.cjs → utils-BRVP7Mnu.cjs} +2 -2
  69. package/dist/utils-CBD4g2Nc.d.cts +1 -1
  70. package/dist/utils-QKFAbPT6.d.ts +1 -1
  71. package/package.json +3 -2
  72. package/src/contexts/amplitudeContext/__tests__/amplitudeContext.test.tsx +525 -0
  73. package/src/contexts/amplitudeContext/amplitudeContext.tsx +6 -2
  74. package/src/contexts/userIdentityContext/__tests__/userIdentityContext.test.tsx +0 -162
  75. package/src/contexts/userIdentityContext/userIdentityContext.tsx +13 -4
  76. package/dist/amplitudeContext-C8tT74Mi.cjs +0 -286
  77. package/dist/amplitudeContext-DCk6Va-j.js +0 -264
  78. package/dist/userIdentityContext-BqbNu7xu.cjs +0 -132
  79. package/dist/userIdentityContext-BxFH9FNQ.js +0 -115
  80. /package/dist/{AmplitudeOperations-ChZWcSsc.js → AmplitudeOperations-C-ieCm9m.js} +0 -0
  81. /package/dist/{AmplitudeOperations-JggIc1zD.cjs → AmplitudeOperations-p7APchq9.cjs} +0 -0
  82. /package/dist/{amplitudeContext-BItT9HmT.js → amplitudeContext-DbicJUzl.js} +0 -0
  83. /package/dist/{amplitudeContext-DPtyVv3Q.cjs → amplitudeContext-q3mggFSE.cjs} +0 -0
@@ -496,168 +496,6 @@ describe("UserIdentityProvider", () => {
496
496
  { timeout: 3000 }
497
497
  );
498
498
  });
499
-
500
- it("should not call identifyUser when context is not ready", async () => {
501
- const identifySpy = vi.spyOn(CommerceApiClient, "identifyUser");
502
- const logWarnSpy = vi.spyOn(Logger, "logWarn");
503
-
504
- // Mock localStorage to be unavailable
505
- const originalLocalStorage = window.localStorage;
506
- Object.defineProperty(window, "localStorage", {
507
- value: undefined,
508
- writable: true,
509
- });
510
-
511
- renderWithProviders(<IdentifyUserComponent />);
512
-
513
- await waitFor(() => {
514
- expect(screen.getByTestId("identify-button")).toBeInTheDocument();
515
- });
516
-
517
- await act(async () => {
518
- screen.getByTestId("identify-button").click();
519
- });
520
-
521
- await waitFor(() => {
522
- expect(logWarnSpy).toHaveBeenCalledWith(
523
- "[UserIdentityContext] Context not ready, skipping identifyUser",
524
- undefined
525
- );
526
- expect(identifySpy).not.toHaveBeenCalled();
527
- });
528
-
529
- // Restore localStorage
530
- Object.defineProperty(window, "localStorage", {
531
- value: originalLocalStorage,
532
- writable: true,
533
- });
534
- });
535
-
536
- it("should handle errors when identifyUser fails", async () => {
537
- const identifySpy = vi
538
- .spyOn(CommerceApiClient, "identifyUser")
539
- .mockRejectedValueOnce(new Error("API Error"));
540
- const logErrorSpy = vi.spyOn(Logger, "logError");
541
-
542
- renderWithProviders(<IdentifyUserComponent />);
543
-
544
- await waitFor(() => {
545
- expect(screen.getByTestId("identify-button")).toBeInTheDocument();
546
- });
547
-
548
- await act(async () => {
549
- screen.getByTestId("identify-button").click();
550
- });
551
-
552
- await waitFor(() => {
553
- expect(identifySpy).toHaveBeenCalled();
554
- expect(logErrorSpy).toHaveBeenCalledWith(
555
- "[spiffy-ai] Error identifying user",
556
- expect.any(Error)
557
- );
558
- });
559
- });
560
-
561
- it("should skip identifyUser when cdpUserId is not available", async () => {
562
- const identifySpy = vi.spyOn(CommerceApiClient, "identifyUser");
563
- const logWarnSpy = vi.spyOn(Logger, "logWarn");
564
-
565
- // The current implementation uses "UNKNOWN_CDP_USER_ID" as placeholder
566
- // and checks if cdpUserId is falsy, so it will skip
567
- renderWithProviders(<IdentifyUserComponent />);
568
-
569
- await waitFor(() => {
570
- expect(screen.getByTestId("identify-button")).toBeInTheDocument();
571
- });
572
-
573
- await act(async () => {
574
- screen.getByTestId("identify-button").click();
575
- });
576
-
577
- // Note: The current implementation checks `if (!cdpUserId)` but uses "UNKNOWN_CDP_USER_ID"
578
- // which is truthy, so this test may need adjustment based on actual behavior
579
- // For now, we'll verify the call was made (since "UNKNOWN_CDP_USER_ID" is truthy)
580
- await waitFor(() => {
581
- // The current code will call identifyUser because "UNKNOWN_CDP_USER_ID" is truthy
582
- // If the behavior changes, this test should be updated
583
- expect(identifySpy).toHaveBeenCalled();
584
- });
585
- });
586
- });
587
-
588
- describe("isReady state", () => {
589
- it("should be false when localStorage is not available", async () => {
590
- const originalLocalStorage = window.localStorage;
591
- Object.defineProperty(window, "localStorage", {
592
- value: undefined,
593
- writable: true,
594
- });
595
-
596
- renderWithProviders(<MockComponent />);
597
-
598
- await waitFor(() => {
599
- expect(screen.getByTestId("is-ready").textContent).toBe("false");
600
- });
601
-
602
- // Restore localStorage
603
- Object.defineProperty(window, "localStorage", {
604
- value: originalLocalStorage,
605
- writable: true,
606
- });
607
- });
608
-
609
- it("should be true when localStorage is available", async () => {
610
- renderWithProviders(<MockComponent />);
611
-
612
- await waitFor(() => {
613
- expect(screen.getByTestId("is-ready").textContent).toBe("true");
614
- });
615
- });
616
-
617
- it("should update when localStorage availability changes", async () => {
618
- renderWithProviders(<MockComponent />);
619
-
620
- await waitFor(() => {
621
- expect(screen.getByTestId("is-ready").textContent).toBe("true");
622
- });
623
-
624
- // Note: Testing localStorage becoming unavailable requires unmounting and remounting
625
- // the provider, which is complex. This test verifies the ready state is correct
626
- // when localStorage is available. The unavailable case is tested in the other test.
627
- });
628
- });
629
-
630
- describe("Context Value Memoization", () => {
631
- it("should maintain stable context value references", async () => {
632
- let contextValue1: UserIdentityContextType | undefined;
633
- let contextValue2: UserIdentityContextType | undefined;
634
-
635
- const Component1: React.FC = () => {
636
- const context = useUserIdentity();
637
- contextValue1 = context;
638
- return <div>Component1</div>;
639
- };
640
-
641
- const Component2: React.FC = () => {
642
- const context = useUserIdentity();
643
- contextValue2 = context;
644
- return <div>Component2</div>;
645
- };
646
-
647
- renderWithProviders(
648
- <>
649
- <Component1 />
650
- <Component2 />
651
- </>
652
- );
653
-
654
- await waitFor(() => {
655
- expect(contextValue1).toBeDefined();
656
- expect(contextValue2).toBeDefined();
657
- // Both components should receive the same context instance
658
- expect(contextValue1).toBe(contextValue2);
659
- });
660
- });
661
499
  });
662
500
  });
663
501
 
@@ -50,6 +50,8 @@ const UserIdentityContext = createContext<UserIdentityContextType | undefined>(
50
50
  export const UserIdentityProvider: React.FC<{ children: React.ReactNode }> = ({
51
51
  children,
52
52
  }) => {
53
+ const [localUserId, setLocalUserId] = useState<string | undefined>(undefined);
54
+ const setUserId = useSetAtom(userIdAtom);
53
55
  const {
54
56
  getItem,
55
57
  setItem,
@@ -180,7 +182,18 @@ export const UserIdentityProvider: React.FC<{ children: React.ReactNode }> = ({
180
182
  isReady,
181
183
  ]
182
184
  );
185
+ useEffect(() => {
186
+ if (isReady && !localUserId) {
187
+ const newUserId = getUserIdOrDefault();
188
+ console.log("useUserIdentity useEffect - setting localUserId", newUserId);
189
+ setLocalUserId(newUserId);
190
+ setUserId(newUserId);
191
+ }
192
+ }, [isReady, localUserId, setUserId]);
183
193
 
194
+ if (!localUserId) {
195
+ return null;
196
+ }
184
197
  return (
185
198
  <UserIdentityContext.Provider value={value}>
186
199
  {children}
@@ -190,10 +203,6 @@ export const UserIdentityProvider: React.FC<{ children: React.ReactNode }> = ({
190
203
 
191
204
  export const useUserIdentity = () => {
192
205
  const context = useContext(UserIdentityContext);
193
- const setUserId = useSetAtom(userIdAtom);
194
- useEffect(() => {
195
- setUserId(context?.getUserIdOrDefault() ?? "");
196
- }, [context, setUserId]);
197
206
  if (!context) {
198
207
  throw new Error(
199
208
  "useUserIdentity must be used within a UserIdentityProvider"
@@ -1,286 +0,0 @@
1
- const require_chunk = require('./chunk-CUT6urMc.cjs');
2
- const require_events = require('./events-DYY4l817.cjs');
3
- const require_models = require('./models-DqdLOi2I.cjs');
4
- const require_featureGates = require('./featureGates-qU_ulhpC.cjs');
5
- const require_logger = require('./logger-TBIl4uIH.cjs');
6
- const require_localStorageContext = require('./localStorageContext-NRP-CdmF.cjs');
7
- const require_enviveConfig = require('./enviveConfig-Dv9-esGV.cjs');
8
- const require_orgAnalyticsConfig = require('./orgAnalyticsConfig-Bm23fw4s.cjs');
9
- const require_app = require('./app-BbPSHefQ.cjs');
10
- const require_enviveConfigContext = require('./enviveConfigContext-D2OELZDR.cjs');
11
- const require_featureFlagServiceContext = require('./featureFlagServiceContext-CJyYItqu.cjs');
12
- let react = require("react");
13
- react = require_chunk.__toESM(react);
14
- let jotai = require("jotai");
15
- jotai = require_chunk.__toESM(jotai);
16
- let __amplitude_analytics_browser = require("@amplitude/analytics-browser");
17
- __amplitude_analytics_browser = require_chunk.__toESM(__amplitude_analytics_browser);
18
- let react_jsx_runtime = require("react/jsx-runtime");
19
- react_jsx_runtime = require_chunk.__toESM(react_jsx_runtime);
20
-
21
- //#region src/contexts/amplitudeContext/amplitudeContext.tsx
22
- let SpiffyMetricsEventName = /* @__PURE__ */ function(SpiffyMetricsEventName$1) {
23
- SpiffyMetricsEventName$1["BundleLoaded"] = "Bundle Loaded";
24
- SpiffyMetricsEventName$1["ChatLiveAgentBtnClick"] = "Chat Live Agent Btn Click";
25
- SpiffyMetricsEventName$1["ChatFloatingButtonVisible"] = "Chat Floating Button Visible";
26
- SpiffyMetricsEventName$1["ChatComponentVisible"] = "Chat Component Visible";
27
- SpiffyMetricsEventName$1["ChatComponentExpanded"] = "Chat Component Expanded";
28
- SpiffyMetricsEventName$1["ChatComponentCollapsed"] = "Chat Component Collapsed";
29
- SpiffyMetricsEventName$1["ChatUserMessageInput"] = "Chat User Message Input";
30
- SpiffyMetricsEventName$1["ChatSuggestionClicked"] = "Chat Suggestion Clicked";
31
- SpiffyMetricsEventName$1["ChatAssistantResponse"] = "Chat Assistant Response";
32
- SpiffyMetricsEventName$1["ProductCardClicked"] = "Product Card Clicked";
33
- SpiffyMetricsEventName$1["ProductReviewCardClicked"] = "Product Review Card Clicked";
34
- SpiffyMetricsEventName$1["AddToCartClicked"] = "Add to Cart Clicked";
35
- SpiffyMetricsEventName$1["PromptCardClicked"] = "Prompt Card Clicked";
36
- SpiffyMetricsEventName$1["SupportedEvent"] = "Supported Event";
37
- SpiffyMetricsEventName$1["SearchBackToResponseClicked"] = "Search Back to Response Clicked";
38
- SpiffyMetricsEventName$1["PerformanceMetrics"] = "Performance Metrics";
39
- SpiffyMetricsEventName$1["SearchBarClicked"] = "Search Bar Clicked";
40
- SpiffyMetricsEventName$1["OrderLookupStarted"] = "Order Lookup Started";
41
- SpiffyMetricsEventName$1["OrderLookupFormSubmitted"] = "Order Lookup Form Submitted";
42
- SpiffyMetricsEventName$1["SearchComponentVisible"] = "Search Component Visible";
43
- SpiffyMetricsEventName$1["SearchZeroStateSuggestionClicked"] = "Search Zero State Suggestion Clicked";
44
- SpiffyMetricsEventName$1["SearchInputStarted"] = "Search Input Started";
45
- SpiffyMetricsEventName$1["SearchQuerySubmitted"] = "Search Query Submitted";
46
- SpiffyMetricsEventName$1["SearchResultsViewed"] = "Search Results Viewed";
47
- SpiffyMetricsEventName$1["SearchTimeToFirstClick"] = "Search Time to First Click";
48
- SpiffyMetricsEventName$1["SearchZeroResultsRate"] = "Search Zero Results Rate";
49
- SpiffyMetricsEventName$1["SearchFilterClicked"] = "Search Filter Clicked";
50
- SpiffyMetricsEventName$1["SearchSortClicked"] = "Search Sort Clicked";
51
- return SpiffyMetricsEventName$1;
52
- }({});
53
- const AmplitudeContext = (0, react.createContext)(null);
54
- const AmplitudeProvider = ({ children }) => {
55
- const userId = (0, jotai.useAtomValue)(require_app.userIdAtom);
56
- const amplitudeApiKey = (0, jotai.useAtomValue)(require_enviveConfig.amplitudeApiKeyAtom);
57
- const dataResidency = (0, jotai.useAtomValue)(require_enviveConfig.dataResidencyAtom);
58
- const orgGaConfig = (0, jotai.useAtomValue)(require_orgAnalyticsConfig.orgAnalyticsGoogleAnalyticsConfigAtom);
59
- const env = (0, jotai.useAtomValue)(require_enviveConfig.envAtom);
60
- const contextSource = (0, jotai.useAtomValue)(require_enviveConfig.contextSourceAtom);
61
- (0, jotai.useAtomValue)(require_enviveConfig.identifyingPrefixAtom);
62
- const { getItem } = require_localStorageContext.useLocalStorage();
63
- const { publicKey, featureOverrides, variantUrlOverride, variantInfoOverride, show, orgShortName, featureGates } = require_enviveConfigContext.useEnviveConfig();
64
- const { featureFlagService } = require_featureFlagServiceContext.useFeatureFlagService();
65
- const [amplitudeClient, setAmplitudeClient] = react.default.useState(void 0);
66
- const [internalEventTrackingEnrichment, setInternalEventTrackingEnrichment] = react.default.useState(void 0);
67
- const [supplementalDefaultProps, setSupplementalDefaultProps] = react.default.useState({});
68
- const isReady = Boolean(userId && featureFlagService && amplitudeApiKey && userId);
69
- const getDefaultTrackingProps = (0, react.useCallback)(() => {
70
- const gatesProps = featureGates ? featureGates.reduce((acc, curr) => {
71
- if (curr.name && curr.value != null) return {
72
- ...acc,
73
- [`feature_gate.${curr.name}`]: curr.value
74
- };
75
- return acc;
76
- }, {}) : {};
77
- const experimentProps = {};
78
- return {
79
- ...gatesProps,
80
- ...experimentProps,
81
- ...supplementalDefaultProps,
82
- app_id: "commerce-chat-react-component",
83
- chat_id: getItem(require_localStorageContext.LocalStorageKeys.ChatId),
84
- env: env || "unknown",
85
- app_source: contextSource,
86
- "org.short_name": orgShortName,
87
- "user.id": userId,
88
- "cdp.user_id": null,
89
- "cdp.provider": null,
90
- "event.source": "web-browser",
91
- "event.type": "user-activity",
92
- "event.id": null,
93
- "event.channel": "web",
94
- "event.timestamp": null
95
- };
96
- }, [
97
- featureGates,
98
- supplementalDefaultProps,
99
- env,
100
- contextSource,
101
- orgShortName,
102
- userId
103
- ]);
104
- const eventPropsToPrefixedEventProps = (0, react.useCallback)((eventName, eventProps) => {
105
- const prefix = eventName.toLowerCase().replace(/\s+/g, "_");
106
- return Object.entries(eventProps).reduce((acc, [key, value$1]) => {
107
- acc[`${prefix}.${key}`] = value$1;
108
- return acc;
109
- }, {});
110
- }, []);
111
- const amplitudeSessionReplayInit = (0, react.useCallback)(() => {
112
- const isEnabled = Boolean(orgShortName === require_models.OrgShortName.UniqueVintage && featureFlagService?.isClientSessionEnabled() && featureFlagService?.isFeatureGateEnabled(require_featureGates.FeatureGates.IsNewFeatureEnabled));
113
- const sampleRate = 1;
114
- try {
115
- require_logger.logger_default.logDebug(`[spiffy-ai] amplitude session-replay initializing isEnabled=${isEnabled} sampleRate=${sampleRate}`);
116
- if (!isEnabled) return isEnabled;
117
- return isEnabled;
118
- } catch (e) {
119
- require_logger.logger_default.logError("[spiffy-ai] Error initializing amplitude session-replay", e);
120
- return false;
121
- }
122
- }, [orgShortName, featureFlagService]);
123
- const getEventTrackingEnrichment = (0, react.useCallback)(() => {
124
- if (internalEventTrackingEnrichment !== void 0) return internalEventTrackingEnrichment;
125
- const enrichment = {
126
- name: "page-view-tracking-enrichment",
127
- type: "enrichment",
128
- setup: async () => void 0,
129
- execute: async (event) => {
130
- let enrichedEvent;
131
- if (["[Amplitude] Page Viewed", `[Spiffy] ${SpiffyMetricsEventName.BundleLoaded}`].includes(event.event_type)) {
132
- const globalProperties = {};
133
- if (publicKey) globalProperties["globalProperties.publicKey"] = publicKey;
134
- if (featureOverrides) Object.entries(featureOverrides).forEach(([key, value$1]) => {
135
- globalProperties[`globalProperties.featureOverrides.${key}`] = String(value$1);
136
- });
137
- if (variantUrlOverride) globalProperties["globalProperties.variantUrlOverride"] = variantUrlOverride;
138
- if (variantInfoOverride) globalProperties["globalProperties.variantInfoOverride"] = JSON.stringify(variantInfoOverride);
139
- if (show != null) globalProperties["globalProperties.show"] = String(show);
140
- const enabledFeatures = featureFlagService.getFeatureFlags();
141
- const enabledFeaturesProperties = Object.entries(enabledFeatures).reduce((acc, [key, value$1]) => ({
142
- ...acc,
143
- [`enabledFeatures.${key}`]: `${value$1}`
144
- }), {});
145
- const timingProperties = { "timing.enriched_at_ms": window.performance?.now() };
146
- enrichedEvent = {
147
- ...event,
148
- event_properties: {
149
- ...event.event_properties,
150
- ...getDefaultTrackingProps(),
151
- ...globalProperties,
152
- ...enabledFeaturesProperties,
153
- ...timingProperties
154
- }
155
- };
156
- } else enrichedEvent = event;
157
- require_events.EventsDispatcher.dispatch(require_events.SpiffyEvent.AMPLITUDE_EVENT, enrichedEvent);
158
- return enrichedEvent;
159
- }
160
- };
161
- setInternalEventTrackingEnrichment(enrichment);
162
- return enrichment;
163
- }, [
164
- internalEventTrackingEnrichment,
165
- getDefaultTrackingProps,
166
- featureFlagService,
167
- publicKey,
168
- featureOverrides,
169
- variantUrlOverride,
170
- variantInfoOverride,
171
- show
172
- ]);
173
- (0, react.useEffect)(() => {
174
- if (isReady && !amplitudeClient) {
175
- const currentAmplitudeInstance = (0, __amplitude_analytics_browser.createInstance)();
176
- const isSessionsEnabled = amplitudeSessionReplayInit();
177
- currentAmplitudeInstance.add(getEventTrackingEnrichment());
178
- currentAmplitudeInstance.init(amplitudeApiKey, userId, {
179
- serverZone: dataResidency,
180
- trackingOptions: { ipAddress: true },
181
- autocapture: {
182
- attribution: true,
183
- pageViews: { trackHistoryChanges: "pathOnly" },
184
- sessions: isSessionsEnabled,
185
- formInteractions: false,
186
- fileDownloads: false
187
- }
188
- });
189
- setAmplitudeClient(currentAmplitudeInstance);
190
- }
191
- }, [
192
- isReady,
193
- amplitudeClient,
194
- amplitudeApiKey,
195
- userId,
196
- dataResidency,
197
- amplitudeSessionReplayInit,
198
- getEventTrackingEnrichment
199
- ]);
200
- const trackEvent = (0, react.useCallback)(async ({ eventName, eventProps, eventGroups, alsoSendToGoogleAnalytics = false }) => {
201
- require_logger.logger_default.logDebug("Submitting event", eventName);
202
- try {
203
- const decoratedEventName = `[Spiffy] ${eventName}`;
204
- if (!amplitudeClient) {
205
- require_logger.logger_default.logWarn("amplitude client undefined", void 0, { event_name: decoratedEventName });
206
- return;
207
- }
208
- const eventData = JSON.stringify({
209
- eventName,
210
- eventProps,
211
- created_at: (/* @__PURE__ */ new Date()).toISOString()
212
- });
213
- const data = new TextEncoder().encode(eventData);
214
- const hashBuffer = await crypto.subtle.digest("SHA-256", data);
215
- const currentInsertId = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
216
- require_logger.logger_default.logDebug(`amplitude tracking ${decoratedEventName}`, null, {
217
- event_name: decoratedEventName,
218
- props: eventProps
219
- });
220
- amplitudeClient.track(decoratedEventName, {
221
- ...getDefaultTrackingProps(),
222
- ...eventProps,
223
- ...eventProps ? eventPropsToPrefixedEventProps(eventName, eventProps) : {}
224
- }, {
225
- ...eventGroups,
226
- insert_id: currentInsertId
227
- });
228
- if (alsoSendToGoogleAnalytics && orgGaConfig) {
229
- require_logger.logger_default.logDebug("[spiffy-ai] GA tracking", decoratedEventName);
230
- if (window.dataLayer) window.dataLayer.push({
231
- event: decoratedEventName,
232
- eventProps
233
- });
234
- }
235
- } catch (err) {
236
- require_logger.logger_default.logError("[spiffy-ai] Error tracking event", err, {
237
- eventName,
238
- eventProps
239
- });
240
- }
241
- }, [
242
- amplitudeClient,
243
- getDefaultTrackingProps,
244
- eventPropsToPrefixedEventProps,
245
- orgGaConfig
246
- ]);
247
- const value = (0, react.useMemo)(() => ({
248
- trackEvent,
249
- isReady,
250
- setSupplementalDefaultProps: (props) => setSupplementalDefaultProps(props)
251
- }), [
252
- trackEvent,
253
- isReady,
254
- setSupplementalDefaultProps
255
- ]);
256
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AmplitudeContext.Provider, {
257
- value,
258
- children
259
- });
260
- };
261
- const useAmplitude = () => {
262
- const context = (0, react.useContext)(AmplitudeContext);
263
- if (!context) throw new Error("useAmplitude must be used within AmplitudeProvider");
264
- return context;
265
- };
266
-
267
- //#endregion
268
- Object.defineProperty(exports, 'AmplitudeProvider', {
269
- enumerable: true,
270
- get: function () {
271
- return AmplitudeProvider;
272
- }
273
- });
274
- Object.defineProperty(exports, 'SpiffyMetricsEventName', {
275
- enumerable: true,
276
- get: function () {
277
- return SpiffyMetricsEventName;
278
- }
279
- });
280
- Object.defineProperty(exports, 'useAmplitude', {
281
- enumerable: true,
282
- get: function () {
283
- return useAmplitude;
284
- }
285
- });
286
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW1wbGl0dWRlQ29udGV4dC1DOHRUNzRNaS5janMiLCJuYW1lcyI6WyJBbXBsaXR1ZGVQcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+IiwidXNlcklkQXRvbSIsImFtcGxpdHVkZUFwaUtleUF0b20iLCJkYXRhUmVzaWRlbmN5QXRvbSIsIm9yZ0FuYWx5dGljc0dvb2dsZUFuYWx5dGljc0NvbmZpZ0F0b20iLCJlbnZBdG9tIiwiY29udGV4dFNvdXJjZUF0b20iLCJpZGVudGlmeWluZ1ByZWZpeEF0b20iLCJ1c2VMb2NhbFN0b3JhZ2UiLCJ1c2VFbnZpdmVDb25maWciLCJ1c2VGZWF0dXJlRmxhZ1NlcnZpY2UiLCJSZWFjdCIsIkxvY2FsU3RvcmFnZUtleXMiLCJ2YWx1ZSIsIk9yZ1Nob3J0TmFtZSIsIkZlYXR1cmVHYXRlcyIsImVucmljaG1lbnQ6IEVucmljaG1lbnRQbHVnaW4iLCJlbnJpY2hlZEV2ZW50OiBFdmVudCIsImdsb2JhbFByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4iLCJTcGlmZnlFdmVudCIsImN1cnJlbnRBbXBsaXR1ZGVJbnN0YW5jZTogQnJvd3NlckNsaWVudCJdLCJzb3VyY2VzIjpbIi4uL3NyYy9jb250ZXh0cy9hbXBsaXR1ZGVDb250ZXh0L2FtcGxpdHVkZUNvbnRleHQudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCwge1xuICBjcmVhdGVDb250ZXh0LFxuICB1c2VDb250ZXh0LFxuICB1c2VDYWxsYmFjayxcbiAgdXNlTWVtbyxcbiAgdXNlRWZmZWN0LFxufSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZUF0b21WYWx1ZSB9IGZyb20gXCJqb3RhaVwiO1xuaW1wb3J0IHsgY3JlYXRlSW5zdGFuY2UgfSBmcm9tIFwiQGFtcGxpdHVkZS9hbmFseXRpY3MtYnJvd3NlclwiO1xuaW1wb3J0IHsgRmVhdHVyZUdhdGVzIH0gZnJvbSBcInNyYy9hcHBsaWNhdGlvbi9tb2RlbHMvZmVhdHVyZUdhdGVzXCI7XG5pbXBvcnQgeyBPcmdTaG9ydE5hbWUgfSBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL21vZGVsc1wiO1xuaW1wb3J0IHsgRXZlbnRzRGlzcGF0Y2hlciwgU3BpZmZ5RXZlbnQgfSBmcm9tIFwic3JjL2V2ZW50c1wiO1xuaW1wb3J0IHtcbiAgYW1wbGl0dWRlQXBpS2V5QXRvbSxcbiAgY29udGV4dFNvdXJjZUF0b20sXG4gIGRhdGFSZXNpZGVuY3lBdG9tLFxuICBpZGVudGlmeWluZ1ByZWZpeEF0b20sXG59IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuaW1wb3J0IHtcbiAgTG9jYWxTdG9yYWdlS2V5cyxcbiAgdXNlTG9jYWxTdG9yYWdlLFxufSBmcm9tIFwic3JjL2NvbnRleHRzL2xvY2FsU3RvcmFnZUNvbnRleHRcIjtcbmltcG9ydCB7IG9yZ0FuYWx5dGljc0dvb2dsZUFuYWx5dGljc0NvbmZpZ0F0b20gfSBmcm9tIFwic3JjL2F0b21zL29yZy9vcmdBbmFseXRpY3NDb25maWdcIjtcbmltcG9ydCB7IHVzZXJJZEF0b20gfSBmcm9tIFwic3JjL2F0b21zL2FwcFwiO1xuaW1wb3J0IHsgZW52QXRvbSB9IGZyb20gXCJzcmMvYXRvbXMvZW52aXZlL2Vudml2ZUNvbmZpZ1wiO1xuaW1wb3J0IExvZ2dlciBmcm9tIFwic3JjL2FwcGxpY2F0aW9uL2xvZ2dpbmcvbG9nZ2VyXCI7XG5pbXBvcnQgdHlwZSB7XG4gIEJyb3dzZXJDbGllbnQsXG4gIEVucmljaG1lbnRQbHVnaW4sXG4gIEV2ZW50LFxuICBTZXJ2ZXJab25lVHlwZSxcbn0gZnJvbSBcIkBhbXBsaXR1ZGUvYW5hbHl0aWNzLXR5cGVzXCI7XG5pbXBvcnQgeyB1c2VFbnZpdmVDb25maWcgfSBmcm9tIFwic3JjL2NvbnRleHRzL2Vudml2ZUNvbmZpZ0NvbnRleHQvZW52aXZlQ29uZmlnQ29udGV4dFwiO1xuaW1wb3J0IHtcbiAgdXNlRmVhdHVyZUZsYWdTZXJ2aWNlLFxufSBmcm9tIFwic3JjL2NvbnRleHRzL2ZlYXR1cmVGbGFnU2VydmljZUNvbnRleHQvZmVhdHVyZUZsYWdTZXJ2aWNlQ29udGV4dFwiO1xuaW1wb3J0IHsgdXNlVXNlcklkZW50aXR5IH0gZnJvbSBcInNyYy9jb250ZXh0cy91c2VySWRlbnRpdHlDb250ZXh0L3VzZXJJZGVudGl0eUNvbnRleHRcIjtcblxuZXhwb3J0IGVudW0gU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSB7XG4gIEJ1bmRsZUxvYWRlZCA9IFwiQnVuZGxlIExvYWRlZFwiLFxuICBDaGF0TGl2ZUFnZW50QnRuQ2xpY2sgPSBcIkNoYXQgTGl2ZSBBZ2VudCBCdG4gQ2xpY2tcIixcbiAgQ2hhdEZsb2F0aW5nQnV0dG9uVmlzaWJsZSA9IFwiQ2hhdCBGbG9hdGluZyBCdXR0b24gVmlzaWJsZVwiLFxuICBDaGF0Q29tcG9uZW50VmlzaWJsZSA9IFwiQ2hhdCBDb21wb25lbnQgVmlzaWJsZVwiLFxuICBDaGF0Q29tcG9uZW50RXhwYW5kZWQgPSBcIkNoYXQgQ29tcG9uZW50IEV4cGFuZGVkXCIsXG4gIENoYXRDb21wb25lbnRDb2xsYXBzZWQgPSBcIkNoYXQgQ29tcG9uZW50IENvbGxhcHNlZFwiLFxuICBDaGF0VXNlck1lc3NhZ2VJbnB1dCA9IFwiQ2hhdCBVc2VyIE1lc3NhZ2UgSW5wdXRcIixcbiAgQ2hhdFN1Z2dlc3Rpb25DbGlja2VkID0gXCJDaGF0IFN1Z2dlc3Rpb24gQ2xpY2tlZFwiLFxuICBDaGF0QXNzaXN0YW50UmVzcG9uc2UgPSBcIkNoYXQgQXNzaXN0YW50IFJlc3BvbnNlXCIsXG4gIFByb2R1Y3RDYXJkQ2xpY2tlZCA9IFwiUHJvZHVjdCBDYXJkIENsaWNrZWRcIixcbiAgUHJvZHVjdFJldmlld0NhcmRDbGlja2VkID0gXCJQcm9kdWN0IFJldmlldyBDYXJkIENsaWNrZWRcIixcbiAgQWRkVG9DYXJ0Q2xpY2tlZCA9IFwiQWRkIHRvIENhcnQgQ2xpY2tlZFwiLFxuICBQcm9tcHRDYXJkQ2xpY2tlZCA9IFwiUHJvbXB0IENhcmQgQ2xpY2tlZFwiLFxuICBTdXBwb3J0ZWRFdmVudCA9IFwiU3VwcG9ydGVkIEV2ZW50XCIsXG4gIFNlYXJjaEJhY2tUb1Jlc3BvbnNlQ2xpY2tlZCA9IFwiU2VhcmNoIEJhY2sgdG8gUmVzcG9uc2UgQ2xpY2tlZFwiLFxuICBQZXJmb3JtYW5jZU1ldHJpY3MgPSBcIlBlcmZvcm1hbmNlIE1ldHJpY3NcIixcbiAgU2VhcmNoQmFyQ2xpY2tlZCA9IFwiU2VhcmNoIEJhciBDbGlja2VkXCIsXG4gIE9yZGVyTG9va3VwU3RhcnRlZCA9IFwiT3JkZXIgTG9va3VwIFN0YXJ0ZWRcIixcbiAgT3JkZXJMb29rdXBGb3JtU3VibWl0dGVkID0gXCJPcmRlciBMb29rdXAgRm9ybSBTdWJtaXR0ZWRcIixcbiAgU2VhcmNoQ29tcG9uZW50VmlzaWJsZSA9IFwiU2VhcmNoIENvbXBvbmVudCBWaXNpYmxlXCIsXG4gIFNlYXJjaFplcm9TdGF0ZVN1Z2dlc3Rpb25DbGlja2VkID0gXCJTZWFyY2ggWmVybyBTdGF0ZSBTdWdnZXN0aW9uIENsaWNrZWRcIiwgLy8gVGhpcyBpcyB0aGUgc2Nyb2xsaW5nIGxpc3Qgb2Ygc3VnZ2VzdGlvbiBidXR0b25zIGluIGdsb2JhbCBzZWFyY2hcbiAgU2VhcmNoSW5wdXRTdGFydGVkID0gXCJTZWFyY2ggSW5wdXQgU3RhcnRlZFwiLFxuICBTZWFyY2hRdWVyeVN1Ym1pdHRlZCA9IFwiU2VhcmNoIFF1ZXJ5IFN1Ym1pdHRlZFwiLFxuICAvLyBTZWFyY2hBdXRvY29tcGxldGVWaWV3ZWQgPSAnU2VhcmNoIEF1dG9jb21wbGV0ZSBWaWV3ZWQnLCAvLyBUT0RPOiBhZGQgdGhpcyB3aGVuIGF1dG9jb21wbGV0ZSBpcyBhZGRlZFxuICAvLyBTZWFyY2hBdXRvY29tcGxldGVDbGlja2VkID0gJ1NlYXJjaCBBdXRvY29tcGxldGUgQ2xpY2tlZCcsIC8vIFRPRE86IGFkZCB0aGlzIHdoZW4gYXV0b2NvbXBsZXRlIGlzIGFkZGVkXG4gIFNlYXJjaFJlc3VsdHNWaWV3ZWQgPSBcIlNlYXJjaCBSZXN1bHRzIFZpZXdlZFwiLFxuICBTZWFyY2hUaW1lVG9GaXJzdENsaWNrID0gXCJTZWFyY2ggVGltZSB0byBGaXJzdCBDbGlja1wiLFxuICBTZWFyY2haZXJvUmVzdWx0c1JhdGUgPSBcIlNlYXJjaCBaZXJvIFJlc3VsdHMgUmF0ZVwiLFxuICBTZWFyY2hGaWx0ZXJDbGlja2VkID0gXCJTZWFyY2ggRmlsdGVyIENsaWNrZWRcIixcbiAgU2VhcmNoU29ydENsaWNrZWQgPSBcIlNlYXJjaCBTb3J0IENsaWNrZWRcIixcbn1cblxuaW50ZXJmYWNlIFRyYWNrRXZlbnRQYXJhbXMge1xuICBldmVudE5hbWU6IFNwaWZmeU1ldHJpY3NFdmVudE5hbWU7XG4gIGV2ZW50UHJvcHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgZXZlbnRHcm91cHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgYWxzb1NlbmRUb0dvb2dsZUFuYWx5dGljcz86IGJvb2xlYW47XG59XG5cbmludGVyZmFjZSBBbXBsaXR1ZGVDb250ZXh0VHlwZSB7XG4gIHRyYWNrRXZlbnQ6IChwYXJhbXM6IFRyYWNrRXZlbnRQYXJhbXMpID0+IFByb21pc2U8dm9pZD47XG4gIGlzUmVhZHk6IGJvb2xlYW47XG4gIHNldFN1cHBsZW1lbnRhbERlZmF1bHRQcm9wczogKHByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4gdm9pZDtcbn1cblxuY29uc3QgQW1wbGl0dWRlQ29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8QW1wbGl0dWRlQ29udGV4dFR5cGUgfCBudWxsPihudWxsKTtcblxuZXhwb3J0IGNvbnN0IEFtcGxpdHVkZVByb3ZpZGVyOiBSZWFjdC5GQzx7IGNoaWxkcmVuOiBSZWFjdC5SZWFjdE5vZGUgfT4gPSAoe1xuICBjaGlsZHJlbixcbn0pID0+IHtcbiAgY29uc3QgdXNlcklkID0gdXNlQXRvbVZhbHVlKHVzZXJJZEF0b20pO1xuICBjb25zdCBhbXBsaXR1ZGVBcGlLZXkgPSB1c2VBdG9tVmFsdWUoYW1wbGl0dWRlQXBpS2V5QXRvbSk7XG4gIGNvbnN0IGRhdGFSZXNpZGVuY3kgPSB1c2VBdG9tVmFsdWUoZGF0YVJlc2lkZW5jeUF0b20pO1xuICBjb25zdCBvcmdHYUNvbmZpZyA9IHVzZUF0b21WYWx1ZShvcmdBbmFseXRpY3NHb29nbGVBbmFseXRpY3NDb25maWdBdG9tKTtcbiAgY29uc3QgZW52ID0gdXNlQXRvbVZhbHVlKGVudkF0b20pO1xuICBjb25zdCBjb250ZXh0U291cmNlID0gdXNlQXRvbVZhbHVlKGNvbnRleHRTb3VyY2VBdG9tKTtcbiAgY29uc3QgaWRlbnRpZnlpbmdQcmVmaXggPSB1c2VBdG9tVmFsdWUoaWRlbnRpZnlpbmdQcmVmaXhBdG9tKTtcbiAgY29uc3QgeyBnZXRJdGVtIH0gPSB1c2VMb2NhbFN0b3JhZ2UoKTtcbiAgY29uc3Qge1xuICAgIHB1YmxpY0tleSxcbiAgICBmZWF0dXJlT3ZlcnJpZGVzLFxuICAgIHZhcmlhbnRVcmxPdmVycmlkZSxcbiAgICB2YXJpYW50SW5mb092ZXJyaWRlLFxuICAgIHNob3csXG4gICAgb3JnU2hvcnROYW1lLFxuICAgIGZlYXR1cmVHYXRlcyxcbiAgfSA9IHVzZUVudml2ZUNvbmZpZygpO1xuXG4gIGNvbnN0IHsgZmVhdHVyZUZsYWdTZXJ2aWNlIH0gPSB1c2VGZWF0dXJlRmxhZ1NlcnZpY2UoKTtcblxuICBjb25zdCBbYW1wbGl0dWRlQ2xpZW50LCBzZXRBbXBsaXR1ZGVDbGllbnRdID0gUmVhY3QudXNlU3RhdGU8XG4gICAgQnJvd3NlckNsaWVudCB8IHVuZGVmaW5lZFxuICA+KHVuZGVmaW5lZCk7XG4gIGNvbnN0IFtpbnRlcm5hbEV2ZW50VHJhY2tpbmdFbnJpY2htZW50LCBzZXRJbnRlcm5hbEV2ZW50VHJhY2tpbmdFbnJpY2htZW50XSA9XG4gICAgUmVhY3QudXNlU3RhdGU8RW5yaWNobWVudFBsdWdpbiB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcbiAgY29uc3QgW3N1cHBsZW1lbnRhbERlZmF1bHRQcm9wcywgc2V0U3VwcGxlbWVudGFsRGVmYXVsdFByb3BzXSA9XG4gICAgUmVhY3QudXNlU3RhdGU8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+KHt9KTtcblxuICBjb25zdCBpc1JlYWR5ID0gQm9vbGVhbihcbiAgICB1c2VySWQgJiYgZmVhdHVyZUZsYWdTZXJ2aWNlICYmIGFtcGxpdHVkZUFwaUtleSAmJiB1c2VySWRcbiAgKTtcblxuICBjb25zdCBnZXREZWZhdWx0VHJhY2tpbmdQcm9wcyA9IHVzZUNhbGxiYWNrKCgpOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9PiB7XG4gICAgY29uc3QgZ2F0ZXNQcm9wcyA9IGZlYXR1cmVHYXRlc1xuICAgICAgPyBmZWF0dXJlR2F0ZXMucmVkdWNlPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+PigoYWNjLCBjdXJyKSA9PiB7XG4gICAgICAgICAgaWYgKGN1cnIubmFtZSAmJiBjdXJyLnZhbHVlICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB7IC4uLmFjYywgW2BmZWF0dXJlX2dhdGUuJHtjdXJyLm5hbWV9YF06IGN1cnIudmFsdWUgfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgICAgfSwge30pXG4gICAgICA6IHt9O1xuICAgIGNvbnN0IGV4cGVyaW1lbnRQcm9wcyA9IHt9OyAvLyBObyBkaXJlY3QgZXF1aXZhbGVudCBmb3IgZXhwZXJpbWVudHMgaW4gRW52aXZlQ29uZmlnIHlldFxuXG4gICAgY29uc3Qgb3JnTGV2ZWxBbXBsaXR1ZGVUcmFja2luZ1Byb3BzID0ge1xuICAgICAgLi4uZ2F0ZXNQcm9wcyxcbiAgICAgIC4uLmV4cGVyaW1lbnRQcm9wcyxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLm9yZ0xldmVsQW1wbGl0dWRlVHJhY2tpbmdQcm9wcyxcbiAgICAgIC4uLnN1cHBsZW1lbnRhbERlZmF1bHRQcm9wcyxcbiAgICAgIC8vIFRPRE86IG9yZ19pZCBpcyBub3QgZGlyZWN0bHkgYXZhaWxhYmxlIGluIEVudml2ZUNvbmZpZy4gTmVlZCB0byBmaW5kIGEgbmV3IHNvdXJjZSBvciBkZXJpdmUgaXQuXG4gICAgICAvLyBvcmdfaWQ6IG9yZ0NvbmZpZz8ub3JnPy5vcmc/LmlkLFxuICAgICAgYXBwX2lkOiBcImNvbW1lcmNlLWNoYXQtcmVhY3QtY29tcG9uZW50XCIsXG4gICAgICBjaGF0X2lkOiBnZXRJdGVtKExvY2FsU3RvcmFnZUtleXMuQ2hhdElkKSxcbiAgICAgIGVudjogZW52IHx8IFwidW5rbm93blwiLFxuICAgICAgYXBwX3NvdXJjZTogY29udGV4dFNvdXJjZSxcbiAgICAgIFwib3JnLnNob3J0X25hbWVcIjogb3JnU2hvcnROYW1lLFxuICAgICAgXCJ1c2VyLmlkXCI6IHVzZXJJZCxcbiAgICAgIFwiY2RwLnVzZXJfaWRcIjogbnVsbCxcbiAgICAgIFwiY2RwLnByb3ZpZGVyXCI6IG51bGwsXG4gICAgICBcImV2ZW50LnNvdXJjZVwiOiBcIndlYi1icm93c2VyXCIsXG4gICAgICBcImV2ZW50LnR5cGVcIjogXCJ1c2VyLWFjdGl2aXR5XCIsXG4gICAgICBcImV2ZW50LmlkXCI6IG51bGwsXG4gICAgICBcImV2ZW50LmNoYW5uZWxcIjogXCJ3ZWJcIixcbiAgICAgIFwiZXZlbnQudGltZXN0YW1wXCI6IG51bGwsXG4gICAgfTtcbiAgfSwgW1xuICAgIGZlYXR1cmVHYXRlcyxcbiAgICBzdXBwbGVtZW50YWxEZWZhdWx0UHJvcHMsXG4gICAgZW52LFxuICAgIGNvbnRleHRTb3VyY2UsXG4gICAgb3JnU2hvcnROYW1lLFxuICAgIHVzZXJJZCxcbiAgXSk7XG5cbiAgY29uc3QgZXZlbnRQcm9wc1RvUHJlZml4ZWRFdmVudFByb3BzID0gdXNlQ2FsbGJhY2soXG4gICAgKFxuICAgICAgZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLFxuICAgICAgZXZlbnRQcm9wczogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgICApOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9PiB7XG4gICAgICBjb25zdCBwcmVmaXggPSBldmVudE5hbWUudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9cXHMrL2csIFwiX1wiKTtcbiAgICAgIHJldHVybiBPYmplY3QuZW50cmllcyhldmVudFByb3BzKS5yZWR1Y2UoKGFjYywgW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICAgIGFjY1tgJHtwcmVmaXh9LiR7a2V5fWBdID0gdmFsdWU7XG4gICAgICAgIHJldHVybiBhY2M7XG4gICAgICB9LCB7fSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik7XG4gICAgfSxcbiAgICBbXVxuICApO1xuXG4gIGNvbnN0IGFtcGxpdHVkZVNlc3Npb25SZXBsYXlJbml0ID0gdXNlQ2FsbGJhY2soKCk6IGJvb2xlYW4gPT4ge1xuICAgIGNvbnN0IGlzRW5hYmxlZCA9IEJvb2xlYW4oXG4gICAgICBvcmdTaG9ydE5hbWUgPT09IE9yZ1Nob3J0TmFtZS5VbmlxdWVWaW50YWdlICYmXG4gICAgICAgIGZlYXR1cmVGbGFnU2VydmljZT8uaXNDbGllbnRTZXNzaW9uRW5hYmxlZCgpICYmXG4gICAgICAgIGZlYXR1cmVGbGFnU2VydmljZT8uaXNGZWF0dXJlR2F0ZUVuYWJsZWQoXG4gICAgICAgICAgRmVhdHVyZUdhdGVzLklzTmV3RmVhdHVyZUVuYWJsZWRcbiAgICAgICAgKVxuICAgICk7XG4gICAgY29uc3Qgc2FtcGxlUmF0ZSA9IDE7XG5cbiAgICB0cnkge1xuICAgICAgTG9nZ2VyLmxvZ0RlYnVnKFxuICAgICAgICBgW3NwaWZmeS1haV0gYW1wbGl0dWRlIHNlc3Npb24tcmVwbGF5IGluaXRpYWxpemluZyBpc0VuYWJsZWQ9JHtpc0VuYWJsZWR9IHNhbXBsZVJhdGU9JHtzYW1wbGVSYXRlfWBcbiAgICAgICk7XG5cbiAgICAgIGlmICghaXNFbmFibGVkKSB7XG4gICAgICAgIHJldHVybiBpc0VuYWJsZWQ7XG4gICAgICB9XG5cbiAgICAgIC8vIGFtcGxpdHVkZUluc3RhbmNlLmFkZChzZXNzaW9uUmVwbGF5UGx1Z2luKHsgc2FtcGxlUmF0ZSB9KSk7XG5cbiAgICAgIHJldHVybiBpc0VuYWJsZWQ7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgTG9nZ2VyLmxvZ0Vycm9yKFxuICAgICAgICBcIltzcGlmZnktYWldIEVycm9yIGluaXRpYWxpemluZyBhbXBsaXR1ZGUgc2Vzc2lvbi1yZXBsYXlcIixcbiAgICAgICAgZVxuICAgICAgKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH0sIFtvcmdTaG9ydE5hbWUsIGZlYXR1cmVGbGFnU2VydmljZV0pO1xuXG4gIGNvbnN0IGdldEV2ZW50VHJhY2tpbmdFbnJpY2htZW50ID0gdXNlQ2FsbGJhY2soKCk6IEVucmljaG1lbnRQbHVnaW4gPT4ge1xuICAgIGlmIChpbnRlcm5hbEV2ZW50VHJhY2tpbmdFbnJpY2htZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBpbnRlcm5hbEV2ZW50VHJhY2tpbmdFbnJpY2htZW50O1xuICAgIH1cblxuICAgIGNvbnN0IGVucmljaG1lbnQ6IEVucmljaG1lbnRQbHVnaW4gPSB7XG4gICAgICBuYW1lOiBcInBhZ2Utdmlldy10cmFja2luZy1lbnJpY2htZW50XCIsXG4gICAgICB0eXBlOiBcImVucmljaG1lbnRcIixcbiAgICAgIHNldHVwOiBhc3luYyAoKSA9PiB1bmRlZmluZWQsXG4gICAgICBleGVjdXRlOiBhc3luYyAoZXZlbnQ6IEV2ZW50KTogUHJvbWlzZTxFdmVudD4gPT4ge1xuICAgICAgICBsZXQgZW5yaWNoZWRFdmVudDogRXZlbnQ7XG5cbiAgICAgICAgY29uc3QgZXZlbnRzVG9FbnJpY2ggPSBbXG4gICAgICAgICAgXCJbQW1wbGl0dWRlXSBQYWdlIFZpZXdlZFwiLFxuICAgICAgICAgIGBbU3BpZmZ5XSAke1NwaWZmeU1ldHJpY3NFdmVudE5hbWUuQnVuZGxlTG9hZGVkfWAsXG4gICAgICAgIF07XG5cbiAgICAgICAgaWYgKGV2ZW50c1RvRW5yaWNoLmluY2x1ZGVzKGV2ZW50LmV2ZW50X3R5cGUpKSB7XG4gICAgICAgICAgY29uc3QgZ2xvYmFsUHJvcGVydGllczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gICAgICAgICAgaWYgKHB1YmxpY0tleSkge1xuICAgICAgICAgICAgZ2xvYmFsUHJvcGVydGllc1tcImdsb2JhbFByb3BlcnRpZXMucHVibGljS2V5XCJdID0gcHVibGljS2V5O1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZmVhdHVyZU92ZXJyaWRlcykge1xuICAgICAgICAgICAgT2JqZWN0LmVudHJpZXMoZmVhdHVyZU92ZXJyaWRlcykuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICAgICAgICAgIGdsb2JhbFByb3BlcnRpZXNbYGdsb2JhbFByb3BlcnRpZXMuZmVhdHVyZU92ZXJyaWRlcy4ke2tleX1gXSA9XG4gICAgICAgICAgICAgICAgU3RyaW5nKHZhbHVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAodmFyaWFudFVybE92ZXJyaWRlKSB7XG4gICAgICAgICAgICBnbG9iYWxQcm9wZXJ0aWVzW1wiZ2xvYmFsUHJvcGVydGllcy52YXJpYW50VXJsT3ZlcnJpZGVcIl0gPVxuICAgICAgICAgICAgICB2YXJpYW50VXJsT3ZlcnJpZGU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh2YXJpYW50SW5mb092ZXJyaWRlKSB7XG4gICAgICAgICAgICBnbG9iYWxQcm9wZXJ0aWVzW1wiZ2xvYmFsUHJvcGVydGllcy52YXJpYW50SW5mb092ZXJyaWRlXCJdID1cbiAgICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkodmFyaWFudEluZm9PdmVycmlkZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzaG93ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGdsb2JhbFByb3BlcnRpZXNbXCJnbG9iYWxQcm9wZXJ0aWVzLnNob3dcIl0gPSBTdHJpbmcoc2hvdyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZW5hYmxlZEZlYXR1cmVzID0gZmVhdHVyZUZsYWdTZXJ2aWNlIS5nZXRGZWF0dXJlRmxhZ3MoKTtcbiAgICAgICAgICBjb25zdCBlbmFibGVkRmVhdHVyZXNQcm9wZXJ0aWVzID0gT2JqZWN0LmVudHJpZXMoXG4gICAgICAgICAgICBlbmFibGVkRmVhdHVyZXNcbiAgICAgICAgICApLnJlZHVjZTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PihcbiAgICAgICAgICAgIChhY2MsIFtrZXksIHZhbHVlXSkgPT4gKHtcbiAgICAgICAgICAgICAgLi4uYWNjLFxuICAgICAgICAgICAgICBbYGVuYWJsZWRGZWF0dXJlcy4ke2tleX1gXTogYCR7dmFsdWV9YCxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAge31cbiAgICAgICAgICApO1xuXG4gICAgICAgICAgY29uc3QgdGltaW5nUHJvcGVydGllcyA9IHtcbiAgICAgICAgICAgIFwidGltaW5nLmVucmljaGVkX2F0X21zXCI6IHdpbmRvdy5wZXJmb3JtYW5jZT8ubm93KCksXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGVucmljaGVkRXZlbnQgPSB7XG4gICAgICAgICAgICAuLi5ldmVudCxcbiAgICAgICAgICAgIGV2ZW50X3Byb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgLi4uZXZlbnQuZXZlbnRfcHJvcGVydGllcyxcbiAgICAgICAgICAgICAgLi4uZ2V0RGVmYXVsdFRyYWNraW5nUHJvcHMoKSxcbiAgICAgICAgICAgICAgLi4uZ2xvYmFsUHJvcGVydGllcyxcbiAgICAgICAgICAgICAgLi4uZW5hYmxlZEZlYXR1cmVzUHJvcGVydGllcyxcbiAgICAgICAgICAgICAgLi4udGltaW5nUHJvcGVydGllcyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlbnJpY2hlZEV2ZW50ID0gZXZlbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBFdmVudHNEaXNwYXRjaGVyLmRpc3BhdGNoKFNwaWZmeUV2ZW50LkFNUExJVFVERV9FVkVOVCwgZW5yaWNoZWRFdmVudCk7XG5cbiAgICAgICAgcmV0dXJuIGVucmljaGVkRXZlbnQ7XG4gICAgICB9LFxuICAgIH07XG4gICAgc2V0SW50ZXJuYWxFdmVudFRyYWNraW5nRW5yaWNobWVudChlbnJpY2htZW50KTtcbiAgICByZXR1cm4gZW5yaWNobWVudDtcbiAgfSwgW1xuICAgIGludGVybmFsRXZlbnRUcmFja2luZ0VucmljaG1lbnQsXG4gICAgZ2V0RGVmYXVsdFRyYWNraW5nUHJvcHMsXG4gICAgZmVhdHVyZUZsYWdTZXJ2aWNlLFxuICAgIHB1YmxpY0tleSxcbiAgICBmZWF0dXJlT3ZlcnJpZGVzLFxuICAgIHZhcmlhbnRVcmxPdmVycmlkZSxcbiAgICB2YXJpYW50SW5mb092ZXJyaWRlLFxuICAgIHNob3csXG4gIF0pO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKGlzUmVhZHkgJiYgIWFtcGxpdHVkZUNsaWVudCkge1xuICAgICAgY29uc3QgY3VycmVudEFtcGxpdHVkZUluc3RhbmNlOiBCcm93c2VyQ2xpZW50ID0gY3JlYXRlSW5zdGFuY2UoKTtcbiAgICAgIGNvbnN0IGlzU2Vzc2lvbnNFbmFibGVkID0gYW1wbGl0dWRlU2Vzc2lvblJlcGxheUluaXQoKTtcbiAgICAgIGN1cnJlbnRBbXBsaXR1ZGVJbnN0YW5jZS5hZGQoZ2V0RXZlbnRUcmFja2luZ0VucmljaG1lbnQoKSk7XG4gICAgICBjdXJyZW50QW1wbGl0dWRlSW5zdGFuY2UuaW5pdChhbXBsaXR1ZGVBcGlLZXkhLCB1c2VySWQhLCB7XG4gICAgICAgIHNlcnZlclpvbmU6IGRhdGFSZXNpZGVuY3kgYXMgU2VydmVyWm9uZVR5cGUsXG4gICAgICAgIHRyYWNraW5nT3B0aW9uczoge1xuICAgICAgICAgIGlwQWRkcmVzczogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgICAgYXV0b2NhcHR1cmU6IHtcbiAgICAgICAgICBhdHRyaWJ1dGlvbjogdHJ1ZSxcbiAgICAgICAgICBwYWdlVmlld3M6IHtcbiAgICAgICAgICAgIHRyYWNrSGlzdG9yeUNoYW5nZXM6IFwicGF0aE9ubHlcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNlc3Npb25zOiBpc1Nlc3Npb25zRW5hYmxlZCxcbiAgICAgICAgICBmb3JtSW50ZXJhY3Rpb25zOiBmYWxzZSxcbiAgICAgICAgICBmaWxlRG93bmxvYWRzOiBmYWxzZSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgc2V0QW1wbGl0dWRlQ2xpZW50KGN1cnJlbnRBbXBsaXR1ZGVJbnN0YW5jZSk7XG4gICAgfVxuICB9LCBbXG4gICAgaXNSZWFkeSxcbiAgICBhbXBsaXR1ZGVDbGllbnQsXG4gICAgYW1wbGl0dWRlQXBpS2V5LFxuICAgIHVzZXJJZCxcbiAgICBkYXRhUmVzaWRlbmN5LFxuICAgIGFtcGxpdHVkZVNlc3Npb25SZXBsYXlJbml0LFxuICAgIGdldEV2ZW50VHJhY2tpbmdFbnJpY2htZW50LFxuICBdKTtcblxuICBjb25zdCB0cmFja0V2ZW50ID0gdXNlQ2FsbGJhY2soXG4gICAgYXN5bmMgKHtcbiAgICAgIGV2ZW50TmFtZSxcbiAgICAgIGV2ZW50UHJvcHMsXG4gICAgICBldmVudEdyb3VwcyxcbiAgICAgIGFsc29TZW5kVG9Hb29nbGVBbmFseXRpY3MgPSBmYWxzZSxcbiAgICB9OiBUcmFja0V2ZW50UGFyYW1zKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICBMb2dnZXIubG9nRGVidWcoXCJTdWJtaXR0aW5nIGV2ZW50XCIsIGV2ZW50TmFtZSk7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBkZWNvcmF0ZWRFdmVudE5hbWUgPSBgW1NwaWZmeV0gJHtldmVudE5hbWV9YDtcblxuICAgICAgICBpZiAoIWFtcGxpdHVkZUNsaWVudCkge1xuICAgICAgICAgIExvZ2dlci5sb2dXYXJuKFwiYW1wbGl0dWRlIGNsaWVudCB1bmRlZmluZWRcIiwgdW5kZWZpbmVkLCB7XG4gICAgICAgICAgICBldmVudF9uYW1lOiBkZWNvcmF0ZWRFdmVudE5hbWUsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZXZlbnREYXRhID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgIGV2ZW50TmFtZSxcbiAgICAgICAgICBldmVudFByb3BzLFxuICAgICAgICAgIGNyZWF0ZWRfYXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKTtcbiAgICAgICAgY29uc3QgZGF0YSA9IGVuY29kZXIuZW5jb2RlKGV2ZW50RGF0YSk7XG4gICAgICAgICAvLyBjYWxjdWxhdGUgYSBoYXNoIG9mIHRoZSBldmVudCBwcm9wZXJ0aWVzIHRvIHVzZSBhcyB0aGUgaW5zZXJ0X2lkIHNvIHRoYXQgZHVwbGljYXRlIGV2ZW50c1xuICAgICAgICAvLyBhcmUgYXV0b21hdGljYWxseSBkcm9wcGVkIGJ5IEFtcGxpdHVkZVxuICAgICAgICBjb25zdCBoYXNoQnVmZmVyID0gYXdhaXQgY3J5cHRvLnN1YnRsZS5kaWdlc3QoXCJTSEEtMjU2XCIsIGRhdGEpO1xuICAgICAgICBjb25zdCBoYXNoQXJyYXkgPSBBcnJheS5mcm9tKG5ldyBVaW50OEFycmF5KGhhc2hCdWZmZXIpKTtcbiAgICAgICAgY29uc3QgY3VycmVudEluc2VydElkID0gaGFzaEFycmF5XG4gICAgICAgICAgLm1hcCgoYikgPT4gYi50b1N0cmluZygxNikucGFkU3RhcnQoMiwgXCIwXCIpKVxuICAgICAgICAgIC5qb2luKFwiXCIpO1xuXG4gICAgICAgIExvZ2dlci5sb2dEZWJ1ZyhgYW1wbGl0dWRlIHRyYWNraW5nICR7ZGVjb3JhdGVkRXZlbnROYW1lfWAsIG51bGwsIHtcbiAgICAgICAgICBldmVudF9uYW1lOiBkZWNvcmF0ZWRFdmVudE5hbWUsXG4gICAgICAgICAgcHJvcHM6IGV2ZW50UHJvcHMsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGFtcGxpdHVkZUNsaWVudC50cmFjayhcbiAgICAgICAgICBkZWNvcmF0ZWRFdmVudE5hbWUsXG4gICAgICAgICAge1xuICAgICAgICAgICAgLi4uZ2V0RGVmYXVsdFRyYWNraW5nUHJvcHMoKSxcbiAgICAgICAgICAgIC4uLmV2ZW50UHJvcHMsXG4gICAgICAgICAgICAuLi4oZXZlbnRQcm9wc1xuICAgICAgICAgICAgICA/IGV2ZW50UHJvcHNUb1ByZWZpeGVkRXZlbnRQcm9wcyhldmVudE5hbWUsIGV2ZW50UHJvcHMpXG4gICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgLi4uZXZlbnRHcm91cHMsXG4gICAgICAgICAgICBpbnNlcnRfaWQ6IGN1cnJlbnRJbnNlcnRJZCxcbiAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKGFsc29TZW5kVG9Hb29nbGVBbmFseXRpY3MgJiYgb3JnR2FDb25maWcpIHtcbiAgICAgICAgICAvLyBUT0RPOiBBZGQgaW4gd2luZG93RGF0YUxheWVyU2VydmljZSBvciBjb250ZXh0IGFsdGVybmF0aXZlIGFuZCBob29rIGl0IHVwIGhlcmVcbiAgICAgICAgICBMb2dnZXIubG9nRGVidWcoXCJbc3BpZmZ5LWFpXSBHQSB0cmFja2luZ1wiLCBkZWNvcmF0ZWRFdmVudE5hbWUpO1xuICAgICAgICAgIGlmICh3aW5kb3cuZGF0YUxheWVyKSB7XG4gICAgICAgICAgICAod2luZG93LmRhdGFMYXllciBhcyBhbnlbXSkucHVzaCh7XG4gICAgICAgICAgICAgIGV2ZW50OiBkZWNvcmF0ZWRFdmVudE5hbWUsXG4gICAgICAgICAgICAgIGV2ZW50UHJvcHM6IGV2ZW50UHJvcHMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBMb2dnZXIubG9nRXJyb3IoXCJbc3BpZmZ5LWFpXSBFcnJvciB0cmFja2luZyBldmVudFwiLCBlcnIsIHtcbiAgICAgICAgICBldmVudE5hbWUsXG4gICAgICAgICAgZXZlbnRQcm9wcyxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSxcbiAgICBbXG4gICAgICBhbXBsaXR1ZGVDbGllbnQsXG4gICAgICBnZXREZWZhdWx0VHJhY2tpbmdQcm9wcyxcbiAgICAgIGV2ZW50UHJvcHNUb1ByZWZpeGVkRXZlbnRQcm9wcyxcbiAgICAgIG9yZ0dhQ29uZmlnLFxuICAgIF1cbiAgKTtcblxuICBjb25zdCB2YWx1ZSA9IHVzZU1lbW8oXG4gICAgKCkgPT4gKHtcbiAgICAgIHRyYWNrRXZlbnQsXG4gICAgICBpc1JlYWR5LFxuICAgICAgc2V0U3VwcGxlbWVudGFsRGVmYXVsdFByb3BzOiAocHJvcHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PlxuICAgICAgICBzZXRTdXBwbGVtZW50YWxEZWZhdWx0UHJvcHMocHJvcHMpLFxuICAgIH0pLFxuICAgIFt0cmFja0V2ZW50LCBpc1JlYWR5LCBzZXRTdXBwbGVtZW50YWxEZWZhdWx0UHJvcHNdXG4gICk7XG5cbiAgcmV0dXJuIChcbiAgICA8QW1wbGl0dWRlQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17dmFsdWV9PlxuICAgICAge2NoaWxkcmVufVxuICAgIDwvQW1wbGl0dWRlQ29udGV4dC5Qcm92aWRlcj5cbiAgKTtcbn07XG5cbmV4cG9ydCBjb25zdCB1c2VBbXBsaXR1ZGUgPSAoKSA9PiB7XG4gIGNvbnN0IGNvbnRleHQgPSB1c2VDb250ZXh0KEFtcGxpdHVkZUNvbnRleHQpO1xuICBpZiAoIWNvbnRleHQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJ1c2VBbXBsaXR1ZGUgbXVzdCBiZSB1c2VkIHdpdGhpbiBBbXBsaXR1ZGVQcm92aWRlclwiKTtcbiAgfVxuICByZXR1cm4gY29udGV4dDtcbn07XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXNDQSxJQUFZLDRFQUFMO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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