@envive-ai/react-hooks 0.3.56 → 0.3.58
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/application/commerce-api.cjs +11 -12
- package/dist/application/commerce-api.js +11 -12
- package/dist/application/logging/index.cjs +13 -0
- package/dist/application/logging/index.d.cts +3 -0
- package/dist/application/logging/index.d.ts +3 -0
- package/dist/application/logging/index.js +4 -0
- package/dist/application/logging/logLevel.cjs +123 -0
- package/dist/application/logging/logLevel.d.cts +47 -0
- package/dist/application/logging/logLevel.d.ts +47 -0
- package/dist/application/logging/logLevel.js +115 -0
- package/dist/application/logging/logger.cjs +6 -1
- package/dist/application/logging/logger.d.cts +13 -0
- package/dist/application/logging/logger.d.ts +13 -0
- package/dist/application/logging/logger.js +7 -1
- package/dist/atoms/app/index.d.cts +7 -7
- package/dist/atoms/app/index.d.ts +6 -6
- package/dist/atoms/app/variant.d.ts +6 -6
- package/dist/atoms/chat/chatState.d.cts +18 -18
- package/dist/atoms/chat/chatState.d.ts +19 -19
- package/dist/atoms/chat/form.d.cts +2 -2
- package/dist/atoms/chat/form.d.ts +2 -2
- package/dist/atoms/chat/index.d.ts +2 -2
- package/dist/atoms/chat/lastMessage.d.cts +2 -2
- package/dist/atoms/chat/lastMessage.d.ts +2 -2
- package/dist/atoms/chat/messageQueue.d.cts +6 -6
- package/dist/atoms/chat/messageQueue.d.ts +6 -6
- package/dist/atoms/chat/performanceMetrics.d.cts +6 -6
- package/dist/atoms/chat/performanceMetrics.d.ts +6 -6
- package/dist/atoms/chat/renderedWidgetRefs.d.cts +2 -2
- package/dist/atoms/chat/renderedWidgetRefs.d.ts +2 -2
- package/dist/atoms/chat/replies.d.cts +1 -1
- package/dist/atoms/chat/replies.d.ts +3 -3
- package/dist/atoms/chat/suggestions.d.cts +2 -2
- package/dist/atoms/chat/suggestions.d.ts +2 -2
- package/dist/atoms/envive/enviveConfig.d.ts +14 -14
- package/dist/atoms/globalSearch/globalSearch.d.cts +5 -5
- package/dist/atoms/globalSearch/globalSearch.d.ts +5 -5
- package/dist/atoms/org/customerService.d.cts +6 -6
- package/dist/atoms/org/customerService.d.ts +6 -6
- package/dist/atoms/org/graphqlConfig.d.cts +4 -4
- package/dist/atoms/org/graphqlConfig.d.ts +5 -5
- package/dist/atoms/org/newOrgConfigAtom.d.cts +2 -2
- package/dist/atoms/org/newOrgConfigAtom.d.ts +3 -3
- package/dist/atoms/org/orgAnalyticsConfig.d.cts +4 -4
- package/dist/atoms/org/orgAnalyticsConfig.d.ts +5 -5
- package/dist/atoms/search/chatSearch.d.cts +17 -17
- package/dist/atoms/search/chatSearch.d.ts +17 -17
- package/dist/atoms/search/searchAPI.d.cts +13 -13
- package/dist/atoms/search/searchAPI.d.ts +13 -13
- package/dist/atoms/search/types.d.cts +1 -1
- package/dist/atoms/search/types.d.ts +1 -1
- package/dist/atoms/widget/chatPreviewLoading.d.ts +2 -2
- package/dist/contexts/salesAgentContext/salesAgentService.cjs +2 -2
- package/dist/contexts/salesAgentContext/salesAgentService.js +2 -2
- package/dist/contexts/systemSettingsContext/systemSettingsContext.d.cts +2 -2
- package/dist/contexts/types.d.cts +1 -1
- package/dist/contexts/types.d.ts +1 -1
- package/dist/contexts/typesV3.d.cts +1 -1
- package/dist/contexts/typesV3.d.ts +1 -1
- package/dist/hooks/ChatToggle/useChatToggle.cjs +10 -8
- package/dist/hooks/ChatToggle/useChatToggle.d.cts +4 -3
- package/dist/hooks/ChatToggle/useChatToggle.d.ts +4 -3
- package/dist/hooks/ChatToggle/useChatToggle.js +11 -9
- package/dist/hooks/GrabAndScroll/useGrabAndScroll.d.cts +2 -2
- package/dist/hooks/Intersection/useIntersection.cjs +7 -5
- package/dist/hooks/Intersection/useIntersection.js +7 -5
- package/dist/hooks/Search/useSearchInput.cjs +1 -1
- package/dist/hooks/Search/useSearchInput.js +1 -1
- package/dist/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.cjs +8 -6
- package/dist/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.js +8 -6
- package/dist/hooks/WidgetInteraction/types.cjs +40 -1
- package/dist/hooks/WidgetInteraction/types.d.cts +16 -2
- package/dist/hooks/WidgetInteraction/types.d.ts +16 -2
- package/dist/hooks/WidgetInteraction/types.js +41 -2
- package/dist/hooks/utils.d.cts +1 -1
- package/dist/hooks/utils.d.ts +1 -1
- package/dist/services/amplitudeService/amplitudeService.cjs +14 -5
- package/dist/services/amplitudeService/amplitudeService.js +14 -5
- package/package.json +5 -1
- package/src/application/__tests__/commerceApiStreaming.test.ts +171 -0
- package/src/application/commerce-api.ts +21 -21
- package/src/application/logging/__tests__/logger.test.ts +159 -0
- package/src/application/logging/index.ts +12 -0
- package/src/application/logging/logLevel.ts +162 -0
- package/src/application/logging/logger.ts +13 -0
- package/src/contexts/salesAgentContext/salesAgentService.ts +1 -1
- package/src/contexts/userIdentityContext/__tests__/userIdentityContext.test.tsx +4 -5
- package/src/hooks/ChatToggle/__tests__/useChatToggle.test.ts +273 -0
- package/src/hooks/ChatToggle/useChatToggle.ts +39 -12
- package/src/hooks/Intersection/useIntersection.ts +7 -4
- package/src/hooks/TrackComponentVisibleEvent/useTrackComponentVisibleEvent.ts +8 -5
- package/src/hooks/WidgetInteraction/__tests__/chatTriggerWidget.test.ts +51 -0
- package/src/hooks/WidgetInteraction/types.ts +53 -0
- package/src/services/amplitudeService/__tests__/amplitudeService.test.ts +76 -0
- package/src/services/amplitudeService/amplitudeService.ts +37 -5
|
@@ -10,6 +10,14 @@ import { projectToGA4 } from "../ga4ProjectionService/ga4ProjectionService.js";
|
|
|
10
10
|
|
|
11
11
|
//#region src/services/amplitudeService/amplitudeService.ts
|
|
12
12
|
const logger = new logger_default("amplitudeService");
|
|
13
|
+
const UTF8_TRANSPORT_PREFIX = "__spiffy_utf8__:";
|
|
14
|
+
const containsSupplementaryUnicode = (value) => Array.from(value).some((character) => (character.codePointAt(0) ?? 0) > 65535);
|
|
15
|
+
const encodeSupplementaryUnicode = (value) => {
|
|
16
|
+
if (typeof value === "string") return containsSupplementaryUnicode(value) ? `${UTF8_TRANSPORT_PREFIX}${encodeURIComponent(value)}` : value;
|
|
17
|
+
if (Array.isArray(value)) return value.map(encodeSupplementaryUnicode);
|
|
18
|
+
if (value !== null && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, nestedValue]) => [key, encodeSupplementaryUnicode(nestedValue)]));
|
|
19
|
+
return value;
|
|
20
|
+
};
|
|
13
21
|
const EXPERIMENT_NAMESPACES = ["ml", "merchant"];
|
|
14
22
|
const buildExperimentProps = (assignments) => {
|
|
15
23
|
const byNamespace = /* @__PURE__ */ new Map();
|
|
@@ -257,9 +265,10 @@ var AmplitudeService = class AmplitudeService {
|
|
|
257
265
|
eventName,
|
|
258
266
|
eventProps
|
|
259
267
|
});
|
|
268
|
+
const amplitudeEventProps = eventName === EnviveMetricsEventName.WidgetTextResponse || eventName === EnviveMetricsEventName.WidgetTextClicked ? encodeSupplementaryUnicode(mappedEventProps) : mappedEventProps;
|
|
260
269
|
const eventData = JSON.stringify({
|
|
261
270
|
eventName,
|
|
262
|
-
eventProps:
|
|
271
|
+
eventProps: amplitudeEventProps,
|
|
263
272
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
264
273
|
});
|
|
265
274
|
const data = new TextEncoder().encode(eventData);
|
|
@@ -267,12 +276,12 @@ var AmplitudeService = class AmplitudeService {
|
|
|
267
276
|
const currentInsertId = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
268
277
|
logger.logDebug(`amplitude tracking ${decoratedEventName}`, null, {
|
|
269
278
|
event_name: decoratedEventName,
|
|
270
|
-
props:
|
|
279
|
+
props: amplitudeEventProps
|
|
271
280
|
});
|
|
272
281
|
this.amplitudeClient.track(decoratedEventName, {
|
|
273
282
|
...this.getDefaultTrackingProps(eventName),
|
|
274
|
-
...
|
|
275
|
-
...
|
|
283
|
+
...amplitudeEventProps,
|
|
284
|
+
...amplitudeEventProps ? this.eventPropsToPrefixedEventProps(eventName, amplitudeEventProps) : {}
|
|
276
285
|
}, {
|
|
277
286
|
...eventGroups,
|
|
278
287
|
insert_id: currentInsertId
|
|
@@ -303,4 +312,4 @@ var AmplitudeService = class AmplitudeService {
|
|
|
303
312
|
|
|
304
313
|
//#endregion
|
|
305
314
|
export { AmplitudeService };
|
|
306
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW1wbGl0dWRlU2VydmljZS5qcyIsIm5hbWVzIjpbIkxvZ2dlciIsIkVYUEVSSU1FTlRfTkFNRVNQQUNFUzogRXhwZXJpbWVudE5hbWVzcGFjZVtdIiwiZW5yaWNobWVudDogRW5yaWNobWVudFBsdWdpbiIsImVucmljaGVkRXZlbnQ6IEV2ZW50IiwiZ2xvYmFsUHJvcGVydGllczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiIsImN1cnJlbnRBbXBsaXR1ZGVJbnN0YW5jZTogQnJvd3NlckNsaWVudCJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZXJ2aWNlcy9hbXBsaXR1ZGVTZXJ2aWNlL2FtcGxpdHVkZVNlcnZpY2UudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRXZlbnRzRGlzcGF0Y2hlciwgU3BpZmZ5RXZlbnQgfSBmcm9tICdzcmMvZXZlbnRzJztcbmltcG9ydCB7IExvY2FsU3RvcmFnZUtleXMgfSBmcm9tICdzcmMvY29udGV4dHMvbG9jYWxTdG9yYWdlQ29udGV4dCc7XG5pbXBvcnQgTG9nZ2VyIGZyb20gJ3NyYy9hcHBsaWNhdGlvbi9sb2dnaW5nL2xvZ2dlcic7XG5pbXBvcnQgdHlwZSB7XG4gIEJyb3dzZXJDbGllbnQsXG4gIEVucmljaG1lbnRQbHVnaW4sXG4gIEV2ZW50LFxuICBTZXJ2ZXJab25lVHlwZSxcbn0gZnJvbSAnQGFtcGxpdHVkZS9hbmFseXRpY3MtdHlwZXMnO1xuaW1wb3J0IHsgRmVhdHVyZUZsYWdTZXJ2aWNlIH0gZnJvbSAnc3JjL3NlcnZpY2VzL2ZlYXR1cmVGbGFnU2VydmljZSc7XG5pbXBvcnQgeyBXaWRnZXRUeXBlVjMgfSBmcm9tICdzcmMvY29udGV4dHMvdHlwZXNWMyc7XG5pbXBvcnQgeyBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzIH0gZnJvbSAnc3JjL2FwcGxpY2F0aW9uL21vZGVscy9jaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzJztcbmltcG9ydCB7IEV4cGVyaW1lbnROYW1lc3BhY2UsIE9yZ0NvbmZpZ0V4cGVyaW1lbnRBc3NpZ25tZW50IH0gZnJvbSAnc3JjL2FwcGxpY2F0aW9uL21vZGVscyc7XG5pbXBvcnQgeyBwcm9qZWN0VG9HQTQgfSBmcm9tICcuLi9nYTRQcm9qZWN0aW9uU2VydmljZS9nYTRQcm9qZWN0aW9uU2VydmljZSc7XG5pbXBvcnQgeyBFbnZpdmVNZXRyaWNzRXZlbnROYW1lLCBTcGlmZnlNZXRyaWNzRXZlbnROYW1lIH0gZnJvbSAnLi9ldmVudE5hbWVzJztcblxuLy8gUmUtZXhwb3J0IGV2ZW50IG5hbWVzIGZvciBjb252ZW5pZW5jZVxuZXhwb3J0IHsgRW52aXZlTWV0cmljc0V2ZW50TmFtZSwgU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSB9O1xuXG5jb25zdCBsb2dnZXIgPSBuZXcgTG9nZ2VyKCdhbXBsaXR1ZGVTZXJ2aWNlJyk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhY2tFdmVudFBhcmFtcyB7XG4gIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSB8IEVudml2ZU1ldHJpY3NFdmVudE5hbWU7XG4gIGV2ZW50UHJvcHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgZXZlbnRHcm91cHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgYWxzb1NlbmRUb0dvb2dsZUFuYWx5dGljcz86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQW1wbGl0dWRlU2VydmljZUNvbmZpZyB7XG4gIHVzZXJJZDogc3RyaW5nO1xuICBhbXBsaXR1ZGVBcGlLZXk6IHN0cmluZztcbiAgZGF0YVJlc2lkZW5jeTogc3RyaW5nO1xuICBlbnY6IHN0cmluZztcbiAgY29udGV4dFNvdXJjZTogc3RyaW5nO1xuICBvcmdTaG9ydE5hbWU6IHN0cmluZztcbiAgb3JnSWQ6IHN0cmluZztcbiAgZmVhdHVyZUZsYWdTZXJ2aWNlOiBGZWF0dXJlRmxhZ1NlcnZpY2U7XG4gIHNob3c6IGJvb2xlYW47XG4gIGVudml2ZU9uOiBib29sZWFuO1xuICBlbmFibGVkRmVhdHVyZXM/OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPjtcbiAgZ2V0TG9jYWxTdG9yYWdlSXRlbTogbnVsbCB8ICgoa2V5OiBzdHJpbmcpID0+IHN0cmluZyB8IG51bGwpO1xuICAvLyBDYXB0dXJlZCBhdCBjb25zdHJ1Y3Rpb24uIERyaXZlcyBgZXhwZXJpbWVudC57bnN9LipgIGV2ZW50LXByb3BlcnR5XG4gIC8vIGVucmljaG1lbnQuIFNvdXJjZWQgZnJvbSAvdjEvb3JnL2NvbmZpZyB3aGVuIHRoZSBgdXNlX3VuaWZpZWRfY29uZmlnYFxuICAvLyBnYXRlIGlzIG9uOyBvdGhlcndpc2Ugb21pdHRlZCAocHJvcHMgZW1pdCBhcyBudWxsKS5cbiAgZXhwZXJpbWVudEFzc2lnbm1lbnRzPzogT3JnQ29uZmlnRXhwZXJpbWVudEFzc2lnbm1lbnRbXTtcbn1cblxuLy8gTmFtZXNwYWNlcyBlbWl0dGVkIG9uIGV2ZXJ5IGV2ZW50IHdpdGggY29uc3RhbnQga2V5cywgc28gdGhlIEJpZ1F1ZXJ5XG4vLyBzY2hlbWEgaXMgc3RhYmxlIHJlZ2FyZGxlc3Mgb2Ygd2hpY2ggKGlmIGFueSkgZXhwZXJpbWVudCBpcyBydW5uaW5nLlxuLy8gQ3VycmVudGx5IGBtbGAgKyBgbWVyY2hhbnRgOyBtYXRjaGVzIGBFeHBlcmltZW50TmFtZXNwYWNlYC5cbmNvbnN0IEVYUEVSSU1FTlRfTkFNRVNQQUNFUzogRXhwZXJpbWVudE5hbWVzcGFjZVtdID0gWydtbCcsICdtZXJjaGFudCddO1xuXG5jb25zdCBidWlsZEV4cGVyaW1lbnRQcm9wcyA9IChcbiAgYXNzaWdubWVudHM6IE9yZ0NvbmZpZ0V4cGVyaW1lbnRBc3NpZ25tZW50W10gfCB1bmRlZmluZWQsXG4pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9PiB7XG4gIGNvbnN0IGJ5TmFtZXNwYWNlID0gbmV3IE1hcDxFeHBlcmltZW50TmFtZXNwYWNlLCBPcmdDb25maWdFeHBlcmltZW50QXNzaWdubWVudD4oKTtcbiAgKGFzc2lnbm1lbnRzID8/IFtdKS5mb3JFYWNoKGEgPT4ge1xuICAgIGlmIChhLmxheWVyX25hbWUgIT0gbnVsbCAmJiBhLm5hbWVzcGFjZSAhPSBudWxsKSB7XG4gICAgICBieU5hbWVzcGFjZS5zZXQoYS5uYW1lc3BhY2UsIGEpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBFWFBFUklNRU5UX05BTUVTUEFDRVMucmVkdWNlPFJlY29yZDxzdHJpbmcsIHVua25vd24+PigoYWNjLCBucykgPT4ge1xuICAgIGNvbnN0IGEgPSBieU5hbWVzcGFjZS5nZXQobnMpO1xuICAgIGFjY1tgZXhwZXJpbWVudC4ke25zfS5sYXllcl9uYW1lYF0gPSBhPy5sYXllcl9uYW1lID8/IG51bGw7XG4gICAgYWNjW2BleHBlcmltZW50LiR7bnN9LmV4cGVyaW1lbnRfbmFtZWBdID0gYT8uYWxsb2NhdGVkX2V4cGVyaW1lbnRfbmFtZSA/PyBudWxsO1xuICAgIGFjY1tgZXhwZXJpbWVudC4ke25zfS5ncm91cF9uYW1lYF0gPSBhPy5ncm91cF9uYW1lID8/IG51bGw7XG4gICAgLy8gYHJ1bGVfaWRgIHJlc2VydmVkIOKAlCBiYWNrZW5kIGRvZXNuJ3QgY3VycmVudGx5IHN1cmZhY2UgaXQuXG4gICAgYWNjW2BleHBlcmltZW50LiR7bnN9LnJ1bGVfaWRgXSA9IG51bGw7XG4gICAgcmV0dXJuIGFjYztcbiAgfSwge30pO1xufTtcblxuZXhwb3J0IGNsYXNzIEFtcGxpdHVkZVNlcnZpY2Uge1xuICBwcml2YXRlIGFtcGxpdHVkZUNsaWVudDogQnJvd3NlckNsaWVudCB8IHVuZGVmaW5lZDtcblxuICBwcml2YXRlIGludGVybmFsRXZlbnRUcmFja2luZ0VucmljaG1lbnQ6IEVucmljaG1lbnRQbHVnaW4gfCB1bmRlZmluZWQ7XG5cbiAgcHJpdmF0ZSBzdXBwbGVtZW50YWxEZWZhdWx0UHJvcHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG5cbiAgcHJpdmF0ZSBjb25maWc6IEFtcGxpdHVkZVNlcnZpY2VDb25maWc7XG5cbiAgcHJpdmF0ZSBpbml0UHJvbWlzZTogUHJvbWlzZTx2b2lkPjtcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IEFtcGxpdHVkZVNlcnZpY2VDb25maWcpIHtcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgICB0aGlzLmluaXRQcm9taXNlID0gdGhpcy5pbml0aWFsaXplKCk7XG4gIH1cblxuICBnZXQgaXNNb2NrQXBpS2V5KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZy5hbXBsaXR1ZGVBcGlLZXkgPT09ICdtb2NrLWFtcGxpdHVkZS1rZXknO1xuICB9XG5cbiAgLy8gTXVzdCBub3QgZGVwZW5kIG9uIGBhbXBsaXR1ZGVDbGllbnRgOiB0aGUgU0RLIG5vdyBsb2FkcyB2aWEgZHluYW1pY1xuICAvLyBpbXBvcnQsIGFuZCBBbXBsaXR1ZGVQcm92aWRlciB1bm1vdW50cyBpdHMgZW50aXJlIHN1YnRyZWUgd2hpbGVcbiAgLy8gaXNSZWFkeSBpcyBmYWxzZSDigJQgZ2F0aW5nIG9uIHRoZSBjbGllbnQgd291bGQgYmxvY2sgd2lkZ2V0IHJlbmRlcmluZ1xuICAvLyBvbiB0aGUgYW5hbHl0aWNzIGNodW5rIGRvd25sb2FkLiBFdmVudHMgYXdhaXRlZCBpbiB0cmFja0V2ZW50IHF1ZXVlXG4gIC8vIGJlaGluZCBgaW5pdFByb21pc2VgIGluc3RlYWQuXG4gIGdldCBpc1JlYWR5KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBCb29sZWFuKFxuICAgICAgdGhpcy5jb25maWcudXNlcklkICYmXG4gICAgICB0aGlzLmNvbmZpZy5mZWF0dXJlRmxhZ1NlcnZpY2UgJiZcbiAgICAgIHRoaXMuY29uZmlnLmFtcGxpdHVkZUFwaUtleSAmJlxuICAgICAgIXRoaXMuaXNNb2NrQXBpS2V5LFxuICAgICk7XG4gIH1cblxuICAvKiogUmVzb2x2ZXMgb25jZSBTREsgaW5pdGlhbGl6YXRpb24gaGFzIHNldHRsZWQgKG5ldmVyIHJlamVjdHMpLiAqL1xuICBpbml0aWFsaXplZCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5pbml0UHJvbWlzZTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0TG9jYWxTdG9yYWdlSXRlbShrZXk6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICAgIGlmICh0aGlzLmNvbmZpZy5nZXRMb2NhbFN0b3JhZ2VJdGVtKSB7XG4gICAgICByZXR1cm4gdGhpcy5jb25maWcuZ2V0TG9jYWxTdG9yYWdlSXRlbShrZXkpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgd2luZG93LmxvY2FsU3RvcmFnZSkge1xuICAgICAgcmV0dXJuIHdpbmRvdy5sb2NhbFN0b3JhZ2UuZ2V0SXRlbShrZXkpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RGVmYXVsdFRyYWNraW5nUHJvcHMoXG4gICAgZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lIHwgRW52aXZlTWV0cmljc0V2ZW50TmFtZSxcbiAgKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICAgIGNvbnN0IGZlYXR1cmVHYXRlcyA9IE9iamVjdC5lbnRyaWVzKHRoaXMuY29uZmlnLmZlYXR1cmVGbGFnU2VydmljZS5nZXRGZWF0dXJlRmxhZ3MoKSk7XG4gICAgY29uc3QgZ2F0ZXNQcm9wcyA9XG4gICAgICBmZWF0dXJlR2F0ZXMubGVuZ3RoID4gMFxuICAgICAgICA/IGZlYXR1cmVHYXRlcy5yZWR1Y2U8UmVjb3JkPHN0cmluZywgYm9vbGVhbj4+KChhY2MsIFtuYW1lLCB2YWx1ZV0pID0+IHtcbiAgICAgICAgICAgIGlmIChuYW1lICYmIHZhbHVlICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uYWNjLCBbYGZlYXR1cmVfZ2F0ZS4ke25hbWV9YF06IHZhbHVlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICAgIH0sIHt9KVxuICAgICAgICA6IHt9O1xuICAgIGNvbnN0IGV4cGVyaW1lbnRQcm9wcyA9IGJ1aWxkRXhwZXJpbWVudFByb3BzKHRoaXMuY29uZmlnLmV4cGVyaW1lbnRBc3NpZ25tZW50cyk7XG5cbiAgICBjb25zdCBlbnZpcm9ubWVudFByb3BzID0ge1xuICAgICAgJ2Vudmlyb25tZW50LmV4ZWN1dGlvbl9jb250ZXh0JzogJ2J1bmRsZScsXG4gICAgICAnZW52aXJvbm1lbnQucGFnZV91cmwnOiB3aW5kb3cubG9jYXRpb24uaHJlZixcbiAgICAgICdlbnZpcm9ubWVudC5lbnZpdmVfdXNlcl9pZCc6IHRoaXMuY29uZmlnLnVzZXJJZCxcbiAgICAgICdlbnZpcm9ubWVudC5leGVjdXRpb25fZW52aXJvbm1lbnQnOiB0aGlzLmNvbmZpZy5lbnYgfHwgJ3Vua25vd24nLFxuICAgICAgJ2Vudmlyb25tZW50LmNvbnRleHRfc291cmNlJzogdGhpcy5jb25maWcuY29udGV4dFNvdXJjZSxcbiAgICAgICdlbnZpcm9ubWVudC5zYWxlc19hZ2VudF9lbmFibGVkJzogdGhpcy5jb25maWcuZW5hYmxlZEZlYXR1cmVzPy5zYWxlc0FnZW50ID8/IGZhbHNlLFxuICAgICAgJ2Vudmlyb25tZW50LnNlYXJjaF9lbmFibGVkJzogdGhpcy5jb25maWcuZW5hYmxlZEZlYXR1cmVzPy5zZWFyY2hBZ2VudCA/PyBmYWxzZSxcbiAgICAgICdlbnZpcm9ubWVudC5lbnZpdmVfb25fcXVlcnlfcGFyYW0nOiB0aGlzLmNvbmZpZy5lbnZpdmVPbixcbiAgICAgICdlbnZpcm9ubWVudC53aW5kb3dfc2hvdyc6IHRoaXMuY29uZmlnLnNob3csXG4gICAgICAnZW52aXJvbm1lbnQuZW52aXZlX2VuYWJsZWQnOiB0aGlzLmNvbmZpZy5lbmFibGVkRmVhdHVyZXM/LmVudml2ZSxcbiAgICB9O1xuXG4gICAgY29uc3Qgb3JnTGV2ZWxBbXBsaXR1ZGVUcmFja2luZ1Byb3BzID0gQW1wbGl0dWRlU2VydmljZS5pc1YzRW52aXZlRXZlbnQoZXZlbnROYW1lKVxuICAgICAgPyB7XG4gICAgICAgICAgLi4udGhpcy5jb25maWcuZmVhdHVyZUZsYWdTZXJ2aWNlLmdldEZ1bGxGbGFnVmFsdWVzKCksXG4gICAgICAgICAgLi4uZXhwZXJpbWVudFByb3BzLFxuICAgICAgICAgIC4uLmVudmlyb25tZW50UHJvcHMsXG4gICAgICAgIH1cbiAgICAgIDoge1xuICAgICAgICAgIC4uLmdhdGVzUHJvcHMsXG4gICAgICAgICAgLi4uZXhwZXJpbWVudFByb3BzLFxuICAgICAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICAuLi5vcmdMZXZlbEFtcGxpdHVkZVRyYWNraW5nUHJvcHMsXG4gICAgICAuLi50aGlzLnN1cHBsZW1lbnRhbERlZmF1bHRQcm9wcyxcbiAgICAgIGFwcF9pZDogJ2NvbW1lcmNlLWNoYXQtcmVhY3QtY29tcG9uZW50JyxcbiAgICAgIGNoYXRfaWQ6IHRoaXMuZ2V0TG9jYWxTdG9yYWdlSXRlbShMb2NhbFN0b3JhZ2VLZXlzLkNoYXRJZCksXG4gICAgICBlbnY6IHRoaXMuY29uZmlnLmVudiB8fCAndW5rbm93bicsXG4gICAgICBhcHBfc291cmNlOiB0aGlzLmNvbmZpZy5jb250ZXh0U291cmNlLFxuICAgICAgb3JnX2lkOiB0aGlzLmNvbmZpZy5vcmdJZCxcbiAgICAgICdvcmcuc2hvcnRfbmFtZSc6IHRoaXMuY29uZmlnLm9yZ1Nob3J0TmFtZSxcbiAgICAgICd1c2VyLmlkJzogdGhpcy5jb25maWcudXNlcklkLFxuICAgICAgJ2NkcC51c2VyX2lkJzogbnVsbCxcbiAgICAgICdjZHAucHJvdmlkZXInOiBudWxsLFxuICAgICAgJ2V2ZW50LnNvdXJjZSc6ICd3ZWItYnJvd3NlcicsXG4gICAgICAnZXZlbnQudHlwZSc6ICd1c2VyLWFjdGl2aXR5JyxcbiAgICAgICdldmVudC5pZCc6IG51bGwsXG4gICAgICAnZXZlbnQuY2hhbm5lbCc6ICd3ZWInLFxuICAgICAgJ2V2ZW50LnRpbWVzdGFtcCc6IG51bGwsXG4gICAgfTtcbiAgfVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG4gIHByaXZhdGUgZXZlbnRQcm9wc1RvUHJlZml4ZWRFdmVudFByb3BzKFxuICAgIGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSB8IEVudml2ZU1ldHJpY3NFdmVudE5hbWUsXG4gICAgZXZlbnRQcm9wczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgICBjb25zdCBwcmVmaXggPSBldmVudE5hbWUudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9cXHMrL2csICdfJyk7XG4gICAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKGV2ZW50UHJvcHMpLnJlZHVjZShcbiAgICAgIChhY2MsIFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgICBhY2NbYCR7cHJlZml4fS4ke2tleX1gXSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgfSxcbiAgICAgIHt9IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGdldEV2ZW50VHJhY2tpbmdFbnJpY2htZW50KCk6IEVucmljaG1lbnRQbHVnaW4ge1xuICAgIGlmICh0aGlzLmludGVybmFsRXZlbnRUcmFja2luZ0VucmljaG1lbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHRoaXMuaW50ZXJuYWxFdmVudFRyYWNraW5nRW5yaWNobWVudDtcbiAgICB9XG5cbiAgICBjb25zdCBlbnJpY2htZW50OiBFbnJpY2htZW50UGx1Z2luID0ge1xuICAgICAgbmFtZTogJ3BhZ2Utdmlldy10cmFja2luZy1lbnJpY2htZW50JyxcbiAgICAgIHR5cGU6ICdlbnJpY2htZW50JyxcbiAgICAgIHNldHVwOiBhc3luYyAoKSA9PiB1bmRlZmluZWQsXG4gICAgICBleGVjdXRlOiBhc3luYyAoZXZlbnQ6IEV2ZW50KTogUHJvbWlzZTxFdmVudD4gPT4ge1xuICAgICAgICBsZXQgZW5yaWNoZWRFdmVudDogRXZlbnQ7XG5cbiAgICAgICAgY29uc3QgZXZlbnRzVG9FbnJpY2ggPSBbXG4gICAgICAgICAgJ1tBbXBsaXR1ZGVdIFBhZ2UgVmlld2VkJyxcbiAgICAgICAgICBgW1NwaWZmeV0gJHtTcGlmZnlNZXRyaWNzRXZlbnROYW1lLkJ1bmRsZUxvYWRlZH1gLFxuICAgICAgICAgIGBbRW52aXZlXSAke0Vudml2ZU1ldHJpY3NFdmVudE5hbWUuUGFnZVZpZXdlZH1gLFxuICAgICAgICBdO1xuXG4gICAgICAgIGlmIChldmVudHNUb0VucmljaC5pbmNsdWRlcyhldmVudC5ldmVudF90eXBlKSkge1xuICAgICAgICAgIGNvbnN0IGdsb2JhbFByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5zaG93ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGdsb2JhbFByb3BlcnRpZXNbJ2dsb2JhbFByb3BlcnRpZXMuc2hvdyddID0gU3RyaW5nKHRoaXMuY29uZmlnLnNob3cpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBnbG9iYWxQcm9wZXJ0aWVzWydnbG9iYWxQcm9wZXJ0aWVzLmVudiddID0gU3RyaW5nKHRoaXMuY29uZmlnLmVudik7XG5cbiAgICAgICAgICBjb25zdCBlbmFibGVkRmVhdHVyZXNQcm9wZXJ0aWVzID0gT2JqZWN0LmVudHJpZXMoXG4gICAgICAgICAgICB0aGlzLmNvbmZpZz8uZW5hYmxlZEZlYXR1cmVzID8/ICh7fSBhcyBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiksXG4gICAgICAgICAgKS5yZWR1Y2U8UmVjb3JkPHN0cmluZywgc3RyaW5nPj4oXG4gICAgICAgICAgICAoYWNjLCBba2V5LCB2YWx1ZV0pID0+ICh7XG4gICAgICAgICAgICAgIC4uLmFjYyxcbiAgICAgICAgICAgICAgW2BlbmFibGVkRmVhdHVyZXMuJHtrZXl9YF06IGAke3ZhbHVlfWAsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIHt9LFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCB0aW1pbmdQcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgJ3RpbWluZy5lbnJpY2hlZF9hdF9tcyc6XG4gICAgICAgICAgICAgIHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93LnBlcmZvcm1hbmNlPy5ub3coKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgZW5yaWNoZWRFdmVudCA9IHtcbiAgICAgICAgICAgIC4uLmV2ZW50LFxuICAgICAgICAgICAgZXZlbnRfcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAuLi5ldmVudC5ldmVudF9wcm9wZXJ0aWVzLFxuICAgICAgICAgICAgICAuLi50aGlzLmdldERlZmF1bHRUcmFja2luZ1Byb3BzKFxuICAgICAgICAgICAgICAgIGV2ZW50LmV2ZW50X3R5cGUgYXMgU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSB8IEVudml2ZU1ldHJpY3NFdmVudE5hbWUsXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIC4uLmdsb2JhbFByb3BlcnRpZXMsXG4gICAgICAgICAgICAgIC4uLmVuYWJsZWRGZWF0dXJlc1Byb3BlcnRpZXMsXG4gICAgICAgICAgICAgIC4uLnRpbWluZ1Byb3BlcnRpZXMsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZW5yaWNoZWRFdmVudCA9IGV2ZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgRXZlbnRzRGlzcGF0Y2hlci5kaXNwYXRjaChTcGlmZnlFdmVudC5BTVBMSVRVREVfRVZFTlQsIGVucmljaGVkRXZlbnQpO1xuXG4gICAgICAgIHJldHVybiBlbnJpY2hlZEV2ZW50O1xuICAgICAgfSxcbiAgICB9O1xuICAgIHRoaXMuaW50ZXJuYWxFdmVudFRyYWNraW5nRW5yaWNobWVudCA9IGVucmljaG1lbnQ7XG4gICAgcmV0dXJuIGVucmljaG1lbnQ7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGluaXRpYWxpemUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgaXNSZWFkeSA9IEJvb2xlYW4oXG4gICAgICB0aGlzLmNvbmZpZy51c2VySWQgJiYgdGhpcy5jb25maWcuZmVhdHVyZUZsYWdTZXJ2aWNlICYmIHRoaXMuY29uZmlnLmFtcGxpdHVkZUFwaUtleSxcbiAgICApO1xuXG4gICAgaWYgKCFpc1JlYWR5KSB7XG4gICAgICBsb2dnZXIubG9nRGVidWcoJ0FtcGxpdHVkZVNlcnZpY2UgaXMgbm90IHJlYWR5Jywge1xuICAgICAgICBpc1JlYWR5LFxuICAgICAgICB1c2VySWQ6IHRoaXMuY29uZmlnLnVzZXJJZCxcbiAgICAgICAgaGFzRmVhdHVyZUZsYWdTZXJ2aWNlOiAhIXRoaXMuY29uZmlnLmZlYXR1cmVGbGFnU2VydmljZSxcbiAgICAgICAgaGFzQW1wbGl0dWRlQXBpS2V5OiAhIXRoaXMuY29uZmlnLmFtcGxpdHVkZUFwaUtleSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmlzTW9ja0FwaUtleSkge1xuICAgICAgbG9nZ2VyLmxvZ1dhcm4oXG4gICAgICAgICdNb2NrIEFQSSBrZXkgZGV0ZWN0ZWQg4oCUIHJ1bm5pbmcgaW4gbW9jayBtb2RlLCBubyBldmVudHMgd2lsbCBiZSBzZW50IHRvIEFtcGxpdHVkZS4nLFxuICAgICAgICB0aGlzLmNvbmZpZy5hbXBsaXR1ZGVBcGlLZXksXG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5hbXBsaXR1ZGVDbGllbnQpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIER5bmFtaWMgaW1wb3J0IGtlZXBzIHRoZSBBbXBsaXR1ZGUgU0RLIG91dCBvZiB0aGUgZWFnZXJcbiAgICAgICAgLy8gaW5qZWN0aW9uLWJ1bmRsZSBjaHVuazsgdHJhY2tFdmVudCBxdWV1ZXMgYmVoaW5kIGluaXRQcm9taXNlLlxuICAgICAgICBjb25zdCB7IGNyZWF0ZUluc3RhbmNlIH0gPSBhd2FpdCBpbXBvcnQoJ0BhbXBsaXR1ZGUvYW5hbHl0aWNzLWJyb3dzZXInKTtcbiAgICAgICAgY29uc3QgY3VycmVudEFtcGxpdHVkZUluc3RhbmNlOiBCcm93c2VyQ2xpZW50ID0gY3JlYXRlSW5zdGFuY2UoKTtcblxuICAgICAgICBjdXJyZW50QW1wbGl0dWRlSW5zdGFuY2UuYWRkKHRoaXMuZ2V0RXZlbnRUcmFja2luZ0VucmljaG1lbnQoKSk7XG4gICAgICAgIGN1cnJlbnRBbXBsaXR1ZGVJbnN0YW5jZS5pbml0KHRoaXMuY29uZmlnLmFtcGxpdHVkZUFwaUtleSwgdGhpcy5jb25maWcudXNlcklkLCB7XG4gICAgICAgICAgc2VydmVyWm9uZTogdGhpcy5jb25maWcuZGF0YVJlc2lkZW5jeSBhcyBTZXJ2ZXJab25lVHlwZSxcbiAgICAgICAgICB0cmFja2luZ09wdGlvbnM6IHtcbiAgICAgICAgICAgIGlwQWRkcmVzczogdHJ1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGF1dG9jYXB0dXJlOiB7XG4gICAgICAgICAgICBhdHRyaWJ1dGlvbjogdHJ1ZSxcbiAgICAgICAgICAgIHBhZ2VWaWV3czoge1xuICAgICAgICAgICAgICB0cmFja0hpc3RvcnlDaGFuZ2VzOiAncGF0aE9ubHknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNlc3Npb25zOiBmYWxzZSxcbiAgICAgICAgICAgIGZvcm1JbnRlcmFjdGlvbnM6IGZhbHNlLFxuICAgICAgICAgICAgZmlsZURvd25sb2FkczogZmFsc2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYW1wbGl0dWRlQ2xpZW50ID0gY3VycmVudEFtcGxpdHVkZUluc3RhbmNlO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGxvZ2dlci5sb2dFcnJvcignRmFpbGVkIHRvIGxvYWQgb3IgaW5pdGlhbGl6ZSB0aGUgQW1wbGl0dWRlIFNESycsIGVycik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIG1hcFdpZGdldFR5cGVUb0NoYXRDb21wb25lbnQod2lkZ2V0VHlwZTogdW5rbm93bik6IHN0cmluZyB7XG4gICAgc3dpdGNoICh3aWRnZXRUeXBlKSB7XG4gICAgICBjYXNlIFdpZGdldFR5cGVWMy5GbG9hdGluZ0J1dHRvblYzOlxuICAgICAgICByZXR1cm4gJ2Zsb2F0aW5nX2J1dHRvbic7XG4gICAgICBjYXNlIFdpZGdldFR5cGVWMy5UeXBpbmdBbmltYXRpb25WMzpcbiAgICAgIGNhc2UgV2lkZ2V0VHlwZVYzLkNoYXRQcmV2aWV3VjM6XG4gICAgICBjYXNlIFdpZGdldFR5cGVWMy5Tb2NpYWxQcm9vZlYzOlxuICAgICAgICByZXR1cm4gJ2VtYmVkZGVkX3dpZGdldCc7XG4gICAgICBjYXNlIFdpZGdldFR5cGVWMy5UaXRsZWRQcm9tcHRDYXJvdXNlbFYzOlxuICAgICAgY2FzZSBXaWRnZXRUeXBlVjMuUHJvbXB0Q2Fyb3VzZWxWMzpcbiAgICAgICAgcmV0dXJuICdzdWdnZXN0aW9uX2Jhcic7XG4gICAgICBjYXNlIFdpZGdldFR5cGVWMy5Qcm9kdWN0Q2FyZFYzOlxuICAgICAgICByZXR1cm4gJ2ltYWdlX3Byb21wdF9jYXJkJztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiAndW5rbm93bic7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIG1hcFRyaWdnZXJMb2NhdGlvblRvQ2hhdENvbXBvbmVudCh0cmlnZ2VyTG9jYXRpb246IHVua25vd24pOiBzdHJpbmcge1xuICAgIHN3aXRjaCAodHJpZ2dlckxvY2F0aW9uKSB7XG4gICAgICBjYXNlIENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uVjMuUFJPRFVDVF9DQVJEX1BST01QVF9CVVRUT046XG4gICAgICBjYXNlIENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uVjMuUFJPRFVDVF9DQVJEX1RFWFRfRklFTEQ6XG4gICAgICAgIHJldHVybiAncHJvbXB0X2NhcmQnO1xuICAgICAgY2FzZSBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzLlBST01QVF9DQVJPVVNFTDpcbiAgICAgIGNhc2UgQ2hhdEVsZW1lbnREaXNwbGF5TG9jYXRpb25WMy5USVRMRURfUFJPTVBUX0NBUk9VU0VMOlxuICAgICAgICByZXR1cm4gJ3RvcF9yZXZpZXdzX3NuaXBwZXQnO1xuICAgICAgY2FzZSBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzLlRZUElOR19BTklNQVRJT046XG4gICAgICBjYXNlIENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uVjMuU09DSUFMX1BST09GX1BSSU1BUllfQlVUVE9OOlxuICAgICAgY2FzZSBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzLlNPQ0lBTF9QUk9PRl9TRUNPTkRBUllfQlVUVE9OOlxuICAgICAgY2FzZSBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzLlNPQ0lBTF9QUk9PRl9URVhUX0ZJRUxEOlxuICAgICAgY2FzZSBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzLkNIQVRfUFJFVklFV19DT01QQVJJU09OX1BST01QVF9CVVRUT046XG4gICAgICBjYXNlIENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uVjMuQ0hBVF9QUkVWSUVXX0NPTVBBUklTT05fVEVYVF9GSUVMRDpcbiAgICAgIGNhc2UgQ2hhdEVsZW1lbnREaXNwbGF5TG9jYXRpb25WMy5DSEFUX1BSRVZJRVdfUFJPTVBUX0JVVFRPTjpcbiAgICAgIGNhc2UgQ2hhdEVsZW1lbnREaXNwbGF5TG9jYXRpb25WMy5DSEFUX1BSRVZJRVdfVEVYVF9GSUVMRDpcbiAgICAgICAgcmV0dXJuICdjaGF0X3ByZXZpZXcnO1xuICAgICAgY2FzZSBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzLkZMT0FUSU5HX0NIQVRfT1ZFUkxBWTpcbiAgICAgIGNhc2UgQ2hhdEVsZW1lbnREaXNwbGF5TG9jYXRpb25WMy5GTE9BVElOR19DSEFUX0NMT1NFX0JVVFRPTjpcbiAgICAgICAgcmV0dXJuICdpbl9jaGF0JztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiB0cmlnZ2VyTG9jYXRpb24gYXMgc3RyaW5nO1xuICAgIH1cbiAgfVxuXG4gIC8vIFRoaXMgYWxsb3dzIHVzIHRvIG1hcCB0aGUgZXZlbnQgcHJvcHMgdG8gdGhlIGNvcnJlY3QgZm9ybWF0IGZvciB0aGUgbGVnYWN5IGFtcGxpdHVkZSBldmVudHNcbiAgc3RhdGljIG1hcEV2ZW50UHJvcHMoeyBldmVudE5hbWUsIGV2ZW50UHJvcHMgfTogVHJhY2tFdmVudFBhcmFtcyk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgICBjb25zdCBtZXNzYWdlTWV0YWRhdGEgPSBldmVudFByb3BzPy5tZXNzYWdlX21ldGFkYXRhID8/IHt9O1xuICAgIGNvbnN0IHRyaWdnZXJMb2NhdGlvbiA9XG4gICAgICBtZXNzYWdlTWV0YWRhdGEgIT09IG51bGwgJiZcbiAgICAgIHR5cGVvZiBtZXNzYWdlTWV0YWRhdGEgPT09ICdvYmplY3QnICYmXG4gICAgICAndHJpZ2dlcl9sb2NhdGlvbicgaW4gbWVzc2FnZU1ldGFkYXRhXG4gICAgICAgID8gbWVzc2FnZU1ldGFkYXRhLnRyaWdnZXJfbG9jYXRpb25cbiAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBpZiAoZXZlbnROYW1lID09PSBTcGlmZnlNZXRyaWNzRXZlbnROYW1lLkNoYXRDb21wb25lbnRFeHBhbmRlZCkge1xuICAgICAgY29uc3QgbWFwcGVkVHJpZ2dlckxvY2NhdGlvbiA9XG4gICAgICAgIEFtcGxpdHVkZVNlcnZpY2UubWFwVHJpZ2dlckxvY2F0aW9uVG9DaGF0Q29tcG9uZW50KHRyaWdnZXJMb2NhdGlvbik7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5ldmVudFByb3BzLFxuICAgICAgICBtZXNzYWdlX21ldGFkYXRhOiB7XG4gICAgICAgICAgLi4ubWVzc2FnZU1ldGFkYXRhLFxuICAgICAgICAgIHRyaWdnZXJfbG9jYXRpb246IG1hcHBlZFRyaWdnZXJMb2NjYXRpb24sXG4gICAgICAgICAgZnVsbF90cmlnZ2VyX2xvY2F0aW9uOiB0cmlnZ2VyTG9jYXRpb24sXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChldmVudE5hbWUgPT09IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUuQ2hhdENvbXBvbmVudFZpc2libGUpIHtcbiAgICAgIGNvbnN0IG1hcHBlZFdpZGdldFR5cGUgPSBBbXBsaXR1ZGVTZXJ2aWNlLm1hcFdpZGdldFR5cGVUb0NoYXRDb21wb25lbnQoXG4gICAgICAgIGV2ZW50UHJvcHM/LndpZGdldF90eXBlLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IG1hcHBlZFRyaWdnZXJMb2NjYXRpb24gPVxuICAgICAgICBBbXBsaXR1ZGVTZXJ2aWNlLm1hcFRyaWdnZXJMb2NhdGlvblRvQ2hhdENvbXBvbmVudCh0cmlnZ2VyTG9jYXRpb24pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uZXZlbnRQcm9wcyxcbiAgICAgICAgbWVzc2FnZV9tZXRhZGF0YToge1xuICAgICAgICAgIC4uLm1lc3NhZ2VNZXRhZGF0YSxcbiAgICAgICAgICB0cmlnZ2VyX2xvY2F0aW9uOiBtYXBwZWRUcmlnZ2VyTG9jY2F0aW9uLFxuICAgICAgICAgIGZ1bGxfdHJpZ2dlcl9sb2NhdGlvbjogdHJpZ2dlckxvY2F0aW9uLFxuICAgICAgICB9LFxuICAgICAgICBjaGF0X2NvbXBvbmVudDogbWFwcGVkV2lkZ2V0VHlwZSxcbiAgICAgICAgJ2NoYXQuY29tcG9uZW50X3Zpc2libGUnOiB0cnVlLFxuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIGV2ZW50UHJvcHMgPz8ge307XG4gIH1cblxuICBzdGF0aWMgaXNWM0Vudml2ZUV2ZW50KGV2ZW50TmFtZTogU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSB8IEVudml2ZU1ldHJpY3NFdmVudE5hbWUpOiBib29sZWFuIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhFbnZpdmVNZXRyaWNzRXZlbnROYW1lKS5pbmNsdWRlcyhldmVudE5hbWUgYXMgRW52aXZlTWV0cmljc0V2ZW50TmFtZSk7XG4gIH1cblxuICBzdGF0aWMgZGVjb3JhdGVFdmVudE5hbWUoZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lIHwgRW52aXZlTWV0cmljc0V2ZW50TmFtZSk6IHN0cmluZyB7XG4gICAgaWYgKEFtcGxpdHVkZVNlcnZpY2UuaXNWM0Vudml2ZUV2ZW50KGV2ZW50TmFtZSkpIHtcbiAgICAgIHJldHVybiBgW0Vudml2ZV0gJHtldmVudE5hbWV9YDtcbiAgICB9XG4gICAgcmV0dXJuIGBbU3BpZmZ5XSAke2V2ZW50TmFtZX1gO1xuICB9XG5cbiAgYXN5bmMgdHJhY2tFdmVudCh7XG4gICAgZXZlbnROYW1lLFxuICAgIGV2ZW50UHJvcHMsXG4gICAgZXZlbnRHcm91cHMsXG4gICAgYWxzb1NlbmRUb0dvb2dsZUFuYWx5dGljcyA9IGZhbHNlLFxuICB9OiBUcmFja0V2ZW50UGFyYW1zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuaXNNb2NrQXBpS2V5KSByZXR1cm47XG4gICAgYXdhaXQgdGhpcy5pbml0UHJvbWlzZTtcbiAgICBsb2dnZXIubG9nRGVidWcoJ1N1Ym1pdHRpbmcgZXZlbnQnLCBldmVudE5hbWUpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkZWNvcmF0ZWRFdmVudE5hbWUgPSBBbXBsaXR1ZGVTZXJ2aWNlLmRlY29yYXRlRXZlbnROYW1lKGV2ZW50TmFtZSk7XG5cbiAgICAgIGlmICghdGhpcy5hbXBsaXR1ZGVDbGllbnQpIHtcbiAgICAgICAgbG9nZ2VyLmxvZ1dhcm4oJ2FtcGxpdHVkZSBjbGllbnQgdW5kZWZpbmVkJywgdW5kZWZpbmVkLCB7XG4gICAgICAgICAgZXZlbnRfbmFtZTogZGVjb3JhdGVkRXZlbnROYW1lLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtYXBwZWRFdmVudFByb3BzID0gQW1wbGl0dWRlU2VydmljZS5tYXBFdmVudFByb3BzKHsgZXZlbnROYW1lLCBldmVudFByb3BzIH0pO1xuXG4gICAgICBjb25zdCBldmVudERhdGEgPSBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIGV2ZW50TmFtZSxcbiAgICAgICAgZXZlbnRQcm9wczogbWFwcGVkRXZlbnRQcm9wcyxcbiAgICAgICAgY3JlYXRlZF9hdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBlbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKCk7XG4gICAgICBjb25zdCBkYXRhID0gZW5jb2Rlci5lbmNvZGUoZXZlbnREYXRhKTtcbiAgICAgIC8vIGNhbGN1bGF0ZSBhIGhhc2ggb2YgdGhlIGV2ZW50IHByb3BlcnRpZXMgdG8gdXNlIGFzIHRoZSBpbnNlcnRfaWQgc28gdGhhdCBkdXBsaWNhdGUgZXZlbnRzXG4gICAgICAvLyBhcmUgYXV0b21hdGljYWxseSBkcm9wcGVkIGJ5IEFtcGxpdHVkZVxuICAgICAgY29uc3QgaGFzaEJ1ZmZlciA9IGF3YWl0IGNyeXB0by5zdWJ0bGUuZGlnZXN0KCdTSEEtMjU2JywgZGF0YSk7XG4gICAgICBjb25zdCBoYXNoQXJyYXkgPSBBcnJheS5mcm9tKG5ldyBVaW50OEFycmF5KGhhc2hCdWZmZXIpKTtcbiAgICAgIGNvbnN0IGN1cnJlbnRJbnNlcnRJZCA9IGhhc2hBcnJheS5tYXAoYiA9PiBiLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAnMCcpKS5qb2luKCcnKTtcblxuICAgICAgbG9nZ2VyLmxvZ0RlYnVnKGBhbXBsaXR1ZGUgdHJhY2tpbmcgJHtkZWNvcmF0ZWRFdmVudE5hbWV9YCwgbnVsbCwge1xuICAgICAgICBldmVudF9uYW1lOiBkZWNvcmF0ZWRFdmVudE5hbWUsXG4gICAgICAgIHByb3BzOiBtYXBwZWRFdmVudFByb3BzLFxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMuYW1wbGl0dWRlQ2xpZW50LnRyYWNrKFxuICAgICAgICBkZWNvcmF0ZWRFdmVudE5hbWUsXG4gICAgICAgIHtcbiAgICAgICAgICAuLi50aGlzLmdldERlZmF1bHRUcmFja2luZ1Byb3BzKGV2ZW50TmFtZSksXG4gICAgICAgICAgLi4ubWFwcGVkRXZlbnRQcm9wcyxcbiAgICAgICAgICAuLi4obWFwcGVkRXZlbnRQcm9wc1xuICAgICAgICAgICAgPyB0aGlzLmV2ZW50UHJvcHNUb1ByZWZpeGVkRXZlbnRQcm9wcyhldmVudE5hbWUsIG1hcHBlZEV2ZW50UHJvcHMpXG4gICAgICAgICAgICA6IHt9KSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIC4uLmV2ZW50R3JvdXBzLFxuICAgICAgICAgIGluc2VydF9pZDogY3VycmVudEluc2VydElkLFxuICAgICAgICB9LFxuICAgICAgKTtcblxuICAgICAgLy8gVE9ETzogUHVsbCBnYUVuYWJsZWQgZnJvbSBvcmcgY29uZmlnIHdoZW4gYXZhaWxhYmxlLiBIYXJkY29kZWQgdG8gdHJ1ZSBmb3Igbm93LlxuICAgICAgY29uc3QgZ2FFbmFibGVkID0gdHJ1ZTtcblxuICAgICAgaWYgKEFtcGxpdHVkZVNlcnZpY2UuaXNWM0Vudml2ZUV2ZW50KGV2ZW50TmFtZSkgJiYgZ2FFbmFibGVkKSB7XG4gICAgICAgIGNvbnN0IG1lcmdlZFByb3BzRm9yR0E0ID0ge1xuICAgICAgICAgIC4uLnRoaXMuZ2V0RGVmYXVsdFRyYWNraW5nUHJvcHMoZXZlbnROYW1lKSxcbiAgICAgICAgICAuLi5tYXBwZWRFdmVudFByb3BzLFxuICAgICAgICB9O1xuICAgICAgICBwcm9qZWN0VG9HQTQoZXZlbnROYW1lIGFzIEVudml2ZU1ldHJpY3NFdmVudE5hbWUsIG1lcmdlZFByb3BzRm9yR0E0KTtcbiAgICAgIH0gZWxzZSBpZiAoYWxzb1NlbmRUb0dvb2dsZUFuYWx5dGljcyAmJiBnYUVuYWJsZWQpIHtcbiAgICAgICAgbG9nZ2VyLmxvZ0RlYnVnKCdHQSB0cmFja2luZycsIGRlY29yYXRlZEV2ZW50TmFtZSk7XG4gICAgICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB3aW5kb3cuZGF0YUxheWVyKSB7XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgICAod2luZG93LmRhdGFMYXllciBhcyBhbnlbXSkucHVzaCh7XG4gICAgICAgICAgICBldmVudDogZGVjb3JhdGVkRXZlbnROYW1lLFxuICAgICAgICAgICAgZXZlbnRQcm9wcyxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nZ2VyLmxvZ0Vycm9yKCdFcnJvciB0cmFja2luZyBldmVudCcsIGVyciwge1xuICAgICAgICBldmVudE5hbWUsXG4gICAgICAgIGV2ZW50UHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvLyBFbnN1cmUgdGhhdCBzdXBwbGVtZW50YWwgZGVmYXVsdCBwcm9wcyBhcmUgbWVyZ2VkIHdpdGggdGhlIGV4aXN0aW5nIHByb3BzXG4gIHNldFN1cHBsZW1lbnRhbERlZmF1bHRQcm9wcyhwcm9wczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiB2b2lkIHtcbiAgICB0aGlzLnN1cHBsZW1lbnRhbERlZmF1bHRQcm9wcyA9IHByb3BzO1xuICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBbUJBLE1BQU0sU0FBUyxJQUFJQSxlQUFPLG1CQUFtQjtBQStCN0MsTUFBTUMsd0JBQStDLENBQUMsTUFBTSxXQUFXO0FBRXZFLE1BQU0sd0JBQ0osZ0JBQzRCO0NBQzVCLE1BQU0sOEJBQWMsSUFBSSxLQUF5RDtBQUNqRixFQUFDLGVBQWUsRUFBRSxFQUFFLFNBQVEsTUFBSztBQUMvQixNQUFJLEVBQUUsY0FBYyxRQUFRLEVBQUUsYUFBYSxLQUN6QyxhQUFZLElBQUksRUFBRSxXQUFXLEVBQUU7R0FFakM7QUFDRixRQUFPLHNCQUFzQixRQUFpQyxLQUFLLE9BQU87RUFDeEUsTUFBTSxJQUFJLFlBQVksSUFBSSxHQUFHO0FBQzdCLE1BQUksY0FBYyxHQUFHLGdCQUFnQixHQUFHLGNBQWM7QUFDdEQsTUFBSSxjQUFjLEdBQUcscUJBQXFCLEdBQUcsNkJBQTZCO0FBQzFFLE1BQUksY0FBYyxHQUFHLGdCQUFnQixHQUFHLGNBQWM7QUFFdEQsTUFBSSxjQUFjLEdBQUcsYUFBYTtBQUNsQyxTQUFPO0lBQ04sRUFBRSxDQUFDOztBQUdSLElBQWEsbUJBQWIsTUFBYSxpQkFBaUI7Q0FXNUIsWUFBWSxRQUFnQztrQ0FOZ0IsRUFBRTtBQU81RCxPQUFLLFNBQVM7QUFDZCxPQUFLLGNBQWMsS0FBSyxZQUFZOztDQUd0QyxJQUFJLGVBQXdCO0FBQzFCLFNBQU8sS0FBSyxPQUFPLG9CQUFvQjs7Q0FRekMsSUFBSSxVQUFtQjtBQUNyQixTQUFPLFFBQ0wsS0FBSyxPQUFPLFVBQ1osS0FBSyxPQUFPLHNCQUNaLEtBQUssT0FBTyxtQkFDWixDQUFDLEtBQUssYUFDUDs7O0NBSUgsY0FBNkI7QUFDM0IsU0FBTyxLQUFLOztDQUdkLEFBQVEsb0JBQW9CLEtBQTRCO0FBQ3RELE1BQUksS0FBSyxPQUFPLG9CQUNkLFFBQU8sS0FBSyxPQUFPLG9CQUFvQixJQUFJO0FBRTdDLE1BQUksT0FBTyxXQUFXLGVBQWUsT0FBTyxhQUMxQyxRQUFPLE9BQU8sYUFBYSxRQUFRLElBQUk7QUFFekMsU0FBTzs7Q0FHVCxBQUFRLHdCQUNOLFdBQ3lCO0VBQ3pCLE1BQU0sZUFBZSxPQUFPLFFBQVEsS0FBSyxPQUFPLG1CQUFtQixpQkFBaUIsQ0FBQztFQUNyRixNQUFNLGFBQ0osYUFBYSxTQUFTLElBQ2xCLGFBQWEsUUFBaUMsS0FBSyxDQUFDLE1BQU0sV0FBVztBQUNuRSxPQUFJLFFBQVEsU0FBUyxLQUNuQixRQUFPO0lBQUUsR0FBRztLQUFNLGdCQUFnQixTQUFTO0lBQU87QUFFcEQsVUFBTztLQUNOLEVBQUUsQ0FBQyxHQUNOLEVBQUU7RUFDUixNQUFNLGtCQUFrQixxQkFBcUIsS0FBSyxPQUFPLHNCQUFzQjtFQUUvRSxNQUFNLG1CQUFtQjtHQUN2QixpQ0FBaUM7R0FDakMsd0JBQXdCLE9BQU8sU0FBUztHQUN4Qyw4QkFBOEIsS0FBSyxPQUFPO0dBQzFDLHFDQUFxQyxLQUFLLE9BQU8sT0FBTztHQUN4RCw4QkFBOEIsS0FBSyxPQUFPO0dBQzFDLG1DQUFtQyxLQUFLLE9BQU8saUJBQWlCLGNBQWM7R0FDOUUsOEJBQThCLEtBQUssT0FBTyxpQkFBaUIsZUFBZTtHQUMxRSxxQ0FBcUMsS0FBSyxPQUFPO0dBQ2pELDJCQUEyQixLQUFLLE9BQU87R0FDdkMsOEJBQThCLEtBQUssT0FBTyxpQkFBaUI7R0FDNUQ7QUFZRCxTQUFPO0dBQ0wsR0FYcUMsaUJBQWlCLGdCQUFnQixVQUFVLEdBQzlFO0lBQ0UsR0FBRyxLQUFLLE9BQU8sbUJBQW1CLG1CQUFtQjtJQUNyRCxHQUFHO0lBQ0gsR0FBRztJQUNKLEdBQ0Q7SUFDRSxHQUFHO0lBQ0gsR0FBRztJQUNKO0dBR0gsR0FBRyxLQUFLO0dBQ1IsUUFBUTtHQUNSLFNBQVMsS0FBSyxvQkFBb0IsaUJBQWlCLE9BQU87R0FDMUQsS0FBSyxLQUFLLE9BQU8sT0FBTztHQUN4QixZQUFZLEtBQUssT0FBTztHQUN4QixRQUFRLEtBQUssT0FBTztHQUNwQixrQkFBa0IsS0FBSyxPQUFPO0dBQzlCLFdBQVcsS0FBSyxPQUFPO0dBQ3ZCLGVBQWU7R0FDZixnQkFBZ0I7R0FDaEIsZ0JBQWdCO0dBQ2hCLGNBQWM7R0FDZCxZQUFZO0dBQ1osaUJBQWlCO0dBQ2pCLG1CQUFtQjtHQUNwQjs7Q0FJSCxBQUFRLCtCQUNOLFdBQ0EsWUFDeUI7RUFDekIsTUFBTSxTQUFTLFVBQVUsYUFBYSxDQUFDLFFBQVEsUUFBUSxJQUFJO0FBQzNELFNBQU8sT0FBTyxRQUFRLFdBQVcsQ0FBQyxRQUMvQixLQUFLLENBQUMsS0FBSyxXQUFXO0FBQ3JCLE9BQUksR0FBRyxPQUFPLEdBQUcsU0FBUztBQUMxQixVQUFPO0tBRVQsRUFBRSxDQUNIOztDQUdILEFBQVEsNkJBQStDO0FBQ3JELE1BQUksS0FBSyxvQ0FBb0MsT0FDM0MsUUFBTyxLQUFLO0VBR2QsTUFBTUMsYUFBK0I7R0FDbkMsTUFBTTtHQUNOLE1BQU07R0FDTixPQUFPLFlBQVk7R0FDbkIsU0FBUyxPQUFPLFVBQWlDO0lBQy9DLElBQUlDO0FBUUosUUFOdUI7S0FDckI7S0FDQSxZQUFZLHVCQUF1QjtLQUNuQyxZQUFZLHVCQUF1QjtLQUNwQyxDQUVrQixTQUFTLE1BQU0sV0FBVyxFQUFFO0tBQzdDLE1BQU1DLG1CQUEyQyxFQUFFO0FBRW5ELFNBQUksS0FBSyxPQUFPLFFBQVEsS0FDdEIsa0JBQWlCLDJCQUEyQixPQUFPLEtBQUssT0FBTyxLQUFLO0FBRXRFLHNCQUFpQiwwQkFBMEIsT0FBTyxLQUFLLE9BQU8sSUFBSTtLQUVsRSxNQUFNLDRCQUE0QixPQUFPLFFBQ3ZDLEtBQUssUUFBUSxtQkFBb0IsRUFBRSxDQUNwQyxDQUFDLFFBQ0MsS0FBSyxDQUFDLEtBQUssWUFBWTtNQUN0QixHQUFHO09BQ0YsbUJBQW1CLFFBQVEsR0FBRztNQUNoQyxHQUNELEVBQUUsQ0FDSDtLQUVELE1BQU0sbUJBQW1CLEVBQ3ZCLHlCQUNFLE9BQU8sV0FBVyxjQUFjLE9BQU8sYUFBYSxLQUFLLEdBQUcsUUFDL0Q7QUFFRCxxQkFBZ0I7TUFDZCxHQUFHO01BQ0gsa0JBQWtCO09BQ2hCLEdBQUcsTUFBTTtPQUNULEdBQUcsS0FBSyx3QkFDTixNQUFNLFdBQ1A7T0FDRCxHQUFHO09BQ0gsR0FBRztPQUNILEdBQUc7T0FDSjtNQUNGO1VBRUQsaUJBQWdCO0FBR2xCLHFCQUFpQixTQUFTLFlBQVksaUJBQWlCLGNBQWM7QUFFckUsV0FBTzs7R0FFVjtBQUNELE9BQUssa0NBQWtDO0FBQ3ZDLFNBQU87O0NBR1QsTUFBYyxhQUE0QjtFQUN4QyxNQUFNLFVBQVUsUUFDZCxLQUFLLE9BQU8sVUFBVSxLQUFLLE9BQU8sc0JBQXNCLEtBQUssT0FBTyxnQkFDckU7QUFFRCxNQUFJLENBQUMsU0FBUztBQUNaLFVBQU8sU0FBUyxpQ0FBaUM7SUFDL0M7SUFDQSxRQUFRLEtBQUssT0FBTztJQUNwQix1QkFBdUIsQ0FBQyxDQUFDLEtBQUssT0FBTztJQUNyQyxvQkFBb0IsQ0FBQyxDQUFDLEtBQUssT0FBTztJQUNuQyxDQUFDO0FBQ0Y7O0FBR0YsTUFBSSxLQUFLLGNBQWM7QUFDckIsVUFBTyxRQUNMLHNGQUNBLEtBQUssT0FBTyxnQkFDYjtBQUNEOztBQUdGLE1BQUksQ0FBQyxLQUFLLGdCQUNSLEtBQUk7R0FHRixNQUFNLEVBQUUsbUJBQW1CLE1BQU0sT0FBTztHQUN4QyxNQUFNQywyQkFBMEMsZ0JBQWdCO0FBRWhFLDRCQUF5QixJQUFJLEtBQUssNEJBQTRCLENBQUM7QUFDL0QsNEJBQXlCLEtBQUssS0FBSyxPQUFPLGlCQUFpQixLQUFLLE9BQU8sUUFBUTtJQUM3RSxZQUFZLEtBQUssT0FBTztJQUN4QixpQkFBaUIsRUFDZixXQUFXLE1BQ1o7SUFDRCxhQUFhO0tBQ1gsYUFBYTtLQUNiLFdBQVcsRUFDVCxxQkFBcUIsWUFDdEI7S0FDRCxVQUFVO0tBQ1Ysa0JBQWtCO0tBQ2xCLGVBQWU7S0FDaEI7SUFDRixDQUFDO0FBQ0YsUUFBSyxrQkFBa0I7V0FDaEIsS0FBSztBQUNaLFVBQU8sU0FBUyxrREFBa0QsSUFBSTs7O0NBSzVFLE9BQU8sNkJBQTZCLFlBQTZCO0FBQy9ELFVBQVEsWUFBUjtHQUNFLEtBQUssYUFBYSxpQkFDaEIsUUFBTztHQUNULEtBQUssYUFBYTtHQUNsQixLQUFLLGFBQWE7R0FDbEIsS0FBSyxhQUFhLGNBQ2hCLFFBQU87R0FDVCxLQUFLLGFBQWE7R0FDbEIsS0FBSyxhQUFhLGlCQUNoQixRQUFPO0dBQ1QsS0FBSyxhQUFhLGNBQ2hCLFFBQU87R0FDVCxRQUNFLFFBQU87OztDQUliLE9BQU8sa0NBQWtDLGlCQUFrQztBQUN6RSxVQUFRLGlCQUFSO0dBQ0UsS0FBSyw2QkFBNkI7R0FDbEMsS0FBSyw2QkFBNkIsd0JBQ2hDLFFBQU87R0FDVCxLQUFLLDZCQUE2QjtHQUNsQyxLQUFLLDZCQUE2Qix1QkFDaEMsUUFBTztHQUNULEtBQUssNkJBQTZCO0dBQ2xDLEtBQUssNkJBQTZCO0dBQ2xDLEtBQUssNkJBQTZCO0dBQ2xDLEtBQUssNkJBQTZCO0dBQ2xDLEtBQUssNkJBQTZCO0dBQ2xDLEtBQUssNkJBQTZCO0dBQ2xDLEtBQUssNkJBQTZCO0dBQ2xDLEtBQUssNkJBQTZCLHdCQUNoQyxRQUFPO0dBQ1QsS0FBSyw2QkFBNkI7R0FDbEMsS0FBSyw2QkFBNkIsMkJBQ2hDLFFBQU87R0FDVCxRQUNFLFFBQU87OztDQUtiLE9BQU8sY0FBYyxFQUFFLFdBQVcsY0FBeUQ7RUFDekYsTUFBTSxrQkFBa0IsWUFBWSxvQkFBb0IsRUFBRTtFQUMxRCxNQUFNLGtCQUNKLG9CQUFvQixRQUNwQixPQUFPLG9CQUFvQixZQUMzQixzQkFBc0Isa0JBQ2xCLGdCQUFnQixtQkFDaEI7QUFFTixNQUFJLGNBQWMsdUJBQXVCLHVCQUF1QjtHQUM5RCxNQUFNLHlCQUNKLGlCQUFpQixrQ0FBa0MsZ0JBQWdCO0FBQ3JFLFVBQU87SUFDTCxHQUFHO0lBQ0gsa0JBQWtCO0tBQ2hCLEdBQUc7S0FDSCxrQkFBa0I7S0FDbEIsdUJBQXVCO0tBQ3hCO0lBQ0Y7O0FBR0gsTUFBSSxjQUFjLHVCQUF1QixzQkFBc0I7R0FDN0QsTUFBTSxtQkFBbUIsaUJBQWlCLDZCQUN4QyxZQUFZLFlBQ2I7R0FDRCxNQUFNLHlCQUNKLGlCQUFpQixrQ0FBa0MsZ0JBQWdCO0FBQ3JFLFVBQU87SUFDTCxHQUFHO0lBQ0gsa0JBQWtCO0tBQ2hCLEdBQUc7S0FDSCxrQkFBa0I7S0FDbEIsdUJBQXVCO0tBQ3hCO0lBQ0QsZ0JBQWdCO0lBQ2hCLDBCQUEwQjtJQUMzQjs7QUFFSCxTQUFPLGNBQWMsRUFBRTs7Q0FHekIsT0FBTyxnQkFBZ0IsV0FBcUU7QUFDMUYsU0FBTyxPQUFPLE9BQU8sdUJBQXVCLENBQUMsU0FBUyxVQUFvQzs7Q0FHNUYsT0FBTyxrQkFBa0IsV0FBb0U7QUFDM0YsTUFBSSxpQkFBaUIsZ0JBQWdCLFVBQVUsQ0FDN0MsUUFBTyxZQUFZO0FBRXJCLFNBQU8sWUFBWTs7Q0FHckIsTUFBTSxXQUFXLEVBQ2YsV0FDQSxZQUNBLGFBQ0EsNEJBQTRCLFNBQ007QUFDbEMsTUFBSSxLQUFLLGFBQWM7QUFDdkIsUUFBTSxLQUFLO0FBQ1gsU0FBTyxTQUFTLG9CQUFvQixVQUFVO0FBQzlDLE1BQUk7R0FDRixNQUFNLHFCQUFxQixpQkFBaUIsa0JBQWtCLFVBQVU7QUFFeEUsT0FBSSxDQUFDLEtBQUssaUJBQWlCO0FBQ3pCLFdBQU8sUUFBUSw4QkFBOEIsUUFBVyxFQUN0RCxZQUFZLG9CQUNiLENBQUM7QUFDRjs7R0FHRixNQUFNLG1CQUFtQixpQkFBaUIsY0FBYztJQUFFO0lBQVc7SUFBWSxDQUFDO0dBRWxGLE1BQU0sWUFBWSxLQUFLLFVBQVU7SUFDL0I7SUFDQSxZQUFZO0lBQ1osNkJBQVksSUFBSSxNQUFNLEVBQUMsYUFBYTtJQUNyQyxDQUFDO0dBRUYsTUFBTSxPQURVLElBQUksYUFBYSxDQUNaLE9BQU8sVUFBVTtHQUd0QyxNQUFNLGFBQWEsTUFBTSxPQUFPLE9BQU8sT0FBTyxXQUFXLEtBQUs7R0FFOUQsTUFBTSxrQkFEWSxNQUFNLEtBQUssSUFBSSxXQUFXLFdBQVcsQ0FBQyxDQUN0QixLQUFJLE1BQUssRUFBRSxTQUFTLEdBQUcsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLENBQUMsS0FBSyxHQUFHO0FBRXBGLFVBQU8sU0FBUyxzQkFBc0Isc0JBQXNCLE1BQU07SUFDaEUsWUFBWTtJQUNaLE9BQU87SUFDUixDQUFDO0FBRUYsUUFBSyxnQkFBZ0IsTUFDbkIsb0JBQ0E7SUFDRSxHQUFHLEtBQUssd0JBQXdCLFVBQVU7SUFDMUMsR0FBRztJQUNILEdBQUksbUJBQ0EsS0FBSywrQkFBK0IsV0FBVyxpQkFBaUIsR0FDaEUsRUFBRTtJQUNQLEVBQ0Q7SUFDRSxHQUFHO0lBQ0gsV0FBVztJQUNaLENBQ0Y7R0FHRCxNQUFNLFlBQVk7QUFFbEIsT0FBSSxpQkFBaUIsZ0JBQWdCLFVBQVUsSUFBSSxVQUtqRCxjQUFhLFdBSmE7SUFDeEIsR0FBRyxLQUFLLHdCQUF3QixVQUFVO0lBQzFDLEdBQUc7SUFDSixDQUNtRTtZQUMzRCw2QkFBNkIsV0FBVztBQUNqRCxXQUFPLFNBQVMsZUFBZSxtQkFBbUI7QUFDbEQsUUFBSSxPQUFPLFdBQVcsZUFBZSxPQUFPLFVBRTFDLENBQUMsT0FBTyxVQUFvQixLQUFLO0tBQy9CLE9BQU87S0FDUDtLQUNELENBQUM7O1dBR0MsS0FBSztBQUNaLFVBQU8sU0FBUyx3QkFBd0IsS0FBSztJQUMzQztJQUNBO0lBQ0QsQ0FBQzs7O0NBS04sNEJBQTRCLE9BQXNDO0FBQ2hFLE9BQUssMkJBQTJCIn0=
|
|
315
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW1wbGl0dWRlU2VydmljZS5qcyIsIm5hbWVzIjpbIkxvZ2dlciIsIkVYUEVSSU1FTlRfTkFNRVNQQUNFUzogRXhwZXJpbWVudE5hbWVzcGFjZVtdIiwiZW5yaWNobWVudDogRW5yaWNobWVudFBsdWdpbiIsImVucmljaGVkRXZlbnQ6IEV2ZW50IiwiZ2xvYmFsUHJvcGVydGllczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiIsImN1cnJlbnRBbXBsaXR1ZGVJbnN0YW5jZTogQnJvd3NlckNsaWVudCJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZXJ2aWNlcy9hbXBsaXR1ZGVTZXJ2aWNlL2FtcGxpdHVkZVNlcnZpY2UudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRXZlbnRzRGlzcGF0Y2hlciwgU3BpZmZ5RXZlbnQgfSBmcm9tICdzcmMvZXZlbnRzJztcbmltcG9ydCB7IExvY2FsU3RvcmFnZUtleXMgfSBmcm9tICdzcmMvY29udGV4dHMvbG9jYWxTdG9yYWdlQ29udGV4dCc7XG5pbXBvcnQgTG9nZ2VyIGZyb20gJ3NyYy9hcHBsaWNhdGlvbi9sb2dnaW5nL2xvZ2dlcic7XG5pbXBvcnQgdHlwZSB7XG4gIEJyb3dzZXJDbGllbnQsXG4gIEVucmljaG1lbnRQbHVnaW4sXG4gIEV2ZW50LFxuICBTZXJ2ZXJab25lVHlwZSxcbn0gZnJvbSAnQGFtcGxpdHVkZS9hbmFseXRpY3MtdHlwZXMnO1xuaW1wb3J0IHsgRmVhdHVyZUZsYWdTZXJ2aWNlIH0gZnJvbSAnc3JjL3NlcnZpY2VzL2ZlYXR1cmVGbGFnU2VydmljZSc7XG5pbXBvcnQgeyBXaWRnZXRUeXBlVjMgfSBmcm9tICdzcmMvY29udGV4dHMvdHlwZXNWMyc7XG5pbXBvcnQgeyBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzIH0gZnJvbSAnc3JjL2FwcGxpY2F0aW9uL21vZGVscy9jaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzJztcbmltcG9ydCB7IEV4cGVyaW1lbnROYW1lc3BhY2UsIE9yZ0NvbmZpZ0V4cGVyaW1lbnRBc3NpZ25tZW50IH0gZnJvbSAnc3JjL2FwcGxpY2F0aW9uL21vZGVscyc7XG5pbXBvcnQgeyBwcm9qZWN0VG9HQTQgfSBmcm9tICcuLi9nYTRQcm9qZWN0aW9uU2VydmljZS9nYTRQcm9qZWN0aW9uU2VydmljZSc7XG5pbXBvcnQgeyBFbnZpdmVNZXRyaWNzRXZlbnROYW1lLCBTcGlmZnlNZXRyaWNzRXZlbnROYW1lIH0gZnJvbSAnLi9ldmVudE5hbWVzJztcblxuLy8gUmUtZXhwb3J0IGV2ZW50IG5hbWVzIGZvciBjb252ZW5pZW5jZVxuZXhwb3J0IHsgRW52aXZlTWV0cmljc0V2ZW50TmFtZSwgU3BpZmZ5TWV0cmljc0V2ZW50TmFtZSB9O1xuXG5jb25zdCBsb2dnZXIgPSBuZXcgTG9nZ2VyKCdhbXBsaXR1ZGVTZXJ2aWNlJyk7XG5cbi8vIEFtcGxpdHVkZSdzIG1hbmFnZWQgQmlnUXVlcnkgZGF0YSBjYW4gc3VyZmFjZSBzdXBwbGVtZW50YXJ5IFVuaWNvZGUgYXMgVStGRkZELlxuLy8gS2VlcCB0aGUgd2lkZ2V0LXRyYWluaW5nIHBheWxvYWQgQVNDSUktc2FmZSB3aXRob3V0IGNoYW5naW5nIHRoZSBkaXNwbGF5ZWQgdGV4dC5cbmNvbnN0IFVURjhfVFJBTlNQT1JUX1BSRUZJWCA9ICdfX3NwaWZmeV91dGY4X186JztcblxuY29uc3QgY29udGFpbnNTdXBwbGVtZW50YXJ5VW5pY29kZSA9ICh2YWx1ZTogc3RyaW5nKTogYm9vbGVhbiA9PlxuICBBcnJheS5mcm9tKHZhbHVlKS5zb21lKGNoYXJhY3RlciA9PiAoY2hhcmFjdGVyLmNvZGVQb2ludEF0KDApID8/IDApID4gMHhmZmZmKTtcblxuY29uc3QgZW5jb2RlU3VwcGxlbWVudGFyeVVuaWNvZGUgPSAodmFsdWU6IHVua25vd24pOiB1bmtub3duID0+IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gY29udGFpbnNTdXBwbGVtZW50YXJ5VW5pY29kZSh2YWx1ZSlcbiAgICAgID8gYCR7VVRGOF9UUkFOU1BPUlRfUFJFRklYfSR7ZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKX1gXG4gICAgICA6IHZhbHVlO1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIHJldHVybiB2YWx1ZS5tYXAoZW5jb2RlU3VwcGxlbWVudGFyeVVuaWNvZGUpO1xuICB9XG4gIGlmICh2YWx1ZSAhPT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIE9iamVjdC5lbnRyaWVzKHZhbHVlKS5tYXAoKFtrZXksIG5lc3RlZFZhbHVlXSkgPT4gW1xuICAgICAgICBrZXksXG4gICAgICAgIGVuY29kZVN1cHBsZW1lbnRhcnlVbmljb2RlKG5lc3RlZFZhbHVlKSxcbiAgICAgIF0pLFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBUcmFja0V2ZW50UGFyYW1zIHtcbiAgZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lIHwgRW52aXZlTWV0cmljc0V2ZW50TmFtZTtcbiAgZXZlbnRQcm9wcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBldmVudEdyb3Vwcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBhbHNvU2VuZFRvR29vZ2xlQW5hbHl0aWNzPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBbXBsaXR1ZGVTZXJ2aWNlQ29uZmlnIHtcbiAgdXNlcklkOiBzdHJpbmc7XG4gIGFtcGxpdHVkZUFwaUtleTogc3RyaW5nO1xuICBkYXRhUmVzaWRlbmN5OiBzdHJpbmc7XG4gIGVudjogc3RyaW5nO1xuICBjb250ZXh0U291cmNlOiBzdHJpbmc7XG4gIG9yZ1Nob3J0TmFtZTogc3RyaW5nO1xuICBvcmdJZDogc3RyaW5nO1xuICBmZWF0dXJlRmxhZ1NlcnZpY2U6IEZlYXR1cmVGbGFnU2VydmljZTtcbiAgc2hvdzogYm9vbGVhbjtcbiAgZW52aXZlT246IGJvb2xlYW47XG4gIGVuYWJsZWRGZWF0dXJlcz86IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+O1xuICBnZXRMb2NhbFN0b3JhZ2VJdGVtOiBudWxsIHwgKChrZXk6IHN0cmluZykgPT4gc3RyaW5nIHwgbnVsbCk7XG4gIC8vIENhcHR1cmVkIGF0IGNvbnN0cnVjdGlvbi4gRHJpdmVzIGBleHBlcmltZW50Lntuc30uKmAgZXZlbnQtcHJvcGVydHlcbiAgLy8gZW5yaWNobWVudC4gU291cmNlZCBmcm9tIC92MS9vcmcvY29uZmlnIHdoZW4gdGhlIGB1c2VfdW5pZmllZF9jb25maWdgXG4gIC8vIGdhdGUgaXMgb247IG90aGVyd2lzZSBvbWl0dGVkIChwcm9wcyBlbWl0IGFzIG51bGwpLlxuICBleHBlcmltZW50QXNzaWdubWVudHM/OiBPcmdDb25maWdFeHBlcmltZW50QXNzaWdubWVudFtdO1xufVxuXG4vLyBOYW1lc3BhY2VzIGVtaXR0ZWQgb24gZXZlcnkgZXZlbnQgd2l0aCBjb25zdGFudCBrZXlzLCBzbyB0aGUgQmlnUXVlcnlcbi8vIHNjaGVtYSBpcyBzdGFibGUgcmVnYXJkbGVzcyBvZiB3aGljaCAoaWYgYW55KSBleHBlcmltZW50IGlzIHJ1bm5pbmcuXG4vLyBDdXJyZW50bHkgYG1sYCArIGBtZXJjaGFudGA7IG1hdGNoZXMgYEV4cGVyaW1lbnROYW1lc3BhY2VgLlxuY29uc3QgRVhQRVJJTUVOVF9OQU1FU1BBQ0VTOiBFeHBlcmltZW50TmFtZXNwYWNlW10gPSBbJ21sJywgJ21lcmNoYW50J107XG5cbmNvbnN0IGJ1aWxkRXhwZXJpbWVudFByb3BzID0gKFxuICBhc3NpZ25tZW50czogT3JnQ29uZmlnRXhwZXJpbWVudEFzc2lnbm1lbnRbXSB8IHVuZGVmaW5lZCxcbik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0+IHtcbiAgY29uc3QgYnlOYW1lc3BhY2UgPSBuZXcgTWFwPEV4cGVyaW1lbnROYW1lc3BhY2UsIE9yZ0NvbmZpZ0V4cGVyaW1lbnRBc3NpZ25tZW50PigpO1xuICAoYXNzaWdubWVudHMgPz8gW10pLmZvckVhY2goYSA9PiB7XG4gICAgaWYgKGEubGF5ZXJfbmFtZSAhPSBudWxsICYmIGEubmFtZXNwYWNlICE9IG51bGwpIHtcbiAgICAgIGJ5TmFtZXNwYWNlLnNldChhLm5hbWVzcGFjZSwgYSk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIEVYUEVSSU1FTlRfTkFNRVNQQUNFUy5yZWR1Y2U8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+KChhY2MsIG5zKSA9PiB7XG4gICAgY29uc3QgYSA9IGJ5TmFtZXNwYWNlLmdldChucyk7XG4gICAgYWNjW2BleHBlcmltZW50LiR7bnN9LmxheWVyX25hbWVgXSA9IGE/LmxheWVyX25hbWUgPz8gbnVsbDtcbiAgICBhY2NbYGV4cGVyaW1lbnQuJHtuc30uZXhwZXJpbWVudF9uYW1lYF0gPSBhPy5hbGxvY2F0ZWRfZXhwZXJpbWVudF9uYW1lID8/IG51bGw7XG4gICAgYWNjW2BleHBlcmltZW50LiR7bnN9Lmdyb3VwX25hbWVgXSA9IGE/Lmdyb3VwX25hbWUgPz8gbnVsbDtcbiAgICAvLyBgcnVsZV9pZGAgcmVzZXJ2ZWQg4oCUIGJhY2tlbmQgZG9lc24ndCBjdXJyZW50bHkgc3VyZmFjZSBpdC5cbiAgICBhY2NbYGV4cGVyaW1lbnQuJHtuc30ucnVsZV9pZGBdID0gbnVsbDtcbiAgICByZXR1cm4gYWNjO1xuICB9LCB7fSk7XG59O1xuXG5leHBvcnQgY2xhc3MgQW1wbGl0dWRlU2VydmljZSB7XG4gIHByaXZhdGUgYW1wbGl0dWRlQ2xpZW50OiBCcm93c2VyQ2xpZW50IHwgdW5kZWZpbmVkO1xuXG4gIHByaXZhdGUgaW50ZXJuYWxFdmVudFRyYWNraW5nRW5yaWNobWVudDogRW5yaWNobWVudFBsdWdpbiB8IHVuZGVmaW5lZDtcblxuICBwcml2YXRlIHN1cHBsZW1lbnRhbERlZmF1bHRQcm9wczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcblxuICBwcml2YXRlIGNvbmZpZzogQW1wbGl0dWRlU2VydmljZUNvbmZpZztcblxuICBwcml2YXRlIGluaXRQcm9taXNlOiBQcm9taXNlPHZvaWQ+O1xuXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogQW1wbGl0dWRlU2VydmljZUNvbmZpZykge1xuICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICAgIHRoaXMuaW5pdFByb21pc2UgPSB0aGlzLmluaXRpYWxpemUoKTtcbiAgfVxuXG4gIGdldCBpc01vY2tBcGlLZXkoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmFtcGxpdHVkZUFwaUtleSA9PT0gJ21vY2stYW1wbGl0dWRlLWtleSc7XG4gIH1cblxuICAvLyBNdXN0IG5vdCBkZXBlbmQgb24gYGFtcGxpdHVkZUNsaWVudGA6IHRoZSBTREsgbm93IGxvYWRzIHZpYSBkeW5hbWljXG4gIC8vIGltcG9ydCwgYW5kIEFtcGxpdHVkZVByb3ZpZGVyIHVubW91bnRzIGl0cyBlbnRpcmUgc3VidHJlZSB3aGlsZVxuICAvLyBpc1JlYWR5IGlzIGZhbHNlIOKAlCBnYXRpbmcgb24gdGhlIGNsaWVudCB3b3VsZCBibG9jayB3aWRnZXQgcmVuZGVyaW5nXG4gIC8vIG9uIHRoZSBhbmFseXRpY3MgY2h1bmsgZG93bmxvYWQuIEV2ZW50cyBhd2FpdGVkIGluIHRyYWNrRXZlbnQgcXVldWVcbiAgLy8gYmVoaW5kIGBpbml0UHJvbWlzZWAgaW5zdGVhZC5cbiAgZ2V0IGlzUmVhZHkoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIEJvb2xlYW4oXG4gICAgICB0aGlzLmNvbmZpZy51c2VySWQgJiZcbiAgICAgIHRoaXMuY29uZmlnLmZlYXR1cmVGbGFnU2VydmljZSAmJlxuICAgICAgdGhpcy5jb25maWcuYW1wbGl0dWRlQXBpS2V5ICYmXG4gICAgICAhdGhpcy5pc01vY2tBcGlLZXksXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBSZXNvbHZlcyBvbmNlIFNESyBpbml0aWFsaXphdGlvbiBoYXMgc2V0dGxlZCAobmV2ZXIgcmVqZWN0cykuICovXG4gIGluaXRpYWxpemVkKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLmluaXRQcm9taXNlO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRMb2NhbFN0b3JhZ2VJdGVtKGtleTogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgaWYgKHRoaXMuY29uZmlnLmdldExvY2FsU3RvcmFnZUl0ZW0pIHtcbiAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5nZXRMb2NhbFN0b3JhZ2VJdGVtKGtleSk7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB3aW5kb3cubG9jYWxTdG9yYWdlKSB7XG4gICAgICByZXR1cm4gd2luZG93LmxvY2FsU3RvcmFnZS5nZXRJdGVtKGtleSk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREZWZhdWx0VHJhY2tpbmdQcm9wcyhcbiAgICBldmVudE5hbWU6IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUgfCBFbnZpdmVNZXRyaWNzRXZlbnROYW1lLFxuICApOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gICAgY29uc3QgZmVhdHVyZUdhdGVzID0gT2JqZWN0LmVudHJpZXModGhpcy5jb25maWcuZmVhdHVyZUZsYWdTZXJ2aWNlLmdldEZlYXR1cmVGbGFncygpKTtcbiAgICBjb25zdCBnYXRlc1Byb3BzID1cbiAgICAgIGZlYXR1cmVHYXRlcy5sZW5ndGggPiAwXG4gICAgICAgID8gZmVhdHVyZUdhdGVzLnJlZHVjZTxSZWNvcmQ8c3RyaW5nLCBib29sZWFuPj4oKGFjYywgW25hbWUsIHZhbHVlXSkgPT4ge1xuICAgICAgICAgICAgaWYgKG5hbWUgJiYgdmFsdWUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICByZXR1cm4geyAuLi5hY2MsIFtgZmVhdHVyZV9nYXRlLiR7bmFtZX1gXTogdmFsdWUgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgICAgfSwge30pXG4gICAgICAgIDoge307XG4gICAgY29uc3QgZXhwZXJpbWVudFByb3BzID0gYnVpbGRFeHBlcmltZW50UHJvcHModGhpcy5jb25maWcuZXhwZXJpbWVudEFzc2lnbm1lbnRzKTtcblxuICAgIGNvbnN0IGVudmlyb25tZW50UHJvcHMgPSB7XG4gICAgICAnZW52aXJvbm1lbnQuZXhlY3V0aW9uX2NvbnRleHQnOiAnYnVuZGxlJyxcbiAgICAgICdlbnZpcm9ubWVudC5wYWdlX3VybCc6IHdpbmRvdy5sb2NhdGlvbi5ocmVmLFxuICAgICAgJ2Vudmlyb25tZW50LmVudml2ZV91c2VyX2lkJzogdGhpcy5jb25maWcudXNlcklkLFxuICAgICAgJ2Vudmlyb25tZW50LmV4ZWN1dGlvbl9lbnZpcm9ubWVudCc6IHRoaXMuY29uZmlnLmVudiB8fCAndW5rbm93bicsXG4gICAgICAnZW52aXJvbm1lbnQuY29udGV4dF9zb3VyY2UnOiB0aGlzLmNvbmZpZy5jb250ZXh0U291cmNlLFxuICAgICAgJ2Vudmlyb25tZW50LnNhbGVzX2FnZW50X2VuYWJsZWQnOiB0aGlzLmNvbmZpZy5lbmFibGVkRmVhdHVyZXM/LnNhbGVzQWdlbnQgPz8gZmFsc2UsXG4gICAgICAnZW52aXJvbm1lbnQuc2VhcmNoX2VuYWJsZWQnOiB0aGlzLmNvbmZpZy5lbmFibGVkRmVhdHVyZXM/LnNlYXJjaEFnZW50ID8/IGZhbHNlLFxuICAgICAgJ2Vudmlyb25tZW50LmVudml2ZV9vbl9xdWVyeV9wYXJhbSc6IHRoaXMuY29uZmlnLmVudml2ZU9uLFxuICAgICAgJ2Vudmlyb25tZW50LndpbmRvd19zaG93JzogdGhpcy5jb25maWcuc2hvdyxcbiAgICAgICdlbnZpcm9ubWVudC5lbnZpdmVfZW5hYmxlZCc6IHRoaXMuY29uZmlnLmVuYWJsZWRGZWF0dXJlcz8uZW52aXZlLFxuICAgIH07XG5cbiAgICBjb25zdCBvcmdMZXZlbEFtcGxpdHVkZVRyYWNraW5nUHJvcHMgPSBBbXBsaXR1ZGVTZXJ2aWNlLmlzVjNFbnZpdmVFdmVudChldmVudE5hbWUpXG4gICAgICA/IHtcbiAgICAgICAgICAuLi50aGlzLmNvbmZpZy5mZWF0dXJlRmxhZ1NlcnZpY2UuZ2V0RnVsbEZsYWdWYWx1ZXMoKSxcbiAgICAgICAgICAuLi5leHBlcmltZW50UHJvcHMsXG4gICAgICAgICAgLi4uZW52aXJvbm1lbnRQcm9wcyxcbiAgICAgICAgfVxuICAgICAgOiB7XG4gICAgICAgICAgLi4uZ2F0ZXNQcm9wcyxcbiAgICAgICAgICAuLi5leHBlcmltZW50UHJvcHMsXG4gICAgICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLm9yZ0xldmVsQW1wbGl0dWRlVHJhY2tpbmdQcm9wcyxcbiAgICAgIC4uLnRoaXMuc3VwcGxlbWVudGFsRGVmYXVsdFByb3BzLFxuICAgICAgYXBwX2lkOiAnY29tbWVyY2UtY2hhdC1yZWFjdC1jb21wb25lbnQnLFxuICAgICAgY2hhdF9pZDogdGhpcy5nZXRMb2NhbFN0b3JhZ2VJdGVtKExvY2FsU3RvcmFnZUtleXMuQ2hhdElkKSxcbiAgICAgIGVudjogdGhpcy5jb25maWcuZW52IHx8ICd1bmtub3duJyxcbiAgICAgIGFwcF9zb3VyY2U6IHRoaXMuY29uZmlnLmNvbnRleHRTb3VyY2UsXG4gICAgICBvcmdfaWQ6IHRoaXMuY29uZmlnLm9yZ0lkLFxuICAgICAgJ29yZy5zaG9ydF9uYW1lJzogdGhpcy5jb25maWcub3JnU2hvcnROYW1lLFxuICAgICAgJ3VzZXIuaWQnOiB0aGlzLmNvbmZpZy51c2VySWQsXG4gICAgICAnY2RwLnVzZXJfaWQnOiBudWxsLFxuICAgICAgJ2NkcC5wcm92aWRlcic6IG51bGwsXG4gICAgICAnZXZlbnQuc291cmNlJzogJ3dlYi1icm93c2VyJyxcbiAgICAgICdldmVudC50eXBlJzogJ3VzZXItYWN0aXZpdHknLFxuICAgICAgJ2V2ZW50LmlkJzogbnVsbCxcbiAgICAgICdldmVudC5jaGFubmVsJzogJ3dlYicsXG4gICAgICAnZXZlbnQudGltZXN0YW1wJzogbnVsbCxcbiAgICB9O1xuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcbiAgcHJpdmF0ZSBldmVudFByb3BzVG9QcmVmaXhlZEV2ZW50UHJvcHMoXG4gICAgZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lIHwgRW52aXZlTWV0cmljc0V2ZW50TmFtZSxcbiAgICBldmVudFByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICAgIGNvbnN0IHByZWZpeCA9IGV2ZW50TmFtZS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL1xccysvZywgJ18nKTtcbiAgICByZXR1cm4gT2JqZWN0LmVudHJpZXMoZXZlbnRQcm9wcykucmVkdWNlKFxuICAgICAgKGFjYywgW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICAgIGFjY1tgJHtwcmVmaXh9LiR7a2V5fWBdID0gdmFsdWU7XG4gICAgICAgIHJldHVybiBhY2M7XG4gICAgICB9LFxuICAgICAge30gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RXZlbnRUcmFja2luZ0VucmljaG1lbnQoKTogRW5yaWNobWVudFBsdWdpbiB7XG4gICAgaWYgKHRoaXMuaW50ZXJuYWxFdmVudFRyYWNraW5nRW5yaWNobWVudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gdGhpcy5pbnRlcm5hbEV2ZW50VHJhY2tpbmdFbnJpY2htZW50O1xuICAgIH1cblxuICAgIGNvbnN0IGVucmljaG1lbnQ6IEVucmljaG1lbnRQbHVnaW4gPSB7XG4gICAgICBuYW1lOiAncGFnZS12aWV3LXRyYWNraW5nLWVucmljaG1lbnQnLFxuICAgICAgdHlwZTogJ2VucmljaG1lbnQnLFxuICAgICAgc2V0dXA6IGFzeW5jICgpID0+IHVuZGVmaW5lZCxcbiAgICAgIGV4ZWN1dGU6IGFzeW5jIChldmVudDogRXZlbnQpOiBQcm9taXNlPEV2ZW50PiA9PiB7XG4gICAgICAgIGxldCBlbnJpY2hlZEV2ZW50OiBFdmVudDtcblxuICAgICAgICBjb25zdCBldmVudHNUb0VucmljaCA9IFtcbiAgICAgICAgICAnW0FtcGxpdHVkZV0gUGFnZSBWaWV3ZWQnLFxuICAgICAgICAgIGBbU3BpZmZ5XSAke1NwaWZmeU1ldHJpY3NFdmVudE5hbWUuQnVuZGxlTG9hZGVkfWAsXG4gICAgICAgICAgYFtFbnZpdmVdICR7RW52aXZlTWV0cmljc0V2ZW50TmFtZS5QYWdlVmlld2VkfWAsXG4gICAgICAgIF07XG5cbiAgICAgICAgaWYgKGV2ZW50c1RvRW5yaWNoLmluY2x1ZGVzKGV2ZW50LmV2ZW50X3R5cGUpKSB7XG4gICAgICAgICAgY29uc3QgZ2xvYmFsUHJvcGVydGllczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gICAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNob3cgIT0gbnVsbCkge1xuICAgICAgICAgICAgZ2xvYmFsUHJvcGVydGllc1snZ2xvYmFsUHJvcGVydGllcy5zaG93J10gPSBTdHJpbmcodGhpcy5jb25maWcuc2hvdyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGdsb2JhbFByb3BlcnRpZXNbJ2dsb2JhbFByb3BlcnRpZXMuZW52J10gPSBTdHJpbmcodGhpcy5jb25maWcuZW52KTtcblxuICAgICAgICAgIGNvbnN0IGVuYWJsZWRGZWF0dXJlc1Byb3BlcnRpZXMgPSBPYmplY3QuZW50cmllcyhcbiAgICAgICAgICAgIHRoaXMuY29uZmlnPy5lbmFibGVkRmVhdHVyZXMgPz8gKHt9IGFzIFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+KSxcbiAgICAgICAgICApLnJlZHVjZTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PihcbiAgICAgICAgICAgIChhY2MsIFtrZXksIHZhbHVlXSkgPT4gKHtcbiAgICAgICAgICAgICAgLi4uYWNjLFxuICAgICAgICAgICAgICBbYGVuYWJsZWRGZWF0dXJlcy4ke2tleX1gXTogYCR7dmFsdWV9YCxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAge30sXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IHRpbWluZ1Byb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICAndGltaW5nLmVucmljaGVkX2F0X21zJzpcbiAgICAgICAgICAgICAgdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cucGVyZm9ybWFuY2U/Lm5vdygpIDogdW5kZWZpbmVkLFxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBlbnJpY2hlZEV2ZW50ID0ge1xuICAgICAgICAgICAgLi4uZXZlbnQsXG4gICAgICAgICAgICBldmVudF9wcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgIC4uLmV2ZW50LmV2ZW50X3Byb3BlcnRpZXMsXG4gICAgICAgICAgICAgIC4uLnRoaXMuZ2V0RGVmYXVsdFRyYWNraW5nUHJvcHMoXG4gICAgICAgICAgICAgICAgZXZlbnQuZXZlbnRfdHlwZSBhcyBTcGlmZnlNZXRyaWNzRXZlbnROYW1lIHwgRW52aXZlTWV0cmljc0V2ZW50TmFtZSxcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgLi4uZ2xvYmFsUHJvcGVydGllcyxcbiAgICAgICAgICAgICAgLi4uZW5hYmxlZEZlYXR1cmVzUHJvcGVydGllcyxcbiAgICAgICAgICAgICAgLi4udGltaW5nUHJvcGVydGllcyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlbnJpY2hlZEV2ZW50ID0gZXZlbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBFdmVudHNEaXNwYXRjaGVyLmRpc3BhdGNoKFNwaWZmeUV2ZW50LkFNUExJVFVERV9FVkVOVCwgZW5yaWNoZWRFdmVudCk7XG5cbiAgICAgICAgcmV0dXJuIGVucmljaGVkRXZlbnQ7XG4gICAgICB9LFxuICAgIH07XG4gICAgdGhpcy5pbnRlcm5hbEV2ZW50VHJhY2tpbmdFbnJpY2htZW50ID0gZW5yaWNobWVudDtcbiAgICByZXR1cm4gZW5yaWNobWVudDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaW5pdGlhbGl6ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBpc1JlYWR5ID0gQm9vbGVhbihcbiAgICAgIHRoaXMuY29uZmlnLnVzZXJJZCAmJiB0aGlzLmNvbmZpZy5mZWF0dXJlRmxhZ1NlcnZpY2UgJiYgdGhpcy5jb25maWcuYW1wbGl0dWRlQXBpS2V5LFxuICAgICk7XG5cbiAgICBpZiAoIWlzUmVhZHkpIHtcbiAgICAgIGxvZ2dlci5sb2dEZWJ1ZygnQW1wbGl0dWRlU2VydmljZSBpcyBub3QgcmVhZHknLCB7XG4gICAgICAgIGlzUmVhZHksXG4gICAgICAgIHVzZXJJZDogdGhpcy5jb25maWcudXNlcklkLFxuICAgICAgICBoYXNGZWF0dXJlRmxhZ1NlcnZpY2U6ICEhdGhpcy5jb25maWcuZmVhdHVyZUZsYWdTZXJ2aWNlLFxuICAgICAgICBoYXNBbXBsaXR1ZGVBcGlLZXk6ICEhdGhpcy5jb25maWcuYW1wbGl0dWRlQXBpS2V5LFxuICAgICAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaXNNb2NrQXBpS2V5KSB7XG4gICAgICBsb2dnZXIubG9nV2FybihcbiAgICAgICAgJ01vY2sgQVBJIGtleSBkZXRlY3RlZCDigJQgcnVubmluZyBpbiBtb2NrIG1vZGUsIG5vIGV2ZW50cyB3aWxsIGJlIHNlbnQgdG8gQW1wbGl0dWRlLicsXG4gICAgICAgIHRoaXMuY29uZmlnLmFtcGxpdHVkZUFwaUtleSxcbiAgICAgICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmFtcGxpdHVkZUNsaWVudCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gRHluYW1pYyBpbXBvcnQga2VlcHMgdGhlIEFtcGxpdHVkZSBTREsgb3V0IG9mIHRoZSBlYWdlclxuICAgICAgICAvLyBpbmplY3Rpb24tYnVuZGxlIGNodW5rOyB0cmFja0V2ZW50IHF1ZXVlcyBiZWhpbmQgaW5pdFByb21pc2UuXG4gICAgICAgIGNvbnN0IHsgY3JlYXRlSW5zdGFuY2UgfSA9IGF3YWl0IGltcG9ydCgnQGFtcGxpdHVkZS9hbmFseXRpY3MtYnJvd3NlcicpO1xuICAgICAgICBjb25zdCBjdXJyZW50QW1wbGl0dWRlSW5zdGFuY2U6IEJyb3dzZXJDbGllbnQgPSBjcmVhdGVJbnN0YW5jZSgpO1xuXG4gICAgICAgIGN1cnJlbnRBbXBsaXR1ZGVJbnN0YW5jZS5hZGQodGhpcy5nZXRFdmVudFRyYWNraW5nRW5yaWNobWVudCgpKTtcbiAgICAgICAgY3VycmVudEFtcGxpdHVkZUluc3RhbmNlLmluaXQodGhpcy5jb25maWcuYW1wbGl0dWRlQXBpS2V5LCB0aGlzLmNvbmZpZy51c2VySWQsIHtcbiAgICAgICAgICBzZXJ2ZXJab25lOiB0aGlzLmNvbmZpZy5kYXRhUmVzaWRlbmN5IGFzIFNlcnZlclpvbmVUeXBlLFxuICAgICAgICAgIHRyYWNraW5nT3B0aW9uczoge1xuICAgICAgICAgICAgaXBBZGRyZXNzOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYXV0b2NhcHR1cmU6IHtcbiAgICAgICAgICAgIGF0dHJpYnV0aW9uOiB0cnVlLFxuICAgICAgICAgICAgcGFnZVZpZXdzOiB7XG4gICAgICAgICAgICAgIHRyYWNrSGlzdG9yeUNoYW5nZXM6ICdwYXRoT25seScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2Vzc2lvbnM6IGZhbHNlLFxuICAgICAgICAgICAgZm9ybUludGVyYWN0aW9uczogZmFsc2UsXG4gICAgICAgICAgICBmaWxlRG93bmxvYWRzOiBmYWxzZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hbXBsaXR1ZGVDbGllbnQgPSBjdXJyZW50QW1wbGl0dWRlSW5zdGFuY2U7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgbG9nZ2VyLmxvZ0Vycm9yKCdGYWlsZWQgdG8gbG9hZCBvciBpbml0aWFsaXplIHRoZSBBbXBsaXR1ZGUgU0RLJywgZXJyKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBzdGF0aWMgbWFwV2lkZ2V0VHlwZVRvQ2hhdENvbXBvbmVudCh3aWRnZXRUeXBlOiB1bmtub3duKTogc3RyaW5nIHtcbiAgICBzd2l0Y2ggKHdpZGdldFR5cGUpIHtcbiAgICAgIGNhc2UgV2lkZ2V0VHlwZVYzLkZsb2F0aW5nQnV0dG9uVjM6XG4gICAgICAgIHJldHVybiAnZmxvYXRpbmdfYnV0dG9uJztcbiAgICAgIGNhc2UgV2lkZ2V0VHlwZVYzLlR5cGluZ0FuaW1hdGlvblYzOlxuICAgICAgY2FzZSBXaWRnZXRUeXBlVjMuQ2hhdFByZXZpZXdWMzpcbiAgICAgIGNhc2UgV2lkZ2V0VHlwZVYzLlNvY2lhbFByb29mVjM6XG4gICAgICAgIHJldHVybiAnZW1iZWRkZWRfd2lkZ2V0JztcbiAgICAgIGNhc2UgV2lkZ2V0VHlwZVYzLlRpdGxlZFByb21wdENhcm91c2VsVjM6XG4gICAgICBjYXNlIFdpZGdldFR5cGVWMy5Qcm9tcHRDYXJvdXNlbFYzOlxuICAgICAgICByZXR1cm4gJ3N1Z2dlc3Rpb25fYmFyJztcbiAgICAgIGNhc2UgV2lkZ2V0VHlwZVYzLlByb2R1Y3RDYXJkVjM6XG4gICAgICAgIHJldHVybiAnaW1hZ2VfcHJvbXB0X2NhcmQnO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuICd1bmtub3duJztcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgbWFwVHJpZ2dlckxvY2F0aW9uVG9DaGF0Q29tcG9uZW50KHRyaWdnZXJMb2NhdGlvbjogdW5rbm93bik6IHN0cmluZyB7XG4gICAgc3dpdGNoICh0cmlnZ2VyTG9jYXRpb24pIHtcbiAgICAgIGNhc2UgQ2hhdEVsZW1lbnREaXNwbGF5TG9jYXRpb25WMy5QUk9EVUNUX0NBUkRfUFJPTVBUX0JVVFRPTjpcbiAgICAgIGNhc2UgQ2hhdEVsZW1lbnREaXNwbGF5TG9jYXRpb25WMy5QUk9EVUNUX0NBUkRfVEVYVF9GSUVMRDpcbiAgICAgICAgcmV0dXJuICdwcm9tcHRfY2FyZCc7XG4gICAgICBjYXNlIENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uVjMuUFJPTVBUX0NBUk9VU0VMOlxuICAgICAgY2FzZSBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzLlRJVExFRF9QUk9NUFRfQ0FST1VTRUw6XG4gICAgICAgIHJldHVybiAndG9wX3Jldmlld3Nfc25pcHBldCc7XG4gICAgICBjYXNlIENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uVjMuVFlQSU5HX0FOSU1BVElPTjpcbiAgICAgIGNhc2UgQ2hhdEVsZW1lbnREaXNwbGF5TG9jYXRpb25WMy5TT0NJQUxfUFJPT0ZfUFJJTUFSWV9CVVRUT046XG4gICAgICBjYXNlIENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uVjMuU09DSUFMX1BST09GX1NFQ09OREFSWV9CVVRUT046XG4gICAgICBjYXNlIENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uVjMuU09DSUFMX1BST09GX1RFWFRfRklFTEQ6XG4gICAgICBjYXNlIENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uVjMuQ0hBVF9QUkVWSUVXX0NPTVBBUklTT05fUFJPTVBUX0JVVFRPTjpcbiAgICAgIGNhc2UgQ2hhdEVsZW1lbnREaXNwbGF5TG9jYXRpb25WMy5DSEFUX1BSRVZJRVdfQ09NUEFSSVNPTl9URVhUX0ZJRUxEOlxuICAgICAgY2FzZSBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzLkNIQVRfUFJFVklFV19QUk9NUFRfQlVUVE9OOlxuICAgICAgY2FzZSBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzLkNIQVRfUFJFVklFV19URVhUX0ZJRUxEOlxuICAgICAgICByZXR1cm4gJ2NoYXRfcHJldmlldyc7XG4gICAgICBjYXNlIENoYXRFbGVtZW50RGlzcGxheUxvY2F0aW9uVjMuRkxPQVRJTkdfQ0hBVF9PVkVSTEFZOlxuICAgICAgY2FzZSBDaGF0RWxlbWVudERpc3BsYXlMb2NhdGlvblYzLkZMT0FUSU5HX0NIQVRfQ0xPU0VfQlVUVE9OOlxuICAgICAgICByZXR1cm4gJ2luX2NoYXQnO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHRyaWdnZXJMb2NhdGlvbiBhcyBzdHJpbmc7XG4gICAgfVxuICB9XG5cbiAgLy8gVGhpcyBhbGxvd3MgdXMgdG8gbWFwIHRoZSBldmVudCBwcm9wcyB0byB0aGUgY29ycmVjdCBmb3JtYXQgZm9yIHRoZSBsZWdhY3kgYW1wbGl0dWRlIGV2ZW50c1xuICBzdGF0aWMgbWFwRXZlbnRQcm9wcyh7IGV2ZW50TmFtZSwgZXZlbnRQcm9wcyB9OiBUcmFja0V2ZW50UGFyYW1zKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICAgIGNvbnN0IG1lc3NhZ2VNZXRhZGF0YSA9IGV2ZW50UHJvcHM/Lm1lc3NhZ2VfbWV0YWRhdGEgPz8ge307XG4gICAgY29uc3QgdHJpZ2dlckxvY2F0aW9uID1cbiAgICAgIG1lc3NhZ2VNZXRhZGF0YSAhPT0gbnVsbCAmJlxuICAgICAgdHlwZW9mIG1lc3NhZ2VNZXRhZGF0YSA9PT0gJ29iamVjdCcgJiZcbiAgICAgICd0cmlnZ2VyX2xvY2F0aW9uJyBpbiBtZXNzYWdlTWV0YWRhdGFcbiAgICAgICAgPyBtZXNzYWdlTWV0YWRhdGEudHJpZ2dlcl9sb2NhdGlvblxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGlmIChldmVudE5hbWUgPT09IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUuQ2hhdENvbXBvbmVudEV4cGFuZGVkKSB7XG4gICAgICBjb25zdCBtYXBwZWRUcmlnZ2VyTG9jY2F0aW9uID1cbiAgICAgICAgQW1wbGl0dWRlU2VydmljZS5tYXBUcmlnZ2VyTG9jYXRpb25Ub0NoYXRDb21wb25lbnQodHJpZ2dlckxvY2F0aW9uKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLmV2ZW50UHJvcHMsXG4gICAgICAgIG1lc3NhZ2VfbWV0YWRhdGE6IHtcbiAgICAgICAgICAuLi5tZXNzYWdlTWV0YWRhdGEsXG4gICAgICAgICAgdHJpZ2dlcl9sb2NhdGlvbjogbWFwcGVkVHJpZ2dlckxvY2NhdGlvbixcbiAgICAgICAgICBmdWxsX3RyaWdnZXJfbG9jYXRpb246IHRyaWdnZXJMb2NhdGlvbixcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKGV2ZW50TmFtZSA9PT0gU3BpZmZ5TWV0cmljc0V2ZW50TmFtZS5DaGF0Q29tcG9uZW50VmlzaWJsZSkge1xuICAgICAgY29uc3QgbWFwcGVkV2lkZ2V0VHlwZSA9IEFtcGxpdHVkZVNlcnZpY2UubWFwV2lkZ2V0VHlwZVRvQ2hhdENvbXBvbmVudChcbiAgICAgICAgZXZlbnRQcm9wcz8ud2lkZ2V0X3R5cGUsXG4gICAgICApO1xuICAgICAgY29uc3QgbWFwcGVkVHJpZ2dlckxvY2NhdGlvbiA9XG4gICAgICAgIEFtcGxpdHVkZVNlcnZpY2UubWFwVHJpZ2dlckxvY2F0aW9uVG9DaGF0Q29tcG9uZW50KHRyaWdnZXJMb2NhdGlvbik7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5ldmVudFByb3BzLFxuICAgICAgICBtZXNzYWdlX21ldGFkYXRhOiB7XG4gICAgICAgICAgLi4ubWVzc2FnZU1ldGFkYXRhLFxuICAgICAgICAgIHRyaWdnZXJfbG9jYXRpb246IG1hcHBlZFRyaWdnZXJMb2NjYXRpb24sXG4gICAgICAgICAgZnVsbF90cmlnZ2VyX2xvY2F0aW9uOiB0cmlnZ2VyTG9jYXRpb24sXG4gICAgICAgIH0sXG4gICAgICAgIGNoYXRfY29tcG9uZW50OiBtYXBwZWRXaWRnZXRUeXBlLFxuICAgICAgICAnY2hhdC5jb21wb25lbnRfdmlzaWJsZSc6IHRydWUsXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gZXZlbnRQcm9wcyA/PyB7fTtcbiAgfVxuXG4gIHN0YXRpYyBpc1YzRW52aXZlRXZlbnQoZXZlbnROYW1lOiBTcGlmZnlNZXRyaWNzRXZlbnROYW1lIHwgRW52aXZlTWV0cmljc0V2ZW50TmFtZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKEVudml2ZU1ldHJpY3NFdmVudE5hbWUpLmluY2x1ZGVzKGV2ZW50TmFtZSBhcyBFbnZpdmVNZXRyaWNzRXZlbnROYW1lKTtcbiAgfVxuXG4gIHN0YXRpYyBkZWNvcmF0ZUV2ZW50TmFtZShldmVudE5hbWU6IFNwaWZmeU1ldHJpY3NFdmVudE5hbWUgfCBFbnZpdmVNZXRyaWNzRXZlbnROYW1lKTogc3RyaW5nIHtcbiAgICBpZiAoQW1wbGl0dWRlU2VydmljZS5pc1YzRW52aXZlRXZlbnQoZXZlbnROYW1lKSkge1xuICAgICAgcmV0dXJuIGBbRW52aXZlXSAke2V2ZW50TmFtZX1gO1xuICAgIH1cbiAgICByZXR1cm4gYFtTcGlmZnldICR7ZXZlbnROYW1lfWA7XG4gIH1cblxuICBhc3luYyB0cmFja0V2ZW50KHtcbiAgICBldmVudE5hbWUsXG4gICAgZXZlbnRQcm9wcyxcbiAgICBldmVudEdyb3VwcyxcbiAgICBhbHNvU2VuZFRvR29vZ2xlQW5hbHl0aWNzID0gZmFsc2UsXG4gIH06IFRyYWNrRXZlbnRQYXJhbXMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5pc01vY2tBcGlLZXkpIHJldHVybjtcbiAgICBhd2FpdCB0aGlzLmluaXRQcm9taXNlO1xuICAgIGxvZ2dlci5sb2dEZWJ1ZygnU3VibWl0dGluZyBldmVudCcsIGV2ZW50TmFtZSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGRlY29yYXRlZEV2ZW50TmFtZSA9IEFtcGxpdHVkZVNlcnZpY2UuZGVjb3JhdGVFdmVudE5hbWUoZXZlbnROYW1lKTtcblxuICAgICAgaWYgKCF0aGlzLmFtcGxpdHVkZUNsaWVudCkge1xuICAgICAgICBsb2dnZXIubG9nV2FybignYW1wbGl0dWRlIGNsaWVudCB1bmRlZmluZWQnLCB1bmRlZmluZWQsIHtcbiAgICAgICAgICBldmVudF9uYW1lOiBkZWNvcmF0ZWRFdmVudE5hbWUsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1hcHBlZEV2ZW50UHJvcHMgPSBBbXBsaXR1ZGVTZXJ2aWNlLm1hcEV2ZW50UHJvcHMoeyBldmVudE5hbWUsIGV2ZW50UHJvcHMgfSk7XG4gICAgICBjb25zdCBhbXBsaXR1ZGVFdmVudFByb3BzID1cbiAgICAgICAgZXZlbnROYW1lID09PSBFbnZpdmVNZXRyaWNzRXZlbnROYW1lLldpZGdldFRleHRSZXNwb25zZSB8fFxuICAgICAgICBldmVudE5hbWUgPT09IEVudml2ZU1ldHJpY3NFdmVudE5hbWUuV2lkZ2V0VGV4dENsaWNrZWRcbiAgICAgICAgICA/IChlbmNvZGVTdXBwbGVtZW50YXJ5VW5pY29kZShtYXBwZWRFdmVudFByb3BzKSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilcbiAgICAgICAgICA6IG1hcHBlZEV2ZW50UHJvcHM7XG5cbiAgICAgIGNvbnN0IGV2ZW50RGF0YSA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgZXZlbnROYW1lLFxuICAgICAgICBldmVudFByb3BzOiBhbXBsaXR1ZGVFdmVudFByb3BzLFxuICAgICAgICBjcmVhdGVkX2F0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKTtcbiAgICAgIGNvbnN0IGRhdGEgPSBlbmNvZGVyLmVuY29kZShldmVudERhdGEpO1xuICAgICAgLy8gY2FsY3VsYXRlIGEgaGFzaCBvZiB0aGUgZXZlbnQgcHJvcGVydGllcyB0byB1c2UgYXMgdGhlIGluc2VydF9pZCBzbyB0aGF0IGR1cGxpY2F0ZSBldmVudHNcbiAgICAgIC8vIGFyZSBhdXRvbWF0aWNhbGx5IGRyb3BwZWQgYnkgQW1wbGl0dWRlXG4gICAgICBjb25zdCBoYXNoQnVmZmVyID0gYXdhaXQgY3J5cHRvLnN1YnRsZS5kaWdlc3QoJ1NIQS0yNTYnLCBkYXRhKTtcbiAgICAgIGNvbnN0IGhhc2hBcnJheSA9IEFycmF5LmZyb20obmV3IFVpbnQ4QXJyYXkoaGFzaEJ1ZmZlcikpO1xuICAgICAgY29uc3QgY3VycmVudEluc2VydElkID0gaGFzaEFycmF5Lm1hcChiID0+IGIudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsICcwJykpLmpvaW4oJycpO1xuXG4gICAgICBsb2dnZXIubG9nRGVidWcoYGFtcGxpdHVkZSB0cmFja2luZyAke2RlY29yYXRlZEV2ZW50TmFtZX1gLCBudWxsLCB7XG4gICAgICAgIGV2ZW50X25hbWU6IGRlY29yYXRlZEV2ZW50TmFtZSxcbiAgICAgICAgcHJvcHM6IGFtcGxpdHVkZUV2ZW50UHJvcHMsXG4gICAgICB9KTtcblxuICAgICAgdGhpcy5hbXBsaXR1ZGVDbGllbnQudHJhY2soXG4gICAgICAgIGRlY29yYXRlZEV2ZW50TmFtZSxcbiAgICAgICAge1xuICAgICAgICAgIC4uLnRoaXMuZ2V0RGVmYXVsdFRyYWNraW5nUHJvcHMoZXZlbnROYW1lKSxcbiAgICAgICAgICAuLi5hbXBsaXR1ZGVFdmVudFByb3BzLFxuICAgICAgICAgIC4uLihhbXBsaXR1ZGVFdmVudFByb3BzXG4gICAgICAgICAgICA/IHRoaXMuZXZlbnRQcm9wc1RvUHJlZml4ZWRFdmVudFByb3BzKGV2ZW50TmFtZSwgYW1wbGl0dWRlRXZlbnRQcm9wcylcbiAgICAgICAgICAgIDoge30pLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgLi4uZXZlbnRHcm91cHMsXG4gICAgICAgICAgaW5zZXJ0X2lkOiBjdXJyZW50SW5zZXJ0SWQsXG4gICAgICAgIH0sXG4gICAgICApO1xuXG4gICAgICAvLyBUT0RPOiBQdWxsIGdhRW5hYmxlZCBmcm9tIG9yZyBjb25maWcgd2hlbiBhdmFpbGFibGUuIEhhcmRjb2RlZCB0byB0cnVlIGZvciBub3cuXG4gICAgICBjb25zdCBnYUVuYWJsZWQgPSB0cnVlO1xuXG4gICAgICBpZiAoQW1wbGl0dWRlU2VydmljZS5pc1YzRW52aXZlRXZlbnQoZXZlbnROYW1lKSAmJiBnYUVuYWJsZWQpIHtcbiAgICAgICAgY29uc3QgbWVyZ2VkUHJvcHNGb3JHQTQgPSB7XG4gICAgICAgICAgLi4udGhpcy5nZXREZWZhdWx0VHJhY2tpbmdQcm9wcyhldmVudE5hbWUpLFxuICAgICAgICAgIC4uLm1hcHBlZEV2ZW50UHJvcHMsXG4gICAgICAgIH07XG4gICAgICAgIHByb2plY3RUb0dBNChldmVudE5hbWUgYXMgRW52aXZlTWV0cmljc0V2ZW50TmFtZSwgbWVyZ2VkUHJvcHNGb3JHQTQpO1xuICAgICAgfSBlbHNlIGlmIChhbHNvU2VuZFRvR29vZ2xlQW5hbHl0aWNzICYmIGdhRW5hYmxlZCkge1xuICAgICAgICBsb2dnZXIubG9nRGVidWcoJ0dBIHRyYWNraW5nJywgZGVjb3JhdGVkRXZlbnROYW1lKTtcbiAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5kYXRhTGF5ZXIpIHtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAgICh3aW5kb3cuZGF0YUxheWVyIGFzIGFueVtdKS5wdXNoKHtcbiAgICAgICAgICAgIGV2ZW50OiBkZWNvcmF0ZWRFdmVudE5hbWUsXG4gICAgICAgICAgICBldmVudFByb3BzLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2dnZXIubG9nRXJyb3IoJ0Vycm9yIHRyYWNraW5nIGV2ZW50JywgZXJyLCB7XG4gICAgICAgIGV2ZW50TmFtZSxcbiAgICAgICAgZXZlbnRQcm9wcyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIEVuc3VyZSB0aGF0IHN1cHBsZW1lbnRhbCBkZWZhdWx0IHByb3BzIGFyZSBtZXJnZWQgd2l0aCB0aGUgZXhpc3RpbmcgcHJvcHNcbiAgc2V0U3VwcGxlbWVudGFsRGVmYXVsdFByb3BzKHByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHZvaWQge1xuICAgIHRoaXMuc3VwcGxlbWVudGFsRGVmYXVs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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@envive-ai/react-hooks",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.58",
|
|
4
4
|
"description": "React hooks for connecting to Envive AI services.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -74,6 +74,10 @@
|
|
|
74
74
|
"import": "./dist/application/commerce-api.js",
|
|
75
75
|
"require": "./dist/application/commerce-api.cjs"
|
|
76
76
|
},
|
|
77
|
+
"./application/logging": {
|
|
78
|
+
"import": "./dist/application/logging/index.js",
|
|
79
|
+
"require": "./dist/application/logging/index.cjs"
|
|
80
|
+
},
|
|
77
81
|
"./application/models": {
|
|
78
82
|
"import": "./dist/application/models/index.js",
|
|
79
83
|
"require": "./dist/application/models/index.cjs"
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ContextEnvEnum,
|
|
3
|
+
ContextSourceEnum,
|
|
4
|
+
ResponseCategory,
|
|
5
|
+
} from '@spiffy-ai/commerce-api-client';
|
|
6
|
+
import { getAtomStore } from 'src/atoms/atomStore/atomStore';
|
|
7
|
+
import { enviveConfigAtom } from 'src/atoms/envive/enviveConfig';
|
|
8
|
+
import { NextMessageRequest, Response } from 'src/application/models';
|
|
9
|
+
import CommerceApiClient from '../commerce-api';
|
|
10
|
+
|
|
11
|
+
const { mockV1NextResponsesPostRaw } = vi.hoisted(() => ({
|
|
12
|
+
mockV1NextResponsesPostRaw: vi.fn(),
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
vi.mock('@spiffy-ai/commerce-api-client', async (importOriginal: () => Promise<unknown>) => {
|
|
16
|
+
const actual = (await importOriginal()) as typeof import('@spiffy-ai/commerce-api-client');
|
|
17
|
+
return {
|
|
18
|
+
...actual,
|
|
19
|
+
InferenceApi: vi.fn().mockImplementation(function InferenceApi() {
|
|
20
|
+
return { v1NextResponsesPostRaw: mockV1NextResponsesPostRaw };
|
|
21
|
+
}),
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const payload: NextMessageRequest = {
|
|
26
|
+
id: 'req-1',
|
|
27
|
+
context: {
|
|
28
|
+
chatId: 'chat-1',
|
|
29
|
+
orgId: 'org-1',
|
|
30
|
+
orgShortName: 'test-org',
|
|
31
|
+
userId: 'user-1',
|
|
32
|
+
source: ContextSourceEnum.App,
|
|
33
|
+
env: ContextEnvEnum.Dev,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const productRecord = (id: string, title: string, description = 'A great shoe') =>
|
|
38
|
+
JSON.stringify({
|
|
39
|
+
id,
|
|
40
|
+
category: 'product',
|
|
41
|
+
created_at: '2026-08-28 14:42:58.529065+00:00',
|
|
42
|
+
attributes: {
|
|
43
|
+
id: `sku-${id}`,
|
|
44
|
+
title,
|
|
45
|
+
description,
|
|
46
|
+
url: `https://example.com/${id}`,
|
|
47
|
+
image_url: `https://example.com/${id}.jpg`,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const streamFromByteChunks = (chunks: Uint8Array[]): ReadableStream<Uint8Array> =>
|
|
52
|
+
new ReadableStream({
|
|
53
|
+
start(controller) {
|
|
54
|
+
chunks.forEach(chunk => controller.enqueue(chunk));
|
|
55
|
+
controller.close();
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const streamFromStringChunks = (chunks: string[]): ReadableStream<Uint8Array> => {
|
|
60
|
+
const encoder = new TextEncoder();
|
|
61
|
+
return streamFromByteChunks(chunks.map(chunk => encoder.encode(chunk)));
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const mockStreamedResponse = (body: ReadableStream<Uint8Array>) => {
|
|
65
|
+
mockV1NextResponsesPostRaw.mockResolvedValueOnce({ raw: { body } });
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const collectStream = async (): Promise<Response[]> => {
|
|
69
|
+
const results: Response[] = [];
|
|
70
|
+
for await (const response of CommerceApiClient.getNextResponseStreaming(payload)) {
|
|
71
|
+
results.push(response);
|
|
72
|
+
}
|
|
73
|
+
return results;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
beforeEach(() => {
|
|
77
|
+
vi.clearAllMocks();
|
|
78
|
+
getAtomStore().set(enviveConfigAtom, {
|
|
79
|
+
baseUrl: 'https://commerce-api.test',
|
|
80
|
+
orgLevelApiKey: 'test-key',
|
|
81
|
+
orgId: 'org-1',
|
|
82
|
+
orgShortName: 'test-org',
|
|
83
|
+
env: 'dev',
|
|
84
|
+
contextSource: 'app',
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('CommerceApiClient.getNextResponseStreaming — NDJSON chunk handling', () => {
|
|
89
|
+
it('parses records split mid-line across chunk boundaries', async () => {
|
|
90
|
+
const record1 = productRecord('rec-1', 'Kelly Mary Jane Flat');
|
|
91
|
+
const record2 = productRecord('rec-2', '27 Edit Carla Ballet Flat');
|
|
92
|
+
// Cut each record in the middle of a JSON string, as observed on cellular connections
|
|
93
|
+
mockStreamedResponse(
|
|
94
|
+
streamFromStringChunks([
|
|
95
|
+
record1.slice(0, 120),
|
|
96
|
+
`${record1.slice(120)}\n${record2.slice(0, 80)}`,
|
|
97
|
+
`${record2.slice(80)}\n`,
|
|
98
|
+
]),
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const results = await collectStream();
|
|
102
|
+
|
|
103
|
+
expect(results.map(r => r.id)).toEqual(['rec-1', 'rec-2']);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('does not re-prepend a consumed partial to later chunks', async () => {
|
|
107
|
+
const record1 = productRecord('rec-1', 'First');
|
|
108
|
+
const record2 = productRecord('rec-2', 'Second');
|
|
109
|
+
const record3 = productRecord('rec-3', 'Third');
|
|
110
|
+
// record1 completes in chunk 2, which ends cleanly on a newline; the old
|
|
111
|
+
// implementation kept the stale partial and corrupted record3 in chunk 3
|
|
112
|
+
mockStreamedResponse(
|
|
113
|
+
streamFromStringChunks([
|
|
114
|
+
record1.slice(0, 100),
|
|
115
|
+
`${record1.slice(100)}\n${record2}\n`,
|
|
116
|
+
`${record3}\n`,
|
|
117
|
+
]),
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
const results = await collectStream();
|
|
121
|
+
|
|
122
|
+
expect(results.map(r => r.id)).toEqual(['rec-1', 'rec-2', 'rec-3']);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('flushes a final record that has no trailing newline', async () => {
|
|
126
|
+
const record1 = productRecord('rec-1', 'First');
|
|
127
|
+
const record2 = productRecord('rec-2', 'Last, unterminated');
|
|
128
|
+
mockStreamedResponse(
|
|
129
|
+
streamFromStringChunks([`${record1}\n${record2.slice(0, 90)}`, record2.slice(90)]),
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const results = await collectStream();
|
|
133
|
+
|
|
134
|
+
expect(results.map(r => r.id)).toEqual(['rec-1', 'rec-2']);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('decodes multi-byte UTF-8 characters split across chunk boundaries', async () => {
|
|
138
|
+
const record = productRecord('rec-1', 'Café flat', 'Voilà — c’est chic');
|
|
139
|
+
const bytes = new TextEncoder().encode(`${record}\n`);
|
|
140
|
+
// Split inside the multi-byte sequence of “é”
|
|
141
|
+
const splitAt = bytes.findIndex(b => b === 0xc3) + 1;
|
|
142
|
+
mockStreamedResponse(streamFromByteChunks([bytes.slice(0, splitAt), bytes.slice(splitAt)]));
|
|
143
|
+
|
|
144
|
+
const results = await collectStream();
|
|
145
|
+
|
|
146
|
+
expect(results).toHaveLength(1);
|
|
147
|
+
expect(results[0].category).toBe(ResponseCategory.Product);
|
|
148
|
+
if (results[0].category === ResponseCategory.Product) {
|
|
149
|
+
expect(results[0].attributes.title).toBe('Café flat');
|
|
150
|
+
expect(results[0].attributes.description).toBe('Voilà — c’est chic');
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('drops a malformed line without breaking the rest of the stream', async () => {
|
|
155
|
+
const record = productRecord('rec-1', 'Survivor');
|
|
156
|
+
mockStreamedResponse(streamFromStringChunks([`{"not": "valid json"\n${record}\n[DONE]\n`]));
|
|
157
|
+
|
|
158
|
+
const results = await collectStream();
|
|
159
|
+
|
|
160
|
+
expect(results.map(r => r.id)).toEqual(['rec-1']);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('strips SSE "data: " prefixes and skips [DONE] markers', async () => {
|
|
164
|
+
const record = productRecord('rec-1', 'Prefixed');
|
|
165
|
+
mockStreamedResponse(streamFromStringChunks([`data: ${record}\ndata: [DONE]\n`]));
|
|
166
|
+
|
|
167
|
+
const results = await collectStream();
|
|
168
|
+
|
|
169
|
+
expect(results.map(r => r.id)).toEqual(['rec-1']);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
@@ -263,34 +263,24 @@ class CommerceApiClient {
|
|
|
263
263
|
const reader = response.raw.body.getReader();
|
|
264
264
|
const decoder = new TextDecoder('utf-8');
|
|
265
265
|
|
|
266
|
+
// Buffer holding the trailing incomplete line of the previous chunk
|
|
266
267
|
let partial = '';
|
|
267
|
-
|
|
268
|
+
|
|
268
269
|
const safeParse = (line: string): unknown => {
|
|
269
270
|
try {
|
|
270
271
|
return JSON.parse(line); // Parse the JSON string
|
|
271
272
|
} catch (err) {
|
|
272
|
-
logger.logError('Error parsing streamed line', err, {
|
|
273
|
-
|
|
274
|
-
partial,
|
|
275
|
-
});
|
|
276
|
-
// swallow the error and set the partial to our current chunk
|
|
277
|
-
partial = line;
|
|
278
|
-
return partial;
|
|
273
|
+
logger.logError('Error parsing streamed line', err, { line });
|
|
274
|
+
return null;
|
|
279
275
|
}
|
|
280
276
|
};
|
|
281
277
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
// merge the partial with the incoming chunk
|
|
285
|
-
const lines = `${partial}${chunk}`.split('\n');
|
|
286
|
-
|
|
287
|
-
const parsedLines = lines
|
|
278
|
+
const parseLines = (lines: string[]): unknown[] =>
|
|
279
|
+
lines
|
|
288
280
|
.map(line => line.replace(/^data: /, '').trim()) // Remove the "data: " prefix
|
|
289
281
|
.filter(line => line !== '' && line !== '[DONE]') // Remove empty lines and "[DONE]"
|
|
290
282
|
.map(safeParse)
|
|
291
|
-
.filter(v => v);
|
|
292
|
-
return parsedLines;
|
|
293
|
-
};
|
|
283
|
+
.filter(v => v != null);
|
|
294
284
|
|
|
295
285
|
while (true) {
|
|
296
286
|
// eslint-disable-next-line no-await-in-loop
|
|
@@ -300,11 +290,12 @@ class CommerceApiClient {
|
|
|
300
290
|
break;
|
|
301
291
|
}
|
|
302
292
|
|
|
303
|
-
//
|
|
304
|
-
|
|
305
|
-
const
|
|
293
|
+
// A chunk boundary can fall mid-line, so only parse the lines that
|
|
294
|
+
// are terminated by a newline and hold the rest until the next chunk
|
|
295
|
+
const lines = `${partial}${decoder.decode(value, { stream: true })}`.split('\n');
|
|
296
|
+
partial = lines.pop() ?? '';
|
|
306
297
|
|
|
307
|
-
for (const parsedLine of
|
|
298
|
+
for (const parsedLine of parseLines(lines)) {
|
|
308
299
|
const validatedResponse = validateResponse(parsedLine);
|
|
309
300
|
|
|
310
301
|
if (validatedResponse) {
|
|
@@ -312,6 +303,15 @@ class CommerceApiClient {
|
|
|
312
303
|
}
|
|
313
304
|
}
|
|
314
305
|
}
|
|
306
|
+
|
|
307
|
+
// Flush the remainder of a stream that didn't end with a newline
|
|
308
|
+
for (const parsedLine of parseLines([`${partial}${decoder.decode()}`])) {
|
|
309
|
+
const validatedResponse = validateResponse(parsedLine);
|
|
310
|
+
|
|
311
|
+
if (validatedResponse) {
|
|
312
|
+
yield validatedResponse;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
315
|
} catch (error: unknown) {
|
|
316
316
|
logger.logError('Failed to get next streaming responses', error, {
|
|
317
317
|
payloadContext: payload?.context,
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import Logger from 'src/application/logging/logger';
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_LOG_LEVEL,
|
|
4
|
+
LOG_LEVEL_STORAGE_KEY,
|
|
5
|
+
getLogLevel,
|
|
6
|
+
isLevelEnabled,
|
|
7
|
+
resetLogLevelForTesting,
|
|
8
|
+
setLogLevel,
|
|
9
|
+
} from 'src/application/logging/logLevel';
|
|
10
|
+
|
|
11
|
+
const setHref = (href: string) => {
|
|
12
|
+
Object.defineProperty(window, 'location', {
|
|
13
|
+
configurable: true,
|
|
14
|
+
value: { ...window.location, href, search: new URL(href).search },
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe('logger log level', () => {
|
|
19
|
+
const originalHref = window.location.href;
|
|
20
|
+
let spies: ReturnType<typeof vi.spyOn>[] = [];
|
|
21
|
+
let logger: Logger;
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
resetLogLevelForTesting();
|
|
25
|
+
window.localStorage.clear();
|
|
26
|
+
setHref('https://merchant.example.com/products/thing');
|
|
27
|
+
delete (window as { _envive?: unknown })._envive;
|
|
28
|
+
delete (window as { _spiffy?: unknown })._spiffy;
|
|
29
|
+
logger = new Logger('testCaller');
|
|
30
|
+
spies = [
|
|
31
|
+
vi.spyOn(console, 'debug').mockImplementation(() => {}),
|
|
32
|
+
vi.spyOn(console, 'info').mockImplementation(() => {}),
|
|
33
|
+
vi.spyOn(console, 'warn').mockImplementation(() => {}),
|
|
34
|
+
vi.spyOn(console, 'error').mockImplementation(() => {}),
|
|
35
|
+
];
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
spies.forEach(spy => spy.mockRestore());
|
|
40
|
+
resetLogLevelForTesting();
|
|
41
|
+
setHref(originalHref);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const emitAll = () => {
|
|
45
|
+
logger.logDebug('d');
|
|
46
|
+
logger.logInfo('i');
|
|
47
|
+
logger.logWarn('w', undefined);
|
|
48
|
+
logger.logError('e', undefined);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const emitted = () => ({
|
|
52
|
+
debug: (console.debug as unknown as { mock: { calls: unknown[] } }).mock.calls.length,
|
|
53
|
+
info: (console.info as unknown as { mock: { calls: unknown[] } }).mock.calls.length,
|
|
54
|
+
warn: (console.warn as unknown as { mock: { calls: unknown[] } }).mock.calls.length,
|
|
55
|
+
error: (console.error as unknown as { mock: { calls: unknown[] } }).mock.calls.length,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('mutes debug and info but keeps warn and error by default', () => {
|
|
59
|
+
expect(DEFAULT_LOG_LEVEL).toBe('warn');
|
|
60
|
+
expect(getLogLevel()).toBe('warn');
|
|
61
|
+
|
|
62
|
+
emitAll();
|
|
63
|
+
|
|
64
|
+
expect(emitted()).toEqual({ debug: 0, info: 0, warn: 1, error: 1 });
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('silences every level at "silent"', () => {
|
|
68
|
+
setLogLevel('silent');
|
|
69
|
+
|
|
70
|
+
emitAll();
|
|
71
|
+
|
|
72
|
+
expect(emitted()).toEqual({ debug: 0, info: 0, warn: 0, error: 0 });
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('emits every level at "debug"', () => {
|
|
76
|
+
setLogLevel('debug');
|
|
77
|
+
|
|
78
|
+
emitAll();
|
|
79
|
+
|
|
80
|
+
expect(emitted()).toEqual({ debug: 1, info: 1, warn: 1, error: 1 });
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('keeps the existing output format when a level is enabled', () => {
|
|
84
|
+
setLogLevel('debug');
|
|
85
|
+
|
|
86
|
+
logger.logDebug('a message', { extra: true });
|
|
87
|
+
|
|
88
|
+
expect(console.debug).toHaveBeenCalledWith(
|
|
89
|
+
expect.stringMatching(/^DEBUG: \[envive-ai\] .+ - testCaller - a message$/),
|
|
90
|
+
{ extra: true },
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('honours the window override without a reload', () => {
|
|
95
|
+
expect(isLevelEnabled('debug')).toBe(false);
|
|
96
|
+
|
|
97
|
+
(window as { _envive?: { logLevel?: string } })._envive = { logLevel: 'debug' };
|
|
98
|
+
|
|
99
|
+
expect(isLevelEnabled('debug')).toBe(true);
|
|
100
|
+
expect(getLogLevel()).toBe('debug');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('accepts the _spiffy window override and is case-insensitive', () => {
|
|
104
|
+
(window as { _spiffy?: { logLevel?: string } })._spiffy = { logLevel: 'DEBUG' };
|
|
105
|
+
|
|
106
|
+
expect(getLogLevel()).toBe('debug');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('ignores an unrecognised level and falls back to the default', () => {
|
|
110
|
+
(window as { _envive?: { logLevel?: string } })._envive = { logLevel: 'chatty' };
|
|
111
|
+
|
|
112
|
+
expect(getLogLevel()).toBe(DEFAULT_LOG_LEVEL);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('reads the level from the query param and persists it for later navigations', () => {
|
|
116
|
+
setHref('https://merchant.example.com/products/thing?envive_log_level=debug');
|
|
117
|
+
|
|
118
|
+
expect(getLogLevel()).toBe('debug');
|
|
119
|
+
expect(window.localStorage.getItem(LOG_LEVEL_STORAGE_KEY)).toBe('debug');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('applies a persisted level on a page without the query param', () => {
|
|
123
|
+
window.localStorage.setItem(LOG_LEVEL_STORAGE_KEY, 'info');
|
|
124
|
+
|
|
125
|
+
expect(getLogLevel()).toBe('info');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('lets the query param win over a level pinned programmatically', () => {
|
|
129
|
+
setHref('https://merchant.example.com/products/thing?envive_log_level=debug');
|
|
130
|
+
setLogLevel('silent');
|
|
131
|
+
|
|
132
|
+
expect(getLogLevel()).toBe('debug');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('lets setLogLevel(undefined) fall back to the levers below it', () => {
|
|
136
|
+
window.localStorage.setItem(LOG_LEVEL_STORAGE_KEY, 'info');
|
|
137
|
+
setLogLevel('silent');
|
|
138
|
+
expect(getLogLevel()).toBe('silent');
|
|
139
|
+
|
|
140
|
+
setLogLevel(undefined);
|
|
141
|
+
|
|
142
|
+
expect(getLogLevel()).toBe('info');
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('survives localStorage throwing', () => {
|
|
146
|
+
const getItem = vi.spyOn(window.localStorage, 'getItem').mockImplementation(() => {
|
|
147
|
+
throw new Error('blocked');
|
|
148
|
+
});
|
|
149
|
+
const setItem = vi.spyOn(window.localStorage, 'setItem').mockImplementation(() => {
|
|
150
|
+
throw new Error('blocked');
|
|
151
|
+
});
|
|
152
|
+
setHref('https://merchant.example.com/products/thing?envive_log_level=debug');
|
|
153
|
+
|
|
154
|
+
expect(getLogLevel()).toBe('debug');
|
|
155
|
+
|
|
156
|
+
getItem.mockRestore();
|
|
157
|
+
setItem.mockRestore();
|
|
158
|
+
});
|
|
159
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { default } from 'src/application/logging/logger';
|
|
2
|
+
export {
|
|
3
|
+
DEFAULT_LOG_LEVEL,
|
|
4
|
+
getLogLevel,
|
|
5
|
+
isLevelEnabled,
|
|
6
|
+
LOG_LEVEL_QUERY_PARAM,
|
|
7
|
+
LOG_LEVEL_STORAGE_KEY,
|
|
8
|
+
LOG_LEVELS,
|
|
9
|
+
resetLogLevelForTesting,
|
|
10
|
+
setLogLevel,
|
|
11
|
+
} from 'src/application/logging/logLevel';
|
|
12
|
+
export type { LogLevel } from 'src/application/logging/logLevel';
|